基于javafx和虹软ArcFace的高校新生人脸录入与识别系统 一、需求分析 二、关键技术 三、实现目标 四、效果展示 八、项目总结

随着人脸识别技术的快速发展,各大高校也开始尝试在新生入校时就通过人脸识别相关技术对新生人脸信息进行采集并录入高校人脸信息库中。在今后的学习生活中,已经录入人脸信息的同学可以轻松的通过人脸识别设备进行人份认证。

人脸识别在高校中的使用场景也十分广泛,例如高校宿舍进出管理,实验室进出管理,图书馆进出管理,图书借阅等。笔者所在学校在信息化建设过程中也充分的发挥了人脸识别的作用,在疫情期间结合人脸识别搭建了一套测温系统。

本项目旨在通过javafx以及webcam和ArcFace等技术搭建一个简单的高校新生人脸信息录入与识别系统。

二、关键技术

javafx:JavaFX 是一个开源的下一代客户端应用平台,适用于基于Java构建的桌面、移动端和嵌入式系统。 它是许多个人和公司的共同努力的成果,目的是为开发丰富的客户端应用提供一个现代、高效、功能齐全的工具包。

webcam:java第三方库,可以调用系统摄像头并进行拍照

ArcFace:虹软提供的离线人脸识别库,版本为3.0。

三、实现目标

可以通过摄像头对用户信息(人脸信息、姓名、学号、专业班级)进行录入,数据使用mysql进行存储。

可以通过人脸对用户信息进行识别

四、效果展示

1、人脸信息录入

基于javafx和虹软ArcFace的高校新生人脸录入与识别系统
一、需求分析
二、关键技术
三、实现目标
四、效果展示
八、项目总结

用户人脸已经录入则提示:

基于javafx和虹软ArcFace的高校新生人脸录入与识别系统
一、需求分析
二、关键技术
三、实现目标
四、效果展示
八、项目总结

当检测不到人脸信息时:

基于javafx和虹软ArcFace的高校新生人脸录入与识别系统
一、需求分析
二、关键技术
三、实现目标
四、效果展示
八、项目总结

录入成功:

基于javafx和虹软ArcFace的高校新生人脸录入与识别系统
一、需求分析
二、关键技术
三、实现目标
四、效果展示
八、项目总结

数据库:

基于javafx和虹软ArcFace的高校新生人脸录入与识别系统
一、需求分析
二、关键技术
三、实现目标
四、效果展示
八、项目总结

2、人脸信息识别

基于javafx和虹软ArcFace的高校新生人脸录入与识别系统
一、需求分析
二、关键技术
三、实现目标
四、效果展示
八、项目总结

识别结果:

基于javafx和虹软ArcFace的高校新生人脸录入与识别系统
一、需求分析
二、关键技术
三、实现目标
四、效果展示
八、项目总结
无人脸信息则没有反应:

基于javafx和虹软ArcFace的高校新生人脸录入与识别系统
一、需求分析
二、关键技术
三、实现目标
四、效果展示
八、项目总结

五、代码实现及数据库设计

1、数据库设计

基于javafx和虹软ArcFace的高校新生人脸录入与识别系统
一、需求分析
二、关键技术
三、实现目标
四、效果展示
八、项目总结

2、流程图

人脸信息录入流程图

基于javafx和虹软ArcFace的高校新生人脸录入与识别系统
一、需求分析
二、关键技术
三、实现目标
四、效果展示
八、项目总结

人脸信息识别流程图

基于javafx和虹软ArcFace的高校新生人脸录入与识别系统
一、需求分析
二、关键技术
三、实现目标
四、效果展示
八、项目总结

3、代码实现

依赖:

<dependencies>
        <!-- https://mvnrepository.com/artifact/com.github.sarxos/webcam-capture -->
        <dependency>
            <groupId>com.github.sarxos</groupId>
            <artifactId>webcam-capture</artifactId>
            <version>0.3.12</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-core -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.6.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.7</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
    </dependencies>

工具类:

package zzuli.zw.camera;

