opencv(python) 影象分割
阿新 • • 發佈:2021-10-09
影象分割
-
基於閾值
優點:灰度閾值化,簡單,快速,廣泛用於硬體處理影象,如:FPGA實時影象處理
場景:各個物體不接觸,物體和背景灰度值差別較明顯,閾值處理效果好 -
基於邊緣
返回結果:邊緣檢測的結果是點,不能作為影象分割的點,需要進一步處理,將邊緣點沿著圖形邊界連線,形成邊緣鏈。
檢測運算元: Sobel, Laplace, Canny
import cv2 as cv import numpy as np # 基於閾值 def water_shed(img_path): img = cv.imread(img_path) # 原圖灰度處理,輸出單通道圖片 gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 二值化處理Otsu演算法 reval_0, dst_otsu = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV|cv.THRESH_OTSU) # 二值化處理Triangle演算法 reval_t, dst_tri = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV|cv.THRESH_TRIANGLE) # 滑動視窗尺寸 kernel = np.ones((3, 3), np.uint8) # 形態學處理:開處理,膨脹邊緣 opening = cv.morphologyEx(dst_tri, cv.MORPH_OPEN, kernel, iterations=2) # 膨脹處理背景區域 dilate_bg = cv.dilate(opening, kernel, iterations=3) # 計算開處理影象到鄰域非零畫素距離 dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 5) # 正則處理 norm = cv.normalize(dist_transform, 0, 255, cv.NORM_MINMAX) # 閾值處理距離影象,獲取影象前景圖 retval_D, dst_fg = cv.threshold(dist_transform, 0.5 * dist_transform.max(), 255, 0) # 前景圖格式轉換 dst_fg = np.uint8(dst_fg) # 未知區域計算:背景減去前景 unknown = cv.subtract(dilate_bg, dst_fg) cv.imshow("Difference value", unknown) cv.imwrite(r'D:\workplace\data\opencv\unknown_reginon.png', unknown) # 處理連線區域 retval_C, marks = cv.connectedComponents(dst_fg) cv.imshow('Connect marks', marks) cv.imwrite(r'D:\workplace\data\opencv\connect_marks.png', marks) # 處理掩模 marks = marks + 1 marks[unknown == 255] = 0 cv.imshow("marks undown", marks) # 分水嶺演算法分割 marks = cv.watershed(img, marks) # 繪製分割線 img[marks == -1] = [255, 0, 255] cv.imshow("Watershed", img) cv.imwrite(r'D:\workplace\data\opencv\watershed.png', img) cv.waitKey(0) # 基於邊緣 def cutImage(sourceDir): # 讀取圖片 img = cv.imread(sourceDir) # 灰度化 gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 高斯模糊處理:去噪(效果最好) blur = cv.GaussianBlur(gray, (9, 9), 0) # Sobel計算XY方向梯度 gradX = cv.Sobel(gray, ddepth=cv.CV_32F, dx=1, dy=0) gradY = cv.Sobel(gray, ddepth=cv.CV_32F, dx=0, dy=1) # 計算梯度差 gradient = cv.subtract(gradX, gradY) # 絕對值 gradient = cv.convertScaleAbs(gradient) # 高斯模糊處理:去噪(效果最好) blured = cv.GaussianBlur(gradient, (9, 9), 0) # 二值化 _ , dst = cv.threshold(blured, 90, 255, cv.THRESH_BINARY) # 滑動視窗 kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (107, 76)) # 形態學處理:形態閉處理(腐蝕) closed = cv.morphologyEx(dst, cv.MORPH_CLOSE, kernel) # 腐蝕與膨脹迭代 closed = cv.erode(closed, None, iterations=4) closed = cv.dilate(closed, None, iterations=4) # 獲取輪廓 _, cnts, _ = cv.findContours(closed.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) c = sorted(cnts, key=cv.contourArea, reverse=True)[0] rect = cv.minAreaRect(c) box = np.int0(cv.boxPoints(rect)) draw_img = cv.drawContours(img.copy(), [box], -1, (0, 0, 255), 3) cv.imshow("Box", draw_img) cv.imwrite(r'D:\workplace\data\opencv\monkey.png', draw_img) cv.waitKey(0) if __name__ == '__main__': sourceDir = r"D:\workplace\data\opencv\football.jpg" cutImage(sourceDir)