Search code examples
c++opencvblobcaffeproto

OpenCV cv::dnn::Net::getBlob return dnn::Blob::matRefConst has rows == -1 and cols == -1


Screenshot: wrong result of getBlob returned:

image here

here is addition code:

resize(img, img, Size(224, 224));

dnn::Blob inputBlob = dnn::Blob::fromImages(img); 
net.setBlob(".data", inputBlob); 
net.forward(); 
dnn::Blob prob = net.getBlob( "loss1"/*"prob"*/); 

and prototxt file: # name: "nin_imagenet" # next five line is changed compared to caffe's prototxt # i delete the layers who has top: "data" input: "data" # input name input_dim: 1 # batchsize
input_dim: 3 # number of channels input_dim: 224 # width input_dim: 224 # height

# unchaged text
# ...

# another changed compared to caffe's prototxt
# i delete layers who has **bottom: "label"**  
layers {
  name: "loss1"
  type: SOFTMAX
  bottom: "fc81"
  top: "loss1"
}
# changed below

Solution

  • I think it because you deal with 4D blob, not a matrix, size is stored in size array (see below example). Try to extract planes using this code piece:

    //-------------------------------------------------------
    // Extract plane with defined n and c from nchw blob
    //-------------------------------------------------------
    void mtcnn::extractPlane(Mat &src, int n, int ch, Mat &dst)
    {
        const int rows = src.size[2];
        const int cols = src.size[3];
        dst = cv::Mat::zeros(rows, cols, CV_32FC1);
    
        for (int row = 0; row < rows; row++)
        {
            const float *ptrsrc = src.ptr<float>(n, ch, row);
            float *ptrdst = dst.ptr<float>(row);
            for (int col = 0; col < cols; col++)
            {
                ptrdst[col] = ptrsrc[col];
            }
        }
    } 
    

    Hope you use something like this to set input data:

            inputBlob = blobFromImage(img, 0.0078125, Size(ws, hs), Scalar(127.5, 127.5, 127.5)); //Convert Mat to batch of images
            p_net.setInput(inputBlob, "data"); //set the network input