OpenCV实战记录之基于分水岭算法的图像分割

1. 什么是图像分割

图像分割是将一幅图像分成多个不相交的区域,每个区域内具有一定的相似度,不同区域之间相似度较小。图像分割是图像处理中的重要技术,在计算机视觉领域中有着广泛的应用,如物体识别、目标跟踪、场景分析等。

2. 分水岭算法介绍

2.1 算法准备

在介绍分水岭算法之前,我们需要了解一些概念。

梯度:图像中像素值的变化量就是图像的梯度。

距离变换:计算像素点到最近分割边界像素点的距离。

分水岭变换:就像实际的分水岭一样,将水流向集合点(或者所有的局部极小点),在这些点,水汇集成一个池子。在图像中,水流向的不是湖泊,而是相邻的像素,通过计算图像的梯度,将整幅图像分割成小区域,每个小区域内的像素灰度值一样。

2.2 分水岭算法流程

图像分割中,最常用的算法就是分水岭算法。

分水岭算法流程:预处理、计算距离变换、寻找 markers、执行分水岭变换。

预处理:首先,将图像根据一定的标准进行减噪处理,便于后续处理。

计算距离变换:对灰度值进行处理,产生梯度值,然后计算距离变换矩阵。

寻找 markers:在距离变换矩阵中,设置 markers,一般是在图像的物体轮廓处标记标记一些点作为 marker。

执行分水岭变换:将 markers 传入 opencv 的分水岭变换函数,进行分割,得到每个像素所在的区域。

3. 分水岭算法代码实现

下面是一个使用 OpenCV 实现分水岭算法的代码:

import cv2

import numpy as np

# 读入图片

img = cv2.imread("test.jpg")

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 进行标准化处理和高斯滤波

ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

kernel = np.ones((3, 3), np.uint8)

opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)

# 距离变换

dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)

ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)

# 获取 markers

sure_fg = np.uint8(sure_fg)

unknown = cv2.subtract(opening, sure_fg)

# 执行分水岭变换

ret, markers = cv2.connectedComponents(sure_fg)

markers = markers + 1

markers[unknown == 255] = 0

markers = cv2.watershed(img, markers)

# 在原图中将不同区域标记不同颜色

img[markers == -1] = [255, 0, 0]

cv2.imshow("result", img)

cv2.waitKey()

4. 实战应用

图像分割技术有着广泛的应用,如医学图像分割、工业视觉图像分析、地理信息系统、智能交通等领域,下面以医学图像分割为例。

4.1 医学图像分割应用

缺血性卒中是一种血管性疾病,急性期病人有显著的脑组织水肿,也称为“脑水肿”,严重时会压迫周围正常脑组织,严重影响患者生命质量。

在缺血性卒中治疗的过程中,需要对患者头部进行一系列的医学影像检查,如 CT、MRI 等,医生对患者进行诊断并选择相应的治疗方案。

CT 影像数据具有体积大、数据丰富、噪声复杂等特点,因此医生在进行诊断前需要进行对头部医学影像进行分割,分离出骨骼和软组织,以便更好地识别问题点。

分水岭算法在医学图像分割中有着广泛的应用,下图是使用分水岭算法对 CT 影像进行分割的结果。

后端开发标签