opencv关于直方图的归一化,均衡化

来源:互联网 发布:怎么使用淘宝客 编辑:程序博客网 时间:2024/06/06 09:47
#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include <iostream>#include <stdio.h>using namespace cv;using namespace std;/**  @function main */int main(int argc, char** argv){Mat src, dst;char* source_window = "Source image";char* equalized_window = "Equalized Image";/// 加载源图像src = imread(argv[1], 1);if (!src.data){cout << "Usage: ./Histogram_Demo <path_to_image>" << endl;return -1;}/// 转为灰度图cvtColor(src, src, CV_BGR2GRAY);cout << "(width, height)" <<"( " <<src.cols<<", "<<src.rows<<")"<<endl;/// 应用直方图均衡化equalizeHist(src, dst);/// 显示结果namedWindow(source_window, CV_WINDOW_AUTOSIZE);namedWindow(equalized_window, CV_WINDOW_AUTOSIZE);imwrite("原始图像对应的灰度图.jpg", src);imwrite("均衡化后的图.jpg",dst);imshow(source_window, src);moveWindow(source_window,50,50);imshow(equalized_window, dst);moveWindow(equalized_window,350,50);/// 等待用户按键退出程序waitKey(0);return 0;}/*(width, height)( 259, 261)    moveWindow(const string&name, int x, int y)x--The new x-coordinate of the windowy--The new y-coordinate of the window    所以想要把两个窗口挪在同一行,则它们应该具有相同的y值,不同的x值从代码和实验结果我们可以看到,对于直方图均衡化而言,我们无法控制,只是输入一幅图像,然后我们把它转化成灰度的,然后调用equalizeHist(src, dst);直接输出的dst就是我们要求的均衡化后的图像;直方图均衡化的原理直方图均衡化主要用于增强动态范围偏小的图像的反差。这个方法的基本思想是把原始图像的直方图变换为在整个灰度范围内的均匀分布的形式,这样就增加了像素灰度值的动态范围,从而达到增强图像整体对比度的效果。*/

我看了将近两天的代码,感觉自己真的是脑力不行,总是理解的不到位;

需要理解的东西都放在代码里了,大家可以看看;

