如何基于Google Vision归一化顶点使用Python OpenCV裁剪图像
OpenCV适配Google Vision目标检测归一化坐标偏移解决方案
问题描述
- 运行环境:Python
- 业务逻辑:对接Google Vision多对象检测能力,基于接口返回的
boundingPoly.normalizedVertices归一化顶点数据,通过OpenCV实现原始图像的目标区域裁剪 - 异常现象:参考公开社区方案编写轮廓绘制、区域裁剪代码后,绘制的检测轮廓与实际目标位置存在偏移,裁剪结果无法匹配目标位置;经校验排除接口误差,Google Vision返回的目标定位结果本身准确
- 复现材料:接口返回示例响应结构、业务场景实测归一化坐标点、测试原图、错误效果截图、正确识别结果截图
根因分析
OpenCV读取图像后返回的
ndarray对象的shape属性维度顺序为(高度, 宽度, 通道数),与Google Vision返回的归一化坐标(x, y)对应的(宽度, 高度)映射逻辑不匹配,直接按shape返回顺序做系数相乘会导致像素坐标计算错误。
修复方案
错误实现(触发位置偏移)
import cv2 # 读取测试图像 img = cv2.imread("test_target.jpg") img_h, img_w = img.shape[:2] # 接口返回的示例归一化顶点 norm_vertices = [ {"x": 0.12, "y": 0.08}, {"x": 0.48, "y": 0.08}, {"x": 0.48, "y": 0.62}, {"x": 0.12, "y": 0.62} ] pixel_points = [] for v in norm_vertices: # 错误:宽高映射顺序颠倒,x乘了高度、y乘了宽度 px = int(v["x"] * img_h) py = int(v["y"] * img_w) pixel_points.append([px, py]) # 后续绘制轮廓、裁剪逻辑均会出现偏移
正确实现(坐标完全匹配)
import cv2 import numpy as np # 读取测试图像 img = cv2.imread("test_target.jpg") # OpenCV shape顺序:高度、宽度、通道数 img_h, img_w = img.shape[:2] # 接口返回的示例归一化顶点 norm_vertices = [ {"x": 0.12, "y": 0.08}, {"x": 0.48, "y": 0.08}, {"x": 0.48, "y": 0.62}, {"x": 0.12, "y": 0.62} ] x_coords = [] y_coords = [] for v in norm_vertices: # 正确映射:x对应宽度维度,y对应高度维度 px = int(v["x"] * img_w) py = int(v["y"] * img_h) x_coords.append(px) y_coords.append(py) # 计算裁剪框边界 x1, x2 = min(x_coords), max(x_coords) y1, y2 = min(y_coords), max(y_coords) # OpenCV数组切片顺序:高度方向索引在前,宽度方向索引在后 crop_result = img[y1:y2, x1:x2] # 绘制检测轮廓验证 contour = np.array(list(zip(x_coords, y_coords)), dtype=np.int32) cv2.polylines(img, [contour], isClosed=True, color=(0, 255, 0), thickness=2) cv2.imwrite("correct_detect_result.jpg", img)
注意事项
- Google Vision返回的归一化坐标值域为[0,1],x为水平方向(宽度)占比,y为垂直方向(高度)占比
- OpenCV图像矩阵的索引规则为
[行号(高度方向), 列号(宽度方向)],做区域裁剪时不要颠倒宽高的切片顺序
内容的提问来源于stack exchange,提问作者James Parker
相关产品推荐
相关产品推荐

