ocr识别图片并在大图定位小图的位置-py
·
1
import cv2
import numpy as np
from PIL import Image
class TemplateMatcher:
def __init__(self, screenshot_path: str):
"""
screenshot_path: 完整截图路径
"""
self.screenshot_path = screenshot_path
self.original_image = cv2.imread(screenshot_path)
if self.original_image is None:
raise ValueError(f"无法读取截图文件: {screenshot_path}")
# 转为灰度图,提高匹配稳定性
self.gray_image = cv2.cvtColor(self.original_image, cv2.COLOR_BGR2GRAY)
def find_position(self, template_path: str, threshold: float = 0.8):
"""
template_path: 模板图路径
threshold: 模板匹配阈值,0.0 ~ 1.0,越高越严格
返回 (x, y) 或者 None
"""
template = cv2.imread(template_path)
if template is None:
raise ValueError(f"无法读取模板图文件: {template_path}")
template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
h, w = template_gray.shape
best_score = -1
best_pos = None
# 多尺度匹配(提升复杂 UI 的识别率)
for scale in np.linspace(0.8, 1.2, 10): # 可调整范围
# 调整模板大小
resized_template = cv2.resize(template_gray, (int(w * scale), int(h * scale)))
# 跳过尺度太小/太大的
if resized_template.shape[0] <= 5 or resized_template.shape[1] <= 5:
print(f"跳过尺度 {scale:.2f},模板尺寸 {resized_template.shape}")
continue
# 模板匹配
result = cv2.matchTemplate(self.gray_image, resized_template, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
if max_val > best_score:
best_score = max_val
best_pos = max_loc
best_scale = scale
best_template_shape = resized_template.shape
# 匹配度不足,返回 None
if best_score < threshold:
print(f"匹配度 {best_score:.3f} 低于阈值 {threshold}")
return None
th, tw = best_template_shape
# 返回模板中心点坐标
center_x = best_pos[0] + tw // 2
center_y = best_pos[1] + th // 2
print(f"最佳匹配度: {best_score:.3f}, scale={best_scale:.2f}")
return (center_x, center_y)
def debug_draw_match(screenshot_path, template_path, position, output="debug_output.png"):
img = cv2.imread(screenshot_path)
template = cv2.imread(template_path)
h, w, _ = template.shape
x, y = position
# 左上角坐标
top_left = (x - w // 2, y - h // 2)
# 右下角坐标
bottom_right = (x + w // 2, y + h // 2)
# 画红框
cv2.rectangle(img, top_left, bottom_right, (0, 0, 255), 3)
cv2.imwrite(output, img)
print(f"验证图已输出到: {output}")
2
import cv2
import numpy as np
from matcher import debug_draw_match
class ORBMatcher:
def __init__(self, screenshot_path: str):
self.img = cv2.imread(screenshot_path, cv2.IMREAD_GRAYSCALE)
if self.img is None:
raise ValueError("无法读取截图文件")
# ORB 特征点检测器
self.orb = cv2.ORB_create(nfeatures=2000)
self.kp_img, self.des_img = self.orb.detectAndCompute(self.img, None)
# 特征点匹配器
self.matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
def find_position(self, template_path: str, min_matches=12):
tpl = cv2.imread(template_path, cv2.IMREAD_GRAYSCALE)
if tpl is None:
raise ValueError("无法读取模板图")
kp_tpl, des_tpl = self.orb.detectAndCompute(tpl, None)
matches = self.matcher.match(des_tpl, self.des_img)
# 根据距离排序(越小越好)
matches = sorted(matches, key=lambda x: x.distance)
# 如果匹配点太少 → 模板不存在
if len(matches) < min_matches:
return None
# 取前 N 个最佳匹配
good = matches[:min_matches]
# 均值计算中心位置
points = []
for m in good:
(x, y) = self.kp_img[m.trainIdx].pt
points.append((x, y))
# 求匹配区域的平均坐标
avg_x = int(sum([p[0] for p in points]) / len(points))
avg_y = int(sum([p[1] for p in points]) / len(points))
return (avg_x, avg_y)
更多推荐



所有评论(0)