千家信息网

C++ OpenCV如何实现身份证离线识别

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这篇文章将为大家详细讲解有关C++ OpenCV如何实现身份证离线识别,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。OpenCV身份证离线识别技术的主要技术就是通过
千家信息网最后更新 2026年11月03日C++ OpenCV如何实现身份证离线识别

这篇文章将为大家详细讲解有关C++ OpenCV如何实现身份证离线识别,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

OpenCV身份证离线识别技术的主要技术就是通过OpenCV找到身份证号码区域,然后通过OCR进行数字识别该区域的截图即可得到身份证号码。本地ORC使用tess-two来完成,Tesseract是C++实现的OCR引擎,在Android中使用不是很方便,需要封装JavaAPI才能在Android平台中进行调用,然而tess-two已经帮我们做好了这些事情,通过集成tess-two就可以很方便的完成文字识别。

总体思路

图像的预处理

1、无损压缩

首先要处理的问题就是图片的大小不一样,因为每台设备的的像素或者说每个图片的大小本身都不一样,处理过程也会有所差异,所以首先解决的问题就是大小统一,先通过无损压缩把图片处理为大小一致的图像。根据经验值(或者说这是处理证件类的通用手法),先把图像处理为640×400的大小。

2、灰度化

现在大部分的彩色图像都是采用RGB颜色模式,处理图像的时候,要分别对RGB三种分量进行处理,实际上RGB并不能反映图像的形态特征,只是从光学的原理上进行颜色的调配。图像灰度化处理可以作为图像处理的预处理步骤,为之后的图像分割、图像识别和图像分析等上层操作做准备。

其实可以仔细想想,如果是处理一张RGB图像的话,一个像素点需要同时处理3个值,灰度化之后只需要处理一个值。如果是对比的话,一个RGB像素点就有256×256×256种可能,但是如果是对比灰度图的像素点,则只有256种可能,65536倍的速度提升,所以很多时候做其他图像处理之前,先转化为灰度图。

图像灰度化处理有分量法、最大值法、平均值法、加权平均法,其中用得较多的是加权平均法。由于人眼对绿色的敏感最高,对蓝色敏感最低,因此,按下式对RGB三分量进行加权平均能得到较合理的灰度图像:

3、图像二值化

通过以上对彩色图片进行灰度化以后,把获取到的灰度图像进行二值化处理。对于二值化,其目的是将目标用户背景分类,为后续车道的识别做准备。灰度图像二值化最常用的方法是阈值法,他利用图像中目标与背景的差异,把图像分别设置为两个不同的级别,选取一个合适的阈值,以确定某像素是目标还是背景,从而获得二值化的图像。比如以100为阈值对图像进行二值化操作:

