avant codex

This commit is contained in:
2026-02-22 15:05:40 +01:00
parent fed449c784
commit 20af00d653
291 changed files with 51868 additions and 424 deletions
+37
View File
@@ -0,0 +1,37 @@
# Test YOLO (feuilles/plantes)
## 1) Créer et activer un venv
```bash
python3 -m venv .venv
source .venv/bin/activate
```
## 2) Installer les dépendances
```bash
pip install --upgrade pip
pip install ultralyticsplus==0.0.28 ultralytics==8.0.43 opencv-python matplotlib
```
## 3) Lancer un test
```bash
python3 test_yolo/test_yolo_leaf.py --image /chemin/vers/ma_plante.jpg
```
Sorties générées :
- `test_yolo/output/detections.json`
- `test_yolo/output/annotated.jpg`
## 4) Paramètres utiles
```bash
python3 test_yolo/test_yolo_leaf.py \
--image /chemin/vers/ma_plante.jpg \
--conf 0.25 \
--iou 0.45 \
--max-det 1000 \
--json-out test_yolo/output/detections.json \
--image-out test_yolo/output/annotated.jpg
```
Binary file not shown.

After

Width:  |  Height:  |  Size: 810 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 842 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 918 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 895 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 831 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

@@ -0,0 +1,65 @@
{
"image": "image/Image collée (8).png",
"model": "foduucom/plant-leaf-detection-and-classification",
"model_source": "/home/gilles/.cache/huggingface/hub/models--foduucom--plant-leaf-detection-and-classification/snapshots/fe7b672ca4719fb7eb1b8c677c24631342a24022/best.pt",
"params": {
"conf": 0.03,
"iou": 0.6,
"max_det": 1000
},
"count": 4,
"detections": [
{
"index": 0,
"class_id": 8,
"class_name": "raspberry",
"class_name_fr": "raspberry",
"confidence": 0.886375367641449,
"bbox_xyxy": [
79.77804565429688,
5.03753137588501,
172.6075897216797,
62.644927978515625
]
},
{
"index": 1,
"class_id": 8,
"class_name": "raspberry",
"class_name_fr": "raspberry",
"confidence": 0.8398752212524414,
"bbox_xyxy": [
161.0865478515625,
54.80467987060547,
233.95501708984375,
127.42171478271484
]
},
{
"index": 2,
"class_id": 8,
"class_name": "raspberry",
"class_name_fr": "raspberry",
"confidence": 0.8144381046295166,
"bbox_xyxy": [
86.82860565185547,
82.79867553710938,
171.43515014648438,
195.80043029785156
]
},
{
"index": 3,
"class_id": 8,
"class_name": "raspberry",
"class_name_fr": "raspberry",
"confidence": 0.5520069599151611,
"bbox_xyxy": [
165.154052734375,
9.37171459197998,
231.52166748046875,
60.80621337890625
]
}
]
}
+169
View File
@@ -0,0 +1,169 @@
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import json
from pathlib import Path
TOKEN_FR = {
"healthy": "saine",
"leaf": "feuille",
"plant": "plante",
"disease": "maladie",
"blight": "mildiou",
"rust": "rouille",
"spot": "tache",
"scab": "tavelure",
"mold": "moisissure",
"mildew": "oidium",
"powdery": "poudreux",
"bacterial": "bacterien",
"viral": "viral",
"virus": "virus",
"yellow": "jaune",
"mosaic": "mosaique",
"late": "tardif",
"early": "precoce",
"septoria": "septoriose",
"target": "cible",
"black": "noire",
"rot": "pourriture",
}
def translate_label_to_fr(label: str) -> str:
tokens = (
label.replace("-", " ")
.replace("_", " ")
.replace(",", " ")
.replace("(", " ")
.replace(")", " ")
.split()
)
if not tokens:
return label
translated = [TOKEN_FR.get(tok.lower(), tok.lower()) for tok in tokens]
return " ".join(translated)
def resolve_model(model_arg: str) -> tuple[str, str]:
model_path = Path(model_arg)
if model_path.exists():
return str(model_path), model_arg
lower = model_arg.lower()
if "/" in model_arg and not lower.endswith((".pt", ".onnx", ".engine", ".torchscript")):
try:
from huggingface_hub import hf_hub_download
except Exception as exc:
raise SystemExit(
"Le modèle semble être un repo Hugging Face. Installe:\n"
"pip install huggingface_hub\n"
f"Détail: {exc}"
)
try:
downloaded = hf_hub_download(repo_id=model_arg, filename="best.pt")
return downloaded, model_arg
except Exception as exc:
raise SystemExit(
f"Impossible de télécharger best.pt depuis le repo Hugging Face '{model_arg}'.\n"
f"Détail: {exc}"
)
return model_arg, model_arg
def main() -> int:
parser = argparse.ArgumentParser(
description="Test YOLO feuille/plante avec sortie JSON et image annotée."
)
parser.add_argument("--image", required=True, help="Chemin image à analyser")
parser.add_argument(
"--model",
default="foduucom/plant-leaf-detection-and-classification",
help="Chemin vers .pt/.onnx ou repo Hugging Face (best.pt)",
)
parser.add_argument("--conf", type=float, default=0.25, help="Seuil confiance")
parser.add_argument("--iou", type=float, default=0.45, help="Seuil IoU NMS")
parser.add_argument("--max-det", type=int, default=1000, help="Nombre max de détections")
parser.add_argument(
"--json-out",
default="test_yolo/output/detections.json",
help="Fichier JSON de sortie",
)
parser.add_argument(
"--image-out",
default="test_yolo/output/annotated.jpg",
help="Image annotée de sortie",
)
args = parser.parse_args()
image_path = Path(args.image)
if not image_path.exists():
raise SystemExit(f"Image introuvable: {image_path}")
try:
import cv2
from ultralytics import YOLO
except Exception as exc:
raise SystemExit(
"Dépendances manquantes. Installe dans un venv:\n"
"pip install ultralytics opencv-python matplotlib huggingface_hub\n"
f"Détail: {exc}"
)
model_source, model_display = resolve_model(args.model)
model = YOLO(model_source)
model.overrides["conf"] = args.conf
model.overrides["iou"] = args.iou
model.overrides["max_det"] = args.max_det
results = model.predict(str(image_path))
result = results[0]
boxes = result.boxes
names = getattr(result, "names", {})
detections: list[dict] = []
for i, box in enumerate(boxes):
cls_id = int(box.cls.item())
conf = float(box.conf.item())
xyxy = [float(v) for v in box.xyxy[0].tolist()]
detections.append(
{
"index": i,
"class_id": cls_id,
"class_name": names.get(cls_id, str(cls_id)),
"class_name_fr": translate_label_to_fr(names.get(cls_id, str(cls_id))),
"confidence": conf,
"bbox_xyxy": xyxy,
}
)
payload = {
"image": str(image_path),
"model": model_display,
"model_source": model_source,
"params": {"conf": args.conf, "iou": args.iou, "max_det": args.max_det},
"count": len(detections),
"detections": detections,
}
json_out = Path(args.json_out)
json_out.parent.mkdir(parents=True, exist_ok=True)
json_out.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
annotated = result.plot()
image_out = Path(args.image_out)
image_out.parent.mkdir(parents=True, exist_ok=True)
cv2.imwrite(str(image_out), annotated)
print(f"Détections: {len(detections)}")
print(f"JSON: {json_out}")
print(f"Image annotée: {image_out}")
return 0
if __name__ == "__main__":
raise SystemExit(main())