jc il y a 6 heures
Parent
commit
fb16743d48

BIN
libs/WIN64/libarcsoft_face.dll


BIN
libs/WIN64/libarcsoft_face_engine.dll


BIN
libs/WIN64/libarcsoft_face_engine_jni.dll


+ 6 - 1
pom.xml

@@ -100,7 +100,6 @@
 <!--        </dependency>-->
 
 <!--        引入虹软jar包-->
-
         <dependency>
             <groupId>com.arcsoft.face</groupId>
             <artifactId>arcsoft-sdk-face</artifactId>
@@ -109,6 +108,12 @@
             <systemPath>${basedir}/libs/arcsoft-sdk-face-3.0.0.0.jar</systemPath>
         </dependency>
 
+        <dependency>
+            <groupId>io.minio</groupId>
+            <artifactId>minio</artifactId>
+            <version>7.1.0</version>
+        </dependency>
+
     </dependencies>
     <dependencyManagement>
         <dependencies>

+ 23 - 1
src/main/java/com/neko/controller/UserController.java

@@ -10,6 +10,7 @@ import com.neko.utils.ThirdlyResult;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
@@ -121,7 +122,7 @@ public class UserController {
     }
 
     /**
-     * 修改个人信息
+     * 修改密码
      * @param dto
      * @return
      */
@@ -129,4 +130,25 @@ public class UserController {
     public ResultVo updapeUserPwd(@RequestBody UserPwdDto dto){
         return userService.updapeUserPwd(dto);
     }
+
+    /**
+     * 修改头像
+     * @param token
+     * @param multipartFile
+     * @return
+     */
+    @RequestMapping("updateArata")
+    public ResultVo updateArata(@RequestParam("token") String token,@RequestParam("multipartFile")MultipartFile multipartFile){
+        return userService.updateArata(token,multipartFile);
+    }
+
+    /**
+     * 上传minio
+     * @param multipartFile
+     * @return
+     */
+    @RequestMapping("minioTuPian")
+    public ResultVo minioTuPian(MultipartFile multipartFile){
+        return userService.minioTuPian(multipartFile);
+    }
 }

+ 171 - 0
src/main/java/com/neko/face/FaceTestMd.java

