簡體   English   中英

在 C++ 中計算單通道直方圖的均值和標准差

[英]Calculating the mean and standard deviation in C++ for single channeled histogram

我想計算 HSV 圖像直方圖的平均值和標准偏差,但我只想為 V 通道做這個直方圖和計算。

我一直在閱讀有關如何為一組通道執行此操作的示例,並嘗試了這些方法,但我對我最初創建直方圖的方法是否僅對一個通道正確感到困惑,因為程序在我嘗試時不斷崩潰執行它。

這是我目前所擁有的(變量 test 是一個 cv::Mat 圖像,這可以是您希望用來重現問題的任何圖像)。 我可能遺漏了一些明顯的東西,並且 for 循環在值的范圍方面可能不正確,但我之前沒有在 C++ 中這樣做過。

        cv::cvtColor(test, test, CV_BGR2HSV);


        int v_bins = 50;
        int histSize[] = { v_bins };
        cv::MatND hist;

        float v_ranges[] = { 0, 255};
        cv::vector<cv::Mat> channel(3);
        split(test, channel);

        const float* ranges[] = { v_ranges };
        int channels[] = {0};

        cv::calcHist(&channel[2], 1, channels, cv::Mat(), hist, 1, histSize, ranges, true, false); //histogram calculation

        float mean=0;

        float rows= hist.size().height;
        float cols = hist.size().width;

        for (int v = 0; v < v_bins; v++)
        {
            std::cout << hist.at<float>(v, v) << std::endl;;
            mean = mean + hist.at<float>(v);
        }

        mean = mean / (rows*cols);
        std::cout << mean<< std::endl;;

您可以簡單地使用cv::meanStdDev ,它計算數組元素的均值和標准差。

請注意, meanstddev參數都是cv::Scalar ,因此您需要執行mean[0]stddev[0]來獲取單通道數組hist的雙hist

此代碼將闡明它的用法:

#include <opencv2\opencv.hpp>
#include <iostream>

int main()
{
    cv::Mat test = cv::imread("path_to_image");

    cv::cvtColor(test, test, CV_BGR2HSV);

    int v_bins = 50;
    int histSize[] = { v_bins };
    cv::MatND hist;

    float v_ranges[] = { 0, 255 };
    cv::vector<cv::Mat> channel(3);
    split(test, channel);

    const float* ranges[] = { v_ranges };
    int channels[] = { 0 };

    cv::calcHist(&channel[2], 1, channels, cv::Mat(), hist, 1, histSize, ranges, true, false); //histogram calculation

    cv::Scalar mean, stddev;
    cv::meanStdDev(hist, mean, stddev);

    std::cout << "Mean: " << mean[0] << "   StdDev: " << stddev[0] << std::endl;

    return 0;
}

更新

您可以根據它們的定義計算均值和標准差:

double dmean = 0.0;
double dstddev = 0.0;

// Mean standard algorithm
for (int i = 0; i < v_bins; ++i)
{
    dmean += hist.at<float>(i);
}
dmean /= v_bins;

// Standard deviation standard algorithm
std::vector<double> var(v_bins);
for (int i = 0; i < v_bins; ++i)
{
    var[i] = (dmean - hist.at<float>(i)) * (dmean - hist.at<float>(i));
}
for (int i = 0; i < v_bins; ++i)
{
    dstddev += var[i];
}
dstddev = sqrt(dstddev / v_bins);

std::cout << "Mean: " << dmean << "   StdDev: " << dstddev << std::endl;

並且您將獲得與 OpenCV meanStdDev相同的值。

在直方圖上計算統計數據時要小心。 如果您只運行meanStdDev ,您將獲得 bin 值的均值和標准差。 這並沒有告訴你很多。

可能你想要的是均值和標准差強度。

因此,如果您想從直方圖(或一組直方圖)中導出圖像均值和標准差,則可以使用以下代碼:

// assume histogram is of type cv::Mat and comes from cv::calcHist

double s = 0;
double total_hist = 0;

for(int i=0; i < histogram.total(); ++i){
    s += histogram.at<float>(i) * (i + 0.5); // bin centre
    total_hist += histogram.at<float>(i);
}

double mean = s / total_hist;

double t = 0;
for(int i=0; i < histogram.total(); ++i){
    double x = (i - mean);
    t += histogram.at<float>(i)*x*x;
}
double stdev = std::sqrt(t / total_hist);

從均值的定義來看:

mean = sum(x * p(x)) // expectation
std = sqrt(sum( p(x)*(x - mean)**2 ) // sqrt(variance)

平均值是 x 的期望值 所以histogram[x]/sum(histogram)給你p(x) 標准差的定義類似,來自方差 數字稍微簡單一些,因為像素只能取整數值並且是單位間隔的。

請注意,如果您想使用accumulate選項計算一批圖像的歸一化統計數據,這也很有用。

改編自: 如何計算直方圖的標准偏差? (Python,Matplotlib)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM