JavaCV 学习初步:调用本机摄像头、人脸检测

IDEA 2020
jdk 1.8
opencv 4.5.5

安装 OpenCV 环境

先下载安装 OpenCV:https://opencv.org/releases.html

官网如下,我点击进入 GitHub

我们需要下载对应的版本的 OpenCV,这里最新版的是 4.5.5

一定要注意版本问题,版本不一致可能会出现各种问题,尽量版本保持一致。如果出现 no jniopencv_core in java.library.path 错误,就是版本问题导致的

下载源码,里面的 data 文件夹中有我们需要的人脸分类数据

因为我是 windows10 系统,所以我下载了 opencv-4.5.5-vc14_vc15.exe 进行安装

然后点击进行安装

创建项目进行测试

我们创建一个 springboot 项目,创建之后将下面 pom 依赖复制粘贴进去

<dependencies>
        <!--SpringBoot Web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


        <!--JavaCV-->
        <!--注意下面的版本号,和下载的 opencv 版本要尽量接近,可避免很多错误-->
        <!-- 都是从 https://mvnrepository.com/ 搜索到的最新版本 2022/4/7 -->

        <!-- javacv+javacpp核心库-->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.5.7</version>
        </dependency>

        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv-platform</artifactId>
            <version>1.5.7</version>
        </dependency>

        <!-- ffmpeg最小依赖包,必须包含上面的javacv+javacpp核心库 -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>ffmpeg</artifactId>
            <version>5.0-1.5.7</version>
        </dependency>

        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>ffmpeg-platform</artifactId>
            <version>5.0-1.5.7</version>
        </dependency>

        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>opencv-platform</artifactId>
            <version>4.5.5-1.5.7</version>
        </dependency>

    </dependencies>

然后在 application.properties 文件中设置一下端口,防止默认端口被占用

server.port=8889

这个时候我们需要将源码中 data\haarcascades_cuda 目录下的 haarcascade_frontalface_alt.xml 文件复制粘贴项目中的 resources 目录下,这个文件是用于人脸特征分辨的数据文件

创建一个 Controller

OpencvController

package com.example.opencvtest02.controller;

import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;

import static org.bytedeco.opencv.global.opencv_imgproc.*;

import javax.swing.*;


/**
 * @author z
 * @link https://blog.csdn.net/eguid_1/article/details/107420243
 */
@Controller
public class OpencvController {

    // 在这里进行测试
    public static void main(String[] args) throws Exception {

        // 这个 xml 文件路径一定要正确,否则会报如下行的错误,如果报错,请输出查看 xml 路径是否正确
        // error: (-215:Assertion failed) !empty() in function ‘cv::CascadeClassifier::detectMultiScale‘
        // @link: https://blog.csdn.net/qq_43061705/article/details/97142914

        // 这里路径代码做了修改,下面下载的项目是旧版绝对路径代码
        String url = new URL(Thread.currentThread().getContextClassLoader().getResource("") + "haarcascade_frontalface_alt.xml").getPath();
        String xmlPath = new File(url).toString();
        faceDetection(xmlPath, 960, 540);

    }

    /**
     * 人脸检测-eguid
     *
     * @param cascadeClassifierXml 基于Haar特征的cascade正面人脸分类器
     * @param width                图像宽度
     * @param height               图像高度
     */
    @PostMapping("/face")
    public static void faceDetection(String cascadeClassifierXml, Integer width, Integer height) throws Exception, InterruptedException {
        // 开启摄像头,获取图像(得到的图像为frame类型,需要转换为mat类型进行检测和识别)
        OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
        if (width != null && width > 1 && height != null && height > 1) {
            grabber.setImageWidth(width);
            grabber.setImageHeight(height);
        }
        grabber.start();

        if (width == null || height == null) {
            height = grabber.getImageHeight();
            width = grabber.getImageWidth();
        }

        // 新建一个预览窗口
        CanvasFrame canvas = new CanvasFrame("人脸检测");
        canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        canvas.setVisible(true);
        canvas.setFocusable(true);
        canvas.setSize(width, height);

        //窗口置顶
        if (canvas.isAlwaysOnTopSupported()) {
            canvas.setAlwaysOnTop(true);
        }
        Frame frame = null;

        // 读取opencv人脸检测器
        CascadeClassifier cascade = new CascadeClassifier(cascadeClassifierXml);

        while (canvas.isVisible() && (frame = grabber.grab()) != null) {
            // 从frame中直接获取Mat
            Mat img = (Mat) frame.opaque;
            //存放灰度图
            Mat grayImg = new Mat();
            //摄像头色彩模式设置成ImageMode.Gray下不需要再做灰度
            // 摄像头获取的是彩色图像,所以先灰度化下
            cvtColor(img, grayImg, COLOR_BGRA2GRAY);
            //如果要获取摄像头灰度图,可以直接对FrameGrabber进行设置grabber.setImageMode(ImageMode.GRAY);,grabber.grab()获取的都是灰度图

            // 均衡化直方图
            equalizeHist(grayImg, grayImg);

            // 检测到的人脸
            RectVector faces = new RectVector();
            cascade.detectMultiScale(grayImg, faces);

            // 遍历人脸
            for (int i = 0; i < faces.size(); i++) {
                Rect faceI = faces.get(i);
                //绘制人脸矩形区域,scalar色彩顺序:BGR(蓝绿红)
                rectangle(img, faceI, new Scalar(0, 255, 0, 1));

                int posX = Math.max(faceI.tl().x() - 10, 0);
                int posY = Math.max(faceI.tl().y() - 10, 0);
                // 在人脸矩形上方绘制提示文字
                putText(img, "people face", new Point(posX, posY), FONT_HERSHEY_COMPLEX, 1.0, new Scalar(0, 0, 255, 2.0));
            }

            // 获取摄像头图像并放到窗口上显示,frame是一帧视频图像
            canvas.showImage(frame);
            // 40毫秒刷新一次图像
            Thread.sleep(40);
        }
        cascade.close();
        canvas.dispose();
        // 停止抓取
        grabber.close();
    }

}

点击执行 OpencvController 下的 main 方法执行,可以看到会弹出一个 960×540 大小的窗口,且会实时更新人脸检测信息


测试项目下载:OpenCVTest02.zip


参考文章

建议学习

可以浏览学习

发表评论