mirror of
https://github.com/opencv/opencv.git
synced 2024-11-26 04:00:30 +08:00
Make DNN Crop layer match Caffe default offset behavior
and add parametric unit test for crop layer.
This commit is contained in:
parent
a55aed5f42
commit
d1a3b530be
@ -110,27 +110,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
crop_ranges.resize(dims, Range::all());
|
crop_ranges.resize(dims, Range::all());
|
||||||
for (int i = 0; i < dims; i++)
|
for (int i = start_axis; i < dims; i++)
|
||||||
{
|
|
||||||
if( i < start_axis )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!offset.empty()) //normal case
|
|
||||||
{
|
{
|
||||||
if (offset_final[i] < 0 || offset_final[i] + inpSzBlob.size[i] > inpBlob.size[i])
|
if (offset_final[i] < 0 || offset_final[i] + inpSzBlob.size[i] > inpBlob.size[i])
|
||||||
CV_Error(Error::StsBadArg, "invalid crop parameters");
|
CV_Error(Error::StsBadArg, "invalid crop parameters or blob sizes");
|
||||||
|
|
||||||
crop_ranges[i] = Range(offset_final[i], offset_final[i] + inpSzBlob.size[i]);
|
crop_ranges[i] = Range(offset_final[i], offset_final[i] + inpSzBlob.size[i]);
|
||||||
}
|
}
|
||||||
else //detect offset automatically so that cropped image is center of original one
|
|
||||||
{
|
|
||||||
if (inpSzBlob.size[i] > inpBlob.size[i])
|
|
||||||
CV_Error(Error::StsBadArg, "invalid output blob size");
|
|
||||||
|
|
||||||
int cur_crop = (inpBlob.size[i] - inpSzBlob.size[i]) / 2;
|
|
||||||
crop_ranges[i] = Range(cur_crop, cur_crop + inpSzBlob.size[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr)
|
void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr)
|
||||||
|
@ -715,4 +715,87 @@ INSTANTIATE_TEST_CASE_P(Layer_Test, Scale_untrainable, Combine(
|
|||||||
/*conv fusion*/ testing::Bool()
|
/*conv fusion*/ testing::Bool()
|
||||||
));
|
));
|
||||||
|
|
||||||
|
typedef testing::TestWithParam<tuple<Vec4i, Vec4i, int, int, int> > Crop;
|
||||||
|
TEST_P(Crop, Accuracy)
|
||||||
|
{
|
||||||
|
Vec4i inpShapeVec = get<0>(GetParam());
|
||||||
|
Vec4i sizShapeVec = get<1>(GetParam());
|
||||||
|
int axis = get<2>(GetParam());
|
||||||
|
int numOffsets = get<3>(GetParam());
|
||||||
|
int offsetVal = get<4>(GetParam());
|
||||||
|
const int inpShape[] = {inpShapeVec[0], inpShapeVec[1], inpShapeVec[2], inpShapeVec[3]};
|
||||||
|
const int sizShape[] = {sizShapeVec[0], sizShapeVec[1], sizShapeVec[2], sizShapeVec[3]};
|
||||||
|
|
||||||
|
// Create a network with two inputs. Crop layer crops a first input to
|
||||||
|
// the size of a second one.
|
||||||
|
// See http://caffe.berkeleyvision.org/tutorial/layers/crop.html
|
||||||
|
Net net;
|
||||||
|
|
||||||
|
LayerParams lp;
|
||||||
|
lp.name = "testCrop";
|
||||||
|
lp.type = "Crop";
|
||||||
|
lp.set("axis", axis);
|
||||||
|
if (numOffsets > 0)
|
||||||
|
{
|
||||||
|
std::vector<int> offsets(numOffsets, offsetVal);
|
||||||
|
lp.set("offset", DictValue::arrayInt<int*>(&offsets[0], offsets.size()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
offsetVal = 0;
|
||||||
|
int id = net.addLayerToPrev(lp.name, lp.type, lp);
|
||||||
|
net.connect(0, 1, id, 1);
|
||||||
|
|
||||||
|
Mat inpImage(4, inpShape, CV_32F);
|
||||||
|
Mat sizImage(4, sizShape, CV_32F);
|
||||||
|
randu(inpImage, -1, 1);
|
||||||
|
randu(sizImage, -1, 1);
|
||||||
|
|
||||||
|
std::vector<String> inpNames(2);
|
||||||
|
inpNames[0] = "cropImage";
|
||||||
|
inpNames[1] = "sizImage";
|
||||||
|
net.setInputsNames(inpNames);
|
||||||
|
net.setInput(inpImage, inpNames[0]);
|
||||||
|
net.setInput(sizImage, inpNames[1]);
|
||||||
|
|
||||||
|
// There are a few conditions that represent invalid input to the crop
|
||||||
|
// layer, so in those cases we want to verify an exception is thrown.
|
||||||
|
|
||||||
|
bool shouldThrowException = false;
|
||||||
|
if (numOffsets > 1 && numOffsets != 4 - axis)
|
||||||
|
shouldThrowException = true;
|
||||||
|
else
|
||||||
|
for (int i = axis; i < 4; i++)
|
||||||
|
if (sizShape[i] + offsetVal > inpShape[i])
|
||||||
|
shouldThrowException = true;
|
||||||
|
|
||||||
|
Mat out;
|
||||||
|
if (shouldThrowException)
|
||||||
|
{
|
||||||
|
ASSERT_ANY_THROW(out = net.forward());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out = net.forward();
|
||||||
|
|
||||||
|
// Finally, compare the cropped output blob from the DNN layer (out)
|
||||||
|
// to a reference blob (ref) that we compute here.
|
||||||
|
|
||||||
|
std::vector<Range> crop_range;
|
||||||
|
crop_range.resize(4, Range::all());
|
||||||
|
for (int i = axis; i < 4; i++)
|
||||||
|
crop_range[i] = Range(offsetVal, sizShape[i] + offsetVal);
|
||||||
|
|
||||||
|
Mat ref(sizImage.dims, sizImage.size, CV_32F);
|
||||||
|
inpImage(&crop_range[0]).copyTo(ref);
|
||||||
|
normAssert(out, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(Layer_Test, Crop, Combine(
|
||||||
|
/*input blob shape*/ Values(Vec4i(1, 3, 20, 30)),
|
||||||
|
/*cropsize blob shape*/ Values(Vec4i(1, 3, 10, 12)),
|
||||||
|
/*start axis*/ Values(0, 1, 2),
|
||||||
|
/*number of offsets*/ Values(0, 1, 2, 4),
|
||||||
|
/*offset value*/ Values(3, 4)
|
||||||
|
));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user