apache php 多个网站,个人网站备案与企业备案,wordpress 不能换主题,19年做网站基础入门 直方图是对数据分布情况的图形表示#xff0c;特别适用于图像处理领域。在图像处理中#xff0c;直方图通常用于表示图像中像素值的分布情况。直方图由一系列矩形条#xff08;也被称为bin#xff09;组成#xff0c;每个矩形条的高度表示某个像素值#xff08;…基础入门 直方图是对数据分布情况的图形表示特别适用于图像处理领域。在图像处理中直方图通常用于表示图像中像素值的分布情况。直方图由一系列矩形条也被称为bin组成每个矩形条的高度表示某个像素值或像素值范围在图像中出现的频次。直方图的横轴X轴表示像素值的范围通常对于8位灰度图像其范围为0-255。直方图的纵轴Y轴表示在图像中每个像素值或像素值范围出现的频次。 在OpenCV中计算直方图使用cv::calcHist函数其函数原型如下。
void cv::calcHist(const Mat* images, int nimages, const int* channels, const Mat mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool accumulatefalse); 各个参数的含义如下。 images输入图像或图像集合的指针数组。images指向一个图像矩阵数组nimages指定数组的长度即要处理的图像数量。通常当处理单个图像时会传递一个包含单个图像地址的指针。 nimages输入图像的数量表示images数组中图像的个数。 channels一个整数数组指定了要从每个图像中使用的通道的索引。比如如果处理的是一个三通道的BGR图像并且只想计算蓝色通道的直方图则应传递{0}。如果想计算所有通道的联合直方图则可以传递{0, 1, 2}。 mask: 可选的掩码图像它定义了一个感兴趣的区域只有这个区域内的像素才会被用于计算直方图。如果不需要掩码可以传递一个空的cv::Mat()。 hist输出的直方图它是一个多维数据的数组其维度取决于dims和histSize参数。这个输出直方图需要事先创建好或使用智能指自动管理内存。 dims直方图的维度。对于单通道图像通常是1对于多通道联合直方图这个值会更高。 histSize指定每一维直方图的bin桶数量的数组。对于单通道8位图像通常使用{256}来表示从0到255的每个灰度级都有一个bin。 ranges指定每个维度的值范围的数组的指针。通常情况下对于单通道8位图像每个维度的范围是{0, 256}意味着从0到255的像素值范围。数组中的每个元素都是一个包含两个元素起始值和结束值的数组。 accumulate如果设置为true则当前计算的直方图会被累积到hist中已有的值上。默认值为false意味着每次调用都会重新计算直方图而不保留之前的结果。 实战解析 在下面的实战代码中我们首先读取一张图像并转换为灰度图像img。然后计算该图像的灰度直方图hist。其中histSize设为256意味着将灰度级分为256个区间。接下来我们使用cv::normalize函数对其进行归一化处理以确保直方图的高度总和为1便于可视化展示。 最后我们创建一个新的图像histImage用于绘制直方图。通过循环遍历每个bin根据每个bin的高度在histImage上绘制相应的矩形条形成可视化的直方图。直方图的背景色为白色矩形条的颜色为蓝色。
#include opencv2/opencv.hpp
using namespace cv;#include iostream
using namespace std;int main()
{Mat img imread(OpenCV.png, IMREAD_GRAYSCALE);if(img.empty()){cout Can not open or find the image endl;return -1;}// 计算灰度直方图int channels[] {0};int histSize 256;float range[] {0, 256};const float* histRange {range};bool uniform true;bool accumulate false;Mat hist;calcHist(img, 1, channels, Mat(), hist, 1, histSize, histRange, uniform, accumulate);// 对直方图进行归一化normalize(hist, hist, 0, 1, NORM_MINMAX, -1, Mat());// 绘制直方图int hist_w 512;int hist_h 400;int bin_w cvRound((double)hist_w / histSize);Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(255, 255, 255));for(int i 1; i histSize; i){rectangle(histImage, Point(bin_w*(i-1), hist_h - cvRound(hist.atfloat(i-1)*hist_h)),Point(bin_w*(i), hist_h), Scalar(255, 0, 0), -1);}// 显示原图和直方图imshow(Original Image, img);imshow(Histogram, histImage);waitKey(0);destroyAllWindows();return 0;
} 执行上面的代码运行效果可参考下图。 直方图比较 比较两个直方图的相似度是通过cv::compareHist函数实现的常用于图像检索、对象识别等场景该函数的原型如下。
double cv::compareHist(InputArray H1, InputArray H2, int method); 各个参数的含义如下。 H1第一个直方图。 H2第二个直方图需要与H1有相同的尺寸和类型。 method指定用于比较直方图的方法被定义为枚举类型cv::HistCompMethods常用的比较方法如下。 cv::HISTCMP_CORREL相关性方法计算两个直方图之间的皮尔逊相关系数。此时函数返回值表示两个直方图之间的皮尔逊相关系数范围从[-1, 1]。值接近1表示两个直方图非常相似高度相关值接近-1表示两者几乎完全负相关而接近0则表示没有线性关系。 cv::HISTCMP_INTERSECT交集方法计算两直方图的重叠部分。此时函数返回值的范围是[0, 1]。值越接近1表示直方图越相似值越接近0表示差异越大。 cv::HISTCMP_BHATTACHARYYA巴氏距离计算两直方图的巴塔查里亚距离。此时函数返回值用于衡量两个直方图的相似度。这是一种基于概率密度函数的测度值越小表示直方图越相似。最大值为1表示完全不相似。 在下面的实战代码中我们首先读取两张灰度图像img1和img2。然后分别计算每张图像的灰度直方图并使用cv::normalize函数对直方图进行了归一化处理。接下来我们使用cv::compareHist函数比较这两个直方图。最后我们输出了比较结果展示了两幅图像直方图的相似度。
#include opencv2/opencv.hpp
using namespace cv;#include iostream
using namespace std;int main()
{Mat img1 imread(OpenCV.png, IMREAD_GRAYSCALE);Mat img2 imread(C.png, IMREAD_GRAYSCALE);if(img1.empty() || img2.empty()){cout Can not open or find the image endl;return -1;}// 计算两幅图像的直方图int histSize 256;float range[] {0, 256};const float* histRange {range};bool uniform true;bool accumulate false;Mat hist1;Mat hist2;calcHist(img1, 1, 0, Mat(), hist1, 1, histSize, histRange, uniform, accumulate);calcHist(img2, 1, 0, Mat(), hist2, 1, histSize, histRange, uniform, accumulate);// 归一化直方图normalize(hist1, hist1, 0, 1, NORM_MINMAX, -1, Mat());normalize(hist2, hist2, 0, 1, NORM_MINMAX, -1, Mat());// 比较直方图double result compareHist(hist1, hist2, HISTCMP_CORREL);// 输出0.953461cout result endl;waitKey(0);destroyAllWindows();return 0;
}