2017-06-21 14 views
5

Przeprowadzam test nowej struktury Vision, którą Apple wprowadził w WWDC2017. Dokładnie patrzę na wykrywanie kodów kreskowych - udało mi się uzyskać po zeskanowaniu obrazu z Kamery/Galerii, że jest to obraz kodu kreskowego, czy nie. Jednak nie widzę rzeczywistej wartości kodu kreskowego ani danych ładunku podczas przeglądania kodu kreskowegoDescriptor. Wygląda na to, że nic nie jest widoczne na stronie https://developer.apple.com/documentation/coreimage/cibarcodedescriptor w celu zidentyfikowania żadnej z właściwości.Detekcja kodu kreskowego Vision dla iOS 11

Dostaję te błędy:

  • nie można połączyć się z usługą zdalnej: Błąd Domain = kod NSCocoaErrorDomain = 4097 "połączenie się z usługą o nazwie
    com.apple.BarcodeSupport.BarcodeNotificationService"
  • libMobileGestalt MobileGestalt.c: 555: brak dostępu do InverseDeviceID (zobacz problem/11744455>)
  • połączenie z usługą o nazwie com.apple.BarcodeSupport.BarcodeNotificationService Error
    Domain = kod NSCocoaErrorDomain = 4097

Czy istnieje jakiś sposób, aby uzyskać dostęp do wartości kodu kreskowego z VNBarcodeObservation? Każda pomoc będzie bardzo ceniona. Dziękuję Ci! Oto kod używam:

@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") 
       } 
      } 
     } 
    } 
+0

wyjazdu [Session # 510 - Postępy w podstawowej obrazu: Filtry metalowe, Vision, a więcej - WWDC 2017] (https://developer.apple .com/videos/play/wwdc2017/510 /) o 35min zaczynają mówić o CIBarcodeDescriptor i errorCorrectedPayload. Niestety nie byłem w stanie odczytać komunikatu w ładowności. – nathan

+0

Tak, jestem w stanie naprawić te błędy, dodając "OS_ACTIVITY_MODE" jako wyłączone w "Edit Scheme" -> Run-> Arguments, ale nie jestem w stanie wyodrębnić danych z ładunku. Jestem w stanie zeskanować kod paskowy, a następnie zrobić z niego obraz, który pokazał w filmie, ale wciąż mam problem z wyodrębnieniem ciągu informacji z rodzaju danych. –

+0

Użyłem twojego kodu jako podstawy dla moich własnych testów i miałem * trochę * szczęścia (iOS 11 beta 3), ale wyniki były zastanawiające. 'ErrorCorrectedPayload' zawiera dane, które * czasami * można odczytać. https://stackoverflow.com/questions/45037418/zlib-stream-in-ios-11-vision-framework-barcodes-sometimes-decompress-ocenami – oelna

Odpowiedz

2

Jeśli Apple nie zamierza dostarczyć bibliotekę dla tego, coś jak poniżej będzie działać:

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

A potem

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

Czy możesz wyjaśnić/powiązać ochronę zmiennej' reprezentacja'? Próbuję parsować 'CIQRCodeDescriptor', a moja wartość' reprezentacji' (czyli 2) powoduje, że moje 'descriptor.bytes' jest zerowe. – raoul

+1

Twoja reprezentacja jest "alfanumeryczna", więc będziesz potrzebować innego algorytmu. http://www.thonky.com/qr-code-tutorial/alphanumeric-mode-encoding –

6

Najwyraźniej w systemie iOS 11 beta 5 Apple wprowadził nową właściwość payloadStringValue z VNBarcodeObservation. Teraz można odczytać informacji z QR-code bez problemów

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