OpenCV3. copyTo()函数

本文介绍了OpenCV中copyTo函数的定义和用法,其参数可以是输出图像或输出图像与掩码图。同时指出使用时的注意点,一是OutputArray选择,涉及函数功能及Mat类浅拷贝原理;二是Mask大小选择,mask必须和输入图像大小相同,否则会抛出异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义和用法:

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<opencv2/core/core.hpp>  
#include<opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include<iostream>
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);    # img2 拷贝到 roi中
						 # roi 是 img1的 兴趣区域
	
	imshow("logan img2", img2);
	imshow("after mask img1", img1);
	waitKey();
	return 0;
}

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

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

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

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

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

img2.copyTo(img1);   # 注意:img2会完全覆盖img1

结果如下:
在这里插入图片描述

改成这样的话,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的代码时,我试着将代码改成了如下这样:

// C++

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这一句抛出了异常:

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值