package com.objecteye.service.impl; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.objecteye.entity.PageResult; import com.objecteye.pojo.*; import com.objecteye.service.HumanVehicleAssociationService; import com.objecteye.utils.CompareDistance; import com.objecteye.utils.HttpClientUtils; import com.objecteye.utils.UserTools; import com.objecteye.utils.VehicleEngine; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; /** * @author yumiu */ @Service @Slf4j public class HumanVehicleAssociationServiceImpl implements HumanVehicleAssociationService { @Autowired private MongoTemplate mongoTemplate; @Autowired private HttpClientUtils httpClientUtils; @Autowired private VehicleEngine vehicleEngine; @Autowired private CompareDistance compareDistance; @Value("${topN}") private int topN; @Value("${threadNum}") private int threadNum; private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); /** * 以人搜车 * * @param currentpage * @param pagevolume * @param picfile * @return */ @Override public PageResult searchVehicleFromHuman(Long starttime, Long endtime, Float thresholds, int currentpage, int pagevolume, MultipartFile picfile) { if (null == picfile || picfile.equals("undefined")) { return null; } //创建返回的数据对象 Vector searchVehicleFromPeopleInfos = new Vector<>(); String peopleFace = httpClientUtils.multiToPeople(picfile); JSONObject peopleFaceJson = JSONObject.parseObject(peopleFace); Integer code = peopleFaceJson.getInteger("code"); if (code == 0) { JSONObject result = peopleFaceJson.getJSONObject("result"); if (result == null) { return null; } Integer count = result.getInteger("count"); if (count > 0) { JSONArray info = result.getJSONArray("info"); //创建treeMap,设置为降序排列 TreeMap treeMap = new TreeMap<>((a, b) -> b - a); for (int i = 0; i < info.size(); i++) { int size = 0; JSONObject peopleInfoSingle = info.getJSONObject(i); JSONObject faceDetectInfoParam = peopleInfoSingle.getJSONObject("faceDetectInfoParam"); JSONObject face_position = faceDetectInfoParam.containsKey("face_position") ? faceDetectInfoParam.getJSONObject("face_position") : null; Integer width = 0; Integer height = 0; if (null != face_position) { width = face_position.getInteger("width"); height = face_position.getInteger("height"); } //获取到面积 size = width * height; JSONArray featureArray = peopleInfoSingle.containsKey("feature") ? peopleInfoSingle.getJSONArray("feature") : null; treeMap.put(size, featureArray); } //获取到最大的人像 JSONArray maxFeaArr = treeMap.get(treeMap.firstKey()); //将JSONArr转换为float[] float[] feaFloats = new float[512]; for (int i = 0; i < feaFloats.length; i++) { feaFloats[i] = maxFeaArr.getFloat(i); } //调用人脸检索接口获取相似的人像的RetrieveKey int localTopN = 20000; SearchDataFromRetrieveDb searchDataFromRetrieveDb = vehicleEngine.searchDataFromRetrieveDb(localTopN, thresholds, threadNum, feaFloats); List list = searchDataFromRetrieveDb.getResult(); Map retrieveKeyDbResultMap = list.stream() .collect(Collectors.toMap(SearchDataFromRetrieveDbResult::getRetrieveKey, a -> a, (k1, k2) -> k1)); Criteria criteria = new Criteria(); if (starttime == null) { if (endtime != null) { criteria.and("pictime").lte(endtime); } } else { if (endtime == null) { criteria.and("pictime").gte(starttime); } else { criteria.and("pictime").gte(starttime).lte(endtime); } } Query primaryStepQuery = Query.query(criteria).with(Sort.by(Sort.Order.desc("pictime"))); primaryStepQuery.fields().include("id"); primaryStepQuery.fields().include("personid"); primaryStepQuery.fields().include("pictime"); primaryStepQuery.fields().include("vehicle_plate_hphm"); primaryStepQuery.fields().include("picurl"); primaryStepQuery.fields().include("personUrl"); // 数据库过滤结果 List rabbitMqVehicles = mongoTemplate.find(primaryStepQuery, RabbitMQVehicle.class); for (RabbitMQVehicle rabbitMqVehicle : rabbitMqVehicles) { if (rabbitMqVehicle == null) { continue; } if (retrieveKeyDbResultMap.containsKey(rabbitMqVehicle.getPersonid())) { SearchDataFromRetrieveDbResult searchDataFromRetrieveDbResult = retrieveKeyDbResultMap.get(rabbitMqVehicle.getPersonid()); SearchVehicleFromPeopleInfo searchVehicleFromPeopleSingle = new SearchVehicleFromPeopleInfo(rabbitMqVehicle.getId(), simpleDateFormat.format(new Date(rabbitMqVehicle.getPictime())), rabbitMqVehicle.getVehicle_plate_hphm(), searchDataFromRetrieveDbResult.getScore(), rabbitMqVehicle.getPicurl(), rabbitMqVehicle.getPersonUrl()); searchVehicleFromPeopleInfos.add(searchVehicleFromPeopleSingle); } } return UserTools.makePageResultByBaseList(searchVehicleFromPeopleInfos, currentpage, pagevolume); } } return null; } /** * 根据精准车辆号牌查询人像 * * @param currentpage * @param pagevolume * @param hphm * @return */ @Override public SearchPeopleOfhphmResult searchPeopleFromHphm(Long starttime, Long endtime, Integer currentpage, Integer pagevolume, String hphm) { SearchPeopleOfhphmResult searchPeopleOfhphmResult = new SearchPeopleOfhphmResult(); List list = null; if (!"".equals(hphm)) { list = new ArrayList(); //首先根据车辆号牌查询到相关的车辆 List byHphm = findByHphm(starttime, endtime, hphm, currentpage, pagevolume); for (RabbitMQVehicle rmqv : byHphm) { Long pictime = rmqv.getPictime(); //获取时间范围 starttime = (starttime == null) ? 0 : starttime; endtime = (endtime == null) ? 9999999999999L : endtime; if (pictime <= endtime && pictime >= starttime) { SearchPeopleOfHphmInfo searchPeopleOfHphmInfo = new SearchPeopleOfHphmInfo(rmqv.getId(), simpleDateFormat.format(new Date(rmqv.getPictime())), rmqv.getVehicle_plate_hphm(), rmqv.getPersonUrl()); list.add(searchPeopleOfHphmInfo); } } searchPeopleOfhphmResult.setTotal((int) Math.ceil((double) list.size() / pagevolume)); searchPeopleOfhphmResult.setRow(list); } return searchPeopleOfhphmResult; } /** * 通过personid获取到车辆信息 * * @return */ @Override public RabbitMQVehicle findVehicleByRetrieveKey(String personid) { Query query = new Query(); Criteria criteria = Criteria.where("personid").is(personid); query.addCriteria(criteria); return mongoTemplate.findOne(query, RabbitMQVehicle.class); } /** * 通过车辆号牌获取到车辆信息 * * @return */ @Override public List findByHphm(Long starttime, Long endtime, String hphm, int currentPage, int pageSize) { Query query = new Query(); query.with(Sort.by(Sort.Order.desc("pictime"))); int skip = (currentPage - 1) * pageSize; query.addCriteria(new Criteria().andOperator(Criteria.where("vehicle_plate_hphm").is(hphm), Criteria.where("personUrl").ne(null))); query.skip(skip); query.limit(pageSize); return mongoTemplate.find(query, RabbitMQVehicle.class); } /** * 通过retrieveKey获取到人信息 * * @return */ @Override public FaceInfoParam findPeopleByRetrieveKey(String retrieveKey, int currentPage, int pageSize) { Query query = new Query(); int skip = (currentPage - 1) * pageSize; Criteria criteria = Criteria.where("retrieveKey").is(retrieveKey); query.addCriteria(criteria); query.skip(skip);// 从那条记录开始 query.limit(pageSize);// 取多少条记录 return mongoTemplate.findOne(query, FaceInfoParam.class); } /** * 根据车辆图片查询关联的人 * * @param number * @param threshold * @param currentpage * @param pagevolume * @param picfile * @return */ @Override public List searchPeopleOfVehiclePic(int number, double threshold, int currentpage, int pagevolume, MultipartFile picfile) { List list = null; //根据MultipartFile,调用接口获取到该车辆的信息 JSONObject byPic = findByPic(number, threshold, currentpage, pagevolume, picfile); //根据查询到的车辆获取到每辆车的retrieveKey if (byPic != null && byPic.getInteger("total") > 0) { list = new ArrayList(); JSONArray rowArr = byPic.getJSONArray("row"); for (int i = 0; i < rowArr.size(); i++) { String retrieveKey = rowArr.getJSONObject(i).getString("retrieveKey"); //根据retrieveKey查询到相关人 Query query = new Query(); query.addCriteria(Criteria.where("retrieveKey").is(retrieveKey)); FaceInfoParam faceInfoParamSingle = mongoTemplate.findOne(query, FaceInfoParam.class); list.add(faceInfoParamSingle); } } return list; } /** * 通过过车序号和图片查询车辆集合 * * @param number * @param threshold * @param currentpage * @param pagevolume * @param picfile * @return */ public JSONObject findByPic(int number, double threshold, int currentpage, int pagevolume, MultipartFile picfile) { JSONObject data = null; //封装结果的对象 if (picfile == null) { return data; } //查询到所有数据信息 List allRabbitMQVehicleList = mongoTemplate.findAll(RabbitMQVehicle.class); String vehicleInfoByBase64 = httpClientUtils.multiToVehicle(picfile); JSONArray infoArr = JSONObject.parseObject(vehicleInfoByBase64).getJSONObject("result").getJSONArray("info"); //获取到用户选中的车辆 int size = infoArr.size(); if (number < size) { JSONObject vehicleSingleInfo = infoArr.getJSONObject(number); //获取该车辆的特征信息 double[] currentFeature = new double[256]; JSONArray featureArr = vehicleSingleInfo.getJSONObject("vehicle_fea_res").getJSONArray("feature"); //将featureArr转换为double[]类型 for (int i = 0; i < featureArr.size(); i++) { currentFeature[i] = featureArr.getDouble(i); } double currentFea = compareDistance.getDistance(currentFeature); //遍历mongodb所有的车辆信息 List pvc = new ArrayList(); for (RabbitMQVehicle rabbitMQVehicle : allRabbitMQVehicleList) { int vehicle_special_type = rabbitMQVehicle.getVehicle_special_type(); double[] dbFeature = rabbitMQVehicle.getVehicle_fea_feature(); //进行比对 double dbFea = compareDistance.getDistance(dbFeature); double similar = compareDistance.simDistance(currentFeature, currentFea, dbFeature, dbFea); if (threshold <= similar) { similar = (double) Math.round(similar * 100) / 100; similar = similar >= 1 ? 1 : similar; PicVehicleCompare picVehicleCompare = new PicVehicleCompare(); picVehicleCompare.setSimilar(similar); picVehicleCompare.setRabbitMQVehicle(rabbitMQVehicle); pvc.add(picVehicleCompare); } } //对row进行排序 pvc.sort((o1, o2) -> { if (o2.getSimilar() == o1.getSimilar()) { return 0; } else { return (o2.getSimilar() > o1.getSimilar()) ? 1 : -1; } }); //对row进行分页查询 List picVehicleComparesNew = UserTools.getPagedResultByBaseList(pvc, currentpage, pagevolume); //根据总条数获取总页数 int totalPage = UserTools.getPageTotalByBaseList(pvc, pagevolume); //获取row数据 JSONArray row = new JSONArray(); for (PicVehicleCompare next : picVehicleComparesNew) { JSONObject rowData = new JSONObject(); //获取id RabbitMQVehicle rabbitMQVehicle1 = next.getRabbitMQVehicle(); String id = rabbitMQVehicle1.getId(); rowData.put("id", id); rowData.put("hphm", rabbitMQVehicle1.getVehicle_plate_hphm()); Long pictime = rabbitMQVehicle1.getPictime(); rowData.put("phototime", simpleDateFormat.format(new Date(pictime))); rowData.put("recordid", rabbitMQVehicle1.getRecordid()); // 新方法,如果不需要四舍五入,可以使用RoundingMode.DOWN double similar = next.getSimilar(); BigDecimal bg = new BigDecimal(similar).setScale(2, RoundingMode.UP); rowData.put("similar", bg.doubleValue()); rowData.put("retrieveKey", rabbitMQVehicle1.getPersonid()); //添加图片路径 rowData.put("picurl", rabbitMQVehicle1.getPicurl()); row.add(rowData); } data = new JSONObject(); if (pvc.size() > 0 && row.size() > 0) { data.put("total", totalPage); data.put("row", row); } } return data; } }