天天看點

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例程: