2021年11月15日补充了BufferedImage转Mat类(便于上传后比较)
某工J2EE大作业
在线搜索+人脸识别
首先要做的事
1.下载openCV
连接:https://pan.baidu.com/s/1eyzqcjnw17s_LpDXVmt-rA
提取码:tqn1
2.准备好IDEA web项目,服务器是tomcat(其实其他也行)
提取码:tqn1
项目需配置好tomcat相关库,启动后 首页为 login.jsp
有问题欢迎私聊…
在opencv安装目录下[opencv->build->java]根据电脑类型,复制x86或x64的dll文件
查看电脑类型方法:[我的电脑->属性] 看是基于什么的处理器
复制后,找到刚刚建的项目的java JDK目录
不知道的可以在IDEA 项目管理->SDK下找到,如图:
找到后,进入bin目录,将刚刚复制的dll文件粘贴到bin目录下
将要使用的jar包记得放在web\WEB-INF目录下!(包括openCV的jar包)
刚刚的目录下有openCV的jar包,复制放置在项目的web\WEB-INF目录下
(因为部署服务器会构建工件在C盘部署,所以本地指定的库路径在服务器上是无法使用的
因此必须以资源的形式一并构建过去)
以上就完成了OpenCV的环境配置,可以愉快的编写代码了!
以下是网络上的一个简单直方图匹配,侵删,稍作改进以适应tomcat的图片网络传输,成功率比较低,诸位也可以另寻算法
package com.Tool;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
/**
* 1. 灰度化(减小图片大小)
* 2. 人脸识别
* 3. 人脸切割
* 4. 规一化(人脸直方图)
* 5. 直方图相似度匹配
*/
public class FaceCompare {
// 初始化人脸探测器
static CascadeClassifier faceDetector;
static {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
faceDetector = new CascadeClassifier("lib/cascade_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(Mat mat_1, Mat mat_2) {
Mat hist_1 = new Mat();
Mat hist_2 = new Mat();
//颜色范围
MatOfFloat ranges = new MatOfFloat(0f, 256f);
//直方图大小, 越大匹配越精确 (越慢)
MatOfInt histSize = new MatOfInt(1000000);
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 String find(Mat mat_1,String realPath,int num){
String realName=null;
double hist=0;
double tempHist=0;
for (int i = 1000; i < 1000+num; i++) {
Mat mat_2 = conv_Mat(realPath+"p"+i+".jpg");
if((tempHist=compare_image(mat_1,mat_2))>hist){
hist=tempHist;
realName=""+i;
}
}
if(hist<0.2){
return "null";
}
return realName;
}
public static void main(String[] args) {
//图片命名格式:
//原图1:p1000.jpg
//上传测试1:test001.jpg
//原图2:p1001.jpg
//上传测试2:test002.jpg
//设置本地图片存放的文件夹名
String basePicPath = "test";//绝对路径也可
//设置存放的图片张数
int n=1;
//读取本地图片--单张图片对比
double compareHist = compare_image(conv_Mat(basePicPath + "//p1000.jpg"), conv_Mat(basePicPath + "//test001.jpg"));
System.out.println(compareHist);
if (compareHist > 0.72) {
System.out.println("人脸匹配");
} else {
System.out.println("人脸不匹配");
}
//以下为部署到tomcat测试
/*
FileInputStream fin = null;
BufferedImage image = null;
try {
fin = new FileInputStream("test/test001.jpg");
//转为image
image = ImageIO.read(fin);
} catch (IOException e) {
e.printStackTrace();
}
//BufImageToMat tool=new BufImageToMat();
//转为Mat开始比较,并传给FaceCompare类,返回数据库编号
//Mat mat=tool.BufImg2Mat(image,BufferedImage.TYPE_3BYTE_BGR, CvType.CV_8UC3);
//String num=FaceCompare.find(mat,"test/",n);
//test
//System.out.println(num);
*/
}
}
数据集的好坏决定了匹配的成功率
OpenCV提供了一些训练好的数据集可以供我们使用
在opencv安装目录【opencv\sources\data\haarcascades】中
红线是三个正面人脸匹配的数据集,各有优劣,可以搜搜区别
可以看出老外还是比较闲,连cat face都做了hhh
//工具类
public class BufImageToMat {
/**
* @param image 读入图片
*/
public Mat bufferToMartix(BufferedImage image) {
Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3);
byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
if (mat != null) {
try {
mat.put(0, 0, data);
} catch (Exception e) {
return null;
}
}
return mat;
}
/**
* bufImage转Mat类
* @param original 输入图片
* @param imgType 图片类型 一般设置为默认 BufferedImage.TYPE_3BYTE_BGR
* @param matType 直方图类型 一般设置为默认 CvType.CV_8UC3*/
public 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;
}
}
(已完…)
有问题欢迎私聊