cv_project_test / CV-Project /varification.py
Himel09's picture
Upload 10 files
e194ef7 verified
Raw
History Blame Contribute Delete
7.4 kB
import os
# ─────────────────────────────────────────────────────────────────────────────
# ✏️ EDIT THIS PATH
# ─────────────────────────────────────────────────────────────────────────────
DATASET_DIR = r"D:\merged_dataset"
NC = 20 # total number of classees
# ─────────────────────────────────────────────────────────────────────────────
IMG_EXTS = {".jpg", ".jpeg", ".png", ".bmp", ".webp", ".avif"}
def verify_split(split):
img_dir = os.path.join(DATASET_DIR, split, "images")
lbl_dir = os.path.join(DATASET_DIR, split, "labels")
errors = []
warnings = []
if not os.path.isdir(img_dir):
print(f" [SKIP] {split}/images folder not found β€” skipping")
return
img_files = {os.path.splitext(f)[0]: f
for f in os.listdir(img_dir)
if os.path.splitext(f)[1].lower() in IMG_EXTS}
lbl_files = {os.path.splitext(f)[0]: f
for f in os.listdir(lbl_dir)
if f.endswith(".txt")} if os.path.isdir(lbl_dir) else {}
total_images = len(img_files)
total_labels = len(lbl_files)
total_boxes = 0
# ── Check 1: every image has a label ─────────────────────────────────────
for stem in img_files:
if stem not in lbl_files:
errors.append(f" [NO LABEL] {img_files[stem]}")
# ── Check 2: every label has an image ────────────────────────────────────
for stem in lbl_files:
if stem not in img_files:
warnings.append(f" [NO IMAGE] {lbl_files[stem]}")
# ── Check 3–7: validate label content ────────────────────────────────────
for stem, lbl_fname in lbl_files.items():
lbl_path = os.path.join(lbl_dir, lbl_fname)
try:
with open(lbl_path, "r") as f:
lines = [l.strip() for l in f.readlines() if l.strip()]
except Exception as e:
errors.append(f" [READ ERROR] {lbl_fname}: {e}")
continue
if len(lines) == 0:
warnings.append(f" [EMPTY] {lbl_fname} β€” no annotations")
continue
for i, line in enumerate(lines, 1):
parts = line.split()
# Check 4: must have exactly 5 values
if len(parts) != 5:
errors.append(
f" [BAD FORMAT] {lbl_fname} line {i}: "
f"expected 5 values, got {len(parts)} β†’ '{line}'"
)
continue
try:
cls_id = int(parts[0])
x, y, w, h = float(parts[1]), float(parts[2]), \
float(parts[3]), float(parts[4])
except ValueError:
errors.append(
f" [NOT NUMERIC] {lbl_fname} line {i}: '{line}'"
)
continue
# Check 3: class ID in range
if cls_id < 0 or cls_id >= NC:
errors.append(
f" [BAD CLASS ID] {lbl_fname} line {i}: "
f"class={cls_id} (valid range 0–{NC-1})"
)
# Check 5: bbox values in [0, 1]
for val_name, val in [("x", x), ("y", y), ("w", w), ("h", h)]:
if not (0.0 <= val <= 1.0):
errors.append(
f" [OUT OF RANGE] {lbl_fname} line {i}: "
f"{val_name}={val} (must be 0.0–1.0)"
)
total_boxes += 1
# ── Print split report ────────────────────────────────────────────────────
status = "PASS" if not errors else "FAIL"
print(f"\n [{status}] {split}/")
print(f" images : {total_images}")
print(f" labels : {total_labels}")
print(f" boxes : {total_boxes}")
if warnings:
print(f" warnings ({len(warnings)}):")
for w in warnings[:20]:
print(w)
if len(warnings) > 20:
print(f" ... and {len(warnings)-20} more warnings")
if errors:
print(f" errors ({len(errors)}):")
for e in errors[:30]:
print(e)
if len(errors) > 30:
print(f" ... and {len(errors)-30} more errors")
else:
print(" No errors found!")
return len(errors)
def main():
print("=" * 70)
print(" Label verification report")
print(f" Dataset : {DATASET_DIR}")
print(f" nc : {NC} classes (valid IDs: 0 – {NC-1})")
print("=" * 70)
total_errors = 0
for split in ("train", "valid", "test"):
result = verify_split(split)
if result:
total_errors += result
print("\n" + "=" * 70)
if total_errors == 0:
print(" ALL CHECKS PASSED β€” dataset is ready for training!")
else:
print(f" TOTAL ERRORS: {total_errors} β€” fix these before training.")
print("=" * 70)
# ── Class ID distribution ─────────────────────────────────────────────────
print("\n Class ID distribution across entire dataset:")
class_counts = {i: 0 for i in range(NC)}
for split in ("train", "valid", "test"):
lbl_dir = os.path.join(DATASET_DIR, split, "labels")
if not os.path.isdir(lbl_dir):
continue
for fname in os.listdir(lbl_dir):
if not fname.endswith(".txt"):
continue
with open(os.path.join(lbl_dir, fname), "r") as f:
for line in f:
parts = line.strip().split()
if parts:
try:
class_counts[int(parts[0])] += 1
except (ValueError, KeyError):
pass
class_names = [
'Mask','can','cellphone','electronics','gbottle','glove','metal',
'misc','net','pbag','pbottle','plastic','rod','sunglasses','tire',
'Microplastic','fiber','film','fragment','pallet'
]
print(f"\n {'ID':>3} {'Class':<15} {'Boxes':>8}")
print(f" {'─'*3} {'─'*15} {'─'*8}")
for i in range(NC):
name = class_names[i] if i < len(class_names) else f"class_{i}"
count = class_counts[i]
flag = " ← ZERO annotations!" if count == 0 else ""
print(f" {i:>3} {name:<15} {count:>8}{flag}")
if __name__ == "__main__":
main()