目录

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/

最新文章

  1. R语言——绘制半圆形图
  2. C语言程序设计第七次作业
  3. 【笔记】jquery阻止冒泡事件发生的语句
  4. 软工实践练习一——使用Git进行代码管理心得
  5. 3、JavaScript
  6. 美团网基于机器学习方法的POI品类推荐算法
  7. SmartDo数据挖掘思路
  8. 网络爬虫系统Heritrix的结构分析 (个人读书报告)
  9. dom select选单
  10. ListNode线性表
  11. Linux负载均衡软件LVS之三(配置篇)
  12. DevOps之服务-监控工具
  13. 在mac OS10.10下安装 cocoapods遇到的一些问题
  14. java 语法分析器 括号匹配
  15. 查找 管道 exec
  16. 关于sdk&gt;=23的android版本权限的问题
  17. PHP百分号转小数,php 小数转换百分数函数
  18. 导出Excel过程中遇到的问题java.lang.NoClassDefFoundError: org/apache/xmlbeans/XmlException
  19. 2017-2018-1 20179202《Linux内核原理与分析》第二周作业
  20. iOS开发之--打印一堆奇怪东西的解决方案

热门文章

  1. 有人相爱,有人夜里开车看海,有人leetcode第一题都做不出来。
  2. java中HashMap的设计精妙在哪?
  3. Java 多线程写zip文件遇到的错误 write beyond end of stream!
  4. 表驱动法在STM32中的应用
  5. Codeforces Round #802 (Div. 2)C. Helping the Nature(差分)
  6. Codeforces Round #829 (Div. 2) D. Factorial Divisibility(数学)
  7. linux 2021
  8. MYSQL5.7 保姆级安装教程
  9. Go语言核心36讲40
  10. Atcoder补题计划