OpenCV 中的影象分割
影象處理是計算機視覺任務中的關鍵步驟。在 Python 中,我們可以使用 opencv
庫來實現使用不同物件和方法的多種影象處理技術。
本教程將演示如何在 Python 中使用 opencv
執行影象分割。
在 Python 中使用 opencv
進行影象分割
影象分割是指將給定影象分成若干部分的過程。
我們新增了連線沿分段部分邊界的點的曲線。這些曲線稱為等高線。
影象分割在計算機視覺中非常有用,並且有許多現實生活中的應用。我們可以使用這種技術來分割影象的各個部分以對各種物件進行分類。
幾種可用的方法可用於在 Python 中使用 opencv
進行影象分割。
每種影象分割技術不同的主要方法通常是基於分割影象的標準。我們可以基於檢測一些顏色、預定義演算法(如分水嶺演算法)、邊緣檢測,甚至根據使用者輸入選擇分割部分來進行影象分割。
我們將在以下部分討論其中一些方法。
使用 GrabCut
演算法使用 opencv
進行影象分割
此方法需要使用者使用滑鼠和鍵盤進行互動。內建的 opencv
庫具有可以從滑鼠和鍵盤讀取使用者輸入的物件和方法。
GrabCut
演算法是一種非常簡單且有用的影象分割工具。在這種技術中,我們使用使用者輸入來選擇給定影象的某個區域。
該演算法自動檢測分割部分的前景和背景,我們可以將它們顯示出來。
我們可以使用 opencv
庫中的 grabCut()
函式來實現該演算法。我們將在此函式中將影象與所選區域的框一起傳遞以進行影象分割。
有關示例,請參見以下程式碼。
import cv2
import numpy as np
def algo_grabcut(img, bounding_box):
seg = np.zeros(img.shape[:2],np.uint8)
x,y,width,height = bounding_box
seg[y:y+height, x:x+width] = 1
background_mdl = np.zeros((1,65), np.float64)
foreground_mdl = np.zeros((1,65), np.float64)
cv2.grabCut(img, seg, bounding_box, background_mdl, foreground_mdl, 5,
cv2.GC_INIT_WITH_RECT)
mask_new = np.where((seg==2)|(seg==0),0,1).astype('uint8')
img = img*mask_new[:,:,np.newaxis]
cv2.imshow('Output', img)
def box_draw(click, x, y, flag_param, parameters):
global x_pt, y_pt, drawing, topleft_pt, bottomright_pt, img
if click == cv2.EVENT_LBUTTONDOWN:
drawing = True
x_pt, y_pt = x, y
elif click == cv2.EVENT_MOUSEMOVE:
if drawing:
topleft_pt, bottomright_pt = (x_pt,y_pt), (x,y)
image[y_pt:y, x_pt:x] = 255 - img[y_pt:y, x_pt:x]
cv2.rectangle(image, topleft_pt, bottomright_pt, (0,255,0), 2)
elif click == cv2.EVENT_LBUTTONUP:
drawing = False
topleft_pt, bottomright_pt = (x_pt,y_pt), (x,y)
image[y_pt:y, x_pt:x] = 255 - image[y_pt:y, x_pt:x]
cv2.rectangle(image, topleft_pt, bottomright_pt, (0,255,0), 2)
bounding_box = (x_pt, y_pt, x-x_pt, y-y_pt)
algo_grabcut(img, bounding_box)
drawing = False
topleft_pt, bottomright_pt = (-1,-1), (-1,-1)
img = cv2.imread("img4.jpg")
img = cv2.resize( img ,(500,500))
image = img.copy()
cv2.namedWindow('Frame')
cv2.setMouseCallback('Frame', box_draw)
while True:
cv2.imshow('Frame', image)
ch = cv2.waitKey(1)
if ch == 32:
break
cv2.destroyAllWindows()
輸出:
讓我們瞭解上面示例中發生的情況。
box_draw()
函式讀取使用者與滑鼠的互動以選擇影象分割區域。盒子和影象被傳遞給 algo_grabcut()
函式,該函式獲取影象併為分割影象建立二進位制掩碼。
我們使用這個掩碼並顯示分段部分的前景。
使用 opencv
進行影象分割的顏色檢測
在 Python 中,我們可以使用 opencv
進行顏色檢測。影象有不同的顏色空間來表示其顏色。
對於我們的例子,我們將使用 HSV 顏色空間來確定給定顏色的範圍。
我們將使用不同的顏色進行影象分割。我們為給定顏色建立一個範圍,並使用 opencv
庫中的 inRange()
函式來檢測與該顏色匹配的物件。
這將返回一個二進位制掩碼。然後我們細化這個掩碼並將輪廓新增到這個檢測到的部分。
如前所述,輪廓是分段部分邊界上的曲線。我們將使用 findContours()
函式使用建立的蒙版查詢邊界,然後使用 drawContours()
函式繪製這些輪廓。
請參閱下面的程式碼。
import cv2
import numpy as np
img = cv2.imread('img4.jpg')
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
bound_lower = np.array([36, 25, 25])
bound_upper = np.array([70, 255,255 ])
mask_green = cv2.inRange(hsv_img, bound_lower, bound_upper)
kernel = np.ones((7,7),np.uint8)
mask_green = cv2.morphologyEx(mask_green, cv2.MORPH_CLOSE, kernel)
mask_green = cv2.morphologyEx(mask_green, cv2.MORPH_OPEN, kernel)
seg_img = cv2.bitwise_and(img, img, mask=mask_green)
contours, hier = cv2.findContours(mask_green.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
output = cv2.drawContours(seg_img, contours, -1, (0, 0, 255), 3)
cv2.imshow("Result", seg_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
輸出:
在上面的程式碼中,我們從給定的影象中分割出綠色物件。首先,我們使用 cvtColor
函式將影象轉換為 HSV 顏色空間。
然後我們繼續建立儲存檢測到的顏色的蒙版。我們也從這個面具中刪除了任何不需要的噪音。
然後我們將輪廓繪製到檢測到的段並顯示它。waitKey()
函式可防止影象視窗自動關閉。
它等待使用者按下某個鍵然後關閉它。
まとめ
在本教程中,我們討論了使用 Python 的 opencv
庫進行影象分割。我們還為此實施了一些技術,儘管還有更多可能。
我們討論了影象分割背後的基礎知識,以及每種方法的方法和最終結果。
我們詳細討論了兩種方法。首先,我們實現了 GrabCut
演算法。
在該演算法中,使用者選擇他想要用於分割的區域。從這部分,我們檢測前景物件並顯示它們。
在第二種技術中,我們使用了顏色檢測。我們檢測到綠色物體。
在這種型別的分割中,我們將影象轉換為給定的顏色空間,並使用該模型的顏色範圍來使用 inRange()
函式檢測顏色。我們使用這個掩碼進行影象分割並在邊緣周圍繪製輪廓。
Manav is a IT Professional who has a lot of experience as a core developer in many live projects. He is an avid learner who enjoys learning new things and sharing his findings whenever possible.
LinkedIn