# include <iostream># include <opencv2/highgui/highgui.hpp># include <opencv2/imgproc/imgproc.hpp>using namespace std;using namespace cv;/*显示直方图函数*///Mat &mat,使用的是C++中的取引用void showHistogram(Mat &mat, int bins, char *wndName) {int histSize[] = {bins};//直方图大小,对应每一个维度的bins数float range[] = {0,bins};//在ranges数组中的位置对应第几维的取值范围const float *ranges[] = {range};int channels[] = {0};MatND hist;calcHist(&mat,1,channels,Mat(),hist,1, histSize,ranges,true,false);cout << hist << endl;double maxVal;//Find the global minimum and maximum in an arrayminMaxLoc(hist,0,&maxVal,0,0);int scale = 2;//histogram size(width)int histHeight = 256;//创建了一个画布,宽度为256X2,高度为256,正好就是直方图Mat histImage = Mat::zeros(histHeight,bins*scale,CV_8UC1);for (int i = 0; i < bins; i++) {//以次处理第i个bin,从0到bins-1,取第i个bin中的数据,即灰度级为i的像素个数float binVal = hist.at<float>(i);//这个是为什么呢?没有看懂//这句话的含义是对于这个试验中的直方图,bin中最大数为6820,//我们为这个数定义的高度是256,即maxVal对应于histHeight,//那么如果一个桶中的数值为binVal,则它在画布上对应的高度为//binVal*histHeight/maxVal,对这个数进行四舍五入,即为第i个灰度级//应画出的直方图i级灰度的高int intensity = cvRound(binVal*histHeight/maxVal);//但这个地方的两个点的设置,我没看懂?/*我做了实验,开始的两个点为Point(0,255),和Point(1,256),程序把256X512的图像,左下的两个像素点涂成了白色,我没理解,如果有同学理解了,请告诉我。*/rectangle(histImage,Point(i*scale,histHeight-1),Point((i+1)*scale-1,histHeight-intensity),CV_RGB(255,255,255));imshow(wndName, histImage);/*char name[40];sprintf(name, "%s%s", wndName, ".jpg");imwrite(name,histImage);waitKey(0);*/}namedWindow(wndName, CV_WINDOW_AUTOSIZE);imshow(wndName,histImage);char name[40];sprintf(name,"%s%s",wndName,".jpg");imwrite(name,histImage);}int main(int argc, char** argv) {Mat src, dst;char * source_window = "Source Image";char *equalized_window = "Equalized Image";src = imread(argv[1],1/*>0返回3通道彩色图*/);if (!src.data) {cerr << "Read Image Failed!" << endl;exit(1);}//读入了彩色图像cvtColor(src, src,CV_BGR2GRAY);equalizeHist(src,dst);namedWindow(source_window,CV_WINDOW_AUTOSIZE);imshow(source_window,src);moveWindow(source_window,50,50);namedWindow(equalized_window,CV_WINDOW_AUTOSIZE);imshow(equalized_window,dst);moveWindow(equalized_window,350,50);waitKey(0);//显示直方图int bins = 256;showHistogram(src,bins,"Original Image Hist");showHistogram(dst,bins,"Equalized Image Hist");waitKey(0);return 0;}/*=================[0;0;0;0;0;0;0;1;1;2;2;5;7;13;15;7;15;11;14;23;28;27;44;51;56;90;103;119;136;168;168;202;242;307;340;475;498;675;815;1027;1238;1374;1715;2013;2387;2855;3323;3907;4823;5730;6280;--一维直方图中最大值5070;2827;1691;1226;988;871;807;937;983;993;927;866;788;797;663;747;673;677;639;667;679;677;721;810;739;746;739;766;838;884;915;1003;1147;1379;1609;1646;1636;1487;1346;1228;1098;1047;1008;936;919;847;874;890;868;799;816;882;816;769;808;784;791;827;793;807;855;877;853;895;934;900;956;1039;1135;1016;1183;1167;1271;1427;1314;1390;1406;1430;1486;1510;1585;1420;1481;1409;1322;1221;1304;1257;1302;1247;1167;1318;1269;1237;1297;1375;1400;1424;1498;1480;1535;1479;1443;1534;1395;1426;1396;1473;1491;1482;1631;1724;1736;1808;1750;1746;1677;1719;1757;1852;1736;1788;1735;1509;1430;1333;1304;1330;1209;1062;1033;1004;931;918;882;929;896;826;870;807;784;844;830;848;805;765;690;685;658;616;623;580;582;473;517;487;447;511;435;486;484;596;596;618;664;692;638;692;686;671;812;795;769;777;852;841;932;1047;1153;1267;1307;1302;1323;1307;1255;1080;961;743;611;450;361;330;265;220;178;158;155;130;91;88;79;54;61;46;11]直方图均衡化的优点是能自动地增强整个图像的对比度,计算过程中没有用户可以调整的参数。但正因为如此,它的具体增强效果却无法由用户控制,因为处理的结果总是得到全局均衡化的直方图。而实际应用中有时需要修正直方图使之成为某个特定的形状,从而可以有选择的增强图像中某个灰度值范围内的对比度或使图像灰度值的分布满足特定的要求。这时就可以采用相对灵活的直方图规定化;=================*/


 

这个图是第二个代码所使用的图片,对于理解opencv的灰度直方图有帮助;

代码的来源是:

http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/histograms/histogram_equalization/histogram_equalization.html

也可参考的代码有:

http://blog.csdn.net/morewindows/article/details/8364690

http://blog.csdn.net/tercel_zhang/article/details/42423433

另外关于rectangle的两个点的理解,可参考:

http://lib.csdn.net/article/opencv/25688


0 0