在图像处理过程中,若经过分割后的图像存在倾斜现象,会为后续的分析与识别带来不便。因此,需要对倾斜图像进行矫正处理,使其恢复水平状态。本文介绍一种基于 OpenCV 的图像自动矫正方法,利用霍夫变换检测直线,并计算整体旋转角度,最终通过仿射变换实现图像校正。
主要处理流程如下:
- 使用 Canny 算子提取图像边缘;
- 应用霍夫变换检测图像中的直线;
- 筛选出可用于角度估计的直线并计算平均倾斜角;
- 构建旋转矩阵,将图像反向旋转至水平;
- 使用仿射变换完成图像矫正。
步骤一:边缘检测与直线提取
首先读取输入图像并转换为灰度图,随后使用 Canny 算法提取边缘信息:
img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
canny_img = cv2.Canny(img, 50, 200, 3)
接着调用 cv2.HoughLines 方法检测图像中所有直线。该函数返回的结果是一个包含多个 (rho, theta) 参数对的数组,其形状为 (N, 1, 2),其中 N 是检测到的直线数量。
lines = cv2.HoughLines(canny_img, rho=1, theta=np.pi/180, threshold=100)
参数说明:
- rho:从图像左上角原点到直线的垂直距离;
- theta:从原点引向直线的垂线与 x 轴正方向之间的夹角,顺时针方向为正。
步骤二:绘制直线并分类筛选
为了可视化每条直线,定义一个辅助函数用于根据 rho 和 theta 计算直线的两个端点:
def _compute_line_pt(rho, theta, size=(2000,2000)):
a, b = np.cos(theta), np.sin(theta)
x0, y0 = a * rho, b * rho
x1 = int(x0 + size[0] * (-b))
y1 = int(y0 + size[1] * a)
x2 = int(x0 - size[0] * (-b))
y2 = int(y0 - size[1] * a)
return (x1,y1), (x2, y2)
遍历所有检测出的直线,根据 theta 值判断其方向。当 theta 接近 0 或 π/2 时,对应的是接近水平或垂直的直线。我们关注的是接近水平的线条(即 theta ∈ [π/4, 3π/4] 之外的部分),这些线条更能反映图像的整体倾斜趋势。
thetas, out_thetas = [], []
for rho, theta in lines[:, 0]:
pt1, pt2 = _compute_line_pt(rho, theta)
if (theta < np.pi/4) or (theta > 3*np.pi/4):
cv2.line(img_hough, pt1, pt2, (0, 255, 0), 2)
out_thetas.append(theta)
else:
thetas.append(theta)
cv2.line(img_hough, pt1, pt2, (255, 0, 0), 2)
在结果图中,绿色线条表示被忽略的方向(非主倾斜方向),蓝色线条则用于后续角度估算。红色粗线代表最终计算得出的主要倾斜方向。
步骤三:计算平均旋转角度
将所有符合条件的蓝色直线的 theta 角度取平均值,得到图像的整体倾斜角度。由于 OpenCV 中旋转为逆时针为正,因此需对该角度取负值以实现反向旋转矫正。
步骤四:生成旋转矩阵并进行图像变换
使用 cv2.getRotationMatrix2D 函数生成二维旋转矩阵。设置图像中心为旋转中心,缩放比例保持为 1.0,避免图像变形。
h, w = img_hough.shape[:2]
c_h, c_w = h // 2, w // 2
matrix = cv2.getRotationMatrix2D((c_w, c_h), -rotation_degree, 1.0)
dst = cv2.warpAffine(img, matrix, (w,h))
步骤五:执行仿射变换完成矫正
调用 cv2.warpAffine 对原图进行旋转矫正:
rotated_img = cv2.warpAffine(
src=img,
M=matrix,
dsize=(w, h),
flags=cv2.INTER_LINEAR,
borderMode=cv2.BORDER_CONSTANT,
borderValue=(0, 0, 0)
)
参数解释:
- src:输入图像(numpy 数组);
- M:2×3 的仿射变换矩阵;
- dsize:输出图像尺寸(宽度, 高度);
- dst:可选输出图像;
- flags:插值方式,默认使用双线性插值;
- borderMode:边界填充模式;
- borderValue:填充颜色(BGR 格式)。
最终效果展示
下图为原始倾斜图像与矫正后结果的对比:



雷达卡


京公网安备 11010802022788号







