25-直方图计算
文章目录
直方图计算(Histogram)
1、直方图概念;
2、相关API;
3、代码演示;
直方图
1、直方图:像素值经统计得到的图像;一切图像的属性值,都可以建立直方图,基于图像像素的灰度直方图是最常见的;
2、直方图的属性:
- dims : 维度(通道值)
- bins : 表示在维度中子区域大小的划分,如上图;
- range : 表示值的范围;
相关API
1、API : split()
: 将多通道图像分为多个单通道图像;
split(
const Mat & src, //输入的多通道图像
Mat* mvbegin // 输出的单通道图像数组
)
2、API : calcHist()
: 计算直方图
直方图显示
Code
思路:先将传入图像分离为单通道图像(Split()函数),然后调用calcHist()计算每个单通道图像的直方图值,再创建绘制窗口对RGB的直方图值进行显示,为显示所有数据需要对直方图的值归一化到新建的窗口高度范围内,然后调用画直线AP依次画出直方图曲线;
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc ,char** argv)
{
Mat src = imread("C:\\Users\\hello\\Desktop\\18.jpg");
if (!src.data)
{
cout << "could not load the image..." << endl;
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
//定义一个数组
vector<Mat> bgr_image;
split(src, bgr_image);
//分通道显示
imshow("blue channel image", bgr_image[0]);
imshow("green channel image", bgr_image[1]);
imshow("red channel image", bgr_image[2]);
int histSize = 256;
float range[] = {
0,256 }; //256为空
const float *histRanges = {
range };
Mat b_hist, g_hist, r_hist;
//计算直方图
calcHist(&bgr_image[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRanges, true, false);
calcHist(&bgr_image[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRanges, true, false);
calcHist(&bgr_image[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRanges, true, false);
//绘制直方图
int hist_h = 400; //高度匹配
int hist_w = 512;
int bin_w = hist_w / histSize;
//归一化直方图计算数据, 进行高度匹配 防止像素的最大次数超过400
normalize(b_hist, b_hist, 0, hist_h, NORM_MINMAX, -1);
normalize(g_hist, g_hist, 0, hist_h, NORM_MINMAX, -1);
normalize(r_hist, r_hist, 0, hist_h, NORM_MINMAX, -1);
Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0)); //创建一个合适大小类型的Mat对象
//render histogram chart 绘制直方图曲线
for (int i = 1; i < histSize; i++)
{
line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(b_hist.at<float>(i - 1))),
Point((i)*bin_w, hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, LINE_AA);
line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(g_hist.at<float>(i - 1))),
Point((i)*bin_w, hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, LINE_AA);
line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(r_hist.at<float>(i - 1))),
Point((i)*bin_w, hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, LINE_AA);
}
imshow("histogram image", histImage);
waitKey(0);
return 0;
}
效果
显示曲线如下:直方图可以用来寻找阈值