如何在将图像提供给 CoreML 模型之前对其进行预处理?

Posted

技术标签:

【中文标题】如何在将图像提供给 CoreML 模型之前对其进行预处理?【英文标题】:How do I preprocess the image before giving it to CoreML Model? 【发布时间】:2019-03-31 14:05:37 【问题描述】:

我创建了一个图像相似性模型并使用参考数据图像对其进行了测试。我测试了 turicreate 模型,我得到了参考数据图像的零距离,并且在将这段代码与 coreml 模型一起使用时也得到了同样的结果:

image = tc.image_analysis.resize(reference_data[0]['image'], *reversed(model.input_image_shape))
image = PIL.Image.fromarray(image.pixel_data)
mlmodel.predict('image':image)`

然而,当在 ios 中使用模型作为 VNCoreMLModel 时,没有返回零距离的参考图像测试,其中大多数甚至不是最短距离,即参考图像 0 与参考 id 78 的最短距离. 由于 coreml 模型在 python 中工作,我认为这是一个预处理问题,所以我在将图像传递给 CoreMLModel 之前自己对图像进行了预处理。这样做给了我一个与参考图像匹配最短距离的参考 id 的一致输出——是的。距离仍然不是零,所以我试图做任何我能想到的来影响图像以获得一些差异,但我不能让它更接近于零。 预处理代码:

+ (CVPixelBufferRef)pixelBufferForImage:(UIImage *)image sideLength:(CGFloat)sideLength 
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(sideLength, sideLength), YES, image.scale);
    [image drawInRect:CGRectMake(0, 0, sideLength, sideLength)];
    UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    CFStringRef keys[2] = kCVPixelBufferCGImageCompatibilityKey, kCVPixelBufferCGBitmapContextCompatibilityKey;
    CFBooleanRef values[2] = kCFBooleanTrue, kCFBooleanTrue;
    CFDictionaryRef attrs = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CVPixelBufferRef buffer;
    int status = CVPixelBufferCreate(kCFAllocatorDefault, (int)(sideLength), (int)(sideLength), kCVPixelFormatType_32ARGB, attrs, &buffer);
    if (status != kCVReturnSuccess) 
        return nil;
    

    CVPixelBufferLockBaseAddress(buffer, kCVPixelBufferLock_ReadOnly);
    void *data = CVPixelBufferGetBaseAddress(buffer);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
    CGContextRef context = CGBitmapContextCreate(data, sideLength, sideLength, 8, CVPixelBufferGetBytesPerRow(buffer), colorSpace, kCGImageAlphaNoneSkipFirst);

    CGContextTranslateCTM(context, 0, sideLength);
    CGContextScaleCTM(context, 1.0, -1.0);

    UIGraphicsPushContext(context);
    [resizedImage drawInRect:CGRectMake(0, 0, sideLength, sideLength)];
    UIGraphicsPopContext();
    CVPixelBufferUnlockBaseAddress(buffer, kCVPixelBufferLock_ReadOnly);
    return buffer;

mlmodel 采用大小为 (224, 224) 的 RGB 图像

我还能对图片做些什么来改善我的结果?

【问题讨论】:

【参考方案1】:

我和你在同一条船上。由于图像预处理涉及到模糊的使用、从 RGB 到灰度的转换等步骤。使用 Objective C++ 包装器会更容易。下面的链接很好地理解了如何使用标头类进行链接。

https://www.timpoulsen.com/2019/using-opencv-in-an-ios-app.html

希望对你有帮助!

图片来源:https://medium.com/@borisohayon/ios-opencv-and-swift-1ee3e3a5735b

【讨论】:

以上是关于如何在将图像提供给 CoreML 模型之前对其进行预处理?的主要内容,如果未能解决你的问题,请参考以下文章

如何在将密码保存到用户模型 Django 之前对其进行加密?

iOS-机器学习框架CoreML

在将 SCNPhysicsVehicleWheels 导入 Xcode 之前对其进行缩放

继续训练 CoreML 模型

多个按需动态加载的 CoreML 模型

如何使用对象检测模型改进 CoreML 图像分类器模型?