java opencv调用摄像头识别人脸并截图

package com.gapf.supervise.web.controller.v1;/**
 * Description: TODO
 * @author OWolfe
 * @date 2020/8/31 13:45
 */

import com.alibaba.fastjson.JSON;
import com.gapf.common.config.GapfConfig;
import com.gapf.management.utils.FaceUtils;
import com.gapf.management.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.opencv.core.Point;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author Crazy.X
 */
@Slf4j
@RestController
@RequestMapping("/{version}")
public class FaceController extends JPanel{
    private static final long serialVersionUID = 1L;
    //每一帧视频的BufferedImage对象
    private static BufferedImage mImg;
    //图片名字格式
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyymmddHHmmss");
    //图片保存地址
    public static final String FACE_PATH = "/face/";
    //图片格式
    private static String format = "jpg";
    //人脸识别器位置
//    private static String altPath = "haarcascade_frontalface_alt.xml";

    static {
        //在调用之前,一定要加上这句话,目的是加载OpenCV API相关的DLL支持,没有它是不会正确运行的
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    /**
     * 将Mat对象转换为BufferedImage
     * @param mat
     * @return
     */
    private static BufferedImage mat2BI(Mat mat) {
        int dataSize = mat.cols() * mat.rows() * (int) mat.elemSize();
        byte[] data = new byte[dataSize];
        mat.get(0, 0, data);
        int type = mat.channels() == 1 ?
                BufferedImage.TYPE_BYTE_GRAY : BufferedImage.TYPE_3BYTE_BGR;

        if (type == BufferedImage.TYPE_3BYTE_BGR) {
            for (int i = 0; i < dataSize; i += 3) {
                byte blue = data[i + 0];
                data[i + 0] = data[i + 2];
                data[i + 2] = blue;
            }
        }
        BufferedImage image = new BufferedImage(mat.cols(), mat.rows(), type);
        image.getRaster().setDataElements(0, 0, mat.cols(), mat.rows(), data);
        return image;
    }

    /**
     * 将BufferedImage在窗口显示出来
     * @param g
     */
    public void paintComponent(Graphics g) {
        if (mImg != null) {
            g.drawImage(mImg, 0, 0, mImg.getWidth(), mImg.getHeight(), this);
        }
    }


    /**
     * opencv实现人脸识别、画框、转换为BufferedImage对象
     * @param img
     */
    public static String detectFace(Mat img,CascadeClassifier faceDetector) {

        System.out.println("Running DetectFace ... ");

        //转为灰度图,直方图均衡化的前提
        Mat greyScaleImg = new Mat();
        Imgproc.cvtColor(img, greyScaleImg, Imgproc.COLOR_RGB2GRAY,0);

        //缩放图片,可提高检测速率,减少检测时间
        Mat smallImg=img.clone();
        Imgproc.resize(greyScaleImg,smallImg,new Size(img.width()*0.2,img.height()*0.2));

        //直方图均衡化,提高图像质量
        Mat qualityImg = new Mat();
        Imgproc.equalizeHist(smallImg,qualityImg);

        // 在图片中检测人脸
        MatOfRect faceDetections = new MatOfRect();
        faceDetector.detectMultiScale(qualityImg, faceDetections);

        //人脸坐标
        Rect[] rects = faceDetections.toArray();
        //如果检测到人脸
        if (rects != null && rects.length >= 1) {
            String name = sdf.format(new Date());
            //画框
            for (Rect rect : rects) {
//                Imgproc.rectangle(img, new Point(rect.x*10, rect.y*10),
//                        new Point(rect.x*10 + rect.width*10, rect.y*10 + rect.height*10),
//                        new Scalar(0, 255, 245), 2);
                Imgproc.rectangle(img, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
                        new Scalar(0, 0, 255), 2);
//                save(qualityImg, rect, "E:\\dir\\img"+name+".jpg");
            }
            //将这一帧保存起来
            String filePath  = GapfConfig.getUploadPath()+FACE_PATH+ File.separator + name + "." + format;
            File f = new File(filePath);
            BufferedImage bufferedImage = mat2BI(img);
            try {
                ImageIO.write(bufferedImage, format, f);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return filePath;
        } else {
            return null;
        }

        //测试是否正常接收摄像头视频流此方法只需这一步
        //return mat2BI(img);
    }
    /**
     * opencv将人脸进行截图并保存
     * @param img
     */
    private static void save(Mat img, Rect rect, String outFile){
        Mat sub = img.submat(rect);
        Mat mat = new Mat();
        Size size = new Size(300, 300);
        Imgproc.resize(sub, mat, size);
        Imgcodecs.imwrite(outFile, mat);
    }
    /**
     * 识别人脸
     * @param
     */
    @GetMapping("/face/search")
    public void searchFace(String rtsp) {
        VideoCapture capture = new VideoCapture();  //打开摄像头,参数为0:代表本地摄像头
        try {
            //打开rtsp地址,需要把opencv\build\bin下的opencv_ffmpeg320_64.dll,拷贝一份到idea工作空间当前项目下,若是打开本地摄像头直接在上一步填入参数0即可,不需要capture.open(rtsp);这一步
            capture.open(rtsp);
            if (!capture.isOpened()) {
                throw new Exception("camera not found!");
            }

//            JFrame frame = new JFrame("camera");
//            frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            FaceController panel = new FaceController();
//            frame.setContentPane(panel);
//            //设置窗口尺寸
//            /*frame.setSize((int) capture.get(Videoio.CAP_PROP_FRAME_WIDTH) + frame.getInsets().left + frame.getInsets().right,
//                    (int) (capture.get(Videoio.CAP_PROP_FRAME_HEIGHT) + frame.getInsets().top + frame.getInsets().bottom));  全屏*/
//            frame.setSize(1024,768);
//            //打开窗口
//            frame.setVisible(true);
            Mat capImg = new Mat();
//            while (frame.isShowing()) {
            while (capture.isOpened()) {
                //读取一帧视频画面
                capture.read(capImg);

                //从配置文件lbpcascade_frontalface.xml中创建一个人脸识别器,该文件位于opencv安装目录中
                //opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml文件
                String altPath = ResourceUtils.getFile("classpath:static/haarcascade_frontalface_alt.xml").getPath();
                Resource resource = new ClassPathResource(altPath);
                String path= resource.getFile().getPath();
                CascadeClassifier faceDetector = new CascadeClassifier(path);

                //识别人脸,转换为BufferedImage对象
                String imageUrl = detectFace(capImg,faceDetector);
                if(imageUrl!=null){
                    String file = FaceUtils.uploadFile(imageUrl);
                    String mapStr = FaceUtils.searchFace(file);
                    float score = 0f;
                    if(!StringUtil.isBlank(mapStr)){
                        HashMap hashMap = JSON.parseObject(mapStr, HashMap.class);
                        Map<String, Map> bodyMap= (Map<String, Map>) hashMap.get("body");
                        Map<String, Map> dataMap= (Map<String, Map>) hashMap.get("data");
                        List<Map<String, Map>> listMap= (List<Map<String, Map>>) dataMap.get("matchList");
                        List<Map<String, Object>> facelistMap= (List<Map<String, Object>>) listMap.get(0).get("faceItems");
                        Map<String, Object> resultMap= (Map<String, Object>) facelistMap.get(0);
                        score= Float.valueOf(resultMap.get("score").toString());
                        if(score>0.6){
                            System.out.println("-----------------"+resultMap.get("entityId"));
                            break;
                        }
                    }
                }
                //刷新
                panel.repaint();
            }
                capture.release();
            //关闭Frame窗口
//            frame.dispose();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("--done--");
            capture.release();
        }
    }
    @GetMapping("/face/search1")
    public void searchFace1(String rtsp) throws IOException {
        String path = ResourceUtils.getFile("classpath:static/haarcascade_frontalface_alt.xml").getPath();
        System.out.println(path);
    }
    public static void main(String[] args) throws IOException {

    }
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值