[英]OpenCV - Mean of Mat object in C++
我們如何獲得輸入RGB圖像(3維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)x 3)的矩陣,然后可以對參數REDUCE_AVG
使用reduce
操作來計算平均行數。 然后將矩陣reshape
為正確的大小。 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 <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;
}
計算數組元素的平均值。
C ++:標量均值(InputArray src,InputArray mask = noArray())
Python: cv2.mean(src [,mask])→retval
C: CvScalar cvAvg(const CvArr * arr,const CvArr * mask = NULL)
Python: cv.Avg(arr,mask = None)→標量
參數: src –輸入數組,應該具有1到4個通道,以便可以將結果存儲在Scalar_中。 遮罩–可選的操作遮罩。
函數mean對每個通道獨立地計算數組元素的平均值M,然后將其返回:
當所有mask元素均為0時,函數返回Scalar :: all(0)。
還要檢查此答案如何計算和使用cvMat平均值
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.