实习目的与意义¶

掌握图像分割和边缘检测的基本概念与原理,熟悉常用算法(阈值分割、Roberts、Sobel、Prewitt、LoG、Canny)及其适用场景。

理解数学形态学(腐蚀、膨胀、开运算、闭运算)的基本操作及在二值图像后处理中的作用。

提高使用 Python 和 OpenCV 进行遥感数字图像处理的编程能力,培养实验设计、结果分析与对比评估的综合素质。

通过动手实践,加深对算法优缺点和参数选择影响的认识,为后续高级影像处理研究奠定基础。

实习步骤简述¶

二值阈值分割: 调用 cv2.threshold 对原始影像进行阈值分割,生成二值图像并保存至 result/threshold/。

边缘检测: 分别使用 Roberts、Prewitt、Sobel、LoG、Canny 算子对原图或灰度图进行边缘检测,比较不同算子的检测效果,将结果保存至 result/edges/。

数学形态学处理:对步骤3生成的二值图像,依次进行腐蚀、膨胀、开运算、闭运算,并将各步骤处理后的图像保存至 result/morphology/。

结果查看与分析: 将各算法处理结果进行可视化对比,观察不同算法参数对分割、检测效果的影响。

In [219]:
import numpy as np
import cv2
import matplotlib.pyplot as plt
import rasterio
import warnings
warnings.filterwarnings("ignore")
In [220]:
# 二值化
with rasterio.open('data/chunk_2_2.tiff') as src:
    img = src.read(2)
    band_b = src.read(1)
    band_g = src.read(2)
    band_r = src.read(3)


img_max = img.max()
img_min = img.min()
img = ((img - img_min) / (img_max - img_min) * 255).astype(np.uint8)

binary_img = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)[1]
plt.imshow(binary_img, cmap='gray')
Out[220]:
<matplotlib.image.AxesImage at 0x1e574d11090>
No description has been provided for this image
In [221]:
# 边缘检测
# Roberts算子

roberts_x = np.array([[1, 0],
                   [0, -1]])
roberts_y = np.array([[0, 1],
                   [-1, 0]])

roberts_edge_x = cv2.filter2D(img, -1, roberts_x)
roberts_edge_y = cv2.filter2D(img, -1, roberts_y)
roberts_edge = np.sqrt(roberts_edge_x**2 + roberts_edge_y**2)
plt.imshow(roberts_edge, cmap='gray')
Out[221]:
<matplotlib.image.AxesImage at 0x1e574d66e90>
No description has been provided for this image
In [222]:
# 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_edge_x = cv2.filter2D(img, -1, prewitt_x)
prewitt_edge_y = cv2.filter2D(img, -1, prewitt_y)
prewitt_edge = np.sqrt(prewitt_edge_x**2 + prewitt_edge_y**2)
plt.imshow(prewitt_edge, cmap='gray')
Out[222]:
<matplotlib.image.AxesImage at 0x1e573128cd0>
No description has been provided for this image
In [223]:
# sobel算子
sobel_edge_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobel_edge_y = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobel_edge = np.sqrt(sobel_edge_x**2 + sobel_edge_y**2)
plt.imshow(sobel_edge, cmap='gray')
Out[223]:
<matplotlib.image.AxesImage at 0x1e573182ad0>
No description has been provided for this image
In [224]:
# 拉普拉斯-高斯算子
log_edge = cv2.GaussianBlur(img, (3, 3), 0)
log_edge = cv2.Laplacian(log_edge, cv2.CV_64F)
log_edge = np.absolute(log_edge)
plt.imshow(log_edge, cmap='gray')
Out[224]:
<matplotlib.image.AxesImage at 0x1e56ca94910>
No description has been provided for this image
In [225]:
# canny算子
canny_edge = cv2.Canny(img, 100, 200)
plt.imshow(canny_edge, cmap='gray')
Out[225]:
<matplotlib.image.AxesImage at 0x1e56caf6710>
No description has been provided for this image
In [234]:
# 腐蚀
img = band_g + band_r + band_b
img = ((img - img.min()) / (img.max() - img.min()) * 255).astype(np.uint8)
img = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)[1]
kernel = np.ones((5, 5), np.uint8)
erosion = cv2.erode(img, kernel, iterations=1)
plt.imshow(erosion, cmap='gray')
Out[234]:
<matplotlib.image.AxesImage at 0x1e57c3a3750>
No description has been provided for this image
In [238]:
# 膨胀
dilation = cv2.dilate(img, kernel, iterations=4)
plt.imshow(dilation, cmap='gray')
Out[238]:
<matplotlib.image.AxesImage at 0x1e57d1aafd0>
No description has been provided for this image
In [239]:
# 开运算
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
plt.imshow(opening, cmap='gray')
Out[239]:
<matplotlib.image.AxesImage at 0x1e57d228e10>
No description has been provided for this image
In [240]:
# 闭运算
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
plt.imshow(closing, cmap='gray')
Out[240]:
<matplotlib.image.AxesImage at 0x1e57d28ac10>
No description has been provided for this image

总结¶

Roberts、Prewitt、Sobel 属于一阶微分算子,对噪声较敏感但计算高效

LoG 作为二阶微分算子,能较好地定位边缘位置,但对图像平滑依赖较强

Canny 算法则因其多阶段流程(高斯滤波、梯度计算、非极大值抑制、双阈值检测)表现出最优的边缘连续性与抗噪能力。

心得体会¶

不同算法对参数高度敏感。例如 Canny 的高低阈值、形态学操作的核大小,都会显著影响结果质量。这让我意识到在实际项目中必须结合具体数据反复调试。