掩碼實現圖片摳圖
目錄
- 掩碼實現圖片摳圖
- 1 掩碼
- 1.1 概念
- 1.2 創建掩碼
- 1.3摳圖思路
- 2 代碼測試
1 掩碼
1.1 概念
掩碼(Mask)是一種用于指定圖像處理操作區域的工具。掩碼通常是一個與圖像尺寸相同的二值圖像,其中像素值為0表示不處理,像素值為255(或1)表示處理。掩碼可以用于多種操作,如圖像濾波、圖像合成、圖像分割等。掩碼的尺寸必須與圖像的尺寸相同。掩碼的像素值通常為0或255(或1),但也可以是其他值,具體取決于應用場景。通過使用掩碼,可以更精確地控制圖像處理操作的范圍,從而實現更復雜的效果。
1.2 創建掩碼
- mask = np.zeros((height, width), dtype=np.uint8),創建一個全黑的掩碼
- (height, width), 高寬
- dtype=np.uint8 ,數據類型
- cv2.rectangle(mask, (x1, y1), (x2, y2), 255, -1),在掩碼上繪制矩形
- (x1, y1), (x2, y2)起點和對角線坐標 ,
- 255顏色, -1表全填充
import cv2
import numpy as np
# 創建一個全黑的掩碼
mask = np.zeros((300, 300), dtype=np.uint8)
# 在掩碼上繪制一個白色矩形
cv2.rectangle(mask, (50, 50), (100, 100), 255, -1)
cv2.imshow('mask',mask)
cv2.waitKey(0)
運行如下
1.3摳圖思路
-
圖像讀取與預處理
讀取圖像并轉換為灰度圖,進行高斯濾波以減少噪聲。 -
邊緣檢測
使用Canny算法檢測圖像中的邊緣。 -
輪廓檢測與排序
查找圖像中的輪廓,并根據面積進行排序。 -
二值化處理
對灰度圖進行二值化處理,確定閾值。 -
輪廓篩選
根據輪廓的寬度、高度和寬高比篩選出符合條件的輪廓。 -
掩碼操作
在掩碼上繪制篩選后的輪廓,并對原圖像和掩碼進行與操作,以提取區域。
2 代碼測試
原圖
代碼展示:
import numpy as np
import cv2# 定義一個函數用于顯示圖像,并等待用戶按下任意鍵關閉窗口
def cv_chow(name, img):cv2.imshow(name, img)cv2.waitKey(0)# 定義一個函數用于對四個點進行排序,返回一個有序的矩形頂點列表
def order_points(pts):rect = np.zeros((4, 2), dtype="float32")s = pts.sum(axis=1) # 計算每個點的x和y坐標之和rect[0] = pts[np.argmin(s)] # 最小的和為左上角rect[2] = pts[np.argmax(s)] # 最大的和為右下角diff = np.diff(pts, axis=1) # 計算每個點的x和y坐標之差rect[1] = pts[np.argmin(diff)] # 最小的差為右上角rect[3] = pts[np.argmax(diff)] # 最大的差為左下角return rect# 定義一個函數用于對輪廓進行排序,支持從左到右、從右到左、從上到下、從下到上四種排序方式
def sort_contours(cons, method='left-to-right'):reverse = Falsei = 0if method == 'right-to-left' or method == 'bottom-to-top':reverse = Trueif method == 'top-to-bottom' or method == 'bottom-to-top':i = 1boundingBoxes = [cv2.boundingRect(c) for c in cons] # 獲取每個輪廓的邊界框(cons, boundingBoxes) = zip(*sorted(zip(cons, boundingBoxes),key=lambda b: b[1][i], reverse=reverse))return cons, boundingBoxes# 讀取圖像
img = cv2.imread('img_3.png')# 復制圖像用于繪制輪廓
cont_img = img.copy()# 將圖像轉換為灰度圖
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 對灰度圖進行高斯濾波,以減少噪聲
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
cv_chow('blurred', blurred)# 使用Canny邊緣檢測算法檢測圖像中的邊緣
edg = cv2.Canny(blurred, 75, 200)
cv_chow('edg', edg)# 查找圖像中的輪廓
cnts = cv2.findContours(edg.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]# 在圖像上繪制所有輪廓
cv2.drawContours(cont_img, cnts, -1, (0, 0, 255), 3)
cv_chow('cont_img', cont_img)# 根據輪廓面積對輪廓進行排序,從大到小
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)# 對灰度圖進行二值化處理,使用Otsu's方法自動確定閾值
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
cv_chow('thresh', thresh)# 在二值化圖像中查找輪廓
thresh_cnt = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]# 初始化一個列表用于存儲符合條件的輪廓
qus_cnts = []# 初始化一個列表用于存儲所有的掩碼
mask_all = []# 創建一個與二值化圖像大小相同的黑色掩碼
mask = np.zeros(thresh.shape, dtype='uint8')# 遍歷所有輪廓,篩選出符合條件的輪廓
for c in thresh_cnt:(x, y, w, h) = cv2.boundingRect(c) # 獲取輪廓的邊界框ar = w / float(h) # 計算邊界框的寬高比if w >= 8 and h >= 10 and 0.5 <= ar <= 2: # 根據寬度、高度和寬高比篩選輪廓qus_cnts.append(c)# 遍歷篩選后的輪廓,繪制掩碼并進行與操作
for i in qus_cnts:cv2.drawContours(mask, [i], -1, 255, -1) # 在掩碼上繪制輪廓cv_chow('mask', mask)img_mask_and = cv2.bitwise_and(img, img, mask=mask) # 對原圖像和掩碼進行與操作cv_chow('img_mask_and', img_mask_and)
運行結果: