使用百度 PaddleOCR对身份证识别的简单处理

news2025/1/11 18:49:04

一:引言

     本文才用百度的PaddleOCR对身份证进行识别的处理,由于直接使用并未进行对跟多数据集进行训练,当前的效果是对非少数民族的身份证识别率可以达到85%以上,同时要求身份证图片是正面且相对清晰。否则效果不理想,本文主要介绍PaddleOCR是什么、安装总流程、PaddleOCR的简单使用、和对身份证识别结果的处理。经过处理后,在保证正面的情况且相对清晰的情况下身份证对非少数民族的识别可以达95%以上,对除了朝鲜族少数民族身份证外其他的也可达90%以上.

.PaddleOCR是什么?

看看官方怎么说:PaddleOCR/README_ch.md at release/2.6 · PaddlePaddle/PaddleOCR · GitHub

2.1:简介

          PaddleOCR是百度深度学习框架PaddlePaddle开源的OCR项目,旨在打造一套丰富、领先、且实用的OCR工具库,助力使用者训练出更好的模型,并应用落地。PaddleOCR包含丰富的文本检测、文本识别以及端到端算法。

 2.2:PaddleOCR特性:

  • 超轻量级中文OCR模型,总模型仅8.6M
  • 单模型支持中英文数字组合识别、竖排文本识别、长文本识别
  • 检测模型DB(4.1M)+识别模型CRNN(4.5M)
  • 实用通用中文OCR模型
  • 多种预测推理部署方案,包括服务部署和端侧部署
  • 多种文本检测训练算法,EAST、DB、SAST
  • 多种文本识别训练算法,Rosetta、CRNN、STAR-Net、RARE、SRN
  • 可运行于Linux、Windows、MacOS等多种系统

三:安装流程

3.1:paddlepaddle环境的安装

      官方安装链接:开始使用_飞桨-源于产业实践的开源深度学习平台

具体看链接的教程,其中有 CPU 版的 PaddlePaddle和 GPU 版的 PaddlePaddle需要注意

3.1.1:CPU 版、GPU 版的区别

         PaddlePaddle CPU 版本是指使用 CPU 进行推理和训练的版本。它可以在不需要 GPU 的情况下运行,对于没有 GPU 设备或者对成本要求较高的用户来说非常有用。

        在 CPU 版本中,模型的训练和推理速度比 GPU 版本慢,但是仍然可以解决一些简单的问题。另外,在开发阶段,CPU 版本也可以帮助用户验证模型的功能和效果,以便在之后在 GPU 上进行更深入的训练。

        因此,PaddlePaddle CPU 版本可以帮助用户在不需要 GPU 的情况下进行模型开发和评估,从而降低了开发成本。

3.1.2:cuda、cudnn安装可以参考

tensorflow【cpu/gpu、cuda、cudnn】全网最详细安装、常用python镜像源、tensorflow 深度学习强化学习教学_汀、的博客-CSDN博客_tensorflow深度学习

手把手教你 win10 安装Paddlepaddle-GPU_AI小鸭学院的博客-CSDN博客


3.2:安装PaddleOCR whl包

直接用以下命令下载速度贼快:

pip install --index-url https://pypi.douban.com/simple paddleocr==2.6.1.3   

2.6.1.3代表要下载的版本,不写下载最新版本

如果下载遇到有些库下载超时,可才用以下命令单独下载

 pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple      

四:PaddleOCR的使用

4.1:基本使用方法

from paddleocr import PaddleOCR

# 识别身份证
def findIdcardResult():
    # 定义图片路径
    img_path = r'C:\Users\Jewel\Desktop\身份证\蒙文.png'
    

    #加载预训练的模型

    # Paddleocr目前支持的多语言语种可以通过修改lang参数进行切换
    # 例如`ch`, `en`, `fr`, `german`, `korean`, `japan`
    # 这里 use_angle_cls=False 为不使用自定义训练集
    ocr = PaddleOCR(use_angle_cls=False , lang="ch")

    # use_angle_cls=True使用训练模型,模型放在models目录下
    # ocr = PaddleOCR(use_angle_cls=True,lang="ch",
    #                 rec_model_dir='../models/ch_PP-OCRv3_rec_slim_infer/',
    #                 cls_model_dir='../models/ch_ppocr_mobile_v2.0_cls_slim_infer/',
    #                 det_model_dir='../models/ch_PP-OCRv3_det_slim_infer/')

    # 识别图片中的文字
    result = ocr.ocr(img_path, cls=True)
    print(result)
  

