JetPack Compose Recomposition против IOS Vision для OCR не работаетAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 JetPack Compose Recomposition против IOS Vision для OCR не работает

Сообщение Anonymous »

Я пытаюсь использовать Compose Multiplatform и создать приложение, которое использует комплект ML для Android и Vision для iOS для чтения слов, снятых камерой. На Android все работает нормально. На iOS, однако, есть огромная проблема: производительность ужасна, а приложение не отвечает. Проще говоря, я открываю заднюю камеру и пытаюсь прочитать слова, но по какой -то причине я не могу найти правильный поток, в котором можно сделать тяжелую работу, потому что приложение не удается (плохой запрос) или потому, что пользовательский интерфейс не обновляется, даже если на стороне журнала я вижу, как слова распознаются < /p>
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.interop.UIKitView
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.useContents
import platform.AVFoundation.AVAuthorizationStatusAuthorized
import platform.AVFoundation.AVAuthorizationStatusDenied
import platform.AVFoundation.AVAuthorizationStatusNotDetermined
import platform.AVFoundation.AVAuthorizationStatusRestricted
import platform.AVFoundation.AVCaptureConnection
import platform.AVFoundation.AVCaptureDevice
import platform.AVFoundation.AVCaptureDeviceInput
import platform.AVFoundation.AVCaptureInput
import platform.AVFoundation.AVCaptureOutput
import platform.AVFoundation.AVCaptureSession
import platform.AVFoundation.AVCaptureSessionPresetPhoto
import platform.AVFoundation.AVCaptureVideoDataOutput
import platform.AVFoundation.AVCaptureVideoDataOutputSampleBufferDelegateProtocol
import platform.AVFoundation.AVCaptureVideoPreviewLayer
import platform.AVFoundation.AVLayerVideoGravityResizeAspectFill
import platform.AVFoundation.AVMediaTypeVideo
import platform.AVFoundation.authorizationStatusForMediaType
import platform.AVFoundation.requestAccessForMediaType
import platform.CoreGraphics.CGRectMake
import platform.CoreMedia.CMSampleBufferGetImageBuffer
import platform.CoreMedia.CMSampleBufferRef
import platform.CoreVideo.kCVPixelBufferPixelFormatTypeKey
import platform.CoreVideo.kCVPixelFormatType_32BGRA
import platform.UIKit.UIScreen
import platform.UIKit.UIView
import platform.Vision.VNImageRequestHandler
import platform.Vision.VNRecognizeTextRequest
import platform.Vision.VNRecognizedText
import platform.Vision.VNRecognizedTextObservation
import platform.darwin.NSObject
import platform.darwin.dispatch_async
import platform.darwin.dispatch_get_main_queue

@OptIn(ExperimentalForeignApi::class)
actual class CameraPermissionManager {

private lateinit var captureSession: AVCaptureSession
private lateinit var textRecognitionRequest: VNRecognizeTextRequest
private lateinit var videoLayer: AVCaptureVideoPreviewLayer

@Composable
actual fun RequestCameraPermission(
onPermissionGranted: @Composable () -> Unit,
onPermissionDenied: @Composable () -> Unit
) {
var hasPermission by remember { mutableStateOf(false) }
var permissionRequested by remember { mutableStateOf(false) }

LaunchedEffect(Unit) {
val status = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo)
when (status) {
AVAuthorizationStatusAuthorized -> {
hasPermission = true
}

AVAuthorizationStatusNotDetermined -> {
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo) { granted ->
dispatch_async(dispatch_get_main_queue()) {
hasPermission = granted
permissionRequested = true
}
}
}

AVAuthorizationStatusDenied, AVAuthorizationStatusRestricted -> {
hasPermission = false
}

else -> {}
}
}

if (hasPermission) {
onPermissionGranted()
} else if (permissionRequested) {
onPermissionDenied()
}
}

@Composable
actual fun StartCameraPreview(onTextDetected: (String) -> Unit) {
val screenWidth = UIScreen.mainScreen.bounds.useContents { size.width }
val screenHeight = UIScreen.mainScreen.bounds.useContents { size.height }
val previewView = remember {
UIView(frame = CGRectMake(0.0, 0.0, screenWidth, screenHeight))
}

LaunchedEffect(Unit) {
// Setup AVCaptureSession
captureSession = AVCaptureSession().apply {
sessionPreset = AVCaptureSessionPresetPhoto
}

val device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
val input = device?.let { AVCaptureDeviceInput.deviceInputWithDevice(it, null) }
captureSession.addInput(input as AVCaptureInput)

videoLayer = AVCaptureVideoPreviewLayer(session = captureSession).apply {
this.videoGravity = AVLayerVideoGravityResizeAspectFill
this.frame = previewView.bounds
}
previewView.layer.addSublayer(videoLayer)

// Setup Vision Text Recognition
textRecognitionRequest = VNRecognizeTextRequest { request, _ ->
val observations = request?.results?.filterIsInstance()
observations?.forEach { observation ->
val topCandidate = observation.topCandidates(1u).firstOrNull()?.toString() ?: ""
onTextDetected(topCandidate)
}
}

val videoOutput = AVCaptureVideoDataOutput().apply {
videoSettings = mapOf(kCVPixelBufferPixelFormatTypeKey to kCVPixelFormatType_32BGRA)
setSampleBufferDelegate(
createSampleBufferDelegate(onTextDetected),
dispatch_get_main_queue()
)
}

captureSession.addOutput(videoOutput)
captureSession.startRunning()
}

DisposableEffect(Unit) {
onDispose {
captureSession.stopRunning()
}
}

UIKitView(
factory = {
previewView
},
modifier = Modifier.fillMaxSize()
)
}

private fun createSampleBufferDelegate(onTextDetected: (String) -> Unit): AVCaptureVideoDataOutputSampleBufferDelegateProtocol {
return object : NSObject(), AVCaptureVideoDataOutputSampleBufferDelegateProtocol {
override fun captureOutput(
output: AVCaptureOutput,
didOutputSampleBuffer: CMSampleBufferRef?,
fromConnection: AVCaptureConnection
) {
if (didOutputSampleBuffer != null) {
processSampleBuffer(didOutputSampleBuffer, onTextDetected)
}
}
}
}

private fun processSampleBuffer(
sampleBuffer: CMSampleBufferRef,
onTextDetected: (String) -> Unit
) {
val pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)

if (pixelBuffer == null) {
println("CameraPermissionManager || Pixel buffer is null")
return
}

val handler = VNImageRequestHandler(pixelBuffer, options = mapOf())

val request = VNRecognizeTextRequest { request, error ->
if (error != null) {
println("CameraPermissionManager || Error recognizing text: $error")
return@VNRecognizeTextRequest
}

val observations = request?.results?.filterIsInstance()

observations?.forEach { observation ->
val topCandidates = observation.topCandidates(1u)
topCandidates.firstOrNull()?.let { candidate ->
val recognizedText = candidate as? VNRecognizedText
recognizedText?.string?.let { text ->
onTextDetected(text)
} ?: run {
println("CameraPermissionManager || Recognized text is null")
}
}
}
}

try {
handler.performRequests(listOf(request), null)
} catch (e: Exception) {
println("CameraPermissionManager || Error performing Vision request: $e")
}
}
}
< /code>
Что я делаю не так? Что мне изменить? Видение должно быть лучшим для iOS, и все же, как только я пытаюсь изменить ветку для части распознавания слова, все замораживает и ничего не работает. У вас есть какие -нибудь рабочие предложения?

Подробнее здесь: https://stackoverflow.com/questions/789 ... ot-working
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»