印刷字体识别系统

在线体验各类最新模型,更有模型 免费Token 额度领取!
立即体验
简介: 一个基于Python的印刷字体识别系统,遵循 GNU_GPL_v3 许可,具备字体倾斜校正、行与字符分割及字符识别功能。采用HOG算法训练SVM模型,使用Chars74K数据集。系统包含简单UI,支持动态加载和结果展示。核心算法包括自适应扩展+连通域辅助的行分割,以及垂直投影+连通域+极小值法细分粘连字符的字符分割。项目文件结构清晰,涵盖图像处理、模型训练与加载等功能模块。

印刷字体识别系统

*本项目遵循 GNU_GPL_v3 许可

简介

使用 Python 编写,带简单 UI。
可实现字体倾斜校正、行和字符分割、字符识别。

项目地址:https://github.com/kjx52/PFRS

倾斜校正使用传统的投影法。
行分割采用 自适应扩展+连通域辅助+智能 padding,字符分割采用 垂直投影+连通域+极小值法细分粘连字符。
字体识别使用 HOG 算法,公开 Chars74K 数据集训练。该数据集可在这里找到。
技术细节描述详见第四节。

还有一点,这个系统虽然对手写体具有一定的区分能力,但大部分情况下还是差强人意。
改进方面可以试一下使用torchvision的 datasets 手写数据集来训练。

from torchvision import datasets
train = datasets.EMNIST(root='data', split='letters', train=True, download=True)

使用方法

本项目集成性很高,使用简单。
不幸的是本仓库永远没有还没有发布版。

  1. 下载测试数据集和本仓库
  2. 将数据集放到本仓库目录下改为EnglishFnt.tgz
  3. 运行
    pip install -r requirements.txt   # 下载软件包
    python main.py                    # 执行
    

项目内容

文件结构树:

Printing_font_recognition_system/
│  character_recognition.py
│  config.py
│  dataset_loader.py
│  image_processing.py
│  main.py
│  requirements.txt
│  test_system.py
│  ui.py
│
├─screenshot/
└─templates/

其中:

  • main.py 是系统的集成启动器,负责所有的检查和任务执行,包括加载训练数据、训练和加载模型、启动UI界面等。启动器的下一步改进可能包括加入模型切换功能。
  • ui.py 是配套的一个简单的图形化界面,包括控制面板和结果展示等,该UI实现了动态加载和总控。一堆警告,但它跑起来了。下一步或将加入 debug 调试功能。
  • image_processing.py 图形处理脚本,包括倾斜校正以及行、字符分割等功能。
  • character_recognition.py 涉及到支持向量机(SVM)模型的训练和加载,用 HOG 特征提取算法识别字符。
  • dataset_loader.py 用于解压和加载 Chars74K 训练数据集。
  • config.py 包括该系统的配置参数,如模型存储路径和训练数据路径等:
    # config.py
    MODEL_PATH = 'models/svm_classifier.pkl'
    MODEL_DIR = 'models'
    IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png']
    DATASET_DIR = 'datasets'
    CHARS74K_ZIP = './EnglishFnt.tgz'
    TEMP_DIR = 'templates'
    
  • requirements.txt,该系统所需的软件包,请确保其全部安装了。

一些算法实现

分割

预处理对图片进行灰度化、二值化和去噪操作。
行分割最初采用水平投影来实现,但在不同字体下会产生很多问题,如由于“j”和“g”等下半部分超出其他字符,故会被分到新行中。现在我们使用 自适应扩展+连通域辅助+智能 padding 的方法来解决这一问题。

# 其他代码...

#合并有“尾巴”的行
merged_ranges = []
i = 0
while i < len(line_ranges):
    s, e = line_ranges[i]
    line_height = e - s
    # padding为行高的20%,最小2像素
    padding = max(2, int(line_height * 0.2))
    e_ext = min(processed.shape[0], e + padding)
    # 检查扩展区是否有黑色像素
    ext_region = processed[e:e_ext, :]
    has_tail = np.sum(ext_region > 0) > 0
    # 如果扩展区有内容且与下一行重叠,合并
    if has_tail and i + 1 < len(line_ranges):
        next_s, next_e = line_ranges[i+1]
        if e_ext > next_s:
            merged_ranges.append((s, next_e))
            i += 2
            continue
        # 如果扩展区无内容,回滚到未扩展
        merged_ranges.append((s, e_ext if has_tail else e))
        i += 1

# 其他代码...

上述代码是智能 padding 的部分,在完成基础分割后我们会将该行向下扩展 padding 的距离,用来检测是否有遗漏,若没有则回滚。padding 高度为行高的 20%,最小为 2 像素。

对于字符分割,单独使用传统垂直投影法在针对粗体字符的分割部分可能会出现字符粘连问题,故现在使用 垂直投影+连通域+极小值法细分粘连字符 进行缓解。

# 其他代码...

