如何用Python与OpenCV将任意角度图像旋转至垂直0度?
用Python+OpenCV将任意倾斜图像纠正至垂直0度
完全可以实现你的需求,核心就是先检测图像的倾斜角度,再通过旋转操作抵消该角度。下面是具体的实现方案:
核心思路
- 图像预处理:将图像转为灰度并二值化,突出主体的轮廓/线条,为角度检测做准备
- 倾斜角度检测:通过霍夫变换检测直线角度,或通过轮廓的最小外接矩形提取旋转角度
- 图像旋转纠正:根据检测到的角度,对原图进行旋转,抵消倾斜并处理旋转后的黑边问题
代码实现
1. 导入依赖库
import cv2 import numpy as np
2. 图像预处理函数
def preprocess_image(image_path): # 读取图像 img = cv2.imread(image_path) # 转为灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 自适应二值化(适配不同光照条件) thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) return img, thresh
3. 倾斜角度检测(两种可选方法)
方法一:霍夫变换检测直线角度
适合文本类图像,通过检测文本行的直线方向判断倾斜角度
def detect_angle_hough(thresh_img): # 检测图像中的直线 lines = cv2.HoughLinesP(thresh_img, 1, np.pi/180, threshold=50, minLineLength=50, maxLineGap=10) angles = [] for line in lines: x1, y1, x2, y2 = line[0] # 计算直线的倾斜角度(弧度转角度) angle = np.arctan2(y2 - y1, x2 - x1) * 180 / np.pi angles.append(angle) # 取角度中位数,避免异常值干扰 median_angle = np.median(angles) # 调整角度至-45~45范围,对应垂直纠正的角度 if median_angle < -45: median_angle += 90 elif median_angle > 45: median_angle -= 90 return median_angle
方法二:轮廓最小外接矩形检测角度
适合有明确主体的图像,通过主体轮廓的外接矩形获取旋转角度
def detect_angle_contour(thresh_img): # 寻找图像中的外部轮廓 contours, _ = cv2.findContours(thresh_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 筛选出面积最大的轮廓(假设为图像主体) largest_contour = max(contours, key=cv2.contourArea) # 获取轮廓的最小外接矩形 rect = cv2.minAreaRect(largest_contour) angle = rect[2] # 调整角度至正确的纠正范围 if angle < -45: angle += 90 return angle
4. 图像旋转纠正函数
def rotate_image(image, angle): (h, w) = image.shape[:2] center = (w // 2, h // 2) # 生成旋转矩阵 M = cv2.getRotationMatrix2D(center, angle, 1.0) # 计算旋转后的图像尺寸,避免出现黑边 cos = np.abs(M[0, 0]) sin = np.abs(M[0, 1]) new_w = int((h * sin) + (w * cos)) new_h = int((h * cos) + (w * sin)) # 调整旋转矩阵的平移参数,让图像居中 M[0, 2] += (new_w / 2) - center[0] M[1, 2] += (new_h / 2) - center[1] # 执行旋转,用边缘复制填充空白区域 rotated = cv2.warpAffine(image, M, (new_w, new_h), borderMode=cv2.BORDER_REPLICATE) return rotated
5. 主调用示例
if __name__ == "__main__": # 替换为你的图像路径 img_path = "tilted_image.jpg" original_img, thresh_img = preprocess_image(img_path) # 选择一种角度检测方法 # angle = detect_angle_hough(thresh_img) angle = detect_angle_contour(thresh_img) # 旋转图像(负角度抵消原有倾斜) rotated_img = rotate_image(original_img, -angle) # 保存结果并显示 cv2.imwrite("vertical_image.jpg", rotated_img) cv2.imshow("Original", original_img) cv2.imshow("Vertical", rotated_img) cv2.waitKey(0) cv2.destroyAllWindows()
注意事项
- 预处理的二值化参数(如
11和2)可能需要根据你的图像调整,确保主体轮廓清晰 - 如果图像倾斜角度接近90度,两种方法都会自动调整为正确的纠正角度
- 旋转时的
borderMode参数可以替换为cv2.BORDER_CONSTANT,并用borderValue指定填充颜色
内容的提问来源于stack exchange,提问作者Jeremy Sapienza
相关产品推荐
相关产品推荐

