断断续续地折腾了大半个月,终于把身份证照片脸部识别以及OCR字体识别功能用Java实现了,需求很简单:通过摄像头所照的一张放在黑色底板上的身份证照,识别照片上身份证里面的人名和地址(OCR中文),再截取身份证上的头像用Base64编码。生成一个规定格式的XML然后把人名,地址和头像照片的编码放到XML里面。

其中用到了OpenCV, Tesseract-OCR 还有一些对BufferedImage进行图像处理的东西。代码倒也不算很复杂,但是其中几个问题的确很烧脑细胞,花了不少时间才解决(Jedi本人辛苦开发+原创码字博文共享,希望能):

1.  相片里面身份证的位置不确定问题: 底板比较大身份证可以在上面随意位置摆放

解决方法很简单,人脸识别时候把人脸的位置坐标返回出来,利用这个坐标来确定身份证位置也大大缩小需要字体OCR识别的区域。不需要整张照片做OCR也节省了许多运算时间。

2.  OpenCV人脸识别的容错率问题(有时候一张照片可以识别出三个头像来, 连个模糊的色块也能识别为一个头像,汗啊),当然了,识别人脸时候需要的lbpcascade_frontalface.xml是必须的。上网找就有不少地方有的下载。运行时需要这个xml位于你的可运行jar所在的同个路径下

解决方法是思路就是指定进行人脸识别的最大和最小像素范围minSize和maxSize(就是多大尺寸以内才去分析是不是人脸,当然要具体情况具体设置,minsize最好设大一点点,不然一个模糊小色块都会可能被误当作是人脸,T_T),然后设置参数scaleFactor,minNeighbors和flags来提高识别正确率,具体代码如下:

public int[] detectFace(String imageFileName) {

int[] RectPosition = new int[4];

CascadeClassifier faceDetector = new CascadeClassifier("lbpcascade_frontalface.xml");

Mat image = Highgui.imread(imageFileName);

MatOfRect faceDetections = new MatOfRect();

//指定人脸识别的最大和最小像素范围

Size minSize = new Size(120, 120);

Size maxSize = new Size(250, 250);

//参数设置为scaleFactor=1.1f, minNeighbors=4, flags=0 以此来增加识别人脸的正确率

faceDetector.detectMultiScale(image, faceDetections, 1.1f, 4, 0, minSize, maxSize);

//对识别出来的头像画个方框,并且返回这个方框的位置坐标和大小

for (Rect rect : faceDetections.toArray()) {

Core.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x

+ rect.width, rect.y + rect.height), new Scalar(0, 255, 0));

RectPosition[0]=rect.x;

RectPosition[1]=rect.y;

RectPosition[2]=rect.width;

RectPosition[3]=rect.height;

System.out.println(rect.x +" "+ rect.y + " "+rect.width+" "+rect.height);

}

// 下面注释掉的三行可以用来生成识别出的人脸图像,保存下来以便Debug用

//          String filename = "face.png";

//          System.out.println(String.format("Writing %s", filename));

//          Highgui.imwrite(filename, image);

return RectPosition;

}

3.  Tesseract-OCR对身份证上的字体识别率比较低的问题。Tesseract自带的chi_sim.traineddatad(识别库)对身份证上字体的识别率偏低,想了很多办法,也用了很多时间精力去用身份证专用的华文细黑字体库来做训练 (关于如何使用jTessBoxEditor-1.2来生成tif图片和矫正每个字体的识别,还有如何用命令行进行训练生成tessdata识别库的问题,学到的经验多到几乎可以写一大篇文档了。这个要等有时间再总结了),捣腾了很多次之后发现出来的tessdata并没有比原生自带的chi_sim识别率提高多少,可能是需要从大到小不同字体都进行训练才行。

4.  身份证照片解析度不高,1600x1200的摄像头照出来的效果不敢恭维而且身份证相片上面有很多弧形干扰线导致识别率更加低

为了提高解析度消除干扰线,我用了Tess4J自带的ImageHelper.convertImageToBinary()把图像处理成黑白照片,一次性解决了字体受干扰的问题,不过由照片上笔画比较多的字体笔画间隙出现了模糊,我在转换黑背之前加上了一个图像处理的步骤,消除字体笔画间隙的干扰让字体更加清晰,方法如下:

