package com.iden.bms.service; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.fill.FillConfig; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.face.monitor.FaceMonitor; import com.face.monitor.model.FaceModel; import com.iden.common.facetool.FaceIdenTool; import com.iden.common.entity.IdenCamera; import com.iden.common.entity.IdenCameraVideo; import com.iden.common.entity.IdenCommunity; import com.iden.common.entity.IdenFaceImage; import com.iden.common.exception.BDException; import com.iden.common.service.IdenCameraService; import com.iden.common.service.IdenCameraVideoService; import com.iden.common.service.IdenCommunityService; import com.iden.common.service.IdenFaceImageService; import com.iden.common.util.ByteUtil; import com.iden.common.util.DateUtils; import com.iden.common.util.ImgUtil; import com.iden.common.vo.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import java.util.*; /** * * @author makejava * @since 2021-05-21 00:08:38 */ @Slf4j @Service public class TraceService { @Resource private IdenCameraVideoService idenCameraVideoService; @Resource private IdenCommunityService idenCommunityService; @Resource private IdenCameraService idenCameraService; @Resource private IdenFaceImageService idenFaceImageService; @Value("${iden.root:#{null}}") private String idenRoot; @Value("${file.url:#{null}}") private String fileUrl; @Value("${ffmpeg.path:#{null}}") private String ffmpegPath; /** * 上传图像 * @param file * @return 访问URL */ public String uploadImage(MultipartFile file) throws BDException { String imageUrl = null; try { if (file != null) { //获取文件名 String fileName = file.getOriginalFilename(); if (org.springframework.util.StringUtils.isEmpty(fileName) || file.getSize() == 0) { throw new BDException("图像文件不能为空!"); } //验证文件名是否合格 if (!ImgUtil.isImg(fileName)) { throw new BDException("图像文件必须是图片格式!"); } String saveFileName = DateUtils.getCurrYyyyMMddHHmmssDate() + "_" + UUID.randomUUID().toString() + fileName.substring(fileName.lastIndexOf(".")); String picFullFileName = idenRoot + "data/final/trace/" + saveFileName; FileOutputStream fos = new FileOutputStream(picFullFileName); fos.write(file.getBytes()); imageUrl = fileUrl + "trace/" + saveFileName; } else { throw new BDException("上传失败"); } } catch (Exception e) { throw new BDException("上传失败",e); } return imageUrl; } /** * 上传图像查询轨迹列表 * 图像识别,使用特征码查询图像库,得到图库表中对应的数据列表 * @return */ public Map> listUploadImagesTrace(String imageNames, String beginTime, String endTime, UserLoginedConvertVO loginUser) { Map> result = new HashMap<>(); Date dateBegin = null; if(StringUtils.isNotEmpty(beginTime)){ dateBegin = DateUtils.strToDate(beginTime,"yyyy-MM-dd HH:mm:ss"); } Date dateEnd = null; if(StringUtils.isNotEmpty(endTime)){ dateEnd = DateUtils.strToDate(endTime,"yyyy-MM-dd HH:mm:ss"); } if(imageNames.endsWith(",")) { imageNames = imageNames.substring(0, imageNames.length() - 1); } String[] imageNameArr = imageNames.split(","); File[] imgFiles = new File[imageNameArr.length]; for (int i = 0; i < imageNameArr.length; i++) { if (StringUtils.isNotEmpty(imageNameArr[i])){ imgFiles[i] = new File(idenRoot + "data/final/trace/" + imageNameArr[i]); } } //上传的图像的特征码结构体数组 FaceModel[] faceModels = FaceIdenTool.extractFeature(idenRoot,imgFiles); //初始化引擎,加载摄像头上传的在时间段内的图像人脸特征库 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().isNotNull(IdenFaceImage::getFeatPtr) .ge(IdenFaceImage::getPhotographTime,dateBegin) .le(IdenFaceImage::getPhotographTime,dateEnd) .orderByAsc(IdenFaceImage::getPhotographTime); List idenFaceImageList = this.idenFaceImageService.list(queryWrapper); if (CollUtil.isEmpty(idenFaceImageList)) { return result; } FaceModel[] dataset = new FaceModel[idenFaceImageList.size()]; for(int i = 0; i < idenFaceImageList.size(); i++){ IdenFaceImage idenFaceImage = idenFaceImageList.get(i); dataset[i] = new FaceModel(); dataset[i].setPersonId(idenFaceImage.getId().intValue()); dataset[i].setName(String.valueOf(i)); dataset[i].setFeatValue(ByteUtil.hex2Byte(idenFaceImage.getFeatPtr())); } FaceMonitor faceMonitorFaceImag = FaceIdenTool.initFaceMonitorWithDataset(idenRoot,dataset); for(int i = 0; i < faceModels.length; i++) { FaceModel faceModel = faceModels[i]; List traceVOList = new ArrayList<>(); FaceRetrieveResultVO faceRetrieveResultVO = FaceIdenTool.getHitResult(faceMonitorFaceImag,faceModel,true); if (faceRetrieveResultVO != null) { long hitIndex = faceRetrieveResultVO.getIndex(); IdenFaceImage idenFaceImage = idenFaceImageService.getById(hitIndex); if(idenFaceImage != null){ for(IdenFaceImage idenFaceImage1 : idenFaceImageList){ if(idenFaceImage.getUid().equals(idenFaceImage1.getUid())) { TraceVO vo = new TraceVO(); BeanUtil.copyProperties(idenFaceImage1,vo); if(vo.getCameraId() != null){ IdenCamera idenCamera = this.idenCameraService.getById(vo.getCameraId()); if(idenCamera != null) { vo.setDistrict(idenCamera.getDistrict()); vo.setSubdistrict(idenCamera.getSubdistrict()); vo.setCameraName(idenCamera.getName()); Long communityId = idenCamera.getCommunityId(); if(communityId != null ){ IdenCommunity idenCommunity = this.idenCommunityService.getById(communityId); if(idenCommunity != null) { vo.setCommunityName(idenCommunity.getName()); } } } } traceVOList.add(vo); } } } } result.put(imageNameArr[i],traceVOList); } return result; } public List getCameraVideoList(Long cameraId, String beginTime,String endTime) { Date dateBegin = null; if(StringUtils.isNotEmpty(beginTime)){ dateBegin = DateUtils.strToDate(beginTime,"yyyy-MM-dd HH:mm:ss"); } Date dateEnd = null; if(StringUtils.isNotEmpty(endTime)){ dateEnd = DateUtils.strToDate(endTime,"yyyy-MM-dd HH:mm:ss"); } List vos = new ArrayList<>(); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(IdenCameraVideo::getCameraId,cameraId) .le(dateEnd != null,IdenCameraVideo::getPhotographBeginTime,dateEnd) .ge(dateBegin != null,IdenCameraVideo::getPhotographEndTime,dateBegin) .orderByAsc(IdenCameraVideo::getPhotographEndTime); List idenCameraVideos = this.idenCameraVideoService.list(queryWrapper); if(CollUtil.isNotEmpty(idenCameraVideos)){ idenCameraVideos.forEach(item->{ CameraVideoVO vo = new CameraVideoVO(); BeanUtil.copyProperties(item,vo); vos.add(vo); }); } return vos; } public void exportToExcel(Map> map, UserLoginedConvertVO loginUser, HttpServletResponse response) throws Exception { if(map == null || map.size() == 0){ return; } List records = new ArrayList<>(); map.keySet().forEach(item->{ records.addAll(map.get(item)); }); InputStream excelTemplateIs = null; try { response.reset(); // 非常重要 response.addHeader("Access-Control-Allow-Origin", "*"); response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); final String fileName = URLEncoder.encode("轨迹表", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + System.currentTimeMillis() + ".xlsx"); // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替 // {} 代表普通变量 {.} 代表是list的变量 excelTemplateIs = this.getClass().getResourceAsStream("/static/template/export/IdenTraceTemplate.xlsx"); ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(excelTemplateIs).build(); WriteSheet writeSheet = EasyExcel.writerSheet("轨迹表").build(); // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。 // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用 // 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存 // 如果数据量大 list不是最后一行 参照另一个 FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.FALSE).build(); excelWriter.fill(records, fillConfig, writeSheet); excelWriter.finish(); } catch (Exception e) { e.printStackTrace(); } finally { if(excelTemplateIs != null){ try { excelTemplateIs.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } } } public String cutVideo(Long videoId,String beginTime,String ednTime,UserLoginedConvertVO loginUser) { String videoUrl = null; try { IdenCameraVideo idenCameraVideo = this.idenCameraVideoService.getById(videoId); if(idenCameraVideo == null){ return null; } IdenCamera idenCamera = this.idenCameraService.getById(idenCameraVideo.getCameraId()); if (idenCamera == null){ return null; } Long duration = DateUtils.betweenTimeSS(beginTime,ednTime); //s String videoFileName = idenCameraVideo.getVideoUrl().substring(idenCameraVideo.getVideoUrl().lastIndexOf("/") + 1); log.info("videoFileName:" + videoFileName); String videoFileExt = videoFileName.substring(videoFileName.lastIndexOf(".") + 1); log.info("videoFileExt:" + videoFileExt); String outFileName = UUID.randomUUID().toString() + "." + videoFileExt; log.info("outFileName:" + outFileName); String videoFilepath = idenRoot + "data/final/camera/video/" + idenCamera.getCode() + "/" + videoFileName; log.info("videoFilepath:" + videoFilepath); //String videoFilepath = "e:/20211223123223_76639ced-6400-11ec-b8f9-fa163e4e1e9f.mp4"; String ountFilePath = idenRoot + "data/final/tmp/" + idenCamera.getCode() + "/" + outFileName; //String ountFilePath = "e:/xx9.mp4"; videoUrl = fileUrl + "tmp/" + idenCamera.getCode() + "/" + outFileName; String cmd = ffmpegPath + " -ss " + beginTime + " -i " + videoFilepath + " -t " + duration + " -c:v copy -c:a copy " + ountFilePath; log.info("开始运行视频剪辑命令:" + cmd); Runtime.getRuntime().exec(cmd); log.info("视频剪辑完成"); } catch (IOException e) { e.printStackTrace(); } return videoUrl; } }