opencv知识点:
计算直方图数据 - calcHist
四舍五入浮点数 - cvRound
寻找最小/最大值 - minMaxLoc
本课所解决的问题:
如何绘制HSV图像的二维直方图?
1.二维直方图
上节课中,我们学习了一维直方图的绘制,那我们该如何绘制二维直方图呢?
关于二维直方图的绘制,我们通常选择HSV模式下的图像
我们回顾HSV的知识,可以发现
H(色调)范围是[0,180]
S(饱和度)范围是[0,255]
V(明度)范围是[0,255]
calcHist
计算一维数组的直方图(输入图像可以有多通道)
共10个参数
第1个参数 图像数组
第2个参数 输入图像数量
第3个参数 通道数组
第4个参数 可选mask
第5个参数 输出直方图数据(值与对应频次)的n维数组
第6个参数 直方图维数
当通道为1个时,我们选择维度为1维,此时直方图数据就为一维数组
当维度为2个时,我们选择维度为2维,此时直方图数据就为二维数组
………………
最大支持32维
也就是说,n张图像 每张图像m个通道 可以计算出相应的直方图数据
但对于绘制来说,一般都只绘制到2维,3维及以上就很复杂了
第7个参数 histSize( bins数组,x轴长度)
第8个参数 ranges(取值范围数组)
//以下参数暂时用不到
第9个参数 指示直方图bin间隔是否一致
默认为true,即等间隔取值
如果为false,则range不能写{0,255}这种,就要写{1,1,……,1}这种
第10个参数 累计标志(默认为false)
当多张图像的时候,
如果为true,则绘制直每张方图的时候,不会从头清空
会在前者直方图的基础上继续
cvRound
将浮点数四舍五入到最近的整数
共1个参数
第1个参数 要处理的浮点数
minMaxLoc
寻找最小/最大值
共5个参数
第1个参数 输入
第2个参数 输出的最小值
第3个参数 输出的最大值
第4个参数 最小值下标
第5个参数 最大值下标
本课中计算的直方图维数为2维,采取方式为
示例代码
输出一下
//函数定义
void histogram_2d_demo(Mat& image);
//函数实现
void QuickDemo::histogram_2d_demo(Mat& image) {
// 2D 直方图
Mat hsv, hs_hist;
cvtColor(image, hsv, COLOR_BGR2HSV);
int hbins = 30;
int sbins = 32;
int hist_bins[] = { hbins, sbins };
float h_range[] = { 0, 180 };
float s_range[] = { 0, 256 };
const float* hs_ranges[] = { h_range, s_range };
int hs_channels[] = { 0, 1 };
calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_ranges);
std::cout << hs_hist;
}
二维直方图
//函数实现
void QuickDemo::histogram_2d_demo(Mat& image) {
// 2D 直方图
Mat hsv, hs_hist;
cvtColor(image, hsv, COLOR_BGR2HSV);
int hbins = 30;
int sbins = 32;
int hist_bins[] = { hbins, sbins };
float h_range[] = { 0, 180 };
float s_range[] = { 0, 256 };
const float* hs_ranges[] = { h_range, s_range };
int hs_channels[] = { 0, 1 };
calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_ranges);
std::cout << hs_hist;
double maxVal = 0;//寻找直方图数据中的最大值
minMaxLoc(hs_hist, 0, &maxVal, 0, 0);
int scale = 10;
//行320 列300
Mat hist2d_image = Mat::zeros(sbins * scale, hbins * scale, CV_8UC3);
//h30行,s32列,一行一行的绘制矩形
for (int h = 0; h < hbins; h++) {
for (int s = 0; s < sbins; s++)
{
float binVal = hs_hist.at(h, s);//位于横h,列s处的频次
int intensity = cvRound(binVal * 255 / maxVal);//白色的强度,频次越大,小矩形越接近白色
Point p1(h * scale, s * scale);
/*
矩形左上角的点
*/
Point p2((h + 1) * scale - 1, (s + 1) * scale - 1);
/*
矩形右下角的点
-1只是为了不与其他矩形的左上角重合,不-1差异也不大
*/
rectangle(hist2d_image, p1, p2, Scalar::all(intensity), -1);
}
}
//灰色的图像不容看出差异,这里我们转换色彩风格
applyColorMap(hist2d_image, hist2d_image,COLORMAP_DEEPGREEN);
imshow("H-S Histogram", hist2d_image);
}