@@ -0,0 +1,171 @@
+package com.neko.face;
+
+import com.arcsoft.face.*;
+import com.arcsoft.face.enums.*;
+import com.arcsoft.face.toolkit.ImageInfo;
+import com.arcsoft.face.toolkit.ImageInfoEx;
+
+import static com.arcsoft.face.toolkit.ImageFactory.getGrayData;
+import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Date 2025/5/23 18:57
+ * @Author neko
+ **/
+public class FaceTestMd {
+    public static void main(String[] args) {
+
+        //从官网获取
+        String appId = "7QqJ1iFejXvwgt2UqVGM7aSMknu5SpXJEoixwVjUMJNn";
+        String sdkKey = "Bs5JhkCG7NDRSakHoQkmk2Ys7LbpvJ7X9VvMLEVSrMgi";
+
+
+        // 加载引擎
+        FaceEngine faceEngine = new FaceEngine("D:\\javatext\\Zg5\\week1\\nekomimi\\libs\\WIN64");
+        //激活引擎
+        int errorCode = faceEngine.activeOnline(appId, sdkKey);
+
+        if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
+            System.out.println("引擎激活失败");
+        }
+
+
+        ActiveFileInfo activeFileInfo=new ActiveFileInfo();
+        errorCode = faceEngine.getActiveFileInfo(activeFileInfo);
+        if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
+            System.out.println("获取激活文件信息失败");
+        }
+
+        //引擎配置
+        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);
+
+
+        //初始化引擎
+        errorCode = faceEngine.init(engineConfiguration);
+
+        if (errorCode != ErrorInfo.MOK.getValue()) {
+            System.out.println("初始化引擎失败");
+        }
+
+
+        //人脸检测
+        ImageInfo imageInfo = getRGBData(new File("D:\\计算机\\b9e4b8a58d3db22741714f8ad24d175.jpg"));
+        List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
+        errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
+        System.out.println(faceInfoList);
+
+        //特征提取
+        FaceFeature faceFeature = new FaceFeature();
+        errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
+        System.out.println("特征值大小:" + faceFeature.getFeatureData().length);
+
+        //人脸检测2
+        ImageInfo imageInfo2 = getRGBData(new File("D:\\计算机\\030ab513d80c49522cbe28062ba5b7e.jpg"));
+//        ImageInfo imageInfo2 = getRGBData(new File("D:\\计算机\\536d6c8a02947d1128642d34c009d06.jpg"));
+        List<FaceInfo> faceInfoList2 = new ArrayList<FaceInfo>();
+        errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(),imageInfo2.getImageFormat(), faceInfoList2);
+        System.out.println(faceInfoList2);
+
+        //特征提取2
+        FaceFeature faceFeature2 = new FaceFeature();
+        errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2.get(0), faceFeature2);
+        System.out.println("特征值大小:" + faceFeature2.getFeatureData().length);
+
+        //特征比对
+        FaceFeature targetFaceFeature = new FaceFeature();
+        targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
+        FaceFeature sourceFaceFeature = new FaceFeature();
+        sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData());
+        FaceSimilar faceSimilar = new FaceSimilar();
+
+        errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
+
+        System.out.println("相似度:" + faceSimilar.getScore());
+
+        //设置活体测试
+        errorCode = faceEngine.setLivenessParam(0.5f, 0.7f);
+        //人脸属性检测
+        FunctionConfiguration configuration = new FunctionConfiguration();
+        configuration.setSupportAge(true);
+        configuration.setSupportFace3dAngle(true);
+        configuration.setSupportGender(true);
+        configuration.setSupportLiveness(true);
+        errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, configuration);
+
+
+        //性别检测
+        List<GenderInfo> genderInfoList = new ArrayList<GenderInfo>();
+        errorCode = faceEngine.getGender(genderInfoList);
+        System.out.println("性别:" + genderInfoList.get(0).getGender());
+
+        //年龄检测
+        List<AgeInfo> ageInfoList = new ArrayList<AgeInfo>();
+        errorCode = faceEngine.getAge(ageInfoList);
+        System.out.println("年龄:" + ageInfoList.get(0).getAge());
+
+        //3D信息检测
+        List<Face3DAngle> face3DAngleList = new ArrayList<Face3DAngle>();
+        errorCode = faceEngine.getFace3DAngle(face3DAngleList);
+        System.out.println("3D角度:" + face3DAngleList.get(0).getPitch() + "," + face3DAngleList.get(0).getRoll() + "," + face3DAngleList.get(0).getYaw());
+
+        //活体检测
+        List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
+        errorCode = faceEngine.getLiveness(livenessInfoList);
+        System.out.println("活体:" + livenessInfoList.get(0).getLiveness());
+
+
+        //IR属性处理
+        ImageInfo imageInfoGray = getGrayData(new File("D:\\计算机\\b9e4b8a58d3db22741714f8ad24d175.jpg"));
+        List<FaceInfo> faceInfoListGray = new ArrayList<FaceInfo>();
+        errorCode = faceEngine.detectFaces(imageInfoGray.getImageData(), imageInfoGray.getWidth(), imageInfoGray.getHeight(), imageInfoGray.getImageFormat(), faceInfoListGray);
+
+        FunctionConfiguration configuration2 = new FunctionConfiguration();
+        configuration2.setSupportIRLiveness(true);
+        errorCode = faceEngine.processIr(imageInfoGray.getImageData(), imageInfoGray.getWidth(), imageInfoGray.getHeight(), imageInfoGray.getImageFormat(), faceInfoListGray, configuration2);
+        //IR活体检测
+        List<IrLivenessInfo> irLivenessInfo = new ArrayList<>();
+        errorCode = faceEngine.getLivenessIr(irLivenessInfo);
+        System.out.println("IR活体:" + irLivenessInfo.get(0).getLiveness());
+
+        ImageInfoEx imageInfoEx = new ImageInfoEx();
+        imageInfoEx.setHeight(imageInfo.getHeight());
+        imageInfoEx.setWidth(imageInfo.getWidth());
+        imageInfoEx.setImageFormat(imageInfo.getImageFormat());
+        imageInfoEx.setImageDataPlanes(new byte[][]{imageInfo.getImageData()});
+        imageInfoEx.setImageStrides(new int[]{imageInfo.getWidth() * 3});
+        List<FaceInfo> faceInfoList1 = new ArrayList<>();
+        errorCode = faceEngine.detectFaces(imageInfoEx, DetectModel.ASF_DETECT_MODEL_RGB, faceInfoList1);
+
+        FunctionConfiguration fun = new FunctionConfiguration();
+        fun.setSupportAge(true);
+        errorCode = faceEngine.process(imageInfoEx, faceInfoList1, functionConfiguration);
+        List<AgeInfo> ageInfoList1 = new ArrayList<>();
+        int age = faceEngine.getAge(ageInfoList1);
+        System.out.println("年龄:" + ageInfoList1.get(0).getAge());
+
+        FaceFeature feature = new FaceFeature();
+        errorCode = faceEngine.extractFaceFeature(imageInfoEx, faceInfoList1.get(0), feature);
+
+
+        //引擎卸载
+        errorCode = faceEngine.unInit();
+
+    }
+}

