{
namespace dnn
{
+static inline int scaleAndRoundRoi(float f, float scale)
+{
+ return (int)(f * scale + (f >= 0.f ? 0.5f : -0.5f));
+}
class PoolingLayerImpl : public PoolingLayer
{
public:
PoolingLayerImpl(const LayerParams& params)
{
- type = PoolingLayer::MAX;
+ type = MAX;
computeMaxIdx = true;
globalPooling = false;
{
String pool = params.get<String>("pool").toLowerCase();
if (pool == "max")
- type = PoolingLayer::MAX;
+ type = MAX;
else if (pool == "ave")
- type = PoolingLayer::AVE;
+ type = AVE;
else if (pool == "stochastic")
- type = PoolingLayer::STOCHASTIC;
+ type = STOCHASTIC;
else
CV_Error(Error::StsBadArg, "Unknown pooling type \"" + pool + "\"");
getPoolingKernelParams(params, kernel.height, kernel.width, globalPooling,
}
else if (params.has("pooled_w") || params.has("pooled_h") || params.has("spatial_scale"))
{
- type = PoolingLayer::ROI;
+ type = ROI;
+ computeMaxIdx = false;
}
setParamsFrom(params);
ceilMode = params.get<bool>("ceil_mode", true);
{
return backendId == DNN_BACKEND_DEFAULT ||
backendId == DNN_BACKEND_HALIDE && haveHalide() &&
- (type == PoolingLayer::MAX ||
- type == PoolingLayer::AVE && !pad.width && !pad.height);
+ (type == MAX || type == AVE && !pad.width && !pad.height);
}
#ifdef HAVE_OPENCL
virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
{
- if (type == PoolingLayer::MAX)
+ if (type == MAX)
return initMaxPoolingHalide(inputs);
- else if (type == PoolingLayer::AVE)
+ else if (type == AVE)
return initAvePoolingHalide(inputs);
else
return Ptr<BackendNode>();
float spatialScale;
PoolingInvoker() : src(0), rois(0), dst(0), mask(0), nstripes(0),
- computeMaxIdx(0), poolingType(PoolingLayer::MAX), spatialScale(0) {}
+ computeMaxIdx(0), poolingType(MAX), spatialScale(0) {}
static void run(const Mat& src, const Mat& rois, Mat& dst, Mat& mask, Size kernel,
Size stride, Size pad, int poolingType, float spatialScale,
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 ystartROI = scaleAndRoundRoi(roisData[2], spatialScale);
+ int yendROI = scaleAndRoundRoi(roisData[4], spatialScale);
int roiHeight = std::max(yendROI - ystartROI + 1, 1);
- roiRatio = (float)roiHeight / height;
+ float 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);
}
ofs0 += delta;
int x1 = x0 + delta;
- if( poolingType == MAX || poolingType == ROI)
+ if( poolingType == MAX)
for( ; x0 < x1; x0++ )
{
- 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;
- }
+ int xstart = x0 * stride_w - pad_w;
+ int xend = min(xstart + kernel_w, inp_width);
xstart = max(xstart, 0);
- xend = min(xend, inp_width);
if (xstart >= xend || ystart >= yend)
{
dstData[x0] = 0;
}
}
}
- else
+ else if (poolingType == AVE)
{
for( ; x0 < x1; x0++ )
{
}
}
}
+ else // ROI
+ {
+ const float *roisData = rois->ptr<float>(n);
+ int xstartROI = scaleAndRoundRoi(roisData[1], spatialScale);
+ int xendROI = scaleAndRoundRoi(roisData[3], spatialScale);
+ int roiWidth = std::max(xendROI - xstartROI + 1, 1);
+ float roiRatio = (float)roiWidth / width;
+ for( ; x0 < x1; x0++ )
+ {
+ int xstart = xstartROI + x0 * roiRatio;
+ int xend = xstartROI + std::ceil((x0 + 1) * roiRatio);
+ xstart = max(xstart, 0);
+ xend = min(xend, inp_width);
+ if (xstart >= xend || ystart >= yend)
+ {
+ dstData[x0] = 0;
+ if (compMaxIdx && dstMaskData)
+ dstMaskData[x0] = -1;
+ continue;
+ }
+ float max_val = -FLT_MAX;
+ for (int y = ystart; y < yend; ++y)
+ for (int x = xstart; x < xend; ++x)
+ {
+ const int index = y * inp_width + x;
+ float val = srcData[index];
+ max_val = std::max(max_val, val);
+ }
+ dstData[x0] = max_val;
+ }
+ }
}
}
};
out.height = 1;
out.width = 1;
}
- else if (type == PoolingLayer::ROI)
+ else if (type == ROI)
{
out.height = pooledSize.height;
out.width = pooledSize.width;
}
return flops;
}
+private:
+ enum Type
+ {
+ MAX,
+ AVE,
+ STOCHASTIC,
+ ROI
+ };
};
Ptr<PoolingLayer> PoolingLayer::create(const LayerParams& params)