import com.arcsoft.face.*;
import com.arcsoft.face.enums.DetectMode;
import com.arcsoft.face.enums.DetectOrient;
import com.arcsoft.face.toolkit.ImageFactory;
import com.arcsoft.face.toolkit.ImageInfo;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;

/**
 * @ClassName FaceUtils
 * @Description TODO
 * @Author wu2wen
 * @Date 2021/7/9 15:00
 * @Version 1.0
 */
public class FaceUtils {
    private  FaceEngine faceEngine;
    private ImageInfo imageInfo;
    private FunctionConfiguration functionConfiguration;
    //根据实际情况进行配置
    private static final String configFile = "C:\Users\wu2we\Desktop\ArcSoft_ArcFace_Java_Windows_x64_V3.0\libs\WIN64";
    public FaceUtils(){
        faceEngine = new FaceEngine(configFile);
        //引擎配置
        EngineConfiguration engineConfiguration = new EngineConfiguration();
        engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
        engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
        engineConfiguration.setDetectFaceMaxNum(10);
        engineConfiguration.setDetectFaceScaleVal(16);
        //功能配置
        functionConfiguration = new FunctionConfiguration();
        functionConfiguration.setSupportAge(true);
        functionConfiguration.setSupportFace3dAngle(true);
        functionConfiguration.setSupportFaceDetect(true);
        functionConfiguration.setSupportFaceRecognition(true);
        functionConfiguration.setSupportGender(true);
        functionConfiguration.setSupportLiveness(true);
        functionConfiguration.setSupportIRLiveness(true);
        engineConfiguration.setFunctionConfiguration(functionConfiguration);
        faceEngine.init(engineConfiguration);
    }
    public FaceUtils(String imageUrl){
        imageInfo = getRGBData(new File(imageUrl));
        faceEngine = new FaceEngine(configFile);
        //引擎配置
        EngineConfiguration engineConfiguration = new EngineConfiguration();
        engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
        engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
        engineConfiguration.setDetectFaceMaxNum(10);
        engineConfiguration.setDetectFaceScaleVal(16);
        //功能配置
        functionConfiguration = new FunctionConfiguration();
        functionConfiguration.setSupportAge(true);
        functionConfiguration.setSupportFace3dAngle(true);
        functionConfiguration.setSupportFaceDetect(true);
        functionConfiguration.setSupportFaceRecognition(true);
        functionConfiguration.setSupportGender(true);
        functionConfiguration.setSupportLiveness(true);
        engineConfiguration.setFunctionConfiguration(functionConfiguration);
        faceEngine.init(engineConfiguration);
    }

    public FaceEngine getFaceEngine() {
        return faceEngine;
    }

    public void setImageInfo(String imageUrl) {
        this.imageInfo = getRGBData(new File(imageUrl));
    }
    public float compareTo(byte[] byte1,byte[] byte2){
        //特征比对
        FaceFeature targetFaceFeature = new FaceFeature();
        targetFaceFeature.setFeatureData(byte1);
        FaceFeature sourceFaceFeature = new FaceFeature();
        sourceFaceFeature.setFeatureData(byte2);
        FaceSimilar faceSimilar = new FaceSimilar();
        int errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
        if (errorCode != ResponseCode.MOK)return -1;
        System.out.println("相似度:" + faceSimilar.getScore());
        return faceSimilar.getScore();
    }
    /**
     * @Date: 2021/7/9 16:43
     * @Author 索半斤
     * @Description: 获取人脸信息
     * @MethodName:
     */
    public  List<FaceInfo> getFaceInfo(){
        if (imageInfo == null)return null;
        List<FaceInfo> faceInfoList = new ArrayList<>();
        int errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
        if (errorCode != ResponseCode.MOK)return null;
        if (faceInfoList.size() == 0)return null;
        return faceInfoList;
    }
    /**
     * @Date: 2021/7/9 16:43
     * @Author 索半斤
     * @Description: 检测是否为活体
     * @MethodName:
     */
    public  boolean isLive(){
        if (imageInfo == null)return false;
        faceEngine.setLivenessParam(0.5f, 0.7f);
        FunctionConfiguration configuration = new FunctionConfiguration();
        configuration.setSupportAge(true);
        configuration.setSupportFace3dAngle(true);
        configuration.setSupportGender(true);
        configuration.setSupportLiveness(true);
        List<FaceInfo> faceInfo = getFaceInfo();
        int errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfo, configuration);
        if (errorCode != ResponseCode.MOK)return false;
        //活体检测
        List<LivenessInfo> livenessInfoList = new ArrayList<>();
        errorCode = faceEngine.getLiveness(livenessInfoList);
        if (errorCode != ResponseCode.MOK)return false;
        if (livenessInfoList.size() == 0)return false;
        return livenessInfoList.get(0).getLiveness() == 1;
    }
    /**
     * @Date: 2021/7/9 15:46
     * @Author 索半斤
     * @Description: 获取人脸特征值
     * @MethodName:
     */
    public byte[] getFaceFeature(){
        if (imageInfo == null)return null;
        if (!isLive())return null;
        List<FaceInfo> faceInfoList = getFaceInfo();
        if (faceInfoList == null || faceInfoList.size() == 0)return null;
        //特征提取
        FaceFeature faceFeature = new FaceFeature();
        int errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
        if (errorCode != ResponseCode.MOK)return null;
        return faceFeature.getFeatureData();
    }

    public void unInit(){
        faceEngine.unInit();
    }
}

