如何使用OpenCV校准旋转图像,使数字行保持未旋转状态?
图像旋转修正解决方案
问题描述
- 正常图像包含三个六边形和一行未旋转的数字
- 异常图像存在不同角度的旋转,需修正为数字行保持水平的状态
示例图像

用OpenCV实现的步骤
1. 图像预处理
先将图像转为灰度图并二值化,突出目标轮廓:
import cv2 import numpy as np # 读取图像(替换为你的图片路径) img = cv2.imread('rotated_image.png') # 转灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 自适应二值化,适配不同光照 _, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
2. 计算旋转角度
通过数字行的轮廓外接矩形获取旋转角度:
# 查找所有外部轮廓 contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 筛选数字区域的轮廓(用面积过滤掉六边形的大轮廓,阈值按需调整) digit_contours = [cnt for cnt in contours if cv2.contourArea(cnt) < 500] # 合并数字轮廓,计算最小外接矩形 combined_cnt = np.concatenate(digit_contours) rect = cv2.minAreaRect(combined_cnt) angle = rect[2] # 修正角度范围:minAreaRect返回的角度是[-90,0),转换为实际需要旋转的角度 if angle < -45: angle = 90 + angle
3. 旋转修正图像
根据计算的角度旋转图像,避免内容被裁剪:
# 获取图像中心 h, w = img.shape[:2] center = (w // 2, h // 2) # 生成旋转矩阵 rot_mat = cv2.getRotationMatrix2D(center, angle, 1.0) # 计算旋转后的图像尺寸,防止内容被裁掉 cos_val = np.abs(rot_mat[0, 0]) sin_val = np.abs(rot_mat[0, 1]) new_width = int(h * sin_val + w * cos_val) new_height = int(h * cos_val + w * sin_val) # 调整旋转矩阵的平移参数,让图像居中 rot_mat[0, 2] += (new_width / 2) - center[0] rot_mat[1, 2] += (new_height / 2) - center[1] # 执行旋转,用INTER_CUBIC保证画质,BORDER_REPLICATE填充边缘 corrected_img = cv2.warpAffine(img, rot_mat, (new_width, new_height), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)
4. 可选优化:结合六边形轮廓校验角度
如果数字轮廓识别不准,可以提取三个六边形的大轮廓,计算它们的整体旋转角度,和数字行的角度交叉验证,取更准确的结果:
# 筛选六边形轮廓(面积较大的三个) hex_contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3] combined_hex_cnt = np.concatenate(hex_contours) hex_rect = cv2.minAreaRect(combined_hex_cnt) hex_angle = hex_rect[2] if hex_angle < -45: hex_angle = 90 + hex_angle # 取两个角度的平均值或者更稳定的那个 final_angle = (angle + hex_angle) / 2
内容的提问来源于stack exchange,提问作者vincy9501
相关产品推荐
相关产品推荐

