[OpenCV实战]25 使用OpenCV进行泊松克隆
目录
1 Seamless Cloning实现
1.1 Seamless Cloning实例
1.2 正常克隆(NORMAL_CLONE)与混合克隆(MIXED_CLONE)
1.2.1 Normal Cloning Result
1.2.2 Mixed Cloning Result
1.2.3 MONOCHROME TRANSFER Result
2 Seamless Cloning相关介绍
3 参考
OpenCV3中引入的令人兴奋的新功能之一称为泊松克隆Seamless cloning (有人也叫无缝克隆)。使用此新功能,您可以从一个图像复制对象,并将其粘贴到另一个图像中,使组合看起来无缝且自然。上面的图像是使用天空和飞机的场景创建的。如果我简单地将飞机图像覆盖在天空图像的顶部,结果将显得荒谬见下图。
当然,没有人会做那样的组合。你显然会小心地掩盖图像,也许在Photoshop中花了半天之后会得到一幅下图所示的图像。
如果你是一名艺术家,你将花费另外半天时间,仔细调整飞机上的颜色,使其与天空背景融为一体,并创造出美丽的构图。但是有两个问题。首先,你没有半天的时间。其次,你可能不是艺术家!
如果您可以在飞机周围制作一个非常粗糙的掩膜,并创建一个类似于第一张图的漂亮组合,这不是很酷吗?如果只需要10行代码呢?这不仅很酷,而且很厉害!
现在让我们看看我用来生成上面图像的代码。本文所有代码见:
https://github.com/luohenyueji/OpenCV-Practical-Exercise
1 Seamless Cloning 实现
1.1 Seamless Cloning 实例
快速浏览一下Seamless Cloning的用法
C++:
seamlessClone(Mat src, Mat dst, Mat mask, Point center, Mat output, int flags)
Python:
output = cv2.seamlessClone(src, dst, mask, center, flags)
详细参数介绍如下:
1)src目标图像,在本次给出的示例中是飞机。
2)dst背景图像,在本次示例中是天空。
3)mask目标图像上的掩模,表示目标图像上那些区域是感兴趣区域。如果只对飞机感兴趣,那么mask上就只有飞机所在的区域。
4)center 目标图像的中心在背景图像上的坐标!注意是目标图像的中心!
5)flags 选择融合的方式,目前有NORMAL_CLONE、MIXED_CLONE和MONOCHROME_TRANSFER三种方法。
6)output 输出图像。
现在让我们看看我用来生成上面图像的代码。
C++:
// OpenCV_SeamlessCloning.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
// Read images : src image will be cloned into dst
//目标图像
Mat src = imread("image/airplane.jpg");
//背景图像
Mat dst = imread("image/sky.jpg");
// Create a rough mask around the airplane. 创建掩模
Mat src_mask = Mat::zeros(src.rows, src.cols, src.depth());
// Define the mask as a closed polygon 定义轮廓类似目标物体的多边形
Point poly[1][7];
poly[0][0] = Point(4, 80);
poly[0][1] = Point(30, 54);
poly[0][2] = Point(151, 63);
poly[0][3] = Point(254, 37);
poly[0][4] = Point(298, 90);
poly[0][5] = Point(272, 134);
poly[0][6] = Point(43, 122);
const Point* polygons[1] = { poly[0] };
int num_points[] = { 7 };
// Create mask by filling the polygon 填充多边形
fillPoly(src_mask, polygons, num_points, 1, Scalar(255, 255, 255));
// The location of the center of the src in the dst 目标图像在背景图像中心点左边
Point center(800, 100);
// Seamlessly clone src into dst and put the results in output
Mat output;
seamlessClone(src, dst, src_mask, center, output, NORMAL_CLONE);
// Write result
imwrite("opencv-seamless-cloning-example.jpg", output);
imshow("result", output);
waitKey(0);
return 0;
}
Python:
import cv2
import numpy as np
# Read images
src = cv2.imread("image/airplane.jpg")
dst = cv2.imread("image/sky.jpg")
# Create a rough mask around the airplane.
src_mask = np.zeros(src.shape, src.dtype)
poly = np.array([ [4,80], [30,54], [151,63], [254,37], [298,90], [272,134], [43,122] ], np.int32)
cv2.fillPoly(src_mask, [poly], (255, 255, 255))
# This is where the CENTER of the airplane will be placed
center = (800,100)
# Clone seamlessly.
output = cv2.seamlessClone(src, dst, src_mask, center, cv2.NORMAL_CLONE)
# Write result
cv2.imwrite("opencv-seamless-cloning-example.jpg", output);
在上面的例子中,我使用的克隆类型(标志)是NORMAL_CLONE。还有另一种类型MIXED_CLONE,与NORMAL_CLONE略有不同。让我们看看这两种类型在细节上有何不同。
1.2正常克隆((NORMAL_CLONE)与混合克隆(MIXED_CLONE)
我有一个5岁的儿子,如果我善待他,他会给我一张“I love you”的纸条,如下图所示。曾经有一段时间,孩子们渴望得到父母的认可,但现在父母必须尽最大努力去赢得“I love you”的纸条。不管怎样,回到克隆。我将使用其中一个“I love you”的纸条来说明不同融合方式的区别。
让我们尝试将这个图像克隆到下图所示的木质纹理图像上。我们将是使用全白的掩模将源图像克隆在木质纹理图像的中心。
代码如下:
C++:
#include "pch.h"
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
// Read images : src image will be cloned into dst
//目标图像
Mat src = imread("image/iloveyouticket.jpg");
//背景图像
Mat dst = imread("image/wood-texture.jpg");
// Create an all white mask 白色掩模
Mat src_mask = 255 * Mat::ones(src.rows, src.cols, src.depth());
// The location of the center of the src in the dst 图像中心
Point center(dst.cols/2,dst.rows/2);
// Seamlessly clone src into dst and put the results in output
Mat normal_clone;
Mat mixed_clone;
Mat nonochrome_clone;
seamlessClone(src, dst, src_mask, center, normal_clone, NORMAL_CLONE);
seamlessClone(src, dst, src_mask, center, mixed_clone, MIXED_CLONE);
seamlessClone(src, dst, src_mask, center, nonochrome_clone, MONOCHROME_TRANSFER);
// Write results
imwrite("opencv-normal-clone-example.jpg", normal_clone);
imwrite("opencv-mixed-clone-example.jpg", mixed_clone);
imwrite("opencv-nonochrome-clone-example.jpg", nonochrome_clone);
return 0;
}
Python:
import cv2
import numpy as np
# Read images : src image will be cloned into dst
im = cv2.imread("image/wood-texture.jpg")
obj= cv2.imread("image/iloveyouticket.jpg")
# Create an all white mask
mask = 255 * np.ones(obj.shape, obj.dtype)
# The location of the center of the src in the dst
width, height, channels = im.shape
center = (int(height/2), int(width/2))
# Seamlessly clone src into dst and put the results in output
normal_clone = cv2.seamlessClone(obj, im, mask, center, cv2.NORMAL_CLONE)
mixed_clone = cv2.seamlessClone(obj, im, mask, center, cv2.MIXED_CLONE)
monochrome_clone = cv2.seamlessClone(obj, im, mask, center, cv2.MONOCHROME_TRANSFER)
# Write results
cv2.imwrite("opencv-normal-clone-example.jpg", normal_clone)
cv2.imwrite("opencv-mixed-clone-example.jpg", mixed_clone)
cv2.imwrite("opencv-monochrome-clone-example.jpg", monochrome_clone)
1.2.1 Normal Cloning Result
如果我们使用NORMAL_CLONE标志使用Normal
Cloning,我们将得到下图所示的结果。现在我们没有使用好的掩码,你可以看到单词“I”和“Love”之间以及“you”之间的过度平滑“和”Paa“。也就是这些字之间没有纹理背景。当然我们很懒。我们可以创建一个粗糙的掩码并改进结果。但如果你懒惰而聪明,你会使用混合克隆。
1.2.2 Mixed Cloning Result
在“正常克隆”中,源图像的纹理(渐变)将保留在克隆区域中。在混合克隆中,克隆区域的纹理(梯度)由源图像和目标图像的组合确定。混合克隆不会产生平滑区域,因为它会选择源图像和目标图像之间的主要纹理(渐变)。混合克隆的结果下图所示。请注意,“I”和“Love”,“you”和“Paa”之间的纹理不再平滑。懒人欢呼!
1.2.3 MONOCHROME TRANSFER Result
MONOCHROME_TRANSFER融合方式类似于NORMAL_CLONE,只是用单色融合。结果下图所示。
2 Seamless Cloning 相关介绍
OpenCV中的泊松克隆是由Patrick Perez,Michel Gangnet和Andrew Blake撰写的具有影响力的SIGGRAPH
2003论文题为Poisson Image Editing的实现。论文见:
http://www.irisa.fr/vista/Papers/2003_siggraph_perez.pdf
该论文的理论和实现细节实际上非常酷,但超出了本文的范围。详细可见:
https://blog.csdn.net/hjimce/article/details/45716603
3 参考
https://www.learnopencv.com/seamless-cloning-using-opencv-python-cpp/
本文来自博客园,作者:落痕的寒假,转载请注明原文链接:https://www.cnblogs.com/luohenyueji/p/16990945.html
![](https://gitcode.net/LuohenYJ/article_picture_warehouse/-/raw/main/wechat/content/%E5%8A%A0%E6%B2%B9%E9%B8%AD.gif)