基于OpenCV與Python實現(xiàn)的身份證號碼識別案例詳解
一、案例背景與價值
身份證號碼識別是計算機視覺在證件信息提取中的典型應用,廣泛應用于??身份驗證、自動化錄入、政務系統(tǒng)??等場景。本案例基于Python的OpenCV庫,實現(xiàn)身份證號碼的??定位→分割→識別??全流程,兼顧實用性與可復現(xiàn)性。
二、技術(shù)棧說明
??編程語言??:Python 3.x
??核心庫??:
OpenCV(cv2):圖像預處理、輪廓檢測、形態(tài)學操作
NumPy:數(shù)值計算與數(shù)組處理
(可選)Tesseract OCR:替代模板匹配的字符識別方案
三、整體實現(xiàn)流程
身份證號碼識別遵循四大核心步驟:
??圖像預處理??:降噪、二值化、增強字符邊緣
??號碼區(qū)域定位??:通過輪廓檢測與位置篩選鎖定18位數(shù)字區(qū)域
??字符分割??:垂直投影或輪廓排序分割單個字符
??字符識別??:模板匹配/機器學習模型識別數(shù)字(含字母X)
四、數(shù)據(jù)準備
需提前準備兩張圖片:
sfzh.png:包含0-9數(shù)字的模板圖像(用于訓練字符模板)

sfz.jpg:待識別的身份證原件圖像

