feat(ocr): 添加喷涂任务OCR识别功能
- 新增BatchUploadResponse、RecognizeByPathRequest、OcrResultData和RecognizeByPathResponse数据类 - 在Service中添加batchUpload接口返回类型修改和recognizeByPath新接口 - 修改SprayingOCRActivity从观察uploadSuccessPath改为观察ocrResult并传递识别结果参数 - 移除SprayingResultActivity中图片解码相关代码和依赖,新增OCR结果显示逻辑 - 修改SprayingOCRVM中上传成功后的处理流程,增加OCR识别步骤和结果处理 - 在MyApplication中新增appComponent3用于OCR服务组件管理
这个提交包含在:
父节点
3dfd8494e9
当前提交
931dd43fe5
@ -22,6 +22,7 @@ public class MyApplication extends App {
|
|||||||
public static AppComponent appComponent1;
|
public static AppComponent appComponent1;
|
||||||
// 喷涂
|
// 喷涂
|
||||||
public static AppComponent appComponent2;
|
public static AppComponent appComponent2;
|
||||||
|
public static AppComponent appComponent3;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
@ -29,9 +30,11 @@ public class MyApplication extends App {
|
|||||||
appComponent = HttpManager.getAppComponent(baseUrl, new HeaderInterceptor(getApplicationContext()));
|
appComponent = HttpManager.getAppComponent(baseUrl, new HeaderInterceptor(getApplicationContext()));
|
||||||
appComponent1 = HttpManager.getAppComponent("https://22v1322u01.vicp.fun", new HeaderInterceptor(getApplicationContext()));
|
appComponent1 = HttpManager.getAppComponent("https://22v1322u01.vicp.fun", new HeaderInterceptor(getApplicationContext()));
|
||||||
appComponent2 = HttpManager.getAppComponent("https://22v1322u01.vicp.fun", new HeaderInterceptor(getApplicationContext()));
|
appComponent2 = HttpManager.getAppComponent("https://22v1322u01.vicp.fun", new HeaderInterceptor(getApplicationContext()));
|
||||||
|
appComponent3 = HttpManager.getAppComponent("https://22v1322u01.vicp.fun", new HeaderInterceptor(getApplicationContext()));
|
||||||
|
|
||||||
// appComponent1 = HttpManager.getAppComponent("http://192.168.6.20:12119", new HeaderInterceptor(getApplicationContext()));
|
// appComponent1 = HttpManager.getAppComponent("http://192.168.6.20:12119", new HeaderInterceptor(getApplicationContext()));
|
||||||
// appComponent2 = HttpManager.getAppComponent("http://192.168.6.156:10085", new HeaderInterceptor(getApplicationContext()));
|
// appComponent2 = HttpManager.getAppComponent("http://192.168.6.156:10085", new HeaderInterceptor(getApplicationContext()));
|
||||||
|
// appComponent3 = HttpManager.getAppComponent("http://192.168.22.125:8820/", new HeaderInterceptor(getApplicationContext()));
|
||||||
|
|
||||||
initSdk();
|
initSdk();
|
||||||
|
|
||||||
|
|||||||
@ -10,3 +10,25 @@ data class SubmitTaskResponse(
|
|||||||
val data: Any? = null
|
val data: Any? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class BatchUploadResponse(
|
||||||
|
val code: Int,
|
||||||
|
val message: String,
|
||||||
|
val data: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
data class RecognizeByPathRequest(
|
||||||
|
val filePath: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class OcrResultData(
|
||||||
|
val judgment: String = "",
|
||||||
|
val one: String = "",
|
||||||
|
val two: String = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
data class RecognizeByPathResponse(
|
||||||
|
val code: Int,
|
||||||
|
val message: String,
|
||||||
|
val data: OcrResultData? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,10 @@ import com.nova.brain.glass.model.data.BackToRequest
|
|||||||
import com.nova.brain.glass.model.data.GetTaskInfoRequest
|
import com.nova.brain.glass.model.data.GetTaskInfoRequest
|
||||||
import com.nova.brain.glass.model.data.GetTaskInfoResponse
|
import com.nova.brain.glass.model.data.GetTaskInfoResponse
|
||||||
import com.nova.brain.glass.model.data.RecognizeData
|
import com.nova.brain.glass.model.data.RecognizeData
|
||||||
|
import com.nova.brain.glass.model.data.BatchUploadResponse
|
||||||
|
import com.nova.brain.glass.model.data.OcrResultData
|
||||||
|
import com.nova.brain.glass.model.data.RecognizeByPathRequest
|
||||||
|
import com.nova.brain.glass.model.data.RecognizeByPathResponse
|
||||||
import com.nova.brain.glass.model.data.SubmitTaskRequest
|
import com.nova.brain.glass.model.data.SubmitTaskRequest
|
||||||
import com.nova.brain.glass.model.data.SubmitTaskResponse
|
import com.nova.brain.glass.model.data.SubmitTaskResponse
|
||||||
import com.nova.brain.glass.model.data.PushToNextData
|
import com.nova.brain.glass.model.data.PushToNextData
|
||||||
@ -70,7 +74,10 @@ interface Service {
|
|||||||
|
|
||||||
@Multipart
|
@Multipart
|
||||||
@POST("/skyscopicsecond-api/api/aiGlasses/batchUpload")
|
@POST("/skyscopicsecond-api/api/aiGlasses/batchUpload")
|
||||||
fun batchUpload(@Part multipartFile: MultipartBody.Part): Observable<ResponseBody>
|
fun batchUpload(@Part multipartFile: MultipartBody.Part): Observable<BatchUploadResponse>
|
||||||
|
|
||||||
|
@POST("/skyscopicsecond-api/api/aiGlasses/recognizeByPath")
|
||||||
|
fun recognizeByPath(@Body body: RecognizeByPathRequest): Observable<RecognizeByPathResponse>
|
||||||
|
|
||||||
@POST("/skyscopicsecond-api/api/aiGlasses/submitTask")
|
@POST("/skyscopicsecond-api/api/aiGlasses/submitTask")
|
||||||
fun submitTask(@Body body: SubmitTaskRequest): Observable<SubmitTaskResponse>
|
fun submitTask(@Body body: SubmitTaskRequest): Observable<SubmitTaskResponse>
|
||||||
|
|||||||
@ -115,12 +115,14 @@ class SprayingOCRActivity :
|
|||||||
message.showMessage()
|
message.showMessage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
viewModel.uploadSuccessPath.observe(this) { path ->
|
viewModel.ocrResult.observe(this) { result ->
|
||||||
if (path.isNullOrBlank()) return@observe
|
if (result == null) return@observe
|
||||||
viewModel.clearUploadSuccessPath()
|
viewModel.clearOcrResult()
|
||||||
startActivity(Intent(this@SprayingOCRActivity, SprayingResultActivity::class.java).apply {
|
startActivity(Intent(this@SprayingOCRActivity, SprayingResultActivity::class.java).apply {
|
||||||
putExtra("path", path)
|
|
||||||
putExtra("taskId", taskId)
|
putExtra("taskId", taskId)
|
||||||
|
putExtra("judgment", result.judgment)
|
||||||
|
putExtra("one", result.one)
|
||||||
|
putExtra("two", result.two)
|
||||||
})
|
})
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,11 +10,9 @@ import android.os.Looper
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.core.view.doOnLayout
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.nova.brain.glass.R
|
import com.nova.brain.glass.R
|
||||||
import com.nova.brain.glass.databinding.ActivitySprayingResultBinding
|
import com.nova.brain.glass.databinding.ActivitySprayingResultBinding
|
||||||
import com.nova.brain.glass.helper.BitmapDecodeHelper
|
|
||||||
import com.nova.brain.glass.helper.GlassMediaServiceHelper
|
import com.nova.brain.glass.helper.GlassMediaServiceHelper
|
||||||
import com.nova.brain.glass.helper.OfflineCmdListener
|
import com.nova.brain.glass.helper.OfflineCmdListener
|
||||||
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
|
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
|
||||||
@ -31,7 +29,6 @@ import com.xuqm.base.common.LogHelper
|
|||||||
import com.xuqm.base.extensions.showMessage
|
import com.xuqm.base.extensions.showMessage
|
||||||
import com.xuqm.base.ui.BaseListFormLayoutNormalActivity
|
import com.xuqm.base.ui.BaseListFormLayoutNormalActivity
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.Executors
|
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
class SprayingResultActivity :
|
class SprayingResultActivity :
|
||||||
@ -45,7 +42,8 @@ class SprayingResultActivity :
|
|||||||
.orEmpty()
|
.orEmpty()
|
||||||
.ifBlank { "1493291302287048704" }
|
.ifBlank { "1493291302287048704" }
|
||||||
}
|
}
|
||||||
private val imageDecodeExecutor = Executors.newSingleThreadExecutor()
|
private var ocrOne: String = ""
|
||||||
|
private var ocrTwo: String = ""
|
||||||
private var status = true
|
private var status = true
|
||||||
private var successDialog: AlertDialog? = null
|
private var successDialog: AlertDialog? = null
|
||||||
private val uiHandler = Handler(Looper.getMainLooper())
|
private val uiHandler = Handler(Looper.getMainLooper())
|
||||||
@ -191,15 +189,19 @@ class SprayingResultActivity :
|
|||||||
message.showMessage()
|
message.showMessage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
intent.getStringExtra("path")?.apply {
|
val judgment = intent.getStringExtra("judgment").orEmpty()
|
||||||
showResultImage(this)
|
ocrOne = intent.getStringExtra("one").orEmpty()
|
||||||
|
ocrTwo = intent.getStringExtra("two").orEmpty()
|
||||||
|
status = judgment != "不合格"
|
||||||
setStatusImage()
|
setStatusImage()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun setStatusImage() {
|
fun setStatusImage() {
|
||||||
binding.tvTaskHeader.text = if (status) "OCR识别结果:合格" else "OCR识别结果:不合格"
|
binding.tvTaskHeader.text = if (status) "OCR识别结果:合格" else "OCR识别结果:不合格"
|
||||||
binding.status.setImageResource(if (status) R.mipmap.ocr_true else R.mipmap.ocr_false)
|
binding.status.setImageResource(if (status) R.mipmap.ocr_true else R.mipmap.ocr_false)
|
||||||
|
binding.value1.text = "识码一:$ocrOne"
|
||||||
|
binding.value2.text = "识码二:$ocrTwo"
|
||||||
|
binding.value3.text = if (status) "两码一致,符合要求!" else "两码不一致,不符合要求!"
|
||||||
if (status) {
|
if (status) {
|
||||||
binding.value1.paintFlags =
|
binding.value1.paintFlags =
|
||||||
binding.value1.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
|
binding.value1.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
|
||||||
@ -272,21 +274,7 @@ class SprayingResultActivity :
|
|||||||
|
|
||||||
override fun adapter(): BasePagedAdapter<ItemItem> = adapter
|
override fun adapter(): BasePagedAdapter<ItemItem> = adapter
|
||||||
|
|
||||||
private fun showResultImage(path: String) {
|
|
||||||
binding.iv.doOnLayout {
|
|
||||||
val targetWidth = it.width.coerceAtLeast(1)
|
|
||||||
val targetHeight = it.height.coerceAtLeast(1)
|
|
||||||
imageDecodeExecutor.execute {
|
|
||||||
val bitmap = BitmapDecodeHelper.decodeSampledBitmap(path, targetWidth, targetHeight)
|
|
||||||
runOnUiThread {
|
|
||||||
if (isFinishing || isDestroyed) {
|
|
||||||
return@runOnUiThread
|
|
||||||
}
|
|
||||||
binding.iv.setImageBitmap(bitmap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showSuccessDialogThenBackToTaskList() {
|
private fun showSuccessDialogThenBackToTaskList() {
|
||||||
successDialog?.dismiss()
|
successDialog?.dismiss()
|
||||||
|
|||||||
@ -3,6 +3,8 @@ package com.nova.brain.glass.viewmodel
|
|||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import com.nova.brain.glass.MyApplication
|
import com.nova.brain.glass.MyApplication
|
||||||
import com.nova.brain.glass.model.ItemItem
|
import com.nova.brain.glass.model.ItemItem
|
||||||
|
import com.nova.brain.glass.model.data.OcrResultData
|
||||||
|
import com.nova.brain.glass.model.data.RecognizeByPathRequest
|
||||||
import com.nova.brain.glass.repository.Service
|
import com.nova.brain.glass.repository.Service
|
||||||
import com.xuqm.base.di.manager.HttpManager
|
import com.xuqm.base.di.manager.HttpManager
|
||||||
import com.xuqm.base.viewmodel.BaseListViewModel
|
import com.xuqm.base.viewmodel.BaseListViewModel
|
||||||
@ -22,10 +24,10 @@ enum class UploadState {
|
|||||||
FAILED
|
FAILED
|
||||||
}
|
}
|
||||||
|
|
||||||
class SprayingOCRVM: BaseListViewModel<ItemItem>() {
|
class SprayingOCRVM : BaseListViewModel<ItemItem>() {
|
||||||
val uploadState = MutableLiveData(UploadState.IDLE)
|
val uploadState = MutableLiveData(UploadState.IDLE)
|
||||||
val uploadError = MutableLiveData<String>()
|
val uploadError = MutableLiveData<String>()
|
||||||
val uploadSuccessPath = MutableLiveData<String?>()
|
val ocrResult = MutableLiveData<OcrResultData?>()
|
||||||
private var uploadingPath: String? = null
|
private var uploadingPath: String? = null
|
||||||
private var uploadDisposable: Disposable? = null
|
private var uploadDisposable: Disposable? = null
|
||||||
|
|
||||||
@ -55,10 +57,15 @@ class SprayingOCRVM: BaseListViewModel<ItemItem>() {
|
|||||||
.batchUpload(multipartFile)
|
.batchUpload(multipartFile)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe({
|
.subscribe({ response ->
|
||||||
if (uploadingPath != path) return@subscribe
|
if (uploadingPath != path) return@subscribe
|
||||||
uploadState.value = UploadState.SUCCESS
|
if (response.code == 200 && !response.data.isNullOrBlank()) {
|
||||||
uploadSuccessPath.value = path
|
uploadState.value = UploadState.IDLE
|
||||||
|
startRecognize(path, response.data)
|
||||||
|
} else {
|
||||||
|
uploadState.value = UploadState.FAILED
|
||||||
|
uploadError.value = if (response.message.isBlank()) "附件上传失败" else response.message
|
||||||
|
}
|
||||||
}, { e ->
|
}, { e ->
|
||||||
if (uploadingPath != path) return@subscribe
|
if (uploadingPath != path) return@subscribe
|
||||||
uploadState.value = UploadState.FAILED
|
uploadState.value = UploadState.FAILED
|
||||||
@ -68,6 +75,28 @@ class SprayingOCRVM: BaseListViewModel<ItemItem>() {
|
|||||||
add(disposable)
|
add(disposable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun startRecognize(localPath: String, serverPath: String) {
|
||||||
|
val disposable = HttpManager.getApi(MyApplication.appComponent2, Service::class.java)
|
||||||
|
.recognizeByPath(RecognizeByPathRequest(filePath = serverPath))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({ response ->
|
||||||
|
if (uploadingPath != localPath) return@subscribe
|
||||||
|
if (response.code == 200) {
|
||||||
|
uploadState.value = UploadState.SUCCESS
|
||||||
|
ocrResult.value = response.data ?: OcrResultData()
|
||||||
|
} else {
|
||||||
|
uploadState.value = UploadState.FAILED
|
||||||
|
uploadError.value = if (response.message.isBlank()) "OCR识别失败" else response.message
|
||||||
|
}
|
||||||
|
}, { e ->
|
||||||
|
if (uploadingPath != localPath) return@subscribe
|
||||||
|
uploadState.value = UploadState.FAILED
|
||||||
|
uploadError.value = e.message ?: "OCR识别失败"
|
||||||
|
})
|
||||||
|
add(disposable)
|
||||||
|
}
|
||||||
|
|
||||||
fun cancelUpload() {
|
fun cancelUpload() {
|
||||||
uploadingPath = null
|
uploadingPath = null
|
||||||
uploadDisposable?.dispose()
|
uploadDisposable?.dispose()
|
||||||
@ -77,7 +106,7 @@ class SprayingOCRVM: BaseListViewModel<ItemItem>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearUploadSuccessPath() {
|
fun clearOcrResult() {
|
||||||
uploadSuccessPath.value = null
|
ocrResult.value = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
正在加载...
在新工单中引用
屏蔽一个用户