目录

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/

[OpenCV实战]25 使用OpenCV进行泊松克隆的更多相关文章

  1. [OpenCV实战]50 用OpenCV制作低成本立体相机

    本文主要讲述利用OpenCV制作低成本立体相机以及如何使用OpenCV创建3D视频,准确来说是模仿双目立体相机,我们通常说立体相机一般是指双目立体相机,就是带两个摄像头的那种(目就是指眼睛,双目就是两 ...

  2. [OpenCV实战]48 基于OpenCV实现图像质量评价

    本文主要介绍基于OpenCV contrib中的quality模块实现图像质量评价.图像质量评估Image Quality Analysis简称IQA,主要通过数学度量方法来评价图像质量的好坏. 本文 ...

  3. [OpenCV实战]44 使用OpenCV进行图像超分放大

    图像超分辨率(Image Super Resolution)是指从低分辨率图像或图像序列得到高分辨率图像.图像超分辨率是计算机视觉领域中一个非常重要的研究问题,广泛应用于医学图像分析.生物识别.视频监 ...

  4. [OpenCV实战]45 基于OpenCV实现图像哈希算法

    目前有许多算法来衡量两幅图像的相似性,本文主要介绍在工程领域最常用的图像相似性算法评价算法:图像哈希算法(img hash).图像哈希算法通过获取图像的哈希值并比较两幅图像的哈希值的汉明距离来衡量两幅 ...

  5. [OpenCV实战]47 基于OpenCV实现视觉显著性检测

    人类具有一种视觉注意机制,即当面对一个场景时,会选择性地忽略不感兴趣的区域,聚焦于感兴趣的区域.这些感兴趣的区域称为显著性区域.视觉显著性检测(Visual Saliency Detection,VS ...

  6. [OpenCV实战]46 在OpenCV下应用图像强度变换实现图像对比度均衡

    本文主要介绍基于图像强度变换算法来实现图像对比度均衡.通过图像对比度均衡能够抑制图像中的无效信息,使图像转换为更符合计算机或人处理分析的形式,以提高图像的视觉价值和使用价值.本文主要通过OpenCV ...

  7. [OpenCV实战]36 使用OpenCV在视频中实现简单背景估计

    目录 1 时间中值滤波 2 使用中值进行背景估计 3 帧差分 4 总结和代码 5 参考 许多计算机视觉应用中,硬件配置往往较低.在这种情况下,我们必须使用简单而有效的技术.在这篇文章中,我们将介绍一种 ...

  8. [OpenCV实战]33 使用OpenCV进行Hough变换

    目录 1 什么是霍夫变换 1.1 应用霍夫变换以检测图像中的线条 1.2 累加器 1.3 线条检测 1.4 圆环的检测 2 代码 3 参考 1 什么是霍夫变换 霍夫变换是用于检测图像中的简单形状(诸如 ...

  9. [OpenCV实战]26 基于OpenCV实现选择性搜索算法

    目录 1 背景 1.1 目标检测与目标识别 1.2 滑动窗口算法 1.3 候选区域选择算法 2 选择性搜索算法 2.1 什么是选择性搜索? 2.2 选择性搜索相似性度量 2.3 结果 3 代码 4 参 ...

随机推荐

  1. Vu3.x如何给v-for循环出来的输入框绑定v-mode的值,以及实现父子组件传值、双向绑定

    观前须知:本人演示使用的input是自己手敲的,如果使用的是element-ui等表单组建的input框请选择性参考,不保证我的方法对你们也完全有效. 父组件代码: 这里我的MiniInput是以组件 ...

  2. Kafka 之producer拦截器(interceptor)

    Kafka 之producer拦截器(interceptor) 一.拦截器原理 Producer拦截器(interceptor)是在Kafka 0.10版本被引入的,主要用于实现clients端的定制 ...

  3. 6.ElasticSearch系列之倒排索引

    1. 倒排索引简介 对于书通过目录查找对应章节内容的方式属于正排索引,而对于想查询文本,如我爱中国在书籍中出现的次数与具体位置,则是倒排索引的范畴. 2. 倒排索引核心组成 单词词典(Term Dic ...

  4. Bootstrap‘s JavaScript requires jQuery

    1.遇到的第一个问题:modal.js:6 Uncaught Error: Bootstrap's JavaScript requires jQuery at modal.js:6 2.遇到的第二个问 ...

  5. java中的垃圾回收算法与垃圾回收器

    常用的垃圾回收算法 标记-清除 标记清除算法是一种非移动式的回收算法,分为标记 清除 2个阶段,简而言之就是先标记出需要回收的对象,标记完成后再回收掉所有标记的内存对象,如下图 可见回收后图中被标记的 ...

  6. .net core Blazor+自定义日志提供器实现实时日志查看器

    场景 我们经常远程连接服务器去查看日志,比较麻烦,如果直接访问项目的某个页面就能实时查看日志就比较奈斯了,花了1天研究了下.net core 日志的原理,结合blazor实现了基本效果. 实现原理 自 ...

  7. Python基础之模块:6、hashlib模块 subprocess模块 logging模块

    目录 一.hashlib模块 1.简介 2.基本操作与用法 二.subprocess模块 1.简介 2.基本操作与用法 三.logging模块 1.简介 2.基本操作与用法 一.hashlib模块 1 ...

  8. Day1:Markdown文本基础操作

    Markdown学习 标题 一级标题 输入:#+空格+标题名字 :快捷键(Ctrl+1~6) 二级标题 输入:##+空格+标题名字 为二级标题 依次加#(最多六级标题) 三级标题 四级标题 字体 He ...

  9. webpack -- element-ui 的按需引入

    简单说明原理: 使用babel-plugin-component实现按需引入.打包.将webpack配置成多入口,保证最终打包的目录结构符合babel-plugin-component插件的要求,实现 ...

  10. 【云原生 · Kubernetes】runtime组件

    个人名片: 因为云计算成为了监控工程师‍ 个人博客:念舒_C.ying CSDN主页️:念舒_C.ying runtime组件 8.1 部署cri-o组件 8.2 下载二进制文件 8.3 修改配置文件 ...