+ 26 - 0
src/main/java/com/neko/miniofile/config/MinioConfig.java

@@ -0,0 +1,26 @@
+package com.neko.miniofile.config;
+
+import io.minio.MinioClient;
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * @Date 2025/3/10 16:43
+ * @Author neko
+ **/
+@Data
+@EnableConfigurationProperties(MinioConfigProperties.class)
+public class MinioConfig {
+    @Autowired
+    private MinioConfigProperties minioConfigProperties;
+
+    @Bean
+    public MinioClient minioClient(){
+        return MinioClient.builder()
+                .endpoint(minioConfigProperties.getEndpoint())
+                .credentials(minioConfigProperties.getAccesskey(),minioConfigProperties.getSecretKey())
+                .build();
+    }
+}

+ 18 - 0
src/main/java/com/neko/miniofile/config/MinioConfigProperties.java

@@ -0,0 +1,18 @@
+package com.neko.miniofile.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * @Date 2025/3/10 16:39
+ * @Author neko
+ **/
+@Data
+@ConfigurationProperties(prefix = "minio")
+public class MinioConfigProperties {
+    //服务器地址
+    private String endpoint;
+    private String accesskey;
+    private String secretKey;
+    private String bucketName;
+}

+ 27 - 0
src/main/java/com/neko/miniofile/service/FileService.java

@@ -0,0 +1,27 @@
+package com.neko.miniofile.service;
+
+import io.minio.errors.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * @Date 2025/3/10 18:04
+ * @Author neko
+ **/
+public interface FileService {
+    //上传
+    public String uploadHtml(String fileName, InputStream inputStream);
+    public String uploadImage(String fileName,InputStream inputStream) throws IOException, ServerException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException;
+
+    //删除
+    public void delete(String fileName);
+
+    String downloadFile(String fileName, InputStream filePath) throws ServerException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException;
+
+    //下载
+
+
+}

+ 88 - 0
src/main/java/com/neko/miniofile/service/impl/FileServiceImpl.java

@@ -0,0 +1,88 @@
+package com.neko.miniofile.service.impl;
+
+import com.neko.miniofile.config.MinioConfig;
+import com.neko.miniofile.config.MinioConfigProperties;
+import com.neko.miniofile.service.FileService;
+import io.minio.DownloadObjectArgs;
+import io.minio.MinioClient;
+import io.minio.ObjectWriteResponse;
+import io.minio.PutObjectArgs;
+import io.minio.errors.*;
+import lombok.SneakyThrows;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Import;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * @Date 2025/3/10 18:06
+ * @Author neko
+ **/
+@Service
+@Import(MinioConfig.class)
+@EnableConfigurationProperties(MinioConfigProperties.class)
+public class FileServiceImpl implements FileService {
+    @Autowired
+    private MinioClient minioClient;
+    @Autowired
+    private MinioConfigProperties configProperties;
+
+    @SneakyThrows
+    @Override
+    public String uploadHtml(String fileName, InputStream inputStream) {
+        PutObjectArgs putObjectArgs = PutObjectArgs.builder()
+                .bucket(configProperties.getBucketName())
+                .contentType("text/html")
+                .object(fileName)
+                .stream(inputStream, inputStream.available(), -1)
+                .build();
+        ObjectWriteResponse response = minioClient.putObject(putObjectArgs);
+        //获取地址
+        String path = minioClient.getObjectUrl(putObjectArgs.bucket(),putObjectArgs.object());
+        return path;
+    }
+
+    @Override
+    public String uploadImage(String fileName, InputStream inputStream) throws IOException, ServerException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
+        PutObjectArgs putObjectArgs = PutObjectArgs.builder()
+                .bucket(configProperties.getBucketName())
+                .contentType("image/jpg")
+                .object(fileName)
+                .stream(inputStream,inputStream.available(),-1)
+                .build();
+        ObjectWriteResponse response = minioClient.putObject(putObjectArgs);
+
+        //获取地址
+        String path = minioClient.getObjectUrl(putObjectArgs.bucket(),putObjectArgs.object());
+        return path;
+    }
+
+    @Override
+    public void delete(String fileName) {
+        try {
+            minioClient.removeObject(configProperties.getBucketName(),fileName);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public String downloadFile(String fileName, InputStream filePath) throws ServerException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
+
+        DownloadObjectArgs downloadObjectArgs = DownloadObjectArgs.builder()
+                .bucket(configProperties.getBucketName())
+                .object(fileName)
+                .filename(filePath.toString())
+                .build();
+        minioClient.downloadObject(downloadObjectArgs);
+
+        return "下载成功保存至:"+filePath;
+    }
+
+
+}

