基于PaddleOCR的多视角集装箱箱号检测辨认

一、我的项目介绍

集装箱号是指装运进口货物集装箱的箱号,填写托运单时必填此项。标准箱号形成基本概念:采纳ISO6346(1995)规范

规范集装箱箱号由11位编码组成,如:CBHU 123456 7,包含三个局部:

  1. 第一局部由4位英文字母组成。前三位代码次要阐明箱主、经营人,第四位代码阐明集装箱的类型。列如CBHU 结尾的规范集装箱是表明箱主和经营人为中远集运
  2. 第二局部由6位数字组成。是箱体注册码,用于一个集装箱箱体持有的惟一标识
  3. 第三局部为校验码由前4位字母和6位数字通过校验规定运算失去,用于辨认在校验时是否产生谬误。即第11位编号

本教程基于PaddleOCR进行集装箱箱号检测辨认工作,应用大量数据别离训练检测、辨认模型,最初将他们串联在一起实现集装箱箱号检测辨认的工作

成果展现:

二、环境筹备

首先点击左侧套件抉择PaddleOCR 进行下载。

三、数据集介绍

本教程所应用的集装箱箱号数据集,该数据蕴含3003张分辨率为1920×1080的集装箱图像

1、PaddleOCR检测模型训练标注规定如下,两头用"\t"分隔:

" 图像文件名                    json.dumps编码的图像标注信息"ch4_test_images/img_61.jpg    [{"transcription": "MASA", "points": [[310, 104], [416, 141], [418, 216], [312, 179]]}, {...}]

其中json.dumps编码前的图像标注信息是蕴含多个字典的list,字典中的 points 示意文本框的四个点的坐标(x, y),从左上角的点开始顺时针排列。 transcription 示意以后文本框的文字,当其内容为“###”时,示意该文本框有效,在训练时会跳过。

2、PaddleOCR辨认模型训练标注规定如下,两头用"\t"分隔:

" 图像文件名                 图像标注信息 "train_data/rec/train/word_001.jpg   简略可依赖train_data/rec/train/word_002.jpg   用科技让简单的世界更简略

四、数据整顿

4.1 检测模型所需数据筹备

将数据集3000张图片按2:1划分成训练集和验证集,运行以下代码

from tqdm import tqdmfinename = "all_label.txt"f = open(finename)lines = f.readlines() t = open('det_train_label.txt','w')v = open('det_eval_label.txt','w')count = 0for line in tqdm(lines):    if count < 2000:        t.writelines(line)        count += 1    else:        v.writelines(line)f.close()t.close()v.close()

4.2 辨认模型所需数据筹备

咱们依据检测局部的正文,裁剪数据集尽可能只蕴含文字局部图片作为辨认的数据,运行以下代码

from PIL import Imageimport jsonfrom tqdm import tqdmimport osimport numpy as npimport cv2import mathfrom PIL import Image, ImageDrawclass Rotate(object):    def __init__(self, image: Image.Image, coordinate):        self.image = image.convert('RGB')        self.coordinate = coordinate        self.xy = [tuple(self.coordinate[k]) for k in ['left_top', 'right_top', 'right_bottom', 'left_bottom']]        self._mask = None        self.image.putalpha(self.mask)    @property    def mask(self):        if not self._mask:            mask = Image.new('L', self.image.size, 0)            draw = ImageDraw.Draw(mask, 'L')            draw.polygon(self.xy, fill=255)            self._mask = mask        return self._mask    def run(self):        image = self.rotation_angle()        box = image.getbbox()        return image.crop(box)    def rotation_angle(self):        x1, y1 = self.xy[0]        x2, y2 = self.xy[1]        angle = self.angle([x1, y1, x2, y2], [0, 0, 10, 0]) * -1        return self.image.rotate(angle, expand=True)    def angle(self, v1, v2):        dx1 = v1[2] - v1[0]        dy1 = v1[3] - v1[1]        dx2 = v2[2] - v2[0]        dy2 = v2[3] - v2[1]        angle1 = math.atan2(dy1, dx1)        angle1 = int(angle1 * 180 / math.pi)        angle2 = math.atan2(dy2, dx2)        angle2 = int(angle2 * 180 / math.pi)        if angle1 * angle2 >= 0:            included_angle = abs(angle1 - angle2)        else:            included_angle = abs(angle1) + abs(angle2)            if included_angle > 180:                included_angle = 360 - included_angle        return included_angledef image_cut_save(path, bbox, save_path):    """    :param path: 图片门路    :param left: 区块左上角地位的像素点离图片左边界的间隔    :param upper:区块左上角地位的像素点离图片上边界的间隔    :param right:区块右下角地位的像素点离图片左边界的间隔    :param lower:区块右下角地位的像素点离图片上边界的间隔    """    img_width  = 1920    img_height = 1080    img = Image.open(path)    coordinate = {'left_top': bbox[0], 'right_top': bbox[1], 'right_bottom': bbox[2], 'left_bottom': bbox[3]}    rotate = Rotate(img, coordinate)        left, upper = bbox[0]    right, lower = bbox[2]    if lower-upper > right-left:        rotate.run().convert('RGB').transpose(Image.ROTATE_90).save(save_path)    else:        rotate.run().convert('RGB').save(save_path)    return True#读取检测标注制作辨认数据集files = ["det_train_label.txt","det_eval_label.txt"]filetypes =["train","eval"]for index,filename in enumerate(files):    f = open(filename)    l = open('rec_'+filetypes[index]+'_label.txt','w')    if index == 0:        data_dir = "RecTrainData"    else:        data_dir = "RecEvalData"    if not os.path.exists(data_dir):        os.mkdir(data_dir)    lines = f.readlines()     for line in tqdm(lines):        image_name = line.split("\t")[0].split("/")[-1]        annos = json.loads(line.split("\t")[-1])        img_path = os.path.join("/home/aistudio/input0/images",image_name)        for i,anno in enumerate(annos):            data_path = os.path.join(data_dir,str(i)+"_"+image_name)            if image_cut_save(img_path,anno["points"],data_path):                l.writelines(str(i)+"_"+image_name+"\t"+anno["transcription"]+"\n")    l.close()    f.close()

