本次案例将为大家介绍直方图计算和直方图均衡化,直方图的计算非常有用,在很多场合下都可以用上,不仅仅是在图像的灰度值上,还可能是在图像的其他特征上;图像的均衡化在图像预处理时经常被用到,它可以增强对比度,使得像素强度分布范围更广。

1、原理

直方图计算:

直方图均衡化:

学习OpenCV:

2、代码实现

程序功能:

①输入一张图片,分解图像的三个通道,对三个通道进行直方图计算,并显示出来

②分解图像的三个通道,对三个通道进行直方图均衡,再合并三个通道,最后显示图像和直方图计算图像

#include "stdafx.h"

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>

using namespace std;
using namespace cv;

Mat calchistcontrol(vector<Mat> rgb);
void draw(Mat hist,int histSize,Mat histImage,int bin_w,int hist_h,int rgb);
/** @函数 main */
int main( int argc, char** argv )
{
	Mat src, dst,rgb_merge,histImage,histImage1;
	/// 装载图像
	src = imread("scenery2.jpg" , 1 );
	imshow("source_image",src);

	if( !src.data )
	{ return -1; }

	/// 分割成3个单通道图像 ( R, G 和 B )
	vector<Mat> rgb_planes;
	split( src, rgb_planes );

	///直方图计算
	histImage=calchistcontrol(rgb_planes);

	///三个通道直方图均衡化
	vector<Mat> rgb_planes1;
	split(src,rgb_planes1);
	equalizeHist(rgb_planes1[0],rgb_planes1[0]);
	equalizeHist(rgb_planes1[1],rgb_planes1[1]);
	equalizeHist(rgb_planes1[2],rgb_planes1[2]);

	///三个通道直方图均衡化后直方图计算
	histImage1=calchistcontrol(rgb_planes1);

	///合并三通道
	merge(rgb_planes1,rgb_merge);

	/// 显示直方图
	imshow("calcHist Demo", histImage );
	imshow("calcHist Demo1",histImage1);
	imshow("rgb_merge",rgb_merge);

	waitKey(0);

	return 0;

}
Mat calchistcontrol(vector<Mat> rgb)
{

	vector<Mat> rgb_planes;
	rgb_planes=rgb;
	/// 设定bin数目
	int histSize = 255;

	/// 设定取值范围 ( R,G,B) )
	float range[] = { 0, 255 } ;
	const float* histRange = { range };

	bool uniform = true; bool accumulate = false;

	Mat r_hist, g_hist, b_hist;

	/// 计算直方图:
	calcHist( &rgb_planes[0], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );
	calcHist( &rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
	calcHist( &rgb_planes[2], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );

	// 创建直方图画布
	int hist_w = 400; int hist_h = 400;
	int bin_w = cvRound( (double) hist_w/histSize );

	Mat histImage( hist_w, hist_h, CV_8UC3, Scalar( 0,0,0) );

	/// 将直方图归一化到范围 [ 0, histImage.rows ]
	normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
	normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
	normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );

	/// 在直方图画布上画出直方图
	draw(r_hist,histSize,histImage,bin_w,hist_h,1);
	draw(g_hist,histSize,histImage,bin_w,hist_h,2);
	draw(b_hist,histSize,histImage,bin_w,hist_h,3);
	return histImage;
}
void draw(Mat hist,int histSize,Mat histImage,int bin_w,int hist_h,int rgb)
{
	Scalar a;
    switch(rgb)
	{
	case 1: a=Scalar(0,0,255);break;
	case 2: a=Scalar(0,255,0);break;
	case 3: a=Scalar(255,0,0);break;
	}
	int flag=1,first;
		for( int i = 0; i < histSize; i++ )
	{  
		if (flag==1)
	{
		if (cvRound(hist.at<float>(i)!=0))
		{
			flag=2;
			first=i;
		}
		else
		{
			i++;
		}
	}
		else
		{
			if (cvRound(hist.at<float>(i)!=0))
			{
			line( histImage, Point( bin_w*(first), hist_h - cvRound(hist.at<float>(first)) ) ,
			      Point( bin_w*(i), hist_h - cvRound(hist.at<float>(i)) ),
			      a, 2, 8, 0  );
			first=i;
			}
			else
			{
				i++;
			}
		}

	}
}

3、运行结果

直方图均衡化 rgb 直方图均衡化计算_equalizeHist


                                  图1、源图像

直方图均衡化 rgb 直方图均衡化计算_直方图均衡化 rgb_02

                                      图2、合并图像

直方图均衡化 rgb 直方图均衡化计算_calcHist_03

  

直方图均衡化 rgb 直方图均衡化计算_equalizeHist_04

        图3、源图像直方图                     图4、合并图像直方图

4、用到的类和函数

calcHist

功能:计算图像 的直方图

结构:

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

arrays :源图像集,他们都需要有同样的depth,CV_8U或者CV_32F,同样的size,可以有任意的通道数

narrays :输入图像的个数

channels :需要统计的通道 (dim)索引

mask :掩码( 0 表示忽略该像素), 如果未定义,则不使用掩码,如果不为null,则只有与mask非零元素对应的像素点会被包含在计算直方图当中。

hist :输出直方图数组,是一个 dims 维的数组

dims :直方图的维数

histSize :直方图的大小,即每个维度的bin数目

ranges:每个维度的取值范围

uniform 、accumulate: bin大小相同,清除直方图痕迹

hist.at<float>(i)表示第i个bin中所保存的统计数量

equalizeHist

功能:灰度图象直方图均衡化

结构:

void equalizeHist(InputArray src, OutputArray dst)

src:源图像,8bit单通道图片

dst:目标图像,和源图像有同样的size和type

操作:

①、计算src的直方图H

②、归一化直方图,使得H中bins的和为255;

③、计算直方图积分

                               直方图均衡化 rgb 直方图均衡化计算_equalizeHist_05

④、采用H'作为查询表进行变换:直方图均衡化 rgb 直方图均衡化计算_直方图均衡_06

该方法归一化图像亮度和增强对比度。