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的主要内容,如果未能解决你的问题,请参考以下文章

tf.keras 模型到 coreml 模型,不支持 BatchNormalization

.h5 keras 模型到 coreml 的分类转换在 IOS 中不起作用

如何将 Turi Create 创建的 CoreML 模型转换为 Keras?

如何在 Keras 中生成 class_labels.txt 以在 CoreML 模型中使用?

如何在 TensorFlow、Keras 或 PyTorch 中部署 CoreML 模型?

将 keras 模型转换为 coreml 时出错(“InputLayer”对象不可迭代)