MLKit Обнаружение текста на iOS работает для фотографий, взятых из Assets.xcassets, но не той же фотографии, сделанной на камеру / загруженной с рулона камеры

Я использую Google Text Detection API от MLKit для обнаружения текста по изображениям. Кажется, что он отлично работает на скриншотах, но когда я пытаюсь использовать его на изображениях, сделанных в приложении (с помощью AVFoundation) или на фотографиях, загруженных с камеры, он выдает небольшое количество, казалось бы, случайных символов.

Это мой код для запуска фактического обнаружения текста:

func runTextRecognition(with image: UIImage) {
    let visionImage = VisionImage(image: image)
    textRecognizer.process(visionImage) { features, error in
        self.processResult(from: features, error: error)
    }
}

func processResult(from text: VisionText?, error: Error?) {
    guard error == nil, let text = text else {
        print("oops")
        return
    }
    let detectedText = text.text

    let okAlert = UIAlertAction(title: "OK", style: .default) { (action) in
        // handle user input
    }

    let alert = UIAlertController(title: "Detected text", message: detectedText, preferredStyle: .alert)
    alert.addAction(okAlert)

    self.present(alert, animated: true) {
        print("alert was presented")
    }
}

Это мой код для использования изображений с камеры (работает для скриншотов, а не для изображений, снятых камерой):

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    if let image = info[.originalImage] as? UIImage {
        self.runTextRecognition(with: image)
        uploadView.image = image
    } else {
        print("error")
    }
    self.dismiss(animated: true, completion: nil)
}

Это мой код для использования фотографий, сделанных на камеру внутри приложения (никогда не работает, результаты всегда ерунда):

func photoOutput(_ output: AVCapturePhotoOutput,
                 didFinishProcessingPhoto photo: AVCapturePhoto,
                 error: Error?) {
    PHPhotoLibrary.shared().performChanges( {
        let creationRequest = PHAssetCreationRequest.forAsset()
        creationRequest.addResource(with: PHAssetResourceType.photo, data: photo.fileDataRepresentation()!, options: nil)
    }, completionHandler: nil)

    let testImage = UIImage(data: photo.fileDataRepresentation()!)

    self.runTextRecognition(with: testImage!)
}

И это то, что я сделал для использования тестовых изображений, которые я поместил в Assets.xcassets (это единственный, который последовательно работает хорошо):

let uiimage = UIImage(named: "testImage")

self.runTextRecognition(with: uiimage!)

Я думаю, что мои проблемы могут лежать в ориентации UIImage, но я не уверен. Любая помощь приветствуется!

0 ответов

Если ваш imagepicker работает нормально, проблема может быть в ориентации изображения. Для быстрой проверки вы можете сделать несколько изображений в разной ориентации и посмотреть, работает ли это.

Моя проблема заключалась в том, что распознавание текста работало с изображения, выбранного из галереи, но не с камеры. Это была проблема ориентации.

Решение 1

Перед преобразованием в зрительное изображение зафиксируйте ориентацию изображения следующим образом.

let fixedImage = pickedImage.fixImageOrientation()

Добавьте это расширение.

extension UIImage {
    func fixImageOrientation() -> UIImage {
        UIGraphicsBeginImageContext(self.size)
        self.draw(at: .zero)
        let fixedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return fixedImage ?? self
    } }

Решение 2

Документация Firebase предоставляет способ исправить любую ориентацию.

func imageOrientation(
    deviceOrientation: UIDeviceOrientation,
    cameraPosition: AVCaptureDevice.Position
    ) -> VisionDetectorImageOrientation {
    switch deviceOrientation {
    case .portrait:
        return cameraPosition == .front ? .leftTop : .rightTop
    case .landscapeLeft:
        return cameraPosition == .front ? .bottomLeft : .topLeft
    case .portraitUpsideDown:
        return cameraPosition == .front ? .rightBottom : .leftBottom
    case .landscapeRight:
        return cameraPosition == .front ? .topRight : .bottomRight
    case .faceDown, .faceUp, .unknown:
        return .leftTop
    }
}

Создать метаду:

let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
let metadata = VisionImageMetadata()
metadata.orientation = imageOrientation(
    deviceOrientation: UIDevice.current.orientation,
    cameraPosition: cameraPosition
)

Установите метаданные для изображения Vision.

let image = VisionImage(buffer: sampleBuffer)
image.metadata = metadata
Другие вопросы по тегам