Multiple ONNX models using opencv and c++ for inference - c++

I am trying to load, multiple ONNX models, whereby I can process different inputs inside the same algorithm. Let's assume that model 1 would receive as input an image and output a set of 6 values (int) related to this image. The second model would also receive an image but output a binary classification instead.
So far, I have managed to successfully run on a single model. However when I try to load the second one I got an error:
// Load first .onnx model using OpenCV's DNN module
cv::dnn::Net net = cv::dnn::readNet("model_1.onnx");
net.setPreferableBackend(cv::dnn::DNN_BACKEND_DEFAULT);
net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
// Load second .onnx model using OpenCV's DNN module
cv::dnn::Net net_2 = cv::dnn::readNet("model_2.onnx");
net_2.setPreferableBackend(cv::dnn::DNN_BACKEND_DEFAULT);
net_2.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
Everything runs without errors until this point. But I got errors when trying to retrieve data from the second model.
// Forward first model
net.setInput(blob);
net.forward(output_blobs, output_names);
// Forward second model
net_2.setInput(blob);
net_2.forward(output_blobs_2, output_names_2);
Any help or advice will be more than welcome.

Related

Approach to get the weight values from the pre-trained weights from Darknet?

I'm currently trying to implement YOLOv3 object detection model in C(only detection, not training).
I have tested my convolution method with arbitrary values and it seems to be working as I expected.
Before stacking up multiple method calls to do forward propagation, I thought it would be safe to test with the actual pretrained weight file data.
When I look up Darknet's pre-trained weight file, it was a huge chunk of binary files. I tried to convert it to hex and decimals, but it still doesn't look simple to pinpoint what part of values to use.
So, my question is, what should I do to extract the decimal numbers of the weights or the filter values so that I can use them in the same order of the forward propagation happening in YOLOv3?
*I'm currently trying to build my c version of YOLOv3 using the structure image shown in https://www.itread01.com/content/1541167345.html
*My c code will be run on an FPGA board called MicroZed, along with other HDL code.
*I tried to plug some printf functions into some places of Darknet code to see what kinds of data are moving around when YOLOv3 runs, however, when I ran it on in Linux terminal, it didn't show anything new and kept outputting the same results.
Any help or advice will be really appreciated. Thank you!
I am not too sure if there is a direct way to read darknet weights, but you can convert it into .h5 format and obtain the weight values from it
You can convert the darknet yolov3 weights into .h5 format (used by keras) by using the appropriate command from this repository.
You can choose the command based on your Yolo version from the list shown in the ReadMe of the linked repo. For the standard yolov3, the command for converting is
python tools/model_converter/convert.py cfg/yolov3.cfg weights/yolov3.weights weights/yolov3.h5
Once you have the .h5weights, you can use the below code snippet for obtaining the
values from the weights. credit/source
import h5py
path = "<path to weights>.h5"
weights = {}
keys = []
with h5py.File(path, 'r') as f: # open file
f.visit(keys.append) # append all keys to list
for key in keys:
if ':' in key: # contains data if ':' in key
param_name = f[key].name
weights[f[key].name] = f[key].value
print(param_name,weights[f[key].name])

Export Weka Fiji plugin segmentation as ROI

