如何使用另一个垫子图像替换垫子中的值

时间:2018-12-04 12:35:20

标签: c++ numpy opencv

我有一个480x480的Mat A和478x478的MatB。 我想在C ++中使用Mat B填充Mat A(不包括A的边框)。 在python中,我使用了numpy的以下符号

A[1:-1,1:-1] = B[:,:,0]

要在c ++中实现相同目的,我尝试使用以下代码使用通道和范围,但没有用。

std::vector<Mat> B_channel(3);
split(B, B_channel);
A(cv::Range(1,479), cv::Range(1, 479)) = B_channel[0];

如何在C ++中实现相同的目标。

1 个答案:

答案 0 :(得分:2)

要在C ++中实现与python代码相同的效果,您可以执行以下示例:

  cv::Mat A(100, 100, CV_8U, cv::Scalar::all(0));
  cv::Mat B(98, 98, CV_8U, cv::Scalar::all(1));
  std::cout << "sumAll A: " << cv::sum(A) << std::endl;

  B.copyTo(A.colRange(1, A.cols - 1).rowRange(1, A.rows - 1)); // This is the copy part
  std::cout << "sumAll A: " << cv::sum(A) << std::endl;

我打印所有的总和以验证是否已复制。第一种情况为0,第二种情况为9604。在两种情况下都是正确的。要记住的重要事项:如果大小不匹配,则copyTo将重新初始化矩阵,并可能产生意外结果。

要进一步分解代码,请执行以下操作:

A.colRange(1, A.cols - 1).rowRange(1, A.rows - 1)

等效于:

 A[1:-1,1:-1]

在python中,而copyTo会将值(而不是标头)从一个cv :: Mat复制到另一个。如果您使用复制运算符(=),它将仅复制标头,在这种情况下,只是将其写在您用A(cv::Range(1,479), cv::Range(1, 479))创建的临时标头上,这可以访问A中的数据。此标头被破坏,您的数据完全相同。

要获取要复制到的标题部分,可以用几种方法来完成。我写的是列和行的范围。另一个是您编写的(带有两个范围),第三个是使用cv::Rect。所以最后所有这些都是等效的:

B.copyTo(A.colRange(1, A.cols - 1).rowRange(1, A.rows - 1));
B.copyTo(A(cv::Range(1, A.cols - 1), cv::Range(1, A.rows - 1)));
B.copyTo(A(cv::Rect(1,1,A.cols -2, A.rows -2)));

在最后一种情况下,cv :: Rect为(x,y,宽度,高度),因此在其他情况下为-2而不是-1。

您可以在使用copyTo来获取图像B的子集之前对B进行同样的操作。