1. 程式人生 > 其它 >opencv(python) 影象分割

opencv(python) 影象分割

影象分割

  • 基於閾值

    優點:灰度閾值化,簡單,快速,廣泛用於硬體處理影象,如: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)