五、试验

因为数据集比拟少,为了模型更好和更快的收敛,这里选用 PaddleOCR 中的 PP-OCRv3 模型进行检测和辨认。PP-OCRv3在PP-OCRv2的根底上,中文场景端到端Hmean指标相比于PP-OCRv2晋升5%, 英文数字模型端到端成果晋升11%。具体优化细节请参考PP-OCRv3技术报告。

5.1 检测模型

5.1.1 检测模型配置

PaddleOCR提供了许多检测模型,在门路PaddleOCR-2.6.0/configs/det下可找到模型及其配置文件。如咱们选用模型ch_PP-OCRv3_det_student.yml,其配置文件门路在:PaddleOCR-2.6.0/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml。应用前需对其进行必要的设置,如训练参数、数据集门路等。将局部要害配置展现如下:

#要害训练参数use_gpu: true #是否应用显卡epoch_num: 1200 #训练epoch个数save_model_dir: ./output/ch_PP-OCR_V3_det/ #模型保留门路save_epoch_step: 200 #每训练200epoch,保留一次模型eval_batch_step: [0, 100] #训练每迭代100次,进行一次验证pretrained_model: ./PaddleOCR-release2.5/pretrain_models/ch_PP-OCR_V3_det/best_accuracy.pdparams #预训练模型门路#训练集门路设置Train:  dataset:    name: SimpleDataSet    data_dir: /input0/images #图片文件夹门路    label_file_list:      - ./det_train_label.txt #标签门路

文件间接放在更目录里,自行替换即可 /home/aistudio/ch_PP-OCRv3_det_student.yml

5.1.2 模型微调

在notebook中运行如下命令对模型进行微调,其中 -c 传入的为配置好的模型文件门路

%run /home/aistudio/PaddleOCR-2.6.0/tools/train.py \    -c /home/aistudio/PaddleOCR-2.6.0/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml

应用默认超参数,模型ch_PP-OCRv3_det_student在训练集上训练100个epoch后,模型在验证集上的hmean达到:90.96%,尔后再无显著增长

[2023/03/21 15:57:09] ppocr INFO: best metric, hmean: 0.909551282051282, precision: 0.8977836411609498,recall: 0.921611681990265, fps: 20.347745459258228, best_epoch: 100

5.2 辨认模型

5.2.1 辨认模型配置

PaddleOCR也提供了许多辨认模型,在门路PaddleOCR-2.6.0/configs/rec下可找到模型及其配置文件。如咱们选用模型ch_PP-OCRv3_rec_distillation,其配置文件门路在:PaddleOCR-2.6.0/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml。应用前需对其进行必要的设置,如训练参数、数据集门路等。将局部要害配置展现如下:

