[C++] Using DNN with Tiny Yolo v2, not getting 13x13 (just 125 x 1)

asked 2019-12-20 10:40:29 -0600

exbigboss gravatar image

updated 2019-12-22 13:12:12 -0600

berak gravatar image

Hey all,

I'm trying to use this model as a test reference: https://github.com/onnx/models/tree/m...

They claim the output is supposed to be a 1x125x13x13 but I'm not sure I'm getting that...

My OpenCV version is 4.1.1.

I can see that I get a [125 x 1] but I'm not sure where the 13x13 is supposed to come from or how I'm supposed to process these results into getting the bounding box data...

Here's my code below:

#include <opencv2/dnn/dnn.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>

#include <gsl/span>

#include <vector>
#include <iostream>
#include <cassert>

int main()
{
    auto img = cv::imread("/home/christian/Downloads/horse.jpg");

    assert(img.channels() == 3);
    assert(img.depth() == CV_8U);

    img.convertTo(img, CV_32F);
    cv::resize(img, img, cv::Size(416, 416));

    assert(img.cols == 416);
    assert(img.rows == 416);
    assert(img.channels() == 3);
    assert(img.depth() == CV_32F);

    auto model = cv::String("/home/christian/Downloads/tiny_yolov2 (1)/tiny_yolov2/model.onnx");
    auto net   = cv::dnn::readNet(model);

    auto outLayers    = net.getUnconnectedOutLayers();
    auto outLayerType = net.getLayer(outLayers[0])->type;
    std::cout << "layer type is : " << outLayerType << "\n";

    auto layerNames = net.getLayerNames();
    std::cout << layerNames.size() << "\n";
    for (auto const& name : layerNames)
    {
        std::cout << name << "\n";
    }

    auto blob = cv::Mat();
    cv::dnn::blobFromImage(img, blob, 1.0 / 255, cv::Size(416, 416), cv::Scalar(0, 0, 0), true, false, CV_32F);

    net.setInput(blob);

    auto outs = std::vector<std::vector<cv::Mat>>();
    outs.resize(13);
    for (auto& out : outs)
    {
        out.resize(13);
    }

    auto outNames = net.getUnconnectedOutLayersNames();
    net.forward(outs, outNames);

    for (auto const& out : outs)
    {
        std::cout << out.size() << "\n";
        auto& o = out[0];
        std::cout << o.size() << "\n";
        std::cout << o.rows << ", " << o.cols << "\n";
    }

    return 0;
}
edit retag flag offensive close merge delete

Comments

1

in general, use cout << blob.size not cout << blob.size() for multidimensional Mat's

(blob.rows and blob.cols will be invalid / -1 in this case)

berak gravatar imageberak ( 2019-12-20 11:28:17 -0600 )edit
1

Great tip! I just tried cout << blob.size << "\n"; and I actually got: 1 x 125 x 13 x 13! So there was the 13x13 there the whole time lol.

Now I just gotta figure out how to properly access the underlying data...

exbigboss gravatar imageexbigboss ( 2019-12-20 11:36:24 -0600 )edit
1

i haven't tried yolo2 (and afaik, we don't have a sample) but the receipe might look like:

// assuming 1 x 125 x 13 x 13
// loop over channels
for (int c=0; c<125; c++) {
        // get a 13x13 slice for each channel:
        Mat x(13, 13, CV_32F, blob.ptr<float>(0,c));
        // do something with x
}
berak gravatar imageberak ( 2019-12-20 12:50:58 -0600 )edit