Я попытался интегрировать распознавание цифровых рукописных данных в приложение для Android с помощью Jetpack Compose, но заметил, что точность распознавания значительно ниже по сравнению с использованием макетов XML. Несмотря на выполнение одних и тех же шагов реализации, результаты распознавания в Compose постоянно хуже. Может ли кто-нибудь помочь мне понять, почему это может происходить и как я могу повысить точность распознавания цифровых рукописных данных в Jetpack Compose?
Я выполнил обычные шаги, чтобы интегрировать распознавание цифровых рукописных данных в свое приложение для Android. используя Jetpack Compose, ожидая такой же точности, как и при использовании макетов XML. Однако результаты распознавания в Compose заметно хуже, ошибок и неточностей больше. Я пробовал настраивать различные параметры и конфигурации, но точность существенно не улучшилась.
Теперь я поделюсь своим кодом создания
Основное действие –>
val TAG = "Image Recognition"
public class MainActivity : ComponentActivity() {
companion object {
var inkBuilder = StrokeManager.inkBuilder
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
StrokeManager.downloadModel()
}
setContent {
DemoTheme {
App()
}
}
}
}
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun App() {
val context = LocalContext.current
var bitmap: ImageBitmap? by remember {
mutableStateOf(null)
}
var textState by remember {
mutableStateOf("")
}
var imageUri: Uri? by remember {
mutableStateOf(null)
}
val lines = remember {
mutableStateListOf()
}
val imageLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.GetContent()
) { result ->
if (result != null) {
imageUri = result
}
}
Column(
verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth()
) {
Canvas(
modifier = Modifier
.fillMaxWidth()
.height(300.dp)
.pointerInput(true) {
detectDragGestures { change, dragAmount ->
change.consume()
val line = Line(
start = change.position - dragAmount,
end = change.position
)
lines.add(line)
}
}.pointerInteropFilter {
addNewTouchEvent(it)
true
}
) {
lines.forEach { line ->
drawLine(
color = line.color,
start = line.start,
end = line.end,
strokeWidth = line.strokeWidth.toPx(),
cap = StrokeCap.Round
)
}
}
Button(
modifier = Modifier
.height(50.dp)
.fillMaxWidth(),
onClick = {
StrokeManager.recognize(){
textState = it
}
}
) {
Text("Recognise Character")
}
Spacer(modifier = Modifier.height(10.dp))
Button(
modifier = Modifier
.height(50.dp)
.fillMaxWidth(),
onClick = {
lines.clear()
inkBuilder = Ink.builder()
textState = ""
}
) {
Text("Clear")
}
if (textState.isNotEmpty()) {
Text(textState)
}
}
}
data class Line(
val start: Offset,
val end: Offset,
val color: Color = Color.Black,
val strokeWidth: Dp = 8.dp
)
StrokeManager.kt ->
object StrokeManager {
private val TAG = "Image Recognition"
var inkBuilder: Ink.Builder = Ink.builder()
private lateinit var strokeBuilder: Ink.Stroke.Builder
private lateinit var digitalInkRecognitionModel: DigitalInkRecognitionModel
fun addNewTouchEvent(event: MotionEvent) {
val action = event.actionMasked
val x = event.x
val y = event.y
when (action) {
MotionEvent.ACTION_DOWN -> {
strokeBuilder = Ink.Stroke.builder()
strokeBuilder.addPoint(Ink.Point.create(x, y))
}
MotionEvent.ACTION_MOVE -> strokeBuilder.addPoint(Ink.Point.create(x, y))
MotionEvent.ACTION_UP -> {
strokeBuilder.addPoint(Ink.Point.create(x, y))
inkBuilder.addStroke(strokeBuilder.build())
}
else -> {
// its seems only this part of code is working
// not the above cases as told by doc. maybe due its Compose code Using XML
if(!this::strokeBuilder.isInitialized){
strokeBuilder = Ink.Stroke.builder()
}
strokeBuilder.addPoint(Ink.Point.create(x, y))
inkBuilder.addStroke(strokeBuilder.build())
// Action not relevant for ink construction
Log.d(TAG, "Action not relevant for ink construction")
}
}
}
// Define a suspend function to download the model
suspend fun downloadModel() {
val modelIdentifier = DigitalInkRecognitionModelIdentifier.fromLanguageTag("en-IN")
digitalInkRecognitionModel = DigitalInkRecognitionModel.builder(modelIdentifier!!).build()
val remoteModelManager = RemoteModelManager.getInstance()
remoteModelManager.isModelDownloaded(digitalInkRecognitionModel)
.addOnSuccessListener { isDownloaded ->
if (isDownloaded) {
Log.i(TAG, "Model is already downloaded")
} else {
Log.i(TAG, "Model is not downloaded")
remoteModelManager.download(digitalInkRecognitionModel,DownloadConditions.Builder().build())
.addOnSuccessListener {
Log.i( TAG,"Model Downloaded!")
}
.addOnFailureListener { e ->
Log.e(TAG,"Error while downloading a model : $e"
)
}
}
}
}
fun recognize(
recognised : (String) -> Unit
) {
if(!this::digitalInkRecognitionModel.isInitialized){
Log.e(TAG, "Model not initialized")
return
}
// Get a recognizer for the language
val recognizer: DigitalInkRecognizer =
DigitalInkRecognition.getClient(
DigitalInkRecognizerOptions.builder(digitalInkRecognitionModel).build()
)
val ink = inkBuilder.build()
recognizer
.recognize(ink)
.addOnSuccessListener { result ->
var textState = ""
result.candidates.forEach{
textState += "-> \n $it.text"
}
recognised(textState)
Log.d(TAG, "Recognised Text: ${textState}")
}
.addOnFailureListener { e ->
Log.e(TAG, "Exception $e")
recognised("Error")
}
}
}
Теперь XML-код, который я использовал, был взят с GitHub, и я тщательно его изучил.
ссылка на его репозиторий -> https://github. com/icanerdogan/DigitalInkRecognition-MLKit/tree/main
XML-код MainActivity ->
class MainActivity : AppCompatActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.apply {
textView.movementMethod = ScrollingMovementMethod()
StrokeManager.downloadInkRecognition()
buttonRecognize.setOnClickListener {
textView.visibility = View.VISIBLE
buttonRecognize.visibility = View.INVISIBLE
StrokeManager.drawRecognizer(textView)
}
buttonClear.setOnClickListener {
drawView.clear()
StrokeManager.clear()
textView.visibility = View.INVISIBLE
buttonRecognize.visibility = View.VISIBLE
}
}
}
}
DrawView.kt ->
class DrawView(context: Context, attributeSet: AttributeSet?) : View(context, attributeSet) {
private var currentStrokePaint : Paint = Paint()
private val canvasPaint : Paint = Paint(Paint.DITHER_FLAG)
private val currentStroke : Path = Path()
private var drawCanvas : Canvas? = null
private lateinit var canvasBitmap : Bitmap
init {
currentStrokePaint.color = Color.BLACK
currentStrokePaint.isAntiAlias = true
currentStrokePaint.strokeWidth = STROKE_WIDTH_DP
currentStrokePaint.style = Paint.Style.STROKE
currentStrokePaint.strokeJoin = Paint.Join.ROUND
currentStrokePaint.strokeCap = Paint.Cap.ROUND
}
override fun onTouchEvent(event: MotionEvent): Boolean {
val action = event.actionMasked
val x = event.x
val y = event.y
when(action) {
MotionEvent.ACTION_DOWN -> currentStroke.moveTo(x, y)
MotionEvent.ACTION_MOVE -> currentStroke.lineTo(x, y)
MotionEvent.ACTION_UP -> {
currentStroke.lineTo(x, y)
drawCanvas?.drawPath(currentStroke, currentStrokePaint)
currentStroke.reset()
}
else -> {}
}
StrokeManager.addNewTouchEvent(event)
invalidate()
return true
}
override fun onDraw(canvas: Canvas) {
canvas.drawBitmap(canvasBitmap, 0f, 0f, canvasPaint)
canvas.drawPath(currentStroke, currentStrokePaint)
}
fun clear() {
onSizeChanged(canvasBitmap.width, canvasBitmap.height, canvasBitmap.width, canvasBitmap.height)
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
drawCanvas = Canvas(canvasBitmap)
invalidate()
}
companion object {
private const val STROKE_WIDTH_DP = 6.0f
}
}
XML-код
Подробнее здесь: https://stackoverflow.com/questions/783 ... layout-why
Jetpack Compose Точность распознавания цифровых рукописных данных намного хуже, чем XML-макет: почему? ⇐ Android
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Почему мои модели классификации намного хуже, чем его регрессионная производительность?
Anonymous » » в форуме Python - 0 Ответы
- 1 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Рассчитайте точность, полноту, точность и сбалансированную точность из матрицы путаницы.
Anonymous » » в форуме Python - 0 Ответы
- 38 Просмотры
-
Последнее сообщение Anonymous
-