#要害训练参数use_gpu: true #是否应用显卡epoch_num: 1200 #训练epoch个数save_model_dir: ./output/rec_ppocr_v3_distillation #模型保留门路save_epoch_step: 200 #每训练200epoch,保留一次模型eval_batch_step: [0, 100] #训练每迭代100次,进行一次验证pretrained_model: ./PaddleOCR-release-2.5/pretrain_models/PPOCRv3/best_accuracy.pdparams #预训练模型门路#训练集门路设置Train:  dataset:    name: SimpleDataSet    data_dir: ./RecTrainData/ #图片文件夹门路    label_file_list:      - ./rec_train_label.txt #标签门路            Eval:  dataset:    name: SimpleDataSet    data_dir: ./RecEvalData/    label_file_list:    - ./rec_eval_label.txt

文件间接放在更目录里,自行替换即可 /home/aistudio/ch_PP-OCRv3_rec_distillation.yml

5.2.2 模型微调

在notebook中运行如下命令对模型进行微调,其中 -c 传入的为配置好的模型文件门路

%run /home/aistudio/PaddleOCR-2.6.0/tools/train.py \    -c /home/aistudio/PaddleOCR-2.6.0/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml

应用默认超参数,模型ch_PP-OCRv3_rec_distillation在训练集上训练50个epoch后,模型在验证集上的精度达到:91.11%,尔后再无显著增长

[2023/03/21 20:04:28] ppocr INFO: best metric, acc: 0.9110600272522444, norm_edit_dis: 0.9427426548965615,Teacher_acc: 0.9040291998159589, Teacher_norm_edit_dis: 0.9405629345025616, fps: 246.029195787707, best_epoch: 50

六、后果展现

6.1 检测模型推理

在notebook中运行如下命令应用微调过的模型检测测试图片中的文字,其中:

  • Global.infer_img 为图片门路或图片文件夹门路,
  • Global.pretrained_model 为微调过的模型,
  • Global.save_res_path 为推理后果保留门路
%run /home/aistudio/PaddleOCR-2.6.0/tools/infer_det.py \    -c /home/aistudio/PaddleOCR-2.6.0/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \    -o Global.infer_img="/home/aistudio/input0/images" Global.pretrained_model="./output/ch_PP-OCR_V3_det/best_accuracy" Global.save_res_path="./output/det_infer_res/predicts.txt"

6.2 辨认模型推理

在notebook中运行如下命令应用微调过的模型检测测试图片中的文字,其中:

  • Global.infer_img 为图片门路或图片文件夹门路,
  • Global.pretrained_model 为微调过的模型,
  • Global.save_res_path 为推理后果保留门路
%run /home/aistudio/PaddleOCR-2.6.0/tools/infer_rec.py \    -c /home/aistudio/PaddleOCR-2.6.0/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml \    -o Global.infer_img="./RecEvalData/" Global.pretrained_model="./output/rec_ppocr_v3_distillation/best_accuracy" Global.save_res_path="./output/rec_infer_res/predicts.txt"    

局部后果展现:

./RecEvalData/0_1-122720001-OCR-AS-B01.jpg    {"Student": {"label": "EITU1786393", "score": 0.9737951755523682}, "Teacher": {"label": "EITU1786393", "score": 0.9882291555404663}}./RecEvalData/0_1-122720001-OCR-LB-C02.jpg    {"Student": {"label": "EITU1786393", "score": 0.9709678888320923}, "Teacher": {"label": "EITU1786393", "score": 0.9925146698951721}}./RecEvalData/0_1-122720001-OCR-RF-D01.jpg    {"Student": {"label": "EITU1786393", "score": 0.9985160231590271}, "Teacher": {"label": "EITU1786393", "score": 0.9967824816703796}}./RecEvalData/0_1-122728001-OCR-RF-D01.jpg    {"Student": {"label": "DFSU4119250", "score": 0.9663339257240295}, "Teacher": {"label": "DFSU4119250", "score": 0.9600133299827576}}./RecEvalData/0_1-122740001-OCR-AH-A01.jpg    {"Student": {"label": "MRKU4306585", "score": 0.9916775226593018}, "Teacher": {"label": "MRKU4306585", "score": 0.9929805994033813}}./RecEvalData/0_1-122749001-OCR-AH-A01.jpg    {"Student": {"label": "FCGU4996010", "score": 0.9195910096168518}, "Teacher": {"label": "FCGU4996010", "score": 0.9424482583999634}}./RecEvalData/0_1-122830001-OCR-AS-B01.jpg    {"Student": {"label": "MEDU4024195", "score": 0.9861812591552734}, "Teacher": {"label": "MEDU4024195", "score": 0.9718942642211914}}./RecEvalData/0_1-122843001-OCR-RF-D01.jpg    {"Student": {"label": "TGU864295", "score": 0.9045045375823975}, "Teacher": {"label": "TGU864395", "score": 0.8963061571121216}}