+ 5 - 0
src/main/java/com/neko/service/UserService.java

@@ -6,6 +6,7 @@ import com.neko.domain.dto.userDto.PhoneLoginDto;
 import com.neko.domain.dto.userDto.YanDto;
 import com.neko.domain.pojo.User;
 import com.neko.utils.ResultVo;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.net.UnknownHostException;
 
@@ -48,4 +49,8 @@ public interface UserService extends IService<User> {
     ResultVo myUserData(String token);
 
     ResultVo updapeUserPwd(UserPwdDto dto);
+
+    ResultVo minioTuPian(MultipartFile multipartFile);
+
+    ResultVo updateArata(String token, MultipartFile multipartFile);
 }

+ 43 - 0
src/main/java/com/neko/service/impl/UserServiceImpl.java

@@ -15,10 +15,12 @@ import com.neko.domain.pojo.UserLog;
 import com.neko.domain.pojo.UserProfile;
 import com.neko.mapper.UserLogMapper;
 import com.neko.mapper.UserProfileMapper;
+import com.neko.miniofile.service.FileService;
 import com.neko.service.UserService;
 import com.neko.mapper.UserMapper;
 import com.neko.utils.*;
 import io.jsonwebtoken.Claims;
+import io.minio.errors.*;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.http.HttpResponse;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -26,10 +28,14 @@ import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.util.DigestUtils;
 import org.springframework.util.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.IOException;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 
@@ -52,6 +58,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
     UserProfileMapper userProfileMapper;
     @Autowired
     UserLogMapper userLogMapper;
+    @Autowired
+    FileService fileService;
 
     @Override
     public ResultVo phoenLogin(PhoneLoginDto dto) throws Exception {
@@ -351,6 +359,41 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
 
         return ResultVo.success(ApiServiceExceptionEnum.RESULT_SUCCES,"修改密码成功");
     }
+
+    @Override
+    public ResultVo minioTuPian(MultipartFile multipartFile) {
+        try {
+            String fileName = multipartFile.getOriginalFilename();
+            fileName = UUID.randomUUID().toString().replaceAll("-","")+fileName.substring(fileName.lastIndexOf("."));
+            String path = fileService.uploadImage(fileName,multipartFile.getInputStream());
+
+            return ResultVo.success(path);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public ResultVo updateArata(String token, MultipartFile multipartFile) {
+        Claims claims = AppJwtUtil.getClaimsBody(token);
+        String id = claims.get("id").toString();
+        QueryWrapper<UserProfile> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(UserProfile::getUserId,id);
+        UserProfile userProfile = userProfileMapper.selectOne(queryWrapper);
+        if(userProfile==null){
+            return ResultVo.error(ApiServiceExceptionEnum.RESULT_ERROR);
+        }
+
+        String fileName = multipartFile.getOriginalFilename();
+        fileName = UUID.randomUUID().toString().replaceAll("-","")+fileName.substring(fileName.lastIndexOf("."));
+        try {
+            String path = fileService.uploadImage(fileName,multipartFile.getInputStream());
+            userProfile.setAvatar(path);
+            return ResultVo.success("修改成功");
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
 }
 
 

+ 2 - 0
src/main/resources/META-INF/spring.factories

@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+  com.neko.miniofile.service.impl.FileServiceImpl

+ 5 - 13
src/main/resources/application.yml

@@ -27,16 +27,8 @@ arcsoft:
   appid: 7QqJ1iFejXvwgt2UqVGM7aSMknu5SpXJEoixwVjUMJNn
   sdkkey: Bs5JhkCG7NDRSakHoQkmk2Ys7LbpvJ7X9VvMLEVSrMgi
   libpath: D:\kee\renlianshibie\ArcSoft_ArcFace_Java_Windows_x64_V3.0\libs\WIN64
-  engine-configuration:       #引擎配置
-    detectMode: IMAGE
-    detectFaceOrientPriority: ASF_OP_ALL_OUT
-    detectFaceScale: 32
-    detectFaceMaxNum: 8
-  function-configuration:     #功能配置
-    supportAge: true
-    supportFace3dAngle: true
-    supportFaceDetect: true
-    supportFaceRecognition: true
-    supportGender: true
-    supportLiveness: true
-    supportIRLiveness: true
+minio:
+  endpoint: http://47.95.170.81:19000
+  accesskey: minioadmin
+  secretKey: minioadmin
+  bucketName: loli