当应用崩溃导致实时捕获时,会检测到从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美元
我的问题是应用识别文本的速度变慢。
获取框架->转换为图像转换为图像->发送谷歌
vision API检测文本->转换为获得唯一准确的输出
>请分享您的验证码,谢谢。
答案 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
//..
}
}
希望对您有帮助!。