diff --git a/bonus-common/bonus-common-core/lib/arcsoft-sdk-face-3.0.0.0-linux.jar b/bonus-common/bonus-common-core/lib/arcsoft-sdk-face-3.0.0.0-linux.jar new file mode 100644 index 0000000..3091a2e Binary files /dev/null and b/bonus-common/bonus-common-core/lib/arcsoft-sdk-face-3.0.0.0-linux.jar differ diff --git a/bonus-common/bonus-common-core/lib/arcsoft-sdk-face-3.0.0.0-windows.jar b/bonus-common/bonus-common-core/lib/arcsoft-sdk-face-3.0.0.0-windows.jar new file mode 100644 index 0000000..a5dcac9 Binary files /dev/null and b/bonus-common/bonus-common-core/lib/arcsoft-sdk-face-3.0.0.0-windows.jar differ diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/face/ArcFaceHelper.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/face/ArcFaceHelper.java new file mode 100644 index 0000000..e60bf95 --- /dev/null +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/face/ArcFaceHelper.java @@ -0,0 +1,244 @@ +package com.bonus.common.core.utils.face; + +import com.arcsoft.face.*; +import com.arcsoft.face.enums.*; +import org.apache.commons.lang3.StringUtils; + +import javax.imageio.ImageIO; +import java.awt.color.ColorSpace; +import java.awt.image.BufferedImage; +import java.awt.image.ColorConvertOp; +import java.awt.image.DataBufferByte; +import java.io.*; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +/** + * 人脸识别工具类 + * @author zys + */ +public class ArcFaceHelper { + + private static final String APP_ID = "52XE2dQBtdmMsfDMvyKmPCD1nGBSGQWQGUyJh5z9JhND"; + /** + * x64 + */ + private static final String WIN64_SDK_KEY = "GggpcEphVxXLXcpEZz6tdC19o3QhbuktDm3YTUhUGr7J"; + /** + * linux_64 + */ + private static final String LINUX64_SDK_KEY = "GggpcEphVxXLXcpEZz6tdC19evqXbbhMyYt71DGLwnCp"; + + private static FaceEngine faceEngine = null; + + public static final float STANDARD_SCORE = 0.85F; + + static { + try{ + String os = System.getProperty("os.name"); + if(StringUtils.startsWith(os.toLowerCase(), "win")){ + faceEngine = new FaceEngine("D:\\arcsoft_lib_64"); + //激活引擎 + faceEngine.activeOnline(APP_ID, WIN64_SDK_KEY); + } else { + faceEngine = new FaceEngine("/data/arcsoft_lib_64"); + //激活引擎 + faceEngine.activeOnline(APP_ID, LINUX64_SDK_KEY); + } + }catch (Throwable e){ + System.out.println("加载人脸识别引擎异常:" + e.getMessage()); + } + } + + public static FaceEngine getFaceEngine() { + return faceEngine; + } + + public FaceResult getFaceFeatures(String imgSrc) { + if(imgSrc.contains("http")){ + return getFaceFeatures(getNetUrlHttp(imgSrc)); + }else{ + return getFaceFeatures(new File(imgSrc)); + } + } + + public static FaceResult getFaceFeatures(File file) { + ImageInfo imageInfo = getRGBData(file); + if (imageInfo == null){ + return null; + } + EngineConfiguration engineConfiguration = EngineConfiguration.builder().functionConfiguration( + FunctionConfiguration.builder() + .supportFaceDetect(true) + .supportAge(true) + .supportFace3dAngle(true) + .supportFaceDetect(true) + .supportFaceRecognition(true) + .supportGender(true) + .build()).build(); + //初始化引擎 + faceEngine.init(engineConfiguration); + //人脸检测 + List lstFaceInfo = new ArrayList(); + faceEngine.detectFaces(imageInfo.getRgbData(), imageInfo.getWidth(), imageInfo.getHeight(), + ImageFormat.CP_PAF_BGR24, lstFaceInfo); + System.out.println("检测到人脸数:" + lstFaceInfo.size()); + if (lstFaceInfo.size() == 0) { + return null; +// throw new NullPointerException("未检测到人脸"); + } + FaceResult result = new FaceResult(); + //提取人脸特征 + FaceFeature faceFeature = new FaceFeature(); + int code = faceEngine.extractFaceFeature(imageInfo.getRgbData(), imageInfo.getWidth(), imageInfo.getHeight(), + ImageFormat.CP_PAF_BGR24, lstFaceInfo.get(0), faceFeature); + System.out.println("提取特征结果码:" + code); + result.setFeatures(faceFeature.getFeatureData()); + //人脸信息检测 + int processCode = faceEngine.process(imageInfo.getRgbData(), imageInfo.getWidth(), imageInfo.getHeight(), + ImageFormat.CP_PAF_BGR24, lstFaceInfo, + FunctionConfiguration.builder().supportAge(true).supportFace3dAngle(true).supportGender(true).build()); + System.out.println("人脸信息检测码:" + processCode); + if(code != 0 || processCode != 0){ + return null; +// throw new IllegalArgumentException("提取特征失败"); + } + //性别提取 + List genderInfoList = new ArrayList(); + int genderCode = faceEngine.getGender(genderInfoList); + //0:MALE;1:FEMALE;-1:UNKNOWN + result.setSex(genderInfoList.get(0).getGender()); + System.out.println("性别:" + genderInfoList.get(0).getGender() + ",性别提取码:" + genderCode); + //年龄提取 + List ageInfoList = new ArrayList(); + int ageCode = faceEngine.getAge(ageInfoList); + result.setAge(ageInfoList.get(0).getAge()); + System.out.println("年龄:" + ageInfoList.get(0).getAge() + ",年龄提取码:" + ageCode); + //3D信息提取 + List face3DAngleList = new ArrayList(); + int face3dCode = faceEngine.getFace3DAngle(face3DAngleList); + System.out.println("3D信息:" + face3DAngleList + ",3D信息提取码:" + face3dCode); + unInintEngine(); + return result; + } + + public static void unInintEngine() { + int code = faceEngine.unInit(); + System.out.println("销毁引擎:" + code); + } + + public static ImageInfo getRGBData(File file) { + if (file == null){ + return null; + } + ImageInfo imageInfo; + try { + //将图片文件加载到内存缓冲区 + BufferedImage image = ImageIO.read(file); + imageInfo = bufferedImage2ImageInfo(image); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + return imageInfo; + } + + private static ImageInfo bufferedImage2ImageInfo(BufferedImage image) { + ImageInfo imageInfo = new ImageInfo(); + int width = image.getWidth(); + int height = image.getHeight(); + // 使图片居中 + width = width & (~3); + height = height & (~3); + imageInfo.setWidth(width); + imageInfo.setHeight(height); + //根据原图片信息新建一个图片缓冲区 + BufferedImage resultImage = new BufferedImage(width, height, image.getType()); + //得到原图的rgb像素矩阵 + int[] rgb = image.getRGB(0, 0, width, height, null, 0, width); + //将像素矩阵 绘制到新的图片缓冲区中 + resultImage.setRGB(0, 0, width, height, rgb, 0, width); + //进行数据格式化为可用数据 + BufferedImage dstImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR); + try { + if (resultImage.getType() != BufferedImage.TYPE_3BYTE_BGR) { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); + ColorConvertOp colorConvertOp = new ColorConvertOp(cs, dstImage.createGraphics().getRenderingHints()); + colorConvertOp.filter(resultImage, dstImage); + } else { + dstImage = resultImage; + } + } catch (Exception e) { + // TODO: handle exception + System.err.println(e.toString()); + } + + //获取rgb数据 + imageInfo.setRgbData(((DataBufferByte) (dstImage.getRaster().getDataBuffer())).getData()); + return imageInfo; + } + + private static File getNetUrlHttp(String path){ + //对本地文件命名,path是http的完整路径,主要得到资源的名字 + String newUrl = path; + newUrl = newUrl.split("[?]")[0]; + String[] bb = newUrl.split("/"); + //得到最后一个分隔符后的名字 + String fileName = bb[bb.length - 1]; + + //保存到本地的路径 + String filePath; + String os = System.getProperty("os.name"); + if(StringUtils.startsWith(os.toLowerCase(), "win")){ + filePath = "D:\\images\\"+fileName; + } else { + filePath = "/data/real_name/faceDetection/"+fileName; + } + + File file = null; + + URL urlfile; + InputStream inputStream = null; + OutputStream outputStream = null; + try{ + //判断文件的父级目录是否存在,不存在则创建 + file = new File(filePath); + if(!file.getParentFile().exists()){ + file.getParentFile().mkdirs(); + } + try{ + //创建文件 + file.createNewFile(); + }catch (Exception e){ + e.printStackTrace(); + } + //下载 + urlfile = new URL(newUrl); + inputStream = urlfile.openStream(); + outputStream = new FileOutputStream(file); + + int bytesRead = 0; + byte[] buffer = new byte[8192]; + while ((bytesRead=inputStream.read(buffer,0,8192))!=-1) { + outputStream.write(buffer, 0, bytesRead); + } + }catch (Exception e) { + e.printStackTrace(); + }finally { + try { + if (null != outputStream) { + outputStream.close(); + } + if (null != inputStream) { + inputStream.close(); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + return file; + } + +} diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/face/FaceResult.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/face/FaceResult.java new file mode 100644 index 0000000..2d044e8 --- /dev/null +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/face/FaceResult.java @@ -0,0 +1,33 @@ +package com.bonus.common.core.utils.face; + +public class FaceResult { + + private Integer age; + private Integer sex; + private byte[] features; + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public Integer getSex() { + return sex; + } + + public void setSex(Integer sex) { + this.sex = sex; + } + + public byte[] getFeatures() { + return features; + } + + public void setFeatures(byte[] features) { + this.features = features; + } + +} diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/face/ImageInfo.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/face/ImageInfo.java new file mode 100644 index 0000000..40a2424 --- /dev/null +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/face/ImageInfo.java @@ -0,0 +1,33 @@ +package com.bonus.common.core.utils.face; + +public class ImageInfo { + + private byte[] rgbData; + private int width; + private int height; + + public byte[] getRgbData() { + return rgbData; + } + + public void setRgbData(byte[] rgbData) { + this.rgbData = rgbData; + } + + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + public int getHeight() { + return height; + } + + public void setHeight(int height) { + this.height = height; + } + +} diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/json/FastJsonHelper.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/json/FastJsonHelper.java new file mode 100644 index 0000000..5fab49f --- /dev/null +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/json/FastJsonHelper.java @@ -0,0 +1,186 @@ +package com.bonus.common.core.utils.json; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; + +import java.util.List; + +/** + * @author fly + * @version 1 + * json与jsonArray所有自定义bean嵌套的相关操作 + * 将fast json 简单的封装和添加注释而成 + * + * com.alibaba + * fastjson + * 1.2.47 + * + *修改时间:2021-09-30 + */ + public class FastJsonHelper { + + /** + * JSONArray : 相当于 List + * JSONObject: 相当于 Map + * public static final Object parse(String text); // 把JSON文本parse为JSONObject或者JSONArray + * public static final JSONObject parseObject(String text); // 把JSON文本parse成JSONObject + * public static final T parseObject(String text, Class clazz); // 把JSON文本parse为JavaBean + * public static final JSONArray parseArray(String text); // 把JSON文本parse成JSONArray + * public static final List< > parseArray(String text, Class clazz); //把JSON文本parse成JavaBean集合 + * public static final String toJSONString(Object object); // 将JavaBean序列化为JSON文本 || JSONObject转成JSON文本 + * public static final String toJSONString(Object object, boolean prettyFormat); // 将JavaBean序列化为带格式的JSON文本 + * public static final Object toJSON(Object javaObject); //将JavaBean转换为JSONObject或者JSONArray。 + */ + + + + /** + * 将任意bean转换成json字符串 + * fast json + * @param bean + * @param + * @return + */ + public static String beanToJsonStr(T bean) { + String jsonStr = JSON.toJSONString(bean); + return jsonStr; + } + + /** + * 把一个json字符串转换成bean对象 + * fast json + * @param str + * @param + * @return + */ + public static T jsonStrToBean(String str, Class clazz) { + T bean = JSON.parseObject(str, clazz); + return bean; + } + + /** + * 把一个jsonObj转换成bean对象 + * fast json + * @param jsonObj + * @param + * @return + */ + public static T jsonObjToBean(JSONObject jsonObj, Class clazz) { + String s = jsonObj.toJSONString(); + T bean = JSON.parseObject(s, clazz); + return bean; + } + + /** + * 把一个bean对象转换成jsonObj + * fast json + * @param bean + * @param + * @return + */ + public static JSONObject beanToJsonObj(T bean) { + Object o = JSON.toJSON(bean); + return (JSONObject) o; + } + + /** + * 把一个jsonStr转换成jsonObj + * fast json + * @param str + * @return + */ + public static JSONObject jsonStrToJsonObj(String str) { + Object o = JSON.parseObject(str); + return (JSONObject) o; + } + + /** + * 把一个jsonObj转换成jsonStr + * fast json + * @param jsonObj + * @return + */ + public static String jsonObjToJsonStr(JSONObject jsonObj) { + String s = jsonObj.toJSONString(); + return s; + } + + + /** + * 把一个beanList对象转换成jsonArrStr + * fast json + * @param beanList + * @param + * @return + */ + public static String beanListToJsonArrStr(List beanList) { + JSONArray o = (JSONArray)JSON.toJSON(beanList); + String s = JSON.toJSONString(o); + return s; + } + + /** + * 把一个jsonArrStr转换成beanList对象 + * fast json + * @param jsonArrStr + * @param + * @return + */ + public static List jsonArrStrToBeanList(String jsonArrStr, Class clazz) { + List ts = JSON.parseArray(jsonArrStr, clazz); + return ts; + } + + + /** + * 把一个JsonArr转换成JsonArrStr + * fast json + * @param jsonArr + * @return + */ + public static String jsonArrToJsonArrStr(JSONArray jsonArr) { + String s = JSON.toJSONString(jsonArr); + return s; + } + + + /** + * 把一个JsonArrStr文本转换成JsonArr + * fast json + * @param jsonArrStr + * @return + */ + public static JSONArray jsonArrStrToJsonArr(String jsonArrStr) { + Object o = JSON.parse(jsonArrStr); + return (JSONArray) o; + } + + + /** + * 把一个JsonArr转换成beanList + * fast json + * @param jsonArr + * @return + */ + public static List jsonArrToBeanList(JSONArray jsonArr, Class clazz) { + String s = JSON.toJSONString(jsonArr); + List ts = JSON.parseArray(s, clazz); + return ts; + } + + + /** + * 把一个beanList文本转换成JsonArr + * fast json + * @param beanList + * @return + */ + public static JSONArray beanListToJsonArr(List beanList) { + Object o = JSON.toJSON(beanList); + return (JSONArray) o; + } + + + } + diff --git a/bonus-modules/bonus-bmw/src/main/java/com/bonus/bmw/controller/BmWorkerContractController.java b/bonus-modules/bonus-bmw/src/main/java/com/bonus/bmw/controller/BmWorkerContractController.java index ee7022c..a4c0e53 100644 --- a/bonus-modules/bonus-bmw/src/main/java/com/bonus/bmw/controller/BmWorkerContractController.java +++ b/bonus-modules/bonus-bmw/src/main/java/com/bonus/bmw/controller/BmWorkerContractController.java @@ -3,6 +3,7 @@ import com.bonus.bmw.domain.vo.BmWorkerContract; import com.bonus.bmw.domain.vo.BmWorkerWageCard; import com.bonus.bmw.service.impl.BmWorkerContractServiceImpl; import com.bonus.common.core.utils.StringUtils; +import com.bonus.common.core.utils.json.FastJsonHelper; import com.bonus.common.core.web.controller.BaseController; import com.bonus.common.core.web.domain.AjaxResult; import com.bonus.common.core.web.page.TableDataInfo; @@ -17,6 +18,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.multipart.MultipartFile; import java.util.ArrayList; import java.util.List; @@ -101,8 +103,11 @@ public class BmWorkerContractController extends BaseController { @RequiresPermissionsOrInnerAuth(innerAuth = @InnerAuth) @PostMapping("/edit") @SysLog(title = "合同管理", businessType = OperaType.UPDATE, logType = 0, module = "施工人员->红绿灯管理->合同管理", details = "修改合同") - public AjaxResult edit(@Validated @RequestBody BmWorkerContract o) { + public AjaxResult edit(@RequestParam(value = "files") MultipartFile[] files,@RequestParam(value = "fileMsg") String fileMsg, @RequestParam(value = "params")String params) { try { + System.out.println("fileMsg:"+fileMsg); + System.out.println(files.length); + BmWorkerContract o = FastJsonHelper.jsonStrToBean(params, BmWorkerContract.class); return toAjax(service.updateByPrimaryKey(o)); } catch (Exception e) { logger.error(e.toString(), e); diff --git a/bonus-modules/bonus-bmw/src/main/java/com/bonus/bmw/controller/PmWorkerController.java b/bonus-modules/bonus-bmw/src/main/java/com/bonus/bmw/controller/PmWorkerController.java index d192a76..d77dd75 100644 --- a/bonus-modules/bonus-bmw/src/main/java/com/bonus/bmw/controller/PmWorkerController.java +++ b/bonus-modules/bonus-bmw/src/main/java/com/bonus/bmw/controller/PmWorkerController.java @@ -5,6 +5,8 @@ import com.bonus.bmw.domain.vo.BmWorkerWageCard; import com.bonus.bmw.domain.vo.PmWorker; import com.bonus.bmw.service.PmWorkerService; import com.bonus.bmw.service.impl.PmWorkerServiceImpl; +import com.bonus.common.core.utils.face.ArcFaceHelper; +import com.bonus.common.core.utils.face.FaceResult; import com.bonus.common.core.web.controller.BaseController; import com.bonus.common.core.web.domain.AjaxResult; import com.bonus.common.core.web.page.TableDataInfo; @@ -16,7 +18,11 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.multipart.MultipartFile; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; @@ -108,6 +114,42 @@ public class PmWorkerController extends BaseController { return error("系统异常,请联系管理员"); } + /** + * 人脸照片合格检测 + * @param file + * @return + */ + @RequiresPermissionsOrInnerAuth(innerAuth = @InnerAuth) + @PostMapping("/faceDetection") + @SysLog(title = "人脸照片合格检测", businessType = OperaType.UPDATE, logType = 0, module = "施工人员->出入场管理->人员入场管理", details = "人脸照片合格检测") + public AjaxResult faceDetection(@RequestParam(value = "file") MultipartFile file) { + if (file == null || file.isEmpty()) { + return AjaxResult.error("文件为空:" ); + } + // 创建临时文件 + File tempFile = null; + try { + // 获取文件后缀 + String originalFilename = file.getOriginalFilename(); + String suffix = ""; + if (originalFilename != null && originalFilename.contains(".")) { + suffix = originalFilename.substring(originalFilename.lastIndexOf(".")); + } + // 创建临时文件 + tempFile = Files.createTempFile("temp-image-", suffix).toFile(); + tempFile.deleteOnExit(); // JVM退出时自动删除 + // 将 MultipartFile 写入临时文件 + file.transferTo(tempFile); + ArcFaceHelper arcFaceHelper = new ArcFaceHelper(); + // 调用原方法,传入临时文件的路径 + FaceResult faceFeatures = arcFaceHelper.getFaceFeatures(tempFile.getAbsolutePath()); + return AjaxResult.success(faceFeatures); + } catch (IOException e) { + // 处理异常(如磁盘满、权限不足等) + e.printStackTrace(); + return AjaxResult.error("人脸检测失败:"+e.getMessage()); + } + } }