Files
zjsh_yolov11/muban/main.py

166 lines
4.0 KiB
Python
Raw Permalink Normal View History

2026-03-10 13:58:21 +08:00
import os
import cv2
import numpy as np
# =========================================================
# 全局配置
# =========================================================
TEMPLATE_DIR = "./muban_image1"
# 三个 ROIx, y, w, h
ROI_1 = (782, 614, 164, 128)
ROI_2 = (837, 791, 100, 99)
ROI_3 = (873, 736, 141, 110)
USE_GRAY = False
TM_METHOD = cv2.TM_CCOEFF_NORMED
SCORE_THRESH = 0.4
# =========================================================
# 模板加载
# =========================================================
def load_templates(template_dir):
templates = []
if not os.path.isdir(template_dir):
raise RuntimeError(f"模板目录不存在: {template_dir}")
for fname in os.listdir(template_dir):
if not fname.lower().endswith((".png", ".jpg", ".jpeg", ".bmp")):
continue
path = os.path.join(template_dir, fname)
img = cv2.imread(path)
if img is None:
continue
if USE_GRAY:
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
h, w = img.shape[:2]
name = os.path.splitext(fname)[0]
templates.append({
"name": name,
"img": img,
"h": h,
"w": w
})
print(f"[INFO] 已加载 {len(templates)} 个模板")
return templates
TEMPLATES = load_templates(TEMPLATE_DIR)
# =========================================================
# ROI 裁剪
# =========================================================
def crop_roi(img, roi):
x, y, w, h = roi
return img[y:y + h, x:x + w]
# =========================================================
# 单 ROI 模板匹配
# =========================================================
def match_one_roi(img, roi):
roi_img = crop_roi(img, roi)
if roi_img.size == 0:
return None, 0.0
if USE_GRAY:
roi_img = cv2.cvtColor(roi_img, cv2.COLOR_BGR2GRAY)
best_name = None
best_score = -1.0
for t in TEMPLATES:
if t["h"] > roi_img.shape[0] or t["w"] > roi_img.shape[1]:
continue
res = cv2.matchTemplate(roi_img, t["img"], TM_METHOD)
_, max_val, _, _ = cv2.minMaxLoc(res)
if max_val > best_score:
best_score = max_val
best_name = t["name"]
if best_score < SCORE_THRESH:
return None, best_score
return best_name, best_score
# =========================================================
# 核心逻辑ROI_1 → ROI_2 → ROI_3
# =========================================================
def match_image(img):
roi_list = [
("roi1", ROI_1),
("roi2", ROI_2),
("roi3", ROI_3),
]
for roi_name, roi in roi_list:
name, score = match_one_roi(img, roi)
if name is not None:
return {
"result": name,
"roi": roi_name,
"score": score
}
return {
"result": None,
"roi": None,
"score": 0.0
}
# =========================================================
# 可视化(只画命中的 ROI
# =========================================================
def draw_result(img, result):
vis = img.copy()
roi_map = {
"roi1": ROI_1,
"roi2": ROI_2,
"roi3": ROI_3
}
if result["roi"] not in roi_map:
return vis
x, y, w, h = roi_map[result["roi"]]
text = f'{result["result"]} {result["score"]:.2f}'
cv2.rectangle(vis, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(
vis, text, (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX,
0.7, (0, 255, 0), 2
)
return vis
# =========================================================
# main 测试
# =========================================================
if __name__ == "__main__":
img = cv2.imread("1.png")
if img is None:
raise RuntimeError("测试图片未找到")
result = match_image(img)
print("[RESULT]", result)
vis = draw_result(img, result)
cv2.imshow("template match", vis)
cv2.waitKey(0)
cv2.destroyAllWindows()