6.3 检测辨认模型串联推理

6.3.1 模型转换

在串联推理前首先须要将训练保留的模型转换成推理模型,别离执行如下检测命令即可。其中,-c传入要转换模型的配置文件门路,-o Global.pretrained_model为要被转换的模型文件,Global.save_inference_dir为转换失去推理模型的贮存门路

# 检测模型转换%run /home/aistudio/PaddleOCR-2.6.0/tools/export_model.py \-c /home/aistudio/PaddleOCR-2.6.0/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml  \-o Global.pretrained_model="./output/ch_PP-OCR_V3_det/best_accuracy" Global.save_inference_dir="./output/det_inference/"# 辨认模型转换%run /home/aistudio/PaddleOCR-2.6.0/tools/export_model.py \-c /home/aistudio/PaddleOCR-2.6.0/configs/rec/PP-OCRv3/ch_PP-OCRv3_rec_distillation.yml \-o Global.pretrained_model="./output/rec_ppocr_v3_distillation/best_accuracy" Global.save_inference_dir="./output/rec_inference/"

6.3.2 模型串联推理

转换结束后,PaddleOCR提供了检测和辨认模型的串联工具,能够将训练好的任一检测模型和任一辨认模型串联成两阶段的文本识别系统。输出图像通过文本检测、检测框改正、文本辨认、得分过滤四个次要阶段输入文本地位和辨认后果。执行代码如下,其中image_dir为单张图像或者图像汇合的门路,det_model_dir为检测inference模型的门路,rec_model_dir为辨认inference模型的门路。可视化辨认后果默认保留到 ./inference_results 文件夹外面

%run /home/aistudio/PaddleOCR-2.6.0/tools/infer/predict_system.py \--image_dir="OCRTest" \--det_model_dir="./output/det_inference/" \--rec_model_dir="./output/rec_inference/Student/"

后果展现:

1-122700001-OCR-LF-C01.jpg    [{"transcription": "TTEMU3108252", "points": [[1226, 133], [1322, 133], [1322, 883], [1226, 883]]}, {"transcription": "22G1", "points": [[1417, 214], [1479, 216], [1471, 463], [1409, 461]]}]1-122720001-OCR-AH-A01.jpg    [{"transcription": "ITU1786393", "points": [[225, 206], [918, 215], [917, 318], [224, 309]]}]1-122720001-OCR-AS-B01.jpg    [{"transcription": "EITU1786393", "points": [[919, 283], [1389, 296], [1387, 372], [917, 359]]}, {"transcription": "45G1", "points": [[1104, 399], [1288, 399], [1288, 486], [1104, 486]]}]1-122720001-OCR-LB-C02.jpg    [{"transcription": "TU1", "points": [[226, 10], [515, 6], [516, 97], [227, 102]]}, {"transcription": "45G1", "points": [[489, 114], [784, 104], [787, 204], [492, 213]]}]1-122720001-OCR-RF-D01.jpg    [{"transcription": "EITU1786393", "points": [[216, 38], [941, 27], [942, 125], [217, 135]]}, {"transcription": "45G1", "points": [[452, 137], [719, 133], [720, 218], [453, 223]]}]

以1-122720001-OCR-AS-B01.jpg测试样例进行展现:

多视角辨认后果为:EITU1786393

七.总结

本我的项目做了基于PaddleOCR的多视角集装箱箱号检测辨认,应用大量数据别离训练检测、辨认模型,最初将他们串联在一起实现集装箱箱号检测辨认的工作。其中集装箱号是指装运进口货物集装箱的箱号,填写托运单时必填此项。标准箱号形成基本概念:采纳ISO6346(1995)规范。

从后果上看,基于PaddleOCR的多视角集装箱箱号检测辨认获得了不错的成果,但也存在一些改良中央。

  • 数据集样本量和丰盛度不够
  • 训练不充沛,因为算力和工夫限度,自己就简略训练了100 epochs左右进行了。
  • 模型参数调优(目前默认参数)
    等等

源我的项目链接:https://aistudio.baidu.com/aistudio/projectdetail/5766320?contributionType=1

欢送关注fork 三连