OpenCV篇——項目(一)OCR識別讀取銀行卡號碼

目錄

信用卡數字識別系統:前言與代碼解析

前言

項目代碼

??????結果演示

代碼模塊解析

1. 參數解析模塊

2. 輪廓排序函數

3. 圖像預處理模塊

4. 輸入圖像處理流程

5. 卡號區域定位

6. 數字識別與輸出

系統優勢


信用卡數字識別系統:前言與代碼解析

前言

信用卡數字識別是金融自動化處理的核心技術之一,通過計算機視覺技術自動提取卡面信息,可應用于支付驗證、身份認證等場景。本系統基于模板匹配和圖像處理技術,實現對信用卡卡號的自動識別。系統通過預處理、輪廓檢測和特征匹配三個關鍵階段,準確識別信用卡上的16位數字,并自動判斷發卡機構(Visa/MasterCard等)。以下將詳細解析代碼各模塊功能。


項目代碼

import argparse
import imutils
import numpy as np
import myutils
from imutils import contours
import cv2# 設置參數結果
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,help="path to input image containing credit card")
ap.add_argument("-t", "--template", required=True,help="path to input template image")
args = vars(ap.parse_args())# 指定信用卡類型
FIRST_NUMBER = {"3": "American Express","4": "Visa","5": "MasterCard","6": "Discover Card"
}def sort_contours(cnts, method="left-to-right"):reverse = Falsei = 0if method == "right-to-left" or method == "bottom-to-top":reverse = Trueif method == "top-to-bottom" or method == "bottom-to-top":i = 1boundingBoxes = [cv2.boundingRect(c) for c in cnts]  # 用一個最小的矩形,把找到的形狀包起來x,y,h,w(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),key=lambda b: b[1][i], reverse=reverse))return cnts, boundingBoxesdef resize(image, width=None, height=None, inter=cv2.INTER_AREA):dim = None(h, w) = image.shape[:2]if width is None and height is None:return imageif width is None:r = height / float(h)dim = (int(w * r), height)else:r = width / float(w)dim = (width, int(h * r))resized = cv2.resize(image, dim, interpolation=inter)return resized# 繪圖展示
def cv_show(name,img):cv2.imshow(name,img)cv2.waitKey(0)cv2.destroyAllWindows()return None# 讀取一個模板
img=cv2.imread(args["template"])
cv_show("img",img)# 灰度圖展示
ref=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv_show("ref",ref)# 二值圖像
ref=cv2.threshold(ref,10,255,cv2.THRESH_BINARY_INV)[1]
cv_show("ref",ref)# 計算輪廓果
ref_,refCnts = cv2.findContours(ref.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,ref_,-1,(0,0,255),3)
cv_show("img",img)
print(np.array(refCnts).shape)
refCnts =sort_contours(ref_, method="left-to-right")[0]
digits = {}# 遍歷模板輪廓
for (i,c) in enumerate(refCnts):(x,y,w,h) = cv2.boundingRect(c)roi = ref[y:y+h,x:x+w]roi = cv2.resize(roi,(57,88))digits[i] = roi# 初始化卷積核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
squareKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))# 讀取輸入圖像、預處理
image = cv2.imread(args["image"])
cv_show("image",image)
image = resize(image,width=300)
gary= cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv_show("gary",gary)# 禮帽操作,突出更明亮的區域
tophat = cv2.morphologyEx(gary,cv2.MORPH_TOPHAT,rectKernel)
cv_show("tophat",tophat)
gradx=cv2.Sobel(tophat,ddepth=cv2.CV_32F,dx=1,dy=0,ksize=-1)
gradx = np.absolute(gradx)
(minVal,maxVal) = (np.min(gradx),np.max(gradx))
gradx = (255 * ((gradx - minVal) / (maxVal - minVal)))
gradx = gradx.astype("uint8")
print(np.array(gradx).shape)
cv_show("gradx",gradx)# 通過閉操作(先膨脹,再腐蝕)將數字連在一起
gradx = cv2.morphologyEx(gradx,cv2.MORPH_CLOSE,rectKernel)
cv_show("gradx",gradx)
# THRESH_OTSU會自動尋找全局閾值,適合雙峰,需要把閾值參數設置為0
thresh = cv2.threshold(gradx,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show("thresh",thresh)# 再來一個閉操作
thresh = cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,squareKernel)
cv_show("thresh",thresh)# 計算輪廓
thresh_,threshCnts = cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = thresh_
cur_img=image.copy()
cv2.drawContours(cur_img,cnts,-1,(0,0,255),3)
cv_show("cur_img",cur_img)
locs=[]# 遍歷輪廓
for (i,c) in enumerate(cnts):(x,y,w,h)=cv2.boundingRect(c)ar = w / float(h)# 選擇合適的區域,根據實際任務來,這里的基本都是四個數字一組if ar > 2.5 and ar < 4.0:# 滿足條件的區域可能是數字的區域if (w > 40 and w < 55) and (h > 10 and h < 20):# 符合尺寸的保存locs.append((x,y,w,h))
# 將符合條件的輪廓從左到右排序
locs = sorted(locs,key=lambda x:x[0])
output=[]
# 遍歷每一個輪廓中的數字
for (i,(gx,gy,gw,gh)) in enumerate(locs):# initialzie the list of group digitsgroupOutput = []# 根據坐標提取數字的區域group = gary[gy-5:gy+gh+5,gx-5:gx+gw+5]cv_show("group",group)# 預處理group = cv2.threshold(group,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]cv_show("group",group)# 計算每一組的輪廓group_,groupCnts = cv2.findContours(group.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)group_ = contours.sort_contours(group_,method="left-to-right")[0]# 計算每一個組中的數字for c in group_:(x,y,w,h) = cv2.boundingRect(c)digit = group[y:y+h,x:x+w]digit = cv2.resize(digit,(57,88))cv_show("digit",digit)# 計算匹配得分scores = []# 在模板中計算每一個得分for (digitt,digitTempl) in digits.items():result = cv2.matchTemplate(digit,digitTempl,cv2.TM_CCOEFF)(_,score,_,_) = cv2.minMaxLoc(result)scores.append(score)# 獲得匹配得分最適合的數字groupOutput.append(str(np.argmax(scores)))# 畫出來cv2.rectangle(image,(gx-5,gy-5),(gx+gw+5,gy+gh+5),(0,0,255),1)cv2.putText(image,"".join(groupOutput),(gx,gy-15),cv2.FONT_HERSHEY_SIMPLEX,0.65,(0,0,255),2)# 得到結果output.extend(groupOutput)
# 打印結果
print("Credit Card Type: {}".format(FIRST_NUMBER[output[0]]))
print("Credit Card #: {}".format("".join(output)))
cv2.imshow("Image", image)
cv2.waitKey(0)

