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

#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 window
		y--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 array
	minMaxLoc(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


  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值