Ask Your Question

Revision history [back]

Here is an implementation based on @berak suggestion :

#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/dnn/layer.details.hpp>
#include <opencv2/dnn/shape_utils.hpp>

using namespace cv;
using namespace std;
using namespace cv::dnn;


class myCropLayer : public Layer
{
public:
    myCropLayer(const LayerParams &params) : Layer(params)
    {
    }

    static cv::Ptr<Layer> create(LayerParams& params)
    {
        return cv::Ptr<Layer>(new myCropLayer(params));
    }

    virtual bool getMemoryShapes(const std::vector<std::vector<int> > &inputs,
                                 const int requiredOutputs,
                                 std::vector<std::vector<int> > &outputs,
                                 std::vector<std::vector<int> > &internals) const CV_OVERRIDE
    {
        CV_UNUSED(requiredOutputs); CV_UNUSED(internals);
        std::vector<int> outShape(4);
        outShape[0] = inputs[0][0];  // batch size
        outShape[1] = inputs[0][1];  // number of channels
        outShape[2] = inputs[1][2];
        outShape[3] = inputs[1][3];
        outputs.assign(1, outShape);
        return false;
    }

    virtual void forward(std::vector<Mat*> &input, std::vector<Mat> &output, std::vector<Mat> &internals) CV_OVERRIDE
    {
         cv::Mat * inp = input[0];
        cv::Mat  out = output[0];
        int ystart = (inp->size[2] - out.size[2]) / 2;
        int xstart = (inp->size[3] - out.size[3]) / 2;
        int yend = ystart + out.size[2];
        int xend = xstart + out.size[3];

        const int batchSize = inp->size[0];
        const int numChannels = inp->size[1];
        const int height = out.size[2];
        const int width = out.size[3];

        int sz[] = { (int)batchSize, numChannels, height, width };
        out.create(4, sz, CV_32F);
        for(int i=0; i<batchSize; i++)
        {
            for(int j=0; j<numChannels; j++)
            {
                cv::Mat plane(inp->size[2], inp->size[3], CV_32F, inp->ptr<float>(i,j));
                cv::Mat crop = plane(cv::Range(ystart,yend), cv::Range(xstart,xend));
                cv::Mat targ(height, width, CV_32F, out.ptr<float>(i,j));
                crop.copyTo(targ);
            }
        }
    }


    virtual void forward(cv::InputArrayOfArrays inputs_arr,
                         cv::OutputArrayOfArrays outputs_arr,
                         cv::OutputArrayOfArrays internals_arr) CV_OVERRIDE
    {
        cerr << "myCropLayer:forward ENTERNING" << endl << flush ;

        std::vector<cv::Mat> inputs, outputs;
        inputs_arr.getMatVector(inputs);
        outputs_arr.getMatVector(outputs);

        cv::Mat& inp = inputs[0];
        cv::Mat& out = outputs[0];

        int ystart = (inp.size[2] - out.size[2]) / 2;
        int xstart = (inp.size[3] - out.size[3]) / 2;
        int yend = ystart + out.size[2];
        int xend = xstart + out.size[3];

        const int batchSize = inp.size[0];
        const int numChannels = inp.size[1];
        const int height = out.size[2];
        const int width = out.size[3];

        int sz[] = { (int)batchSize, numChannels, height, width };
        out.create(4, sz, CV_32F);
        for(int i=0; i<batchSize; i++)
        {
            for(int j=0; j<numChannels; j++)
            {
                cv::Mat plane(inp.size[2], inp.size[3], CV_32F, inp.ptr<float>(i,j));
                cv::Mat crop = plane(cv::Range(ystart,yend), cv::Range(xstart,xend));
                cv::Mat targ(height, width, CV_32F, out.ptr<float>(i,j));
                crop.copyTo(targ);
            }    
};



int main( int argc, char* argv[] )
{

    CV_DNN_REGISTER_LAYER_CLASS(Crop, myCropLayer);
    Net net = readNet("/home/jfeldmar/Code/HED_EdgeDetection/Edge_detection/deploy.prototxt", "/home/jfeldmar/Code/HED_EdgeDetection/Edge_detection/hed_pretrained_bsds.caffemodel");


     cv::Mat img = cv::imread("/home/jfeldmar/Code/HED_EdgeDetection/Edge_detection/colin_mcalpin.jpg");
    cv::Size reso(128,128);
    Mat theInput ;
    resize( img, theInput, reso ) ;
    cv::Mat blob = blobFromImage(theInput, 1.0, reso, cv::Scalar(104.00698793, 116.66876762, 122.67891434), false, false);


    net.setInput(blob);
    cv::Mat out = net.forward(); // outputBlobs contains all output blobs for each layer specified in outBlobNames.

    std::vector<cv::Mat> vectorOfImagesFromBlob;
    imagesFromBlob( out,    vectorOfImagesFromBlob);
    cv::Mat tmpMat = vectorOfImagesFromBlob[0] *255;
    Mat tmpMatUchar;
    tmpMat.convertTo(tmpMatUchar, CV_8U);

    // old code cv::Mat tmpMat = out.reshape(1, reso.height) ;
    cv::resize(tmpMatUchar, out, img.size());

    cv::imshow("out", out);
    cv::waitKey();

    return 0;
}