Commit 1913eb70 authored by Vitaliy Lyudvichenko's avatar Vitaliy Lyudvichenko

Adding of shape utils, more clearer layers implementations, more ocl tests

parent b70a9dc1
/*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*/
#ifndef __OPENCV_DNN_DNN_SHAPE_UTILS_HPP__
#define __OPENCV_DNN_DNN_SHAPE_UTILS_HPP__
#include <opencv2/core.hpp>
#include <ostream>
namespace cv {
namespace dnn {
std::ostream &operator<< (std::ostream &s, cv::Range &r)
{
return s << "[" << r.start << ", " << r.end << ")";
}
//Reshaping
template<typename Mat>
void reshape(Mat &m, const BlobShape &shape)
{
m = m.reshape(1, shape.dims(), shape.ptr());
}
template<typename Mat>
Mat reshaped(const Mat &m, const BlobShape &shape)
{
return m.reshape(1, shape.dims(), shape.ptr());
}
//Slicing
struct _Range : public cv::Range
{
_Range(const Range &r) : cv::Range(r) {}
_Range(int start, int size = 1) : cv::Range(start, start + size) {}
};
template<typename Mat>
Mat slice(const Mat &m, const _Range &r0)
{
//CV_Assert(m.dims >= 1);
cv::AutoBuffer<cv::Range, 4> ranges(m.dims);
for (int i = 1; i < m.dims; i++)
ranges[i] = Range::all();
ranges[0] = r0;
return m(&ranges[0]);
}
template<typename Mat>
Mat slice(const Mat &m, const _Range &r0, const _Range &r1)
{
CV_Assert(m.dims >= 2);
cv::AutoBuffer<cv::Range, 4> ranges(m.dims);
for (int i = 2; i < m.dims; i++)
ranges[i] = Range::all();
ranges[0] = r0;
ranges[1] = r1;
// for (int i = 0; i < m.dims; i++)
// std::cout << ranges[i] << "\n";
return m(&ranges[0]);
}
template<typename Mat>
Mat slice(const Mat &m, const _Range &r0, const _Range &r1, const _Range &r2)
{
CV_Assert(m.dims <= 3);
cv::AutoBuffer<cv::Range, 4> ranges(m.dims);
for (int i = 3; i < m.dims; i++)
ranges[i] = Range::all();
ranges[0] = r0;
ranges[1] = r1;
ranges[2] = r2;
return m(&ranges[0]);
}
template<typename Mat>
Mat slice(const Mat &m, const _Range &r0, const _Range &r1, const _Range &r2, const _Range &r3)
{
CV_Assert(m.dims <= 4);
cv::AutoBuffer<cv::Range, 4> ranges(m.dims);
for (int i = 4; i < m.dims; i++)
ranges[i] = Range::all();
ranges[0] = r0;
ranges[1] = r1;
ranges[2] = r2;
ranges[3] = r3;
return m(&ranges[0]);
}
}
}
#endif
......@@ -45,6 +45,7 @@
#include "convolution_layer.hpp"
#include "op_im2col.hpp"
#include "op_blas.hpp"
#include <opencv2/dnn/shape_utils.hpp>
#include <iostream>
namespace cv
......@@ -54,18 +55,6 @@ namespace dnn
typedef BlobShape Shape;
template<typename Mat>
void reshape(Mat &m, const BlobShape &shape)
{
m = m.reshape(1, shape.dims(), shape.ptr());
}
template<typename Mat>
Mat reshaped(const Mat &m, const BlobShape &shape)
{
return m.reshape(1, shape.dims(), shape.ptr());
}
ConvolutionLayer::ConvolutionLayer(LayerParams &params) : Layer(params)
{
getKernelParams(params, kerH, kerW, padH, padW, strideH, strideW);
......@@ -122,12 +111,7 @@ void ConvolutionLayer::allocate(const std::vector<Blob*> &inputs, std::vector<Bl
outputs[i].create(Shape(inputs[i]->num(), topCn, topH, topW));
}
#ifdef HAVE_OPENCL
useOpenCL = ocl::useOpenCL() && tryUseOpenCL;
#else
useOpenCL = false;
#endif
int allocFlags = useOpenCL ? Blob::ALLOC_BOTH : Blob::ALLOC_MAT;
if (!is1x1())
......@@ -149,33 +133,31 @@ inline bool ConvolutionLayer::is1x1() const
return (kerH == 1 && kerW == 1) && (strideW == 1 && strideH == 1); //hotfix with stride
}
template<typename Mat>
template<typename XMat>
void ConvolutionLayer::forward_(std::vector<Blob*> &inputs, std::vector<Blob> &outputs)
{
Mat weightsMat = reshaped(blobs[0].getRefConst<Mat>(), Shape(outCn, ksize));
Mat biasesMat = reshaped(blobs[1].getRefConst<Mat>(), Shape(outCn, 1));
XMat weightsMat = reshaped(blobs[0].getRefConst<XMat>(), Shape(outCn, ksize));
XMat biasesMat = reshaped(blobs[1].getRefConst<XMat>(), Shape(outCn, 1));
for (size_t ii = 0; ii < outputs.size(); ii++)
{
Blob &inpBlob = *inputs[ii];
Blob &outBlob = outputs[ii];
Mat inpMat = inpBlob.getRefConst<Mat>();
Mat outMat = reshaped(outBlob.getRef<Mat>(), Shape(inpBlob.num()*group*outGroupCn, outH*outW));
XMat inpMat = inpBlob.getRefConst<XMat>();
XMat outMat = reshaped(outBlob.getRef<XMat>(), Shape(inpBlob.num()*group*outGroupCn, outH*outW));
int outCurrCn = 0;
for (int n = 0; n < inpBlob.num(); n++)
{
int kerCurrCn = 0;
for (int g = 0; g < group; g++)
{
im2col(inpBlob, n, g, colBlob);
const Mat &colMat = colBlob.getRefConst<Mat>();
XMat colMat, curInp = slice(inpMat, n, _Range(g * inpGroupCn, inpGroupCn));
im2col(curInp, colMat);
Range kerRange(kerCurrCn, kerCurrCn + outGroupCn);
Mat kerMat = weightsMat.rowRange(kerRange);
_Range kerRange(g * outGroupCn, outGroupCn);
XMat kerMat = weightsMat.rowRange(kerRange);
Range outRange(outCurrCn, outCurrCn + outGroupCn);
Mat dstMat = outMat.rowRange(outRange);
_Range outRange((g + n * group) * outGroupCn, outGroupCn);
XMat dstMat = outMat.rowRange(outRange);
dnn::gemm(kerMat, colMat, 1, dstMat, 0);
......@@ -183,9 +165,6 @@ void ConvolutionLayer::forward_(std::vector<Blob*> &inputs, std::vector<Blob> &o
{
dnn::gemm(biasesMat.rowRange(kerRange), biasOnesMat, 1, dstMat, 1);
}
kerCurrCn += outGroupCn;
outCurrCn += outGroupCn;
}
}
}
......@@ -199,35 +178,39 @@ void ConvolutionLayer::forward(std::vector<Blob*> &inputs, std::vector<Blob> &ou
forward_<UMat>(inputs, outputs);
}
void ConvolutionLayer::im2col(Blob &inpBlob, int imNum, int cnGroup, Blob &colBlob)
void ConvolutionLayer::im2col(const UMat &srcImg, UMat &dstCol)
{
#ifdef HAVE_OPENCL
if (useOpenCL)
if (!is1x1())
{
std::vector<Range> ranges(4, Range::all());
ranges[0] = Range(imNum, imNum+1);
ranges[1] = Range(cnGroup*inpGroupCn, (cnGroup + 1)*inpGroupCn);
UMat src = inpBlob.umatRef()(&ranges[0]);
UMat &dst = colBlob.umatRef();
im2col_ocl(src, inpGroupCn, inpH, inpW, kerH, kerW, padH, padW, strideH, strideW, dst);
return;
im2col_ocl(srcImg, inpGroupCn, inpH, inpW, kerH, kerW, padH, padW, strideH, strideW, this->colBlob.umatRef());
dstCol = this->colBlob.umatRefConst();
}
#endif // HAVE_OPENCL
Mat &colMat = colBlob.matRef();
uchar *srcPtr = inpBlob.ptr(imNum, cnGroup*inpGroupCn);
else
{
dstCol = reshaped(srcImg, Shape(ksize, outH*outW));
}
#else
CV_Error(Error::StsInternal, "");
dstCol = srcImg; //supress warning
#endif
}
void ConvolutionLayer::im2col(const Mat &srcImg, Mat &dstCol)
{
if (is1x1())
{
colMat = Mat(ksize, inpBlob.rows()*inpBlob.cols(), inpBlob.type(), srcPtr);
dstCol = reshaped(srcImg, Shape(ksize, outH*outW));
return;
}
if (inpBlob.type() == CV_32F)
im2col_CpuPBody<float>::run((float*)srcPtr, inpGroupCn, inpH, inpW, kerH, kerW, padH, padW, strideH, strideW, colMat.ptr<float>());
if (inpBlob.type() == CV_64F)
im2col_CpuPBody<double>::run((double*)srcPtr, inpGroupCn, inpH, inpW, kerH, kerW, padH, padW, strideH, strideW, colMat.ptr<double>());
Mat &colMat = colBlob.matRef();
if (srcImg.type() == CV_32F)
im2col_CpuPBody<float>::run(srcImg.ptr<float>(), inpGroupCn, inpH, inpW, kerH, kerW, padH, padW, strideH, strideW, colMat.ptr<float>());
if (srcImg.type() == CV_64F)
im2col_CpuPBody<double>::run(srcImg.ptr<double>(), inpGroupCn, inpH, inpW, kerH, kerW, padH, padW, strideH, strideW, colMat.ptr<double>());
dstCol = colMat;
}
void ConvolutionLayer::computeInpOutShape(const Blob &inpBlob)
......
......@@ -70,7 +70,9 @@ namespace dnn
inline bool is1x1() const;
virtual void computeInpOutShape(const Blob &inpBlob);
void im2col(Blob &inpBlob, int imNum, int cnGroup, Blob &colBlob);
void im2col(const Mat &srcImg, Mat &dstCol);
void im2col(const UMat &srcImg, UMat &dstCol);
public:
ConvolutionLayer() {}
......
......@@ -16,10 +16,7 @@ void gemm(InputArray A, InputArray B, double alpha, InputOutputArray C, double b
if (C.isMat())
gemmCPU(A.getMat(), B.getMat(), alpha, C.getMatRef(), beta, flags);
else
{
cv::gemm(A, B, alpha, C, beta, C, flags);
std::cout << "OCL gemm\n";
}
}
inline void SwapRowCols(const Mat &A, int &rows, int &cols, bool isTrans)
......
......@@ -40,9 +40,8 @@
//M*/
#include "../precomp.hpp"
#include <opencv2/core/ocl.hpp>
#include "op_im2col.hpp"
#include "opencl_kernels_dnn.hpp"
#include "op_im2col.hpp"
namespace cv
{
......@@ -50,7 +49,7 @@ namespace dnn
{
#ifdef HAVE_OPENCL
void im2col_ocl(UMat &img,
void im2col_ocl(const UMat &img,
int channels, int height, int width,
int kernel_h, int kernel_w,
int pad_h, int pad_w,
......@@ -79,7 +78,7 @@ void im2col_ocl(UMat &img,
CV_Assert(im2col_ker.run(1, &globalSize, &localSize, true));
}
#endif // HAVE_OPENCL
#endif
}
}
......@@ -148,7 +148,7 @@ void col2im_cpu(const Dtype* data_col,
}
#ifdef HAVE_OPENCL
void im2col_ocl(UMat &img,
void im2col_ocl(const UMat &img,
int channels, int height, int width,
int kernel_h, int kernel_w,
int pad_h, int pad_w,
......
......@@ -40,4 +40,5 @@
//M*/
#include <opencv2/core.hpp>
#include "cvconfig.h"
#include <opencv2/dnn.hpp>
......@@ -43,6 +43,7 @@
#include "test_precomp.hpp"
#include "npy_blob.hpp"
#include <opencv2/core/ocl.hpp>
#include <opencv2/ts/ocl_test.hpp>
namespace cvtest
{
......@@ -56,7 +57,7 @@ static std::string _tf(TString filename)
return (getOpenCVExtraDir() + "/dnn/") + filename;
}
TEST(Reproducibility_GoogLeNet, Accuracy)
static void launchGoogleNetTest()
{
Net net;
{
......@@ -78,5 +79,16 @@ TEST(Reproducibility_GoogLeNet, Accuracy)
normAssert(out, ref);
}
TEST(Reproducibility_GoogLeNet, Accuracy)
{
OCL_OFF(launchGoogleNetTest());
}
OCL_TEST(Reproducibility_GoogLeNet, Accuracy)
{
OCL_ON(launchGoogleNetTest());
OCL_OFF();
}
}
#endif
......@@ -44,6 +44,7 @@
#include <iostream>
#include "npy_blob.hpp"
#include <opencv2/dnn/all_layers.hpp>
#include <opencv2/ts/ocl_test.hpp>
namespace cvtest
{
......@@ -57,7 +58,7 @@ static String _tf(TString filename)
return (getOpenCVExtraDir() + "/dnn/layers/") + filename;
}
static void testLayer(String basename, bool useCaffeModel = false, bool useCommonInputBlob = true)
void testLayerUsingCaffeModels(String basename, bool useCaffeModel = false, bool useCommonInputBlob = true)
{
String prototxt = _tf(basename + ".prototxt");
String caffemodel = _tf(basename + ".caffemodel");
......@@ -86,58 +87,62 @@ static void testLayer(String basename, bool useCaffeModel = false, bool useCommo
TEST(Layer_Test_Softmax, Accuracy)
{
testLayer("layer_softmax");
testLayerUsingCaffeModels("layer_softmax");
}
OCL_TEST(Layer_Test_Softmax, Accuracy)
{
OCL_ON(testLayerUsingCaffeModels("layer_softmax"));
OCL_OFF();
}
TEST(Layer_Test_LRN_spatial, Accuracy)
{
testLayer("layer_lrn_spatial");
testLayerUsingCaffeModels("layer_lrn_spatial");
}
TEST(Layer_Test_LRN_channels, Accuracy)
{
testLayer("layer_lrn_channels");
testLayerUsingCaffeModels("layer_lrn_channels");
}
TEST(Layer_Test_Convolution, Accuracy)
{
testLayer("layer_convolution", true);
testLayerUsingCaffeModels("layer_convolution", true);
}
OCL_TEST(Layer_Test_Convolution, Accuracy)
{
OCL_ON(testLayerUsingCaffeModels("layer_convolution", true));
OCL_OFF();
}
//TODO: move this test into separate file
TEST(Layer_Test_Convolution, AccuracyOCL)
TEST(Layer_Test_DeConvolution, Accuracy)
{
if (cv::ocl::haveOpenCL())
{
cv::ocl::setUseOpenCL(true);
testLayer("layer_convolution", true);
cv::ocl::setUseOpenCL(false);
}
testLayerUsingCaffeModels("layer_deconvolution", true, false);
}
OCL_TEST(Layer_Test_DeConvolution, Accuracy)
{
OCL_ON(testLayerUsingCaffeModels("layer_deconvolution", true, false););
OCL_OFF();
}
TEST(Layer_Test_InnerProduct, Accuracy)
{
testLayer("layer_inner_product", true);
testLayerUsingCaffeModels("layer_inner_product", true);
}
TEST(Layer_Test_Pooling_max, Accuracy)
{
testLayer("layer_pooling_max");
testLayerUsingCaffeModels("layer_pooling_max");
}
TEST(Layer_Test_Pooling_ave, Accuracy)
{
testLayer("layer_pooling_ave");
}
TEST(Layer_Test_DeConvolution, Accuracy)
{
testLayer("layer_deconvolution", true, false);
testLayerUsingCaffeModels("layer_pooling_ave");
}
TEST(Layer_Test_MVN, Accuracy)
{
testLayer("layer_mvn");
testLayerUsingCaffeModels("layer_mvn");
}
TEST(Layer_Test_Reshape, squeeze)
......
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