使用xcode AVFoundation扫描EAN13条码时发生了奇怪的事情

时间:2018-03-22 09:20:24

标签: ios swift avfoundation barcode ean-13

我写了一个小的ios应用程序来扫描ean13条形码,关于灵敏度存在一个奇怪的问题,它可以读取制造商在产品上印有条形码的产品中100%的ean13条形码,例如,CD盒,药盒,巧克力,黄油,茶盒......,但如果条形码是手动打印而不是制造商的条形码打印。然后读取条形码有问题,但这些条形码是一个有效的ean13条形码,它可以通过条形码阅读器设备硬件轻松读取,甚至可以通过我从苹果商店下载的一些条形码扫描应用程序读取,例如, QRbot。

例如,下图显示了手动打印的ean13条形码,它是一个有效的ean13条形码,可以通过条形码阅读器硬件轻松读取,也可以通过从应用商店下载的QRbot应用程序读取。但它无法从我使用AVFoundation编写的应用程序中读取。 ean13barcode

以下是完整的代码:

import UIKit 

import AVFoundation

class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {

@IBOutlet weak var scanFrame: UIImageView!
var video = AVCaptureVideoPreviewLayer()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let session = AVCaptureSession()
    let captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
    do
    {
        let input = try AVCaptureDeviceInput(device: captureDevice)
        session.addInput(input)
    }
    catch
    {
        print ("Error opening device")
    }

    let output = AVCaptureMetadataOutput()
    session.addOutput(output)
    output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
    output.metadataObjectTypes = [AVMetadataObjectTypeEAN13Code]
    video = AVCaptureVideoPreviewLayer(session: session)
    video.frame = view.layer.bounds
    view.layer.addSublayer(video)
    self.view.bringSubview(toFront: scanFrame)
    session.startRunning()
    output.rectOfInterest = video.metadataOutputRectOfInterest(for: scanFrame.frame)

}


func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {       
    if metadataObjects != nil && metadataObjects.count != 0
    {
        if let object = metadataObjects[0] as? AVMetadataMachineReadableCodeObject
        {
            if object.type == AVMetadataObjectTypeEAN13Code
            {
                let alert = UIAlertController(title: "QR Code", message: object.stringValue, preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "Scan again?", style: .default, handler: nil))
                alert.addAction(UIAlertAction(title: "Copy to clipboard", style: .default, handler: { (nil) in
                    UIPasteboard.general.string = object.stringValue
                }))

                print(object.stringValue)
                present(alert, animated: true, completion: nil)
            }
        }
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

提前致谢!

enter image description here

1 个答案:

答案 0 :(得分:0)

您好我刚刚修改了一些代码,如果您复制粘贴它应该可行。该课程基于此tutorial 别忘了在info.plist中添加相机隐私 我还删除了scanFrame,因此我也不必处理用户界面,如果需要,可以添加回来。

import UIKit
import Foundation
import AVFoundation

class ViewController: UIViewController {

    var session: AVCaptureSession!
    var previewLayer: AVCaptureVideoPreviewLayer!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Create a session object.

        session = AVCaptureSession()

        // Set the captureDevice.

        let videoCaptureDevice = AVCaptureDevice.default(for: AVMediaType.video)

        // Create input object.

        let videoInput: AVCaptureDeviceInput?

        do {
            videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice!)
        } catch {
            return
        }
        // Add input to the session.

        if (session.canAddInput(videoInput!)) {
            session.addInput(videoInput!)
        } else {
            scanningNotPossible()
        }

        // Create output object.

        let metadataOutput = AVCaptureMetadataOutput()

        // Add output to the session.

        if (session.canAddOutput(metadataOutput)) {
            session.addOutput(metadataOutput)

            // Send captured data to the delegate object via a serial queue.

            metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)

            // Set barcode type for which to scan: EAN-13.

            metadataOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.ean13]

        } else {
            scanningNotPossible()
        }

        // Add previewLayer and have it show the video data.

        previewLayer = AVCaptureVideoPreviewLayer(session: session);
        previewLayer.frame = view.layer.bounds;
        previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill;
        view.layer.addSublayer(previewLayer);

        // Begin the capture session.

        session.startRunning()
    }

    func scanningNotPossible() {
        // Let the user know that scanning isn't possible with the current device.
        let alert = UIAlertController(title: "Can't Scan.", message: "Let's try a device equipped with a camera.", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        present(alert, animated: true, completion: nil)
        session = nil
    }


    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        if (session?.isRunning == false) {
            session.startRunning()
        }
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        if (session?.isRunning == true) {
            session.stopRunning()
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
extension ViewController: AVCaptureMetadataOutputObjectsDelegate {
    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        if metadataObjects.count != 0
        {
            if let object = metadataObjects[0] as? AVMetadataMachineReadableCodeObject
            {
                if object.type == AVMetadataObject.ObjectType.ean13
                {
                    let alert = UIAlertController(title: "Barcode Code", message: object.stringValue, preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "Scan again?", style: .default, handler: nil))
                    alert.addAction(UIAlertAction(title: "Copy to clipboard", style: .default, handler: { (nil) in
                        UIPasteboard.general.string = object.stringValue
                    }))

                    print(object.stringValue ?? "error")
                    present(alert, animated: true, completion: nil)
                }
            }
        }
    }
}

enter image description here