版本说明 paddleocr默认使用PP-OCRv3模型(--ocr_version PP-OCRv3),如需使用其他版本可通过设置参数--ocr_version,具体版本说明如下:

版本名称版本说明
PP-OCRv3支持中、英文检测和识别,方向分类器,支持多语种识别
PP-OCRv2支持中英文的检测和识别,方向分类器,多语言暂未更新
PP-OCR支持中、英文检测和识别,方向分类器,支持多语种识别

 paddleocr 总共需要三个模型,检测模型(det模型)、方向分类器(cls模型)、识别模型(rec模型)

如需新增自己训练的模型,可以在paddleocr中增加模型链接和字段,重新编译即可。

4.2:使用训练好的模型

举个例子,从官网飞桨AI Studio - 人工智能学习与实训社区下载一个库

  比如【PP-OCRv3】模型,下载到本地之后分别进行解压,创建一个models文件夹,把下载好的模型文件解压到该models文件夹中,并将models文件夹放入到PaddleOCR根目录下,如下所示:

 # use_angle_cls=True使用训练模型,模型放在models目录下
 ocr = PaddleOCR(use_angle_cls=True,lang="ch",
                     rec_model_dir='../models/ch_PP-OCRv3_rec_slim_infer/',
                    cls_model_dir='../models/ch_ppocr_mobile_v2.0_cls_slim_infer/',
                     det_model_dir='../models/ch_PP-OCRv3_det_slim_infer/')

ocr的模型通常已经在足够数据量的数据集上训练过,各类模型大致关系为:

  • 普通训练模型:大多数情况指没有经过太多训练的模型,适合在你自己有大量数据的情况下进行训练
  • 预训练模型:由官方已经训练过的模型,但可以供用户使用新的数据进行 finetune,适合在你的数据量不太多的情况下进行
  • 推理模型:官方已经调整好,可以直接用来做 ocr 的识别任务的模型,不适合于重新训练

4.3:身份证识别

from paddleocr import PaddleOCR
from common import IdCardStraight


# 识别身份证
def findIdcardResult(img_path):
    # 定义文件路径
    img_path = r'C:\Users\Jewel\Desktop\身份证\蒙文.png'
    # 初始化ocr模型和后处理模型
    ocr = PaddleOCR(use_angle_cls=False, lang="ch")
    # 获取模型检测结果
    result = ocr.ocr(img_path, cls=True)
    print(result)
    # 将检测到的文字放到一个列表中
    # txtArr = [line[1][0] for line in result[0]]
    txtArr = []
    for line in result[0]:
        txt = line[1][0]
        # 发现朝鲜文、彝文的身份证
        if (("姓" in txt and "性" in txt and "住" in txt) or ("名" in txt and "别" in txt and "生" in txt)) and line[1][1] < 0.75:
            continue
        else:
            txtArr.append(txt)

    print(txtArr)
    postprocessing = IdCardStraight(txtArr)
    # # 将结果送入到后处理模型中
    id_result = postprocessing.run()
    print(id_result)
    return id_result

对识别处理的数据进行处理 


import re
import json
import string


def verifyByIDCard(idcard):
    """
    验证身份证号码是否有效
    """
    sz = len(idcard)
    if sz != 18:
        return False

    weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
    validate = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
    sum = 0
    for i in range(len(weight)):
        sum += weight[i] * int(idcard[i])
    m = sum % 11
    return validate[m] == idcard[sz - 1]


