seamlessClone是一種圖像融合技術,使用此函數可以輕松将一幅圖像中的指定目标複制後粘貼到另一幅圖像中,并自然的融合。
函數說明:
- src: 輸入8位3通道圖像的貼圖
- dst: 輸入8位3通道圖像的原圖
- mask: 輸入8位1或3通道圖像(目标掩碼區域圖像)
- p: 對象被放置在目标圖像dst中的位置
- blend: 輸出圖像,與dst具有相同大小和類型
- flags: 克隆方法可以是cv :: NORMAL_CLONE,cv :: MIXED_CLONE或cv ::MONOCHROME_TRANSFER
克隆方法1:NORMAL_CLONE: 不保留dst 圖像的texture細節。目标區域的梯度隻由源圖像決定。
import cv2
import numpy as np
from math import sqrt
# 原圖
img_back = cv2.imread(r"test.png")
# 貼圖
img_obj = cv2.imread(r"defect_images/def3.png")
# 掩膜,确定貼圖的ROI區域(0表示不需要的區域,255表示需要貼合的區域)
mask = 255*np.ones(img_obj.shape,img_obj.dtype)
# 擷取原圖寬高
width,height,channels = img_back.shape
# 粘貼位置
loaction = (height//2,width//2)
# 進行貼合
normal_clone = cv2.seamlessClone(img_obj,img_back,mask,loaction,cv2.MIXED_CLONE)
# 顯示貼合結果
while (1):
cv2.imshow('selectROI', normal_clone)
if cv2.waitKey(1) & 0xFF == 27: # Esc按下退出
break
cv2.destroyAllWindows()
案例:
from tkinter import *
from tkinter.ttk import Combobox
from tkinter.filedialog import askopenfilename, asksaveasfilename
from PIL import Image,ImageTk
import cv2
import numpy as np
init_window = Tk()
# 執行個體一個主視窗
init_window.title('grid frames')
init_window.geometry('1000x600+200+70')
init_window.resizable(0,0) # 禁止改變窗體大小
'''
全局變量
'''
frame1_img_path = ""
'''
輔助函數
fun1:打開目錄
fun2
fun3
'''
'''
圖像融合
'''
def imgs_merge():
# 原圖
img_back = cv2.imread("test.png")
# 貼圖
img_obj = cv2.imread("defect_images/def3.png")
# 掩膜,确定貼圖的ROI區域(0表示不需要的區域,255表示需要貼合的區域)
mask = 255 * np.ones(img_obj.shape, img_obj.dtype)
# 擷取原圖寬高
width, height, channels = img_back.shape
# 粘貼位置
loaction = (height // 2, width // 2)
# 進行貼合
normal_clone = cv2.seamlessClone(img_obj, img_back, mask, loaction, cv2.NORMAL_CLONE)
global frame1_mergeimg
frame1_mergeimg = resize_img_to_canvas(normal_clone, frame_1_canvas.winfo_width(), frame_1_canvas.winfo_height())
# img = cv2.imread(frame1_img_path)
# img2 = cv2.resize(img, (), interpolation=cv2.INTER_LANCZOS4)
# img3 = Image.fromarray(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))
# # img3.show()
# frame1_img = ImageTk.PhotoImage(img3)
frame_1_canvas.create_image((0, 0), image=frame1_mergeimg, anchor="nw")
'''
打開圖像檔案路徑
'''
'''
ReSize适應畫布大小
'''
def resize_imgpath_to_canvas(img_path,width,height):
img = cv2.imread(img_path)
img2 = cv2.resize(img, (width, height),interpolation=cv2.INTER_LANCZOS4)
img3 = Image.fromarray(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))
# img3.show()
img_resized = ImageTk.PhotoImage(img3)
return img_resized
def resize_img_to_canvas(img,width,height):
img2 = cv2.resize(img, (width, height),interpolation=cv2.INTER_LANCZOS4)
img3 = Image.fromarray(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))
# img3.show()
img_resized = ImageTk.PhotoImage(img3)
return img_resized
'''
切換圖檔
'''
'''
打開圖像檔案路徑
'''
def open_imgfile():
img_path = askopenfilename(
title='請選擇圖檔檔案',
# 篩選常見圖檔檔案
filetypes=[('圖檔', '.jpg .png .gif .bmp .jpeg')],
)
if img_path and img_path.endswith(('.jpg', '.png', '.gif', '.jpeg', '.bmp')):
# 圖像路徑
path = img_path
# 圖像檔案夾路徑
# dir = path_split(path)[0]
# print("message",path,dir)
# canvas.delete("all")
global frame1_img_path
frame1_img_path = path
print(frame1_img_path)
global frame1_img
frame1_img = resize_imgpath_to_canvas(frame1_img_path,frame_1_canvas.winfo_width(), frame_1_canvas.winfo_height())
# img = cv2.imread(frame1_img_path)
# img2 = cv2.resize(img, (), interpolation=cv2.INTER_LANCZOS4)
# img3 = Image.fromarray(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))
# # img3.show()
# frame1_img = ImageTk.PhotoImage(img3)
frame_1_canvas.create_image((0, 0), image=frame1_img, anchor="nw")
'''
布局配置
'''
# 第一行權重
init_window.grid_rowconfigure(0, weight=1)
# 第二行權重
init_window.grid_rowconfigure(1, weight=2)
# 第三行權重
init_window.grid_rowconfigure(2, weight=2)
# 第一列權重
init_window.grid_columnconfigure(0, weight=6)
# 第二列權重
init_window.grid_columnconfigure(1, weight=3)
# 隻有對每一行每一列都設定了grid_row/columnconfigure才能實作frame大小的擴充,其中weight參數可以設定每一塊的權重
frame_1 = Frame(init_window,padx=5,pady=5,bg='red')
frame_2 = Frame(init_window,padx=5,pady=5,bg='pink')
frame_3 = Frame(init_window,padx=5,pady=5,bg='peachpuff')
frame_4 = Frame(init_window,padx=5,pady=5,bg='green')
'''
frame1 : 畫布:顯示圖像
'''
frame_1_canvas = Canvas(frame_1,bg="#123445")
frame_1_canvas.pack(fill=BOTH,expand=YES)
'''
frame2 :
1.畫布:顯示貼合的缺陷
2.label
3.下拉框
'''
frame_2_canvas = Canvas(frame_2,width= 150,height = 100, bg="#123445")
frame_2_label = Label(frame_2, text='圖檔格式:')
val = StringVar()
frame_2_Combobox = Combobox(frame_2, values=("jpg","png","bmp"),textvariable=val)
frame_2_canvas.pack(fill=BOTH,expand=YES)
frame_2_label.pack()
frame_2_Combobox.pack()
frame2_img = resize_imgpath_to_canvas("defect_images/def3.png",150,100)
frame_2_canvas.create_image((100, 10), image=frame2_img, anchor="nw")
'''
frame3 :
1.label
2.輸入框:MaxCopyNum
3.label
4.輸入框:ImgDir
5.label
6.輸入框:OutDir
7.按鈕:連續
8.按鈕:單張
'''
frame_3_label1 = Label(frame_3, text='MaxCopyNum:')
Entry_MaxCopyNum = Entry(frame_3, width=10)
frame_3_label2 = Label(frame_3, text='ImgDir:')
Entry_ImgDir = Entry(frame_3, width=30)
frame_3_label3 = Label(frame_3, text='OutDir:')
Entry_OutDir = Entry(frame_3, width=30)
Button_Continue = Button(frame_3, text=" 連續 ")
Button_Single = Button(frame_3, text=" 單張 ")
frame_3_label1.pack()
Entry_MaxCopyNum.pack()
frame_3_label2.pack()
Entry_ImgDir.pack()
frame_3_label3.pack()
Entry_OutDir.pack()
Button_Continue.pack(side = RIGHT)
Button_Single.pack(side = LEFT)
'''
frame4 : 畫布
1.label
1.輸入框:DefectDir
1.label
2.輸入框:OutDir
3.按鈕:切換圖檔
4.按鈕:切換缺陷
5.按鈕:融合
'''
frame_4_label1 = Label(frame_4, text='DefectDir:')
Entry_DefectDir = Entry(frame_4, width=30)
frame_4_label2 = Label(frame_4, text='OutDir:')
Entry_OutDir = Entry(frame_4, width=30)
Button_ChangeImg = Button(frame_4, text=" 切換圖檔 ",command=open_imgfile)
Button_ChangeDef = Button(frame_4, text=" 切換缺陷 ")
Button_Merge = Button(frame_4, text=" 融合 ",command=imgs_merge)
frame_4_label1.pack()
Entry_DefectDir.pack()
frame_4_label2.pack()
Entry_OutDir.pack()
Button_ChangeImg.pack()
Button_ChangeDef.pack()
Button_Merge.pack()
'''
布局挂載
'''
frame_1.grid(row=0,column=0, rowspan=4,sticky=NSEW)
frame_2.grid(row=0,column=1,sticky=NSEW)
frame_3.grid(row=1,column=1,sticky=NSEW)
frame_4.grid(row=2,column=1,sticky=NSEW)
# 這裡的sticky參數也是必須的,相當于允許frame在什麼方向擴充NSEW分别就是 北南東西
'''
運作界面
'''
init_window.mainloop()