在opencv中,绘制彩色图片的三个通道的图像直方图

1、绘制图像直方图的步骤

  • 调用split函数,将彩色图像的通道进行分离
  • 调用calcHist函数,返回Mat类型的向量
  • 如果要在特定长宽的图像中显示图像直方图,需要进行归一化操作
  • 在for循环中绘制直线

2、具体函数讲解

(1) split()函数

split(InputArray src, OutputArray dst);
其中:
    第一个参数src:是指输入的图像
    第二个参数dst:是指输出的数组或者是向量(vector类型)

如果可以用一个动作形容调用该函数的话,我习惯称之为削土豆。 

(2)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 )

其中:
    第一个参数images:输入应当是一个数组(图像的地址)
    第二个参数nimages:是指输入数组(图像地址)的个数
    第三个参数channels:指通道数
    第四个参数mask:掩膜
    第五个参数hist:输出的图像直方图,一个二维数组
    第六个参数dims:直方图的维数
    第七个参数histSize:应当是一个指针,指向一个保存直方图尺寸的变量(例如int *histSize = 256)
    第八个参数ranges:应当是一个指向指针的指针,具体含义是指直方图的范围(比如[0, 256])

(3)normalize()函数

void normalize(InputArray src,OutputArraydst, double alpha = 1, double beta = 0, intnorm_type = NORM_L2, int dtype = -1, InputArray mask = noArray());
 
其中:
    第一个参数src:输入图像
    第二个参数dst:输出图像
    第三参数alpha:输出的最小值
    第四个参数beta:输出的最大值
    第五个参数norm_type:归一化的类型,类型包括NORM_INF,NORM_L1,NORM_L2,NORM_MINMAX等
    第六个参数dtype:默认值-1,当参数为负数时,输出矩阵和src有同样的类型,否则,它和src有同样的通道数。
    第七个参数mask:掩膜

3、完整代码

(1) 源图

(2) 效果图

完整代码如下:

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

int main(int argc, char ** argv) {
	Mat srcImage = imread("1.jpg");
	if (!srcImage.data) {
		printf("could not load this picture!\n");
		return -1;
	}
	imshow("源图像", srcImage);
	//调用split函数,将图像的通道进行拆分
	vector<Mat> channels;
	split(srcImage, channels);
	int histsize = 256;
	float range[] = { 0, 256 };
	const float * histRange = { range };
	Mat b_hist, r_hist, g_hist;
	calcHist(&channels[0], 1,0, Mat(), b_hist, 1,&histsize, &histRange);
	calcHist(&channels[1], 1, 0, Mat(), g_hist, 1, &histsize, &histRange);
	calcHist(&channels[2], 1, 0, Mat(), r_hist, 1,  &histsize, &histRange);

	//创建相关变量
	int hist_w = 512;
	int hist_h = 400;
	int bins = cvRound((double)hist_w / histsize);
	Mat histImage = Mat(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0));

	//归一化处理
	normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
	normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
	normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

	//画图
	//绘制的是离散的图形,曲线并没有连在一起
	//for (size_t i = 0;i < histsize -1; i++) {
	//	//画蓝色通道的直方图
	//	line(histImage, Point(bins * i, hist_h - cvRound( b_hist.at<float>(i))),
	//		Point(bins * i, hist_h - cvRound(b_hist.at<float>(i + 1))), Scalar(0, 0, 255), 2, LINE_AA);
	//	//画绿色通道的直方图
	//	line(histImage, Point(bins * i, hist_h - cvRound( g_hist.at<float>(i))),
	//		Point(bins * i, hist_h - cvRound( g_hist.at<float>(i + 1))), Scalar(0, 255, 0), 2, LINE_AA);
	//	//画红色通道的直方图
	//	line(histImage, Point(bins * i, hist_h - cvRound( r_hist.at<float>(i))),
	//		Point(bins * i, hist_h - cvRound(r_hist.at<float>(i + 1))), Scalar(255, 0, 0),2, LINE_AA);
	//}
	//方法二
	//绘制的是连续的图形,和第一种的主要区别就是在绘图时取的第二个点的x不同
	for (size_t i = 0; i < histsize -1; i++) {
		line(histImage, Point(bins * i, hist_h - cvRound(b_hist.at<float>(i))),
			Point(bins * (i+1), hist_h - cvRound(b_hist.at<float>(i + 1))), Scalar(0, 0, 255), 1, LINE_AA);
		line(histImage, Point(bins * i, hist_h - cvRound(g_hist.at<float>(i))),
			Point(bins * (i + 1), hist_h - cvRound(g_hist.at<float>(i + 1))), Scalar(0, 255, 0), 1, LINE_AA);
		line(histImage, Point(bins * i, hist_h - cvRound(r_hist.at<float>(i))),
			Point(bins *(i + 1), hist_h - cvRound(r_hist.at<float>(i + 1))), Scalar(255, 0, 0), 1, LINE_AA);
	}
	imshow("图像直方图", histImage);
	waitKey(0);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值