《opencv学习笔记二》opencv中绘制直方图之归一化处理统计结果

opencv中用calHist函数得到直方图信息后,需要将其绘制出来,但是有些像素点的统计次数可能几千次甚至上万次,为了将其在一个预先确定大小的图(设为dstImage)中绘制出来,需要将得到的直方图各个像素点的次数归一化到 [o,dstImage.rows] 这个范围内,再进行绘制。

可以使用函数:
C++: void normalize(InputArray src, InputOutputArray dst, double alpha=1, double 	    beta=0, int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray() )
结合修改的官方参考程序进行解释。

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

  using namespace std;
  using namespace cv;

int main(int argc, char** argv){
	Mat srcImage = imread("miao.png", 0);
	imshow("hi", srcImage);
	if (srcImage.empty())cout << "source image is empty" << endl;

	MatND dstHist;
	float hrange[] = { 0, 255 };				//所有的的灰度值范围
	const float* ranges[] = { hrange };
	int dims = 1;	
	int size = 256;	
	/*如果是彩色图像的话,传入的参数可以是 [0], [1], [2] 它们分别对应着通道 B, G, R。*/ 
	int channels = 0;	//如果输入图像是灰度图,它的值就是 [0];	
	//输出的直方图dstHist   为一个一维数组[1*256]  其值为灰度值[0-256]对应点的出现频次
	calcHist(&srcImage, 1, &channels, Mat(), dstHist, dims, &size, ranges);   
	//直方图绘制
	int scale = 1;
	int hist_h = scale*size, hist_w = size;
	int bin_w= hist_w/size;							//即bin_w=1;
	Mat dstImage(hist_h, hist_w, CV_8U, Scalar(0));	//展示直方图的图纸的大小,颜色为黑色
	//将 dstHist 归一化到[0,dstHist.rows]
	normalize(dstHist, dstHist, 0, dstHist.rows, NORM_MINMAX, -1, Mat());//归一化结果存在dstHist
	/*这个for循环可以遍历下归一化后的直方图统计数值,看看是不是都在指定范围内*/
	for (int i = 0; i < size; i++){
		cout << cvRound(dstHist.at<float>(i)) << endl;
	}
	for (int i = 1; i < size; i++){
		line(dstImage, 
			Point(bin_w*(i - 1), hist_h-cvRound(dstHist.at<float>(i - 1))),
			Point(bin_w*(i),  hist_h-cvRound(dstHist.at<float>(i))),
			Scalar(255, 255, 255), 2, 8, 0);
	}
	imshow("1-Dhistogram ", dstImage);
	waitKey(0);
	return 0;
}

效果如图:

当然对于归一化处理官方参考的程序里还提供了另一种人工计算方式,在此一并给出。

int scale = 1;
Mat dstImage (size*scale, size, CV_8U, Scalar(0));		//直方图   h=size*scale, w=size;  
double minValue = 0;
double maxValue = 0;
minMaxLoc(dstHist, &minValue, &maxValue, 0, 0);
//绘制直方图方法一
for (int i = 0; i < size; i++){
	float binValue = dstHist.at<float>(i);				  //依次取出0-256个灰度值
	int realValue  = saturate_cast<int>(binValue*256 / maxValue);
	rectangle(dstImage,
		Point(scale*i, size - 1),
		Point(scale*(i + 1) - 1, size - realValue),
		Scalar(255));
		cout << "i::" << i << "\tbinValue:" << binValue << "\trealValue:" << realValue << endl;
}

可将这个计算得到的统计次数与上面方法一得到的统计次数进行比较,会发现二者是一致的,数据相同。其直方图为:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值