有什么类似于 C++ 中的 img.mean(2) 或 C++ 的 OpenCV 库吗?
不,但您可以轻松计算。有几种方法可以做到:
循环遍历所有图像,并将每个值设置为输入像素值的平均值。注意计算比uchar(这里我使用double)具有更多容量和准确性的类型的平均值的中间值,否则您可能会得到错误的结果。您还可以进一步优化代码,例如请参阅this question 及其答案。您只需更改内部循环中计算的函数即可计算平均值。
使用reduce。您可以将reshape 大小为rows x cols 的3 通道矩阵设为形状矩阵((rows*cols) x 3),然后您可以使用reduce 操作和参数REDUCE_AVG 来计算平均行-明智的。然后reshape 矩阵来修正大小。 reshape 操作非常快,因为你只是修改了头部而不影响存储的数据。
使用矩阵运算对通道求和。您可以使用split 获取每个通道的矩阵,并将它们相加。总结时注意不要使你的价值观饱和! (感谢 beaker 提供这个。)
您可以看到,第一种方法在使用小矩阵时速度更快,但是随着大小的增加,第二种方法的性能要好得多,因为您利用了 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 <opencv2\opencv.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;
}