XML标签文件转换为TXT标签文件
| import os |
| import xml.etree.ElementTree as ET |
| |
| |
| class_mapping = { |
| 'person': '0', |
| 'car': '1', |
| 'bike': '2' |
| } |
| |
| |
| source_folder = r'F:\data\xml' |
| target_folder = r'F:\data\txt' |
| |
| |
| os.makedirs(target_folder, exist_ok=True) |
| |
| |
| image_width = 0 |
| image_height = 0 |
| |
| |
| for xml_file in os.listdir(source_folder): |
| if xml_file.endswith('.xml'): |
| |
| xml_path = os.path.join(source_folder, xml_file) |
| |
| |
| tree = ET.parse(xml_path) |
| root = tree.getroot() |
| |
| |
| size = root.find('size') |
| if size is not None: |
| width = int(size.find('width').text) |
| height = int(size.find('height').text) |
| |
| image_width = max(image_width, width) |
| image_height = max(image_height, height) |
| |
| |
| txt_file_name = xml_file.replace('.xml', '.txt') |
| txt_file_path = os.path.join(target_folder, txt_file_name) |
| |
| |
| with open(txt_file_path, 'w') as txt_file: |
| |
| for obj in root.findall('object'): |
| |
| name = obj.find('name').text |
| category_id = class_mapping.get(name, None) |
| if category_id is None: |
| continue |
| |
| |
| bndbox = obj.find('bndbox') |
| xmin = float(bndbox.find('xmin').text) |
| ymin = float(bndbox.find('ymin').text) |
| xmax = float(bndbox.find('xmax').text) |
| ymax = float(bndbox.find('ymax').text) |
| |
| |
| x_center = (xmin + xmax) / 2 |
| y_center = (ymin + ymax) / 2 |
| width = xmax - xmin |
| height = ymax - ymin |
| |
| |
| normalized_x_center = x_center / image_width |
| normalized_y_center = y_center / image_height |
| normalized_width = width / image_width |
| normalized_height = height / image_height |
| |
| |
| txt_file.write(f'{category_id} {normalized_x_center} {normalized_y_center} {normalized_width} {normalized_height}\n') |
| |
| |
| print('Conversion from XML to TXT completed.') |
TXT标签文件转换为XML标签文件
| import os |
| import xml.etree.ElementTree as ET |
| from PIL import Image |
| |
| |
| class_mapping = { |
| '0': 'person', |
| '1': 'car', |
| '2': 'bike' |
| } |
| |
| |
| source_folder = r'F:\data\txt' |
| target_folder = r'F:\data\xml' |
| image_folder = r'F:\data\images' |
| |
| |
| os.makedirs(target_folder, exist_ok=True) |
| |
| |
| for txt_file in os.listdir(source_folder): |
| if txt_file.endswith('.txt'): |
| |
| txt_path = os.path.join(source_folder, txt_file) |
| |
| |
| xml_file_name = txt_file.replace('.txt', '.xml') |
| xml_file_path = os.path.join(target_folder, xml_file_name) |
| |
| |
| image_file_name = txt_file.replace('.txt', '.png') |
| image_path = os.path.join(image_folder, image_file_name) |
| |
| |
| if not os.path.exists(image_path): |
| print(f"Image file not found: {image_path}") |
| continue |
| |
| |
| with Image.open(image_path) as img: |
| image_width, image_height = img.size |
| |
| |
| with open(txt_path, 'r') as txt_file: |
| tree = ET.ElementTree(ET.Element('annotation')) |
| root = tree.getroot() |
| |
| |
| folder = ET.SubElement(root, 'folder') |
| folder.text = os.path.basename(os.path.dirname(image_path)) |
| filename = ET.SubElement(root, 'filename') |
| filename.text = image_file_name |
| path = ET.SubElement(root, 'path') |
| path.text = os.path.abspath(image_path) |
| |
| |
| source = ET.SubElement(root, 'source') |
| database = ET.SubElement(source, 'database') |
| database.text = 'Unknown' |
| |
| |
| size = ET.SubElement(root, 'size') |
| width = ET.SubElement(size, 'width') |
| width.text = str(image_width) |
| height = ET.SubElement(size, 'height') |
| height.text = str(image_height) |
| depth = ET.SubElement(size, 'depth') |
| depth.text = '1' |
| |
| |
| segmented = ET.SubElement(root, 'segmented') |
| segmented.text = '0' |
| |
| |
| for line in txt_file: |
| values = line.strip().split() |
| category_id = values[0] |
| x_center = float(values[1]) * image_width |
| y_center = float(values[2]) * image_height |
| bbox_width = float(values[3]) * image_width |
| bbox_height = float(values[4]) * image_height |
| |
| |
| obj = ET.SubElement(root, 'object') |
| name = ET.SubElement(obj, 'name') |
| name.text = class_mapping[category_id] |
| pose = ET.SubElement(obj, 'pose') |
| pose.text = 'Unspecified' |
| truncated = ET.SubElement(obj, 'truncated') |
| truncated.text = '0' |
| difficult = ET.SubElement(obj, 'difficult') |
| difficult.text = '0' |
| |
| |
| bndbox = ET.SubElement(obj, 'bndbox') |
| xmin = ET.SubElement(bndbox, 'xmin') |
| xmin.text = str(int(x_center - bbox_width / 2)) |
| ymin = ET.SubElement(bndbox, 'ymin') |
| ymin.text = str(int(y_center - bbox_height / 2)) |
| xmax = ET.SubElement(bndbox, 'xmax') |
| xmax.text = str(int(x_center + bbox_width / 2)) |
| ymax = ET.SubElement(bndbox, 'ymax') |
| ymax.text = str(int(y_center + bbox_height / 2)) |
| |
| |
| tree.write(xml_file_path, encoding='utf-8', xml_declaration=True) |
| |
| |
| print('Conversion from TXT to XML completed.') |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