class IdCardStraight:
    """
    身份证OCR返回结果,正常的身份证大概率识别没有什么问题,少数名族身份证,壮文、藏文、蒙文基本识别也没问题
    """
    nation_list = ["汉", "蒙古", "回", "藏", "维吾尔", "苗", "彝", "壮", "布依", "朝鲜", "满", "侗", "瑶", "白",
                   "土家", "哈尼", "哈萨克", "傣", "黎", "傈僳", "佤", "畲", "高山", "拉祜", "水", "东乡", "纳西",
                   "景颇", "柯尔克孜", "土", "达斡尔", "仫佬", "羌", "布朗", "撒拉", "毛难", "仡佬", "锡伯", "阿昌",
                   "普米", "塔吉克", "怒", "乌孜别克", "俄罗斯", "鄂温克", "崩龙", "保安", "裕固", "京", "塔塔尔",
                   "独龙", "鄂伦春", "赫哲", "门巴", "珞巴", "基诺"]

    def __init__(self, result):
        self.result = [
            i.replace(" ", "").translate(str.maketrans("", "", string.punctuation))
            for i in result
        ]
        print(self.result)
        self.out = {"result": {}}
        self.res = self.out["result"]
        self.res["name"] = ""
        self.res["idNumber"] = ""
        self.res["address"] = ""
        self.res["gender"] = ""
        self.res["nationality"] = ""

    def birth_no(self):
        """
        身份证号码
        """
        for i in range(len(self.result)):
            txt = self.result[i]

            # 身份证号码
            if "X" in txt or "x" in txt:
                res = re.findall("\d*[X|x]", txt)
            else:
                res = re.findall("\d{18}", txt)

            if len(res) > 0:
                # 验证身份证号码是否有效  因为像藏文会出现刷出的身份证有超过18位数字的情况
                if verifyByIDCard(res[0]):
                    self.res["idNumber"] = res[0]
                    self.res["gender"] = "男" if int(res[0][16]) % 2 else "女"
                    break

    def full_name(self):
        """
        身份证姓名
        """
        # 如果姓名后面有跟文字,则取名后面的字段,如果"名"不存在,那肯定也就没有"姓名",所以在没有"名"的情况下只要判断是否有"姓"就可以了
        # 名字限制是2位以上,所以至少这个集合得3位数,才进行"名"或"姓"的判断
        for i in range(len(self.result)):
            txt = self.result[i]
            if ("姓名" in txt or "名" in txt or "姓" in txt) and len(txt) > 3:
                resM = re.findall("名[\u4e00-\u9fa5]+", txt)
                resX = re.findall("姓[\u4e00-\u9fa5]+", txt)
                if len(resM) > 0:
                    name = resM[0].split("名")[-1]
                elif len(resX) > 0:
                    name = resX[0].split("姓")[-1]
                if len(name) > 1:
                    self.res["name"] = name
                    self.result[i] = "temp"  # 避免身份证姓名对地址造成干扰
                    return

        # 如果姓名或名后面没有跟文字,但是有名 或姓名这个字段出现过的,去后面的集合为名字
        # 如果取的一个几个只有一个字,则接着取后面的集合,一般最多取2个集合就够了
        # 由于像新疆文、彝文这种类型的身份证,识别处理的集合值可能是英文,要进行去除
        indexName = -1
        for i in range(len(self.result)):
            txt = self.result[i]
            if "姓名" in txt or "名" in txt:
                indexName = i
                break
        if indexName == -1:
            for i in range(len(self.result)):
                txt = self.result[i]
                if "姓" in txt:
                    indexName = i
                    break
        if indexName == -1:
            return
        resName = self.result[indexName + 1]
        if len(resName) < 2:
            resName = resName + self.result[indexName + 2]
            self.res["name"] = resName
            self.result[indexName + 2] = "temp"  # 避免身份证姓名对地址造成干扰
        else:
            self.res["name"] = resName
            self.result[indexName + 1] = "temp"  # 避免身份证姓名对地址造成干扰

    def sex(self):
        """
        性别女民族汉
        """
        for i in range(len(self.result)):
            txt = self.result[i]
            if "男" in txt:
                self.res["gender"] = "男"

            elif "女" in txt:
                self.res["gender"] = "女"

    def national(self):
        # 性别女民族汉
        # 先判断是否有"民族xx"或"族xx"或"民xx"这种类型的数据,有的话获取xx的数据,然后在56个名族的字典里判断是否包含某个民族,包含则取对应的民族
        for i in range(len(self.result)):
            txt = self.result[i]
            if ("民族" in txt or "族" in txt or "民" in txt) and len(txt) > 2:
                resZ = re.findall("族[\u4e00-\u9fa5]+", txt)
                resM = re.findall("民[\u4e00-\u9fa5]+", txt)
                if len(resZ) > 0:
                    nationOcr = resZ[0].split("族")[-1]
                elif len(resM) > 0:
                    nationOcr = resM[0].split("民")[-1]

                for nation in self.nation_list:
                    if nation in nationOcr:
                        self.res["nationality"] = nation
                        self.result[i] = "nation"  # 避免民族对特殊情况下名字造成干扰
                        return
        # 如果 "民族" 或 "族" 和对应的民族是分开的,则记录对应对应的位置,取后一位的字符,同样去字典里判断
        indexNational = -1
        for i in range(len(self.result)):
            txt = self.result[i]
            if "族" in txt:
                indexNational = i
                break
        # 如果没有"民族"或 "族" ,则去判断是否含有"民",有则记录对应的位置,取后一位的字符,同样去字典里判断
        if indexNational == -1:
            for i in range(len(self.result)):
                txt = self.result[i]
                if "民" in txt:
                    indexNational = i
                    break
        if indexNational == -1:
            return
        national = self.result[indexNational + 1]
        for nation in self.nation_list:
            if nation in national:
                self.res["nationality"] = nation
                self.result[indexNational + 1] = "nation"  # 避免民族对特殊情况下名字造成干扰
                break

    def address(self):
        """
        地址
        """
        addString = []
        for i in range(len(self.result)):
            txt = self.result[i]
            # 这步的操作是去除下”公民身份号码“里的号对地址的干扰
            txt = txt.replace("号码", "")
            if "公民" in txt:
                txt = "temp"
            # 身份证地址    盟,旗,苏木,嘎查  蒙语行政区划  ‘大学’有些大学集体户的地址会写某某大学

            if (
                    "住址" in txt
                    or "址" in txt
                    or "省" in txt
                    or "市" in txt
                    or "县" in txt
                    or "街" in txt
                    or "乡" in txt
                    or "村" in txt
                    or "镇" in txt
                    or "区" in txt
                    or "城" in txt
                    or "室" in txt
                    or "组" in txt
                    or "号" in txt
                    or "栋" in txt
                    or "巷" in txt
                    or "盟" in txt
                    or "旗" in txt
                    or "苏木" in txt
                    or "嘎查" in txt
                    or "大学" in txt
            ):
                # 默认地址至少是在集合的第2位以后才会出现,避免经过上面的名字识别判断未能识别出名字,
                # 且名字含有以上的这些关键字照成被误以为是地址,默认地址的第一行的文字长度要大于7,只有取到了第一行的地址,才会继续往下取地址
                if i < 2 or len(addString) < 1 and len(txt) < 7:
                    continue
                    # 如果字段中含有"住址"、"省"、"址"则认为是地址的第一行,同时通过"址"
                # 这个字分割字符串
                if "住址" in txt or "省" in txt or "址" in txt:
                    # 通过"址"这个字分割字符串,取集合中的倒数第一个元素
                    addString.insert(0, txt.split("址")[-1])
                else:
                    addString.append(txt)
                self.result[i] = "temp"

        if len(addString) > 0:
            self.res["address"] = "".join(addString)
        else:
            self.res["address"] = ""

    def predict_name(self):
        """
        如果PaddleOCR返回的不是姓名xx连着的,则需要去猜测这个姓名,此处需要改进
        """
        for i in range(len(self.result)):
            txt = self.result[i]
            if self.res["name"] == "":
                if 1 < len(txt) < 5:
                    if (
                            "性别" not in txt
                            and "姓名" not in txt
                            and "民族" not in txt
                            and "住址" not in txt
                            and "出生" not in txt
                            and "号码" not in txt
                            and "身份" not in txt
                            and "nation" not in txt
                    ):
                        result = re.findall("[\u4e00-\u9fa5]{2,4}", txt)
                        if len(result) > 0:
                            self.res["name"] = result[0]
                            break
        for i in range(len(self.result)):
            txt = self.result[i]

    def run(self):
        self.full_name()
        self.sex()
        self.national()
        self.birth_no()
        self.address()
        self.predict_name()
        return json.dumps(self.out, ensure_ascii=False)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/561372.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于java的时间管理系统的设计与实现