for start, end in optimized_ranges:
    # 粘连字符细分
    w = end - start
    char_img = line_img[:, start:end]
    h = char_img.shape[0]
    # 如果宽度过大,尝试在该区域内寻找极小值分割
    if w > h * 1.2:
        # 在该区域内做二次垂直投影
        sub_processed = self.preprocess_image(char_img)
        sub_proj = np.sum(sub_processed, axis=0)
        min_indices = [
            k
            for k in range(1, len(sub_proj) - 1)
            if sub_proj[k] < sub_proj[k - 1]
            and sub_proj[k] < sub_proj[k + 1]
            and sub_proj[k] < threshold
        ]
        # 根据极小值点分割
        last = 0
        for idx in min_indices + [w]:
            if idx - last > 3:
                sub_char = char_img[:, last:idx]
                if sub_char.shape[1] > 3:
                    char_images.append(sub_char)
            last = idx
    elif 3 < w < h * 3 and h > 5:
        char_images.append(char_img)
    cv2.rectangle(line_img_copy, (start, 0), (end, line_img.shape[0]), (0, 0, 255), 1)

# 其他代码...

需要注意的是,即使是使用了连通域和极小值法,在面对某些紧凑字体时,该方法依然会失效。

识别

字符识别部分包含两个主要函数。
preprocess_char_img 函数负责将训练样本统一为白底黑字,居中填充到32x32。
train_svm_classifier 被设计为模型训练函数,它包括

  1. HOG特征的提取和标准化
  2. PCA降维
  3. 训练模型并保存

具体实现:

# 其他代码...

def train_svm_classifier(self, samples, labels):
    """使用公开数据集训练SVM分类器"""
    print("开始训练SVM分类器...")

    # 提取HOG特征
    features = []
    for img in tqdm(samples):
        pre_img = self.preprocess_char_img(img)
        fd = hog(pre_img, orientations=9, pixels_per_cell=(8, 8),
        cells_per_block=(2, 2), visualize=False)
        features.append(fd)

    x = np.array(features)
    y = np.array(labels)

    # 特征标准化
    self.scaler = StandardScaler()
    x_scaled = self.scaler.fit_transform(x)

    # PCA降维
    self.pca = PCA(n_components=0.95)  # 保留95%的方差
    x_pca = self.pca.fit_transform(x_scaled)

    # 训练SVM
    self.svm_model = SVC(kernel='rbf', C=10, gamma=0.001, probability=True)
    self.svm_model.fit(x_pca, y)

    print("完成,已保存到", MODEL_PATH)

    # 保存模型
    joblib.dump({
   
        'model': self.svm_model,
        'scaler': self.scaler,
        'pca': self.pca
    }, MODEL_PATH)

# 其他代码...

该模型训练速度快,方便部署和使用。

后记

本项目遵循 GNU_GPL_v3 许可

该系统还有诸多问题亟需解决。Such as the damn UI.
不过作为课设应该是合格了。

Jessarin
2025/06/12

目录
相关文章
|
开发工具 git
如何在vscode编辑器中实时查看代码git记录(被谁修改、自己什么时候修改)
如何在vscode编辑器中实时查看代码git记录(被谁修改、自己什么时候修改)
8387 0
如何在vscode编辑器中实时查看代码git记录(被谁修改、自己什么时候修改)
|
11月前
|
运维 监控 安全
计算机网络及其安全组件纲要
本文主要介绍了 “计算机网络及常见组件” 的基本概念,涵盖网卡、IP、MAC、OSI模型、路由器、交换机、防火墙、WAF、IDS、IPS、域名、HTTP、HTTPS、网络拓扑等内容。
480 0
|
11月前
|
运维 监控 NoSQL
分布式不是“分布痛”吗?说说那些年我踩过的运维坑和总结的血泪经验
分布式不是“分布痛”吗?说说那些年我踩过的运维坑和总结的血泪经验
298 0
|
存储 人工智能 PyTorch
【AI系统】张量并行
在大模型训练中,单个设备难以满足需求,模型并行技术应运而生。其中,张量并行(Tensor Parallelism, TP)将模型内部的参数和计算任务拆分到不同设备上,特别适用于大规模模型。本文介绍了张量并行的基本概念、实现方法及其在矩阵乘法、Transformer、Embedding和Cross Entropy Loss等场景中的应用,以及通过PyTorch DeviceMesh实现TP的具体步骤。
1744 11
【AI系统】张量并行
|
机器学习/深度学习 文字识别 算法
百度飞桨(PaddlePaddle) - PaddleHub OCR 文字识别简单使用
百度飞桨(PaddlePaddle) - PaddleHub OCR 文字识别简单使用
1315 0
|
自然语言处理 算法 搜索推荐
分词算法的基本原理及应用
分词算法的基本原理及应用
|
存储 UED
从零开始构建个人网站:初学者指南
【5月更文挑战第9天】本文是初学者构建个人网站的指南,包括明确目标、选择域名和主机、挑选网站建设工具(如WordPress、Wix、Squarespace)、设计网站结构和布局、创建内容、优化测试以及推广维护。按照这些步骤,新手也能轻松建立自己的个人网站。记得在过程中不断学习和改进,祝你建站成功!
2177 1
|
API 计算机视觉
【OpenCV】形态学滤波(2):开运算、形态学梯度、顶帽、黑帽
【OpenCV】形态学滤波(2):开运算、形态学梯度、顶帽、黑帽
485 1
|
监控 Java 测试技术
持续集成与持续部署:原理、实践与代码示例
持续集成与持续部署:原理、实践与代码示例
415 3