Opencv累积=真与假的差异

时间:2021-06-06 09:47:44

标签: c++ opencv

我有这部分代码。我是初学者,想了解这段代码。有人可以解释一下如果我将累积设置为 true 会发生什么。假的区别在哪里。如果有人可以向我解释其中的区别,那就太好了。 我只是看到输出不同,但我不知道为什么

#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <opencv2/imgproc.hpp>

using namespace std;
using namespace cv;

cv::Mat plotHistogram(cv::Mat &image, bool cumulative = false, int histSize = 256);

int main()
{
    cv::Mat img = cv::imread("\\schrott.png"); // Read the file
    if (img.empty()) // Check for invalid input
    {
        std::cout << "Could not open or find the frame" << std::endl;
        return -1;
    }

    cv::Mat img_gray;
    cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);    // In case img is colored

    cv::namedWindow("Input Image", cv::WINDOW_AUTOSIZE); // Create a window for display.
    cv::imshow("Input Image", img);
    cv::Mat hist;
    
    hist = plotHistogram(img_gray);
    cv::namedWindow("Histogram", cv::WINDOW_NORMAL); // Create a window for display.
    cv::imshow("Histogram", hist);
    cv::waitKey(0);
}

cv::Mat plotHistogram(cv::Mat &image, bool cumulative, int histSize) {
    // Create Image for Histogram
    int hist_w = 1024; int hist_h = 800;
    int bin_w = cvRound((double)hist_w / histSize);

    cv::Mat histImage(hist_h, hist_w, CV_8UC1, Scalar(255, 255, 255));

    if (image.channels() > 1) {
        cerr << "plotHistogram: Please insert only gray images." << endl;
        return histImage;
    }

    // Calculate Histogram
    float range[] = { 0, 256 };
    const float* histRange = { range };

    cv::Mat hist;
    calcHist(&image, 1, 0, Mat(), hist, 1, &histSize, &histRange);

    if (cumulative) {
        cv::Mat accumulatedHist = hist.clone();
        for (int i = 1; i < histSize; i++) {
            accumulatedHist.at<float>(i) += accumulatedHist.at<float>(i - 1);
        }
        hist = accumulatedHist;
    }

    // Normalize the result to [ 0, histImage.rows ]
    normalize(hist, hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

    // Draw bars
    for (int i = 1; i < histSize; i++) {
        cv::rectangle(histImage, Point(bin_w * (i - 1), hist_h),
            Point(bin_w * (i), hist_h - cvRound(hist.at<float>(i))),
            Scalar(50, 50, 50), 1);
    }

    return histImage;   // Not really call by value, as cv::Mat only saves a pointer to the image data
}
``

2 个答案:

答案 0 :(得分:2)

不看代码:直方图和累积直方图的区别在于索引i处的累积直方图具有索引i处的正常直方图的值,加上索引 i - 1 处的累积直方图。有一个 C++ stl 算法可以做同样的事情,它被称为 std::partial_sum

换句话说,在图像处理中,累积直方图告诉您有多少像素最多具有给定的颜色值 c

例如,给定一个数组 [0, 1, 2, 1, 2, 3, 2, 1, 2, 3, 4],我们可以像这样绘制直方图和累积直方图:

1

这里的X轴是数组元素的值,Y轴是这个元素在数组中出现的次数。这是图像处理中的典型模式:在颜色直方图中,X 轴通常是您的颜色值。例如,在 8bpp 灰度图像中,X 轴的值在 0..255 范围内。 Y 轴是具有该特定颜色值的像素数。

累积直方图的一个重要特性(与正常直方图相反)是它是单调递增的,即 h[i] >= h[i - 1] 其中 i = 1..length(h)h 是累积直方图。这允许诸如直方图均衡化之类的操作。由于单调递增序列在定义上也是排序序列,因此您还可以对其执行仅允许在排序序列上执行的操作,例如二分查找。

下一步通常是计算归一化累积直方图,这是通过将累积直方图中的每个值除以原始数组中的值数量来完成的。例如

a = [1, 2, 3, 4]
h = hist(a)          // histogram of a
ch = partial_sum(h)  // cumulative histogram of a
nch = ch / length(a) // normalized, cumulative histogram of a

另一个例子,给定一个数组 [1, 2, 3, 4, 3, 2, 1],我们可以像这样绘制直方图和累积直方图:

2

这里的 X 轴是数组中从 1 开始的索引,Y 轴是该元素的值。

这是另一个数字:

4

另一个,解释相同:

5

答案 1 :(得分:1)

从累积直方图开始可能是好的。直方图是根据像素的强度分布的像素数,但如果所讨论的是累积直方图;我们没有在垂直轴上找到单个 bin 的计数,而是我们映射计算所有 bin 中像素强度值的累积数量,直到当前 bin。线性累积分布或累积直方图对于一些图像处理算法(例如图像均衡)是必不可少的。

直方图 (H):

 For each pixel of the image 
        value = Intensity(pixel)
        H(value)++
    end 

H 的累积直方图:

enter image description here

当您将累积设置为真时;您现在正在计算累积直方图,因此输出不同是正常的。在迭代的每一步中,您将先前的直方图值添加到累积直方图。

if (cumulative) {
    cv::Mat accumulatedHist = hist.clone();
    for (int i = 1; i < histSize; i++) {
        accumulatedHist.at<float>(i) += accumulatedHist.at<float>(i - 1);
    }
    hist = accumulatedHist;
}

当从普通直方图切换到累积直方图时,您可以将其视为一种技巧。

 accumulatedHist.at<float>(i) += accumulatedHist.at<float>(i - 1);

这些参考资料可能有助于理解基本结构

Histograms

Histogram Equalization

Cumulative Distribution Function