我们已经使用AVCaptureSession在收据上实现了QRCode读取。我们注意到的一个问题是,它在读取QRCode的命中率上相当挑剔。你真的必须努力让它认识到收据上有QRCode。我试着看看是否有人发表了关于如何提高命中率的材料。我已经实现了AutoFocus,这有点帮助。
我确实看过:Reading on QRCodes on iOS with AVCaptureSession -- alignment issues?但是那里没有可行的建议。
有关其他方法的任何想法吗?
以下是读者代码:
import UIKit
import AVFoundation
final class BarcodeReader: NSObject {
fileprivate var captureSession: AVCaptureSession?
fileprivate var videoPreviewLayer: AVCaptureVideoPreviewLayer?
fileprivate unowned let barcodeReaderDelegate: BarcodeReaderDelegate
init(barcodeReaderDelegate: BarcodeReaderDelegate) {
self.barcodeReaderDelegate = barcodeReaderDelegate
}
func start(in view: UIView) throws {
if captureSession == nil {
captureSession = try configuredCaptureSession()
}
if videoPreviewLayer == nil {
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession!)
videoPreviewLayer!.videoGravity = AVLayerVideoGravityResizeAspectFill
videoPreviewLayer!.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer!)
}
captureSession!.startRunning()
}
fileprivate func configuredCaptureSession() throws -> AVCaptureSession {
let captureSession = AVCaptureSession()
// NOTE: Remember to add a message in your Info.plist file under the
// key NSCameraUsageDescription or this will crash the app.
let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
// make sure that auto focus is turned on
if (device?.isFocusModeSupported(.continuousAutoFocus))! {
try device?.lockForConfiguration()
device?.focusMode = .continuousAutoFocus
device?.unlockForConfiguration()
}
let input = try AVCaptureDeviceInput(device: device)
captureSession.addInput(input)
let output = AVCaptureMetadataOutput()
captureSession.addOutput(output)
output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
output.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
return captureSession
}
func stop() {
captureSession?.stopRunning()
}
}
extension BarcodeReader: AVCaptureMetadataOutputObjectsDelegate {
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
guard let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject else { return }
guard metadataObject.type == AVMetadataObjectTypeQRCode else { return
}
stop()
barcodeReaderDelegate.barcodeReader(self, found: metadataObject.stringValue)
}
}
protocol BarcodeReaderDelegate: class {
func barcodeReader(_ barcodeReader: BarcodeReader, found code: String)
}