Commit 966b2f55 authored by Li Peng's avatar Li Peng

Overhaul bioinspired opencl implementation

This patch update bioinspired opencl code to make it working
with latest opencv, major changes include:

1. data structure update, e.g. oclMat to UMat.
2. opencl kernel optimization to get it running faster
3. accuracy and perf test update.
Signed-off-by: 's avatarLi Peng <peng.li@intel.com>
parent 86342522
......@@ -447,11 +447,6 @@ the log scale that is applied
*/
CV_EXPORTS_W Ptr<Retina> createRetina(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const float reductionFactor=1.0f, const float samplingStrenght=10.0f);
#ifdef HAVE_OPENCV_OCL
Ptr<Retina> createRetina_OCL(Size inputSize);
Ptr<Retina> createRetina_OCL(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const float reductionFactor=1.0f, const float samplingStrenght=10.0f);
#endif
//! @}
//! @}
......
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
// Fangfang Bai, fangfang@multicorewareinc.com
// Jin Ma, jin@multicorewareinc.com
//
// 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*/
#include "perf_precomp.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core/ocl.hpp"
#ifdef HAVE_OPENCV_OCL
#include "opencv2/ocl.hpp"
using namespace std::tr1;
using namespace cv;
using namespace perf;
namespace cvtest {
namespace ocl {
///////////////////////// Retina ////////////////////////
typedef tuple<bool, int, double, double> RetinaParams;
typedef TestBaseWithParam<RetinaParams> RetinaFixture;
#define OCL_TEST_CYCLE() for(; startTimer(), next(); cv::ocl::finish(), stopTimer())
PERF_TEST_P(RetinaFixture, Retina,
::testing::Combine(testing::Bool(), testing::Values((int)cv::bioinspired::RETINA_COLOR_BAYER),
testing::Values(1.0, 0.5), testing::Values(10.0, 5.0)))
{
if (!cv::ocl::haveOpenCL())
throw TestBase::PerfSkipTestException();
RetinaParams params = GetParam();
bool colorMode = get<0>(params), useLogSampling = false;
int colorSamplingMethod = get<1>(params);
double reductionFactor = get<2>(params), samplingStrength = get<3>(params);
Mat input = cv::imread(cvtest::TS::ptr()->get_data_path() + "shared/lena.png", colorMode);
ASSERT_FALSE(input.empty());
Mat gold_parvo, gold_magno;
if (getSelectedImpl() == "plain")
{
Ptr<bioinspired::Retina> gold_retina = bioinspired::createRetina(
input.size(), colorMode, colorSamplingMethod,
useLogSampling, reductionFactor, samplingStrength);
TEST_CYCLE()
{
gold_retina->run(input);
gold_retina->getParvo(gold_parvo);
gold_retina->getMagno(gold_magno);
}
}
else if (getSelectedImpl() == "ocl")
{
cv::ocl::oclMat ocl_input(input), ocl_parvo, ocl_magno;
Ptr<cv::bioinspired::Retina> ocl_retina = cv::bioinspired::createRetina_OCL(
input.size(), colorMode, colorSamplingMethod, useLogSampling,
reductionFactor, samplingStrength);
OCL_TEST_CYCLE()
{
ocl_retina->run(ocl_input);
ocl_retina->getParvo(ocl_parvo);
ocl_retina->getMagno(ocl_magno);
}
}
else
CV_TEST_FAIL_NO_IMPL();
SANITY_CHECK_NOTHING();
}
} } // namespace cvtest::ocl
#endif // HAVE_OPENCV_OCL
#include "../perf_precomp.hpp"
#include "opencv2/ts/ocl_perf.hpp"
using namespace std::tr1;
using namespace cv;
using namespace perf;
namespace cvtest {
namespace ocl {
///////////////////////// Retina ////////////////////////
typedef tuple<bool, int, double, double> RetinaParams;
typedef TestBaseWithParam<RetinaParams> RetinaFixture;
OCL_PERF_TEST_P(RetinaFixture, Retina,
::testing::Combine(testing::Bool(), testing::Values((int)cv::bioinspired::RETINA_COLOR_BAYER),
testing::Values(1.0, 0.5), testing::Values(10.0, 5.0)))
{
RetinaParams params = GetParam();
bool colorMode = get<0>(params), useLogSampling = false;
int colorSamplingMethod = get<1>(params);
float reductionFactor = static_cast<float>(get<2>(params));
float samplingStrength = static_cast<float>(get<3>(params));
Mat input = imread(getDataPath("cv/shared/lena.png"), colorMode);
ASSERT_FALSE(input.empty());
UMat ocl_parvo, ocl_magno;
{
Ptr<cv::bioinspired::Retina> retina = cv::bioinspired::createRetina(
input.size(), colorMode, colorSamplingMethod, useLogSampling,
reductionFactor, samplingStrength);
OCL_TEST_CYCLE()
{
retina->run(input);
retina->getParvo(ocl_parvo);
retina->getMagno(ocl_magno);
}
}
SANITY_CHECK_NOTHING();
}
} } // namespace cvtest::ocl
......@@ -42,12 +42,4 @@
#include "perf_precomp.hpp"
static const char * impls[] =
{
#ifdef HAVE_OPENCV_OCL
"ocl",
#endif
"plain"
};
CV_PERF_TEST_MAIN_WITH_IMPLS(ocl, impls, ::perf::TestBase::setModulePerformanceStrategy(::perf::PERF_STRATEGY_SIMPLE))
CV_PERF_TEST_MAIN(bioinspired)
......@@ -48,13 +48,10 @@
#include "opencv2/core/utility.hpp"
#include "opencv2/core/private.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/core/opencl/ocl_defs.hpp"
#include <valarray>
#ifdef HAVE_OPENCV_OCL
#include "opencv2/ocl/private/util.hpp"
#endif
namespace cv
{
......
......@@ -70,6 +70,7 @@
*/
#include "precomp.hpp"
#include "retinafilter.hpp"
#include "retina_ocl.hpp"
#include <cstdio>
#include <sstream>
#include <valarray>
......@@ -292,11 +293,25 @@ private:
bool _convertCvMat2ValarrayBuffer(InputArray inputMatToConvert, std::valarray<float> &outputValarrayMatrix);
#ifdef HAVE_OPENCL
ocl::RetinaOCLImpl* _ocl_retina;
bool ocl_run(InputArray inputImage);
bool ocl_getParvo(OutputArray retinaOutput_parvo);
bool ocl_getMagno(OutputArray retinaOutput_magno);
bool ocl_getParvoRAW(OutputArray retinaOutput_parvo);
bool ocl_getMagnoRAW(OutputArray retinaOutput_magno);
#endif
};
// smart pointers allocation :
Ptr<Retina> createRetina(Size inputSize){ return makePtr<RetinaImpl>(inputSize); }
Ptr<Retina> createRetina(Size inputSize, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const float reductionFactor, const float samplingStrenght){
Ptr<Retina> createRetina(Size inputSize)
{
return makePtr<RetinaImpl>(inputSize);
}
Ptr<Retina> createRetina(Size inputSize, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const float reductionFactor, const float samplingStrenght)
{
return makePtr<RetinaImpl>(inputSize, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght);
}
......@@ -306,18 +321,34 @@ RetinaImpl::RetinaImpl(const cv::Size inputSz)
{
_retinaFilter = 0;
_init(inputSz, true, RETINA_COLOR_BAYER, false);
#ifdef HAVE_OPENCL
_ocl_retina = 0;
if (inputSz.width % 4 == 0)
_ocl_retina = new ocl::RetinaOCLImpl(inputSz);
#endif
}
RetinaImpl::RetinaImpl(const cv::Size inputSz, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const float reductionFactor, const float samplingStrenght)
{
_retinaFilter = 0;
_init(inputSz, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght);
#ifdef HAVE_OPENCL
_ocl_retina = 0;
if (inputSz.width % 4 == 0)
_ocl_retina = new ocl::RetinaOCLImpl(inputSz, colorMode, colorSamplingMethod,
useRetinaLogSampling, reductionFactor, samplingStrenght);
#endif
}
RetinaImpl::~RetinaImpl()
{
if (_retinaFilter)
delete _retinaFilter;
#ifdef HAVE_OPENCL
if (_ocl_retina)
delete _ocl_retina;
#endif
}
/**
......@@ -529,8 +560,18 @@ void RetinaImpl::setupIPLMagnoChannel(const bool normaliseOutput, const float pa
_retinaParameters.IplMagno.localAdaptintegration_k = localAdaptintegration_k;
}
#ifdef HAVE_OPENCL
bool RetinaImpl::ocl_run(InputArray inputMatToConvert)
{
_ocl_retina->run(inputMatToConvert);
return true;
}
#endif
void RetinaImpl::run(InputArray inputMatToConvert)
{
CV_OCL_RUN((_ocl_retina != 0), ocl_run(inputMatToConvert));
// first convert input image to the compatible format : std::valarray<float>
const bool colorMode = _convertCvMat2ValarrayBuffer(inputMatToConvert.getMat(), _inputBuffer);
// process the retina
......@@ -559,8 +600,18 @@ void RetinaImpl::applyFastToneMapping(InputArray inputImage, OutputArray outputT
}
#ifdef HAVE_OPENCL
bool RetinaImpl::ocl_getParvo(OutputArray retinaOutput_parvo)
{
_ocl_retina->getParvo(retinaOutput_parvo);
return true;
}
#endif
void RetinaImpl::getParvo(OutputArray retinaOutput_parvo)
{
CV_OCL_RUN((_ocl_retina != 0) && retinaOutput_parvo.isUMat(), ocl_getParvo(retinaOutput_parvo));
if (_retinaFilter->getColorMode())
{
// reallocate output buffer (if necessary)
......@@ -572,24 +623,57 @@ void RetinaImpl::getParvo(OutputArray retinaOutput_parvo)
}
//retinaOutput_parvo/=255.0;
}
#ifdef HAVE_OPENCL
bool RetinaImpl::ocl_getMagno(OutputArray retinaOutput_magno)
{
_ocl_retina->getMagno(retinaOutput_magno);
return true;
}
#endif
void RetinaImpl::getMagno(OutputArray retinaOutput_magno)
{
CV_OCL_RUN((_ocl_retina != 0) && retinaOutput_magno.isUMat(), ocl_getMagno(retinaOutput_magno));
// reallocate output buffer (if necessary)
_convertValarrayBuffer2cvMat(_retinaFilter->getMovingContours(), _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), false, retinaOutput_magno);
//retinaOutput_magno/=255.0;
}
#ifdef HAVE_OPENCL
bool RetinaImpl::ocl_getMagnoRAW(OutputArray magnoOutputBufferCopy)
{
_ocl_retina->getMagnoRAW(magnoOutputBufferCopy);
return true;
}
#endif
// original API level data accessors : copy buffers if size matches, reallocate if required
void RetinaImpl::getMagnoRAW(OutputArray magnoOutputBufferCopy){
CV_OCL_RUN((_ocl_retina != 0) && magnoOutputBufferCopy.isUMat(), ocl_getMagnoRAW(magnoOutputBufferCopy));
// get magno channel header
const cv::Mat magnoChannel=cv::Mat(getMagnoRAW());
// copy data
magnoChannel.copyTo(magnoOutputBufferCopy);
}
#ifdef HAVE_OPENCL
bool RetinaImpl::ocl_getParvoRAW(OutputArray parvoOutputBufferCopy)
{
_ocl_retina->getParvoRAW(parvoOutputBufferCopy);
return true;
}
#endif
void RetinaImpl::getParvoRAW(OutputArray parvoOutputBufferCopy){
CV_OCL_RUN((_ocl_retina != 0) && parvoOutputBufferCopy.isUMat(), ocl_getParvoRAW(parvoOutputBufferCopy));
// get parvo channel header
const cv::Mat parvoChannel=cv::Mat(getMagnoRAW());
const cv::Mat parvoChannel=cv::Mat(getParvoRAW());
// copy data
parvoChannel.copyTo(parvoOutputBufferCopy);
}
......@@ -649,7 +733,7 @@ void RetinaImpl::_convertValarrayBuffer2cvMat(const std::valarray<float> &grayMa
for (unsigned int j=0;j<nbColumns;++j)
{
cv::Point2d pixel(j,i);
outMat.at<unsigned char>(pixel)=(unsigned char)*(valarrayPTR++);
outMat.at<unsigned char>(pixel)=(unsigned char)cvRound(*(valarrayPTR++));
}
}
}
......@@ -665,9 +749,9 @@ void RetinaImpl::_convertValarrayBuffer2cvMat(const std::valarray<float> &grayMa
{
cv::Point2d pixel(j,i);
cv::Vec3b pixelValues;
pixelValues[2]=(unsigned char)*(valarrayPTR);
pixelValues[1]=(unsigned char)*(valarrayPTR+nbPixels);
pixelValues[0]=(unsigned char)*(valarrayPTR+doubleNBpixels);
pixelValues[2]=(unsigned char)cvRound(*(valarrayPTR));
pixelValues[1]=(unsigned char)cvRound(*(valarrayPTR+nbPixels));
pixelValues[0]=(unsigned char)cvRound(*(valarrayPTR+doubleNBpixels));
outMat.at<cv::Vec3b>(pixel)=pixelValues;
}
......@@ -729,7 +813,15 @@ bool RetinaImpl::_convertCvMat2ValarrayBuffer(InputArray inputMat, std::valarray
return imageNumberOfChannels>1; // return bool : false for gray level image processing, true for color mode
}
void RetinaImpl::clearBuffers() { _retinaFilter->clearAllBuffers(); }
void RetinaImpl::clearBuffers()
{
#ifdef HAVE_OPENCL
if (_ocl_retina != 0)
_ocl_retina->clearBuffers();
#endif
_retinaFilter->clearAllBuffers();
}
void RetinaImpl::activateMovingContoursProcessing(const bool activate) { _retinaFilter->activateMovingContoursProcessing(activate); }
......
This diff is collapsed.
This diff is collapsed.
......@@ -44,87 +44,39 @@
//M*/
#include "test_precomp.hpp"
#include "opencv2/opencv_modules.hpp"
#include "opencv2/bioinspired.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/ts/ocl_test.hpp"
#include "opencv2/core/ocl.hpp" // cv::ocl::haveOpenCL
#ifdef HAVE_OPENCL
#if defined(HAVE_OPENCV_OCL)
#include "opencv2/ocl.hpp"
#define RETINA_ITERATIONS 5
static double checkNear(const cv::Mat &m1, const cv::Mat &m2)
{
return cv::norm(m1, m2, cv::NORM_INF);
}
#define PARAM_TEST_CASE(name, ...) struct name : testing::TestWithParam< std::tr1::tuple< __VA_ARGS__ > >
#define GET_PARAM(k) std::tr1::get< k >(GetParam())
static int oclInit = false;
static int oclAvailable = false;
namespace cvtest {
namespace ocl {
PARAM_TEST_CASE(Retina_OCL, bool, int, bool, double, double)
{
bool colorMode;
int colorSamplingMethod;
bool useLogSampling;
double reductionFactor;
double samplingStrength;
float reductionFactor;
float samplingStrength;
virtual void SetUp()
{
colorMode = GET_PARAM(0);
colorSamplingMethod = GET_PARAM(1);
useLogSampling = GET_PARAM(2);
reductionFactor = GET_PARAM(3);
samplingStrength = GET_PARAM(4);
if (!oclInit)
{
if (cv::ocl::haveOpenCL())
{
try
{
const cv::ocl::DeviceInfo& dev = cv::ocl::Context::getContext()->getDeviceInfo();
std::cout << "Device name:" << dev.deviceName << std::endl;
oclAvailable = true;
}
catch (...)
{
std::cout << "Device name: N/A" << std::endl;
}
}
oclInit = true;
}
reductionFactor = static_cast<float>(GET_PARAM(3));
samplingStrength = static_cast<float>(GET_PARAM(4));
}
};
TEST_P(Retina_OCL, Accuracy)
OCL_TEST_P(Retina_OCL, Accuracy)
{
if (!oclAvailable)
{
std::cout << "SKIP test" << std::endl;
return;
}
using namespace cv;
Mat input = imread(cvtest::TS::ptr()->get_data_path() + "shared/lena.png", colorMode);
CV_Assert(!input.empty());
ocl::oclMat ocl_input(input);
Ptr<bioinspired::Retina> ocl_retina = bioinspired::createRetina_OCL(
input.size(),
colorMode,
colorSamplingMethod,
useLogSampling,
reductionFactor,
samplingStrength);
Ptr<bioinspired::Retina> gold_retina = bioinspired::createRetina(
Ptr<bioinspired::Retina> retina = bioinspired::createRetina(
input.size(),
colorMode,
colorSamplingMethod,
......@@ -134,31 +86,35 @@ TEST_P(Retina_OCL, Accuracy)
Mat gold_parvo;
Mat gold_magno;
ocl::oclMat ocl_parvo;
ocl::oclMat ocl_magno;
UMat ocl_parvo;
UMat ocl_magno;
for(int i = 0; i < RETINA_ITERATIONS; i ++)
{
ocl_retina->run(ocl_input);
gold_retina->run(input);
gold_retina->getParvo(gold_parvo);
gold_retina->getMagno(gold_magno);
OCL_OFF(retina->run(input));
OCL_OFF(retina->getParvo(gold_parvo));
OCL_OFF(retina->getMagno(gold_magno));
OCL_OFF(retina->clearBuffers());
ocl_retina->getParvo(ocl_parvo);
ocl_retina->getMagno(ocl_magno);
OCL_ON(retina->run(input));
OCL_ON(retina->getParvo(ocl_parvo));
OCL_ON(retina->getMagno(ocl_magno));
OCL_ON(retina->clearBuffers());
int eps = colorMode ? 2 : 1;
int eps = 1;
EXPECT_LE(checkNear(gold_parvo, (Mat)ocl_parvo), eps);
EXPECT_LE(checkNear(gold_magno, (Mat)ocl_magno), eps);
EXPECT_MAT_NEAR(gold_parvo, ocl_parvo, eps);
EXPECT_MAT_NEAR(gold_magno, ocl_magno, eps);
}
}
INSTANTIATE_TEST_CASE_P(Contrib, Retina_OCL, testing::Combine(
OCL_INSTANTIATE_TEST_CASE_P(Contrib, Retina_OCL, testing::Combine(
testing::Bool(),
testing::Values((int)cv::bioinspired::RETINA_COLOR_BAYER),
testing::Values(false/*,true*/),
testing::Values(1.0, 0.5),
testing::Values(10.0, 5.0)));
#endif
} } // namespace cvtest::ocl
#endif // HAVE_OPENCL
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