opencv 图像直方图详解

文章目录

理论基础

直方图
直方图是数值数据分布的精确图形表示。为了构建直方图,第一步是将值的范围分段,即将整个值的范围分成一系列间隔,然后计算每个间隔中有多少值。 这些值通常被指定为连续的,不重叠的变量间隔。 间隔必须相邻,并且通常是(但不是必须的)相等的大小。
图像直方图
图像直方图统计的可以是对描述图像有用的任何特征,如灰度值,梯度等。
直方图是图像的一个统计特征,它具有旋转、缩放、平移不变性,被应用于灰度图像的阈值分割,对比度调整,颜色匹配等等。下面以灰度图像灰度直方图说明统计的原理:

opencv 图像直方图详解
考虑以上灰度值图像,我们如何统计这些数据呢?我们知道灰度值在0 – 255范围之间总共 256 个值,可以将我们的范围划分为子部分(称为bins),例如:
opencv 图像直方图详解
计算每个bini范围内像素的数量。得到下图(x轴表示bin,y轴表示每个箱子中的像素数)。
opencv 图像直方图详解
直方图重要概念:
dim:希望收集数据的参数数量。在上面例子中,dims = 1是因为我们只计算每个像素(在灰度图像中)的强度值。
bin:在上面例子的示例中,bins = 16
range:要测量的值的限制。在本例中:range = [0,255]

; 一、opencv 函数支持calcHist()

计算一组数组的直方图。函数原型,三个重载函数:

CV_EXPORTS void calcHist( const Mat* images, int nimages,
                          const int* channels, InputArray mask,
                          OutputArray hist, int dims, const int* histSize,
                          const float** ranges, bool uniform = true, bool accumulate = false );

CV_EXPORTS void calcHist( const Mat* images, int nimages,
                          const int* channels, InputArray mask,
                          SparseMat& hist, int dims,
                          const int* histSize, const float** ranges,
                          bool uniform = true, bool accumulate = false );

CV_EXPORTS_W void calcHist( InputArrayOfArrays images,
                            const std::vector<int>& channels,
                            InputArray mask, OutputArray hist,
                            const std::vector<int>& histSize,
                            const std::vector<float>& ranges,
                            bool accumulate = false );

参数说明:
images:源数组。它们都应该具有相同的深度,CV_8U, CV_16U或CV_32F,以及相同的大小。它们中的每一个都可以有任意数量的通道。
nimages:源图像个数。
channels:要测量的通道。
mask:源数组上使用的掩码(0表示要忽略的像素)。如果没有定义,则不使用
hist:输出直方图数组。
dims:直方图维度,必须是正的,不大于CV_MAX_DIMS(在当前OpenCV版本中等于32)。
histSize:每个维度bind的数量
ranges:每个维度要测量的值的范围
uniform:表示直方图是否均匀的标志(见上)。
accumulate:积累标志。如果设置了,则分配直方图时,一开始不清除。该特性使您能够从多个数组集合中计算出一个直方图,或者及时更新直方图。

代码示例

    cv::Mat image = cv::imread("D:\\QtProject\\Opencv_Example\\Hist\\Hist.png", cv::IMREAD_GRAYSCALE);
    if (image.empty()) {
      cout << "Cannot load image" << endl;
      return;
    }
    imshow("image",image);
    const int bins[1] = { 256 };
    float hranges[2] = { 0,255 };
    const float* ranges[1] = { hranges };

    Mat hist;

    calcHist(&image, 1, 0, Mat(), hist, 1, bins, ranges);

    int hist_w = 500;
    int hist_h = 600;
    int bin_w = cvRound((double)hist_w / bins[0]);
    Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);

    normalize(hist, hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

    for (int i = 1; i < bins[0]; i++) {
        line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(hist.at<float>(i - 1))),
            Point(bin_w*(i), hist_h - cvRound(hist.at<float>(i))), Scalar(0, 255, 0), 2, 8, 0);
    }

    namedWindow("Histogram", WINDOW_AUTOSIZE);
    imshow("Histogram", histImage);

运行效果:
原图:

opencv 图像直方图详解
直方图:
opencv 图像直方图详解
参考文章:https://docs.opencv.org/4.x/d8/dbc/tutorial_histogram_calculation.html

Original: https://blog.csdn.net/weixin_44901043/article/details/123366240
Author: liu_jie_bin
Title: opencv 图像直方图详解

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/632746/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球