TraceService.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. package com.iden.bms.service;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import cn.hutool.core.collection.CollUtil;
  4. import com.alibaba.excel.EasyExcel;
  5. import com.alibaba.excel.ExcelWriter;
  6. import com.alibaba.excel.write.metadata.WriteSheet;
  7. import com.alibaba.excel.write.metadata.fill.FillConfig;
  8. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  9. import com.face.monitor.FaceMonitor;
  10. import com.face.monitor.model.FaceModel;
  11. import com.iden.common.facetool.FaceIdenTool;
  12. import com.iden.common.entity.IdenCamera;
  13. import com.iden.common.entity.IdenCameraVideo;
  14. import com.iden.common.entity.IdenCommunity;
  15. import com.iden.common.entity.IdenFaceImage;
  16. import com.iden.common.exception.BDException;
  17. import com.iden.common.service.IdenCameraService;
  18. import com.iden.common.service.IdenCameraVideoService;
  19. import com.iden.common.service.IdenCommunityService;
  20. import com.iden.common.service.IdenFaceImageService;
  21. import com.iden.common.util.ByteUtil;
  22. import com.iden.common.util.DateUtils;
  23. import com.iden.common.util.ImgUtil;
  24. import com.iden.common.vo.*;
  25. import lombok.extern.slf4j.Slf4j;
  26. import org.apache.commons.lang3.StringUtils;
  27. import org.springframework.beans.factory.annotation.Value;
  28. import org.springframework.stereotype.Service;
  29. import org.springframework.web.multipart.MultipartFile;
  30. import javax.annotation.Resource;
  31. import javax.servlet.http.HttpServletResponse;
  32. import java.io.File;
  33. import java.io.FileOutputStream;
  34. import java.io.IOException;
  35. import java.io.InputStream;
  36. import java.net.URLEncoder;
  37. import java.util.*;
  38. /**
  39. *
  40. * @author makejava
  41. * @since 2021-05-21 00:08:38
  42. */
  43. @Slf4j
  44. @Service
  45. public class TraceService {
  46. @Resource
  47. private IdenCameraVideoService idenCameraVideoService;
  48. @Resource
  49. private IdenCommunityService idenCommunityService;
  50. @Resource
  51. private IdenCameraService idenCameraService;
  52. @Resource
  53. private IdenFaceImageService idenFaceImageService;
  54. @Value("${iden.root:#{null}}")
  55. private String idenRoot;
  56. @Value("${file.url:#{null}}")
  57. private String fileUrl;
  58. @Value("${ffmpeg.path:#{null}}")
  59. private String ffmpegPath;
  60. /**
  61. * 上传图像
  62. * @param file
  63. * @return 访问URL
  64. */
  65. public String uploadImage(MultipartFile file) throws BDException {
  66. String imageUrl = null;
  67. try {
  68. if (file != null) {
  69. //获取文件名
  70. String fileName = file.getOriginalFilename();
  71. if (org.springframework.util.StringUtils.isEmpty(fileName) || file.getSize() == 0) {
  72. throw new BDException("图像文件不能为空!");
  73. }
  74. //验证文件名是否合格
  75. if (!ImgUtil.isImg(fileName)) {
  76. throw new BDException("图像文件必须是图片格式!");
  77. }
  78. String saveFileName = DateUtils.getCurrYyyyMMddHHmmssDate() + "_" + UUID.randomUUID().toString() + fileName.substring(fileName.lastIndexOf("."));
  79. String picFullFileName = idenRoot + "data/final/trace/" + saveFileName;
  80. FileOutputStream fos = new FileOutputStream(picFullFileName);
  81. fos.write(file.getBytes());
  82. imageUrl = fileUrl + "trace/" + saveFileName;
  83. } else {
  84. throw new BDException("上传失败");
  85. }
  86. } catch (Exception e) {
  87. throw new BDException("上传失败",e);
  88. }
  89. return imageUrl;
  90. }
  91. /**
  92. * 上传图像查询轨迹列表
  93. * 图像识别,使用特征码查询图像库,得到图库表中对应的数据列表
  94. * @return
  95. */
  96. public Map<String,List<TraceVO>> listUploadImagesTrace(String imageNames, String beginTime, String endTime, UserLoginedConvertVO loginUser) {
  97. Map<String,List<TraceVO>> result = new HashMap<>();
  98. Date dateBegin = null;
  99. if(StringUtils.isNotEmpty(beginTime)){
  100. dateBegin = DateUtils.strToDate(beginTime,"yyyy-MM-dd HH:mm:ss");
  101. }
  102. Date dateEnd = null;
  103. if(StringUtils.isNotEmpty(endTime)){
  104. dateEnd = DateUtils.strToDate(endTime,"yyyy-MM-dd HH:mm:ss");
  105. }
  106. if(imageNames.endsWith(",")) {
  107. imageNames = imageNames.substring(0, imageNames.length() - 1);
  108. }
  109. String[] imageNameArr = imageNames.split(",");
  110. File[] imgFiles = new File[imageNameArr.length];
  111. for (int i = 0; i < imageNameArr.length; i++) {
  112. if (StringUtils.isNotEmpty(imageNameArr[i])){
  113. imgFiles[i] = new File(idenRoot + "data/final/trace/" + imageNameArr[i]);
  114. }
  115. }
  116. //上传的图像的特征码结构体数组
  117. FaceModel[] faceModels = FaceIdenTool.extractFeature(idenRoot,imgFiles);
  118. //初始化引擎,加载摄像头上传的在时间段内的图像人脸特征库
  119. QueryWrapper<IdenFaceImage> queryWrapper = new QueryWrapper<>();
  120. queryWrapper.lambda().isNotNull(IdenFaceImage::getFeatPtr)
  121. .ge(IdenFaceImage::getPhotographTime,dateBegin)
  122. .le(IdenFaceImage::getPhotographTime,dateEnd)
  123. .orderByAsc(IdenFaceImage::getPhotographTime);
  124. List<IdenFaceImage> idenFaceImageList = this.idenFaceImageService.list(queryWrapper);
  125. if (CollUtil.isEmpty(idenFaceImageList)) {
  126. return result;
  127. }
  128. FaceModel[] dataset = new FaceModel[idenFaceImageList.size()];
  129. for(int i = 0; i < idenFaceImageList.size(); i++){
  130. IdenFaceImage idenFaceImage = idenFaceImageList.get(i);
  131. dataset[i] = new FaceModel();
  132. dataset[i].setPersonId(idenFaceImage.getId().intValue());
  133. dataset[i].setName(String.valueOf(i));
  134. dataset[i].setFeatValue(ByteUtil.hex2Byte(idenFaceImage.getFeatPtr()));
  135. }
  136. FaceMonitor faceMonitorFaceImag = FaceIdenTool.initFaceMonitorWithDataset(idenRoot,dataset);
  137. for(int i = 0; i < faceModels.length; i++) {
  138. FaceModel faceModel = faceModels[i];
  139. List<TraceVO> traceVOList = new ArrayList<>();
  140. FaceRetrieveResultVO faceRetrieveResultVO = FaceIdenTool.getHitResult(faceMonitorFaceImag,faceModel,true);
  141. if (faceRetrieveResultVO != null) {
  142. long hitIndex = faceRetrieveResultVO.getIndex();
  143. IdenFaceImage idenFaceImage = idenFaceImageService.getById(hitIndex);
  144. if(idenFaceImage != null){
  145. for(IdenFaceImage idenFaceImage1 : idenFaceImageList){
  146. if(idenFaceImage.getUid().equals(idenFaceImage1.getUid())) {
  147. TraceVO vo = new TraceVO();
  148. BeanUtil.copyProperties(idenFaceImage1,vo);
  149. if(vo.getCameraId() != null){
  150. IdenCamera idenCamera = this.idenCameraService.getById(vo.getCameraId());
  151. if(idenCamera != null) {
  152. vo.setDistrict(idenCamera.getDistrict());
  153. vo.setSubdistrict(idenCamera.getSubdistrict());
  154. vo.setCameraName(idenCamera.getName());
  155. Long communityId = idenCamera.getCommunityId();
  156. if(communityId != null ){
  157. IdenCommunity idenCommunity = this.idenCommunityService.getById(communityId);
  158. if(idenCommunity != null) {
  159. vo.setCommunityName(idenCommunity.getName());
  160. }
  161. }
  162. }
  163. }
  164. traceVOList.add(vo);
  165. }
  166. }
  167. }
  168. }
  169. result.put(imageNameArr[i],traceVOList);
  170. }
  171. return result;
  172. }
  173. public List<CameraVideoVO> getCameraVideoList(Long cameraId, String beginTime,String endTime) {
  174. Date dateBegin = null;
  175. if(StringUtils.isNotEmpty(beginTime)){
  176. dateBegin = DateUtils.strToDate(beginTime,"yyyy-MM-dd HH:mm:ss");
  177. }
  178. Date dateEnd = null;
  179. if(StringUtils.isNotEmpty(endTime)){
  180. dateEnd = DateUtils.strToDate(endTime,"yyyy-MM-dd HH:mm:ss");
  181. }
  182. List<CameraVideoVO> vos = new ArrayList<>();
  183. QueryWrapper<IdenCameraVideo> queryWrapper = new QueryWrapper<>();
  184. queryWrapper.lambda().eq(IdenCameraVideo::getCameraId,cameraId)
  185. .le(dateEnd != null,IdenCameraVideo::getPhotographBeginTime,dateEnd)
  186. .ge(dateBegin != null,IdenCameraVideo::getPhotographEndTime,dateBegin)
  187. .orderByAsc(IdenCameraVideo::getPhotographEndTime);
  188. List<IdenCameraVideo> idenCameraVideos = this.idenCameraVideoService.list(queryWrapper);
  189. if(CollUtil.isNotEmpty(idenCameraVideos)){
  190. idenCameraVideos.forEach(item->{
  191. CameraVideoVO vo = new CameraVideoVO();
  192. BeanUtil.copyProperties(item,vo);
  193. vos.add(vo);
  194. });
  195. }
  196. return vos;
  197. }
  198. public void exportToExcel(Map<String,List<TraceVO>> map, UserLoginedConvertVO loginUser, HttpServletResponse response) throws Exception {
  199. if(map == null || map.size() == 0){
  200. return;
  201. }
  202. List<TraceVO> records = new ArrayList<>();
  203. map.keySet().forEach(item->{
  204. records.addAll(map.get(item));
  205. });
  206. InputStream excelTemplateIs = null;
  207. try {
  208. response.reset(); // 非常重要
  209. response.addHeader("Access-Control-Allow-Origin", "*");
  210. response.setContentType("application/vnd.ms-excel");
  211. response.setCharacterEncoding("utf-8");
  212. final String fileName = URLEncoder.encode("轨迹表", "UTF-8");
  213. response.setHeader("Content-disposition", "attachment;filename=" + fileName + System.currentTimeMillis() + ".xlsx");
  214. // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
  215. // {} 代表普通变量 {.} 代表是list的变量
  216. excelTemplateIs = this.getClass().getResourceAsStream("/static/template/export/IdenTraceTemplate.xlsx");
  217. ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(excelTemplateIs).build();
  218. WriteSheet writeSheet = EasyExcel.writerSheet("轨迹表").build();
  219. // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
  220. // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
  221. // 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
  222. // 如果数据量大 list不是最后一行 参照另一个
  223. FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.FALSE).build();
  224. excelWriter.fill(records, fillConfig, writeSheet);
  225. excelWriter.finish();
  226. } catch (Exception e) {
  227. e.printStackTrace();
  228. } finally {
  229. if(excelTemplateIs != null){
  230. try {
  231. excelTemplateIs.close();
  232. } catch (IOException ioe) {
  233. ioe.printStackTrace();
  234. }
  235. }
  236. }
  237. }
  238. public String cutVideo(Long videoId,String beginTime,String ednTime,UserLoginedConvertVO loginUser) {
  239. String videoUrl = null;
  240. try {
  241. IdenCameraVideo idenCameraVideo = this.idenCameraVideoService.getById(videoId);
  242. if(idenCameraVideo == null){
  243. return null;
  244. }
  245. IdenCamera idenCamera = this.idenCameraService.getById(idenCameraVideo.getCameraId());
  246. if (idenCamera == null){
  247. return null;
  248. }
  249. Long duration = DateUtils.betweenTimeSS(beginTime,ednTime); //s
  250. String videoFileName = idenCameraVideo.getVideoUrl().substring(idenCameraVideo.getVideoUrl().lastIndexOf("/") + 1);
  251. log.info("videoFileName:" + videoFileName);
  252. String videoFileExt = videoFileName.substring(videoFileName.lastIndexOf(".") + 1);
  253. log.info("videoFileExt:" + videoFileExt);
  254. String outFileName = UUID.randomUUID().toString() + "." + videoFileExt;
  255. log.info("outFileName:" + outFileName);
  256. String videoFilepath = idenRoot + "data/final/camera/video/" + idenCamera.getCode() + "/" + videoFileName;
  257. log.info("videoFilepath:" + videoFilepath);
  258. //String videoFilepath = "e:/20211223123223_76639ced-6400-11ec-b8f9-fa163e4e1e9f.mp4";
  259. String ountFilePath = idenRoot + "data/final/tmp/" + idenCamera.getCode() + "/" + outFileName;
  260. //String ountFilePath = "e:/xx9.mp4";
  261. videoUrl = fileUrl + "tmp/" + idenCamera.getCode() + "/" + outFileName;
  262. String cmd = ffmpegPath + " -ss " + beginTime + " -i " + videoFilepath
  263. + " -t " + duration + " -c:v copy -c:a copy " + ountFilePath;
  264. log.info("开始运行视频剪辑命令:" + cmd);
  265. Runtime.getRuntime().exec(cmd);
  266. log.info("视频剪辑完成");
  267. } catch (IOException e) {
  268. e.printStackTrace();
  269. }
  270. return videoUrl;
  271. }
  272. }