[Python] 纯文本查看 复制代码
import time
from mss import mss
import cv2
import numpy as np
mss_instance = mss()
class ImageBase:
def __init__(self, binary_img):
self._binary = np.where(binary_img > 0, 1, 0).astype(np.int8)
def extract_characters(self):
img = (self._binary.astype(np.uint8) * 255).astype(np.uint8)
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(img, connectivity=8)
chars = []
for i in range(1, num_labels):
x1, y1 = stats[i, 0], stats[i, 1]
x2, y2 = stats[i, 0] + stats[i, 2], stats[i, 1] + stats[i, 3]
w, h = stats[i, 2], stats[i, 3]
area = stats[i, 4]
if area <= 1:
continue
char_img = self._binary[y1:y2, x1:x2]
# ===================== 修复+补充 =====================
if h > 11:
char_img = char_img[:11, :]
char_img = self.simplify_2d_array(char_img) # 裁剪空白
elif h < 11:
pad_rows = 11 - char_img.shape[0]
pad_matrix = np.zeros((pad_rows, char_img.shape[1]), dtype=np.int8)
char_img = np.vstack([char_img, pad_matrix])
# 字符信息
char_info = {
"rect": x1,
"w": char_img.shape[1],
"h": char_img.shape[0],
"data": char_img,
"hex_str": self.dot2hex(char_img)
}
chars.append(char_info)
chars.sort(key=lambda item: item["rect"])
return chars
# 🔥 补充:修复全0点阵崩溃问题(最关键!)
def simplify_2d_array(self, arr):
coords = np.argwhere(arr == 1)
# 防护:如果没有有效像素(全0),返回最小点阵,不崩溃
if coords.size == 0:
return np.zeros((1, 1), dtype=np.int8)
min_row, min_col = coords.min(axis=0)
max_row, max_col = coords.max(axis=0)
return arr[min_row:max_row + 1, min_col:max_col + 1]
def dot2hex(self, dot_matrix):
matrix = dot_matrix.T
bits = ''.join(str(v) for v in matrix.flatten())
mod = len(bits) % 4
if mod != 0:
bits += '0' * (4 - mod)
hex_string = ''
for i in range(0, len(bits), 4):
nibble = bits[i:i + 4]
hex_string += format(int(nibble, 2), 'X')
return hex_string
def calc_hamming_similarity(hex1: str, hex2: str) -> float:
"""基于位级汉明距离的相似度(0~1),长度不同时返回0"""
if len(hex1) != len(hex2):
return 0.0
v1 = int(hex1, 16)
v2 = int(hex2, 16)
xor = v1 ^ v2
diff_bits = xor.bit_count()
total_bits = len(hex1) * 4
return 1.0 - (diff_bits / total_bits)
def parse_zk(zk_list):
hex_to_char = {}
items = []
for line in zk_list:
parts = line.split("$")
hex_str, char = parts[0], parts[1]
hex_to_char[hex_str] = char
items.append({"hex": hex_str, "char": char})
return hex_to_char, items
def ocr_hex_match(chars, hex_to_char, zk_items, threshold=0.85):
result = []
for char in chars:
current_hex = char["hex_str"]
# 先精准匹配(你要的get逻辑)
if current_hex in hex_to_char:
result.append(hex_to_char[current_hex])
continue
# 兜底汉明相似度匹配
best_sim = 0.0
best_char = "?"
for item in zk_items:
sim = calc_hamming_similarity(current_hex, item["hex"])
if sim == 1.0:
best_char = item["char"]
break
if sim > best_sim:
best_sim = sim
best_char = item["char"]
result.append(best_char if best_sim >= threshold else "?")
return "".join(result)
# 🔥 优化:复用全局mss,删除冗余函数
def Stressshow_img(img, colors):
image = img.copy()
colors = colors.split("|")
masks = np.zeros_like(image[:, :, 0], dtype=np.uint8)
for color in colors:
r, g, b = int(color[4:6], 16), int(color[2:4], 16), int(color[0:2], 16)
dr, dg, db = int(color[7:9], 16), int(color[9:11], 16), int(color[11:13], 16) if len(color) > 6 else (0, 0, 0)
lower = np.array([max(0, r - dr), max(0, g - dg), max(0, b - db)], dtype=np.uint8)
upper = np.array([min(255, r + dr), min(255, g + dg), min(255, b + db)], dtype=np.uint8)
mask = cv2.inRange(image, lower, upper)
masks = cv2.bitwise_or(masks, mask)
return masks
# 你的字库(完全不变)
zk = [
'200401007FFFFE$1$0.0.25$11',
'3FCFFB21C4188318E1F018$6$0.0.41$11',
'C01800$.$0.0.4$2',
'40588610C21CE6F78CF0$3$0.0.33$11',
'385F0620C418C71FA1E0$5$0.0.33$11',
'73DFFF30C21843FCDCF00C$8$0.0.47$11',
'060FFBC7C01803007C7BFE040$0$0.0.43$11',
'40F83E0CC19C63F85E08$2$0.0.35$11'
]
if __name__ == '__main__':
st = time.time()
# 识别区域
x1, y1, x2, y2 = 1782, 1035, 1833, 1054
monitor = {"top": y1, "left": x1, "width": x2 - x1, "height": y2 - y1}
# 截图
pic = mss_instance.grab(monitor)
test_img = cv2.cvtColor(np.array(pic), cv2.COLOR_RGBA2RGB)
# 二值化
mask = Stressshow_img(test_img, 'f7f7f8-303030|b2b7ba-303030')
# 字符分割+识别
img_base = ImageBase(mask)
char_list = img_base.extract_characters()
hex_to_char, zk_items = parse_zk(zk)
final_text = ocr_hex_match(char_list, hex_to_char, zk_items, threshold=0.9)
# 输出
print(f"耗时:{time.time() - st:.4f}s")
print(f"✅ 最终识别结果:{final_text}")