绘制RGB三色直方图

版权声明:本文为博主原创文章,转载请标明出处! https://blog.csdn.net/qq_27396861/article/details/87822860

计算直方图:calcHist()函数
用于计算一个或者多个阵列的直方图。

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 )

1)const Mat类型的images,输入的数组(或数组集),它们需为相同的深度(CV_8U或CV_32F)和相同的尺寸;
2)int类型的nimages,输入数组的个数,也就是第一个参数中存放了多少张“图像”,有几个原数组;
3)const int
类型的channels,需要统计的通道(dim)索引。第一个数组通道从0到images[0].channels() - 1,而第二个数组通道从images[0].channels()计算到images[0].channels() + images.channels() - 1;
4)InputArray类型的mask,可选的操作掩码。如果此掩码不为空,那么它必须为8位,并且与images[i]有同样大小的尺寸。这里的非零掩码元素用于标记出统计直方图的数组元素数据;
5)OutputArray类型的hist,输出的目标直方图,一个二维数组;
6)int类型的dims,需要计算的直方图的维度,必须是正数,且不大于CV_MAX_DIMS;
7)const int*类型histSize,存放每个维度的直方图尺寸的数组;
8)const float**类型ranges,表示每一个维度数组(第六个参数dims)的每一维的边界阵列,可以理解为每一维数值的取值范围;
9)bool类型的uniform,指示直方图是否均匀的标识符,有默认值true;
10)bool类型的accumulate,累计标识符,有默认值false。若其为true,直方图在配置阶段不会被清零。此功能主要是允许从多个阵列中计算单个直方图,或者用于在特定的时间更新直方图;

找寻最值:minMaxLoc()函数
作用是在数组中找到全局最小值和最大值。

void minMaxLoc( InputArray src, double* minVal, double* maxVal = 0,
    Point* minLoc = 0, Point* maxLoc = 0, InputArray mask = noArray() )

InputArray类型的src,输入的单通道阵列;
double类型的minVal,返回最小值的指针。若无须返回,此值为NULL;
double
类型的maxVal,返回的最大值的指针。若无须返回,此值为NULL;
Point类型的minLoc,返回最小位置的指针(二维情况下)。若无须返回,此值为NULL;
Point
类型的maxLoc,返回最大位置的指针(二维情况下)。若无须返回,此值为NULL;
InputArray类型的mask,用于选择子阵列的可选掩膜;

#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;

int main()
{
	Mat srcImage = imread("lantian.jpg");

	int bins = 256;
	int hist_size[] = {bins};
	float range[] = {0, 255};
	const float* ranges[] = { range };
	MatND redHist, greenHist, blueHist;

	// 红色部分直方图计算
	int channels_r[] = {0};
	calcHist(&srcImage, 1, channels_r, Mat(), redHist, 1, hist_size, ranges);

	// 绿色部分直方图计算
	int channels_g[] = {1};
	calcHist(&srcImage, 1, channels_g, Mat(), greenHist, 1, hist_size, ranges);

	// 蓝色部分直方图计算
	int channels_b[] = {2};
	calcHist(&srcImage, 1, channels_b, Mat(), blueHist, 1, hist_size, ranges);

	// 求最大值
	double maxValue_red, maxValue_green, maxValue_blue;
	minMaxLoc(redHist, 0, &maxValue_red, 0, 0);
	minMaxLoc(greenHist, 0, &maxValue_green);
	minMaxLoc(blueHist, 0, &maxValue_blue);
	printf("maxValue_red = %f, maxValue_green = %f, maxValue_blue = %f\n", maxValue_red, maxValue_green, maxValue_blue);

	int scale = 256;
	double rate_red = (scale / maxValue_red) * 0.9;
	double rate_green = (scale / maxValue_green) * 0.9;
	double rate_blue = (scale / maxValue_blue) * 0.9;
	
	Mat dstImage = Mat::zeros(scale, scale*3, CV_8UC3);
	// 开始绘制
	for (int i = 0; i < bins; i++)
	{
		float binValue_red = redHist.at<float>(i);
		float binValue_green = greenHist.at<float>(i);
		float binValue_blue = blueHist.at<float>(i);
		
		//绘制红色分量
		line(dstImage, Point(i, scale), Point(i, scale - binValue_red * rate_red), Scalar(0, 0, 255));
		//绘制绿色分量
		line(dstImage, Point((i+bins), scale), Point(i + bins, scale - binValue_green * rate_green), Scalar(0, 255, 0));
		//绘制蓝色分量
		line(dstImage, Point((i + 2*bins), scale), Point(i + 2*bins, scale - binValue_blue * rate_blue), Scalar(255, 0, 0));
	}

	imshow("srcImage", srcImage);
	imshow("图像RGB直方图", dstImage);

	waitKey(0);
	return 0;
}

运行效果:
源图片
处理后的图片

猜你喜欢

转载自blog.csdn.net/qq_27396861/article/details/87822860