如何使用另一个矩阵图像替换矩阵中的值

3

我有一个大小为480x480的矩阵A和一个大小为478x478的矩阵B。 我想使用C++将矩阵B填充到矩阵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++中实现相同的功能。

"did not work" 的意思是什么? - 463035818_is_not_a_number
B_channel中的值没有被复制到A中。 当我尝试输出A时,我看到的是全零,这就是我用cv::Mat A = cv::Mat :: zeros(cv::Size(480, 480),CV_8UC1)初始化A的结果。 - Saikiran
2
B_channel[0].copyTo(A(Rect(1,1,A.cols-2, A.rows-2))); - Kinght 金
1个回答

3
要在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复制值(而不是头文件)到另一个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, width, height),因此与其他情况的-1不同,这里是-2。
在使用copyTo获取图像B的子集之前,您也可以对B执行相同的操作。

感谢您提供详细的答案。那么B[:,:,0]这部分怎么样? - Saikiran
@Saikiran,不幸的是,我不知道比你使用 split 更好的方法。但是,如果您希望将相同的边框应用于所有通道,可以使用之前的相同方法,而不是使用具有 1 个通道的矩阵,而是使用具有 3 个通道的矩阵。 - api55

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接