網(wǎng)站首頁 編程語言 正文
OpenCV身份證離線識別技術(shù)的主要技術(shù)就是通過OpenCV找到身份證號碼區(qū)域,然后通過OCR進(jìn)行數(shù)字識別該區(qū)域的截圖即可得到身份證號碼。本地ORC使用tess-two來完成,Tesseract是C++實(shí)現(xiàn)的OCR引擎,在Android中使用不是很方便,需要封裝JavaAPI才能在Android平臺中進(jìn)行調(diào)用,然而tess-two已經(jīng)幫我們做好了這些事情,通過集成tess-two就可以很方便的完成文字識別。
總體思路
圖像的預(yù)處理
1、無損壓縮
首先要處理的問題就是圖片的大小不一樣,因?yàn)槊颗_設(shè)備的的像素或者說每個(gè)圖片的大小本身都不一樣,處理過程也會有所差異,所以首先解決的問題就是大小統(tǒng)一,先通過無損壓縮把圖片處理為大小一致的圖像。根據(jù)經(jīng)驗(yàn)值(或者說這是處理證件類的通用手法),先把圖像處理為640×400的大小。
2、灰度化
現(xiàn)在大部分的彩色圖像都是采用RGB顏色模式,處理圖像的時(shí)候,要分別對RGB三種分量進(jìn)行處理,實(shí)際上RGB并不能反映圖像的形態(tài)特征,只是從光學(xué)的原理上進(jìn)行顏色的調(diào)配。圖像灰度化處理可以作為圖像處理的預(yù)處理步驟,為之后的圖像分割、圖像識別和圖像分析等上層操作做準(zhǔn)備。
其實(shí)可以仔細(xì)想想,如果是處理一張RGB圖像的話,一個(gè)像素點(diǎn)需要同時(shí)處理3個(gè)值,灰度化之后只需要處理一個(gè)值。如果是對比的話,一個(gè)RGB像素點(diǎn)就有256×256×256種可能,但是如果是對比灰度圖的像素點(diǎn),則只有256種可能,65536倍的速度提升,所以很多時(shí)候做其他圖像處理之前,先轉(zhuǎn)化為灰度圖。
圖像灰度化處理有分量法、最大值法、平均值法、加權(quán)平均法,其中用得較多的是加權(quán)平均法。由于人眼對綠色的敏感最高,對藍(lán)色敏感最低,因此,按下式對RGB三分量進(jìn)行加權(quán)平均能得到較合理的灰度圖像:
3、圖像二值化
通過以上對彩色圖片進(jìn)行灰度化以后,把獲取到的灰度圖像進(jìn)行二值化處理。對于二值化,其目的是將目標(biāo)用戶背景分類,為后續(xù)車道的識別做準(zhǔn)備。灰度圖像二值化最常用的方法是閾值法,他利用圖像中目標(biāo)與背景的差異,把圖像分別設(shè)置為兩個(gè)不同的級別,選取一個(gè)合適的閾值,以確定某像素是目標(biāo)還是背景,從而獲得二值化的圖像。比如以100為閾值對圖像進(jìn)行二值化操作:
f(i, j) = \left{\begin{array}{cc} 0, & (\text { gray }< = 100) \ 255, & (\text { gray }>100) \end{array}\right.
4、膨脹與腐蝕
膨脹與腐蝕屬于圖像處理中最基本的形態(tài)學(xué)運(yùn)算,形態(tài)學(xué)操作就是基于形狀的一系列圖像處理操作。OpenCV為進(jìn)行圖像的形態(tài)學(xué)變換提供了快捷且方便的函數(shù)。主要用于噪聲消除、分割出獨(dú)立的圖像元素、在圖像中連接相鄰的元素、尋找圖像中的明顯的極大值區(qū)域或極小值區(qū)域、求出圖像的梯度。
簡單理解,膨脹就是求局部最大值的操作。腐蝕就是求局部最小值的操作。在處理身份證的時(shí)候,我們希望把身份證號碼等數(shù)字區(qū)域連接在一起,即在圖像中連接相鄰的元素,所以需要使用膨脹處理,就跟蒸饅頭的酵母粉一樣,可以是我們想要的元素膨脹并且黏合在一起。
5、輪廓檢測與圖像分割
通過圖像的膨脹操作,身份證號碼區(qū)域已經(jīng)被連接在一起了,目前需要做的事情就是檢測出該區(qū)域的輪廓,使用拉普拉斯算子可以完成這個(gè)操作,OpenCV內(nèi)部也提供了findContours函數(shù)做輪廓檢測。
那么如何分割出身份證號碼區(qū)域呢?其實(shí)有一個(gè)非常簡單的思路,由于身份證號碼是一串不換行的數(shù)字,寬高比通常是大于9:1的,而且是位于最后一行的,如果有其他的部分的寬高比大于9:1但是卻不是位于最后,那么也不能認(rèn)為是身份證號碼,只有坐標(biāo)是最底部,而且寬高比滿足大于9:1的條件才可以。
主要代碼
VS2022 + OpenCV4.5.4
#include <iostream> #include <opencv2/opencv.hpp> #include <vector> #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、輪廓檢測,把所有的連續(xù)的閉包用矩形包起來 /* * 一個(gè)矩形用兩個(gè)點(diǎn)表示,contours就包含了很多矩形 */ vector<vector<Point>> contours; vector<Rect> rects; findContours(dst, contours, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0)); for (size_t i = 0; i < contours.size(); i++) { // 基于兩點(diǎn)構(gòu)建矩形 Rect rect = boundingRect(contours.at(i)); // 繪制矩形 rectangle(dst, rect, Scalar(0, 0, 255)); imshow("contours", dst); // 對符合條件的圖片進(jìn)行篩選,寬高比大于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); // 如果只找到了一個(gè)矩形,說明這個(gè)就是,如果多個(gè)就找出縱坐標(biāo)最低的矩形 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})
實(shí)現(xiàn)效果
來看看通過一系列的處理效果吧:
接下來要干的事情就主要有兩件,首先是繼承tess-two到Android,這樣離線識別便搞定了,另外一件事情就是圖像預(yù)處理的代碼移植到Android上,這兩件事情完成便搞定了身份證號碼離線識別的功能了。
原文鏈接:https://zouchanglin.cn/4212809718.html
相關(guān)推薦
- 2022-12-03 高并發(fā)技巧之Redis和本地緩存使用技巧分享_Redis
- 2021-10-09 OpenCV提取圖像中圓線上的數(shù)據(jù)具體流程_C 語言
- 2022-04-18 python接口測試返回?cái)?shù)據(jù)為字典取值方式_python
- 2023-01-07 Flutter?Widget開發(fā)之Focus組件圖文詳解_Android
- 2022-12-07 React?diff算法超詳細(xì)講解_React
- 2022-10-31 Kotlin標(biāo)準(zhǔn)庫函數(shù)使用分析及介紹_Android
- 2022-06-14 C#實(shí)現(xiàn)FTP上傳文件的方法_C#教程
- 2022-06-07 victoriaMetrics庫布隆過濾器初始化及使用詳解_Golang
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支