基于OpenCV的銀行卡號識別系統:從原理到實現

引言

在現代金融科技應用中,銀行卡號的自動識別是一項重要技術。本文將詳細介紹如何使用Python和OpenCV庫構建一個完整的銀行卡號識別系統。該系統能夠從銀行卡圖像中提取卡號信息,并根據卡號首數字判斷銀行卡類型。

技術棧

  • ?OpenCV: 計算機視覺庫,用于圖像處理和特征提取
  • ?NumPy: 科學計算庫,用于數組操作和數值計算
  • ?argparse: 命令行參數解析庫
  • ?自定義工具函數: 用于輪廓處理和圖像調整

創造函數

這里為了優化主函數的簡潔性,我們另寫了一個py文件,然后在主函數內導入。

這里寫了一個排序函數,是我們對我們在圖像中得到的輪廓進行從左到右排。

import cv2def 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](cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),key=lambda b: b[1][i],reverse=reverse))return cnts, boundingBoxes

還一個resize函數,這個和最初的resize不一樣,這個變大變小是等比變化的。

def 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

系統架構

主要思路:

? ? ? ? 先對模板圖像(包含數字的圖像)進行灰度圖處理,二值化。然后找出全部輪廓(這里輪廓是亂序的,我們用我們寫的函數,對順序進行整理),找出輪廓的的外接矩形。然后對輪廓進行裁剪,然后把用字典把圖像和對應數字保存下來。

? ? ? ? 再對我們要檢測的圖像進行處理。灰度圖,二值化,然后進行圖像形態學處理(把我們的數字變的更明顯,然后把背景給去除),找出我們的所在位置。然后裁剪出來,然后對每一個圖像再進行每一個數字的定位。然后再對比,找出最大值的對應的索引,然后再保存就ok了。

代碼詳解

1 模板處理

image=cv2.imread(args["template"])
cv_show("image", image)
ref=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv_show("ref", ref)

先進行二值化處理,不過我們的的圖像原本就是二值化的,所以沒啥區別

這里進行了一次圖像轉化,因為輪廓檢測對白色檢測。原本是黑色的。

ref=cv2.threshold(ref,127,255,cv2.THRESH_BINARY_INV)[1]
cv_show("ref", ref)

refCount,_=cv2.findContours(ref,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(image,refCount,-1,(0,255,0),3)
cv_show("ref", image)
refCnts=myfun.sort_contours(refCount,method='left-to-right')[0]

把每個輪廓畫出,并進行排序。


digits={}
for (i, cnt) in enumerate(refCnts):(x, y, w, h) = cv2.boundingRect(cnt)roi = ref[y:y+h, x:x+w]roi=cv2.resize(roi,(57,88))cv2.imshow("ROI", roi)digits[i] = roi
print(digits)

然后把每個數字的輪廓找外界矩形,然后保存下來

裁剪成這樣,然后再保存下來。

2 圖片處理

傳入圖片進行展示

進行二值化處理

gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv_show("gray", gray)

定義核

rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
squareKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))

這里比較大,效果好。

進行頂帽處理

????????頂帽操作是原圖像與開運算之間的差。開運算是先腐蝕后膨脹,頂帽操作用于突出比周圍亮的區域,常用于增強圖像中的細小亮細節或去除不均勻光照。如下圖,我們用原圖減去我們進行開運算的圖,就可以看到我們數字的地方消失了,只剩背景了,減去之后就剛好只剩數字了。

tophat=cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,rectKernel)
cv_show("tophat", tophat)

進行腐蝕

closeX=cv2.morphologyEx(gray,cv2.MORPH_CLOSE,rectKernel)
cv_show("closeX", closeX)

這樣我們的數字就更好選取一點了,然后這里四個一組可以直接選取了,注意這里我們要觀察數字的特征,以便于我們對輪廓更好選取。

進行二值處理

