Opencv Кумулятивный = разница между истиной и ложью

#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 amp;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 amp;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(amp;image, 1, 0, Mat(), hist, 1, amp;histSize, amp;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
}
``
 

Ответ №1:

Не глядя на код: разница между гистограммой и кумулятивной гистограммой заключается в том , что кумулятивная гистограмма по индексу 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

Ответ №2:

Начать с того, какова совокупная гистограмма, может быть хорошо. Гистограмма-это распределение количества пикселей в соответствии с их интенсивностью, но если речь идет о кумулятивной гистограмме; мы не находим подсчетов для одной ячейки на вертикальной оси, а скорее сопоставляем, на котором подсчитывается совокупное количество значений интенсивности пикселей во всех ячейках вплоть до текущей ячейки. А линейное кумулятивное распределение или кумулятивная гистограмма необходимы для некоторых алгоритмов обработки изображений, например для выравнивания изображения.

Гистограмма (H):

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

Кумулятивная гистограмма H:

введите описание изображения здесь

Когда вы устанавливаете кумулятивное значение true; теперь вы вычисляете кумулятивную гистограмму, поэтому нормально, чтобы выходные данные были разными. На каждом шаге итерации вы добавляете предыдущее значение гистограммы к суммарной гистограмме.

 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);
 

Эти ссылки могут быть полезны для понимания базовой структуры

Гистограммы

Выравнивание гистограммы

Функция Кумулятивного Распределения