serizba / cppflow

Run TensorFlow models in C++ without installation and without Bazel
https://serizba.github.io/cppflow/
MIT License
781 stars 177 forks source link

How to convert tensor to cv::Mat or float array? #98

Closed seungtaek94 closed 3 years ago

seungtaek94 commented 3 years ago

hi.

I'm working on segmentation task.

I successfully load my pre-trained model and get output tensor that has shape (1, 512, 1024).

I want to convert output tensor to cv::Mat.

Any comments is thanks for me :)

serizba commented 3 years ago

Hi @seungtaek94

You can get your result in an std::vector with tensor::get_data<T>(). Then you can create a cv::Mat and put the data there:

//create Mat from vector
vector<float> output_vector = output_tensor.get_data<float>();
Mat m = Mat(512, 1024, CV_32F);
memcpy(m.data, output_vector.data(), output_vector.size()*sizeof(float));

Change float and CV_32F with your type. I haven't tried this, but I guess it should be something similar.

Hope it works!

seungtaek94 commented 3 years ago

@serizba Thanks for your reply.

It works for me with few change. Thanks :)

and another..

How can i make tensor from cv::Mat(CV_8UC3, 3x512x1024)?

I trided like below but it has error when i run it.

cppflow::tensor Mat2Tensor(Mat input, cppflow::tensor imgSize = { 512, 1024 })
{
    std::vector<uchar> vecTensor;

    if (input.isContinuous()) {
        vecTensor.assign(input.data, input.data + input.total() * input.channels());
    }
    else {
        for (int i = 0; i < input.rows; ++i) {
            vecTensor.insert(vecTensor.end(), input.ptr<uchar>(i), input.ptr<uchar>(i) + input.cols * input.channels());
        }
    }

    cppflow::tensor inputTensor = cppflow::tensor(vecTensor, {1, 512, 1024, 3});
    std::cout << inputTensor.shape() << std::endl;
    std::cout << inputTensor << std::endl;

    return  inputTensor;
}
serizba commented 3 years ago

Hi, you can create a vector first, and then create a tensor:

// Read image 
cv::Mat img = cv::imread("test.jpg", cv::IMREAD_COLOR);
int rows = img.rows; int cols = img.cols; int channels = img.channels();

// Put image in tensor 
std::vector<uint8_t > img_data; 
img_data.assign(img.data, img.data + img.total() * channels); 
auto img_tensor = cppflow::tensor(img_data, {rows, cols, channels});

Something similar to this. Hope it helps!

seungtaek94 commented 3 years ago

@serizba

thanks, its really helps for me :)

bmiftah commented 1 year ago

Hi , I am also working on segmenation problem. The model was trained and succecssfully loaded to c++ using the method suggested. I was tring to threshold my model output to generate a binary image . I want to threshold the pixles to certain value and make all pixles either 1 or 0 based on the thresholding reference. here is what I tried based on my search : -

cppflow::model model("model_abdomen"); auto output_tensor = model_abdomen(input); output_tensor = tf.where(outputtensor >0.5, 1, 0) -- hoping to threshold my output at 0.5 , i,e if pixle is > 0.5 1 else 0 . Cany anyone help me to share how to put "output_tensor = tf.where(output_tensor >0.5, 1, 0)_" from cppflow , can I simple do cppflow::tensorflow.where .... In addition , what is the function to change tensorf to image in c++ using the cppflow interfece ..

Thank you.