首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >单通道直方图C++中均值和标准差的计算

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

Stack Overflow用户
提问于 2015-11-06 14:43:52
回答 2查看 22.2K关注 0票数 6

我想要计算HSV图像直方图的均值和标准差,但我只想做这个直方图和V通道的计算。

我一直在读关于如何为一组频道这样做的例子,并且尝试过这些方法,但是我对我最初创建直方图的方法是否正确感到困惑,因为当我试图执行它时,程序总是崩溃。

下面是我现在拥有的内容(变量测试是cv::Mat映像,这可以是您希望用来重新创建问题的任何图像)。我可能遗漏了一些显而易见的东西,for循环在值的范围上可能不正确,但是我以前没有在C++中这样做。

代码语言:javascript
运行
复制
        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;;
EN

回答 2

Stack Overflow用户

发布于 2015-11-06 19:33:44

您可以简单地使用简历::来计算数组元素的平均偏差和标准差。

请注意,meanstddev参数都是cv::Scalar,因此需要执行mean[0]stddev[0]来获取单个通道数组hist的双值。

这段代码将澄清它的用法:

代码语言:javascript
运行
复制
#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;
}

更新

您可以通过它们的定义计算平均值和标准差:

代码语言:javascript
运行
复制
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相同的值。

票数 6
EN

Stack Overflow用户

发布于 2020-02-16 22:23:55

在直方图上计算统计数据时要小心。如果您只运行meanStdDev,您将得到bin值的平均值和stdev。这并不能告诉你太多。

也许你想要的是平均强度和stdev强度。

因此,如果要从直方图(或直方图集)导出图像均值和标准差,则可以使用以下代码:

代码语言:javascript
运行
复制
// 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);

根据平均数的定义:

代码语言:javascript
运行
复制
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)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33569323

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档