tomcat+jsp IDEA 在线人脸识别 寻找系统 基于openCV

也可以叫软院寻人(2022年3月22日更新完毕)

2021年11月15日补充了BufferedImage转Mat类(便于上传后比较)
某工J2EE大作业
在线搜索+人脸识别
首先要做的事
1.下载openCV
连接:https://pan.baidu.com/s/1eyzqcjnw17s_LpDXVmt-rA
提取码:tqn1
2.准备好IDEA web项目,服务器是tomcat(其实其他也行)

3月22日上传源码

链接:https://pan.baidu.com/s/1DJcPZbLSDE7C9T6lNd5pwQ

提取码:tqn1

项目需配置好tomcat相关库,启动后 首页为 login.jsp
有问题欢迎私聊…

开始!

1.为java JDK配置openCV连接库

在opencv安装目录下[opencv->build->java]根据电脑类型,复制x86或x64的dll文件
查看电脑类型方法:[我的电脑->属性] 看是基于什么的处理器
电脑类型
复制后,找到刚刚建的项目的java JDK目录
不知道的可以在IDEA 项目管理->SDK下找到,如图:
JDK路径
找到后,进入bin目录,将刚刚复制的dll文件粘贴到bin目录下

2.IDEA中一些配置

将要使用的jar包记得放在web\WEB-INF目录下!(包括openCV的jar包)
刚刚的目录下有openCV的jar包,复制放置在项目的web\WEB-INF目录下
(因为部署服务器会构建工件在C盘部署,所以本地指定的库路径在服务器上是无法使用的
因此必须以资源的形式一并构建过去)
jar包路径
以上就完成了OpenCV的环境配置,可以愉快的编写代码了!

以下是网络上的一个简单直方图匹配,侵删,稍作改进以适应tomcat的图片网络传输,成功率比较低,诸位也可以另寻算法

3.简单直方匹配代码

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

补充:少了工具类 bufImage转mat

//工具类
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;
    }
}

(已完…)
有问题欢迎私聊

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值