zoukankan      html  css  js  c++  java
  • java 调用本机摄像头获取人脸图片的实现

    话不多说,直接提供两种获取摄像头人脸图片的方式

    1. 使用 tracking.js 前端获取 --  实际web项目中最常用的

          tracking.js 文档地址: https://trackingjs.com/

          获取步骤:

                A:  引入 tracking.js 和  face.js

                B: 调用 tracking 获取摄像头视频,放到 <video> 中,设置人脸监测

                C: 调用人脸检测方法,针对视频每一帧图片进行监测,当监测到人脸区域时,使用 canvas 绘制人脸区域

                D: 然后针对存在人脸的图片进行截图,截图区域为监测到的人脸区域,可设置参数调整截图范围,这样就当前图片(该图片为视频中的某一帧存在人脸的图片)中截取到了人脸

          代码如下:

             html 代码   

    <!DOCTYPE html>
    <html  lang="zh" xmlns:th="http://www.thymeleaf.org">
    <head>
      <meta charset="utf-8">
      <title>人脸识别</title>
      <link rel="stylesheet" th:href="@{/css/layer.css}">
      <link rel="stylesheet" th:href="@{/css/demo.css}">
      <script type="text/javascript" th:src="@{/js/jquery-1.9.1.js}"></script>
      <script type="text/javascript" th:src="@{/js/layer.js}"></script>
      <script th:src="@{/js/tracking-min.js}"></script>
      <script th:src="@{/js/face-min.js}"></script>
    </head>
    <body>
        <div>
            <p align="center">人脸图片检测</p>
        </div>
      <div class="demo-frame">
        <div class="demo-container">
            <div id="face1">
                 <video id="video" width="640" height="480"></video>
                 <canvas id="canvas" width="640" height="480"></canvas>
            </div>
          </div>
      </div>
      <script  type="text/javascript" th:inline="javascript">
        window.onload = function() {
          var video = document.getElementById('video');
          var canvas = document.getElementById('canvas');
          var context = canvas.getContext('2d');
          // 创建人脸追踪对象 ,并初始化
          var tracker = new tracking.ObjectTracker('face');
          tracker.setInitialScale(4);
          tracker.setStepSize(2);
          tracker.setEdgesDensity(0.1);
          // 从摄像头获取视频,放到 video 中,同时开启人脸监测
          tracking.track('#video', tracker, { camera: true });
          // 监听视频中的每一帧,判断是否存在人脸
          tracker.on('track', function(event) {
            if(event.data.length===0){
                console.info('无人脸');
                context.clearRect(0, 0, canvas.width, canvas.height);
            }else{
                //存在人脸
              event.data.forEach(function(rect) {
                  // 一张图片可能存在多个人脸,遍历人脸信息
                  // canvas 画图,设置颜色
                  context.strokeStyle = '#FF0000';
                  // 画一个 矩形框,定义位置为人脸区域做坐标
                  context.strokeRect(rect.x, rect.y, rect.width, rect.height);
                  // 显示坐标值
                  context.font = '11px Helvetica';
                  context.fillStyle = "#fff";
                  context.fillText('x: ' + rect.x + 'px', rect.x + rect.width + 5, rect.y + 11);
                  context.fillText('y: ' + rect.y + 'px', rect.x + rect.width + 5, rect.y + 22);
                  // 针对监测到人脸进行处理
                  Shoot(rect.x, rect.y, rect.width, rect.height);
                  // 此处休眠1分中 -- 避免频繁获取,方便调试,实际开发不需要
                  sleep(1000*60*1);
              });
            }
          });
    
          function Shoot(x,y,width,height) {
              var trackerTask = tracking.track(video, tracker);
            //先清除掉 canvas 画的框,避免截图获取到这个框 -- 理论上从视频获取不会截取到,但调试时实际有截取,所以做下清除
            context.clearRect(0, 0, canvas.width, canvas.height);
            //从视频的这个区域画图,捕获人脸
            context.drawImage(video,x-50,y-50,width+50,height+100,0,0,width+50,height+100);
            //将图片写到元素
             var img = document.createElement("img");
             img.src = this.canvas.toDataURL("image/png");
             //打印下截取到图片的 base64 编码
             console.log(img.src);
            //删除字符串前的提示信息 "data:image/png;base64,"
             var b64 = img.src.substring(22);
             //以下为调用后端接口
             var path = "/faceLogin";
            $.ajax({
                type : 'post',
                dataType : 'json',
                url : path,
                data : {
                    imgdata:b64,
                    identityImgBase64:"身份证图片base64编码",
                    name:"姓名"
                },
                success : function(result){
                    if(result.code=='0'){
                        //停止人脸监听
                        trackerTask.stop();
                        //其他代码....
                    }else{
                        // 此处根据业务需要,决定是否停止监听
                        trackerTask.stop();
                        //其他代码....
                     }
                }
            })
          }
    
             //休眠方法--测试
            function sleep(numberMillis) {
                var now = new Date();
                var exitTime = now.getTime() + numberMillis;
                while (true) {
                    now = new Date();
                    if (now.getTime() > exitTime)
                        return;
                }
            }
        };
    </script>
    </body>
    </html>

         相关 css

              demo.css

    * {
      margin: 0;
      padding: 0;
      font-family: Helvetica, Arial, sans-serif;
    }
    
    .demo-title {
      position: absolute;
      width: 100%;
      background: #2e2f33;
      z-index: 2;
      padding: .7em 0;
    }
    
    .demo-title a {
      color: #fff;
      border-bottom: 1px dotted #a64ceb;
      text-decoration: none;
    }
    
    .demo-title p {
      color: #fff;
      text-align: center;
      text-transform: lowercase;
      font-size: 15px;
    }
    
    .demo-frame {
      width: 854px;
      height: 658px;
      position: fixed;
      top: 50%;
      left: 50%;
      margin: -329px 0 0 -429px;
      padding: 95px 20px 45px 34px;
      overflow: hidden;
      -webkit-box-sizing: border-box;
      -moz-box-sizing: border-box;
      -ms-box-sizing: border-box;
      box-sizing: border-box;
    }
    
    .demo-container {
      width: 100%;
      height: 530px;
      position: relative;
      background: #eee;
      overflow: hidden;
      border-bottom-right-radius: 10px;
      border-bottom-left-radius: 10px;
    }
    
    .dg.ac {
      z-index: 100 !important;
      top: 50px !important;
    }
    
    #face1{
        width: 1200px;
        height: 900px;
    }
    
    /*#face2{
        margin-left: 65%;
         550px;
        height: 300px;
        background-color: black;
    }*/
    #video{
      margin-left: 80px;
      margin-top: 25px;
      position: absolute; 
    }
    #canvas {
      margin-left: 80px;
      margin-top: 25px;
      position: absolute;
     }
    #canvas1 {
        margin-left: 72%;
        margin-top: 200px;
        width:480px; 
        height:360px; 
     /* background-color:#A64CEB;*/
    }
    p{
        font-size: 50px;
        font-family: "仿宋";
        margin-top: 50px;
        }

    2. java 后端获取: 使用 openimaj 从摄像头视频中获取队员人脸  --- 此方式好像没啥用,自己写着玩的

         代码如下:

             A: 引入maven依赖 

            <!-- openimaj 用于从摄像头获取人脸拍照 文档地址 : http://openimaj.org -->
            <dependency>
                <groupId>com.github.sarxos</groupId>
                <artifactId>webcam-capture</artifactId>
                <version>0.3.12</version>
            </dependency>
            <dependency>
                <artifactId>faces</artifactId>
                <groupId>org.openimaj</groupId>
                <version>1.3.10</version>
                <scope>compile</scope>
            </dependency>

         B: demo代码如下,运行main即可

            

    import cn.hutool.core.collection.CollectionUtil;
    import lombok.Data;
    import lombok.extern.slf4j.Slf4j;
    import org.openimaj.image.*;
    import org.openimaj.image.colour.RGBColour;
    import org.openimaj.image.colour.Transforms;
    import org.openimaj.image.processing.face.detection.DetectedFace;
    import org.openimaj.image.processing.face.detection.FaceDetector;
    import org.openimaj.image.processing.face.detection.HaarCascadeDetector;
    import org.openimaj.video.VideoDisplay;
    import org.openimaj.video.VideoDisplayListener;
    import org.openimaj.video.capture.VideoCapture;
    import org.openimaj.video.capture.VideoCaptureException;
    
    import javax.imageio.ImageIO;
    import javax.swing.*;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.LinkedList;
    import java.util.List;
    
    /**
     * 摄像头拍照工具类 : 调用本机摄像头抓取人脸拍照
     * @author qxl
     * @date 2020/10/12
     */
    @Slf4j
    @Data
    public class WebcamCaptureUtil {
    
        // 视频捕获对象
        private VideoCapture vc;
        // 视频显示 JFrame 窗口对象
        private JFrame windows;
        // 视频显示对象
        private VideoDisplay<MBFImage> vd;
        //捕获人脸图片存放集合
        private LinkedList<BufferedImage> faceImages = new LinkedList<>();
    
        /**
         * 打开摄像头捕获人脸,数据存入 faceImages
         */
        public void faceCapture() throws VideoCaptureException{
            // 创建视频捕获对象
            vc = new VideoCapture(320,240);
            //创建 JFrame 窗口,用于显示视频
            windows = DisplayUtilities.makeFrame("摄像头人脸检测中...");
            windows.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            windows.setVisible(true);
            //创建视频显示对象
            vd = VideoDisplay.createVideoDisplay(vc,windows);
            // 监听视频
            vd.addVideoListener(
                 //视频显示的监听--针对每一帧的图片
                new VideoDisplayListener<MBFImage>(){
                    public void beforeUpdate(MBFImage frame){
                        FaceDetector<DetectedFace,FImage> fd = new HaarCascadeDetector(40);
                        List<DetectedFace> faces = fd.detectFaces(Transforms.calculateIntensity(frame));
                        for(DetectedFace face : faces ) {
                            frame.drawShape(face.getBounds(), RGBColour.RED);
                            BufferedImage image = ImageUtilities.createBufferedImageForDisplay(face.getFacePatch());
                            faceImages.addLast(image);
                        }
                    }
    
                    public void afterUpdate(VideoDisplay<MBFImage> display){
                    }
            });
        }
    
        /**
         * 保存人脸图片
         * @param image  要保存的image
         * @param savePath  保存的路径
         * @param imageName  图片名称
         */
        public void saveImage(BufferedImage image,String savePath,String imageName) throws IOException {
            File path = new File(savePath);
            if (!path.exists()) {//如果文件不存在,则创建该目录
                path.mkdirs();
            }
            File file = new File(savePath + "/" + imageName + ".png");
            ImageIO.write(image,"png",file);
        }
    
    
        /**
         * 关闭摄像头及人脸捕获
         */
        public void closeWebcam(){
            if(vc != null){
                vc.stopCapture();
                vc.close();
            }
            if(vd != null){
                vd.close();
            }
            if(windows != null){
                // 关闭 jFrame 窗口
                windows.removeNotify();
            }
        }
    
        /**
         * 清理缓存图片
         */
        public void clearFaceImages(){
            faceImages.clear();
        }
    
    
        public static void main(String[] args) {
            WebcamCaptureUtil webcamCaptureUtil = new WebcamCaptureUtil();
            try {
                //开始人脸捕获
                webcamCaptureUtil.faceCapture();
                //等待捕获人脸
                LinkedList<BufferedImage> faceImages = webcamCaptureUtil.getFaceImages();
                String filePath = "D:\" + "/picture/" + new SimpleDateFormat("yyyy-MM-dd").format(new Date());
                //假设获取10张图片之后,人脸比对成功
                int count = 0;
                while (count<10){
                   if (CollectionUtil.isNotEmpty(faceImages)){
                       String time = new SimpleDateFormat("yyyMMdd_HHmmss").format(new Date());
                       BufferedImage image = faceImages.pollFirst();
                       if (image != null){
                           webcamCaptureUtil.saveImage(image,filePath,time);
                       }
                       Thread.sleep(1000L);
                       count++;
                   }
                }
                //关闭摄像头
                webcamCaptureUtil.closeWebcam();
                //打印集合元素个数
                System.out.println("未清空前"+faceImages.size());
                webcamCaptureUtil.clearFaceImages();
                System.out.println("清空后"+ faceImages.size());
            } catch (VideoCaptureException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    }

    以上就是前后端从摄像头获取人脸的两种方式,如果想要实现人脸对比,可参考我的另一篇博客: 虹软SDK离线人脸比对

     原创作品,转载注明出处: https://www.cnblogs.com/huaixiaonian/p/13822115.html ,谢谢!

  • 相关阅读:
    Mysql数据库的一些操作
    【狂神说Java】JavaWeb入门到实战1---笔记
    图神经网络学习
    HWSX网址
    python如何判断两个数组完全相等?
    SQL-3-菜鸟教程
    SQL-2
    时间序列相似度分析算法
    pip install 安装不了怎么办?
    leetcode 3 无重复字符的最长子串
  • 原文地址:https://www.cnblogs.com/huaixiaonian/p/13822115.html
Copyright © 2011-2022 走看看