注意事項:

由于作者用于較新的PyCharm版本是2024版本,它與傳統的PyCharm有區分,而且作者在學習過程中同樣發現一些問題,這個代碼前面可以不用寫排序,而最新版本里面不知什么原因調用接口時候報錯說沒有這個模塊函數,于是作者只能將排序等需要的模塊分開出來,寫入項目中。

??????結果演示

代碼模塊解析

1. 參數解析模塊
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="輸入信用卡圖像路徑")
ap.add_argument("-t", "--template", required=True, help="模板圖像路徑")
args = vars(ap.parse_args())
  • 功能:通過命令行參數接收輸入圖像和模板圖像路徑
  • 參數說明
    • -i/--image:待識別的信用卡圖像
    • -t/--template:數字模板圖像(包含0-9標準數字)

PyCharm2024通過argparse模塊操作命令行設置方法如下,接下來的步驟是中文展示,作者PyCharm已經漢化,若未漢化也可記作者選擇按鈕的位置點擊:

第一步:將需要的圖片存放在本人知道的文件路徑

原圖片如下:

模板圖片如下:

我存放的路徑如下:

第二步:右擊項目代碼,選擇“更多運行/調試”后,在選擇下拉列表中的“修改運行配置”

第三步:在新打開的對話框選擇“運行”欄下最后一行點擊“展開”

第四步:輸入之前存放模板和原圖片的路徑

注:由于作者存放圖片和模板與項目同一個文件夾目錄下,因此可以省略具體的路徑,若用戶存放不在同一個文件夾目錄下,那么需要你加上如下格式:

--image

盤符:\文件夾1名稱\文件夾2名稱\.....\圖片名稱和后綴名(.png,.jpg等等)

--template

盤符:\文件夾1名稱\文件夾2名稱\.....\圖片名稱和后綴名(.png,.jpg等等)

