-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
633 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
115 changes: 115 additions & 0 deletions
115
app/src/main/java/com/plweegie/magmolecular/ocr/TextAnalyzer.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package com.plweegie.magmolecular.ocr | ||
|
||
import android.content.Context | ||
import android.graphics.Rect | ||
import android.util.Log | ||
import android.widget.Toast | ||
import androidx.camera.core.ImageAnalysis | ||
import androidx.camera.core.ImageProxy | ||
import androidx.lifecycle.Lifecycle | ||
import androidx.lifecycle.MutableLiveData | ||
import androidx.lifecycle.coroutineScope | ||
import com.google.mlkit.common.MlKitException | ||
import com.google.mlkit.vision.common.InputImage | ||
import com.google.mlkit.vision.text.Text | ||
import com.google.mlkit.vision.text.TextRecognition | ||
import com.plweegie.magmolecular.utils.ImageUtils | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.launch | ||
import kotlinx.coroutines.plus | ||
import kotlinx.coroutines.tasks.await | ||
import kotlinx.coroutines.withContext | ||
|
||
|
||
class TextAnalyzer( | ||
private val context: Context, | ||
private val result: MutableLiveData<String>, | ||
private val imageCropPercentages: MutableLiveData<Pair<Int, Int>>, | ||
lifecycle: Lifecycle | ||
) : ImageAnalysis.Analyzer { | ||
|
||
private companion object { | ||
const val TAG = "TextAnalyzer" | ||
} | ||
|
||
private val detector = TextRecognition.getClient() | ||
private val textAnalyzerScope = lifecycle.coroutineScope + Dispatchers.Default | ||
|
||
init { | ||
lifecycle.addObserver(detector) | ||
} | ||
|
||
@androidx.camera.core.ExperimentalGetImage | ||
override fun analyze(imageProxy: ImageProxy) { | ||
val mediaImage = imageProxy.image ?: return | ||
|
||
val rotationDegrees = imageProxy.imageInfo.rotationDegrees | ||
|
||
// We requested a setTargetAspectRatio, but it's not guaranteed that's what the camera | ||
// stack is able to support, so we calculate the actual ratio from the first frame to | ||
// know how to appropriately crop the image we want to analyze. | ||
val imageHeight = mediaImage.height | ||
val imageWidth = mediaImage.width | ||
|
||
val actualAspectRatio = imageWidth / imageHeight | ||
|
||
val convertImageToBitmap = ImageUtils.convertYuv420888ImageToBitmap(mediaImage) | ||
val cropRect = Rect(0, 0, imageWidth, imageHeight) | ||
|
||
// If the image has a way wider aspect ratio than expected, crop less of the height so we | ||
// don't end up cropping too much of the image. If the image has a way taller aspect ratio | ||
// than expected, we don't have to make any changes to our cropping so we don't handle it | ||
// here. | ||
val currentCropPercentages = imageCropPercentages.value ?: return | ||
if (actualAspectRatio > 3) { | ||
val originalHeightCropPercentage = currentCropPercentages.first | ||
val originalWidthCropPercentage = currentCropPercentages.second | ||
imageCropPercentages.value = | ||
Pair(originalHeightCropPercentage / 2, originalWidthCropPercentage) | ||
} | ||
|
||
// If the image is rotated by 90 (or 270) degrees, swap height and width when calculating | ||
// the crop. | ||
val cropPercentages = imageCropPercentages.value ?: return | ||
val heightCropPercent = cropPercentages.first | ||
val widthCropPercent = cropPercentages.second | ||
val (widthCrop, heightCrop) = when (rotationDegrees) { | ||
90, 270 -> Pair(heightCropPercent / 100f, widthCropPercent / 100f) | ||
else -> Pair(widthCropPercent / 100f, heightCropPercent / 100f) | ||
} | ||
|
||
cropRect.inset( | ||
(imageWidth * widthCrop / 2).toInt(), | ||
(imageHeight * heightCrop / 2).toInt() | ||
) | ||
val croppedBitmap = | ||
ImageUtils.rotateAndCrop(convertImageToBitmap, rotationDegrees, cropRect) | ||
|
||
textAnalyzerScope.launch { | ||
recognizeText(InputImage.fromBitmap(croppedBitmap, 0)) | ||
imageProxy.close() | ||
} | ||
} | ||
|
||
private suspend fun recognizeText(image: InputImage): Text? = | ||
try { | ||
detector.process(image).await().also { | ||
result.postValue(it.text) | ||
} | ||
} catch (e: Exception) { | ||
Log.e(TAG, "Text recognition error", e) | ||
getErrorMessage(e)?.let { | ||
withContext(Dispatchers.Main) { | ||
Toast.makeText(context, it, Toast.LENGTH_SHORT).show() | ||
} | ||
} | ||
null | ||
} | ||
|
||
private fun getErrorMessage(exception: Exception): String? { | ||
val mlKitException = exception as? MlKitException ?: return exception.message | ||
return if (mlKitException.errorCode == MlKitException.UNAVAILABLE) { | ||
"Waiting for text recognition model to be downloaded" | ||
} else exception.message | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
app/src/main/java/com/plweegie/magmolecular/ocr/TextRecognitionActivity.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.plweegie.magmolecular.ocr | ||
|
||
import android.os.Bundle | ||
import androidx.appcompat.app.AppCompatActivity | ||
import com.plweegie.magmolecular.R | ||
import dagger.hilt.android.AndroidEntryPoint | ||
|
||
|
||
@AndroidEntryPoint | ||
class TextRecognitionActivity : AppCompatActivity() { | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
setContentView(R.layout.activity_text_recognition) | ||
|
||
if (savedInstanceState == null) { | ||
supportFragmentManager.beginTransaction() | ||
.replace(R.id.container, TextRecognitionFragment.newInstance()) | ||
.commitNow() | ||
} | ||
} | ||
} |
Oops, something went wrong.