Search code examples
pythonc++kerashdf5

Running Keras DNN model (UNet) using OpenCV readNetFromTensorFlow: Error: Unknown layer type Shape in op decoder_stage0_upsampling/Shape


Python version 3.7

Keras version 2.3.1

TensorFlow version 1.14.0

I am wanting to run my UNet Keras model using OpenCV's readNetFromTensorflow in C++. I have successfully converted my HDF5 file to .pb per this issue: How we can convert keras model .h5 file to tensorflow saved model (.pb)

However when I try and run the command (in python first for ease of testing):

net = cv.dnn.readNetFromTensorflow('tensorflow/my_model.pb')

I receive the failure:

error: (-2) Unknown layer type Shape in op decoder_stage0_upsampling/Shape in function cv::dnn::experimental_dnn_v2::`anonymous-namespace'::TFImporter::populateNet

Is there a workaround to this using OpenCV? Or will using Tensorflows C++ API be best in this situation.


Solution

  • I have solved my problem and will add my solution here for anyone else looking to perform inference with OpenCV on their own UNet.

    Step 1: Convert H5/HDF5 file to .pb as stated in my above question.

    Step 2: OpenCV must be upgraded to 4.2.0 (not sure if my solution is supported in anything else between 3.3.1 [my starting OpenCV Version] and 4.2.0)

    Step 3: Load your network as described in the code in my question, this should be successful. Once done, load your image and use cv2.blobFromImage() to construct a blob, then set your input, and lastly perform inference:

    blob = cv.dnn.blobFromImage(image, 1 / 255.0, (256,256), swapRB=True)
    net.setInput(blob)
    out = net.forward()
    

    View your output: You will end up with a (1,1,x,y) shape. Reshape your output using your desired function (in my case I just use np.resize()). Plot your output and view your results!

    Hope this helps others who do not want to deal with TensorFlow C++ API and need to get a relatively good working C++ inference setup.

    Edit: As a note I should mention I have yet to test this with the C++ OpenCV library. I plan on doing this in the next week or so. If this solution does not work similarly in C++, I will note it here.

    Edit 2: Tested and working well in C++