【图像处理】基于OpenCV底层实现的直方图匹配
image processing 系列:
直方图匹配算法。又称直方图规定化。简单说。就是依据某函数、或者另外一张图片的引导,使得原图改变。
感觉解释的最好的是:http://www.360doc.com/content/13/1106/16/10724725_327179043.shtml
完整代码:github (里面同一时候包括OSTU / 大津算法、直方图均衡化等算法,还包括两种測试图片)。
由于我个人兴趣爱好(放P就是老师逼的。
。。)。不同意使用 OpenCV 封装好的直方图函数。
依据实例解说,了解了直方图匹配算法底层的操作(多说一句,这个样例能够是我见过最好的直方图匹配算法解说,也是非常难见的此算法的样例,必读)。
注:实例解说中 0->3 的意义是,原图中灰度级为 0 的像素点所有转化为原图中的 3 灰度级。
上代码(当中,srcImg 是原图。dstImg 是须要匹配的图,flag 标记两者是 RGB 图还是灰度图):
cv::Mat ycMatchHist(cv::Mat srcImg, cv::Mat dstImg, int flag) { // ****** 假设是 RGB 图片则转为灰度图片操作 ****** Mat out(srcImg); if (flag == YC_RGB) { cvtColor(srcImg, out, CV_BGR2GRAY); } else if (flag == YC_GRAY) { } int grayLevel[colvl]; for(int i=0; i<colvl; i++) grayLevel[i] = i; int grayArr[colvl]; int srcRow = srcImg.rows; int srcCol = srcImg.cols; int dstRow = dstImg.rows; int dstCol = dstImg.cols; float srcCdfArr[colvl] = {0.f}; float dstCdfArr[colvl] = {0.f}; float tmp; // *** 求解源图片的累积直方图(概率)分布 *** memset(grayArr, 0, sizeof(grayArr)); for(size_t nrow = 0; nrow < srcRow; nrow++) for(size_t ncol = 0; ncol < srcCol; ncol++) { int tag = srcImg.at<uchar>(nrow, ncol); grayArr[tag]++; } tmp = 0; for(int i=0; i<colvl; i++) { tmp += grayArr[i]; srcCdfArr[i] = tmp / (srcRow * srcCol); // std::cout<<srcCdfArr[i]<<std::endl; } // *** 求解目标图片的累积直方图(概率)分布 *** memset(grayArr, 0, sizeof(grayArr)); for(size_t nrow = 0; nrow < dstRow; nrow++) for(size_t ncol = 0; ncol < dstCol; ncol++) { int tag = dstImg.at<uchar>(nrow, ncol); grayArr[tag]++; } tmp = 0; for(int i=0; i<colvl; i++) { tmp += grayArr[i]; dstCdfArr[i] = tmp / (dstRow * dstCol); } // *** 直方图匹配算法 *** int histMap[colvl]; int minTag; for(int i=0; i<colvl; i++) { float minMap = 10.f; for(int j=0; j<colvl; j++) { if (minMap > abs(srcCdfArr[i] - dstCdfArr[j])) { minMap = abs(srcCdfArr[i] - dstCdfArr[j]); minTag = j; } } histMap[i] = minTag; } for(size_t nrow = 0; nrow < out.rows; nrow++) for(size_t ncol = 0; ncol < out.cols; ncol++) { int tag = out.at<uchar>(nrow, ncol); out.at<uchar>(nrow, ncol) = histMap[tag]; } return out; }
实验结果例如以下:
原图为;
须要匹配的图是。
终于输出的是图。
匹配图片的灰度累积直方图为:;
终于输出的灰度累积直方图为:
两者非常接近了,证明匹配算法是可行的(当然假设我说错了,欢迎打脸。共同进步哈哈~)