采集向量优化调试

This commit is contained in:
2026-01-08 15:02:44 +08:00
parent 378e6088e7
commit 2a55ddb617
35 changed files with 663 additions and 1112 deletions
@@ -1,134 +0,0 @@
//package com.sw.dualscreen.activity
//
//import android.annotation.SuppressLint
//import androidx.activity.viewModels
//import androidx.core.widget.addTextChangedListener
//import androidx.recyclerview.widget.LinearLayoutManager
//import com.sw.dualscreen.R
//import com.sw.dualscreen.adapter.CollectedFoodAdapter
//import com.sw.dualscreen.databinding.ActivityCollectedDataBinding
//import com.sw.dualscreen.databinding.LayoutEmptySearchBinding
//import com.sw.dualscreen.dialog.WarnDialog
//import com.sw.dualscreen.ext.addOnActionSearchListener
//import com.sw.dualscreen.ext.hideKeyboard
//import com.sw.dualscreen.objbox.CollectedFoodInfo
//import com.sw.dualscreen.objbox.Food
//import com.sw.dualscreen.objbox.ObjectBox
//import com.sw.dualscreen.viewmodel.BaseViewModel
//import com.sw.dualscreen.viewmodel.UserViewModel
//import com.sw.plate.utils.ToastUtils
//import io.objectbox.Box
//import io.objectbox.kotlin.boxFor
//import kotlin.getValue
//
//class CollectedDataActivity : BaseActivity<ActivityCollectedDataBinding>() {
// private val viewModel by viewModels<UserViewModel>()
// override fun getViewModel(): BaseViewModel {
// return viewModel
// }
//
// override fun inflateViewBinding(): ActivityCollectedDataBinding {
// return ActivityCollectedDataBinding.inflate(layoutInflater)
// }
//
// private val list: MutableList<CollectedFoodInfo> = mutableListOf()
// private val adapter by lazy {
// CollectedFoodAdapter(list).apply {
// isStateViewEnable = true
// addOnItemChildClickListener(R.id.ivDeleteFood) { _, _, position ->
// deleteGoods(position)
// }
// }
// }
//
// override fun initialize() {
// super.initialize()
// binding.rvFoodList.let {
// it.layoutManager = LinearLayoutManager(this)
// it.adapter = adapter
// }
// binding.ivBack.setOnClickListener { finish() }
// binding.ivGoodsSearch.setOnClickListener {
// val searchName = binding.etInputGoods.text.toString().trim()
// if (searchName.isBlank()) {
// ToastUtils.showToast("请输入物品名称")
// return@setOnClickListener
// }
// getCollectGoods(searchName)
// }
// binding.etInputGoods.let { v ->
// v.addOnActionSearchListener {
// val searchName = binding.etInputGoods.text.toString().trim()
// if (searchName.isBlank()) {
// ToastUtils.showToast("请输入物品名称")
// return@addOnActionSearchListener
// }
// getCollectGoods(searchName)
// }
// v.addTextChangedListener {
// if (it.isNullOrBlank()) {
// getCollectGoods()
// }
// }
// }
// getCollectGoods()
// }
//
//
// private var box: Box<Food>? = null
//
// @SuppressLint("NotifyDataSetChanged")
// private fun getCollectGoods(searchName:String?=null) {
// if (box == null) {
// box = ObjectBox.boxStore.boxFor(Food::class)
// }
// list.clear()
// var queryList = box?.all?.distinctBy { it.name }
// if (searchName.isNullOrBlank().not()) {
// queryList = queryList?.filter { it.name?.contains(searchName) == true }
// }
// queryList?.forEach {
// list.add(CollectedFoodInfo(foodName = it.name))
// }
// adapter.notifyDataSetChanged()
// if (list.isEmpty()) {
// loadEmptyView()
// }
// binding.root.hideKeyboard()
// }
//
// private var emptyBinding: LayoutEmptySearchBinding? = null
// private fun loadEmptyView() {
// if (emptyBinding == null) {
// emptyBinding = LayoutEmptySearchBinding.inflate(layoutInflater, binding.rvFoodList, false)
// }
// emptyBinding?.root?.let { layout ->
// layout.setOnClickListener { layout.hideKeyboard() }
// adapter.stateView = layout
// }
// }
//
// private fun deleteGoods(position: Int) {
// WarnDialog(
// context = context,
// content = "请确认是否删除菜品:${list[position].foodName}",
// confirmBlock = {
// Thread {
// runOnUiThread {
// showWaitingDialog("加载中……")
// }
// val name = list[position].foodName
// val filterIdList = box?.all?.filter { it.name == name }?.map { it.id }
// box?.removeByIds(filterIdList)
// runOnUiThread {
// hideWaitingDialog()
// adapter.removeAt(position)
// ToastUtils.showToast("删除成功")
// if (list.isEmpty()) {
// loadEmptyView()
// }
// }
// }.start()
// }).show()
// }
//}
@@ -8,17 +8,21 @@ import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.R
import com.sw.dualscreen.adapter.CollectedFoodNewAdapter
import com.sw.dualscreen.databinding.ActivityCollectedFoodBinding
import com.sw.dualscreen.dialog.WarnDialog
import com.sw.dualscreen.dialog.RemindDialog
import com.sw.dualscreen.ext.addOnActionSearchListener
import com.sw.dualscreen.ext.gone
import com.sw.dualscreen.ext.hideKeyboard
import com.sw.dualscreen.ext.visible
import com.sw.dualscreen.model.response.ResetBoxEvent
import com.sw.dualscreen.objbox.CollectedFoodInfo
import com.sw.dualscreen.objbox.Food
import com.sw.dualscreen.objbox.ObjectBox
import com.sw.dualscreen.viewmodel.BaseViewModel
import com.sw.dualscreen.viewmodel.UserViewModel
import com.sw.plate.utils.ToastUtils
import io.objectbox.Box
import io.objectbox.kotlin.boxFor
import org.greenrobot.eventbus.EventBus
class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
@@ -47,6 +51,7 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
override fun initialize() {
super.initialize()
box = ObjectBox.boxStore.boxFor(Food::class)
//binding.root.setOnClickListener { it.hideKeyboard() }
binding.rvFoodList.let {
it.layoutManager = LinearLayoutManager(this)
@@ -99,7 +104,7 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
}
private var box: Box<Food>? = null
private lateinit var box: Box<Food>
@SuppressLint("NotifyDataSetChanged")
private fun getCollectGoods(searchName: String? = null) {
@@ -181,7 +186,7 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
}
private fun loadDeleteDialog(position: Int) {
WarnDialog(
RemindDialog(
context = context,
content = "请确认是否删除菜品:${list[position].foodName}",
confirmBlock = {
@@ -195,8 +200,16 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
viewModel.deleteCollectFood(food.foodId, GlobalData.foodModelVersion) { deleteSuccess ->
if (deleteSuccess) {
Thread {
val filterIdList = box?.all?.filter { it.foodName == food.foodName }?.map { it.id }
box?.removeByIds(filterIdList)
val filterFoodList = box.all.filter { it.foodName == food.foodName }
filterFoodList.forEach { it.isDel = true }
box.put(filterFoodList)
// val filterIdList = filterFoodList.map { it.id }
////// ObjectBox.boxStore.runInTx {
//// box.removeByIds(filterIdList)
////// EventBus.getDefault().post(ResetBoxEvent())
////// }
runOnUiThread {
hideWaitingDialog()
adapter.removeAt(position)
@@ -1,370 +0,0 @@
//package com.sw.dualscreen.activity
//
//import android.annotation.SuppressLint
//import android.content.Context
//import android.content.Intent
//import android.graphics.Bitmap
//import android.graphics.Typeface
//import android.net.Uri
//import android.view.View
//import android.view.inputmethod.EditorInfo
//import android.view.inputmethod.InputMethodManager
//import android.widget.Toast
//import androidx.activity.viewModels
//import androidx.camera.view.PreviewView
//import androidx.core.net.toUri
//import androidx.core.view.updateLayoutParams
//import androidx.lifecycle.lifecycleScope
//import androidx.recyclerview.widget.GridLayoutManager
//import com.example.utils.FloatBase64Utils
//import com.sw.dualscreen.R
//import com.sw.dualscreen.adapter.FoodCollectionAdapter
//import com.sw.dualscreen.adapter.GenericItemAdapter
//import com.sw.dualscreen.adapter.GridSpacingItemDecoration
//import com.sw.dualscreen.adapter.dpToPx
//import com.sw.dualscreen.databinding.ActivityFoodCollectionBinding
//import com.sw.dualscreen.databinding.ItemSearchFoodInfoBinding
//import com.sw.dualscreen.databinding.LayoutCameraPreviewBinding
//import com.sw.dualscreen.ext.clickWithDebounce
//import com.sw.dualscreen.ext.dp
//import com.sw.dualscreen.model.response.FoodInfo
//import com.sw.dualscreen.objbox.Food
//import com.sw.dualscreen.objbox.FoodCollectionBean
//import com.sw.dualscreen.objbox.FoodModule
//import com.sw.dualscreen.objbox.ObjectBox
//import com.sw.dualscreen.utils.BitmapCropper
//import com.sw.dualscreen.utils.BitmapSaver
//import com.sw.dualscreen.utils.CameraHelper
//import com.sw.dualscreen.utils.CameraUtils
//import com.sw.dualscreen.utils.Debouncer
//import com.sw.dualscreen.utils.ImageUtil
//import com.sw.dualscreen.viewmodel.BaseViewModel
//import com.sw.dualscreen.viewmodel.UserViewModel
//import com.sw.plate.utils.ToastUtils
//import io.objectbox.Box
//import io.objectbox.kotlin.boxFor
//import kotlinx.coroutines.launch
//import org.pytorch.IValue
//import org.pytorch.Module
//import org.pytorch.torchvision.TensorImageUtils
//import timber.log.Timber
//import kotlin.math.max
//
//class FoodCollectionActivity : BaseActivity<ActivityFoodCollectionBinding>() {
// companion object {
// val MAX_COUNT = 100
// }
// private val viewModel by viewModels<UserViewModel>()
// private var selectedFoodId: String? = ""
// private var selectedFoodName: String? = ""
//
// private var box: Box<Food>? = null
// private val foodCollectionList: MutableList<FoodCollectionBean> = mutableListOf()
//
//// private lateinit var cameraHelper: CameraHelper
//
// private lateinit var foodAdapter: GenericItemAdapter<FoodInfo, ItemSearchFoodInfoBinding>
// private val foodList = mutableListOf<FoodInfo>() // 适配器内部维护的数据列表
// private val debouncer = Debouncer(2000)
// private lateinit var previewView: PreviewView
//
// private val cameraUtils: CameraUtils by lazy {
// CameraUtils(this)
// }
//
// private val collectionAdapter: FoodCollectionAdapter by lazy {
// FoodCollectionAdapter(foodCollectionList).apply {
//// setOnItemClickListener { _, _, position ->
//// if (list[position].isShowCamera) {
////// takePhoto()
//// cameraHelper.openCamera()
//// }
//// }
// addOnItemChildClickListener(R.id.ivDelete) { _, _, position ->
//// list.removeAt(position)
//// collectionAdapter.notifyItemRemoved(position)
//// collectionAdapter.notifyItemRangeChanged(position, list.size)
// foodCollectionList[position].let {
// it.bitmap = null
// it.isShowCamera = true
// it.isFinish = false
// }
// notifyItemChanged(position)
// }
// }
// }
//
// override fun getViewModel(): BaseViewModel {
// return viewModel
// }
//
// override fun inflateViewBinding(): ActivityFoodCollectionBinding {
// return ActivityFoodCollectionBinding.inflate(layoutInflater)
// }
//
// private val cameraCallback: (Uri) -> Unit = { uri ->
// val index = foodCollectionList.indexOfFirst { it.bitmap == null }
// if (index == -1) {
// ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据")
// rerurn@ cameraCallback
// }
// ImageUtil.uriToBitmap(this, uri)?.let { bitmap ->
//// val cropBitmap = BitmapCropper.cropCenter(
//// original = bitmap,
//// targetWidth = 1300, targetHeight = 900,
//// //offsetX = 30, offsetY = 100
//// )
// val file = BitmapSaver.saveToAppFilesDir(
// bitmap, this, "IMG_CROP_${System.currentTimeMillis()}.jpg"
// )
// Timber.d("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}")
//
// foodCollectionList[index].let {
// it.bitmap = bitmap
// it.isShowCamera = false
// it.imageUri = file?.toUri()
// }
// collectionAdapter.notifyItemChanged(index)
// }
// }
//
// @SuppressLint("NotifyDataSetChanged")
// private fun takePhoto() {
// val count = foodCollectionList.count { it.bitmap != null }
// if (count >= MAX_COUNT) {
// ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据")
// return
// }
// cameraUtils.takePhoto(cameraCallback)
// }
//
// override fun initialize() {
// cameraUtils.initCamera()
// val previewBinding =
// LayoutCameraPreviewBinding.inflate(layoutInflater, binding.flCameraPreview)
// previewView = previewBinding.previewView.also {
// it.updateLayoutParams {
// width = 180.dp
// height = 180.dp
// }
// }
// cameraUtils.setPreviewController(previewView)
// // 初始化 CameraHelper
//// cameraHelper = CameraHelper(
//// context = this,
//// caller = this,
//// authority = "${packageName}.fileprovider"
//// ) { uri, path ->
//// //if (foodCollectionList.size < 6) {
//// // val insertIndex = if (foodCollectionList.isEmpty()) 0 else foodCollectionList.size - 1
//// // foodCollectionList.add(insertIndex, FoodCollectionBean(imageUri = uri))
//// //} else {
//// // foodCollectionList[foodCollectionList.size - 1] = FoodCollectionBean(imageUri = uri)
//// //}
//// //collectionAdapter.notifyDataSetChanged()
//// cameraCallback(uri)
//// }
//
// binding.ivBack.setOnClickListener {
// val intent = Intent(this, MainActivity::class.java)
// startActivity(intent)
// finish()
// }
// repeat(MAX_COUNT) {
// foodCollectionList.add(FoodCollectionBean(isShowCamera = true))
// }
// binding.rvFoodCollection.let {
// it.layoutManager = GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false)
// it.adapter = collectionAdapter
// }
//
// binding.btnFoodSearch.setOnClickListener {
// searchInfo()
// }
//
// binding.btnSave.setOnClickListener {
// if (selectedFoodName.isNullOrBlank()) {
// Toast.makeText(this, "请选择菜品名称", Toast.LENGTH_SHORT).show()
// return@setOnClickListener
// }
// if (foodCollectionList.size <= 1) {
// Toast.makeText(this, "请拍摄菜品照片", Toast.LENGTH_SHORT).show()
// return@setOnClickListener
// }
// vectorThread()
// }
//
// binding.editFoodName.setOnEditorActionListener { v, actionId, event ->
// if (actionId == EditorInfo.IME_ACTION_SEARCH) {
// searchInfo()
// val imm =
// v.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
// imm.hideSoftInputFromWindow(v.windowToken, 0)
// true
// } else {
// false
// }
// }
//
// binding.btnCollectedGoods.setOnClickListener {
// startActivity(Intent(this, CollectedDataActivity::class.java))
// }
// binding.btnTakePhoto.clickWithDebounce {
// binding.btnTakePhoto.text = "拍照"
// val count = foodCollectionList.count { it.bitmap != null }
// if (count >= MAX_COUNT) {
// ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据")
// return@clickWithDebounce
// }
//// cameraHelper.openCamera()
// takePhoto()
// }
// binding.btnClearData.setOnClickListener { clearData() }
// foodAdapter = createAdapter()
// binding.recyclerview.layoutManager = GridLayoutManager(context, 2)
// // 添加间距装饰(12dp)
// binding.recyclerview.addItemDecoration(
// GridSpacingItemDecoration(
// spanCount = 2,
// spacing = dpToPx(30),
// includeEdge = false // 包含边缘间距
// )
// )
// binding.recyclerview.adapter = foodAdapter
// }
//
// private fun vectorThread() {
// //Loading.show(this)
// showWaitingDialog("加载中……")
// Thread {
// foodCollectionList
// .filter { it.bitmap != null }
// .forEachIndexed { index, it ->
// image2VectorTask(it, index)
// }
// runOnUiThread {
// window.decorView.postDelayed({
// //Loading.dismiss()
// hideWaitingDialog()
// }, 1000)
// }
// }.start()
// }
//
// private fun initBox() {
// if (box == null) {
// box = ObjectBox.boxStore.boxFor(Food::class)
// }
// }
//
// private fun image2VectorTask(item: FoodCollectionBean, position: Int) {
// initBox()
// val imageVector = FoodModule.bitmap2FloatArray(item.bitmap!!)
//
// val base64Str = FloatBase64Utils.floatArrayToBase64(imageVector)
// Timber.tag("mzf1").e(base64Str)
//// viewModel.postImageData(
//// context,
//// foodId = selectedFoodId.toString(),
//// foodName = selectedFoodName.toString(),
//// foodVector = base64Str,
//// uri = item.imageUri!!
//// )
// box?.put(Food(name = checkedItem!!.foodName, foodIdx = 0, foodVector = imageVector))
// foodCollectionList[position].let {
// it.imageVector = imageVector
// it.isFinish = true
// }
//
// runOnUiThread {
// collectionAdapter.notifyItemChanged(position)
// }
// }
//
//
// private fun searchInfo() {
// debouncer.debounce {
// viewModel.searchByFoodName(binding.editFoodName.text.toString())
// }
// }
//
// override fun registerDataChange() {
// super.registerDataChange()
// lifecycleScope.launch {
// viewModel.searchFoodInfoList.collect {
//// foodList.clear()
//// foodList.addAll(it)
// foodAdapter.updateData(it)
// }
// }
// }
//
//
// private var checkedItem: FoodInfo? = null
// private fun createAdapter(): GenericItemAdapter<FoodInfo, ItemSearchFoodInfoBinding> {
// return GenericItemAdapter(
// items = emptyList(),
// bindingInflater = ItemSearchFoodInfoBinding::inflate,
// bindCallback = { item, position ->
// this.tvName.text = item.foodName
// if (item.id != checkedItem?.id) {
// this.tvName.typeface = Typeface.defaultFromStyle(Typeface.NORMAL)
// this.tvName.setTextColor(resources.getColor(R.color.search_normal))
// this.llRoot.setBackgroundResource(R.drawable.grid_search_item_normal)
// } else {
// this.tvName.typeface = Typeface.defaultFromStyle(Typeface.BOLD)
// this.tvName.setTextColor(resources.getColor(R.color.search_checked))
// this.llRoot.setBackgroundResource(R.drawable.grid_search_item_checked)
// }
//
// this.llRoot.setOnClickListener {
// Timber.d("itemClick ${item.foodName}, position = $position")
// checkedItem = item
//// viewModel.updateCurrentItem(item)
//// itemClickCallback(item)
// selectedFoodName = item.foodName
// selectedFoodId = item.id
//
// foodAdapter.notifyDataSetChanged()
// }
// }
// )
// }
//
// private var clickIndex = -1
//
// @SuppressLint("NotifyDataSetChanged")
// private fun clearData() {
// foodCollectionList.forEach {
// it.bitmap = null
// it.isShowCamera = true
// it.isFinish = false
// }
// collectionAdapter.notifyDataSetChanged()
//
// clickIndex = -1
// binding.editFoodName.setText("")
//// foodList.clear()
//// foodAdapter.updateData(mutableListOf())
//// foodAdapter.notifyDataSetChanged()
// //loadEmptyView()
// }
//
// override fun onResume() {
// super.onResume()
// cameraUtils.bind()
// binding.llCameraFlag.run {
// visibility = View.VISIBLE
// postDelayed({
// visibility = View.GONE
// }, 3000)
// }
// }
//
// override fun onPause() {
// super.onPause()
// cameraUtils.unbind()
// binding.llCameraFlag.visibility = View.VISIBLE
// }
//
//}
@@ -51,7 +51,7 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
}
}
}
private val box by lazy { ObjectBox.boxStore.boxFor(Food::class) }
// private val box by lazy { ObjectBox.boxStore.boxFor(Food::class) }
private fun saveFoodVector(list: List<FoodVector>) {
val vectorList = list.map { vt ->
val foodVector = vt.foodVector?.removeSurrounding("[", "]")?.split(",")?.map { it.toFloatOrNull()?:0.0f }?.toFloatArray()
@@ -63,6 +63,7 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
foodVector = foodVector
)
}
val box = ObjectBox.boxStore.boxFor(Food::class)
box.put(vectorList)
}
@@ -25,8 +25,10 @@ import androidx.recyclerview.widget.GridLayoutManager
import com.google.common.util.concurrent.ListenableFuture
import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.GlobalKey
import com.sw.dualscreen.activity.fragment.CollectFragment
import com.sw.dualscreen.adapter.SearchFoodAdapter
import com.sw.dualscreen.databinding.ActivityMainBinding
import com.sw.dualscreen.dialog.RemindDialog
import com.sw.dualscreen.ext.dp
import com.sw.dualscreen.ext.gone
import com.sw.dualscreen.ext.load
@@ -36,12 +38,16 @@ import com.sw.dualscreen.model.response.ClickBackEvent
import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.FoodOrder
import com.sw.dualscreen.model.response.PaySuccessEvent
import com.sw.dualscreen.model.response.ResetBoxEvent
import com.sw.dualscreen.model.response.UserFaceModel
import com.sw.dualscreen.objbox.Food
import com.sw.dualscreen.objbox.FoodModule
import com.sw.dualscreen.objbox.FoodModule.IdNameScore
import com.sw.dualscreen.objbox.ObjectBox
import com.sw.dualscreen.presentation.MainScreenPresentation
import com.sw.dualscreen.sdk.SensorScaleUtils
import com.sw.dualscreen.socket.TcpClient
import com.sw.dualscreen.utils.ActivityManager
import com.sw.dualscreen.utils.BitmapSaver
import com.sw.dualscreen.utils.Debouncer
import com.sw.dualscreen.utils.GsonUtils
@@ -58,7 +64,12 @@ import com.sw.plate.utils.ToastUtils
import com.sw.plate.utils.arcface.facedb.FaceDatabase
import com.sw.plate.utils.arcface.facedb.entity.FaceEntity
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
import io.objectbox.Box
import io.objectbox.kotlin.boxFor
import kotlinx.coroutines.Job
import kotlinx.coroutines.runBlocking
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.json.JSONObject
@@ -69,6 +80,7 @@ import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.Locale
import java.util.concurrent.Executors
import kotlin.collections.get
import kotlin.math.roundToInt
/**
@@ -135,6 +147,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
override fun initialize() {
super.initialize()
box = ObjectBox.boxStore.boxFor(Food::class)
isPageVisible = true
addBackEventListener()
//FoodModule.init(this)
@@ -262,7 +275,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
binding.previewView.visibility = View.VISIBLE
binding.ivImg.visibility = View.GONE
resumeAnalysis()
viewModel.cleanIdentifiedFoodInfoList()
// viewModel.cleanIdentifiedFoodInfoList()
return
}
pauseAnalysis()
@@ -318,6 +331,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
SensorScaleUtils.addWeightListener { weight ->
Timber.d("registerDataChange weight = $weight")
if (isPageVisible.not() || isStartRecognize.not()) {
if (ActivityManager.currentActivity() is MainActivity) {
isPageVisible = true
}
return@addWeightListener
}
val isWeightChange = weight - lastWeight > 0.05
@@ -328,8 +344,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
private fun recognizeByWeight(weight: Double, isWeightChange: Boolean, block: () -> Unit = {}) {
presentation?.updateWeight(weight)
if (weight <= 0.005) {//余量取餐,检测到秤上没有东西,重新启动识别菜品 && presentation?.mealPickupMode == 1
if (weight <= 0.005) {
////余量取餐,检测到秤上没有东西,重新启动识别菜品 && presentation?.mealPickupMode == 1
isRecognitionFood = true
return
}
if (isWeightChange && isRecognitionFood) { // 大于50g
@@ -368,7 +386,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
}
failCount++
hideWaitingDialog()
// ToastUtils.showToast("拍照异常,请手动放置后重新识别")
shutdownCamera()
setupCamera()
@@ -389,39 +406,42 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
val queryData = GsonUtils.toJson(list)
val recData = GsonUtils.toJson(scoreList)
Timber.d("registerDataChange识别后查询接口数据:$queryData,识别数据:$recData")
if (list.isEmpty()) {
binding.tvToSearch.let {
it.text = "未查询到,手动搜索"
it.visible()
}
return
}
list.forEach { foodInfo ->
val scoreItem = scoreList.firstOrNull { it.name == foodInfo.foodName }
val score = scoreItem?.score ?: 0.0
foodInfo.score = ((1 - score) * 10000).roundToInt()
}
val list2 = try {
val orderList = scoreList.map { it.name.trim() }
list.sortedBy { orderList.indexOf(it.foodName) }
} catch (e: Exception) {
e.printStackTrace()
list
}
//接口已处理排序
// val list2 = try {
// val orderList = scoreList.map { it.name.trim() }
// list.sortedBy { orderList.indexOf(it.foodName) }
// } catch (e: Exception) {
// e.printStackTrace()
// list
// }
searchFoodList.clear()
searchFoodList.addAll(list2)
searchFoodList.addAll(list)
adapter.notifyDataSetChanged()
//adapter.updateData(list)
if (list2.isNotEmpty()) {
checkedItem = list2[0]
checkedItem!!.photoUri = lastPhotoUri
checkedItem!!.isChecked = true
adapter.notifyItemChanged(0)
updateCurrentFood(checkedItem)
lastPhotoUri = null
LightManager.closeRedLight()
binding.flPay.visible()
binding.tvToSearch.let {
it.text = "以上都不是,手动搜索"
it.visible()
}
} else {
binding.flPay.gone()
binding.tvToSearch.gone()
checkedItem = list[0].also {
it.photoUri = lastPhotoUri
it.isChecked = true
}
adapter.notifyItemChanged(0)
updateCurrentFood(checkedItem)
// lastPhotoUri = null
LightManager.closeRedLight()
binding.tvToSearch.let {
it.text = "以上都不是,手动搜索"
it.visible()
}
}
@@ -653,14 +673,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
binding.tvTitleTime.text = dateTime
}
private var isPageVisible = true
public var isPageVisible = true
override fun onResume() {
super.onResume()
isPageVisible = true
// 启动定时器
handler.postDelayed(timeoutRunnable, TIME_OUT)
// ToastUtils.showToast("isPageVisible=$isPageVisible")
if (isFirstOpen) {
//首次
setupSecondaryDisplay()
@@ -778,6 +798,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
}
foodOrderId = orderId
block()
if (checkedItem!!.isFromSearch == true) {
//当前菜名为手动搜索选择,非识别结果,保存向量数据
saveFoodVector(checkedItem!!)
}
}
}
}
@@ -886,6 +911,111 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
}
}
/**
* 将uri转为文件和向量数据并提交
*/
private fun saveFoodVector(foodInfo: FoodInfo) {
try {
lastPhotoUri?.let { uri ->
uri2File(uri) { imageFile, imageVector ->
runBlocking {
uploadCollectFoodPics(foodInfo, imageFile, imageVector)
}
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* 上传菜品信息
*/
private suspend fun uploadCollectFoodPics(
foodInfo: FoodInfo,
imageFile: File?,
imageVector: FloatArray?
) {
if (imageFile == null || imageVector == null) {
Timber.tag(TAG)
.d("是否null判断,imageFile == null:${imageFile == null},imageVector == null:${imageVector == null}")
return
}
val foodId = foodInfo.foodId
val foodName = foodInfo.foodName ?: ""
val foodModelVersion = GlobalData.foodModelVersion
val params = HashMap<String, RequestBody>()
params["foodId"] = foodId.toRequestBody()
params["foodName"] = foodName.toRequestBody()
params["version"] = foodModelVersion.toRequestBody()
val files = listOf(imageFile)
val vectors = listOf(imageVector)
val foodVectorList = vectors.map {
it.joinToString(
separator = ",",
prefix = "[",
postfix = "]"
)
}
val foodVectorJson =
foodVectorList.joinToString(separator = ",", prefix = "[", postfix = "]")
Timber.tag(TAG).d("json=$foodVectorJson")
params["foodVector"] = foodVectorJson.toRequestBody()
val idList = viewModel.uploadCollectFoodPics(files, params)
if (idList.isNullOrEmpty()) {
loadRemindDialog("未返回id")
Timber.tag(TAG).d("idList为空")
return
}
Timber.tag(TAG)
.d("uploadCollectFoodPics-已采集向量总数:${box.all.filter { it.isDel.not() }.size}条")
val filterList = box.all.filter { it.collectId == idList[0] }
if (filterList.isNotEmpty()) {
loadRemindDialog("返回的id${idList[0]}已存在")
return
}
box.put(
Food(
collectId = idList[0],
foodId = foodId,
foodName = foodName,
foodVector = imageVector,
version = foodModelVersion
)
)
}
private fun loadRemindDialog(msg: String) {
runOnUiThread {
RemindDialog(
context = context,
content = msg,
confirmBlock = {}
).show()
}
}
private lateinit var box: Box<Food>
private fun uri2File(uri: Uri, block: (File?, FloatArray?) -> Unit) {
ImageUtil.uriToBitmap(this, uri)?.let { bitmap ->
val imageVector = try {
FoodModule.bitmap2FloatArray(bitmap)
} catch (e: Exception) {
e.printStackTrace()
return@let
}
val imageFile = BitmapSaver.saveToAppFilesDir(
bitmap, this, "IMG_CROP_${System.currentTimeMillis()}.jpg"
)
Timber.d("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${imageFile?.absolutePath}")
block(imageFile, imageVector)
if (bitmap.isRecycled.not()) {
bitmap.recycle()
}
}
}
override fun onDestroy() {
//SensorScaleUtils.closeScale()
faceTaskJob?.cancel()
@@ -1091,13 +1221,18 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
hideWaitingDialog()
Timber.d("registerDataChange photoUri 识别数据名称:$foodName")
binding.flPay.run {
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
//0-计费,1-不计费
if (chargeMode == 0) visible() else gone()
}
if (TextUtils.isEmpty(foodName)) {
LightManager.closeGreenLight()
LightManager.closeRedLight()
//binding.layoutRescan.visibility = View.VISIBLE
binding.flPay.visible()
binding.tvToSearch.let {
it.text = "未识别到,手动搜索"
it.text = "未识别到,手动搜索"
it.visible()
}
} else {
@@ -1117,4 +1252,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
}
}
// @Subscribe(threadMode = ThreadMode.MAIN)
// public fun onResetBox(event: ResetBoxEvent) {
// ObjectBox.boxStore.close()
// ObjectBox.init(this)
// }
}
@@ -36,6 +36,7 @@ import com.sw.plate.utils.ToastUtils
import io.objectbox.Box
import io.objectbox.kotlin.boxFor
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import timber.log.Timber
@@ -51,7 +52,12 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
private var selectedFoodId: String? = ""
private var selectedFoodName: String? = ""
private val box by lazy { ObjectBox.boxStore.boxFor(Food::class) }
private var box: Box<Food>?=null
fun initBox() {
if (box == null) {
box = ObjectBox.boxStore.boxFor(Food::class)
}
}
private val foodCollectionList = mutableListOf<FoodCollectionBean>().apply {
repeat(MAX_COUNT) {
add(FoodCollectionBean(isShowCamera = true))
@@ -192,7 +198,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
}
binding.btnFoodSearch.setOnClickListener {
searchInfo()
searchFood()
}
binding.btnSave.setOnClickListener {
@@ -209,7 +215,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
binding.editFoodName.setOnEditorActionListener { v, actionId, event ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
searchInfo()
searchFood()
val imm =
v.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(v.windowToken, 0)
@@ -236,15 +242,14 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
it.adapter = searchFoodAdapter
}
searchInfo()
searchFood()
}
@SuppressLint("NotifyDataSetChanged")
private fun upload() {
lifecycleScope.launch {
val totalFileCount = foodCollectionList.count { it.imageFile != null }
settingActivity?.showWaitingDialog("图片上传中0/$totalFileCount")
settingActivity?.showWaitingDialog2("图片上传中0/$totalFileCount")
val params = HashMap<String, RequestBody>()
//params["placeId"] = restId.toRequestBody()
params["foodId"] = checkedItem!!.foodId.toRequestBody()
@@ -256,46 +261,58 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
uploadImage = { batch ->
val files = batch.map { it.imageFile }
val foodVectorList =
batch.filter { it.imageVector != null }.map { it.imageVector!!.joinToString(separator = ",", prefix = "[", postfix = "]")}
batch.filter { it.imageVector != null }.map {
it.imageVector!!.joinToString(
separator = ",",
prefix = "[",
postfix = "]"
)
}
val foodVectorJson =
foodVectorList.joinToString(separator = ",", prefix = "[", postfix = "]")
Timber.tag(TAG).d("json=$foodVectorJson")
params["foodVector"] = foodVectorJson.toRequestBody()
settingActivity?.viewModel?.uploadCollectFoodPics(files, params)
},
onProgress = { count, batch, idList->
activity?.runOnUiThread {
settingActivity?.showWaitingDialog2("图片上传中$count/$totalFileCount")
//batch.forEach {
// it.uploadSuccess = true
//}
Thread {
val foodList = batch.mapIndexed { index, it ->
Food(
collectId = if (index < idList.size) idList[index] else null,
foodId = checkedItem!!.foodId,
foodName = checkedItem!!.foodName,
foodVector = it.imageVector,
version = GlobalData.foodModelVersion
)
}
box.put(foodList)
activity?.runOnUiThread {
batch.forEach { it.uploadSuccess = true }
collectionAdapter.notifyDataSetChanged()
}
}.start()
onProgress = { count, batch, idList ->
//batch.forEach {
// it.uploadSuccess = true
//}
runBlocking {
activity?.runOnUiThread {
settingActivity?.showWaitingDialog2("图片上传中$count/$totalFileCount")
}
val foodList = batch.mapIndexed { index, it ->
Food(
collectId = if (index < idList.size) idList[index] else null,
foodId = checkedItem!!.foodId,
foodName = checkedItem!!.foodName,
foodVector = it.imageVector,
version = GlobalData.foodModelVersion
)
}
initBox()
box?.put(foodList)
activity?.runOnUiThread {
batch.forEach { it.isFinish = true }
collectionAdapter.notifyDataSetChanged()
}
}
},
onError = {
settingActivity?.hideWaitingDialog()
activity?.runOnUiThread {
ToastUtils.showToast("上传失败,请稍后重试")
binding.root.postDelayed({
settingActivity?.hideWaitingDialog()
ToastUtils.showToast("上传失败,请稍后重试")
}, 1000)
}
},
onComplete = {
//vectorThread()
settingActivity?.hideWaitingDialog()
binding.root.postDelayed({
settingActivity?.hideWaitingDialog()
ToastUtils.showToast("上传成功")
}, 1000)
}
).processUploads()
}
@@ -320,59 +337,59 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
// }
}
private fun vectorThread() {
settingActivity?.showWaitingDialog("加载中……")
Thread {
foodCollectionList
// .filter { it.bitmap != null }
// .filter { it.imageVector != null }
.forEachIndexed { index, it ->
if (it.imageVector == null) {
return@forEachIndexed
}
image2VectorTask(imageVector = it.imageVector!!, index)
}
activity?.runOnUiThread {
binding.root.postDelayed({
settingActivity?.hideWaitingDialog()
}, 1000)
}
}.start()
}
private fun image2VectorTask(imageVector: FloatArray?, position: Int) {
if (imageVector == null) return
//// val imageVector = FoodModule.bitmap2FloatArray(item.bitmap!!)
////
////// val base64Str = FloatBase64Utils.floatArrayToBase64(imageVector)
////// Timber.tag("mzf1").e(base64Str)
//////// viewModel.postImageData(
//////// context,
//////// foodId = selectedFoodId.toString(),
//////// foodName = selectedFoodName.toString(),
//////// foodVector = base64Str,
//////// uri = item.imageUri!!
//////// )
// box.put(
// Food(
// collectId = null,
// foodId = checkedItem!!.foodId,
// foodName = checkedItem!!.foodName,
// foodVector = imageVector,
// version = "1.0.0"
// )
// )
// if (position > -1) {
// foodCollectionList[position].isFinish = true
// private fun vectorThread() {
// settingActivity?.showWaitingDialog("加载中……")
// Thread {
// foodCollectionList
//// .filter { it.bitmap != null }
//// .filter { it.imageVector != null }
// .forEachIndexed { index, it ->
// if (it.imageVector == null) {
// return@forEachIndexed
// }
// image2VectorTask(imageVector = it.imageVector!!, index)
// }
// activity?.runOnUiThread {
// collectionAdapter.notifyItemChanged(position)
// binding.root.postDelayed({
// settingActivity?.hideWaitingDialog()
// }, 1000)
// }
// }
}
// }.start()
// }
// private fun image2VectorTask(imageVector: FloatArray?, position: Int) {
// if (imageVector == null) return
////// val imageVector = FoodModule.bitmap2FloatArray(item.bitmap!!)
//////
//////// val base64Str = FloatBase64Utils.floatArrayToBase64(imageVector)
//////// Timber.tag("mzf1").e(base64Str)
////////// viewModel.postImageData(
////////// context,
////////// foodId = selectedFoodId.toString(),
////////// foodName = selectedFoodName.toString(),
////////// foodVector = base64Str,
////////// uri = item.imageUri!!
////////// )
//// box.put(
//// Food(
//// collectId = null,
//// foodId = checkedItem!!.foodId,
//// foodName = checkedItem!!.foodName,
//// foodVector = imageVector,
//// version = "1.0.0"
//// )
//// )
//// if (position > -1) {
//// foodCollectionList[position].isFinish = true
//// activity?.runOnUiThread {
//// collectionAdapter.notifyItemChanged(position)
//// }
//// }
// }
@SuppressLint("NotifyDataSetChanged")
private fun searchInfo() {
private fun searchFood() {
debouncer.debounce {
settingActivity?.searchByFoodName(binding.editFoodName.text.toString()) {
searchFoodList.clear()
@@ -399,8 +416,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
clickIndex = -1
binding.editFoodName.setText("")
searchFoodList.clear()
searchFoodAdapter.notifyDataSetChanged()
searchFood()
}
override fun onResume() {