2026年11月14日

影像辨識加上規則判斷的小流程

Python影像規則

常見需求:希望用影像辨識加上邏輯判斷,決定下一步要通過、重拍還是標記。這類需求往往被講得很寬,但要先做出一個「看得懂為什麼會這樣判」的小流程,之後才適合換成真正的模型。

這次測試到哪裡

inspect_and_decide.py 已在本機用 Pillow 產生的三張圖測過:偏暗的圖會建議重拍,幾乎沒有對比的亮圖會拒絕,對比足夠的圖會通過。這是亮度與對比的規則量測,不是訓練好的辨識模型,也沒有接攝影機或實體機台。

三層怎麼分工

層做什麼
感測讀入圖片,計算可重現的量,例如平均亮度與對比。
決策用寫下來的門檻決定 pass、retake 或 reject,並留下原因。
動作把結果寫成 JSON 或紀錄檔,供之後的人重看,而不是只在畫面上一閃。

先用量測,再考慮模型

若你的實際任務是辨識特定物件或缺陷,最終可能會用到訓練資料與模型。那一步需要標註品質、評估方式與誤判成本,本篇不假裝已經完成。先把「輸入一張圖、輸出一個帶原因的決定」這條管線做穩,之後只替換決策函式即可。

依賴是 Pillow。本機測試時安裝在虛擬環境中;請在你的環境執行 pip install -r requirements.txt。

inspect_and_decide.py
#!/usr/bin/env python3
"""對圖片做亮度與對比的量測,再用規則決定通過、重拍或標記。

這不是訓練好的辨識模型,只是可重現的量測加上門檻。
"""

from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path

from PIL import Image, ImageStat


def inspect(path: Path, dark: float, blank: float) -> dict:
    image = Image.open(path).convert("L")
    stats = ImageStat.Stat(image)
    mean = float(stats.mean[0])
    stddev = float(stats.stddev[0])
    if mean < dark:
        decision = "retake"
        reason = f"畫面偏暗(平均亮度 {mean:.1f} < {dark}),建議重拍或補光"
    elif stddev < blank:
        decision = "reject"
        reason = f"對比過低(標準差 {stddev:.1f} < {blank}),畫面可能近乎空白或過曝"
    else:
        decision = "pass"
        reason = f"亮度 {mean:.1f}、對比 {stddev:.1f} 通過目前門檻"
    return {
        "file": path.name,
        "mean_brightness": round(mean, 2),
        "contrast_stddev": round(stddev, 2),
        "decision": decision,
        "reason": reason,
    }


def main() -> int:
    parser = argparse.ArgumentParser(description="影像量測與規則判斷")
    parser.add_argument("images", nargs="+", type=Path)
    parser.add_argument("--dark", type=float, default=40.0, help="平均亮度低於此值則建議重拍")
    parser.add_argument("--blank", type=float, default=8.0, help="標準差低於此值則視為空白或無資訊")
    parser.add_argument("-o", "--output", type=Path)
    args = parser.parse_args()

    results = []
    for path in args.images:
        row = inspect(path, args.dark, args.blank)
        results.append(row)
        print(f"{row['file']}: {row['decision']} — {row['reason']}")
    if args.output:
        args.output.parent.mkdir(parents=True, exist_ok=True)
        args.output.write_text(json.dumps(results, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
    return 0


if __name__ == "__main__":
    sys.exit(main())
requirements.txt
pillow>=10

執行

python inspect_and_decide.py dark.png blank.png ok.png -o result.json

若輸入是人的臉、身分證件或其他可識別資料,還要處理同意與個人資料保護,不要把圖片傳到你無法說明保存方式的地方。本篇的範例只用幾何色塊,沒有使用人像。

常見錯誤

下載