f(i, j) = \left{\begin{array}{cc} 0, & (\text { gray }< = 100) \ 255, & (\text { gray }>100) \end{array}\right.

4、膨胀与腐蚀

膨胀与腐蚀属于图像处理中最基本的形态学运算,形态学操作就是基于形状的一系列图像处理操作。OpenCV为进行图像的形态学变换提供了快捷且方便的函数。主要用于噪声消除、分割出独立的图像元素、在图像中连接相邻的元素、寻找图像中的明显的极大值区域或极小值区域、求出图像的梯度。

简单理解,膨胀就是求局部最大值的操作。腐蚀就是求局部最小值的操作。在处理身份证的时候,我们希望把身份证号码等数字区域连接在一起,即在图像中连接相邻的元素,所以需要使用膨胀处理,就跟蒸馒头的酵母粉一样,可以是我们想要的元素膨胀并且黏合在一起。

5、轮廓检测与图像分割

通过图像的膨胀操作,身份证号码区域已经被连接在一起了,目前需要做的事情就是检测出该区域的轮廓,使用拉普拉斯算子可以完成这个操作,OpenCV内部也提供了findContours函数做轮廓检测。

那么如何分割出身份证号码区域呢?其实有一个非常简单的思路,由于身份证号码是一串不换行的数字,宽高比通常是大于9:1的,而且是位于最后一行的,如果有其他的部分的宽高比大于9:1但是却不是位于最后,那么也不能认为是身份证号码,只有坐标是最底部,而且宽高比满足大于9:1的条件才可以。

主要代码

VS2022 + OpenCV4.5.4

#include #include #include #define DEFAULT_CARD_WIDTH 640#define DEFAULT_CARD_HEIGHT 400#define FIX_IDCARD_SIZE Size(DEFAULT_CARD_WIDTH, DEFAULT_CARD_HEIGHT)#define FIX_TEMPLATE_SIZE Size(153, 28)using namespace std;using namespace cv;int main() {    std::cout << "Hello, World!" << std::endl;    Mat src = imread("src.png");    imshow("src", src);    //处理身份证    Mat src_img = src;    //1、无损压缩 640*400 (通用卡片类的处理方式)    resize(src_img, src_img, FIX_IDCARD_SIZE);    imshow("dst", src_img);        Mat dst_img;    //2、灰度化    Mat dst;    cvtColor(src_img, dst, COLOR_BGR2GRAY);    imshow("gray", dst);        //3、二值化(降噪)    threshold(dst, dst, 100, 255, THRESH_BINARY);    imshow("threshold", dst);        // 4.1 腐蚀、膨胀    Mat erodeElement = getStructuringElement(MORPH_RECT, Size(20, 10));    erode(dst, dst, erodeElement);    imshow("erode", dst);    //4、轮廓检测,把所有的连续的闭包用矩形包起来    /*     * 一个矩形用两个点表示,contours就包含了很多矩形     */    vector> contours;    vector rects;        findContours(dst, contours, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));        for (size_t i = 0; i < contours.size(); i++)    {        // 基于两点构建矩形        Rect rect = boundingRect(contours.at(i));        // 绘制矩形        rectangle(dst, rect, Scalar(0, 0, 255));        imshow("contours", dst);        // 对符合条件的图片进行筛选,宽高比大于1:9的        if(rect.width > rect.height*9)        {            cout << "找到了" << endl;            rects.push_back(rect);            rectangle(dst, rect, Scalar(0, 0, 255));                // 还需要再次矫正            //dst_img = src_img(rect);        }    }        // imshow("dst_Img", dst_img);        // 如果只找到了一个矩形,说明这个就是,如果多个就找出纵坐标最低的矩形    if(rects.size() == 1)    {        Rect rect = rects.at(0);        dst_img = src_img(rect);    }else    {        int lowPoint = 0;        Rect finalRect;            for (size_t i = 0; i < rects.size(); ++i)        {            Rect rect = rects.at(i);            Point p = rect.tl();            if(rect.tl().y > lowPoint)            {                lowPoint = rect.tl().y;                finalRect = rect;            }        }            rectangle(dst, finalRect, Scalar(255, 255, 0));        dst_img = src_img(finalRect);    }            imshow("dst_Img", dst_img);    waitKey();    return 0;}

CMakeList.txt

cmake_minimum_required (VERSION 3.8)project(opencv_idcard)set(CMAKE_CXX_STANDARD 11)add_executable (opencv_idcard "opencv_idcard.cpp" )set(OpenCV_DIR "D:/develop/opencv-4.5.4/opencv-4.5.4-build")find_package(OpenCV REQUIRED)include_directories(${OpenCV_INCLUDE_DIRS})target_link_libraries(opencv_idcard ${OpenCV_LIBS})

实现效果

来看看通过一系列的处理效果吧:

接下来要干的事情就主要有两件,首先是继承tess-two到Android,这样离线识别便搞定了,另外一件事情就是图像预处理的代码移植到Android上,这两件事情完成便搞定了身份证号码离线识别的功能了。

关于"C++ OpenCV如何实现身份证离线识别"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

图像 处理 身份 身份证 灰度 就是 号码 区域 事情 像素 图像处理 大小 矩形 元素 图片 形态 轮廓 检测 C++ 分量 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网金融科技 科技互联网企业 没上市的科技互联网公司 广州互联网科技公司 华中科技大学互联网 银优互联网科技有限公司 齐家互联网科技有限公司 新华互联网科技校企合作 贵州叶脉互联网科技有限公司所属行业 互联网校园科技培训 互联网经济与金融科技 移动互联网科技公司 未来五年的互联网科技 互联网科技大赛获奖感言 世界互联网领先科技成果获奖 深圳互联网科技的发展 神州科技互联网有限公司 上海万顺科技互联网有限公司招聘 互联网金融金融科技 互联网科技快速发展优美句子 互联网科技股 广州百单互联网科技有限公司 佰商互联网科技有限公司 互联网和黑科技的看法 科技类公司包括互联网吗 江苏苏星互联网科技有限公司 雨阳互联网卡科技有限公司 广东工业互联网大赛深圳学泰科技 第三届互联网大会安防黑科技 平安好医生打造互联网科技医疗
0