Keras 模型到 Coreml 并使用 OpenCV

Posted

技术标签:

【中文标题】Keras 模型到 Coreml 并使用 OpenCV【英文标题】:Keras model to Coreml and using OpenCV 【发布时间】:2018-08-10 05:11:45 【问题描述】:

我有一个 Keras 模型并已成功将其转换为 Coreml。我将 RGB 格式的彩色 50x50 图像传递给模型,一切都在 Python 中的 Keras 模型中运行。但是,我真的很难从 Coreml 模型中获得相同的结果。我在我的 ios 应用程序中使用 OpenCV,需要将 cv::Mat 转换为 CVPixelBufferRef。我很肯定我的输入有问题,但我无法弄清楚它是什么。我发送到 Python 模型的输入的预处理看起来像这样

image = cv2.resize(image, (50, 50)) image = image.astype("float") / 255.0 image = img_to_array(image) image = np.expand_dims(image, axis=0)

任何帮助将不胜感激。下面是从 Keras 到 Coreml 的转换及其输出,以及将 cv::Mat 转换为 CVPixelBufferRef 的函数(这里的图像已经调整为 50x50)。

Keras 到 Coreml 的转换

coreml_model = coremltools.converters.keras.convert(model, input_names='image', image_input_names='image', output_names='output', class_labels=output_labels, image_scale=1/255.0)

OpenCV Mat 到 CVPixelBufferRef

int width = 50;//frame.cols;
int height = 50;//frame.rows;

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                         kCVPixelBufferCGBitmapContextCompatibilityKey,
                         [NSNumber numberWithInt:width], kCVPixelBufferWidthKey,
                         [NSNumber numberWithInt:height], kCVPixelBufferHeightKey,
                         nil];

CVPixelBufferRef imageBuffer;
CVReturn status = CVPixelBufferCreate(kCFAllocatorMalloc, width, height, kCVPixelFormatType_32BGRA, (CFDictionaryRef) CFBridgingRetain(options), &imageBuffer);

NSParameterAssert(status == kCVReturnSuccess && imageBuffer != NULL);

CVPixelBufferLockBaseAddress(imageBuffer, 0);
void *base = CVPixelBufferGetBaseAddress(imageBuffer) ;
memcpy(base, frame.data, frame.total()*4);
CVPixelBufferUnlockBaseAddress(imageBuffer, 0);

return imageBuffer;

【问题讨论】:

通常当这种事情发生时,您的输入与模型所期望的格式不同。由于 OpenCV 以 BGR 顺序加载图像并且您的模型需要 RGB,因此这是我首先要看的地方。也许使用kCVPixelFormatType_32RGBA?此外,将 CVPixelBuffer 转换回图像以在屏幕上显示它也很有用,这样您就可以看到它的实际外观。 谢谢你,我会试一试! 【参考方案1】:

如果您尝试使用 OpenCV 加载图像并将其输入到 Keras 模型中,则需要格外小心,因为 Keras 在训练时默认使用 PIL 加载图像。问题是 PIL 将图像加载为 RGB 格式,而 OpenCV 将图像加载为 BGR 格式。因此,如果您直接将 OpenCV 图像提供给 Keras,您不会收到任何错误,但您的结果将是完全错误的。

至于解决这个问题,在Python中你可以简单地使用

img[...,[0,2]]=img[...,[2,0]]

在 OpenCV 格式和 PIL 格式之间转换 3 通道图像文件。

【讨论】:

是的,我遇到了这个问题并解决了它。最大的问题是 OpenCV 和 CoreGraphics 中的坐标系不同。 cv::Mat 中的 (0,0) 位于左上角,而 CoreGraphics 中的 (0,0) 位于左下角。我必须将图像坐标从 cv::Mat 转换为 CoreGraphics 的坐标系。

以上是关于Keras 模型到 Coreml 并使用 OpenCV的主要内容,如果未能解决你的问题,请参考以下文章