欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenCV 实战 - 图像融合(cv::copyTo())

程序员文章站 2022-07-14 16:52:00
...

cv::copyTo()

OpenCV 中 cv::copyTo 是用来复制矩阵对象 Mat 的,可以实现直接创建一个副本,且在副本矩阵上的操作不会影响原矩阵。

cv::copyTo() 声明

 /** @brief Copies the matrix to another one.

The method copies the matrix data to another matrix. Before copying the data, the method invokes :
@code
    m.create(this->size(), this->type());
@endcode
so that the destination matrix is reallocated if needed. While m.copyTo(m); works flawlessly, the function does not handle the case of a partial overlap between the source and the destination matrices.

When the operation mask is specified, if the Mat::create call shown above reallocates the matrix, the newly allocated matrix is initialized with all zeros before copying the data.
@param m Destination matrix. If it does not have a proper size or type before the operation, it is reallocated.
 */
void copyTo( OutputArray m ) const;

同时 cv::copyTo() 被重载了,声明如下:

/** @overload
@param m Destination matrix. If it does not have a proper size or type before the operation, it is reallocated.
@param mask Operation mask of the same size as \*this. Its non-zero elements indicate which matrix elements need to be copied. The mask has to be of type CV_8U and can have 1 or multiple channels.
*/
void copyTo( OutputArray m, InputArray mask ) const;

可以看到重载处注释:第二个参数 mask 的尺寸与原图像相同,它的非零元素表示需要复制的矩阵元素,mask 必须是 CV_8U 类型的,可以有 1 个或多个通道。

测试

下图是两张 1000*1000 的图像

OpenCV 实战 - 图像融合(cv::copyTo())

OpenCV 实战 - 图像融合(cv::copyTo())

目标是将两张图像叠在一起,同时在第一张图像中的白色圆形区域内复制第二张图像的对应区域,即完成图像融合,形成如下效果。

OpenCV 实战 - 图像融合(cv::copyTo())

由于 cv::copyTo 可以复制将 mask 矩阵中的非零元素的位置对应于原图像中该位置的值,从而可以实现图像融合,代码如下:

#include <iostream>
#include <sstream>
#include <fstream>

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/highgui/highgui.hpp>

#define background "0_background.png"
#define foreground "HappyFish.jpg"

void image_fusion1(cv::Mat& matBackGround, cv::Mat& matForeGround, cv::Mat& matFusion);

int main(int argc, char** argv)
{
	cv::Mat matBackGround;
	cv::Mat matForeGround;

	cv::Mat matFusion;

	image_fusion1(matBackGround, matForeGround, matFusion);

	return 0;
}

void image_fusion1(cv::Mat& matBackGround, cv::Mat& matForeGround, cv::Mat& matFusion)
{
	matBackGround = cv::imread(cv::samples::findFile(background), cv::IMREAD_COLOR);
	matForeGround = cv::imread(cv::samples::findFile(foreground), cv::IMREAD_COLOR);

	//cv::namedWindow("Background", cv::WINDOW_AUTOSIZE);
	//cv::namedWindow("Foreground", cv::WINDOW_AUTOSIZE);
	//cv::namedWindow("Image Fusion", cv::WINDOW_AUTOSIZE);

	matForeGround.copyTo(matFusion, matBackGround);

	cv::imshow("Background", matBackGround);
	cv::imshow("Foreground", matForeGround);
	cv::imshow("Image Fusion", matFusion);

	cv::imwrite("Image Fusion.png", matFusion);

	cv::waitKey(0);
}