Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 求平均w/o极值_C++_Opencv_Matrix_Statistics_Average - Fatal编程技术网

C++ 求平均w/o极值

C++ 求平均w/o极值,c++,opencv,matrix,statistics,average,C++,Opencv,Matrix,Statistics,Average,我知道有一个选项可以在OpenCV中查找Mat的平均值: cv::mean(mat); 我想知道在OpenCV中是否还有一个选项可以找到没有极值的平均值(例如,只有10%到90%之间的值)。我不知道OpenCV,但我怀疑它是否有一个现成的函数用于此。然而,一个简单的实现可能是这样的: double m = cv::mean(mat); Mat temp = mat; ... set all elements in temp to 0, where abs(temp[i][j] - m) >

我知道有一个选项可以在OpenCV中查找
Mat
的平均值:

cv::mean(mat);

我想知道在OpenCV中是否还有一个选项可以找到没有极值的平均值(例如,只有10%到90%之间的值)。

我不知道OpenCV,但我怀疑它是否有一个现成的函数用于此。然而,一个简单的实现可能是这样的:

double m = cv::mean(mat);
Mat temp = mat;
... set all elements in temp to 0, where abs(temp[i][j] - m) > tolerance
... and count those elements in count
int N = mat.total(); // total number of elements
m = cv::sum(temp) / (N-count)

编辑:事实上,这并不是问题所要求的。但是,如果可以假设值的高斯分布,则可以根据标准偏差(必须计算)估计公差值,以排除数据的上/下10%。

否,没有OpenCV函数可以做到这一点。但是,您可以实现自己的


最棘手的部分是计算与百分比对应的值。这可以通过计算图像的累积直方图轻松实现

但是,要使方法通用,您无法知道矩阵中有哪些值,因此需要依赖
映射

请注意,如果您只处理
CV_8U
图像,您可以在知道最多有256个不同值的情况下进行优化。要实现这一点,您可以得到一个提示

因此,这是一个可能的实现,它在最多4个通道(如
cv::mean
)的
Mat
上工作,并且不预先知道不同值的可能数量。您可以检查示例矩阵初始化中的注释/取消注释部分是否正确执行:

#include <opencv2/opencv.hpp>
#include <vector>
#include <numeric>
#include <map>
#include <iostream>
using namespace cv;
using namespace std;

double robustMeanC1(const Mat1d& src, Vec2d bounds)
{
    // Compute histogram (with no predefined range)
    map<double, int> hist;
    for (int r = 0; r < src.rows; ++r)
    {
        for (int c = 0; c < src.cols; ++c)
        {
            double key = src(r,c);
            if (hist.count(key) == 0) {
                hist.insert(make_pair(key, 1));
            }
            else {
                hist[key]++;
            }
        }
    }

    // Get vectors from map
    vector<double> vals;
    vector<int> sums;
    vals.reserve(hist.size());
    sums.reserve(hist.size());
    for (auto kv : hist)
    {
        vals.push_back(kv.first);
        sums.push_back(kv.second);
    }

    // Compute cumulative histogram
    vector<int> cumhist(sums);
    for (int i=1; i<sums.size(); ++i)
    {
        cumhist[i] = cumhist[i - 1] + sums[i];
    }

    // Compute bounds
    int total = src.rows * src.cols;
    double low_bound = (total * bounds[0]) / 100.0;
    double upp_bound = (total * bounds[1]) / 100.0;
    int low_index = distance(cumhist.begin(), upper_bound(cumhist.begin(), cumhist.end(), low_bound));
    int upp_index = distance(cumhist.begin(), upper_bound(cumhist.begin(), cumhist.end(), upp_bound));

    if (low_index == upp_index) {upp_index++;}

    // Compute mean
    double mean = 0.0;
    int count = 0;
    for (int i = low_index; i < upp_index; ++i)
    {
        mean += vals[i] * sums[i];
        count += sums[i];
    }
    mean /= count;

    return mean;
}

Scalar robustMean(const Mat& src, Vec2d bounds) 
{
    Mat m;
    src.convertTo(m, CV_64F);

    Scalar res(0.0, 0.0, 0.0, 0.0);

    if (m.channels() == 1)
    {
        res[0] = robustMeanC1(m, bounds);
    } 
    else
    {
        vector<Mat1d> planes;
        split(m, planes);

        if (planes.size() > 4)
        {
            // Error, at most 4 channels
            return Scalar(0,0,0,0);
        }

        for (int i = 0; i < planes.size(); ++i)
        {
            res[i] = robustMeanC1(planes[i], bounds);
        }
    }
    return res;
}



int main()
{
    Mat1d m(10,10, 5.f);
    m(Range(0,1), Range::all()) = 2.0;
    //m(Range(1, 2), Range::all()) = 80.0;
    //randu(m, Scalar(0), Scalar(1));

    //Mat3b m = imread("path_to_image");

    Scalar rs = robustMean(m, Vec2d(10, 90));
    Scalar s = mean(m);

    cout << "Robust Mean: " << rs << endl;
    cout << "       Mean: " << s << endl;

    return 0;
}
#包括
#包括
#包括
#包括
#包括
使用名称空间cv;
使用名称空间std;
双robustMeanC1(常数Mat1d&src,Vec2d界)
{
//计算直方图(无预定义范围)
地图历史;
对于(int r=0;rcout我只需对
Mat
元素进行排序,并取截断向量的平均值

#include <algorithm>
#include <vector>
// c in [0,1] the portion of middvalues added to the mean
template<class _T> _T avg( std::vector< _T > & vec, double c )
{
    if ( c < 0.0 )
        c = 0.0;
    else if ( c > 1.0 )
        c = 1.0;
    const size_t len = (size_t)( c * (double)vec.size() );
    if ( len == 0 )
        return 0.0;
    std::vector< _T >::iterator beg = vec.begin();
    std::vector< _T >::iterator end = vec.end();
    if ( len < vec.size() )
    {    
        beg += ( vec.size() - len )/2;
        end = beg + len;
        std::nth_element( vec.begin(), beg, vec.end() );
        std::nth_element( beg, end, vec.end() );
    }
    double sum = 0.0, d = 0.0;
    for ( std::vector<_T>::iterator it = beg; it!=end; ++it, d+=1.0 )
        sum += *it;
    return sum/d;
}
// fill the vector and compute for each channel separately.
#包括
#包括
//c在[0,1]中,将中间值的部分加到平均值中
模板平均值(标准::向量<向量>和向量,双c)
{
if(c<0.0)
c=0.0;
否则,如果(c>1.0)
c=1.0;
常量大小长度=(大小)(c*(双精度)向量大小();
如果(len==0)
返回0.0;
std::vector<\u T>::迭代器beg=vec.begin();
std::vector<\T>::迭代器end=vec.end();
if(len

为了简单起见,这里尾和头是同一部分。

cv::mean也考虑了零值。因此平均值会很低。@Bschs这就是为什么最后一行会对normalization@tobi303这不适用于一般矩阵,例如值可以小于0。但是,这种方法适用于图像,因为您没有公差不能固定,但会对每个图像重新计算。因此,这并不能回答问题,因为您忽略了如何计算阈值。其余的都可以,而BSCH是错误的:D@Miki我同意你关于容忍度的观点。实际上我误解了答案,认为离群值比平均值低了一小部分应该被跳过(实际上仍然不是我的代码在做什么,但这可以很容易地修复)。另一方面,我不明白,为什么负面条目会是一个错误problem@tobi303我的错,我忽略了它。只是宽容的东西:D