OpenCV学习笔记(九)之直方图均衡化(图像增强)

图像直方图

1、图像直方图介绍

  图像直方图(Image Histogram)是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数。可以借助观察该直方图了解需要如何调整亮度分布。这种直方图中,横坐标的左侧为纯黑、较暗的区域,而右侧为较亮、纯白的区域。因此,一张较暗图片的图像直方图中的数据多集中于左侧和中间部分;而整体明亮、只有少量阴影的图像则相反,数据多集中在右侧和中间部分。很多数码相机提供图像直方图功能,拍摄者可以通过观察图像直方图了解到当前图像是否过分曝光或者曝光不足。计算机视觉领域常借助图像直方图来实现图像的二值化,其是图像像素值的统计学特征、计算代价较小,具有图像平移、旋转、缩放不变性等众多优点,广泛地应用于图像处理的各个领域,特别是灰度图像的阈值分割、基于颜色的图像检索以及图像分类、反向投影跟踪。常见的分为“灰度直方图”和“颜色直方图”这两种。
下图是OpenCV中的图像直方图测试结果:
OpenCV学习笔记(九)之直方图均衡化(图像增强)_第1张图片
  直方图中横坐标为灰度值级数,以8位单通道的灰度图像为例,其横坐标范围为【0~255】的闭区间;纵坐标为图像在每个灰度级的像素数,一般要做归一化处理。

2、OpenCV中计算直方图的API函数

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 );

每个参数具体含义如下:

  • images,输入图像,其深度可以为 CV_8U 或 CV_16U 或 CV_32F;
  • nimages ,要计算直方图的图像的个数,此函数可以为多图像求直方图,我们通常情况下都只作用于单一图像,所以通常nimages=1;
  • channels,图像的通道是一个数组,如果是灰度图像则 channels[1]={0}; 如果是彩色图像则 channels[3]={0,1,2};如果只是求彩色图像第2个通道的直方图则channels[1]={1};
  • mask,可选的掩码,不使用时可设为空,即 Mat()。必须要和输入图像具有相同的大小,在进行直方图计算的时候,只会统计该掩码不为0的对应像素;
  • hist,输出的直方图;
  • dims,得到的直方图的维数,灰度图像为1维,彩色图像为3维;
  • histSize,直方图横坐标的区间数,如果是10,则它会横坐标分为10份,然后统计每个区间 ranges 的像素点总和,为了得到最为精确的直方图,假设像素值取值在0~255之间,则将其设置为256得到的直方图就很精确;
  • ranges,直方图每个维度要统计的灰度级的范围,对于8位图像来说,其范围为 [0,255] 的任意区间;
  • uniform,是否对得到的直方图数组进行归一化处理,默认为true;
  • accumulate,累积标志,在多个图像时,是否累计计算像素值的个数,默认值为false。

直方图均衡化

1、直方图均衡化介绍

  图像直方图均衡化可以用于图像增强、对输入图像进行直方图均衡化处理,提升后续对象检测的准确率,在OpenCV人脸检测的代码演示中已经很常见。此外对医学影像图像与卫星遥感图像也经常通过直方图均衡化来提升图像质量。简单来说,就是通过调整图像的灰阶分布,使得像素点在0~255灰阶上的分布更加均衡,提高了图像的对比度,达到改善图像主观视觉效果的目的。对比度较低的图像适合使用直方图均衡化方法来增强图像细节。
下图是OpenCV中的图像直方图均衡化测试结果:

可以看出,上图中左侧对比度较低的图像经过直方图均衡化处理后就变为了右侧对比度比较强的图像。

2、OpenCV中计算直方图均衡化的API函数

CV_EXPORTS_W void equalizeHist( InputArray src, OutputArray dst );

使用方法比较简单,每个参数具体含义如下:

  • src,输入图像,其必须为8位单通道灰度图;
  • dst,输出图像,大小和深度与 src 一致;

代码实现

// HistogramEqualization.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include 
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
	Mat srcImage, GrayImage, GrayHisEquImg, GrayHisImg, GrayEquImg, Histogram1, Histogram2;
	srcImage = imread("star.jpg");
	if (nullptr == srcImage.data)
	{
		cout << "图片加载失败!" << endl;
		return 0;
	}
	cvtColor(srcImage, GrayImage, COLOR_BGR2GRAY);  //转换灰度图
	/*直方图均衡化*/
	GrayHisEquImg.create(GrayImage.rows, GrayImage.cols, GrayImage.type());
	GrayHisEquImg.setTo(0);
	equalizeHist(GrayImage, GrayHisEquImg);

	/** 创建直方图,一维, 每个维度上均分 */
	int HisImgWidth = 512;
	int HisImgHeight = 400;
	const int bins = 256;
	float range[] = { 0, 255 };
	const float *ranges[] = { range };
	const int channel = 0;
	GrayHisImg.create(HisImgHeight, HisImgWidth, CV_8UC1);
	GrayHisImg.setTo(255);
	GrayEquImg.create(HisImgHeight, HisImgWidth, CV_8UC1);
	GrayEquImg.setTo(255);

	calcHist(&GrayImage, 1, &channel, Mat(), Histogram1, 1, &bins, ranges, true, false);
	calcHist(&GrayHisEquImg, 1, &channel, Mat(), Histogram2, 1, &bins, ranges, true, false);
	// 归一化直方图数据
	normalize(Histogram1, Histogram1, 0, GrayHisImg.rows, NORM_MINMAX, -1, Mat());
	normalize(Histogram2, Histogram2, 0, GrayEquImg.rows, NORM_MINMAX, -1, Mat());
	// 绘制柱状直方图
	for (int i = 1; i < bins; i++)
	{
		rectangle(GrayHisImg, Point(2*(i-1), HisImgHeight - 1), Point(2*i, HisImgHeight - cvRound(Histogram1.at<float>(i-1))), Scalar(0, 0, 0), 2, 8, 0);
		rectangle(GrayEquImg, Point(2*(i-1), HisImgHeight - 1), Point(2*i, HisImgHeight - cvRound(Histogram2.at<float>(i-1))), Scalar(0, 0, 0), 2, 8, 0);
	}
	
	namedWindow("src");
	namedWindow("GrayImage");
	namedWindow("GrayHisEquImg");
 	namedWindow("GrayHisImg");
 	namedWindow("GrayEquImg");
	imshow("src", srcImage);
	imshow("GrayImage", GrayImage);
	imshow("GrayHisEquImg", GrayHisEquImg);
	imshow("GrayHisImg", GrayHisImg);
	imshow("GrayEquImg", GrayEquImg);

	while (true)
	{
		if (waitKey(10) == 27)
		{
			break;
		}
	}
	destroyAllWindows();
	return 1;
}

最后来两张完整的测试图片
直方图均衡化前后图像:

直方图均衡化前后直方图图像:
OpenCV学习笔记(九)之直方图均衡化(图像增强)_第2张图片

你可能感兴趣的:(OpenCV学习笔记)