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)