基于C++的OpenCV4入门基础–图像的灰度直方图

不管现实多么惨不忍睹,都要持之以恒地相信,这只是黎明前短暂的黑暗而已。不要惶恐眼前的难关迈不过去,不要担心此刻的付出没有回报,别再花时间等待天降好运。真诚做人,努力做事!你想要的,岁月都会给你。基于C++的OpenCV4入门基础–图像的灰度直方图,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

图像直方图是反映图像像素分布的统计表,横坐标代表像素值的取值区间,纵坐标代表每一像素值在图像中的像素总数或者所占的百分比。 灰度直方图是图像灰度级的函数,用来描述每个灰度级在图像矩阵中的像素个数。

灰度直方图反映了图像中的灰度分布规律,直观地表现了图像中各灰度级的占比,很好地体现出图像的亮度和对比度信息:灰度图分布居中说明亮度正常,偏左说明亮度较暗,偏右表明亮度较高;狭窄陡峭表明对比度降低,宽泛平缓表明对比度较高。

根据直方图的形态可以判断图像的质量,通过调控直方图的形态可以改善图像的质量。
直方图和addWeight方法都可以改善图像亮度和对比度。
直方图比较可以判断图像的相似度。

OpenCV 提供了函数 cv2.calcHist 可以计算直方图,Numpy 中的函数 np.bincount 也可以实现同样的功能。

CV_EXPORTS void calcHist( const Mat* images, int nimages,
                          const int* channels, InputArray mask,
                          OutputArray hist, int dims, const int* histSize,
                          const float** ranges, bool uniform = true, bool accumulate = false );

函数 cv2.calcHist 可以计算一维直方图或二维直方图,函数的参数 images, channels, histSize, ranges 在计算一维直方图时也要带 [] 号。

参数说明:
images:输入图像,用 [] 括号表示数组
channels: 直方图计算的通道,用 [] 括号表示
mask:掩模图像,一般置为 None
histSize:直方柱的数量,一般取 256
ranges:像素值的取值范围,一般为 [0,256]
返回值 hist:返回每一像素值在图像中的像素总数,形状为 (histSize,1)
注意:
1.参数 images, channels, histSize, ranges 都要带 [] 号。
2.mask 是与 images 大小相同的掩模图像,掩模为 0 的区域不作处理。不使用掩模时设为 None。
3. channels 设置对彩色图像的指定通道计算直方图,灰度图像时设为 0。
4. Numpy 中的函数 np.bincount 也可以实现同样的功能,但该函数返回值的形状为 (histSize,)

1,图像直方图概念
在这里插入图片描述
那么,对于我们的图像直方图统计来说,对于 RGB 彩色图,像素值的范围是0~255,那么像素等级就有256个等级,也就是bin的个数是256,当然bin的个数也可以根据需要进行设置,例如设置16个bin,那么每个bin的范围是0-15

2,统计并绘制直方图:
对与 RGB 彩色图像我们通过通道分离,对每一个图像通道进行直方图统计,并绘制统计直方图,绘制通过直线实现,其中前后两个点分别是相邻两个bin

	Mat src = imread("F:/code/images/yuan_test.png");
	if (src.empty()) {
		printf("fail to read");
		return -1;
	}
	namedWindow("input", WINDOW_AUTOSIZE);
	imshow("input", src);

	//通道分离
	vector<Mat> mv;
	split(src, mv);

	//直方图计算
	
	//设定像素取值范围
	int histSize = 256;//像素等级数,也就是bin的个数
	float range[] = { 0,255 };//需要统计的像素值范围
	const float* histRanges = { range };

	//三个通道分别计算直方图
	Mat b_hist, g_hist, r_hist;//统计后输出的 Mat
	
	calcHist(&mv[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRanges, true, false);
	calcHist(&mv[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRanges, true, false);
	calcHist(&mv[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRanges, true, false);

	//创建直方图画布并归一化处理
	Mat histImage = Mat::zeros(Size(600, 400), CV_8UC3);
	int margin = 50;
	int nm = histImage.rows - 2*margin;//像素直方图统计值显示的最大值
	float bh = (float)(histImage.cols - 2*margin) / (float)histSize;//每个 bin 的宽度

	normalize(b_hist, b_hist, 0, nm, NORM_MINMAX, -1, Mat());//使用最小值和最大值进行归一化处理,最小值是0,最大值是nm
	normalize(g_hist, g_hist, 0, nm, NORM_MINMAX, -1, Mat());
	normalize(r_hist, r_hist, 0, nm, NORM_MINMAX, -1, Mat());

	//绘制前后两个统计点
	for (int i = 0; i < histSize - 1; i++) {
		line(histImage, Point( i * bh + margin, nm - b_hist.at<float>(i) + margin ),
			Point((i + 2) * bh + margin, nm - b_hist.at<float>(i+1) + margin), Scalar(255,0,0), 1, LINE_AA);
		line(histImage, Point(i * bh + margin, nm - g_hist.at<float>(i) + margin),
			Point((i + 2) * bh + margin, nm - g_hist.at<float>(i + 1) + margin), Scalar(0, 255, 0), 1, LINE_AA);
		line(histImage, Point(i * bh + margin, nm - r_hist.at<float>(i) + margin),
			Point((i + 2) * bh + margin, nm - r_hist.at<float>(i + 1) + margin), Scalar(0, 0, 255), 1, LINE_AA);
	}

	namedWindow("histImage", WINDOW_AUTOSIZE);
	imshow("histImage", histImage);

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/182017.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!