CIDetectorTypeQRCode не может сканировать прозрачные изображения - PullRequest
0 голосов
/ 25 января 2019

Я пытаюсь отсканировать QR-изображения, которые пользователь выбирает с диска. Я обнаружил странную проблему, когда все библиотеки, которые я пробовал, потерпели неудачу (старый порт CIDetector ZXING или ZBAR). Я знаю, что есть способы добавить белый фон (например, перерисовать изображение или использовать CIFilter), чтобы изображение было отсканировано.

Как правильно сканировать QR-коды с прозрачным фоном (настройте CIContext или CIDetector). (изображение ниже не сканируется на iOS и macOS).

https://en.wikipedia.org/wiki/QR_code#/media/File:QR_code_for_mobile_English_Wikipedia.svg QR CODE PICTURE

- (void)scanImage:(CIImage *)image
{
    NSArray <CIFeature *>*features = [[self QRdetector] featuresInImage:image];
    NSLog(@"Number of features found: %lu", [features count]);
}

- (CIDetector *)QRdetector
{
    CIContext *context = [CIContext contextWithOptions:@{kCIContextWorkingColorSpace : [NSNull null]}]; //no difference using special options or nil as a context

    CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:context options:@{CIDetectorAccuracy : CIDetectorAccuracyHigh, CIDetectorAspectRatio : @(1)}];
    return detector;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSURL *URL = [[NSBundle mainBundle] URLForResource:@"transparentqrcode" withExtension:@"png"];
    UIImage *image = [UIImage imageWithContentsOfFile:[URL path]];

    CIImage *ciImage = [CIImage imageWithContentsOfURL:URL];

    //CUSTOM CODE TO ADD WHITE BACKGROUND
    CIFilter *filter = [CIFilter filterWithName:@"CISourceAtopCompositing"];
    [filter setDefaults];
    CIColor *whiteColor = [[CIColor alloc] initWithColor:[UIColor whiteColor]];
    CIImage *colorImage = [CIImage imageWithColor:whiteColor];

    colorImage = [colorImage imageByCroppingToRect:ciImage.extent];
    [filter setValue:ciImage forKey:kCIInputImageKey];
    [filter setValue:colorImage forKey:kCIInputBackgroundImageKey];
    CIImage *newImage = [filter valueForKey:kCIOutputImageKey];


    [self scanImage:ciImage];
    return YES;
}

1 Ответ

0 голосов
/ 25 января 2019

Как уже упоминалось в комментариях, CIDetector рассматривает альфа-канал как черный Замена на белый работает - если только сам QRCode не белый с прозрачным фоном.

Я не проводил профилирование, чтобы выяснить, будет ли это быстрее, но лучше будет .

- (IBAction)didTap:(id)sender {

    NSURL *URL = [[NSBundle mainBundle] URLForResource:@"transparentqrcode" withExtension:@"png"];

    CIImage *ciImage = [CIImage imageWithContentsOfURL:URL];

    NSArray <CIFeature *>*features = [self getImageFeatures:ciImage];

    // if CIDetector failed to find / process a QRCode in the image,
    // (such as when the image has a transparent background),
    // invert the colors and try again
    if (features.count == 0) {
        CIFilter *filter = [CIFilter filterWithName:@"CIColorInvert"];
        [filter setValue:ciImage forKey:kCIInputImageKey];
        CIImage *newImage = [filter valueForKey:kCIOutputImageKey];
        features = [self getImageFeatures:newImage];
    }

    if (features.count > 0) {
        for (CIQRCodeFeature* qrFeature in features) {
            NSLog(@"QRFeature.messageString : %@ ", qrFeature.messageString);
        }
    } else {
        NSLog(@"Unable to decode image!");
    }

}

- (NSArray <CIFeature *>*)getImageFeatures:(CIImage *)image
{
    NSArray <CIFeature *>*features = [[self QRdetector] featuresInImage:image];
    NSLog(@"Number of features found: %lu", [features count]);
    return features;
}

- (CIDetector *)QRdetector
{
    CIContext *context = [CIContext contextWithOptions:@{kCIContextWorkingColorSpace : [NSNull null]}]; //no difference using special options or nil as a context

    CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:context options:@{CIDetectorAccuracy : CIDetectorAccuracyHigh, CIDetectorAspectRatio : @(1)}];
    return detector;
}
...