thresh=cv2.threshold(closeX,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show("thresh", thresh)

畫出輪廓

threshCnts,h=cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts=threshCnts
cur_img=img.copy()
cv2.drawContours(cur_img,cnts,-1,(0,255,0),3)

對數字部分排序

cv_show("cur_img", cur_img)
locs=[]
for (i, cnt) in enumerate(cnts):(x, y, w, h) = cv2.boundingRect(cnt)ar=w/float(h)if ar>2.5 and ar<4.0:if (w>40 and h<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):groupOutput = []group = gray[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)# 計算每一組的輪廓digitCnts, hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)digitCnts = myfun.sort_contours(digitCnts, method="left-to-right")[0]# 計算每一組中的每一個數值for c in digitCnts:# 找到當前數值的輪廓, resize成合適的大小(x, y, w, h) = cv2.boundingRect(c)roi = group[y:y + h, x:x + w]roi = cv2.resize(roi, (57, 88))cv_show('roi', roi)# 使用模板匹配,計算匹配得分scores = []# 在模板中計算每一個得分for (digit, digitROI) in digits.items():# 模板匹配result = cv2.matchTemplate(roi, digitROI, cv2.TM_CCOEFF)(_, score, _, _) = cv2.minMaxLoc(result)scores.append(score)# 得到最合適的數字groupOutput.append(str(np.argmax(scores)))# 畫出來cv2.rectangle(img, (gX - 5, gY - 5), (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)cv2.putText(img, "".join(groupOutput), (gX, gY - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)output.extend(groupOutput)  # 得到結果,將一個列表的元素添加到另一個列表的末尾。

結果展示

結論

本文介紹的銀行卡號識別系統展示了傳統計算機視覺技術在金融科技中的應用。通過合理的圖像預處理、特征提取和模板匹配,實現了較高的識別準確率。這種技術不僅適用于銀行卡識別,還可推廣到其他卡證識別場景,具有廣泛的應用前景。

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

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

相關文章

概率論第三講——多維隨機變量及其分布

文章目錄考綱n維隨機變量及其分布函數聯合分布函數邊緣分布函數二維離散型隨機變量的概率分布、邊緣分布和條件分布二維連續型隨機變量的概率密度、邊緣概率密度和條件概率密度常見的二位分布二維均勻分布二維正態分布隨機變量的相互獨立性概念相互獨立的充要條件相互獨立的性質…

純軟件實現電腦屏幕錄制/存儲到硬盤錄像機/onvif模擬器/onvif虛擬監控/綠色版雙擊開箱即用

一、前言說明 在銀行、超市、考試中心、工控系統、網課教學、居家辦公等場景中&#xff0c;傳統監控攝像頭難以清晰錄制電腦屏幕內容&#xff0c;導致關鍵操作無法有效追溯。為解決這一難題&#xff0c;我們推出了一套純軟件實現的電子屏幕監控方案&#xff0c;徹底取代依賴硬…

【算法--鏈表】86.分割鏈表--通俗講解

一、題目是啥?一句話說清 給你一個鏈表和一個值 x,把鏈表分成兩部分:所有小于 x 的節點都放在大于或等于 x 的節點之前,并且保持節點原來的相對順序。 示例: 輸入:head = [1,4,3,2,5,2], x = 3 輸出:[1,2,2,4,3,5](所有小于3的節點1、2、2都在大于等于3的節點4、3、5…

707, 設計鏈表, LinkedList, 單鏈表, Dummy Head, C++

目錄 題意速覽解題思路與設計要點C 代碼實現&#xff08;單鏈表 虛擬頭結點&#xff09;時間復雜度與空間復雜度常見坑位與邊界用例對比&#xff1a;雙鏈表如何優化單元測試樣例&#xff08;可直接粘貼運行&#xff09;總結 題意速覽 設計一個支持如下操作的鏈表&#xff1a…

NAS自建筆記服務leanote2

leanote2(GitHub - wiselike/leanote2: leanote2, 適用于NAS自建的筆記服務) 是一個開源的在線筆記應用程序&#xff0c;繼承自原 leanote 項目。向原 leanote 的開發者表示深深的感謝與尊重&#xff0c;正是他們的辛勤付出奠定了這個優秀的筆記平臺的基礎。 但由于 leanote 項…

模型剪枝----ResNet18剪枝實戰

剪枝 模型剪枝&#xff08;Model Pruning&#xff09; 是一種 模型壓縮&#xff08;Model Compression&#xff09; 技術&#xff0c;主要思想是&#xff1a; 深度神經網絡里有很多 冗余參數&#xff08;對預測結果貢獻很小&#xff09;。 通過去掉這些冗余連接/通道/卷積核&am…

K8S-Pod(上)

Pod概念 Pod 是可以在 Kubernetes 中創建和管理的、最小的可部署的計算單元。 Pod是一組&#xff08;一個或多個&#xff09;容器&#xff1b;這些容器共享存儲、網絡、以及怎樣運行這些容器的規約。Pod 中的內容總是并置&#xff08;colocated&#xff09;的并且一同調度&am…

Flink TaskManager日志時間與實際時間有偏差

Flink 啟動一個任務后&#xff0c;發現TaskManager上日志時間與實際時間相差約 15 小時。 核心原因可能是&#xff1a; 1、 服務器&#xff08;或容器&#xff09;的系統時間配置錯誤2、 Flink 日志組件&#xff08;如 Logback/Log4j&#xff09;的時間配置未使用系統默認時區…

Webug3.0通關筆記18 中級進階第06關 實戰練習:DisCuz論壇SQL注入漏洞

目錄 一、環境搭建 1、服務啟動 2、源碼解壓 3、構造訪問靶場URL 4、靶場安裝 5、訪問論壇首頁 二、代碼分析 1、源碼分析 2、SQL注入分析 三、滲透實戰 &#xff08;1&#xff09;判斷是否有SQL注入風險 &#xff08;2&#xff09;查詢賬號密碼 Discuz! 作為國內知…

SWEET:大語言模型的選擇性水印

摘要背景與問題大語言模型出色的生成能力引發了倫理與法律層面的擔憂&#xff0c;于是通過嵌入水印來檢測機器生成文本的方法逐漸發展起來。但現有工作在代碼生成任務中無法良好發揮作用&#xff0c;原因在于代碼生成任務本身的特性&#xff08;代碼有其特定的語法、邏輯結構&a…

FastDFS V6雙IP特性及配置

FastDFS V6.0開始支持雙IP&#xff0c;tracker server和storage server均支持雙IP。V6.0新增特性說明如下&#xff1a;支持雙IP&#xff0c;一個內網IP&#xff0c;一個外網IP&#xff0c;可以支持NAT方式的內網和外網兩個IP&#xff0c;解決跨機房或混合云部署問題。FastDFS雙…

筆記本、平板如何成為電腦拓展屏?向日葵16成為副屏功能一鍵實現

向日葵16重磅上線&#xff0c;本次更新新增了諸多實用功能&#xff0c;提升遠控效率&#xff0c;實現應用融合突破設備邊界&#xff0c;同時全面提升遠控性能&#xff0c;操作更順滑、畫質更清晰&#xff01;無論遠程辦公、設計、IT運維、開發還是游戲娛樂&#xff0c;向日葵16…

基于Spring Boot + MyBatis的用戶管理系統配置

我來為您詳細分析這兩個配置文件的功能和含義。 一、文件整體概述 這是一個基于Spring Boot MyBatis的用戶管理系統配置&#xff1a; UserMapper.xml&#xff1a;MyBatis的SQL映射文件&#xff0c;定義了用戶表的增刪改查操作application.yml&#xff1a;Spring Boot的核心配置…

80(HTTP默認端口)和8080端口(備用HTTP端口)區別

文章目錄**1. 用途**- **80端口**- **8080端口****2. 默認配置**- **80端口**- **8080端口****3. 聯系**- **邏輯端口**&#xff1a;兩者都是TCP/IP協議中的邏輯端口&#xff0c;用于標識不同的網絡服務。- **可配置性**&#xff1a;端口號可以根據需要修改&#xff08;例如將T…

【開題答辯全過程】以 汽車知名品牌信息管理系統為例,包含答辯的問題和答案

個人簡介一名14年經驗的資深畢設內行人&#xff0c;語言擅長Java、php、微信小程序、Python、Golang、安卓Android等開發項目包括大數據、深度學習、網站、小程序、安卓、算法。平常會做一些項目定制化開發、代碼講解、答辯教學、文檔編寫、也懂一些降重方面的技巧。感謝大家的…

從全棧工程師視角解析Java與前端技術在電商場景中的應用

從全棧工程師視角解析Java與前端技術在電商場景中的應用 面試背景介紹 面試官&#xff1a;你好&#xff0c;很高興見到你。我叫李明&#xff0c;是這家電商平臺的資深架構師。今天我們會聊聊你的技術能力和項目經驗。你可以先簡單介紹一下自己嗎&#xff1f; 應聘者&#xff1a…

【python】python進階——多線程

引言在現代軟件開發中&#xff0c;程序的執行效率至關重要。無論是處理大量數據、響應用戶交互&#xff0c;還是與外部系統通信&#xff0c;常常需要讓程序同時執行多個任務。Python作為一門功能強大且易于學習的編程語言&#xff0c;提供了多種并發編程方式&#xff0c;其中多…

【JavaEE】(23) 綜合練習--博客系統

一、功能描述 用戶登錄后&#xff0c;可查看所有人的博客。點擊 “查看全文” 可查看該博客完整內容。如果該博客作者是登錄用戶&#xff0c;可以編輯或刪除博客。發表博客的頁面同編輯頁面。 本練習的博客網站&#xff0c;并沒有添加注冊功能&#xff0c;以及上傳作者頭像功能…

MySQL全庫檢索關鍵詞 - idea 工具 Full-Text Search分享

我們經常要在庫中查找一個數據&#xff0c;又不知道在哪個表、哪個字段&#xff1b;或者想找到哪里有在用這個數據。我們可以用&#xff1a;idea 的 Database工具 - Full-Text Search打開idea&#xff0c;在工具欄找到 Database 然后新建自己的連接&#xff0c;然后右鍵&#x…

銀行卡號識別案例

代碼實現&#xff1a;import cv2 import numpy as np import argparse import myutils-i moban.png -t card1.pngap argparse.ArgumentParser() ap.add_argument("-i","--image", requiredTrue,help"path to input image") ap.add_argument(&quo…