我写了一个小的ios应用程序来扫描ean13条码,在灵敏度方面有一个奇怪的问题,它可以从产品中读取100%的ean13条码,这些产品的条码是由制造商在产品上打印的,例如CD盒、药盒、巧克力、黄油、茶盒……,但是如果条码是手工打印的话生产商的条码打印。然后读取条形码是一个问题,但这些条形码是有效的ean13条形码,条形码阅读器设备硬件甚至我从苹果商店下载的一些条形码扫描应用程序(例如QRbot)都可以轻松读取。
例如,下图显示了一个手动打印的ean13条形码,它是一个有效的ean13条形码,条形码阅读器硬件可以很容易地读取,也可以通过从应用商店下载的QRbot应用程序读取。但我用AVFoundation编写的应用程序无法读取它。
以下是完整的代码:
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.
}
}
提前谢谢!
最佳答案
嗨,我刚刚修改了你的一些代码,如果你复制粘贴这个应该可以。课程基于此tutorial
别忘了在info.plist中添加相机隐私
另外,我已经删除了scanFrame,这样我就不必再处理UI了,如果需要的话,可以添加回来。
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)
}
}
}
}
}
关于ios - 使用xcode AVFoundation扫描EAN13条码时发生奇怪的情况,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49424747/