一种移动端简单的检测图像中身份证(银行卡)的方式

一种简单的检测图像中身份证(银行卡)的方式

客户端检测身份证、银行卡之类的功能应该是很常见的,一般都是采用集成第三方OCR sdk来完成信息的采集。但是如何只是初步识别相机镜头中到底包不包含身份证,然后检测到后自动裁剪身份证卡片区域上传到服务器上,并不需要识别具体信息,这个功能用sdk做的话,显然有些大材小用了(其实就是产品提的奇葩需求)。怎么办?自己动手,丰衣足食。

1、提取卡片区域

要检测相机的镜头中有没有身份证。首先要把图像中的卡片区域给找出来。只有正确的找到卡片所在区域,才能进一步提取卡片的特征。如何提取卡片区域呢?这里分为四步:图像灰度化、边缘检测、Hough变换求卡片位置、透视变换

  • 1、灰度化
    没啥好说的,我们感兴趣的是图像的边缘,对色彩信息并不感兴趣,所以只需要灰度图就可以了。RGB图转灰度图算法,
    G r a y = R ∗ 0.299 + G ∗ 0.587 + B ∗ 0.114 Gray = R*0.299 + G*0.587 + B*0.114 Gray=R0.299+G0.587+B0.114
    因为浮点数计算比较慢,我们可以做一下变换用位运算来加速算法, 变换之后的公式为
    G r a y = ( R ∗ 38 + G ∗ 75 + B ∗ 15 ) > > 7 Gray= (R*38 + G*75 + B*15) >> 7 Gray=(R38+G75+B15)>>7
  • 2、边缘检测
    我们先假设用户在拍摄身份证时,拍摄背景区域是简单的,这样卡片和背景会有明显的界限,我们就能用检测边缘的算法区提取卡片的边缘,边缘检测算法当然是用大名鼎鼎的Canny算法。
  • 3、Hough变换求卡片位置
    边缘检测之后我们可以得到边缘的的一系列点,这些点有可能是卡片边缘,当然也有可能是背景图像中的其他边缘信息。然后我们用Hough变换就可以检测出图像中可能存在的直线。当然如果图像中存在卡片,我们大概率会得到至少四条直线线(就是卡片的四条边),然后我们就可以进一步得到四个交点即是卡片的四个角点的坐标。
  • 4、透视变换
    从上一步中我们已经得到了卡片四个角点的位置,这个时候就可以提取出来卡片区域的图像了。但是因为相机拍摄角度以及距离远近的原因,所以得到的卡片区域不一定是标准的矩形,有可能会发生形变,图像也会尺寸不一。这个时候我们需要对卡片区域进行透视变换操作,将卡片区域映射成860*540的矩形。透视变换一方面可以将不规则的卡片区域映射成标准矩形,减少旋转、形变对检测效果的干扰,另外一方面还可以将图像尺寸归一化,为下一步提取图像特征做好准备。

其实还有另外一套检测卡片区域的流程,再进行边缘检测后,进行适度的腐蚀膨胀,然后用Opencv的findContours函数求出图像中一系列的连通区域,然后再从中找出最大的联通区域,我们即可认为这个就是卡片区域(因为我们假设拍摄的背景是简单的),然后再用boundingRect函数求出最大连通区域的最小外接矩形就可以了,这种方式也可以求出卡片区域的位置,但是相对于Hough变换来说,精确到要差一些,而且关键是不能精确的求出卡片的四个角点的精确坐标。

2、识别卡片