背景 要设计一个时间管理系统&#xff0c;通过这个系统能够满足时间管理的管理功能。系统的主要功能包括首页&#xff0c;个人中心&#xff0c;系统公告管理&#xff0c;用户管理&#xff0c;时间分类管理&#xff0c;事件数据管理&#xff0c;目标数据管理&#xff0c;用户日…

【系统软件】源码编译安装ZLIB——Could NOT find ZLIB(missing:ZLIB_LIBRARY ZLIB_INCLUDE_DIR

【系统软件】源码编译安装ZLIB——Could NOT find ZLIB(missing:ZLIB_LIBRARY ZLIB_INCLUDE_DIR 前言一、简介二、源码下载三、解压、构建四、编译五、安装六、安装成功后如下图七、如何使用zlib中的include 前言 今天原本打算源码编译安装protobuf&#xff0c;但是在构建项目…

图神经网络GNN GCN AlphaFold2 虚拟药物筛选和新药设计

文章目录 图神经网络1. Geometric Deep LearningRepresentation learning 表征学习机器学习的数据类型&#xff1a;序列、网格、图引出GNN 2. Graph Neural NetworksMachine Learning Lifecyclelearning graph is hardFeature Learning in GraphsWays to Analyze NetworksA Nai…

chatgpt赋能Python-python_plot标题

Python Plot 标题&#xff1a;如何让你的数据可视化更加引人注目 Python是数据科学和可视化领域中最受欢迎的编程语言之一。Python的可视化库让数据可视化变得非常容易、灵活和美观。 在创建一个数据可视化时&#xff0c;最重要的是让图表或图形作品的标题尽可能引人注目。这…

chatgpt赋能Python-python_plt_标题

Python plt&#xff1a;用Python创建出色的可视化图表 Python是一种广泛使用的高级编程语言&#xff0c;它被用于各种不同的领域&#xff0c;包括Web开发、数据科学、人工智能和计算机视觉等。Python拥有一个强大的生态系统&#xff0c;其中包括了大量的第三方库和工具&#x…

chatgpt赋能Python-python_property描述符

Python Property描述符&#xff1a;什么是Property&#xff1f; 介绍 在Python中&#xff0c;属性是一种非常强大的方式&#xff0c;在代码中隐藏数据并将其保护起来。我们可以使用属性来让代码更可读&#xff0c;更易于维护&#xff0c;并降低代码中的错误风险。 Python中&a…

一、服务端渲染技术NUXT

文章目录 一、服务端渲染技术NUXT1.1 什么是服务端渲染1.2 什么是NUXT 2、NUXT环境初始化2.1 下载压缩包2.2解压2.3修改package.json2.4修改nuxt.config.js2.5终端中进入项目目录安装依赖2.6 引入element-ui2.7 测试运行2.8 NUXT目录结构 3、封装axios3.1 安装axios3.2 封装axi…

抖音矩阵系统开发分析(附代码部分)

简介 本文档旨在介绍抖音SEO源码开发相关内容&#xff0c;包括技术架构、关键模块、实现原理等方面的内容。 技术架构 抖音SEO源码采用的是分布式架构。整个系统可以分为以下几个模块&#xff1a; 数据抓取模块&#xff1a;负责从抖音服务器抓取数据&#xff0c;并进行去重和…

一个公司,一个机器视觉工程师

​一个公司,一个机器视觉工程师。 大家觉得这种公司,这种情况可能很难,很尴尬。 其实一个公司,一个机器视觉工程师,公司业务上是有需求的,多数选择有经验的机器视觉工程师,我遇到的视觉人机器视觉粉丝里面还是比较多的。这样子的公司大多数是选择有经验的机器视觉工程师…

【22-23春】AI作业10-经典卷积网络

1.LeNet & MNIST LeNet是一种神经网络的模型&#xff0c;用于图像识别和分类。他包含 3 个卷积层&#xff0c;2 个池化层&#xff0c;1 个全连接层。其中所有卷积层的所有卷积核都为 5x5&#xff0c;步长 strid1&#xff0c;池化方法都为全局 pooling&#xff0c;激活函数…

一元函数的凹性concavity以及二阶导数

凹性&#xff08;concavity&#xff09;与函数导数的变化率有关。一个函数f是上凹(即抛物线方向开口向上)&#xff0c;其导数f是增函数&#xff0c;也意味着f的导数&#xff08;即f&#xff09;是正数&#xff1b;类似的一个函数f是下凹(即抛物线方向开口向下)&#xff0c;其导…

chatgpt赋能Python-python_plot_标题

Python Plot: 如何更好地可视化你的数据 如果你需要更好地理解你的数据&#xff0c;Python Plot是一个非常好的工具。在这篇文章里&#xff0c;我将向你介绍如何使用Python Plot来可视化你的数据。我们将讨论如何使用Python Plot创建各种不同类型的图形&#xff0c;以及如何使…

chatgpt赋能Python-python_os_system_隐藏cmd窗口

Python os.system函数 在Python中&#xff0c;os.system函数是一个非常常用的系统调用函数。它的作用是执行一个命令行语句。不过&#xff0c;使用os.system函数有时候会出现一个问题&#xff0c;就是会弹出一个命令行窗口。而在一些特殊场合下&#xff0c;我们可能希望这个命…

chatgpt赋能Python-python_plot坐标轴

Python绘图库中坐标轴的设置 介绍 Python是一种简单易学&#xff0c;功能强大的编程语言。它被广泛用于数据科学和可视化领域。Python绘图库中的坐标轴设置可以让我们更好地展示数据&#xff0c;让我们更轻松地理解数据。本篇文章将介绍Python绘图库中坐标轴设置的方法和技巧…

chatgpt赋能Python-python_plt颜色

Python plt颜色详解&#xff1a;掌握常用颜色与自定义颜色的技巧 在数据可视化的过程中&#xff0c;使用合适的颜色方案可以让图表更加清晰、易于理解。Python的matplotlib库中的plt模块提供了丰富的颜色方案供我们使用。在本篇文章中&#xff0c;我们将深入探讨plt颜色的基础…

Microsoft Office 2016安装

哈喽&#xff0c;大家好。今天一起学习的是office2016的安装&#xff0c;有兴趣的小伙伴也可以来一起试试手。 一、测试演示参数 演示操作系统&#xff1a;Windows 10 支持Win7、11安装&#xff0c;不支持WinXP系统 系统类型&#xff1a;64位 演示版本&#xff1a;SW_DVD5_Of…

py实现经典排序之冒泡和快排

文章目录 0、十大经典排序算法0.1 关于时间复杂度0.2 关于稳定性 1、冒泡排序(Bubble Sort)1.1 冒泡排序简介1.2 冒泡排序思路1.3 冒泡排序代码实现 2、快排2.1 快排简介2.2 快排思路2.3 快排代码实现 0、十大经典排序算法 0.1 关于时间复杂度 平方阶 (O(n2)) 排序 各类简单排…

mysql表操作

文章目录 mysql 操作表创建表创建表实例查看表结构修改表结构删除表结构删除表结构 mysql 操作表 mysql表操作至少有以下俩种&#xff1a; DDL【data definition language】 数据定义语言&#xff0c;用来维护存储数据的结构 代表指令: create, drop, alter DML【data manipu…

2023 conda 安装、配置环境变量、换源

0.先卸载干净再安装 1.下载安装包 这个就不要用镜像下载&#xff0c;官网很快的 Free Download | Anacondahttps://www.anaconda.com/download 2.安装软件 首先 NEXT&#xff0c;接着 I Agree 来到这个页面 选择下面的All Users&#xff0c;再接着往下 选择安装路径 建议…

chatgpt赋能Python-python_print快捷键

Python print快捷键——简化开发效率 作为Python开发者&#xff0c;我们经常需要使用print语句来调试代码。然而&#xff0c;在大型项目中&#xff0c;如果频繁使用print并手动打印变量名称和内容&#xff0c;会浪费大量时间&#xff0c;影响开发效率。此时&#xff0c;使用Py…