当应用程序崩溃以进行实时捕获时,检测到文本从AVCaptureDataSampleBufferDelegate获取图像,回调输出

时间:2019-02-27 05:17:42

标签: ios swift avcapturedevice avcapture

当应用崩溃导致实时捕获时,会检测到从AVCaptureDataSampleBufferDelegate回调中获取图像时输出的文本。 从我已使用该代码的发送Google视觉API获取图像回叫 有人工作吗? 我的代码

import UIKit
import FirebaseMLVision
import FirebaseMLModelInterpreter
import AVKit

protocol ImageDelegate: class {
  func getImage(imageOutFrame: String)
}
var photoOutput: AVCaptureVideoDataOutput!
var videoDataOutputQueue: DispatchQueue!
var previewLayer:AVCaptureVideoPreviewLayer!
var captureDevice : AVCaptureDevice!
var captureSession = AVCaptureSession()
var context = CIContext()
weak var delegate: ImageDelegate?
var vision = Vision.vision()
var textRecognizer = vision.onDeviceTextRecognizer()

extension UIViewController: AVCaptureVideoDataOutputSampleBufferDelegate {      
  // To set the camera and its position to capture
  func setUpAVCapture(capturePreview: UIView) {
    captureSession.sessionPreset = AVCaptureSession.Preset.vga640x480
    guard let device = AVCaptureDevice
      .default(AVCaptureDevice.DeviceType.builtInWideAngleCamera,
               for: .video,
               position: AVCaptureDevice.Position.back) else {
                return
    }
    captureDevice = device
    captureDevice.isFocusModeSupported(.continuousAutoFocus)
    try! captureDevice.lockForConfiguration()
    captureDevice.focusMode = .continuousAutoFocus
    captureDevice.unlockForConfiguration()
    beginSession(capturePreview: capturePreview)
  }
// Function to setup the beginning of the capture session
  func beginSession(capturePreview : UIView){

    var deviceInput: AVCaptureDeviceInput!

    do {
      deviceInput = try AVCaptureDeviceInput(device: captureDevice)
      guard deviceInput != nil else {
        print("error: cant get deviceInput")
        return
      }
      if captureSession.canAddInput(deviceInput){
        captureSession.addInput(deviceInput)
      }         
      photoOutput = AVCaptureVideoDataOutput()
      photoOutput.alwaysDiscardsLateVideoFrames=true
      videoDataOutputQueue = DispatchQueue(label: "VideoDataOutputQueue")
      photoOutput.setSampleBufferDelegate(self, queue: videoDataOutputQueue)            
      if captureSession.canAddOutput(photoOutput){
        captureSession.addOutput(photoOutput)
      }          
      photoOutput.connection(with: .video)?.isEnabled = true          
      previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
      previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill          
      let rootLayer :CALayer = capturePreview.layer
      rootLayer.masksToBounds=true          
      rootLayer.addSublayer(previewLayer)          
       captureDevice.configureDesiredFrameRate(0)          
      captureSession.startRunning()
    } catch let error as NSError {
      deviceInput = nil
       exit(0)
      print("error: \(error.localizedDescription)")
    }        
  }     
  public func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    connection.videoOrientation = AVCaptureVideoOrientation.portrait            
    DispatchQueue.global(qos: .userInteractive).async {
      guard let imag = self.imageFromSampleBuffer(sampleBuffer : sampleBuffer) else { return }
    let image = VisionImage(image: imag)
    textRecognizer.process(image) { result, error in
      guard error == nil, let result = result else {
        return
      }
      let resultText = result.text
      let matched = self.matches(for: RegEx.wholeRegex , in: resultText)          
      let m = matched.joined(separator: "")
      print(m)          
      delegate?.getImage(imageOutFrame: m)
      }
  }
  }      
  func imageFromSampleBuffer(sampleBuffer : CMSampleBuffer) -> UIImage? {
    guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return nil }
    let ciImage = CIImage(cvPixelBuffer: imageBuffer)
    guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else { return nil }        
    let img = UIImage(cgImage: cgImage)
    let n = img.fixedOrientation()
    return n
  }
  func stopCamera(){
    captureSession.stopRunning()
    captureDevice = nil
  }      
}    
extension AVCaptureDevice {      
  /// http://stackoverflow.com/questions/21612191/set-a-custom-avframeraterange-for-an-avcapturesession#27566730
  func configureDesiredFrameRate(_ desiredFrameRate: Int) {        
    var isFPSSupported = false        
    do {          
      if let videoSupportedFrameRateRanges = activeFormat.videoSupportedFrameRateRanges as? [AVFrameRateRange] {
        for range in videoSupportedFrameRateRanges {
          if (range.maxFrameRate >= Double(desiredFrameRate) && range.minFrameRate <= Double(desiredFrameRate)) {
            isFPSSupported = true
            break
          }
        }
      }          
      if isFPSSupported {
        try lockForConfiguration()
        activeVideoMaxFrameDuration = CMTimeMake(value: 1, timescale: Int32(desiredFrameRate))
        activeVideoMinFrameDuration = CMTimeMake(value: 1, timescale: Int32(desiredFrameRate))
        unlockForConfiguration()
      }          
    } catch {
      print("lockForConfiguration error: \(error.localizedDescription)")
    }
  }
}

让r esultText = result.text仅获得美元价值 例如实时捕获

  

xcsrf $ 16.54245 ssxvcxv

我得到了类似的输出

16.54245美元

  •   

    我的问题是应用识别文本的速度变慢。

  • 1)我已经设置了帧频,但是不起作用
  • 2)我使用了Dispatch,但无法正常工作。
  •   

    获取框架->转换为图像转换为图像->发送谷歌

  •   

    vision API检测文本->转换为获得唯一准确的输出

>请分享您的验证码,谢谢。

1 个答案:

答案 0 :(得分:0)

当我使用VisionImage方法中的UIImage初始化captureOutput对象时,我的应用程序也崩溃了。我没有用VisionImage初始化CMSampleBuffer的原因是我需要裁剪相机预览层的特定部分。我很难割种CMSampleBuffer

原因
就我而言,当文本识别器仍在运行时,当新的视频帧变得可用时,就会发生崩溃,因为在打开相机时反复调用captureOutput

解决方案
我放置了一个标志变量,以防止在处理图像时调用文本识别器。检查以下代码以获取详细信息。

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {

    guard let image = self.imageFromSampleBuffer(sampleBuffer : sampleBuffer) else { return }
    let image = VisionImage(image: image)

    guard isRunningTextRecognizer == false else {
            return
    }

    isRunningTextRecognizer = true
    let textRecognizer = vision.onDeviceTextRecognizer()
    textRecognizer.process(image) { (text, error) in
        //...
        self.isRunningTextRecognizer = false
        //..
    }
}

希望对您有帮助!。