CIDetector doesn’t work for QR-code detection on certain devices

I want to detect QR codes on CIImage and wrote code including below two lines.


NSDictionary *detectorConfiguration = [NSDictionary dictionaryWithObjectsAndKeys:CIDetectorAccuracyHigh, CIDetectorAccuracy, nil];

CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:detectorConfiguration];


But unexpectedly "detector" is nil after the second line executed, and so detection fails.

This issue always occurs on some devices and never occurs on other devices.

It seems to depend also on iOS versions.

For example, tested by simulator, "detector" is nil on

iPhone5 (iOS8.4)

iPhone5 (iOS9.0)

iPhone5s (iOS8.4)

while non-nil on

iPhone5s (iOS9.0)


For other detector types (rectangle, face, text on iOS9.0), this issue doesn't seem to occur.

Does anybody know why this occurs? Thanks.

Replies

Same problem here, but with the iPhone 4s on iOS 9. QR detector mode returns nil, the other modes work.

Hi,


I'm suspicious that this now only works on devices with hardware pattern recognition (in the A7 core, for the fingerprint scanner), even on the simulator. I've created a reduced test case as:

        let filter = CIFilter(name: "CIQRCodeGenerator", withInputParameters: [
            "inputMessage": "test".dataUsingEncoding(NSUTF8StringEncoding)!,
            ])
        let transform = CGAffineTransformMakeScale(5.0, 5.0)
        let image = filter!.outputImage!.imageByApplyingTransform(transform)
       
        let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: nil)
        let features = detector.featuresInImage(image, options: nil)
       
        print(features.count)


Does not work on (iOS 9.2):

  • iPad 2
  • iPad Retina
  • iPhone 4s
  • iPhone 5


Works on (iOS 9.2):

  • iPad Air
  • iPad Air 2
  • iPad Pro
  • iPhone 5s
  • iPhone 6
  • iPhone 6 Plus
  • iPhone 6s
  • iPhone 6s Plus


The actual QR code generation works on all.


If you're capturing straight from the camera, you might have more luck with AVCaptureMetadataOutput.

Good news on this one: AVCaptureMetadataOutput works fine on the same devices, so scanning straight from the camera is fine. This means that you can replace (or supplement) the frame capture with:


            let output = AVCaptureMetadataOutput();
            output.setMetadataObjectsDelegate(self, queue: dispatch_queue)
            captureSession.addOutput(output)
          
            if output.availableMetadataObjectTypes.contains({object_type in
                return object_type as! String == AVMetadataObjectTypeQRCode
            }) {
                output.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
            } else {
                print("No QR support")
            }


And:


    func captureOutput(captureOutput: AVCaptureOutput, didOutputMetadataObjects metadataObjects:[AnyObject], fromConnection connection: AVCaptureConnection) {
        metadataObjects.forEach({metadata in
            if let qr_metadata = metadata as? AVMetadataMachineReadableCodeObject {
                handleQRCode(qr_metadata.stringValue)
            } else {
                print("Unparseable")
            }
        })
    }

Hi all,


I'm also having a very similar issue.


Is there a solution for this? (I'm not using the camera, so, the solution described above does not apply to me)


Thanks