Yolo11 + OCR 营业执照识别+信息抽取(预期后续改用其他ocr更简单,推理预计使用onnxruntim加速,分c++和python两种方式部署)

目录

一 数据集制作

1 labelimg的安装与使用

2 标注方式

3 数据集制作

二 模型训练 

三 使用Yolo11 + OCR 实现“营业执照”信息解析完整方案

1 cutLinesforcode.py

2 getBusinessLicenseContentPart.py

3 getPartWords.py

4 pdfTojpg.py

5 main.py


本项目可用于毕业设计参考实验营业执照分为横版竖版整体检测+识别效果如下所示:

说明:图片来源于网络,如有侵权,请联系作者删除。

系统:Ubuntu 20.04

需要的依赖:

  • pdf2image
  • pip install pdf2image -i https://pypi.tuna.tsinghua.edu.cn/simple
  • yolo11
  • pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple
  • pytesseract
  • pip install pytesseract -i https://pypi.tuna.tsinghua.edu.cn/simple

    sudo apt update
     
    sudo apt install tesseract-ocr
     
    # 在线安装中文字库
     
    sudo apt-get install tesseract-ocr-chi-sim

    一 数据集制作

    使用labelimg工具进行数据标注任务。

    1 labelimg的安装与使用

    安装方法: pip install labelimg
    使用方法如下:
    cd到labellmg所在路径

    python labellmg.py

    标注后生成的标记文件是xml文件。

    2 标注方式

    本项目的目标是解析出营业执照的统一社会信用代码、名称、类型、法定代表人、经营范围、注册资本、成立日期、营业期限和住所等信息。
    标注方式如下:

     

    你可以根据自己的需求去对应进行数据集的制作,类比即可。

    3 数据集制作

    原始数据集格式如下图所示:

  • Annotations 里面存放标签xml文件
  • JPEGImage 里面存放原始图片
  • labels 里面存放的是标签txt文件。这个文件夹里的文件是通过脚本xmI_txt.py生成的。
  • xmI_txt.py代码如下

    import xml.etree.ElementTree as ET
    import os
    import random
     
    # TODO 这里按照类别去修改
    classes = ['code', 'specialcode', 'name', 'type', 'representative', 'range', 'registered', 'date', 'limit', 'address']
    # TODO 这里按照实际XML文件夹路径去修改
    xml_filepath = 'data/Annotations/'
    # TODO 这里按照实际想要保存结果txt文件夹的路径去修改
    labels_savepath = 'data/labels/'
    abs_path = os.getcwd()
     
     
    def convert(size, box):
        dw = 1. / (size[0])
        dh = 1. / (size[1])
        x = (box[0] + box[1]) / 2.0 - 1
        y = (box[2] + box[3]) / 2.0 - 1
        w = box[1] - box[0]
        h = box[3] - box[2]
        x = x * dw
        w = w * dw
        y = y * dh
        h = h * dh
        return x, y, w, h
     
     
    def convert_annotation(image_id):
        in_file = open(xml_filepath + '%s.xml' % (image_id), encoding='UTF-8')
        out_file = open(labels_savepath + '%s.txt' % (image_id), 'w')
        tree = ET.parse(in_file)
        root = tree.getroot()
        size = root.find('size')
        w = int(size.find('width').text)
        h = int(size.find('height').text)
        for obj in root.iter('object'):
            difficult = obj.find('difficult').text
            cls = obj.find('name').text
            if cls not in classes or int(difficult) == 1:
                continue
            cls_id = classes.index(cls)
            xmlbox = obj.find('bndbox')
            b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
                 float(xmlbox.find('ymax').text))
            b1, b2, b3, b4 = b
            # 标注越界修正
            if b2 > w:
                b2 = w
            if b4 > h:
                b4 = h
            b = (b1, b2, b3, b4)
            bb = convert((w, h), b)
            out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
     
     
    def run():
        total_xml = os.listdir(xml_filepath)
        num = len(total_xml)
        names = []
        for xml in total_xml:
            names.append(xml[:-4])
        for name in names:
            convert_annotation(name)
        pass
     
     
    if __name__ == '__main__':
        run()
        pass

    然后,根据JPEGlmage 文件夹和labels文件夹通过脚本deal_dataset.py将数据集划分为如下结构。

    deal_dataset.py 代码如下:

    import os
    import random
    import shutil
     
    # 原数据集目录
    root_dir = 'data/'
    # 划分比例
    train_ratio = 0.8
    valid_ratio = 0.1
    test_ratio = 0.1
     
    # 设置随机种子
    random.seed(42)
     
    # TODo 这里按照实际数据集路径去修改
    split_dir = 'data_new/'
    os.makedirs(os.path.join(split_dir, 'train/images'), exist_ok=True)
    os.makedirs(os.path.join(split_dir, 'train/labels'), exist_ok=True)
    os.makedirs(os.path.join(split_dir, 'valid/images'), exist_ok=True)
    os.makedirs(os.path.join(split_dir, 'valid/labels'), exist_ok=True)
    os.makedirs(os.path.join(split_dir, 'test/images'), exist_ok=True)
    os.makedirs(os.path.join(split_dir, 'test/labels'), exist_ok=True)
     
    # TODo 这里按照实际数据集路径去修改
    imgpath = "JPEGImage"
    labelpath = "labels"
    image_files = os.listdir(os.path.join(root_dir, imgpath))
    image_files.sort(key=lambda x: int(x.split('.')[0]))
    print(image_files)
    label_files = os.listdir(os.path.join(root_dir, labelpath))
    label_files.sort(key=lambda x: int(x.split('.')[0]))
    print(label_files)
    # 随机打乱文件列表
    combined_files = list(zip(image_files, label_files))
    random.shuffle(combined_files)
    image_files_shuffled, label_files_shuffled = zip(*combined_files)
    print(image_files_shuffled)
    print(label_files_shuffled)
    # 根据比例计算划分的边界索引
    train_bound = int(train_ratio * len(image_files_shuffle

    作者:九不多

    物联沃分享整理
    物联沃-IOTWORD物联网 » Yolo11 + OCR 营业执照识别+信息抽取(预期后续改用其他ocr更简单,推理预计使用onnxruntim加速,分c++和python两种方式部署)

    发表回复