如何将图像中的所有物体旋转调整为垂直朝向?
OpenCV图像物体朝向垂直对齐问题修正
你提供的代码存在以下几处错误,导致无法实现需求:
cv2.findContours的返回值处理逻辑错误,你将取值切片[-2:]单独放在一行,没有赋值给变量,这行代码完全不生效。不同版本OpenCV的findContours返回值数量不同,必须用[-2:]取最后两个返回值才能稳定拿到轮廓和层级信息。- 对
cv2.minAreaRect返回的角度参数理解错误,该角度的取值范围是**[-90, 0)**,不存在大于0的情况,你写的if angle>0分支永远不会触发,角度计算逻辑完全失效。 - 代码中使用了未定义的变量
cimg,你前面只定义了image、Gray、binary三个变量,运行时会直接报错。 - 现有逻辑是每检测到一个轮廓就旋转整张原图,只能对齐当前遍历到的物体的朝向,其他物体朝向会更歪,没法实现所有物体都垂直的需求。如果需要让所有独立物体分别对齐垂直方向,需要先把每个物体从原图中抠出,单独旋转后再放回对应位置。
修正后的多物体分别对齐垂直代码
import cv2 import numpy as np from scipy import ndimage from matplotlib import pyplot as plt # 读取图像 image = cv2.imread(r'C:\Users\Desktop\Sam.jpg') # 转换为灰度图 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 二值化处理 _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV) # 提取外轮廓,正确处理不同版本OpenCV的返回值 contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2:] # 创建输出画布,和原图大小一致 output = np.zeros_like(image) for cnt in contours: # 过滤小噪声轮廓 if cv2.contourArea(cnt) < 10: continue # 计算最小外接矩形 rect = cv2.minAreaRect(cnt) (cx, cy), (w, h), angle = rect # 修正角度计算逻辑 if w > h: angle += 90 # 计算需要旋转的角度 rotate_angle = -angle # 提取当前物体的掩码 mask = np.zeros_like(gray) cv2.drawContours(mask, [cnt], -1, 255, -1) # 抠出物体区域 obj = cv2.bitwise_and(image, image, mask=mask) # 裁剪物体的外接矩形区域减少计算量 x, y, w_rect, h_rect = cv2.boundingRect(cnt) obj_crop = obj[y:y+h_rect, x:x+w_rect] mask_crop = mask[y:y+h_rect, x:x+w_rect] # 旋转物体和掩码 rotated_obj = ndimage.rotate(obj_crop, rotate_angle, reshape=True) rotated_mask = ndimage.rotate(mask_crop, rotate_angle, reshape=True) # 计算旋转后物体放回原图的位置 new_h, new_w = rotated_obj.shape[:2] new_x = int(cx - new_w / 2) new_y = int(cy - new_h / 2) # 处理边界溢出的情况 if new_x < 0: rotated_obj = rotated_obj[:, -new_x:] rotated_mask = rotated_mask[:, -new_x:] new_x = 0 if new_y < 0: rotated_obj = rotated_obj[-new_y:, :] rotated_mask = rotated_mask[-new_y:, :] new_y = 0 if new_x + rotated_obj.shape[1] > output.shape[1]: rotated_obj = rotated_obj[:, :output.shape[1] - new_x] rotated_mask = rotated_mask[:, :output.shape[1] - new_x] if new_y + rotated_obj.shape[0] > output.shape[0]: rotated_obj = rotated_obj[:output.shape[0] - new_y, :] rotated_mask = rotated_mask[:output.shape[0] - new_y, :] # 将旋转后的物体放回输出画布 output[new_y:new_y+rotated_obj.shape[0], new_x:new_x+rotated_obj.shape[1]][rotated_mask>0] = rotated_obj[rotated_mask>0] # 显示结果 plt.figure(figsize=(10,10)) plt.imshow(cv2.cvtColor(output, cv2.COLOR_BGR2RGB)) plt.axis('off') plt.show()
如果你只需要对齐单张图里的单个物体,直接对整张图按照上面的角度计算逻辑旋转即可,不需要单独抠取每个物体。
内容的提问来源于stack exchange,提问作者zma
相关产品推荐
相关产品推荐

