openCV3 图像处理(三)

使用分水岭算法进行图像分割

分水岭算法主要用于图像分段,通常是把一副彩色图像灰度化,然后再求梯度图,最后在梯度图的基础上进行分水岭算法,求得分段图像的边缘线。
算法具体步骤可参照分水岭算法

具体算法步骤

  1. 源图像转换为灰度图
  2. 找到前景图像的近似估计,使用Otsu’s 二值化
    Otsu’s 二值化:最大类间方差法
    cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU

按图像的灰度特性,将图像分成背景和目标2部分。背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。

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

得到使类间方差最大的阈值thresh

  1. 去除噪声数据
    形态学变换morphologyEx函数
    morphologyEx(src, op, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
    src 源图像\thresh
    op 变换方式
    cv2.MORPH_OPEN 开运算先腐蚀后膨胀
    cv2.MORPH_CLOSE 闭运算先膨胀后腐蚀
    kernel 结构元素
    return:
    opening 处理后的图像

闭运算用来连接被误分为许多小块的对象,而开运算用于移除由图像噪音形成的斑点。
具体参照形态学变换相关概念
腐蚀:腐蚀操作会把前景物体的边缘腐蚀掉。原理是卷积核沿着图像滑动,如果与卷积 核对应的原图像像素值都是1,那么中心元素保持原值,否则为0.
效果,靠近前景的像素被腐蚀为0,前景物体变小,图像白色区域减少,对于去除白噪声很有用,可以断开两个连接在一起的物体。
膨胀:与腐蚀相反,卷积核当中只要有一个值是1,中心元素值就是1。此操作会增加前景中的白色区域,一般在去噪声的时候都是先腐蚀再膨胀,腐蚀的过程会使得前景变小,使用膨胀操作使前景变换回来。膨胀也可以使相互分离的物体连接。
参照腐蚀和膨胀

  1. 膨胀操作,确定背景区域sure_bg

    dilate(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
    确定膨胀操作过程中的邻域的形状,各点像素值将被替换为对应邻域上的最大值
    参数:
    src opening
    kernel 结构元素

  2. 距离变换,确定的前景区域sure_fg

    distanceTransform(src, distanceType, maskSize, dst=None, dstType=None)
    distanceType

    第二个参数 0,1,2 分别表示 CV_DIST_L1, CV_DIST_L2 , CV_DIST_C

距离变换函数具体参数参数说明

  1. 确定前景和背景重合部分

    subtract(src1, src2, dst=None, mask=None, dtype=None)

  2. 创建标签(与原图像大小相同,int32的数组)并标记其中区域
    对确定分类区域使用不同正整数标记,不确定区域使用0标记

    cv2.connectedComponents(image, labels=None, connectivity=None, ltype=None)
    背景标0,其余1++

  3. 若背景标记为0,分水岭算法会将其当成未知区域,对其+1,对不确定区域(上述函数输出结果中使用未知区域定义)标记为0

  4. 使用分水岭算法
    边界区域标记变为-1

    cv2.watershed(image, markers)

代码实例

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread(r"F:\opencv\basil.jpg")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# 设置阈值,将图像分为两部分--黑色部分and白色部分
ret,thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

# morphologyEx变换去除噪声数据(膨胀之后再腐蚀的操作,提取图像特征)
kernel = np.zeros((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel,iterations = 2)

# 对morophologyEx 变换后的图像惊醒膨胀操作,可以得到大部分都是背景的区域
sure_bg = cv2.dilate(opening,kernel,iterations=5)

# 通过distanceTransform获取确定的前景区域
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret,sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)

# 确定前景和背景重合的部分
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)

# 设置“栅栏”
ret, markers = cv2.connectedComponents(sure_fg)

# 在背景区域上+1,将unknown区域设为0
markers = markers + 1
markers[unknown==255] = 0

markers = cv2.watershed(img,markers)
img[markers == -1] = [255,0,0]
plt.imshow(img)
plt.show()

补充概念

  • 距离变换

距离变换的基本含义是计算一个图像中非零像素点到最近的零像素点的距离,也就是到零像素点的最短距离最常见的距离变换算法就是通过连续的腐蚀操作来实现,腐蚀操作的停止条件是所有前景像素都被完腐蚀。
这样根据腐蚀的先后顺序,我们就得到各个前景像素点到前景中心骨架像素点的距离。根据各个像素点的距离值,设置为不同的灰度值。这样就完成了二值图像的距离变换

  • 白噪声

是指功率谱密度在整个频域内是常数的噪声。 所有频率具有相同能量密度的随机噪声称为白噪声

  • 结构元素

形态学处理的核心就是定义结构元素,在OpenCV-Python中,可以使用其自带的getStructuringElement函数,也可以直接使用NumPy的ndarray来定义一个结构元素。
参照形态学处理

kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) 5×5十字形结构
(a,b)指定大小
OpenCV内置的常量定义椭圆(MORPH_ELLIPSE)和十字形结构(MORPH_CROSS)矩形(MORPH_RECT)

你可能感兴趣的:(计算机视觉)