在用python進行圖像處理的時候經常需要把一個圖片的指定目標復制到另一個圖像上,而圖像的其他區域保持不變,有點類似給圖像打上水印,但是這個水印區域是完全覆蓋圖像的。最近找到了一個比較好的實現方法,主要使用opencv的按位運算章節的內容,分享給大家。
參考資料:OpenCV-Python 中文教程 10 圖像上的算術運算 10.3 按位運算
代碼實現:
1 import cv2 2 import matplotlib.pyplot as plt 3
4
5 # 加載原始圖片
6 img1 = cv2.imread('original.jpg') 7 # 加載logo圖片
8 img_logo = cv2.imread('opencv_logo.jpg') 9
10 plt.figure(), plt.subplot(1, 2, 1), plt.title("original"), plt.imshow(img1, "gray") 11 plt.subplot(1, 2, 2), plt.title("logo_img"), plt.imshow(img_logo, "gray") 12
13 # 獲取logo圖片的寬,高
14 height, width = img_logo.shape[:2] 15 # 設置你要替換的原始圖片中左上角坐標位置(x, y)
16 roi_coord_top_lef = [200, 300] 17 # 獲取原始圖片中要和roi融合的區域,截取的長度大小默認就是logo圖片的長寬大小
18 roi = img1[roi_coord_top_lef[1]:roi_coord_top_lef[1]+height, roi_coord_top_lef[0]:roi_coord_top_lef[0]+width] 19
20 # Now create a mask of logo and create its inverse mask also
21 # 把logo圖片轉成灰度圖片
22 img2gray = cv2.cvtColor(img_logo,cv2.COLOR_BGR2GRAY) 23 plt.figure(), plt.subplot(1, 3, 1), plt.title("gray image"), plt.imshow(img2gray, "gray") 24 # 把logo灰度圖片轉換成二值圖片,現在是背景白色,前景黑色
25 ret, mask = cv2.threshold(img2gray, 175, 255, cv2.THRESH_BINARY) 26 plt.subplot(1, 3, 2), plt.title("binary image - mask"), plt.imshow(mask, "gray") 27 # logo圖片的前景和背景交換,現在是背景黑色,前景是白色
28 mask_inv = cv2.bitwise_not(mask) 29 plt.subplot(1, 3, 3), plt.title("binary image - mask inv"), plt.imshow(mask_inv, "gray") 30
31 # 讓原始圖片與背景白色,前景黑色的mask相與從而保留原始圖片的區域
32 img1_bg = cv2.bitwise_and(roi, roi, mask=mask) 33 plt.figure(), plt.subplot(1, 3, 1), plt.title("img1_bg"), plt.imshow(img1_bg) 34 # 讓logo圖片與背景黑色,前景白色的mask_inv相與從而保留logo圖片的區域
35 img2_fg = cv2.bitwise_and(img_logo, img_logo, mask = mask_inv) 36 plt.subplot(1, 3, 2), plt.title("img2_fg"), plt.imshow(img2_fg) 37 # 對應相加兩張圖片,填充黑色0像素區域
38 dst = cv2.add(img1_bg,img2_fg) 39 plt.subplot(1, 3, 3), plt.title("dst"), plt.imshow(dst) 40
41 img1[roi_coord_top_lef[1]:roi_coord_top_lef[1]+height, roi_coord_top_lef[0]:roi_coord_top_lef[0]+width] = dst 42 plt.figure(), plt.imshow(img1, "gray") 43 plt.show()
結果圖片:
這個方法也可以實現精確的復制一張圖片的輪廓內部區域到另一張圖片上。這里,重點就是要把要復制的輪廓區域的那張圖除了前景(輪廓以及它的內部區域)以外的區域都設置為全白像素或者全黑的像素,即生成類似以上 opencv_logo.jpg 這張圖片。具體實現方法可以這樣
1. 生成一個和輪廓圖一樣大小的純白色或者純黑色的畫布: canva = np.zeros((height, image, 3), dtype=np.uint8) (這里生成的是純黑色)
2. 在畫布上畫出輪廓區域: canva = cv2.fillPoly(canva, pts=cnt, color=0) (注意,這里的輪廓需要是 (x, y) 類型,所以需要把從用 cv2.findContours() 得到的輪廓 cnt 進行 cnt = cnt[:, ::-1] 進行這個處理)
3. 把想要復制的圖片區域和 canva 進行相與: cv2.bitwise(cavna, img2)
大致思路就是以上三點,通過以上3點就可以生成類似 opencv_logo.png 這樣的圖片,之后再實現圖像印章的功能。