天天看点

OpenCV图像无缝融合-seamlessClone介绍与使用(Python/C++源码)

导读

本期将介绍并演示OpenCV使用seamlessClone实现图像无缝融合效果。

介绍

seamlessClone是OpenCV3后添加的函数,使用此函数可以轻松将一幅图像中的指定目标复制后粘贴到另一幅图像中,并自然的融合。函数说明:

OpenCV图像无缝融合-seamlessClone介绍与使用(Python/C++源码)

参数:

src 输入8位3通道图像(截取目标的大图)
dst 输入8位3通道图像(待粘贴融合的目标背景图标)
mask 输入8位1或3通道图像(目标掩码区域图像)
p 对象被放置在目标图像dst中的位置
blend 输出图像,与dst具有相同大小和类型。
flags 克隆方法可以是cv :: NORMAL_CLONE,cv :: MIXED_CLONE或cv :: MONOCHROME_TRANSFER

-NORMAL_CLONE: 不保留dst 图像的texture细节。目标区域的梯度只由源图像决定。

-MIXED_CLONE:

-MONOCHROME_TRANSFER: 不保留src图像的颜色细节,只有src图像的质地,颜色和目标图像一样,可以用来进行皮肤质地填充。

效果展示

手动框选左图中的花灯,然后自动粘贴融合到右图背景中:

参数对比演示与实现步骤

src图:

OpenCV图像无缝融合-seamlessClone介绍与使用(Python/C++源码)

框选ROI区域设定mask:

OpenCV图像无缝融合-seamlessClone介绍与使用(Python/C++源码)

dst背景图:

OpenCV图像无缝融合-seamlessClone介绍与使用(Python/C++源码)

NORMAL_CLONE:

OpenCV图像无缝融合-seamlessClone介绍与使用(Python/C++源码)

MIXED_CLONE:

OpenCV图像无缝融合-seamlessClone介绍与使用(Python/C++源码)

MONOCHROME_TRANSFER:

OpenCV图像无缝融合-seamlessClone介绍与使用(Python/C++源码)

对比发现第二种MIXED_CLONE参数效果融合最自然,不会覆盖背景图信息。

放花灯程序实现步骤:

(1) 使用OpenCV鼠标事件绘制矩形截取Rect设置mask(不会的话看我B站的视频教程有详细讲解);

(2) 使用seamlessClone完成图像融合。

效果见开头效果视频,源码如下:

(1) Python版本:

import cv2
import numpy as np


flag = False
x1=y1=0


def gen_light(rect):
  global temp2,result,dst,temp
  temp2 = temp.copy() #原图备份
  mask1 = np.zeros(temp2.shape, temp2.dtype)
  cv2.rectangle(mask1,rect,(255,255,255),-1)
  result = cv2.seamlessClone(temp2, dst, mask1, (400,200), cv2.MONOCHROME_TRANSFER)
  cv2.imshow('result',result)
def screenShot(event,x,y,flags,param):
  global x1,y1,flag,img,temp
  if event==cv2.EVENT_LBUTTONDOWN: #鼠标左键按下
    flag = True #表示当前鼠标左键是按下的
    x1 = x
    y1 = y
  elif event==cv2.EVENT_MOUSEMOVE: #鼠标移动
    if(flag):
      img = temp.copy()#原图复制(把绘制的矩形清空)
      cv2.rectangle(img,(x1,y1),(x,y),(0,255,0),2)
  elif event==cv2.EVENT_LBUTTONUP: #鼠标左键弹起
    flag = False
    ROI = temp[y1:y,x1:x] #---y1:y2, x1:x2
    gen_light((x1,y1,x-x1,y-y1))
    
img = cv2.imread('light.jpg') #读取图像
dst = cv2.imread("./2.jpg")
temp = img.copy() #原图备份


cv2.imshow("result", dst)


cv2.namedWindow('selectROI')


cv2.setMouseCallback('selectROI',screenShot)


while(1):
  cv2.imshow('selectROI',img)
  if cv2.waitKey(1)&0xFF==27: #Esc按下退出
    break


cv2.destroyAllWindows()      

(2) C++版本核心代码:

//鼠标事件绘制矩形代码看B站视频,地址:
//https://www.bilibili.com/video/BV1sa4y1s7FR?p=10
Mat src = imread("light.jpg");
Mat dst = imread("2.jpg");


Mat mask = Mat::zeros(src.rows, src.cols, src.depth());
rectangle() //绘制mask自己添加
Point center(400,200);
Mat output;
seamlessClone(src, dst, mask, center, output, NORMAL_CLONE);      

OpenCV例程: