springboot集成opencv实现人脸识别功能的详细步骤

网友投稿 1202 2023-01-11

springboot集成opencv实现人脸识别功能的详细步骤

springboot集成opencv实现人脸识别功能的详细步骤

前言

项目中检测人脸图片是否合法的功能,之前用的是百度的人脸识别接口,由于成本高昂不得不寻求替代方案。

什么是opencv?

OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在linux、Windows、android和Mac OS操作系统上。轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了python、java、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法

项目集成步骤

由于项目是放在Linux系统中跑的,开发环境是Windows10,所以项目中涉及到opencv的要分两套。

准备工作

Windows安装opencv

opencv官网-安装包https://opencv.org/releases/

我这里选择的是4.1.1版本

分别-了Windows版本和源码

Windows环境下集成

安装opencv,没什么说的,指定一个路径安装即可,注意安装路径不能是中文。

项目中集成的三个关键点。

引入jar依赖

读取OpenCV自带的人脸识别特征XML文件

配置opencv的库文件地址

关键点1:引入jar包

jar包位置在安装路径下的java文件夹中

两种方式引入

方式一:idea添加jar

或者直接在Libraries中添加二者皆可。

方式二:将jar上传至私服,在maven中引入

我这里是将jar上传至私服,然后引用的。

注意Windows版的jar和Linux中的jar不一样,二者要区分开来

通过Maven配置在不同环境下加载不同的jar

dev

com.***.cloud.resource

opencv-window

411

true

test

com.***.cloud.resource

opencv-linux

411

关键点2:配置人脸识别特征XML文件的地址

在bootstrap.yml添加如下参数

# 函数库地址 在 vm optionis中 配置

# windows地址: -Djava.library.path=D:\software\opencv\build\java\x64

# linux地址: -Djava.library.path=/usr/local/opencv-4.1.1/build/lib/

opencv:

lib:

linuxxmlpath: /usr/local/share/opencv4/haarcascades/haarcascade_frontalface_alt.xml

windowxmlpath: D:\software\opencv\sources\data\haarcascades\haarcascade_frontalface_alt.xml

测试的方法中就直接写死了

/**

* 初始化人脸探测器

*/

static CascadeClassifier faceDetector;

static {

String systemProperties = String.valueOf(System.getProperties());

log.info(systemProperties);

System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

faceDetector = new CascadeClassifier("D:\\software\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");

}

注意路径!!

关键点3:配置opencv的库文件地址

-Djava.library.path=D:\software\opencv\build\java\x64

这里其实指向的就是 该目录下的 opencv_java411.dll 文件

(linux的配置见下文)

代码

测试方法

package com.example.opencvdemo.test;

import lombok.extern.slf4j.Slf4j;

import org.opencv.core.*;

import org.opencv.highgui.HighGui;

import org.opencv.imgcodecs.Imgcodecs;

import org.opencv.imgproc.Imgproc;

import org.opencv.objdetect.CascadeClassifier;

/**

* @author aaron

* @since 2021-06-07

*/

@Slf4j

public class FaceVideo {

/**

* 初始化人脸探测器

*/

static CascadeClassifier faceDetector;

static {

String systemProperties = String.valueOf(System.getProperties());

log.info(systemProperties);

System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

faceDetector = new CascadeClassifier("D:\\software\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");

}

public static void main(String[] args){

// 3- 本地图片人脸识别,识别成功并保存人脸图片到本地

String imgPath = "C:\\Users\\Administrator\\Pictures\\wang.jpg";

face(imgPath);

}

/**

* OpenCV-4.1.1 图片人脸识别

*

* @return: void

* @date: 2019年5月7日12:16:55

*/

public static void face(String imgPath) {

/**

* 读取本地

*/

Mat image = Imgcodecs.imread(imgPath);

if (image.empty()) {

System.out.println("image 内容不存在!");

return;

}

// 3 特征匹配

MatOfRect face = new MatOfRect();

faceDetector.detectMultiScale(image, face);

// 4 匹配 Rect 矩阵 数组

Rect[] rects = face.toArray();

System.out.println("匹配到 " + rects.length + " 个人脸");

// 5 为每张识别到的人脸画一个圈

int i = 1;

for (Rect rect : face.toArray()) {

Imgproc.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),

new Scalar(0, 255, 0), 3);

imageCut(imgPath, "D:\\pictures\\" + i + ".jpg", rect.x, rect.y, rect.width, rect.height);// 进行图片裁剪

i++;

}

