C++ 求平均w/o极值
我知道有一个选项可以在OpenCV中查找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) >
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;r cout我只需对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