public BufferedImage replaceWithWhiteColor(BufferedImage bi) {

int[] rgb = new int[3];

int width = bi.getWidth();

int height = bi.getHeight();

int minx = bi.getMinX();

int miny = bi.getMinY();

/**

* 遍历图片的像素,为处理图片上的杂色,所以要把指定像素上的颜色换成目标白色 用二层循环遍历长和宽上的每个像素

*/

int hitCount = 0;

for (int i = minx; i < width-1; i++) {

for (int j = miny; j < height; j++) {

/**

* 得到指定像素(i,j)上的RGB值,

*/

int pixel = bi.getRGB(i, j);

int pixelNext = bi.getRGB(i+1, j);

/**

* 分别进行位操作得到 r g b上的值

*/

rgb[0] = (pixel & 0xff0000) >> 16;

rgb[1] = (pixel & 0xff00) >> 8;

rgb[2] = (pixel & 0xff);

/**

* 进行换色操作,我这里是要换成白底,那么就判断图片中rgb值是否在范围内的像素

*/

//经过不断尝试,RGB数值相互间相差15以内的都基本上是灰色,

//对以身份证来说特别是介于73到78之间,还有大于100的部分RGB值都是干扰色,将它们一次性转变成白色

if ((Math.abs(rgb[0] - rgb[1]) < 15)

&& (Math.abs(rgb[0] - rgb[2]) < 15)

&& (Math.abs(rgb[1] - rgb[2]) < 15) &&

(((rgb[0] > 73)&& (rgb[0] < 78))||(rgb[0] > 100))) {

//进行换色操作,0xffffff是白色

bi.setRGB(i, j, 0xffffff);

}

}

}

return bi;

}

5.  关于Java调用DLL的问题,OpenCV和Tesseract-OCR都不是Java原生的,需要去load外部的DLL动态链接库文件

OpenCV需要用到opencv_java2410.dll (这个DLL和相关的opencv-2410.jar可以下载并安装opencv-2.4.10.exe之后在openCV的安装路径下找到opencv\build\java\, 里面有64位和32位不同的版本,需要根据你运行时的JRE/JDK是否为64位来决定),而且需要在运行时候用System.load("C:\\opencv_java2410.dll") 导入,这里我用了绝对路径去load这个opencv_java2410.dll. 所以在发布的时候可以用一个bat判断是否在C:\根目录下是否存在这个dll,没有的话就立马copy一个过去再运行java。(bat批处理来调用java的时候可以指定jre,也可以避免java版本64位或者32位的问题)