怎么识别裁剪到的卡片是身份证,而不是银行卡或者其他的卡片之类的?如果你对图像处理和机器学习方面的知识比较了解的话,你就会说很简单啊,先用图像处理算法去提取图像特征,然后用SVM啥的训练一个模型出来不就行了?但是,问题来了,身份证照片这种属于比较敏感的数据,哪来的训练数据集呢。没有数据集只能使用很少样本的情况下,该怎么做呢?放在其他图形检测来说可能真的没法做了,但是身份证有点不一样,身份证正面和背面都是属于有很标准,而且很突出的的特征的,比如身份证正面的文字、头像位置都是固定不变的。所以我们就可以通过少量样本就可以提取出身份证的通用特征出来!
在上一步我们通过透视变换将卡片图像变换成860 * 540的图像(因为身份证的比例是86:54),我们可以直接用这个身份证的灰度矩阵当特征吗?当然可以,但是有个问题,首先这样特征向量就很大(860*540),会导致计算量也很大,而且还会导致过拟合问题,从而陷入局部最优解。而且直接用灰度值作为特征值容易受到光照变换的影响,那么如何获取光照不变的特征值呢?我们可以先对灰度图进行二值化处理,采用OTSU大津算法自适应分割图像,将图像进一步分为背景和前景两部分,这样无论光照如何变化,对分割后的图像来说都影响不大,就可以避免光照变化带来的影响。解决对光照敏感问题,我们再来解决过拟合的问题。这个问题也很好解决,来一次pooling操作就好了,我们可以将身份证卡片进一步分成10 * 10的方格,统计每个方格的像素值为255(前景)或者0(背景)的点的个数作为该方格的特征值,然后就能得到一个10 * 10的特征矩阵了。而且pooling不仅能防止过拟合,由于特征维度减少了,计算量也相应的减小了,并且还能对旋转、形变、位移和噪声产生一定的抵抗力,可谓一举多得。
以上就是提取卡片特征向量的过程,然后我们就可以提取标准身份证的特征向量作为识别模型了。只需要少数几张身份证,拍摄200张标准样片,然后提取特征向量,平均一下求的最后的结果就可以作为识别模型了。然后再用同样的方法区提取待检测卡片的特征向量,这样我们就有了标准模型向量和待检测卡片的特征向量两个向量。那么我们就可以通过比较这两个特征向量的相似程度,从而来判断两张图片的相似程度。度量两个向量的相似程度的算法有很多,这里我们可以采用向量的余弦距离来度量。如果计算出待检测的卡片的特征向量和模型向量的余弦距离大于某一个阈值(比如0.8),那么我们就可以认为待检测卡片就是一张身份证了,这样我们就可以把卡片图像截取出来,并上传给服务器了,

3、总结

  • 优点:以上算法就是算法简单,不需要用很大的数据集来训练模型,而且扫描身份证速度也很快,平均80ms就能完成一次识别(Android开发的话,图像处理算法可以集成opencv用现成的函数,也可以自己用C++实现,毕竟如果用Java来做图像处理的话太慢了),而且具有一定的光照、旋转、形变、位移的不敏感性。
  • 缺点:当然这种做法只是简单的对图像中有没有身份证进行检测,因为算法实在是很简单,所以会存在很多问题。比如,在第一步提取卡片区域时,我们是假设用户拍摄身份证时,会把身份证放到一个相对简单的背景中,这样我们在做Hough变换检测直线时,就能相对容易的检测出卡片的正确位置;假如拍摄的背景非常复杂,比如都是网格图案的话,第一步检测卡片区域就会相当困难了,这是检测算法本身缺陷导致的,所以很难避免。我们只能去提示用户把身份证放在干净的桌面上去拍摄。
    还有就是有没有可能一个卡片提取的特征和身份证提取的特征很近似?这种可能当然是有的,根据我们的特征提取算法,我们就能知道,这样的卡片首先得和身份证结构上很相似才行,一般像银行卡、驾驶证之类的结构上还是有些差别的。(当然我们在计算余弦距离时设有阈值,也是为了过滤这种情况),但即使用户真的上传了不合格的身份证,还有服务器那边帮我们兜底,因为服务器端会对上传的照片再进行OCR识别,如果照片有问题就会返回失败,所以第二步对最终结果影响不大。所以可以改进的方向就是第一步,如何高效准确的提取出卡片的位置。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值