OpenCV 从入门到精通教程-第3章 图像几何变换

第3章 图像几何变换

3.1 缩放、平移、旋转

缩放

python

resized = cv2.resize(img, (width, height))   # 指定尺寸
resized = cv2.resize(img, None, fx=0.5, fy=0.5)   # 比例缩放

常用插值方法:cv2.INTER_LINEAR(默认)、cv2.INTER_CUBICcv2.INTER_AREA(适合缩小)。

平移:通过构建平移矩阵实现。

python

rows, cols = img.shape[:2]
# x 方向平移 50,y 方向平移 100
M = np.float32([[1, 0, 50], [0, 1, 100]])
translated = cv2.warpAffine(img, M, (cols, rows))

旋转

python

# 获取围绕图像中心的旋转矩阵(角度为正表示逆时针)
M = cv2.getRotationMatrix2D((cols/2, rows/2), 45, 1.0)
rotated = cv2.warpAffine(img, M, (cols, rows))

3.2 仿射变换与透视变换

仿射变换:平行线保持平行。需要原图中三个不共线的点和目标图中对应的三个点。

python

pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv2.getAffineTransform(pts1, pts2)
affine = cv2.warpAffine(img, M, (cols, rows))

透视变换:任意四边形到矩形的变换。需要四个对应点。

python

pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv2.getPerspectiveTransform(pts1, pts2)
perspective = cv2.warpPerspective(img, M, (300,300))

透视变换在文档扫描、车牌校正中非常常用。

3.3 图像金字塔

图像金字塔是同一图像不同分辨率的集合,常用于图像融合、特征检测。

  • 高斯金字塔:向下采样(缩小)
  • 拉普拉斯金字塔:由高斯金字塔计算而得,常用于图像恢复

python

lower_res = cv2.pyrDown(img)   # 宽度和高度减半
higher_res = cv2.pyrUp(img)    # 宽度和高度加倍

示例:反复执行下采样得到的图像金字塔。


第4章 图像滤波与增强

4.1 平滑滤波

平滑(模糊)可以去除噪声,但也可能丢失边缘细节。

  • 均值滤波:简单平均
  • 高斯滤波:加权平均,中心权重大,去噪同时保留边缘更多
  • 中值滤波:取邻域中值,有效去除椒盐噪声
  • 双边滤波:保持边缘的平滑,考虑空间邻近度和像素相似度

python

# 均值滤波 (5x5 核)
blur = cv2.blur(img, (5,5))
# 高斯滤波 (核大小必须为正奇数)
gaussian = cv2.GaussianBlur(img, (5,5), 0)
# 中值滤波 (核大小取奇数)
median = cv2.medianBlur(img, 5)
# 双边滤波 (直径, sigmaColor, sigmaSpace)
bilateral = cv2.bilateralFilter(img, 9, 75, 75)

4.2 边缘检测

边缘是图像中亮度急剧变化的区域。OpenCV 提供了多种边缘检测算子。

  • Sobel 算子:计算一阶导数,可指定方向。
  • Laplacian 算子:计算二阶导数。
  • Canny 边缘检测:最常用的方法,低错误率、良好定位。

python

# Sobel
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)   # x方向
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)   # y方向
sobel_absx = cv2.convertScaleAbs(sobelx)              # 转为 uint8
sobel_combined = cv2.addWeighted(sobel_absx, 0.5, cv2.convertScaleAbs(sobely), 0.5, 0)

# Laplacian
laplacian = cv2.Laplacian(img, cv2.CV_64F)
laplacian_abs = cv2.convertScaleAbs(laplacian)

# Canny(推荐使用灰度图)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 100, 200)   # 阈值1, 阈值2

Canny 中较小的阈值用于边缘连接,较大的阈值用于检测强边缘。通常阈值2是阈值1的2~3倍。

4.3 图像锐化

通过增强高频成分使图像边缘更清晰。可以自定义一个锐化核:

python

kernel = np.array([[0, -1, 0],
                   [-1, 5,-1],
                   [0, -1, 0]])
sharpened = cv2.filter2D(img, -1, kernel)

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注