8.直方图
一.直方图
简单的说灰度直方图就是:一幅图像中灰度级与出现这种灰度的概率之间关系的图形,灰度直方图是一种统计表达,反映了不同灰度级出现的统计概率(个数),其横坐标是:灰度级,纵坐标是:出现的个数(概率)。
(1)直方图的离散函数 h(rk)=nk。其中rk是第K级的灰度值,nk是图像中灰度为rk的像素的个数。
(2)归一化直方图 p(rk)=nk/MN。其中k = 0,1,2.....L-1(灰度级的范围是[ 0 , L-1]),MN表示像素的总的个数。
算法实现:
Mat histogram_normalization(Mat& img, int a, int b) { int width = img.cols; int height = img.rows; int channel = img.channels(); int c = 0, d = 0; //图片灰度阈值 int val; Mat out = Mat::zeros(height, width, CV_8UC3); //get c, d for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { for (int _c = 0; _c < channel; _c++) { val = (float)img.at<Vec3b>(y, x)[_c]; c = fmin(val, c); d = fmax(val, d); } } } // histogram transformation for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { for (int _c = 0; _c < 3; _c++) { val = (float)img.at<Vec3b>(y, x)[_c]; if (val < a) out.at<Vec3b>(y, x)[_c] = (uchar)a; else if (val >= c && val < d) out.at<Vec3b>(y, x)[_c] = (uchar)(b - a) / (d - c)*(val - c) + a; else out.at<Vec3b>(y, x)[_c] = (uchar)b; } } } return out; }
二. 直方图操作
这种操作不能将图像灰度等级分布在整个灰度区域,但可以提高对比度。
算法实现:
1 cv::Mat histogram_transform(cv::Mat img, int m0, int s0) 2 { 3 // get height and width 4 int width = img.cols; 5 int height = img.rows; 6 int channel = img.channels(); 7 cv::Mat out = cv::Mat::zeros(height, width, CV_8UC3); 8 double val = 0; 9 double sum = 0.0, squared_sum = 0.0; 10 for (int y = 0; y < height; y++) 11 { 12 for (int x = 0; x < width; x++) 13 { 14 for (int c = 0; c < channel; c++) 15 { 16 val = (float)img.at<Vec3b>(y, x)[c]; 17 sum += val; 18 squared_sum += (val * val); 19 } 20 } 21 } 22 double m, sigma; 23 //期望 24 m = sum / (height*width*channel); 25 //标准差 26 sigma = sqrt(squared_sum / (height*width*channel) - m * m); 27 28 cout << "期望 : " << m << endl; 29 cout<<"标准差"<< sigma<<endl; 30 // histogram transformation 31 for (int y = 0; y < height; y++) 32 { 33 for (int x = 0; x < width; x++) 34 { 35 for (int c = 0; c < channel; c++) 36 { 37 val = img.at<Vec3b>(y, x)[c]; 38 out.at<Vec3b>(y, x)[c] = (uchar)(s0 / sigma * (val - m) + m0); 39 } 40 41 } 42 } 43 return out; 44 }
三、均衡化
算法实现:
1 // histogram equalization 2 cv::Mat histogram_equalization(cv::Mat img) 3 { 4 // get height and width 5 int width = img.cols; 6 int height = img.rows; 7 int channel = img.channels(); 8 9 // output image 10 cv::Mat out = cv::Mat::zeros(height, width, CV_8UC3); 11 12 // histogram equalization hyper-parameters 13 double Zmax = 255; 14 double hist[255] = { 0 }; 15 double S = height * width*channel; 16 int val = 0; 17 //统计像素个数 18 for (int y = 0; y < height; y++) 19 { 20 for (int x = 0; x < width; x++) 21 { 22 for (int c = 0; c < channel; c++) 23 { 24 val = (int)img.at<cv::Vec3b>(y, x)[c]; 25 hist[val]++; 26 } 27 } 28 } 29 30 double hist_sum = 0; 31 //均衡化处理 32 for (int y = 0; y < height; y++) 33 { 34 for (int x = 0; x < width; x++) 35 { 36 for (int c = 0; c < channel; c++) 37 { 38 val = (int)img.at<cv::Vec3b>(y, x)[c]; 39 hist_sum = 0; 40 for (int k = 0; k < val; k++) 41 { 42 hist_sum += hist[k]; 43 } 44 out.at<cv::Vec3b>(y, x)[c] = (uchar)(Zmax / S * hist_sum); 45 } 46 } 47 } 48