Generalized Blob constructor and added vector of images support.

AlexNet and GoogLeNet tests updated.
pull/265/head
Vitaliy Lyudvichenko 10 years ago
parent d02bced118
commit 85ad43d325
  1. 15
      modules/dnn/include/opencv2/dnn/blob.hpp
  2. 13
      modules/dnn/include/opencv2/dnn/blob.inl.hpp
  3. 105
      modules/dnn/src/blob.cpp
  4. 5
      modules/dnn/src/dnn.cpp
  5. 41
      modules/dnn/test/test_alexnet.cpp
  6. 24
      modules/dnn/test/test_common.hpp
  7. 33
      modules/dnn/test/test_googlenet.cpp
  8. 1
      modules/dnn/test/test_precomp.hpp

@ -50,7 +50,11 @@ namespace dnn
{
public:
explicit Blob();
explicit Blob(InputArray in);
/** @brief constucts 4-dimensional blob from input
* @param in 2-dimensional or 3-dimensional single-channel image (or vector from them)
* @param dstCn if specified force size of ouptut blob channel-dimension
*/
explicit Blob(InputArray in, int dstCn = -1);
void create(const BlobShape &shape, int type = CV_32F);
@ -111,6 +115,15 @@ namespace dnn
template<typename TFloat>
TFloat *ptr(int n = 0, int cn = 0, int row = 0, int col = 0);
/** @brief share data with other blob and returns *this
@returns *this
*/
Blob &shareFrom(const Blob &blob);
/** @brief adjust blob shape to required (data reallocated if needed)
@returns *this
*/
Blob &reshape(const BlobShape &shape);
int type() const;
bool isFloat() const;
bool isDouble() const;

@ -254,6 +254,19 @@ inline const int * Blob::sizes() const
return &m.size[0];
}
inline Blob &Blob::shareFrom(const Blob &blob)
{
this->m = blob.m;
return *this;
}
inline Blob &Blob::reshape(const BlobShape &shape)
{
m.reshape(1, shape.dims(), shape.ptr());
return *this;
}
}
}

@ -11,45 +11,106 @@ namespace dnn
m = Mat(4, zeros, CV_32F, NULL);
}
Blob::Blob(InputArray in)
static inline int getMatChannels(const Mat &mat)
{
CV_Assert(in.isMat() || in.isUMat());
return (mat.dims <= 2) ? mat.channels() : mat.size[0];
}
if (in.isMat())
static BlobShape getBlobShpae(std::vector<Mat> &vmat, int requestedCn = -1)
{
Mat mat = in.getMat();
BlobShape shape(4);
int cnSum = 0, matCn;
CV_Assert(vmat.size() > 0);
CV_Assert(mat.dims == 2);
int rows = mat.rows;
int cols = mat.cols;
int cn = mat.channels();
int type = mat.type();
int dstType = CV_MAKE_TYPE(CV_MAT_DEPTH(type), 1);
for (size_t i = 0; i < vmat.size(); i++)
{
Mat &mat = vmat[i];
CV_Assert(!mat.empty());
CV_Assert((mat.dims == 3 && mat.channels() == 1) || mat.dims <= 2);
this->create(BlobShape(1, cn, rows, cols), dstType);
uchar *data = m.data;
int step = rows * cols * CV_ELEM_SIZE(dstType);
matCn = getMatChannels(mat);
cnSum += getMatChannels(mat);
if (cn == 1)
if (i == 0)
{
Mat wrapper2D(rows, cols, dstType, m.data);
mat.copyTo(wrapper2D);
shape[-1] = mat.cols;
shape[-2] = mat.rows;
shape[-3] = (requestedCn <= 0) ? matCn : requestedCn;
}
else
{
std::vector<Mat> wrappers(cn);
for (int i = 0; i < cn; i++)
if (mat.cols != shape[-1] || mat.rows != shape[-2])
CV_Error(Error::StsError, "Each Mat.size() must be equal");
if (requestedCn <= 0 && matCn != shape[-3])
CV_Error(Error::StsError, "Each Mat.chnannels() (or number of planes) must be equal");
}
}
if (cnSum % shape[-3] != 0)
CV_Error(Error::StsError, "Total number of channels in vector is not a multiple of requsted channel number");
shape[0] = cnSum / shape[-3];
return shape;
}
static std::vector<Mat> extractMatVector(InputArray in)
{
if (in.isMat() || in.isUMat())
{
return std::vector<Mat>(1, in.getMat());
}
else if (in.isMatVector())
{
return *static_cast<const std::vector<Mat>*>(in.getObj());
}
else if (in.isUMatVector())
{
wrappers[i] = Mat(rows, cols, dstType, data);
data += step;
std::vector<Mat> vmat;
in.getMatVector(vmat);
return vmat;
}
else
{
CV_Assert(in.isMat() || in.isMatVector() || in.isUMat() || in.isUMatVector());
return std::vector<Mat>();
}
}
Blob::Blob(InputArray in, int dstCn)
{
CV_Assert(dstCn == -1 || dstCn > 0);
std::vector<Mat> inMats = extractMatVector(in);
BlobShape dstShape = getBlobShpae(inMats, dstCn);
m.create(dstShape.dims(), dstShape.ptr(), CV_32F);
cv::split(mat, wrappers);
std::vector<Mat> wrapBuf(dstShape[-3]);
int elemSize = m.elemSize();
uchar *ptr = this->ptrRaw();
for (size_t i = 0; i < inMats.size(); i++)
{
Mat inMat = inMats[i];
if (inMat.dims <= 2)
{
inMat.convertTo(inMat, m.type());
wrapBuf.resize(0);
for (int cn = 0; cn < inMat.channels(); cn++)
{
wrapBuf.push_back(Mat(inMat.rows, inMat.cols, m.type(), ptr));
ptr += elemSize * inMat.total();
}
cv::split(inMat, wrapBuf);
}
else
{
CV_Error(cv::Error::StsNotImplemented, "Not Implemented");
inMat.convertTo(Mat(inMat.dims, inMat.size, m.type(), ptr), m.type());
ptr += elemSize * inMat.total();
}
}
}

