Vision Framework Barcode Detection for iOS 11

I tested the new Vision concept that Apple introduced at WWDC2017. I specifically look at barcode detection - I managed to get after scanning the image from the camera / gallery that this is a barcode image or not. However, I do not see what the actual value of the barcode or payload data is when viewing the barcodeDescriptor. Nothing seems to display on the https://developer.apple.com/documentation/coreimage/cibarcodedescriptor page to identify any of the properties.

I get the following errors:

  • Cannot connect to the remote service: Domain Error = NSCocoaErrorDomain Code = 4097 "connection to the service with the name
    com.apple.BarcodeSupport.BarcodeNotificationService "
  • libMobileGestalt MobileGestalt.c: 555: cannot access InverseDeviceID (see problem / 11744455>)
  • connecting to a service named com.apple.BarcodeSupport.BarcodeNotificationService Error
    Domain = NSCocoaErrorDomain Code = 4097

Is there a way to access the barcode value from VNBarcodeObservation? Any help would be greatly appreciated. Thanks! Here is the code I'm using:

@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") } } } } 
+5
source share
2 answers

Apparently, in iOS 11 beta 5, Apple introduced the new payloadStringValue property of VNBarcodeObservation . Now you can read information from the QR code without any problems.

 if let payload = barcodeObservation.payloadStringValue { print("payload is \(payload)") } 
+6
source

If Apple is not going to provide a library for this, the following will work:

 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 } } } 

And then

 String(data: descriptor.bytes!, encoding: .utf8 /* or whatever */) 
+2
source

Source: https://habr.com/ru/post/1269076/


All Articles