使用go做身份证号码识别
实例图片
实现代码
package main
import (
"fmt"
"github.com/nfnt/resize"
"image"
"image/color"
"image/draw"
"image/jpeg"
"os"
"strconv"
"strings"
)
var numSign = map[int]string{
0: "0011111001111111111000111100000111000001110000010111111100111110",
1: "0000000000110000001000000110000001100000011111111111111111111111",
2: "0110001101100011110001111100010111001101110110010111100100110000",
4: "0000010000001110000111100011011001100110111111110111111100000110",
6: "0011111001111111010110011101000111010001110110010100111101001110",
8: "0000011001111111011111011101100111011001110110010111111101110111",
}
func main() {
imgFile, err := os.Open("./img/idcard.jpeg")
if err != nil {
panic(fmt.Sprintf("打开文件失败:%+v", err))
}
defer imgFile.Close()
img, err := jpeg.Decode(imgFile)
if err != nil {
panic(fmt.Sprintf("解析图片失败:%+v", err))
}
locImg := imgLocation(img)
binImg := imgBinarzation(locImg)
imgCutSide := imgCutSide(binImg)
imgCutSilce := imgCutSilce(imgCutSide)
imgNum := imgDiscern(imgCutSilce)
fmt.Println(imgNum)
}
func imgSign(imgBinary string) string {
if imgBinary == "" {
return imgBinary
}
imgBinarySign := strings.Split(imgBinary, "")
maxSimilarity := 0
num := ""
for n, sign := range numSign {
tmpSimilarity := 0
signArr := strings.Split(sign, "")
for k, s := range imgBinarySign {
if s == signArr[k] {
tmpSimilarity++
}
}
if maxSimilarity < tmpSimilarity {
maxSimilarity = tmpSimilarity
num = strconv.Itoa(n)
}
}
return num
}
func imgDiscern(imgs []image.Image) string {
signNum := make([]string, 0)
for _, img := range imgs {
tmpSignNum := make([]string, 0)
rect := img.Bounds()
for x := 0; x < rect.Dx(); x++ {
for y := 0; y < rect.Dy(); y++ {
r, _, _, _ := img.At(x, y).RGBA()
if r > 0x7788 {
tmpSignNum = append(tmpSignNum, "1")
} else {
tmpSignNum = append(tmpSignNum, "0")
}
}
}
signNum = append(signNum, strings.Join(tmpSignNum, ""))
}
res := make([]string, 0)
for _, v := range signNum {
res = append(res, imgSign(v))
}
return strings.Join(res, "")
}
func imgCutSilce(img image.Image) []image.Image {
rect := img.Bounds()
imgs := make([]image.Image, 0)
nowCutStartX := 0
nowCutEndX := 0
for x := 0; x <= rect.Dx(); x++ {
lxflag := true
for y := 0; y < rect.Dy(); y++ {
r, _, _, _ := img.At(x, y).RGBA()
if r == 0x0000 {
continue
} else {
nowCutEndX = x
lxflag = false
break
}
}
if lxflag {
if nowCutEndX == x-1 {
rectangle := image.Rectangle{
Min: image.Point{X: 0, Y: 0},
Max: image.Point{X: x - nowCutStartX, Y: rect.Dy()},
}
newImg := image.NewGray(rectangle)
draw.Draw(newImg, newImg.Bounds(), img, image.Point{X: nowCutStartX, Y: 0}, draw.Over)
newResizeImg := resize.Resize(8, 8, newImg, resize.Lanczos3)
imgs = append(imgs, newResizeImg)
} else {
nowCutStartX = x + 1
}
}
}
return imgs
}
func imgCutSide(img image.Image) image.Image {
rect := img.Bounds()
leftStartX := 0
for x := 0; x < rect.Dx(); x++ {
lxflag := false
for y := 0; y < rect.Dy(); y++ {
r, _, _, _ := img.At(x, y).RGBA()
if r == 0xFFFF {
lxflag = true
break
}
}
if lxflag {
leftStartX = x
break
}
}
leftStartY := 0
for y := 0; y < rect.Dy(); y++ {
lyflag := false
for x := 0; x < rect.Dx(); x++ {
r, _, _, _ := img.At(x, y).RGBA()
if r == 0xFFFF {
lyflag = true
break
}
}
if lyflag {
leftStartY = y
break
}
}
rightEndX := 0
for x := rect.Dx(); x > 0; x-- {
rxflag := false
for y := rect.Dy(); y > 0; y-- {
r, _, _, _ := img.At(x, y).RGBA()
if r == 0xFFFF {
rxflag = true
break
}
}
if rxflag {
rightEndX = x
break
}
}
rightEndY := 0
for y := rect.Dy(); y > 0; y-- {
ryflag := false
for x := rect.Dy(); x > 0; x-- {
r, _, _, _ := img.At(x, y).RGBA()
if r == 0xFFFF {
ryflag = true
break
}
}
if ryflag {
rightEndY = y
break
}
}
rectangle := image.Rectangle{
Min: image.Point{X: 0, Y: 0},
Max: image.Point{X: rightEndX - leftStartX, Y: rightEndY - leftStartY},
}
newSideImg := image.NewGray(rectangle)
draw.Draw(newSideImg, newSideImg.Bounds(), img, image.Point{X: leftStartX, Y: leftStartY}, draw.Over)
return newSideImg
}
func imgBinarzation(img image.Image) image.Image {
binImg := image.NewGray16(img.Bounds())
draw.Draw(binImg, binImg.Bounds(), img, img.Bounds().Min, draw.Over)
rect := binImg.Bounds()
for x := 0; x < rect.Dx(); x++ {
for y := 0; y < rect.Dy(); y++ {
r, _, _, _ := binImg.At(x, y).RGBA()
if r < 0x7788 {
binImg.Set(x, y, color.White)
} else {
binImg.Set(x, y, color.Black)
}
}
}
return binImg
}
func imgLocation(img image.Image) image.Image {
rect := img.Bounds()
leftLoc := image.Point{X: rect.Dx() * 200 / 606, Y: rect.Dy() * 315 / 383}
rightLoc := image.Point{X: rect.Dx() * 474 / 606, Y: rect.Dy() * 340 / 383}
rectangle := image.Rectangle{
Min: image.Point{X: 0, Y: 0},
Max: image.Point{X: rightLoc.X - leftLoc.X, Y: rightLoc.Y - leftLoc.Y},
}
locImg := image.NewNRGBA(rectangle)
draw.Draw(locImg, locImg.Bounds(), img, leftLoc, draw.Over)
return locImg
}
func imgView(img ...image.Image) {
for i := 0; i < len(img); i++ {
dts, err := os.Create(fmt.Sprintf("./view/cutImg%d.jpeg", i))
if err != nil {
panic(fmt.Sprintf("创建失败:%+v", err))
}
defer dts.Close()
err = jpeg.Encode(dts, img[i], nil)
if err != nil {
panic(fmt.Sprintf("写入图片失败:%+v", err))
}
}
}