|
|
|
@ -54,12 +54,74 @@ namespace dnn |
|
|
|
|
class BaseConvolutionLayerImpl : public ConvolutionLayer |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
BaseConvolutionLayerImpl(); |
|
|
|
|
virtual void allocate(const std::vector<Mat*> &inputs, std::vector<Mat> &outputs); |
|
|
|
|
BaseConvolutionLayerImpl() |
|
|
|
|
{ |
|
|
|
|
numOutput = -1; |
|
|
|
|
group = -1; |
|
|
|
|
inpH = inpW = inpCn = 0; |
|
|
|
|
outH = outW = outCn = 0; |
|
|
|
|
inpGroupCn = outGroupCn = 0; |
|
|
|
|
ksize = 0; |
|
|
|
|
bias = false; |
|
|
|
|
#ifdef HAVE_LAPACK |
|
|
|
|
int nthreads = cv::getThreadNum(); |
|
|
|
|
if (getBlasThreads() != nthreads) |
|
|
|
|
{ |
|
|
|
|
setBlasThreads(nthreads); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
void allocate(const std::vector<Mat*> &inputs, std::vector<Mat> &outputs) |
|
|
|
|
{ |
|
|
|
|
CV_Assert(inputs.size() > 0); |
|
|
|
|
|
|
|
|
|
init(); |
|
|
|
|
|
|
|
|
|
const Mat &input = *inputs[0]; |
|
|
|
|
CV_Assert(input.dims == 4 && (input.type() == CV_32F || input.type() == CV_64F)); |
|
|
|
|
for (size_t i = 0; i < inputs.size(); i++) |
|
|
|
|
{ |
|
|
|
|
CV_Assert(inputs[i]->type() == input.type()); |
|
|
|
|
CV_Assert(inputs[i]->dims == 4 && inputs[i]->size[1] == input.size[1]); |
|
|
|
|
CV_Assert(inputs[i]->size[2] == input.size[2] && inputs[i]->size[3] == input.size[3]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
computeInpOutShape(input); |
|
|
|
|
|
|
|
|
|
if (bias) |
|
|
|
|
{ |
|
|
|
|
biasOnesBlob.create(1, outH * outW, input.type()); |
|
|
|
|
biasOnesBlob.setTo(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void init(); |
|
|
|
|
outputs.resize(inputs.size()); |
|
|
|
|
for (size_t i = 0; i < inputs.size(); i++) |
|
|
|
|
{ |
|
|
|
|
int sz[] = { inputs[i]->size[0], outCn, outH, outW }; |
|
|
|
|
outputs[i].create(4, sz, input.type()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!is1x1()) |
|
|
|
|
{ |
|
|
|
|
colRowBlob.create((int)colRowBlobShape.size(), &colRowBlobShape[0], input.type()); |
|
|
|
|
colRowBlob.setTo(0); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void init() |
|
|
|
|
{ |
|
|
|
|
CV_Assert(blobs.size() >= 1 && blobs.size() <= 2); |
|
|
|
|
CV_Assert(blobs[0].dims == 4 && blobs[0].size[3] == kernel.width && blobs[0].size[2] == kernel.height); |
|
|
|
|
|
|
|
|
|
bias = (blobs.size() >= 2); |
|
|
|
|
} |
|
|
|
|
virtual void computeInpOutShape(const Mat &inpBlob) = 0; |
|
|
|
|
bool is1x1() const; |
|
|
|
|
bool is1x1() const |
|
|
|
|
{ |
|
|
|
|
return (kernel.height == 1 && kernel.width == 1) && |
|
|
|
|
(stride.height == 1 && stride.width == 1) && |
|
|
|
|
(dilation.height == 1 && dilation.width == 1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int numOutput, group; |
|
|
|
|
int inpH, inpW, inpCn; |
|
|
|
@ -76,306 +138,185 @@ public: |
|
|
|
|
class ConvolutionLayerImpl : public BaseConvolutionLayerImpl |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
virtual void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs); |
|
|
|
|
virtual void computeInpOutShape(const Mat &inpBlob); |
|
|
|
|
|
|
|
|
|
void im2col(const Mat &srcImg, Mat &dstCol); |
|
|
|
|
void im2row(const Mat &srcImg, Mat &dstRow); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class DeConvolutionLayerImpl : public BaseConvolutionLayerImpl |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
virtual void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs); |
|
|
|
|
|
|
|
|
|
virtual void computeInpOutShape(const Mat &inpBlob); |
|
|
|
|
void col2im(const Mat &colMat, Mat &dstImg); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BaseConvolutionLayerImpl::BaseConvolutionLayerImpl(): |
|
|
|
|
numOutput(-1), group(-1), |
|
|
|
|
inpH(0), inpW(0), inpCn(0), |
|
|
|
|
outH(0), outW(0), outCn(0), |
|
|
|
|
inpGroupCn(0), outGroupCn(0), |
|
|
|
|
ksize(0), bias(false) |
|
|
|
|
{ |
|
|
|
|
#ifdef HAVE_LAPACK |
|
|
|
|
if (getBlasThreads() != cv::getThreadNum()) |
|
|
|
|
void computeInpOutShape(const Mat &input) |
|
|
|
|
{ |
|
|
|
|
setBlasThreads(cv::getThreadNum()); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
CV_Assert(!bias || blobs[1].total() == (size_t)blobs[0].size[0]); |
|
|
|
|
|
|
|
|
|
void BaseConvolutionLayerImpl::init() |
|
|
|
|
{ |
|
|
|
|
CV_Assert(blobs.size() >= 1 && blobs.size() <= 2); |
|
|
|
|
CV_Assert(blobs[0].dims == 4 && blobs[0].size[3] == kernel.width && blobs[0].size[2] == kernel.height); |
|
|
|
|
numOutput = blobs[0].size[0]; |
|
|
|
|
|
|
|
|
|
bias = (blobs.size() >= 2); |
|
|
|
|
} |
|
|
|
|
inpH = input.size[2]; |
|
|
|
|
inpW = input.size[3]; |
|
|
|
|
inpCn = input.size[1]; |
|
|
|
|
outCn = numOutput; |
|
|
|
|
|
|
|
|
|
void BaseConvolutionLayerImpl::allocate(const std::vector<Mat*> &inputs, std::vector<Mat> &outputs) |
|
|
|
|
{ |
|
|
|
|
CV_Assert(inputs.size() > 0); |
|
|
|
|
|
|
|
|
|
init(); |
|
|
|
|
if (padMode.empty()) |
|
|
|
|
{ |
|
|
|
|
outH = (inpH + 2 * pad.height - (dilation.height * (kernel.height - 1) + 1)) / stride.height + 1; |
|
|
|
|
outW = (inpW + 2 * pad.width - (dilation.width * (kernel.width - 1) + 1)) / stride.width + 1; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
getConvPoolOutParams(inpH, inpW, kernel, stride, pad, padMode, outH, outW); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const Mat &input = *inputs[0]; |
|
|
|
|
CV_Assert(input.dims == 4 && (input.type() == CV_32F || input.type() == CV_64F)); |
|
|
|
|
for (size_t i = 0; i < inputs.size(); i++) |
|
|
|
|
{ |
|
|
|
|
CV_Assert(inputs[i]->type() == input.type()); |
|
|
|
|
CV_Assert(inputs[i]->dims == 4 && inputs[i]->size[1] == input.size[1]); |
|
|
|
|
CV_Assert(inputs[i]->size[2] == input.size[2] && inputs[i]->size[3] == input.size[3]); |
|
|
|
|
} |
|
|
|
|
group = inpCn / blobs[0].size[1]; |
|
|
|
|
|
|
|
|
|
computeInpOutShape(input); |
|
|
|
|
CV_Assert(inpCn % group == 0 && outCn % group == 0); |
|
|
|
|
CV_Assert(blobs[0].size[0] == outCn && blobs[0].size[1] == inpCn / group); |
|
|
|
|
|
|
|
|
|
if (bias) |
|
|
|
|
{ |
|
|
|
|
biasOnesBlob.create(1, outH * outW, input.type()); |
|
|
|
|
biasOnesBlob.setTo(1); |
|
|
|
|
} |
|
|
|
|
outGroupCn = outCn / group; |
|
|
|
|
inpGroupCn = inpCn / group; |
|
|
|
|
ksize = inpGroupCn * kernel.height * kernel.width; |
|
|
|
|
|
|
|
|
|
outputs.resize(inputs.size()); |
|
|
|
|
for (size_t i = 0; i < inputs.size(); i++) |
|
|
|
|
{ |
|
|
|
|
int sz[] = { inputs[i]->size[0], outCn, outH, outW }; |
|
|
|
|
outputs[i].create(4, sz, input.type()); |
|
|
|
|
colRowBlobShape.clear(); |
|
|
|
|
colRowBlobShape.push_back(outH*outW); |
|
|
|
|
colRowBlobShape.push_back(ksize); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!is1x1()) |
|
|
|
|
void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs) |
|
|
|
|
{ |
|
|
|
|
colRowBlob.create((int)colRowBlobShape.size(), &colRowBlobShape[0], input.type()); |
|
|
|
|
colRowBlob.setTo(0); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
CV_Assert(inputs.size() > 0); |
|
|
|
|
|
|
|
|
|
bool BaseConvolutionLayerImpl::is1x1() const |
|
|
|
|
{ |
|
|
|
|
return (kernel.height == 1 && kernel.width == 1) && |
|
|
|
|
(stride.height == 1 && stride.width == 1) && |
|
|
|
|
(dilation.height == 1 && dilation.width == 1); |
|
|
|
|
} |
|
|
|
|
Mat weightsMat = blobs[0].reshape(1, outCn); |
|
|
|
|
Mat biasesMat = bias ? blobs[1].reshape(1, outCn) : Mat(); |
|
|
|
|
|
|
|
|
|
void ConvolutionLayerImpl::computeInpOutShape(const Mat &input) |
|
|
|
|
{ |
|
|
|
|
CV_Assert(!bias || blobs[1].total() == (size_t)blobs[0].size[0]); |
|
|
|
|
|
|
|
|
|
numOutput = blobs[0].size[0]; |
|
|
|
|
|
|
|
|
|
inpH = input.size[2]; |
|
|
|
|
inpW = input.size[3]; |
|
|
|
|
inpCn = input.size[1]; |
|
|
|
|
outCn = numOutput; |
|
|
|
|
|
|
|
|
|
if (padMode.empty()) |
|
|
|
|
{ |
|
|
|
|
outH = (inpH + 2 * pad.height - (dilation.height * (kernel.height - 1) + 1)) / stride.height + 1; |
|
|
|
|
outW = (inpW + 2 * pad.width - (dilation.width * (kernel.width - 1) + 1)) / stride.width + 1; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
getConvPoolOutParams(inpH, inpW, kernel, stride, pad, padMode, outH, outW); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
group = inpCn / blobs[0].size[1]; |
|
|
|
|
|
|
|
|
|
CV_Assert(inpCn % group == 0 && outCn % group == 0); |
|
|
|
|
CV_Assert(blobs[0].size[0] == outCn && blobs[0].size[1] == inpCn / group); |
|
|
|
|
|
|
|
|
|
outGroupCn = outCn / group; |
|
|
|
|
inpGroupCn = inpCn / group; |
|
|
|
|
ksize = inpGroupCn * kernel.height * kernel.width; |
|
|
|
|
|
|
|
|
|
colRowBlobShape.clear(); |
|
|
|
|
colRowBlobShape.push_back(outH*outW); |
|
|
|
|
colRowBlobShape.push_back(ksize); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ConvolutionLayerImpl::forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs) |
|
|
|
|
{ |
|
|
|
|
CV_Assert(inputs.size() > 0); |
|
|
|
|
|
|
|
|
|
Mat weightsMat = blobs[0].reshape(1, outCn); |
|
|
|
|
Mat biasesMat = bias ? blobs[1].reshape(1, outCn) : Mat(); |
|
|
|
|
|
|
|
|
|
for (size_t ii = 0; ii < outputs.size(); ii++) |
|
|
|
|
{ |
|
|
|
|
int numImg = inputs[ii]->size[0]; |
|
|
|
|
Mat inpMat = *inputs[ii]; |
|
|
|
|
Mat outMat = outputs[ii].reshape(1, numImg*group*outGroupCn); |
|
|
|
|
|
|
|
|
|
for (int n = 0; n < numImg; n++) |
|
|
|
|
for (size_t ii = 0; ii < outputs.size(); ii++) |
|
|
|
|
{ |
|
|
|
|
for (int g = 0; g < group; g++) |
|
|
|
|
int numImg = inputs[ii]->size[0]; |
|
|
|
|
Mat inpMat = *inputs[ii]; |
|
|
|
|
Mat outMat = outputs[ii].reshape(1, numImg*group*outGroupCn); |
|
|
|
|
|
|
|
|
|
for (int n = 0; n < numImg; n++) |
|
|
|
|
{ |
|
|
|
|
Mat colMat, curInp = slice(inpMat, n, _Range(g * inpGroupCn, inpGroupCn)); |
|
|
|
|
for (int g = 0; g < group; g++) |
|
|
|
|
{ |
|
|
|
|
Mat curInp = slice(inpMat, n, _Range(g * inpGroupCn, inpGroupCn)); |
|
|
|
|
|
|
|
|
|
im2row(curInp, colMat); |
|
|
|
|
im2row(curInp, colRowBlob); |
|
|
|
|
|
|
|
|
|
_Range kerRange(g * outGroupCn, outGroupCn); |
|
|
|
|
Mat kerMat = weightsMat.rowRange(kerRange); |
|
|
|
|
_Range kerRange(g * outGroupCn, outGroupCn); |
|
|
|
|
Mat kerMat = weightsMat.rowRange(kerRange); |
|
|
|
|
|
|
|
|
|
_Range outRange((g + n * group) * outGroupCn, outGroupCn); |
|
|
|
|
Mat dstMat = outMat.rowRange(outRange); |
|
|
|
|
_Range outRange((g + n * group) * outGroupCn, outGroupCn); |
|
|
|
|
Mat dstMat = outMat.rowRange(outRange); |
|
|
|
|
|
|
|
|
|
dnn::gemm(kerMat, colMat, 1, dstMat, 0, GEMM_2_T); |
|
|
|
|
dnn::gemm(kerMat, colRowBlob, 1, dstMat, 0, GEMM_2_T); |
|
|
|
|
|
|
|
|
|
if (bias) |
|
|
|
|
{ |
|
|
|
|
dnn::gemm(biasesMat.rowRange(kerRange), biasOnesBlob, 1, dstMat, 1); |
|
|
|
|
if (bias) |
|
|
|
|
{ |
|
|
|
|
dnn::gemm(biasesMat.rowRange(kerRange), biasOnesBlob, 1, dstMat, 1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ConvolutionLayerImpl::im2col(const Mat &srcImg, Mat &dstCol) |
|
|
|
|
{ |
|
|
|
|
if (is1x1()) |
|
|
|
|
void im2row(const Mat &srcImg, Mat &dstRow) |
|
|
|
|
{ |
|
|
|
|
dstCol = srcImg.reshape(1, ksize); |
|
|
|
|
return; |
|
|
|
|
if (is1x1()) |
|
|
|
|
{ |
|
|
|
|
transpose(srcImg.reshape(1, ksize), dstRow); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
cv::dnn::im2row(srcImg.ptr<float>(), inpGroupCn, inpH, inpW, kernel.height, |
|
|
|
|
kernel.width, pad.height, pad.width, stride.height, stride.width, |
|
|
|
|
dilation.height, dilation.width, outH, outW, dstRow.ptr<float>()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
Mat &colMat = colRowBlob; |
|
|
|
|
if (srcImg.type() == CV_32F) |
|
|
|
|
im2col_CpuPBody<float>::run(srcImg.ptr<float>(), inpGroupCn, inpH, inpW, kernel.height, |
|
|
|
|
kernel.width, pad.height, pad.width, stride.height, stride.width, |
|
|
|
|
dilation.height, dilation.width, outH, outW, colMat.ptr<float>()); |
|
|
|
|
if (srcImg.type() == CV_64F) |
|
|
|
|
im2col_CpuPBody<double>::run(srcImg.ptr<double>(), inpGroupCn, inpH, inpW, kernel.height, |
|
|
|
|
kernel.width, pad.height, pad.width, stride.height, stride.width, |
|
|
|
|
dilation.height, dilation.width, outH, outW, colMat.ptr<double>()); |
|
|
|
|
|
|
|
|
|
dstCol = colMat; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ConvolutionLayerImpl::im2row(const Mat &srcImg, Mat &dstRow) |
|
|
|
|
class DeConvolutionLayerImpl : public BaseConvolutionLayerImpl |
|
|
|
|
{ |
|
|
|
|
if (is1x1()) |
|
|
|
|
public: |
|
|
|
|
void computeInpOutShape(const Mat &inpBlob) |
|
|
|
|
{ |
|
|
|
|
dstRow = srcImg.reshape(1, ksize).t(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Mat &colMat = colRowBlob; |
|
|
|
|
if (srcImg.type() == CV_32F) |
|
|
|
|
im2row_CpuPBody<float>::run(srcImg.ptr<float>(), inpGroupCn, inpH, inpW, kernel.height, |
|
|
|
|
kernel.width, pad.height, pad.width, stride.height, stride.width, |
|
|
|
|
dilation.height, dilation.width, outH, outW, colMat.ptr<float>()); |
|
|
|
|
if (srcImg.type() == CV_64F) |
|
|
|
|
im2row_CpuPBody<double>::run(srcImg.ptr<double>(), inpGroupCn, inpH, inpW, kernel.height, |
|
|
|
|
kernel.width, pad.height, pad.width, stride.height, stride.width, |
|
|
|
|
dilation.height, dilation.width, outH, outW, colMat.ptr<double>()); |
|
|
|
|
|
|
|
|
|
dstRow = colMat; |
|
|
|
|
} |
|
|
|
|
CV_Assert(!bias || blobs[1].total() == (size_t)blobs[0].size[0]); |
|
|
|
|
|
|
|
|
|
//Deconvolution
|
|
|
|
|
numOutput = blobs[0].size[0]; |
|
|
|
|
|
|
|
|
|
void DeConvolutionLayerImpl::computeInpOutShape(const Mat &inpBlob) |
|
|
|
|
{ |
|
|
|
|
CV_Assert(!bias || blobs[1].total() == (size_t)blobs[0].size[0]); |
|
|
|
|
inpH = inpBlob.size[2]; |
|
|
|
|
inpW = inpBlob.size[3]; |
|
|
|
|
inpCn = inpBlob.size[1]; |
|
|
|
|
|
|
|
|
|
numOutput = blobs[0].size[0]; |
|
|
|
|
outH = stride.height * (inpH - 1) + kernel.height - 2 * pad.height + adjustPad.height; |
|
|
|
|
outW = stride.width * (inpW - 1) + kernel.width - 2 * pad.width + adjustPad.width; |
|
|
|
|
outCn = numOutput; |
|
|
|
|
|
|
|
|
|
inpH = inpBlob.size[2]; |
|
|
|
|
inpW = inpBlob.size[3]; |
|
|
|
|
inpCn = inpBlob.size[1]; |
|
|
|
|
group = inpCn / blobs[0].size[1]; |
|
|
|
|
outGroupCn = outCn / group; |
|
|
|
|
inpGroupCn = inpCn / group; |
|
|
|
|
ksize = outGroupCn * kernel.height * kernel.width; |
|
|
|
|
|
|
|
|
|
outH = stride.height * (inpH - 1) + kernel.height - 2 * pad.height + adjustPad.height; |
|
|
|
|
outW = stride.width * (inpW - 1) + kernel.width - 2 * pad.width + adjustPad.width; |
|
|
|
|
outCn = numOutput; |
|
|
|
|
CV_Assert(inpCn % group == 0 && outCn % group == 0); |
|
|
|
|
CV_Assert(blobs[0].size[0] == outCn && blobs[0].size[1] == inpCn / group); |
|
|
|
|
|
|
|
|
|
group = inpCn / blobs[0].size[1]; |
|
|
|
|
outGroupCn = outCn / group; |
|
|
|
|
inpGroupCn = inpCn / group; |
|
|
|
|
ksize = outGroupCn * kernel.height * kernel.width; |
|
|
|
|
colRowBlobShape.clear(); |
|
|
|
|
colRowBlobShape.push_back(ksize); |
|
|
|
|
colRowBlobShape.push_back(inpH * inpW); |
|
|
|
|
|
|
|
|
|
CV_Assert(inpCn % group == 0 && outCn % group == 0); |
|
|
|
|
CV_Assert(blobs[0].size[0] == outCn && blobs[0].size[1] == inpCn / group); |
|
|
|
|
|
|
|
|
|
colRowBlobShape.clear(); |
|
|
|
|
colRowBlobShape.push_back(ksize); |
|
|
|
|
colRowBlobShape.push_back(inpH * inpW); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void DeConvolutionLayerImpl::forward(std::vector<Mat *> &inputs, std::vector<Mat> &outputs) |
|
|
|
|
{ |
|
|
|
|
Mat weightsMat = blobs[0].reshape(1, inpCn); |
|
|
|
|
Mat biasesMat = bias ? blobs[1].reshape(1, outCn) : Mat(); |
|
|
|
|
ofsbuf.resize(ksize*3); |
|
|
|
|
for( int k = 0; k < ksize; k++ ) |
|
|
|
|
{ |
|
|
|
|
int w_offset = k % kernel.width; |
|
|
|
|
int h_offset = (k / kernel.width) % kernel.height; |
|
|
|
|
int c_im = k / kernel.height / kernel.width; |
|
|
|
|
ofsbuf[k*3] = w_offset; |
|
|
|
|
ofsbuf[k*3+1] = h_offset; |
|
|
|
|
ofsbuf[k*3+2] = c_im; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (size_t ii = 0; ii < outputs.size(); ii++) |
|
|
|
|
void forward(std::vector<Mat *> &inputs, std::vector<Mat> &outputs) |
|
|
|
|
{ |
|
|
|
|
int numImg = inputs[ii]->size[0]; |
|
|
|
|
Mat convBlob = inputs[ii]->reshape(1, numImg*inpCn); |
|
|
|
|
Mat decnBlob = outputs[ii].reshape(1, numImg*outCn); |
|
|
|
|
Mat weightsMat = blobs[0].reshape(1, inpCn); |
|
|
|
|
Mat biasesMat = bias ? blobs[1].reshape(1, outCn) : Mat(); |
|
|
|
|
|
|
|
|
|
for (int n = 0; n < numImg; n++) |
|
|
|
|
for (size_t ii = 0; ii < outputs.size(); ii++) |
|
|
|
|
{ |
|
|
|
|
for (int g = 0; g < group; g++) |
|
|
|
|
int numImg = inputs[ii]->size[0]; |
|
|
|
|
Mat convBlob = inputs[ii]->reshape(1, numImg*inpCn); |
|
|
|
|
Mat decnBlob = outputs[ii].reshape(1, numImg*outCn); |
|
|
|
|
|
|
|
|
|
for (int n = 0; n < numImg; n++) |
|
|
|
|
{ |
|
|
|
|
Mat dstMat = decnBlob.rowRange(_Range((g + n * group) * outGroupCn, outGroupCn)); |
|
|
|
|
Mat &colMat = (is1x1()) ? dstMat : colRowBlob; |
|
|
|
|
for (int g = 0; g < group; g++) |
|
|
|
|
{ |
|
|
|
|
Mat dstMat = decnBlob.rowRange(_Range((g + n * group) * outGroupCn, outGroupCn)); |
|
|
|
|
Mat &colMat = (is1x1()) ? dstMat : colRowBlob; |
|
|
|
|
|
|
|
|
|
Mat convMat = convBlob.rowRange(_Range((g + n * group) * inpGroupCn, inpGroupCn)); |
|
|
|
|
Mat wghtMat = weightsMat.rowRange(_Range(g * inpGroupCn, inpGroupCn)); |
|
|
|
|
Mat convMat = convBlob.rowRange(_Range((g + n * group) * inpGroupCn, inpGroupCn)); |
|
|
|
|
Mat wghtMat = weightsMat.rowRange(_Range(g * inpGroupCn, inpGroupCn)); |
|
|
|
|
|
|
|
|
|
dnn::gemm(wghtMat, convMat, 1, colMat, 0, GEMM_1_T); |
|
|
|
|
dnn::gemm(wghtMat, convMat, 1, colMat, 0, GEMM_1_T); |
|
|
|
|
|
|
|
|
|
if (!is1x1()) |
|
|
|
|
col2im(colMat, dstMat); |
|
|
|
|
if (!is1x1()) |
|
|
|
|
col2im(colMat, dstMat); |
|
|
|
|
|
|
|
|
|
if (bias) |
|
|
|
|
{ |
|
|
|
|
Mat curBiasMat = biasesMat.rowRange(_Range(g * outGroupCn, outGroupCn)); |
|
|
|
|
dnn::gemm(curBiasMat, biasOnesBlob, 1, dstMat, 1); |
|
|
|
|
if (bias) |
|
|
|
|
{ |
|
|
|
|
Mat curBiasMat = biasesMat.rowRange(_Range(g * outGroupCn, outGroupCn)); |
|
|
|
|
dnn::gemm(curBiasMat, biasOnesBlob, 1, dstMat, 1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void DeConvolutionLayerImpl::col2im(const Mat &colMat, Mat &dstImg) |
|
|
|
|
{ |
|
|
|
|
if (is1x1()) |
|
|
|
|
void col2im(const Mat &colMat, Mat &dstImg) |
|
|
|
|
{ |
|
|
|
|
dstImg = colMat; |
|
|
|
|
return; |
|
|
|
|
if (is1x1()) |
|
|
|
|
{ |
|
|
|
|
dstImg = colMat; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
cv::dnn::col2im(colMat.ptr<float>(), outGroupCn, outH, outW, kernel.height, kernel.width, |
|
|
|
|
pad.height, pad.width, stride.height, stride.width, |
|
|
|
|
dilation.height, dilation.width, dstImg.ptr<float>(), &ofsbuf[0]); |
|
|
|
|
} |
|
|
|
|
if (dstImg.type() == CV_32F) |
|
|
|
|
col2im_CpuPBody<float>::run(colMat.ptr<float>(), outGroupCn, outH, outW, kernel.height, kernel.width, pad.height, pad.width, stride.height, stride.width, dstImg.ptr<float>()); |
|
|
|
|
if (dstImg.type() == CV_64F) |
|
|
|
|
col2im_CpuPBody<double>::run(colMat.ptr<double>(), inpGroupCn, inpH, inpW, kernel.height, kernel.width, pad.height, pad.width, stride.height, stride.width, dstImg.ptr<double>()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//Initializers
|
|
|
|
|
|
|
|
|
|
/*Ptr<BaseConvolutionLayer> ConvolutionLayer::create(Size kernel, Size stride, Size pad, Size dilation)
|
|
|
|
|
{ |
|
|
|
|
ConvolutionLayerImpl *l = new ConvolutionLayerImpl(); |
|
|
|
|
l->kernel = kernel; |
|
|
|
|
l->pad = pad; |
|
|
|
|
l->stride = stride; |
|
|
|
|
l->dilation = dilation; |
|
|
|
|
return Ptr<BaseConvolutionLayer>(l); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ptr<BaseConvolutionLayer> DeconvolutionLayer::create(Size kernel, Size stride, Size pad, Size dilation, Size adjustPad) |
|
|
|
|
{ |
|
|
|
|
DeConvolutionLayerImpl *l = new DeConvolutionLayerImpl(); |
|
|
|
|
l->kernel = kernel; |
|
|
|
|
l->pad = pad; |
|
|
|
|
l->stride = stride; |
|
|
|
|
l->dilation = dilation; |
|
|
|
|
l->adjustPad = adjustPad; |
|
|
|
|
|
|
|
|
|
return Ptr<BaseConvolutionLayer>(l); |
|
|
|
|
}*/ |
|
|
|
|
std::vector<int> ofsbuf; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//Convolution and Deconvolution
|
|
|
|
|
static void initConvDeconvLayerFromCaffe(Ptr<BaseConvolutionLayer> l, const LayerParams ¶ms) |
|
|
|
|