157 lines
4.3 KiB
Python
157 lines
4.3 KiB
Python
"""Generate a CSV report matching merged images to source stamp images.
|
|
|
|
This script is intentionally standalone and does not import cmbot project code.
|
|
Edit the three paths below, then run:
|
|
|
|
python match_stamp.py
|
|
|
|
It does not copy, move, rename, or delete any image files.
|
|
"""
|
|
from __future__ import print_function
|
|
|
|
import csv
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
|
|
OUTPUT_DIR = r"D:\chengma\cmbot\output\20260623_094529"
|
|
STAMP_DIR = r"D:\chengma\印花和底图\已处理印花\卡通71(66大码200斤 KEKE已上)\横1"
|
|
REPORT_PATH = r"D:\chengma\cmbot\match_stamp_report.csv"
|
|
|
|
IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".webp"}
|
|
FIELDNAMES = [
|
|
"status",
|
|
"code",
|
|
"merged_image",
|
|
"stamp_image",
|
|
"merged_folder",
|
|
"message",
|
|
]
|
|
|
|
|
|
def is_image(path):
|
|
return path.is_file() and path.suffix.lower() in IMAGE_EXTENSIONS
|
|
|
|
|
|
def extract_code_from_merged_name(path):
|
|
"""Extract stamp code from the final underscore suffix.
|
|
|
|
Example: 1_TY037.png -> TY037.
|
|
"""
|
|
stem = path.stem
|
|
if "_" not in stem:
|
|
return ""
|
|
code = stem.rsplit("_", 1)[1].strip()
|
|
return code
|
|
|
|
|
|
def iter_images(root):
|
|
root = Path(root)
|
|
if not root.exists():
|
|
return
|
|
for path in sorted(root.rglob("*")):
|
|
if is_image(path):
|
|
yield path
|
|
|
|
|
|
def build_stamp_index(stamp_dir):
|
|
index = {}
|
|
for path in iter_images(stamp_dir):
|
|
code = path.stem.strip()
|
|
if not code:
|
|
continue
|
|
index.setdefault(code, []).append(path.resolve())
|
|
return index
|
|
|
|
|
|
def match_merged_image(path, stamp_index):
|
|
code = extract_code_from_merged_name(path)
|
|
if not code:
|
|
return {
|
|
"status": "bad_name",
|
|
"code": "",
|
|
"merged_image": str(path.resolve()),
|
|
"stamp_image": "",
|
|
"merged_folder": str(path.parent.resolve()),
|
|
"message": "File name has no underscore suffix code",
|
|
}
|
|
|
|
candidates = stamp_index.get(code, [])
|
|
if not candidates:
|
|
return {
|
|
"status": "missing",
|
|
"code": code,
|
|
"merged_image": str(path.resolve()),
|
|
"stamp_image": "",
|
|
"merged_folder": str(path.parent.resolve()),
|
|
"message": "No stamp image found for code",
|
|
}
|
|
|
|
stamp_paths = " | ".join(str(p) for p in candidates)
|
|
if len(candidates) > 1:
|
|
return {
|
|
"status": "duplicate",
|
|
"code": code,
|
|
"merged_image": str(path.resolve()),
|
|
"stamp_image": stamp_paths,
|
|
"merged_folder": str(path.parent.resolve()),
|
|
"message": "Multiple stamp images found for code",
|
|
}
|
|
|
|
return {
|
|
"status": "matched",
|
|
"code": code,
|
|
"merged_image": str(path.resolve()),
|
|
"stamp_image": stamp_paths,
|
|
"merged_folder": str(path.parent.resolve()),
|
|
"message": "",
|
|
}
|
|
|
|
|
|
def write_csv(rows, report_path):
|
|
report_path = Path(report_path)
|
|
report_path.parent.mkdir(parents=True, exist_ok=True)
|
|
with report_path.open("w", encoding="utf-8-sig", newline="") as f:
|
|
writer = csv.DictWriter(f, fieldnames=FIELDNAMES)
|
|
writer.writeheader()
|
|
for row in rows:
|
|
writer.writerow(row)
|
|
|
|
|
|
def generate_report(output_dir, stamp_dir, report_path):
|
|
output_dir = Path(output_dir)
|
|
stamp_dir = Path(stamp_dir)
|
|
|
|
stamp_index = build_stamp_index(stamp_dir)
|
|
rows = []
|
|
for path in iter_images(output_dir):
|
|
rows.append(match_merged_image(path, stamp_index))
|
|
|
|
write_csv(rows, report_path)
|
|
return rows
|
|
|
|
|
|
def summarize(rows):
|
|
counts = {}
|
|
for row in rows:
|
|
status = row.get("status", "")
|
|
counts[status] = counts.get(status, 0) + 1
|
|
return counts
|
|
|
|
|
|
def main():
|
|
started = datetime.now()
|
|
rows = generate_report(OUTPUT_DIR, STAMP_DIR, REPORT_PATH)
|
|
counts = summarize(rows)
|
|
print("Generated report: {}".format(Path(REPORT_PATH).resolve()))
|
|
print("Merged images: {}".format(len(rows)))
|
|
print("Matched: {}".format(counts.get("matched", 0)))
|
|
print("Missing: {}".format(counts.get("missing", 0)))
|
|
print("Duplicate: {}".format(counts.get("duplicate", 0)))
|
|
print("Bad name: {}".format(counts.get("bad_name", 0)))
|
|
print("Elapsed: {}".format(datetime.now() - started))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|