最新推送
This commit is contained in:
292
yolo11_detect/annotations.xml
Normal file
292
yolo11_detect/annotations.xml
Normal file
@ -0,0 +1,292 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<annotations>
|
||||
<version>1.1</version>
|
||||
<meta>
|
||||
<task>
|
||||
<id>282</id>
|
||||
<name>detect12.31</name>
|
||||
<size>64</size>
|
||||
<mode>annotation</mode>
|
||||
<overlap>0</overlap>
|
||||
<bugtracker></bugtracker>
|
||||
<created>2025-12-31 01:23:25.627596+00:00</created>
|
||||
<updated>2025-12-31 01:50:37.361043+00:00</updated>
|
||||
<subset>default</subset>
|
||||
<start_frame>0</start_frame>
|
||||
<stop_frame>63</stop_frame>
|
||||
<frame_filter></frame_filter>
|
||||
<segments>
|
||||
<segment>
|
||||
<id>195</id>
|
||||
<start>0</start>
|
||||
<stop>63</stop>
|
||||
<url>http://www.xj-robot.com:9000/api/jobs/195</url>
|
||||
</segment>
|
||||
</segments>
|
||||
<owner>
|
||||
<username>huangxin</username>
|
||||
<email>2193534909@qq.com</email>
|
||||
</owner>
|
||||
<assignee></assignee>
|
||||
<labels>
|
||||
<label>
|
||||
<name>clamp1</name>
|
||||
<color>#edb093</color>
|
||||
<type>any</type>
|
||||
<attributes>
|
||||
</attributes>
|
||||
</label>
|
||||
<label>
|
||||
<name>clamp0</name>
|
||||
<color>#b7aa2c</color>
|
||||
<type>any</type>
|
||||
<attributes>
|
||||
</attributes>
|
||||
</label>
|
||||
<label>
|
||||
<name>bag</name>
|
||||
<color>#ff0033</color>
|
||||
<type>any</type>
|
||||
<attributes>
|
||||
</attributes>
|
||||
</label>
|
||||
<label>
|
||||
<name>bag35</name>
|
||||
<color>#00ff00</color>
|
||||
<type>any</type>
|
||||
<attributes>
|
||||
</attributes>
|
||||
</label>
|
||||
</labels>
|
||||
</task>
|
||||
<dumped>2025-12-31 01:50:58.885062+00:00</dumped>
|
||||
</meta>
|
||||
<image id="0" name="20251113103451.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.00" ytl="451.30" xbr="54.10" ybr="748.27" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="1" name="20251114144244.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1241.10" ytl="375.60" xbr="1627.70" ybr="798.70" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="2" name="20251118172322.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.44" ytl="453.60" xbr="110.36" ybr="764.20" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="3" name="20251120150918.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.93" ytl="449.50" xbr="138.81" ybr="759.26" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="4" name="20251125134834.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1465.20" ytl="407.40" xbr="1791.10" ybr="729.50" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="5" name="20251126094509.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.00" ytl="445.68" xbr="66.30" ybr="742.65" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="6" name="20251204152220.jpg" width="1920" height="1080">
|
||||
<box label="bag35" source="manual" occluded="0" xtl="507.10" ytl="419.30" xbr="1038.71" ybr="809.16" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="7" name="20251204152803.jpg" width="1920" height="1080">
|
||||
<box label="bag35" source="manual" occluded="0" xtl="494.46" ytl="424.40" xbr="1013.09" ybr="807.64" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="8" name="20251205152201.jpg" width="1920" height="1080">
|
||||
<box label="bag35" source="manual" occluded="0" xtl="475.76" ytl="398.23" xbr="1021.55" ybr="803.70" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="9" name="20251205155845.jpg" width="1920" height="1080">
|
||||
<box label="bag35" source="manual" occluded="0" xtl="500.30" ytl="408.06" xbr="1029.10" ybr="804.43" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="10" name="20251205160635.jpg" width="1920" height="1080">
|
||||
<box label="bag35" source="manual" occluded="0" xtl="491.49" ytl="402.80" xbr="1028.60" ybr="825.40" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="11" name="20251205171012.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1338.20" ytl="381.20" xbr="1579.10" ybr="826.70" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="13" name="20251206144825.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1397.10" ytl="383.10" xbr="1622.10" ybr="835.10" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="14" name="20251206152857.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1589.40" ytl="357.00" xbr="1910.60" ybr="720.20" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="15" name="20251206155437.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1541.90" ytl="450.40" xbr="1920.00" ybr="753.85" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="16" name="20251206155749.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="767.73" ytl="383.15" xbr="1355.62" ybr="803.24" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="17" name="20251206160106.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1370.00" ytl="407.40" xbr="1601.50" ybr="845.40" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="18" name="20251206160652.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="2.96" ytl="418.93" xbr="245.27" ybr="794.64" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="19" name="20251206165236.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1394.30" ytl="390.60" xbr="1611.80" ybr="843.50" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="21" name="20251207112047.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1332.60" ytl="409.30" xbr="1575.40" ybr="839.80" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="22" name="20251207112635.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1439.10" ytl="393.39" xbr="1637.00" ybr="810.80" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="23" name="20251207113241.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="2.83" ytl="451.29" xbr="87.80" ybr="748.25" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="24" name="20251207113739.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="843.30" ytl="349.50" xbr="1384.90" ybr="761.30" z_order="0">
|
||||
</box>
|
||||
<box label="bag" source="manual" occluded="0" xtl="1308.30" ytl="445.70" xbr="1651.90" ybr="822.00" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="25" name="20251207125532.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1378.40" ytl="421.40" xbr="1603.40" ybr="837.90" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="26" name="20251207131551.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.20" ytl="453.10" xbr="57.13" ybr="756.00" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="27" name="20251207133134.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1395.20" ytl="411.10" xbr="1608.10" ybr="830.40" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="29" name="20251208095901.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.23" ytl="438.40" xbr="106.46" ybr="786.55" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="30" name="20251208111050.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="3.77" ytl="455.02" xbr="113.90" ybr="751.99" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="31" name="20251208111456.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1233.60" ytl="395.30" xbr="1633.30" ybr="809.90" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="32" name="20251208111840.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1375.60" ytl="406.50" xbr="1601.50" ybr="833.20" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="33" name="20251208112750.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="4.70" ytl="455.02" xbr="74.70" ybr="751.99" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="34" name="20251208140111.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1332.60" ytl="398.06" xbr="1574.40" ybr="825.80" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="35" name="20251208141110.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1386.80" ytl="416.73" xbr="1618.30" ybr="828.60" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="36" name="20251208141959.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1405.50" ytl="407.40" xbr="1627.70" ybr="829.50" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="38" name="20251208143931.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1411.13" ytl="417.70" xbr="1632.30" ybr="829.49" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="39" name="20251208155510.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="808.70" ytl="384.96" xbr="1367.10" ybr="776.26" z_order="0">
|
||||
</box>
|
||||
<box label="bag" source="manual" occluded="0" xtl="1323.29" ytl="431.20" xbr="1629.50" ybr="822.50" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="40" name="20251208160835.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1363.03" ytl="409.75" xbr="1604.70" ybr="841.20" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="42" name="20251209160625.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1338.75" ytl="401.34" xbr="1577.70" ybr="841.20" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="43" name="20251212094345.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.90" ytl="423.97" xbr="69.54" ybr="788.06" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="44" name="20251212102833.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.00" ytl="456.10" xbr="92.00" ybr="750.55" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="46" name="20251212111954.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1377.16" ytl="406.77" xbr="1603.90" ybr="846.50" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="48" name="20251212112958.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.00" ytl="457.10" xbr="69.60" ybr="739.40" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="49" name="20251212125451.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.27" ytl="454.30" xbr="111.50" ybr="749.60" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="50" name="20251212141425.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.00" ytl="454.30" xbr="58.40" ybr="741.24" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="51" name="20251212152645.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1393.93" ytl="405.83" xbr="1615.10" ybr="842.80" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="52" name="20251212155613.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.00" ytl="456.10" xbr="120.80" ybr="768.26" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="53" name="20251212160246.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.00" ytl="453.30" xbr="81.70" ybr="756.14" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="54" name="20251212160553.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.00" ytl="452.40" xbr="92.00" ybr="761.73" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="55" name="20251212161201.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="868.73" ytl="399.54" xbr="1421.51" ybr="821.97" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="56" name="20251212163016.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.39" ytl="450.79" xbr="109.99" ybr="774.78" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="57" name="20251212163740.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1.18" ytl="443.90" xbr="387.87" ybr="821.80" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="58" name="20251212164158.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1378.09" ytl="398.38" xbr="1599.26" ybr="810.17" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="60" name="20251217100715.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1382.75" ytl="404.90" xbr="1609.50" ybr="816.70" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="61" name="20251217112739.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="0.27" ytl="451.50" xbr="106.90" ybr="750.55" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="62" name="20251217132610.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1396.72" ytl="402.11" xbr="1614.20" ybr="828.80" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
<image id="63" name="20251217135234.jpg" width="1920" height="1080">
|
||||
<box label="bag" source="manual" occluded="0" xtl="1403.24" ytl="393.72" xbr="1624.41" ybr="829.70" z_order="0">
|
||||
</box>
|
||||
</image>
|
||||
</annotations>
|
||||
100
yolo11_detect/cvattodetect.py
Normal file
100
yolo11_detect/cvattodetect.py
Normal file
@ -0,0 +1,100 @@
|
||||
import os
|
||||
import xml.etree.ElementTree as ET
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def cvat_to_yolo_detect(xml_path, output_dir, class_name_to_id=None):
|
||||
"""
|
||||
将 CVAT 导出的 XML(目标检测模式)转换为 YOLO Detect 格式
|
||||
|
||||
Args:
|
||||
xml_path (str): CVAT 导出的 XML 文件路径
|
||||
output_dir (str): 输出 .txt 标注文件的目录
|
||||
class_name_to_id (dict, optional): 类别名到 ID 的映射。
|
||||
如果为 None,则自动从 XML 的 <labels> 中按顺序分配(0,1,2...)
|
||||
"""
|
||||
output_dir = Path(output_dir)
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
tree = ET.parse(xml_path)
|
||||
root = tree.getroot()
|
||||
|
||||
# 自动提取类别顺序(如果未提供映射)
|
||||
if class_name_to_id is None:
|
||||
class_name_to_id = {}
|
||||
labels_elem = root.find(".//labels")
|
||||
if labels_elem is not None:
|
||||
for idx, label in enumerate(labels_elem.findall("label")):
|
||||
name = label.find("name").text
|
||||
class_name_to_id[name] = idx
|
||||
else:
|
||||
print("⚠️ 未找到 <labels>,请手动提供 class_name_to_id")
|
||||
|
||||
print(f"类别映射: {class_name_to_id}")
|
||||
|
||||
# 遍历所有 <image>
|
||||
for image in root.findall("image"):
|
||||
img_name = image.get("name")
|
||||
width = int(image.get("width"))
|
||||
height = int(image.get("height"))
|
||||
|
||||
# 构建 .txt 文件名(去掉扩展名)
|
||||
stem = Path(img_name).stem
|
||||
txt_path = output_dir / f"{stem}.txt"
|
||||
|
||||
boxes = []
|
||||
for box in image.findall("box"):
|
||||
label = box.get("label")
|
||||
if label not in class_name_to_id:
|
||||
print(f"⚠️ 未知类别 '{label}',跳过(图片: {img_name})")
|
||||
continue
|
||||
|
||||
class_id = class_name_to_id[label]
|
||||
xtl = float(box.get("xtl"))
|
||||
ytl = float(box.get("ytl"))
|
||||
xbr = float(box.get("xbr"))
|
||||
ybr = float(box.get("ybr"))
|
||||
|
||||
# 转为 YOLO 格式(归一化)
|
||||
x_center = (xtl + xbr) / 2 / width
|
||||
y_center = (ytl + ybr) / 2 / height
|
||||
w = (xbr - xtl) / width
|
||||
h = (ybr - ytl) / height
|
||||
|
||||
# 限制在 [0,1](防止因标注误差越界)
|
||||
x_center = max(0.0, min(1.0, x_center))
|
||||
y_center = max(0.0, min(1.0, y_center))
|
||||
w = max(0.0, min(1.0, w))
|
||||
h = max(0.0, min(1.0, h))
|
||||
|
||||
boxes.append(f"{class_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}")
|
||||
|
||||
# 写入 .txt 文件(即使无框也创建空文件)
|
||||
with open(txt_path, "w") as f:
|
||||
f.write("\n".join(boxes))
|
||||
|
||||
print(f"✅ {img_name} → {len(boxes)} 个目标")
|
||||
|
||||
print(f"\n🎉 转换完成!YOLO 标注已保存至: {output_dir}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# ====== 配置区 ======
|
||||
XML_PATH = "annotations.xml" # 替换为你的 CVAT XML 路径
|
||||
OUTPUT_LABELS_DIR = "labels" # 输出的 YOLO .txt 目录
|
||||
|
||||
# 方式1:自动从 XML 提取类别(推荐)
|
||||
#CLASS_MAP = None
|
||||
|
||||
# 方式2:手动指定(确保与训练时一致)
|
||||
CLASS_MAP = {
|
||||
"bag": 0,
|
||||
"bag35": 1,
|
||||
}
|
||||
|
||||
# ====== 执行转换 ======
|
||||
cvat_to_yolo_detect(
|
||||
xml_path=XML_PATH,
|
||||
output_dir=OUTPUT_LABELS_DIR,
|
||||
class_name_to_id=CLASS_MAP
|
||||
)
|
||||
141
yolo11_detect/trans_detecttocvat.py
Normal file
141
yolo11_detect/trans_detecttocvat.py
Normal file
@ -0,0 +1,141 @@
|
||||
import os
|
||||
import xml.etree.ElementTree as ET
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def yolo_detect_to_cvat(
|
||||
images_dir,
|
||||
labels_dir,
|
||||
output_xml,
|
||||
class_id_to_name,
|
||||
):
|
||||
"""
|
||||
将 YOLO Detect 格式转换为 CVAT XML(目标检测 box)
|
||||
|
||||
Args:
|
||||
images_dir (str): 图片目录
|
||||
labels_dir (str): YOLO txt 标注目录
|
||||
output_xml (str): 输出 CVAT XML 路径
|
||||
class_id_to_name (dict): {0: "xxx", 1: "yyy"}
|
||||
"""
|
||||
|
||||
images_dir = Path(images_dir)
|
||||
labels_dir = Path(labels_dir)
|
||||
|
||||
# ----------------------------
|
||||
# 创建 XML 结构
|
||||
# ----------------------------
|
||||
annotations = ET.Element("annotations")
|
||||
|
||||
version = ET.SubElement(annotations, "version")
|
||||
version.text = "1.1"
|
||||
|
||||
# labels
|
||||
meta = ET.SubElement(annotations, "meta")
|
||||
task = ET.SubElement(meta, "task")
|
||||
labels_elem = ET.SubElement(task, "labels")
|
||||
|
||||
for class_id, name in class_id_to_name.items():
|
||||
label = ET.SubElement(labels_elem, "label")
|
||||
name_elem = ET.SubElement(label, "name")
|
||||
name_elem.text = name
|
||||
|
||||
image_id = 0
|
||||
|
||||
# ----------------------------
|
||||
# 遍历图片
|
||||
# ----------------------------
|
||||
for img_path in sorted(images_dir.iterdir()):
|
||||
if img_path.suffix.lower() not in [".jpg", ".png", ".jpeg"]:
|
||||
continue
|
||||
|
||||
import cv2
|
||||
img = cv2.imread(str(img_path))
|
||||
if img is None:
|
||||
print(f"⚠️ 无法读取图片: {img_path}")
|
||||
continue
|
||||
|
||||
height, width = img.shape[:2]
|
||||
|
||||
image_elem = ET.SubElement(
|
||||
annotations,
|
||||
"image",
|
||||
{
|
||||
"id": str(image_id),
|
||||
"name": img_path.name,
|
||||
"width": str(width),
|
||||
"height": str(height),
|
||||
}
|
||||
)
|
||||
|
||||
label_txt = labels_dir / f"{img_path.stem}.txt"
|
||||
|
||||
# ----------------------------
|
||||
# 有 / 无标签都要建 image
|
||||
# ----------------------------
|
||||
if label_txt.exists():
|
||||
with open(label_txt, "r") as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
class_id, xc, yc, w, h = map(float, line.split())
|
||||
class_id = int(class_id)
|
||||
|
||||
label_name = class_id_to_name.get(class_id)
|
||||
if label_name is None:
|
||||
print(f"⚠️ 未知 class_id: {class_id}")
|
||||
continue
|
||||
|
||||
# YOLO → CVAT 坐标
|
||||
box_w = w * width
|
||||
box_h = h * height
|
||||
xtl = xc * width - box_w / 2
|
||||
ytl = yc * height - box_h / 2
|
||||
xbr = xtl + box_w
|
||||
ybr = ytl + box_h
|
||||
|
||||
ET.SubElement(
|
||||
image_elem,
|
||||
"box",
|
||||
{
|
||||
"label": label_name,
|
||||
"xtl": f"{xtl:.2f}",
|
||||
"ytl": f"{ytl:.2f}",
|
||||
"xbr": f"{xbr:.2f}",
|
||||
"ybr": f"{ybr:.2f}",
|
||||
"occluded": "0",
|
||||
"source": "manual",
|
||||
}
|
||||
)
|
||||
|
||||
image_id += 1
|
||||
print(f"✅ {img_path.name}")
|
||||
|
||||
# ----------------------------
|
||||
# 写 XML
|
||||
# ----------------------------
|
||||
tree = ET.ElementTree(annotations)
|
||||
tree.write(output_xml, encoding="utf-8", xml_declaration=True)
|
||||
|
||||
print(f"\n🎉 转换完成,CVAT XML 已生成:{output_xml}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
IMAGES_DIR = "/media/hx/04e879fa-d697-4b02-ac7e-a4148876ebb0/dataset/detect/1"
|
||||
LABELS_DIR = "/media/hx/04e879fa-d697-4b02-ac7e-a4148876ebb0/dataset/detect/1"
|
||||
OUTPUT_XML = "annotations.xml"
|
||||
|
||||
# ⚠️ 一定要和 YOLO 训练时一致
|
||||
CLASS_ID_TO_NAME = {
|
||||
#0: "hole",
|
||||
#1: "crack"
|
||||
0: "bag"
|
||||
}
|
||||
|
||||
yolo_detect_to_cvat(
|
||||
images_dir=IMAGES_DIR,
|
||||
labels_dir=LABELS_DIR,
|
||||
output_xml=OUTPUT_XML,
|
||||
class_id_to_name=CLASS_ID_TO_NAME
|
||||
)
|
||||
Reference in New Issue
Block a user