结合openCV来做身份证上的人脸识别,并将识别到的人脸保存下来,再用Tesseract的java实现tess4j做身份证文字信息采集案例
注:身份证人脸截图能够实现,身份证文字信息采集识别率不高,需要自己训练中文识别器来提高识别率。如何训练不在这里讨论。
下载地址:
https://download.csdn.net/download/l_sunrise/10965150
注意路径问题 ,可直接根据lbpcascade_frontalface.xml文件所在磁盘位置绝对路径来创建,也可将此文件引入到工程资源文件夹下,根据其路径找到该文件创建人脸识别器
由于Tesseract默认支持的是英文和数字的检查,若想其支持中文检查,需要自己下载中文检测器并放入tessdata文件夹下,可将整个文件夹拷贝进工程资源文件夹下,然后指明tessdata文件夹位置和扫描时需要识别中文
包含中文包,以tess4j的方式使用Tesseract做OCR,只需要其中的D:\tesseract\Tesseract-OCR\tessdata文件夹里的东西
下载地址:
https://download.csdn.net/download/l_sunrise/10988911
net.java.dev.jna
jna
4.1.0
net.sourceforge.tess4j
tess4j
3.2.1
com.sun.jna
jna
package testTess4j;
import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
import net.sourceforge.tess4j.util.ImageHelper;
import org.opencv.core.*;
import org.opencv.objdetect.CascadeClassifier;
import util.ClassPathUtil;
import util.ImgChangeUtil;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
/**
* @author LBW
* @name 身份证信息采集及人脸图片采集
* @date 2019/2/28 - 15:10
*/
public class Tess4jTest {
static {
//运行需要配置 VM options:-Djava.library.path=C:\\opencv\\build\\java\\x64(opencv_java320.dll的位置)
//因为用到openCV,在调用之前,一定要加上这句话,目的是加载OpenCV API相关的DLL支持,没有它是不会正确运行的
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
public static void main(String[] args) throws IOException {
ITesseract instance = new Tesseract();
//设置tessdata目录绝对路径
instance.setDatapath(ClassPathUtil.getPath()+"tessdata");
//如果需要识别英文之外的语种,需要指定识别语种,并且需要将对应的语言包放进项目中
instance.setLanguage("chi_sim");
// 指定需要识别的图片
File imageFile = new File("F:\\imgs\\3225d9bc0bf5835aaacb5db0e1a3904.jpg");
BufferedImage img= ImageIO.read(imageFile);
/**************************************截取身份证人脸图 start***********************************/
long startTime = System.currentTimeMillis();
BufferedImage faceImg = img;
//用来记录人脸坐标
int[] rectPosition = new int[4];
//从配置文件lbpcascade_frontalface.xml中创建一个人脸识别器
//该文件在openCV包C:\opencv\sources\data\haarcascades\中
CascadeClassifier faceDetector = new CascadeClassifier(ClassPathUtil.getPath()+"/haarcascades/haarcascade_frontalface_alt2.xml");
//将BufferedImage转换为Mat对象
Mat mat = ImgChangeUtil.BufImg2Mat(faceImg,BufferedImage.TYPE_3BYTE_BGR, CvType.CV_8UC3);
//指定人脸识别的最大和最小像素范围
Size minSize = new Size(500, 500);
Size maxSize = new Size(1500, 1500);
// 在图片中检测人脸,参数设置为scaleFactor=1.1f, minNeighbors=4, flags=0 以此来增加识别人脸的正确率
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(mat, faceDetections,1.1f, 4, 0, minSize, maxSize);
//人脸坐标
Rect[] rects = faceDetections.toArray();
//如果检测到人脸
if (rects != null && rects.length >= 1) {
System.out.println("识别到人脸,执行保存!");
for (Rect rect : rects) {
rectPosition[0]=rect.x-120;
rectPosition[1]=rect.y-240;
rectPosition[2]=rect.width+200;
rectPosition[3]=rect.height+600;
}
//将Mat对象转换回BufferedImage对象
faceImg = ImgChangeUtil.Mat2BufImg(mat,".jpg");
//截取图片
faceImg=ImageHelper.getSubImage(faceImg, rectPosition[0], rectPosition[1], rectPosition[2], rectPosition[3]);
ImageIO.write(faceImg,"jpg",new File("F:\\imgs\\faceImg1.jpg"));
}
System.out.println("人脸图片检测并保存耗时:"+(System.currentTimeMillis()-startTime)+"ms");
/**************************************截取身份证人脸图 end***********************************/
/***************************************提高 OCR 效率 start**********************************/
//int width=new Double(img.getWidth()*0.6).intValue();
//int height=new Double(img.getHeight()*0.25).intValue();
//如果需要识别的信息位置固定,可以截取图片,只识别那一部分,以提高识别效率
//img=ImageHelper.getSubImage(img, width, height, 1100, 1200);
//图片置灰
img = ImageHelper.convertImageToGrayscale(img);
//图片锐化
img = ImageHelper.convertImageToBinary(img);
//图片放大5倍,增强识别率
//img = ImageHelper.getScaledInstance(img, img.getWidth() * 5, img.getHeight() * 5);
/***************************************提高 OCR 效率 end***********************************/
startTime = System.currentTimeMillis();
String ocrResult = null;
try {
//执行OCR扫描识别文字
ocrResult = instance.doOCR(img);
} catch (TesseractException e) {
System.out.println("识别失败!");
e.printStackTrace();
}
// 输出识别结果
System.out.println("OCR Result: \n" + ocrResult + "\n耗时:" + (System.currentTimeMillis() - startTime) + "ms");
}
}
ClassPathUtil:
package util;//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import java.net.URLDecoder;
public class ClassPathUtil {
public ClassPathUtil() {
}
public static String getPath() {
String path = null;
try {
path = ClassPathUtil.class.getClassLoader().getResource("").getPath().toString();
String systemName = System.getProperty("os.name");
if (systemName.startsWith("Windows")) {
path = URLDecoder.decode(path.substring(1), "utf-8");
} else {
path = URLDecoder.decode(path, "utf-8");
}
} catch (Exception var2) {
var2.printStackTrace();
}
return path;
}
}
ImgChangeUtil:
package util;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.imgcodecs.Imgcodecs;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
/**
* @author
* @name openCV - Mat 对象与 BufferedImage 互转
* @date 2019/3/1 - 11:10
*/
public class ImgChangeUtil {
/**
* Mat转换成BufferedImage
*
* @param matrix
* 要转换的Mat
* @param fileExtension
* 格式为 ".jpg", ".png", etc
* @return
*/
public static BufferedImage Mat2BufImg (Mat matrix, String fileExtension) {
// convert the matrix into a matrix of bytes appropriate for
// this file extension
MatOfByte mob = new MatOfByte();
Imgcodecs.imencode(fileExtension, matrix, mob);
// convert the "matrix of bytes" into a byte array
byte[] byteArray = mob.toArray();
BufferedImage bufImage = null;
try {
InputStream in = new ByteArrayInputStream(byteArray);
bufImage = ImageIO.read(in);
} catch (Exception e) {
e.printStackTrace();
}
return bufImage;
}
/**
* BufferedImage转换成Mat
*
* @param original
* 要转换的BufferedImage
* @param imgType
* bufferedImage的类型 如 BufferedImage.TYPE_3BYTE_BGR
* @param matType
* 转换成mat的type 如 CvType.CV_8UC3
*/
public static Mat BufImg2Mat (BufferedImage original, int imgType, int matType) {
if (original == null) {
throw new IllegalArgumentException("original == null");
}
// Don't convert if it already has correct type
if (original.getType() != imgType) {
// Create a buffered image
BufferedImage image = new BufferedImage(original.getWidth(), original.getHeight(), imgType);
// Draw the image onto the new buffer
Graphics2D g = image.createGraphics();
try {
g.setComposite(AlphaComposite.Src);
g.drawImage(original, 0, 0, null);
} finally {
g.dispose();
}
}
byte[] pixels = ((DataBufferByte) original.getRaster().getDataBuffer()).getData();
Mat mat = Mat.eye(original.getHeight(), original.getWidth(), matType);
mat.put(0, 0, pixels);
return mat;
}
}