OpenCV3之——copyTo()函数的使用方法

参考链接:

https://www.cnblogs.com/minglou/articles/9594495.html

https://blog.csdn.net/qq_35294564/article/details/81045381

 

定义和用法:

copyTo这个函数有两种定义方式,分别是:

void copyTo( OutputArray m ) const;

void copyTo( OutputArray m, InputArray mask ) const;

 

也就是参数可以是一张输出图像,或者一张输出图像和一个掩码图。

那么:

image.copyTo(imageROI);

就是把image这张图复制(copy to)到imageROI上。

image.copyTo(imageROI,mask);

则是不仅把image这张图复制(copy to)到mageROI上,且image对应mask中像素值为0的像素点都不会贴到imageROI上。

 

值得注意的地方:

1.OutputArray的选择

我在跑参考链接2中的这段代码的时候发现了一个问题,代码如下:

#include  
#include  
#include   
#include
using namespace cv;

int main()
{
	Mat img1 = imread("baboon.jpg", 0);
	Mat img2 = imread("linux.jpg", 0);
	imshow("initial img1", img1);

	Mat roi = img1(Rect(0, 0, img2.cols, img2.rows));
	//分别令像素值为1、0,以及令mask=img2.clone();观察输出结果
	//Mat mask(roi.rows, roi.cols, roi.depth(), Scalar(0));
	//Mat mask = img2.clone();
	img2.copyTo(roi);
	imshow("logan img2", img2);
	imshow("after mask img1", img1);
	waitKey();
	return 0;
}

img2调用copyTo函数,把img2贴到图像roi上(没使用掩码图),然后这段代码的显示结果如下:

OpenCV3之——copyTo()函数的使用方法_第1张图片

这段代码实现了把logo图(也就是img2)贴到大猩猩图(img1)上,不过copyTo函数的参数是roi并不是img1,那roi又是什么呢?代码中是这么定义的:

Mat roi = img1(Rect(0, 0, img2.cols, img2.rows));

可以见得roi是img1图像的一部分,还是从左上角开始,长宽等于img2的一部分。

那么如果我把copyTo这句改成下面这样,结果会是怎么呢?

img2.copyTo(img1);

结果如下:

OpenCV3之——copyTo()函数的使用方法_第2张图片

改成这样的话,img2并没有粘贴到img1上,而是img1完完全全拷贝了img2,大小也发生了变换。

为什么呢?

原因是:

1、copyTo函数的功能其实就是把输入图像完完全全拷贝到输出图像上,并且将输出图像的大小调整成输入图像的大小。(这段来自于copyTo函数源代码的注释:If it does not have a proper size or type before the operation, it is reallocated.)

2、改之前之所以可以把img2贴到img1上是因为,roi的定义调用了Mat类的赋值运算符,Mat类中的拷贝构造函数和赋值运算符定义的新Mat对象,都属于浅拷贝,即只为新构造的对象创建新的矩阵头,并将矩阵指针指向对其进行赋值或拷贝的Mat对象像素值存储的位置。也就是说,这种形式新定义的Mat对象,它的像素值和旧Mat对象的像素值,其实是一个矩阵的值,所以对新对象的像素值进行修改,旧的对象的像素值也会变化。(解释来源于《OpenCV3编程入门》)因此img2调用copyTo函数将值赋给roi时,img1构造roi中那部分像素值也发生了变化,从而img2贴到了img1上。

2.Mask大小的选择

在跑链接2的代码时,我试着将代码改成了如下这样:

int main()
{
	Mat img1 = imread("baboon.jpg", 0);
	Mat img2 = imread("linux.jpg", 0);
	imshow("initial img1", img1);

	Mat roi = img1(Rect(0, 0, img2.cols, img2.rows));
	//分别令像素值为1、0,以及令mask=img2.clone();观察输出结果
	Mat mask(roi.rows - 10, roi.cols - 10, roi.depth(), Scalar(0));
	//Mat mask = img2.clone();
	img2.copyTo(roi,mask);
	imshow("logan img2", img2);
	imshow("after mask img1", img1);
	waitKey();
	return 0;
}

原来代码中的mask长宽为roi.rows和roi.cols,但是我各减了10,想看看这样会发生什么。

而结果在copyTo这一句抛出了异常:

OpenCV3之——copyTo()函数的使用方法_第3张图片

原因:@param mask Operation mask. Its non-zero elements indicate which matrix elements need to be copied.

也就是说,mask是决定img2哪个像素点需要拷贝,哪个像素点不需要拷贝的,因此它必须和img2大小相同。

你可能感兴趣的:(OpenCV学习)