I am using Imagej/Fiji Weka plugin for classifying different regions of the image and I would like to obtain those regions for further processing… (as Rois? a table with the classes?)
So in the end I want to get the area for each of the segmented classes.. I need to script this task as it is part of a pipeline… But not sure how to do extract the results from Weka Imagej Plugin…
Actually this code example is just to illustrate the idea.. Anyone has a basic example on applying a classifier and exporting results?
Thank you in advance
import trainableSegmentation.*;
import ij.IJ;
import ij.ImagePlus;
// input train image
input = IJ.openImage( someImage.jpg" );
// create Weka Segmentation object
segmentator = new WekaSegmentation( input );
// load classifier from file
segmentator.loadClassifier( "classifier.model" );
result = segmentator.applyClassifier( input );
...
You have a couple of answers about that in the image.sc forum: https://forum.image.sc/t/measuring-area-fraction-in-a-weka-classifed-image/7979
https://forum.image.sc/t/quantifing-weka-output/4660/6
That being said, you can also directly use the resulting label image for measurement within other plugins, such as the ones from MorphoLibJ (after installation, under Plugins > MorphoLibJ > Analyze).

On loading the saved Keras sequential model, my test data gives low accuracy in the beginning

I am creating a simple sequential Keras model which will take 10k inputs in a batch of 100. Each input has 3 columns and the corresponding output is sum of that row.
Sequential model has 2 layers- LSTM(Stateful=true) , Dense.
Now, after compiling and fitting the model, I am saving it in 'model.h5' file.
Then, I read the saved model, and call model.predict with a test data (size=10k , batch_size = 100).
Problem: the prediction doesn't work properly for first 400-500 inputs and for the rest its working perfectly fine with very low val_loss.
Case1: I make the LSTM layer Stateless(i.e. Stateful=False)
In this case Keras is providing very accurate outputs for all the test data.
Case2: Instead of saving and then reading again, if I directly apply model.predict on the model created, all the outputs are coming accurately.
But, I need Stateful=True, also, I want to save my model and then resume work on that model later.
1.Is there any way to solve this?
2.Also, when I am providing test data, how is the model's accuracy increasing? ( because the first 400-500 tests provide inaccurate results and the rest are pretty accurate)
Your problem seems to come from losing the hidden states of your cells. During model building they might be reset and this might cause the problem.
So (it's a little bit cumbersome), but you could save and load also a states of your network:
How to save? (assuming that i-th layer is a recurrentone):
hidden_state = model.layers[i].states[0].eval()
cell_state = model.layers[i].states[0].eval()
numpy.save("some name", hidden_state)
numpy.save("some other name", cell_state)
Now when you can reload the hidden state, here you can read on how to set the hidden state in a layer.
Of course - it's the best to pack all of this methods in some kind of object and e.g. class constructor methods.

Unable to deploy a Cloud ML model

Why I try to deploy my trained model to Google Cloud ML, I get the following error:
Create Version failed.Model validation failed: Model metagraph does not have inputs collection.
What does this mean and how to get around this?
The Tensorflow model deployed on CloudML did not have a collection named “inputs”. This collection should name all the input tensors for your graph. Similarly, a collection named “outputs” is required to name the output tensors for your graph. Assuming your graph has two input tensors x and y, and one output tensor scores, this can be done as follows:
tf.add_to_collection(“inputs”, json.dumps({“x” : x.name, “y”: y.name}))
tf.add_to_collection(“outputs”, json.dumps({“scores”: scores.name}))
Here “x”, “y” and “scores” become aliases to the actual tensor names (x.name, y.name and scores.name)

Caffe GoogleNet classification.cpp gives random outputs

I used Caffe GoogleNet model to train my own data (10k images, 2 classes). I stop it at 400000th iteration with an accuracy of ~80%.
If I run the below command:
./build/examples/cpp_classification/classification.bin
models/bvlc_googlenet/deploy.prototxt
models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel
data/ilsvrc12/imagenet_mean.binaryproto
data/ilsvrc12/synset_words.txt
1.png
it gives me a different -- apparently random -- result each time (i.e. if I run it n times, then I get n different results). Why? Does my training fail? Does it still use the old data from the reference model?
I don't think it is a problem with the training. Even if the training data wasn't, it should give the same (possibly wrong) output every time. If you are getting random results, it indicates that the weights are not being loaded properly.
When you load a .caffemodel against a .prototxt, caffe will load the weights of all the layers in the prototxt whose names match with the ones in the caffemodel. For the other layers, it will do a random initialisation (gaussian xavier, etc according to the specification in the prototxt).
So the best thing for you to do now is to check if the model was trained using the same prototxt you are using now.
I see that you are using GoogleNet prototxt and reference_caffenet caffemodel. Is this intentional?
When you want to deploy the fine-tuned model, you should check two main things:
Inputs:
Input image uses a BGR channel instead of RGB (e.g. opencv)
Mean file: Is same as mean file when training?
Prototxt:
When fine-tuning the model, you will change some layers' name in the original prototxt, and you should check whether the same layer name used?
And there are some
Fine-tune tricks and CS231n_transfer_learning which are very useful for fine-tuning.