1 | initial version |
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 ¶ms) : 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;
}