From 53ce6e1c2ed95e289953bc8051fa2c31715ee9f4 Mon Sep 17 00:00:00 2001 From: xiaoyan Date: Wed, 17 May 2023 16:01:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20POI=E5=BD=95=E5=83=8F=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=BE=85=E5=8A=A9=E5=AE=A1=E6=A0=B8=E5=BE=97=E5=88=86=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outdoor/activity/HomeActivity.java | 1 + .../outdoor/activity/PicturesActivity.java | 46 ++++----- .../com/navinfo/outdoor/api/Constant.java | 3 + .../outdoor/fragment/AreaHubFragment.java | 3 + .../outdoor/fragment/BuildingInFragment.java | 3 + .../outdoor/fragment/PoiVideoFragment.java | 3 + .../outdoor/fragment/TrafficHubFragment.java | 3 + .../outdoor/util/PictureCheckHelper.kt | 96 +++++++++++++++++-- 8 files changed, 126 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/com/navinfo/outdoor/activity/HomeActivity.java b/app/src/main/java/com/navinfo/outdoor/activity/HomeActivity.java index 7d1fefc..a715fe2 100644 --- a/app/src/main/java/com/navinfo/outdoor/activity/HomeActivity.java +++ b/app/src/main/java/com/navinfo/outdoor/activity/HomeActivity.java @@ -364,6 +364,7 @@ public class HomeActivity extends BaseActivity { public void accept(Map stringBooleanMap) throws Exception { Log.d("HomeActivity", "checkMockLocation结果:"+stringBooleanMap.isEmpty()); if (!stringBooleanMap.isEmpty()) { + Constant.mockGPSMap = stringBooleanMap; StringBuilder stringBuilder = new StringBuilder("检查到疑似存在以下违规行为:\n"); for (String key: stringBooleanMap.keySet() ) { diff --git a/app/src/main/java/com/navinfo/outdoor/activity/PicturesActivity.java b/app/src/main/java/com/navinfo/outdoor/activity/PicturesActivity.java index 5c594e9..4648e32 100644 --- a/app/src/main/java/com/navinfo/outdoor/activity/PicturesActivity.java +++ b/app/src/main/java/com/navinfo/outdoor/activity/PicturesActivity.java @@ -144,6 +144,7 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen private TextureMapView tvMapView; private List removables, trackRemovableList; private Polyline polyline; + private Geometry taskGeometry; // 当前任务的geometry private String finalVideoPath, geoWkt, detail; // 摄像后最终保存的文件名 private int matchTrack; // 是否通过轨迹匹配照片 private ViewGroup layerChange; // 切换地图和相机的父控件 @@ -155,7 +156,7 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen // private Timer timer; // private TimerTask timerTask; private Disposable disposable; // RxJava循环拍照的控制对象 - private FlowableEmitter> pictureEmitter; // RxJava控制照片生成 + private FlowableEmitter> pictureEmitter; // RxJava控制照片生成 private SystemTTS systemTTS; private StringBuilder picturesBuilder; private LatLng startLatLine, endLatLine; @@ -226,7 +227,7 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen } }); speedCheck = new PicturesSpeedCheck(); - pictureCheckHelper = new PictureCheckHelper(PicturesActivity.this); + pictureCheckHelper = new PictureCheckHelper(PicturesActivity.this, checkFile); gson = new Gson(); recorderDao = PoiDatabase.getInstance(PicturesActivity.this).getRecorderDao(); } @@ -418,9 +419,9 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen } }); - Flowable> pictureResultFlowable = Flowable.create(new FlowableOnSubscribe>() { + Flowable> pictureResultFlowable = Flowable.create(new FlowableOnSubscribe>() { @Override - public void subscribe(FlowableEmitter> emitter) throws Exception { + public void subscribe(FlowableEmitter> emitter) throws Exception { pictureEmitter = emitter; } }, BackpressureStrategy.BUFFER).subscribeOn(Schedulers.io()); @@ -438,12 +439,12 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen pictureResultFlowable.subscribeOn(Schedulers.io()) // 指定上游为IO线程 .observeOn(Schedulers.io()) - .doOnNext(new io.reactivex.functions.Consumer>() { + .doOnNext(new io.reactivex.functions.Consumer>() { @Override - public void accept(Map map) throws Exception { + public void accept(Pair map) throws Exception { - int fileIndex = (int) map.get("index"); - PictureResult pictureResult = (PictureResult) map.get("picture"); + int fileIndex = map.first; + PictureResult pictureResult = map.second; // 图片和paper.txt处理 File currentFile = new File(paperFile.getParentFile().getAbsolutePath() + "/" + fileIndex + ".webp"); CameraUtils.writeToFile(pictureResult.getData(), currentFile); // 生成照片文件 @@ -466,30 +467,30 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen } }) .observeOn(AndroidSchedulers.mainThread()) - .doOnNext(new io.reactivex.functions.Consumer>() { + .doOnNext(new io.reactivex.functions.Consumer>() { @Override - public void accept(Map map) { + public void accept(Pair map) { // 绘制图标 initMarker(booleanExtra); // 设置主界面拍照个数显示 - tvTitle.setText(Integer.parseInt(map.get("index").toString())+""); + tvTitle.setText(Integer.parseInt(map.first.toString())+""); } }) .observeOn(Schedulers.computation())// 开始进行图片辅助判定 - .subscribe(new FlowableSubscriber>() { + .subscribe(new FlowableSubscriber>() { @Override public void onSubscribe(Subscription s) { s.request(Integer.MAX_VALUE); } @Override - public void onNext(Map map) { - pictureCheckHelper.savePictureCheckResult((Activity) PicturesActivity.this, new Gson(), type, map, - checkFile, sensorOritationLifecycle.getYDegree(), currentSpeed, false); + public void onNext(Pair map) { + pictureCheckHelper.savePictureCheckResult((Activity) PicturesActivity.this, type, map, + sensorOritationLifecycle.getYDegree(), currentSpeed, 100/*当前位置和任务的距离*/,false); // 记录当前完成多少个图片的处理 - int index = Integer.parseInt(map.get("index").toString()); + int index = Integer.parseInt(map.first.toString()); dealPictureIndex = index; } @@ -537,10 +538,8 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen } if (pictureEmitter!=null) { - Map map = new HashMap(); + Pair map = new Pair(videoIndex++, result); emitterPictureIndex = videoIndex; - map.put("index", videoIndex++); - map.put("picture", result); pictureEmitter.onNext(map); } } else { @@ -679,14 +678,14 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen if (geoWkt != null) { List lineStringList = new ArrayList<>(); String geo = Geohash.getInstance().decode(geoWkt); - Geometry geometry = GeometryTools.createGeometry(geo); - if ("MultiLineString".equals(geometry.getGeometryType())) { - MultiLineString multiLineString = (MultiLineString) geometry; + taskGeometry = GeometryTools.createGeometry(geo); + if ("MultiLineString".equals(taskGeometry.getGeometryType())) { + MultiLineString multiLineString = (MultiLineString) taskGeometry; for (int i = 0; i < multiLineString.getNumGeometries(); i++) { lineStringList.add((LineString) multiLineString.getGeometryN(i)); } } else { - lineStringList.add((LineString) geometry); + lineStringList.add((LineString) taskGeometry); } BitmapDescriptor bitmapLine = null; if (type != 0) { @@ -1452,6 +1451,7 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen Intent intent = new Intent(); finalVideoPath = Objects.requireNonNull(paperFile.getParentFile()).getAbsolutePath() + "/" + (videoIndex-1) + ".webp"; intent.putExtra(Constant.INTENT_PICTURES_PATH, finalVideoPath); + intent.putExtra(Constant.INTENT_PICTURES_CREDIBLE, pictureCheckHelper.getCheckResultScore()); setResult(0x111, intent); PicturesActivity.this.finish(); handler = null; diff --git a/app/src/main/java/com/navinfo/outdoor/api/Constant.java b/app/src/main/java/com/navinfo/outdoor/api/Constant.java index e9e3656..2c0c487 100644 --- a/app/src/main/java/com/navinfo/outdoor/api/Constant.java +++ b/app/src/main/java/com/navinfo/outdoor/api/Constant.java @@ -14,6 +14,7 @@ import com.umeng.umcrash.UMCrash; import java.io.File; import java.util.HashSet; +import java.util.Map; import java.util.Set; /** @@ -43,6 +44,7 @@ public class Constant { public static String LOG_FOLDER = ROOT_FOLDER + "/log"; public static String GPS_LOG_FOLDER = ROOT_FOLDER + "/gps_log"; public static int TelLength = 0; + public static Map mockGPSMap; // 是否模拟定位,如果模拟定位,该map不为空 public static void initRootFolder(String userId) { BASE_FOLDER = ROOT_FOLDER + "/" + userId; @@ -173,6 +175,7 @@ public class Constant { public static final String INTENT_JPG_PATH = "INTENT_JPG_PATH"; // 拍照界面指定的图片保存位置 public static final String INTENT_PHOTO_PATH = "INTENT_PHOTO_PATH"; // 拍照界面指定的图片保存位置 public static final String INTENT_PICTURES_PATH = "INTENT_VIDEO_PATH"; // 拍照界面指定的视频文件保存位置 + public static final String INTENT_PICTURES_CREDIBLE = "INTENT_PICTURES_CREDIBLE"; // 拍照界面获得的照片置信度 public static final String INTENT_VIDEO_OBLATION = "INTENT_VIDEO_OBLATION"; // 视频拍摄时屏幕方向 0-强制横屏 其他-任意 public static final String INTENT_TYPE = "type";//poiEntity 的type public static final String INTENT_GEO_WKT = "geowkt";//poiEntity 的geowkt diff --git a/app/src/main/java/com/navinfo/outdoor/fragment/AreaHubFragment.java b/app/src/main/java/com/navinfo/outdoor/fragment/AreaHubFragment.java index dcd934a..ab27dd9 100644 --- a/app/src/main/java/com/navinfo/outdoor/fragment/AreaHubFragment.java +++ b/app/src/main/java/com/navinfo/outdoor/fragment/AreaHubFragment.java @@ -723,6 +723,9 @@ public class AreaHubFragment extends BaseDrawerFragment implements View.OnClickL List fileListByUUID = AWMp4ParserHelper.getInstance().getFileListByUUID(showPoiEntity.getId()); fmPoiVideoPic.setTag(fileListByUUID); } + + // 更新当前POI的置信度 + showPoiEntity.setCredible(data.getIntExtra(Constant.INTENT_PICTURES_CREDIBLE, 0)); } } } diff --git a/app/src/main/java/com/navinfo/outdoor/fragment/BuildingInFragment.java b/app/src/main/java/com/navinfo/outdoor/fragment/BuildingInFragment.java index 94a1bec..35a6f5b 100644 --- a/app/src/main/java/com/navinfo/outdoor/fragment/BuildingInFragment.java +++ b/app/src/main/java/com/navinfo/outdoor/fragment/BuildingInFragment.java @@ -824,6 +824,9 @@ public class BuildingInFragment extends BaseDrawerFragment implements View.OnCli List fileListByUUID = AWMp4ParserHelper.getInstance().getFileListByUUID(showPoiEntity.getId()); fmPoiVideoPic.setTag(fileListByUUID); } + + // 更新当前POI的置信度 + showPoiEntity.setCredible(data.getIntExtra(Constant.INTENT_PICTURES_CREDIBLE, 0)); } } } diff --git a/app/src/main/java/com/navinfo/outdoor/fragment/PoiVideoFragment.java b/app/src/main/java/com/navinfo/outdoor/fragment/PoiVideoFragment.java index cb282fa..230eff0 100644 --- a/app/src/main/java/com/navinfo/outdoor/fragment/PoiVideoFragment.java +++ b/app/src/main/java/com/navinfo/outdoor/fragment/PoiVideoFragment.java @@ -727,6 +727,9 @@ public class PoiVideoFragment extends BaseDrawerFragment implements View.OnClick List fileListByUUID = AWMp4ParserHelper.getInstance().getFileListByUUID(showPoiEntity.getId()); fmPoiVideoPic.setTag(fileListByUUID); } + + // 更新当前POI的置信度 + showPoiEntity.setCredible(data.getIntExtra(Constant.INTENT_PICTURES_CREDIBLE, 0)); } } } diff --git a/app/src/main/java/com/navinfo/outdoor/fragment/TrafficHubFragment.java b/app/src/main/java/com/navinfo/outdoor/fragment/TrafficHubFragment.java index dec6f7b..6839fc0 100644 --- a/app/src/main/java/com/navinfo/outdoor/fragment/TrafficHubFragment.java +++ b/app/src/main/java/com/navinfo/outdoor/fragment/TrafficHubFragment.java @@ -723,6 +723,9 @@ public class TrafficHubFragment extends BaseDrawerFragment implements View.OnCli List fileListByUUID = AWMp4ParserHelper.getInstance().getFileListByUUID(showPoiEntity.getId()); fmPoiVideoPic.setTag(fileListByUUID); } + + // 更新当前POI的置信度 + showPoiEntity.setCredible(data.getIntExtra(Constant.INTENT_PICTURES_CREDIBLE, 0)); } } } diff --git a/app/src/main/java/com/navinfo/outdoor/util/PictureCheckHelper.kt b/app/src/main/java/com/navinfo/outdoor/util/PictureCheckHelper.kt index 609615f..a365443 100644 --- a/app/src/main/java/com/navinfo/outdoor/util/PictureCheckHelper.kt +++ b/app/src/main/java/com/navinfo/outdoor/util/PictureCheckHelper.kt @@ -20,15 +20,24 @@ import java.io.File /** * 照片辅助检查工具类 * */ -class PictureCheckHelper(val context: Context) { - val checkResult = CheckResult() +class PictureCheckHelper(val context: Context, val checkFile: File) { + var checkResult = CheckResult() + val gson = Gson() private val sensorDegree by lazy { PreferencesUtils.getString(context, "sensorDegree", "45").toInt()} private val poiMinSpeed by lazy { PreferencesUtils.getString(context, "poiMinSpeed", "5").toDouble() } private val poiMaxSpeed by lazy { PreferencesUtils.getString(context, "poiMaxSpeed", "30").toDouble() } private val roadMinSpeed by lazy { PreferencesUtils.getString(context, "roadMinSpeed", "20").toDouble() } private val roadMaxSpeed by lazy { PreferencesUtils.getString(context, "roadMaxSpeed", "120").toDouble() } private val satelliteCount by lazy { PreferencesUtils.getString(context, "satelliteCount", "15").toInt() } + private val nameSet: MutableSet = mutableSetOf() + init { + // 初始化时读取已有文件,如果存在按照文件内容初始化数据 + if (checkFile!=null&&checkFile.exists()) { + val checkResultStr = FileUtils.readFileContent(checkFile.absolutePath) + checkResult = gson.fromJson(checkResultStr, CheckResult::class.java) + } + } fun addocrCheck(result: Boolean) { if (result) checkResult.ocrChecked++ @@ -69,7 +78,13 @@ class PictureCheckHelper(val context: Context) { fun addGpsRssiCheck(result: Int) { checkResult.gpsRssiChecked=checkResult.gpsRssiChecked+result - checkResult.gpsRssiCount=checkResult.gpsRssiCount+4 + checkResult.gpsRssiCount=checkResult.gpsRssiCount++ + } + + + fun addDistanceCheck(result: Boolean) { + if (result) checkResult.distanceChecked++ + checkResult.distanceCount++ } inner class CheckResult { @@ -102,13 +117,17 @@ class PictureCheckHelper(val context: Context) { // 信号强度检查 var gpsRssiChecked = 0 var gpsRssiCount = 0 + + // 距离检查 + var distanceChecked = 0 + var distanceCount = 0 } - fun savePictureCheckResult(activity: Activity, gson: Gson, type: Int/*采集类型*/, - map: Map, checkFile: File/*检查结果的文件*/, - yDegree: Float/*y轴上的旋转角*/, currentSpeed: Double, isAutoTakePicture: Boolean) { + fun savePictureCheckResult(activity: Activity, type: Int/*采集类型*/, + map: android.util.Pair, + yDegree: Float/*y轴上的旋转角*/, currentSpeed: Double, distance: Double, isAutoTakePicture: Boolean) { val resultMap: MutableMap = mutableMapOf() - val pictureResult = map["picture"] as PictureResult? + val pictureResult = map.second // 如果当前拍照是POI拍照模式,才需要做ocr识别以及附近POI查询 // 如果当前拍照是POI拍照模式,才需要做ocr识别以及附近POI查询 if (type == 3) { @@ -138,7 +157,7 @@ class PictureCheckHelper(val context: Context) { .get() resultMap["name"] = maxOcrViewResult.name // 周边搜索,判定周边POI是否存在 - if (this.checkResult.nearestChecked < 3) { + if (this.checkResult.nearestChecked < 3 && !nameSet.contains(maxOcrViewResult.name)) { // 发送请求,查询周边POI是否存在 val name = maxOcrViewResult.name val httpParams = HttpParams() @@ -157,7 +176,7 @@ class PictureCheckHelper(val context: Context) { .token(Constant.ACCESS_TOKEN) okGoBuilder.getRequest(object : Callback { override fun onSuccess(taskNameBean: TaskNameBean?, id: Int) { - if (taskNameBean!!.code == 200) { + if (taskNameBean!!.code == 200&&taskNameBean.body!=null) { // body中保存了当前名称是否在周边存在对应的POI this@PictureCheckHelper.addNearestCheck(true) XLog.d("nearest: ${name}, taskBean: ${gson.toJson(taskNameBean)}") } else { @@ -180,6 +199,8 @@ class PictureCheckHelper(val context: Context) { } }) } + // 将当前名称添加到name缓存中 + nameSet.add(maxOcrViewResult.name) } else { this@PictureCheckHelper.addocrCheck(false) resultMap["ocr"] = "false" @@ -225,6 +246,15 @@ class PictureCheckHelper(val context: Context) { // 记录卫星强度 resultMap["gpsRssi"] = LocationLifeCycle.getInstance().tencentLocation.gpsRssi.toString() + "" this@PictureCheckHelper.addGpsRssiCheck(LocationLifeCycle.getInstance().tencentLocation.gpsRssi) + + // 记录距离检查 + resultMap["distance"] = distance.toString() + if (distance<50) { + this@PictureCheckHelper.addDistanceCheck(true) + } else { + this@PictureCheckHelper.addDistanceCheck(false) + } + // 记录json文件到指定文件 FileUtils.writeFile( checkFile.absolutePath, @@ -237,4 +267,52 @@ class PictureCheckHelper(val context: Context) { true ) } + + /** + * 获取当前测评结果 + * */ + fun getCheckResultScore(): Int { + var score = 0 + if (checkResult!=null) { + // 是否有模拟定位 + if (Constant.mockGPSMap!=null&&Constant.mockGPSMap.isNotEmpty()) { + score -= 100 + } + //任务线与定位点匹配 + if (checkResult.distanceCount!=0&&checkResult.distanceChecked.toFloat()/checkResult.distanceCount>0.5f) { + score += 20 + } + //TODO 使用自动捕捉 + //作业速度 + if (checkResult.speedCount!=0&&checkResult.speedChecked.toFloat()/checkResult.speedCount>0.7f) { + score += 20 + } + // 拍照姿态 + if (checkResult.angleCount!=0&&checkResult.angleChecked.toFloat()/checkResult.angleCount>0.7f) { + score += 10 + } + // 照片清晰度 + if (checkResult.ocrChecked>5) { + score += 30 + } + // 信号强度 + if (checkResult.gpsRssiCount!=0) { + val rssiCheckResult = checkResult.gpsRssiChecked.toFloat()/checkResult.gpsRssiCount + if (rssiCheckResult >= 0f&&rssiCheckResult<0.2f) { + // 无信号 + score -= 100 + } else if (rssiCheckResult>=0.2f&&rssiCheckResult<1.2f) { + score -= 20 + } else if (rssiCheckResult>=1.2f&&rssiCheckResult<2.2f) { + score -= 0 + }else { + score += 20 + } + } + if (checkResult.nearestChecked>=3) { + score += 30 + } + } + return score + } } \ No newline at end of file