Java+opencv实现人脸识别
写这篇博客,是因为以前经常使用python+opencv实现人脸处理,后来发现java也可以实现,于是便学习了下,以下将代码和实现过程贴出。
使用到的技术:java+opencv+mysql
我这里用的是opencv4.1,这里可以自行下载(其实只需要一个opencv的dll文件放在java安装目录的bin下面既可)
核心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();
@Override
public 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;
}
@Override
public 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);
}
}
网站操作流程如下:
第一步:人脸采集(支持上传图片预览)
入库成功:
开始人脸识别(人脸匹配成功):
写在最后:因篇幅有限,不能讲所有代码贴出,如果需要可以加我:3459067873