1
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
"""标注预览图生成: 动物红色实线框 + 生境 cover 黄色虚线框
|
||||
|
||||
用法:
|
||||
venv/bin/python visualize_labels.py --input datasets/images --labels datasets/labels --output datasets/pheasant_label
|
||||
"""
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
CLASSES = ["pheasant", "cover"]
|
||||
LABELS = {"pheasant": "野鸡", "cover": "疑似区域"}
|
||||
|
||||
|
||||
def draw_dashed(draw, box, outline, width, dash=12, gap=8):
|
||||
x1, y1, x2, y2 = box
|
||||
for (ax, ay, bx, by) in [(x1, y1, x2, y1), (x2, y1, x2, y2),
|
||||
(x2, y2, x1, y2), (x1, y2, x1, y1)]:
|
||||
length = max(abs(bx - ax), abs(by - ay))
|
||||
steps = max(int(length / (dash + gap)), 1)
|
||||
for i in range(steps):
|
||||
s = i / steps
|
||||
e = min((i * (dash + gap) + dash) / length, 1.0)
|
||||
if e <= s:
|
||||
continue
|
||||
draw.line([ax + (bx - ax) * s, ay + (by - ay) * s,
|
||||
ax + (bx - ax) * e, ay + (by - ay) * e],
|
||||
fill=outline, width=width)
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="标注预览图生成")
|
||||
ap.add_argument("--input", default="datasets/images")
|
||||
ap.add_argument("--labels", default="datasets/labels")
|
||||
ap.add_argument("--output", default="datasets/pheasant_label")
|
||||
args = ap.parse_args()
|
||||
|
||||
img_dir = Path(args.input)
|
||||
lab_dir = Path(args.labels)
|
||||
out_dir = Path(args.output)
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
count = 0
|
||||
for img_path in sorted(img_dir.rglob("*")):
|
||||
if img_path.suffix.lower() not in (".jpg", ".jpeg", ".png", ".webp", ".bmp"):
|
||||
continue
|
||||
rel = img_path.relative_to(img_dir)
|
||||
lab_path = lab_dir / rel.with_suffix(".txt")
|
||||
if not lab_path.exists():
|
||||
continue
|
||||
im = Image.open(img_path).convert("RGB")
|
||||
W, H = im.size
|
||||
d = ImageDraw.Draw(im)
|
||||
for line in lab_path.read_text().splitlines():
|
||||
parts = line.split()
|
||||
if not parts:
|
||||
continue
|
||||
cid, cx, cy, w, h = map(float, parts)
|
||||
box = ((cx - w / 2) * W, (cy - h / 2) * H,
|
||||
(cx + w / 2) * W, (cy + h / 2) * H)
|
||||
if int(cid) == 1: # cover 生境: 黄色虚线
|
||||
draw_dashed(d, box, (255, 200, 0), width=5)
|
||||
d.text((box[0] + 6, max(box[1] - 28, 4)), "疑似区域",
|
||||
fill=(255, 200, 0))
|
||||
else: # 动物: 红色实线
|
||||
d.rectangle(box, outline=(255, 0, 0), width=6)
|
||||
label = LABELS.get(CLASSES[int(cid)], CLASSES[int(cid)])
|
||||
d.text((box[0] + 6, max(box[1] - 28, 4)), label,
|
||||
fill=(255, 0, 0))
|
||||
out = out_dir / (img_path.stem + ".jpg")
|
||||
im.save(out, quality=92)
|
||||
count += 1
|
||||
print(out.name)
|
||||
print(f"共生成 {count} 张")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user