您可以轻松转换此 MATLAB 代码:
idx = A > 0;
B(idx) = 0;
// same as
B(A>0) = 0;
OpenCV 为:
Mat1d A(...)
Mat1d B(...)
Mat1b idx = A > 0;
B.setTo(0, idx) = 0;
// or
B.setTo(0, A > 0);
关于性能,在 C++ 中,处理原始指针通常更快(这取决于启用的优化)(但速度更慢)readable):
for (int r = 0; r < B.rows; ++r)
{
double* pA = A.ptr<double>(r);
double* pB = B.ptr<double>(r);
for (int c = 0; c < B.cols; ++c)
{
if (pA[c] > 0.0) pB[c] = 0.0;
}
}
另请注意,在 OpenCV 中没有任何boolean矩阵,但它是一个CV_8UC1
矩阵(又名单通道矩阵unsigned char
), 在哪里0
means false
,以及任何值>0
是真的(通常255
).
评估
注意这可能会有所不同根据 OpenCV 启用的优化。您可以在 PC 上测试下面的代码以获得准确的结果。
时间(毫秒):
my results my results @AdrienDescamps
(OpenCV 3.0 No IPP) (OpenCV 2.4.9)
Matlab : 13.473
C++ Mask: 640.824 5.81815 ~5
C++ Loop: 5.24414 4.95127 ~4
注意:我不完全确定 OpenCV 3.0 的性能下降,所以我只是说:在您的 PC 上测试下面的代码以获得准确的结果。
正如@AdrienDecamps 在评论中所说:
OpenCV 3.0 的性能下降似乎与 OpenCL 选项有关,该选项现在在比较运算符中启用。
C++ Code
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
// Random initialize A with values in [-100, 100]
Mat1d A(1000, 1000);
randu(A, Scalar(-100), Scalar(100));
// B initialized with some constant (5) value
Mat1d B(A.rows, A.cols, 5.0);
// Operation: B(A>0) = 0;
{
// Using mask
double tic = double(getTickCount());
B.setTo(0, A > 0);
double toc = (double(getTickCount()) - tic) * 1000 / getTickFrequency();
cout << "Mask: " << toc << endl;
}
{
// Using for loop
double tic = double(getTickCount());
for (int r = 0; r < B.rows; ++r)
{
double* pA = A.ptr<double>(r);
double* pB = B.ptr<double>(r);
for (int c = 0; c < B.cols; ++c)
{
if (pA[c] > 0.0) pB[c] = 0.0;
}
}
double toc = (double(getTickCount()) - tic) * 1000 / getTickFrequency();
cout << "Loop: " << toc << endl;
}
getchar();
return 0;
}
Matlab代码
% Random initialize A with values in [-100, 100]
A = (rand(1000) * 200) - 100;
% B initialized with some constant (5) value
B = ones(1000) * 5;
tic
B(A>0) = 0;
toc
UPDATE
OpenCV 3.0在函数中使用IPP优化setTo
。如果您启用了该功能(您可以检查cv::getBuildInformation()
),您将获得更快的计算速度。