人脸信息录入:

package zzuli.zw.camera;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamEvent;
import com.github.sarxos.webcam.WebcamListener;
import com.github.sarxos.webcam.WebcamResolution;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class MyCameraConfig extends Application {
    /**
     * 拍照存储的文件路径
     */
    String filePath = "C:/image/";

    private static class WebCamInfo {
        private String webCamName;
        private int webCamIndex;

        public String getWebCamName() {
            return webCamName;
        }

        public void setWebCamName(String webCamName) {
            this.webCamName = webCamName;
        }

        public int getWebCamIndex() {
            return webCamIndex;
        }

        public void setWebCamIndex(int webCamIndex) {
            this.webCamIndex = webCamIndex;
        }
    }

    private FlowPane bottomCameraControlPane;
    private FlowPane topPane;
    private ImageView imgWebCamCapturedImage;
    private Webcam webCam = null;
    private boolean stopCamera = false;
    private BufferedImage grabbedImage;
    private ObjectProperty<Image> imageProperty = new SimpleObjectProperty<>();
    private BorderPane webCamPane;

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("摄像");
        BorderPane root = new BorderPane();
        topPane = new FlowPane();
        topPane.setAlignment(Pos.CENTER);
        topPane.setHgap(20);
        topPane.setOrientation(Orientation.HORIZONTAL);
        topPane.setPrefHeight(40);
        root.setTop(topPane);
        webCamPane = new BorderPane();
        webCamPane.setStyle("-fx-background-color: #ccc;");
        imgWebCamCapturedImage = new ImageView();
        webCamPane.setCenter(imgWebCamCapturedImage);
        root.setCenter(webCamPane);
        createTopPanel();
        bottomCameraControlPane = new FlowPane();
        bottomCameraControlPane.setOrientation(Orientation.HORIZONTAL);
        bottomCameraControlPane.setAlignment(Pos.CENTER);
        bottomCameraControlPane.setHgap(20);
        bottomCameraControlPane.setVgap(10);
        bottomCameraControlPane.setPrefHeight(40);
        bottomCameraControlPane.setDisable(true);
        createCameraControls();
        root.setBottom(bottomCameraControlPane);
        primaryStage.setScene(new Scene(root));
        primaryStage.setHeight(700);
        primaryStage.setWidth(600);
        primaryStage.centerOnScreen();
        primaryStage.show();
        Platform.runLater(this::setImageViewSize);
    }

    protected void setImageViewSize() {
        double height = webCamPane.getHeight();
        double width = webCamPane.getWidth();
        imgWebCamCapturedImage.setFitHeight(height);
        imgWebCamCapturedImage.setFitWidth(width);
        imgWebCamCapturedImage.prefHeight(height);
        imgWebCamCapturedImage.prefWidth(width);
        imgWebCamCapturedImage.setPreserveRatio(true);
    }

    private void createTopPanel() {
        int webCamCounter = 0;
        Label lbInfoLabel = new Label("选择摄像头:");
        ObservableList<WebCamInfo> options = FXCollections.observableArrayList();
        topPane.getChildren().add(lbInfoLabel);
        for (Webcam webcam : Webcam.getWebcams()) {
            WebCamInfo webCamInfo = new WebCamInfo();
            webCamInfo.setWebCamIndex(webCamCounter);
            webCamInfo.setWebCamName(webcam.getName());
            options.add(webCamInfo);
            webCamCounter++;
        }

        ComboBox<WebCamInfo> cameraOptions = new ComboBox<>();
        cameraOptions.setItems(options);
        String cameraListPromptText = "选择摄像头:";
        cameraOptions.setPromptText(cameraListPromptText);
        cameraOptions.getSelectionModel().selectedItemProperty().addListener((ObservableValue<? extends WebCamInfo> arg0, WebCamInfo arg1, WebCamInfo arg2) -> {
            if (arg2 != null) {
                initializeWebCam(arg2.getWebCamIndex());
            }
        });
        topPane.getChildren().add(cameraOptions);
    }

    protected void initializeWebCam(final int webCamIndex) {
        Task<Void> webCamTask = new Task<Void>() {
            @Override
            protected Void call() {
                webCam = Webcam.getWebcams().get(webCamIndex);
                webCam.setViewSize(WebcamResolution.VGA.getSize());
                webCam.open();
                startWebCamStream();
                return null;
            }
        };
        Thread webCamThread = new Thread(webCamTask);
        webCamThread.setDaemon(true);
        webCamThread.start();
        bottomCameraControlPane.setDisable(false);
    }

    protected void startWebCamStream() {
        stopCamera = false;
        Task<Void> task = new Task<Void>() {
            @Override
            protected Void call() {
                while (!stopCamera) {
                    try {
                        if ((grabbedImage = webCam.getImage()) != null) {
                            Platform.runLater(() -> {
                                Image mainImage = SwingFXUtils.toFXImage(grabbedImage, null);

                                imageProperty.set(mainImage);
                            });
                            grabbedImage.flush();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                return null;
            }
        };
        Thread th = new Thread(task);
        th.setDaemon(true);
        th.start();
        imgWebCamCapturedImage.imageProperty().bind(imageProperty);
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello");
                Platform.runLater(()->{
                    getImagine();
                    timer.cancel();
                });
            }
        }, 2000);

    }

    private void createCameraControls() {
    }

    protected void getImagine() {
        Image image = imgWebCamCapturedImage.getImage();
        ImageView imageView = new ImageView();
        Label label = new Label("姓      名:");
        TextField textField = new TextField();
        HBox hBox = new HBox(5);
        hBox.setAlignment(Pos.CENTER);
        hBox.getChildren().addAll(label, textField);
        Label label2 = new Label("专业年级:");
        TextField textField2 = new TextField();
        HBox hBox2 = new HBox(5);
        hBox2.setAlignment(Pos.CENTER);
        hBox2.getChildren().addAll(label2, textField2);
        Label label3 = new Label("学      号:");
        TextField textField3 = new TextField();
        Label label4 = new Label("相   似  度:");
        TextField textField4 = new TextField();
        HBox hBox3 = new HBox(5);
        hBox3.setAlignment(Pos.CENTER);
        hBox3.getChildren().addAll(label3, textField3);
        HBox hBox4 = new HBox(5);
        hBox4.setAlignment(Pos.CENTER);
        hBox4.getChildren().addAll(label4, textField4);
        Stage stage = new Stage();
        stage.setOnHiding(event -> {
           Timer timer = new Timer();
           timer.schedule(new TimerTask() {
               @Override
               public void run() {
                   System.out.println("hello");
                   Platform.runLater(()->{
                       getImagine();
                       timer.cancel();
                   });
               }
           }, 2000);
        });
        Alert alert = new Alert(Alert.AlertType.WARNING);
        VBox vBox = new VBox(10);
        try {
            File file = new File(filePath + "temp" + ".png");
            ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", file);
            FaceUtils faceUtils = new FaceUtils();
            faceUtils.setImageInfo(filePath + "temp"+ ".png");
            byte[] faceFeature = faceUtils.getFaceFeature();
            if (faceFeature == null) {
                Timer timer = new Timer();
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        System.out.println("hello");
                        Platform.runLater(()->{
                            getImagine();
                            timer.cancel();
                        });
                    }
                }, 2000);
            } else {
                Student studentInfo = new Student();
                studentInfo.setFeature(faceFeature);
                InfoMapper infoMapper = new InfoMapper();
                List<Student> allInfo = infoMapper.findAllInfo();
                Map<Float,Student> map = new TreeMap<>((o1, o2) -> (int)(o2-o1));
                for (Student student1 : allInfo) {
                    byte[] feature = student1.getFeature();
                    float compare = faceUtils.compareTo(faceFeature, feature);
                    map.put(compare, student1);
                }
                Set<Float> keySet = map.keySet();
                for (Float aFloat : keySet) {
                    Student student = map.get(aFloat);
                    textField.setText(student.getName());
                    textField2.setText(student.getGrade());
                    textField3.setText(student.getStudent());
                    textField4.setText(aFloat.toString());
                    InputStream inputStream = new FileInputStream(student.getImage());
                    imageView.setImage(new Image(inputStream));
                    inputStream.close();
                    break;
                }
                vBox.setAlignment(Pos.CENTER);
                vBox.setPadding(new Insets(10, 10, 10, 10));
                vBox.getChildren().addAll(imageView, hBox, hBox2, hBox3,hBox4);
                stage.setScene(new Scene(vBox));
                stage.show();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        launch(args);
    }
}
————————————————
版权声明:本文为CSDN博主「哆啦是只小猫咪」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43437555/article/details/118657775

