如何将YOLOv5输出的相对坐标边界框转换为NZTM2000绝对坐标
YOLOv5相对边界框转NZTM2000绝对坐标系方案
我用YOLOv5模型对带地理坐标的影像做树木预测,得到的是相对坐标格式的边界框,现在要把这些边界框转换成和影像一致的NZGD 2000新西兰横轴墨卡托(NZTM 2000)绝对坐标系。
现有YOLOv5推理代码
models= torch.hub.load('ultralytics/yolov5', 'custom', 'C:/Users/yolov5-master/runs/train/exp/weights/best.pt') im=r'C:\imagery1.PNG' results = models(im) results.print() results.show() results.xyxy[0] a=results.pandas().xyxy[0] df=pd.DataFrame(a) print(df)
边界框转多边形代码
# 多边形转边界框函数 def bbox(long0, lat0, lat1, long1): return Polygon([[long0, lat0], #long0=xmin, lat0=ymin, lat1=ymax, long1=xmax [long1,lat0], [long1,lat1], [long0, lat1]]) test = bbox(144.2734528,350.0042114,359.900177,152.4013672) test1=bbox(366.7437744,215.1108856,226.6479034,376.282196) gpd.GeoDataFrame(pd.DataFrame(['p1','p2'], columns = ['geom']), geometry = [test,test1]).to_file(r'C:\delete\poly1.shp')
影像地理信息
- 坐标系:NZGD 2000 New Zealand Transverse Mercator(NZTM 2000)
- 影像范围:
- 顶部(Y最大值):5702588.730967 m
- 底部(Y最小值):5702581.666007 m
- 左侧(X最小值):1902830.371719 m
- 右侧(X最大值):1902837.436679 m
转换步骤与代码实现
核心逻辑
相对坐标转绝对坐标的本质是像素坐标到地理坐标的线性映射:
- 获取影像的像素宽高
- 对每个边界框的xmin、xmax、ymin、ymax,按以下公式计算绝对坐标:
- 绝对X坐标 = 影像左侧X + (相对X像素值 / 影像像素宽度) * (影像右侧X - 影像左侧X)
- 绝对Y坐标 = 影像顶部Y - (相对Y像素值 / 影像像素高度) * (影像顶部Y - 影像底部Y)
(注:影像像素坐标系Y轴向下,地理坐标系Y轴向上,需做反向映射)
完整代码实现
import pandas as pd import geopandas as gpd from shapely.geometry import Polygon from PIL import Image import torch # 1. 加载YOLOv5结果与影像信息 models= torch.hub.load('ultralytics/yolov5', 'custom', 'C:/Users/yolov5-master/runs/train/exp/weights/best.pt') im_path = r'C:\imagery1.PNG' results = models(im_path) df = results.pandas().xyxy[0] # 获取影像像素宽高 img = Image.open(im_path) img_width, img_height = img.size # 影像地理范围(NZTM2000坐标系) img_left = 1902830.371719 # 左侧X img_right = 1902837.436679 # 右侧X img_top = 5702588.730967 # 顶部Y img_bottom = 5702581.666007 # 底部Y # 2. 定义坐标转换函数 def pixel_to_nztm(x_pixel, y_pixel): x_nztm = img_left + (x_pixel / img_width) * (img_right - img_left) y_nztm = img_top - (y_pixel / img_height) * (img_top - img_bottom) return x_nztm, y_nztm # 3. 批量转换边界框并生成GeoDataFrame geometries = [] for idx, row in df.iterrows(): xmin_pix, ymin_pix, xmax_pix, ymax_pix = row['xmin'], row['ymin'], row['xmax'], row['ymax'] xmin, ymin = pixel_to_nztm(xmin_pix, ymin_pix) xmax, ymax = pixel_to_nztm(xmax_pix, ymax_pix) poly = Polygon([[xmin, ymin], [xmax, ymin], [xmax, ymax], [xmin, ymax]]) geometries.append(poly) # 创建GeoDataFrame并保存为SHP文件(NZTM2000对应EPSG:2193) gdf = gpd.GeoDataFrame(df, geometry=geometries, crs="EPSG:2193") gdf.to_file(r'C:\delete\tree_bboxes_nztm.shp')
关键说明
- NZTM2000对应的EPSG编码是2193,保存SHP时必须指定正确CRS,否则坐标无效
- 确保影像未经过缩放、裁剪等变换,否则需额外校正参数
- 如果YOLO输出的是归一化坐标(0-1),先通过
x_pixel = x_norm * img_width、y_pixel = y_norm * img_height转换为像素坐标,再执行上述流程
内容的提问来源于stack exchange,提问作者user30985
相关产品推荐
相关产品推荐

