先來看看今天的結果圖
-> 此篇文章的程式碼 github
Day22_p圖_merge_two_images.ipynb
前言
我們該來運用之前學過的所有東西了!
綜合運用篇就是來一次運用前面的所學!
用 OpenCV 來P圖囉!
我們準備了之前的貓貓(img1):
以及迷你版的我本人(img2):
來練習把我P到貓貓圖上面吧!
這裡我們先提供大家等等步驟的思路:
- 將要P的圖,改成適當大小 (
cv2.resize
) - 將要P的圖,使用漫水填充法,濾出背景 (
cv2.floodFill
) - 將濾出背景的圖,挖出人物,取得遮罩(黑色) (
cv2.cvtColor, cv2.threshold
) - 將遮罩印在原來的圖片上,有點像挖空的感覺 (
cv2.bitwise_and
) - 挖空後,反向取得原先要P圖的人物 (
cv2.bitwise_not, cv2.bitwise_and
) - 合併人物至原來的圖片 (
cv2.add
)
將要P的圖,改成適當大小 (cv2.resize
)
def resize_img(img, scale_percent=25):
width = int(img.shape[1] * scale_percent / 100) # 縮放後圖片寬度
height = int(img.shape[0] * scale_percent / 100) # 縮放後圖片高度
dim = (width, height) # 圖片形狀
resize_img = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
return resize_img
因為原來的我圖片太大了,我們先將這張圖片縮小25%。
將要P的圖,使用漫水填充法,濾出背景 (cv2.floodFill
)
copyIma = img2.copy()
h, w = img2.shape[:2]
mask = np.zeros([h+2, w+2], np.uint8)
cv2.floodFill(copyIma, mask, (30, 30), (255, 255, 255), (100, 100, 100), (50, 50, 50), cv2.FLOODFILL_FIXED_RANGE)
這部分的內容可以參考昨天我所寫的:
【沒錢ps,我用OpenCV!】Day 21 – 花式修圖3,OpenCV 也有 photoshop 的魔術棒工具?! 漫水填充法 cv2.floodFill (Magic Wand Tool)
將濾出背景的圖,挖出人物,取得遮罩(黑色) (cv2.cvtColor, cv2.threshold
)
img2gray = cv2.cvtColor(copyIma,cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(img2gray, 254, 255, cv2.THRESH_BINARY)
取得上面的漫水填充法結果圖後,我們一樣先轉成灰階,
由於剛剛我們使用 (255, 255, 255) 來填充背景部分,
我們設定閥值(threshold)為 254,濾出背景。
最後我們要取得遮罩,等等要拿來挖空原圖,
遮罩有點類似就是要挖空的形狀,所以我們把挖空的地方填成黑色。
將遮罩印在原來的圖片上,有點像挖空的感覺 (cv2.bitwise_and
)
rows, cols, channels = img2.shape
x = 450
y = 170
roi = img1[y:y+rows, x:x+cols]
print("Use mask to crop origin image1:")
img1_bg = cv2.bitwise_and(roi, roi, mask = mask)
我們先透過 roi 設定好我們想p圖的位置,
之後直接把這區域先取出來,然後使用 cv2.bitwise_and
直接進行挖空,
- 因為mask黑色部分是0,只要and之後都會是黑,
- 而白色部分是255,只要and之後都會保持原樣。
挖空後,反向操作取得原先要P圖的人物 (cv2.bitwise_not, cv2.bitwise_and
)
mask_inv = cv2.bitwise_not(mask)
img2_fg = cv2.bitwise_and(img2, img2, mask = mask_inv)
現在換我們來 cv2.bitwise_and
要p的圖片,
我們先將原來的mask運用 cv2.bitwise_not
,取得反向的mask,
變成這個mask專門來幫助我們挖掉背景。
- 因為mask黑色部分(現在是背景)是0,只要and之後都會是黑,
- 而白色部分是255(現在是人),只要and之後都會保持原樣。
合併人物至原來的圖片 (cv2.add
)
dst = cv2.add(img1_bg,img2_fg)
img1[y:y+rows, x:x+cols] = dst
剛剛在步驟4,我們已經把原圖要p的地方挖空(=0)
剛剛在步驟5,我們已經把要p的地方取出(有乾淨的值),其他背景(=0)
我們只需要將這兩個單純相加 (=0的地方已經不構成影響),
即可以得到乾淨的合成圖片。
我們使用 cv2.add
。
最後只要合併結果至原圖,p圖就完成囉!
本文同步發佈在: 第 12 屆 iT 邦幫忙鐵人賽
【沒錢ps,我用OpenCV!】Day 22 – 綜合運用1,用 OpenCV 來P圖囉! 來運用各種之前學習的各種東西吧! merge two images
Reference
【沒錢ps,我用OpenCV!】Day 3 – 基本修圖2,OpenCV 圖片的剪裁、旋轉、縮放 (crop, rotate, resize),在 jupyter 中直接找尋圖片的座標
【沒錢ps,我用OpenCV!】Day 15 – 進階修圖2,OpenCV 當然也有像 ps 圖層的功能! 什麼?圖片也能加減法?! Add, Subtract, AddWeighted
【沒錢ps,我用OpenCV!】Day 17 – 進階修圖4,運用 OpenCV 的終極圖層處理大全, 想P圖該怎麼P (bitwise_or, and, xor, not, addWeighted)
【沒錢ps,我用OpenCV!】Day 18 – 進階修圖5,運用 OpenCV 做圖片二值化,產生黑白的圖片吧!cv2.threshold 各種選擇參數大全
【沒錢ps,我用OpenCV!】Day 21 – 花式修圖3,OpenCV 也有 photoshop 的魔術棒工具?! 漫水填充法 cv2.floodFill (Magic Wand Tool)
https://docs.opencv.org/master/d0/d86/tutorial_py_image_arithmetics.html