人脸信息识别:

package zzuli.zw.camera;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamEvent;
import com.github.sarxos.webcam.WebcamListener;
import com.github.sarxos.webcam.WebcamResolution;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class MyCameraConfig extends Application {
    /**
     * 拍照存储的文件路径
     */
    String filePath = "C:/image/";

    private static class WebCamInfo {
        private String webCamName;
        private int webCamIndex;

        public String getWebCamName() {
            return webCamName;
        }

        public void setWebCamName(String webCamName) {
            this.webCamName = webCamName;
        }

        public int getWebCamIndex() {
            return webCamIndex;
        }

        public void setWebCamIndex(int webCamIndex) {
            this.webCamIndex = webCamIndex;
        }
    }

    private FlowPane bottomCameraControlPane;
    private FlowPane topPane;
    private ImageView imgWebCamCapturedImage;
    private Webcam webCam = null;
    private boolean stopCamera = false;
    private BufferedImage grabbedImage;
    private ObjectProperty<Image> imageProperty = new SimpleObjectProperty<>();
    private BorderPane webCamPane;

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("摄像");
        BorderPane root = new BorderPane();
        topPane = new FlowPane();
        topPane.setAlignment(Pos.CENTER);
        topPane.setHgap(20);
        topPane.setOrientation(Orientation.HORIZONTAL);
        topPane.setPrefHeight(40);
        root.setTop(topPane);
        webCamPane = new BorderPane();
        webCamPane.setStyle("-fx-background-color: #ccc;");
        imgWebCamCapturedImage = new ImageView();
        webCamPane.setCenter(imgWebCamCapturedImage);
        root.setCenter(webCamPane);
        createTopPanel();
        bottomCameraControlPane = new FlowPane();
        bottomCameraControlPane.setOrientation(Orientation.HORIZONTAL);
        bottomCameraControlPane.setAlignment(Pos.CENTER);
        bottomCameraControlPane.setHgap(20);
        bottomCameraControlPane.setVgap(10);
        bottomCameraControlPane.setPrefHeight(40);
        bottomCameraControlPane.setDisable(true);
        createCameraControls();
        root.setBottom(bottomCameraControlPane);
        primaryStage.setScene(new Scene(root));
        primaryStage.setHeight(700);
        primaryStage.setWidth(600);
        primaryStage.centerOnScreen();
        primaryStage.show();
        Platform.runLater(this::setImageViewSize);
    }

    protected void setImageViewSize() {
        double height = webCamPane.getHeight();
        double width = webCamPane.getWidth();
        imgWebCamCapturedImage.setFitHeight(height);
        imgWebCamCapturedImage.setFitWidth(width);
        imgWebCamCapturedImage.prefHeight(height);
        imgWebCamCapturedImage.prefWidth(width);
        imgWebCamCapturedImage.setPreserveRatio(true);
    }

    private void createTopPanel() {
        int webCamCounter = 0;
        Label lbInfoLabel = new Label("选择摄像头:");
        ObservableList<WebCamInfo> options = FXCollections.observableArrayList();
        topPane.getChildren().add(lbInfoLabel);
        for (Webcam webcam : Webcam.getWebcams()) {
            WebCamInfo webCamInfo = new WebCamInfo();
            webCamInfo.setWebCamIndex(webCamCounter);
            webCamInfo.setWebCamName(webcam.getName());
            options.add(webCamInfo);
            webCamCounter++;
        }

        ComboBox<WebCamInfo> cameraOptions = new ComboBox<>();
        cameraOptions.setItems(options);
        String cameraListPromptText = "选择摄像头:";
        cameraOptions.setPromptText(cameraListPromptText);
        cameraOptions.getSelectionModel().selectedItemProperty().addListener((ObservableValue<? extends WebCamInfo> arg0, WebCamInfo arg1, WebCamInfo arg2) -> {
            if (arg2 != null) {
                initializeWebCam(arg2.getWebCamIndex());
            }
        });
        topPane.getChildren().add(cameraOptions);
    }

    protected void initializeWebCam(final int webCamIndex) {
        Task<Void> webCamTask = new Task<Void>() {
            @Override
            protected Void call() {
                webCam = Webcam.getWebcams().get(webCamIndex);
                webCam.setViewSize(WebcamResolution.VGA.getSize());
                webCam.open();
                startWebCamStream();
                return null;
            }
        };
        Thread webCamThread = new Thread(webCamTask);
        webCamThread.setDaemon(true);
        webCamThread.start();
        bottomCameraControlPane.setDisable(false);
    }

    protected void startWebCamStream() {
        stopCamera = false;
        Task<Void> task = new Task<Void>() {
            @Override
            protected Void call() {
                while (!stopCamera) {
                    try {
                        if ((grabbedImage = webCam.getImage()) != null) {
                            Platform.runLater(() -> {
                                Image mainImage = SwingFXUtils.toFXImage(grabbedImage, null);

                                imageProperty.set(mainImage);
                            });
                            grabbedImage.flush();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                return null;
            }
        };
        Thread th = new Thread(task);
        th.setDaemon(true);
        th.start();
        imgWebCamCapturedImage.imageProperty().bind(imageProperty);
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello");
                Platform.runLater(()->{
                    getImagine();
                    timer.cancel();
                });
            }
        }, 2000);

    }

    private void createCameraControls() {
    }

    protected void getImagine() {
        Image image = imgWebCamCapturedImage.getImage();
        ImageView imageView = new ImageView();
        Label label = new Label("姓      名:");
        TextField textField = new TextField();
        HBox hBox = new HBox(5);
        hBox.setAlignment(Pos.CENTER);
        hBox.getChildren().addAll(label, textField);
        Label label2 = new Label("专业年级:");
        TextField textField2 = new TextField();
        HBox hBox2 = new HBox(5);
        hBox2.setAlignment(Pos.CENTER);
        hBox2.getChildren().addAll(label2, textField2);
        Label label3 = new Label("学      号:");
        TextField textField3 = new TextField();
        Label label4 = new Label("相   似  度:");
        TextField textField4 = new TextField();
        HBox hBox3 = new HBox(5);
        hBox3.setAlignment(Pos.CENTER);
        hBox3.getChildren().addAll(label3, textField3);
        HBox hBox4 = new HBox(5);
        hBox4.setAlignment(Pos.CENTER);
        hBox4.getChildren().addAll(label4, textField4);
        Stage stage = new Stage();
        stage.setOnHiding(event -> {
           Timer timer = new Timer();
           timer.schedule(new TimerTask() {
               @Override
               public void run() {
                   System.out.println("hello");
                   Platform.runLater(()->{
                       getImagine();
                       timer.cancel();
                   });
               }
           }, 2000);
        });
        Alert alert = new Alert(Alert.AlertType.WARNING);
        VBox vBox = new VBox(10);
        try {
            File file = new File(filePath + "temp" + ".png");
            ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", file);
            FaceUtils faceUtils = new FaceUtils();
            faceUtils.setImageInfo(filePath + "temp"+ ".png");
            byte[] faceFeature = faceUtils.getFaceFeature();
            if (faceFeature == null) {
                Timer timer = new Timer();
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        System.out.println("hello");
                        Platform.runLater(()->{
                            getImagine();
                            timer.cancel();
                        });
                    }
                }, 2000);
            } else {
                Student studentInfo = new Student();
                studentInfo.setFeature(faceFeature);
                InfoMapper infoMapper = new InfoMapper();
                List<Student> allInfo = infoMapper.findAllInfo();
                Map<Float,Student> map = new TreeMap<>((o1, o2) -> (int)(o2-o1));
                for (Student student1 : allInfo) {
                    byte[] feature = student1.getFeature();
                    float compare = faceUtils.compareTo(faceFeature, feature);
                    map.put(compare, student1);
                }
                Set<Float> keySet = map.keySet();
                for (Float aFloat : keySet) {
                    Student student = map.get(aFloat);
                    textField.setText(student.getName());
                    textField2.setText(student.getGrade());
                    textField3.setText(student.getStudent());
                    textField4.setText(aFloat.toString());
                    InputStream inputStream = new FileInputStream(student.getImage());
                    imageView.setImage(new Image(inputStream));
                    inputStream.close();
                    break;
                }
                vBox.setAlignment(Pos.CENTER);
                vBox.setPadding(new Insets(10, 10, 10, 10));
                vBox.getChildren().addAll(imageView, hBox, hBox2, hBox3,hBox4);
                stage.setScene(new Scene(vBox));
                stage.show();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        launch(args);
    }
}

