Opencv实现身份证OCR识别的示例详解
更新时间:2024年03月06日 10:27:22 作者:落日流年
这篇文章主要为大家详细介绍了如何使用Opencv实现身份证OCR识别功能,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以跟随小编一起了解一下
Opencv 配置IDEA可参考:Java调用opencv IDEA环境配置的教程详解
opencv位置:
OpencvUtil类:
package com.x.common.utils; import org.opencv.core.*; import org.opencv.core.Point; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import org.opencv.objdetect.CascadeClassifier; 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; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class OpencvUtil { private static final int BLACK = 0; private static final int WHITE = 255; /** * 灰化处理 * @return */ public static Mat gray (Mat mat){ Mat gray = new Mat(); Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY,1); return gray; } /** * 二值化处理 * @return */ public static Mat binary (Mat mat){ Mat binary = new Mat(); Imgproc.adaptiveThreshold(mat, binary, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 25, 10); return binary; } /** * 模糊处理 * @param mat * @return */ public static Mat blur (Mat mat) { Mat blur = new Mat(); Imgproc.blur(mat,blur,new Size(5,5)); return blur; } /** *膨胀 * @param mat * @return */ public static Mat dilate (Mat mat,int size){ Mat dilate=new Mat(); Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(size,size)); //膨胀 Imgproc.dilate(mat, dilate, element, new Point(-1, -1), 1); return dilate; } /** * 腐蚀 * @param mat * @return */ public static Mat erode (Mat mat,int size){ Mat erode=new Mat(); Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(size,size)); //腐蚀 Imgproc.erode(mat, erode, element, new Point(-1, -1), 1); return erode; } /** * 边缘检测 * @param mat * @return */ public static Mat carry(Mat mat){ Mat dst=new Mat(); //高斯平滑滤波器卷积降噪 Imgproc.GaussianBlur(mat, dst, new Size(3,3), 0); //边缘检测 Imgproc.Canny(mat, dst, 50, 150); return dst; } /** * 轮廓检测 * @param mat * @return */ public static List<MatOfPoint> findContours(Mat mat){ List<MatOfPoint> contours=new ArrayList<>(); Mat hierarchy = new Mat(); Imgproc.findContours(mat, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); return contours; } /** * 清除小面积轮廓 * @param mat * @param size * @return */ public static Mat drawContours(Mat mat,int size){ List<MatOfPoint> cardContours=OpencvUtil.findContours(mat); for (int i = 0; i < cardContours.size(); i++) { double area=OpencvUtil.area(cardContours.get(i)); if(area<size){ Imgproc.drawContours(mat, cardContours, i, new Scalar( 0, 0, 0),-1 ); } } return mat; } /** * 人脸识别 * @param mat * @return */ public static Mat face(Mat mat){ CascadeClassifier faceDetector = new CascadeClassifier( System.getProperty("user.dir")+"\\opencv\\haarcascades\\haarcascade_frontalface_alt.xml"); // 在图片中检测人脸 MatOfRect faceDetections = new MatOfRect(); //指定人脸识别的最大和最小像素范围 Size minSize = new Size(100, 100); Size maxSize = new Size(500, 500); //参数设置为scaleFactor=1.1f, minNeighbors=4, flags=0 以此来增加识别人脸的正确率 faceDetector.detectMultiScale(mat, faceDetections, 1.1f, 4, 0, minSize, maxSize); Rect[] rects = faceDetections.toArray(); if(rects != null && rects.length == 1){ // 在每一个识别出来的人脸周围画出一个方框 Rect rect = rects[0]; return mat; }else{ return null; } } /** * 循环进行人脸识别 * */ public static Mat faceLoop(Mat src){ Mat face=new Mat(); //默认人脸识别失败时图像旋转90度 int k=90; while (k>0){ for(int i=0;i<360/k;i++){ //人脸识别 face= OpencvUtil.face(src); if(face==null){ src = rotate3(src,k); }else{ break; } } if(face!=null){ break; }else{ k=k-30; } } return src; } /** * 剪切身份证区域 * @param mat */ public static Mat houghLinesP(Mat begin,Mat mat){ //灰度 mat=OpencvUtil.gray(mat); //二值化 mat=OpencvUtil.binary(mat); //腐蚀 mat=OpencvUtil.erode(mat,5); //边缘检测 mat=OpencvUtil.carry(mat); //降噪 mat=OpencvUtil.navieRemoveNoise(mat,1); //膨胀 mat=OpencvUtil.dilate(mat,3); //轮廓检测,清除小的轮廓部分 List<MatOfPoint> contours=OpencvUtil.findContours(mat); for(int i=0;i<contours.size();i++){ double area=OpencvUtil.area(contours.get(i)); if(area<5000){ Imgproc.drawContours(mat, contours, i, new Scalar( 0, 0, 0), -1); } } Mat storage = new Mat(); Imgproc.HoughLinesP(mat, storage, 1, Math.PI / 180, 10, 0, 10); double[] maxLine = new double[]{0,0,0,0}; //获取最长的直线 for (int x = 0; x < storage.rows(); x++) { double[] vec = storage.get(x, 0); double x1 = vec[0], y1 = vec[1], x2 = vec[2], y2 = vec[3]; double newLength = Math.sqrt(Math.abs((x1 - x2)* (x1 - x2)+(y1 - y2)* (y1 - y2))); double oldLength = Math.sqrt(Math.abs((maxLine[0] - maxLine[2])* (maxLine[0] - maxLine[2])+(maxLine[1] - maxLine[3])* (maxLine[1] - maxLine[3]))); if(newLength>oldLength){ maxLine = vec; } } //计算最长线的角度 double angle = getAngle(maxLine[0],maxLine[1],maxLine[2],maxLine[3]); //旋转角度 mat = rotate3( mat,angle); begin = rotate3( begin,angle); Imgproc.HoughLinesP(mat, storage, 1, Math.PI / 180, 10, 10, 10); List<double[]> lines=new ArrayList<>(); //在mat上划线 for (int x = 0; x < storage.rows(); x++) { double[] vec = storage.get(x, 0); double x1 = vec[0], y1 = vec[1], x2 = vec[2], y2 = vec[3]; Point start = new Point(x1, y1); Point end = new Point(x2, y2); //获取与图像x边缘近似平行的直线 if(Math.abs(start.y-end.y)<5){ if(Math.abs(x2-x1)>20){ lines.add(vec); } } //获取与图像y边缘近似平行的直线 if(Math.abs(start.x-end.x)<5){ if(Math.abs(y2-y1)>20){ lines.add(vec); } } } //获取最大的和最小的X,Y坐标 double maxX=0.0,minX=10000,minY=10000,maxY=0.0; for(int i=0;i<lines.size();i++){ double[] vec = lines.get(i); double x1 = vec[0], y1 = vec[1], x2 = vec[2], y2 = vec[3]; maxX=maxX>x1?maxX:x1; maxX=maxX>x2?maxX:x2; minX=minX>x1?x1:minX; minX=minX>x2?x2:minX; maxY=maxY>y1?maxY:y1; maxY=maxY>y2?maxY:y2; minY=minY>y1?y1:minY; minY=minY>y2?y2:minY; } if(maxX<mat.cols()&&minX>0&&maxY<mat.rows()&&minY>0){ List<Point> list=new ArrayList<>(); Point point1=new Point(minX+10,minY+10); Point point2=new Point(minX+10,maxY-10); Point point3=new Point(maxX-10,minY+10); Point point4=new Point(maxX-10,maxY-10); list.add(point1); list.add(point2); list.add(point3); list.add(point4); mat=shear(begin,list); }else{ mat=begin; } return mat; } /** * 计算角度 * @param px1 * @param py1 * @param px2 * @param py2 * @return */ public static double getAngle(double px1, double py1, double px2, double py2) { //两点的x、y值 double x = px2-px1; double y = py2-py1; double hypotenuse = Math.sqrt(Math.pow(x, 2)+Math.pow(y, 2)); //斜边长度 double cos = x/hypotenuse; double radian = Math.acos(cos); //求出弧度 double angle = 180/(Math.PI/radian); //用弧度算出角度 if (y<0) { angle = -angle; } else if ((y == 0) && (x<0)) { angle = 180; } while (angle<0){ angle = angle +90; } return angle; } /** * 累计概率hough变换直线检测 * @param mat */ public static Mat houghLines(Mat mat){ Mat storage = new Mat(); Imgproc.HoughLines(mat, storage, 1, Math.PI / 180, 50, 0, 0, 0, 1); for (int x = 0; x < storage.rows(); x++) { double[] vec = storage.get(x, 0); double rho = vec[0]; double theta = vec[1]; Point pt1 = new Point(); Point pt2 = new Point(); double a = Math.cos(theta); double b = Math.sin(theta); double x0 = a * rho; double y0 = b * rho; pt1.x = Math.round(x0 + 1000 * (-b)); pt1.y = Math.round(y0 + 1000 * (a)); pt2.x = Math.round(x0 - 1000 * (-b)); pt2.y = Math.round(y0 - 1000 * (a)); if (theta >= 0) { Imgproc.line(mat, pt1, pt2, new Scalar(255), 3); } } return mat; } /** * 根据四点坐标截取模板图片 * @param mat * @param pointList * @return */ public static Mat shear (Mat mat,List<Point> pointList){ int x=minX(pointList); int y=minY(pointList); int xl=xLength(pointList)>mat.cols()-x?mat.cols()-x:xLength(pointList); int yl=yLength(pointList)>mat.rows()-y?mat.rows()-y:yLength(pointList); Rect re=new Rect(x,y,xl,yl); return new Mat(mat,re); } /** * 图片旋转 * @param splitImage * @param angle * @return */ public static Mat rotate3(Mat splitImage, double angle){ double thera = angle * Math.PI / 180; double a = Math.sin(thera); double b = Math.cos(thera); int wsrc = splitImage.width(); int hsrc = splitImage.height(); int wdst = (int) (hsrc * Math.abs(a) + wsrc * Math.abs(b)); int hdst = (int) (wsrc * Math.abs(a) + hsrc * Math.abs(b)); Mat imgDst = new Mat(hdst, wdst, splitImage.type()); Point pt = new Point(splitImage.cols() / 2, splitImage.rows() / 2); // 获取仿射变换矩阵 Mat affineTrans = Imgproc.getRotationMatrix2D(pt, angle, 1.0); //System.out.println(affineTrans.dump()); // 改变变换矩阵第三列的值 affineTrans.put(0, 2, affineTrans.get(0, 2)[0] + (wdst - wsrc) / 2); affineTrans.put(1, 2, affineTrans.get(1, 2)[0] + (hdst - hsrc) / 2); Imgproc.warpAffine(splitImage, imgDst, affineTrans, imgDst.size(), Imgproc.INTER_CUBIC | Imgproc.WARP_FILL_OUTLIERS); return imgDst; } /** * 图像直方图处理 * @param mat * @return */ public static Mat equalizeHist(Mat mat){ Mat dst = new Mat(); List<Mat> mv = new ArrayList<>(); Core.split(mat, mv); for (int i = 0; i < mat.channels(); i++) { Imgproc.equalizeHist(mv.get(i), mv.get(i)); } Core.merge(mv, dst); return dst; } /** * 8邻域降噪,又有点像9宫格降噪;即如果9宫格中心被异色包围,则同化 * @param pNum 默认值为1 */ public static Mat navieRemoveNoise(Mat mat,int pNum) { int i, j, m, n, nValue, nCount; int nWidth = mat.cols(); int nHeight = mat.rows(); // 如果一个点的周围都是白色的,而它确是黑色的,删除它 for (j = 1; j < nHeight - 1; ++j) { for (i = 1; i < nWidth - 1; ++i) { nValue = (int)mat.get(j, i)[0]; if (nValue == 0) { nCount = 0; // 比较以(j ,i)为中心的9宫格,如果周围都是白色的,同化 for (m = j - 1; m <= j + 1; ++m) { for (n = i - 1; n <= i + 1; ++n) { if ((int)mat.get(m, n)[0] == 0) { nCount++; } } } if (nCount <= pNum) { // 周围黑色点的个数小于阀值pNum,把该点设置白色 mat.put(j, i, WHITE); } } else { nCount = 0; // 比较以(j ,i)为中心的9宫格,如果周围都是黑色的,同化 for (m = j - 1; m <= j + 1; ++m) { for (n = i - 1; n <= i + 1; ++n) { if ((int)mat.get(m, n)[0] == 0) { nCount++; } } } if (nCount >= 7) { // 周围黑色点的个数大于等于7,把该点设置黑色;即周围都是黑色 mat.put(j, i, BLACK); } } } } return mat; } /** * 连通域降噪 * @param pArea 默认值为1 */ public static Mat contoursRemoveNoise(Mat mat,double pArea) { //mat=floodFill(mat,mat.new Point(mat.cols()/2,mat.rows()/2),new Color(225,0,0)); int i, j, color = 1; int nWidth = mat.cols(), nHeight = mat.rows(); for (i = 0; i < nWidth; ++i) { for (j = 0; j < nHeight; ++j) { if ((int) mat.get(j, i)[0] == BLACK) { //用不同颜色填充连接区域中的每个黑色点 //floodFill就是把一个点x的所有相邻的点都涂上x点的颜色,一直填充下去,直到这个区域内所有的点都被填充完为止 Imgproc.floodFill(mat, new Mat(), new Point(i, j), new Scalar(color)); color++; } } } //统计不同颜色点的个数 int[] ColorCount = new int[255]; for (i = 0; i < nWidth; ++i) { for (j = 0; j < nHeight; ++j) { if ((int) mat.get(j, i)[0] != 255) { ColorCount[(int) mat.get(j, i)[0] - 1]++; } } } //去除噪点 for (i = 0; i < nWidth; ++i) { for (j = 0; j < nHeight; ++j) { if (ColorCount[(int) mat.get(j, i)[0] - 1] <= pArea) { mat.put(j, i, WHITE); } } } for (i = 0; i < nWidth; ++i) { for (j = 0; j < nHeight; ++j) { if ((int) mat.get(j, i)[0] < WHITE) { mat.put(j, i, BLACK); } } } return mat; } /** * Mat转换成BufferedImage * * @param matrix * 要转换的Mat * @param fileExtension * 格式为 ".jpg", ".png", etc * @return */ public static BufferedImage Mat2BufImg (Mat matrix, String fileExtension) { MatOfByte mob = new MatOfByte(); Imgcodecs.imencode(fileExtension, matrix, mob); 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"); } if (original.getType() != imgType) { BufferedImage image = new BufferedImage(original.getWidth(), original.getHeight(), imgType); Graphics2D g = image.createGraphics(); try { g.setComposite(AlphaComposite.Src); g.drawImage(original, 0, 0, null); } finally { g.dispose(); } } DataBufferByte dbi =(DataBufferByte)original.getRaster().getDataBuffer(); byte[] pixels = dbi.getData(); Mat mat = Mat.eye(original.getHeight(), original.getWidth(), matType); mat.put(0, 0, pixels); return mat; } /** * 人眼识别 * @param mat * @return */ public static List<Point> eye(Mat mat){ List<Point> eyeList=new ArrayList<>(); CascadeClassifier eyeDetector = new CascadeClassifier( System.getProperty("user.dir")+"\\opencv\\haarcascades\\haarcascade_eye.xml"); // 在图片中检测人眼 MatOfRect eyeDetections = new MatOfRect(); //指定人脸识别的最大和最小像素范围 Size minSize = new Size(20, 20); Size maxSize = new Size(30, 30); eyeDetector.detectMultiScale(mat, eyeDetections, 1.1f, 3, 0, minSize, maxSize); Rect[] rects = eyeDetections.toArray(); if(rects != null && rects.length == 2){ Point point1=new Point(rects[0].x,rects[0].y); eyeList.add(point1); Point point2=new Point(rects[1].x,rects[1].y); eyeList.add(point2); }else{ return null; } return eyeList; } /** * 获取轮廓的顶点坐标 * @param contour * @return */ public static List<Point> getPointList(MatOfPoint contour){ MatOfPoint2f mat2f=new MatOfPoint2f(); contour.convertTo(mat2f,CvType.CV_32FC1); RotatedRect rect=Imgproc.minAreaRect(mat2f); Mat points=new Mat(); Imgproc.boxPoints(rect,points); return getPoints(points.dump()); } /** * 获取轮廓的面积 * @param contour * @return */ public static double area (MatOfPoint contour){ MatOfPoint2f mat2f=new MatOfPoint2f(); contour.convertTo(mat2f,CvType.CV_32FC1); RotatedRect rect=Imgproc.minAreaRect(mat2f); return rect.boundingRect().area(); } /** * 获取点坐标集合 * @param str * @return */ public static List<Point> getPoints(String str){ List<Point> points=new ArrayList<>(); str=str.replace("[","").replace("]",""); String[] pointStr=str.split(";"); for(int i=0;i<pointStr.length;i++){ double x=Double.parseDouble(pointStr[i].split(",")[0]); double y=Double.parseDouble(pointStr[i].split(",")[1]); Point po=new Point(x,y); points.add(po); } return points; } /** * 获取最小的X坐标 * @param points * @return */ public static int minX(List<Point> points){ Collections.sort(points, new XComparator(false)); return (int)(points.get(0).x>0?points.get(0).x:-points.get(0).x); } /** * 获取最小的Y坐标 * @param points * @return */ public static int minY(List<Point> points){ Collections.sort(points, new YComparator(false)); return (int)(points.get(0).y>0?points.get(0).y:-points.get(0).y); } /** * 获取最长的X坐标距离 * @param points * @return */ public static int xLength(List<Point> points){ Collections.sort(points, new XComparator(false)); return (int)(points.get(3).x-points.get(0).x); } /** * 获取最长的Y坐标距离 * @param points * @return */ public static int yLength(List<Point> points){ Collections.sort(points, new YComparator(false)); return (int)(points.get(3).y-points.get(0).y); } //集合排序规则(根据X坐标排序) public static class XComparator implements Comparator<Point> { private boolean reverseOrder; // 是否倒序 public XComparator(boolean reverseOrder) { this.reverseOrder = reverseOrder; } public int compare(Point arg0, Point arg1) { if(reverseOrder) return (int)arg1.x - (int)arg0.x; else return (int)arg0.x - (int)arg1.x; } } //集合排序规则(根据Y坐标排序) public static class YComparator implements Comparator<Point> { private boolean reverseOrder; // 是否倒序 public YComparator(boolean reverseOrder) { this.reverseOrder = reverseOrder; } public int compare(Point arg0, Point arg1) { if(reverseOrder) return (int)arg1.y - (int)arg0.y; else return (int)arg0.y - (int)arg1.y; } } }
OCRUtil类:
package com.xinjian.x.common.ocr; import net.sourceforge.tess4j.ITesseract; import net.sourceforge.tess4j.Tesseract; import net.sourceforge.tess4j.util.LoadLibs; import java.awt.image.BufferedImage; import java.io.File; public class OCRUtil { /** * 识别图片信息 * @param img * @return */ public static String getImageMessage(BufferedImage img,String language){ String result="end"; try{ ITesseract instance = new Tesseract(); File tessDataFolder = LoadLibs.extractTessResources("tessdata"); instance.setLanguage(language); instance.setDatapath(tessDataFolder.getAbsolutePath()); result = instance.doOCR(img); //System.out.println(result); }catch(Exception e){ System.out.println(e.getMessage()); } return result; } }
language为语言包名称eng或者chi_sim,chi_sim语言包可能与jar包不匹配需要注意
<!--OCR Tesseract--> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>4.1.0</version> </dependency> <dependency> <groupId>net.sourceforge.tess4j</groupId> <artifactId>tess4j</artifactId> <version>2.0.1</version> <exclusions> <exclusion> <groupId>com.sun.jna</groupId> <artifactId>jna</artifactId> </exclusion> </exclusions> </dependency>
Main 方法:
package com.xinjian.x.modules.orc; import com.xinjian.x.common.ocr.OCRUtil; import com.xinjian.x.common.utils.OpencvUtil; import org.opencv.core.*; import org.opencv.core.Point; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; import static com.xinjian.x.common.utils.OpencvUtil.rotate3; import static com.xinjian.x.common.utils.OpencvUtil.shear; public class OrcTest { static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); //注意程序运行的时候需要在VM option添加该行 指明opencv的dll文件所在路径 //-Djava.library.path=$PROJECT_DIR$\opencv\x64 } public static void main(String[] args){ String path="D:/Users/xinjian09/Desktop/c.jpg"; Mat mat= Imgcodecs.imread(path); cardUp(mat); } /** * 身份证反面识别 */ public static void cardDown(Mat mat){ //灰度 mat=OpencvUtil.gray(mat); //二值化 mat=OpencvUtil.binary(mat); //腐蚀 mat=OpencvUtil.erode(mat,3); //膨胀 mat=OpencvUtil.dilate(mat,3); //检测是否有居民身份证字体,若有为正向,若没有则旋转图片 for(int i=0;i<4;i++){ String temp=temp(mat); if(!temp.contains("居")&&!temp.contains("民")){ mat= rotate3(mat,90); }else{ break; } } Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/result.jpg", mat); String organization=organization (mat); System.out.print("签发机关是:"+organization); String time=time (mat); System.out.print("有效期限是:"+time); } public static String temp (Mat mat){ Point point1=new Point(mat.cols()*0.30,mat.rows()*0.25); Point point2=new Point(mat.cols()*0.30,mat.rows()*0.25); Point point3=new Point(mat.cols()*0.90,mat.rows()*0.45); Point point4=new Point(mat.cols()*0.90,mat.rows()*0.45); List<Point> list=new ArrayList<>(); list.add(point1); list.add(point2); list.add(point3); list.add(point4); Mat temp= shear(mat,list); List<MatOfPoint> nameContours=OpencvUtil.findContours(temp); for (int i = 0; i < nameContours.size(); i++) { double area=OpencvUtil.area(nameContours.get(i)); if(area<100){ Imgproc.drawContours(temp, nameContours, i, new Scalar( 0, 0, 0), -1); } } Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/temp.jpg", temp); BufferedImage nameBuffer=OpencvUtil.Mat2BufImg(temp,".jpg"); String nameStr=OCRUtil.getImageMessage(nameBuffer,"chi_sim"); nameStr=nameStr.replace("\n",""); return nameStr; } public static String organization (Mat mat){ Point point1=new Point(mat.cols()*0.36,mat.rows()*0.68); Point point2=new Point(mat.cols()*0.36,mat.rows()*0.68); Point point3=new Point(mat.cols()*0.80,mat.rows()*0.80); Point point4=new Point(mat.cols()*0.80,mat.rows()*0.80); List<Point> list=new ArrayList<>(); list.add(point1); list.add(point2); list.add(point3); list.add(point4); Mat name= shear(mat,list); List<MatOfPoint> nameContours=OpencvUtil.findContours(name); for (int i = 0; i < nameContours.size(); i++) { double area=OpencvUtil.area(nameContours.get(i)); if(area<100){ Imgproc.drawContours(name, nameContours, i, new Scalar( 0, 0, 0), -1); } } Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/organization.jpg", name); BufferedImage nameBuffer=OpencvUtil.Mat2BufImg(name,".jpg"); String nameStr=OCRUtil.getImageMessage(nameBuffer,"chi_sim"); nameStr=nameStr.replace("\n",""); return nameStr+"\n"; } public static String time (Mat mat){ Point point1=new Point(mat.cols()*0.38,mat.rows()*0.82); Point point2=new Point(mat.cols()*0.38,mat.rows()*0.82); Point point3=new Point(mat.cols()*0.85,mat.rows()*0.92); Point point4=new Point(mat.cols()*0.85,mat.rows()*0.92); List<Point> list=new ArrayList<>(); list.add(point1); list.add(point2); list.add(point3); list.add(point4); Mat time= shear(mat,list); List<MatOfPoint> timeContours=OpencvUtil.findContours(time); for (int i = 0; i < timeContours.size(); i++) { double area=OpencvUtil.area(timeContours.get(i)); if(area<100){ Imgproc.drawContours(time, timeContours, i, new Scalar( 0, 0, 0), -1); } } Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/time.jpg", time); //起始日期 Point startPoint1=new Point(0,0); Point startPoint2=new Point(0,time.rows()); Point startPoint3=new Point(time.cols()*0.47,0); Point startPoint4=new Point(time.cols()*0.47,time.rows()); List<Point> startList=new ArrayList<>(); startList.add(startPoint1); startList.add(startPoint2); startList.add(startPoint3); startList.add(startPoint4); Mat start= shear(time,startList); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/start.jpg", start); BufferedImage yearBuffer=OpencvUtil.Mat2BufImg(start,".jpg"); String startStr=OCRUtil.getImageMessage(yearBuffer,"eng"); startStr=startStr.replace("-",""); startStr=startStr.replace(" ",""); startStr=startStr.replace("\n",""); //截止日期 Point endPoint1=new Point(time.cols()*0.47,0); Point endPoint2=new Point(time.cols()*0.47,time.rows()); Point endPoint3=new Point(time.cols(),0); Point endPoint4=new Point(time.cols(),time.rows()); List<Point> endList=new ArrayList<>(); endList.add(endPoint1); endList.add(endPoint2); endList.add(endPoint3); endList.add(endPoint4); Mat end= shear(time,endList); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/end.jpg", end); BufferedImage endBuffer=OpencvUtil.Mat2BufImg(end,".jpg"); String endStr=OCRUtil.getImageMessage(endBuffer,"chi_sim"); if(!endStr.contains("长")&&!endStr.contains("期")){ endStr=OCRUtil.getImageMessage(endBuffer,"eng"); endStr=endStr.replace("-",""); endStr=endStr.replace(" ",""); } return startStr+"-"+endStr; } /** * 身份证正面识别 */ public static void cardUp (Mat mat){ Mat begin=mat.clone(); //截取身份证区域,并校正旋转角度 mat = OpencvUtil.houghLinesP(begin,mat); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/houghLinesP.jpg", mat); //循环进行人脸识别,校正图片方向 mat=OpencvUtil.faceLoop(mat); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/face.jpg", mat); //灰度 mat=OpencvUtil.gray(mat); //二值化 mat=OpencvUtil.binary(mat); //腐蚀 mat=OpencvUtil.erode(mat,1); //膨胀 mat=OpencvUtil.dilate(mat,1); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/bbb.jpg", mat); //获取名称 String name=name(mat); System.out.print("姓名是:"+name); //获取性别 String sex=sex(mat); System.out.print("性别是:"+sex); //获取民族 String nation=nation(mat); System.out.print("民族是:"+nation); //获取出生日期 String birthday=birthday(mat); System.out.print("出生日期是:"+birthday); //获取住址 String address=address(mat); System.out.print("住址是:"+address); //获取身份证 String card=card(mat); System.out.print("身份证号是:"+card); } public static String name(Mat mat){ Point point1=new Point(mat.cols()*0.18,mat.rows()*0.11); Point point2=new Point(mat.cols()*0.18,mat.rows()*0.24); Point point3=new Point(mat.cols()*0.4,mat.rows()*0.11); Point point4=new Point(mat.cols()*0.4,mat.rows()*0.24); List<Point> list=new ArrayList<>(); list.add(point1); list.add(point2); list.add(point3); list.add(point4); Mat name= shear(mat,list); name=OpencvUtil.drawContours(name,50); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/name.jpg", name); BufferedImage nameBuffer=OpencvUtil.Mat2BufImg(name,".jpg"); String nameStr=OCRUtil.getImageMessage(nameBuffer,"chi_sim"); nameStr=nameStr.replace("\n",""); return nameStr+"\n"; } public static String sex(Mat mat){ Point point1=new Point(mat.cols()*0.18,mat.rows()*0.25); Point point2=new Point(mat.cols()*0.18,mat.rows()*0.35); Point point3=new Point(mat.cols()*0.25,mat.rows()*0.25); Point point4=new Point(mat.cols()*0.25,mat.rows()*0.35); List<Point> list=new ArrayList<>(); list.add(point1); list.add(point2); list.add(point3); list.add(point4); Mat sex= shear(mat,list); sex=OpencvUtil.drawContours(sex,50); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/sex.jpg", sex); BufferedImage sexBuffer=OpencvUtil.Mat2BufImg(sex,".jpg"); String sexStr=OCRUtil.getImageMessage(sexBuffer,"chi_sim"); sexStr=sexStr.replace("\n",""); return sexStr+"\n"; } public static String nation(Mat mat){ Point point1=new Point(mat.cols()*0.39,mat.rows()*0.25); Point point2=new Point(mat.cols()*0.39,mat.rows()*0.36); Point point3=new Point(mat.cols()*0.55,mat.rows()*0.25); Point point4=new Point(mat.cols()*0.55,mat.rows()*0.36); List<Point> list=new ArrayList<>(); list.add(point1); list.add(point2); list.add(point3); list.add(point4); Mat nation= shear(mat,list); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/nation.jpg", nation); BufferedImage nationBuffer=OpencvUtil.Mat2BufImg(nation,".jpg"); String nationStr=OCRUtil.getImageMessage(nationBuffer,"chi_sim"); nationStr=nationStr.replace("\n",""); return nationStr+"\n"; } public static String birthday(Mat mat){ Point point1=new Point(mat.cols()*0.18,mat.rows()*0.35); Point point2=new Point(mat.cols()*0.18,mat.rows()*0.35); Point point3=new Point(mat.cols()*0.55,mat.rows()*0.48); Point point4=new Point(mat.cols()*0.55,mat.rows()*0.48); List<Point> list=new ArrayList<>(); list.add(point1); list.add(point2); list.add(point3); list.add(point4); Mat birthday= shear(mat,list); birthday=OpencvUtil.drawContours(birthday,50); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/birthday.jpg", birthday); //年份 Point yearPoint1=new Point(0,0); Point yearPoint2=new Point(0,birthday.rows()); Point yearPoint3=new Point(birthday.cols()*0.29,0); Point yearPoint4=new Point(birthday.cols()*0.29,birthday.rows()); List<Point> yearList=new ArrayList<>(); yearList.add(yearPoint1); yearList.add(yearPoint2); yearList.add(yearPoint3); yearList.add(yearPoint4); Mat year= shear(birthday,yearList); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/year.jpg", year); BufferedImage yearBuffer=OpencvUtil.Mat2BufImg(year,".jpg"); String yearStr=OCRUtil.getImageMessage(yearBuffer,"eng"); //月份 Point monthPoint1=new Point(birthday.cols()*0.44,0); Point monthPoint2=new Point(birthday.cols()*0.44,birthday.rows()); Point monthPoint3=new Point(birthday.cols()*0.55,0); Point monthPoint4=new Point(birthday.cols()*0.55,birthday.rows()); List<Point> monthList=new ArrayList<>(); monthList.add(monthPoint1); monthList.add(monthPoint2); monthList.add(monthPoint3); monthList.add(monthPoint4); Mat month= shear(birthday,monthList); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/month.jpg", month); BufferedImage monthBuffer=OpencvUtil.Mat2BufImg(month,".jpg"); String monthStr=OCRUtil.getImageMessage(monthBuffer,"eng"); //日期 Point dayPoint1=new Point(birthday.cols()*0.69,0); Point dayPoint2=new Point(birthday.cols()*0.69,birthday.rows()); Point dayPoint3=new Point(birthday.cols()*0.80,0); Point dayPoint4=new Point(birthday.cols()*0.80,birthday.rows()); List<Point> dayList=new ArrayList<>(); dayList.add(dayPoint1); dayList.add(dayPoint2); dayList.add(dayPoint3); dayList.add(dayPoint4); Mat day= shear(birthday,dayList); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/day.jpg", day); BufferedImage dayBuffer=OpencvUtil.Mat2BufImg(day,".jpg"); String dayStr=OCRUtil.getImageMessage(dayBuffer,"eng"); String birthdayStr=yearStr+"年"+monthStr+"月"+dayStr+"日"; birthdayStr=birthdayStr.replace("\n",""); return birthdayStr+"\n"; } public static String address(Mat mat){ Point point1=new Point(mat.cols()*0.17,mat.rows()*0.47); Point point2=new Point(mat.cols()*0.17,mat.rows()*0.47); Point point3=new Point(mat.cols()*0.61,mat.rows()*0.76); Point point4=new Point(mat.cols()*0.61,mat.rows()*0.76); List<Point> list=new ArrayList<>(); list.add(point1); list.add(point2); list.add(point3); list.add(point4); Mat address= shear(mat,list); address=OpencvUtil.drawContours(address,50); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/address.jpg", address); BufferedImage addressBuffer=OpencvUtil.Mat2BufImg(address,".jpg"); return OCRUtil.getImageMessage(addressBuffer,"chi_sim")+"\n"; } public static String card(Mat mat){ Point point1=new Point(mat.cols()*0.34,mat.rows()*0.75); Point point2=new Point(mat.cols()*0.34,mat.rows()*0.75); Point point3=new Point(mat.cols()*0.89,mat.rows()*0.91); Point point4=new Point(mat.cols()*0.89,mat.rows()*0.91); List<Point> list=new ArrayList<>(); list.add(point1); list.add(point2); list.add(point3); list.add(point4); Mat card= shear(mat,list); card=OpencvUtil.drawContours(card,50); Imgcodecs.imwrite("D:/Users/xinjian09/Desktop/card.jpg", card); BufferedImage cardBuffer=OpencvUtil.Mat2BufImg(card,".jpg"); return OCRUtil.getImageMessage(cardBuffer,"eng")+"\n"; } }
以上就是Opencv实现身份证OCR识别的示例详解的详细内容,更多关于Opencv身份证OCR识别的资料请关注脚本之家其它相关文章!
相关文章
在deepin上如何使用Fleet开发SpringBoot 3.0.0项目
这篇文章主要介绍了在deepin上使用Fleet开发SpringBoot 3.0.0项目的过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2023-09-09
最新评论