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

Программируем под IOS
Ответить
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 МБ.

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