C++ 计算C+中的平均值和标准偏差+;对于单通道直方图

C++ 计算C+中的平均值和标准偏差+;对于单通道直方图,c++,image,opencv,image-processing,histogram,C++,Image,Opencv,Image Processing,Histogram,我想计算HSV图像直方图的平均值和标准偏差,但我只想对V通道进行直方图和计算 我一直在阅读关于如何对一组通道执行此操作的示例,并尝试了这些方法,但我对最初创建直方图的方法是否正确感到困惑,因为当我尝试执行它时,程序不断崩溃 这是我目前拥有的(变量test是一个cv::Mat图像,它可以是您希望用于重新创建问题的任何图像)。我可能已经错过了一些明显的,for循环可能在值范围上是不正确的,但是我以前没有在C++中这样做过。 cv::cvtColor(test, test, CV_BG

我想计算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;;
cvt颜色(测试,测试,cv_BGR2HSV); int v_bins=50; int histSize[]={v_bins}; cv::MatND hist; 浮动v_范围[]={0,255}; 向量通道(3); 拆分(测试、通道); 常量浮点*范围[]={v_范围}; int通道[]={0}; cv::calcHist(&channel[2],1,channel,cv::Mat(),hist,1,histSize,ranges,true,false)//直方图计算 浮动平均值=0; 浮动行=历史大小().高度; float cols=历史大小().宽度; 对于(int v=0;v 请注意,
mean
stddev
参数都是
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;
}
#包括
#包括
int main()
{
cv::Mat test=cv::imread(“路径到图像”);
cv::CVT颜色(测试,测试,cv_BGR2HSV);
int v_bins=50;
int histSize[]={v_bins};
cv::MatND hist;
浮动v_范围[]={0,255};
向量通道(3);
拆分(测试、通道);
常量浮点*范围[]={v_范围};
int通道[]={0};
cv::calcHist(&channel[2],1,channel,cv::Mat(),hist,1,histSize,ranges,true,false);//直方图计算
cv:标量平均值,标准差;
cv::平均标准差(历史,平均标准差);

std::cout在计算直方图的统计数据时要小心。如果您只运行
meanstdev
,您将得到bin值的平均值和stdev。这不会告诉您太多

可能你想要的是平均值和stdev强度

因此,如果您想从直方图(或一组直方图)推导出图像的平均值和标准偏差,则可以使用以下代码:

// 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);
平均值是x的值。因此
直方图[x]/sum(直方图)
为您提供
p(x)
。标准偏差的定义类似,来自。数字稍微简单一些,因为像素只能取整数值,并且是单位间隔的

注意:如果要使用
累积
选项计算一批图像的归一化统计信息,这也很有用


改编自:

cv::矢量频道(3)我认为这是必要的,因为HSV被分为3个通道,我只需要V通道来记录历史。我想知道是否有cv::vector?或std::vector@sturkmen
cv::vector
适用于3.0之前的OpenCV版本。有关详细信息,请参阅。好的。我得到了一个输出,但对我来说,我得到的结果看起来很奇怪。我得到了一个平均值为69271.2,标准偏差为86937.1。这对直方图来说是现实的还是出了什么问题?@Bardslyta我还通过计算定义中的平均值和标准偏差更新了答案。你可以看到结果与OpenCV相同。如果你不期望这些结果,也许你不应该计算我an和stddev在直方图上,但在图像上。好的。我似乎误读了平均值和标准偏差函数,试图在直方图上而不是在图像上进行。很抱歉,混淆了什么是v_bins?@Hossein“v”频道的bins数。请参阅第一个片段
// 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)