opencv#25 直方图均衡化

本节将介绍如何根据图像的直方图对图像的亮度进行调整。也就是均衡化。

通过图像直方图,我们可以判断图像是否过暗或过亮,当图像直方图过多的集中在灰度值较小的区域时,那么它所表示的是图像存在过暗的情况,反之过亮。就会导致图像中的纹理信息没办法很好的显示。

像素距离拉伸

例如我想拉大较小值的灰度值区域,那么我们可以将较小值的灰度值区域斜率调大(改变x与y的映射关系,比如幂函数的形式)。

equalizeHist()

vodi cv::equalizeHist(InputArray    src,
                      OutputArray   dst
                     )

·src:需要直方图均衡化的CV_8UC1图像(只有处理单通道图像才涉及到均衡化,若是彩色图像,要先转化为灰度图像)。

·dst:直方图均衡化后输出图像,与src具有相同尺寸和数据类型。

#include 
#include 

using namespace cv; //opencv的命名空间
using namespace std;

void drawHist(Mat &hist, int type, string name)//归一化并绘制直方图函数
{
	int hist_w = 512;
	int hist_h = 400;
	int width = 2;
	Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);
	normalize(hist, hist, 1, 0, type, -1, Mat());
	for (int i = 1; i <= hist.rows; i++)
	{
		rectangle(histImage, Point(width * (i - 1), hist_h - 1),
			Point(width * i - 1, hist_h - cvRound(hist_h * hist.at(i - 1)) - 1),
			Scalar(255, 255, 255), -1);
	}
	imshow(name, histImage);
}

//主函数
int main()
{
	Mat img = imread("E:/opencv/opencv-4.6.0-vc14_vc15/opencv/xyp.jpg");
	if (img.empty())
	{
		cout << "请确认图像文件名称是否正确" << endl;
		return -1;
	}
	Mat gray,hist,hist2;
	cvtColor(img, gray, COLOR_BGR2GRAY); //转为灰度图像,只有一个通道
	Mat equalimg;
	
	equalizeHist(gray, equalimg);//将图像直方图均衡化

	const int channels[1] = { 0 };
	float inRanges[2] = { 0,255 };
	const float* ranges[1] = { inRanges };
	const int bins[1] = { 256 };

	calcHist(&gray, 1, channels, Mat(), hist, 1, bins, ranges);//计算原图像直方图
	calcHist(&equalimg, 1, channels, Mat(), hist2, 1, bins, ranges);//计算均衡化后图像直方图

	//绘制直方图
	drawHist(hist, NORM_INF, "hist");
	drawHist(hist2, NORM_INF, "hist2");


	imshow("原图", gray);
	imshow("均衡化后的图像",equalimg);



	waitKey(0);//等待函数用于显示图像
	return 0;

}

均衡化后的图像能够较为清晰的看到原先图像中所不能看清的纹理,很好的提高了图像的纹理展示,也能够让我们更好的了解图像中的信息,均衡化后的直方图分布将最大值分布更多的集中在中心区域。

你可能感兴趣的:(计算机视觉,图像处理,人工智能)