简体   繁体   English

CIDetectorTypeQRCode无法扫描透明图像

[英]CIDetectorTypeQRCode fails to scan transparent images

I am trying to scan QR images that user chooses from disk. 我正在尝试扫描用户从磁盘选择的QR图像。 I found a strange issue where all libraries I tried failed (CIDetector old port of ZXING or ZBAR). 我发现了一个奇怪的问题,即所有尝试使用的库都失败了(CIDetector ZXING或ZBAR的旧端口)。 I know that there are ways to add white background (eg redraw image or using CIFilter) so the image will get scanned. 我知道有多种方法可以添加白色背景(例如重绘图像或使用CIFilter),以便对图像进行扫描。

What is the correct way of scanning QR codes with transparent background (configure CIContext or CIDetector). 扫描具有透明背景的QR码的正确方法是什么(配置CIContext或CIDetector)。 (the image below fails to scan on iOS and macOS). (下图无法在iOS和macOS上扫描)。

https://en.wikipedia.org/wiki/QR_code#/media/File:QR_code_for_mobile_English_Wikipedia.svg https://en.wikipedia.org/wiki/QR_code#/media/File:QR_code_for_mobile_English_Wikipedia.svg QR码图片

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

As mentioned in the comments, it appears CIDetector treats the alpha channel as black. 如评论中所述, CIDetector似乎将alpha通道视为黑色。 Replacing it with white works --- unless the QRCode itself is white with a transparent background. 用白色代替它---除非QRCode本身是带有透明背景的白色。

I haven't done any profiling to see if this would be quicker, but it might be a better option. 我没有进行任何配置分析,以查看这样做是否更快,但这可能是一个更好的选择。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM