身份证号码识别(golang)

身份证号码识别(golang)

使用golang写一个简单的身份证号码识别

基本思路

  1. 拿到一张身份证图片,先确定身份证号码的位置
  2. 将该部分取出,然后进行二值化,比如将数字变成白色,背景变为黑色
  3. 按照第二步数字的颜色(这里以数字为白色为例),遍历像素点找出左边第一个白点和右边最后一个白点的坐标,对图片更加细致的切割
  4. 将图片分割即将每一个数字切割出来
  5. 识别数字

结果展示:

在这里插入图片描述
识别结果:
在这里插入图片描述

代码实现

主函数

file, err := os.Open("xxxx") //此处自行更改自己所需要识别的图片路径defer file.Close()if err != nil {panic(err)}//解析图片img, err := jpeg.Decode(file)if err != nil {log.Fatalln(err)}

其他函数自行在主函数中调用

  1. 号码定位
func Number(src image.Image)image.Image{rect := src.Bounds() // 获取图片的大小//左上角坐标//此处图片的尺寸需要根据所需识别的图片进行确定left := image.Point{X: rect.Dx()*220 / 620 , Y: rect.Dy()*325/385}//右下角坐标//此处图片的尺寸需要根据所需识别的图片进行确定right := image.Point{X: rect.Dx()*540 / 620 , Y: rect.Dy()*345/385}newReact := image.Rectangle{Min: image.Point{X: 0, Y: 0},Max: image.Point{X: right.X - left.X, Y: right.Y - left.Y},} // 创建一个新的矩形 ,将原图切割后的图片保存在该矩形中newImage := image.NewRGBA(newReact) // 创建一个新的图片draw.Draw(newImage, newReact, src, left, draw.Over) // 将原图绘制到新图片中return newImage
}
  1. 将图片二值化
func Binarization(src image.Image)image.Image{//将图片灰化dst := image.NewGray16(src.Bounds()) // 创建一个新的灰度图draw.Draw(dst, dst.Bounds(), src, src.Bounds().Min, draw.Src) // 将原图绘制到新图片中//遍历像素点,实现二值化for x := 0; x < src.Bounds().Dx(); x++ {for y := 0; y < src.Bounds().Dy(); y++ {r,_,_,_ := src.At(x, y).RGBA() //取出每个像素的r,g,b,aif r < 0x5555{dst.Set(x, y, color.White) //将灰度值小于0x5555的像素置为0}else{dst.Set(x,y,color.Black)}}}return dst
}
  1. 寻找边缘坐标更加细致的切割图片
func CutImage(src image.Image) image.Image{var left , right image.Point //左上角右下角坐标//寻找左边边缘白点的x坐标for x:= 0 ; x < src.Bounds().Dx() ; x++{for y := 0 ; y < src.Bounds().Dy() ; y++{r,_,_,_ := src.At(x,y).RGBA()if r == 0xFFFF{left.X = xx = src.Bounds().Dx()  //使外层循环结束break}}}//寻找左边边缘白点的y坐标for y:= 0 ; y < src.Bounds().Dy() ; y++{for x := 0 ; x < src.Bounds().Dx() ; x++{r,_,_,_ := src.At(x,y).RGBA()if r == 0xFFFF{left.Y = yy = src.Bounds().Dy()  //使外层循环结束break}}}//寻找右边边缘白点的x坐标for x:= src.Bounds().Dx()  ; x > 0 ; x--{for y := src.Bounds().Dy() ; y > 0 ; y--{r,_,_,_ := src.At(x,y).RGBA()if r == 0xFFFF{right.X = x + 1x = 0  //使外层循环结束break}}}//寻找右边边缘白点的y坐标for y:= src.Bounds().Dy()-1 ; y > 0 ; y--{for x := src.Bounds().Dx()-1 ; x > 0 ; x--{r,_,_,_ := src.At(x,y).RGBA()if r == 0xFFFF{right.Y = y + 1y = 0  //使外层循环结束break}}}//按照坐标点将图像精准切割newReact := image.Rect(0, 0, right.X - left.X + 1 ,right.Y - left.Y  +2) // 创建一个新的矩形 ,将原图切割后的图片保存在该矩形中log.Println(left, right)log.Println(src.Bounds(),newReact)dst := image.NewRGBA(newReact) draw.Draw(dst ,dst.Bounds() , src , left , draw.Over)return dst
}
  1. 将每一个数字切割出来
