From 1ca7182979f83531ace6e320b997bf70c53c4a0f Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Thu, 17 Jul 2025 17:59:14 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E6=8A=A5=E5=9B=BE=E7=89=87=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E8=BF=9B=E8=A1=8C=E8=A3=81=E5=88=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../basic/controller/viid/ViidController.java | 51 ++++++++++++++++--- .../facebody/adapter/BceFaceBodyAdapter.java | 1 - .../pc/device/entity/DeviceConfigEntity.java | 10 ++++ .../pc/device/entity/DeviceCropConfig.java | 13 +++++ .../java/com/ycwl/basic/utils/ImageUtils.java | 31 +++++++++++ 5 files changed, 97 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/ycwl/basic/model/pc/device/entity/DeviceCropConfig.java diff --git a/src/main/java/com/ycwl/basic/controller/viid/ViidController.java b/src/main/java/com/ycwl/basic/controller/viid/ViidController.java index 93f5611..b21f9d2 100644 --- a/src/main/java/com/ycwl/basic/controller/viid/ViidController.java +++ b/src/main/java/com/ycwl/basic/controller/viid/ViidController.java @@ -12,6 +12,7 @@ import com.ycwl.basic.mapper.DeviceMapper; import com.ycwl.basic.mapper.FaceSampleMapper; import com.ycwl.basic.mapper.SourceMapper; import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity; +import com.ycwl.basic.model.pc.device.entity.DeviceCropConfig; import com.ycwl.basic.model.pc.device.entity.DeviceEntity; import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity; import com.ycwl.basic.model.pc.source.entity.SourceEntity; @@ -53,6 +54,8 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import jakarta.servlet.http.HttpServletRequest; + +import java.awt.image.RasterFormatException; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -244,8 +247,14 @@ public class ViidController { continue; } DeviceConfigEntity deviceConfig = deviceRepository.getDeviceConfig(device.getId()); + if (deviceConfig == null) { + log.warn("设备配置不存在:" + deviceID); + return new VIIDBaseResp( + new ResponseStatusObject(faceId, "/VIID/Faces", "0", "OK", sdfTime.format(new Date())) + ); + } int viidMode = 0; - if (deviceConfig != null && deviceConfig.getViidType() != null) { + if (deviceConfig.getViidType() != null) { viidMode = deviceConfig.getViidType(); } Date shotTime = null; @@ -285,7 +294,7 @@ public class ViidController { if (viidMode == 0) { // 遍历每个图片对象 // 先找到type14的图片 - List type14ImageList = subImageList.getSubImageInfoObject().stream().filter(subImage -> "14".equals(subImage.getType())).collect(Collectors.toList()); + List type14ImageList = subImageList.getSubImageInfoObject().stream().filter(subImage -> "14".equals(subImage.getType())).toList(); for (SubImageInfoObject subImage : subImageList.getSubImageInfoObject()) { // base64转换成MultipartFIle MultipartFile file = ImageUtils.base64ToMultipartFile(subImage.getData()); @@ -318,7 +327,7 @@ public class ViidController { faceSampleMapper.updateScore(faceSample.getId(), addFaceResp.getScore()); } } - if (deviceConfig != null && Integer.valueOf(1).equals(deviceConfig.getEnablePreBook())) { + if (Integer.valueOf(1).equals(deviceConfig.getEnablePreBook())) { DynamicTaskGenerator.addTask(faceSample.getId()); } }); @@ -337,11 +346,37 @@ public class ViidController { // 上传oss MultipartFile _file = ImageUtils.base64ToMultipartFile(_subImage.getData()); String filename = StorageUtil.joinPath(PHOTO_PATH, UUID.randomUUID() + "." + ext); - String _sourceUrl = scenicStorageAdapter.uploadFile(_file, filename); - scenicStorageAdapter.setAcl(StorageAcl.PUBLIC_READ, filename); - source.setUrl(_sourceUrl); - source.setPosJson(JSON.toJSONString(facePosition)); - sourceMapper.add(source); + ThreadPoolExecutor executor = getExecutor(scenicId); + executor.execute(() -> { + DeviceCropConfig cropConfig = deviceConfig.getCropConfig(); + MultipartFile _finalFile = _file; + if (cropConfig != null) { + if (cropConfig.getCropType() == 1) { + // 按固定位置截图 + try { + _finalFile = ImageUtils.cropImage(_file, cropConfig.getTargetX(), cropConfig.getTargetY(), cropConfig.getTargetWidth(), cropConfig.getTargetHeight()); + } catch (IOException ignored) { + } catch (RasterFormatException ignored) { + } + } else if (cropConfig.getCropType() == 2) { + // 按人脸位置 + try { + int targetX = facePosition.getLtX() - (cropConfig.getTargetWidth() - facePosition.getWidth()); + int targetY = facePosition.getLtY() - (cropConfig.getTargetHeight() - facePosition.getHeight()); + _finalFile = ImageUtils.cropImage(_file, targetX, targetY, cropConfig.getTargetWidth(), cropConfig.getTargetHeight()); + } catch (IOException ignored) { + } catch (RasterFormatException ignored) { + } + facePosition.setImgHeight(cropConfig.getTargetHeight()); + facePosition.setImgWidth(cropConfig.getTargetWidth()); + } + } + String _sourceUrl = scenicStorageAdapter.uploadFile(_finalFile, filename); + scenicStorageAdapter.setAcl(StorageAcl.PUBLIC_READ, filename); + source.setUrl(_sourceUrl); + source.setPosJson(JSON.toJSONString(facePosition)); + sourceMapper.add(source); + }); } log.info("人脸信息及原图{}张入库成功!设备ID:{}", type14ImageList.size(), deviceID); } diff --git a/src/main/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapter.java b/src/main/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapter.java index d71de2e..ba186a7 100644 --- a/src/main/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapter.java +++ b/src/main/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapter.java @@ -278,7 +278,6 @@ public class BceFaceBodyAdapter implements IFaceBodyAdapter { try { AipFace client = getClient(); HashMap options = new HashMap<>(); - options.put("quality_control", "LOW"); options.put("max_user_num", "50"); try { searchFaceLimiter.acquire(); diff --git a/src/main/java/com/ycwl/basic/model/pc/device/entity/DeviceConfigEntity.java b/src/main/java/com/ycwl/basic/model/pc/device/entity/DeviceConfigEntity.java index 7768f75..c4d834b 100644 --- a/src/main/java/com/ycwl/basic/model/pc/device/entity/DeviceConfigEntity.java +++ b/src/main/java/com/ycwl/basic/model/pc/device/entity/DeviceConfigEntity.java @@ -1,5 +1,6 @@ package com.ycwl.basic.model.pc.device.entity; +import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; @@ -62,4 +63,13 @@ public class DeviceConfigEntity { private Integer videoFree; private Long pairDevice; private String videoCrop; + private String cropConfig; + + public void setCropConfig(DeviceCropConfig cropConfig) { + this.cropConfig = JSON.toJSONString(cropConfig); + } + + public DeviceCropConfig getCropConfig() { + return JSON.parseObject(cropConfig, DeviceCropConfig.class); + } } diff --git a/src/main/java/com/ycwl/basic/model/pc/device/entity/DeviceCropConfig.java b/src/main/java/com/ycwl/basic/model/pc/device/entity/DeviceCropConfig.java new file mode 100644 index 0000000..e7e4f77 --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/pc/device/entity/DeviceCropConfig.java @@ -0,0 +1,13 @@ +package com.ycwl.basic.model.pc.device.entity; + +import lombok.Data; + +@Data +public class DeviceCropConfig { + // 截图类型 0:无截图 1:固定截图 2:按人脸位置截图 + private Integer cropType; + private Integer targetWidth; + private Integer targetHeight; + private Integer targetX; + private Integer targetY; +} diff --git a/src/main/java/com/ycwl/basic/utils/ImageUtils.java b/src/main/java/com/ycwl/basic/utils/ImageUtils.java index e41c74d..61d231d 100644 --- a/src/main/java/com/ycwl/basic/utils/ImageUtils.java +++ b/src/main/java/com/ycwl/basic/utils/ImageUtils.java @@ -3,7 +3,10 @@ package com.ycwl.basic.utils; import cn.hutool.core.codec.Base64; import org.springframework.web.multipart.MultipartFile; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -21,6 +24,34 @@ public class ImageUtils { } return new Base64DecodedMultipartFile(b, baseStrs[0]); } + + public static MultipartFile cropImage(MultipartFile file, int x, int y, int w, int h) throws IOException { + BufferedImage image = ImageIO.read(file.getInputStream()); + if (image.getWidth() > w) { + w = image.getWidth(); + } + if (image.getHeight() > h) { + h = image.getHeight(); + } + int targetX = x; + if (x < 0) { + targetX = 0; + } else if ((x + w) > image.getWidth()) { + targetX = image.getWidth() - w; + } + int targetY = y; + if (y < 0) { + targetY = 0; + } else if ((y + h) > image.getHeight()) { + targetY = image.getHeight() - h; + } + BufferedImage targetImage = image.getSubimage(targetX, targetY, w, h); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(targetImage, "jpg", baos); + baos.close(); + return new Base64DecodedMultipartFile(baos.toByteArray(), "image/jpeg"); + } + public static class Base64DecodedMultipartFile implements MultipartFile { private final byte[] imgContent;