2. 輪廓排序函數
def sort_contours(cnts, method="left-to-right"):reverse = Falsei = 0if method == "right-to-left" or method == "bottom-to-top":reverse = Trueif method == "top-to-bottom" or method == "bottom-to-top":i = 1boundingBoxes = [cv2.boundingRect(c) for c in cnts]  # 用一個最小的矩形,把找到的形狀包起來x,y,h,w(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),key=lambda b: b[1][i], reverse=reverse))return cnts, boundingBoxes

  • 功能:對檢測到的輪廓按空間位置排序
  • 排序邏輯
    • 計算每個輪廓的邊界框 (x,y,w,h)
    • method參數選擇排序基準(X軸或Y軸坐標)
    • 支持四種排序方向:左→右、右→左、上→下、下→上
3. 圖像預處理模塊
# 模板預處理流程
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 灰度化
ref = cv2.threshold(ref,10,255,cv2.THRESH_BINARY_INV)[1]  # 二值化反轉

  • 關鍵操作
    • 灰度轉換:將RGB圖像轉為單通道灰度圖
    • 二值化:通過閾值處理突出數字區域
    • 輪廓提取findContours定位每個數字的獨立輪廓
    • 模板存儲:將0-9數字按索引存入字典digits
4. 輸入圖像處理流程
# 核心處理鏈
image = resize(image, width=300)  # 尺寸標準化
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # 灰度化
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)  # 頂帽運算
gradx = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0)  # Sobel邊緣檢測
gradx = cv2.morphologyEx(gradx, cv2.MORPH_CLOSE, rectKernel)  # 閉運算

  • 處理階段
    1. 尺寸歸一化:固定寬度為300像素,保持比例
    2. 頂帽運算:突出亮色區域(信用卡數字通常為亮色)
    3. Sobel算子:檢測垂直邊緣(數字的豎直筆畫)
    4. 形態學閉操作:連接數字筆畫形成連續區域
5. 卡號區域定位
# 數字區域篩選
for (i,c) in enumerate(cnts):(x,y,w,h) = cv2.boundingRect(c)ar = w / float(h)  # 寬高比if 2.5 < ar < 4.0 and 40<w<55 and 10<h<20:locs.append((x,y,w,h))  # 保存候選區域

  • 篩選條件
    • 寬高比 $2.5 < \frac{w}{h} < 4.0$(信用卡數字的典型比例)
    • 寬度 $40 < w < 55$ 像素
    • 高度 $10 < h < 20$ 像素
  • 結果:獲得4組數字區域的坐標 locs
6. 數字識別與輸出
# 模板匹配識別
for c in group_:digit = cv2.resize(roi, (57,88))  # 標準化尺寸scores = []for digitTempl in digits.values():score = cv2.matchTemplate(digit, digitTempl, cv2.TM_CCOEFF)scores.append(score)  # 存儲匹配得分groupOutput.append(str(np.argmax(scores)))  # 選擇最高分對應數字# 可視化輸出
cv2.rectangle(image, (gx-5,gy-5), (gx+gw+5,gy+gh+5), (0,0,255), 1)
cv2.putText(image, "".join(groupOutput), (gx,gy-15), cv2.FONT_HERSHEY_SIMPLEX, ...)
# 得到結果
output.extend(groupOutput)
# 打印結果
print("Credit Card Type: {}".format(FIRST_NUMBER[output[0]]))
print("Credit Card #: {}".format("".join(output)))
cv2.imshow("Image", image)
cv2.waitKey(0)

  • 識別流程
    1. 截取單個數字區域并縮放至模板尺寸
    2. 與0-9模板進行相似度匹配(TM_CCOEFF相關系數法)
    3. 選擇最高匹配得分對應的數字
  • 輸出形式
    • 紅色矩形框標記數字組區域
    • 在區域上方顯示識別出的4位數字

系統優勢

  1. 形態學操作鏈:通過頂帽、閉操作等組合優化數字區域提取
  2. 動態模板匹配:適應不同字體和尺寸的數字
  3. 空間約束:利用寬高比和尺寸過濾誤檢區域
  4. 實時可視化:各階段結果可實時顯示便于調試

該系統實現了從原始圖像到卡號識別的完整流程,準確率依賴模板質量和圖像清晰度,可通過優化預處理參數進一步提升性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/912631.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/912631.shtml
英文地址,請注明出處:http://en.pswp.cn/news/912631.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Adobe AI高效設計秘籍與創新思維進階

