OpenCV-C++中Mat对象的平均值
OpenCV - Mean of Mat object in C++
我们如何获得输入RGB图像(三维Mat对象)的平均值,从而获得灰色图像?OpenCV的cvtColor()
函数基于预先存在的公式将图像转换为灰色。我想得到所有三个通道的平均值,并将结果图像存储在另一个矩阵中。OpenCV中的cv::mean()
函数返回所有输入通道的标量平均值。
如果这是Python,img
是RGB图像,img.mean(2)
会得到我想要的。与Python相比,连续调用addWeighted()
函数和使用gray= blue/3.0 + red/3.0 +green/3.0
[分割通道后]会产生不同的结果。
在C++或C++的OpenCV库中有类似img.mean(2)
的东西吗?
在C++或C++的OpenCV库中有类似于img.mean(2)的东西吗?
没有,但你可以很容易地计算出来。有几种方法可以做到这一点:
-
在所有图像上循环,并将每个值设置为输入像素值的平均值。注意计算一个比
uchar
(这里我使用的是double
)容量和精度更高的类型的平均值的中间值,否则可能会得到错误的结果。您还可以进一步优化代码,例如,查看此问题及其答案。您只需要更改内环中计算的函数即可计算平均值。 -
使用
reduce
。您可以将大小为rows x cols
的3通道矩阵reshape
设为形状为((rows*cols)x3)的矩阵,然后您可以使用参数为REDUCE_AVG
的reduce
运算来计算平均行数。然后CCD_ 15对矩阵进行大小校正。reshape
操作非常快,因为您只需修改标头而不会影响存储的数据。 -
使用矩阵运算求和通道。您可以使用
split
来获得每个通道的矩阵,并对它们求和。在总结的时候注意不要让你的价值观饱和(感谢烧杯。)
您可以看到,第一种方法在使用小矩阵时速度更快,但一旦大小增加,第二种方法的性能就会更好,因为您利用了OpenCV优化。第三种方法效果出奇地好(多亏了矩阵表达式)。
一些数字,时间以毫秒为单位。根据启用的OpenCV优化,您的计算机上的时间可能会有所不同。磨合释放!
Size : 10x10 100x100 1000x1000 10000x10000
Loop : 0.0077 0.3625 34.82 3456.71
Reduce: 1.44 1.42 8.88 716.75
Split : 0.1158 0.0656 2.26304 246.476
代码:
#include <opencv2opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
Mat3b img(1000, 1000);
randu(img, Scalar(0, 0, 0), Scalar(10, 10, 10));
{
double tic = double(getTickCount());
Mat1b mean_img(img.rows, img.cols, uchar(0));
for (int r = 0; r < img.rows; ++r) {
for (int c = 0; c < img.cols; ++c) {
const Vec3b& v = img(r, c);
mean_img(r, c) = static_cast<uchar>(round((double(v[0]) + double(v[1]) + double(v[2])) / 3.0));
}
}
double toc = (double(getTickCount()) - tic) * 1000.0 / getTickFrequency();
cout << "Loop: " << toc << endl;
}
{
double tic = double(getTickCount());
Mat1b mean_img2 = img.reshape(1, img.rows*img.cols);
reduce(mean_img2, mean_img2, 1, REDUCE_AVG);
mean_img2 = mean_img2.reshape(1, img.rows);
double toc = (double(getTickCount()) - tic) * 1000.0 / getTickFrequency();
cout << "Reduce: " << toc << endl;
}
{
double tic = double(getTickCount());
vector<Mat1b> planes;
split(img, planes);
Mat1b mean_img3;
if (img.channels() == 3) {
mean_img3 = (planes[0] + planes[1] + planes[2]) / 3.0;
}
double toc = (double(getTickCount()) - tic) * 1000.0 / getTickFrequency();
cout << "Split: " << toc << endl;
}
getchar();
return 0;
}
mean()
计算数组元素的平均值。
C++:标量均值(InputArray src,InputArray mask=noArray())
Python:cv2.mean(src[,mask])→重新评估
C:CvScalar cvAvg(const CvArr*arr,const Cv4Arr*mask=NULL)
Python:cv.Avg(arr,mask=None)→标量
参数:src–应该有1到4个通道的输入数组,以便将结果存储在Scalar_中。mask–可选操作掩码。
函数平均值计算阵列元素的平均值M,独立于每个通道,并返回:
当所有掩码元素都是0时,函数返回Scalar::all(0)。
还要检查这个答案如何计算和使用cvMat平均值
- 什么时候调用组成单元对象的析构函数
- 计算数组c++的平均值
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- C++使用整数的压缩数组初始化对象
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 将对象移动到std::shared_ptr
- 代理对象的常量正确性
- 提升 ASIO 无法识别计时器对象
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 如何返回一个类的两个对象相加的结果
- 使用std::函数映射对象方法
- 是否需要删除包含对象的"pair"?
- 如何返回多个矢量对象的平均值?C++
- 如何使用对象制作分数列表并获得平均值
- OpenCV-C++中Mat对象的平均值