Added concat layer, implemented average pooling to run GoogLeNet. Fixed transpose error in FullyConnected layer (hotfix in softmax layer). Added GoogleNet test and updated AlexNet test (both nets now work fine).pull/265/head
parent
6fd67d44b0
commit
983823468d
7 changed files with 221 additions and 34 deletions
@ -0,0 +1,82 @@ |
|||||||
|
#include "../precomp.hpp" |
||||||
|
#include "layers_common.hpp" |
||||||
|
#include <iostream> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
namespace cv |
||||||
|
{ |
||||||
|
namespace dnn |
||||||
|
{ |
||||||
|
class ConcatLayer : public Layer |
||||||
|
{ |
||||||
|
int axis; |
||||||
|
|
||||||
|
public: |
||||||
|
ConcatLayer(LayerParams& params); |
||||||
|
void allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs); |
||||||
|
void forward(std::vector<Blob*> &inputs, std::vector<Blob> &outputs); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
REGISTER_LAYER_CLASS(Concat, ConcatLayer) |
||||||
|
|
||||||
|
|
||||||
|
ConcatLayer::ConcatLayer(LayerParams ¶ms) |
||||||
|
{ |
||||||
|
axis = params.get<int>("axis", 1); |
||||||
|
CV_Assert(axis == 0 || axis == 1); |
||||||
|
} |
||||||
|
|
||||||
|
void ConcatLayer::allocate(const std::vector<Blob *> &inputs, std::vector<Blob> &outputs) |
||||||
|
{ |
||||||
|
CV_Assert(inputs.size() > 0); |
||||||
|
|
||||||
|
int axisSum = 0; |
||||||
|
for (size_t i = 0; i < inputs.size(); i++) |
||||||
|
{ |
||||||
|
Vec4i refShape = inputs[0]->shape(); |
||||||
|
Vec4i curShape = inputs[i]->shape(); |
||||||
|
|
||||||
|
for (int axisId = 0; axisId < 4; axisId++) |
||||||
|
{ |
||||||
|
if (axisId != axis && refShape[axisId] != curShape[axisId]) |
||||||
|
CV_Error(cv::Error::StsBadArg, "Inconsitent shape for ConcatLayer"); |
||||||
|
} |
||||||
|
|
||||||
|
axisSum += curShape[axis]; |
||||||
|
} |
||||||
|
|
||||||
|
Vec4i shape = inputs[0]->shape(); |
||||||
|
shape[axis] = axisSum; |
||||||
|
outputs.resize(1); |
||||||
|
outputs[0].create(shape); |
||||||
|
} |
||||||
|
|
||||||
|
void ConcatLayer::forward(std::vector<Blob *> &inputs, std::vector<Blob> &outputs) |
||||||
|
{ |
||||||
|
float *dstPtr = outputs[0].ptr<float>(); |
||||||
|
|
||||||
|
if (axis == 0) |
||||||
|
{ |
||||||
|
for (size_t i = 0; i < inputs.size(); i++) |
||||||
|
{ |
||||||
|
const float *srcPtr = inputs[i]->ptr<float>(); |
||||||
|
memcpy(dstPtr, srcPtr, inputs[i]->total() * sizeof(float)); |
||||||
|
dstPtr += inputs[i]->total(); |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
for (int n = 0; n < outputs[0].num(); n++) |
||||||
|
{ |
||||||
|
for (size_t i = 0; i < inputs.size(); i++) |
||||||
|
{ |
||||||
|
Blob &inp = *inputs[i]; |
||||||
|
memcpy(dstPtr, inp.ptr<float>(n), inp.total(1) * sizeof(float)); |
||||||
|
dstPtr += inp.total(1); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
#include "test_precomp.hpp" |
||||||
|
#include "npy_blob.hpp" |
||||||
|
|
||||||
|
namespace cvtest |
||||||
|
{ |
||||||
|
|
||||||
|
using namespace std; |
||||||
|
using namespace testing; |
||||||
|
using namespace cv; |
||||||
|
using namespace cv::dnn; |
||||||
|
|
||||||
|
static std::string getOpenCVExtraDir() |
||||||
|
{ |
||||||
|
return cvtest::TS::ptr()->get_data_path(); |
||||||
|
} |
||||||
|
|
||||||
|
template<typename TStr> |
||||||
|
static std::string getTestFile(TStr filename) |
||||||
|
{ |
||||||
|
return (getOpenCVExtraDir() + "/dnn/") + filename; |
||||||
|
} |
||||||
|
|
||||||
|
inline void normAssert(InputArray ref, InputArray get, const char *comment = "") |
||||||
|
{ |
||||||
|
double normL1 = cvtest::norm(ref, get, NORM_L1)/ ref.getMat().total(); |
||||||
|
EXPECT_LE(normL1, 0.0001) << comment; |
||||||
|
|
||||||
|
double normInf = cvtest::norm(ref, get, NORM_INF); |
||||||
|
EXPECT_LE(normInf, 0.001) << comment; |
||||||
|
} |
||||||
|
|
||||||
|
inline void normAssert(Blob ref, Blob test, const char *comment = "") |
||||||
|
{ |
||||||
|
normAssert(ref.getMatRef(), test.getMatRef(), comment); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(Reproducibility_GoogLeNet, Accuracy) |
||||||
|
{ |
||||||
|
Net net; |
||||||
|
{ |
||||||
|
Ptr<Importer> importer = createCaffeImporter(getTestFile("bvlc_googlenet.prototxt"), getTestFile("bvlc_googlenet.caffemodel")); |
||||||
|
ASSERT_TRUE(importer != NULL); |
||||||
|
importer->populateNet(net); |
||||||
|
} |
||||||
|
|
||||||
|
std::vector<Mat> inpMats(2); |
||||||
|
inpMats[0] = imread(getTestFile("googlenet_0.png")); |
||||||
|
inpMats[1] = imread(getTestFile("googlenet_1.png")); |
||||||
|
ASSERT_TRUE(!inpMats[0].empty() && !inpMats[1].empty()); |
||||||
|
|
||||||
|
inpMats[0].convertTo(inpMats[0], CV_32F); |
||||||
|
Blob inp(inpMats[0]); |
||||||
|
|
||||||
|
net.setBlob("data", inp); |
||||||
|
net.forward(); |
||||||
|
|
||||||
|
Blob out = net.getBlob("prob"); |
||||||
|
Blob ref = blobFromNPY(getTestFile("googlenet.npy")); |
||||||
|
normAssert(out, ref); |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue