txt和xml互相转换

该代码实现了YOLO(YouOnlyLookOnce)标注从XML到YOLO格式的转换,以及两个检测结果的融合。它使用了归一化的坐标,并提供了基于概率的融合方法,用于合并来自不同源的检测信息。此外,还包括了一个测试函数来展示如何应用这些功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

# gt_parse_yolo.py
import cv2
from gt_prob_class import *
import os


class FileName(object):
    def __init__(self, file_path):
        self.file_path = file_path
        self.full_name = os.path.split(file_path)[1]
        self.file_name = self.full_name.split('.')[0]


class DetectResult(object):
    def __init__(self, txt_path, img_path):
        self.datas = np.loadtxt(txt_path)
        self.len_datas = len(self.datas.shape)

        self.label = self.datas[:, 0]
        self.yolo_box = self.datas[:, [1, 2, 3, 4]]
        self.score = self.datas[:, -1]

        self.image = cv2.imread(img_path)
        self.h = self.image.shape[0]
        self.w = self.image.shape[1]
        self.b_box = self.yolo2xml()
        self.info = self.dict4prob()

    def yolo2xml(self):
        # yolo标注内容分别指类别、归一化后的中心点x坐标,归一化后的中心点y坐标,归一化后的目标框宽度w,归一化后的目标况高度h
        x0 = self.datas[:, 1] * self.w
        y0 = self.datas[:, 2] * self.h
        w0 = self.datas[:, 3] * self.w
        h0 = self.datas[:, 4] * self.h

        x1 = x0 - w0 / 2.0
        y1 = y0 - h0 / 2.0
        x2 = x0 + w0 / 2.0
        y2 = y0 + h0 / 2.0

        b_box = np.array([x1, y1, x2, y2]).T

        return b_box

    def dict4prob(self):
        info_1 = dict()
        info_1['bbox'] = self.b_box
        info_1['score'] = self.score
        info_1['class'] = self.label
        info_1['prob'] = self.score
        return info_1


def xml2yolo(size, label, box, score):
    print(box)  # x1, y1, x2, y2
    dw = 1. / size[1]
    dh = 1. / size[0]
    x = (box[:, 0] + box[:, 2]) / 2.0
    y = (box[:, 1] + box[:, 3]) / 2.0
    w = box[:, 2] - box[:, 0]
    h = box[:, 3] - box[:, 1]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    new_box = np.column_stack((label, x, y, w, h, score))
    return new_box


def test_main(txt_path0, txt_path1, img_path0, save_name):
    # 文件路径信息
    # txt_path0 = r'D:\Graduate\dissertation\data_Kaist\gt_kaist\set00_V000_I01225.txt'
    # txt_path1 = r'D:\Graduate\dissertation\data_Kaist\gt_kaist\set00_V000_I01225.txt'
    # img_path0 = r'D:\Graduate\dissertation\data_Kaist\gt_kaist\set00_V000_I01225.jpg'
    img = cv2.imread(img_path0)

    # 得到字典
    detect_result1 = DetectResult(txt_path0, img_path0)
    detect_result2 = DetectResult(txt_path1, img_path0)

    # probEn计算
    keep, out_scores, out_boxes, out_class = test_vit(detect_result1.info, detect_result2.info)
    out_scores, out_boxes, out_class = np.array(out_scores), np.array(out_boxes), np.array(out_class)

    # 结果写入txt中
    yolo_content = xml2yolo(img.shape, out_class, out_boxes, out_scores)
    print('结果:')
    print('keep: \n', keep)
    print('out_scores: \n', out_scores)
    print('out_boxes: \n', np.array(out_boxes))
    print('out_class: \n', out_class)
    print('yolo_content: \n', yolo_content)

    save_path = ''
    np.savetxt(save_path + save_name, yolo_content, fmt='%f', delimiter=' ')


def process_all():
    uv_txt_dir = ''
    rgb_txt_dir = ''
    img_dir = ''
    file_names = os.listdir(uv_txt_dir)
    for file_name in file_names:
        uv_path = uv_txt_dir + file_name
        fm = FileName(file_name)
        rgb_path = rgb_txt_dir + file_name
        img_path = img_dir + fm.file_name + '.jpg'
        test_main(uv_path, rgb_path, img_path, file_name)


# process_all()

# 文件路径信息
txt_path0 = r'D:\Graduate\dissertation\data_Kaist\gt_kaist\set00_V000_I01225.txt'
txt_path1 = r'D:\Graduate\dissertation\data_Kaist\gt_kaist\set00_V000_I01227.txt'
img_path0 = r'D:\Graduate\dissertation\data_Kaist\gt_kaist\set00_V000_I01225.jpg'
save_name = '1.txt'
test_main(txt_path0, txt_path1, img_path0, save_name)
# gt_prob_class.py
import numpy as np
import torch


def weighted_box_fusion(bbox, score):
    weight = score / np.sum(score)
    out_bbox = np.array(bbox) * weight[:, None]
    out_bbox = np.sum(out_bbox, axis=0)
    return out_bbox


