我写了一个小的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.
}
}
提前致谢!
答案 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)
}
}
}
}
}