Commit 9c6c69a4 authored by Aleksandr Rybnikov's avatar Aleksandr Rybnikov Committed by Vadim Pisarevsky

Fixed and added tests (#987)

parent ee79c1f4
......@@ -48,11 +48,20 @@ ocv_add_perf_tests()
# ----------------------------------------------------------------------------
# Download pre-trained models for complex testing on GoogLeNet and AlexNet
# ----------------------------------------------------------------------------
OCV_OPTION(${the_module}_DOWNLOAD_CAFFE_MODELS "Use GoogLeNet Caffe model for testing" OFF IF BUILD_TESTS AND DEFINED ENV{OPENCV_TEST_DATA_PATH})
if(BUILD_TESTS AND DEFINED ENV{OPENCV_TEST_DATA_PATH} AND (DOWNLOAD_EXTERNAL_TEST_DATA OR ${the_module}_DOWNLOAD_CAFFE_MODELS))
OCV_OPTION(${the_module}_DOWNLOAD_MODELS "Use GoogLeNet Caffe model for testing" OFF IF BUILD_TESTS AND DEFINED ENV{OPENCV_TEST_DATA_PATH})
if(BUILD_TESTS AND DEFINED ENV{OPENCV_TEST_DATA_PATH} AND (DOWNLOAD_EXTERNAL_TEST_DATA OR ${the_module}_DOWNLOAD_MODELS))
add_custom_command( TARGET opencv_test_${name} POST_BUILD
COMMAND ${CMAKE_COMMAND} -Dmodel=GoogleNet -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/download_model.cmake)
add_custom_command( TARGET opencv_test_${name} POST_BUILD
COMMAND ${CMAKE_COMMAND} -Dmodel=Alexnet -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/download_model.cmake)
add_custom_command( TARGET opencv_test_${name} POST_BUILD
COMMAND ${CMAKE_COMMAND} -Dmodel=Inception -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/download_model.cmake)
add_custom_command( TARGET opencv_test_${name} POST_BUILD
COMMAND ${CMAKE_COMMAND} -Dmodel=Enet -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/download_model.cmake)
add_definitions(-DENABLE_CAFFE_MODEL_TESTS=1)
add_definitions(-DENABLE_CAFFE_ALEXNET_TEST=1)
add_definitions(-DENABLE_TF_INCEPTION_TESTS=1)
add_definitions(-DENABLE_TORCH_ENET_TESTS=1)
endif()
# ----------------------------------------------------------------------------
......
......@@ -8,6 +8,19 @@ set(GG16_dst "$ENV{OPENCV_TEST_DATA_PATH}/dnn/VGG_ILSVRC_16_layers.caffemodel")
set(voc-fcn32s_url "http://dl.caffe.berkeleyvision.org/fcn32s-heavy-pascal.caffemodel")
set(voc-fcn32s_dst "$ENV{OPENCV_TEST_DATA_PATH}/dnn/fcn32s-heavy-pascal.caffemodel")
set(Alexnet_url "http://dl.caffe.berkeleyvision.org/bvlc_alexnet.caffemodel")
set(Alexnet_dst "$ENV{OPENCV_TEST_DATA_PATH}/dnn/bvlc_alexnet.caffemodel")
set(Alexnet_sha "9116a64c0fbe4459d18f4bb6b56d647b63920377")
set(Inception_url "https://github.com/petewarden/tf_ios_makefile_example/raw/master/data/tensorflow_inception_graph.pb")
set(Inception_dst "$ENV{OPENCV_TEST_DATA_PATH}/dnn/tensorflow_inception_graph.pb")
set(Enet_url "https://www.dropbox.com/sh/dywzk3gyb12hpe5/AABoUwqQGWvClUu27Z1EWeu9a/model-best.net?dl=0")
set(Enet_dst "$ENV{OPENCV_TEST_DATA_PATH}/dnn/Enet-model-best.net")
set(Fcn_url "http://dl.caffe.berkeleyvision.org/fcn8s-heavy-pascal.caffemodel")
set(Fcn_dst "$ENV{OPENCV_TEST_DATA_PATH}/dnn/fcn8s-heavy-pascal.caffemodel")
if(NOT model)
set(model "GoogleNet")
endif()
......
......@@ -115,6 +115,7 @@ int main(int argc, char **argv)
}
resize(img, img, Size(224, 224)); //GoogLeNet accepts only 224x224 RGB-images
cv::cvtColor(img, img, cv::COLOR_BGR2RGB);
dnn::Blob inputBlob = dnn::Blob::fromImages(img); //Convert Mat to dnn::Blob batch of images
//! [Prepare blob]
......
......@@ -425,7 +425,7 @@ message LayerParameter {
// The blobs containing the numeric parameters of the layer.
repeated BlobProto blobs = 7;
// Specifies on which bottoms the backpropagation should be skipped.
// The size must be either 0 or equal to the number of bottoms.
repeated bool propagate_down = 11;
......@@ -571,7 +571,7 @@ message ContrastiveLossParameter {
// Hadsell paper. New models should probably use this version.
// legacy_version = true uses (margin - d^2). This is kept to support /
// reproduce existing models and results
optional bool legacy_version = 2 [default = false];
optional bool legacy_version = 2 [default = false];
}
message ConvolutionParameter {
......
......@@ -111,6 +111,7 @@ void BaseConvolutionLayerImpl::allocate(const std::vector<Blob*> &inputs, std::v
if (!is1x1())
{
colRowBlob.create(colRowBlobShape, input.type(), allocFlags);
colRowBlob.setTo(0);
}
}
......@@ -250,11 +251,11 @@ void ConvolutionLayerImpl::im2row(const Mat &srcImg, Mat &dstRow)
if (srcImg.type() == CV_32F)
im2row_CpuPBody<float>::run(srcImg.ptr<float>(), inpGroupCn, inpH, inpW, kernel.height,
kernel.width, pad.height, pad.width, stride.height, stride.width,
dilation.height, dilation.width, outW, outH, colMat.ptr<float>());
dilation.height, dilation.width, outH, outW, colMat.ptr<float>());
if (srcImg.type() == CV_64F)
im2row_CpuPBody<double>::run(srcImg.ptr<double>(), inpGroupCn, inpH, inpW, kernel.height,
kernel.width, pad.height, pad.width, stride.height, stride.width,
dilation.height, dilation.width, outW, outH, colMat.ptr<double>());
dilation.height, dilation.width, outH, outW, colMat.ptr<double>());
dstRow = colMat;
}
......@@ -268,11 +269,9 @@ void ConvolutionLayerImpl::im2row(const UMat &srcImg, UMat &dstCol)
void DeConvolutionLayerImpl::computeInpOutShape(const Blob &inpBlob)
{
BlobShape bs0 = blobs[0].shape();
BlobShape bs1 = blobs[1].shape();
CV_Assert(!bias || blobs[1].total() == (size_t)blobs[0].channels());
CV_Assert(!bias || blobs[1].total() == (size_t)blobs[0].num());
numOutput = blobs[0].channels();
numOutput = blobs[0].num();
inpH = inpBlob.rows();
inpW = inpBlob.cols();
......@@ -282,13 +281,13 @@ void DeConvolutionLayerImpl::computeInpOutShape(const Blob &inpBlob)
outW = stride.width * (inpW - 1) + kernel.width - 2 * pad.width + adjustPad.width;
outCn = numOutput;
group = inpCn / blobs[0].num();
group = inpCn / blobs[0].channels();
outGroupCn = outCn / group;
inpGroupCn = inpCn / group;
ksize = outGroupCn * kernel.height * kernel.width;
CV_Assert(inpCn % group == 0 && outCn % group == 0);
CV_Assert(blobs[0].channels() == outCn && blobs[0].num() == inpCn / group);
CV_Assert(blobs[0].num() == outCn && blobs[0].channels() == inpCn / group);
colRowBlobShape = BlobShape(ksize, inpH * inpW);
}
......
......@@ -106,23 +106,23 @@ static XMat getPlane(XMat &m, int n, int cn)
void LRNLayerImpl::channelNoramlization(Blob &src, Blob &dst)
{
if (!useOpenCL)
channelNoramlization_<Mat>(src, dst);
channelNormalization_<Mat>(src, dst);
else
{
//channelNoramlization_ocl(src.getRefConst<UMat>(), dst.getRef<UMat>()); //consumes a lot of memory
channelNoramlization_<UMat>(src, dst);
channelNormalization_<UMat>(src, dst);
}
}
template<typename XMat>
void LRNLayerImpl::channelNoramlization_(Blob &srcBlob, Blob &dstBlob)
void LRNLayerImpl::channelNormalization_(Blob &srcBlob, Blob &dstBlob)
{
int num = srcBlob.num();
int channels = srcBlob.channels();
int ksize = (size - 1) / 2;
int sizeNormFactor = normBySize ? size : 1;
XMat srcMat = srcBlob.getRefConst<XMat>();
XMat srcMat = srcBlob.getRefConst<XMat>().clone();
XMat dstMat = dstBlob.getRef<XMat>();
for (int n = 0; n < num; n++)
......@@ -156,7 +156,7 @@ void LRNLayerImpl::channelNoramlization_(Blob &srcBlob, Blob &dstBlob)
}
}
bool LRNLayerImpl::channelNoramlization_ocl(const UMat &src, UMat &dst)
bool LRNLayerImpl::channelNormalization_ocl(const UMat &src, UMat &dst)
{
#ifdef HAVE_OPENCL
if (src.offset != 0 || dst.offset != 0) //TODO: add offset
......
......@@ -56,8 +56,8 @@ class LRNLayerImpl : public LRNLayer
void channelNoramlization(Blob &src, Blob &dst);
template<typename XMat>
void channelNoramlization_(Blob &src, Blob &dst);
bool channelNoramlization_ocl(const UMat &src, UMat &dst);
void channelNormalization_(Blob &src, Blob &dst);
bool channelNormalization_ocl(const UMat &src, UMat &dst);
void spatialNormalization(Blob &src, Blob &dst);
template<typename XMat>
......@@ -67,8 +67,8 @@ class LRNLayerImpl : public LRNLayer
public:
LRNLayerImpl(int type = CHANNEL_NRM, int size = 5, double alpha = 1, double beta = 0.75, double bias = 1,
bool normBySize = true);
LRNLayerImpl(int type = CHANNEL_NRM, int size = 5, double alpha = 1,
double beta = 0.75, double bias = 1, bool normBySize = true);
void allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs);
void forward(std::vector<Blob*> &inputs, std::vector<Blob> &outputs);
};
......
......@@ -44,6 +44,7 @@ void MaxUnpoolLayerImpl::forward(std::vector<Blob*> &inputs, std::vector<Blob> &
for(int i_n = 0; i_n < outputs.size(); i_n++)
{
Blob& outBlob = outputs[i_n];
outBlob.setTo(0);
CV_Assert(input.channels() == outBlob.channels());
for (int i_c = 0; i_c < input.channels(); i_c++)
......
......@@ -73,7 +73,7 @@ void ReshapeLayerImpl::forward(std::vector<Blob*> &inputs, std::vector<Blob> &ou
{
for (size_t i = 0; i < outputs.size(); i++)
{
Blob& srcBlob = *inputs[i];
Blob srcBlob = *inputs[i];
BlobShape inputShape = inputs[i]->shape();
bool channelsReduced = inputShape.dims() > outShapes[i].dims() ||
(inputShape.dims() == 4 && inputShape[1] > outShapes[i][1]);
......
......@@ -640,7 +640,7 @@ void TFImporter::populateNet(Net dstNet)
if(hasLayerAttr(layer, "bias")) {
layerParams.set("bias", getLayerAttr(layer, "bias").f());
}
layerParams.set("norm_sz", false);
layerParams.set("norm_by_size", false);
int id = dstNet.addLayer(name, "LRN", layerParams);
layer_id[name] = id;
......
......@@ -375,6 +375,7 @@ struct TorchImporter : public ::cv::dnn::Importer
int typeStorage = parseStorageType(className);
CV_Assert(typeStorage >= 0 && typeTensor == typeStorage);
readTorchStorage(indexStorage, typeStorage);
typeTensor = storages[indexStorage].type();
readedIndexes.insert(indexStorage);
}
......@@ -723,7 +724,10 @@ struct TorchImporter : public ::cv::dnn::Importer
layerParams.set("adj_h", static_cast<int>(scalarParams.get<double>("adjH")));
layerParams.set("num_output", static_cast<int>(scalarParams.get<double>("nOutputPlane")));
layerParams.blobs.push_back(tensorParams["weight"].second);
Blob weights = tensorParams["weight"].second;
BlobShape shape = weights.shape(),
reorderedShape = BlobShape(shape[1], shape[0], shape[2], shape[3]);
layerParams.blobs.push_back(weights.reshape(reorderedShape));
bool bias = tensorParams.count("bias");
layerParams.set("bias_term", bias);
......
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#if defined(ENABLE_CAFFE_MODEL_TESTS) && defined(ENABLE_CAFFE_ALEXNET_TEST) //AlexNet is disabled now
#include "test_precomp.hpp"
#include "npy_blob.hpp"
namespace cvtest
{
using namespace cv;
using namespace cv::dnn;
template<typename TString>
static std::string _tf(TString filename)
{
return (getOpenCVExtraDir() + "/dnn/") + filename;
}
TEST(Reproducibility_AlexNet, Accuracy)
{
Net net;
{
Ptr<Importer> importer = createCaffeImporter(_tf("bvlc_alexnet.prototxt"), _tf("bvlc_alexnet.caffemodel"));
ASSERT_TRUE(importer != NULL);
importer->populateNet(net);
}
std::vector<Mat> inpMats;
inpMats.push_back( imread(_tf("alexnet_0.png")) );
inpMats.push_back( imread(_tf("alexnet_1.png")) );
ASSERT_TRUE(!inpMats[0].empty() && !inpMats[1].empty());
net.setBlob(".data", Blob(inpMats));
net.forward();
Blob out = net.getBlob("prob");
Blob ref = blobFromNPY(_tf("alexnet.npy"));
normAssert(ref, out, "prob");
}
}
#endif
......@@ -40,6 +40,7 @@
//M*/
#include "test_precomp.hpp"
#include "npy_blob.hpp"
namespace cvtest
{
......@@ -73,4 +74,69 @@ TEST(Test_Caffe, read_googlenet)
}
}
#if defined(ENABLE_CAFFE_MODEL_TESTS)
#if defined(ENABLE_CAFFE_ALEXNET_TEST) //AlexNet is disabled now
TEST(Reproducibility_AlexNet, Accuracy)
{
Net net;
{
Ptr<Importer> importer = createCaffeImporter(_tf("bvlc_alexnet.prototxt"), _tf("bvlc_alexnet.caffemodel"));
ASSERT_TRUE(importer != NULL);
importer->populateNet(net);
}
Mat sample = imread(_tf("grace_hopper_227.png"));
ASSERT_TRUE(!sample.empty());
cv::cvtColor(sample, sample, cv::COLOR_BGR2RGB);
Size inputSize(227, 227);
if (sample.size() != inputSize)
resize(sample, sample, inputSize);
net.setBlob(".data", dnn::Blob::fromImages(sample));
net.forward();
Blob out = net.getBlob("prob");
Blob ref = blobFromNPY(_tf("caffe_alexnet_prob.npy"));
normAssert(ref, out);
}
#endif
#if defined(ENABLE_CAFFE_FCN_TEST)
TEST(Reproducibility_FCN, Accuracy)
{
Net net;
{
Ptr<Importer> importer = createCaffeImporter(_tf("fcn8s-heavy-pascal.prototxt"), _tf("fcn8s-heavy-pascal.caffemodel"));
ASSERT_TRUE(importer != NULL);
importer->populateNet(net);
}
Mat sample = imread(_tf("street.png"));
ASSERT_TRUE(!sample.empty());
Size inputSize(500, 500);
if (sample.size() != inputSize)
resize(sample, sample, inputSize);
cv::cvtColor(sample, sample, cv::COLOR_BGR2RGB);
net.setBlob(".data", dnn::Blob::fromImages(sample));
net.forward();
Blob out = net.getBlob("score");
Blob ref = blobFromNPY(_tf("caffe_fcn8s_prob.npy"));
normAssert(ref, out);
}
#endif
#endif
}
......@@ -9,7 +9,10 @@
Test for Tensorflow models loading
*/
#if defined(ENABLE_TF_INCEPTION_TESTS)
#include "test_precomp.hpp"
#include "npy_blob.hpp"
namespace cvtest
{
......@@ -32,7 +35,7 @@ TEST(Test_TensorFlow, read_inception)
importer->populateNet(net);
}
Mat sample = imread(_tf("grace_hopper.jpg"));
Mat sample = imread(_tf("grace_hopper_227.png"));
ASSERT_TRUE(!sample.empty());
Mat input;
resize(sample, input, Size(224, 224));
......@@ -47,4 +50,31 @@ TEST(Test_TensorFlow, read_inception)
std::cout << out.dims() << std::endl;
}
TEST(Test_TensorFlow, inception_accuracy)
{
Net net;
{
Ptr<Importer> importer = createTensorflowImporter(_tf("tensorflow_inception_graph.pb"));
ASSERT_TRUE(importer != NULL);
importer->populateNet(net);
}
Mat sample = imread(_tf("grace_hopper_227.png"));
ASSERT_TRUE(!sample.empty());
resize(sample, sample, Size(224, 224));
cv::cvtColor(sample, sample, cv::COLOR_BGR2RGB);
dnn::Blob inputBlob = dnn::Blob::fromImages(sample);
net.setBlob(".input", inputBlob);
net.forward();
Blob out = net.getBlob("softmax2");
Blob ref = blobFromNPY(_tf("tf_inception_prob.npy"));
normAssert(ref, out);
}
}
#endif
......@@ -42,6 +42,7 @@
#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER
#if defined(ENABLE_TORCH_TESTS) && ENABLE_TORCH_TESTS
#include "test_precomp.hpp"
#include "npy_blob.hpp"
namespace cvtest
{
......@@ -52,9 +53,13 @@ using namespace cv;
using namespace cv::dnn;
template<typename TStr>
static std::string _tf(TStr filename)
static std::string _tf(TStr filename, bool inTorchDir = true)
{
return (getOpenCVExtraDir() + "/dnn/torch/") + filename;
String path = getOpenCVExtraDir() + "/dnn/";
if (inTorchDir)
path += "torch/";
path += filename;
return path;
}
TEST(Torch_Importer, simple_read)
......@@ -82,6 +87,8 @@ static void runTorchNet(String prefix, String outLayerName, bool isBinary)
net.setBlob(".0", inp);
net.forward();
if (outLayerName.empty())
outLayerName = net.getLayerNames().back();
Blob out = net.getBlob(outLayerName);
normAssert(outRef, out);
......@@ -123,6 +130,37 @@ TEST(Torch_Importer, run_concat)
runTorchNet("net_concat", "l2_torchMerge", false);
}
TEST(Torch_Importer, run_deconv)
{
runTorchNet("net_deconv", "", false);
}
#if defined(ENABLE_TORCH_ENET_TESTS)
TEST(Torch_Importer, ENet_accuracy)
{
Net net;
{
Ptr<Importer> importer = createTorchImporter(_tf("Enet-model-best.net", false));
ASSERT_TRUE(importer != NULL);
importer->populateNet(net);
}
Mat sample = imread(_tf("street.png", false));
cv::cvtColor(sample, sample, cv::COLOR_BGR2RGB);
sample.convertTo(sample, CV_32F, 1/255.0);
dnn::Blob inputBlob = dnn::Blob::fromImages(sample);
net.setBlob("", inputBlob);
net.forward();
dnn::Blob out = net.getBlob(net.getLayerNames().back());
Blob ref = blobFromNPY(_tf("torch_enet_prob.npy", false));
normAssert(ref, out);
}
#endif
}
#endif
#endif
......@@ -65,3 +65,7 @@ net_concat:add(nn.ReLU())
net_concat:add(nn.Tanh())
net_concat:add(nn.Sigmoid())
save(net_concat, torch.rand(2, 6, 4, 3) - 0.5, 'net_concat')
local net_deconv = nn.Sequential()
net_deconv:add(nn.SpatialFullConvolution(3, 9, 4, 5, 1, 2, 0, 1, 0, 1))
save(net_deconv, torch.rand(2, 3, 4, 3) - 0.5, 'net_deconv')
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment