Java+opencv实现人脸识别
写这篇博客,是因为以前经常使用python+opencv实现人脸处理,后来发现java也可以实现,于是便学习了下,以下将代码和实现过程贴出。
目录
1、环境准备
使用到的技术:java+opencv+mysql
我这里用的是opencv4.1,这里可以自行下载(其实只需要一个opencv的dll文件放在java安装目录的bin下面既可)
2、代码实现
核心opencv人脸识别类(识别算法):
package com.dialect.utils;import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;import java.util.Arrays;/*** 1. 灰度化(减小图片大小)* 2. 人脸识别* 3. 人脸切割* 4. 规一化(人脸直方图)* 5. 直方图相似度匹配*** @Description: 比较两张图片人脸的匹配度* @date 2019/2/1813:47*/
public class FaceCompare {// 初始化人脸探测器static CascadeClassifier faceDetector;static {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);faceDetector = new CascadeClassifier("E:\\eclipseworkspace\\FaceDectcoSys\\src\\haarcascade_frontalface_default.xml");}// 灰度化人脸public static Mat conv_Mat(String img) {Mat image0 = Imgcodecs.imread(img);Mat image1 = new Mat();// 灰度化Imgproc.cvtColor(image0, image1, Imgproc.COLOR_BGR2GRAY);// 探测人脸MatOfRect faceDetections = new MatOfRect();faceDetector.detectMultiScale(image1, faceDetections);// rect中人脸图片的范围for (Rect rect : faceDetections.toArray()) {Mat face = new Mat(image1, rect);return face;}return null;}public static double compare_image(String img_1, String img_2) {Mat mat_1 = conv_Mat(img_1);Mat mat_2 = conv_Mat(img_2);Mat hist_1 = new Mat();Mat hist_2 = new Mat();//颜色范围MatOfFloat ranges = new MatOfFloat(0f, 256f);//直方图大小, 越大匹配越精确 (越慢)MatOfInt histSize = new MatOfInt(1000);Imgproc.calcHist(Arrays.asList(mat_1), new MatOfInt(0), new Mat(), hist_1, histSize, ranges);Imgproc.calcHist(Arrays.asList(mat_2), new MatOfInt(0), new Mat(), hist_2, histSize, ranges);// CORREL 相关系数double res = Imgproc.compareHist(hist_1, hist_2, Imgproc.CV_COMP_CORREL);return res;}public static void main(String[] args) {String basePicPath = "E:\\eclipseworkspace\\FaceDectcoSys\\WebContent\\static\\images\\";double compareHist = compare_image(basePicPath + "fbb1.jpg", basePicPath + "fbb2.jpg");System.out.println(compareHist);if (compareHist > 0.72) {System.out.println("人脸匹配");} else {System.out.println("人脸不匹配");}}
}
测试两张图片相似度(美女照片自己网上找):
测试结果:相似度0.82左右,还好了
接着实现网页
数据库dao:
package com.dialect.info.dao;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;import com.dialect.info.bean.Dect;/*** 人脸信息DAO接口* @author admin* @version 2020-05-10*/
public class DectDao {/*** 添加* @param con* @param Dialect* @return* @throws Exception*/public int add(Connection con,Dect dect)throws Exception{dect.setId(UUID.randomUUID().toString().replace("-", ""));String sql="insert into dect values(?,?)";PreparedStatement pstmt=con.prepareStatement(sql);pstmt.setString(1,dect.getId());pstmt.setString(2,dect.getBase64());return pstmt.executeUpdate();}/*** 查询所有* @param con* @param dialect* @return* @throws Exception*/public List<Dect> list(Connection con)throws Exception{List<Dect> list = new ArrayList<>();Dect entity=null;String sql = "select a.* from dect a";PreparedStatement pstmt=con.prepareStatement(sql);ResultSet rs=pstmt.executeQuery();while(rs.next()){entity = new Dect();entity.setId(rs.getString("id"));entity.setBase64(rs.getString("base64"));list.add(entity);}return list;}}
service层:
package com.dialect.info.service.impl;import java.sql.Connection;
import java.util.List;import com.dialect.info.bean.Dect;
import com.dialect.info.dao.DectDao;
import com.dialect.info.service.DectService;
import com.dialect.utils.DbUtil;
import com.dialect.utils.Page;/*** 人脸信息DAO接口* @author admin* @version 2020-05-10*/
public class DectServiceImpl implements DectService {DectDao dectDao = new DectDao();@Overridepublic int add(Dect dect) {try {Connection con = DbUtil.getCon();Integer result =dectDao.add(con, dect);DbUtil.closeCon(con);return result;} catch (Exception e) {e.printStackTrace();}return 0;}@Overridepublic List<Dect> select() {try {Connection con = DbUtil.getCon();List<Dect> list = dectDao.list(con);DbUtil.closeCon(con);return list;} catch (Exception e) {e.printStackTrace();}return null;}}
control控制层:
package com.dialect.info.controller;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;import com.dialect.info.bean.Dect;
import com.dialect.info.dao.DectDao;
import com.dialect.info.service.DectService;
import com.dialect.info.service.impl.DectServiceImpl;
import com.dialect.utils.Page;
import com.dialect.utils.picToBase64;
import com.dialect.utils.FaceCompare; @WebServlet("/dect")
public class DectController extends HttpServlet {private static final long serialVersionUID = 1L;DectDao dectDao=new DectDao();DectService dectService = new DectServiceImpl();protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String method = request.getParameter("method");if ("upload".equals(method)) {upload(request,response);}else if ("select".equals(method)) {select(request, response);}else if ("list".equals(method)) {list(request, response);}else if ("form".equals(method)) {form(request, response);}}//添加private void upload(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.err.println("---开始上传---");String para = request.getParameter("base64");String s = para.replace("data:image/jpeg;base64,","");System.err.println(para);System.err.println(s);Dect dect = new Dect();dect.setBase64(s);int res = dectService.add(dect);// System.err.println(res);// String res = "1";
// String res2 = "3";// 解决json中文乱码response.setContentType("text/json;charset=UTF-8");response.setCharacterEncoding("UTF-8");PrintWriter out = response.getWriter();
// String str ="{\"success\":"+res+",\"age\":"+res2 +"}";String str ="{\"success\":"+res+"}";out.println(str);out.flush();out.close();}//添加private void select(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.err.println("---进来了select方法---");FaceCompare faceCompare = new FaceCompare();String para = request.getParameter("base64");String s = para.replace("data:image/jpeg;base64,","");System.err.println(para);System.err.println(s);picToBase64 pic = new picToBase64();String imgPath1 = "E:\\eclipseworkspace\\FaceDectcoSys\\WebContent\\static\\images\\img1.jpg";String imgPath2 = "E:\\eclipseworkspace\\FaceDectcoSys\\WebContent\\static\\images\\img2.jpg";
// String imgPath1 = "E:\\img1.jpg";
// String imgPath2 = "E:\\img2.jpg";//String imgPath2 = "E:\\eclipseworkspace\\FaceDectcogSys\\WebContent\\static\\images\\img2";pic.Base64ToImage(s, imgPath1);List<Dect> list = dectService.select();int shibie_flag = 0;double res = 0;System.err.println(list.size());if (list.size()>0){for(Dect dect:list){System.err.println(dect.getBase64());String s1 = dect.getBase64().replace("data:image/jpeg;base64,","");System.err.println("s1:"+s1);picToBase64 pic2 = new picToBase64();pic2.Base64ToImage(s1, imgPath2);res = faceCompare.compare_image(imgPath1, imgPath2);if (res > 0.72){System.out.println("人脸匹配");shibie_flag = 1;break;}}}response.setContentType("text/json;charset=UTF-8");response.setCharacterEncoding("UTF-8");PrintWriter out = response.getWriter();String str ="{\"success\":"+shibie_flag+",\"res\":"+res +"}";
// String str ="{\"success\":"+res+"}";out.println(str);out.flush();out.close();
// response.sendRedirect(contextPath+"/dialect?method=list");}//列表查询private void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.getRequestDispatcher("/dectList2.jsp").forward(request, response);}//form跳转页面private void form(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.getRequestDispatcher("/dectList3.jsp").forward(request, response);}}
3、运行效果
网站操作流程如下:
第一步:人脸采集(支持上传图片预览)
入库成功:
开始人脸识别(人脸匹配成功):
写在最后:因篇幅有限,不能讲所有代码贴出,如果遇到问题可以加博主V交流:Code2Life2