Python 将深度学习目标检测的结果框转化为矢量的shapefile

本文介绍了一种将遥感影像中的目标检测结果转换为Shapefile的方法,便于地理信息系统(GIS)中的进一步分析。该方法使用Python编程实现,包括从TXT文件或数组中读取检测框坐标,并将其转换为地理坐标。
部署运行你感兴趣的模型镜像

在遥感影像的目标检测中,我们通常希望将检测结果与原始影像进行叠加,以便查看和分析。最简单的方法就是将检测结果输出成shapefile的形式,下面提供一种基于Python的转换方法

import os

import gdal
import geopandas as gpd
import ogr
import osr
import rasterio.features
import shapely


def box_list2shp(det_file, img_file, out_shapefile):
    """
    将一系列坐标点的边界框数据转换成shapefile
    :param det_file: 输入的检测结果文件,每一行为一个检测框(x1, y1, x2, y2, x3, y3, x4, y4, label)
    :param img_file: 输入的原始影像路径
    :param out_shapefile: 输出的矢量路径
    """

    bbox_data, label_data = get_box_from_txt(det_file, img_file)
    # bbox_data, label_data = get_box_from_array(det_file, img_file)
    with rasterio.open(img_file) as raster:   # 从原始影像中获取投影和几何信息
        crs = raster.crs

    polygon_list = []
    for i in range(len(bbox_data)):
        polygon = shapely.geometry.Polygon(bbox_data[i])
        polygon_list.append(polygon)

    out_data = gpd.GeoSeries(polygon_list, index=label_data, crs=crs)
    out_data.to_file(out_shapefile, driver='ESRI Shapefile', encoding='utf-8')
    print("successfully convert box-list to shapefile")

其中,get_box_from_txt函数是从DOTA格式的txt文件中读取检测框坐标和对应标签,代码如下:

import gdal

def get_box_from_txt(txt_file, img_file):
    """
    从txt文件中读取目标检测的边界框坐标点和标签信息
    :param img_file: 原始影像数据,为了获取投影信息
    :return box_data: 由图像坐标点组成的一系列边界框
    :return label_data : 边界框对应的标签信息
    """

    dataset = gdal.Open(img_file)
    with open(txt_file, 'r', encoding='utf-8') as f:
        bbox_data = []
        label_data = []
        for line in f.readlines():
            curLine = line.strip().split(" ")
            x1 = float(curLine[0])
            y1 = float(curLine[1])
            x2 = float(curLine[2])
            y2 = float(curLine[3])
            x3 = float(curLine[4])
            y3 = float(curLine[5])
            x4 = float(curLine[6])
            y4 = float(curLine[7])
            if dataset.GetProjection() is None:  # 没有投影则需要进行这种转换
                box = [(x1, -y1), (x2, -y2), (x3, -y3), (x4, -y4)]
            else:    # 图像坐标转地理坐标
                x1, y1 = imagexy2geo(dataset, y1, x1)
                x2, y2 = imagexy2geo(dataset, y2, x2)
                x3, y3 = imagexy2geo(dataset, y3, x3)
                x4, y4 = imagexy2geo(dataset, y4, x4)
                box = [(x1, y1), (x2, y2), (x3, y3), (x4, y4)]
            label = curLine[8]
            bbox_data.append(box)
            label_data.append(label)
    return bbox_data, label_data

get_box_from_array函数是从检测结果的坐标数组中读取检测框和对应标签,代码如下:

def get_box_from_array(result_array, classnames, img_file):
    """
    从输出的list中读取目标检测的边界框坐标点和标签信息
    :param result_array: 检测结果的list文件,格式为[ class_num, 9, obj_num], 9代表四个坐标点和置信度
    :param classnames: 类别列表
    :param img_file: 原始影像数据,为了获取投影信息
    :return box_data: 由图像坐标点组成的一系列边界框
    :return label_data : 边界框对应的标签信息
    """

    dataset = gdal.Open(img_file)
    bbox_data = []
    label_data = []
    for idx, class_result in enumerate(result_array):
        for result in class_result:
            x1 = float(result[0])
            y1 = float(result[1])
            x2 = float(result[2])
            y2 = float(result[3])
            x3 = float(result[4])
            y3 = float(result[5])
            x4 = float(result[6])
            y4 = float(result[7])
            if dataset.GetProjection() is None:
                box = [(x1, -y1), (x2, -y2), (x3, -y3), (x4, -y4)]
            else:
                x1, y1 = imagexy2geo(dataset, y1, x1)
                x2, y2 = imagexy2geo(dataset, y2, x2)
                x3, y3 = imagexy2geo(dataset, y3, x3)
                x4, y4 = imagexy2geo(dataset, y4, x4)
                box = [(x1, y1), (x2, y2), (x3, y3), (x4, y4)]
            label = classnames[idx]
            bbox_data.append(box)
            label_data.append(label)
    return bbox_data, label_data

imagexy2geo 图像坐标转地理坐标的代码如下:

import gdal 

def imagexy2geo(dataset, row, col):
    '''
    根据GDAL的六参数模型将影像图上坐标(行列号)转为投影坐标或地理坐标(根据具体数据的坐标系统转换)
    :param dataset: GDAL地理数据,gdal.Open("xxx.tif")
    :param row: 像素的行号
    :param col: 像素的列号
    :return: 行列号(row, col)对应的投影坐标或地理坐标(x, y)
    '''

    trans = dataset.GetGeoTransform()
    px = trans[0] + col * trans[1] + row * trans[2]
    py = trans[3] + col * trans[4] + row * trans[5]
    return px, py

注:记得在文件中import相关包

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

### 关于旋转检测中矢量信息 #### 使用场景 在遥感影像处理领域,旋转检测被广泛应用。对于航空和卫星图像中的目标识别而言,传统矩形边无法精确描述倾斜放置的目标对象,而采用带有角度参数的旋转矩形可以更好地拟合这些目标的真实形状[^3]。 #### 矢量信息的重要性 为了提高模型对不同姿态下的物体定位精度,在R3Det算法架内引入了特征金字塔网络(FPN),并通过一系列改进措施增强了小尺寸物体的表现力。特别是在定义锚点时考虑到了尺度变化的影响,并且允许更加灵活地调整候选区域的方向属性[^1]。 #### 实现方法 具体到实现层面,假设存在`n`个查询向量作为输入,则每个查询对应着一组预测结果: - `p_i`: 表示第i个查询所对应的类别得分; - `b_i`: 是指由该查询产生的坐标偏移量集合,用于修正初始设定好的默认边界位置; - 若某次推理过程中确实找到了相匹配的实际标注数据,则会进一步计算其与真值之间的差异程度以便后续优化权重更新过程。 ```python import torch.nn as nn class RotationBoxHead(nn.Module): def __init__(self, num_classes=20, in_channels=256): super(RotationBoxHead, self).__init__() # 定义回归分支 self.reg_conv = nn.Conv2d(in_channels=in_channels, out_channels=num_classes * 5, # 每一类都有[x,y,w,h,theta] kernel_size=(1, 1)) def forward(self, features): pred_bboxes = self.reg_conv(features) return pred_bboxes.view(pred_bboxes.size(0), -1, 5) # [batch_size, n_anchors*num_classes, 5] ``` 上述代码片段展示了如何构建一个简单的头部结构来估计旋转的位置参数。这里采用了卷积操作直接从高层语义空间映射至具体的几何变换系数上,最终输出形式为`(x_center, y_center, width, height, angle)`五元组表示法。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小李AI飞刀^_^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值