func SplitImage(src image.Image) []image.Image  {var dsts []image.ImageleftX := 0for x := 0 ; x < src.Bounds().Dx() ; x++ {temp := falsefor y := 0; y < src.Bounds().Dy(); y++ {r, _, _, _ := src.At(x, y).RGBA()if r == 0xFFFF {temp = truebreak}}if temp {continue}dst := image.NewGray16(image.Rect(0, 0, x-leftX, src.Bounds().Dy()))draw.Draw(dst, dst.Bounds(), src, image.Point{X: leftX, Y: 0}, draw.Src)//下一个起点for x1 := x + 1 ; x1 < src.Bounds().Dx(); x1++ {temp := falsefor y := 0; y < src.Bounds().Dy(); y++ {r, _, _, _ := src.At(x1, y).RGBA()if r == 0xFFFF {temp = truebreak}}if temp {leftX = x1x = x1break}}img := resize.Resize(8 , 8 , dst  ,resize.Lanczos3)dsts = append(dsts , img)}//fmt.Println(len(dsts))return dsts
}

这部分使用了一个外部库,用来更改图片尺寸大小,将每个数字所在的图片的大小进行统一可以更好的进行数字识别
库名 :“github.com/nfnt/resize”

go get github.com/nfnt/resize

使用该命令导入该包

  1. 数字识别
  • 需要先设置一个库,将每个数字的图片遍历出来的结果与该库的内容进行比较,来确定该数字
var Data = map[string]string{"0": "0111110011111110000000001000000010000000100000100111111000011000","1": "0100000001000000010000001100000011000000111111101111111011111110","2": "0000001010000110000010001000100010011000000100001110000001100000","3": "0000000000000000000000000001000000110000011100101101001011001110","4": "0000110000011100001001000100010000000100000111100000110000000100","5": "0000000011100000001000000000000000000010000100000001011000011100","6": "0000110000111110001100100110000010000000100100100001111000001100","7": "0000000000000000000011100001111000010000001000001100000011000000","8": "0100111011111010100100100001000000010000101100100110111000000100","9": "0010000001110000100110000000101000001110100011000111100001100000",
}
  • 对每个数字图片进行遍历,得到的结果与库进行比较到处结果
func NumberDistinguish(srcs []image.Image) string {id := ""for i := 0; i < len(srcs); i++ {// 获取图片的指纹sign := ""for x := 0; x < srcs[i].Bounds().Dx(); x++ {for y := 0; y < srcs[i].Bounds().Dy(); y++ {r, _, _, _ := srcs[i].At(x, y).RGBA()if r > 0x7777 {sign += "1"} else {sign += "0"}}}// 对比指纹number := ""//对比相似率percent := 0.0for k, v := range database.Data {sum := 0for i := 0; i < 64; i++ {if v[i:i+1] == sign[i:i+1] {sum++}}//不断比较当匹配率达到最大时,就是此时所对应的数字if float64(sum)/64 > percent {number = kpercent = float64(sum) / 64  }}log.Println(sign, number, percent)id += number}return id
}

在代码调试过程中需要将图片输出查看

  • 查看单张图片
func ShowImg(src image.Image) {dst, err := os.Create("./preview/output.jpg") //可以自己更改为想要将图片存放的位置if err != nil {log.Fatalln(err)}jpeg.Encode(dst, src, nil)
}
  • 查看多张图片
func ShowImgs(srcs []image.Image) {for i := 0; i < len(srcs); i++ {dst, err := os.Create(fmt.Sprintf("./preview/output-%d.jpg", i))if err != nil {log.Fatalln(err)}jpeg.Encode(dst, srcs[i], nil)}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/56167.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

居民身份证号码查询系统

居民身份证号码查询系统(IDio)1.4.0.140单文件版居民身份证号码查询系统(IDio)是用以根据身份证号码查找所属的省市区、出生年月日、性别等信息的工具。身份证号码查询特色&#xff1a;准确及时&#xff0c;包括最新的行政区域信息&#xff1b;地图定位&#xff1a;一键显示地区…

身份证归属地查询软件(离线版)

这是一款使用C#语言写的软件&#xff0c;可以实现身份证归属地离线查询功能&#xff0c;目前源代码已经开源至码云&#xff0c;github平台&#xff0c;效果如下&#xff1a; 当输入前两位数字时&#xff0c;可查询到相关省&#xff1b;当输入前四位数字时&#xff0c;可查询到相…

通过身份证号码进行归属地的查询、出生日期,以及判断性别(升级版)

程序输出结果 添加类&#xff08;IDInfo.cs&#xff09;–获取身份证中的各种信息 using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.IO;namespace IDInformation02 {class IDInfo{public string GetUserBirthday(string IDInfo){//读取出生日期string res &…

身份证归属地查询接口

一、前言 身份证号归属地查询&#xff0c;支持18位身份证号。 二、接口文档 1.接口URL www.idmayi.com:8099/api/cardplace/v1/getCardPlace 2.调用方法 GET 3.请求参数 4.返回值 三、调试入口 官方地址&#xff1a;www.idmayi.com

马斯克的这波神操作,让我意识到保持写代码的能力有多重要

作为一个在IT行业摸爬滚打了多年的老油条&#xff0c;我是越来越看不懂现在的互联网行业了。 至少曾经我听过太多人吐槽写代码的永远干不过写PPT的&#xff0c;并且在现实工作中验证过也确实如此&#xff0c;但是老马的这一波骚操作&#xff0c;让推特工程师打印出最近30-60天…

马斯克新要求+1:写周报,具体到代码行数的那种……

自从埃隆・马斯克&#xff08; Elon Musk &#xff09;入主 Twitter 以来&#xff0c;一些的操作紧随其后展开&#xff0c;先有要求工程师默写代码&#xff0c;随后又解雇纠错员工、裁了近八成工程师、整顿系统架构……这也让马斯克一跃成坐拥“热搜体质”&#xff0c;备受国内…

马斯克是全人类的?他旗下有9家公司,特斯拉被评为最没技术含量

最近&#xff0c;“马仔很忙”一词被人们津津乐道。其主角马斯克正被“逼捐事件”“亿万富翁税”搞得焦头烂额。连同前一阵子特斯拉股价暴涨的原因&#xff0c;马斯克成为了舆论关注焦点。不了解他的人&#xff0c;只是感慨特斯拉这个企业的庞大潜力。 人们不知道的是&#xf…

市值暴涨8000亿,马斯克告诉了美国同行,为啥需要中国市场?

马斯克访华仅仅40多个小时&#xff0c;却带动了股价连涨5天&#xff0c;涨幅最高达到20%&#xff0c;市值飙涨8000亿元人民币&#xff0c;马斯克也因此再度问鼎全球首富之位&#xff0c;凸显出中国之行给他带来的巨大好处。 一、中国市场带动了特斯拉的辉煌 2018年马斯克为产能…

AutoGPT - 全自动人工智能助手

最近一款基于GPT-4的最强语言模型AutoGPT火遍了整个AI圈&#xff0c;是目前为数不多的完全自主运行的人工智能之一&#xff0c;它会根据你提的目标来制定计划&#xff0c;然后自己执行完整个计划&#xff0c;整个过程自动化的能力非常的强。 问题驱动 – 人工&#xff08;Manua…

应急响应 | 完善企业网络安全应急响应计划的工具推荐

为什么制定应急响应&#xff08;IR&#xff09;计划很重要&#xff1f; 随着网络威胁的数量和严重程度不断增加&#xff0c;以及日益复杂的IT环境&#xff0c;企业必须启用应急响应和恢复流程&#xff0c;来保障企业的网络安全。 随着零日漏洞的增加&#xff0c;威胁变得越来越…

MLPerf最新发榜!这家AI芯片公司再获世界第一,大模型性能狂超A100

「Python数据之道」分享 来源&#xff1a;机器之心 此次是墨芯连续第二次问鼎 MLPerf&#xff0c;也是又一次 “12nm 战胜 4nm”。 ChatGPT 引爆大模型浪潮&#xff0c;也带来了算力挑战&#xff1a;当大模型进入大规模部署阶段&#xff0c;海量算力需求、推理加速等痛点&#…

80%的代码AI帮你写?还没这么夸张,不过也快了

兔年春节一过&#xff0c;APIcat进入到云服务版本的开发阶段&#xff0c;过年前发生了一件大事&#xff0c;Chatgpt横空出世&#xff0c;不少人预测Chatgpt会替代的10大行业&#xff0c;其中就有程序员。 这时&#xff0c;一位特斯拉的老哥出来说&#xff0c;GitHub Copilot帮…

Android中英文单词录入背诵软件

PC端演示&#xff1a; Android端演示(GIF太大&#xff0c;就图片吧)&#xff1a; 源代码下载地址&#xff1a;http://suo.im/6f6zLa&#xff0c;解压密码&#xff1a;lrbs7 我在上传资源时&#xff0c;没有为任何一个设置下载需要C币或是积分&#xff0c;但是平…

⚡写一个有发音的背单词软件⚡——四六级必过系列

四六级必过 ⚡导读演示爬虫阶段GUI阶段朗读单词阶段封装阶段⚡肥学有话说⚡导读 你还在为小小英语而发愁吗?,你还在为备考四六级没有动力而难过吗?那么今天教你写一个背单词软件你不会不想学吧。兄弟们新学期都开始了大家和我一起肥学一起吧!! 演示 用python教大家怎么写…

一款c#实现的实用好玩儿的背单词程序

1.程序功能&#xff1a; 软件logo&#xff1a; 1.可实现背四级单词、六级单词、考研单词、托福单词、雅思单词、中考单词、高考单词、新概念单词的功能。 2.四级单词、六级单词、考研单词、托福单词、雅思单词、中考单词、高考单词、新概念单词以一定的格式存储在记事儿本里通…

程序员快速记忆英文单词的专属诀窍

本文来自作者 曹某某 在 GitChat 上分享 「程序员快速记忆英文单词的专属诀窍」&#xff0c;「阅读原文」查看交流实录。 「文末高能」 编辑 | 哈比 首先感谢选择我这个专题的所有的读者。这是我第一次在 GitChat 做分享。我希望我的分享能够带来一些有趣和有用的东西&#xff…

大模型扎堆涌现,AIGC 的价值到底是什么?

ChatGPT 在 2023 年初爆红之后&#xff0c;AIGC 引发了各行业的热切关注&#xff0c;国内的各类大模型不断推出。近日&#xff0c;科大讯飞对外发布了“讯飞星火认知大模型”&#xff0c;现场不仅实测了文本生成、语言理解、知识问答、数学、逻辑推理等能力表现&#xff0c;科大…

win10的cmd中显示:telnet不是内部或外部命令也不是可运行的程序或批处理?

先说说什么是telnet命令&#xff1f; telnet命令用于登录远程主机&#xff0c;对远程主机进行管理。 举个栗子&#xff1a;在cmd中运行telnet localhost 8431 也就等同于在浏览器中输入localhost:8431 如果在cmd中使用telnet指令发现报错&#xff1a;telnet不是内部或外部命…

在VSCode下利用PlateFormIO开发Arduino的MicroROS遇到的一些问题

文章目录 简介1.左下角没有platformio的相关按钮2.vscode没有串行监视器&#xff08;Serial Monitor&#xff09;3.关于trajectory_msgs/msg/joint_trajectory.hpp的相关问题4.关于control_msgs::action::FollowJointTrajectory的相关问题4.1.方法一4.2.方法二 5.关于moveit_ms…

进程管理(笔记)

如果对内存寻址熟悉的话, 或者认真看过上一节的内容: 内存管理之内存寻址: https://blog.csdn.net/qq_40482358/article/details/130868188. 那么对linux系统中的进程管理应该已经有一个初步的认识了: cr3作为一个控制寄存器, 描述当前进程的页目录的物理内存基地址, 当进程切换…