def prepare_data(info1, info2, info3='', method=None):
    out_dict = {}
    for key in info1.keys():
        if key != 'img_name':
            data1 = np.array(info1[key])
            data2 = np.array(info2[key])
            data_all = np.concatenate((data1, data2), axis=0)

            if info3:
                data3 = np.array(info3[key])
                data_all = np.concatenate((data_all, data3), axis=0)
            out_dict[key] = data_all
    return out_dict


def bayesian_fusion_single_class(match_score_vec, pred_class):
    match_score_vec.resize((1, 2))
    match_score_vec = match_score_vec.T
    scores = np.zeros((match_score_vec.shape[0], 2))
    scores[:, :1] = match_score_vec
    scores[:, -1] = 1 - np.sum(match_score_vec, axis=1)
    log_scores = np.log(scores)
    sum_logits = np.sum(log_scores, axis=0)
    exp_logits = np.exp(sum_logits)
    score_norm = exp_logits / np.sum(exp_logits)
    out_score = np.max(score_norm)
    out_class = np.argmax(score_norm)
    return out_score, out_class


def nms_bayesian(dict_collect, thresh, method):
    score_method, box_method = method
    classes = dict_collect['class']
    dets = dict_collect['bbox']
    scores = dict_collect['score']
    probs = dict_collect['prob']

    x1 = dets[:, 0] + classes * 640
    y1 = dets[:, 1] + classes * 512
    x2 = dets[:, 2] + classes * 640
    y2 = dets[:, 3] + classes * 512

    areas = (x2 - x1 + 1) * (y2 - y1 + 1)
    order = scores.argsort()[::-1]

    keep = []
    out_classes = []
    match_scores = []
    match_bboxs = []
    while order.size > 0:
        i = order[0]
        keep.append(i)

        xx1 = np.maximum(x1[i], x1[order[1:]])
        yy1 = np.maximum(y1[i], y1[order[1:]])
        xx2 = np.minimum(x2[i], x2[order[1:]])
        yy2 = np.minimum(y2[i], y2[order[1:]])

        w = np.maximum(0.0, xx2 - xx1 + 1)
        h = np.maximum(0.0, yy2 - yy1 + 1)
        inter = w * h
        ovr = inter / (areas[i] + areas[order[1:]] - inter)

        inds = np.where(ovr <= thresh)[0]
        match = np.where(ovr > thresh)[0]
        match_ind = order[match + 1]

        match_prob = list(probs[match_ind])
        match_score = list(scores[match_ind])
        match_bbox = list(dets[match_ind][:, :4])
        original_prob = probs[i]
        original_score = scores[i].tolist()
        original_bbox = dets[i][:4]

        if len(match_score) > 0:
            match_score += [original_score]
            match_prob += [original_prob]
            match_bbox += [original_bbox]

            if score_method == "probEn":
                final_score, out_class = bayesian_fusion_single_class(np.asarray(match_prob), classes[i])
                out_classes.append(out_class)
            elif score_method == 'avg':
                final_score = np.mean(np.asarray(match_score))
                out_classes.append(classes[i])
            elif score_method == 'max':
                final_score = np.max(match_prob)
                out_classes.append(classes[i])

            if box_method == "v-avg":
                1
            elif box_method == 's-avg':
                final_bbox = weighted_box_fusion(match_bbox, match_score)
            elif box_method == 'avg':
                1
            elif box_method == 'argmax':
                max_score_id = np.argmax(match_score)
                final_bbox = match_bbox[max_score_id]

            match_scores.append(final_score)
            match_bboxs.append(final_bbox)
        else:
            match_scores.append(original_score)
            match_bboxs.append(original_bbox)
            out_classes.append(classes[i])

        order = order[inds + 1]

    assert len(keep) == len(match_scores)
    assert len(keep) == len(match_bboxs)
    assert len(keep) == len(out_classes)

    match_bboxs = match_bboxs
    match_scores = torch.Tensor(match_scores)
    match_classes = torch.Tensor(out_classes)

    return keep, match_scores, match_bboxs, match_classes


def test_vit(info_1, info_2):
    threshold = 0.5
    dict_collect = prepare_data(info_1, info_2)

    method = 'probEn', 's-avg'
    keep, out_scores, out_boxes, out_class = nms_bayesian(dict_collect, threshold, method=method)
    return keep, out_scores, out_boxes, out_class


def test_main():
    info_1 = {}
    # x1, y1, x2, y2(如果是yolo格式的话,需要乘以图像的宽高)
    info_1['bbox'] = [[295.4176330566406, 225.91998291015625, 332.5729675292969, 254.29959106445312],
                      [465.919921875, 226.74783325195312, 498.17022705078125, 251.9710235595703]]
    info_1['score'] = [0.9996856451034546, 0.9983585476875305]
    info_1['class'] = [0, 0]
    info_1['prob'] = info_1['score']

    info_2 = {}
    info_2['bbox'] = [[290.4176330566406, 220.91998291015625, 330.5729675292969, 250.29959106445312],
                      [463.919921875, 225.74783325195312, 494.17022705078125, 250.9710235595703]]
    info_2['score'] = [0.8996856451034546, 0.8883585476875305]
    info_2['class'] = [0, 0]
    info_2['prob'] = info_2['score']
    test_vit(info_1, info_2)


if __name__ == '__main__':
    test_main()


有许多其他自己的代码,做保存用。

互相转换体现在xml2yolo和yolo2xml中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值