feat: POI录像增加辅助审核得分功能

This commit is contained in:
xiaoyan 2023-05-17 16:01:24 +08:00
parent 8a3ccbd0f5
commit 53ce6e1c2e
8 changed files with 126 additions and 32 deletions

View File

@ -364,6 +364,7 @@ public class HomeActivity extends BaseActivity {
public void accept(Map<String, Boolean> 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()
) {

View File

@ -144,6 +144,7 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
private TextureMapView tvMapView;
private List<Removable> 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<Map<String, Object>> pictureEmitter; // RxJava控制照片生成
private FlowableEmitter<Pair<Integer, PictureResult>> 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<Map<String, Object>> pictureResultFlowable = Flowable.create(new FlowableOnSubscribe<Map<String, Object>>() {
Flowable<Pair<Integer, PictureResult>> pictureResultFlowable = Flowable.create(new FlowableOnSubscribe<Pair<Integer, PictureResult>>() {
@Override
public void subscribe(FlowableEmitter<Map<String, Object>> emitter) throws Exception {
public void subscribe(FlowableEmitter<Pair<Integer, PictureResult>> 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<Map<String, Object>>() {
.doOnNext(new io.reactivex.functions.Consumer<Pair<Integer, PictureResult>>() {
@Override
public void accept(Map<String, Object> map) throws Exception {
public void accept(Pair<Integer, PictureResult> 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<Map<String, Object>>() {
.doOnNext(new io.reactivex.functions.Consumer<Pair<Integer, PictureResult>>() {
@Override
public void accept(Map<String, Object> map) {
public void accept(Pair<Integer, PictureResult> map) {
// 绘制图标
initMarker(booleanExtra);
// 设置主界面拍照个数显示
tvTitle.setText(Integer.parseInt(map.get("index").toString())+"");
tvTitle.setText(Integer.parseInt(map.first.toString())+"");
}
})
.observeOn(Schedulers.computation())// 开始进行图片辅助判定
.subscribe(new FlowableSubscriber<Map<String, Object>>() {
.subscribe(new FlowableSubscriber<Pair<Integer, PictureResult>>() {
@Override
public void onSubscribe(Subscription s) {
s.request(Integer.MAX_VALUE);
}
@Override
public void onNext(Map<String, Object> map) {
pictureCheckHelper.savePictureCheckResult((Activity) PicturesActivity.this, new Gson(), type, map,
checkFile, sensorOritationLifecycle.getYDegree(), currentSpeed, false);
public void onNext(Pair<Integer, PictureResult> 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<String, Object> map = new HashMap();
Pair<Integer, PictureResult> 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<LineString> 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;

View File

@ -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<String, Boolean> 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

View File

@ -723,6 +723,9 @@ public class AreaHubFragment extends BaseDrawerFragment implements View.OnClickL
List<File> fileListByUUID = AWMp4ParserHelper.getInstance().getFileListByUUID(showPoiEntity.getId());
fmPoiVideoPic.setTag(fileListByUUID);
}
// 更新当前POI的置信度
showPoiEntity.setCredible(data.getIntExtra(Constant.INTENT_PICTURES_CREDIBLE, 0));
}
}
}

View File

@ -824,6 +824,9 @@ public class BuildingInFragment extends BaseDrawerFragment implements View.OnCli
List<File> fileListByUUID = AWMp4ParserHelper.getInstance().getFileListByUUID(showPoiEntity.getId());
fmPoiVideoPic.setTag(fileListByUUID);
}
// 更新当前POI的置信度
showPoiEntity.setCredible(data.getIntExtra(Constant.INTENT_PICTURES_CREDIBLE, 0));
}
}
}

View File

@ -727,6 +727,9 @@ public class PoiVideoFragment extends BaseDrawerFragment implements View.OnClick
List<File> fileListByUUID = AWMp4ParserHelper.getInstance().getFileListByUUID(showPoiEntity.getId());
fmPoiVideoPic.setTag(fileListByUUID);
}
// 更新当前POI的置信度
showPoiEntity.setCredible(data.getIntExtra(Constant.INTENT_PICTURES_CREDIBLE, 0));
}
}
}

View File

@ -723,6 +723,9 @@ public class TrafficHubFragment extends BaseDrawerFragment implements View.OnCli
List<File> fileListByUUID = AWMp4ParserHelper.getInstance().getFileListByUUID(showPoiEntity.getId());
fmPoiVideoPic.setTag(fileListByUUID);
}
// 更新当前POI的置信度
showPoiEntity.setCredible(data.getIntExtra(Constant.INTENT_PICTURES_CREDIBLE, 0));
}
}
}

View File

@ -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<String> = 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<String, Any>, checkFile: File/*检查结果的文件*/,
yDegree: Float/*y轴上的旋转角*/, currentSpeed: Double, isAutoTakePicture: Boolean) {
fun savePictureCheckResult(activity: Activity, type: Int/*采集类型*/,
map: android.util.Pair<Int, PictureResult>,
yDegree: Float/*y轴上的旋转角*/, currentSpeed: Double, distance: Double, isAutoTakePicture: Boolean) {
val resultMap: MutableMap<String, String> = 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<TaskNameBean?> {
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
}
}