吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 302|回复: 2
上一主题 下一主题
收起左侧

[Python 原创] 基于汉明距离实现的点阵ocr

[复制链接]
跳转到指定楼层
楼主
18834161486 发表于 2026-5-22 10:33 回帖奖励
为了方便使用,代码使用大漠字库来实现点阵。
使用洪水填充算法来区分图片中点阵的位置。
使用汉明距离进行模糊匹配。
缺点:
1、点阵中的有效点必须是连续的,不连续的话算法就分成俩点阵了。
2、因为基于x坐标进行排序,只支持单行文字。多行可以自己改排序算法。
3、点阵高度只到11,这个是受大漠字库限制。
只在自己电脑上进行了测试,有问题可以反馈 。代码框架采用传统手敲代码和cv工艺,优化由不要钱的deepseek+豆包优化。
[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

    # &#128293; 补充:修复全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)


# &#128293; 优化:复用全局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"&#9989; 最终识别结果:{final_text}")

免费评分

参与人数 1热心值 +1 收起 理由
weidechan + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
li962905857 发表于 2026-5-22 14:02
虽然我看不懂 但是我支持你
3#
mmnn123 发表于 2026-5-22 15:37
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-5-23 07:25

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表