项目功能实现:对一张彩色图像进行二维直方图绘制
二维直方图通常在HSV色域空间进行处理
按照之前的博文结构来,这里就不在赘述了
一、头文件
histogram_2d.h
#pragma once
#include<opencv2/opencv.hpp>
using namespace cv;
class HISTOGRAM2D {
public:
void histogram_2d(Mat& image);
};
#pragma once
二、函数实现
histogram_2d.cpp
Mat hsv, hs_hist;
hsv用于存储转到HSV色域空间的对象信息
hs_hist用于存储直方图数据信息
cvtColor(image, hsv, COLOR_BGR2HSV);
二维直方图通常都转到HSV色域空间中进行处理,其中S:0-255,H:0-180
int hbins = 30, sbins = 32;
H范围0-180,分为30个间隔
S范围0-255,分为32个间隔
bin相当于直方图中的一个柱体
calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_ranges, true, false);
参数一:要处理图片的指针,这里传入的是转到HSV色域空间的hsv对象
参数二:输入图像的个数,这里只处理一张图片,故为1
参数三:需要统计直方图的第几个通道,
参数四:掩模,mask必须是一个8位(CV_8U)的数组并且和images的数组大小相同,这里Mat()
表示对图片本身进行处理即可
参数五:直方图计算的结果,通过hs_hist接收
参数六:输出直方图的维度,这里是二维
参数七:直方图中每个dims维度需要分成多少个区间
参数八:统计像素值的区间,0-255
参数九:是否对得到的直方图数组进行归一化处理
参数十:多个图像时,是否累积计算像素值的个数
Mat hist2d_image = Mat::zeros(sbins * scale, hbins * scale, CV_8UC3);
创建画布对象hist2d_image
rectangle(hist2d_image, Point(h * scale, s * scale), Point((h + 1) * scale - 1, (s + 1) * scale - 1), Scalar::all(intensity), -1);
根据参数信息绘制矩形即可,也就是bin,一个个柱体
applyColorMap(hist2d_image,hist2d_image,COLORMAP_JET);
二维的直方图是灰度的,可以转换成自定义彩色图片进行显示
详细可参考博文:九、OpenCV自带colormap
#include"histogram_2d.h"
#include<iostream>
#include<opencv2/opencv.hpp>
void HISTOGRAM2D::histogram_2d(Mat& image) {
//2D直方图
Mat hsv, hs_hist;
cvtColor(image, hsv, COLOR_BGR2HSV);//先转换到HSV色域空间、S:0-255,H:0-180
int hbins = 30, sbins = 32;//0-180分为30个间隔、0-255分为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, true, false);
double maxVal = 0;//存储二维直方图中最大值
minMaxLoc(hs_hist, 0, &maxVal, 0, 0);//归一化
int scale = 10;
Mat hist2d_image = Mat::zeros(sbins * scale, hbins * scale, CV_8UC3);//创建画布
for (int h = 0; h < hbins; h++) {
for (int s = 0; s < sbins; s++) {
float binVal = hs_hist.at<float>(h, s);
int intensity = cvRound(binVal * 255 / maxVal);
rectangle(hist2d_image, Point(h * scale, s * scale), Point((h + 1) * scale - 1, (s + 1) * scale - 1), Scalar::all(intensity), -1);
}
}
applyColorMap(hist2d_image,hist2d_image,COLORMAP_JET);
imshow("hist2d_image",hist2d_image);
}
三、主函数
yy_main.cpp
#include <opencv2/opencv.hpp>
#include <iostream>
#include "histogram_2d.h"
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src = cv::imread("E:/C++_workspace/beyond.jpg", IMREAD_COLOR);
if (src.empty()) {
printf("load image is false...\n");
return -1;
}
namedWindow("yanyu", WINDOW_FREERATIO);
imshow("yanyu", src);
HISTOGRAM2D yy;
yy.histogram_2d(src);
waitKey(0);
destroyAllWindows();
return 0;
}
项目结构如下:
运行结果如下: