用户52327593035
复制
删除
import cv2
import numpy as np
import mss
import pytesseract
import os
from PIL import Image
# ================== 🎯 配置区 ==================
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
OCR_LANG = 'chi_sim'
MATCH_THRESHOLD = 0.8 # 匹配阈值(可调)
# 定义两个场景
SCENES = [
{
"name": "场景1",
"template_path": r"D:\yunfe\手机悠悠\零.png",
"check_region": {"x": 0, "y": 0, "w": 2560, "h": 1600},
"ocr_fields": {
"卖价": {'x': 200, 'y': 720, 'w': 71, 'h': 33}
}
},
{
"name": "场景2",
"template_path": r"D:\yunfe\手机悠悠\崭新出厂.png",
"check_region": {"x": 0, "y": 0, "w": 2560, "h": 1600},
"ocr_fields": {
"定价": {'x': 58, 'y': 378, 'w': 68, 'h': 32}
}
}
]
IMAGE_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff', '.webp'}
def validate_images_in_scenes(scenes):
"""加载并验证模板图像(支持中文路径)"""
valid_templates = []
for scene in scenes:
path = scene["template_path"]
ext = os.path.splitext(path.lower())[1]
if ext not in IMAGE_EXTENSIONS:
print(f"[⚠️ ] 不支持格式: {path}")
continue
if not os.path.exists(path):
print(f"[❌] 文件不存在: {path}")
continue
try:
with Image.open(path) as img:
img_rgb = np.array(img.convert("RGB"))
if img.mode == "RGBA":
img_rgb = img_rgb[:, :, :3]
img_bgr = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR)
print(f"[✅] 加载成功: {scene['name']} -> {os.path.basename(path)}")
valid_templates.append((scene, img_bgr))
except Exception as e:
print(f"[❌] 加载失败: {path} | 错误: {e}")
return valid_templates
def capture_screen(x, y, w, h):
"""截屏并返回 BGR 图像"""
with mss.mss() as sct:
img = np.array(sct.grab({"left": x, "top": y, "width": w, "height": h}))
return cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
def match_template_on_screen(template_img, search_region, threshold=0.8):
"""灰度图模板匹配"""
screen_bgr = capture_screen(
search_region['x'], search_region['y'],
search_region['w'], search_region['h']
)
screen_gray = cv2.cvtColor(screen_bgr, cv2.COLOR_BGR2GRAY)
template_gray = cv2.cvtColor(template_img, cv2.COLOR_BGR2GRAY)
result = cv2.matchTemplate(screen_gray, template_gray, cv2.TM_CCOEFF_NORMED)
_, max_val, _, max_loc = cv2.minMaxLoc(result)
if max_val >= threshold:
return True, max_loc, max_val
return False, None, max_val
def preprocess_for_ocr_with_dot(image_gray):
"""增强小数点识别的预处理"""
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(4, 4))
enhanced = clahe.apply(image_gray)
_, binary = cv2.threshold(enhanced, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
large = cv2.resize(binary, None, fx=3, fy=3, interpolation=cv2.INTER_CUBIC)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
cleaned = cv2.morphologyEx(large, cv2.MORPH_OPEN, kernel)
return cleaned
def read_ocr_fields(field_configs):
"""读取多个字段(仅数字+小数点)"""
results = {}
with mss.mss():
for name, cfg in field_configs.items():
x, y, w, h = cfg['x'], cfg['y'], cfg['w'], cfg['h']
img = np.array(mss.mss().grab({"left": x, "top": y, "width": w, "height": h}))
gray = cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY)
processed = preprocess_for_ocr_with_dot(gray)
config = "--oem 3 --psm 8 -c tessedit_char_whitelist=0123456789."
raw = pytesseract.image_to_string(processed, lang=OCR_LANG, config=config).strip()
cleaned = raw.replace(' ', '')
print(f"📊 [{name}]: '{raw}' → '{cleaned}'")
results[name] = cleaned or None
return results
# ================== ✅ 主程序:一次性检测场景1 和 场景2 ==================
if __name__ == "__main__":
print("🔍 正在加载模板图像...")
templates = validate_images_in_scenes(SCENES)
if not templates:
print("🛑 没有可用模板,程序退出。")
exit(1)
print("\n📸 开始一次性检测所有场景...\n")
# 存储最终结果
all_results = {}
# 遍历每个场景,独立检测
for scene, template in templates:
print(f"🔍 正在检测:【{scene['name']}】")
found, loc, conf = match_template_on_screen(
template,
scene["check_region"],
threshold=MATCH_THRESHOLD
)
if found:
print(f"✅ 匹配成功!相似度={conf:.3f} 位置={loc}")
print(f"📌 正在提取 [{scene['name']}] 的数据...")
result = read_ocr_fields(scene["ocr_fields"])
all_results[scene["name"]] = result
else:
print(f"❌ 未匹配到 【{scene['name']}】,得分={conf:.3f}")
all_results[scene["name"]] = None # 标记为未找到
print("-" * 50) # 分隔线
# 最终汇总输出
print("\n📋 === 最终结果汇总 ===")
for name, data in all_results.items():
if data is not None:
print(f"🟢 {name}: {data}")
else:
print(f"🔴 {name}: 未检测到")
print("\n👋 程序执行完毕,即将退出。")
修改纠正以上脚本