目录
10.1 基础知识
在图像分割中,基本的挑战是将一幅图像划分为多个区域,这些区域需满足特定的条件。通常情况下,针对单色图像的分割算法会依据灰度值的两种主要特性之一:不连续性和相似性。
在第一种特性中,假设各个区域的边界与背景明显不同,允许基于灰度的局部不连续性来检测边界,这种方法主要采用基于边缘的分割技术。而第二种特性则使用基于区域的分割方法,依据预先定义的一组标准将图像分割成相似的区域。
10.2 点,线和边缘检测
10.2.1孤立点检测
点检测以二阶导数为基础,使用拉普拉斯公式:
在输出图像中,超过阈值的点呗标注为1,其他点标注为0,从而产生一幅二值图像。
10.2.2 线检测
线检测是复杂度更高的检测,预期二阶导数将导致更强的响应,通常用3*3的拉普拉斯模型来检测特定方向的线。如以下四个模版:
分别用来测试水平,+45°,垂直,-45°的的线最佳。
10.2.3边缘模型
边缘检测是基于灰度突变来分割图像的最常用的方法。
台阶边缘是指在1个像素的距离上发生两个灰度级间理想的过渡。图a显示了一个垂直台阶边缘的一部分和通过该边缘的一个水平剖面。
数字图像都存在被模糊且带有噪声的边缘,图b斜坡的斜度与边缘的模糊程度成反比。在这一模型中,不再存在一条细的(1像素宽)轨迹。相反,一个边缘点现在是斜坡中包含的任何点。
边缘的第三种模型是所谓的“屋顶”边缘,这种边缘具有图c所示的特性。屋顶边缘是通过一个区域的线的模型,屋顶边缘的基底(宽度)由该线的宽度和尖锐度决定。
10.2.4基本边缘检测
灰度变化也可以用一阶导数来完成。梯度是图像边缘的强度和方向,梯度用Vf来表示,并用向量来定义:
罗伯特交叉梯度算子是最早尝试使用具有对角优势的二维模板之一。公式如下:
Prewitt算子携带了更多有关边缘方向的信息,公式如下:
Sobel算子在上式中心系数加了个权值2,可以平滑图像,公式如下:
罗伯特算子实验代码和结果:
import cv2
import numpy as np
# 读取图像
image = cv2.imread('haitan.png', cv2.IMREAD_GRAYSCALE)
# 定义罗伯特交叉算子
roberts_cross_v = np.array([[1, 0], [0, -1]])
roberts_cross_h = np.array([[0, 1], [-1, 0]])
# 应用罗伯特交叉算子进行边缘检测
vertical_edges = cv2.filter2D(image, -1, roberts_cross_v)
horizontal_edges = cv2.filter2D(image, -1, roberts_cross_h)
# 合并垂直和水平边缘图像
edges = cv2.addWeighted(vertical_edges, 0.5, horizontal_edges, 0.5, 0)
# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Roberts Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
Prewitt算子实验代码和结果:
import cv2
import numpy as np
# 读取图像
image = cv2.imread('haitan.png', cv2.IMREAD_GRAYSCALE)
# 缩小图像(可选)
# scaled_image = cv2.resize(image, None, fx=0.5, fy=0.5)
# 定义Prewitt算子
prewitt_x = np.array([[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]])
prewitt_y = np.array([[-1, -1, -1],
[0, 0, 0],
[1, 1, 1]])
# 应用Prewitt算子进行边缘检测
edges_x = cv2.filter2D(image, -1, prewitt_x)
edges_y = cv2.filter2D(image, -1, prewitt_y)
# 合并x和y方向的边缘检测结果
edges = cv2.addWeighted(edges_x, 0.5, edges_y, 0.5, 0)
# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Prewitt Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
Sobel算子实验代码和结果:
import cv2
import numpy as np
# 读取图像
image = cv2.imread('haitan.png', cv2.IMREAD_GRAYSCALE)
# 缩小图像(可选)
# scaled_image = cv2.resize(image, None, fx=0.5, fy=0.5)
# 应用Sobel算子进行边缘检测
sobel_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
sobel_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
# 将结果转换为uint8类型
sobel_x = cv2.convertScaleAbs(sobel_x)
sobel_y = cv2.convertScaleAbs(sobel_y)
# 合并x和y方向的边缘检测结果
edges = cv2.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0)
# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Sobel Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
10.2.5更先进的边缘检测技术
Marr-Hildreth边缘检测器,将更高级的分析结合到边缘检测处理。
Marr-Hildreth边缘检测器的代码实验及结果:
import cv2
import numpy as np
# 读取图像并转换为灰度图
image = cv2.imread('haitan.png', cv2.IMREAD_GRAYSCALE)
# 定义Marr-Hildreth边缘检测函数
def apply_marr_hildreth(image, sigma):
# 计算Laplacian of Gaussian (LoG)
blurred = cv2.GaussianBlur(image, (0, 0), sigma)
laplacian = cv2.Laplacian(blurred, cv2.CV_64F)
# 寻找零交叉点
laplacian_sign = np.sign(laplacian)
laplacian_sign[laplacian_sign == 0] = -1
zero_crossings = np.zeros(laplacian.shape, dtype=np.uint8)
for i in range(1, laplacian.shape[0] - 1):
for j in range(1, laplacian.shape[1] - 1):
if laplacian_sign[i, j] != laplacian_sign[i - 1, j] or laplacian_sign[i, j] != laplacian_sign[i + 1, j] or \
laplacian_sign[i, j] != laplacian_sign[i, j - 1] or laplacian_sign[i, j] != laplacian_sign[
i, j + 1]:
zero_crossings[i, j] = 255
return zero_crossings
# 调用Marr-Hildreth边缘检测函数
sigma = 1.4 # LoG中的高斯模糊参数
edges = apply_marr_hildreth(image, sigma)
# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Marr-Hildreth Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
坎尼边缘检测器算法更为复杂,但低错误率,边缘点应被很好地定位以及是单一的边缘点响应。
坎尼边缘检测器算法的代码实验及结果:
import cv2
import numpy as np
# 读取图像并转换为灰度图
image = cv2.imread('haitan.png', cv2.IMREAD_GRAYSCALE)
# 使用Canny边缘检测算法
edges = cv2.Canny(image, threshold1=100, threshold2=200) # 这里的阈值可以根据具体情况调整
# 显示原始图像和边缘检测结果
cv2.imshow('Original Image', image)
cv2.imshow('Canny Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
10.2.6边缘链接和边缘检测
边缘检测:是数字图像处理中的一项基本任务,旨在识别图像中明显变化的区域,通常是表示物体边界的线条。边缘检测可以帮助我们分割物体、识别形状、进行目标检测等应用。
边缘连接:边缘检测通常会产生断断续续的边缘线条。边缘连接是指将这些断续的边缘线条连接成连续的轮廓或边界。
局部处理:局部处理是指在边缘检测后,对局部区域内的边缘进行处理,以消除小的断点或不连续。
区域处理:区域处理是指考虑到更大范围内的像素信息,以确保在边缘检测的基础上,相邻区域内的边缘能够正确连接。
全局处理:全局处理考虑整幅图像的边缘分布和结构,以进一步优化边缘连接的质量和准确性。
10.3阈值处理
10.3.1基础知识
从背景中提取物体的一种明显方法是选择一个将这些模式分开的阈值T。然后,f(x,y)>T的任何点(x,y)称为一个对象点;否则将该点称为背景点。换句话说,分割后的图像g(x,y)由下式给出:
当T是一个适用于整个图像的常数时,该公式给出的处理称为全局阈值处理。
当a,b和c是任意三个不同的灰度值。且
而影响波谷特性的关键因素是:
(1)波峰间的间隔(波峰离得越远,分离这些模式的机会越好);
(2)图像中的噪声内容(模式随噪声的增加而展宽);
(3)物体和背景的相对尺寸;
(4)光源的均匀性;
(5)图像反射特性的均匀性。
10.3.2基本的全局阈值处理
通常图像之间有较大变化,即使全局阈值是一种合适的方法,步骤如下:
1.为全局阈值T选择一个初始估计值。
2.用T分割该图像。这将产生两组像素:G₁由灰度值大于T的所有像素组成,G₂由所有小于等于T的像素组成。
3.对G₁和G₂的像素分别计算平均灰度值(均值)m₁和m₂。
4.计算一个新的阈值:
5.重复步骤2到步骤4,直到连续迭代中的T值间的差小于一个预定义的参数△T为止。
下面为全局阈值处理的实验代码和结果:
import cv2
# 读取图像并转换为灰度图
image = cv2.imread('haitan.png', cv2.IMREAD_GRAYSCALE)
# 全局阈值处理
threshold_value = 128 # 设置阈值(这里以128为例)
max_value = 255 # 最大灰度值
# 使用cv2.threshold进行全局阈值处理
_, thresholded_image = cv2.threshold(image, threshold_value, max_value, cv2.THRESH_BINARY)
# 显示原始图像和阈值处理后的图像
cv2.imshow('Original Image', image)
cv2.imshow('Thresholded Image', thresholded_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
10.3.3用Otsu方法的最佳全局阈值处理
Otsu算法能够根据图像的灰度分布自动计算出一个最佳阈值,使得分割后的图像具有最佳的类间方差。
下面是 Otsu算法的实验代码和结果:
import cv2
# 读取图像并转换为灰度图
image = cv2.imread('haitan.png', cv2.IMREAD_GRAYSCALE)
# 使用Otsu算法自动选择最佳阈值
_, thresholded_image = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 显示原始图像和阈值处理后的图像
cv2.imshow('Original Image', image)
cv2.imshow('Thresholded Image', thresholded_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
10.3.4用图像平滑改善全局阈值处理
当噪声不能在源头减少,并且阈值处理又是所选择的分割方法时,那么通常可增强性能的一种技术是在阈值处理之前平滑图像。
下图为直接对噪声图像进行处理和经过平滑图像后对噪声图像处理:
10.3.5利用边缘改进全局阈值处理
利用边缘改进全局阈值处理是通过先进行边缘检测或边缘保护滤波等手段,获取图像中目标边缘的位置和信息,然后根据这些信息调整全局阈值处理方法,以提高在复杂背景或目标边缘模糊情况下的分割效果。这种方法能够减少阈值处理中因背景复杂性或目标边缘模糊导致的误分割问题,从而更精确地提取目标或进行图像分割。
步骤如下:
1.用10.2节讨论的任何一种方法来计算一幅边缘图像,无论是f(x,y)梯度的幅度还是拉普拉斯的绝对值都可以。
2.指定一个阈值T。
3.用步骤2中的阈值对步骤1中的图像进行阈值处理,产生一幅
二值图像g₇(x,y)。在从f(x,y)中选取对应于“强”边缘像素的下一步中,该图像用做一幅模板图像。
4.仅用f(x,y)中对应于gr(x,y)中像素值为1的位置的像素计算直方图
5.用步骤4中的直方图全局地分割f(x,y),例如使用Otsu方法。
10.3.6多阈值处理
多阈值处理使用多个阈值对图像进行多次分割,然后根据每个阈值处理后的结果进行组合或加权,以获得更准确的最终二值化或分割图像。这种方法能够充分利用不同阈值处理后的信息,弥补单一阈值处理可能遗漏的细节或边缘信息,提高图像分割的精度,适用于复杂场景或需要精细分割的图像处理任务。
多阈值处理的实验代码和结果:
import cv2
import numpy as np
# 读取图像并转换为灰度图
image = cv2.imread('haitan.png', cv2.IMREAD_GRAYSCALE)
# 第一个阈值处理
_, thresh1 = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)
# 第二个阈值处理
_, thresh2 = cv2.threshold(image, 150, 255, cv2.THRESH_BINARY)
# 将两个阈值处理后的图像进行组合
combined_image = cv2.bitwise_or(thresh1, thresh2)
# 显示原始图像和多阈值处理后的图像
cv2.imshow('Original Image', image)
cv2.imshow('Combined Thresholded Image', combined_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
10.3.7可变阈值处理
图像分块:可变阈值处理最简单的方法之一是把一幅图像分成不重叠的矩形。这种方法用于补偿光照和/或反射的不均匀性。选择的矩形要足够小,以便每个矩形的光照都近似是均匀的。
基于局部图像特性的可变阈值处理:用一幅图像中每个点的一个邻域内的像素的标准差和均值来说明局部阈值处理的基本方法。
10.4基于区域的分割
10.4.1区域生长
区域生长是根据预先定义的生长准则将像素或子区域组合为更大区域的过程。基本方法是从一组“种子”点开始,将与种子预先定义的性质相似的那些邻域像素添加到每个种子上来形成这些生长区域(如特定范围的灰度或颜色)。
令f(x,y)表示一个输入图像阵列;S(x,y)表示一个种子阵列,阵列中种子点位置处为1,其他位置处为0;Q表示在每个位置(x,y)处所用的属性。算法步骤抵消:
1.在S(x,y)中寻找所有连通分量,并把每个连通分量腐蚀为一个像素;把找到的所有这种像素标记为1,把S中的所有其他像素标记为0。
2.在坐标对(x,y)处形成图像fo:如果输入图像在该坐标处满足给定的属性Q,则令
fe(x,y)=1,否则令fe(x,y)=0。
3.令g是这样形成的图像:即把fo中为8连通种子点的所有1值点,添加到S中的每个种子点。
4.用不同的区域标记(如1,2,3,…)标出g中的每个连通分量。这就是由区域生长得到的分割图像。
10.4.2区域分裂和聚合
区域分裂和聚合是图像分割中常用的两种基于区域的方法。区域分裂指根据预定义的准则将初始区域逐步分割成更小的子区域,直到满足某些停止条件。这可以通过分裂每个区域,如使用阈值或边缘检测算法来实现。区域聚合则是相反的过程,它将相邻或重叠的区域合并为更大的区域,以减少分割后的区域数量或消除不需要的分割边界,通常基于区域的特征或相似度进行合并。
10.5用形态学分水岭的分割
形态学分水岭分割是一种基于数学形态学理论的图像分割方法,旨在有效地处理具有复杂结构和多重对象重叠的图像。其主要思想是将图像视为地形,其中灰度值表示高度,然后通过水域分割线(分水岭)来分隔不同的区域。这种方法包括以下关键步骤:
1.预处理:首先对图像进行预处理,例如去噪、灰度变换等,以准备好进行后续的分水岭变换。
2.灰度标记:通过灰度变换(如梯度、距离变换等),生成灰度标记,将梯度图像视为地形的高度图。
3.寻找种子点:确定潜在的对象区域和背景区域的种子点,这些种子点通常对应于图像中明显的前景和背景特征。
4.泛洪填充:从这些种子点开始,通过泛洪填充(Flood Fill)或类似的方法,将灰度标记向外扩展,直到不同区域的标记相遇。
5.分水岭变换:在泛洪填充的基础上,应用分水岭变换来处理标记的合并和分隔,确保不同对象之间有清晰的分界线。
6.后处理:对分割结果进行后处理,如去除小的无关区域、填充空洞等,以获得最终的分割结果。
10.6分割中运动的应用
10.6.1空间域技术
分别检测在时刻t,和t,获取的两帧图像帧f(x,y,t)和f(x,y,t)之间的变化的最简方法之一是逐像素地比较这两幅图像。在时刻t,和t,获取的两幅图像间的差值图像可以定义为:
10.6.2频率域技术
频率域技术是一种基于信号处理和数学变换的方法,用于分析和处理信号或图像。它的核心思想是将信号或图像从时域转换到频率域,通过不同频率成分的分析来获取更多信息或实现特定的处理目标。常见的频率域技术包括傅里叶变换及其变体,它们能够将信号分解为不同频率的复合波,从而使得信号的特征更加明确,例如在图像处理中可以用于去除噪声、增强特定频率成分或进行滤波等操作。