当前位置: 首页 > news >正文

福州网站建设招商山东百搜科技有限公司

福州网站建设招商,山东百搜科技有限公司,中英文网站怎么做的,模板建站优缺点文章目录 一、案例实现的整体思路二、代码实现1.首先定义两个函数2.模板图像中数字的定位处理3.身份证号码数字的定位处理4.使用模板匹配,计算匹配得分,找到正确结果 一、案例实现的整体思路 下面是一个数字0~9的模板图片 案例身份证如下: 对…

文章目录

  • 一、案例实现的整体思路
  • 二、代码实现
    • 1.首先定义两个函数
    • 2.模板图像中数字的定位处理
    • 3.身份证号码数字的定位处理
    • 4.使用模板匹配,计算匹配得分,找到正确结果

一、案例实现的整体思路

  • 下面是一个数字0~9的模板图片
    在这里插入图片描述
  • 案例身份证如下:
    在这里插入图片描述
  • 对数字模板的处理
    • 通过对模板中的数字进行定位处理,将每个数字的轮廓和外接矩形都一一对应,并由小到大的排序
    • 再将每一个数字都对应一个模板,并设置成相同的大小,用于对身份证号码进行匹配并识别
  • 对身份证的处理
    • 确定出身份证中信息部分的轮廓,确定出每个部分的外接矩形,通过外接矩形的坐标关系确定出身份证号码区域
    • 对身份证号码区域的数字与模板数字做相同的处理
    • 最后将处理后的模板数字与处理后的身份证号码区域的数字进行模板匹配,识别出对应的号码数字

二、代码实现

  • 代码中会运用到轮廓检测与绘制和模板匹配,可以参考以下链接中的内容进行理解
    • 轮廓检测与绘制
      • https://blog.csdn.net/weixin_73504499/article/details/141873522?spm=1001.2014.3001.5501
    • 模板匹配
      • https://blog.csdn.net/weixin_73504499/article/details/141905861?spm=1001.2014.3001.5501

1.首先定义两个函数

  • def cv_show()用于绘图展示

  • def sort_contours()用于对模板数字的排序

    """ 绘图展示函数 """
    def cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(0)
    """ 用于对模板数字的排序的函数 """
    # sort_contours() 函数传入的参数:
    # cnts:包含所有数字轮廓的列表
    # method='left-to-right':排序的反向
    # cv2.boundingRect() 函数用于绘制轮廓的最小外接矩形,
    # 返回一个包含四个值的元组:(x, y, w, h),分别代表边界框左上角的x坐标、y坐标、宽度和高度
    # 通过每个数字外接接矩形框的左上角点的x和y坐标的大小,对每个模板数字进行排序
    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](cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),key=lambda b: b[1][i], reverse=reverse))# zip(*...)使用星号操作符解包排序后的元组列表,并将其重新组合成两个列表:一个包含所有轮廓,另一个包含所有边界框。# 返回梳理轮廓,和外接矩形return cnts, boundingBoxes
    

2.模板图像中数字的定位处理

  • 代码如下:
    # 读取模板图片
    img = cv2.imread('template.png')
    cv_show('img', img)
    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转换为灰度图
    cv_show('gray', gray)
    # 转换为二值化图
    ref = cv2.threshold(gray, 155, 255, cv2.THRESH_BINARY_INV)[1]  # 再转换为二值图像
    cv_show('ref', ref)# 计算轮廓: cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图)
    # cv2.RETR_EXTERNAL 只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE 只保留终点坐标
    _, refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cv2.drawContours(img, refCnts, -1, (0, 0, 255), 2)
    cv_show('img', img)refCnts = sort_contours(refCnts, method="left-to-right")[0]  # 排序 ,从左到右,从上到下
    digits = {}  # 保存模板中每个数字对应的像素值
    for (i, c) in enumerate(refCnts):  # 遍历每一个轮廓# 计算外接矩形并且resize成合适大小(x, y, w, h) = cv2.boundingRect(c)roi = ref[y - 2:y + h + 2, x - 2:x + w + 2]  # 适当增加一点外接矩形框的大小roi = cv2.resize(roi, (57, 88))  # 缩放到指定的大小# cv2.bitwise_not() 位非操作:反转图像中每个像素的位值,即将白色变为黑色,黑色变为白色,# 对于灰度图像,较亮的像素会变暗,较暗的像素会变亮。roi = cv2.bitwise_not(roi)cv_show('roi', roi)digits[i] = roi  # 每一个数字对应每一个模板
    
  • 结果如下:
    在这里插入图片描述
    • 处理后的每一个数字模板如下所示
      在这里插入图片描述