開篇&#xff1a;十年設計征途&#xff0c;Adobe賦能創意飛翔 作為一名在設計領域耕耘十年的旅居職業設計師&#xff0c;我得益于英國帕維斯經濟與音樂學院&#xff08;Parvis School of Economics and Music&#xff09;提供的Adobe正版教育訂閱&#xff0c;得以持續探索技術…

vc formal實例

命令&#xff1a; module load gui 方式啟動命令&#xff0c; 看一下cc_pinmux.tcl 里面有什么&#xff1a; 工具feature 的設置&#xff0c;不太懂 對特定模塊做blackbox, library file, 一般是工具無法識別的模塊&#xff0c;例如 IO lib,memory lib,analog lib, 內部有 …

JavaScript取值get的json/url/普通對象參考

dstore.on(datachanged,function(dstore){ for(i0;i<dstore.getCount();i){ var a dstore.getAt(i); var imp_infoa.get(imp_info); 上面這段JS代碼&#xff0c;imp_info取到的是一長串KEY和VALUE組成的內容&#xff0c;我怎樣可以準確獲取其中一…

【C++】偵測按鍵事件

偵測按鍵事件可以用C的conio.h頭文件&#xff0c;用到的函數&#xff1a; _CRTIMP int __cdecl _getch(void); 輸入以下代碼&#xff1a; #include <iostream> #include <conio.h> using namespace std;int main() {char key;while (true) {cout << "…

Coremail受邀亮相華為開發者大會

6月20-22日&#xff0c;為期三天的HDC.2025華為開發者大會在東莞舉行&#xff0c;全球超過1.2萬名開發者匯聚現場&#xff0c;聚焦鴻蒙生態、AI技術及產業合作。Coremail作為鴻蒙生態的核心伙伴和深度參與者受邀出席&#xff0c;并獲得“智慧辦公最佳產品合作伙伴”獎項。 HDC.…

視頻斷點續播全棧實現:基于HTML5前端與Spring Boot后端

文章目錄 視頻斷點續播功能實現方案核心思路前端實現HTML結構JavaScript實現Spring Boot后端實現1.依賴配置(pom.xml)2.實體類3.存儲庫接口4.服務層5. 控制器實現要點視頻斷點續播功能構思圖流程說明用戶交互:前端核心功能:后端處理:數據存儲:?? 我的個人網站:樂樂主題創…

華為設備 QoS 流分類與流標記深度解析及實驗腳本

一、引言 在復雜網絡環境中&#xff0c;不同業務對網絡質量需求各異。語音通話要求低時延、視頻直播依賴高帶寬、普通文件傳輸對丟包容忍度相對較高 。QoS&#xff08;Quality of Service&#xff0c;服務質量&#xff09;技術通過流分類、流標記等手段&#xff0c;為不同業務…

[論文閱讀] 人工智能 + 軟件工程 | 從軟件工程視角看大語言模型:挑戰與未來之路

從軟件工程視角看大語言模型&#xff1a;挑戰與未來之路 論文標題&#xff1a;Software Engineering for Large Language Models: Research Status, Challenges and the Road Ahead arXiv:2506.23762 Software Engineering for Large Language Models: Research Status, Chall…

【Docker基礎】Docker容器管理:docker rm及其參數詳解

目錄 1 Docker容器生命周期概述 2 docker rm命令基礎 2.1 命令基本語法 2.2 命令功能說明 2.3 基本使用示例 3 docker rm參數詳解 3.1 -f, --force 3.2 -v, --volumes 3.3 -l, --link 3.4 --time 4 docker rm高級用法 4.1 批量刪除容器 4.1.1 刪除所有已停止的容器…

鴻蒙進階——Mindspore Lite AI框架源碼解讀之模型加載詳解(五)

文章大綱 引言一、LiteSession::CompileGraph(Model *model)二、LiteSession::CompileGraph(Model *model) 核心流程1、MindirModel::ConvertTensors1.1、遍歷并執行MindirModel::ConvertTensor1.1.1、MindirModel::LoadTensorData 三、LiteSession::InitGraphInputTensors(mod…

WireShark網絡取證分析第一集到第五集和dvwa靶場環境分析漏洞

文章目錄 一、WireShark網絡取證是什么?二、WireShark網絡取證1.WireShark網絡取證分析第一集Ann的即時通訊好友叫什么名字?在捕獲的即時通訊對話中第一條評論是什么?Ann傳輸的文件叫什么名字?您想提取的文件的魔數是什么(前四個字節)?文件的MD5sum是多少?什么是秘密配方…

【51單片機按下按鍵1,8位共陰極數碼管輸出2022-606。按下按鍵2,8位共陰極數碼管輸出606-1132。】2022-6-10

緣由單片極的共陰極數碼管按下按鍵1和按鍵2輸出的內容-編程語言-CSDN問答 #include "REG52.h" unsigned char code smgduan[]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0,64}; //共陰0~F消隱減號 unsigned char Js0, miao…

HDMI轉12G- SDI GS12170+GS12281-富利威方案設計及技術支持

GS12281 是一款低功耗、多速率、重定時電纜驅動器&#xff0c;支持高達 12G UHD-SDI 的速率。它設計用于接收 100Ω 差分輸入信號&#xff0c;自動從數字視頻信號中恢復嵌入式時鐘并重新定時輸入數據&#xff0c;并通過 75Ω 同軸電纜傳輸重新定時的信號。 100Ω 走線輸入支持…

自然語言處理:NLP入門

本文目錄&#xff1a; 一、概念二、發展史三、核心任務和技術特別分享1&#xff1a;當前挑戰和前沿方向特別分享2&#xff1a;大神名言啟示 前言&#xff1a;從本章開始講解自然語言處理&#xff08;NLP&#xff09;&#xff0c;今天先入個門~ 一、概念 自然語言處理&#xff…

用Fiddler中文版抓包工具掌控微服務架構中的接口調試:聯合Postman與Charles的高效實踐

隨著微服務架構在項目中的廣泛應用&#xff0c;系統被拆分成多個獨立的服務&#xff0c;彼此通過API通信。雖然架構帶來了靈活性&#xff0c;但也大幅增加了接口數量和調用鏈復雜度&#xff1a;一次用戶操作可能觸發跨多個服務的調用&#xff0c;導致前端調試難度飆升。要精準排…

MongoDB 更新文檔指南

MongoDB 更新文檔指南 引言 MongoDB 是一款高性能、可擴展的文檔存儲系統&#xff0c;它為存儲和管理大量數據提供了強大的支持。在 MongoDB 中&#xff0c;更新文檔是常見操作之一&#xff0c;它允許用戶修改現有文檔的內容。本文將詳細講解 MongoDB 中更新文檔的各種方法&a…

Cursor + Serena MCP集成,更好的解析項目架構

項目地址&#xff0c;下到本地。 Serena可以更好的理解項目的架構并總結&#xff0c;而不是簡單的閱讀代碼文件&#xff0c;可以直接用Cursor結合MCP的方式進行使用。&#xff1a;Serena 的語義代碼分析功能建立在語言服務器上&#xff0c;使用廣泛實施的語言服務器協議&#x…

【Python】numpy數組常用數據處理(測試代碼+api例程)

目錄 一、數列生成1.按照間隔生成數列&#xff08;np.array[]&#xff09;2.按照數列數字個數生成數列&#xff08;np.linspace&#xff09; 二、數列增刪改查1.1 數組末尾添加數據&#xff08;np.append&#xff09;1.2 數組指定索引位置添加數據&#xff08;np.insert&#x…

CMU-15445(6)——PROJECT#2-BPlusTree-Task#1

PROJECT#2-BTree 在 PROJECT#2 中&#xff0c;我們需要實現一個B plus Tree&#xff0c;用過 MySQL 的同學肯定對它不陌生&#xff0c;BTree是實現高效數據檢索的核心組件&#xff0c;其內部節點的作用是引導搜索過程&#xff0c;而實際的數據項則存于葉子節點中。該索引結構能…

向量數據庫搜索原理解密:從暴力掃描到近似最近鄰的演進之路

摘要 向量數據庫已成為處理AI時代海量非結構化數據的核心基礎設施。本文深入解析向量搜索的六大核心技術原理,涵蓋暴力掃描、樹結構索引、量化壓縮、圖導航算法等核心機制,通過10張架構圖解與數學公式推導,揭示千萬級向量毫秒級檢索背后的工程奇跡。全文超5000字,包含Fais…