python 实现银行卡号查询银行名称和简称功能
作者:Roc-xb
本章教程利用python实现查询银行卡号名称和简称 。
一、 实例代码
#!/usr/bin/python # -*- coding: UTF-8 -*- """ @author: Roc-xb @desc: python 实现银行卡号查询银行简称 """ import requests def bank_mes(bank_no): try: url = "https://ccdcapi.alipay.com/validateAndCacheCardInfo.json?_input_charset=utf-8&cardNo={}&cardBinCheck=true" data = requests.get(url.format(bank_no)).json() bank_abbr = data['bank'] bank_map = { "ICBC": "中国工商银行", "ABC": "中国农业银行", "CCB": "中国建设银行", "CMB": "招商银行", "BOC": "中国银行", "PSBC": "中国邮政储蓄银行", "COMM": "交通银行", "CITIC": "中信银行", "CMBC": "中国民生银行", "CEB": "中国光大银行", "CIB": "兴业银行", "SPDB": "浦发银行", "GDB": "广发银行", "SPABANK": "平安银行", "HXBANK": "华夏银行", "BJBANK": "北京银行", "SHBANK": "上海银行", "JSBANK": "江苏银行", "BJRCB": "北京农商银行", "JSRCU": "江苏省农村信用社联合社", "BOYK": "营口银行", "WOORI": "友利银行", "DZLCYRCZYH": "陵城圆融村镇银行", "BXBANK": "本溪市商业银行", "WHBANK": "乌海银行", "AXDSCB": "安新大商村镇银行", "RQCZYH": "任丘村镇银行", "JXRCU": "江西省农村信用社", "JKRFCZYH": "长春经开融丰村镇银行", "BOHN": "海南省农村信用社", "CRCBANK": "重庆农村商业银行", "ASCB": "鞍山银行", "LLVB": "兰陵村镇银行", "UBCHN": "海口联合农商银行", "BSB": "蒙商银行", "MMDBCJCZYH": "天水秦州长银村镇银行", "CSRCB": "常熟农商银行", "NJMSCZYH": "固始天骄村镇银行", "IELZSXHDCZYH": "稷山县河东村镇银行", "FSVB": "丰南舜丰村镇银行", "JSB": "晋商银行", "HURCB": "湖北省农信社", "ZGCBANK": "北京中关村银行", "EGBANK": "恒丰银行", "SQZYFDCZYH": "贵阳花溪建设村镇银行", "YJSHCB": "永济市三禾村镇银行有限责任公司", "GXYHGMCZYH": "长春二道农商村镇银行", "SDLJB": "山东利津舜丰村镇银行", "LSBANK": "莱商银行", "JHBANK": "金华银行", "LSBC": "临商银行", "YZBANK": "银座村镇银行", "XMBANK": "厦门银行", "XNZJCZYH": "深圳龙岗鼎业村镇银行", "JXYMYH": "江西裕民银行股份有限公司", "DBSHMCZYH": "调兵山惠民村镇银行", "DRCBCL": "东莞农村商业银行", "RBOZ": "珠海华润银行", "PZHCCB": "四川银行", "GDRCC": "广东省农村信用社联合社", "HANABANK": "韩亚银行", "TLSHCB": "屯留三禾村镇银行", "MTBANK": "浙江民泰商业银行", "LANGFB": "廊坊银行", "BOJZ": "锦州银行", "TJBHB": "天津滨海农村商业银行", "LLBJSJJRFCZYH": "东丰吉银村镇银行", "HSBANK": "徽商银行", "NNJNGMCZYH": "南宁江南国民村镇银行", "NXRCU": "宁夏黄河农村商业银行", "FXLZCB": "费县梁邹村镇银行", "QLBANK": "齐鲁银行", "WRCB": "无锡农村商业银行", "CGXYYH": "长葛轩辕村镇银行", "IBK": "企业银行", "BANKWF": "潍坊银行", "CZBANK": "浙商银行", "LQRB": "临朐村镇银行", "ZYTYCZYH": "宁夏西吉汇发村镇银行", "HRXJB": "湖南银行", "YBF": "豫丰村镇银行", "JZCBANK": "焦作中旅银行", "TLXXCZYH": "铁岭新星村镇银行", "SDSHHJCZYH": "山东商河汇金村镇银行", "WCYRCZYH": "武城圆融村镇银行", "HKBEA": "东亚银行", "GZRCU": "贵州省农村信用社联合社", "LPSZSLDCZYH": "六盘水钟山凉都村镇银行", "RHMYCZYH": "仁怀蒙银村镇银行", "ZZYH": "枣庄银行", "HYXHNSCZYH": "宁夏永宁汇发村镇银行", "LLYRCZYH": "乐陵圆融村镇银行", "ZRCBANK": "张家港农村商业银行", "QHJRCB": "清河金农村镇银行", "WYYCCZYH": "舞阳玉川村镇银行", "DCSFCZYH": "大城舜丰村镇银行", "QDCCB": "青岛银行", "HDCB": "黔西花都村镇银行", "ARCU": "安徽省农村信用社", "SDLCYRCZYH": "历城圆融村镇银行", "QLXACZYH": "隰县新田村镇银行", "ZGCCB": "自贡银行", "ALEJHCB": "阿拉尔津汇村镇银行", "BOHAIB": "渤海银行", "SDEB": "顺德农商银行", "HBC": "湖北银行", "LYCB": "辽阳银行", "FXCB": "阜新银行", "PSATCZYH": "盘山安泰村镇银行", "WJRCB": "苏州农村商业银行", "SDZFQFCZYH": "山东芝罘齐丰村镇银行", "HBFNJXCZYH": "乳山天骄村镇银行", "HSB": "恒生银行", "NYBANK": "广东南粤银行", "BGB": "广西北部湾银行", "DAQINGB": "龙江银行", "CDCB": "成都银行", "DZCBANK": "达州市商业银行", "HLDB": "葫芦岛银行", "ZZZYFDCZYH": "平遥县晋融村镇银行", "ZYBZHLCZYH": "遵义播州汇隆村镇银行", "HEBXFCZYH": "平舆玉川村镇银行", "WZCB": "温州银行", "ZJSYHTCZYH": "浙江松阳恒通村镇银行", "H3CB": "内蒙古银行", "GRCB": "广州农村商业银行", "HSBC": "汇丰银行(中国)", "QHRC": "青海省农村信用社", "LSCCB": "乐山市商业银行", "SZSBK": "石嘴山银行", "SINO": "永丰银行", "CCQTGB": "重庆三峡银行", "HSBK": "衡水市商业银行", "NJXLRB": "内江村镇银行", "GYGSB": "广元贵商村镇银行", "SXBANK": "三湘银行", "CJYMCZYH": "沙河襄通村镇银行", "WAHDCZYH": "平阴蓝海村镇银行", "DLB": "大连银行", "BHB": "河北银行", "LYJDCZYH": "莱阳胶东村镇银行", "AMBZJDYFMCZYH": "包头市昆都仑蒙银村镇银行", "SXQNRCB": "陕西秦农农村商业银行股份有限公司", "YQCCB": "阳泉市商业银行", "XTB": "邢台银行", "SJBANK": "盛京银行", "DYCCB": "东营银行", "SDZHQYCZYH": "山东沾化青云村镇银行", "BDCBANK": "保定银行", "DZBANK": "德州银行", "ANTBANK": "网商银行", "ZJNX": "浙江农商联合银行", "PZBANK": "盘锦银行", "CSCB": "长沙银行", "PBDLCZYH": "平坝鼎立村镇银行", "ZQQLCZYH": "天镇县河东村镇银行", "HZCB": "杭州银行", "JZBANK": "晋中银行", "BOCFCB": "中银富登村镇银行", "RCXNSCZYH": "石阡长征村镇银行", "SRCB": "深圳农村商业银行", "QHSRB": "黄岛舜丰村镇银行", "YACCB": "雅安市商业银行", "ZYB": "中原银行", "SDRCU": "山东省农村信用社联合社", "BOHUIHE": "新疆汇和银行", "QLCZYH": "青隆村镇银行", "GCB": "广州银行", "SXRCCU": "陕西省农信社", "XJRCU": "新疆农村信用社", "JLBANK": "吉林银行", "TACCB": "泰安银行", "GYCB": "贵阳银行", "GSBANK": "甘肃银行", "SDLZHJCZYH": "山东临淄汇金村镇银行", "LSYH": "辽沈银行", "XHCZYH": "新华村镇银行", "HHRXCZYH": "兰西农商村镇银行", "NXTXJHCB": "宁夏同心津汇村镇银行", "NBIZJZSCZCZYH": "松桃长征村镇银行", "RZB": "日照银行", "DHDYCZYH": "德惠敦银村镇银行", "KLB": "昆仑银行", "XZBANK": "西藏银行", "JJBANK": "九江银行", "SXRCU": "山西省农村信用社", "HNBANK": "海南银行股份有限公司", "DJCZCZYH": "德江长征村镇银行", "CGNB": "四川天府银行", "WHFMCZYH": "威海富民村镇银行", "CZCB": "浙江稠州商业银行", "WZMSBANK": "温州民商银行", "ETKQHZCB": "鄂托克旗汇泽村镇银行股份有限公司", "QWXXTCZYH": "阜平大商村镇银行", "SHRCB": "上海农商银行", "SNCCB": "遂宁银行", "TLBANK": "铁岭银行", "NDHB": "宁波东海银行", "NXBANK": "宁夏银行", "NMGNXS": "内蒙古农村信用社联合社", "SNBANK": "苏宁银行", "ZQZSGYCZYH": "虞城通商村镇银行", "DBSCN": "星展银行", "HBRCU": "河北省农村信用社", "LXHRCZYH": "岚县慧融村镇银行", "GYBYDXCZYH": "贵阳白云德信村镇银行", "LNRCC": "辽宁农商银行", "DYLSCB": "东营莱商村镇银行", "TCCB": "天津银行", "BOQZ": "泉州银行", "NBBANK": "宁波银行", "WHRCB": "武汉农村商业银行", "ZYYCCZYH": "正阳玉川村镇银行", "NCB": "江西银行", "ZJKCCB": "张家口银行", "JNBANK": "济宁银行", "KELFMCZ": "库尔勒富民村镇银行", "XCXPCZYH": "许昌新浦村镇银行", "EEDSSHTCZYH": "鄂尔多斯市罕台村镇银行", "KLLACB": "垦利乐安村镇银行", "HRBANK": "哈尔滨银行", "BOQH": "青海银行", "YBCCB": "宜宾市商业银行", "NJNKCZYH": "南江农科村镇银行", "LTSFRB": "乐亭村镇银行", "LZYH": "兰州银行", "NJCB": "南京银行", "JINCHB": "晋城银行", "TZCB": "台州银行", "CQBANK": "重庆银行", "SXBA": "山西银行", "PYYRCZYH": "平原圆融村镇银行", "URB": "联合村镇银行", "FDB": "富滇银行", "LYRTCZYH": "长春绿园融泰村镇银行", "SCRCU": "四川省农村信用社联合社", "AHXABANK": "安徽新安银行", "GAXQB": "贵安新区发展村镇银行", "YTBANK": "烟台银行", "DLRCB": "大连农村商业银行", "PCNKCZYH": "平昌农科村镇银行", "QYLACZYH": "庆云乐安村镇银行", "NYCB": "南阳村镇银行", "ASXHNMCZYH": "安顺西航南马村镇银行", "BTSDHJGCZYH": "江口长征村镇银行", "QHDBANK": "秦皇岛银行", "SDHMB": "山东惠民舜丰村镇银行", "NBCBANK": "宁波通商银行", "JXRJGDCB": "江西瑞金光大村镇银行", "SRBANK": "上饶银行", "BJCPBSCZYH": "哈尔滨阿城农商村镇银行", "HNRCU": "河南省农村信用社", "RXBANK": "瑞信村镇银行", "HNSSXNSCZYH": "山东金乡蓝海村镇银行", "MZKSB": "梅州客商银行", "SHZGMCZYH": "平陆县河东村镇银行", "BOSZ": "苏州银行", "YXCCB": "云南红塔银行", "SCMYCZYH": "水城蒙银村镇银行", "XIB": "厦门国际银行", "BOCD": "承德银行", "HUAMINGBANK": "华明村镇银行", "YYBSCB": "博商银行", "HNRCC": "湖南省农村信用社", "XABANK": "西安银行", "TRCB": "天津农商银行", "BOSH": "新韩银行", "GHB": "广东华兴银行", "CCHRCZYH": "长春朝阳和润村镇银行", "CZRCB": "江南农村商业银行", "URMQCCB": "乌鲁木齐银行", "MYBANK": "绵阳市商业银行", "HDBANK": "邯郸银行", "JRCB": "江苏江阴农村商业银行", "CITICN": "花旗银行(中国)", "KJCZYH": "梅县客家村镇银行", "ZJQZQJSYCZYH": "衢江上银村镇银行", "HLJRCU": "黑龙江省农村信用社联合社", "XJB": "新疆银行", "KCBEBANK": "天津金城银行", "DYCB": "长城华西银行", "QAXLCB": "迁安襄隆村镇银行", "BOD": "东莞银行", "NCBANK": "南洋商业银行", "WHCCB": "威海市商业银行", "BOCZ": "沧州银行", "BOCY": "朝阳银行", "CABANK": "长安银行", "BOL": "中原银行洛阳分行", "HKB": "汉口银行", "WSQBSCZYH": "江苏江都吉银村镇银行", "BOP": "平顶山银行", "GXRCU": "广西壮族自治区农村信用社联合社", "SXCB": "绍兴银行", "YJHLLLCZYH": "神池县河东村镇银行", "PTFMCZYH": "都匀融通村镇银行", "HNCMCJCZYH": "夏县河东村镇银行", "YKYHCCB": "营口沿海银行", "FJNX": "福建省农村信用社联合社", "ZBCB": "齐商银行", "GZB": "赣州银行", "HZCCB": "湖州银行", "GXPNGYCZYH": "浙江文成北银村镇银行", "QJCCB": "曲靖市商业银行", "ZJLXYSCZYH": "浙江兰溪越商村镇银行", "ZXBXBANK": "百信银行", "JXBANK": "嘉兴银行", "WACZYH": "武安村镇银行", "KSRB": "昆山农村商业银行", "FJHXBC": "福建海峡银行", "BDXHRCZYH": "保德县慧融村镇银行", "ZYCBANK": "贵州银行", "KYHNSCZYH": "国民村镇银行", "YGCB": "前郭县阳光村镇银行", "AHDYMFCZYH": "泌阳玉川村镇银行", "SDZPQLCZYH": "芜湖圆融村镇银行", "ZJTLCB": "浙江泰隆商业银行", "NHB": "南海农商银行", "CJCCB": "江苏长江商业银行", "FBBANK": "富邦华一银行", "LZCCB": "柳州银行", "FSCB": "抚顺银行", "LJYSCJCZYH": "闻喜县晋融村镇银行", "QJHMCB": "曲靖惠民村镇银行", "GYSFCB": "廊坊市广阳舜丰村镇银行股份有限公司", "CZCCB": "长治银行", "NXQTXHLSCZYH": "宁夏青铜峡贺兰山村镇银行", "BQGYCZYH": "陕西周至农科村镇银行", "LUZBANK": "泸州银行", "TJNHCZYH": "天津宁河村镇银行", "GSRCU": "甘肃省农村信用社", "GLBANK": "桂林银行", "PDHF": "大洼恒丰村镇银行", "ZZBANK": "郑州银行", "SDGQHJCZYH": "山东高青汇金村镇银行", "TCRCB": "江苏太仓农村商业银行", "HSCZB": "湖商村镇银行", "CDRCB": "成都农商银行", "YSXRCZYH": "元氏信融村镇银行", "YTFSZJCZYH": "汝州玉川村镇银行", "WZYTMGJHCZYH": "铁门关津汇村镇银行", "ZYXPCZCB": "遵义新蒲长征村镇银行", "YDNSCZYH": "尧都农商银行村镇银行", "GYRCB": "贵阳农村商业银行", "ORBANK": "鄂尔多斯银行", "BZSFCB": "霸州舜丰村镇银行", "NBYZ": "宁波鄞州农商行", "SCB": "渣打银行", "JLRCU": "吉林省农村信用社联合社", "YNRCC": "云南省农村信用社", "OJASZCFCZYH": "宁夏彭阳贺兰山村镇银行" } bank_name = bank_map[bank_abbr] print("银行卡号:{}".format(bank_no)) print("银行名称:{}".format(bank_name)) print("银行简称:{}".format(bank_abbr)) except Exception as e: print("银行卡号输入有误:{}".format(e)) if __name__ == '__main__': bank_mes("6217001340011005638")
二、运行效果
基于PyQT5+OpenCv实现银行卡号识别
一、实训内容
选择合适的算法,编写程序进行信用卡号识别;制作交互式用户界面,实现一个能读入信用卡图片并识别信用卡号的系统,系统界面上需要对输入图像、识别结果等进行展示。并对实验结果进行分析,评价算法性能。
二、实现思路
2.1.Python工具和库的选择
选择使用Python工具和库来实现信用卡号识别系统,安装Python所需要使用的库OpenCV、numpy、os、sys、PyQt5、pytesseract、QT Desinger、contours等。确保选择的工具和库提供了所需的图像处理功能,并且易于使用和集成到银行卡识别系统中。
2.2.主程序界面实现思路
该模块主要是实现了一个基于PyQt5的信用卡号识别系统的UI设计,包含有一个Mywindow类的定义和2个功能窗口类的定义以及两个自定义函数。算法原理主要包括以下几个部分:
1.导入需要使用的模块和库:从PyQt5中导入QApplication、QMainWindow、QFileDialog等类,从PyQt5.QtGui中导入用于图像操作的类,从cv2和numpy库中导入用于图像处理的模块,从card_recognize.py模块中导入信用卡号识别的功能。
2.导入UI文件:通过from card_re import Card_re_Window语句将识别信用卡号的窗口的UI文件导入到主程序中。这个UI文件使用Qt Designer软件设计而成,包含了各个窗口的布局、控件和信号槽等信息。
3.创建主窗口并设置UI:自定义一个 MyWindow 类继承于 QMainWindow 和 Ui_Mainwindow,用于界面的初始化和 button 的信号链接。 先调用父类的构造函数进行界面的初始化,加载界面。
4.窗口类的定义:定义了Card_re_class类,该类继承了QMainWindow和对应的UI界面类,如Card_re_class继承了QMainWindow和Card_re_Window类。这些类中定义了对应功能窗口上的按钮、标签、图像显示区等控件,并实现了对应的功能函数,如打开和保存文件、选择文件夹等操作,将图像数据加载到内存中,然后对其进行操作和显示。
5.实现窗口间的跳转:MyWindow类添加了function1、function2两个方法,分别对应主界面上的2个功能按钮。每个方法调用对应的功能窗口类,并且关闭当前界面。这样,当用户点击主界面上的某个功能按钮时,就会自动打开对应的功能窗口,实现了不同功能窗口之间的切换。
6.添加图标:使用QIcon类给窗口添加图标的功能,为窗口添加南阳理工学院校徽图标以增强软件的视觉效果和用户体验,同时也给代码增添了一些标志性特点。
7.两个自定义函数:主要实现了将Qt中的QPixmap对象转换为OpenCV中的Mat对象,以及将OpenCV中的Mat对象转换为Qt中的QImage或QPixmap对象。
总体思路是通过PyQt5信用卡号识别系统的GUI界面,将不同的功能模块分别设计为不同的窗口,用户可以在主界面上选择要进行的操作,然后跳转到相应的功能窗口进行图像处理。
2.3.对模板图片进行预处理
对模板图片进行处理,这部分的主要作用是对一个数字模板(t_img.png)进行图像处理,提取其中的数字轮廓和特征,并将以此识别的外轮廓分割存储到一个列表变量 digits 中,以便后续识别图像时比对。
2.4.对轮廓排序处理
这部分实现对轮廓进行排序的功能。它可以按照指定的排序方法,对一组轮廓 cnts 进行排序,并返回排序后的轮廓集合和对应的外接矩形列表。
2.5.对信用卡进行卡号识别
这部分是代码的核心,主要对输入的信用卡图片进行解析处理,提取出所需要的卡号部分,对卡号部分计算外接矩形,然后分割为每一个数字轮廓为一部分,最后对每个数字轮廓与模板数字轮廓比对,选取得分最高的即认为该数字模板为数字号码,最后将号码输出。
具体思路为:初始化卷积核:rectKernel 和 sqKernel,用于后续进行形态学操作。对输入的图片进行预处理操作:调整尺寸为宽度为 300,转换为灰度图像。使用礼帽(顶帽)操作突出更明亮的区域,使用 Sobel 算子进行边缘检测,对结果进行归一化和二值化。对二值化结果进行闭操作,即先膨胀再腐蚀,将数字连在一起。对闭操作后的结果,再次进行闭操作,对缝隙进行填充。对闭操作后的结果进行轮廓检测,找到符合要求的轮廓区域。将符合要求的轮廓从左到右排序,并遍历每一个轮廓中的数字。根据坐标提取每一个数字组,对每个数字组进行预处理并进行轮廓检测,计算每个数字的匹配得分。找到合适的数字并输出,画出每个数字所在的矩形框。
流程图如下:
三、程序代码
主界面代码:
# UI设计 import sys from PyQt5.QtWidgets import QApplication,QMainWindow # 用于打开和保存文件、选择文件夹等操作 from PyQt5.QtWidgets import QFileDialog # 将图像数据加载到内存中,然后对其进行操作和显示 from PyQt5.QtGui import * # 导入Ui from main_win import Ui_Mainwindow from card_re import Card_re_Window # 给窗口添加图标 from PyQt5.QtGui import QIcon # 银行卡识别 import card_recognize # 图像处理 import cv2 import numpy as np class MyWindow(QMainWindow,Ui_Mainwindow): def __init__(self): # 调用父类构造函数 super().__init__() # 使用 Ui_MainWindow 类中的 setupUi 方法来加载界面 self.setupUi(self) # 创建图标对象并设置窗口图标 self.setWindowIcon(QIcon("logo_64.png")) # 按钮信号链接 self.pushButton1.clicked.connect(self.function1) def function1(self): self.fun1=Card_re_class() self.fun1.show() self.close() class Card_re_class(QMainWindow,Card_re_Window): def __init__(self): super(Card_re_class,self).__init__() # 加载UI self.setupUi(self) # 创建图标对象并设置窗口图标 self.setWindowIcon(QIcon("logo_64.png")) # 按钮信号链接 self.pushButton_return.clicked.connect(self.push_return) self.pushButton_upload.clicked.connect(self.openimage) self.pushButton_save.clicked.connect(self.saveimage) self.pushButton_card_re.clicked.connect(self.fun) def push_return(self): self.Re_main = MyWindow() # 关闭当前窗口 self.close() # 打开新窗口 self.Re_main.show() def openimage(self): # 打开一个文件选择对话框,让用户选择要打开的图片文件 fname = QFileDialog.getOpenFileName(self, '打开图片', './', "Images (*.png *.jpg *.bmp)") # 检查是否选择了一个文件,fname 不为空,则进入下面的代码块 if fname[0]: # 使用 QPixmap 函数从文件路径创建一个 QPixmap 对象 # 然后使用 setPixmap 方法将其设置为 label_daichuli 控件的图片 self.label_daichuli.setPixmap(QPixmap(fname[0])) # 自动换行功能,确保图片可以完全显示在控件中 self.label_daichuli.setWordWrap(True) # 调整为图片大小,以确保图片不会被缩小或拉伸 self.label_daichuli.setScaledContents(True) def saveimage(self): # 打开一个文件选择对话框,让用户选择要保存的图片文件 nfname = QFileDialog.getSaveFileName(self, "保存图片", "./", "Images (*.png *.jpg *.bmp)") if nfname[0]: # 使用pixmap()方法获取label_jieguo标签中的当前图像 # 然后使用save()方法将其保存到用户指定的文件名nfname[0]中 self.label_jieguo.pixmap().save(nfname[0]) def fun(self): # # 获取图像信息,并存储在qimg中,pixmap()方法返回一个QPixmap对象,表示标签中显示的图像 qimg = self.label_daichuli.pixmap() # 将QImage对象格式图像信息转换为numpy数组格式 src = qimage_to_mat(qimg) # 使用自定义模块,将彩色图转换为灰度图像 newsrc,re_text= card_recognize.main_run(src) # 将numpy数组格式的图像数据转化为QImage对象格式的图像数据 pix = mat_to_qimage(newsrc) # 将图像显示在名为结果的标签中,setPixmap()方法接受一个QPixmap对象作为参数,并将其设置为标签中的图像 self.label_jieguo.setPixmap(pix) # setWordWrap()方法接受一个布尔值参数,如果设置为True,则文本将自动换行 self.label_jieguo.setWordWrap(True) # setScaledContents()方法接受一个布尔值参数,如果设置为True,则标签将自动缩放其内容以适应标签大小 self.label_jieguo.setScaledContents(True) ###########在 QLabel 控件中显示识别的文本 self.label_cardnum.setText(re_text) # setWordWrap()方法接受一个布尔值参数,如果设置为True,则文本将自动换行 self.label_cardnum.setWordWrap(True) # setScaledContents()方法接受一个布尔值参数,如果设置为True,则标签将自动缩放其内容以适应标签大小 self.label_cardnum.setScaledContents(True) ################################################################################## def qimage_to_mat(qtpixmap): #qtpixmap转opencv # 将输入的QPixmap对象转换成了一个QImage对象 qimg = qtpixmap.toImage() # 计算了输出的NumPy数组的形状。height是图像的高度,bytesPerLine是每行扫描线的字节数,depth是每个像素的位数 temp_shape = (qimg.height(), qimg.bytesPerLine() * 8 // qimg.depth()) # 将形状元组添加了第四个维度。第四个维度表示RGBA颜色通道 temp_shape += (4,) ptr = qimg.bits() # 获取了指向QImage对象内存缓冲区的指针,并将指针大小设置为QImage对象的大小(以字节为单位) ptr.setsize(qimg.byteCount()) # 创建了一个NumPy数组。该数组的形状为temp_shape,数据类型为uint8 result = np.array(ptr, dtype=np.uint8).reshape(temp_shape) # 丢弃图像的第四个(alpha)通道。结果得到的NumPy数组的形状为(height, width, 3),表示图像的RGB颜色通道 result = result[..., :3] # 将NumPy数组作为qimage2mat函数的输出 return result def mat_to_qimage(cvimg): #opencv转QImage # 判断输入的图像是否是单通道的,也就是灰度图像 if cvimg.ndim==2: #单通道 # 获取图像的高度和宽度 height, width= cvimg.shape # 将BGR格式的图像数据转换为RGB格式 cvimg = cv2.cvtColor(cvimg, cv2.COLOR_BGR2RGB) # 将图像数据转换为QImage对象,并使用QImage.Format_RGB888格式表示。 cvimg = QImage(cvimg.data, width, height, QImage.Format_RGB888) # 将QImage对象转换为QPixmap对象并存储在pix变量中 pix = QPixmap.fromImage(cvimg) return pix else: #多个通道 # 获取图像的高度和宽度 width = cvimg.shape[1] height = cvimg.shape[0] # 根据已知的高度和宽度新建一个空的QPixmap对象 pixmap = QPixmap(width, height) # 将QPixmap对象转换为QImage对象类型的qimg qimg = pixmap.toImage() # 嵌套循环遍历图像的所有像素,获取每个像素的红、绿、蓝三个通道的值 for row in range(0, height): for col in range(0, width): b = cvimg[row, col, 0] g = cvimg[row, col, 1] r = cvimg[row, col, 2] # 使用qRgb()函数将其转换为QColor对象 pix = qRgb(r, g, b) qimg.setPixel(col, row, pix) # 将QImage对象转换为QPixmap对象 pix = QPixmap.fromImage(qimg) return pix if __name__ == '__main__': app = QApplication(sys.argv) # app.setWindowIcon(QIcon('img.png')) 加载头像 mywindow = MyWindow() mywindow.show() sys.exit(app.exec_())
银行卡识别代码:
import cv2 import numpy as np from imutils import contours #对图像中的边缘和轮廓进行识别、分割和提取。使用imutils库的contours函数能够方便地检测到图像中的轮廓, # 并且按照一定的顺序返回,可以用于数字的识别、字符的识别等应用。 #设为全局变量 digits = {} global output output = [] #################################################图像绘图 def cv_show(name,img): cv2.imshow(name,img) cv2.waitKey(0) cv2.destroyAllWindows() ##################################################对输入的轮廓进行排序 def sort_contours(cnts,method="left-to-right"): reverse=False i=0 if method=="right-to-left" or method =="bottom-to-top": reverse=True if method=="top-to-bottom" or method=="bottom-to-top": i=1 # 在轮廓信息中计算外接矩形 boundingBoxes=[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 #重置大小,用于比较模板和图像中的数字是否一致 #插值方法如下: #INTER_NEAREST:最邻近插值 #INTER_LINEAR:双线性插值,默认情况下使用该方式进行插值. #INTER_AREA:基于区域像素关系的一种重采样或者插值方式.该方法是图像抽取的首选方法,它可以产生更少的波纹, #但是当图像放大时,它的效果与INTER_NEAREST效果相似. #INTER_CUBIC:4×4邻域双3次插值 #INTER_LANCZOS4:8×8邻域兰索斯插值 ########################################将输入的图像按照指定的宽度、高度进行缩放 def resize(image,width=None,height=None,inter=cv2.INTER_AREA): dim=None (h,w)=image.shape[:2] #(200,300,3) # 当未指定宽度和高度时,直接返回原图像。 if width is None and height is None: return image if width is None: r=height/float(h) dim=(int(w*r),height) else: r=width/float(w) dim=(width,int(h*r)) # 利用OpenCV中resize函数对图像进行缩放 resized=cv2.resize(image,dim,interpolation=inter) return resized ##################################################读取模板图片并处理########### def process_template(): # 读取一个模板文件 img = cv2.imread("t_img.png") # 灰度图 ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值图像 ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1] cv_show("ref",ref) ######################################计算轮廓 # cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图) # cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标 # 返回的list中每个元素都是图像中的一个轮廓 refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 只需要轮廓resCnts cv2.drawContours(img, refCnts, -1, (0, 0, 255), 3) cv_show("img",img) refCnts = sorted(refCnts, key=cv2.contourArea, reverse=True) refCnts = sort_contours(refCnts, method="left-to-right")[0] # 排序从左到右,从上到下 # 遍历每一个轮廓 for (i, c) in enumerate(refCnts): # 计算外接矩形并且resize成合适大小 (x, y, w, h) = cv2.boundingRect(c) # roi为外接矩形的区域 roi = ref[y:y + h, x:x + w] roi = cv2.resize(roi, (57, 58)) cv_show("ror",roi) # 每一个数字对应一个模板 digits[i] = roi #####################################################选择图片并对银行卡号识别###### def process_img(image): # 初始化卷积核 rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3)) sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) # 读取输入图像,预处理 #image = cv2.imread(img) image = resize(image, width=300) # 转灰度图 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) cv_show("gray",gray) # 礼帽(顶帽)操作,过滤掉没有用的东西,突出更明亮的区域 将核传进去 tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel) cv_show("tophat",tophat) # 计算 ...边缘检测 gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=1) # Sobel算子 gradX = np.absolute(gradX) # 绝对值 (minVal, maxVal) = (np.min(gradX), np.max(gradX)) gradX = (255 * ((gradX - minVal) / (maxVal - minVal))) # 归一化 gradX = gradX.astype("uint8") # 通过闭操作,(先膨胀,在腐蚀)将数字连在一起 gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel) cv_show("gardX",gradX) # THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0 thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] # 再次闭操作,对缝隙进行填充 thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) cv_show("thresh",thresh) # 计算轮廓 threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = threshCnts cur_img = image.copy() cv2.drawContours(cur_img, cnts, -1, (0, 0, 255), 3) cv_show('curimg', 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): # w = 46 h=13 # 符合的轮廓留下来 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] # 预处理 轮廓检测 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 = contours.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, 58)) # 计算匹配得分 scores = [] # 在模板章中计算每一个得分 for (digit, digiROI) in digits.items(): # 模板匹配 result = cv2.matchTemplate(roi, digiROI, 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) img_re=cv2.putText(image, "".join(groupOutput), (gX, gY - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2) # 得到结果 output.extend(groupOutput) return img_re def main_run(img): process_template() img2 =process_img(img) # 避免再次识别卡号重复 text = "银行卡号为: {}".format("".join(output))[-16:] text2="银行卡号为:"+text return img2,text2 if __name__ == '__main__': process_template() img=".\images\card04.png" #img = "card_01.png" process_img(img) print("银行卡号为: {}".format("".join(output)))
UI文件代码1:
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'main_win.ui' # # Created by: PyQt5 UI code generator 5.15.4 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets class Ui_Mainwindow(object): def setupUi(self, Mainwindow): Mainwindow.setObjectName("Mainwindow") Mainwindow.resize(900, 650) font = QtGui.QFont() font.setBold(True) font.setWeight(75) Mainwindow.setFont(font) Mainwindow.setStyleSheet("QPushButton{\n" " background-color:rgb(0,174,236);\n" " border:none;\n" " height:35px;\n" " border-radius:12px;\n" "}\n" "QPushButton::hover{\n" " background-color:rgb(65,184,131);\n" "}\n" "") self.frame_3 = QtWidgets.QFrame(Mainwindow) self.frame_3.setGeometry(QtCore.QRect(-10, 0, 901, 671)) self.frame_3.setStyleSheet("QFrame{\n" " background-color:rgb(255,250,240);\n" " border:none;\n" " height:35px;\n" " border-radius:12px;\n" "}") self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised) self.frame_3.setObjectName("frame_3") self.frame = QtWidgets.QFrame(self.frame_3) self.frame.setGeometry(QtCore.QRect(10, -10, 891, 391)) self.frame.setStyleSheet("QFrame{\n" " background-color:rgb(191,239,255);\n" " border:none;\n" " height:35px;\n" " border-radius:12px;\n" "}") self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) self.frame.setFrameShadow(QtWidgets.QFrame.Raised) self.frame.setObjectName("frame") self.label = QtWidgets.QLabel(self.frame) self.label.setGeometry(QtCore.QRect(320, 130, 241, 151)) font = QtGui.QFont() font.setFamily("Bahnschrift") font.setPointSize(23) self.label.setFont(font) self.label.setObjectName("label") self.pushButton1 = QtWidgets.QPushButton(self.frame_3) self.pushButton1.setGeometry(QtCore.QRect(380, 430, 110, 40)) self.pushButton1.setStyleSheet("QPushButton{\n" " background-color:rgb(0,174,236);\n" " border:none;\n" " height:35px;\n" " border-radius:12px;\n" "}\n" "QPushButton::hover{\n" " background-color:rgb(65,184,131);\n" "}") self.pushButton1.setObjectName("pushButton1") self.retranslateUi(Mainwindow) QtCore.QMetaObject.connectSlotsByName(Mainwindow) def retranslateUi(self, Mainwindow): _translate = QtCore.QCoreApplication.translate Mainwindow.setWindowTitle(_translate("Mainwindow", "银行卡号识别")) self.label.setText(_translate("Mainwindow", "银行卡号识别")) self.pushButton1.setText(_translate("Mainwindow", "选择"))
UI文件代码2:
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'card_re.ui' # # Created by: PyQt5 UI code generator 5.15.4 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets class Card_re_Window(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(900, 650) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.label_daichuli = QtWidgets.QLabel(self.centralwidget) self.label_daichuli.setGeometry(QtCore.QRect(100, 70, 300, 189)) self.label_daichuli.setObjectName("label_daichuli") self.label_jieguo = QtWidgets.QLabel(self.centralwidget) self.label_jieguo.setGeometry(QtCore.QRect(510, 70, 300, 189)) self.label_jieguo.setObjectName("label_jieguo") self.pushButton_upload = QtWidgets.QPushButton(self.centralwidget) self.pushButton_upload.setGeometry(QtCore.QRect(220, 370, 100, 35)) self.pushButton_upload.setStyleSheet("QPushButton{\n" " background-color:rgb(0,174,236);\n" " border:none;\n" " height:35px;\n" " border-radius:12px;\n" "}\n" "QPushButton::hover{\n" " background-color:rgb(65,184,131);\n" "}") self.pushButton_upload.setObjectName("pushButton_upload") self.pushButton_save = QtWidgets.QPushButton(self.centralwidget) self.pushButton_save.setGeometry(QtCore.QRect(580, 370, 100, 35)) self.pushButton_save.setStyleSheet("QPushButton{\n" " background-color:rgb(0,174,236);\n" " border:none;\n" " height:35px;\n" " border-radius:12px;\n" "}\n" "QPushButton::hover{\n" " background-color:rgb(65,184,131);\n" "}") self.pushButton_save.setObjectName("pushButton_save") self.pushButton_card_re = QtWidgets.QPushButton(self.centralwidget) self.pushButton_card_re.setGeometry(QtCore.QRect(390, 440, 110, 40)) self.pushButton_card_re.setStyleSheet("QPushButton{\n" " background-color:rgb(0,174,236);\n" " border:none;\n" " height:35px;\n" " border-radius:12px;\n" "}\n" "QPushButton::hover{\n" " background-color:rgb(65,184,131);\n" "}") self.pushButton_card_re.setObjectName("pushButton_card_re") self.pushButton_return = QtWidgets.QPushButton(self.centralwidget) self.pushButton_return.setGeometry(QtCore.QRect(390, 540, 110, 40)) self.pushButton_return.setStyleSheet("QPushButton{\n" " background-color:rgb(0,174,236);\n" " border:none;\n" " height:35px;\n" " border-radius:12px;\n" "}\n" "QPushButton::hover{\n" " background-color:rgb(65,184,131);\n" "}") self.pushButton_return.setObjectName("pushButton") self.label_cardnum = QtWidgets.QLabel(self.centralwidget) self.label_cardnum.setGeometry(QtCore.QRect(510, 310, 411, 31)) font = QtGui.QFont() font.setPointSize(12) self.label_cardnum.setFont(font) self.label_cardnum.setObjectName("label_cardnum") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 900, 26)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "银行卡识别系统")) self.label_daichuli.setText(_translate("MainWindow", "银行卡")) self.label_jieguo.setText(_translate("MainWindow", "识别后")) self.pushButton_upload.setText(_translate("MainWindow", "选择银行卡")) self.pushButton_save.setText(_translate("MainWindow", "保存图片")) self.pushButton_card_re.setText(_translate("MainWindow", "识别")) self.pushButton_return.setText(_translate("MainWindow", "返回")) self.label_cardnum.setText(_translate("MainWindow", "银行卡号:"))
四、运行结果图片
运行结果主页面图
银行卡识别结果页面图
到此这篇关于python 实现银行卡号查询银行名称和简称的文章就介绍到这了,更多相关python银行卡号查询内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!