Java项目中使用OpenCV检测人脸的应用
一、准备工作
将下载好的opencv的jar包放在项目的根目录下,可以新建一个lib的文件夹,将其放在此处;
在pom文件中引入:
<profiles>
<!-- 生产环境 -->
<profile>
<id>pro</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profiles.active>pro</profiles.active>
</properties>
<dependencies>
<dependency>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
<version>480</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/opencv-480.jar</systemPath>
</dependency>
</dependencies>
</profile>
</profiles>
二、编写人脸库初始化
以下是基于Windows环境,Linux环境中同理
在你的application-dev.properties文件中配置好opencv的文件地址:
############################################################################################################################################
openCV配置
############################################################################################################################################
opencv.lib.path=C:/OpenCV/opencv/build/java/x64/opencv_java480.dll
opencv.face.detector.path=C:/OpenCV/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml
基础配置属性注入,新建一个config文件夹存放SimpFaceProperties类:
@Getter
@Configuration
public class SimpFaceProperties {
/**
* opencv库绝对路径
*/
@Value("${opencv.lib.path:}")
private String openCvLibPath;
/**
* opencv模型数据
*/
@Value("${opencv.face.detector.path:}")
private String openCvFaceXml;
}
可以在你的项目中新建一个专门存放人脸相关服务的模块module,如init文件夹下中的:
@Slf4j
@Component("InitLoadLib")
@SuppressWarnings("all")
public class InitLoadLib {
/**
* 是否加载库
*/
private static boolean IS_LIB_OPEN = false;
private static CascadeClassifier faceDetector;
@Resource
private SimpFaceProperties simpFaceProperties;
/**
* 项目初始化完成后加载lib库
*/
@PostConstruct
public void init() {
if (StringUtils.isBlank(simpFaceProperties.getOpenCvLibPath())) {
log.error("---> init opencv 库未配置");
return;
}
boolean isAbsolutePath = simpFaceProperties.getOpenCvLibPath().contains("/") || simpFaceProperties.getOpenCvLibPath().contains("\\");
// 判断是不是填写的绝对路径
if (isAbsolutePath && !FileUtil.exist(simpFaceProperties.getOpenCvLibPath())) {
log.error("---> init opencv 库不存在:{}", simpFaceProperties.getOpenCvLibPath());
return;
}
try {
// 获取系统类型
String os = System.getProperty("os.name").toLowerCase();
// 判断是不是windows
if (os.contains("windows")) {
log.info("---> init opencv Windows系统");
if (isAbsolutePath) {
System.load(simpFaceProperties.getOpenCvLibPath());
} else {
System.loadLibrary(simpFaceProperties.getOpenCvLibPath());
}
IS_LIB_OPEN = true;
} else if (os.contains("linux")) {
log.info("---> init opencv Linux系统");
if (isAbsolutePath) {
System.load(simpFaceProperties.getOpenCvLibPath());
} else {
System.loadLibrary(simpFaceProperties.getOpenCvLibPath());
}
IS_LIB_OPEN = true;
} else {
log.error("---> init opencv 不支持该系统");
}
if (IS_LIB_OPEN) {
faceDetector = new CascadeClassifier(simpFaceProperties.getOpenCvFaceXml());
}
} catch (Exception e) {
log.error("---> init opencv 库加载失败:{}", e.getMessage());
IS_LIB_OPEN = false;
}
}
public static boolean isOpenCvLib() {
return IS_LIB_OPEN;
}
public static CascadeClassifier getFaceDetector() {
return faceDetector;
}
}
三、编写人脸服务接口业务
控制层中的接口代码:
/**
* 人脸检测
* @param file 文件
* @throws IOException 异常
*/
@PostMapping("faceDetection")
public Object faceDetection(MultipartFile file) throws IOException {
int rlsl = simpFaceService.faceDetection(file);
Map<String, Object> resMap = new HashMap<>();
resMap.put("rlsl", rlsl);
return resMap;
}
新建一个service文件夹,存放SimpFaceService接口服务类:
public interface SimpFaceService {
/**
* 检测图片上人脸数量
* @param file 文件(支持MultipartFile, InputStream, URL(网络文件地址),String(本地文件地址))
* @return 人脸数量
* @throws IOException 异常
*/
int faceDetection(Object file) throws IOException;
}
该接口服务的实现类:
@Service
public class SimpFaceServiceImpl implements SimpFaceService {
@Resource
private SimpFaceProperties simpFaceProperties;
/**
* 检测图片上人脸数量
* @param file 文件(支持MultipartFile, InputStream, URL(网络文件地址),String(本地文件地址))
* @return 人脸数量
* @throws IOException 异常
*/
@Override
public int faceDetection(Object file) throws IOException {
if (!InitLoadLib.isOpenCvLib()) {
return 0;
}
// 文件转byte数组
byte[] byteArray = this.fileToBytes(file);
// 读取图片
Mat mat = Imgcodecs.imdecode(new MatOfByte(byteArray), Imgcodecs.IMREAD_UNCHANGED);
// 目标灰色图像
Mat dstGrayImg = new Mat();
// 转换灰色
Imgproc.cvtColor(mat, dstGrayImg, Imgproc.COLOR_BGR2GRAY);
// 检测脸部
MatOfRect face = new MatOfRect();
// 检测图像中的人脸
InitLoadLib.getFaceDetector().detectMultiScale(dstGrayImg, face);
return face.rows();
}
private byte[] fileToBytes(Object file) throws IOException {
if (file instanceof MultipartFile) {
return IoUtil.readBytes(((MultipartFile) file).getInputStream());
}
if (file instanceof URL) {
return HttpUtil.downloadBytes(((URL) file).getPath());
}
if (file instanceof InputStream) {
return IoUtil.readBytes((InputStream) file);
}
if (file instanceof String) {
return FileUtil.readBytes((String) file);
}
return null;
}
}