点、线和边缘检测
边缘像素是图像中灰度突变的那些像素,而边缘是连接的边缘像素的集合。边缘检测器是设计用来检测边缘像素的局部图像处理方法。
背景知识
按如下方式来得到一维函数 f ( x ) f(x) f(x)在点 x x x处的导数的近似:将函数 f ( x + △ x ) f(x+\bigtriangleup x) f(x+△x)展开为关于 x x x的泰勒级数,令 △ x \bigtriangleup x △x=1,结果如下:
∂ f ∂ x = f ′ ( x ) = f ( x + 1 ) − f ( x ) \frac{\partial f}{\partial x} = {f}^{\prime }\left( x\right) = f\left( {x + 1}\right) - f\left( x\right) ∂x∂f=f′(x)=f(x+1)−f(x)
对上式关于x微分,得到下式:
∂ 2 f ∂ x 2 = ∂ f ′ ( x ) ∂ x = f ′ ( x + 1 ) − f ′ ( x ) \frac{{\partial }^{2}f}{\partial {x}^{2}} = \frac{\partial {f}^{\prime }\left( x\right) }{\partial x} = {f}^{\prime }\left( {x + 1}\right) - {f}^{\prime }\left( x\right) ∂x2∂2f=∂x∂f′(x)=f′(x+1)−f′(x)
= f ( x + 2 ) − f ( x + 1 ) − f ( x + 1 ) + f ( x ) = f\left( {x + 2}\right) - f\left( {x + 1}\right) - f\left( {x + 1}\right) + f\left( x\right) =f(x+2)−f(x+1)−f(x+1)+f(x)
= f ( x + 2 ) − 2 f ( x + 1 ) + f ( x ) = f\left( {x + 2}\right) - {2f}\left( {x + 1}\right) + f\left( x\right) =f(x+2)−2f(x+1)+f(x)
下图(a)图像中包含有不同的实心物体、一条线和单个噪声点。图(b)显示了通过该图像中心的水平灰度剖面。灰度过渡涉及较细物体,如常称为屋顶边缘的线。图(c)显示了剖面线的简化。
得出如下结论(1)一阶导数通常在图像中产生较粗的边缘;(2)二阶导数对精细细节有较强的响应;(3)二阶导数在灰度斜坡和灰度台阶过渡处会产生双边缘响应;(4)二阶导数的符号可用于确定边缘的过渡是从亮到暗还是从暗到亮。
孤立点的检测
在图像处理中,孤立点检测是指识别并标识出图像中与周围像素显著不同的单个像素点。这些孤立点可能是噪声、异常值或者在图像中具有特定意义的关键点,具体取决于应用的上下文和目标。
孤立点检测的方法
1.基于阈值的方法:
全局阈值法:设定一个全局阈值,像素灰度值低于或高于该阈值的被认为是孤立点。
局部阈值法:使用不同的区域或像素邻域的灰度信息来动态调整阈值,提高检测的准确性。
2.基于邻域信息的方法:
像素与邻域像素比较:孤立点的定义是与周围像素显著不同,可以通过比较像素与其邻域像素的差异来判断孤立点。
像素与邻域平均值比较:计算像素与其邻域的平均灰度值,如果像素值与平均值差异大于一定阈值,则认为是孤立点。
3.统计方法:
基于概率模型:假设像素值服从某种分布(如高斯分布),利用统计学方法检测偏离该分布的孤立点。
4.空间域方法:
基于空间关系的方法:考虑像素在图像中的位置信息,利用像素点的空间分布特征来检测孤立点。
应用和场景
图像增强:在去除图像中的噪声点时,孤立点检测能够有效地过滤掉那些与周围像素差异明显的孤立像素,从而提高图像的质量。
物体识别和跟踪:在计算机视觉中,孤立点检测有助于识别和跟踪对象中的特定关键点,如面部识别中的眼睛或嘴巴。
异常检测:在监控系统或自动化生产中,孤立点检测可以用来识别异常或异常情况,如检测工业设备中的异常振动或温度。
线检测
对于线检测,可以预期二阶导数将导致更强的响应,并产生比一阶导数更细的线。下图(a)是原二值图像,(b)是其拉普拉斯图像。©为了使拉普拉斯图像更清晰,取其绝对值,(d)图取其正值。
从(b)到(d)图的变化中,当线的宽度比拉普拉斯模板的尺寸宽时,这些线就被一个零值“山谷”分开了。
边缘模型
边缘检测是基于灰度突变来分割图像的方法,边缘模型根据它们的灰度剖面来分类。
边缘模型通常指的是描述图像中边缘的数学模型或算法。边缘是图像中灰度值快速变化的区域,通常表示物体的边界或者图像中重要的结构信息。边缘检测和边缘增强是图像处理中常见的任务,边缘模型是实现这些任务的基础。
常见的边缘模型和算法
1.基于一阶导数的边缘检测方法:
Sobel算子:Sobel算子是一种常用的一阶导数算子,通过计算图像中每个像素点的梯度大小和方向来检测边缘。
Prewitt算子:类似于Sobel算子,也是基于一阶导数来计算梯度。
2.基于二阶导数的边缘检测方法:
Laplacian算子:Laplacian算子对图像进行二阶导数运算,可以检测出更细微的边缘。
LoG算子:LoG算子先对图像进行高斯平滑(平滑去噪),然后应用Laplacian算子来检测边缘。
3.基于梯度的边缘检测方法:
Canny边缘检测:Canny算法是一种多阶段的边缘检测算法,包括高斯平滑、计算梯度、非极大值抑制和边缘连接等步骤,通常被认为是最优的边缘检测方法之一。
4.基于模型的边缘检测方法:
Active Contour Models:这是一种基于能量最小化的方法,通过定义一个能量函数来描述图像中的边缘,并使用优化算法来找到最优边缘。
边缘模型的应用和意义
目标检测和识别:在计算机视觉中,边缘模型可以帮助检测和识别图像中的物体边界,是目标检测和分割的重要步骤。
图像分割:将图像分割成不同的区域或物体时,边缘模型可以作为分割的依据,帮助提取和描述物体的轮廓。
图像特征提取:边缘通常包含了物体的结构信息和形状特征,可以作为图像特征的一部分,用于后续的分析和识别任务。
基本边缘检测
在图像处理中,基本的边缘检测技术通常涉及图像梯度计算、梯度算子以及与阈值处理结合的方法。
图像梯度及其性质
图像梯度是指图像中灰度值变化最显著的方向和幅度。在二维离散图像中,通常使用一阶导数来计算图像的梯度。假设有一幅灰度图像 ( I(x, y) ),其梯度可以用以下两个分量来表示:
水平方向的梯度 ( G_x ):表示像素灰度值在水平方向上的变化程度。
垂直方向的梯度 ( G_y ):表示像素灰度值在垂直方向上的变化程度。
这两个分量可以通过以下公式计算得到:
[
G
x
=
∂
I
∂
x
,
G
y
=
∂
I
∂
y
]
[ G_x = \frac{\partial I}{\partial x}, \quad G_y = \frac{\partial I}{\partial y} ]
[Gx=∂x∂I,Gy=∂y∂I]其中,
(
∂
I
∂
x
)
( \frac{\partial I}{\partial x} )
(∂x∂I)和
(
∂
I
∂
y
)
( \frac{\partial I}{\partial y} )
(∂y∂I) 分别表示图像 ( I(x, y) ) 在水平和垂直方向上的灰度梯度。
梯度算子
为了计算图像的梯度,常用的算子包括:
1.Sobel算子:
Sobel算子结合了一阶导数的离散逼近,特别适合用于检测图像中的边缘。Sobel算子在水平和垂直方向上分别使用以下核来计算梯度:KaTeX parse error: Undefined control sequence: \- at position 34: …rix}-1 & 0 & 1 \̲-̲2 & 0 & 2 \-1 &…这些核用于对图像进行卷积操作,得到图像在水平和垂直方向上的梯度分量。
2.Prewitt算子:
类似于Sobel算子,Prewitt算子也是一种常用的边缘检测算子,通过不同的卷积核计算图像的梯度。
与阈值处理相结合的梯度
在边缘检测中,通常将梯度幅值作为边缘的强度指标。为了凸显边缘并进行边缘检测,可以结合阈值处理来实现:
1.梯度幅值计算:
计算梯度的幅值
(
Magnitude
=
G
x
2
+
G
y
2
)
( \text{Magnitude} = \sqrt{G_x^2 + G_y^2} )
(Magnitude=Gx2+Gy2),表示像素点的梯度强度。
2.阈值处理:
应用阈值将梯度幅值转换为二值图像(通常是黑白图像),其中大于阈值的像素被认为是边缘点,而小于阈值的像素则被视为非边缘点。
3.边缘连接:
可以使用边缘连接算法(如Canny边缘检测)进一步增强和链接检测到的边缘线段,得到连续的边缘轮廓。
边缘连接和边界检测
边缘连接和边界检测是两个重要的概念,用于将离散的边缘点连接成连续的边界或轮廓。这些技术对于目标检测、图像分割和特征提取等任务至关重要。
边缘连接
边缘连接是指将单个边缘点或边缘片段连接成连续的轮廓线或边界的过程。由于图像中检测到的边缘通常是不连续的,边缘连接技术可以通过以下几种方法实现:
1.局部处理:
边缘跟踪:在局部处理中,可以使用边缘跟踪算法,如基于梯度方向的跟踪(如Sobel算子的梯度方向),或者基于边缘像素邻近性的跟踪来连接相邻的边缘片段。
链码:使用链码描述边缘像素的连接顺序,从而重建边界。
2.区域处理:
边缘填充:利用区域生长或分水岭算法,将边缘点连接到相邻的区域边界上,形成闭合的区域边界。
3.全局处理:
霍夫曼变换:霍夫曼变换(Hough Transform)是一种全局处理方法,可以用来检测和连接图像中的直线、圆等形状。对于边缘连接,特别是检测直线的霍夫曼变换(Hough Line Transform)可以将离散的边缘点连接成直线段。
边界检测
边界检测是指在图像中检测和定位灰度变化显著的区域,通常用于边缘检测和图像分割的前期处理。常见的边缘检测方法已经在之前的回答中提到,包括Sobel、Prewitt、Laplacian等算子。以下是一些具体的应用和例子:
局部处理的例子:
在局部处理中,如果使用Sobel算子检测图像中的边缘,可以得到水平和垂直方向上的边缘响应。通过设置阈值并进行连接,可以得到连续的边缘线段。
区域处理的例子:
考虑一个图像中有多个物体的场景。通过使用区域生长或者分水岭算法,可以将离散的边缘点连接成各个物体的轮廓,从而实现精确的分割。
全局处理的例子:
使用霍夫曼变换检测图像中的直线。例如,如果需要检测一幅图像中的公路边界线,可以利用霍夫曼变换将离散的边缘点连接成直线段,从而精确地提取出公路的边界。
阈值处理
基础知识
灰度阈值处理基础:
灰度阈值处理是将灰度图像的每个像素值与一个阈值进行比较,并将像素值分为两个类别:大于阈值和小于等于阈值。这种方法对于分割具有明显灰度差异的目标非常有效。
图像阈值处理中噪声的作用:
在图像阈值处理中,噪声可以对结果产生显著影响。因为噪声会导致像素灰度值的随机波动,可能使得选择合适的阈值变得更加困难,或者导致不准确的分割结果。
光照和反射的作用:
图像中的光照和反射变化会导致目标区域的灰度值分布不均匀,这对于阈值选择也是一个挑战。例如,当光照不均匀时,可能需要动态调整阈值以适应不同区域的光照强度。具体例子参考下图:
基本的全局阈值处理
全局阈值处理是一种简单有效的方法,适用于整幅图像的阈值选择。
步骤:
Step 1: 将灰度图像转换为单通道灰度图。
Step 2: 选择一个合适的阈值 ( T ),该阈值将灰度图像分成目标(前景)和背景两部分。
Step 3: 遍历图像的每个像素,将像素灰度值与阈值 ( T ) 进行比较:
如果
(
pixel value
>
T
)
( \text{pixel value} > T )
(pixel value>T),则将像素值设为白色(255)。
如果
(
pixel value
≤
T
)
( \text{pixel value} \leq T )
(pixel value≤T),则将像素值设为黑色(0)。
Step 4: 得到二值化图像作为输出。
实验
import cv2
import numpy as np
from matplotlib import pyplot as plt
# 读取灰度图像
img = cv2.imread('D:\Pycharm Projects\pythonStudy\pythonProject1\iankong.jpg', 0)
# 全局阈值处理
_, binary_img = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 显示原始图像和处理结果
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(binary_img, cmap='gray')
plt.title('Binary Image'), plt.xticks([]), plt.yticks([])
plt.show()
实验结果如下
用Otsu方法的最佳全局阈值处理
Otsu方法是一种经典的自动阈值选择算法,旨在通过最小化类内方差和最大化类间方差来确定最佳的全局阈值。
原理
Otsu方法的核心思想是通过统计图像的灰度直方图,将图像分成两个类别(前景和背景),并尝试找到一个阈值,使得两个类别之间的方差最大化。具体步骤如下:
1.计算直方图:统计图像中每个灰度级别的像素数目。
2.初始化:计算总的像素数目以及每个灰度级别的像素数目累积和。
3.遍历灰度级别:对于每一个可能的阈值 ( k )(从0到255),计算以下值:
(
ω
0
(
k
)
)
( \omega_0(k) )
(ω0(k)) 和
(
ω
1
(
k
)
)
( \omega_1(k) )
(ω1(k)):分别是阈值 ( k ) 以下和以上的像素数占总像素数的比例。
(
μ
0
(
k
)
)
( \mu_0(k) )
(μ0(k))和
(
μ
1
(
k
)
)
( \mu_1(k) )
(μ1(k)):分别是阈值 ( k ) 以下和以上的像素的平均灰度值。
4.计算类内方差:对于每一个可能的阈值 ( k ),计算类内方差
(
σ
2
(
k
)
)
( \sigma^2(k) )
(σ2(k)):
[
σ
2
(
k
)
=
ω
0
(
k
)
⋅
ω
1
(
k
)
⋅
(
μ
0
(
k
)
−
μ
1
(
k
)
)
2
]
[\sigma^2(k) = \omega_0(k) \cdot \omega_1(k) \cdot (\mu_0(k) - \mu_1(k))^2]
[σ2(k)=ω0(k)⋅ω1(k)⋅(μ0(k)−μ1(k))2]
5.选择最佳阈值:选择使类间方差
(
σ
B
2
(
k
)
)
( \sigma_B^2(k) )
(σB2(k)) 最大的阈值 ( k ):
[
k
∗
=
arg
max
k
(
σ
B
2
(
k
)
)
]
[k^* = \arg \max_k(\sigma_B^2(k))]
[k∗=argmaxk(σB2(k))]
6.应用阈值:将图像根据阈值 ( k^* ) 进行二值化处理。
实验
import cv2
import numpy as np
from matplotlib import pyplot as plt
# 读取灰度图像
img = cv2.imread('D:\Pycharm Projects\pythonStudy\pythonProject1\iankong.jpg', 0)
# 使用Otsu方法计算最佳阈值
_, binary_img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 显示原始图像和处理结果
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(binary_img, cmap='gray')
plt.title('Binary Image (Otsu)'), plt.xticks([]), plt.yticks([])
plt.show()
实验结果如下:
在实验结果中,可以清楚地看到Otsu方法通过自动选择阈值,有效地将图像分成背景和前景两部分,适用于不同光照条件下的图像。这种方法不需要手动设定阈值,而是根据图像的灰度分布自动选择最佳的分割点,因此具有很好的普适性和实用性。
用图像平滑改善全局阈值处理
图像平滑是通过减少图像噪声来改善图像质量的一种技术。这通常是图像处理中的重要步骤,尤其是在使用全局阈值处理时,因为噪声可能导致错误的分割结果。全局阈值处理是一种简单有效的二值化方法,通过将图像中每个像素值与一个固定的阈值进行比较,决定该像素是属于前景还是背景。
常见的平滑算法包括:均值滤波、中值滤波、高斯滤波。
实验
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取原始图像
image = cv2.imread('D:\Pycharm Projects\pythonStudy\pythonProject1\iankong.jpg', cv2.IMREAD_GRAYSCALE)
# 添加噪声(可选)
noise = np.random.randint(0, 256, image.shape, dtype=np.uint8)
noisy_image = cv2.add(image, noise)
# 显示原始图像与噪声图像
plt.figure(figsize=(10, 5))
plt.subplot(1, 3, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 3, 2)
plt.imshow(noisy_image, cmap='gray')
plt.title('Noisy Image')
plt.axis('off')
# 使用高斯滤波进行平滑
smoothed_image = cv2.GaussianBlur(noisy_image, (5, 5), 0)
plt.subplot(1, 3, 3)
plt.imshow(smoothed_image, cmap='gray')
plt.title('Smoothed Image')
plt.axis('off')
plt.show()
# 全局阈值处理
_, binary_image = cv2.threshold(smoothed_image, 127, 255, cv2.THRESH_BINARY)
# 显示二值图像
plt.figure(figsize=(5, 5))
plt.imshow(binary_image, cmap='gray')
plt.title('Binary Image after Thresholding')
plt.axis('off')
plt.show()
# 保存结果
cv2.imwrite('binary_image.png', binary_image)
实验结果如下:
平滑算法的选取依赖于噪声类型和具体应用。一般来说,高斯滤波在处理高斯噪声时表现良好。
利用边缘改进全局阈值处理
利用边缘改进全局阈值处理是一种图像处理方法,可以通过检测图像中的边缘信息来优化全局阈值处理算法,从而提高图像的分割效果。该方法主要包括以下步骤:
1.边缘检测:使用边缘检测算法(如Canny算法、Sobel算法等)来提取图像中的边缘信息。
2.阈值处理:对原始图像进行全局阈值处理,得到一个初始的二值图像。
3.边缘增强:将步骤1中得到的边缘信息与步骤2中得到的二值图像进行逐像素的逻辑与操作,以增强边缘部分的信息。
4.迭代优化:根据步骤3中得到的边缘增强图像,重新计算全局阈值,并重复步骤2和步骤3,直到满足预设条件(如迭代次数、阈值变化范围等)。
实验
import cv2
import numpy as np
# 读取原始图像
img = cv2.imread('D:\Pycharm Projects\pythonStudy\pythonProject1\iankong.jpg', 0)
# 边缘检测
edges = cv2.Canny(img, 100, 200)
# 全局阈值处理
_, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 边缘增强
enhanced_edges = cv2.bitwise_and(edges, binary)
# 迭代优化
for i in range(5):
# 计算新的全局阈值
_, new_binary = cv2.threshold(enhanced_edges, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 边缘增强
enhanced_edges = cv2.bitwise_and(edges, new_binary)
# 显示结果
cv2.imshow("Original Image", img)
cv2.imshow("Binary Image", binary)
cv2.imshow("Enhanced Edges", enhanced_edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
实验结果如下:
多变量阈值处理
多变量阈值处理是一种图像分割方法,可以根据多个像素特征进行阈值处理,从而更准确地分割图像。与全局阈值处理只使用图像整体像素灰度值相比,多变量阈值处理可以利用更多的信息来确定阈值,提高分割的准确性。
步骤
1.确定输入特征:选择多个与图像分割相关的特征作为输入,可以包括灰度值、颜色通道、纹理特征等。
2.计算特征组合:对于每个像素,根据选定的特征组合计算一个综合特征值。可以根据实际需求,使用加权求和、逻辑运算等方式组合特征。
3.多变量阈值计算:利用Otsu算法或其他合适的方法,对特征组合值进行阈值计算。
4.分割图像:根据计算得到的阈值,将图像分成不同的区域或对象。
基于区域的分割
基于区域的分割是图像分割领域中的一种重要方法,其核心思想是将图像划分为若干个具有相似特征的区域。
区域生长
区域生长是一种从一组“种子”点开始的图像分割技术。这些种子点通常是手动选定的,或者通过某种算法自动确定。然后,根据预设的生长准则(如颜色、纹理、灰度值等),将种子点周围的相似像素加入到相应的区域中,直到没有更多的相似像素可以加入为止。
实验
import cv2
import numpy as np
def region_growing(img, seeds, low_bound, high_bound):
stack = [seeds]
res = np.zeros(img.shape, dtype=np.uint8)
while stack:
s = stack.pop()
i, j = s
res[i, j] = 255
# 检查周围8个领域
neighbors = [(i-1, j-1), (i-1, j), (i-1, j+1),
(i, j-1), (i, j+1),
(i+1, j-1), (i+1, j), (i+1, j+1)]
for ni, nj in neighbors:
if 0 <= ni < img.shape[0] and 0 <= nj < img.shape[1] and res[ni, nj] == 0:
if low_bound <= img[ni, nj] - img[i, j] <= high_bound:
stack.append((ni, nj))
return res
# 读取图像并转换为灰度图
image = cv2.imread('D:\Pycharm Projects\pythonStudy\pythonProject1\iankong.jpg', cv2.IMREAD_GRAYSCALE)
# 假设种子点为(x, y),且灰度值相似范围在[-threshold, threshold]
seeds = (60, 50)
threshold = 10
result = region_growing(image, seeds, -threshold, threshold)
# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Region Growing Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
实验结果如下:
结果图像Region Growing Result将显示基于种子点和预设阈值生长的区域。
区域分裂与聚合
区域分裂与聚合算法首先将图像视为一个整体区域,然后递归地将区域细分为更小的子区域,直到满足某种停止条件(如子区域大小小于预设阈值)。接着,算法会尝试将相邻的相似子区域合并成更大的区域。
伪代码思路如下:
# 伪代码
def split_and_merge(img, threshold_size, similarity_threshold):
# 初始化:将整幅图像作为一个区域
regions = [img]
# 分裂过程(简化处理)
# 这里应递归地将每个区域分割为更小的子区域
# ...
# 聚合过程
# 遍历所有相邻的区域对,如果相似则合并
# ...
# 返回最终的分割结果
return final_regions
用形态学分水岭的分割
背景知识
基本概念:形态学分水岭算法是图像分割的一种常用算法,主要用于将图像中的目标物体从背景中分离出来。该算法基于数学形态学原理,将图像视为地形图,其中目标物体为高地或山峰,背景为低地或山谷。
原理:算法通过一系列形态学运算(如腐蚀和膨胀),将图像中的目标物体抬高,同时使背景下沉,最终在目标物体与背景之间形成分水岭线,实现目标物体的分割。
应用场景:形态学分水岭算法广泛应用于医学图像分割、遥感图像分割、卫星图像处理等领域。
水坝构建
在形态学分水岭算法中,“水坝构建”实际上是指分水岭线的形成过程,而非传统意义上的水坝选型、结构设计和施工步骤。这一过程通过模拟水从低处流向高处的浸入过程来实现。具体来说,算法在每个局部极小值处开始注水,随着水位的上升,不同集水盆之间会形成分水岭线,即水坝。
分水岭分割算法
算法原理:
预处理:对原始图像进行灰度化和去噪处理。
梯度计算:计算图像的梯度图,以突出边缘信息。
二值化:对梯度图进行二值化处理,得到二值化图像。
形态学运算:对二值化图像进行形态学开操作(腐蚀后膨胀),以消除小物体和噪声。
连通区域标记:对形态学运算后的图像进行连通区域标记,得到连通区域的标签图。
分水岭变换:根据标签图计算分水岭线,即目标物体与背景之间的边界。
实验
import cv2
import numpy as np
from matplotlib import pyplot as plt
def watershed_segmentation(image_path):
# 读取图像
img = cv2.imread(image_path)
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)
# 确定背景区域
sure_bg = cv2.dilate(opening, kernel, iterations=3)
# 确定前景区域
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)
# 对标记进行修正,将未知区域标记为 0
markers = markers + 1
markers[unknown == 255] = 0
# 应用分水岭算法
markers = cv2.watershed(img, markers)
# 为不同区域上色
img[markers == -1] = [255, 0, 0]
# 显示结果
plt.subplot(121), plt.imshow(img)
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(markers)
plt.title('Segmented Image'), plt.xticks([]), plt.yticks([])
plt.show()
# 调用函数并传入图像路径
image_path = 'D:\Pycharm Projects\pythonStudy\pythonProject1\iankong.jpg'
watershed_segmentation(image_path)
实验结果如下:
原始图像中,不同的物体或区域可能具有相似的颜色和纹理。经过分水岭分割算法处理后,图像被分割成不同的区域,每个区域都被标记为不同的颜色或数值。
分割中运动的应用
空间域技术
空间域技术直接在像素值上操作,常见的方法包括背景减除、光流法等。
1.背景减除
这种方法假设场景中有一个静态背景,通过减去这个背景模型可以检测到前景物体的运动。
2.光流法
光流法是估计连续帧之间像素点移动方向和速度的方法。它利用了亮度一致性约束,即相邻帧中的相同像素具有相同的灰度值。
频率域技术
频率域技术则涉及将图像转换到不同的域(如傅里叶域),在该域内进行处理后再反变换回空间域。
傅里叶变换 :傅里叶变换可以用来提取视频序列中的周期性运动模式。例如,在某些应用中,可以通过分析频谱图中的特定频率成分来检测和分割周期性运动的物体。
实验:使用OpenCV进行背景减除
import cv2
import numpy as np
# 创建背景减除器
bg_subtractor = cv2.createBackgroundSubtractorMOG2()
# 打开摄像头
cap = cv2.VideoCapture(0)
while True:
# 读取一帧
ret, frame = cap.read()
if not ret:
break
# 应用背景减除
fg_mask = bg_subtractor.apply(frame)
# 显示原始帧和前景掩码
cv2.imshow('Original Frame', frame)
cv2.imshow('Foreground Mask', fg_mask)
# 按'q'键退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 清理资源
cap.release()
cv2.destroyAllWindows()
实验结果如下: