我目前正在将旧的OpenCV C代码移植到OpenCV 2/3的C ++接口,而且我不太确定旧功能的某些等价物。很早我遇到cvZero
的问题。我找到的唯一可能是通过Mat::setTo
设置矩阵内容。现在,必须能够管理多通道标量和不同的数据类型,setTo
遍历矩阵的所有元素并一个接一个地设置它们,而cvZero
基本上执行memset
。我想知道使用C ++接口的推荐方法是什么,以防我只想将图像清除为黑色。
谢谢!
答案 0 :(得分:4)
yourMat = cv::Mat::zeros(yourMat.size(), yourMat.type())
似乎没有分配新内存但只覆盖现有的Mat对象(以前分配了内存,否则.size为0)。不确定memset是否在内部使用,但是这个示例代码使.setTo
版本的处理时间比使用cv::Mat::zeros
的版本长50% - 但我没有评估操作的偏移量(在两个版本中应该完全相同)!
int main(int argc, char* argv[])
{
cv::Mat input = cv::imread("C:/StackOverflow/Input/Lenna.png");
srand(time(NULL));
cv::Mat a = input;
cv::Mat b = input;
cv::imshow("original", a);
b = cv::Mat::zeros(a.size(), a.type());
std::vector<int> randX;
std::vector<int> randY;
std::vector<cv::Vec3b> randC;
int n = 500000;
randX.resize(n);
randY.resize(n);
randC.resize(n);
for (unsigned int i = 0; i < n; ++i)
{
randX[i] = rand() % input.cols;
randY[i] = rand() % input.rows;
randC[i] = cv::Vec3b(rand()%255, rand()%255, rand()%255);
}
clock_t start1 = clock();
for (unsigned int i = 0; i < randX.size(); ++i)
{
b.at<cv::Vec3b>(randY[i], randX[i]) = randC[i];
b = cv::Mat::zeros(b.size(), b.type());
}
clock_t end1 = clock();
clock_t start2 = clock();
for (unsigned int i = 0; i < randX.size(); ++i)
{
b.at<cv::Vec3b>(randY[i], randX[i]) = randC[i];
b.setTo( cv::Scalar(0, 0, 0));
}
clock_t end2 = clock();
std::cout << "time1 = " << ( (end1 - start1) / CLOCKS_PER_SEC ) << " seconds" << std::endl;
std::cout << "time2 = " << ((end2 - start2) / CLOCKS_PER_SEC) << " seconds" << std::endl;
cv::imshow("a", a);
cv::imshow("b", b);
cv::waitKey(0);
return 0;
}
给我输出:
time1 = 14 seconds
time2 = 21 seconds
我的机器上的(发布模式)(没有IPP)。
以及a
和b
的黑色图像,表示没有分配新的内存,但使用了现有的Mat内存。
int n = 250000;
将生成输出
time1 = 6 seconds
time2 = 10 seconds
这不是关于memset是否在内部使用或者是否与cvZero一样快的答案,但至少你现在知道如何设置为比.setTo