Download infer.py from YMmim/object-detection-scratch: direct link, hf CLI and curl.
- Browser
- Download file 5.09 kB
-
https://huggingface.co/YMmim/object-detection-scratch/resolve/main/infer.py
- Command line
-
hf download hf://YMmim/object-detection-scratch/infer.py
-
curl -L -o infer.py https://huggingface.co/YMmim/object-detection-scratch/resolve/main/infer.py
5.09 kB
| """ | |
| Faster R-CNN ๋ฐ๋ฐ๋ฅ ๊ตฌํ โ ์ถ๋ก (inference) ์คํฌ๋ฆฝํธ | |
| ===================================================== | |
| ํ์ต๋ frcnn.pth ๋ก ์์์ ์ด๋ฏธ์ง์์ ๊ฐ์ฒด๋ฅผ ํ์งํ๊ณ , | |
| ๋ฐ์ค + ํด๋์ค๋ช + ์ ์๋ฅผ ๊ทธ๋ ค์ ์ ์ฅํ๋ค. | |
| ์คํ ์: | |
| # ์ด๋ฏธ์ง ํ ์ฅ | |
| python infer.py --ckpt frcnn.pth --image test.jpg | |
| # ํด๋ ์ ๋ชจ๋ ์ด๋ฏธ์ง | |
| python infer.py --ckpt frcnn.pth --image_dir ./samples --out_dir ./results | |
| # ์ ์ ์๊ณ๊ฐ ์กฐ์ (๊ธฐ๋ณธ 0.5) | |
| python infer.py --ckpt frcnn.pth --image test.jpg --score_thresh 0.7 | |
| ์ฃผ์: | |
| - train.py, model.py ๋ฑ๊ณผ ๊ฐ์ ํด๋์์ ์คํํ ๊ฒ. | |
| - ํ์ต๊ณผ ๋์ผํ ๋ฆฌ์ฌ์ด์ฆ/์ ๊ทํ๋ฅผ ์ ์ฉํด์ผ ๊ฒฐ๊ณผ๊ฐ ์ ์. | |
| """ | |
| import os | |
| import argparse | |
| import torch | |
| from PIL import Image, ImageDraw, ImageFont | |
| import torchvision.transforms.functional as F | |
| from model import FasterRCNN | |
| from dataset import NUM_CLASSES, VOC_CLASSES | |
| # ํด๋์ค๋ณ ์์(20๊ฐ) โ ์๊ฐ์ ์ผ๋ก ๊ตฌ๋ถ๋๋๋ก HSV ๋ถํ | |
| def _class_colors(): | |
| import colorsys | |
| colors = [] | |
| for i in range(len(VOC_CLASSES)): | |
| h = i / len(VOC_CLASSES) | |
| r, g, b = colorsys.hsv_to_rgb(h, 0.75, 0.95) | |
| colors.append((int(r * 255), int(g * 255), int(b * 255))) | |
| return colors | |
| CLASS_COLORS = _class_colors() | |
| def preprocess(pil_img, min_size=600, max_size=1000): | |
| """ํ์ต๊ณผ ๋์ผํ ๋ฆฌ์ฌ์ด์ฆ + ์ ๊ทํ. ์๋ณธ ๋ณต์์ฉ scale๋ ๋ฐํ.""" | |
| w, h = pil_img.size | |
| short, long = min(w, h), max(w, h) | |
| scale = min_size / short | |
| if long * scale > max_size: | |
| scale = max_size / long | |
| new_w, new_h = int(round(w * scale)), int(round(h * scale)) | |
| resized = pil_img.resize((new_w, new_h), Image.BILINEAR) | |
| t = F.to_tensor(resized) | |
| t = F.normalize(t, mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) | |
| return t, scale | |
| def draw_detections(pil_img, boxes, labels, scores, scale): | |
| """ํ์ง ๊ฒฐ๊ณผ๋ฅผ ์๋ณธ ์ด๋ฏธ์ง ์ขํ๋ก ๋๋๋ ค ๋ฐ์ค์ ๋ผ๋ฒจ์ ๊ทธ๋ฆฐ๋ค.""" | |
| draw = ImageDraw.Draw(pil_img) | |
| try: | |
| font = ImageFont.truetype("arial.ttf", 16) | |
| except Exception: | |
| font = ImageFont.load_default() | |
| for box, label, score in zip(boxes, labels, scores): | |
| # ๋ชจ๋ธ์ ๋ฆฌ์ฌ์ด์ฆ๋ ์ขํ๋ฅผ ์ถ๋ ฅ โ ์๋ณธ ํฌ๊ธฐ๋ก ๋๋๋ฆผ(รทscale) | |
| x1, y1, x2, y2 = (box / scale).tolist() | |
| cls_idx = int(label) - 1 # 0=๋ฐฐ๊ฒฝ ์ ์ธ | |
| if cls_idx < 0 or cls_idx >= len(VOC_CLASSES): | |
| continue | |
| name = VOC_CLASSES[cls_idx] | |
| color = CLASS_COLORS[cls_idx] | |
| # ๋ฐ์ค | |
| draw.rectangle([x1, y1, x2, y2], outline=color, width=3) | |
| # ๋ผ๋ฒจ ๋ฐฐ๊ฒฝ + ํ ์คํธ | |
| text = f"{name} {score:.2f}" | |
| tb = draw.textbbox((x1, y1), text, font=font) | |
| draw.rectangle([tb[0], tb[1], tb[2], tb[3]], fill=color) | |
| draw.text((x1, y1), text, fill="white", font=font) | |
| return pil_img | |
| def infer_image(model, img_path, device, score_thresh): | |
| pil = Image.open(img_path).convert("RGB") | |
| tensor, scale = preprocess(pil) | |
| tensor = tensor.to(device).unsqueeze(0) | |
| det = model(tensor) # eval ๋ชจ๋ โ {boxes, labels, scores} | |
| keep = det["scores"] >= score_thresh | |
| boxes = det["boxes"][keep].cpu() | |
| labels = det["labels"][keep].cpu() | |
| scores = det["scores"][keep].cpu() | |
| result = draw_detections(pil, boxes, labels, scores, scale) | |
| return result, len(boxes) | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--ckpt", required=True, help="ํ์ต๋ ๊ฐ์ค์น (frcnn.pth)") | |
| ap.add_argument("--image", help="๋จ์ผ ์ด๋ฏธ์ง ๊ฒฝ๋ก") | |
| ap.add_argument("--image_dir", help="์ด๋ฏธ์ง ํด๋ ๊ฒฝ๋ก") | |
| ap.add_argument("--out_dir", default="./results", help="๊ฒฐ๊ณผ ์ ์ฅ ํด๋") | |
| ap.add_argument("--score_thresh", type=float, default=0.5, | |
| help="์ด ์ ์ ์ด์๋ง ํ์") | |
| args = ap.parse_args() | |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| print("device:", device) | |
| model = FasterRCNN(NUM_CLASSES).to(device) | |
| model.load_state_dict(torch.load(args.ckpt, map_location=device)) | |
| model.eval() | |
| print(f"๋ชจ๋ธ ๋ก๋ ์๋ฃ: {args.ckpt}") | |
| os.makedirs(args.out_dir, exist_ok=True) | |
| # ์ฒ๋ฆฌํ ์ด๋ฏธ์ง ๋ชฉ๋ก ๊ตฌ์ฑ | |
| targets = [] | |
| if args.image: | |
| targets.append(args.image) | |
| if args.image_dir: | |
| for fn in os.listdir(args.image_dir): | |
| if fn.lower().endswith((".jpg", ".jpeg", ".png", ".bmp")): | |
| targets.append(os.path.join(args.image_dir, fn)) | |
| if not targets: | |
| print("์ด๋ฏธ์ง๋ฅผ ์ง์ ํ์ธ์: --image ๋๋ --image_dir") | |
| return | |
| for path in targets: | |
| result, n = infer_image(model, path, device, args.score_thresh) | |
| out_path = os.path.join(args.out_dir, "det_" + os.path.basename(path)) | |
| result.save(out_path) | |
| print(f" {os.path.basename(path)}: {n}๊ฐ ํ์ง โ {out_path}") | |
| print(f"์๋ฃ. ๊ฒฐ๊ณผ๋ {args.out_dir} ํด๋์ ์ ์ฅ๋จ.") | |
| if __name__ == "__main__": | |
| main() | |