五、代碼詳解與實戰(zhàn)
1. 基礎函數(shù)定義與導入
首先導入依賴庫,并定義兩個輔助函數(shù):
cv_show:快速顯示圖像(避免重復寫imshow和waitKey)sort_contours:按指定方向排序輪廓(確保字符順序正確)
import cv2
import numpy as np
# 繪圖展示函數(shù):簡化圖像顯示流程
def cv_show(name, image):
cv2.imshow(name, image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 輪廓排序函數(shù):支持左→右、右→左、上→下、下→上
def sort_contours(cnts, method='left-to-right'):
reverse = False
i = 0
if method in ['right-to-left', 'bottom-to-top']:
reverse = True
if method in ['top-to-bottom', 'bottom-to-top']:
i = 1
boundingBoxes = [cv2.boundingRect(c) for c in cnts]
(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
key=lambda b: b[1][i], reverse=reverse))
return cnts, boundingBoxes2. 模板圖像預處理:生成字符匹配模板
首先處理sfzh.png(包含0-9的數(shù)字模板),提取每個數(shù)字的標準輪廓,作為后續(xù)匹配的基準。
步驟1:讀取模板并轉(zhuǎn)灰度/二值圖
# 讀取模板圖像
img_template = cv2.imread("sfzh.png")
cv_show('Template Image', img_template)
# 轉(zhuǎn)灰度圖(減少顏色通道干擾)
gray_template = cv2.imread("sfzh.png", 0)
# 二值化:反閾值化(數(shù)字變白,背景變黑)
ret, ref_bin = cv2.threshold(gray_template, 150, 255, cv2.THRESH_BINARY_INV)
cv_show('Binary Template', ref_bin)步驟2:輪廓檢測與數(shù)字排序
# 查找外輪廓(僅保留數(shù)字的外邊界)
_, contours, _ = cv2.findContours(ref_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 按左→右排序輪廓(確保數(shù)字順序是0→9)
sorted_contours, _ = sort_contours(contours, method='left-to-right')
# 可視化輪廓(確認數(shù)字是否正確檢測)
cv2.drawContours(img_template, sorted_contours, -1, (0, 255, 0), 2)
cv_show('Template with Contours', img_template)步驟3:生成數(shù)字模板字典
對每個數(shù)字輪廓提取ROI(感興趣區(qū)域),統(tǒng)一尺寸并存儲,供后續(xù)匹配使用:
digits = {} # 存儲數(shù)字模板:key=數(shù)字索引,value=標準化后的數(shù)字圖像
for idx, contour in enumerate(sorted_contours):
# 獲取數(shù)字的邊界框
x, y, w, h = cv2.boundingRect(contour)
# 提取ROI并擴展邊界(避免裁剪數(shù)字)
roi = ref_bin[y-2:y+h+2, x-2:x+w+2]
# 統(tǒng)一尺寸為57×88(模板匹配的最佳尺寸)
roi = cv2.resize(roi, (57, 88))
# 按位取反(統(tǒng)一為數(shù)字黑、背景白)
roi = cv2.bitwise_not(roi)
# 存儲模板
digits[idx] = roi
# 關(guān)閉所有窗口
cv2.destroyAllWindows()3. 身份證號碼識別:定位→分割→匹配
接下來處理待識別的身份證圖像sfz.jpg,完成號碼區(qū)域的定位與字符識別。
步驟1:身份證圖像預處理
# 讀取身份證原圖
img_id = cv2.imread('sfz.jpg')
img_copy = img_id.copy() # 用于后續(xù)繪制結(jié)果
cv_show('Original ID Card', img_id)
# 轉(zhuǎn)灰度圖
gray_id = cv2.imread('sfz.jpg', 0)
cv_show('Gray ID Card', gray_id)
# 二值化(閾值根據(jù)原圖亮度調(diào)整)
ret, id_bin = cv2.threshold(gray_id, 120, 255, cv2.THRESH_BINARY_INV)
cv_show('Binary ID Card', id_bin)步驟2:定位身份證號碼區(qū)域
通過輪廓的位置篩選,鎖定身份證底部的18位數(shù)字區(qū)域(??注意:坐標范圍需根據(jù)實際圖像調(diào)整??):
# 查找身份證圖像的所有外輪廓
_, contours_id, _ = cv2.findContours(id_bin.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 篩選號碼區(qū)域:根據(jù)y坐標(330~360)和x坐標(x>220)定位底部數(shù)字
locs = []
for (i, contour) in enumerate(contours_id):
x, y, w, h = cv2.boundingRect(contour)
if 330 < y < 360 and x > 220:
locs.append((x, y, w, h))
# 按x坐標排序(確保數(shù)字從左到右排列)
locs = sorted(locs, key=lambda x: x[0])
步驟3:單字符預處理與模板匹配
對每個篩選出的數(shù)字區(qū)域,進行預處理后與模板匹配,識別具體數(shù)字:
output = [] # 存儲最終識別結(jié)果
for (gX, gY, gW, gH) in locs:
# 1. 提取數(shù)字區(qū)域并擴展邊界
group = gray_id[gY-2:gY+gH+2, gX-2:gX+gW+2]
# 2. 自適應閾值(自動優(yōu)化黑白對比)
group = cv2.threshold(group, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
# 3. 統(tǒng)一尺寸為模板大?。?7×88)
roi = cv2.resize(group, (57, 88))
# 4. 按位取反(與模板格式一致)
roi = cv2.bitwise_not(roi)
# 5. 模板匹配:計算當前ROI與所有模板的相似度
scores = []
for digit, template in digits.items():
# 使用TM_CCOEFF方法(值越大越匹配)
result = cv2.matchTemplate(roi, template, cv2.TM_CCOEFF)
(_, score, _, _) = cv2.minMaxLoc(result)
scores.append(score)
# 6. 取得分最高的模板對應的數(shù)字
jieguo = str(np.argmax(scores))
output.append(jieguo)
# (可選)可視化識別結(jié)果:繪制矩形框與數(shù)字文本
cv2.rectangle(img_copy, (gX-5, gY-5), (gX+gW+5, gY+gH+5), (0, 0, 255), 1)
cv2.putText(img_copy, jieguo, (gX, gY-15),
cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)步驟4:輸出結(jié)果與可視化
# 打印識別結(jié)果(拼接成18位身份證號)
print("識別結(jié)果:{}".format("".join(output)))
# 顯示帶識別標記的身份證圖像
cv2.imshow('ID Card with Recognition', img_copy)
cv2.waitKey(0)
cv2.destroyAllWindows()六、關(guān)鍵說明與優(yōu)化方向
??位置篩選的適配性??:案例中的
330<y<360和x>220是基于特定身份證圖像的坐標,實際應用需根據(jù)輸入圖像調(diào)整(可通過調(diào)試輪廓的(x,y,w,h)可視化確認)。??模板匹配的局限性??:若身份證圖像存在旋轉(zhuǎn)、縮放或光照不均,需增加??角度校正??(如仿射變換)或改用??深度學習模型??(如CNN)提升魯棒性。
??校驗位驗證??:識別完成后,可通過身份證校驗位公式(第18位=前17位的加權(quán)和模11)驗證結(jié)果合法性。
七、效果展示
運行代碼后,終端會輸出識別出的18位身份證號,同時窗口會顯示帶紅色矩形框和數(shù)字標記的身份證圖像(如下示例):
識別結(jié)果:11010119900101123X
以上就是基于OpenCV的身份證號碼識別完整實現(xiàn),代碼可直接復現(xiàn),如需優(yōu)化可針對具體場景調(diào)整參數(shù)或替換識別模型~
總結(jié)
到此這篇關(guān)于基于OpenCV與Python實現(xiàn)身份證號碼識別的文章就介紹到這了,更多相關(guān)OpenCV與Python身份證號碼識別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python?sklearn?中的?make_blobs()?函數(shù)示例詳解
make_blobs()?是?sklearn.datasets中的一個函數(shù),這篇文章主要介紹了Python?sklearn?中的?make_blobs()?函數(shù),本文結(jié)合實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2023-02-02
Pytorch+PyG實現(xiàn)GraphConv過程示例詳解
這篇文章主要為大家介紹了Pytorch+PyG實現(xiàn)GraphConv過程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-04-04
Python腳本,標識符,變量使用,腳本語句,注釋,模塊引用詳解
這篇文章主要為大家詳細介紹了Python腳本,標識符,變量使用,腳本語句,注釋,模塊引用,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02
使用Python將PPT的幻燈片和形狀轉(zhuǎn)為多種圖片格式
這篇文章主要為大家詳細介紹了如何使用Python?將PPT幻燈片和形狀轉(zhuǎn)換為多種圖片格式,即JPG,?PNG,?BMP,?SVG,?TIFF,需要的可以參考下2025-02-02