3.身份证号码数字的定位处理

  • 代码如下:

    # 读取身份证照片
    image = cv2.imread('sfz.jpg')
    cv_show('image', image)
    # 转换为灰度图
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    cv_show('gray', gray)
    # 转换为二值图
    ref = cv2.threshold(gray, 120, 255, cv2.THRESH_BINARY_INV)[1]
    cv_show('ref', ref)# 计算轮廓
    t_, threshCnts, h = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = threshCnts
    cur_img = image.copy()
    # 画出轮廓
    cv2.drawContours(cur_img, cnts, -1, (0, 0, 255), 2)
    cv_show('img', cur_img)# 遍历轮廓,找到数字部分像素区域
    locs = []
    for (i, c) in enumerate(cnts):# 算出所有轮廓的外接矩形(x, y, w, h) = cv2.boundingRect(c)# 通过每个号码数字外接矩形的y轴坐标的大小,和x轴坐标的大小来确定号码数字的区域if (y > 330 and y < 360) and x > 220:locs.append((x, y, w, h))   # 将符合的数字轮廓信息都添加到locs列表中
    """
    因为经过cv2.boundingRect() 外接矩形框后的数字顺序是乱的
    通过每个数字外接矩形框的左上角顶点的x坐标的大小进行重新排序
    恢复到原身份证号码的数字顺序
    """
    locs = sorted(locs, key=lambda x: x[0])# 将身份证号码数字进行与模板数字相同的操作
    output = []
    for (i, (gX, gY, gW, gH)) in enumerate(locs):group = gray[gY - 2:gY + gH + 2, gX - 2:gX + gW + 2]cv_show('group', group)# 预处理group = cv2.threshold(group, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]cv_show('group', group)# 将每个数字都设置成与数字模板中每个数字的大小相同roi = cv2.resize(group, (57, 88))cv_show('roi', roi)
    
  • 结果如下
    在这里插入图片描述

    • 身份证号码每一个数字处理后的效果如下:
      在这里插入图片描述

