首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iOS 11的视觉框架条码检测

iOS 11的视觉框架条码检测
EN

Stack Overflow用户
提问于 2017-06-21 18:04:54
回答 3查看 6.6K关注 0票数 8

我一直在测试苹果在WWDC2017中引入的新的视觉框架。我是专门看条形码检测-我已经能够获得扫描后,从相机/画廊的图像,这是一个条形码图像或不。但是,在查看barcodeDescriptor时,我看不到实际的条形码值或有效载荷数据。在https://developer.apple.com/documentation/coreimage/cibarcodedescriptor页面上似乎没有任何公开的内容来标识任何属性。

我发现了这些错误:

  • 无法连接到远程服务:错误Domain=NSCocoaErrorDomain Code=4097“连接到名为 com.apple.BarcodeSupport.BarcodeNotificationService“
  • libMobileGestalt MobileGestalt.c:555:无法访问InverseDeviceID (见problem/11744455>)
  • 连接到名为com.apple.BarcodeSupport.BarcodeNotificationService Error的服务 Domain=NSCocoaErrorDomain Code=4097

有任何方法从VNBarcodeObservation访问条形码值吗?任何帮助都将不胜感激。谢谢!下面是我使用的代码:

代码语言:javascript
复制
@IBAction func chooseImage(_ sender: Any) {
        imagePicker.allowsEditing = true
        imagePicker.sourceType = .photoLibrary

        present(imagePicker, animated: true, completion: nil)
    }

    @IBAction func takePicture(_ sender: Any) {
        if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerControllerSourceType.camera)){
            imagePicker.sourceType = UIImagePickerControllerSourceType.camera
            self .present(imagePicker, animated: true, completion: nil)
        }
        else{
            let alert = UIAlertController(title: "Warning", message: "Camera not available", preferredStyle: UIAlertControllerStyle.alert)
            alert.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }
    }

    //PickerView Delegate Methods

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

        imagePicker .dismiss(animated: true, completion: nil)
        classificationLabel.text = "Analyzing Image…"

        guard let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage
            else { fatalError("no image from image picker") }
        guard let ciImage = CIImage(image: pickedImage)
            else { fatalError("can't create CIImage from UIImage") }

        imageView.image = pickedImage
        inputImage = ciImage

        // Run the rectangle detector, which upon completion runs the ML classifier.
        let handler = VNImageRequestHandler(ciImage: ciImage, options: [.properties : ""])
        DispatchQueue.global(qos: .userInteractive).async {
            do {
                try handler.perform([self.barcodeRequest])
            } catch {
                print(error)
            }
        }
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController){
        picker .dismiss(animated: true, completion: nil)
        print("picker cancel.")
    }

    lazy var barcodeRequest: VNDetectBarcodesRequest = {
        return VNDetectBarcodesRequest(completionHandler: self.handleBarcodes)
    }()

    func handleBarcodes(request: VNRequest, error: Error?) {
        guard let observations = request.results as? [VNBarcodeObservation]
            else { fatalError("unexpected result type from VNBarcodeRequest") }
        guard observations.first != nil else {
            DispatchQueue.main.async {
                self.classificationLabel.text = "No Barcode detected."
            }
            return
        }

        // Loop through the found results
        for result in request.results! {

            // Cast the result to a barcode-observation
            if let barcode = result as? VNBarcodeObservation {

                // Print barcode-values
                print("Symbology: \(barcode.symbology.rawValue)")

                if let desc = barcode.barcodeDescriptor as? CIQRCodeDescriptor {
                    let content = String(data: desc.errorCorrectedPayload, encoding: .utf8)

                    // FIXME: This currently returns nil. I did not find any docs on how to encode the data properly so far.
                    print("Payload: \(String(describing: content))\n")
                    print("Error-Correction-Level: \(desc.errorCorrectedPayload)\n")
                    print("Symbol-Version: \(desc.symbolVersion)\n")
                }
            }
        }
    }
EN

回答 3

Stack Overflow用户

发布于 2017-08-09 09:11:25

显然,在iOS 11 beta 5中,苹果引入了VNBarcodeObservation的新payloadStringValue特性。现在您可以毫无问题地从QR代码中读取信息。

代码语言:javascript
复制
if let payload = barcodeObservation.payloadStringValue {
    print("payload is \(payload)")
}
票数 9
EN

Stack Overflow用户

发布于 2017-07-30 20:33:07

如果苹果不打算为此提供一个库,下面这样的东西就可以了:

代码语言:javascript
复制
extension CIQRCodeDescriptor {
    var bytes: Data? {
        return errorCorrectedPayload.withUnsafeBytes { (pointer: UnsafePointer<UInt8>) in
            var cursor = pointer

            let representation = (cursor.pointee >> 4) & 0x0f
            guard representation == 4 /* byte encoding */ else { return nil }

            var count = (cursor.pointee << 4) & 0xf0
            cursor = cursor.successor()
            count |= (cursor.pointee >> 4) & 0x0f

            var out = Data(count: Int(count))
            guard count > 0 else { return out }

            var prev = (cursor.pointee << 4) & 0xf0
            for i in 2...errorCorrectedPayload.count {
                if (i - 2) == count { break }

                let cursor = pointer.advanced(by: Int(i))
                let byte = cursor.pointee
                let current = prev | ((byte >> 4) & 0x0f)
                out[i - 2] = current
                prev = (cursor.pointee << 4) & 0xf0
            }
            return out
        }
    }
}

然后

代码语言:javascript
复制
String(data: descriptor.bytes!, encoding: .utf8 /* or whatever */)
票数 2
EN

Stack Overflow用户

发布于 2018-05-03 22:53:16

如果您想直接从VNBarcodeObservation获取原始数据,而不需要遵循某些字符串编码,您可以去掉前面的2/2字节,并且不需要QR代码头来获取实际数据。

代码语言:javascript
复制
            guard let barcode = barcodeObservation.barcodeDescriptor as? CIQRCodeDescriptor else { return }
            let errorCorrectedPayload = barcode.errorCorrectedPayload
            let payloadData = Data(bytes: zip(errorCorrectedPayload.advanced(by: 2),
                                              errorCorrectedPayload.advanced(by: 3)).map { (byte1, byte2) in
                return byte1 << 4 | byte2 >> 4
            })
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44683242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档