CoreML forced use 32Bit RGBA as image input?

Hi, I use coremltools convert my .h5 model file to mlmodel file.

The code is bellow:


import coremltools
coreml_model = coremltools.converters.keras.convert('model2.h5',image_input_names='image')
coreml_model.save('mymodel.mlmodel')


My model's input is a 290*200*3 24Bit RGB image.

But after convert to mlmodel, it shows the input is a 32bit RGBA(290*200*4) image at Xcode.

How can I change the mlmodel's input as my model?


Thanks.

Replies

The model should work just fine the way you have it. Just load your image and put it into a CVPixelBuffer and Core ML will automatically ignore the alpha information.


You can also leave off the `image_input_names='image'` parameter when doing the conversion, in which case you'll have to provide your input as an MLMultiArray object. But that's not very convenient.

Hi kerfuffle,


Thnks for your reply. I try your suggestion but it still not working.

What *exactly* does Xcode show?

Hi kerfuffle,


This is my code bellow:

        guard let prediction = try? model.prediction(image: pixelBuffer!) else{
            print("----fail---")
            return
        }


It always show "---fail---" and not reutn the prediction.

I'm not sure what is the exactly error message.


This is my coreml model bellow:

class Input : MLFeatureProvider {

    /// 290x200  image as color (kCVPixelFormatType_32BGRA) image buffer, 200 pixels wide by 290 pixels high

    var image: CVPixelBuffer

    var featureNames: Set<String> {
        get {
            return ["image"]
        }
    }


and this is my code bellow:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
  
        picker.dismiss(animated: true)
        classifier.text = "Analyzing Image..."
        guard let image = info["UIImagePickerControllerOriginalImage"] as? UIImage else {
            return
        } /
  
        UIGraphicsBeginImageContextWithOptions(CGSize(width: 200, height: 290), true, 2.0)
        image.draw(in: CGRect(x: 0, y: 0, width: 200, height: 290))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
  
        let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
        var pixelBuffer : CVPixelBuffer?
        let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(newImage.size.width), Int(newImage.size.height), kCVPixelFormatType_32ARGB, attrs, &pixelBuffer)
        guard (status == kCVReturnSuccess) else {
            return
        }
  
        CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
        let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)
  
  
        let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
        let context = CGContext(data: pixelData, width: Int(newImage.size.width), height: Int(newImage.size.height), bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue) /
        /
  
        context?.translateBy(x: 0, y: newImage.size.height)
        context?.scaleBy(x: 1.0, y: -1.0)

This code is work with Inceptionv3 model.


This is my keras model code:

model = Sequential()
model.add(Conv2D(filters=32,
  kernel_size=(5,5),
  padding='same',
  input_shape=(290,200,3),
  activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(filters=64,
  kernel_size=(5,5),
  padding='same',
  activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(max_dense+1,activation='softmax'))


Thanks for your reply.

Instead of,


        guard let prediction = try? model.prediction(image: pixelBuffer!) else{
            print("----fail---")
            return
        }


do the following:


do {
   let prediction = try model.prediction(image: pixelBuffer!)
   print(prediction)
} catch {
   print(error)
}


What does it print now?