直方图均衡
获取直方图与直方图均衡化,规定化
原理很简单,就是获取像素点分布,并改变像素点分布。
1、获取直方图
用到的接口是 calcHist(),有三种形式。返回一个图像直方图像素分布。之后再使用opencv画图。
1 void gethist(Mat gray) 2 { 3 //Mat gray; 4 //cvtColor(src, gray, CV_RGB2GRAY); 5 const int channels[] = { 0 }; 6 Mat hist; 7 const int histsize[] = { 256 }; 8 float range[] = { 0, 256 }; 9 const float* ranges[] = { range }; 10 calcHist(&gray, 1, channels, Mat(), hist, 1, histsize, ranges, true, false); 11 double maxval = 0; 12 minMaxLoc(hist, 0, &maxval, 0, 0); 13 int row = cvRound(maxval); 14 Mat histimage(row, 256, CV_8UC1); 15 for (int i = 0; i < 256; i++) 16 { 17 int temp = (int)(hist.at<float>(i, 0)); 18 if (temp) 19 { 20 histimage.col(i).rowRange(Range(row - temp, row)) = 255; 21 } 22 } 23 Mat resizeimage; 24 resize(histimage, resizeimage, Size(256, 256)); 25 imshow("灰度图", gray); 26 imshow("histgram", resizeimage); 27 waitKey(0); 28 }
2、直方图均衡
改变像素值分布,使其基本满足均匀分布。由此可改善图像对比度。
1 Mat histbalance_local(Mat src) 2 { 3 int Hist[256] = { 0 }; 4 float p[256] = { 0 }; 5 float dist[256]; 6 int IMGH = src.rows; 7 int IMGW = src.cols; 8 for (int i = 0; i < IMGH; i++) 9 { 10 for (int j = 0; j < IMGW; j++) 11 { 12 Hist[int(src.at<uchar>(i, j))]++; 13 } 14 } 15 for (int i = 0; i < 256; i++) 16 { 17 p[i]=( (float)(Hist[i]) / (IMGH*IMGW)); 18 } 19 dist[0] = p[0]; 20 for (int i = 1; i < 256; i++) 21 { 22 dist[i] = p[i]+dist[i-1]; 23 } 24 for (int i = 0; i < 256; i++) 25 { 26 Hist[i]=255*dist[i]+0.5; 27 } 28 Mat dst(src.size(), CV_8UC1); 29 for (int i = 0; i < IMGH; i++) 30 { 31 for (int j = 0; j < IMGW; j++) 32 { 33 dst.at<uchar>(i, j)=Hist[int(src.at<uchar>(i, j))]; 34 } 35 } 36 37 //imshow("均衡后图像", dst); 38 return dst; 39 //waitKey(0); 40 41 }
3、直方图规定化
使图像像素值分布基本满足目标图像的分布。原理很简单,就是建立原图像与目标图像像素值映射,映射条件是累计概率分布相似。 看过一些版本的实现,步骤如下:
1、 计算原图像累计概率分布
2、计算目标图像累计概率分布
3、对两幅图像累计概率分布差值最小的像素点建立映射
代码不实现了,感觉有点麻烦,但是原理还是很简单的。这个随便搜就有。