mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
ROIPooling layer
This commit is contained in:
@@ -552,6 +552,7 @@ message LayerParameter {
|
||||
optional ReductionParameter reduction_param = 136;
|
||||
optional ReLUParameter relu_param = 123;
|
||||
optional ReshapeParameter reshape_param = 133;
|
||||
optional ROIPoolingParameter roi_pooling_param = 8266711; // https://github.com/rbgirshick/caffe-fast-rcnn/tree/fast-rcnn
|
||||
optional ScaleParameter scale_param = 142;
|
||||
optional SigmoidParameter sigmoid_param = 124;
|
||||
optional SoftmaxParameter softmax_param = 125;
|
||||
@@ -1605,3 +1606,15 @@ message NormalizedBBox {
|
||||
optional float score = 7;
|
||||
optional float size = 8;
|
||||
}
|
||||
|
||||
// origin: https://github.com/rbgirshick/caffe-fast-rcnn/tree/fast-rcnn
|
||||
// Message that stores parameters used by ROIPoolingLayer
|
||||
message ROIPoolingParameter {
|
||||
// Pad, kernel size, and stride are all given as a single value for equal
|
||||
// dimensions in height and width or as Y, X pairs.
|
||||
optional uint32 pooled_h = 1 [default = 0]; // The pooled output height
|
||||
optional uint32 pooled_w = 2 [default = 0]; // The pooled output width
|
||||
// Multiplicative spatial scale factor to translate ROI coords from their
|
||||
// input scale to the scale used when pooling
|
||||
optional float spatial_scale = 3 [default = 1];
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ void initializeLayerFactory()
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Convolution, ConvolutionLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Deconvolution, DeconvolutionLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Pooling, PoolingLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(ROIPooling, PoolingLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(LRN, LRNLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(InnerProduct, InnerProductLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Softmax, SoftmaxLayer);
|
||||
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
{
|
||||
type = PoolingLayer::MAX;
|
||||
computeMaxIdx = true;
|
||||
globalPooling = false;
|
||||
|
||||
if (params.has("pool"))
|
||||
{
|
||||
@@ -77,12 +78,18 @@ public:
|
||||
type = PoolingLayer::STOCHASTIC;
|
||||
else
|
||||
CV_Error(Error::StsBadArg, "Unknown pooling type \"" + pool + "\"");
|
||||
getPoolingKernelParams(params, kernel.height, kernel.width, globalPooling,
|
||||
pad.height, pad.width, stride.height, stride.width, padMode);
|
||||
}
|
||||
else if (params.has("pooled_w") || params.has("pooled_h") || params.has("spatial_scale"))
|
||||
{
|
||||
type = PoolingLayer::ROI;
|
||||
}
|
||||
|
||||
getPoolingKernelParams(params, kernel.height, kernel.width, globalPooling,
|
||||
pad.height, pad.width, stride.height, stride.width, padMode);
|
||||
setParamsFrom(params);
|
||||
ceilMode = params.get<bool>("ceil_mode", true);
|
||||
pooledSize.width = params.get<uint32_t>("pooled_w", 1);
|
||||
pooledSize.height = params.get<uint32_t>("pooled_h", 1);
|
||||
spatialScale = params.get<float>("spatial_scale", 1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
@@ -91,7 +98,7 @@ public:
|
||||
|
||||
void finalize(const std::vector<Mat*> &inputs, std::vector<Mat> &outputs)
|
||||
{
|
||||
CV_Assert(inputs.size() == 1);
|
||||
CV_Assert(!inputs.empty());
|
||||
|
||||
cv::Size inp(inputs[0]->size[3], inputs[0]->size[2]),
|
||||
out(outputs[0].size[3], outputs[0].size[2]);
|
||||
@@ -171,20 +178,23 @@ public:
|
||||
CV_TRACE_FUNCTION();
|
||||
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
|
||||
|
||||
for (size_t ii = 0; ii < inputs.size(); ii++)
|
||||
switch (type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MAX:
|
||||
maxPooling(*inputs[ii], outputs[2 * ii], outputs[2 * ii + 1]);
|
||||
break;
|
||||
case AVE:
|
||||
avePooling(*inputs[ii], outputs[ii]);
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsNotImplemented, "Not implemented");
|
||||
break;
|
||||
}
|
||||
case MAX:
|
||||
CV_Assert(inputs.size() == 1, outputs.size() == 2);
|
||||
maxPooling(*inputs[0], outputs[0], outputs[1]);
|
||||
break;
|
||||
case AVE:
|
||||
CV_Assert(inputs.size() == 1, outputs.size() == 1);
|
||||
avePooling(*inputs[0], outputs[0]);
|
||||
break;
|
||||
case ROI:
|
||||
CV_Assert(inputs.size() == 2, outputs.size() == 1);
|
||||
roiPooling(*inputs[0], *inputs[1], outputs[0]);
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsNotImplemented, "Not implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,29 +211,33 @@ public:
|
||||
class PoolingInvoker : public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
const Mat* src;
|
||||
const Mat* src, *rois;
|
||||
Mat *dst, *mask;
|
||||
Size kernel, stride, pad;
|
||||
int nstripes;
|
||||
bool computeMaxIdx;
|
||||
std::vector<int> ofsbuf;
|
||||
int poolingType;
|
||||
float spatialScale;
|
||||
|
||||
PoolingInvoker() : src(0), dst(0), mask(0), nstripes(0), computeMaxIdx(0), poolingType(PoolingLayer::MAX) {}
|
||||
PoolingInvoker() : src(0), rois(0), dst(0), mask(0), nstripes(0),
|
||||
computeMaxIdx(0), poolingType(PoolingLayer::MAX), spatialScale(0) {}
|
||||
|
||||
static void run(const Mat& src, Mat& dst, Mat& mask, Size kernel,
|
||||
Size stride, Size pad, int poolingType,
|
||||
static void run(const Mat& src, const Mat& rois, Mat& dst, Mat& mask, Size kernel,
|
||||
Size stride, Size pad, int poolingType, float spatialScale,
|
||||
bool computeMaxIdx, int nstripes)
|
||||
{
|
||||
CV_Assert(src.isContinuous() && dst.isContinuous() &&
|
||||
src.type() == CV_32F && src.type() == dst.type() &&
|
||||
src.dims == 4 && dst.dims == 4 &&
|
||||
src.size[0] == dst.size[0] && src.size[1] == dst.size[1] &&
|
||||
(poolingType == ROI && dst.size[0] == rois.size[0] ||
|
||||
src.size[0] == dst.size[0]) && src.size[1] == dst.size[1] &&
|
||||
(mask.empty() || (mask.type() == src.type() && mask.size == dst.size)));
|
||||
|
||||
PoolingInvoker p;
|
||||
|
||||
p.src = &src;
|
||||
p.rois = &rois;
|
||||
p.dst = &dst;
|
||||
p.mask = &mask;
|
||||
p.kernel = kernel;
|
||||
@@ -232,6 +246,7 @@ public:
|
||||
p.nstripes = nstripes;
|
||||
p.computeMaxIdx = computeMaxIdx;
|
||||
p.poolingType = poolingType;
|
||||
p.spatialScale = spatialScale;
|
||||
|
||||
if( !computeMaxIdx )
|
||||
{
|
||||
@@ -273,12 +288,39 @@ public:
|
||||
ofs /= height;
|
||||
int c = (int)(ofs % channels);
|
||||
int n = (int)(ofs / channels);
|
||||
int ystart = y0 * stride_h - pad_h;
|
||||
int yend = min(ystart + kernel_h, inp_height + pad_h);
|
||||
int ystart, yend;
|
||||
|
||||
const float *srcData;
|
||||
int xstartROI = 0;
|
||||
float roiRatio = 0;
|
||||
if (poolingType == ROI)
|
||||
{
|
||||
const float *roisData = rois->ptr<float>(n);
|
||||
int ystartROI = round(roisData[2] * spatialScale);
|
||||
int yendROI = round(roisData[4] * spatialScale);
|
||||
int roiHeight = std::max(yendROI - ystartROI + 1, 1);
|
||||
roiRatio = (float)roiHeight / height;
|
||||
|
||||
ystart = ystartROI + y0 * roiRatio;
|
||||
yend = ystartROI + std::ceil((y0 + 1) * roiRatio);
|
||||
|
||||
xstartROI = round(roisData[1] * spatialScale);
|
||||
int xendROI = round(roisData[3] * spatialScale);
|
||||
int roiWidth = std::max(xendROI - xstartROI + 1, 1);
|
||||
roiRatio = (float)roiWidth / width;
|
||||
|
||||
CV_Assert(roisData[0] < src->size[0]);
|
||||
srcData = src->ptr<float>(roisData[0], c);
|
||||
}
|
||||
else
|
||||
{
|
||||
ystart = y0 * stride_h - pad_h;
|
||||
yend = min(ystart + kernel_h, inp_height + pad_h);
|
||||
srcData = src->ptr<float>(n, c);
|
||||
}
|
||||
int ydelta = yend - ystart;
|
||||
ystart = max(ystart, 0);
|
||||
yend = min(yend, inp_height);
|
||||
const float *srcData = src->ptr<float>(n, c);
|
||||
float *dstData = dst->ptr<float>(n, c, y0);
|
||||
float *dstMaskData = mask->data ? mask->ptr<float>(n, c, y0) : 0;
|
||||
|
||||
@@ -286,13 +328,29 @@ public:
|
||||
ofs0 += delta;
|
||||
int x1 = x0 + delta;
|
||||
|
||||
if( poolingType == PoolingLayer::MAX )
|
||||
if( poolingType == MAX || poolingType == ROI)
|
||||
for( ; x0 < x1; x0++ )
|
||||
{
|
||||
int xstart = x0 * stride_w - pad_w;
|
||||
int xend = min(xstart + kernel_w, inp_width);
|
||||
int xstart, xend;
|
||||
if (poolingType == ROI)
|
||||
{
|
||||
xstart = xstartROI + x0 * roiRatio;
|
||||
xend = xstartROI + std::ceil((x0 + 1) * roiRatio);
|
||||
}
|
||||
else
|
||||
{
|
||||
xstart = x0 * stride_w - pad_w;
|
||||
xend = xstart + kernel_w;
|
||||
}
|
||||
xstart = max(xstart, 0);
|
||||
|
||||
xend = min(xend, inp_width);
|
||||
if (xstart >= xend || ystart >= yend)
|
||||
{
|
||||
dstData[x0] = 0;
|
||||
if (compMaxIdx && dstMaskData)
|
||||
dstMaskData[x0] = -1;
|
||||
continue;
|
||||
}
|
||||
#if CV_SIMD128
|
||||
if( xstart > 0 && x0 + 7 < x1 && (x0 + 7) * stride_w - pad_w + kernel_w < inp_width )
|
||||
{
|
||||
@@ -489,14 +547,22 @@ public:
|
||||
void maxPooling(Mat &src, Mat &dst, Mat &mask)
|
||||
{
|
||||
const int nstripes = getNumThreads();
|
||||
PoolingInvoker::run(src, dst, mask, kernel, stride, pad, type, computeMaxIdx, nstripes);
|
||||
Mat rois;
|
||||
PoolingInvoker::run(src, rois, dst, mask, kernel, stride, pad, type, spatialScale, computeMaxIdx, nstripes);
|
||||
}
|
||||
|
||||
void avePooling(Mat &src, Mat &dst)
|
||||
{
|
||||
const int nstripes = getNumThreads();
|
||||
Mat rois, mask;
|
||||
PoolingInvoker::run(src, rois, dst, mask, kernel, stride, pad, type, spatialScale, computeMaxIdx, nstripes);
|
||||
}
|
||||
|
||||
void roiPooling(const Mat &src, const Mat &rois, Mat &dst)
|
||||
{
|
||||
const int nstripes = getNumThreads();
|
||||
Mat mask;
|
||||
PoolingInvoker::run(src, dst, mask, kernel, stride, pad, type, computeMaxIdx, nstripes);
|
||||
PoolingInvoker::run(src, rois, dst, mask, kernel, stride, pad, type, spatialScale, computeMaxIdx, nstripes);
|
||||
}
|
||||
|
||||
virtual Ptr<BackendNode> initMaxPoolingHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
|
||||
@@ -632,6 +698,11 @@ public:
|
||||
out.height = 1;
|
||||
out.width = 1;
|
||||
}
|
||||
else if (type == PoolingLayer::ROI)
|
||||
{
|
||||
out.height = pooledSize.height;
|
||||
out.width = pooledSize.width;
|
||||
}
|
||||
else if (padMode.empty())
|
||||
{
|
||||
float height = (float)(in.height + 2 * pad.height - kernel.height) / stride.height;
|
||||
@@ -656,17 +727,13 @@ public:
|
||||
getConvPoolOutParams(in, kernel, stride, padMode, Size(1, 1), out);
|
||||
}
|
||||
|
||||
outputs.resize(type == MAX ? 2 * inputs.size() : inputs.size());
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
int dims[] = {inputs[0][0], inputs[0][1], out.height, out.width};
|
||||
if (type == ROI)
|
||||
{
|
||||
size_t index = type == MAX ? 2*i : i;
|
||||
int dims[] = {inputs[i][0], inputs[i][1], out.height, out.width};
|
||||
outputs[index] = shape(dims);
|
||||
|
||||
if (type == MAX)
|
||||
outputs[index + 1] = shape(dims);
|
||||
CV_Assert(inputs.size() == 2);
|
||||
dims[0] = inputs[1][0]; // Number of proposals;
|
||||
}
|
||||
|
||||
outputs.assign(type == MAX ? 2 : 1, shape(dims));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user