六、完整代码

https://github.com/suobanjin/javacv

七、设计难点

人脸信息自动识别

在第一版设计的时候我采用的是用户被动识别的方式,当用户点击按钮时对当前界面抓拍并进行信息识别。但是考虑到实际的应用场景,我认为不太方便,于是使用定时任务,定时抓取图片进行人脸识别比对。

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        System.out.println("hello");
        Platform.runLater(()->{
            getImagine();
            timer.cancel();
        });
    }
}, 2000);

在摄像头初始化时设置任务,延迟2s后执行。当用户识别成功后会跳转到用户信息界面,这时我们设置窗口关闭事件:

stage.setOnHiding(event -> {
   Timer timer = new Timer();
   timer.schedule(new TimerTask() {
       @Override
       public void run() {
           System.out.println("hello");
           Platform.runLater(()->{
               getImagine();
               timer.cancel();
           });
       }
   }, 2000);
});

同时,当用户识别不成功时:

if (faceFeature == null) {
    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            System.out.println("hello");
            Platform.runLater(()->{
                getImagine();
                timer.cancel();
            });
        }
    }, 2000);
}

八、项目总结

总体而言,本项目较为简单。有许多需要改进的地方:

webcam使用不熟悉,没有过多查看文档,目前在查看文档以便可以实现人脸标记以及避免人脸重复检测
数据存储有何更高效也是需要考虑的问题,可以看到人脸特征值大概在1kb左右,如果人脸信息库信息较多,那么我们如果将数据库中信息全部查出并比对会浪费很多时间,效率较低。目前考虑是否可以存入文件中进行操作,当然这个还需要作比对,看哪个效率更高一点。

了解更多人脸识别产品相关内容请到虹软视觉开放平台