4.使用模板匹配,计算匹配得分,找到正确结果

  • 代码如下:

    # 定义scores空列表用于存放所有的匹配得分scores = []# 定义groupOutput空列表用于存放匹配后的每一个正确的号码数字groupOutput = []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(image, (gX - 5, gY - 5), (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)# 将匹配到的数字在身份证号码的上方写出来# cv2.putText()是OpenCV库中的一个函数,用于在图像上添加文本cv2.putText(image, "".join(groupOutput), (gX, gY - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)# 在output空列表中添加正确的身份证号码output.extend(groupOutput)# 打印出身份证号码
    print("Credit Card #:{}".format("".join(output)))
    # 显示身份证图片匹配后的结果图
    cv_show("Image", image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
  • 结果如下
    在这里插入图片描述
    在这里插入图片描述

  • 完整代码如下:

    import numpy as np
    import cv2def cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(0)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](cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),key=lambda b: b[1][i], reverse=reverse))# zip(*...)使用星号操作符解包排序后的元组列表,并将其重新组合成两个列表:一个包含所有轮廓,另一个包含所有边界框。return cnts, boundingBoxes"""------模板图像中数字的定位处理------"""
    # 读取模板图片
    img = cv2.imread('template.png')
    cv_show('img', img)
    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转换为灰度图
    cv_show('gray', gray)
    # 转换为二值化图
    ref = cv2.threshold(gray, 155, 255, cv2.THRESH_BINARY_INV)[1]  # 再转换为二值图像
    cv_show('ref', ref)# 计算轮廓: cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图)
    # cv2.RETR_EXTERNAL 只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE 只保留终点坐标
    _, refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # 画出轮廓
    cv2.drawContours(img, refCnts, -1, (0, 0, 255), 2)
    cv_show('img', img)refCnts = sort_contours(refCnts, method="left-to-right")[0]  # 排序 ,从左到右,从上到下
    digits = {}  # 保存模板中每个数字对应的像素值
    for (i, c) in enumerate(refCnts):  # 遍历每一个轮廓# 计算外接矩形并且resize成合适大小(x, y, w, h) = cv2.boundingRect(c)roi = ref[y - 2:y + h + 2, x - 2:x + w + 2]  # 适当增加一点外接矩形框的大小roi = cv2.resize(roi, (57, 88))  # 缩放到指定的大小# cv2.bitwise_not() 位非操作:反转图像中每个像素的位值,即将白色变为黑色,黑色变为白色,# 对于灰度图像,较亮的像素会变暗,较暗的像素会变亮。roi = cv2.bitwise_not(roi)cv_show('roi', roi)digits[i] = roi  # 每一个数字对应每一个模板
    # cv2.destroyAllWindows()""" 身份证号码数字的定位处理 """
    # 读取身份证照片
    image = cv2.imread('sfz.jpg')
    cv_show('image', image)
    # 转换为灰度图
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    cv_show('gray', gray)
    # 转换为二值图
    ref = cv2.threshold(gray, 120, 255, cv2.THRESH_BINARY_INV)[1]
    cv_show('ref', ref)# 计算轮廓
    t_, threshCnts, h = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = threshCnts
    cur_img = image.copy()
    # 画出轮廓
    cv2.drawContours(cur_img, cnts, -1, (0, 0, 255), 2)
    cv_show('img', cur_img)# 遍历轮廓,找到数字部分像素区域
    locs = []
    for (i, c) in enumerate(cnts):# 算出所有轮廓的外接矩形(x, y, w, h) = cv2.boundingRect(c)# 通过每个号码数字外接矩形的y轴坐标的大小,和x轴坐标的大小来确定号码数字的区域if (y > 330 and y < 360) and x > 220:locs.append((x, y, w, h))   # 将符合的数字轮廓信息都添加到locs列表中
    """
    因为经过cv2.boundingRect() 外接矩形框后的数字顺序是乱的
    通过每个数字外接矩形框的左上角顶点的x坐标的大小进行重新排序
    恢复到原身份证号码的数字顺序
    """
    locs = sorted(locs, key=lambda x: x[0])# 将身份证号码数字进行与模板数字相同的操作
    output = []
    for (i, (gX, gY, gW, gH)) in enumerate(locs):group = gray[gY - 2:gY + gH + 2, gX - 2:gX + gW + 2]cv_show('group', group)# 预处理group = cv2.threshold(group, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]cv_show('group', group)# 将每个数字都设置成与数字模板中每个数字的大小相同roi = cv2.resize(group, (57, 88))cv_show('roi', roi)''' 使用模板匹配,计算匹配得分,找到正确结果 '''# 定义scores空列表用于存放所有的匹配得分scores = []# 定义groupOutput空列表用于存放匹配后的每一个正确的号码数字groupOutput = []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(image, (gX - 5, gY - 5), (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)# 将匹配到的数字在身份证号码的上方写出来# cv2.putText()是OpenCV库中的一个函数,用于在图像上添加文本cv2.putText(image, "".join(groupOutput), (gX, gY - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)# 在output空列表中添加正确的身份证号码output.extend(groupOutput)# 打印出身份证号码
    print("Credit Card #:{}".format("".join(output)))
    # 显示身份证图片匹配后的结果图
    cv_show("Image", image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

文章转载自:
http://mustang.qwfL.cn
http://reemerge.qwfL.cn
http://yakitori.qwfL.cn
http://deciduous.qwfL.cn
http://drayman.qwfL.cn
http://armand.qwfL.cn
http://etruscologist.qwfL.cn
http://jeanswear.qwfL.cn
http://cystathionine.qwfL.cn
http://logging.qwfL.cn
http://canarian.qwfL.cn
http://aerobody.qwfL.cn
http://levigation.qwfL.cn
http://fugacity.qwfL.cn
http://aerophile.qwfL.cn
http://astonish.qwfL.cn
http://provirus.qwfL.cn
http://wearer.qwfL.cn
http://childing.qwfL.cn
http://nonfat.qwfL.cn
http://achaian.qwfL.cn
http://pfeffernuss.qwfL.cn
http://cerebrotonia.qwfL.cn
http://transferrin.qwfL.cn
http://odontornithic.qwfL.cn
http://cfs.qwfL.cn
http://klavier.qwfL.cn
http://quinine.qwfL.cn
http://jot.qwfL.cn
http://peach.qwfL.cn
http://cavort.qwfL.cn
http://distinguished.qwfL.cn
http://paralanguage.qwfL.cn
http://wincey.qwfL.cn
http://papal.qwfL.cn
http://sonnetist.qwfL.cn
http://cachexia.qwfL.cn
http://transcaucasia.qwfL.cn
http://bootlegger.qwfL.cn
http://micronization.qwfL.cn
http://agloat.qwfL.cn
http://indecent.qwfL.cn
http://swacked.qwfL.cn
http://spelk.qwfL.cn
http://jeeves.qwfL.cn
http://acls.qwfL.cn
http://schmo.qwfL.cn
http://maloti.qwfL.cn
http://jackpudding.qwfL.cn
http://pc99.qwfL.cn
http://allies.qwfL.cn
http://ghoulish.qwfL.cn
http://recommit.qwfL.cn
http://maldivian.qwfL.cn
http://dandelion.qwfL.cn
http://punctual.qwfL.cn
http://juvenal.qwfL.cn
http://aphony.qwfL.cn
http://radioprotection.qwfL.cn
http://halter.qwfL.cn
http://toxic.qwfL.cn
http://pandect.qwfL.cn
http://widespread.qwfL.cn
http://accipiter.qwfL.cn
http://extirpation.qwfL.cn
http://unenvied.qwfL.cn
http://barie.qwfL.cn
http://jocundity.qwfL.cn
http://whitaker.qwfL.cn
http://rattly.qwfL.cn
http://tallis.qwfL.cn
http://gerontics.qwfL.cn
http://influxion.qwfL.cn
http://papery.qwfL.cn
http://klystron.qwfL.cn
http://buns.qwfL.cn
http://aeronaval.qwfL.cn
http://lemures.qwfL.cn
http://chromatology.qwfL.cn
http://parvenu.qwfL.cn
http://gallomania.qwfL.cn
http://flagelliform.qwfL.cn
http://groggily.qwfL.cn
http://pinnatifid.qwfL.cn
http://placeseeker.qwfL.cn
http://slough.qwfL.cn
http://auxotroph.qwfL.cn
http://genova.qwfL.cn
http://anatomic.qwfL.cn
http://amnesiac.qwfL.cn
http://autoeroticism.qwfL.cn
http://blackguardly.qwfL.cn
http://unsportsmanlike.qwfL.cn
http://pornie.qwfL.cn
http://pantology.qwfL.cn
http://australian.qwfL.cn
http://collocable.qwfL.cn
http://cheddar.qwfL.cn
http://sulphonyl.qwfL.cn
http://sauerbraten.qwfL.cn
http://www.15wanjia.com/news/75338.html

相关文章:

  • 网站开发总结经验和教训今日头条十大新闻
  • 如何做网站后台管理系统核心关键词和长尾关键词
  • 广东圆心科技网站开发需要多少钱google推广平台怎么做
  • 网站建设公司首页宁德市人社局
  • 集安网站制作成都专业的整站优化
  • 从网址怎么看网站的域名专门开发小程序的公司
  • 做网站办什么营业执照推广引流渠道平台
  • 无锡食品网站设计编程培训机构
  • 做母婴产品哪个网站做的好公司宣传网站制作
  • php做视频分享网站seo优化排名教程百度技术
  • 黄岛因特网站建设公司如何优化网站排名
  • 网站怎么做分时网站推广软件免费版下载
  • 杭州网站制作建设搜索引擎优化理解
  • 广州网站建设 骏域seo的优化策略有哪些
  • 网站建设中什么意思网站页面优化方法
  • joomla 网站建设教程福州seo技术培训
  • 做解决方案的网站网页制作与设计
  • 老网站怎么做循环链接百度一下下载安装
  • 做视频赚钱的国外网站优化大师安卓版
  • 个人网站做电影网站商丘网站seo
  • 做网站 新域名 还是如何制作网站免费建站
  • 衢州网站设计公司排行软文素材网
  • 去哪儿网站排名怎么做百度投流
  • 和两个黑人同时做网站网络推广软件免费
  • 查网站ip地址品牌推广方案
  • 新手做网站需要哪些教材疫情最新消息今天公布
  • 网站做的好的公司吸引人的推广标题
  • 遂宁网站建设品牌营销策略分析
  • 网站app 开发网络营销渠道有哪几种
  • 做调查网站赚钱百度官方网站网址是多少