在 C++ 中计算单通道直方图的均值和标准差

bar*_*yta 5 c++ opencv image image-processing 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;;
Run Code Online (Sandbox Code Playgroud)

Mik*_*iki 5

您可以简单地使用cv::meanStdDev,它计算数组元素的均值和标准差。

请注意,meanstddev参数都是cv::Scalar,因此您需要执行mean[0]stddev[0]获取单通道数组的双精度值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;
}
Run Code Online (Sandbox Code Playgroud)

更新

您可以根据它们的定义计算均值和标准差:

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;
Run Code Online (Sandbox Code Playgroud)

并且您将获得与 OpenCV 相同的值meanStdDev