mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 00:03:03 +04:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
+28
-29
@@ -1891,44 +1891,46 @@ struct Net::Impl
|
||||
}
|
||||
|
||||
// fuse convolution layer followed by eltwise + relu
|
||||
if ( IS_DNN_OPENCL_TARGET(preferableTarget) )
|
||||
if ( IS_DNN_OPENCL_TARGET(preferableTarget) && ld.layerInstance->type == "Convolution" )
|
||||
{
|
||||
Ptr<EltwiseLayer> nextEltwiseLayer;
|
||||
if( nextData )
|
||||
nextEltwiseLayer = nextData->layerInstance.dynamicCast<EltwiseLayer>();
|
||||
|
||||
if( !nextEltwiseLayer.empty() && pinsToKeep.count(lpNext) == 0 )
|
||||
if( !nextEltwiseLayer.empty() && pinsToKeep.count(lpNext) == 0 &&
|
||||
nextData->inputBlobsId.size() == 2 )
|
||||
{
|
||||
LayerData *eltwiseData = nextData;
|
||||
// go down from the second input and find the first non-skipped layer.
|
||||
LayerData *downLayerData = &layers[eltwiseData->inputBlobsId[1].lid];
|
||||
CV_Assert(downLayerData);
|
||||
while (downLayerData->skip)
|
||||
{
|
||||
downLayerData = &layers[downLayerData->inputBlobsId[0].lid];
|
||||
}
|
||||
CV_Assert(downLayerData);
|
||||
|
||||
// second input layer is current layer.
|
||||
if ( ld.id == downLayerData->id )
|
||||
// Eltwise layer has two inputs. We need to determine which
|
||||
// is a base convolution layer and which could be used as it's bias.
|
||||
LayerData* biasLayerData = 0;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
// go down from the first input and find the first non-skipped layer
|
||||
downLayerData = &layers[eltwiseData->inputBlobsId[0].lid];
|
||||
LayerData *downLayerData = &layers[eltwiseData->inputBlobsId[i].lid];
|
||||
CV_Assert(downLayerData);
|
||||
while (downLayerData->skip)
|
||||
{
|
||||
if ( !downLayerData->type.compare("Eltwise") )
|
||||
downLayerData = &layers[downLayerData->inputBlobsId[1].lid];
|
||||
else
|
||||
if (downLayerData->inputBlobsId.size() == 1)
|
||||
downLayerData = &layers[downLayerData->inputBlobsId[0].lid];
|
||||
else
|
||||
{
|
||||
downLayerData = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<ConvolutionLayer> convLayer = downLayerData->layerInstance.dynamicCast<ConvolutionLayer>();
|
||||
|
||||
// first input layer is convolution layer
|
||||
if( !convLayer.empty() && eltwiseData->consumers.size() == 1 )
|
||||
if (downLayerData && ld.id == downLayerData->id)
|
||||
{
|
||||
biasLayerData = &layers[eltwiseData->inputBlobsId[1 - i].lid];
|
||||
break;
|
||||
}
|
||||
}
|
||||
CV_Assert(biasLayerData);
|
||||
{
|
||||
if( eltwiseData->consumers.size() == 1 )
|
||||
{
|
||||
// fuse eltwise + activation layer
|
||||
LayerData *firstConvLayerData = downLayerData;
|
||||
if (biasLayerData->id < ld.id)
|
||||
{
|
||||
nextData = &layers[eltwiseData->consumers[0].lid];
|
||||
lpNext = LayerPin(eltwiseData->consumers[0].lid, 0);
|
||||
@@ -1942,8 +1944,8 @@ struct Net::Impl
|
||||
!nextData->type.compare("Power")) &&
|
||||
currLayer->setActivation(nextActivLayer) )
|
||||
{
|
||||
CV_Assert(firstConvLayerData->outputBlobsWrappers.size() == 1 && ld.inputBlobsWrappers.size() == 1);
|
||||
ld.inputBlobsWrappers.push_back(firstConvLayerData->outputBlobsWrappers[0]);
|
||||
CV_Assert_N(biasLayerData->outputBlobsWrappers.size() == 1, ld.inputBlobsWrappers.size() == 1);
|
||||
ld.inputBlobsWrappers.push_back(biasLayerData->outputBlobsWrappers[0]);
|
||||
printf_(("\tfused with %s\n", nextEltwiseLayer->name.c_str()));
|
||||
printf_(("\tfused with %s\n", nextActivLayer->name.c_str()));
|
||||
eltwiseData->skip = true;
|
||||
@@ -1994,9 +1996,6 @@ struct Net::Impl
|
||||
}
|
||||
}
|
||||
|
||||
if (preferableBackend != DNN_BACKEND_OPENCV)
|
||||
continue; // Go to the next layer.
|
||||
|
||||
// the optimization #2. if there is no layer that takes max pooling layer's computed
|
||||
// max indices (and only some semantical segmentation networks might need this;
|
||||
// many others only take the maximum values), then we switch the max pooling
|
||||
@@ -3184,7 +3183,7 @@ void Net::setHalideScheduler(const String& scheduler)
|
||||
int64 Net::getPerfProfile(std::vector<double>& timings)
|
||||
{
|
||||
timings = std::vector<double>(impl->layersTimings.begin() + 1, impl->layersTimings.end());
|
||||
int64 total = std::accumulate(timings.begin(), timings.end(), 0);
|
||||
int64 total = (int64)std::accumulate(timings.begin(), timings.end(), 0.0);
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,6 @@ public:
|
||||
else if (params.has("pooled_w") || params.has("pooled_h"))
|
||||
{
|
||||
type = ROI;
|
||||
computeMaxIdx = false;
|
||||
pooledSize.width = params.get<uint32_t>("pooled_w", 1);
|
||||
pooledSize.height = params.get<uint32_t>("pooled_h", 1);
|
||||
}
|
||||
@@ -142,6 +141,7 @@ public:
|
||||
#ifdef HAVE_OPENCL
|
||||
poolOp.release();
|
||||
#endif
|
||||
computeMaxIdx = type == MAX;
|
||||
}
|
||||
|
||||
virtual bool supportBackend(int backendId) CV_OVERRIDE
|
||||
@@ -193,19 +193,14 @@ public:
|
||||
poolOp = Ptr<OCL4DNNPool<float> >(new OCL4DNNPool<float>(config));
|
||||
}
|
||||
|
||||
for (size_t ii = 0; ii < inputs.size(); ii++)
|
||||
{
|
||||
UMat& inpMat = inputs[ii];
|
||||
int out_index = (type == MAX) ? 2 : 1;
|
||||
UMat& outMat = outputs[out_index * ii];
|
||||
UMat maskMat = (type == MAX) ? outputs[2 * ii + 1] : UMat();
|
||||
CV_Assert_N(inputs.size() == 1, !outputs.empty(), !computeMaxIdx || outputs.size() == 2);
|
||||
UMat& inpMat = inputs[0];
|
||||
UMat& outMat = outputs[0];
|
||||
UMat maskMat = computeMaxIdx ? outputs[1] : UMat();
|
||||
|
||||
CV_Assert(inpMat.offset == 0 && outMat.offset == 0);
|
||||
CV_Assert(inpMat.offset == 0 && outMat.offset == 0);
|
||||
|
||||
if (!poolOp->Forward(inpMat, outMat, maskMat))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return poolOp->Forward(inpMat, outMat, maskMat);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -232,9 +227,12 @@ public:
|
||||
switch (type)
|
||||
{
|
||||
case MAX:
|
||||
CV_Assert_N(inputs.size() == 1, outputs.size() == 2);
|
||||
maxPooling(inputs[0], outputs[0], outputs[1]);
|
||||
{
|
||||
CV_Assert_N(inputs.size() == 1, !computeMaxIdx || outputs.size() == 2);
|
||||
Mat mask = computeMaxIdx ? outputs[1] : Mat();
|
||||
maxPooling(inputs[0], outputs[0], mask);
|
||||
break;
|
||||
}
|
||||
case AVE:
|
||||
CV_Assert_N(inputs.size() == 1, outputs.size() == 1);
|
||||
avePooling(inputs[0], outputs[0]);
|
||||
@@ -951,7 +949,10 @@ public:
|
||||
dims[0] = inputs[1][0]; // Number of proposals;
|
||||
dims[1] = psRoiOutChannels;
|
||||
}
|
||||
outputs.assign(type == MAX ? 2 : 1, shape(dims, 4));
|
||||
|
||||
int numOutputs = requiredOutputs ? requiredOutputs : (type == MAX ? 2 : 1);
|
||||
CV_Assert(numOutputs == 1 || (numOutputs == 2 && type == MAX));
|
||||
outputs.assign(numOutputs, shape(dims, 4));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ TEST_P(Test_TensorFlow_nets, Faster_RCNN)
|
||||
(backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16))
|
||||
throw SkipTestException("");
|
||||
|
||||
for (int i = 1; i < 2; ++i)
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
std::string proto = findDataFile("dnn/" + names[i] + ".pbtxt", false);
|
||||
std::string model = findDataFile("dnn/" + names[i] + ".pb", false);
|
||||
|
||||
Reference in New Issue
Block a user