而相对来说Tess4j就简单许多,首先只需要下载tesseract-ocr-setup-3.02.02.exe并安装上(默认的chi_sim. Traineddatad大概40M,安装程序自动连接到Google的服务器下载,没有翻墙的话可能下载失败,需要的童鞋可以到CSDN下载http://download.csdn.net/download/java_mamad/7308769,下载了之后放到C:\Program Files (x86)\Tesseract-OCR\tessdata\就行。然后把安装目录下的liblept168.dll, liblept168d.dll 和libtesseract302.dll拷贝到你的java项目根目录就行了,打包的时候这三个文件也是必须的,必须放到你的可运行jar包的相同路径下。(刚发现tesseract-OCR的所有东西都可以到SourceForge下载:http://sourceforge.net/projects/tesseract-ocr-alt/files/ 不用翻墙可以下得到)

6.  打包jar包发布的时候如果用一个大的jar包里面包含了所有的依赖包(包括jai-imageio.jar)就会出现

sun.misc.ServiceConfigurationError: javax.imageio.spi.ImageOutputStreamSpi: Provider com.sun.med

ia.imageioimpl.stream.ChannelImageOutputStreamSpi could not be instantiated: java.lang.IllegalArgumentException: vendorName == null!

这个是由于imageIO的调用失败导致的,我尝试了很多做法,譬如修改Manifest .MF文件都还是不行T_T,最后还是选择分开单独打包jar和依赖包的方法才行。一个可运行jar包走天下的愿望泡汤了。

7.   调试中发现一张大照片来做OCR识别字体的结果比你限制一个小的区域单独做OCR的效果差很多,所以如果有可能的话还是尽量缩小你要OCR识别字体的范围,不断识别率提高了而且处理起来速度也快很多。我就是通过定位身份证头像大致位置来估算身份证文字位置大小区域来实现的。

8.  在开发中我为了识别完每张图片生成XML之后删除图片,用了file.deleteOnExit(); 结果发现几张图处理完之后全部图都删除了剩下最后一张图没法删除。

研究了大半天才发现问题所在:BufferedImage image = ImageIO.read(new FileInputStream(imgPath));

这样写的代码是存在问题的,因为这个FileInputStream在被GC之前是没有办法去close掉。没有close就会导致了文件无法被删除而且file.deleteOnExie()是不会有IOException抛出的.  查找BUG会相当的confuse费时费力.  正确的写法应该是:

FileInputStream fins = new FileInputStream(imgPath);

BufferedImage image = ImageIO.read(fins);

最后用fins.close(); 关闭这个FileInputStream, 文件就能删除了,良好的编程代码习惯还是要慢慢养成,不然要花很多时间在Debug上面。

9.  另外我也试过了手机上的App扫描全能王和PC上的汉王OCR,感觉都是挺不错的成熟产品识别率挺高的,可惜没有提供第三方可调用的接口(当然不开放了,不然人家怎么赚钱^_^)Google的Tesseract可提升的空间还很大,如果有时间的话多用用不同大小的字体来训练可以获得更高的识别率。

转载于:https://www.cnblogs.com/jedisniper/p/4135076.html

java实现的身份证照片脸部识别(头像截图) 以及OCR字体识别相关推荐

  1. 头像截图上传两种方式(SWFUpload、一个简单易用的flash插件)

    SWFUpload是一个客户端文件上传工具,最初由Vinterwebb.se开发,它通过整合Flash与JavaScript技术为WEB开发者提供了一个具有丰富功能继而超越传统<input ty ...

  2. 类似微信,微博,QQ的头像截图功能, 图片支持缩放

    类似微信,微博,QQ的头像截图功能, 图片支持缩放, 不多说了, 直接上源码! http://pan.baidu.com/s/1gdJxb03

  3. java ocr文字识别软件_Java文字识别软件-调用百度ocr实现文字识别

    java_baidu_ocr Java调用百度OCR文字识别API实现图片文字识别软件 这是一款小巧方便,强大的文字识别软件,由Java编写,配上了窗口界面 调用了百度ocr文字识别API 识别精度高 ...

  4. Java调用百度OCR文字识别API实现图片文字识别软件

    java_baidu_ocr Java调用百度OCR文字识别API实现图片文字识别软件 这是一款小巧方便,强大的文字识别软件,由Java编写,配上了窗口界面 调用了百度ocr文字识别API 识别精度高 ...

  5. Tesseract字体识别 及 jTessBoxEditor工具进行训练 及 Java API实现字体识别

    Tesseract程序识别 程序源码 tesseract项目的github地址 (Linux下可通过包管理器下载安装) 基本使用 注意点:1,图片文件类型为tiff/tif,2,output是输出文件 ...

  6. Java实现百度云OCR接口识别图片文字信息(也包含身份证,银行卡识别,更新添加通用票据识别)

    参考: https://blog.csdn.net/weixin_40165004/article/details/82632229 1.需求背景 因项目需求,需要提取身份证.发票(9/16更新内容) ...

  7. java ocr api_Java调用百度OCR文字识别API实现图片文字识别软件

    Java调用百度OCR文字识别API实现图片文字识别软件 原创isinple 发布于2019-01-06 13:35:59 阅读数 1296 收藏 展开 java_baidu_ocr Java调用百度 ...

  8. java代码编写的文本特征提取_Test1 java语言写的特征提取源代码,有搞文字识别的可以下载一看,简单易学 Develop 274万源代码下载- www.pudn.com...

    文件名称: Test1下载  收藏√  [ 5  4  3  2  1 ] 开发工具: Java 文件大小: 35 KB 上传时间: 2015-03-02 下载次数: 46 提 供 者: 常杰 详细说 ...

  9. Java调用百度OCR文字识别的接口

    调用百度OCR文字识别的接口,来自于百度官网,亲测可以使用 跳转链接 FileUtil的下载链接 Base64Util下载链接 HttpUtil下载链接 GsonUtils下载链接 Accurate. ...

  10. python ocr 文字识别软件,Python文字截图识别OCR工具实例解析

    一.简介 你一定用过那种"OCR神器",可以把图片中的文字提取出来,极大的提高工作效率. 今天,我们就来做一款实时截图识别的小工具.顾名思义,运行程序时,可以实时把你截出来的图片中 ...

最新文章

  1. tp5 日期范围查询_VB实战应用 | 如何巧妙解决日期范围查询问题
  2. 搭建webpack基础配置
  3. 2019春晚百度App日活破3亿 百度系App霸榜AppStore
  4. windows下安装gcc编译器(c/c++/fortran)
  5. 《炬丰科技-半导体工艺》Micro-LED 显示器量化生产关键技术
  6. ORB_SLAM2编译build_ros.sh时报错([rosbuild] Error from directory check: /opt/ros/kinetic/share)
  7. 线程插队--Join方法
  8. 汇编 bne 1b和bne 1f浅析
  9. 《长安十二时辰》,作为程序员,看完我震惊了!涉及通信、云计算、大数据等!...
  10. 迭代学习控制方式Simulink建模与仿真
  11. 2021哈工大深入理解计算机系统Lab5(linklab)
  12. Plantuml类图用法
  13. 青龙面板搭建 纯小白教程
  14. 参加公众号互推的背后
  15. SF中DispSync.cpp源码分析
  16. 最大流算法之一——EK算法
  17. 开源 java CMS - FreeCMS2.4 统计分析
  18. 软件测试集成测试ppt,软件测试单元测试和集成测试.ppt
  19. 字节跳动Lark-EA部门春招-实习/校招/社招-咨询群
  20. 如何从立创商城下载元器件封装

热门文章

  1. windows程序介绍
  2. 无数本高清古籍善本下载,200多个G
  3. Flash CS 6绘图技巧之锁定填充
  4. 龙威ol服务器维护,《龙威OL》搅屎棍职业技能攻略详解
  5. [转]最世界最牛人博客,你可以学习到太多太多`~~
  6. 2021-05-13 Redis面试题 MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据?
  7. 前端代码更新镜像后,浏览器显示缓存
  8. h3c交换机-初级命令
  9. 双操作系统安装(三)Windows及Deepin深度linux双系统安装教程
  10. 【原创】惠普 CQ35-222TX 笔记本电脑安装东皇 v3.2 Mac OS 详解