Search code examples
swiftfirebasemlvision

MLVision incorrect rotation


Trying to use MLVision in portrait mode, however after i take picture in portrait mode it will output only couple characters due to incorrect rotation. Picture has to be taken while in landscape otherwise cannot recognise the text. Tried to go over example provided by Firebase where i've encountered exactly opposite problem when this happens in landscape and works in portrait, however wasn't able to find setting which would determine orientation of image besides metadata, which i've tried to change but without any success.

 var vision: Vision?

override func viewDidLoad() {
    super.viewDidLoad()
    vision = Vision.vision()

}


func recognize(Image: VisionImage){
    let textRecognizer = vision?.onDeviceTextRecognizer()
    textRecognizer?.process(Image) { result, error in
        guard error == nil, let result = result else {
            // ...
            return
        }
        print(result.text)

        // Recognized text
    }
}
@IBAction func scanDocument(_ sender: Any) {
    let vc = UIImagePickerController()
    vc.sourceType = .camera
    vc.allowsEditing = false
    vc.delegate = self
    present(vc, animated: true)

}


func imagePickerController(_ picker: UIImagePickerController,
                           didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

    picker.dismiss(animated: true, completion: nil)
    guard let selectedImage = info[.originalImage] as? UIImage else {
        fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
    }
     recognize(Image: VisionImage(image: selectedImage))

}

Solution

  • To guide the recognizer, you should supply the the orientation of your image

    // Define the metadata for the image.
    let imageMetadata = VisionImageMetadata()
    imageMetadata.orientation = UIUtilities.visionImageOrientation(from: image.imageOrientation)
    
    // Initialize a VisionImage object with the given UIImage.
    let visionImage = VisionImage(image: image)
    visionImage.metadata = imageMetadata
    

    and here's a helper method to find the right orientation from your image

    public static func imageOrientation(fromDevicePosition devicePosition: AVCaptureDevice.Position = .back
    ) -> UIImageOrientation {
      var deviceOrientation = UIDevice.current.orientation
      if deviceOrientation == .faceDown || deviceOrientation == .faceUp ||
        deviceOrientation == .unknown {
        deviceOrientation = currentUIOrientation()
      }
      switch deviceOrientation {
      case .portrait:
        return devicePosition == .front ? .leftMirrored : .right
      case .landscapeLeft:
        return devicePosition == .front ? .downMirrored : .up
      case .portraitUpsideDown:
        return devicePosition == .front ? .rightMirrored : .left
      case .landscapeRight:
        return devicePosition == .front ? .upMirrored : .down
      case .faceDown, .faceUp, .unknown:
        return .up
      }
    }