@ -20,11 +20,10 @@ struct LayerOutId
{
int lid;
int oid;
String name;
LayerOutId() {}
LayerOutId(int layerId, int outputId, const String &outputName = String())
: lid(layerId), oid(outputId), name(outputName) {}
LayerOutId(int layerId, int outputId)
: lid(layerId), oid(outputId) {}
};
struct LayerData

@ -9,32 +9,12 @@ 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)
template<typename TString>
static std::string getTestFile(TString 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 = "")
{
EXPECT_EQ(ref.shape(), test.shape());
normAssert(ref.getMatRef(), test.getMatRef(), comment);
}
TEST(Reproducibility_AlexNet, Accuracy)
{
Net net;
@ -44,20 +24,17 @@ TEST(Reproducibility_AlexNet, Accuracy)
importer->populateNet(net);
}
std::vector<Mat> inpMats(2);
inpMats[0] = imread(getTestFile("alexnet_0.png"));
inpMats[1] = imread(getTestFile("alexnet_1.png"));
std::vector<Mat> inpMats;
inpMats.push_back( imread(getTestFile("alexnet_0.png")) );
inpMats.push_back( imread(getTestFile("alexnet_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.setBlob("data", Blob(inpMats));
net.forward();
Blob out = net.getBlob("prob");
Blob ref = blobFromNPY(getTestFile("alexnet_prob.npy"));
normAssert(out, ref, "prob");
Blob ref = blobFromNPY(getTestFile("alexnet.npy"));
normAssert(ref, out, "prob");
}
}

@ -0,0 +1,24 @@
#ifndef __OPENCV_TEST_COMMON_HPP__
#define __OPENCV_TEST_COMMON_HPP__
inline const std::string &getOpenCVExtraDir()
{
return cvtest::TS::ptr()->get_data_path();
}
inline void normAssert(cv::InputArray ref, cv::InputArray get, const char *comment = "")
{
double normL1 = cvtest::norm(ref, get, cv::NORM_L1)/ ref.getMat().total();
EXPECT_NEAR(normL1, 0, 0.0001) << comment;
double normInf = cvtest::norm(ref, get, cv::NORM_INF);
EXPECT_NEAR(normInf, 0, 0.001) << comment;
}
inline void normAssert(cv::dnn::Blob &ref, cv::dnn::Blob &test, const char *comment = "")
{
EXPECT_EQ(ref.shape(), test.shape());
normAssert(ref.getMatRef(), test.getMatRef(), comment);
}
#endif

@ -9,31 +9,12 @@ 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)
template<typename TString>
static std::string getTestFile(TString 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;
@ -43,14 +24,12 @@ TEST(Reproducibility_GoogLeNet, Accuracy)
importer->populateNet(net);
}
std::vector<Mat> inpMats(2);
inpMats[0] = imread(getTestFile("googlenet_0.png"));
inpMats[1] = imread(getTestFile("googlenet_1.png"));
std::vector<Mat> inpMats;
inpMats.push_back( imread(getTestFile("googlenet_0.png")) );
inpMats.push_back( imread(getTestFile("googlenet_1.png")) );
ASSERT_TRUE(!inpMats[0].empty() && !inpMats[1].empty());
inpMats[0].convertTo(inpMats[0], CV_32F);
Blob inp(inpMats[0]);
Blob inp(inpMats);
net.setBlob("data", inp);
net.forward();

@ -16,5 +16,6 @@
#include "opencv2/ts.hpp"
#include <opencv2/ts/ts_perf.hpp>
#include <opencv2/core/utility.hpp>
#include "test_common.hpp"
#endif

Loading…
Cancel
Save