// 6 展示图片

HighGui.imshow("人脸识别", image);

HighGui.waitKey(0);

}

/**

* 裁剪人脸

*

* @param imagePath

* @param outFile

* @param posX

* @param posY

* @param width

* @param height

*/

public static void imageCut(String imagePath, String outFile, int posX, int posY, int width, int height) {

// 原始图像

Mat image = Imgcodecs.imread(imagePath);

// 截取的区域:参数,坐标X,坐标Y,截图宽度,截图长度

Rect rect = new Rect(posX, posY, width, height);

// 两句效果一样

Mat sub = image.submat(rect); // Mat sub = new Mat(image,rect);

Mat mat = new Mat();

Size size = new Size(width, height);

Imgproc.resize(sub, mat, size);// 将人脸进行截图并保存

Imgcodecs.imwrite(outFile, mat);

System.out.println(String.format("图片裁切成功,裁切后图片文件为: %s", outFile));

}

}

注意!Mat image = Imgcodecs.imread(imgPath);

imgPath中不能带有中文! opencv安装路径中如果有中文的话就会报错。

集成到Springboot

package com.example.opencvdemo.util;

import com.example.opencvdemo.exception.PublicException;

import com.example.opencvdemo.result.ErrorCode;

import com.google.common.primitives.Bytes;

import lombok.extern.slf4j.Slf4j;

import org.opencv.core.*;

import org.opencv.imgcodecs.Imgcodecs;

import org.opencv.objdetect.CascadeClassifier;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.boot.CommandLineRunner;

import org.springframework.stereotype.Component;

import java.io.*;

import java-.URL;

import java-.URLConnection;

import java.util.ArrayList;

import java.util.List;

/**

* @author aaron

* @since 2021-06-07

*/

@Component

@Slf4j

public class OpenCvUtils implements CommandLineRunner {

@Value("${opencv.lib.linuxxmlpath}")

private String linuxXmlPath;

@Value("${opencv.lib.windowxmlpath}")

private String windowXmlPath;

/**

* 人脸探测器对象

*/

static CascadeClassifier faceDetector;

/**

* 判断是否是Windows系统

*/

private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("win");

/**

* 监测图片是否合法,是否只有一张脸

*/

public static void checkFace(String pictureUrl) throws Exception {

// //将在线图片保存为本地图片

// String imgPath = saveLocal(pictureUrl);

// //本地图片

// File file = new File(imgPath);

// FileInputStream fileInputStream = new FileInputStream(file);

// ByteArrayOutputStream out = new ByteArrayOutputStream();

// byte[] localBuff = new byte[fileInputStream.available()];

// fileInputStream.read(localBuff);

// out.write(localBuff);

// log.info("本地图片:"+localBuff.length);

//在线图片

URL url = new URL(pictureUrl);

URLConnection uc = url.openConnection();

InputStream inputStream = uc.getInputStream();

ByteArrayOutputStream swapStream = new ByteArrayOutputStream();

byte[] buff = new byte[1024];

int rc;

while ((rc = inputStream.read(buff, 0, 1024)) > 0) {

swapStream.write(buff, 0, rc);

}

byte[] urlBuff = swapStream.toByteArray();

log.info("在线图片:"+urlBuff.length);

List bs = new ArrayList<>();

bs.addAll(Bytes.asList(urlBuff));

log.info("buffer长度"+bs.size());

/**

* 不好使

*/

// Mat image = Converters.vector_char_to_Mat(bs);

// Mat image = Converters.vector_uchar_to_Mat(bs);

/**

* 读取本地

*/

// Mat image = Imgcodecs.imread(imgPath);

/**

* 读数据流

*/

Mat image = Imgcodecs.imdecode(new MatOfByte(urlBuff), Imgcodecs.IMREAD_UNCHANGED);

if (image.empty()) {

log.error("image 内容不存在!");

return;

}

// 3 特征匹配

MatOfRect face = new MatOfRect();

faceDetector.detectMultiScale(image, face);

// 4 匹配 Rect 矩阵 数组

Rect[] rects = face.toArray();

System.out.println("匹配到 " + rects.length + " 个人脸");

// delFile(imgPath);

if (rects.length == 0) {

throw new PublicException(ErrorCode.A0430.getCode(), "没有监测到人脸");

} else if (rects.length > 1) {

throw new PublicException(ErrorCode.A0430.getCode(), "检测到图片有多张人脸,请重新上传");

}

}

public static String saveLocal(String pictureUrl) throws IOException {

URL url = new URL(pictureUrl);

URLConnection uc = url.openConnection();

InputStream inputStream = uc.getInputStream();

String[] value = pictureUrl.split("/");

String firstFilePath = "D:\\pictures\\";

if (!IS_WINDOWS) {

firstFilePath = "/tmp/tmp-picture/";

}

String fileName = firstFilePath + value[value.length - 1];

FileOutputStream out = new FileOutputStream(fileName);

int j = 0;

while ((j = inputStream.read()) != -1) {

out.write(j);

}

inputStream.close();

return fileName;

}

/**

* Callback used to run the bean.

*

* @param args incoming main method arguments

* @throws Exception on error

*/

@Override

public void run(String... args){

String systemProperties = String.valueOf(System.getProperties());

log.info(systemProperties);

System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

String path = "";

//如果是window系统取出路径开头的/

if (IS_WINDOWS) {

path = windowXmlPath;

}else{

path = linuxXmlPath;

}

/**

* 初始化人脸探测器

*/

faceDetector = new CascadeClassifier(path);

log.info("==========初始化人脸探测器成功===========");

}

}

OpenCV 提供的 API 是直接根据路径读取图片的,所以最开始的时候我是把图片保存到本地在读取才成功的,但是这种方式太憨了点,在实际生产环境中,大部分情况下都是直接读取网络图片。在内存就完成图片和 opencv 的 Mat 对象的转换。这里代码中已经解决了url地址图片转化的问题。

这里附上解决该问题的博客 传送门

Linux安装opencv

Linux平台须要咱们手动编译,-opencv-4.1.1.zip,解压到/user/local目录下,而后编译

yum install ant gcc gtk2-devel pkgconfig zlib-devel

安装unzip命令

yum install -y unzip zip

解压命令

unzip opencv-4.1.1.zip

yum groupinstall "Development Tools"

安装cmake

查看cmake当前版本

cmake --version

yum -y install wget

-获得cmake-3.9.2源码

wget https://cmake.org/files/v3.9/cmake-3.9.2.tar.gz

解压、安装新版本

tar -xvf cmake-3.9.2.tar.gz

cd cmake-3.9.2

./configure

sudo make && make install

cd /usr/local/opencv-4.1.1

mkdir build

cd build

cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -DBUILD_TESTS=OFF ..

make -j8

sudo make install

对应的jar和.so文件在

/usr/local/share/java/opencv4/

人脸识别特征XML文件的地址

/usr/local/share/opencv4/haarcascades/haarcascade_frontalface_alt.xml

Linux启动

jar 启动命令添加Vm options

nohup java -jar -Djava.library.path=/usr/local/opencv-4.1.1/build/lib/ opencv-demo-1.0.jar > logs/opencv-demo-1.0.log 2>&1 &

github直接白嫖

项目代码已上传至github,可通过web接口测试,也可用main方法测试。传送门

参考博客地址

https://blog.csdn-/fangchao2011/article/details/99858927

https://blog.csdn-/eggtargaryen/article/details/83343358

https://blog.csdn-/wangyulj/article/details/79058390

https://blog.csdn-/qq_25775675/article/details/107808544?

https://lequ7.com/guan-yu-springbootspringboot-shi-yong-opencv-zong-jie.htmlutm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242

https://blog.csdn-/whudee/article/details/93379780

以上就是springboot集成opencv实现人脸识别功能的详细内容,更多关于springboot opencv人脸识别的资料请关注我们其它相关文章!

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:医疗类app运营模式(医疗类app运营模式)
下一篇:桌面应用安全测试标准,安全桌面测试的步骤
相关文章

 发表评论

暂时没有评论,来抢沙发吧~