去除人脸识别内容
This commit is contained in:
@@ -25,7 +25,7 @@ export default defineConfig(({ mode, command }) => {
|
|||||||
},
|
},
|
||||||
// vite 相关配置
|
// vite 相关配置
|
||||||
server: {
|
server: {
|
||||||
port: 80,
|
port: 1024,
|
||||||
host: true,
|
host: true,
|
||||||
open: true,
|
open: true,
|
||||||
proxy: {
|
proxy: {
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ spring:
|
|||||||
druid:
|
druid:
|
||||||
# 主库数据源
|
# 主库数据源
|
||||||
master:
|
master:
|
||||||
url: jdbc:mysql://localhost:3306/ry_face?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
url: jdbc:mysql://140.143.206.120:3306/fad_watch?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||||
username: root
|
username: klp
|
||||||
password: 'sVYLnUv0QOWDTyVA'
|
password: KeLunPu123@
|
||||||
# 从库数据源
|
# 从库数据源
|
||||||
slave:
|
slave:
|
||||||
# 从数据源开关/默认关闭
|
# 从数据源开关/默认关闭
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ ruoyi:
|
|||||||
# 版权年份
|
# 版权年份
|
||||||
copyrightYear: 2025
|
copyrightYear: 2025
|
||||||
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
||||||
profile: D:/ruoyi/uploadPath
|
profile: /home/wangyu/uploadPath
|
||||||
# 获取ip地址开关
|
# 获取ip地址开关
|
||||||
addressEnabled: false
|
addressEnabled: false
|
||||||
# 验证码类型 math 数字计算 char 字符验证
|
# 验证码类型 math 数字计算 char 字符验证
|
||||||
@@ -64,7 +64,7 @@ spring:
|
|||||||
devtools:
|
devtools:
|
||||||
restart:
|
restart:
|
||||||
# 热部署开关
|
# 热部署开关
|
||||||
enabled: true
|
enabled: false
|
||||||
data:
|
data:
|
||||||
# redis 配置
|
# redis 配置
|
||||||
redis:
|
redis:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<!-- 日志存放路径 -->
|
<!-- 日志存放路径 -->
|
||||||
<property name="log.path" value="/home/ruoyi/logs" />
|
<property name="log.path" value="/home/wangyu/logs" />
|
||||||
<!-- 日志输出格式 -->
|
<!-- 日志输出格式 -->
|
||||||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
|
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
|
||||||
|
|
||||||
|
|||||||
@@ -59,8 +59,8 @@ public class InitServer implements CommandLineRunner {
|
|||||||
public void run(String... args) throws Exception {
|
public void run(String... args) throws Exception {
|
||||||
// 初始化自动播放
|
// 初始化自动播放
|
||||||
this.initAutoPlay();
|
this.initAutoPlay();
|
||||||
// 获取本机IP地址
|
// TODO 获取本机IP地址
|
||||||
String ip = InetAddress.getLocalHost().getHostAddress();
|
String ip = "localhost";
|
||||||
// 获取http端口号
|
// 获取http端口号
|
||||||
String httpPort = this.env.getProperty("server.port");
|
String httpPort = this.env.getProperty("server.port");
|
||||||
// 获取web路径
|
// 获取web路径
|
||||||
@@ -80,7 +80,7 @@ public class InitServer implements CommandLineRunner {
|
|||||||
"\t wsflv: \t ws://{}:{}/live?url={您的源地址} \n" +
|
"\t wsflv: \t ws://{}:{}/live?url={您的源地址} \n" +
|
||||||
"\t hls(m3u8): \t http://{}:{}/hls?url={您的源地址} \n" +
|
"\t hls(m3u8): \t http://{}:{}/hls?url={您的源地址} \n" +
|
||||||
"\t h2-database: \t http://{}:{}/h2-console \n" +
|
"\t h2-database: \t http://{}:{}/h2-console \n" +
|
||||||
"\t 作者微信: \t chenbai0511 \n" +
|
"\t 作者微信: \t yu5132310 \n" +
|
||||||
"\t 请我喝杯咖啡吧qwq \n" +
|
"\t 请我喝杯咖啡吧qwq \n" +
|
||||||
"--------------------------------------------------------- \n",
|
"--------------------------------------------------------- \n",
|
||||||
port,
|
port,
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ public class FlvHandler extends SimpleChannelInboundHandler<Object> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CameraDto cameraDto = buildCamera(req.uri());
|
CameraDto cameraDto = buildCamera(req.uri());
|
||||||
|
System.out.println(cameraDto);
|
||||||
if (StrUtil.isBlank(cameraDto.getUrl())) {
|
if (StrUtil.isBlank(cameraDto.getUrl())) {
|
||||||
log.info("url有误");
|
log.info("url有误");
|
||||||
sendError(ctx, HttpResponseStatus.BAD_REQUEST);
|
sendError(ctx, HttpResponseStatus.BAD_REQUEST);
|
||||||
@@ -100,6 +100,7 @@ public class FlvHandler extends SimpleChannelInboundHandler<Object> {
|
|||||||
|
|
||||||
if (!req.decoderResult().isSuccess() || (!"websocket".equals(req.headers().get("Upgrade")))) {
|
if (!req.decoderResult().isSuccess() || (!"websocket".equals(req.headers().get("Upgrade")))) {
|
||||||
// http请求
|
// http请求
|
||||||
|
System.out.println("q3gegyaisgd");
|
||||||
sendFlvReqHeader(ctx);
|
sendFlvReqHeader(ctx);
|
||||||
mediaService.playForHttp(cameraDto, ctx);
|
mediaService.playForHttp(cameraDto, ctx);
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import com.ruoyi.common.utils.spring.SpringUtils;
|
|||||||
import com.ruoyi.video.common.ClientType;
|
import com.ruoyi.video.common.ClientType;
|
||||||
import com.ruoyi.video.domain.dto.CameraDto;
|
import com.ruoyi.video.domain.dto.CameraDto;
|
||||||
import com.ruoyi.video.service.MediaService;
|
import com.ruoyi.video.service.MediaService;
|
||||||
import com.ruoyi.video.utils.ArcFaceEngineUtil;
|
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
@@ -97,12 +96,10 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
|
|||||||
*/
|
*/
|
||||||
private Thread listenThread;
|
private Thread listenThread;
|
||||||
|
|
||||||
private ArcFaceEngineUtil arcFaceEngineUtil;
|
|
||||||
|
|
||||||
public MediaTransferFlvByJavacv(CameraDto cameraDto) {
|
public MediaTransferFlvByJavacv(CameraDto cameraDto) {
|
||||||
super();
|
super();
|
||||||
this.cameraDto = cameraDto;
|
this.cameraDto = cameraDto;
|
||||||
this.arcFaceEngineUtil = SpringUtils.getBean(ArcFaceEngineUtil.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
@@ -129,45 +126,43 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
|
|||||||
this.recorderStatus = recorderStatus;
|
this.recorderStatus = recorderStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建拉流器
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected boolean createGrabber() {
|
protected boolean createGrabber() {
|
||||||
// 拉流器
|
|
||||||
grabber = new FFmpegFrameGrabber(cameraDto.getUrl());
|
grabber = new FFmpegFrameGrabber(cameraDto.getUrl());
|
||||||
// 超时时间(15秒)
|
|
||||||
grabber.setOption("stimeout", cameraDto.getNetTimeout());
|
// 这些参数很多是“微秒”单位;如果你的 getNetTimeout() / getReadOrWriteTimeout() 是毫秒,
|
||||||
|
// 记得 *1000 转为微秒字符串。这里演示保守固定值,先跑通为先。
|
||||||
|
String fiveSecUs = "5000000"; // 5s in microseconds
|
||||||
|
String oneMb = "1048576"; // 1MB
|
||||||
|
|
||||||
|
// ---- 通用优化 ----
|
||||||
grabber.setOption("threads", "1");
|
grabber.setOption("threads", "1");
|
||||||
// grabber.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
|
grabber.setOption("buffer_size", oneMb); // 输入缓冲
|
||||||
// 设置缓存大小,提高画质、减少卡顿花屏
|
grabber.setOption("rw_timeout", fiveSecUs); // 读写超时(微秒)
|
||||||
grabber.setOption("buffer_size", "1024000");
|
grabber.setOption("stimeout", fiveSecUs); // 套接字超时(微秒)
|
||||||
|
grabber.setOption("probesize", fiveSecUs); // 探测时长(微秒)
|
||||||
|
grabber.setOption("analyzeduration", fiveSecUs);// 解析时长(微秒)
|
||||||
|
grabber.setOption("fflags", "nobuffer"); // 低延迟
|
||||||
|
grabber.setOption("flags", "low_delay");
|
||||||
|
grabber.setOption("loglevel", "debug"); // 先开调试,稳定后可关
|
||||||
|
|
||||||
// 读写超时,适用于所有协议的通用读写超时
|
// ---- RTSP 关键修正 ----
|
||||||
grabber.setOption("rw_timeout", cameraDto.getReadOrWriteTimeout());
|
if (cameraDto.getUrl().toLowerCase().startsWith("rtsp://")) {
|
||||||
// 探测视频流信息,为空默认5000000微秒
|
// 统一走 TCP(RTP over RTSP/interleaved),避免 461 / NAT / 防火墙问题
|
||||||
grabber.setOption("probesize", cameraDto.getReadOrWriteTimeout());
|
|
||||||
// 解析视频流信息,为空默认5000000微秒
|
|
||||||
grabber.setOption("analyzeduration", cameraDto.getReadOrWriteTimeout());
|
|
||||||
|
|
||||||
// 如果为rtsp流,增加配置
|
|
||||||
if ("rtsp".equals(cameraDto.getUrl().substring(0, 4))) {
|
|
||||||
// 设置打开协议tcp / udp
|
|
||||||
grabber.setOption("rtsp_transport", "tcp");
|
grabber.setOption("rtsp_transport", "tcp");
|
||||||
// 首选TCP进行RTP传输
|
// 不再设置 prefer_tcp(没意义了);确保不带 multicast 相关 flag
|
||||||
grabber.setOption("rtsp_flags", "prefer_tcp");
|
// 只要视频轨,避免音频轨导致的协商失败(可按需移除)
|
||||||
|
grabber.setOption("allowed_media_types", "video");
|
||||||
} else if ("rtmp".equals(cameraDto.getUrl().substring(0, 4))) {
|
// 避免较大的 RTP 乱序延迟
|
||||||
// rtmp拉流缓冲区,默认3000毫秒
|
grabber.setOption("max_delay", "500000"); // 0.5s (微秒)
|
||||||
|
// 某些设备对 UA 比较挑,设置一个常见 UA(可选)
|
||||||
|
grabber.setOption("user_agent", "Lavf/60");
|
||||||
|
}
|
||||||
|
else if (cameraDto.getUrl().toLowerCase().startsWith("rtmp://")) {
|
||||||
grabber.setOption("rtmp_buffer", "1000");
|
grabber.setOption("rtmp_buffer", "1000");
|
||||||
// 默认rtmp流为直播模式,不允许seek
|
}
|
||||||
// grabber.setOption("rtmp_live", "live");
|
else if ("desktop".equalsIgnoreCase(cameraDto.getUrl())) {
|
||||||
|
|
||||||
} else if ("desktop".equals(cameraDto.getUrl())) {
|
|
||||||
// 支持本地屏幕采集,可以用于监控屏幕、局域网和wifi投屏等
|
|
||||||
grabber.setFormat("gdigrab");
|
grabber.setFormat("gdigrab");
|
||||||
grabber.setOption("draw_mouse", "1");// 绘制鼠标
|
grabber.setOption("draw_mouse", "1");
|
||||||
grabber.setNumBuffers(0);
|
grabber.setNumBuffers(0);
|
||||||
grabber.setOption("fflags", "nobuffer");
|
grabber.setOption("fflags", "nobuffer");
|
||||||
grabber.setOption("framerate", "25");
|
grabber.setOption("framerate", "25");
|
||||||
@@ -176,16 +171,16 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
grabber.start();
|
grabber.start();
|
||||||
log.info("\r\n{}\r\n启动拉流器成功", cameraDto.getUrl());
|
log.info("\n{}\n启动拉流器成功", cameraDto.getUrl());
|
||||||
return grabberStatus = true;
|
return (grabberStatus = true);
|
||||||
} catch (FrameGrabber.Exception e) {
|
} catch (FrameGrabber.Exception e) {
|
||||||
MediaService.cameras.remove(cameraDto.getMediaKey());
|
MediaService.cameras.remove(cameraDto.getMediaKey());
|
||||||
log.error("\r\n{}\r\n启动拉流器失败,网络超时或视频源不可用", cameraDto.getUrl());
|
log.error("\n{}\n启动拉流器失败,网络超时或视频源不可用({})", cameraDto.getUrl(), e.getMessage());
|
||||||
// e.printStackTrace();
|
return (grabberStatus = false);
|
||||||
}
|
}
|
||||||
return grabberStatus = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建转码推流录制器
|
* 创建转码推流录制器
|
||||||
*
|
*
|
||||||
@@ -333,7 +328,7 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
|
|||||||
|
|
||||||
if (frame != null) {
|
if (frame != null) {
|
||||||
|
|
||||||
processFaceDetection(frame);
|
|
||||||
|
|
||||||
if (startTime == 0) {
|
if (startTime == 0) {
|
||||||
startTime = System.currentTimeMillis();
|
startTime = System.currentTimeMillis();
|
||||||
@@ -383,16 +378,6 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
|
|||||||
log.info("关闭媒体流-javacv,{} ", cameraDto.getUrl());
|
log.info("关闭媒体流-javacv,{} ", cameraDto.getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Async
|
|
||||||
public void processFaceDetection(Frame frame) {
|
|
||||||
if (arcFaceEngineUtil != null) {
|
|
||||||
ImageInfo imageInfo = arcFaceEngineUtil.frameToImageInfo(frame);
|
|
||||||
if (imageInfo != null) {
|
|
||||||
arcFaceEngineUtil.getUserInfo(imageInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送帧数据
|
* 发送帧数据
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,286 +0,0 @@
|
|||||||
package com.ruoyi.video.utils;
|
|
||||||
|
|
||||||
import com.arcsoft.face.*;
|
|
||||||
import com.arcsoft.face.enums.DetectMode;
|
|
||||||
import com.arcsoft.face.enums.DetectOrient;
|
|
||||||
import com.arcsoft.face.enums.ErrorInfo;
|
|
||||||
import com.arcsoft.face.enums.ImageFormat;
|
|
||||||
import com.arcsoft.face.toolkit.ImageFactory;
|
|
||||||
import com.arcsoft.face.toolkit.ImageInfo;
|
|
||||||
import com.ruoyi.common.config.RuoYiConfig;
|
|
||||||
import com.ruoyi.common.utils.file.FileUploadUtils;
|
|
||||||
import com.ruoyi.video.domain.VImage;
|
|
||||||
import com.ruoyi.video.service.IVImageService;
|
|
||||||
import jakarta.annotation.PostConstruct;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.bytedeco.javacv.Frame;
|
|
||||||
import org.bytedeco.javacv.Java2DFrameConverter;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.awt.image.DataBufferByte;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author: orange
|
|
||||||
* @CreateTime: 2025-01-16
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
public class ArcFaceEngineUtil {
|
|
||||||
|
|
||||||
@Value("${arcFace.appId}")
|
|
||||||
public String appId;
|
|
||||||
|
|
||||||
@Value("${arcFace.sdkKey}")
|
|
||||||
public String sdkKey;
|
|
||||||
|
|
||||||
int errorCode;
|
|
||||||
|
|
||||||
String projectPath = System.getProperty("user.dir");
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IVImageService ivImageService;
|
|
||||||
|
|
||||||
FaceEngine faceEngine = new FaceEngine(projectPath+"\\ruoyi-video\\src\\main\\resources\\libs\\WIN64");
|
|
||||||
|
|
||||||
private final AtomicLong lastSaveTime = new AtomicLong(0); // 记录上次保存的时间戳
|
|
||||||
|
|
||||||
private static final long SAVE_INTERVAL = 10 * 1000; // 10 秒的间隔
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化
|
|
||||||
*/
|
|
||||||
@PostConstruct
|
|
||||||
public void init() {
|
|
||||||
this.errorCode = this.faceEngine.activeOnline(this.appId, this.sdkKey);
|
|
||||||
if (this.errorCode != ErrorInfo.MOK.getValue() && this.errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
|
|
||||||
log.error("引擎激活失败");
|
|
||||||
}
|
|
||||||
|
|
||||||
ActiveFileInfo activeFileInfo = new ActiveFileInfo();
|
|
||||||
this.errorCode = this.faceEngine.getActiveFileInfo(activeFileInfo);
|
|
||||||
if (this.errorCode != ErrorInfo.MOK.getValue() && this.errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
|
|
||||||
log.error("获取激活文件信息失败");
|
|
||||||
}
|
|
||||||
|
|
||||||
EngineConfiguration engineConfiguration = new EngineConfiguration();
|
|
||||||
engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
|
|
||||||
engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
|
|
||||||
engineConfiguration.setDetectFaceMaxNum(10);
|
|
||||||
engineConfiguration.setDetectFaceScaleVal(16);
|
|
||||||
FunctionConfiguration functionConfiguration = new FunctionConfiguration();
|
|
||||||
functionConfiguration.setSupportAge(true);
|
|
||||||
functionConfiguration.setSupportFace3dAngle(true);
|
|
||||||
functionConfiguration.setSupportFaceDetect(true);
|
|
||||||
functionConfiguration.setSupportFaceRecognition(true);
|
|
||||||
functionConfiguration.setSupportGender(true);
|
|
||||||
functionConfiguration.setSupportLiveness(true);
|
|
||||||
functionConfiguration.setSupportIRLiveness(true);
|
|
||||||
engineConfiguration.setFunctionConfiguration(functionConfiguration);
|
|
||||||
this.errorCode = this.faceEngine.init(engineConfiguration);
|
|
||||||
if (this.errorCode != ErrorInfo.MOK.getValue()) {
|
|
||||||
log.error("初始化引擎失败");
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info("------------------------");
|
|
||||||
log.info("ruoyi-video初始化引擎成功");
|
|
||||||
log.info("微信: chenbai0511");
|
|
||||||
log.info("请我喝杯咖啡吧qwq");
|
|
||||||
log.info("------------------------");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frame对象转换为ImageInfo对象
|
|
||||||
* @param frame
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public ImageInfo frameToImageInfo(Frame frame) {
|
|
||||||
if (frame == null || frame.image == null) {
|
|
||||||
log.error("Frame是空或非图像帧------");
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
Java2DFrameConverter converter = new Java2DFrameConverter();
|
|
||||||
BufferedImage image = converter.convert(frame);
|
|
||||||
if (image == null) {
|
|
||||||
log.error("Converted image is null");
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
int width = image.getWidth();
|
|
||||||
int height = image.getHeight();
|
|
||||||
byte[] imageData = ((DataBufferByte)image.getRaster().getDataBuffer()).getData();
|
|
||||||
ImageInfo imageInfo = new ImageInfo();
|
|
||||||
imageInfo.setWidth(width);
|
|
||||||
imageInfo.setHeight(height);
|
|
||||||
imageInfo.setImageFormat(ImageFormat.CP_PAF_BGR24);
|
|
||||||
imageInfo.setImageData(imageData);
|
|
||||||
return imageInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 虹软检测代码
|
|
||||||
* @param imageInfo
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public HashMap<String, Object> getUserInfo(ImageInfo imageInfo) {
|
|
||||||
ImageInfo imageInfoFc = ImageFactory.getRGBData(new File("D:\\cat\\fc.jpg"));
|
|
||||||
List<FaceInfo> faceInfoListFc = new ArrayList();
|
|
||||||
this.faceEngine.detectFaces(imageInfoFc.getImageData(), imageInfoFc.getWidth(), imageInfoFc.getHeight(), imageInfoFc.getImageFormat(), faceInfoListFc);
|
|
||||||
if (faceInfoListFc.isEmpty()) {
|
|
||||||
log.error("未检测到人脸(faceInfoListFc)");
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
FaceFeature faceFeatureFc = new FaceFeature();
|
|
||||||
this.faceEngine.extractFaceFeature(imageInfoFc.getImageData(), imageInfoFc.getWidth(), imageInfoFc.getHeight(), imageInfoFc.getImageFormat(), (FaceInfo)faceInfoListFc.get(0), faceFeatureFc);
|
|
||||||
List<FaceInfo> faceInfoList = new ArrayList();
|
|
||||||
this.errorCode = this.faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
|
|
||||||
if (faceInfoList.isEmpty()) {
|
|
||||||
log.error("未检测到人脸(faceInfoList)");
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
FaceFeature faceFeature = new FaceFeature();
|
|
||||||
this.faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), (FaceInfo)faceInfoList.get(0), faceFeature);
|
|
||||||
FaceFeature targetFaceFeature = new FaceFeature();
|
|
||||||
targetFaceFeature.setFeatureData(faceFeatureFc.getFeatureData());
|
|
||||||
FaceFeature sourceFaceFeature = new FaceFeature();
|
|
||||||
sourceFaceFeature.setFeatureData(faceFeature.getFeatureData());
|
|
||||||
FaceSimilar faceSimilar = new FaceSimilar();
|
|
||||||
this.faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
|
|
||||||
System.out.println("相似度:" + faceSimilar.getScore());
|
|
||||||
if (faceSimilar.getScore() < 0.8F) {
|
|
||||||
this.saveImage(imageInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.errorCode = this.faceEngine.setLivenessParam(0.5F, 0.7F);
|
|
||||||
FunctionConfiguration configuration = new FunctionConfiguration();
|
|
||||||
configuration.setSupportAge(true);
|
|
||||||
configuration.setSupportFace3dAngle(true);
|
|
||||||
configuration.setSupportGender(true);
|
|
||||||
configuration.setSupportLiveness(true);
|
|
||||||
this.errorCode = this.faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, configuration);
|
|
||||||
HashMap<String, Object> map = new HashMap();
|
|
||||||
List<GenderInfo> genderInfoList = new ArrayList();
|
|
||||||
this.errorCode = this.faceEngine.getGender(genderInfoList);
|
|
||||||
if (!genderInfoList.isEmpty()) {
|
|
||||||
System.out.println("性别:" + ((GenderInfo)genderInfoList.get(0)).getGender());
|
|
||||||
map.put("gender", ((GenderInfo)genderInfoList.get(0)).getGender());
|
|
||||||
} else {
|
|
||||||
log.error("未获取到性别信息");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<AgeInfo> ageInfoList = new ArrayList();
|
|
||||||
this.errorCode = this.faceEngine.getAge(ageInfoList);
|
|
||||||
if (!ageInfoList.isEmpty()) {
|
|
||||||
System.out.println("年龄:" + ((AgeInfo)ageInfoList.get(0)).getAge());
|
|
||||||
map.put("age", ((AgeInfo)ageInfoList.get(0)).getAge());
|
|
||||||
} else {
|
|
||||||
log.error("未获取到年龄信息");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Face3DAngle> face3DAngleList = new ArrayList();
|
|
||||||
this.errorCode = this.faceEngine.getFace3DAngle(face3DAngleList);
|
|
||||||
if (!face3DAngleList.isEmpty()) {
|
|
||||||
PrintStream var10000 = System.out;
|
|
||||||
float var10001 = ((Face3DAngle)face3DAngleList.get(0)).getPitch();
|
|
||||||
var10000.println("3D角度:" + var10001 + "," + ((Face3DAngle)face3DAngleList.get(0)).getRoll() + "," + ((Face3DAngle)face3DAngleList.get(0)).getYaw());
|
|
||||||
map.put("3DAngle", face3DAngleList.get(0));
|
|
||||||
} else {
|
|
||||||
log.error("未获取到3D角度信息");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<LivenessInfo> livenessInfoList = new ArrayList();
|
|
||||||
this.errorCode = this.faceEngine.getLiveness(livenessInfoList);
|
|
||||||
if (!livenessInfoList.isEmpty()) {
|
|
||||||
System.out.println("活体:" + ((LivenessInfo)livenessInfoList.get(0)).getLiveness());
|
|
||||||
map.put("liveness", ((LivenessInfo)livenessInfoList.get(0)).getLiveness());
|
|
||||||
} else {
|
|
||||||
log.error("未获取到活体信息");
|
|
||||||
}
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存图片
|
|
||||||
* @param imageInfo
|
|
||||||
*/
|
|
||||||
private void saveImage(ImageInfo imageInfo) {
|
|
||||||
long currentTime = System.currentTimeMillis();
|
|
||||||
long lastTime = lastSaveTime.get();
|
|
||||||
|
|
||||||
if (currentTime - lastTime < SAVE_INTERVAL) {
|
|
||||||
log.info("10 秒内已保存过照片,跳过本次保存");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lastSaveTime.compareAndSet(lastTime, currentTime)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
File dir = new File("D:\\cat");
|
|
||||||
if (!dir.exists()) {
|
|
||||||
dir.mkdirs();
|
|
||||||
}
|
|
||||||
String fileName = "image_" + currentTime + ".jpg";
|
|
||||||
File outputFile = new File(dir, fileName);
|
|
||||||
BufferedImage bufferedImage = this.convertImageInfoToBufferedImage(imageInfo);
|
|
||||||
if (bufferedImage != null) {
|
|
||||||
ImageIO.write(bufferedImage, "jpg", outputFile);
|
|
||||||
log.info("图片已保存:{}", outputFile.getAbsolutePath());
|
|
||||||
String filePath = RuoYiConfig.getUploadPath();
|
|
||||||
MultipartFile multipartFile = new CustomMultipartFile(outputFile, "image/jpeg");
|
|
||||||
String file_name = FileUploadUtils.upload(filePath, multipartFile);
|
|
||||||
VImage vImage = new VImage();
|
|
||||||
vImage.setImageName(file_name);
|
|
||||||
vImage.setImageData(fileName);
|
|
||||||
this.ivImageService.insertVImage(vImage);
|
|
||||||
} else {
|
|
||||||
log.error("无法转换 ImageInfo 为 BufferedImage");
|
|
||||||
}
|
|
||||||
} catch (IOException var16) {
|
|
||||||
log.error("保存图片失败:{}", var16.getMessage(), var16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将ImageInfo转换为BufferedImage
|
|
||||||
* @param imageInfo
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private BufferedImage convertImageInfoToBufferedImage(ImageInfo imageInfo) {
|
|
||||||
if (imageInfo != null && imageInfo.getImageData() != null) {
|
|
||||||
if (imageInfo.getImageFormat() == ImageFormat.CP_PAF_BGR24) {
|
|
||||||
int width = imageInfo.getWidth();
|
|
||||||
int height = imageInfo.getHeight();
|
|
||||||
byte[] imageData = imageInfo.getImageData();
|
|
||||||
BufferedImage bufferedImage = new BufferedImage(width, height, 5);
|
|
||||||
byte[] targetPixels = ((DataBufferByte)bufferedImage.getRaster().getDataBuffer()).getData();
|
|
||||||
System.arraycopy(imageData, 0, targetPixels, 0, imageData.length);
|
|
||||||
return bufferedImage;
|
|
||||||
} else {
|
|
||||||
log.error("不支持的图像格式:{}", imageInfo.getImageFormat());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.error("ImageInfo 或 imageData 为空");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -13,7 +13,8 @@
|
|||||||
|
|
||||||
Date: 16/01/2025 17:33:13
|
Date: 16/01/2025 17:33:13
|
||||||
*/
|
*/
|
||||||
|
CREATE DATABASE IF NOT EXISTS `fad_watch` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
||||||
|
USE `fad_watch`;
|
||||||
SET NAMES utf8mb4;
|
SET NAMES utf8mb4;
|
||||||
SET FOREIGN_KEY_CHECKS = 0;
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user