【Xml Tool】 裁剪某个区域重新生成xml

该代码功能:

对已经标注好的xml文件进行操作

比如,label A 区域中,有多个label B。

现在我希望我能截取label A区域的图片,并根据原始xml生成lable B 的标注文件

注:label B部分区域在label A 外面的话,则扩大label A裁剪区域,使其包括 label B

xml里面 x为w轴

python 复制代码
'''
该代码功能:
对已经标注好的xml文件进行操作
比如,label A 区域中,有多个label B。
现在我希望我能截取label A区域的图片,并根据原始xml生成lable B 的标注文件

注:label B部分区域在label A 外面的话,则扩大label A裁剪区域,使其包括 label B


xml里面 x为w轴
'''
import os
import cv2
import xml.etree.ElementTree as ET
import traceback
import copy

images_path="/media/hxzh/SB@home/hxzh/MH_dataset/Towers/dataset_insulator_clip/images"
xmls_path="/media/hxzh/SB@home/hxzh/MH_dataset/Towers/dataset_insulator_clip/xmls"
save_image_path="/media/hxzh/SB@home/hxzh/MH_dataset/Towers/dataset_insulator_clip/save_images"
save_xmls_path="/media/hxzh/SB@home/hxzh/MH_dataset/Towers/dataset_insulator_clip/save_xmls"

#所要裁剪区域的标签名字
crop_name="100_0_0"

#要生成的标签名
label_name="100_1_0"


def read_xml(filename):
    (fname, suffix) = os.path.splitext(filename)
    if not os.path.exists(f"{images_path}/{fname}.JPG"):
        return 0
    image_ori=cv2.imread(f"{images_path}/{fname}.JPG")

    is_ok=True
    try :
        tree = ET.parse(f"{xmls_path}/{filename}")
        tree_ori=copy.deepcopy(tree)
    except (BaseException,Exception ) as e:
        print(filename,traceback.format_exc())

        return []


    # 获取宽w和高h
    a = tree.find('size')
    w, h = [int(a.find('width').text),
            int(a.find('height').text)]

    objects = []

    if w == 0:
        return []


    crop_area=[]
    label_area=[]

    for obj in tree.findall('object'):
        # 获取name
        name = obj.find('name').text
        if name==crop_name:
            # 读取检测框的左上、右下角点的坐标
            bbox = obj.find('bndbox')
            x1, y1, x2, y2 = [int(bbox.find('xmin').text),
                              int(bbox.find('ymin').text),
                              int(bbox.find('xmax').text),
                              int(bbox.find('ymax').text)]
            #首次确定裁剪区域
            crop_area.append([x1, y1, x2, y2])
        elif name==label_name:
            # 读取检测框的左上、右下角点的坐标
            bbox = obj.find('bndbox')
            x1, y1, x2, y2 = [int(bbox.find('xmin').text),
                              int(bbox.find('ymin').text),
                              int(bbox.find('xmax').text),
                              int(bbox.find('ymax').text)]
            #首次确定裁剪区域
            label_area.append([x1, y1, x2, y2])


    matchs=[]


    for i in crop_area:
        match={}
        match["area"]=i
        match["labels"]=[]
        for j in label_area:
            if  j[0]>=i[0] and j[0]<=i[2]:
                if j[1]>=i[1] and j[1]<=i[3] or j[3]>=i[1] and j[3]<=i[3]:
                    match["labels"].append(j)
            elif j[2]>=i[0] and j[2]<=i[2]:
                if j[1] >= i[1] and j[1] <= i[3] or j[3] >= i[1] and j[3] <= i[3]:
                    match["labels"].append(j)
        if len(match["labels"])!=0:

            min_x=min([k[0] for k in match["labels"]])
            max_x=max([k[2] for k in match["labels"]])
            min_y = min([k[1] for k in match["labels"]])
            max_y = max([k[3] for k in match["labels"]])
            print(min_x,min_y,max_x,max_y)
            print(match["area"][0])

            match["area"][0]=min(match["area"][0] ,min_x)
            match["area"][1]=min(match["area"][1] ,min_y)
            match["area"][2]=max(match["area"][2] ,max_x)
            match["area"][3]=max(match["area"][3] ,max_y)
        matchs.append(match.copy())
    #开始根据matchs 进行裁剪图片和生成xml


    len_matchs=len(matchs)
    image_count=0
    for match in matchs:
        image_count+=1
        #分割图片

        tree_=copy.deepcopy(tree_ori)
        image_crop=image_ori.copy()[match["area"][1]:match["area"][3],match["area"][0]:match["area"][2],:]
        cv2.imwrite(f"{save_image_path}/{fname}_{image_count}.JPG",image_crop)
        save_xml_name=f"{save_xmls_path}/{fname}_{image_count}.xml"


        ww,hh=image_crop.shape[:2]

        label_len=len(match["labels"])
        if label_len==0:
            continue
        a = tree_.find('size')
        a.find('width').text=f"{ww}"
        a.find('height').text=f"{hh}"



        if w == 0:
            return []



        for ind ,ob in enumerate( tree_.findall('object')):
            # 获取name
            if ind<label_len:
                ob.find('name').text=f"{label_name}"
                bbox = ob.find("bndbox")
                bbox.find("xmin").text = f"{match['labels'][ind][0]-match['area'][0]}"
                bbox.find("ymin").text = f"{match['labels'][ind][1]-match['area'][1]}"
                bbox.find("xmax").text = f"{match['labels'][ind][2]-match['area'][0]}"
                bbox.find("ymax").text = f"{match['labels'][ind][3]-match['area'][1]}"
            else:
                tree_.getroot().remove(ob)





        tree_.write(save_xml_name)
        xs = ""
        with open(save_xml_name, 'r', encoding='utf8') as r:
            xs = r.read()
            r.close()
        with open(save_xml_name, 'w', encoding='utf8') as w:
            w.write(xs.replace("<?xml version='1.0' encoding='utf8'?>", ""))
            w.close()











for i in os.listdir(xmls_path):
    read_xml(i)
相关推荐
Raink老师2 小时前
【AI面试临阵磨枪-70】Agent 系统如何做分布式调度、跨服务协作、故障恢复?
人工智能·面试·职场和发展
lishi_19912 小时前
一键部署MoviePilotV2实现NAS全自动追剧
python·媒体·moviepilot
tedcloud1232 小时前
RTK部署教程:构建稳定的AI Workflow环境
服务器·javascript·人工智能·typescript·ocr
Raink老师2 小时前
【AI面试临阵磨枪-71】如何用 AI 优化推荐系统、内容审核、广告创意、搜索体验?
人工智能·面试·职场和发展
AI医影跨模态组学2 小时前
Biomarker Res(IF=11.5)安徽医科大学第一医院:基于机器学习的放射组学模型:子宫内膜癌患者的预后预测及机制探索
人工智能·深度学习·论文·医学·医学影像·影像组学
ftpeak2 小时前
Mooncake:以 KVCache 为中心的分离式 LLM 服务架构
人工智能·ai·架构·ai编程·ai开发
lqqjuly2 小时前
Transformer架构详解 - 第一、二部分:基础与核心思想、核心组件详解
深度学习·神经网络·自然语言处理
Terrence Shen2 小时前
Hermes agent的tools是怎么落地应用的系列
人工智能·llm·agent·hermes
Raink老师2 小时前
【AI面试临阵磨枪-72】电商全场景 AI Agent 设计(商品咨询 / 订单 / 物流 / 售后 / 退款)
人工智能·面试·职场和发展
仙女修炼史2 小时前
CNN更看重Texture还是shape:imagenet-trained cnns are biased
论文阅读·人工智能·cnn