From 43c98188953f1a31b333346495883c7c112a1fce Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Sun, 18 Aug 2013 11:32:04 +1200 Subject: [PATCH 001/295] Adding class for BOW image matcher (Feature #3005). Same prototype as BOWImgDescriptorExtractor, but do only the matching. If the feature is accepted, the BOWImgDescriptorExtractor and BOWImgDescriptorMatcher should probably refactor with inheritance. Add a class to compute the keypoints, descriptors and matching from an image should be added to. --- .../features2d/include/opencv2/features2d.hpp | 35 +++++++++ modules/features2d/src/bagofwords.cpp | 72 +++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index 1f0a92c18..2474dd594 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -1519,6 +1519,41 @@ protected: Ptr dmatcher; }; +/* + * Class to match image descriptors using bag of visual words. + */ +class CV_EXPORTS BOWImgDescriptorMatcher +{ +public: + BOWImgDescriptorMatcher( const Ptr& _dmatcher ); + virtual ~BOWImgDescriptorMatcher(); + + /* + * Compute the matching of the current descriptor according to the vocabulary. + * + * vocDescriptor the descriptors to match + * pointIdxsOfClusters vector of matching + */ + void compute( const Mat & descriptors, Mat& vocDescriptor, std::vector< std::vector< int > > * pointIdxsOfClusters = 0 ); + + /* + * Set the vocabulary + */ + void setVocabulary( const Mat& vocabulary ); + const Mat& getVocabulary() const; + + int descriptorSize() const; + int descriptorType() const; + +protected: + Mat vocabulary; + Ptr dmatcher; + +private: + int _type; +}; + + } /* namespace cv */ #endif diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index 4307983fe..5ef8b5c4b 100644 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -193,4 +193,76 @@ int BOWImgDescriptorExtractor::descriptorType() const return CV_32FC1; } +BOWImgDescriptorMatcher::BOWImgDescriptorMatcher( const Ptr& _dmatcher ) : + dmatcher(_dmatcher), + _type( -1 ) +{} + +BOWImgDescriptorMatcher::~BOWImgDescriptorMatcher() +{} + +void BOWImgDescriptorMatcher::setVocabulary( const Mat& _vocabulary ) +{ + dmatcher->clear(); + CV_Assert( _vocabulary.type() == CV_32F ); + vocabulary = _vocabulary; + dmatcher->add( std::vector(1, vocabulary) ); +} + +const Mat& BOWImgDescriptorMatcher::getVocabulary() const +{ + return vocabulary; +} + +void BOWImgDescriptorMatcher::compute( const Mat & descriptors, Mat& vocDescriptor, std::vector > * pointIdxsOfClusters ) +{ + vocDescriptor.release(); + + int clusterCount = descriptorSize(); // = vocabulary.rows + + _type = descriptors.type(); + + Mat _descriptors; + if( _type != CV_32F ) + descriptors.convertTo( _descriptors, CV_32F ); + else + descriptors.copyTo( _descriptors ); + // Match keypoint descriptors to cluster center (to vocabulary) + std::vector matches; + dmatcher->match( _descriptors, matches ); + + // Compute image descriptor + if( pointIdxsOfClusters ) + { + pointIdxsOfClusters->clear(); + pointIdxsOfClusters->resize(clusterCount); + } + + vocDescriptor = Mat::zeros( 1, clusterCount, descriptorType() ); + float *dptr = (float*)vocDescriptor.data; + for( size_t i = 0; i < matches.size(); i++ ) + { + int queryIdx = matches[i].queryIdx; + int trainIdx = matches[i].trainIdx; // cluster index + CV_Assert( queryIdx == (int)i ); + + dptr[trainIdx] = dptr[trainIdx] + 1.f; + if( pointIdxsOfClusters ) + (*pointIdxsOfClusters)[trainIdx].push_back( queryIdx ); + } + + // Normalize image descriptor. + vocDescriptor /= descriptors.rows; +} + +int BOWImgDescriptorMatcher::descriptorSize() const +{ + return vocabulary.empty() ? 0 : vocabulary.rows; +} + +int BOWImgDescriptorMatcher::descriptorType() const +{ + return _type; +} + } From 7f3273c77f72d3cb22500d2434709eb2b540dbdf Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Thu, 22 Aug 2013 15:00:32 +1200 Subject: [PATCH 002/295] Adding an export for HOGDetector compatibility. An SVM train with HOG could export a single vector for HOGDetector. --- modules/ml/include/opencv2/ml.hpp | 3 +++ modules/ml/src/svm.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/modules/ml/include/opencv2/ml.hpp b/modules/ml/include/opencv2/ml.hpp index 7a334f264..dfa605dbb 100644 --- a/modules/ml/include/opencv2/ml.hpp +++ b/modules/ml/include/opencv2/ml.hpp @@ -518,6 +518,9 @@ public: virtual CvSVMParams get_params() const { return params; }; CV_WRAP virtual void clear(); + // return a single vector for HOG detector. + virtual void get_svm_detector( std::vector< float > & detector ) const; + static CvParamGrid get_default_grid( int param_id ); virtual void write( CvFileStorage* storage, const char* name ) const; diff --git a/modules/ml/src/svm.cpp b/modules/ml/src/svm.cpp index 581abb61b..7ebecf8b8 100644 --- a/modules/ml/src/svm.cpp +++ b/modules/ml/src/svm.cpp @@ -1245,6 +1245,37 @@ const float* CvSVM::get_support_vector(int i) const return sv && (unsigned)i < (unsigned)sv_total ? sv[i] : 0; } +void CvSVM::get_svm_detector( std::vector< float > & detector ) const +{ + CV_Assert( var_all > 0 && + sv_total > 0 && + sv != 0 && + decision_func != 0 && + decision_func->alpha != 0 && + decision_func->sv_count == sv_total ); + float svi = 0.f; + + detector.clear(); //clear stuff in vector. + detector.reserve( var_all + 1 ); //reserve place for memory efficiency. + + /** + * detector^i = \sum_j support_vector_j^i * \alpha_j + * detector^dim = -\rho + */ + for( int i = 0 ; i < var_all ; ++i ) + { + svi = 0.f; + for( int j = 0 ; j < sv_total ; ++j ) + { + if( decision_func->sv_index != NULL ) // sometime the sv_index isn't store on YML/XML. + svi += (float)( sv[decision_func->sv_index[j]][i] * decision_func->alpha[ j ] ); + else + svi += (float)( sv[j][i] * decision_func->alpha[ j ] ); + } + detector.push_back( svi ); + } + detector.push_back( -decision_func->rho ); +} bool CvSVM::set_params( const CvSVMParams& _params ) { From 4fbd5707f7dc2985481d941c768ca2eb14556127 Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Thu, 22 Aug 2013 17:34:31 +1200 Subject: [PATCH 003/295] Fix warning on precision lost due to double to float conversion. --- modules/ml/src/svm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ml/src/svm.cpp b/modules/ml/src/svm.cpp index 7ebecf8b8..f7cf28d5a 100644 --- a/modules/ml/src/svm.cpp +++ b/modules/ml/src/svm.cpp @@ -1274,7 +1274,7 @@ void CvSVM::get_svm_detector( std::vector< float > & detector ) const } detector.push_back( svi ); } - detector.push_back( -decision_func->rho ); + detector.push_back( (float)-decision_func->rho ); } bool CvSVM::set_params( const CvSVMParams& _params ) From 464985205c3a011dec5a789adb38f7a50ebf9df9 Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Thu, 5 Sep 2013 16:05:54 +1200 Subject: [PATCH 004/295] Update PR after mdim review. --- .../features2d/doc/object_categorization.rst | 7 ++ .../features2d/include/opencv2/features2d.hpp | 38 +----- modules/features2d/src/bagofwords.cpp | 117 +++++------------- 3 files changed, 38 insertions(+), 124 deletions(-) diff --git a/modules/features2d/doc/object_categorization.rst b/modules/features2d/doc/object_categorization.rst index 73089ce7a..3cde0ec5b 100644 --- a/modules/features2d/doc/object_categorization.rst +++ b/modules/features2d/doc/object_categorization.rst @@ -118,6 +118,7 @@ The class declaration is the following: :: public: BOWImgDescriptorExtractor( const Ptr& dextractor, const Ptr& dmatcher ); + BOWImgDescriptorExtractor( const Ptr& dmatcher ); virtual ~BOWImgDescriptorExtractor(){} void setVocabulary( const Mat& vocabulary ); @@ -126,6 +127,8 @@ The class declaration is the following: :: Mat& imgDescriptor, vector >* pointIdxsOfClusters=0, Mat* descriptors=0 ); + void compute( const Mat& descriptors, Mat& imgDescriptor, + std::vector >* pointIdxsOfClusters=0 ); int descriptorSize() const; int descriptorType() const; @@ -141,6 +144,7 @@ BOWImgDescriptorExtractor::BOWImgDescriptorExtractor The constructor. .. ocv:function:: BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptr& dextractor, const Ptr& dmatcher ) +.. ocv:function:: BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptr& dmatcher ) :param dextractor: Descriptor extractor that is used to compute descriptors for an input image and its keypoints. @@ -171,11 +175,14 @@ BOWImgDescriptorExtractor::compute Computes an image descriptor using the set visual vocabulary. .. ocv:function:: void BOWImgDescriptorExtractor::compute( const Mat& image, vector& keypoints, Mat& imgDescriptor, vector >* pointIdxsOfClusters=0, Mat* descriptors=0 ) +.. ocv:function:: void BOWImgDescriptorExtractor::compute( const Mat& descriptors, Mat& imgDescriptor, std::vector >* pointIdxsOfClusters ) :param image: Image, for which the descriptor is computed. :param keypoints: Keypoints detected in the input image. + :param descriptors: Computed descriptors to match with vocabulary. + :param imgDescriptor: Computed output image descriptor. :param pointIdxsOfClusters: Indices of keypoints that belong to the cluster. This means that ``pointIdxsOfClusters[i]`` are keypoint indices that belong to the ``i`` -th cluster (word of vocabulary) returned if it is non-zero. diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index 2474dd594..d189b7e8e 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -1502,12 +1502,15 @@ class CV_EXPORTS BOWImgDescriptorExtractor public: BOWImgDescriptorExtractor( const Ptr& dextractor, const Ptr& dmatcher ); + BOWImgDescriptorExtractor( const Ptr& dmatcher ); virtual ~BOWImgDescriptorExtractor(); void setVocabulary( const Mat& vocabulary ); const Mat& getVocabulary() const; void compute( const Mat& image, std::vector& keypoints, Mat& imgDescriptor, std::vector >* pointIdxsOfClusters=0, Mat* descriptors=0 ); + void compute( const Mat& keypointDescriptors, Mat& imgDescriptor, + std::vector >* pointIdxsOfClusters=0 ); // compute() is not constant because DescriptorMatcher::match is not constant int descriptorSize() const; @@ -1519,41 +1522,6 @@ protected: Ptr dmatcher; }; -/* - * Class to match image descriptors using bag of visual words. - */ -class CV_EXPORTS BOWImgDescriptorMatcher -{ -public: - BOWImgDescriptorMatcher( const Ptr& _dmatcher ); - virtual ~BOWImgDescriptorMatcher(); - - /* - * Compute the matching of the current descriptor according to the vocabulary. - * - * vocDescriptor the descriptors to match - * pointIdxsOfClusters vector of matching - */ - void compute( const Mat & descriptors, Mat& vocDescriptor, std::vector< std::vector< int > > * pointIdxsOfClusters = 0 ); - - /* - * Set the vocabulary - */ - void setVocabulary( const Mat& vocabulary ); - const Mat& getVocabulary() const; - - int descriptorSize() const; - int descriptorType() const; - -protected: - Mat vocabulary; - Ptr dmatcher; - -private: - int _type; -}; - - } /* namespace cv */ #endif diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index 5ef8b5c4b..11f8c4ba3 100644 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -121,6 +121,10 @@ BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptr& _dmatcher ) : + dmatcher(_dmatcher) +{} + BOWImgDescriptorExtractor::~BOWImgDescriptorExtractor() {} @@ -144,12 +148,34 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, std::vector if( keypoints.empty() ) return; - int clusterCount = descriptorSize(); // = vocabulary.rows - // Compute descriptors for the image. Mat descriptors; dextractor->compute( image, keypoints, descriptors ); + compute( descriptors, imgDescriptor, pointIdxsOfClusters ); + + // Add the descriptors of image keypoints + if (_descriptors) { + *_descriptors = descriptors.clone(); + } +} + +int BOWImgDescriptorExtractor::descriptorSize() const +{ + return vocabulary.empty() ? 0 : vocabulary.rows; +} + +int BOWImgDescriptorExtractor::descriptorType() const +{ + return CV_32FC1; +} + +void BOWImgDescriptorExtractor::compute( const Mat& descriptors, Mat& imgDescriptor, std::vector >* pointIdxsOfClusters ) +{ + CV_Assert( vocabulary.empty() != false ); + + int clusterCount = descriptorSize(); // = vocabulary.rows + // Match keypoint descriptors to cluster center (to vocabulary) std::vector matches; dmatcher->match( descriptors, matches ); @@ -176,93 +202,6 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, std::vector // Normalize image descriptor. imgDescriptor /= descriptors.rows; - - // Add the descriptors of image keypoints - if (_descriptors) { - *_descriptors = descriptors.clone(); - } -} - -int BOWImgDescriptorExtractor::descriptorSize() const -{ - return vocabulary.empty() ? 0 : vocabulary.rows; -} - -int BOWImgDescriptorExtractor::descriptorType() const -{ - return CV_32FC1; -} - -BOWImgDescriptorMatcher::BOWImgDescriptorMatcher( const Ptr& _dmatcher ) : - dmatcher(_dmatcher), - _type( -1 ) -{} - -BOWImgDescriptorMatcher::~BOWImgDescriptorMatcher() -{} - -void BOWImgDescriptorMatcher::setVocabulary( const Mat& _vocabulary ) -{ - dmatcher->clear(); - CV_Assert( _vocabulary.type() == CV_32F ); - vocabulary = _vocabulary; - dmatcher->add( std::vector(1, vocabulary) ); -} - -const Mat& BOWImgDescriptorMatcher::getVocabulary() const -{ - return vocabulary; -} - -void BOWImgDescriptorMatcher::compute( const Mat & descriptors, Mat& vocDescriptor, std::vector > * pointIdxsOfClusters ) -{ - vocDescriptor.release(); - - int clusterCount = descriptorSize(); // = vocabulary.rows - - _type = descriptors.type(); - - Mat _descriptors; - if( _type != CV_32F ) - descriptors.convertTo( _descriptors, CV_32F ); - else - descriptors.copyTo( _descriptors ); - // Match keypoint descriptors to cluster center (to vocabulary) - std::vector matches; - dmatcher->match( _descriptors, matches ); - - // Compute image descriptor - if( pointIdxsOfClusters ) - { - pointIdxsOfClusters->clear(); - pointIdxsOfClusters->resize(clusterCount); - } - - vocDescriptor = Mat::zeros( 1, clusterCount, descriptorType() ); - float *dptr = (float*)vocDescriptor.data; - for( size_t i = 0; i < matches.size(); i++ ) - { - int queryIdx = matches[i].queryIdx; - int trainIdx = matches[i].trainIdx; // cluster index - CV_Assert( queryIdx == (int)i ); - - dptr[trainIdx] = dptr[trainIdx] + 1.f; - if( pointIdxsOfClusters ) - (*pointIdxsOfClusters)[trainIdx].push_back( queryIdx ); - } - - // Normalize image descriptor. - vocDescriptor /= descriptors.rows; -} - -int BOWImgDescriptorMatcher::descriptorSize() const -{ - return vocabulary.empty() ? 0 : vocabulary.rows; -} - -int BOWImgDescriptorMatcher::descriptorType() const -{ - return _type; } } From 2fe340bf8a8620852b5f2dd083e8bedc4fbff53e Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Thu, 5 Sep 2013 17:33:08 +1200 Subject: [PATCH 005/295] adding sample to train HOG and compare it with default people detector. --- samples/cpp/train_HOG.cpp | 402 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 402 insertions(+) create mode 100644 samples/cpp/train_HOG.cpp diff --git a/samples/cpp/train_HOG.cpp b/samples/cpp/train_HOG.cpp new file mode 100644 index 000000000..eeaafa831 --- /dev/null +++ b/samples/cpp/train_HOG.cpp @@ -0,0 +1,402 @@ +#include + +#include +#include +#include +#include + +#include + +using namespace cv; +using namespace std; + + +/* + * Convert training/testing set to be used by OpenCV Machine Learning algorithms. + * TrainData is a matrix of size (#samples x max(#cols,#rows) per samples), in 32FC1. + * Transposition of samples are made if needed. + */ +void convert_to_ml(const std::vector< cv::Mat > & train_samples, cv::Mat& trainData ) +{ + //--Convert data + const int rows = (int)train_samples.size(); + const int cols = (int)std::max( train_samples[0].cols, train_samples[0].rows ); + cv::Mat tmp(1, cols, CV_32FC1); //< used for transposition if needed + trainData = cv::Mat(rows, cols, CV_32FC1 ); + auto& itr = train_samples.begin(); + auto& end = train_samples.end(); + for( int i = 0 ; itr != end ; ++itr, ++i ) + { + CV_Assert( itr->cols == 1 || + itr->rows == 1 ); + if( itr->cols == 1 ) + { + transpose( *(itr), tmp ); + tmp.copyTo( trainData.row( i ) ); + } + else if( itr->rows == 1 ) + { + itr->copyTo( trainData.row( i ) ); + } + } +} + +void load_images( const string & prefix, const string & filename, vector< Mat > & img_lst ) +{ + string line; + ifstream file; + + file.open( (prefix+filename).c_str() ); + if( !file.is_open() ) + { + cerr << "Unable to open the list of images from " << filename << " filename." << endl; + exit( -1 ); + } + + while( 1 ) + { + getline( file, line ); + if( line == "" ) // no more file to read + break; + Mat img = imread( (prefix+line).c_str() ); // load the image + if( !img.data ) // invalid image, just skip it. + continue; +#ifdef _DEBUG + imshow( "image", img ); + waitKey( 10 ); +#endif + img_lst.push_back( img.clone() ); + } +} + +void sample_neg( const vector< Mat > & full_neg_lst, vector< Mat > & neg_lst, const Size & size ) +{ + Rect box; + box.width = size.width; + box.height = size.height; + + const int size_x = box.width; + const int size_y = box.height; + + srand( time( NULL ) ); + + auto& img = full_neg_lst.begin(); + auto& end = full_neg_lst.end(); + for( ; img != end ; ++img ) + { + box.x = rand() % (img->cols - size_x); + box.y = rand() % (img->rows - size_y); + Mat roi = (*img)(box); + neg_lst.push_back( roi.clone() ); +#ifdef _DEBUG + imshow( "img", roi.clone() ); + waitKey( 10 ); +#endif + } +} + +Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, const Size & size ) +{ + const int DIMX = size.width; + const int DIMY = size.height; + float zoomFac = 3; + Mat visu; + resize(color_origImg, visu, Size(color_origImg.cols*zoomFac, color_origImg.rows*zoomFac)); + + int blockSize = 16; + int cellSize = 8; + int gradientBinSize = 9; + float radRangeForOneBin = CV_PI/(float)gradientBinSize; // dividing 180° into 9 bins, how large (in rad) is one bin? + + // prepare data structure: 9 orientation / gradient strenghts for each cell + int cells_in_x_dir = DIMX / cellSize; + int cells_in_y_dir = DIMY / cellSize; + int totalnrofcells = cells_in_x_dir * cells_in_y_dir; + float*** gradientStrengths = new float**[cells_in_y_dir]; + int** cellUpdateCounter = new int*[cells_in_y_dir]; + for (int y=0; y & img_lst, vector< Mat > & gradient_lst, const Size & size ) +{ + HOGDescriptor hog; + hog.winSize = size; + Mat gray; + vector< Point > location; + vector< float > descriptors; + + auto& img = img_lst.begin(); + auto& end = img_lst.end(); + for( ; img != end ; ++img ) + { + cvtColor( *img, gray, COLOR_BGR2GRAY ); + hog.compute( gray, descriptors, Size( 8, 8 ), Size( 0, 0 ), location ); + gradient_lst.push_back( Mat( descriptors ).clone() ); +#ifdef _DEBUG + imshow( "gradient", get_hogdescriptor_visu( img->clone(), descriptors, size ) ); + waitKey( 10 ); +#endif + } +} + +void train_svm( const vector< Mat > & gradient_lst, const vector< int > & labels ) +{ + SVM svm; + + /* Default values to train SVM */ + SVMParams params; + params.coef0 = 0.0; + params.degree = 3; + params.term_crit.epsilon = 1e-3; + params.gamma = 0; + params.kernel_type = SVM::LINEAR; + params.nu = 0.5; + params.p = 0.1; // for EPSILON_SVR, epsilon in loss function? + params.C = 0.01; // From paper, soft classifier + params.svm_type = SVM::EPS_SVR; // C_SVC; // EPSILON_SVR; // may be also NU_SVR; // do regression task + + Mat train_data; + convert_to_ml( gradient_lst, train_data ); + + clog << "Start training..."; + svm.train( train_data, Mat( labels ), Mat(), Mat(), params ); + clog << "...[done]" << endl; + + svm.save( "my_people_detector.yml" ); +} + +void draw_locations( Mat & img, const vector< Rect > & locations, const Scalar & color ) +{ + if( !locations.empty() ) + { + auto& loc = locations.begin(); + auto& end = locations.end(); + for( ; loc != end ; ++loc ) + { + rectangle( img, *loc, color, 2 ); + } + } +} + +void test_it( const Size & size ) +{ + char key = 27; + Scalar reference( 0, 255, 0 ); + Scalar trained( 0, 0, 255 ); + Mat img, draw; + SVM svm; + HOGDescriptor hog; + HOGDescriptor my_hog; + my_hog.winSize = size; + VideoCapture video; + vector< Rect > locations; + + // Load the trained SVM. + svm.load( "my_people_detector.yml" ); + // Set the trained svm to my_hog + vector< float > hog_detector; + svm.get_svm_detector( hog_detector ); + my_hog.setSVMDetector( hog_detector ); + // Set the people detector. + hog.setSVMDetector( hog.getDefaultPeopleDetector() ); + // Open the camera. + video.open(0); + if( !video.isOpened() ) + { + cerr << "Unable to open the device 0" << endl; + exit( -1 ); + } + + while( true ) + { + video >> img; + if( !img.data ) + break; + + draw = img.clone(); + + locations.clear(); + hog.detectMultiScale( img, locations ); + draw_locations( draw, locations, reference ); + + locations.clear(); + my_hog.detectMultiScale( img, locations ); + draw_locations( draw, locations, trained ); + + imshow( "Video", draw ); + key = waitKey( 10 ); + if( 27 == key ) + break; + } +} + +int main( int argc, char** argv ) +{ + if( argc != 4 ) + { + cout << "Wrong number of parameters." << endl + << "Usage: " << argv[0] << " pos_dir pos.lst neg_dir neg.lst" << endl + << "example: " << argv[0] << " /INRIA_dataset/ Train/pos.lst /INRIA_dataset/ Train/neg.lst" << endl; + exit( -1 ); + } + vector< Mat > pos_lst; + vector< Mat > full_neg_lst; + vector< Mat > neg_lst; + vector< Mat > gradient_lst; + vector< int > labels; + + load_images( argv[1], argv[2], pos_lst ); + labels.assign( pos_lst.size(), +1 ); + const int old = labels.size(); + load_images( argv[3], argv[4], full_neg_lst ); + sample_neg( full_neg_lst, neg_lst, Size( 96,160 ) ); + labels.insert( labels.end(), neg_lst.size(), -1 ); + CV_Assert( old < labels.size() ); + + compute_hog( pos_lst, gradient_lst, Size( 96, 160 ) ); + compute_hog( neg_lst, gradient_lst, Size( 96, 160 ) ); + + train_svm( gradient_lst, labels ); + + test_it( Size( 96, 160 ) ); // change with your parameters + + return 0; +} From 0934344a3d5ed5d7e4c66fb1307fdaa0ec0d7bed Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Thu, 12 Sep 2013 18:38:49 +0200 Subject: [PATCH 006/295] Update sample and code with external computation of HOG detector. --- modules/ml/include/opencv2/ml.hpp | 3 +- modules/ml/src/svm.cpp | 32 ------ samples/cpp/train_HOG.cpp | 156 +++++++++++++++++++----------- 3 files changed, 100 insertions(+), 91 deletions(-) diff --git a/modules/ml/include/opencv2/ml.hpp b/modules/ml/include/opencv2/ml.hpp index dfa605dbb..09b5abdd7 100644 --- a/modules/ml/include/opencv2/ml.hpp +++ b/modules/ml/include/opencv2/ml.hpp @@ -518,8 +518,7 @@ public: virtual CvSVMParams get_params() const { return params; }; CV_WRAP virtual void clear(); - // return a single vector for HOG detector. - virtual void get_svm_detector( std::vector< float > & detector ) const; + virtual const CvSVMDecisionFunc* get_decision_function() const { return decision_func; } static CvParamGrid get_default_grid( int param_id ); diff --git a/modules/ml/src/svm.cpp b/modules/ml/src/svm.cpp index f7cf28d5a..ca538ad5c 100644 --- a/modules/ml/src/svm.cpp +++ b/modules/ml/src/svm.cpp @@ -1245,38 +1245,6 @@ const float* CvSVM::get_support_vector(int i) const return sv && (unsigned)i < (unsigned)sv_total ? sv[i] : 0; } -void CvSVM::get_svm_detector( std::vector< float > & detector ) const -{ - CV_Assert( var_all > 0 && - sv_total > 0 && - sv != 0 && - decision_func != 0 && - decision_func->alpha != 0 && - decision_func->sv_count == sv_total ); - float svi = 0.f; - - detector.clear(); //clear stuff in vector. - detector.reserve( var_all + 1 ); //reserve place for memory efficiency. - - /** - * detector^i = \sum_j support_vector_j^i * \alpha_j - * detector^dim = -\rho - */ - for( int i = 0 ; i < var_all ; ++i ) - { - svi = 0.f; - for( int j = 0 ; j < sv_total ; ++j ) - { - if( decision_func->sv_index != NULL ) // sometime the sv_index isn't store on YML/XML. - svi += (float)( sv[decision_func->sv_index[j]][i] * decision_func->alpha[ j ] ); - else - svi += (float)( sv[j][i] * decision_func->alpha[ j ] ); - } - detector.push_back( svi ); - } - detector.push_back( (float)-decision_func->rho ); -} - bool CvSVM::set_params( const CvSVMParams& _params ) { bool ok = false; diff --git a/samples/cpp/train_HOG.cpp b/samples/cpp/train_HOG.cpp index eeaafa831..ae2d1963b 100644 --- a/samples/cpp/train_HOG.cpp +++ b/samples/cpp/train_HOG.cpp @@ -11,22 +11,64 @@ using namespace cv; using namespace std; +void get_svm_detector(const SVM& svm, vector< float > & hog_detector ) +{ + // get the number of variables + const int var_all = svm.get_var_count(); + // get the number of support vectors + const int sv_total = svm.get_support_vector_count(); + // get the decision function + const CvSVMDecisionFunc* decision_func = svm.get_decision_function(); + // get the support vectors + const float** sv = &(svm.get_support_vector(0)); + + CV_Assert( var_all > 0 && + sv_total > 0 && + decision_func != 0 && + decision_func->alpha != 0 && + decision_func->sv_count == sv_total ); + + float svi = 0.f; + + hog_detector.clear(); //clear stuff in vector. + hog_detector.reserve( var_all + 1 ); //reserve place for memory efficiency. + + /** + * hog_detector^i = \sum_j support_vector_j^i * \alpha_j + * hog_detector^dim = -\rho + */ + for( int i = 0 ; i < var_all ; ++i ) + { + svi = 0.f; + for( int j = 0 ; j < sv_total ; ++j ) + { + if( decision_func->sv_index != NULL ) // sometime the sv_index isn't store on YML/XML. + svi += (float)( sv[decision_func->sv_index[j]][i] * decision_func->alpha[ j ] ); + else + svi += (float)( sv[j][i] * decision_func->alpha[ j ] ); + } + hog_detector.push_back( svi ); + } + hog_detector.push_back( (float)-decision_func->rho ); +} + + /* - * Convert training/testing set to be used by OpenCV Machine Learning algorithms. - * TrainData is a matrix of size (#samples x max(#cols,#rows) per samples), in 32FC1. - * Transposition of samples are made if needed. - */ +* Convert training/testing set to be used by OpenCV Machine Learning algorithms. +* TrainData is a matrix of size (#samples x max(#cols,#rows) per samples), in 32FC1. +* Transposition of samples are made if needed. +*/ void convert_to_ml(const std::vector< cv::Mat > & train_samples, cv::Mat& trainData ) { - //--Convert data + //--Convert data const int rows = (int)train_samples.size(); const int cols = (int)std::max( train_samples[0].cols, train_samples[0].rows ); cv::Mat tmp(1, cols, CV_32FC1); //< used for transposition if needed - trainData = cv::Mat(rows, cols, CV_32FC1 ); - auto& itr = train_samples.begin(); - auto& end = train_samples.end(); - for( int i = 0 ; itr != end ; ++itr, ++i ) - { + trainData = cv::Mat(rows, cols, CV_32FC1 ); + auto& itr = train_samples.begin(); + auto& end = train_samples.end(); + for( int i = 0 ; itr != end ; ++itr, ++i ) + { CV_Assert( itr->cols == 1 || itr->rows == 1 ); if( itr->cols == 1 ) @@ -38,7 +80,7 @@ void convert_to_ml(const std::vector< cv::Mat > & train_samples, cv::Mat& trainD { itr->copyTo( trainData.row( i ) ); } - } + } } void load_images( const string & prefix, const string & filename, vector< Mat > & img_lst ) @@ -52,7 +94,7 @@ void load_images( const string & prefix, const string & filename, vector< Mat > cerr << "Unable to open the list of images from " << filename << " filename." << endl; exit( -1 ); } - + while( 1 ) { getline( file, line ); @@ -102,12 +144,12 @@ Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, float zoomFac = 3; Mat visu; resize(color_origImg, visu, Size(color_origImg.cols*zoomFac, color_origImg.rows*zoomFac)); - + int blockSize = 16; int cellSize = 8; int gradientBinSize = 9; float radRangeForOneBin = CV_PI/(float)gradientBinSize; // dividing 180° into 9 bins, how large (in rad) is one bin? - + // prepare data structure: 9 orientation / gradient strenghts for each cell int cells_in_x_dir = DIMX / cellSize; int cells_in_y_dir = DIMY / cellSize; @@ -122,22 +164,22 @@ Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, { gradientStrengths[y][x] = new float[gradientBinSize]; cellUpdateCounter[y][x] = 0; - + for (int bin=0; bin& descriptorValues, cellx++; celly++; } - + for (int bin=0; bin& descriptorValues, } } } - + // draw cells for (int celly=0; celly& descriptorValues, { int drawX = cellx * cellSize; int drawY = celly * cellSize; - + int mx = drawX + cellSize/2; int my = drawY + cellSize/2; - + rectangle(visu, Point(drawX*zoomFac,drawY*zoomFac), Point((drawX+cellSize)*zoomFac,(drawY+cellSize)*zoomFac), CV_RGB(100,100,100), 1); - + // draw in each cell all 9 gradient strengths for (int bin=0; bin & img_lst, vector< Mat > & gradient_lst, const Size & size ) @@ -322,7 +364,7 @@ void test_it( const Size & size ) Scalar reference( 0, 255, 0 ); Scalar trained( 0, 0, 255 ); Mat img, draw; - SVM svm; + MySVM svm; HOGDescriptor hog; HOGDescriptor my_hog; my_hog.winSize = size; @@ -333,7 +375,7 @@ void test_it( const Size & size ) svm.load( "my_people_detector.yml" ); // Set the trained svm to my_hog vector< float > hog_detector; - svm.get_svm_detector( hog_detector ); + get_svm_detector( svm, hog_detector ); my_hog.setSVMDetector( hog_detector ); // Set the people detector. hog.setSVMDetector( hog.getDefaultPeopleDetector() ); @@ -344,7 +386,7 @@ void test_it( const Size & size ) cerr << "Unable to open the device 0" << endl; exit( -1 ); } - + while( true ) { video >> img; @@ -352,7 +394,7 @@ void test_it( const Size & size ) break; draw = img.clone(); - + locations.clear(); hog.detectMultiScale( img, locations ); draw_locations( draw, locations, reference ); @@ -373,8 +415,8 @@ int main( int argc, char** argv ) if( argc != 4 ) { cout << "Wrong number of parameters." << endl - << "Usage: " << argv[0] << " pos_dir pos.lst neg_dir neg.lst" << endl - << "example: " << argv[0] << " /INRIA_dataset/ Train/pos.lst /INRIA_dataset/ Train/neg.lst" << endl; + << "Usage: " << argv[0] << " pos_dir pos.lst neg_dir neg.lst" << endl + << "example: " << argv[0] << " /INRIA_dataset/ Train/pos.lst /INRIA_dataset/ Train/neg.lst" << endl; exit( -1 ); } vector< Mat > pos_lst; From a4ceb7b6ee9aa7c9507195de34ed3a67ff014ace Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Mon, 11 Nov 2013 19:29:39 +0100 Subject: [PATCH 007/295] Fix compilation issues. --- samples/cpp/train_HOG.cpp | 41 ++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/samples/cpp/train_HOG.cpp b/samples/cpp/train_HOG.cpp index ae2d1963b..2cc15db11 100644 --- a/samples/cpp/train_HOG.cpp +++ b/samples/cpp/train_HOG.cpp @@ -10,6 +10,15 @@ using namespace cv; using namespace std; +void get_svm_detector(const SVM& svm, vector< float > & hog_detector ); +void convert_to_ml(const std::vector< cv::Mat > & train_samples, cv::Mat& trainData ); +void load_images( const string & prefix, const string & filename, vector< Mat > & img_lst ); +void sample_neg( const vector< Mat > & full_neg_lst, vector< Mat > & neg_lst, const Size & size ); +Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, const Size & size ); +void compute_hog( const vector< Mat > & img_lst, vector< Mat > & gradient_lst, const Size & size ); +void train_svm( const vector< Mat > & gradient_lst, const vector< int > & labels ); +void draw_locations( Mat & img, const vector< Rect > & locations, const Scalar & color ); +void test_it( const Size & size ); void get_svm_detector(const SVM& svm, vector< float > & hog_detector ) { @@ -20,7 +29,9 @@ void get_svm_detector(const SVM& svm, vector< float > & hog_detector ) // get the decision function const CvSVMDecisionFunc* decision_func = svm.get_decision_function(); // get the support vectors - const float** sv = &(svm.get_support_vector(0)); + const float** sv = new const float*[ sv_total ]; + for( int i = 0 ; i < sv_total ; ++i ) + sv[ i ] = svm.get_support_vector(i); CV_Assert( var_all > 0 && sv_total > 0 && @@ -50,6 +61,8 @@ void get_svm_detector(const SVM& svm, vector< float > & hog_detector ) hog_detector.push_back( svi ); } hog_detector.push_back( (float)-decision_func->rho ); + + delete[] sv; } @@ -65,8 +78,8 @@ void convert_to_ml(const std::vector< cv::Mat > & train_samples, cv::Mat& trainD const int cols = (int)std::max( train_samples[0].cols, train_samples[0].rows ); cv::Mat tmp(1, cols, CV_32FC1); //< used for transposition if needed trainData = cv::Mat(rows, cols, CV_32FC1 ); - auto& itr = train_samples.begin(); - auto& end = train_samples.end(); + vector< Mat >::const_iterator itr = train_samples.begin(); + vector< Mat >::const_iterator end = train_samples.end(); for( int i = 0 ; itr != end ; ++itr, ++i ) { CV_Assert( itr->cols == 1 || @@ -122,8 +135,8 @@ void sample_neg( const vector< Mat > & full_neg_lst, vector< Mat > & neg_lst, co srand( time( NULL ) ); - auto& img = full_neg_lst.begin(); - auto& end = full_neg_lst.end(); + vector< Mat >::const_iterator img = full_neg_lst.begin(); + vector< Mat >::const_iterator end = full_neg_lst.end(); for( ; img != end ; ++img ) { box.x = rand() % (img->cols - size_x); @@ -221,9 +234,9 @@ Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, // compute average gradient strengths - for (int celly=0; celly& descriptorValues, } // draw cells - for (int celly=0; celly & img_lst, vector< Mat > & gradient_lst, c vector< Point > location; vector< float > descriptors; - auto& img = img_lst.begin(); - auto& end = img_lst.end(); + vector< Mat >::const_iterator img = img_lst.begin(); + vector< Mat >::const_iterator end = img_lst.end(); for( ; img != end ; ++img ) { cvtColor( *img, gray, COLOR_BGR2GRAY ); @@ -349,8 +362,8 @@ void draw_locations( Mat & img, const vector< Rect > & locations, const Scalar & { if( !locations.empty() ) { - auto& loc = locations.begin(); - auto& end = locations.end(); + vector< Rect >::const_iterator loc = locations.begin(); + vector< Rect >::const_iterator end = locations.end(); for( ; loc != end ; ++loc ) { rectangle( img, *loc, color, 2 ); @@ -364,7 +377,7 @@ void test_it( const Size & size ) Scalar reference( 0, 255, 0 ); Scalar trained( 0, 0, 255 ); Mat img, draw; - MySVM svm; + SVM svm; HOGDescriptor hog; HOGDescriptor my_hog; my_hog.winSize = size; From e1955759afaffb87bbb0d7a9abd03b7356be9414 Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Sun, 24 Nov 2013 13:22:10 +0100 Subject: [PATCH 008/295] Fix some warning. Adding missing credit for a function. --- samples/cpp/train_HOG.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/samples/cpp/train_HOG.cpp b/samples/cpp/train_HOG.cpp index 2cc15db11..5975bf88c 100644 --- a/samples/cpp/train_HOG.cpp +++ b/samples/cpp/train_HOG.cpp @@ -150,6 +150,7 @@ void sample_neg( const vector< Mat > & full_neg_lst, vector< Mat > & neg_lst, co } } +// From http://www.juergenwiki.de/work/wiki/doku.php?id=public:hog_descriptor_computation_and_visualization Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, const Size & size ) { const int DIMX = size.width; @@ -158,7 +159,6 @@ Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, Mat visu; resize(color_origImg, visu, Size(color_origImg.cols*zoomFac, color_origImg.rows*zoomFac)); - int blockSize = 16; int cellSize = 8; int gradientBinSize = 9; float radRangeForOneBin = CV_PI/(float)gradientBinSize; // dividing 180° into 9 bins, how large (in rad) is one bin? @@ -166,7 +166,6 @@ Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, // prepare data structure: 9 orientation / gradient strenghts for each cell int cells_in_x_dir = DIMX / cellSize; int cells_in_y_dir = DIMY / cellSize; - int totalnrofcells = cells_in_x_dir * cells_in_y_dir; float*** gradientStrengths = new float**[cells_in_y_dir]; int** cellUpdateCounter = new int*[cells_in_y_dir]; for (int y=0; y& descriptorValues, for (int cellNr=0; cellNr<4; cellNr++) { // compute corresponding cell nr - int cellx = blockx; - int celly = blocky; + cellx = blockx; + celly = blocky; if (cellNr==1) celly++; if (cellNr==2) cellx++; if (cellNr==3) @@ -440,7 +439,7 @@ int main( int argc, char** argv ) load_images( argv[1], argv[2], pos_lst ); labels.assign( pos_lst.size(), +1 ); - const int old = labels.size(); + const unsigned int old = labels.size(); load_images( argv[3], argv[4], full_neg_lst ); sample_neg( full_neg_lst, neg_lst, Size( 96,160 ) ); labels.insert( labels.end(), neg_lst.size(), -1 ); From 0c4da123e9ec924cd70f5ec6751040a38f1c24b3 Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Sun, 24 Nov 2013 14:33:41 +0100 Subject: [PATCH 009/295] Remove duplicate functions. --- modules/features2d/src/bagofwords.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index c0b4b2609..11f8c4ba3 100644 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -204,14 +204,4 @@ void BOWImgDescriptorExtractor::compute( const Mat& descriptors, Mat& imgDescrip imgDescriptor /= descriptors.rows; } -int BOWImgDescriptorExtractor::descriptorSize() const -{ - return vocabulary.empty() ? 0 : vocabulary.rows; -} - -int BOWImgDescriptorExtractor::descriptorType() const -{ - return CV_32FC1; -} - } From e015691b41984dfae796a3ff320825e847f73745 Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Sun, 24 Nov 2013 15:32:52 +0100 Subject: [PATCH 010/295] Fix warnings as errors. --- samples/cpp/train_HOG.cpp | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/samples/cpp/train_HOG.cpp b/samples/cpp/train_HOG.cpp index 5975bf88c..32efa0ef2 100644 --- a/samples/cpp/train_HOG.cpp +++ b/samples/cpp/train_HOG.cpp @@ -38,7 +38,7 @@ void get_svm_detector(const SVM& svm, vector< float > & hog_detector ) decision_func != 0 && decision_func->alpha != 0 && decision_func->sv_count == sv_total ); - + float svi = 0.f; hog_detector.clear(); //clear stuff in vector. @@ -108,11 +108,15 @@ void load_images( const string & prefix, const string & filename, vector< Mat > exit( -1 ); } - while( 1 ) + bool end_of_parsing = false; + while( !end_of_parsing ) { getline( file, line ); if( line == "" ) // no more file to read + { + end_of_parsing = true; break; + } Mat img = imread( (prefix+line).c_str() ); // load the image if( !img.data ) // invalid image, just skip it. continue; @@ -133,7 +137,7 @@ void sample_neg( const vector< Mat > & full_neg_lst, vector< Mat > & neg_lst, co const int size_x = box.width; const int size_y = box.height; - srand( time( NULL ) ); + srand( (unsigned int)time( NULL ) ); vector< Mat >::const_iterator img = full_neg_lst.begin(); vector< Mat >::const_iterator end = full_neg_lst.end(); @@ -152,16 +156,16 @@ void sample_neg( const vector< Mat > & full_neg_lst, vector< Mat > & neg_lst, co // From http://www.juergenwiki.de/work/wiki/doku.php?id=public:hog_descriptor_computation_and_visualization Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, const Size & size ) -{ +{ const int DIMX = size.width; const int DIMY = size.height; float zoomFac = 3; Mat visu; - resize(color_origImg, visu, Size(color_origImg.cols*zoomFac, color_origImg.rows*zoomFac)); + resize(color_origImg, visu, Size( (int)(color_origImg.cols*zoomFac), (int)(color_origImg.rows*zoomFac) ) ); int cellSize = 8; int gradientBinSize = 9; - float radRangeForOneBin = CV_PI/(float)gradientBinSize; // dividing 180° into 9 bins, how large (in rad) is one bin? + float radRangeForOneBin = (float)(CV_PI/(float)gradientBinSize); // dividing 180° into 9 bins, how large (in rad) is one bin? // prepare data structure: 9 orientation / gradient strenghts for each cell int cells_in_x_dir = DIMX / cellSize; @@ -194,7 +198,7 @@ Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, for (int blockx=0; blockx& descriptorValues, int mx = drawX + cellSize/2; int my = drawY + cellSize/2; - rectangle(visu, Point(drawX*zoomFac,drawY*zoomFac), Point((drawX+cellSize)*zoomFac,(drawY+cellSize)*zoomFac), CV_RGB(100,100,100), 1); + rectangle(visu, Point((int)(drawX*zoomFac), (int)(drawY*zoomFac)), Point((int)((drawX+cellSize)*zoomFac), (int)((drawY+cellSize)*zoomFac)), CV_RGB(100,100,100), 1); // draw in each cell all 9 gradient strengths for (int bin=0; bin& descriptorValues, float dirVecX = cos( currRad ); float dirVecY = sin( currRad ); - float maxVecLen = cellSize/2; + float maxVecLen = (float)(cellSize/2.f); float scale = 2.5; // just a visualization scale, to see the lines better // compute line coordinates @@ -284,7 +288,7 @@ Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, float y2 = my + dirVecY * currentGradStrength * maxVecLen * scale; // draw gradient visualization - line(visu, Point(x1*zoomFac,y1*zoomFac), Point(x2*zoomFac,y2*zoomFac), CV_RGB(0,255,0), 1); + line(visu, Point((int)(x1*zoomFac),(int)(y1*zoomFac)), Point((int)(x2*zoomFac),(int)(y2*zoomFac)), CV_RGB(0,255,0), 1); } // for (all bins) @@ -297,7 +301,7 @@ Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, { for (int x=0; x> img; if( !img.data ) @@ -416,9 +421,9 @@ void test_it( const Size & size ) draw_locations( draw, locations, trained ); imshow( "Video", draw ); - key = waitKey( 10 ); + key = (char)waitKey( 10 ); if( 27 == key ) - break; + end_of_process = true; } } @@ -439,7 +444,7 @@ int main( int argc, char** argv ) load_images( argv[1], argv[2], pos_lst ); labels.assign( pos_lst.size(), +1 ); - const unsigned int old = labels.size(); + const unsigned int old = (unsigned int)labels.size(); load_images( argv[3], argv[4], full_neg_lst ); sample_neg( full_neg_lst, neg_lst, Size( 96,160 ) ); labels.insert( labels.end(), neg_lst.size(), -1 ); From bf84d476fc0587f3021b5b5ca638b5160d10d44b Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Sun, 24 Nov 2013 15:38:48 +0100 Subject: [PATCH 011/295] Fix useless space... --- modules/features2d/src/bagofwords.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index 11f8c4ba3..8416ebd93 100644 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -153,10 +153,10 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, std::vector dextractor->compute( image, keypoints, descriptors ); compute( descriptors, imgDescriptor, pointIdxsOfClusters ); - + // Add the descriptors of image keypoints if (_descriptors) { - *_descriptors = descriptors.clone(); + *_descriptors = descriptors.clone(); } } From 9dc713eaba7c3bb290a24153def2699e9d8a71af Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Sun, 24 Nov 2013 15:45:05 +0100 Subject: [PATCH 012/295] Fix name of parameter to have proper documentation. --- modules/features2d/src/bagofwords.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index 8416ebd93..5eb1dd585 100644 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -170,7 +170,7 @@ int BOWImgDescriptorExtractor::descriptorType() const return CV_32FC1; } -void BOWImgDescriptorExtractor::compute( const Mat& descriptors, Mat& imgDescriptor, std::vector >* pointIdxsOfClusters ) +void BOWImgDescriptorExtractor::compute( const Mat& keypointDescriptors, Mat& imgDescriptor, std::vector >* pointIdxsOfClusters ) { CV_Assert( vocabulary.empty() != false ); From 089b8e2f4ad89934ed54636584f664a9737a6077 Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Sun, 24 Nov 2013 17:10:06 +0100 Subject: [PATCH 013/295] Suppress a space! --- samples/cpp/train_HOG.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/cpp/train_HOG.cpp b/samples/cpp/train_HOG.cpp index 32efa0ef2..3f21206a1 100644 --- a/samples/cpp/train_HOG.cpp +++ b/samples/cpp/train_HOG.cpp @@ -38,7 +38,7 @@ void get_svm_detector(const SVM& svm, vector< float > & hog_detector ) decision_func != 0 && decision_func->alpha != 0 && decision_func->sv_count == sv_total ); - + float svi = 0.f; hog_detector.clear(); //clear stuff in vector. From e8b86c86631c50de5457c7e61a918e9a525c58f6 Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Sun, 24 Nov 2013 17:14:23 +0100 Subject: [PATCH 014/295] Fix name of one parameter to fit the documentation. --- modules/features2d/src/bagofwords.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index 5eb1dd585..21301050c 100644 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -178,7 +178,7 @@ void BOWImgDescriptorExtractor::compute( const Mat& keypointDescriptors, Mat& im // Match keypoint descriptors to cluster center (to vocabulary) std::vector matches; - dmatcher->match( descriptors, matches ); + dmatcher->match( keypointDescriptors, matches ); // Compute image descriptor if( pointIdxsOfClusters ) From c90fe65f22508271e0723860739afdeec1ed5e73 Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Sun, 24 Nov 2013 17:16:45 +0100 Subject: [PATCH 015/295] Fix compilation issue related to previous commit. --- modules/features2d/src/bagofwords.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index 21301050c..a98b9723c 100644 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -201,7 +201,7 @@ void BOWImgDescriptorExtractor::compute( const Mat& keypointDescriptors, Mat& im } // Normalize image descriptor. - imgDescriptor /= descriptors.rows; + imgDescriptor /= keypointDescriptors.rows; } } From 4f74e2509ba8bc0baccfbc1e3eefebcd013fd0a8 Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Tue, 26 Nov 2013 22:50:26 +0100 Subject: [PATCH 016/295] Fix the documentation names. --- modules/features2d/doc/object_categorization.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/features2d/doc/object_categorization.rst b/modules/features2d/doc/object_categorization.rst index 55fcdee3c..480efe251 100644 --- a/modules/features2d/doc/object_categorization.rst +++ b/modules/features2d/doc/object_categorization.rst @@ -181,13 +181,13 @@ BOWImgDescriptorExtractor::compute Computes an image descriptor using the set visual vocabulary. .. ocv:function:: void BOWImgDescriptorExtractor::compute( const Mat& image, vector& keypoints, Mat& imgDescriptor, vector >* pointIdxsOfClusters=0, Mat* descriptors=0 ) -.. ocv:function:: void BOWImgDescriptorExtractor::compute( const Mat& descriptors, Mat& imgDescriptor, std::vector >* pointIdxsOfClusters ) +.. ocv:function:: void BOWImgDescriptorExtractor::compute( const Mat& keypointDescriptors, Mat& imgDescriptor, std::vector >* pointIdxsOfClusters ) :param image: Image, for which the descriptor is computed. :param keypoints: Keypoints detected in the input image. - :param descriptors: Computed descriptors to match with vocabulary. + :param keypointDescriptors: Computed descriptors to match with vocabulary. :param imgDescriptor: Computed output image descriptor. From 99c8b8c016950c33f184b8f1753de23f075cf457 Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Wed, 27 Nov 2013 11:06:52 +0100 Subject: [PATCH 017/295] Fix parameter name to fit documentation. --- modules/features2d/src/bagofwords.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index a98b9723c..e04bedb64 100644 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -141,7 +141,7 @@ const Mat& BOWImgDescriptorExtractor::getVocabulary() const } void BOWImgDescriptorExtractor::compute( const Mat& image, std::vector& keypoints, Mat& imgDescriptor, - std::vector >* pointIdxsOfClusters, Mat* _descriptors ) + std::vector >* pointIdxsOfClusters, Mat* descriptors ) { imgDescriptor.release(); @@ -155,8 +155,8 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, std::vector compute( descriptors, imgDescriptor, pointIdxsOfClusters ); // Add the descriptors of image keypoints - if (_descriptors) { - *_descriptors = descriptors.clone(); + if (descriptors) { + *descriptors = descriptors.clone(); } } From b413bcbba4df4c619ce2bceab7bc1709f4f4eac7 Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Wed, 27 Nov 2013 11:36:34 +0100 Subject: [PATCH 018/295] Fix shadow parameter. --- modules/features2d/src/bagofwords.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index e04bedb64..6d181ca69 100644 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -149,14 +149,14 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, std::vector return; // Compute descriptors for the image. - Mat descriptors; - dextractor->compute( image, keypoints, descriptors ); + Mat _descriptors; + dextractor->compute( image, keypoints, _descriptors ); - compute( descriptors, imgDescriptor, pointIdxsOfClusters ); + compute( _descriptors, imgDescriptor, pointIdxsOfClusters ); // Add the descriptors of image keypoints if (descriptors) { - *descriptors = descriptors.clone(); + *descriptors = _descriptors.clone(); } } From fb9c59dd8d68cd310c6d81952c55626b7f87a07f Mon Sep 17 00:00:00 2001 From: Mathieu Barnachon Date: Wed, 27 Nov 2013 18:14:37 +0100 Subject: [PATCH 019/295] Fix default argument. --- modules/features2d/doc/object_categorization.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/features2d/doc/object_categorization.rst b/modules/features2d/doc/object_categorization.rst index 480efe251..6f5a923d5 100644 --- a/modules/features2d/doc/object_categorization.rst +++ b/modules/features2d/doc/object_categorization.rst @@ -181,7 +181,7 @@ BOWImgDescriptorExtractor::compute Computes an image descriptor using the set visual vocabulary. .. ocv:function:: void BOWImgDescriptorExtractor::compute( const Mat& image, vector& keypoints, Mat& imgDescriptor, vector >* pointIdxsOfClusters=0, Mat* descriptors=0 ) -.. ocv:function:: void BOWImgDescriptorExtractor::compute( const Mat& keypointDescriptors, Mat& imgDescriptor, std::vector >* pointIdxsOfClusters ) +.. ocv:function:: void BOWImgDescriptorExtractor::compute( const Mat& keypointDescriptors, Mat& imgDescriptor, std::vector >* pointIdxsOfClusters=0 ) :param image: Image, for which the descriptor is computed. From 69d034ecdfcbbb906dad33a8d4841e7a6adfe7da Mon Sep 17 00:00:00 2001 From: Matthias Bady Date: Thu, 19 Dec 2013 00:15:53 +0100 Subject: [PATCH 020/295] Naive impl. Slower than CPU --- modules/ocl/include/opencv2/ocl.hpp | 20 ++++ modules/ocl/perf/perf_brief.cpp | 104 ++++++++++++++++++++ modules/ocl/src/brief.cpp | 90 +++++++++++++++++ modules/ocl/src/opencl/brief.cl | 144 ++++++++++++++++++++++++++++ 4 files changed, 358 insertions(+) create mode 100644 modules/ocl/perf/perf_brief.cpp create mode 100644 modules/ocl/src/brief.cpp create mode 100644 modules/ocl/src/opencl/brief.cl diff --git a/modules/ocl/include/opencv2/ocl.hpp b/modules/ocl/include/opencv2/ocl.hpp index ea1c214e6..76f3dcc55 100644 --- a/modules/ocl/include/opencv2/ocl.hpp +++ b/modules/ocl/include/opencv2/ocl.hpp @@ -1546,6 +1546,26 @@ namespace cv int calcKeypointsOCL(const oclMat& img, const oclMat& mask, int maxKeypoints); int nonmaxSupressionOCL(oclMat& keypoints); }; + ////////////////////////////////// BRIEF Feature Descriptor ////////////////////////////////// + class CV_EXPORTS BRIEF_OCL + { + public: + static const int PATCH_SIZE = 48; + static const int KERNEL_SIZE = 9; + + explicit BRIEF_OCL( int _bytes = 32 ); + + /* + * Compute the descriptors for a set of keypoints in an image. + * image The image. + * keypoints The input keypoints. Keypoints for which a descriptor cannot be computed are removed. + * descriptors Copmputed descriptors. Row i is the descriptor for keypoint i. + */ + void compute( const oclMat& image, oclMat& keypoints, oclMat& descriptors ) const; + protected: + + int bytes; + }; /////////////////////////////// PyrLKOpticalFlow ///////////////////////////////////// diff --git a/modules/ocl/perf/perf_brief.cpp b/modules/ocl/perf/perf_brief.cpp new file mode 100644 index 000000000..5cba78518 --- /dev/null +++ b/modules/ocl/perf/perf_brief.cpp @@ -0,0 +1,104 @@ +/*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. +// +// Authors: +// * Matthias Bady, aegirxx ==> gmail.com +// +//M*/ + +#include "perf_precomp.hpp" + +using namespace std; +using namespace cv; +using namespace ocl; +using namespace perf; + +///////////// BRIEF //////////////////////// + +typedef TestBaseWithParam > OCL_BRIEF; + +#define BRIEF_IMAGES \ + "cv/detectors_descriptors_evaluation/images_datasets/leuven/img1.png",\ + "stitching/a3.png" + +PERF_TEST_P( OCL_BRIEF, extract, testing::Combine( testing::Values( BRIEF_IMAGES ), testing::Values( 16, 32, 64 ) ) ) +{ + const int threshold = 20; + const std::string filename = std::tr1::get<0>(GetParam( )); + const int bytes = std::tr1::get<1>(GetParam( )); + const Mat img = imread( getDataPath( filename ), IMREAD_GRAYSCALE ); + ASSERT_FALSE( img.empty( ) ); + + if ( RUN_OCL_IMPL ) + { + oclMat d_img( img ); + oclMat d_keypoints; + FAST_OCL fast( threshold ); + fast( d_img, oclMat( ), d_keypoints ); + + BRIEF_OCL brief( bytes ); + + OCL_TEST_CYCLE( ) + { + oclMat d_descriptors; + brief.compute( d_img, d_keypoints, d_descriptors ); + } + + std::vector ocl_keypoints; + fast.downloadKeypoints( d_keypoints, ocl_keypoints ); + SANITY_CHECK_KEYPOINTS( ocl_keypoints ); + } + else if ( RUN_PLAIN_IMPL ) + { + std::vector keypoints; + FAST( img, keypoints, threshold ); + + BriefDescriptorExtractor brief( bytes ); + + TEST_CYCLE( ) + { + Mat descriptors; + brief.compute( img, keypoints, descriptors ); + } + + SANITY_CHECK_KEYPOINTS( keypoints ); + } + else + OCL_PERF_ELSE; +} \ No newline at end of file diff --git a/modules/ocl/src/brief.cpp b/modules/ocl/src/brief.cpp new file mode 100644 index 000000000..442eb7adb --- /dev/null +++ b/modules/ocl/src/brief.cpp @@ -0,0 +1,90 @@ +/*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) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2010, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Matthias Bady aegirxx ==> gmail.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 "precomp.hpp" +#include "opencl_kernels.hpp" + +using namespace cv; +using namespace cv::ocl; + +BRIEF_OCL::BRIEF_OCL( int _bytes ) : bytes( _bytes ) +{ +} + +void +BRIEF_OCL::compute( const oclMat& image, oclMat& keypoints, oclMat& descriptors ) const +{ + oclMat grayImage = image; + if ( image.type( ) != CV_8U ) cvtColor( image, grayImage, COLOR_BGR2GRAY ); + + oclMat sum; + integral( grayImage, sum, CV_32S ); + cl_mem sumTexture = bindTexture(sum); + + //TODO filter keypoints by border + + oclMat xRow = keypoints.row( 0 ); + oclMat yRow = keypoints.row( 1 ); + descriptors = oclMat( keypoints.cols, bytes, CV_8U ); + + std::stringstream build_opt; + build_opt << " -D BYTES=" << bytes << " -D KERNEL_SIZE=" << KERNEL_SIZE; + + const String kernelname = "extractBriefDescriptors"; + size_t globalThreads[3] = {keypoints.cols, 1, 1}; + size_t localThreads[3] = {1, 1, 1}; + + std::vector< std::pair > args; + args.push_back(std::make_pair(sizeof(cl_mem), (void *)&sumTexture)); + args.push_back(std::make_pair(sizeof(cl_mem), (void *)&xRow.data)); + args.push_back(std::make_pair(sizeof(cl_mem), (void *)&yRow.data)); + args.push_back(std::make_pair(sizeof(cl_mem), (void *)&descriptors.data)); + Context* ctx = Context::getContext( ); + openCLExecuteKernel( ctx, &brief, kernelname, globalThreads, localThreads, args, -1, -1, build_opt.str().c_str() ); + openCLFree(sumTexture); +} + +//optimiuerungsstrategieen: +// - vorher ganzes bild blurren (vgl. orb) \ No newline at end of file diff --git a/modules/ocl/src/opencl/brief.cl b/modules/ocl/src/opencl/brief.cl new file mode 100644 index 000000000..5fd03b5e3 --- /dev/null +++ b/modules/ocl/src/opencl/brief.cl @@ -0,0 +1,144 @@ +/*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 +// +// Third party copyrights are property of their respective owners. +// +// @Authors +// Matthias Bady, aegirxx ==> gmail.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*/ + +#ifndef BYTES + #define BYTES 16 +#endif + +#ifndef KERNEL_SIZE + #define KERNEL_SIZE 32 +#endif + +#define HALF_KERNEL (KERNEL_SIZE/2) + +__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST; + +inline int smoothedSum(__read_only image2d_t sum, const int2 pt) +{ + return ( read_imagei( sum, sampler, pt + (int2)( HALF_KERNEL + 1, HALF_KERNEL + 1 )) + - read_imagei( sum, sampler, pt + (int2)( -HALF_KERNEL, HALF_KERNEL + 1 )) + - read_imagei( sum, sampler, pt + (int2)( HALF_KERNEL + 1, -HALF_KERNEL )) + + read_imagei( sum, sampler, pt + (int2)( -HALF_KERNEL, -HALF_KERNEL ))).x; +} + +__kernel void extractBriefDescriptors(__read_only image2d_t sum, __global float* xRow, __global float* yRow, __global uchar* descriptors) +{ + const size_t id = get_global_id( 0 ); + uchar desc[BYTES]; + +const int2 pt = (int2)( xRow[id] + 0.5f, yRow[id] + 0.5f ); +#define SMOOTHED(y,x) smoothedSum(sum, pt + (int2)(x, y)) + desc[0] = (uchar)(((SMOOTHED(-2, -1) < SMOOTHED(7, -1)) << 7) + ((SMOOTHED(-14, -1) < SMOOTHED(-3, 3)) << 6) + ((SMOOTHED(1, -2) < SMOOTHED(11, 2)) << 5) + ((SMOOTHED(1, 6) < SMOOTHED(-10, -7)) << 4) + ((SMOOTHED(13, 2) < SMOOTHED(-1, 0)) << 3) + ((SMOOTHED(-14, 5) < SMOOTHED(5, -3)) << 2) + ((SMOOTHED(-2, 8) < SMOOTHED(2, 4)) << 1) + ((SMOOTHED(-11, 8) < SMOOTHED(-15, 5)) << 0)); + desc[1] = (uchar)(((SMOOTHED(-6, -23) < SMOOTHED(8, -9)) << 7) + ((SMOOTHED(-12, 6) < SMOOTHED(-10, 8)) << 6) + ((SMOOTHED(-3, -1) < SMOOTHED(8, 1)) << 5) + ((SMOOTHED(3, 6) < SMOOTHED(5, 6)) << 4) + ((SMOOTHED(-7, -6) < SMOOTHED(5, -5)) << 3) + ((SMOOTHED(22, -2) < SMOOTHED(-11, -8)) << 2) + ((SMOOTHED(14, 7) < SMOOTHED(8, 5)) << 1) + ((SMOOTHED(-1, 14) < SMOOTHED(-5, -14)) << 0)); + desc[2] = (uchar)(((SMOOTHED(-14, 9) < SMOOTHED(2, 0)) << 7) + ((SMOOTHED(7, -3) < SMOOTHED(22, 6)) << 6) + ((SMOOTHED(-6, 6) < SMOOTHED(-8, -5)) << 5) + ((SMOOTHED(-5, 9) < SMOOTHED(7, -1)) << 4) + ((SMOOTHED(-3, -7) < SMOOTHED(-10, -18)) << 3) + ((SMOOTHED(4, -5) < SMOOTHED(0, 11)) << 2) + ((SMOOTHED(2, 3) < SMOOTHED(9, 10)) << 1) + ((SMOOTHED(-10, 3) < SMOOTHED(4, 9)) << 0)); + desc[3] = (uchar)(((SMOOTHED(0, 12) < SMOOTHED(-3, 19)) << 7) + ((SMOOTHED(1, 15) < SMOOTHED(-11, -5)) << 6) + ((SMOOTHED(14, -1) < SMOOTHED(7, 8)) << 5) + ((SMOOTHED(7, -23) < SMOOTHED(-5, 5)) << 4) + ((SMOOTHED(0, -6) < SMOOTHED(-10, 17)) << 3) + ((SMOOTHED(13, -4) < SMOOTHED(-3, -4)) << 2) + ((SMOOTHED(-12, 1) < SMOOTHED(-12, 2)) << 1) + ((SMOOTHED(0, 8) < SMOOTHED(3, 22)) << 0)); + desc[4] = (uchar)(((SMOOTHED(-13, 13) < SMOOTHED(3, -1)) << 7) + ((SMOOTHED(-16, 17) < SMOOTHED(6, 10)) << 6) + ((SMOOTHED(7, 15) < SMOOTHED(-5, 0)) << 5) + ((SMOOTHED(2, -12) < SMOOTHED(19, -2)) << 4) + ((SMOOTHED(3, -6) < SMOOTHED(-4, -15)) << 3) + ((SMOOTHED(8, 3) < SMOOTHED(0, 14)) << 2) + ((SMOOTHED(4, -11) < SMOOTHED(5, 5)) << 1) + ((SMOOTHED(11, -7) < SMOOTHED(7, 1)) << 0)); + desc[5] = (uchar)(((SMOOTHED(6, 12) < SMOOTHED(21, 3)) << 7) + ((SMOOTHED(-3, 2) < SMOOTHED(14, 1)) << 6) + ((SMOOTHED(5, 1) < SMOOTHED(-5, 11)) << 5) + ((SMOOTHED(3, -17) < SMOOTHED(-6, 2)) << 4) + ((SMOOTHED(6, 8) < SMOOTHED(5, -10)) << 3) + ((SMOOTHED(-14, -2) < SMOOTHED(0, 4)) << 2) + ((SMOOTHED(5, -7) < SMOOTHED(-6, 5)) << 1) + ((SMOOTHED(10, 4) < SMOOTHED(4, -7)) << 0)); + desc[6] = (uchar)(((SMOOTHED(22, 0) < SMOOTHED(7, -18)) << 7) + ((SMOOTHED(-1, -3) < SMOOTHED(0, 18)) << 6) + ((SMOOTHED(-4, 22) < SMOOTHED(-5, 3)) << 5) + ((SMOOTHED(1, -7) < SMOOTHED(2, -3)) << 4) + ((SMOOTHED(19, -20) < SMOOTHED(17, -2)) << 3) + ((SMOOTHED(3, -10) < SMOOTHED(-8, 24)) << 2) + ((SMOOTHED(-5, -14) < SMOOTHED(7, 5)) << 1) + ((SMOOTHED(-2, 12) < SMOOTHED(-4, -15)) << 0)); + desc[7] = (uchar)(((SMOOTHED(4, 12) < SMOOTHED(0, -19)) << 7) + ((SMOOTHED(20, 13) < SMOOTHED(3, 5)) << 6) + ((SMOOTHED(-8, -12) < SMOOTHED(5, 0)) << 5) + ((SMOOTHED(-5, 6) < SMOOTHED(-7, -11)) << 4) + ((SMOOTHED(6, -11) < SMOOTHED(-3, -22)) << 3) + ((SMOOTHED(15, 4) < SMOOTHED(10, 1)) << 2) + ((SMOOTHED(-7, -4) < SMOOTHED(15, -6)) << 1) + ((SMOOTHED(5, 10) < SMOOTHED(0, 24)) << 0)); + desc[8] = (uchar)(((SMOOTHED(3, 6) < SMOOTHED(22, -2)) << 7) + ((SMOOTHED(-13, 14) < SMOOTHED(4, -4)) << 6) + ((SMOOTHED(-13, 8) < SMOOTHED(-18, -22)) << 5) + ((SMOOTHED(-1, -1) < SMOOTHED(-7, 3)) << 4) + ((SMOOTHED(-19, -12) < SMOOTHED(4, 3)) << 3) + ((SMOOTHED(8, 10) < SMOOTHED(13, -2)) << 2) + ((SMOOTHED(-6, -1) < SMOOTHED(-6, -5)) << 1) + ((SMOOTHED(2, -21) < SMOOTHED(-3, 2)) << 0)); + desc[9] = (uchar)(((SMOOTHED(4, -7) < SMOOTHED(0, 16)) << 7) + ((SMOOTHED(-6, -5) < SMOOTHED(-12, -1)) << 6) + ((SMOOTHED(1, -1) < SMOOTHED(9, 18)) << 5) + ((SMOOTHED(-7, 10) < SMOOTHED(-11, 6)) << 4) + ((SMOOTHED(4, 3) < SMOOTHED(19, -7)) << 3) + ((SMOOTHED(-18, 5) < SMOOTHED(-4, 5)) << 2) + ((SMOOTHED(4, 0) < SMOOTHED(-20, 4)) << 1) + ((SMOOTHED(7, -11) < SMOOTHED(18, 12)) << 0)); + desc[10] = (uchar)(((SMOOTHED(-20, 17) < SMOOTHED(-18, 7)) << 7) + ((SMOOTHED(2, 15) < SMOOTHED(19, -11)) << 6) + ((SMOOTHED(-18, 6) < SMOOTHED(-7, 3)) << 5) + ((SMOOTHED(-4, 1) < SMOOTHED(-14, 13)) << 4) + ((SMOOTHED(17, 3) < SMOOTHED(2, -8)) << 3) + ((SMOOTHED(-7, 2) < SMOOTHED(1, 6)) << 2) + ((SMOOTHED(17, -9) < SMOOTHED(-2, 8)) << 1) + ((SMOOTHED(-8, -6) < SMOOTHED(-1, 12)) << 0)); + desc[11] = (uchar)(((SMOOTHED(-2, 4) < SMOOTHED(-1, 6)) << 7) + ((SMOOTHED(-2, 7) < SMOOTHED(6, 8)) << 6) + ((SMOOTHED(-8, -1) < SMOOTHED(-7, -9)) << 5) + ((SMOOTHED(8, -9) < SMOOTHED(15, 0)) << 4) + ((SMOOTHED(0, 22) < SMOOTHED(-4, -15)) << 3) + ((SMOOTHED(-14, -1) < SMOOTHED(3, -2)) << 2) + ((SMOOTHED(-7, -4) < SMOOTHED(17, -7)) << 1) + ((SMOOTHED(-8, -2) < SMOOTHED(9, -4)) << 0)); + desc[12] = (uchar)(((SMOOTHED(5, -7) < SMOOTHED(7, 7)) << 7) + ((SMOOTHED(-5, 13) < SMOOTHED(-8, 11)) << 6) + ((SMOOTHED(11, -4) < SMOOTHED(0, 8)) << 5) + ((SMOOTHED(5, -11) < SMOOTHED(-9, -6)) << 4) + ((SMOOTHED(2, -6) < SMOOTHED(3, -20)) << 3) + ((SMOOTHED(-6, 2) < SMOOTHED(6, 10)) << 2) + ((SMOOTHED(-6, -6) < SMOOTHED(-15, 7)) << 1) + ((SMOOTHED(-6, -3) < SMOOTHED(2, 1)) << 0)); + desc[13] = (uchar)(((SMOOTHED(11, 0) < SMOOTHED(-3, 2)) << 7) + ((SMOOTHED(7, -12) < SMOOTHED(14, 5)) << 6) + ((SMOOTHED(0, -7) < SMOOTHED(-1, -1)) << 5) + ((SMOOTHED(-16, 0) < SMOOTHED(6, 8)) << 4) + ((SMOOTHED(22, 11) < SMOOTHED(0, -3)) << 3) + ((SMOOTHED(19, 0) < SMOOTHED(5, -17)) << 2) + ((SMOOTHED(-23, -14) < SMOOTHED(-13, -19)) << 1) + ((SMOOTHED(-8, 10) < SMOOTHED(-11, -2)) << 0)); + desc[14] = (uchar)(((SMOOTHED(-11, 6) < SMOOTHED(-10, 13)) << 7) + ((SMOOTHED(1, -7) < SMOOTHED(14, 0)) << 6) + ((SMOOTHED(-12, 1) < SMOOTHED(-5, -5)) << 5) + ((SMOOTHED(4, 7) < SMOOTHED(8, -1)) << 4) + ((SMOOTHED(-1, -5) < SMOOTHED(15, 2)) << 3) + ((SMOOTHED(-3, -1) < SMOOTHED(7, -10)) << 2) + ((SMOOTHED(3, -6) < SMOOTHED(10, -18)) << 1) + ((SMOOTHED(-7, -13) < SMOOTHED(-13, 10)) << 0)); + desc[15] = (uchar)(((SMOOTHED(1, -1) < SMOOTHED(13, -10)) << 7) + ((SMOOTHED(-19, 14) < SMOOTHED(8, -14)) << 6) + ((SMOOTHED(-4, -13) < SMOOTHED(7, 1)) << 5) + ((SMOOTHED(1, -2) < SMOOTHED(12, -7)) << 4) + ((SMOOTHED(3, -5) < SMOOTHED(1, -5)) << 3) + ((SMOOTHED(-2, -2) < SMOOTHED(8, -10)) << 2) + ((SMOOTHED(2, 14) < SMOOTHED(8, 7)) << 1) + ((SMOOTHED(3, 9) < SMOOTHED(8, 2)) << 0)); +#if BYTES > 16 + desc[16] = (uchar)(((SMOOTHED(-9, 1) < SMOOTHED(-18, 0)) << 7) + ((SMOOTHED(4, 0) < SMOOTHED(1, 12)) << 6) + ((SMOOTHED(0, 9) < SMOOTHED(-14, -10)) << 5) + ((SMOOTHED(-13, -9) < SMOOTHED(-2, 6)) << 4) + ((SMOOTHED(1, 5) < SMOOTHED(10, 10)) << 3) + ((SMOOTHED(-3, -6) < SMOOTHED(-16, -5)) << 2) + ((SMOOTHED(11, 6) < SMOOTHED(-5, 0)) << 1) + ((SMOOTHED(-23, 10) < SMOOTHED(1, 2)) << 0)); + desc[17] = (uchar)(((SMOOTHED(13, -5) < SMOOTHED(-3, 9)) << 7) + ((SMOOTHED(-4, -1) < SMOOTHED(-13, -5)) << 6) + ((SMOOTHED(10, 13) < SMOOTHED(-11, 8)) << 5) + ((SMOOTHED(19, 20) < SMOOTHED(-9, 2)) << 4) + ((SMOOTHED(4, -8) < SMOOTHED(0, -9)) << 3) + ((SMOOTHED(-14, 10) < SMOOTHED(15, 19)) << 2) + ((SMOOTHED(-14, -12) < SMOOTHED(-10, -3)) << 1) + ((SMOOTHED(-23, -3) < SMOOTHED(17, -2)) << 0)); + desc[18] = (uchar)(((SMOOTHED(-3, -11) < SMOOTHED(6, -14)) << 7) + ((SMOOTHED(19, -2) < SMOOTHED(-4, 2)) << 6) + ((SMOOTHED(-5, 5) < SMOOTHED(3, -13)) << 5) + ((SMOOTHED(2, -2) < SMOOTHED(-5, 4)) << 4) + ((SMOOTHED(17, 4) < SMOOTHED(17, -11)) << 3) + ((SMOOTHED(-7, -2) < SMOOTHED(1, 23)) << 2) + ((SMOOTHED(8, 13) < SMOOTHED(1, -16)) << 1) + ((SMOOTHED(-13, -5) < SMOOTHED(1, -17)) << 0)); + desc[19] = (uchar)(((SMOOTHED(4, 6) < SMOOTHED(-8, -3)) << 7) + ((SMOOTHED(-5, -9) < SMOOTHED(-2, -10)) << 6) + ((SMOOTHED(-9, 0) < SMOOTHED(-7, -2)) << 5) + ((SMOOTHED(5, 0) < SMOOTHED(5, 2)) << 4) + ((SMOOTHED(-4, -16) < SMOOTHED(6, 3)) << 3) + ((SMOOTHED(2, -15) < SMOOTHED(-2, 12)) << 2) + ((SMOOTHED(4, -1) < SMOOTHED(6, 2)) << 1) + ((SMOOTHED(1, 1) < SMOOTHED(-2, -8)) << 0)); + desc[20] = (uchar)(((SMOOTHED(-2, 12) < SMOOTHED(-5, -2)) << 7) + ((SMOOTHED(-8, 8) < SMOOTHED(-9, 9)) << 6) + ((SMOOTHED(2, -10) < SMOOTHED(3, 1)) << 5) + ((SMOOTHED(-4, 10) < SMOOTHED(-9, 4)) << 4) + ((SMOOTHED(6, 12) < SMOOTHED(2, 5)) << 3) + ((SMOOTHED(-3, -8) < SMOOTHED(0, 5)) << 2) + ((SMOOTHED(-13, 1) < SMOOTHED(-7, 2)) << 1) + ((SMOOTHED(-1, -10) < SMOOTHED(7, -18)) << 0)); + desc[21] = (uchar)(((SMOOTHED(-1, 8) < SMOOTHED(-9, -10)) << 7) + ((SMOOTHED(-23, -1) < SMOOTHED(6, 2)) << 6) + ((SMOOTHED(-5, -3) < SMOOTHED(3, 2)) << 5) + ((SMOOTHED(0, 11) < SMOOTHED(-4, -7)) << 4) + ((SMOOTHED(15, 2) < SMOOTHED(-10, -3)) << 3) + ((SMOOTHED(-20, -8) < SMOOTHED(-13, 3)) << 2) + ((SMOOTHED(-19, -12) < SMOOTHED(5, -11)) << 1) + ((SMOOTHED(-17, -13) < SMOOTHED(-3, 2)) << 0)); + desc[22] = (uchar)(((SMOOTHED(7, 4) < SMOOTHED(-12, 0)) << 7) + ((SMOOTHED(5, -1) < SMOOTHED(-14, -6)) << 6) + ((SMOOTHED(-4, 11) < SMOOTHED(0, -4)) << 5) + ((SMOOTHED(3, 10) < SMOOTHED(7, -3)) << 4) + ((SMOOTHED(13, 21) < SMOOTHED(-11, 6)) << 3) + ((SMOOTHED(-12, 24) < SMOOTHED(-7, -4)) << 2) + ((SMOOTHED(4, 16) < SMOOTHED(3, -14)) << 1) + ((SMOOTHED(-3, 5) < SMOOTHED(-7, -12)) << 0)); + desc[23] = (uchar)(((SMOOTHED(0, -4) < SMOOTHED(7, -5)) << 7) + ((SMOOTHED(-17, -9) < SMOOTHED(13, -7)) << 6) + ((SMOOTHED(22, -6) < SMOOTHED(-11, 5)) << 5) + ((SMOOTHED(2, -8) < SMOOTHED(23, -11)) << 4) + ((SMOOTHED(7, -10) < SMOOTHED(-1, 14)) << 3) + ((SMOOTHED(-3, -10) < SMOOTHED(8, 3)) << 2) + ((SMOOTHED(-13, 1) < SMOOTHED(-6, 0)) << 1) + ((SMOOTHED(-7, -21) < SMOOTHED(6, -14)) << 0)); + desc[24] = (uchar)(((SMOOTHED(18, 19) < SMOOTHED(-4, -6)) << 7) + ((SMOOTHED(10, 7) < SMOOTHED(-1, -4)) << 6) + ((SMOOTHED(-1, 21) < SMOOTHED(1, -5)) << 5) + ((SMOOTHED(-10, 6) < SMOOTHED(-11, -2)) << 4) + ((SMOOTHED(18, -3) < SMOOTHED(-1, 7)) << 3) + ((SMOOTHED(-3, -9) < SMOOTHED(-5, 10)) << 2) + ((SMOOTHED(-13, 14) < SMOOTHED(17, -3)) << 1) + ((SMOOTHED(11, -19) < SMOOTHED(-1, -18)) << 0)); + desc[25] = (uchar)(((SMOOTHED(8, -2) < SMOOTHED(-18, -23)) << 7) + ((SMOOTHED(0, -5) < SMOOTHED(-2, -9)) << 6) + ((SMOOTHED(-4, -11) < SMOOTHED(2, -8)) << 5) + ((SMOOTHED(14, 6) < SMOOTHED(-3, -6)) << 4) + ((SMOOTHED(-3, 0) < SMOOTHED(-15, 0)) << 3) + ((SMOOTHED(-9, 4) < SMOOTHED(-15, -9)) << 2) + ((SMOOTHED(-1, 11) < SMOOTHED(3, 11)) << 1) + ((SMOOTHED(-10, -16) < SMOOTHED(-7, 7)) << 0)); + desc[26] = (uchar)(((SMOOTHED(-2, -10) < SMOOTHED(-10, -2)) << 7) + ((SMOOTHED(-5, -3) < SMOOTHED(5, -23)) << 6) + ((SMOOTHED(13, -8) < SMOOTHED(-15, -11)) << 5) + ((SMOOTHED(-15, 11) < SMOOTHED(6, -6)) << 4) + ((SMOOTHED(-16, -3) < SMOOTHED(-2, 2)) << 3) + ((SMOOTHED(6, 12) < SMOOTHED(-16, 24)) << 2) + ((SMOOTHED(-10, 0) < SMOOTHED(8, 11)) << 1) + ((SMOOTHED(-7, 7) < SMOOTHED(-19, -7)) << 0)); + desc[27] = (uchar)(((SMOOTHED(5, 16) < SMOOTHED(9, -3)) << 7) + ((SMOOTHED(9, 7) < SMOOTHED(-7, -16)) << 6) + ((SMOOTHED(3, 2) < SMOOTHED(-10, 9)) << 5) + ((SMOOTHED(21, 1) < SMOOTHED(8, 7)) << 4) + ((SMOOTHED(7, 0) < SMOOTHED(1, 17)) << 3) + ((SMOOTHED(-8, 12) < SMOOTHED(9, 6)) << 2) + ((SMOOTHED(11, -7) < SMOOTHED(-8, -6)) << 1) + ((SMOOTHED(19, 0) < SMOOTHED(9, 3)) << 0)); + desc[28] = (uchar)(((SMOOTHED(1, -7) < SMOOTHED(-5, -11)) << 7) + ((SMOOTHED(0, 8) < SMOOTHED(-2, 14)) << 6) + ((SMOOTHED(12, -2) < SMOOTHED(-15, -6)) << 5) + ((SMOOTHED(4, 12) < SMOOTHED(0, -21)) << 4) + ((SMOOTHED(17, -4) < SMOOTHED(-6, -7)) << 3) + ((SMOOTHED(-10, -9) < SMOOTHED(-14, -7)) << 2) + ((SMOOTHED(-15, -10) < SMOOTHED(-15, -14)) << 1) + ((SMOOTHED(-7, -5) < SMOOTHED(5, -12)) << 0)); + desc[29] = (uchar)(((SMOOTHED(-4, 0) < SMOOTHED(15, -4)) << 7) + ((SMOOTHED(5, 2) < SMOOTHED(-6, -23)) << 6) + ((SMOOTHED(-4, -21) < SMOOTHED(-6, 4)) << 5) + ((SMOOTHED(-10, 5) < SMOOTHED(-15, 6)) << 4) + ((SMOOTHED(4, -3) < SMOOTHED(-1, 5)) << 3) + ((SMOOTHED(-4, 19) < SMOOTHED(-23, -4)) << 2) + ((SMOOTHED(-4, 17) < SMOOTHED(13, -11)) << 1) + ((SMOOTHED(1, 12) < SMOOTHED(4, -14)) << 0)); + desc[30] = (uchar)(((SMOOTHED(-11, -6) < SMOOTHED(-20, 10)) << 7) + ((SMOOTHED(4, 5) < SMOOTHED(3, 20)) << 6) + ((SMOOTHED(-8, -20) < SMOOTHED(3, 1)) << 5) + ((SMOOTHED(-19, 9) < SMOOTHED(9, -3)) << 4) + ((SMOOTHED(18, 15) < SMOOTHED(11, -4)) << 3) + ((SMOOTHED(12, 16) < SMOOTHED(8, 7)) << 2) + ((SMOOTHED(-14, -8) < SMOOTHED(-3, 9)) << 1) + ((SMOOTHED(-6, 0) < SMOOTHED(2, -4)) << 0)); + desc[31] = (uchar)(((SMOOTHED(1, -10) < SMOOTHED(-1, 2)) << 7) + ((SMOOTHED(8, -7) < SMOOTHED(-6, 18)) << 6) + ((SMOOTHED(9, 12) < SMOOTHED(-7, -23)) << 5) + ((SMOOTHED(8, -6) < SMOOTHED(5, 2)) << 4) + ((SMOOTHED(-9, 6) < SMOOTHED(-12, -7)) << 3) + ((SMOOTHED(-1, -2) < SMOOTHED(-7, 2)) << 2) + ((SMOOTHED(9, 9) < SMOOTHED(7, 15)) << 1) + ((SMOOTHED(6, 2) < SMOOTHED(-6, 6)) << 0)); +#endif +#if BYTES > 32 + desc[32] = (uchar)(((SMOOTHED(16, 12) < SMOOTHED(0, 19)) << 7) + ((SMOOTHED(4, 3) < SMOOTHED(6, 0)) << 6) + ((SMOOTHED(-2, -1) < SMOOTHED(2, 17)) << 5) + ((SMOOTHED(8, 1) < SMOOTHED(3, 1)) << 4) + ((SMOOTHED(-12, -1) < SMOOTHED(-11, 0)) << 3) + ((SMOOTHED(-11, 2) < SMOOTHED(7, 9)) << 2) + ((SMOOTHED(-1, 3) < SMOOTHED(-19, 4)) << 1) + ((SMOOTHED(-1, -11) < SMOOTHED(-1, 3)) << 0)); + desc[33] = (uchar)(((SMOOTHED(1, -10) < SMOOTHED(-10, -4)) << 7) + ((SMOOTHED(-2, 3) < SMOOTHED(6, 11)) << 6) + ((SMOOTHED(3, 7) < SMOOTHED(-9, -8)) << 5) + ((SMOOTHED(24, -14) < SMOOTHED(-2, -10)) << 4) + ((SMOOTHED(-3, -3) < SMOOTHED(-18, -6)) << 3) + ((SMOOTHED(-13, -10) < SMOOTHED(-7, -1)) << 2) + ((SMOOTHED(2, -7) < SMOOTHED(9, -6)) << 1) + ((SMOOTHED(2, -4) < SMOOTHED(6, -13)) << 0)); + desc[34] = (uchar)(((SMOOTHED(4, -4) < SMOOTHED(-2, 3)) << 7) + ((SMOOTHED(-4, 2) < SMOOTHED(9, 13)) << 6) + ((SMOOTHED(-11, 5) < SMOOTHED(-6, -11)) << 5) + ((SMOOTHED(4, -2) < SMOOTHED(11, -9)) << 4) + ((SMOOTHED(-19, 0) < SMOOTHED(-23, -5)) << 3) + ((SMOOTHED(-5, -7) < SMOOTHED(-3, -6)) << 2) + ((SMOOTHED(-6, -4) < SMOOTHED(12, 14)) << 1) + ((SMOOTHED(12, -11) < SMOOTHED(-8, -16)) << 0)); + desc[35] = (uchar)(((SMOOTHED(-21, 15) < SMOOTHED(-12, 6)) << 7) + ((SMOOTHED(-2, -1) < SMOOTHED(-8, 16)) << 6) + ((SMOOTHED(6, -1) < SMOOTHED(-8, -2)) << 5) + ((SMOOTHED(1, -1) < SMOOTHED(-9, 8)) << 4) + ((SMOOTHED(3, -4) < SMOOTHED(-2, -2)) << 3) + ((SMOOTHED(-7, 0) < SMOOTHED(4, -8)) << 2) + ((SMOOTHED(11, -11) < SMOOTHED(-12, 2)) << 1) + ((SMOOTHED(2, 3) < SMOOTHED(11, 7)) << 0)); + desc[36] = (uchar)(((SMOOTHED(-7, -4) < SMOOTHED(-9, -6)) << 7) + ((SMOOTHED(3, -7) < SMOOTHED(-5, 0)) << 6) + ((SMOOTHED(3, -7) < SMOOTHED(-10, -5)) << 5) + ((SMOOTHED(-3, -1) < SMOOTHED(8, -10)) << 4) + ((SMOOTHED(0, 8) < SMOOTHED(5, 1)) << 3) + ((SMOOTHED(9, 0) < SMOOTHED(1, 16)) << 2) + ((SMOOTHED(8, 4) < SMOOTHED(-11, -3)) << 1) + ((SMOOTHED(-15, 9) < SMOOTHED(8, 17)) << 0)); + desc[37] = (uchar)(((SMOOTHED(0, 2) < SMOOTHED(-9, 17)) << 7) + ((SMOOTHED(-6, -11) < SMOOTHED(-10, -3)) << 6) + ((SMOOTHED(1, 1) < SMOOTHED(15, -8)) << 5) + ((SMOOTHED(-12, -13) < SMOOTHED(-2, 4)) << 4) + ((SMOOTHED(-6, 4) < SMOOTHED(-6, -10)) << 3) + ((SMOOTHED(5, -7) < SMOOTHED(7, -5)) << 2) + ((SMOOTHED(10, 6) < SMOOTHED(8, 9)) << 1) + ((SMOOTHED(-5, 7) < SMOOTHED(-18, -3)) << 0)); + desc[38] = (uchar)(((SMOOTHED(-6, 3) < SMOOTHED(5, 4)) << 7) + ((SMOOTHED(-10, -13) < SMOOTHED(-5, -3)) << 6) + ((SMOOTHED(-11, 2) < SMOOTHED(-16, 0)) << 5) + ((SMOOTHED(7, -21) < SMOOTHED(-5, -13)) << 4) + ((SMOOTHED(-14, -14) < SMOOTHED(-4, -4)) << 3) + ((SMOOTHED(4, 9) < SMOOTHED(7, -3)) << 2) + ((SMOOTHED(4, 11) < SMOOTHED(10, -4)) << 1) + ((SMOOTHED(6, 17) < SMOOTHED(9, 17)) << 0)); + desc[39] = (uchar)(((SMOOTHED(-10, 8) < SMOOTHED(0, -11)) << 7) + ((SMOOTHED(-6, -16) < SMOOTHED(-6, 8)) << 6) + ((SMOOTHED(-13, 5) < SMOOTHED(10, -5)) << 5) + ((SMOOTHED(3, 2) < SMOOTHED(12, 16)) << 4) + ((SMOOTHED(13, -8) < SMOOTHED(0, -6)) << 3) + ((SMOOTHED(10, 0) < SMOOTHED(4, -11)) << 2) + ((SMOOTHED(8, 5) < SMOOTHED(10, -2)) << 1) + ((SMOOTHED(11, -7) < SMOOTHED(-13, 3)) << 0)); + desc[40] = (uchar)(((SMOOTHED(2, 4) < SMOOTHED(-7, -3)) << 7) + ((SMOOTHED(-14, -2) < SMOOTHED(-11, 16)) << 6) + ((SMOOTHED(11, -6) < SMOOTHED(7, 6)) << 5) + ((SMOOTHED(-3, 15) < SMOOTHED(8, -10)) << 4) + ((SMOOTHED(-3, 8) < SMOOTHED(12, -12)) << 3) + ((SMOOTHED(-13, 6) < SMOOTHED(-14, 7)) << 2) + ((SMOOTHED(-11, -5) < SMOOTHED(-8, -6)) << 1) + ((SMOOTHED(7, -6) < SMOOTHED(6, 3)) << 0)); + desc[41] = (uchar)(((SMOOTHED(-4, 10) < SMOOTHED(5, 1)) << 7) + ((SMOOTHED(9, 16) < SMOOTHED(10, 13)) << 6) + ((SMOOTHED(-17, 10) < SMOOTHED(2, 8)) << 5) + ((SMOOTHED(-5, 1) < SMOOTHED(4, -4)) << 4) + ((SMOOTHED(-14, 8) < SMOOTHED(-5, 2)) << 3) + ((SMOOTHED(4, -9) < SMOOTHED(-6, -3)) << 2) + ((SMOOTHED(3, -7) < SMOOTHED(-10, 0)) << 1) + ((SMOOTHED(-2, -8) < SMOOTHED(-10, 4)) << 0)); + desc[42] = (uchar)(((SMOOTHED(-8, 5) < SMOOTHED(-9, 24)) << 7) + ((SMOOTHED(2, -8) < SMOOTHED(8, -9)) << 6) + ((SMOOTHED(-4, 17) < SMOOTHED(-5, 2)) << 5) + ((SMOOTHED(14, 0) < SMOOTHED(-9, 9)) << 4) + ((SMOOTHED(11, 15) < SMOOTHED(-6, 5)) << 3) + ((SMOOTHED(-8, 1) < SMOOTHED(-3, 4)) << 2) + ((SMOOTHED(9, -21) < SMOOTHED(10, 2)) << 1) + ((SMOOTHED(2, -1) < SMOOTHED(4, 11)) << 0)); + desc[43] = (uchar)(((SMOOTHED(24, 3) < SMOOTHED(2, -2)) << 7) + ((SMOOTHED(-8, 17) < SMOOTHED(-14, -10)) << 6) + ((SMOOTHED(6, 5) < SMOOTHED(-13, 7)) << 5) + ((SMOOTHED(11, 10) < SMOOTHED(0, -1)) << 4) + ((SMOOTHED(4, 6) < SMOOTHED(-10, 6)) << 3) + ((SMOOTHED(-12, -2) < SMOOTHED(5, 6)) << 2) + ((SMOOTHED(3, -1) < SMOOTHED(8, -15)) << 1) + ((SMOOTHED(1, -4) < SMOOTHED(-7, 11)) << 0)); + desc[44] = (uchar)(((SMOOTHED(1, 11) < SMOOTHED(5, 0)) << 7) + ((SMOOTHED(6, -12) < SMOOTHED(10, 1)) << 6) + ((SMOOTHED(-3, -2) < SMOOTHED(-1, 4)) << 5) + ((SMOOTHED(-2, -11) < SMOOTHED(-1, 12)) << 4) + ((SMOOTHED(7, -8) < SMOOTHED(-20, -18)) << 3) + ((SMOOTHED(2, 0) < SMOOTHED(-9, 2)) << 2) + ((SMOOTHED(-13, -1) < SMOOTHED(-16, 2)) << 1) + ((SMOOTHED(3, -1) < SMOOTHED(-5, -17)) << 0)); + desc[45] = (uchar)(((SMOOTHED(15, 8) < SMOOTHED(3, -14)) << 7) + ((SMOOTHED(-13, -12) < SMOOTHED(6, 15)) << 6) + ((SMOOTHED(2, -8) < SMOOTHED(2, 6)) << 5) + ((SMOOTHED(6, 22) < SMOOTHED(-3, -23)) << 4) + ((SMOOTHED(-2, -7) < SMOOTHED(-6, 0)) << 3) + ((SMOOTHED(13, -10) < SMOOTHED(-6, 6)) << 2) + ((SMOOTHED(6, 7) < SMOOTHED(-10, 12)) << 1) + ((SMOOTHED(-6, 7) < SMOOTHED(-2, 11)) << 0)); + desc[46] = (uchar)(((SMOOTHED(0, -22) < SMOOTHED(-2, -17)) << 7) + ((SMOOTHED(-4, -1) < SMOOTHED(-11, -14)) << 6) + ((SMOOTHED(-2, -8) < SMOOTHED(7, 12)) << 5) + ((SMOOTHED(12, -5) < SMOOTHED(7, -13)) << 4) + ((SMOOTHED(2, -2) < SMOOTHED(-7, 6)) << 3) + ((SMOOTHED(0, 8) < SMOOTHED(-3, 23)) << 2) + ((SMOOTHED(6, 12) < SMOOTHED(13, -11)) << 1) + ((SMOOTHED(-21, -10) < SMOOTHED(10, 8)) << 0)); + desc[47] = (uchar)(((SMOOTHED(-3, 0) < SMOOTHED(7, 15)) << 7) + ((SMOOTHED(7, -6) < SMOOTHED(-5, -12)) << 6) + ((SMOOTHED(-21, -10) < SMOOTHED(12, -11)) << 5) + ((SMOOTHED(-5, -11) < SMOOTHED(8, -11)) << 4) + ((SMOOTHED(5, 0) < SMOOTHED(-11, -1)) << 3) + ((SMOOTHED(8, -9) < SMOOTHED(7, -1)) << 2) + ((SMOOTHED(11, -23) < SMOOTHED(21, -5)) << 1) + ((SMOOTHED(0, -5) < SMOOTHED(-8, 6)) << 0)); + desc[48] = (uchar)(((SMOOTHED(-6, 8) < SMOOTHED(8, 12)) << 7) + ((SMOOTHED(-7, 5) < SMOOTHED(3, -2)) << 6) + ((SMOOTHED(-5, -20) < SMOOTHED(-12, 9)) << 5) + ((SMOOTHED(-6, 12) < SMOOTHED(-11, 3)) << 4) + ((SMOOTHED(4, 5) < SMOOTHED(13, 11)) << 3) + ((SMOOTHED(2, 12) < SMOOTHED(13, -12)) << 2) + ((SMOOTHED(-4, -13) < SMOOTHED(4, 7)) << 1) + ((SMOOTHED(0, 15) < SMOOTHED(-3, -16)) << 0)); + desc[49] = (uchar)(((SMOOTHED(-3, 2) < SMOOTHED(-2, 14)) << 7) + ((SMOOTHED(4, -14) < SMOOTHED(16, -11)) << 6) + ((SMOOTHED(-13, 3) < SMOOTHED(23, 10)) << 5) + ((SMOOTHED(9, -19) < SMOOTHED(2, 5)) << 4) + ((SMOOTHED(5, 3) < SMOOTHED(14, -7)) << 3) + ((SMOOTHED(19, -13) < SMOOTHED(-11, 15)) << 2) + ((SMOOTHED(14, 0) < SMOOTHED(-2, -5)) << 1) + ((SMOOTHED(11, -4) < SMOOTHED(0, -6)) << 0)); + desc[50] = (uchar)(((SMOOTHED(-2, 5) < SMOOTHED(-13, -8)) << 7) + ((SMOOTHED(-11, -15) < SMOOTHED(-7, -17)) << 6) + ((SMOOTHED(1, 3) < SMOOTHED(-10, -8)) << 5) + ((SMOOTHED(-13, -10) < SMOOTHED(7, -12)) << 4) + ((SMOOTHED(0, -13) < SMOOTHED(23, -6)) << 3) + ((SMOOTHED(2, -17) < SMOOTHED(-7, -3)) << 2) + ((SMOOTHED(1, 3) < SMOOTHED(4, -10)) << 1) + ((SMOOTHED(13, 4) < SMOOTHED(14, -6)) << 0)); + desc[51] = (uchar)(((SMOOTHED(-19, -2) < SMOOTHED(-1, 5)) << 7) + ((SMOOTHED(9, -8) < SMOOTHED(10, -5)) << 6) + ((SMOOTHED(7, -1) < SMOOTHED(5, 7)) << 5) + ((SMOOTHED(9, -10) < SMOOTHED(19, 0)) << 4) + ((SMOOTHED(7, 5) < SMOOTHED(-4, -7)) << 3) + ((SMOOTHED(-11, 1) < SMOOTHED(-1, -11)) << 2) + ((SMOOTHED(2, -1) < SMOOTHED(-4, 11)) << 1) + ((SMOOTHED(-1, 7) < SMOOTHED(2, -2)) << 0)); + desc[52] = (uchar)(((SMOOTHED(1, -20) < SMOOTHED(-9, -6)) << 7) + ((SMOOTHED(-4, -18) < SMOOTHED(8, -18)) << 6) + ((SMOOTHED(-16, -2) < SMOOTHED(7, -6)) << 5) + ((SMOOTHED(-3, -6) < SMOOTHED(-1, -4)) << 4) + ((SMOOTHED(0, -16) < SMOOTHED(24, -5)) << 3) + ((SMOOTHED(-4, -2) < SMOOTHED(-1, 9)) << 2) + ((SMOOTHED(-8, 2) < SMOOTHED(-6, 15)) << 1) + ((SMOOTHED(11, 4) < SMOOTHED(0, -3)) << 0)); + desc[53] = (uchar)(((SMOOTHED(7, 6) < SMOOTHED(2, -10)) << 7) + ((SMOOTHED(-7, -9) < SMOOTHED(12, -6)) << 6) + ((SMOOTHED(24, 15) < SMOOTHED(-8, -1)) << 5) + ((SMOOTHED(15, -9) < SMOOTHED(-3, -15)) << 4) + ((SMOOTHED(17, -5) < SMOOTHED(11, -10)) << 3) + ((SMOOTHED(-2, 13) < SMOOTHED(-15, 4)) << 2) + ((SMOOTHED(-2, -1) < SMOOTHED(4, -23)) << 1) + ((SMOOTHED(-16, 3) < SMOOTHED(-7, -14)) << 0)); + desc[54] = (uchar)(((SMOOTHED(-3, -5) < SMOOTHED(-10, -9)) << 7) + ((SMOOTHED(-5, 3) < SMOOTHED(-2, -1)) << 6) + ((SMOOTHED(-1, 4) < SMOOTHED(1, 8)) << 5) + ((SMOOTHED(12, 9) < SMOOTHED(9, -14)) << 4) + ((SMOOTHED(-9, 17) < SMOOTHED(-3, 0)) << 3) + ((SMOOTHED(5, 4) < SMOOTHED(13, -6)) << 2) + ((SMOOTHED(-1, -8) < SMOOTHED(19, 10)) << 1) + ((SMOOTHED(8, -5) < SMOOTHED(-15, 2)) << 0)); + desc[55] = (uchar)(((SMOOTHED(-12, -9) < SMOOTHED(-4, -5)) << 7) + ((SMOOTHED(12, 0) < SMOOTHED(24, 4)) << 6) + ((SMOOTHED(8, -2) < SMOOTHED(14, 4)) << 5) + ((SMOOTHED(8, -4) < SMOOTHED(-7, 16)) << 4) + ((SMOOTHED(5, -1) < SMOOTHED(-8, -4)) << 3) + ((SMOOTHED(-2, 18) < SMOOTHED(-5, 17)) << 2) + ((SMOOTHED(8, -2) < SMOOTHED(-9, -2)) << 1) + ((SMOOTHED(3, -7) < SMOOTHED(1, -6)) << 0)); + desc[56] = (uchar)(((SMOOTHED(-5, -22) < SMOOTHED(-5, -2)) << 7) + ((SMOOTHED(-8, -10) < SMOOTHED(14, 1)) << 6) + ((SMOOTHED(-3, -13) < SMOOTHED(3, 9)) << 5) + ((SMOOTHED(-4, -1) < SMOOTHED(-1, 0)) << 4) + ((SMOOTHED(-7, -21) < SMOOTHED(12, -19)) << 3) + ((SMOOTHED(-8, 8) < SMOOTHED(24, 8)) << 2) + ((SMOOTHED(12, -6) < SMOOTHED(-2, 3)) << 1) + ((SMOOTHED(-5, -11) < SMOOTHED(-22, -4)) << 0)); + desc[57] = (uchar)(((SMOOTHED(-3, 5) < SMOOTHED(-4, 4)) << 7) + ((SMOOTHED(-16, 24) < SMOOTHED(7, -9)) << 6) + ((SMOOTHED(-10, 23) < SMOOTHED(-9, 18)) << 5) + ((SMOOTHED(1, 12) < SMOOTHED(17, 21)) << 4) + ((SMOOTHED(24, -6) < SMOOTHED(-3, -11)) << 3) + ((SMOOTHED(-7, 17) < SMOOTHED(1, -6)) << 2) + ((SMOOTHED(4, 4) < SMOOTHED(2, -7)) << 1) + ((SMOOTHED(14, 6) < SMOOTHED(-12, 3)) << 0)); + desc[58] = (uchar)(((SMOOTHED(-6, 0) < SMOOTHED(-16, 13)) << 7) + ((SMOOTHED(-10, 5) < SMOOTHED(7, 12)) << 6) + ((SMOOTHED(5, 2) < SMOOTHED(6, -3)) << 5) + ((SMOOTHED(7, 0) < SMOOTHED(-23, 1)) << 4) + ((SMOOTHED(15, -5) < SMOOTHED(1, 14)) << 3) + ((SMOOTHED(-3, -1) < SMOOTHED(6, 6)) << 2) + ((SMOOTHED(6, -9) < SMOOTHED(-9, 12)) << 1) + ((SMOOTHED(4, -2) < SMOOTHED(-4, 7)) << 0)); + desc[59] = (uchar)(((SMOOTHED(-4, -5) < SMOOTHED(4, 4)) << 7) + ((SMOOTHED(-13, 0) < SMOOTHED(6, -10)) << 6) + ((SMOOTHED(2, -12) < SMOOTHED(-6, -3)) << 5) + ((SMOOTHED(16, 0) < SMOOTHED(-3, 3)) << 4) + ((SMOOTHED(5, -14) < SMOOTHED(6, 11)) << 3) + ((SMOOTHED(5, 11) < SMOOTHED(0, -13)) << 2) + ((SMOOTHED(7, 5) < SMOOTHED(-1, -5)) << 1) + ((SMOOTHED(12, 4) < SMOOTHED(6, 10)) << 0)); + desc[60] = (uchar)(((SMOOTHED(-10, 4) < SMOOTHED(-1, -11)) << 7) + ((SMOOTHED(4, 10) < SMOOTHED(-14, 5)) << 6) + ((SMOOTHED(11, -14) < SMOOTHED(-13, 0)) << 5) + ((SMOOTHED(2, 8) < SMOOTHED(12, 24)) << 4) + ((SMOOTHED(-1, 3) < SMOOTHED(-1, 2)) << 3) + ((SMOOTHED(9, -14) < SMOOTHED(-23, 3)) << 2) + ((SMOOTHED(-8, -6) < SMOOTHED(0, 9)) << 1) + ((SMOOTHED(-15, 14) < SMOOTHED(10, -10)) << 0)); + desc[61] = (uchar)(((SMOOTHED(-10, -6) < SMOOTHED(-7, -5)) << 7) + ((SMOOTHED(11, 5) < SMOOTHED(-3, -15)) << 6) + ((SMOOTHED(1, 0) < SMOOTHED(1, 8)) << 5) + ((SMOOTHED(-11, -6) < SMOOTHED(-4, -18)) << 4) + ((SMOOTHED(9, 0) < SMOOTHED(22, -4)) << 3) + ((SMOOTHED(-5, -1) < SMOOTHED(-9, 4)) << 2) + ((SMOOTHED(-20, 2) < SMOOTHED(1, 6)) << 1) + ((SMOOTHED(1, 2) < SMOOTHED(-9, -12)) << 0)); + desc[62] = (uchar)(((SMOOTHED(5, 15) < SMOOTHED(4, -6)) << 7) + ((SMOOTHED(19, 4) < SMOOTHED(4, 11)) << 6) + ((SMOOTHED(17, -4) < SMOOTHED(-8, -1)) << 5) + ((SMOOTHED(-8, -12) < SMOOTHED(7, -3)) << 4) + ((SMOOTHED(11, 9) < SMOOTHED(8, 1)) << 3) + ((SMOOTHED(9, 22) < SMOOTHED(-15, 15)) << 2) + ((SMOOTHED(-7, -7) < SMOOTHED(1, -23)) << 1) + ((SMOOTHED(-5, 13) < SMOOTHED(-8, 2)) << 0)); + desc[63] = (uchar)(((SMOOTHED(3, -5) < SMOOTHED(11, -11)) << 7) + ((SMOOTHED(3, -18) < SMOOTHED(14, -5)) << 6) + ((SMOOTHED(-20, 7) < SMOOTHED(-10, -23)) << 5) + ((SMOOTHED(-2, -5) < SMOOTHED(6, 0)) << 4) + ((SMOOTHED(-17, -13) < SMOOTHED(-3, 2)) << 3) + ((SMOOTHED(-6, -1) < SMOOTHED(14, -2)) << 2) + ((SMOOTHED(-12, -16) < SMOOTHED(15, 6)) << 1) + ((SMOOTHED(-12, -2) < SMOOTHED(3, -19)) << 0)); +#endif + + for(int i = 0; i Date: Thu, 19 Dec 2013 01:54:57 +0100 Subject: [PATCH 021/295] Optimized version. Faster than CPU --- modules/ocl/src/brief.cpp | 27 +++--- modules/ocl/src/opencl/brief.cl | 164 +++++++++++++++++--------------- 2 files changed, 100 insertions(+), 91 deletions(-) diff --git a/modules/ocl/src/brief.cpp b/modules/ocl/src/brief.cpp index 442eb7adb..6d54eb500 100644 --- a/modules/ocl/src/brief.cpp +++ b/modules/ocl/src/brief.cpp @@ -61,30 +61,27 @@ BRIEF_OCL::compute( const oclMat& image, oclMat& keypoints, oclMat& descriptors oclMat sum; integral( grayImage, sum, CV_32S ); - cl_mem sumTexture = bindTexture(sum); + cl_mem sumTexture = bindTexture( sum ); //TODO filter keypoints by border - oclMat xRow = keypoints.row( 0 ); - oclMat yRow = keypoints.row( 1 ); descriptors = oclMat( keypoints.cols, bytes, CV_8U ); std::stringstream build_opt; build_opt << " -D BYTES=" << bytes << " -D KERNEL_SIZE=" << KERNEL_SIZE; const String kernelname = "extractBriefDescriptors"; - size_t globalThreads[3] = {keypoints.cols, 1, 1}; - size_t localThreads[3] = {1, 1, 1}; + size_t localThreads[3] = {bytes, 1, 1}; + size_t globalThreads[3] = {keypoints.cols * bytes, 1, 1}; std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&sumTexture)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&xRow.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&yRow.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&descriptors.data)); - Context* ctx = Context::getContext( ); - openCLExecuteKernel( ctx, &brief, kernelname, globalThreads, localThreads, args, -1, -1, build_opt.str().c_str() ); - openCLFree(sumTexture); -} + args.push_back( std::make_pair( sizeof (cl_mem), (void *) &sumTexture ) ); + args.push_back( std::make_pair( sizeof (cl_mem), (void *) &keypoints.data ) ); + args.push_back( std::make_pair( sizeof (cl_int), (void *) &keypoints.step ) ); + args.push_back( std::make_pair( sizeof (cl_mem), (void *) &descriptors.data ) ); + args.push_back( std::make_pair( sizeof (cl_int), (void *) &descriptors.step ) ); -//optimiuerungsstrategieen: -// - vorher ganzes bild blurren (vgl. orb) \ No newline at end of file + Context* ctx = Context::getContext( ); + openCLExecuteKernel( ctx, &brief, kernelname, globalThreads, localThreads, args, -1, -1, build_opt.str( ).c_str( ) ); + openCLFree( sumTexture ); +} diff --git a/modules/ocl/src/opencl/brief.cl b/modules/ocl/src/opencl/brief.cl index 5fd03b5e3..f75c99a30 100644 --- a/modules/ocl/src/opencl/brief.cl +++ b/modules/ocl/src/opencl/brief.cl @@ -41,6 +41,9 @@ // //M*/ +#define X_ROW 0 +#define Y_ROW 1 + #ifndef BYTES #define BYTES 16 #endif @@ -53,6 +56,78 @@ __constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST; +__constant char tests[32 * BYTES] = +{ +-2,-1,7,-1,-14,-1,-3,3,1,-2,11,2,1,6,-10,-7,13,2,-1,0,-14,5,5,-3,-2,8,2,4,-11,8,-15,5, +-6,-23,8,-9,-12,6,-10,8,-3,-1,8,1,3,6,5,6,-7,-6,5,-5,22,-2,-11,-8,14,7,8,5,-1,14,-5,-14, +-14,9,2,0,7,-3,22,6,-6,6,-8,-5,-5,9,7,-1,-3,-7,-10,-18,4,-5,0,11,2,3,9,10,-10,3,4,9, +0,12,-3,19,1,15,-11,-5,14,-1,7,8,7,-23,-5,5,0,-6,-10,17,13,-4,-3,-4,-12,1,-12,2,0,8,3,22, +-13,13,3,-1,-16,17,6,10,7,15,-5,0,2,-12,19,-2,3,-6,-4,-15,8,3,0,14,4,-11,5,5,11,-7,7,1, +6,12,21,3,-3,2,14,1,5,1,-5,11,3,-17,-6,2,6,8,5,-10,-14,-2,0,4,5,-7,-6,5,10,4,4,-7, +22,0,7,-18,-1,-3,0,18,-4,22,-5,3,1,-7,2,-3,19,-20,17,-2,3,-10,-8,24,-5,-14,7,5,-2,12,-4,-15, +4,12,0,-19,20,13,3,5,-8,-12,5,0,-5,6,-7,-11,6,-11,-3,-22,15,4,10,1,-7,-4,15,-6,5,10,0,24, +3,6,22,-2,-13,14,4,-4,-13,8,-18,-22,-1,-1,-7,3,-19,-12,4,3,8,10,13,-2,-6,-1,-6,-5,2,-21,-3,2, +4,-7,0,16,-6,-5,-12,-1,1,-1,9,18,-7,10,-11,6,4,3,19,-7,-18,5,-4,5,4,0,-20,4,7,-11,18,12, +-20,17,-18,7,2,15,19,-11,-18,6,-7,3,-4,1,-14,13,17,3,2,-8,-7,2,1,6,17,-9,-2,8,-8,-6,-1,12, +-2,4,-1,6,-2,7,6,8,-8,-1,-7,-9,8,-9,15,0,0,22,-4,-15,-14,-1,3,-2,-7,-4,17,-7,-8,-2,9,-4, +5,-7,7,7,-5,13,-8,11,11,-4,0,8,5,-11,-9,-6,2,-6,3,-20,-6,2,6,10,-6,-6,-15,7,-6,-3,2,1, +11,0,-3,2,7,-12,14,5,0,-7,-1,-1,-16,0,6,8,22,11,0,-3,19,0,5,-17,-23,-14,-13,-19,-8,10,-11,-2, +-11,6,-10,13,1,-7,14,0,-12,1,-5,-5,4,7,8,-1,-1,-5,15,2,-3,-1,7,-10,3,-6,10,-18,-7,-13,-13,10, +1,-1,13,-10,-19,14,8,-14,-4,-13,7,1,1,-2,12,-7,3,-5,1,-5,-2,-2,8,-10,2,14,8,7,3,9,8,2 +#if BYTES > 16 +,-9,1,-18,0,4,0,1,12,0,9,-14,-10,-13,-9,-2,6,1,5,10,10,-3,-6,-16,-5,11,6,-5,0,-23,10,1,2, +13,-5,-3,9,-4,-1,-13,-5,10,13,-11,8,19,20,-9,2,4,-8,0,-9,-14,10,15,19,-14,-12,-10,-3,-23,-3,17,-2, +-3,-11,6,-14,19,-2,-4,2,-5,5,3,-13,2,-2,-5,4,17,4,17,-11,-7,-2,1,23,8,13,1,-16,-13,-5,1,-17, +4,6,-8,-3,-5,-9,-2,-10,-9,0,-7,-2,5,0,5,2,-4,-16,6,3,2,-15,-2,12,4,-1,6,2,1,1,-2,-8, +-2,12,-5,-2,-8,8,-9,9,2,-10,3,1,-4,10,-9,4,6,12,2,5,-3,-8,0,5,-13,1,-7,2,-1,-10,7,-18, +-1,8,-9,-10,-23,-1,6,2,-5,-3,3,2,0,11,-4,-7,15,2,-10,-3,-20,-8,-13,3,-19,-12,5,-11,-17,-13,-3,2, +7,4,-12,0,5,-1,-14,-6,-4,11,0,-4,3,10,7,-3,13,21,-11,6,-12,24,-7,-4,4,16,3,-14,-3,5,-7,-12, +0,-4,7,-5,-17,-9,13,-7,22,-6,-11,5,2,-8,23,-11,7,-10,-1,14,-3,-10,8,3,-13,1,-6,0,-7,-21,6,-14, +18,19,-4,-6,10,7,-1,-4,-1,21,1,-5,-10,6,-11,-2,18,-3,-1,7,-3,-9,-5,10,-13,14,17,-3,11,-19,-1,-18, +8,-2,-18,-23,0,-5,-2,-9,-4,-11,2,-8,14,6,-3,-6,-3,0,-15,0,-9,4,-15,-9,-1,11,3,11,-10,-16,-7,7, +-2,-10,-10,-2,-5,-3,5,-23,13,-8,-15,-11,-15,11,6,-6,-16,-3,-2,2,6,12,-16,24,-10,0,8,11,-7,7,-19,-7, +5,16,9,-3,9,7,-7,-16,3,2,-10,9,21,1,8,7,7,0,1,17,-8,12,9,6,11,-7,-8,-6,19,0,9,3, +1,-7,-5,-11,0,8,-2,14,12,-2,-15,-6,4,12,0,-21,17,-4,-6,-7,-10,-9,-14,-7,-15,-10,-15,-14,-7,-5,5,-12, +-4,0,15,-4,5,2,-6,-23,-4,-21,-6,4,-10,5,-15,6,4,-3,-1,5,-4,19,-23,-4,-4,17,13,-11,1,12,4,-14, +-11,-6,-20,10,4,5,3,20,-8,-20,3,1,-19,9,9,-3,18,15,11,-4,12,16,8,7,-14,-8,-3,9,-6,0,2,-4, +1,-10,-1,2,8,-7,-6,18,9,12,-7,-23,8,-6,5,2,-9,6,-12,-7,-1,-2,-7,2,9,9,7,15,6,2,-6,6 +#endif +#if BYTES > 32 +,16,12,0,19,4,3,6,0,-2,-1,2,17,8,1,3,1,-12,-1,-11,0,-11,2,7,9,-1,3,-19,4,-1,-11,-1,3, +1,-10,-10,-4,-2,3,6,11,3,7,-9,-8,24,-14,-2,-10,-3,-3,-18,-6,-13,-10,-7,-1,2,-7,9,-6,2,-4,6,-13, +4,-4,-2,3,-4,2,9,13,-11,5,-6,-11,4,-2,11,-9,-19,0,-23,-5,-5,-7,-3,-6,-6,-4,12,14,12,-11,-8,-16, +-21,15,-12,6,-2,-1,-8,16,6,-1,-8,-2,1,-1,-9,8,3,-4,-2,-2,-7,0,4,-8,11,-11,-12,2,2,3,11,7, +-7,-4,-9,-6,3,-7,-5,0,3,-7,-10,-5,-3,-1,8,-10,0,8,5,1,9,0,1,16,8,4,-11,-3,-15,9,8,17, +0,2,-9,17,-6,-11,-10,-3,1,1,15,-8,-12,-13,-2,4,-6,4,-6,-10,5,-7,7,-5,10,6,8,9,-5,7,-18,-3, +-6,3,5,4,-10,-13,-5,-3,-11,2,-16,0,7,-21,-5,-13,-14,-14,-4,-4,4,9,7,-3,4,11,10,-4,6,17,9,17, +-10,8,0,-11,-6,-16,-6,8,-13,5,10,-5,3,2,12,16,13,-8,0,-6,10,0,4,-11,8,5,10,-2,11,-7,-13,3, +2,4,-7,-3,-14,-2,-11,16,11,-6,7,6,-3,15,8,-10,-3,8,12,-12,-13,6,-14,7,-11,-5,-8,-6,7,-6,6,3, +-4,10,5,1,9,16,10,13,-17,10,2,8,-5,1,4,-4,-14,8,-5,2,4,-9,-6,-3,3,-7,-10,0,-2,-8,-10,4, +-8,5,-9,24,2,-8,8,-9,-4,17,-5,2,14,0,-9,9,11,15,-6,5,-8,1,-3,4,9,-21,10,2,2,-1,4,11, +24,3,2,-2,-8,17,-14,-10,6,5,-13,7,11,10,0,-1,4,6,-10,6,-12,-2,5,6,3,-1,8,-15,1,-4,-7,11, +1,11,5,0,6,-12,10,1,-3,-2,-1,4,-2,-11,-1,12,7,-8,-20,-18,2,0,-9,2,-13,-1,-16,2,3,-1,-5,-17, +15,8,3,-14,-13,-12,6,15,2,-8,2,6,6,22,-3,-23,-2,-7,-6,0,13,-10,-6,6,6,7,-10,12,-6,7,-2,11, +0,-22,-2,-17,-4,-1,-11,-14,-2,-8,7,12,12,-5,7,-13,2,-2,-7,6,0,8,-3,23,6,12,13,-11,-21,-10,10,8, +-3,0,7,15,7,-6,-5,-12,-21,-10,12,-11,-5,-11,8,-11,5,0,-11,-1,8,-9,7,-1,11,-23,21,-5,0,-5,-8,6, +-6,8,8,12,-7,5,3,-2,-5,-20,-12,9,-6,12,-11,3,4,5,13,11,2,12,13,-12,-4,-13,4,7,0,15,-3,-16, +-3,2,-2,14,4,-14,16,-11,-13,3,23,10,9,-19,2,5,5,3,14,-7,19,-13,-11,15,14,0,-2,-5,11,-4,0,-6, +-2,5,-13,-8,-11,-15,-7,-17,1,3,-10,-8,-13,-10,7,-12,0,-13,23,-6,2,-17,-7,-3,1,3,4,-10,13,4,14,-6, +-19,-2,-1,5,9,-8,10,-5,7,-1,5,7,9,-10,19,0,7,5,-4,-7,-11,1,-1,-11,2,-1,-4,11,-1,7,2,-2, +1,-20,-9,-6,-4,-18,8,-18,-16,-2,7,-6,-3,-6,-1,-4,0,-16,24,-5,-4,-2,-1,9,-8,2,-6,15,11,4,0,-3, +7,6,2,-10,-7,-9,12,-6,24,15,-8,-1,15,-9,-3,-15,17,-5,11,-10,-2,13,-15,4,-2,-1,4,-23,-16,3,-7,-14, +-3,-5,-10,-9,-5,3,-2,-1,-1,4,1,8,12,9,9,-14,-9,17,-3,0,5,4,13,-6,-1,-8,19,10,8,-5,-15,2, +-12,-9,-4,-5,12,0,24,4,8,-2,14,4,8,-4,-7,16,5,-1,-8,-4,-2,18,-5,17,8,-2,-9,-2,3,-7,1,-6, +-5,-22,-5,-2,-8,-10,14,1,-3,-13,3,9,-4,-1,-1,0,-7,-21,12,-19,-8,8,24,8,12,-6,-2,3,-5,-11,-22,-4, +-3,5,-4,4,-16,24,7,-9,-10,23,-9,18,1,12,17,21,24,-6,-3,-11,-7,17,1,-6,4,4,2,-7,14,6,-12,3, +-6,0,-16,13,-10,5,7,12,5,2,6,-3,7,0,-23,1,15,-5,1,14,-3,-1,6,6,6,-9,-9,12,4,-2,-4,7, +-4,-5,4,4,-13,0,6,-10,2,-12,-6,-3,16,0,-3,3,5,-14,6,11,5,11,0,-13,7,5,-1,-5,12,4,6,10, +-10,4,-1,-11,4,10,-14,5,11,-14,-13,0,2,8,12,24,-1,3,-1,2,9,-14,-23,3,-8,-6,0,9,-15,14,10,-10, +-10,-6,-7,-5,11,5,-3,-15,1,0,1,8,-11,-6,-4,-18,9,0,22,-4,-5,-1,-9,4,-20,2,1,6,1,2,-9,-12, +5,15,4,-6,19,4,4,11,17,-4,-8,-1,-8,-12,7,-3,11,9,8,1,9,22,-15,15,-7,-7,1,-23,-5,13,-8,2, +3,-5,11,-11,3,-18,14,-5,-20,7,-10,-23,-2,-5,6,0,-17,-13,-3,2,-6,-1,14,-2,-12,-16,15,6,-12,-2,3,-19 +#endif +}; + inline int smoothedSum(__read_only image2d_t sum, const int2 pt) { return ( read_imagei( sum, sampler, pt + (int2)( HALF_KERNEL + 1, HALF_KERNEL + 1 )) @@ -61,84 +136,21 @@ inline int smoothedSum(__read_only image2d_t sum, const int2 pt) + read_imagei( sum, sampler, pt + (int2)( -HALF_KERNEL, -HALF_KERNEL ))).x; } -__kernel void extractBriefDescriptors(__read_only image2d_t sum, __global float* xRow, __global float* yRow, __global uchar* descriptors) +__kernel void extractBriefDescriptors( + __read_only image2d_t sumImg, __global float* keypoints, int kpRowStep, __global uchar* descriptors, int dscRowStep) { - const size_t id = get_global_id( 0 ); - uchar desc[BYTES]; + const int byte = get_local_id(0); + const int kpId = get_group_id(0); + const int2 kpPos = (int2)(keypoints[X_ROW * (kpRowStep/4) + kpId] + 0.5, keypoints[Y_ROW * (kpRowStep/4) + kpId] + 0.5); -const int2 pt = (int2)( xRow[id] + 0.5f, yRow[id] + 0.5f ); -#define SMOOTHED(y,x) smoothedSum(sum, pt + (int2)(x, y)) - desc[0] = (uchar)(((SMOOTHED(-2, -1) < SMOOTHED(7, -1)) << 7) + ((SMOOTHED(-14, -1) < SMOOTHED(-3, 3)) << 6) + ((SMOOTHED(1, -2) < SMOOTHED(11, 2)) << 5) + ((SMOOTHED(1, 6) < SMOOTHED(-10, -7)) << 4) + ((SMOOTHED(13, 2) < SMOOTHED(-1, 0)) << 3) + ((SMOOTHED(-14, 5) < SMOOTHED(5, -3)) << 2) + ((SMOOTHED(-2, 8) < SMOOTHED(2, 4)) << 1) + ((SMOOTHED(-11, 8) < SMOOTHED(-15, 5)) << 0)); - desc[1] = (uchar)(((SMOOTHED(-6, -23) < SMOOTHED(8, -9)) << 7) + ((SMOOTHED(-12, 6) < SMOOTHED(-10, 8)) << 6) + ((SMOOTHED(-3, -1) < SMOOTHED(8, 1)) << 5) + ((SMOOTHED(3, 6) < SMOOTHED(5, 6)) << 4) + ((SMOOTHED(-7, -6) < SMOOTHED(5, -5)) << 3) + ((SMOOTHED(22, -2) < SMOOTHED(-11, -8)) << 2) + ((SMOOTHED(14, 7) < SMOOTHED(8, 5)) << 1) + ((SMOOTHED(-1, 14) < SMOOTHED(-5, -14)) << 0)); - desc[2] = (uchar)(((SMOOTHED(-14, 9) < SMOOTHED(2, 0)) << 7) + ((SMOOTHED(7, -3) < SMOOTHED(22, 6)) << 6) + ((SMOOTHED(-6, 6) < SMOOTHED(-8, -5)) << 5) + ((SMOOTHED(-5, 9) < SMOOTHED(7, -1)) << 4) + ((SMOOTHED(-3, -7) < SMOOTHED(-10, -18)) << 3) + ((SMOOTHED(4, -5) < SMOOTHED(0, 11)) << 2) + ((SMOOTHED(2, 3) < SMOOTHED(9, 10)) << 1) + ((SMOOTHED(-10, 3) < SMOOTHED(4, 9)) << 0)); - desc[3] = (uchar)(((SMOOTHED(0, 12) < SMOOTHED(-3, 19)) << 7) + ((SMOOTHED(1, 15) < SMOOTHED(-11, -5)) << 6) + ((SMOOTHED(14, -1) < SMOOTHED(7, 8)) << 5) + ((SMOOTHED(7, -23) < SMOOTHED(-5, 5)) << 4) + ((SMOOTHED(0, -6) < SMOOTHED(-10, 17)) << 3) + ((SMOOTHED(13, -4) < SMOOTHED(-3, -4)) << 2) + ((SMOOTHED(-12, 1) < SMOOTHED(-12, 2)) << 1) + ((SMOOTHED(0, 8) < SMOOTHED(3, 22)) << 0)); - desc[4] = (uchar)(((SMOOTHED(-13, 13) < SMOOTHED(3, -1)) << 7) + ((SMOOTHED(-16, 17) < SMOOTHED(6, 10)) << 6) + ((SMOOTHED(7, 15) < SMOOTHED(-5, 0)) << 5) + ((SMOOTHED(2, -12) < SMOOTHED(19, -2)) << 4) + ((SMOOTHED(3, -6) < SMOOTHED(-4, -15)) << 3) + ((SMOOTHED(8, 3) < SMOOTHED(0, 14)) << 2) + ((SMOOTHED(4, -11) < SMOOTHED(5, 5)) << 1) + ((SMOOTHED(11, -7) < SMOOTHED(7, 1)) << 0)); - desc[5] = (uchar)(((SMOOTHED(6, 12) < SMOOTHED(21, 3)) << 7) + ((SMOOTHED(-3, 2) < SMOOTHED(14, 1)) << 6) + ((SMOOTHED(5, 1) < SMOOTHED(-5, 11)) << 5) + ((SMOOTHED(3, -17) < SMOOTHED(-6, 2)) << 4) + ((SMOOTHED(6, 8) < SMOOTHED(5, -10)) << 3) + ((SMOOTHED(-14, -2) < SMOOTHED(0, 4)) << 2) + ((SMOOTHED(5, -7) < SMOOTHED(-6, 5)) << 1) + ((SMOOTHED(10, 4) < SMOOTHED(4, -7)) << 0)); - desc[6] = (uchar)(((SMOOTHED(22, 0) < SMOOTHED(7, -18)) << 7) + ((SMOOTHED(-1, -3) < SMOOTHED(0, 18)) << 6) + ((SMOOTHED(-4, 22) < SMOOTHED(-5, 3)) << 5) + ((SMOOTHED(1, -7) < SMOOTHED(2, -3)) << 4) + ((SMOOTHED(19, -20) < SMOOTHED(17, -2)) << 3) + ((SMOOTHED(3, -10) < SMOOTHED(-8, 24)) << 2) + ((SMOOTHED(-5, -14) < SMOOTHED(7, 5)) << 1) + ((SMOOTHED(-2, 12) < SMOOTHED(-4, -15)) << 0)); - desc[7] = (uchar)(((SMOOTHED(4, 12) < SMOOTHED(0, -19)) << 7) + ((SMOOTHED(20, 13) < SMOOTHED(3, 5)) << 6) + ((SMOOTHED(-8, -12) < SMOOTHED(5, 0)) << 5) + ((SMOOTHED(-5, 6) < SMOOTHED(-7, -11)) << 4) + ((SMOOTHED(6, -11) < SMOOTHED(-3, -22)) << 3) + ((SMOOTHED(15, 4) < SMOOTHED(10, 1)) << 2) + ((SMOOTHED(-7, -4) < SMOOTHED(15, -6)) << 1) + ((SMOOTHED(5, 10) < SMOOTHED(0, 24)) << 0)); - desc[8] = (uchar)(((SMOOTHED(3, 6) < SMOOTHED(22, -2)) << 7) + ((SMOOTHED(-13, 14) < SMOOTHED(4, -4)) << 6) + ((SMOOTHED(-13, 8) < SMOOTHED(-18, -22)) << 5) + ((SMOOTHED(-1, -1) < SMOOTHED(-7, 3)) << 4) + ((SMOOTHED(-19, -12) < SMOOTHED(4, 3)) << 3) + ((SMOOTHED(8, 10) < SMOOTHED(13, -2)) << 2) + ((SMOOTHED(-6, -1) < SMOOTHED(-6, -5)) << 1) + ((SMOOTHED(2, -21) < SMOOTHED(-3, 2)) << 0)); - desc[9] = (uchar)(((SMOOTHED(4, -7) < SMOOTHED(0, 16)) << 7) + ((SMOOTHED(-6, -5) < SMOOTHED(-12, -1)) << 6) + ((SMOOTHED(1, -1) < SMOOTHED(9, 18)) << 5) + ((SMOOTHED(-7, 10) < SMOOTHED(-11, 6)) << 4) + ((SMOOTHED(4, 3) < SMOOTHED(19, -7)) << 3) + ((SMOOTHED(-18, 5) < SMOOTHED(-4, 5)) << 2) + ((SMOOTHED(4, 0) < SMOOTHED(-20, 4)) << 1) + ((SMOOTHED(7, -11) < SMOOTHED(18, 12)) << 0)); - desc[10] = (uchar)(((SMOOTHED(-20, 17) < SMOOTHED(-18, 7)) << 7) + ((SMOOTHED(2, 15) < SMOOTHED(19, -11)) << 6) + ((SMOOTHED(-18, 6) < SMOOTHED(-7, 3)) << 5) + ((SMOOTHED(-4, 1) < SMOOTHED(-14, 13)) << 4) + ((SMOOTHED(17, 3) < SMOOTHED(2, -8)) << 3) + ((SMOOTHED(-7, 2) < SMOOTHED(1, 6)) << 2) + ((SMOOTHED(17, -9) < SMOOTHED(-2, 8)) << 1) + ((SMOOTHED(-8, -6) < SMOOTHED(-1, 12)) << 0)); - desc[11] = (uchar)(((SMOOTHED(-2, 4) < SMOOTHED(-1, 6)) << 7) + ((SMOOTHED(-2, 7) < SMOOTHED(6, 8)) << 6) + ((SMOOTHED(-8, -1) < SMOOTHED(-7, -9)) << 5) + ((SMOOTHED(8, -9) < SMOOTHED(15, 0)) << 4) + ((SMOOTHED(0, 22) < SMOOTHED(-4, -15)) << 3) + ((SMOOTHED(-14, -1) < SMOOTHED(3, -2)) << 2) + ((SMOOTHED(-7, -4) < SMOOTHED(17, -7)) << 1) + ((SMOOTHED(-8, -2) < SMOOTHED(9, -4)) << 0)); - desc[12] = (uchar)(((SMOOTHED(5, -7) < SMOOTHED(7, 7)) << 7) + ((SMOOTHED(-5, 13) < SMOOTHED(-8, 11)) << 6) + ((SMOOTHED(11, -4) < SMOOTHED(0, 8)) << 5) + ((SMOOTHED(5, -11) < SMOOTHED(-9, -6)) << 4) + ((SMOOTHED(2, -6) < SMOOTHED(3, -20)) << 3) + ((SMOOTHED(-6, 2) < SMOOTHED(6, 10)) << 2) + ((SMOOTHED(-6, -6) < SMOOTHED(-15, 7)) << 1) + ((SMOOTHED(-6, -3) < SMOOTHED(2, 1)) << 0)); - desc[13] = (uchar)(((SMOOTHED(11, 0) < SMOOTHED(-3, 2)) << 7) + ((SMOOTHED(7, -12) < SMOOTHED(14, 5)) << 6) + ((SMOOTHED(0, -7) < SMOOTHED(-1, -1)) << 5) + ((SMOOTHED(-16, 0) < SMOOTHED(6, 8)) << 4) + ((SMOOTHED(22, 11) < SMOOTHED(0, -3)) << 3) + ((SMOOTHED(19, 0) < SMOOTHED(5, -17)) << 2) + ((SMOOTHED(-23, -14) < SMOOTHED(-13, -19)) << 1) + ((SMOOTHED(-8, 10) < SMOOTHED(-11, -2)) << 0)); - desc[14] = (uchar)(((SMOOTHED(-11, 6) < SMOOTHED(-10, 13)) << 7) + ((SMOOTHED(1, -7) < SMOOTHED(14, 0)) << 6) + ((SMOOTHED(-12, 1) < SMOOTHED(-5, -5)) << 5) + ((SMOOTHED(4, 7) < SMOOTHED(8, -1)) << 4) + ((SMOOTHED(-1, -5) < SMOOTHED(15, 2)) << 3) + ((SMOOTHED(-3, -1) < SMOOTHED(7, -10)) << 2) + ((SMOOTHED(3, -6) < SMOOTHED(10, -18)) << 1) + ((SMOOTHED(-7, -13) < SMOOTHED(-13, 10)) << 0)); - desc[15] = (uchar)(((SMOOTHED(1, -1) < SMOOTHED(13, -10)) << 7) + ((SMOOTHED(-19, 14) < SMOOTHED(8, -14)) << 6) + ((SMOOTHED(-4, -13) < SMOOTHED(7, 1)) << 5) + ((SMOOTHED(1, -2) < SMOOTHED(12, -7)) << 4) + ((SMOOTHED(3, -5) < SMOOTHED(1, -5)) << 3) + ((SMOOTHED(-2, -2) < SMOOTHED(8, -10)) << 2) + ((SMOOTHED(2, 14) < SMOOTHED(8, 7)) << 1) + ((SMOOTHED(3, 9) < SMOOTHED(8, 2)) << 0)); -#if BYTES > 16 - desc[16] = (uchar)(((SMOOTHED(-9, 1) < SMOOTHED(-18, 0)) << 7) + ((SMOOTHED(4, 0) < SMOOTHED(1, 12)) << 6) + ((SMOOTHED(0, 9) < SMOOTHED(-14, -10)) << 5) + ((SMOOTHED(-13, -9) < SMOOTHED(-2, 6)) << 4) + ((SMOOTHED(1, 5) < SMOOTHED(10, 10)) << 3) + ((SMOOTHED(-3, -6) < SMOOTHED(-16, -5)) << 2) + ((SMOOTHED(11, 6) < SMOOTHED(-5, 0)) << 1) + ((SMOOTHED(-23, 10) < SMOOTHED(1, 2)) << 0)); - desc[17] = (uchar)(((SMOOTHED(13, -5) < SMOOTHED(-3, 9)) << 7) + ((SMOOTHED(-4, -1) < SMOOTHED(-13, -5)) << 6) + ((SMOOTHED(10, 13) < SMOOTHED(-11, 8)) << 5) + ((SMOOTHED(19, 20) < SMOOTHED(-9, 2)) << 4) + ((SMOOTHED(4, -8) < SMOOTHED(0, -9)) << 3) + ((SMOOTHED(-14, 10) < SMOOTHED(15, 19)) << 2) + ((SMOOTHED(-14, -12) < SMOOTHED(-10, -3)) << 1) + ((SMOOTHED(-23, -3) < SMOOTHED(17, -2)) << 0)); - desc[18] = (uchar)(((SMOOTHED(-3, -11) < SMOOTHED(6, -14)) << 7) + ((SMOOTHED(19, -2) < SMOOTHED(-4, 2)) << 6) + ((SMOOTHED(-5, 5) < SMOOTHED(3, -13)) << 5) + ((SMOOTHED(2, -2) < SMOOTHED(-5, 4)) << 4) + ((SMOOTHED(17, 4) < SMOOTHED(17, -11)) << 3) + ((SMOOTHED(-7, -2) < SMOOTHED(1, 23)) << 2) + ((SMOOTHED(8, 13) < SMOOTHED(1, -16)) << 1) + ((SMOOTHED(-13, -5) < SMOOTHED(1, -17)) << 0)); - desc[19] = (uchar)(((SMOOTHED(4, 6) < SMOOTHED(-8, -3)) << 7) + ((SMOOTHED(-5, -9) < SMOOTHED(-2, -10)) << 6) + ((SMOOTHED(-9, 0) < SMOOTHED(-7, -2)) << 5) + ((SMOOTHED(5, 0) < SMOOTHED(5, 2)) << 4) + ((SMOOTHED(-4, -16) < SMOOTHED(6, 3)) << 3) + ((SMOOTHED(2, -15) < SMOOTHED(-2, 12)) << 2) + ((SMOOTHED(4, -1) < SMOOTHED(6, 2)) << 1) + ((SMOOTHED(1, 1) < SMOOTHED(-2, -8)) << 0)); - desc[20] = (uchar)(((SMOOTHED(-2, 12) < SMOOTHED(-5, -2)) << 7) + ((SMOOTHED(-8, 8) < SMOOTHED(-9, 9)) << 6) + ((SMOOTHED(2, -10) < SMOOTHED(3, 1)) << 5) + ((SMOOTHED(-4, 10) < SMOOTHED(-9, 4)) << 4) + ((SMOOTHED(6, 12) < SMOOTHED(2, 5)) << 3) + ((SMOOTHED(-3, -8) < SMOOTHED(0, 5)) << 2) + ((SMOOTHED(-13, 1) < SMOOTHED(-7, 2)) << 1) + ((SMOOTHED(-1, -10) < SMOOTHED(7, -18)) << 0)); - desc[21] = (uchar)(((SMOOTHED(-1, 8) < SMOOTHED(-9, -10)) << 7) + ((SMOOTHED(-23, -1) < SMOOTHED(6, 2)) << 6) + ((SMOOTHED(-5, -3) < SMOOTHED(3, 2)) << 5) + ((SMOOTHED(0, 11) < SMOOTHED(-4, -7)) << 4) + ((SMOOTHED(15, 2) < SMOOTHED(-10, -3)) << 3) + ((SMOOTHED(-20, -8) < SMOOTHED(-13, 3)) << 2) + ((SMOOTHED(-19, -12) < SMOOTHED(5, -11)) << 1) + ((SMOOTHED(-17, -13) < SMOOTHED(-3, 2)) << 0)); - desc[22] = (uchar)(((SMOOTHED(7, 4) < SMOOTHED(-12, 0)) << 7) + ((SMOOTHED(5, -1) < SMOOTHED(-14, -6)) << 6) + ((SMOOTHED(-4, 11) < SMOOTHED(0, -4)) << 5) + ((SMOOTHED(3, 10) < SMOOTHED(7, -3)) << 4) + ((SMOOTHED(13, 21) < SMOOTHED(-11, 6)) << 3) + ((SMOOTHED(-12, 24) < SMOOTHED(-7, -4)) << 2) + ((SMOOTHED(4, 16) < SMOOTHED(3, -14)) << 1) + ((SMOOTHED(-3, 5) < SMOOTHED(-7, -12)) << 0)); - desc[23] = (uchar)(((SMOOTHED(0, -4) < SMOOTHED(7, -5)) << 7) + ((SMOOTHED(-17, -9) < SMOOTHED(13, -7)) << 6) + ((SMOOTHED(22, -6) < SMOOTHED(-11, 5)) << 5) + ((SMOOTHED(2, -8) < SMOOTHED(23, -11)) << 4) + ((SMOOTHED(7, -10) < SMOOTHED(-1, 14)) << 3) + ((SMOOTHED(-3, -10) < SMOOTHED(8, 3)) << 2) + ((SMOOTHED(-13, 1) < SMOOTHED(-6, 0)) << 1) + ((SMOOTHED(-7, -21) < SMOOTHED(6, -14)) << 0)); - desc[24] = (uchar)(((SMOOTHED(18, 19) < SMOOTHED(-4, -6)) << 7) + ((SMOOTHED(10, 7) < SMOOTHED(-1, -4)) << 6) + ((SMOOTHED(-1, 21) < SMOOTHED(1, -5)) << 5) + ((SMOOTHED(-10, 6) < SMOOTHED(-11, -2)) << 4) + ((SMOOTHED(18, -3) < SMOOTHED(-1, 7)) << 3) + ((SMOOTHED(-3, -9) < SMOOTHED(-5, 10)) << 2) + ((SMOOTHED(-13, 14) < SMOOTHED(17, -3)) << 1) + ((SMOOTHED(11, -19) < SMOOTHED(-1, -18)) << 0)); - desc[25] = (uchar)(((SMOOTHED(8, -2) < SMOOTHED(-18, -23)) << 7) + ((SMOOTHED(0, -5) < SMOOTHED(-2, -9)) << 6) + ((SMOOTHED(-4, -11) < SMOOTHED(2, -8)) << 5) + ((SMOOTHED(14, 6) < SMOOTHED(-3, -6)) << 4) + ((SMOOTHED(-3, 0) < SMOOTHED(-15, 0)) << 3) + ((SMOOTHED(-9, 4) < SMOOTHED(-15, -9)) << 2) + ((SMOOTHED(-1, 11) < SMOOTHED(3, 11)) << 1) + ((SMOOTHED(-10, -16) < SMOOTHED(-7, 7)) << 0)); - desc[26] = (uchar)(((SMOOTHED(-2, -10) < SMOOTHED(-10, -2)) << 7) + ((SMOOTHED(-5, -3) < SMOOTHED(5, -23)) << 6) + ((SMOOTHED(13, -8) < SMOOTHED(-15, -11)) << 5) + ((SMOOTHED(-15, 11) < SMOOTHED(6, -6)) << 4) + ((SMOOTHED(-16, -3) < SMOOTHED(-2, 2)) << 3) + ((SMOOTHED(6, 12) < SMOOTHED(-16, 24)) << 2) + ((SMOOTHED(-10, 0) < SMOOTHED(8, 11)) << 1) + ((SMOOTHED(-7, 7) < SMOOTHED(-19, -7)) << 0)); - desc[27] = (uchar)(((SMOOTHED(5, 16) < SMOOTHED(9, -3)) << 7) + ((SMOOTHED(9, 7) < SMOOTHED(-7, -16)) << 6) + ((SMOOTHED(3, 2) < SMOOTHED(-10, 9)) << 5) + ((SMOOTHED(21, 1) < SMOOTHED(8, 7)) << 4) + ((SMOOTHED(7, 0) < SMOOTHED(1, 17)) << 3) + ((SMOOTHED(-8, 12) < SMOOTHED(9, 6)) << 2) + ((SMOOTHED(11, -7) < SMOOTHED(-8, -6)) << 1) + ((SMOOTHED(19, 0) < SMOOTHED(9, 3)) << 0)); - desc[28] = (uchar)(((SMOOTHED(1, -7) < SMOOTHED(-5, -11)) << 7) + ((SMOOTHED(0, 8) < SMOOTHED(-2, 14)) << 6) + ((SMOOTHED(12, -2) < SMOOTHED(-15, -6)) << 5) + ((SMOOTHED(4, 12) < SMOOTHED(0, -21)) << 4) + ((SMOOTHED(17, -4) < SMOOTHED(-6, -7)) << 3) + ((SMOOTHED(-10, -9) < SMOOTHED(-14, -7)) << 2) + ((SMOOTHED(-15, -10) < SMOOTHED(-15, -14)) << 1) + ((SMOOTHED(-7, -5) < SMOOTHED(5, -12)) << 0)); - desc[29] = (uchar)(((SMOOTHED(-4, 0) < SMOOTHED(15, -4)) << 7) + ((SMOOTHED(5, 2) < SMOOTHED(-6, -23)) << 6) + ((SMOOTHED(-4, -21) < SMOOTHED(-6, 4)) << 5) + ((SMOOTHED(-10, 5) < SMOOTHED(-15, 6)) << 4) + ((SMOOTHED(4, -3) < SMOOTHED(-1, 5)) << 3) + ((SMOOTHED(-4, 19) < SMOOTHED(-23, -4)) << 2) + ((SMOOTHED(-4, 17) < SMOOTHED(13, -11)) << 1) + ((SMOOTHED(1, 12) < SMOOTHED(4, -14)) << 0)); - desc[30] = (uchar)(((SMOOTHED(-11, -6) < SMOOTHED(-20, 10)) << 7) + ((SMOOTHED(4, 5) < SMOOTHED(3, 20)) << 6) + ((SMOOTHED(-8, -20) < SMOOTHED(3, 1)) << 5) + ((SMOOTHED(-19, 9) < SMOOTHED(9, -3)) << 4) + ((SMOOTHED(18, 15) < SMOOTHED(11, -4)) << 3) + ((SMOOTHED(12, 16) < SMOOTHED(8, 7)) << 2) + ((SMOOTHED(-14, -8) < SMOOTHED(-3, 9)) << 1) + ((SMOOTHED(-6, 0) < SMOOTHED(2, -4)) << 0)); - desc[31] = (uchar)(((SMOOTHED(1, -10) < SMOOTHED(-1, 2)) << 7) + ((SMOOTHED(8, -7) < SMOOTHED(-6, 18)) << 6) + ((SMOOTHED(9, 12) < SMOOTHED(-7, -23)) << 5) + ((SMOOTHED(8, -6) < SMOOTHED(5, 2)) << 4) + ((SMOOTHED(-9, 6) < SMOOTHED(-12, -7)) << 3) + ((SMOOTHED(-1, -2) < SMOOTHED(-7, 2)) << 2) + ((SMOOTHED(9, 9) < SMOOTHED(7, 15)) << 1) + ((SMOOTHED(6, 2) < SMOOTHED(-6, 6)) << 0)); -#endif -#if BYTES > 32 - desc[32] = (uchar)(((SMOOTHED(16, 12) < SMOOTHED(0, 19)) << 7) + ((SMOOTHED(4, 3) < SMOOTHED(6, 0)) << 6) + ((SMOOTHED(-2, -1) < SMOOTHED(2, 17)) << 5) + ((SMOOTHED(8, 1) < SMOOTHED(3, 1)) << 4) + ((SMOOTHED(-12, -1) < SMOOTHED(-11, 0)) << 3) + ((SMOOTHED(-11, 2) < SMOOTHED(7, 9)) << 2) + ((SMOOTHED(-1, 3) < SMOOTHED(-19, 4)) << 1) + ((SMOOTHED(-1, -11) < SMOOTHED(-1, 3)) << 0)); - desc[33] = (uchar)(((SMOOTHED(1, -10) < SMOOTHED(-10, -4)) << 7) + ((SMOOTHED(-2, 3) < SMOOTHED(6, 11)) << 6) + ((SMOOTHED(3, 7) < SMOOTHED(-9, -8)) << 5) + ((SMOOTHED(24, -14) < SMOOTHED(-2, -10)) << 4) + ((SMOOTHED(-3, -3) < SMOOTHED(-18, -6)) << 3) + ((SMOOTHED(-13, -10) < SMOOTHED(-7, -1)) << 2) + ((SMOOTHED(2, -7) < SMOOTHED(9, -6)) << 1) + ((SMOOTHED(2, -4) < SMOOTHED(6, -13)) << 0)); - desc[34] = (uchar)(((SMOOTHED(4, -4) < SMOOTHED(-2, 3)) << 7) + ((SMOOTHED(-4, 2) < SMOOTHED(9, 13)) << 6) + ((SMOOTHED(-11, 5) < SMOOTHED(-6, -11)) << 5) + ((SMOOTHED(4, -2) < SMOOTHED(11, -9)) << 4) + ((SMOOTHED(-19, 0) < SMOOTHED(-23, -5)) << 3) + ((SMOOTHED(-5, -7) < SMOOTHED(-3, -6)) << 2) + ((SMOOTHED(-6, -4) < SMOOTHED(12, 14)) << 1) + ((SMOOTHED(12, -11) < SMOOTHED(-8, -16)) << 0)); - desc[35] = (uchar)(((SMOOTHED(-21, 15) < SMOOTHED(-12, 6)) << 7) + ((SMOOTHED(-2, -1) < SMOOTHED(-8, 16)) << 6) + ((SMOOTHED(6, -1) < SMOOTHED(-8, -2)) << 5) + ((SMOOTHED(1, -1) < SMOOTHED(-9, 8)) << 4) + ((SMOOTHED(3, -4) < SMOOTHED(-2, -2)) << 3) + ((SMOOTHED(-7, 0) < SMOOTHED(4, -8)) << 2) + ((SMOOTHED(11, -11) < SMOOTHED(-12, 2)) << 1) + ((SMOOTHED(2, 3) < SMOOTHED(11, 7)) << 0)); - desc[36] = (uchar)(((SMOOTHED(-7, -4) < SMOOTHED(-9, -6)) << 7) + ((SMOOTHED(3, -7) < SMOOTHED(-5, 0)) << 6) + ((SMOOTHED(3, -7) < SMOOTHED(-10, -5)) << 5) + ((SMOOTHED(-3, -1) < SMOOTHED(8, -10)) << 4) + ((SMOOTHED(0, 8) < SMOOTHED(5, 1)) << 3) + ((SMOOTHED(9, 0) < SMOOTHED(1, 16)) << 2) + ((SMOOTHED(8, 4) < SMOOTHED(-11, -3)) << 1) + ((SMOOTHED(-15, 9) < SMOOTHED(8, 17)) << 0)); - desc[37] = (uchar)(((SMOOTHED(0, 2) < SMOOTHED(-9, 17)) << 7) + ((SMOOTHED(-6, -11) < SMOOTHED(-10, -3)) << 6) + ((SMOOTHED(1, 1) < SMOOTHED(15, -8)) << 5) + ((SMOOTHED(-12, -13) < SMOOTHED(-2, 4)) << 4) + ((SMOOTHED(-6, 4) < SMOOTHED(-6, -10)) << 3) + ((SMOOTHED(5, -7) < SMOOTHED(7, -5)) << 2) + ((SMOOTHED(10, 6) < SMOOTHED(8, 9)) << 1) + ((SMOOTHED(-5, 7) < SMOOTHED(-18, -3)) << 0)); - desc[38] = (uchar)(((SMOOTHED(-6, 3) < SMOOTHED(5, 4)) << 7) + ((SMOOTHED(-10, -13) < SMOOTHED(-5, -3)) << 6) + ((SMOOTHED(-11, 2) < SMOOTHED(-16, 0)) << 5) + ((SMOOTHED(7, -21) < SMOOTHED(-5, -13)) << 4) + ((SMOOTHED(-14, -14) < SMOOTHED(-4, -4)) << 3) + ((SMOOTHED(4, 9) < SMOOTHED(7, -3)) << 2) + ((SMOOTHED(4, 11) < SMOOTHED(10, -4)) << 1) + ((SMOOTHED(6, 17) < SMOOTHED(9, 17)) << 0)); - desc[39] = (uchar)(((SMOOTHED(-10, 8) < SMOOTHED(0, -11)) << 7) + ((SMOOTHED(-6, -16) < SMOOTHED(-6, 8)) << 6) + ((SMOOTHED(-13, 5) < SMOOTHED(10, -5)) << 5) + ((SMOOTHED(3, 2) < SMOOTHED(12, 16)) << 4) + ((SMOOTHED(13, -8) < SMOOTHED(0, -6)) << 3) + ((SMOOTHED(10, 0) < SMOOTHED(4, -11)) << 2) + ((SMOOTHED(8, 5) < SMOOTHED(10, -2)) << 1) + ((SMOOTHED(11, -7) < SMOOTHED(-13, 3)) << 0)); - desc[40] = (uchar)(((SMOOTHED(2, 4) < SMOOTHED(-7, -3)) << 7) + ((SMOOTHED(-14, -2) < SMOOTHED(-11, 16)) << 6) + ((SMOOTHED(11, -6) < SMOOTHED(7, 6)) << 5) + ((SMOOTHED(-3, 15) < SMOOTHED(8, -10)) << 4) + ((SMOOTHED(-3, 8) < SMOOTHED(12, -12)) << 3) + ((SMOOTHED(-13, 6) < SMOOTHED(-14, 7)) << 2) + ((SMOOTHED(-11, -5) < SMOOTHED(-8, -6)) << 1) + ((SMOOTHED(7, -6) < SMOOTHED(6, 3)) << 0)); - desc[41] = (uchar)(((SMOOTHED(-4, 10) < SMOOTHED(5, 1)) << 7) + ((SMOOTHED(9, 16) < SMOOTHED(10, 13)) << 6) + ((SMOOTHED(-17, 10) < SMOOTHED(2, 8)) << 5) + ((SMOOTHED(-5, 1) < SMOOTHED(4, -4)) << 4) + ((SMOOTHED(-14, 8) < SMOOTHED(-5, 2)) << 3) + ((SMOOTHED(4, -9) < SMOOTHED(-6, -3)) << 2) + ((SMOOTHED(3, -7) < SMOOTHED(-10, 0)) << 1) + ((SMOOTHED(-2, -8) < SMOOTHED(-10, 4)) << 0)); - desc[42] = (uchar)(((SMOOTHED(-8, 5) < SMOOTHED(-9, 24)) << 7) + ((SMOOTHED(2, -8) < SMOOTHED(8, -9)) << 6) + ((SMOOTHED(-4, 17) < SMOOTHED(-5, 2)) << 5) + ((SMOOTHED(14, 0) < SMOOTHED(-9, 9)) << 4) + ((SMOOTHED(11, 15) < SMOOTHED(-6, 5)) << 3) + ((SMOOTHED(-8, 1) < SMOOTHED(-3, 4)) << 2) + ((SMOOTHED(9, -21) < SMOOTHED(10, 2)) << 1) + ((SMOOTHED(2, -1) < SMOOTHED(4, 11)) << 0)); - desc[43] = (uchar)(((SMOOTHED(24, 3) < SMOOTHED(2, -2)) << 7) + ((SMOOTHED(-8, 17) < SMOOTHED(-14, -10)) << 6) + ((SMOOTHED(6, 5) < SMOOTHED(-13, 7)) << 5) + ((SMOOTHED(11, 10) < SMOOTHED(0, -1)) << 4) + ((SMOOTHED(4, 6) < SMOOTHED(-10, 6)) << 3) + ((SMOOTHED(-12, -2) < SMOOTHED(5, 6)) << 2) + ((SMOOTHED(3, -1) < SMOOTHED(8, -15)) << 1) + ((SMOOTHED(1, -4) < SMOOTHED(-7, 11)) << 0)); - desc[44] = (uchar)(((SMOOTHED(1, 11) < SMOOTHED(5, 0)) << 7) + ((SMOOTHED(6, -12) < SMOOTHED(10, 1)) << 6) + ((SMOOTHED(-3, -2) < SMOOTHED(-1, 4)) << 5) + ((SMOOTHED(-2, -11) < SMOOTHED(-1, 12)) << 4) + ((SMOOTHED(7, -8) < SMOOTHED(-20, -18)) << 3) + ((SMOOTHED(2, 0) < SMOOTHED(-9, 2)) << 2) + ((SMOOTHED(-13, -1) < SMOOTHED(-16, 2)) << 1) + ((SMOOTHED(3, -1) < SMOOTHED(-5, -17)) << 0)); - desc[45] = (uchar)(((SMOOTHED(15, 8) < SMOOTHED(3, -14)) << 7) + ((SMOOTHED(-13, -12) < SMOOTHED(6, 15)) << 6) + ((SMOOTHED(2, -8) < SMOOTHED(2, 6)) << 5) + ((SMOOTHED(6, 22) < SMOOTHED(-3, -23)) << 4) + ((SMOOTHED(-2, -7) < SMOOTHED(-6, 0)) << 3) + ((SMOOTHED(13, -10) < SMOOTHED(-6, 6)) << 2) + ((SMOOTHED(6, 7) < SMOOTHED(-10, 12)) << 1) + ((SMOOTHED(-6, 7) < SMOOTHED(-2, 11)) << 0)); - desc[46] = (uchar)(((SMOOTHED(0, -22) < SMOOTHED(-2, -17)) << 7) + ((SMOOTHED(-4, -1) < SMOOTHED(-11, -14)) << 6) + ((SMOOTHED(-2, -8) < SMOOTHED(7, 12)) << 5) + ((SMOOTHED(12, -5) < SMOOTHED(7, -13)) << 4) + ((SMOOTHED(2, -2) < SMOOTHED(-7, 6)) << 3) + ((SMOOTHED(0, 8) < SMOOTHED(-3, 23)) << 2) + ((SMOOTHED(6, 12) < SMOOTHED(13, -11)) << 1) + ((SMOOTHED(-21, -10) < SMOOTHED(10, 8)) << 0)); - desc[47] = (uchar)(((SMOOTHED(-3, 0) < SMOOTHED(7, 15)) << 7) + ((SMOOTHED(7, -6) < SMOOTHED(-5, -12)) << 6) + ((SMOOTHED(-21, -10) < SMOOTHED(12, -11)) << 5) + ((SMOOTHED(-5, -11) < SMOOTHED(8, -11)) << 4) + ((SMOOTHED(5, 0) < SMOOTHED(-11, -1)) << 3) + ((SMOOTHED(8, -9) < SMOOTHED(7, -1)) << 2) + ((SMOOTHED(11, -23) < SMOOTHED(21, -5)) << 1) + ((SMOOTHED(0, -5) < SMOOTHED(-8, 6)) << 0)); - desc[48] = (uchar)(((SMOOTHED(-6, 8) < SMOOTHED(8, 12)) << 7) + ((SMOOTHED(-7, 5) < SMOOTHED(3, -2)) << 6) + ((SMOOTHED(-5, -20) < SMOOTHED(-12, 9)) << 5) + ((SMOOTHED(-6, 12) < SMOOTHED(-11, 3)) << 4) + ((SMOOTHED(4, 5) < SMOOTHED(13, 11)) << 3) + ((SMOOTHED(2, 12) < SMOOTHED(13, -12)) << 2) + ((SMOOTHED(-4, -13) < SMOOTHED(4, 7)) << 1) + ((SMOOTHED(0, 15) < SMOOTHED(-3, -16)) << 0)); - desc[49] = (uchar)(((SMOOTHED(-3, 2) < SMOOTHED(-2, 14)) << 7) + ((SMOOTHED(4, -14) < SMOOTHED(16, -11)) << 6) + ((SMOOTHED(-13, 3) < SMOOTHED(23, 10)) << 5) + ((SMOOTHED(9, -19) < SMOOTHED(2, 5)) << 4) + ((SMOOTHED(5, 3) < SMOOTHED(14, -7)) << 3) + ((SMOOTHED(19, -13) < SMOOTHED(-11, 15)) << 2) + ((SMOOTHED(14, 0) < SMOOTHED(-2, -5)) << 1) + ((SMOOTHED(11, -4) < SMOOTHED(0, -6)) << 0)); - desc[50] = (uchar)(((SMOOTHED(-2, 5) < SMOOTHED(-13, -8)) << 7) + ((SMOOTHED(-11, -15) < SMOOTHED(-7, -17)) << 6) + ((SMOOTHED(1, 3) < SMOOTHED(-10, -8)) << 5) + ((SMOOTHED(-13, -10) < SMOOTHED(7, -12)) << 4) + ((SMOOTHED(0, -13) < SMOOTHED(23, -6)) << 3) + ((SMOOTHED(2, -17) < SMOOTHED(-7, -3)) << 2) + ((SMOOTHED(1, 3) < SMOOTHED(4, -10)) << 1) + ((SMOOTHED(13, 4) < SMOOTHED(14, -6)) << 0)); - desc[51] = (uchar)(((SMOOTHED(-19, -2) < SMOOTHED(-1, 5)) << 7) + ((SMOOTHED(9, -8) < SMOOTHED(10, -5)) << 6) + ((SMOOTHED(7, -1) < SMOOTHED(5, 7)) << 5) + ((SMOOTHED(9, -10) < SMOOTHED(19, 0)) << 4) + ((SMOOTHED(7, 5) < SMOOTHED(-4, -7)) << 3) + ((SMOOTHED(-11, 1) < SMOOTHED(-1, -11)) << 2) + ((SMOOTHED(2, -1) < SMOOTHED(-4, 11)) << 1) + ((SMOOTHED(-1, 7) < SMOOTHED(2, -2)) << 0)); - desc[52] = (uchar)(((SMOOTHED(1, -20) < SMOOTHED(-9, -6)) << 7) + ((SMOOTHED(-4, -18) < SMOOTHED(8, -18)) << 6) + ((SMOOTHED(-16, -2) < SMOOTHED(7, -6)) << 5) + ((SMOOTHED(-3, -6) < SMOOTHED(-1, -4)) << 4) + ((SMOOTHED(0, -16) < SMOOTHED(24, -5)) << 3) + ((SMOOTHED(-4, -2) < SMOOTHED(-1, 9)) << 2) + ((SMOOTHED(-8, 2) < SMOOTHED(-6, 15)) << 1) + ((SMOOTHED(11, 4) < SMOOTHED(0, -3)) << 0)); - desc[53] = (uchar)(((SMOOTHED(7, 6) < SMOOTHED(2, -10)) << 7) + ((SMOOTHED(-7, -9) < SMOOTHED(12, -6)) << 6) + ((SMOOTHED(24, 15) < SMOOTHED(-8, -1)) << 5) + ((SMOOTHED(15, -9) < SMOOTHED(-3, -15)) << 4) + ((SMOOTHED(17, -5) < SMOOTHED(11, -10)) << 3) + ((SMOOTHED(-2, 13) < SMOOTHED(-15, 4)) << 2) + ((SMOOTHED(-2, -1) < SMOOTHED(4, -23)) << 1) + ((SMOOTHED(-16, 3) < SMOOTHED(-7, -14)) << 0)); - desc[54] = (uchar)(((SMOOTHED(-3, -5) < SMOOTHED(-10, -9)) << 7) + ((SMOOTHED(-5, 3) < SMOOTHED(-2, -1)) << 6) + ((SMOOTHED(-1, 4) < SMOOTHED(1, 8)) << 5) + ((SMOOTHED(12, 9) < SMOOTHED(9, -14)) << 4) + ((SMOOTHED(-9, 17) < SMOOTHED(-3, 0)) << 3) + ((SMOOTHED(5, 4) < SMOOTHED(13, -6)) << 2) + ((SMOOTHED(-1, -8) < SMOOTHED(19, 10)) << 1) + ((SMOOTHED(8, -5) < SMOOTHED(-15, 2)) << 0)); - desc[55] = (uchar)(((SMOOTHED(-12, -9) < SMOOTHED(-4, -5)) << 7) + ((SMOOTHED(12, 0) < SMOOTHED(24, 4)) << 6) + ((SMOOTHED(8, -2) < SMOOTHED(14, 4)) << 5) + ((SMOOTHED(8, -4) < SMOOTHED(-7, 16)) << 4) + ((SMOOTHED(5, -1) < SMOOTHED(-8, -4)) << 3) + ((SMOOTHED(-2, 18) < SMOOTHED(-5, 17)) << 2) + ((SMOOTHED(8, -2) < SMOOTHED(-9, -2)) << 1) + ((SMOOTHED(3, -7) < SMOOTHED(1, -6)) << 0)); - desc[56] = (uchar)(((SMOOTHED(-5, -22) < SMOOTHED(-5, -2)) << 7) + ((SMOOTHED(-8, -10) < SMOOTHED(14, 1)) << 6) + ((SMOOTHED(-3, -13) < SMOOTHED(3, 9)) << 5) + ((SMOOTHED(-4, -1) < SMOOTHED(-1, 0)) << 4) + ((SMOOTHED(-7, -21) < SMOOTHED(12, -19)) << 3) + ((SMOOTHED(-8, 8) < SMOOTHED(24, 8)) << 2) + ((SMOOTHED(12, -6) < SMOOTHED(-2, 3)) << 1) + ((SMOOTHED(-5, -11) < SMOOTHED(-22, -4)) << 0)); - desc[57] = (uchar)(((SMOOTHED(-3, 5) < SMOOTHED(-4, 4)) << 7) + ((SMOOTHED(-16, 24) < SMOOTHED(7, -9)) << 6) + ((SMOOTHED(-10, 23) < SMOOTHED(-9, 18)) << 5) + ((SMOOTHED(1, 12) < SMOOTHED(17, 21)) << 4) + ((SMOOTHED(24, -6) < SMOOTHED(-3, -11)) << 3) + ((SMOOTHED(-7, 17) < SMOOTHED(1, -6)) << 2) + ((SMOOTHED(4, 4) < SMOOTHED(2, -7)) << 1) + ((SMOOTHED(14, 6) < SMOOTHED(-12, 3)) << 0)); - desc[58] = (uchar)(((SMOOTHED(-6, 0) < SMOOTHED(-16, 13)) << 7) + ((SMOOTHED(-10, 5) < SMOOTHED(7, 12)) << 6) + ((SMOOTHED(5, 2) < SMOOTHED(6, -3)) << 5) + ((SMOOTHED(7, 0) < SMOOTHED(-23, 1)) << 4) + ((SMOOTHED(15, -5) < SMOOTHED(1, 14)) << 3) + ((SMOOTHED(-3, -1) < SMOOTHED(6, 6)) << 2) + ((SMOOTHED(6, -9) < SMOOTHED(-9, 12)) << 1) + ((SMOOTHED(4, -2) < SMOOTHED(-4, 7)) << 0)); - desc[59] = (uchar)(((SMOOTHED(-4, -5) < SMOOTHED(4, 4)) << 7) + ((SMOOTHED(-13, 0) < SMOOTHED(6, -10)) << 6) + ((SMOOTHED(2, -12) < SMOOTHED(-6, -3)) << 5) + ((SMOOTHED(16, 0) < SMOOTHED(-3, 3)) << 4) + ((SMOOTHED(5, -14) < SMOOTHED(6, 11)) << 3) + ((SMOOTHED(5, 11) < SMOOTHED(0, -13)) << 2) + ((SMOOTHED(7, 5) < SMOOTHED(-1, -5)) << 1) + ((SMOOTHED(12, 4) < SMOOTHED(6, 10)) << 0)); - desc[60] = (uchar)(((SMOOTHED(-10, 4) < SMOOTHED(-1, -11)) << 7) + ((SMOOTHED(4, 10) < SMOOTHED(-14, 5)) << 6) + ((SMOOTHED(11, -14) < SMOOTHED(-13, 0)) << 5) + ((SMOOTHED(2, 8) < SMOOTHED(12, 24)) << 4) + ((SMOOTHED(-1, 3) < SMOOTHED(-1, 2)) << 3) + ((SMOOTHED(9, -14) < SMOOTHED(-23, 3)) << 2) + ((SMOOTHED(-8, -6) < SMOOTHED(0, 9)) << 1) + ((SMOOTHED(-15, 14) < SMOOTHED(10, -10)) << 0)); - desc[61] = (uchar)(((SMOOTHED(-10, -6) < SMOOTHED(-7, -5)) << 7) + ((SMOOTHED(11, 5) < SMOOTHED(-3, -15)) << 6) + ((SMOOTHED(1, 0) < SMOOTHED(1, 8)) << 5) + ((SMOOTHED(-11, -6) < SMOOTHED(-4, -18)) << 4) + ((SMOOTHED(9, 0) < SMOOTHED(22, -4)) << 3) + ((SMOOTHED(-5, -1) < SMOOTHED(-9, 4)) << 2) + ((SMOOTHED(-20, 2) < SMOOTHED(1, 6)) << 1) + ((SMOOTHED(1, 2) < SMOOTHED(-9, -12)) << 0)); - desc[62] = (uchar)(((SMOOTHED(5, 15) < SMOOTHED(4, -6)) << 7) + ((SMOOTHED(19, 4) < SMOOTHED(4, 11)) << 6) + ((SMOOTHED(17, -4) < SMOOTHED(-8, -1)) << 5) + ((SMOOTHED(-8, -12) < SMOOTHED(7, -3)) << 4) + ((SMOOTHED(11, 9) < SMOOTHED(8, 1)) << 3) + ((SMOOTHED(9, 22) < SMOOTHED(-15, 15)) << 2) + ((SMOOTHED(-7, -7) < SMOOTHED(1, -23)) << 1) + ((SMOOTHED(-5, 13) < SMOOTHED(-8, 2)) << 0)); - desc[63] = (uchar)(((SMOOTHED(3, -5) < SMOOTHED(11, -11)) << 7) + ((SMOOTHED(3, -18) < SMOOTHED(14, -5)) << 6) + ((SMOOTHED(-20, 7) < SMOOTHED(-10, -23)) << 5) + ((SMOOTHED(-2, -5) < SMOOTHED(6, 0)) << 4) + ((SMOOTHED(-17, -13) < SMOOTHED(-3, 2)) << 3) + ((SMOOTHED(-6, -1) < SMOOTHED(14, -2)) << 2) + ((SMOOTHED(-12, -16) < SMOOTHED(15, 6)) << 1) + ((SMOOTHED(-12, -2) < SMOOTHED(3, -19)) << 0)); -#endif - - for(int i = 0; i Date: Fri, 20 Dec 2013 00:05:50 +0100 Subject: [PATCH 022/295] added tests --- modules/ocl/include/opencv2/ocl.hpp | 6 +- modules/ocl/perf/perf_brief.cpp | 70 +++++++++-------- modules/ocl/src/brief.cpp | 38 +++++---- modules/ocl/src/opencl/brief.cl | 49 ++++++++---- modules/ocl/test/test_brief.cpp | 115 ++++++++++++++++++++++++++++ 5 files changed, 213 insertions(+), 65 deletions(-) create mode 100644 modules/ocl/test/test_brief.cpp diff --git a/modules/ocl/include/opencv2/ocl.hpp b/modules/ocl/include/opencv2/ocl.hpp index 76f3dcc55..8df9e15c2 100644 --- a/modules/ocl/include/opencv2/ocl.hpp +++ b/modules/ocl/include/opencv2/ocl.hpp @@ -1558,10 +1558,12 @@ namespace cv /* * Compute the descriptors for a set of keypoints in an image. * image The image. - * keypoints The input keypoints. Keypoints for which a descriptor cannot be computed are removed. + * keypoints The input keypoints. * descriptors Copmputed descriptors. Row i is the descriptor for keypoint i. */ - void compute( const oclMat& image, oclMat& keypoints, oclMat& descriptors ) const; + void compute( const oclMat& image, const oclMat& keypoints, oclMat& mask, oclMat& descriptors ) const; + + static int getBorderSize(); protected: int bytes; diff --git a/modules/ocl/perf/perf_brief.cpp b/modules/ocl/perf/perf_brief.cpp index 5cba78518..b3784a66f 100644 --- a/modules/ocl/perf/perf_brief.cpp +++ b/modules/ocl/perf/perf_brief.cpp @@ -50,54 +50,64 @@ using namespace ocl; using namespace perf; ///////////// BRIEF //////////////////////// +typedef TestBaseWithParam > OCL_BRIEF; -typedef TestBaseWithParam > OCL_BRIEF; - -#define BRIEF_IMAGES \ - "cv/detectors_descriptors_evaluation/images_datasets/leuven/img1.png",\ - "stitching/a3.png" - -PERF_TEST_P( OCL_BRIEF, extract, testing::Combine( testing::Values( BRIEF_IMAGES ), testing::Values( 16, 32, 64 ) ) ) +PERF_TEST_P( OCL_BRIEF, extract, testing::Combine( + testing::Values( string( "gpu/opticalflow/rubberwhale1.png" ), + string( "gpu/stereobm/aloe-L.png" ) + ), testing::Values( 16, 32, 64 ), testing::Values( 250, 500, 1000, 2500, 3000 ) ) ) { - const int threshold = 20; const std::string filename = std::tr1::get<0>(GetParam( )); const int bytes = std::tr1::get<1>(GetParam( )); - const Mat img = imread( getDataPath( filename ), IMREAD_GRAYSCALE ); - ASSERT_FALSE( img.empty( ) ); + const size_t numKp = std::tr1::get<2>(GetParam( )); + + Mat img = imread( getDataPath( filename ), IMREAD_GRAYSCALE ); + ASSERT_TRUE( !img.empty( ) ) << "no input image"; + + int threshold = 15; + std::vector keypoints; + while (threshold > 0 && keypoints.size( ) < numKp) + { + FastFeatureDetector fast( threshold ); + fast.detect( img, keypoints, Mat( ) ); + threshold -= 5; + KeyPointsFilter::runByImageBorder( keypoints, img.size( ), BRIEF_OCL::getBorderSize( ) ); + } + ASSERT_TRUE( keypoints.size( ) >= numKp ) << "not enough keypoints"; + keypoints.resize( numKp ); if ( RUN_OCL_IMPL ) { - oclMat d_img( img ); - oclMat d_keypoints; - FAST_OCL fast( threshold ); - fast( d_img, oclMat( ), d_keypoints ); - - BRIEF_OCL brief( bytes ); - - OCL_TEST_CYCLE( ) + Mat kpMat( 2, keypoints.size( ), CV_32FC1 ); + for ( size_t i = 0; i < keypoints.size( ); ++i ) { - oclMat d_descriptors; - brief.compute( d_img, d_keypoints, d_descriptors ); + kpMat.col( i ).row( 0 ) = keypoints[i].pt.x; + kpMat.col( i ).row( 1 ) = keypoints[i].pt.y; } - - std::vector ocl_keypoints; - fast.downloadKeypoints( d_keypoints, ocl_keypoints ); - SANITY_CHECK_KEYPOINTS( ocl_keypoints ); + BRIEF_OCL brief( bytes ); + oclMat imgCL( img ), keypointsCL(kpMat), mask; + while (next( )) + { + startTimer( ); + oclMat descriptorsCL; + brief.compute( imgCL, keypointsCL, mask, descriptorsCL ); + cv::ocl::finish( ); + stopTimer( ); + } + SANITY_CHECK_NOTHING( ) } else if ( RUN_PLAIN_IMPL ) { - std::vector keypoints; - FAST( img, keypoints, threshold ); - BriefDescriptorExtractor brief( bytes ); - TEST_CYCLE( ) + while (next( )) { + startTimer( ); Mat descriptors; brief.compute( img, keypoints, descriptors ); + stopTimer( ); } - - SANITY_CHECK_KEYPOINTS( keypoints ); + SANITY_CHECK_NOTHING( ) } else OCL_PERF_ELSE; diff --git a/modules/ocl/src/brief.cpp b/modules/ocl/src/brief.cpp index 6d54eb500..d176a5e1a 100644 --- a/modules/ocl/src/brief.cpp +++ b/modules/ocl/src/brief.cpp @@ -53,35 +53,39 @@ BRIEF_OCL::BRIEF_OCL( int _bytes ) : bytes( _bytes ) { } -void -BRIEF_OCL::compute( const oclMat& image, oclMat& keypoints, oclMat& descriptors ) const +void BRIEF_OCL::compute( const oclMat& image, const oclMat& keypoints, oclMat& mask, oclMat& descriptors ) const { - oclMat grayImage = image; - if ( image.type( ) != CV_8U ) cvtColor( image, grayImage, COLOR_BGR2GRAY ); - + CV_Assert( image.type( ) == CV_8UC1 ); + if ( keypoints.size( ).area( ) == 0 ) return; + descriptors = oclMat( Mat( keypoints.cols, bytes, CV_8UC1 ) ); + if( mask.cols != keypoints.cols ) + { + mask = oclMat( Mat::ones( 1, keypoints.cols, CV_8UC1 ) ); + } oclMat sum; - integral( grayImage, sum, CV_32S ); + integral( image, sum, CV_32S ); cl_mem sumTexture = bindTexture( sum ); - - //TODO filter keypoints by border - - descriptors = oclMat( keypoints.cols, bytes, CV_8U ); - std::stringstream build_opt; - build_opt << " -D BYTES=" << bytes << " -D KERNEL_SIZE=" << KERNEL_SIZE; - + build_opt + << " -D BYTES=" << bytes + << " -D KERNEL_SIZE=" << KERNEL_SIZE + << " -D BORDER=" << getBorderSize(); const String kernelname = "extractBriefDescriptors"; - size_t localThreads[3] = {bytes, 1, 1}; + size_t localThreads[3] = {bytes, 1, 1}; size_t globalThreads[3] = {keypoints.cols * bytes, 1, 1}; - + Context* ctx = Context::getContext( ); std::vector< std::pair > args; args.push_back( std::make_pair( sizeof (cl_mem), (void *) &sumTexture ) ); args.push_back( std::make_pair( sizeof (cl_mem), (void *) &keypoints.data ) ); args.push_back( std::make_pair( sizeof (cl_int), (void *) &keypoints.step ) ); args.push_back( std::make_pair( sizeof (cl_mem), (void *) &descriptors.data ) ); args.push_back( std::make_pair( sizeof (cl_int), (void *) &descriptors.step ) ); - - Context* ctx = Context::getContext( ); + args.push_back( std::make_pair( sizeof (cl_mem), (void *) &mask.data ) ); openCLExecuteKernel( ctx, &brief, kernelname, globalThreads, localThreads, args, -1, -1, build_opt.str( ).c_str( ) ); openCLFree( sumTexture ); } + +int BRIEF_OCL::getBorderSize( ) +{ + return PATCH_SIZE / 2 + KERNEL_SIZE / 2; +} diff --git a/modules/ocl/src/opencl/brief.cl b/modules/ocl/src/opencl/brief.cl index f75c99a30..343e95bf9 100644 --- a/modules/ocl/src/opencl/brief.cl +++ b/modules/ocl/src/opencl/brief.cl @@ -41,15 +41,16 @@ // //M*/ -#define X_ROW 0 -#define Y_ROW 1 - #ifndef BYTES #define BYTES 16 #endif #ifndef KERNEL_SIZE - #define KERNEL_SIZE 32 + #define KERNEL_SIZE 9 +#endif + +#ifndef BORDER + #define BORDER 0 #endif #define HALF_KERNEL (KERNEL_SIZE/2) @@ -128,29 +129,45 @@ __constant char tests[32 * BYTES] = #endif }; -inline int smoothedSum(__read_only image2d_t sum, const int2 pt) +inline int smoothedSum(__read_only image2d_t sum, const int2 kpPos, const int2 pt) { - return ( read_imagei( sum, sampler, pt + (int2)( HALF_KERNEL + 1, HALF_KERNEL + 1 )) - - read_imagei( sum, sampler, pt + (int2)( -HALF_KERNEL, HALF_KERNEL + 1 )) - - read_imagei( sum, sampler, pt + (int2)( HALF_KERNEL + 1, -HALF_KERNEL )) - + read_imagei( sum, sampler, pt + (int2)( -HALF_KERNEL, -HALF_KERNEL ))).x; + return ( read_imagei( sum, sampler, kpPos + pt + (int2)( HALF_KERNEL + 1, HALF_KERNEL + 1 )) + - read_imagei( sum, sampler, kpPos + pt + (int2)( -HALF_KERNEL, HALF_KERNEL + 1 )) + - read_imagei( sum, sampler, kpPos + pt + (int2)( HALF_KERNEL + 1, -HALF_KERNEL )) + + read_imagei( sum, sampler, kpPos + pt + (int2)( -HALF_KERNEL, -HALF_KERNEL ))).x; } __kernel void extractBriefDescriptors( - __read_only image2d_t sumImg, __global float* keypoints, int kpRowStep, __global uchar* descriptors, int dscRowStep) + __read_only image2d_t sumImg, + __global float* keypoints, int kpRowStep, + __global uchar* descriptors, int dscRowStep, + __global uchar* mask) { - const int byte = get_local_id(0); - const int kpId = get_group_id(0); - const int2 kpPos = (int2)(keypoints[X_ROW * (kpRowStep/4) + kpId] + 0.5, keypoints[Y_ROW * (kpRowStep/4) + kpId] + 0.5); + const int byte = get_local_id(0); + const int kpId = get_group_id(0); + if( !mask[kpId]) + { + return; + } + const float2 kpPos = (float2)(keypoints[kpId], keypoints[kpRowStep/4 + kpId]); + if( kpPos.x < BORDER + || kpPos.y < BORDER + || kpPos.x >= (get_image_width( sumImg ) - BORDER) + || kpPos.y >= (get_image_height( sumImg ) - BORDER) ) + { + if( byte == 0) mask[kpId] = 0; + return; + } uchar descByte = 0; + const int2 pt = (int2)( kpPos.x + 0.5f, kpPos.y + 0.5f ); for(int i = 0; i<8; ++i) { descByte |= ( - smoothedSum(sumImg, (int2)( tests[byte * 32 + (i * 4) + 0], tests[byte * 32 + (i * 4) + 1] )) - < smoothedSum(sumImg, (int2)( tests[byte * 32 + (i * 4) + 2], tests[byte * 32 + (i * 4) + 3] )) + smoothedSum(sumImg, pt, (int2)( tests[byte * 32 + (i * 4) + 1], tests[byte * 32 + (i * 4) + 0] )) + < smoothedSum(sumImg, pt, (int2)( tests[byte * 32 + (i * 4) + 3], tests[byte * 32 + (i * 4) + 2] )) ) << (7-i); } - descriptors[kpId * dscRowStep + byte] = descByte; + if( byte == 0) mask[kpId] = 1; } diff --git a/modules/ocl/test/test_brief.cpp b/modules/ocl/test/test_brief.cpp new file mode 100644 index 000000000..81c638a3f --- /dev/null +++ b/modules/ocl/test/test_brief.cpp @@ -0,0 +1,115 @@ +/*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) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2010, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Matthias Bady aegirxx ==> gmail.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 "test_precomp.hpp" + +using namespace std; +using namespace cv; +using namespace ocl; + +#ifdef HAVE_OPENCL + +namespace +{ +IMPLEMENT_PARAM_CLASS( BRIEF_Bytes, int ) +} + +PARAM_TEST_CASE( BRIEF, BRIEF_Bytes ) +{ + int bytes; + + virtual void SetUp( ) + { + bytes = GET_PARAM( 0 ); + } +}; + +OCL_TEST_P( BRIEF, Accuracy ) +{ + Mat img = readImage( "gpu/opticalflow/rubberwhale1.png", IMREAD_GRAYSCALE ); + ASSERT_TRUE( !img.empty( ) ) << "no input image"; + + FastFeatureDetector fast( 20 ); + std::vector keypoints; + fast.detect( img, keypoints, Mat( ) ); + + Mat descriptorsGold; + BriefDescriptorExtractor brief( bytes ); + brief.compute( img, keypoints, descriptorsGold ); + + Mat kpMat( 2, keypoints.size( ), CV_32FC1 ); + for ( size_t i = 0; i < keypoints.size( ); ++i ) + { + kpMat.col( i ).row( 0 ) = keypoints[i].pt.x; + kpMat.col( i ).row( 1 ) = keypoints[i].pt.y; + } + oclMat imgOcl( img ), keypointsOcl( kpMat ), descriptorsOcl, maskOcl; + + BRIEF_OCL briefOcl( bytes ); + briefOcl.compute( imgOcl, keypointsOcl, maskOcl, descriptorsOcl ); + Mat mask, descriptors; + maskOcl.download( mask ); + descriptorsOcl.download( descriptors ); + + const int numDesc = cv::countNonZero( mask ); + if ( numDesc != descriptors.cols ) + { + size_t idx = 0; + Mat tmp( numDesc, bytes, CV_8UC1 ); + for ( int i = 0; i < descriptors.rows; ++i ) + { + if ( mask.at(i) ) + { + descriptors.row( i ).copyTo( tmp.row( idx++ ) ); + } + } + descriptors = tmp; + } + ASSERT_TRUE( descriptors.size( ) == descriptorsGold.size( ) ) << "Different number of descriptors"; + ASSERT_TRUE( 0 == norm( descriptors, descriptorsGold, NORM_HAMMING ) ) << "Descriptors different"; +} + +INSTANTIATE_TEST_CASE_P( OCL_Features2D, BRIEF, testing::Values( 16, 32, 64 ) ); +#endif \ No newline at end of file From 6e4715309b37449b82fd2294d118ba33e10cd2de Mon Sep 17 00:00:00 2001 From: Matthias Bady Date: Fri, 20 Dec 2013 10:53:21 +0100 Subject: [PATCH 023/295] added documentation --- .../doc/feature_detection_and_description.rst | 52 +++++++++++++++++++ modules/ocl/include/opencv2/ocl.hpp | 14 +++-- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/modules/ocl/doc/feature_detection_and_description.rst b/modules/ocl/doc/feature_detection_and_description.rst index b93d32f1a..bfc53d535 100644 --- a/modules/ocl/doc/feature_detection_and_description.rst +++ b/modules/ocl/doc/feature_detection_and_description.rst @@ -450,7 +450,59 @@ Gets final array of keypoints. The function performs non-max suppression if needed and returns the final amount of keypoints. +ocl::BRIEF_OCL +------------------ +.. ocv:class:: ocl::BRIEF_OCL +Class for computing BRIEF descriptors described in a paper of Calonder M., Lepetit V., +Strecha C., Fua P. *BRIEF: Binary Robust Independent Elementary Features* , +11th European Conference on Computer Vision (ECCV), Heraklion, Crete. LNCS Springer, September 2010. :: + + class CV_EXPORTS BRIEF_OCL + { + public: + static const int PATCH_SIZE = 48; + static const int KERNEL_SIZE = 9; + + explicit BRIEF_OCL(int _bytes = 32); + + //!computes the brief descriptor for a set of given keypoints + //! supports only CV_8UC1 images + void compute(const oclMat& image, const oclMat& keypoints, oclMat& mask, oclMat& descriptors) const; + + static int getBorderSize(); + protected: + ... + }; + +ocl::BRIEF_OCL::BRIEF_OCL +-------------------------- +Constructor. + +.. ocv:function:: ocl::BRIEF_OCL::BRIEF_OCL(int bytes = 32) + + :param bytes: The length of the descriptor in bytes. Supported values are 16, 32 or 64 bytes. + +ocl::BRIEF_OCL::compute +------------------------ +Computes BRIEF descriptors. + +.. ocv:function:: void ocl::BRIEF_OCL::compute(const oclMat& image, const oclMat& keypoints, oclMat& mask, oclMat& descriptors) const + + :param image: Image The input 8-bit grayscale image. + + :param keypoints: The keypoints. + + :param mask: In and output mask. If mask has same cols as keypoints, descriptors are computed for keypoints with non-zero mask element. + On return it indicates for what keypoints a descriptor was computed or not(if a keypoint is near the image border). + + :param descriptors: The computed descriptors. It has size keypoints.cols x bytes. + +ocl::BRIEF_OCL::getBorderSize +----------------------------- +Returns the size of the image border where descriptors cannot be computed + +.. ocv:function:: static int ocl::BRIEF_OCL::getBorderSize() const ocl::HOGDescriptor ---------------------- diff --git a/modules/ocl/include/opencv2/ocl.hpp b/modules/ocl/include/opencv2/ocl.hpp index 8df9e15c2..3e4c666d9 100644 --- a/modules/ocl/include/opencv2/ocl.hpp +++ b/modules/ocl/include/opencv2/ocl.hpp @@ -1546,22 +1546,20 @@ namespace cv int calcKeypointsOCL(const oclMat& img, const oclMat& mask, int maxKeypoints); int nonmaxSupressionOCL(oclMat& keypoints); }; + ////////////////////////////////// BRIEF Feature Descriptor ////////////////////////////////// + class CV_EXPORTS BRIEF_OCL { public: static const int PATCH_SIZE = 48; static const int KERNEL_SIZE = 9; - explicit BRIEF_OCL( int _bytes = 32 ); + explicit BRIEF_OCL(int _bytes = 32); - /* - * Compute the descriptors for a set of keypoints in an image. - * image The image. - * keypoints The input keypoints. - * descriptors Copmputed descriptors. Row i is the descriptor for keypoint i. - */ - void compute( const oclMat& image, const oclMat& keypoints, oclMat& mask, oclMat& descriptors ) const; + //!computes the brief descriptor for a set of given keypoints + //! supports only CV_8UC1 images + void compute(const oclMat& image, const oclMat& keypoints, oclMat& mask, oclMat& descriptors) const; static int getBorderSize(); protected: From 9b0a9f2a24daa9fac061766418f459e628cc7131 Mon Sep 17 00:00:00 2001 From: Matthias Bady Date: Fri, 20 Dec 2013 10:56:27 +0100 Subject: [PATCH 024/295] moved documentation of BriefDescriptorExtractor to correct place --- ...on_interfaces_of_descriptor_extractors.rst | 32 ------------------- .../doc/feature_detection_and_description.rst | 31 ++++++++++++++++++ 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/modules/features2d/doc/common_interfaces_of_descriptor_extractors.rst b/modules/features2d/doc/common_interfaces_of_descriptor_extractors.rst index bf84ed0fb..637e4769a 100644 --- a/modules/features2d/doc/common_interfaces_of_descriptor_extractors.rst +++ b/modules/features2d/doc/common_interfaces_of_descriptor_extractors.rst @@ -119,35 +119,3 @@ them into a single color descriptor. :: protected: ... }; - - - -BriefDescriptorExtractor ------------------------- -.. ocv:class:: BriefDescriptorExtractor : public DescriptorExtractor - -Class for computing BRIEF descriptors described in a paper of Calonder M., Lepetit V., -Strecha C., Fua P. *BRIEF: Binary Robust Independent Elementary Features* , -11th European Conference on Computer Vision (ECCV), Heraklion, Crete. LNCS Springer, September 2010. :: - - class BriefDescriptorExtractor : public DescriptorExtractor - { - public: - static const int PATCH_SIZE = 48; - static const int KERNEL_SIZE = 9; - - // bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes. - BriefDescriptorExtractor( int bytes = 32 ); - - virtual void read( const FileNode& ); - virtual void write( FileStorage& ) const; - virtual int descriptorSize() const; - virtual int descriptorType() const; - virtual int defaultNorm() const; - protected: - ... - }; - -.. note:: - - * A complete BRIEF extractor sample can be found at opencv_source_code/samples/cpp/brief_match_test.cpp diff --git a/modules/features2d/doc/feature_detection_and_description.rst b/modules/features2d/doc/feature_detection_and_description.rst index a6fe7c8fa..02263472b 100644 --- a/modules/features2d/doc/feature_detection_and_description.rst +++ b/modules/features2d/doc/feature_detection_and_description.rst @@ -37,6 +37,37 @@ Detects corners using the FAST algorithm by [Rosten06]_. .. [Rosten06] E. Rosten. Machine Learning for High-speed Corner Detection, 2006. +BriefDescriptorExtractor +------------------------ +.. ocv:class:: BriefDescriptorExtractor : public DescriptorExtractor + +Class for computing BRIEF descriptors described in a paper of Calonder M., Lepetit V., +Strecha C., Fua P. *BRIEF: Binary Robust Independent Elementary Features* , +11th European Conference on Computer Vision (ECCV), Heraklion, Crete. LNCS Springer, September 2010. :: + + class BriefDescriptorExtractor : public DescriptorExtractor + { + public: + static const int PATCH_SIZE = 48; + static const int KERNEL_SIZE = 9; + + // bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes. + BriefDescriptorExtractor( int bytes = 32 ); + + virtual void read( const FileNode& ); + virtual void write( FileStorage& ) const; + virtual int descriptorSize() const; + virtual int descriptorType() const; + virtual int defaultNorm() const; + protected: + ... + }; + +.. note:: + + * A complete BRIEF extractor sample can be found at opencv_source_code/samples/cpp/brief_match_test.cpp + + MSER ---- .. ocv:class:: MSER : public FeatureDetector From a032d947b4d6701ed9cf967ffe022525a753d1b4 Mon Sep 17 00:00:00 2001 From: Matthias Bady Date: Fri, 20 Dec 2013 11:45:07 +0100 Subject: [PATCH 025/295] Fixed doc --- modules/ocl/doc/feature_detection_and_description.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ocl/doc/feature_detection_and_description.rst b/modules/ocl/doc/feature_detection_and_description.rst index bfc53d535..0bc935658 100644 --- a/modules/ocl/doc/feature_detection_and_description.rst +++ b/modules/ocl/doc/feature_detection_and_description.rst @@ -479,7 +479,7 @@ ocl::BRIEF_OCL::BRIEF_OCL -------------------------- Constructor. -.. ocv:function:: ocl::BRIEF_OCL::BRIEF_OCL(int bytes = 32) +.. ocv:function:: ocl::BRIEF_OCL::BRIEF_OCL(int _bytes = 32) :param bytes: The length of the descriptor in bytes. Supported values are 16, 32 or 64 bytes. From 44970ddf560a531f8ce71f9856855b7e2528b4e0 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 30 Dec 2013 12:31:00 +0400 Subject: [PATCH 026/295] eliminate MINGW pragma warning --- modules/core/src/system.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 09daceed5..ee0799ce0 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -982,7 +982,9 @@ public: }; #ifdef WIN32 +#ifdef _MSC_VER #pragma warning(disable:4505) // unreferenced local function has been removed +#endif #ifdef HAVE_WINRT // using C++11 thread attribute for local thread data From 09d25e11c65fa20f9ddba1d25ee4f3344ba4e655 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 28 Dec 2013 15:09:45 +0400 Subject: [PATCH 027/295] fixed bug #3341 --- modules/core/src/arithm.cpp | 4 ++-- modules/core/test/test_arithm.cpp | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index a11b64b44..0517a5fae 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -1272,8 +1272,8 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, bool haveScalar = false, swapped12 = false; int depth2 = src2.depth(); if( src1.size != src2.size || src1.channels() != src2.channels() || - ((kind1 == _InputArray::MATX || kind2 == _InputArray::MATX) && - src1.cols == 1 && src2.rows == 4) ) + (kind1 == _InputArray::MATX && (src1.size() == Size(1,4) || src1.size() == Size(1,1))) || + (kind2 == _InputArray::MATX && (src2.size() == Size(1,4) || src2.size() == Size(1,1))) ) { if( checkScalar(src1, src2.type(), kind1, kind2) ) { diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index 664fa0204..f16c80171 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -1564,3 +1564,19 @@ TEST(Core_round, CvRound) ASSERT_EQ(-2, cvRound(-2.5)); ASSERT_EQ(-4, cvRound(-3.5)); } + + +typedef testing::TestWithParam Mul1; + +TEST_P(Mul1, One) +{ + Size size = GetParam(); + cv::Mat src(size, CV_32FC1, cv::Scalar::all(2)), dst, + ref_dst(size, CV_32FC1, cv::Scalar::all(6)); + + cv::multiply(3, src, dst); + + ASSERT_EQ(0, cv::norm(dst, ref_dst, cv::NORM_INF)); +} + +INSTANTIATE_TEST_CASE_P(Arithm, Mul1, testing::Values(Size(2, 2), Size(1, 1))); From 5db1754d499d21b9dda4a6ad36f98c22db97b994 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 28 Dec 2013 16:28:17 +0400 Subject: [PATCH 028/295] SSE2 optimization of cv::remap doesn't work with big images --- modules/imgproc/src/imgwarp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index 2c87efe44..4748af2ce 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -2201,15 +2201,15 @@ struct RemapVec_8u int operator()( const Mat& _src, void* _dst, const short* XY, const ushort* FXY, const void* _wtab, int width ) const { - int cn = _src.channels(); + int cn = _src.channels(), x = 0, sstep = (int)_src.step; - if( (cn != 1 && cn != 3 && cn != 4) || !checkHardwareSupport(CV_CPU_SSE2) ) + if( (cn != 1 && cn != 3 && cn != 4) || !checkHardwareSupport(CV_CPU_SSE2) || + sstep > 0x8000 ) return 0; const uchar *S0 = _src.data, *S1 = _src.data + _src.step; const short* wtab = cn == 1 ? (const short*)_wtab : &BilinearTab_iC4[0][0][0]; uchar* D = (uchar*)_dst; - int x = 0, sstep = (int)_src.step; __m128i delta = _mm_set1_epi32(INTER_REMAP_COEF_SCALE/2); __m128i xy2ofs = _mm_set1_epi32(cn + (sstep << 16)); __m128i z = _mm_setzero_si128(); From 795c108f2bf2880a81a8d0db1ddc2da71c91864e Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Mon, 30 Dec 2013 18:00:29 +0400 Subject: [PATCH 029/295] Fixed MinGW build by declaring the minimal required Windows version. Also deleted miscellaneous remaining multimon cruft. Deleted #include , because includes it already. This should have a nice side effect of preventing us from accidentally using any Windows API that's too new. --- modules/highgui/src/precomp.hpp | 8 ++++++++ modules/highgui/src/window_w32.cpp | 16 ---------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/modules/highgui/src/precomp.hpp b/modules/highgui/src/precomp.hpp index 88ba8e4b2..af5383b14 100644 --- a/modules/highgui/src/precomp.hpp +++ b/modules/highgui/src/precomp.hpp @@ -57,6 +57,14 @@ #include #if defined WIN32 || defined WINCE + #if !defined _WIN32_WINNT + #ifdef HAVE_MSMF + #define _WIN32_WINNT 0x0600 // Windows Vista + #else + #define _WIN32_WINNT 0x0500 // Windows 2000 + #endif + #endif + #include #undef small #undef min diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 7b78ebc81..59d66b100 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -43,27 +43,11 @@ #if defined WIN32 || defined _WIN32 -#define COMPILE_MULTIMON_STUBS // Required for multi-monitor support -#ifndef _MULTIMON_USE_SECURE_CRT -# define _MULTIMON_USE_SECURE_CRT 0 // some MinGW platforms have no strncpy_s -#endif - -#if defined SM_CMONITORS && !defined MONITOR_DEFAULTTONEAREST -# define MONITOR_DEFAULTTONULL 0x00000000 -# define MONITOR_DEFAULTTOPRIMARY 0x00000001 -# define MONITOR_DEFAULTTONEAREST 0x00000002 -# define MONITORINFOF_PRIMARY 0x00000001 -#endif -#ifndef __inout -# define __inout -#endif - #ifdef __GNUC__ # pragma GCC diagnostic ignored "-Wmissing-declarations" #endif #include -#include #include #include #include From 4f9c081dc313f8fdfee3f0a4572779ae13e27e40 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 28 Dec 2013 01:40:21 +0400 Subject: [PATCH 030/295] fixed bug #3319 --- modules/core/src/precomp.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index c53224e0a..ec8dcc9f2 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -129,12 +129,14 @@ template struct OpMax inline Size getContinuousSize( const Mat& m1, int widthScale=1 ) { + CV_Assert(m1.dims <= 2); return m1.isContinuous() ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } inline Size getContinuousSize( const Mat& m1, const Mat& m2, int widthScale=1 ) { + CV_Assert(m1.dims <= 2 && m1.size() == m2.size()); return (m1.flags & m2.flags & Mat::CONTINUOUS_FLAG) != 0 ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } @@ -142,6 +144,7 @@ inline Size getContinuousSize( const Mat& m1, const Mat& m2, int widthScale=1 ) inline Size getContinuousSize( const Mat& m1, const Mat& m2, const Mat& m3, int widthScale=1 ) { + CV_Assert(m1.dims <= 2 && m1.size() == m2.size() && m1.size() == m3.size()); return (m1.flags & m2.flags & m3.flags & Mat::CONTINUOUS_FLAG) != 0 ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } @@ -150,6 +153,7 @@ inline Size getContinuousSize( const Mat& m1, const Mat& m2, const Mat& m3, const Mat& m4, int widthScale=1 ) { + CV_Assert(m1.dims <= 2 && m1.size() == m2.size() && m1.size() == m3.size() && m1.size() == m4.size()); return (m1.flags & m2.flags & m3.flags & m4.flags & Mat::CONTINUOUS_FLAG) != 0 ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } @@ -158,6 +162,7 @@ inline Size getContinuousSize( const Mat& m1, const Mat& m2, const Mat& m3, const Mat& m4, const Mat& m5, int widthScale=1 ) { + CV_Assert(m1.dims <= 2 && m1.size() == m2.size() && m1.size() == m3.size() && m1.size() == m4.size() && m1.size() == m5.size()); return (m1.flags & m2.flags & m3.flags & m4.flags & m5.flags & Mat::CONTINUOUS_FLAG) != 0 ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } From e21c6e19db0183e40d12b6634aec2d1923496336 Mon Sep 17 00:00:00 2001 From: Robbert Klarenbeek Date: Thu, 2 Jan 2014 21:17:55 +0100 Subject: [PATCH 031/295] Fix algorithm setter argument validation for uchar --- modules/core/src/algorithm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/algorithm.cpp b/modules/core/src/algorithm.cpp index f96f243cb..5f16f95ed 100644 --- a/modules/core/src/algorithm.cpp +++ b/modules/core/src/algorithm.cpp @@ -647,7 +647,7 @@ void AlgorithmInfo::set(Algorithm* algo, const char* parameter, int argType, con || argType == Param::FLOAT || argType == Param::UNSIGNED_INT || argType == Param::UINT64 || argType == Param::UCHAR) { if ( !( p->type == Param::INT || p->type == Param::REAL || p->type == Param::BOOLEAN - || p->type == Param::UNSIGNED_INT || p->type == Param::UINT64 || p->type == Param::FLOAT || argType == Param::UCHAR + || p->type == Param::UNSIGNED_INT || p->type == Param::UINT64 || p->type == Param::FLOAT || p->type == Param::UCHAR || (p->type == Param::SHORT && argType == Param::INT)) ) { string message = getErrorMessageForWrongArgumentInSetter(algo->name(), parameter, p->type, argType); From d3e24f3cbff8a5f1503ff45cdf8d1d8118e4c049 Mon Sep 17 00:00:00 2001 From: Nghia Ho Date: Fri, 3 Jan 2014 14:18:07 +1100 Subject: [PATCH 032/295] Improved documentation for neural network --- modules/ml/doc/neural_networks.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/ml/doc/neural_networks.rst b/modules/ml/doc/neural_networks.rst index 0496e2201..776bf243b 100644 --- a/modules/ml/doc/neural_networks.rst +++ b/modules/ml/doc/neural_networks.rst @@ -240,6 +240,7 @@ This method applies the specified training algorithm to computing/adjusting the The RPROP training algorithm is parallelized with the TBB library. +If you are using the default ``cvANN_MLP::SIGMOID_SYM`` activation function then the output should be in the range [-1,1], instead of [0,1], for optimal results. CvANN_MLP::predict ------------------ @@ -257,6 +258,8 @@ Predicts responses for input samples. The method returns a dummy value which should be ignored. +If you are using the default ``cvANN_MLP::SIGMOID_SYM`` activation function with the default parameter values fparam1=0 and fparam2=0 then the function used is y = 1.7159*tanh(2/3 * x), so the output will range from [-1.7159, 1.7159], instead of [0,1]. + CvANN_MLP::get_layer_count -------------------------- Returns the number of layers in the MLP. From 3f458c6eb114bd46ce7f08b8ca471822ea16d26e Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Viel Date: Fri, 3 Jan 2014 13:16:36 +0100 Subject: [PATCH 033/295] Fix: freeing previous elements has to be done before loading new parameters to avoid trying to delete unexisting objects if arrays size was modified --- .../opencv2/flann/hierarchical_clustering_index.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h b/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h index c27b64834..b511ee908 100644 --- a/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h +++ b/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h @@ -414,12 +414,6 @@ public: void loadIndex(FILE* stream) { - load_value(stream, branching_); - load_value(stream, trees_); - load_value(stream, centers_init_); - load_value(stream, leaf_size_); - load_value(stream, memoryCounter); - free_elements(); if (root!=NULL) { @@ -430,6 +424,12 @@ public: delete[] indices; } + load_value(stream, branching_); + load_value(stream, trees_); + load_value(stream, centers_init_); + load_value(stream, leaf_size_); + load_value(stream, memoryCounter); + indices = new int*[trees_]; root = new NodePtr[trees_]; for (int i=0; i Date: Sat, 4 Jan 2014 18:56:32 +0800 Subject: [PATCH 034/295] Add performance tests for elementwise multiplication --- modules/core/perf/perf_arithm.cpp | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/modules/core/perf/perf_arithm.cpp b/modules/core/perf/perf_arithm.cpp index 22d7def2c..72fd21970 100644 --- a/modules/core/perf/perf_arithm.cpp +++ b/modules/core/perf/perf_arithm.cpp @@ -202,3 +202,49 @@ PERF_TEST_P(Size_MatType, subtractScalar, TYPICAL_MATS_CORE_ARITHM) SANITY_CHECK(c, 1e-8); } + + +PERF_TEST_P(Size_MatType, multiply, TYPICAL_MATS_CORE_ARITHM) +{ + Size sz = get<0>(GetParam()); + int type = get<1>(GetParam()); + cv::Mat a = Mat(sz, type); + cv::Mat b = Mat(sz, type); + cv::Mat c = Mat(sz, type); + + declare.in(a, b, WARMUP_RNG).out(c); + + if (CV_MAT_DEPTH(type) == CV_32S) + { + //According to docs, saturation is not applied when result is 32bit integer + a /= (2 << 16); + b /= (2 << 16); + } + + TEST_CYCLE() multiply(a, b, c); + + SANITY_CHECK(c, 1e-8); +} + +PERF_TEST_P(Size_MatType, multiplyScale, TYPICAL_MATS_CORE_ARITHM) +{ + Size sz = get<0>(GetParam()); + int type = get<1>(GetParam()); + cv::Mat a = Mat(sz, type); + cv::Mat b = Mat(sz, type); + cv::Mat c = Mat(sz, type); + double scale = 0.5; + + declare.in(a, b, WARMUP_RNG).out(c); + + if (CV_MAT_DEPTH(type) == CV_32S) + { + //According to docs, saturation is not applied when result is 32bit integer + a /= (2 << 16); + b /= (2 << 16); + } + + TEST_CYCLE() multiply(a, b, c, scale); + + SANITY_CHECK(c, 1e-8); +} From 34b05794d60e9f7043f652a55a4ad250b22a2dac Mon Sep 17 00:00:00 2001 From: Max Khardin Date: Sat, 4 Jan 2014 19:01:32 +0800 Subject: [PATCH 035/295] Fix source code indents --- modules/core/perf/perf_arithm.cpp | 60 +++++++++++++++---------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/modules/core/perf/perf_arithm.cpp b/modules/core/perf/perf_arithm.cpp index 72fd21970..977a70e0d 100644 --- a/modules/core/perf/perf_arithm.cpp +++ b/modules/core/perf/perf_arithm.cpp @@ -203,48 +203,46 @@ PERF_TEST_P(Size_MatType, subtractScalar, TYPICAL_MATS_CORE_ARITHM) SANITY_CHECK(c, 1e-8); } - PERF_TEST_P(Size_MatType, multiply, TYPICAL_MATS_CORE_ARITHM) { - Size sz = get<0>(GetParam()); - int type = get<1>(GetParam()); - cv::Mat a = Mat(sz, type); - cv::Mat b = Mat(sz, type); - cv::Mat c = Mat(sz, type); + Size sz = get<0>(GetParam()); + int type = get<1>(GetParam()); + cv::Mat a = Mat(sz, type); + cv::Mat b = Mat(sz, type); + cv::Mat c = Mat(sz, type); - declare.in(a, b, WARMUP_RNG).out(c); + declare.in(a, b, WARMUP_RNG).out(c); + if (CV_MAT_DEPTH(type) == CV_32S) + { + //According to docs, saturation is not applied when result is 32bit integer + a /= (2 << 16); + b /= (2 << 16); + } - if (CV_MAT_DEPTH(type) == CV_32S) - { - //According to docs, saturation is not applied when result is 32bit integer - a /= (2 << 16); - b /= (2 << 16); - } + TEST_CYCLE() multiply(a, b, c); - TEST_CYCLE() multiply(a, b, c); - - SANITY_CHECK(c, 1e-8); + SANITY_CHECK(c, 1e-8); } PERF_TEST_P(Size_MatType, multiplyScale, TYPICAL_MATS_CORE_ARITHM) { - Size sz = get<0>(GetParam()); - int type = get<1>(GetParam()); - cv::Mat a = Mat(sz, type); - cv::Mat b = Mat(sz, type); - cv::Mat c = Mat(sz, type); - double scale = 0.5; + Size sz = get<0>(GetParam()); + int type = get<1>(GetParam()); + cv::Mat a = Mat(sz, type); + cv::Mat b = Mat(sz, type); + cv::Mat c = Mat(sz, type); + double scale = 0.5; - declare.in(a, b, WARMUP_RNG).out(c); + declare.in(a, b, WARMUP_RNG).out(c); - if (CV_MAT_DEPTH(type) == CV_32S) - { - //According to docs, saturation is not applied when result is 32bit integer - a /= (2 << 16); - b /= (2 << 16); - } + if (CV_MAT_DEPTH(type) == CV_32S) + { + //According to docs, saturation is not applied when result is 32bit integer + a /= (2 << 16); + b /= (2 << 16); + } - TEST_CYCLE() multiply(a, b, c, scale); + TEST_CYCLE() multiply(a, b, c, scale); - SANITY_CHECK(c, 1e-8); + SANITY_CHECK(c, 1e-8); } From 699eda46b6278a6aeb6a9c58cbb605387b8a0075 Mon Sep 17 00:00:00 2001 From: Max Khardin Date: Sat, 4 Jan 2014 20:09:30 +0800 Subject: [PATCH 036/295] Remove three sneaky tabs --- modules/core/perf/perf_arithm.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/core/perf/perf_arithm.cpp b/modules/core/perf/perf_arithm.cpp index 977a70e0d..d3a75ca9c 100644 --- a/modules/core/perf/perf_arithm.cpp +++ b/modules/core/perf/perf_arithm.cpp @@ -214,9 +214,9 @@ PERF_TEST_P(Size_MatType, multiply, TYPICAL_MATS_CORE_ARITHM) declare.in(a, b, WARMUP_RNG).out(c); if (CV_MAT_DEPTH(type) == CV_32S) { - //According to docs, saturation is not applied when result is 32bit integer - a /= (2 << 16); - b /= (2 << 16); + //According to docs, saturation is not applied when result is 32bit integer + a /= (2 << 16); + b /= (2 << 16); } TEST_CYCLE() multiply(a, b, c); From 2ae20c74a2661d5975529211f4c95206e8558243 Mon Sep 17 00:00:00 2001 From: Kazuki Matsuda Date: Mon, 6 Jan 2014 02:24:14 +0900 Subject: [PATCH 037/295] Fix typo of SparseMat_<_Tp>::SparseMat_(const SparseMat& m) Fix compilation erros when compiling this constructor. First argument type of "convertTo" should be instance, not a pointer of instance. First pull request was created for master branch. But it should be marged for 2.4. https://github.com/Itseez/opencv/pull/2113 --- modules/core/include/opencv2/core/mat.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 8ddc16eb1..45c25900c 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -2401,7 +2401,7 @@ template inline SparseMat_<_Tp>::SparseMat_(const SparseMat& m) if( m.type() == DataType<_Tp>::type ) *this = (const SparseMat_<_Tp>&)m; else - m.convertTo(this, DataType<_Tp>::type); + m.convertTo(*this, DataType<_Tp>::type); } template inline SparseMat_<_Tp>::SparseMat_(const SparseMat_<_Tp>& m) From 601b7d1dd3a3ec9e8af5df461d43632d98ed3a7a Mon Sep 17 00:00:00 2001 From: Nghia Ho Date: Mon, 6 Jan 2014 20:19:07 +1100 Subject: [PATCH 038/295] Fixed a valgrind 'Conditional jump or move depends on uninitialised value(s)' on cv::kmeans(...). The original code used points(sampleCount, 1, CV_32FC2), which confused generateCentersPP into thinking it is a 1 dimensional center, instead of 2. As a result it would set only the x variable and leave y unitialised. --- samples/cpp/kmeans.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/cpp/kmeans.cpp b/samples/cpp/kmeans.cpp index 97de6a0a4..b74211205 100644 --- a/samples/cpp/kmeans.cpp +++ b/samples/cpp/kmeans.cpp @@ -33,7 +33,7 @@ int main( int /*argc*/, char** /*argv*/ ) { int k, clusterCount = rng.uniform(2, MAX_CLUSTERS+1); int i, sampleCount = rng.uniform(1, 1001); - Mat points(sampleCount, 1, CV_32FC2), labels; + Mat points(sampleCount, 2, CV_32F), labels; clusterCount = MIN(clusterCount, sampleCount); Mat centers(clusterCount, 1, points.type()); From 6b9ebcbf3d332f6963b2ab8c37d6a14223921e15 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 7 Jan 2014 02:38:41 +0400 Subject: [PATCH 039/295] deleted extra semicolons --- apps/haartraining/cvclassifier.h | 2 +- .../calib3d/test/test_chessboardgenerator.hpp | 2 +- modules/contrib/src/adaptiveskindetector.cpp | 18 +- modules/contrib/src/ba.cpp | 8 +- modules/contrib/src/facerec.cpp | 6 +- modules/contrib/src/fuzzymeanshifttracker.cpp | 82 +++---- modules/contrib/src/retina.cpp | 2 +- modules/contrib/src/spinimages.cpp | 2 +- modules/core/src/convert.cpp | 204 +++++++++--------- modules/core/src/copy.cpp | 20 +- modules/core/test/test_arithm.cpp | 62 +++--- modules/features2d/src/features2d_init.cpp | 30 +-- modules/gpu/include/opencv2/gpu/gpu.hpp | 4 +- modules/gpu/perf/perf_imgproc.cpp | 8 +- modules/highgui/src/bitstrm.hpp | 2 +- modules/highgui/src/cap_ffmpeg_impl.hpp | 4 +- modules/imgproc/perf/perf_filter2d.cpp | 2 +- modules/imgproc/src/gcgraph.hpp | 2 +- modules/imgproc/src/generalized_hough.cpp | 8 +- modules/imgproc/test/test_cvtyuv.cpp | 2 +- modules/legacy/src/blobtrack.cpp | 2 +- modules/legacy/src/enteringblobdetection.cpp | 4 +- modules/legacy/src/vecfacetracking.cpp | 2 +- modules/ml/src/ml_init.cpp | 2 +- modules/nonfree/src/nonfree_init.cpp | 4 +- modules/ocl/include/opencv2/ocl/ocl.hpp | 2 +- .../opencv2/ocl/private/opencl_utils.hpp | 2 +- modules/ocl/test/test_canny.cpp | 4 +- modules/ocl/test/test_match_template.cpp | 2 +- modules/ocl/test/test_objdetect.cpp | 2 +- modules/ocl/test/utility.hpp | 2 +- modules/superres/src/btv_l1.cpp | 2 +- modules/superres/src/btv_l1_ocl.cpp | 2 +- modules/superres/src/optical_flow.cpp | 20 +- modules/ts/include/opencv2/ts/ts_perf.hpp | 2 +- modules/video/perf/perf_optflowpyrlk.cpp | 2 +- modules/video/src/kalman.cpp | 2 +- modules/video/src/tvl1flow.cpp | 2 +- modules/video/src/video_init.cpp | 6 +- samples/c/adaptiveskindetector.cpp | 46 ++-- samples/cpp/calibration_artificial.cpp | 2 +- .../cpp/tutorial_code/ImgProc/Threshold.cpp | 2 +- 42 files changed, 293 insertions(+), 293 deletions(-) diff --git a/apps/haartraining/cvclassifier.h b/apps/haartraining/cvclassifier.h index df644ed17..3faec500a 100644 --- a/apps/haartraining/cvclassifier.h +++ b/apps/haartraining/cvclassifier.h @@ -338,7 +338,7 @@ typedef enum CvBoostType CV_LKCLASS = 5, /* classification (K class problem) */ CV_LSREG = 6, /* least squares regression */ CV_LADREG = 7, /* least absolute deviation regression */ - CV_MREG = 8, /* M-regression (Huber loss) */ + CV_MREG = 8 /* M-regression (Huber loss) */ } CvBoostType; /****************************************************************************************\ diff --git a/modules/calib3d/test/test_chessboardgenerator.hpp b/modules/calib3d/test/test_chessboardgenerator.hpp index 48b3f3a24..6b669d2f5 100644 --- a/modules/calib3d/test/test_chessboardgenerator.hpp +++ b/modules/calib3d/test/test_chessboardgenerator.hpp @@ -34,7 +34,7 @@ private: Mat rvec, tvec; }; -}; +} #endif diff --git a/modules/contrib/src/adaptiveskindetector.cpp b/modules/contrib/src/adaptiveskindetector.cpp index 0865ad70b..22f729d91 100644 --- a/modules/contrib/src/adaptiveskindetector.cpp +++ b/modules/contrib/src/adaptiveskindetector.cpp @@ -53,7 +53,7 @@ void CvAdaptiveSkinDetector::initData(IplImage *src, int widthDivider, int heigh imgGrayFrame = cvCreateImage(imageSize, IPL_DEPTH_8U, 1); imgLastGrayFrame = cvCreateImage(imageSize, IPL_DEPTH_8U, 1); imgHSVFrame = cvCreateImage(imageSize, IPL_DEPTH_8U, 3); -}; +} CvAdaptiveSkinDetector::CvAdaptiveSkinDetector(int samplingDivider, int morphingMethod) { @@ -78,7 +78,7 @@ CvAdaptiveSkinDetector::CvAdaptiveSkinDetector(int samplingDivider, int morphing imgLastGrayFrame = NULL; imgSaturationFrame = NULL; imgHSVFrame = NULL; -}; +} CvAdaptiveSkinDetector::~CvAdaptiveSkinDetector() { @@ -91,7 +91,7 @@ CvAdaptiveSkinDetector::~CvAdaptiveSkinDetector() cvReleaseImage(&imgGrayFrame); cvReleaseImage(&imgLastGrayFrame); cvReleaseImage(&imgHSVFrame); -}; +} void CvAdaptiveSkinDetector::process(IplImage *inputBGRImage, IplImage *outputHueMask) { @@ -188,7 +188,7 @@ void CvAdaptiveSkinDetector::process(IplImage *inputBGRImage, IplImage *outputHu if (outputHueMask != NULL) cvCopy(imgFilteredFrame, outputHueMask); -}; +} //------------------------- Histogram for Adaptive Skin Detector -------------------------// @@ -200,12 +200,12 @@ CvAdaptiveSkinDetector::Histogram::Histogram() float *ranges[] = { range }; fHistogram = cvCreateHist(1, histogramSize, CV_HIST_ARRAY, ranges, 1); cvClearHist(fHistogram); -}; +} CvAdaptiveSkinDetector::Histogram::~Histogram() { cvReleaseHist(&fHistogram); -}; +} int CvAdaptiveSkinDetector::Histogram::findCoverageIndex(double surfaceToCover, int defaultValue) { @@ -219,7 +219,7 @@ int CvAdaptiveSkinDetector::Histogram::findCoverageIndex(double surfaceToCover, } } return defaultValue; -}; +} void CvAdaptiveSkinDetector::Histogram::findCurveThresholds(int &x1, int &x2, double percent) { @@ -242,7 +242,7 @@ void CvAdaptiveSkinDetector::Histogram::findCurveThresholds(int &x1, int &x2, do x2 = GSD_HUE_UT; else x2 += GSD_HUE_LT; -}; +} void CvAdaptiveSkinDetector::Histogram::mergeWith(CvAdaptiveSkinDetector::Histogram *source, double weight) { @@ -283,4 +283,4 @@ void CvAdaptiveSkinDetector::Histogram::mergeWith(CvAdaptiveSkinDetector::Histog } } } -}; +} diff --git a/modules/contrib/src/ba.cpp b/modules/contrib/src/ba.cpp index 0e2afd95b..ec90cb79a 100644 --- a/modules/contrib/src/ba.cpp +++ b/modules/contrib/src/ba.cpp @@ -938,7 +938,7 @@ static void fjac(int /*i*/, int /*j*/, CvMat *point_params, CvMat* cam_params, C #endif -}; +} static void func(int /*i*/, int /*j*/, CvMat *point_params, CvMat* cam_params, CvMat* estim, void* /*data*/) { //just do projections CvMat _Mi; @@ -977,17 +977,17 @@ static void func(int /*i*/, int /*j*/, CvMat *point_params, CvMat* cam_params, C cvTranspose( _mp2, estim ); cvReleaseMat( &_mp ); cvReleaseMat( &_mp2 ); -}; +} static void fjac_new(int i, int j, Mat& point_params, Mat& cam_params, Mat& A, Mat& B, void* data) { CvMat _point_params = point_params, _cam_params = cam_params, _Al = A, _Bl = B; fjac(i,j, &_point_params, &_cam_params, &_Al, &_Bl, data); -}; +} static void func_new(int i, int j, Mat& point_params, Mat& cam_params, Mat& estim, void* data) { CvMat _point_params = point_params, _cam_params = cam_params, _estim = estim; func(i,j,&_point_params,&_cam_params,&_estim,data); -}; +} void LevMarqSparse::bundleAdjust( vector& points, //positions of points in global coordinate system (input and output) const vector >& imagePoints, //projections of 3d points for every camera diff --git a/modules/contrib/src/facerec.cpp b/modules/contrib/src/facerec.cpp index bd202d206..a3d695ad1 100644 --- a/modules/contrib/src/facerec.cpp +++ b/modules/contrib/src/facerec.cpp @@ -873,7 +873,7 @@ CV_INIT_ALGORITHM(Eigenfaces, "FaceRecognizer.Eigenfaces", obj.info()->addParam(obj, "labels", obj._labels, true); obj.info()->addParam(obj, "eigenvectors", obj._eigenvectors, true); obj.info()->addParam(obj, "eigenvalues", obj._eigenvalues, true); - obj.info()->addParam(obj, "mean", obj._mean, true)); + obj.info()->addParam(obj, "mean", obj._mean, true)) CV_INIT_ALGORITHM(Fisherfaces, "FaceRecognizer.Fisherfaces", obj.info()->addParam(obj, "ncomponents", obj._num_components); @@ -882,7 +882,7 @@ CV_INIT_ALGORITHM(Fisherfaces, "FaceRecognizer.Fisherfaces", obj.info()->addParam(obj, "labels", obj._labels, true); obj.info()->addParam(obj, "eigenvectors", obj._eigenvectors, true); obj.info()->addParam(obj, "eigenvalues", obj._eigenvalues, true); - obj.info()->addParam(obj, "mean", obj._mean, true)); + obj.info()->addParam(obj, "mean", obj._mean, true)) CV_INIT_ALGORITHM(LBPH, "FaceRecognizer.LBPH", obj.info()->addParam(obj, "radius", obj._radius); @@ -891,7 +891,7 @@ CV_INIT_ALGORITHM(LBPH, "FaceRecognizer.LBPH", obj.info()->addParam(obj, "grid_y", obj._grid_y); obj.info()->addParam(obj, "threshold", obj._threshold); obj.info()->addParam(obj, "histograms", obj._histograms, true); - obj.info()->addParam(obj, "labels", obj._labels, true)); + obj.info()->addParam(obj, "labels", obj._labels, true)) bool initModule_contrib() { diff --git a/modules/contrib/src/fuzzymeanshifttracker.cpp b/modules/contrib/src/fuzzymeanshifttracker.cpp index 0ac6d2443..1932ad595 100644 --- a/modules/contrib/src/fuzzymeanshifttracker.cpp +++ b/modules/contrib/src/fuzzymeanshifttracker.cpp @@ -40,7 +40,7 @@ CvFuzzyPoint::CvFuzzyPoint(double _x, double _y) { x = _x; y = _y; -}; +} bool CvFuzzyCurve::between(double x, double x1, double x2) { @@ -50,37 +50,37 @@ bool CvFuzzyCurve::between(double x, double x1, double x2) return true; return false; -}; +} CvFuzzyCurve::CvFuzzyCurve() { value = 0; -}; +} CvFuzzyCurve::~CvFuzzyCurve() { // nothing to do -}; +} void CvFuzzyCurve::setCentre(double _centre) { centre = _centre; -}; +} double CvFuzzyCurve::getCentre() { return centre; -}; +} void CvFuzzyCurve::clear() { points.clear(); -}; +} void CvFuzzyCurve::addPoint(double x, double y) { points.push_back(CvFuzzyPoint(x, y)); -}; +} double CvFuzzyCurve::calcValue(double param) { @@ -101,41 +101,41 @@ double CvFuzzyCurve::calcValue(double param) } } return 0; -}; +} double CvFuzzyCurve::getValue() { return value; -}; +} void CvFuzzyCurve::setValue(double _value) { value = _value; -}; +} CvFuzzyFunction::CvFuzzyFunction() { // nothing to do -}; +} CvFuzzyFunction::~CvFuzzyFunction() { curves.clear(); -}; +} void CvFuzzyFunction::addCurve(CvFuzzyCurve *curve, double value) { curves.push_back(*curve); curve->setValue(value); -}; +} void CvFuzzyFunction::resetValues() { int numCurves = (int)curves.size(); for (int i = 0; i < numCurves; i++) curves[i].setValue(0); -}; +} double CvFuzzyFunction::calcValue() { @@ -152,7 +152,7 @@ double CvFuzzyFunction::calcValue() return s1/s2; else return 0; -}; +} CvFuzzyCurve *CvFuzzyFunction::newCurve() { @@ -160,14 +160,14 @@ CvFuzzyCurve *CvFuzzyFunction::newCurve() c = new CvFuzzyCurve(); addCurve(c); return c; -}; +} CvFuzzyRule::CvFuzzyRule() { fuzzyInput1 = NULL; fuzzyInput2 = NULL; fuzzyOutput = NULL; -}; +} CvFuzzyRule::~CvFuzzyRule() { @@ -179,14 +179,14 @@ CvFuzzyRule::~CvFuzzyRule() if (fuzzyOutput != NULL) delete fuzzyOutput; -}; +} void CvFuzzyRule::setRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1) { fuzzyInput1 = c1; fuzzyInput2 = c2; fuzzyOutput = o1; -}; +} double CvFuzzyRule::calcValue(double param1, double param2) { @@ -202,31 +202,31 @@ double CvFuzzyRule::calcValue(double param1, double param2) } else return v1; -}; +} CvFuzzyCurve *CvFuzzyRule::getOutputCurve() { return fuzzyOutput; -}; +} CvFuzzyController::CvFuzzyController() { // nothing to do -}; +} CvFuzzyController::~CvFuzzyController() { int size = (int)rules.size(); for(int i = 0; i < size; i++) delete rules[i]; -}; +} void CvFuzzyController::addRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1) { CvFuzzyRule *f = new CvFuzzyRule(); rules.push_back(f); f->setRule(c1, c2, o1); -}; +} double CvFuzzyController::calcOutput(double param1, double param2) { @@ -242,7 +242,7 @@ double CvFuzzyController::calcOutput(double param1, double param2) } v = list.calcValue(); return v; -}; +} CvFuzzyMeanShiftTracker::FuzzyResizer::FuzzyResizer() { @@ -298,12 +298,12 @@ CvFuzzyMeanShiftTracker::FuzzyResizer::FuzzyResizer() fuzzyController.addRule(i1L, NULL, oS); fuzzyController.addRule(i1M, NULL, oZE); fuzzyController.addRule(i1H, NULL, oE); -}; +} int CvFuzzyMeanShiftTracker::FuzzyResizer::calcOutput(double edgeDensity, double density) { return (int)fuzzyController.calcOutput(edgeDensity, density); -}; +} CvFuzzyMeanShiftTracker::SearchWindow::SearchWindow() { @@ -328,7 +328,7 @@ CvFuzzyMeanShiftTracker::SearchWindow::SearchWindow() depthLow = 0; depthHigh = 0; fuzzyResizer = NULL; -}; +} CvFuzzyMeanShiftTracker::SearchWindow::~SearchWindow() { @@ -354,7 +354,7 @@ void CvFuzzyMeanShiftTracker::SearchWindow::setSize(int _x, int _y, int _width, if (y + height > maxHeight) height = maxHeight - y; -}; +} void CvFuzzyMeanShiftTracker::SearchWindow::initDepthValues(IplImage *maskImage, IplImage *depthMap) { @@ -408,7 +408,7 @@ void CvFuzzyMeanShiftTracker::SearchWindow::initDepthValues(IplImage *maskImage, depthHigh = 32000; depthLow = 0; } -}; +} bool CvFuzzyMeanShiftTracker::SearchWindow::shift() { @@ -421,7 +421,7 @@ bool CvFuzzyMeanShiftTracker::SearchWindow::shift() { return false; } -}; +} void CvFuzzyMeanShiftTracker::SearchWindow::extractInfo(IplImage *maskImage, IplImage *depthMap, bool initDepth) { @@ -527,7 +527,7 @@ void CvFuzzyMeanShiftTracker::SearchWindow::extractInfo(IplImage *maskImage, Ipl ellipseAngle = 0; density = 0; } -}; +} void CvFuzzyMeanShiftTracker::SearchWindow::getResizeAttribsEdgeDensityLinear(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh) { int x1 = horizontalEdgeTop; @@ -571,7 +571,7 @@ void CvFuzzyMeanShiftTracker::SearchWindow::getResizeAttribsEdgeDensityLinear(in } else { resizeDw = - resizeDx; } -}; +} void CvFuzzyMeanShiftTracker::SearchWindow::getResizeAttribsInnerDensity(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh) { @@ -587,7 +587,7 @@ void CvFuzzyMeanShiftTracker::SearchWindow::getResizeAttribsInnerDensity(int &re resizeDy = (int)(py*dy); resizeDw = (int)((1-px)*dx); resizeDh = (int)((1-py)*dy); -}; +} void CvFuzzyMeanShiftTracker::SearchWindow::getResizeAttribsEdgeDensityFuzzy(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh) { @@ -626,7 +626,7 @@ void CvFuzzyMeanShiftTracker::SearchWindow::getResizeAttribsEdgeDensityFuzzy(int resizeDy = int(-dy1); resizeDh = int(dy1+dy2); } -}; +} bool CvFuzzyMeanShiftTracker::SearchWindow::meanShift(IplImage *maskImage, IplImage *depthMap, int maxIteration, bool initDepth) { @@ -639,7 +639,7 @@ bool CvFuzzyMeanShiftTracker::SearchWindow::meanShift(IplImage *maskImage, IplIm } while (++numShifts < maxIteration); return false; -}; +} void CvFuzzyMeanShiftTracker::findOptimumSearchWindow(SearchWindow &searchWindow, IplImage *maskImage, IplImage *depthMap, int maxIteration, int resizeMethod, bool initDepth) { @@ -679,17 +679,17 @@ void CvFuzzyMeanShiftTracker::findOptimumSearchWindow(SearchWindow &searchWindow searchWindow.setSize(searchWindow.x + resizeDx, searchWindow.y + resizeDy, searchWindow.width + resizeDw, searchWindow.height + resizeDh); } -}; +} CvFuzzyMeanShiftTracker::CvFuzzyMeanShiftTracker() { searchMode = tsSetWindow; -}; +} CvFuzzyMeanShiftTracker::~CvFuzzyMeanShiftTracker() { // nothing to do -}; +} void CvFuzzyMeanShiftTracker::track(IplImage *maskImage, IplImage *depthMap, int resizeMethod, bool resetSearch, int minKernelMass) { @@ -717,4 +717,4 @@ void CvFuzzyMeanShiftTracker::track(IplImage *maskImage, IplImage *depthMap, int else searchMode = tsTracking; } -}; +} diff --git a/modules/contrib/src/retina.cpp b/modules/contrib/src/retina.cpp index 6f08337cc..4a02bbcb4 100644 --- a/modules/contrib/src/retina.cpp +++ b/modules/contrib/src/retina.cpp @@ -85,7 +85,7 @@ Retina::Retina(const cv::Size inputSz, const bool colorMode, RETINA_COLORSAMPLIN { _retinaFilter = 0; _init(inputSz, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); -}; +} Retina::~Retina() { diff --git a/modules/contrib/src/spinimages.cpp b/modules/contrib/src/spinimages.cpp index b01090057..747bf3e12 100644 --- a/modules/contrib/src/spinimages.cpp +++ b/modules/contrib/src/spinimages.cpp @@ -718,7 +718,7 @@ void cv::SpinImageModel::defaultParams() T_GeometriccConsistency = 0.25f; T_GroupingCorespondances = 0.25f; -}; +} Mat cv::SpinImageModel::packRandomScaledSpins(bool separateScale, size_t xCount, size_t yCount) const { diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 3de9f83d1..c37208b5c 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -839,122 +839,122 @@ stype* dst, size_t dstep, Size size, double*) \ } -DEF_CVT_SCALE_ABS_FUNC(8u, cvtScaleAbs_, uchar, uchar, float); -DEF_CVT_SCALE_ABS_FUNC(8s8u, cvtScaleAbs_, schar, uchar, float); -DEF_CVT_SCALE_ABS_FUNC(16u8u, cvtScaleAbs_, ushort, uchar, float); -DEF_CVT_SCALE_ABS_FUNC(16s8u, cvtScaleAbs_, short, uchar, float); -DEF_CVT_SCALE_ABS_FUNC(32s8u, cvtScaleAbs_, int, uchar, float); -DEF_CVT_SCALE_ABS_FUNC(32f8u, cvtScaleAbs_, float, uchar, float); -DEF_CVT_SCALE_ABS_FUNC(64f8u, cvtScaleAbs_, double, uchar, float); +DEF_CVT_SCALE_ABS_FUNC(8u, cvtScaleAbs_, uchar, uchar, float) +DEF_CVT_SCALE_ABS_FUNC(8s8u, cvtScaleAbs_, schar, uchar, float) +DEF_CVT_SCALE_ABS_FUNC(16u8u, cvtScaleAbs_, ushort, uchar, float) +DEF_CVT_SCALE_ABS_FUNC(16s8u, cvtScaleAbs_, short, uchar, float) +DEF_CVT_SCALE_ABS_FUNC(32s8u, cvtScaleAbs_, int, uchar, float) +DEF_CVT_SCALE_ABS_FUNC(32f8u, cvtScaleAbs_, float, uchar, float) +DEF_CVT_SCALE_ABS_FUNC(64f8u, cvtScaleAbs_, double, uchar, float) -DEF_CVT_SCALE_FUNC(8u, uchar, uchar, float); -DEF_CVT_SCALE_FUNC(8s8u, schar, uchar, float); -DEF_CVT_SCALE_FUNC(16u8u, ushort, uchar, float); -DEF_CVT_SCALE_FUNC(16s8u, short, uchar, float); -DEF_CVT_SCALE_FUNC(32s8u, int, uchar, float); -DEF_CVT_SCALE_FUNC(32f8u, float, uchar, float); -DEF_CVT_SCALE_FUNC(64f8u, double, uchar, float); +DEF_CVT_SCALE_FUNC(8u, uchar, uchar, float) +DEF_CVT_SCALE_FUNC(8s8u, schar, uchar, float) +DEF_CVT_SCALE_FUNC(16u8u, ushort, uchar, float) +DEF_CVT_SCALE_FUNC(16s8u, short, uchar, float) +DEF_CVT_SCALE_FUNC(32s8u, int, uchar, float) +DEF_CVT_SCALE_FUNC(32f8u, float, uchar, float) +DEF_CVT_SCALE_FUNC(64f8u, double, uchar, float) -DEF_CVT_SCALE_FUNC(8u8s, uchar, schar, float); -DEF_CVT_SCALE_FUNC(8s, schar, schar, float); -DEF_CVT_SCALE_FUNC(16u8s, ushort, schar, float); -DEF_CVT_SCALE_FUNC(16s8s, short, schar, float); -DEF_CVT_SCALE_FUNC(32s8s, int, schar, float); -DEF_CVT_SCALE_FUNC(32f8s, float, schar, float); -DEF_CVT_SCALE_FUNC(64f8s, double, schar, float); +DEF_CVT_SCALE_FUNC(8u8s, uchar, schar, float) +DEF_CVT_SCALE_FUNC(8s, schar, schar, float) +DEF_CVT_SCALE_FUNC(16u8s, ushort, schar, float) +DEF_CVT_SCALE_FUNC(16s8s, short, schar, float) +DEF_CVT_SCALE_FUNC(32s8s, int, schar, float) +DEF_CVT_SCALE_FUNC(32f8s, float, schar, float) +DEF_CVT_SCALE_FUNC(64f8s, double, schar, float) -DEF_CVT_SCALE_FUNC(8u16u, uchar, ushort, float); -DEF_CVT_SCALE_FUNC(8s16u, schar, ushort, float); -DEF_CVT_SCALE_FUNC(16u, ushort, ushort, float); -DEF_CVT_SCALE_FUNC(16s16u, short, ushort, float); -DEF_CVT_SCALE_FUNC(32s16u, int, ushort, float); -DEF_CVT_SCALE_FUNC(32f16u, float, ushort, float); -DEF_CVT_SCALE_FUNC(64f16u, double, ushort, float); +DEF_CVT_SCALE_FUNC(8u16u, uchar, ushort, float) +DEF_CVT_SCALE_FUNC(8s16u, schar, ushort, float) +DEF_CVT_SCALE_FUNC(16u, ushort, ushort, float) +DEF_CVT_SCALE_FUNC(16s16u, short, ushort, float) +DEF_CVT_SCALE_FUNC(32s16u, int, ushort, float) +DEF_CVT_SCALE_FUNC(32f16u, float, ushort, float) +DEF_CVT_SCALE_FUNC(64f16u, double, ushort, float) -DEF_CVT_SCALE_FUNC(8u16s, uchar, short, float); -DEF_CVT_SCALE_FUNC(8s16s, schar, short, float); -DEF_CVT_SCALE_FUNC(16u16s, ushort, short, float); -DEF_CVT_SCALE_FUNC(16s, short, short, float); -DEF_CVT_SCALE_FUNC(32s16s, int, short, float); -DEF_CVT_SCALE_FUNC(32f16s, float, short, float); -DEF_CVT_SCALE_FUNC(64f16s, double, short, float); +DEF_CVT_SCALE_FUNC(8u16s, uchar, short, float) +DEF_CVT_SCALE_FUNC(8s16s, schar, short, float) +DEF_CVT_SCALE_FUNC(16u16s, ushort, short, float) +DEF_CVT_SCALE_FUNC(16s, short, short, float) +DEF_CVT_SCALE_FUNC(32s16s, int, short, float) +DEF_CVT_SCALE_FUNC(32f16s, float, short, float) +DEF_CVT_SCALE_FUNC(64f16s, double, short, float) -DEF_CVT_SCALE_FUNC(8u32s, uchar, int, float); -DEF_CVT_SCALE_FUNC(8s32s, schar, int, float); -DEF_CVT_SCALE_FUNC(16u32s, ushort, int, float); -DEF_CVT_SCALE_FUNC(16s32s, short, int, float); -DEF_CVT_SCALE_FUNC(32s, int, int, double); -DEF_CVT_SCALE_FUNC(32f32s, float, int, float); -DEF_CVT_SCALE_FUNC(64f32s, double, int, double); +DEF_CVT_SCALE_FUNC(8u32s, uchar, int, float) +DEF_CVT_SCALE_FUNC(8s32s, schar, int, float) +DEF_CVT_SCALE_FUNC(16u32s, ushort, int, float) +DEF_CVT_SCALE_FUNC(16s32s, short, int, float) +DEF_CVT_SCALE_FUNC(32s, int, int, double) +DEF_CVT_SCALE_FUNC(32f32s, float, int, float) +DEF_CVT_SCALE_FUNC(64f32s, double, int, double) -DEF_CVT_SCALE_FUNC(8u32f, uchar, float, float); -DEF_CVT_SCALE_FUNC(8s32f, schar, float, float); -DEF_CVT_SCALE_FUNC(16u32f, ushort, float, float); -DEF_CVT_SCALE_FUNC(16s32f, short, float, float); -DEF_CVT_SCALE_FUNC(32s32f, int, float, double); -DEF_CVT_SCALE_FUNC(32f, float, float, float); -DEF_CVT_SCALE_FUNC(64f32f, double, float, double); +DEF_CVT_SCALE_FUNC(8u32f, uchar, float, float) +DEF_CVT_SCALE_FUNC(8s32f, schar, float, float) +DEF_CVT_SCALE_FUNC(16u32f, ushort, float, float) +DEF_CVT_SCALE_FUNC(16s32f, short, float, float) +DEF_CVT_SCALE_FUNC(32s32f, int, float, double) +DEF_CVT_SCALE_FUNC(32f, float, float, float) +DEF_CVT_SCALE_FUNC(64f32f, double, float, double) -DEF_CVT_SCALE_FUNC(8u64f, uchar, double, double); -DEF_CVT_SCALE_FUNC(8s64f, schar, double, double); -DEF_CVT_SCALE_FUNC(16u64f, ushort, double, double); -DEF_CVT_SCALE_FUNC(16s64f, short, double, double); -DEF_CVT_SCALE_FUNC(32s64f, int, double, double); -DEF_CVT_SCALE_FUNC(32f64f, float, double, double); -DEF_CVT_SCALE_FUNC(64f, double, double, double); +DEF_CVT_SCALE_FUNC(8u64f, uchar, double, double) +DEF_CVT_SCALE_FUNC(8s64f, schar, double, double) +DEF_CVT_SCALE_FUNC(16u64f, ushort, double, double) +DEF_CVT_SCALE_FUNC(16s64f, short, double, double) +DEF_CVT_SCALE_FUNC(32s64f, int, double, double) +DEF_CVT_SCALE_FUNC(32f64f, float, double, double) +DEF_CVT_SCALE_FUNC(64f, double, double, double) -DEF_CPY_FUNC(8u, uchar); -DEF_CVT_FUNC(8s8u, schar, uchar); -DEF_CVT_FUNC(16u8u, ushort, uchar); -DEF_CVT_FUNC(16s8u, short, uchar); -DEF_CVT_FUNC(32s8u, int, uchar); -DEF_CVT_FUNC(32f8u, float, uchar); -DEF_CVT_FUNC(64f8u, double, uchar); +DEF_CPY_FUNC(8u, uchar) +DEF_CVT_FUNC(8s8u, schar, uchar) +DEF_CVT_FUNC(16u8u, ushort, uchar) +DEF_CVT_FUNC(16s8u, short, uchar) +DEF_CVT_FUNC(32s8u, int, uchar) +DEF_CVT_FUNC(32f8u, float, uchar) +DEF_CVT_FUNC(64f8u, double, uchar) -DEF_CVT_FUNC(8u8s, uchar, schar); -DEF_CVT_FUNC(16u8s, ushort, schar); -DEF_CVT_FUNC(16s8s, short, schar); -DEF_CVT_FUNC(32s8s, int, schar); -DEF_CVT_FUNC(32f8s, float, schar); -DEF_CVT_FUNC(64f8s, double, schar); +DEF_CVT_FUNC(8u8s, uchar, schar) +DEF_CVT_FUNC(16u8s, ushort, schar) +DEF_CVT_FUNC(16s8s, short, schar) +DEF_CVT_FUNC(32s8s, int, schar) +DEF_CVT_FUNC(32f8s, float, schar) +DEF_CVT_FUNC(64f8s, double, schar) -DEF_CVT_FUNC(8u16u, uchar, ushort); -DEF_CVT_FUNC(8s16u, schar, ushort); -DEF_CPY_FUNC(16u, ushort); -DEF_CVT_FUNC(16s16u, short, ushort); -DEF_CVT_FUNC(32s16u, int, ushort); -DEF_CVT_FUNC(32f16u, float, ushort); -DEF_CVT_FUNC(64f16u, double, ushort); +DEF_CVT_FUNC(8u16u, uchar, ushort) +DEF_CVT_FUNC(8s16u, schar, ushort) +DEF_CPY_FUNC(16u, ushort) +DEF_CVT_FUNC(16s16u, short, ushort) +DEF_CVT_FUNC(32s16u, int, ushort) +DEF_CVT_FUNC(32f16u, float, ushort) +DEF_CVT_FUNC(64f16u, double, ushort) -DEF_CVT_FUNC(8u16s, uchar, short); -DEF_CVT_FUNC(8s16s, schar, short); -DEF_CVT_FUNC(16u16s, ushort, short); -DEF_CVT_FUNC(32s16s, int, short); -DEF_CVT_FUNC(32f16s, float, short); -DEF_CVT_FUNC(64f16s, double, short); +DEF_CVT_FUNC(8u16s, uchar, short) +DEF_CVT_FUNC(8s16s, schar, short) +DEF_CVT_FUNC(16u16s, ushort, short) +DEF_CVT_FUNC(32s16s, int, short) +DEF_CVT_FUNC(32f16s, float, short) +DEF_CVT_FUNC(64f16s, double, short) -DEF_CVT_FUNC(8u32s, uchar, int); -DEF_CVT_FUNC(8s32s, schar, int); -DEF_CVT_FUNC(16u32s, ushort, int); -DEF_CVT_FUNC(16s32s, short, int); -DEF_CPY_FUNC(32s, int); -DEF_CVT_FUNC(32f32s, float, int); -DEF_CVT_FUNC(64f32s, double, int); +DEF_CVT_FUNC(8u32s, uchar, int) +DEF_CVT_FUNC(8s32s, schar, int) +DEF_CVT_FUNC(16u32s, ushort, int) +DEF_CVT_FUNC(16s32s, short, int) +DEF_CPY_FUNC(32s, int) +DEF_CVT_FUNC(32f32s, float, int) +DEF_CVT_FUNC(64f32s, double, int) -DEF_CVT_FUNC(8u32f, uchar, float); -DEF_CVT_FUNC(8s32f, schar, float); -DEF_CVT_FUNC(16u32f, ushort, float); -DEF_CVT_FUNC(16s32f, short, float); -DEF_CVT_FUNC(32s32f, int, float); -DEF_CVT_FUNC(64f32f, double, float); +DEF_CVT_FUNC(8u32f, uchar, float) +DEF_CVT_FUNC(8s32f, schar, float) +DEF_CVT_FUNC(16u32f, ushort, float) +DEF_CVT_FUNC(16s32f, short, float) +DEF_CVT_FUNC(32s32f, int, float) +DEF_CVT_FUNC(64f32f, double, float) -DEF_CVT_FUNC(8u64f, uchar, double); -DEF_CVT_FUNC(8s64f, schar, double); -DEF_CVT_FUNC(16u64f, ushort, double); -DEF_CVT_FUNC(16s64f, short, double); -DEF_CVT_FUNC(32s64f, int, double); -DEF_CVT_FUNC(32f64f, float, double); -DEF_CPY_FUNC(64s, int64); +DEF_CVT_FUNC(8u64f, uchar, double) +DEF_CVT_FUNC(8s64f, schar, double) +DEF_CVT_FUNC(16u64f, ushort, double) +DEF_CVT_FUNC(16s64f, short, double) +DEF_CVT_FUNC(32s64f, int, double) +DEF_CVT_FUNC(32f64f, float, double) +DEF_CPY_FUNC(64s, int64) static BinaryFunc getCvtScaleAbsFunc(int depth) { diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index cc26b3eb3..894776bb3 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -166,16 +166,16 @@ static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, } -DEF_COPY_MASK(8u, uchar); -DEF_COPY_MASK(16u, ushort); -DEF_COPY_MASK(8uC3, Vec3b); -DEF_COPY_MASK(32s, int); -DEF_COPY_MASK(16uC3, Vec3s); -DEF_COPY_MASK(32sC2, Vec2i); -DEF_COPY_MASK(32sC3, Vec3i); -DEF_COPY_MASK(32sC4, Vec4i); -DEF_COPY_MASK(32sC6, Vec6i); -DEF_COPY_MASK(32sC8, Vec8i); +DEF_COPY_MASK(8u, uchar) +DEF_COPY_MASK(16u, ushort) +DEF_COPY_MASK(8uC3, Vec3b) +DEF_COPY_MASK(32s, int) +DEF_COPY_MASK(16uC3, Vec3s) +DEF_COPY_MASK(32sC2, Vec2i) +DEF_COPY_MASK(32sC3, Vec3i) +DEF_COPY_MASK(32sC4, Vec4i) +DEF_COPY_MASK(32sC6, Vec6i) +DEF_COPY_MASK(32sC8, Vec8i) BinaryFunc copyMaskTab[] = { diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index f16c80171..8fec388df 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -115,7 +115,7 @@ struct BaseAddOp : public BaseElemWiseOp struct AddOp : public BaseAddOp { - AddOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)) {}; + AddOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat& mask) { if( mask.empty() ) @@ -128,7 +128,7 @@ struct AddOp : public BaseAddOp struct SubOp : public BaseAddOp { - SubOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, -1, Scalar::all(0)) {}; + SubOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, -1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat& mask) { if( mask.empty() ) @@ -141,7 +141,7 @@ struct SubOp : public BaseAddOp struct AddSOp : public BaseAddOp { - AddSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, 1, 0, Scalar::all(0)) {}; + AddSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, 1, 0, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat& mask) { if( mask.empty() ) @@ -154,7 +154,7 @@ struct AddSOp : public BaseAddOp struct SubRSOp : public BaseAddOp { - SubRSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, -1, 0, Scalar::all(0)) {}; + SubRSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, -1, 0, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat& mask) { if( mask.empty() ) @@ -167,7 +167,7 @@ struct SubRSOp : public BaseAddOp struct ScaleAddOp : public BaseAddOp { - ScaleAddOp() : BaseAddOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; + ScaleAddOp() : BaseAddOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { scaleAdd(src[0], alpha, src[1], dst); @@ -181,7 +181,7 @@ struct ScaleAddOp : public BaseAddOp struct AddWeightedOp : public BaseAddOp { - AddWeightedOp() : BaseAddOp(2, REAL_GAMMA, 1, 1, Scalar::all(0)) {}; + AddWeightedOp() : BaseAddOp(2, REAL_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { addWeighted(src[0], alpha, src[1], beta, gamma[0], dst); @@ -194,7 +194,7 @@ struct AddWeightedOp : public BaseAddOp struct MulOp : public BaseElemWiseOp { - MulOp() : BaseElemWiseOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; + MulOp() : BaseElemWiseOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} void getValueRange(int depth, double& minval, double& maxval) { minval = depth < CV_32S ? cvtest::getMinVal(depth) : depth == CV_32S ? -1000000 : -1000.; @@ -218,7 +218,7 @@ struct MulOp : public BaseElemWiseOp struct DivOp : public BaseElemWiseOp { - DivOp() : BaseElemWiseOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; + DivOp() : BaseElemWiseOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { cv::divide(src[0], src[1], dst, alpha); @@ -235,7 +235,7 @@ struct DivOp : public BaseElemWiseOp struct RecipOp : public BaseElemWiseOp { - RecipOp() : BaseElemWiseOp(1, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; + RecipOp() : BaseElemWiseOp(1, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { cv::divide(alpha, src[0], dst); @@ -252,7 +252,7 @@ struct RecipOp : public BaseElemWiseOp struct AbsDiffOp : public BaseAddOp { - AbsDiffOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, -1, Scalar::all(0)) {}; + AbsDiffOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, -1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { absdiff(src[0], src[1], dst); @@ -265,7 +265,7 @@ struct AbsDiffOp : public BaseAddOp struct AbsDiffSOp : public BaseAddOp { - AbsDiffSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA, 1, 0, Scalar::all(0)) {}; + AbsDiffSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA, 1, 0, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { absdiff(src[0], gamma, dst); @@ -278,7 +278,7 @@ struct AbsDiffSOp : public BaseAddOp struct LogicOp : public BaseElemWiseOp { - LogicOp(char _opcode) : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)), opcode(_opcode) {}; + LogicOp(char _opcode) : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)), opcode(_opcode) {} void op(const vector& src, Mat& dst, const Mat& mask) { if( opcode == '&' ) @@ -309,7 +309,7 @@ struct LogicOp : public BaseElemWiseOp struct LogicSOp : public BaseElemWiseOp { LogicSOp(char _opcode) - : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+(_opcode != '~' ? SUPPORT_MASK : 0), 1, 1, Scalar::all(0)), opcode(_opcode) {}; + : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+(_opcode != '~' ? SUPPORT_MASK : 0), 1, 1, Scalar::all(0)), opcode(_opcode) {} void op(const vector& src, Mat& dst, const Mat& mask) { if( opcode == '&' ) @@ -341,7 +341,7 @@ struct LogicSOp : public BaseElemWiseOp struct MinOp : public BaseElemWiseOp { - MinOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; + MinOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { cv::min(src[0], src[1], dst); @@ -358,7 +358,7 @@ struct MinOp : public BaseElemWiseOp struct MaxOp : public BaseElemWiseOp { - MaxOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; + MaxOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { cv::max(src[0], src[1], dst); @@ -375,7 +375,7 @@ struct MaxOp : public BaseElemWiseOp struct MinSOp : public BaseElemWiseOp { - MinSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {}; + MinSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { cv::min(src[0], gamma[0], dst); @@ -392,7 +392,7 @@ struct MinSOp : public BaseElemWiseOp struct MaxSOp : public BaseElemWiseOp { - MaxSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {}; + MaxSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { cv::max(src[0], gamma[0], dst); @@ -409,7 +409,7 @@ struct MaxSOp : public BaseElemWiseOp struct CmpOp : public BaseElemWiseOp { - CmpOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; + CmpOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} void generateScalars(int depth, RNG& rng) { BaseElemWiseOp::generateScalars(depth, rng); @@ -437,7 +437,7 @@ struct CmpOp : public BaseElemWiseOp struct CmpSOp : public BaseElemWiseOp { - CmpSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {}; + CmpSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {} void generateScalars(int depth, RNG& rng) { BaseElemWiseOp::generateScalars(depth, rng); @@ -467,7 +467,7 @@ struct CmpSOp : public BaseElemWiseOp struct CopyOp : public BaseElemWiseOp { - CopyOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)) {}; + CopyOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat& mask) { src[0].copyTo(dst, mask); @@ -490,7 +490,7 @@ struct CopyOp : public BaseElemWiseOp struct SetOp : public BaseElemWiseOp { - SetOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, 1, 1, Scalar::all(0)) {}; + SetOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, 1, 1, Scalar::all(0)) {} void op(const vector&, Mat& dst, const Mat& mask) { dst.setTo(gamma, mask); @@ -651,7 +651,7 @@ static void inRangeS(const Mat& src, const Scalar& lb, const Scalar& rb, Mat& ds struct InRangeSOp : public BaseElemWiseOp { - InRangeSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA, 1, 1, Scalar::all(0)) {}; + InRangeSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { cv::inRange(src[0], gamma, gamma1, dst); @@ -681,7 +681,7 @@ struct InRangeSOp : public BaseElemWiseOp struct InRangeOp : public BaseElemWiseOp { - InRangeOp() : BaseElemWiseOp(3, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; + InRangeOp() : BaseElemWiseOp(3, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { Mat lb, rb; @@ -707,7 +707,7 @@ struct InRangeOp : public BaseElemWiseOp struct ConvertScaleOp : public BaseElemWiseOp { - ConvertScaleOp() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)), ddepth(0) { }; + ConvertScaleOp() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)), ddepth(0) { } void op(const vector& src, Mat& dst, const Mat&) { src[0].convertTo(dst, ddepth, alpha, gamma[0]); @@ -742,7 +742,7 @@ struct ConvertScaleOp : public BaseElemWiseOp struct ConvertScaleAbsOp : public BaseElemWiseOp { - ConvertScaleAbsOp() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {}; + ConvertScaleAbsOp() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector& src, Mat& dst, const Mat&) { cv::convertScaleAbs(src[0], dst, alpha, gamma[0]); @@ -810,7 +810,7 @@ static void setIdentity(Mat& dst, const Scalar& s) struct FlipOp : public BaseElemWiseOp { - FlipOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; + FlipOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} void getRandomSize(RNG& rng, vector& size) { cvtest::randomSize(rng, 2, 2, cvtest::ARITHM_MAX_SIZE_LOG, size); @@ -836,7 +836,7 @@ struct FlipOp : public BaseElemWiseOp struct TransposeOp : public BaseElemWiseOp { - TransposeOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; + TransposeOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} void getRandomSize(RNG& rng, vector& size) { cvtest::randomSize(rng, 2, 2, cvtest::ARITHM_MAX_SIZE_LOG, size); @@ -857,7 +857,7 @@ struct TransposeOp : public BaseElemWiseOp struct SetIdentityOp : public BaseElemWiseOp { - SetIdentityOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA, 1, 1, Scalar::all(0)) {}; + SetIdentityOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA, 1, 1, Scalar::all(0)) {} void getRandomSize(RNG& rng, vector& size) { cvtest::randomSize(rng, 2, 2, cvtest::ARITHM_MAX_SIZE_LOG, size); @@ -878,7 +878,7 @@ struct SetIdentityOp : public BaseElemWiseOp struct SetZeroOp : public BaseElemWiseOp { - SetZeroOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; + SetZeroOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} void op(const vector&, Mat& dst, const Mat&) { dst = Scalar::all(0); @@ -954,7 +954,7 @@ static void log(const Mat& src, Mat& dst) struct ExpOp : public BaseElemWiseOp { - ExpOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; + ExpOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} int getRandomType(RNG& rng) { return cvtest::randomType(rng, DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS); @@ -981,7 +981,7 @@ struct ExpOp : public BaseElemWiseOp struct LogOp : public BaseElemWiseOp { - LogOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; + LogOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {} int getRandomType(RNG& rng) { return cvtest::randomType(rng, DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS); diff --git a/modules/features2d/src/features2d_init.cpp b/modules/features2d/src/features2d_init.cpp index 13ef0f8ae..e12310a3b 100644 --- a/modules/features2d/src/features2d_init.cpp +++ b/modules/features2d/src/features2d_init.cpp @@ -59,23 +59,23 @@ Ptr Feature2D::create( const string& feature2DType ) CV_INIT_ALGORITHM(BRISK, "Feature2D.BRISK", obj.info()->addParam(obj, "thres", obj.threshold); - obj.info()->addParam(obj, "octaves", obj.octaves)); + obj.info()->addParam(obj, "octaves", obj.octaves)) /////////////////////////////////////////////////////////////////////////////////////////////////////////// CV_INIT_ALGORITHM(BriefDescriptorExtractor, "Feature2D.BRIEF", - obj.info()->addParam(obj, "bytes", obj.bytes_)); + obj.info()->addParam(obj, "bytes", obj.bytes_)) /////////////////////////////////////////////////////////////////////////////////////////////////////////// CV_INIT_ALGORITHM(FastFeatureDetector, "Feature2D.FAST", obj.info()->addParam(obj, "threshold", obj.threshold); - obj.info()->addParam(obj, "nonmaxSuppression", obj.nonmaxSuppression)); + obj.info()->addParam(obj, "nonmaxSuppression", obj.nonmaxSuppression)) CV_INIT_ALGORITHM(FastFeatureDetector2, "Feature2D.FASTX", obj.info()->addParam(obj, "threshold", obj.threshold); obj.info()->addParam(obj, "nonmaxSuppression", obj.nonmaxSuppression); - obj.info()->addParam(obj, "type", obj.type)); + obj.info()->addParam(obj, "type", obj.type)) /////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -84,7 +84,7 @@ CV_INIT_ALGORITHM(StarDetector, "Feature2D.STAR", obj.info()->addParam(obj, "responseThreshold", obj.responseThreshold); obj.info()->addParam(obj, "lineThresholdProjected", obj.lineThresholdProjected); obj.info()->addParam(obj, "lineThresholdBinarized", obj.lineThresholdBinarized); - obj.info()->addParam(obj, "suppressNonmaxSize", obj.suppressNonmaxSize)); + obj.info()->addParam(obj, "suppressNonmaxSize", obj.suppressNonmaxSize)) /////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -97,7 +97,7 @@ CV_INIT_ALGORITHM(MSER, "Feature2D.MSER", obj.info()->addParam(obj, "maxEvolution", obj.maxEvolution); obj.info()->addParam(obj, "areaThreshold", obj.areaThreshold); obj.info()->addParam(obj, "minMargin", obj.minMargin); - obj.info()->addParam(obj, "edgeBlurSize", obj.edgeBlurSize)); + obj.info()->addParam(obj, "edgeBlurSize", obj.edgeBlurSize)) /////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -109,7 +109,7 @@ CV_INIT_ALGORITHM(ORB, "Feature2D.ORB", obj.info()->addParam(obj, "edgeThreshold", obj.edgeThreshold); obj.info()->addParam(obj, "patchSize", obj.patchSize); obj.info()->addParam(obj, "WTA_K", obj.WTA_K); - obj.info()->addParam(obj, "scoreType", obj.scoreType)); + obj.info()->addParam(obj, "scoreType", obj.scoreType)) /////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -117,7 +117,7 @@ CV_INIT_ALGORITHM(FREAK, "Feature2D.FREAK", obj.info()->addParam(obj, "orientationNormalized", obj.orientationNormalized); obj.info()->addParam(obj, "scaleNormalized", obj.scaleNormalized); obj.info()->addParam(obj, "patternScale", obj.patternScale); - obj.info()->addParam(obj, "nbOctave", obj.nOctaves)); + obj.info()->addParam(obj, "nbOctave", obj.nOctaves)) /////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -126,7 +126,7 @@ CV_INIT_ALGORITHM(GFTTDetector, "Feature2D.GFTT", obj.info()->addParam(obj, "qualityLevel", obj.qualityLevel); obj.info()->addParam(obj, "minDistance", obj.minDistance); obj.info()->addParam(obj, "useHarrisDetector", obj.useHarrisDetector); - obj.info()->addParam(obj, "k", obj.k)); + obj.info()->addParam(obj, "k", obj.k)) /////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -146,7 +146,7 @@ CV_INIT_ALGORITHM(SimpleBlobDetector, "Feature2D.SimpleBlob", obj.info()->addParam(obj, "maxInertiaRatio", obj.params.maxInertiaRatio); obj.info()->addParam(obj, "filterByConvexity", obj.params.filterByConvexity); obj.info()->addParam(obj, "maxConvexity", obj.params.maxConvexity); - ); + ) /////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -167,7 +167,7 @@ CV_INIT_ALGORITHM(HarrisDetector, "Feature2D.HARRIS", obj.info()->addParam(obj, "qualityLevel", obj.qualityLevel); obj.info()->addParam(obj, "minDistance", obj.minDistance); obj.info()->addParam(obj, "useHarrisDetector", obj.useHarrisDetector); - obj.info()->addParam(obj, "k", obj.k)); + obj.info()->addParam(obj, "k", obj.k)) //////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -178,21 +178,21 @@ CV_INIT_ALGORITHM(DenseFeatureDetector, "Feature2D.Dense", obj.info()->addParam(obj, "initXyStep", obj.initXyStep); obj.info()->addParam(obj, "initImgBound", obj.initImgBound); obj.info()->addParam(obj, "varyXyStepWithScale", obj.varyXyStepWithScale); - obj.info()->addParam(obj, "varyImgBoundWithScale", obj.varyImgBoundWithScale)); + obj.info()->addParam(obj, "varyImgBoundWithScale", obj.varyImgBoundWithScale)) CV_INIT_ALGORITHM(GridAdaptedFeatureDetector, "Feature2D.Grid", obj.info()->addParam(obj, "detector", obj.detector, false, 0, 0); // Extra params added to avoid VS2013 fatal error in opencv2/core.hpp (decl. of addParam) obj.info()->addParam(obj, "maxTotalKeypoints", obj.maxTotalKeypoints); obj.info()->addParam(obj, "gridRows", obj.gridRows); - obj.info()->addParam(obj, "gridCols", obj.gridCols)); + obj.info()->addParam(obj, "gridCols", obj.gridCols)) //////////////////////////////////////////////////////////////////////////////////////////////////////////// CV_INIT_ALGORITHM(BFMatcher, "DescriptorMatcher.BFMatcher", obj.info()->addParam(obj, "normType", obj.normType); - obj.info()->addParam(obj, "crossCheck", obj.crossCheck)); + obj.info()->addParam(obj, "crossCheck", obj.crossCheck)) -CV_INIT_ALGORITHM(FlannBasedMatcher, "DescriptorMatcher.FlannBasedMatcher",); +CV_INIT_ALGORITHM(FlannBasedMatcher, "DescriptorMatcher.FlannBasedMatcher",) /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/gpu/include/opencv2/gpu/gpu.hpp b/modules/gpu/include/opencv2/gpu/gpu.hpp index e2fc99b90..e040ccfdd 100644 --- a/modules/gpu/include/opencv2/gpu/gpu.hpp +++ b/modules/gpu/include/opencv2/gpu/gpu.hpp @@ -2443,7 +2443,7 @@ public: Uncompressed_YV12 = (('Y'<<24)|('V'<<16)|('1'<<8)|('2')), // Y,V,U (4:2:0) Uncompressed_NV12 = (('N'<<24)|('V'<<16)|('1'<<8)|('2')), // Y,UV (4:2:0) Uncompressed_YUYV = (('Y'<<24)|('U'<<16)|('Y'<<8)|('V')), // YUYV/YUY2 (4:2:2) - Uncompressed_UYVY = (('U'<<24)|('Y'<<16)|('V'<<8)|('Y')), // UYVY (4:2:2) + Uncompressed_UYVY = (('U'<<24)|('Y'<<16)|('V'<<8)|('Y')) // UYVY (4:2:2) }; enum ChromaFormat @@ -2451,7 +2451,7 @@ public: Monochrome=0, YUV420, YUV422, - YUV444, + YUV444 }; struct FormatInfo diff --git a/modules/gpu/perf/perf_imgproc.cpp b/modules/gpu/perf/perf_imgproc.cpp index d942bed61..4093b16e7 100644 --- a/modules/gpu/perf/perf_imgproc.cpp +++ b/modules/gpu/perf/perf_imgproc.cpp @@ -50,7 +50,7 @@ using namespace perf; // Remap enum { HALF_SIZE=0, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH }; -CV_ENUM(RemapMode, HALF_SIZE, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH); +CV_ENUM(RemapMode, HALF_SIZE, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH) void generateMap(cv::Mat& map_x, cv::Mat& map_y, int remapMode) { @@ -941,7 +941,7 @@ PERF_TEST_P(Sz_TemplateSz_Cn_Method, ImgProc_MatchTemplate8U, CPU_SANITY_CHECK(dst); } -}; +} //////////////////////////////////////////////////////////////////////////////// // MatchTemplate32F @@ -981,7 +981,7 @@ PERF_TEST_P(Sz_TemplateSz_Cn_Method, ImgProc_MatchTemplate32F, CPU_SANITY_CHECK(dst); } -}; +} ////////////////////////////////////////////////////////////////////// // MulSpectrums @@ -1821,7 +1821,7 @@ PERF_TEST_P(Sz_Dp_MinDist, ImgProc_HoughCircles, ////////////////////////////////////////////////////////////////////// // GeneralizedHough -CV_FLAGS(GHMethod, GHT_POSITION, GHT_SCALE, GHT_ROTATION); +CV_FLAGS(GHMethod, GHT_POSITION, GHT_SCALE, GHT_ROTATION) DEF_PARAM_TEST(Method_Sz, GHMethod, cv::Size); diff --git a/modules/highgui/src/bitstrm.hpp b/modules/highgui/src/bitstrm.hpp index e476d9c56..57956beb5 100644 --- a/modules/highgui/src/bitstrm.hpp +++ b/modules/highgui/src/bitstrm.hpp @@ -53,7 +53,7 @@ enum RBS_THROW_EOS=-123, // exception code RBS_THROW_FORB=-124, // exception code RBS_HUFF_FORB=2047, // forrbidden huffman code "value" - RBS_BAD_HEADER=-125, // invalid header + RBS_BAD_HEADER=-125 // invalid header }; typedef unsigned long ulong; diff --git a/modules/highgui/src/cap_ffmpeg_impl.hpp b/modules/highgui/src/cap_ffmpeg_impl.hpp index 151a0cac2..2b185595d 100644 --- a/modules/highgui/src/cap_ffmpeg_impl.hpp +++ b/modules/highgui/src/cap_ffmpeg_impl.hpp @@ -2066,7 +2066,7 @@ enum VideoCodec_YV12 = (('Y'<<24)|('V'<<16)|('1'<<8)|('2')), // Y,V,U (4:2:0) VideoCodec_NV12 = (('N'<<24)|('V'<<16)|('1'<<8)|('2')), // Y,UV (4:2:0) VideoCodec_YUYV = (('Y'<<24)|('U'<<16)|('Y'<<8)|('V')), // YUYV/YUY2 (4:2:2) - VideoCodec_UYVY = (('U'<<24)|('Y'<<16)|('V'<<8)|('Y')), // UYVY (4:2:2) + VideoCodec_UYVY = (('U'<<24)|('Y'<<16)|('V'<<8)|('Y')) // UYVY (4:2:2) }; enum @@ -2074,7 +2074,7 @@ enum VideoChromaFormat_Monochrome = 0, VideoChromaFormat_YUV420, VideoChromaFormat_YUV422, - VideoChromaFormat_YUV444, + VideoChromaFormat_YUV444 }; struct InputMediaStream_FFMPEG diff --git a/modules/imgproc/perf/perf_filter2d.cpp b/modules/imgproc/perf/perf_filter2d.cpp index b897d6ac0..98992e98e 100644 --- a/modules/imgproc/perf/perf_filter2d.cpp +++ b/modules/imgproc/perf/perf_filter2d.cpp @@ -8,7 +8,7 @@ using std::tr1::make_tuple; using std::tr1::get; -CV_ENUM(BorderMode, BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT_101); +CV_ENUM(BorderMode, BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT_101) typedef TestBaseWithParam< tr1::tuple > TestFilter2d; typedef TestBaseWithParam< tr1::tuple > Image_KernelSize; diff --git a/modules/imgproc/src/gcgraph.hpp b/modules/imgproc/src/gcgraph.hpp index 59c9744e7..92b9e124b 100644 --- a/modules/imgproc/src/gcgraph.hpp +++ b/modules/imgproc/src/gcgraph.hpp @@ -380,6 +380,6 @@ bool GCGraph::inSourceSegment( int i ) { CV_Assert( i>=0 && i<(int)vtcs.size() ); return vtcs[i].t == 0; -}; +} #endif diff --git a/modules/imgproc/src/generalized_hough.cpp b/modules/imgproc/src/generalized_hough.cpp index 846a55fe9..8d0ac753f 100644 --- a/modules/imgproc/src/generalized_hough.cpp +++ b/modules/imgproc/src/generalized_hough.cpp @@ -300,7 +300,7 @@ namespace obj.info()->addParam(obj, "votesThreshold", obj.votesThreshold, false, 0, 0, "The accumulator threshold for the template centers at the detection stage. The smaller it is, the more false positions may be detected."); obj.info()->addParam(obj, "dp", obj.dp, false, 0, 0, - "Inverse ratio of the accumulator resolution to the image resolution.")); + "Inverse ratio of the accumulator resolution to the image resolution.")) GHT_Ballard_Pos::GHT_Ballard_Pos() { @@ -466,7 +466,7 @@ namespace obj.info()->addParam(obj, "maxScale", obj.maxScale, false, 0, 0, "Maximal scale to detect."); obj.info()->addParam(obj, "scaleStep", obj.scaleStep, false, 0, 0, - "Scale step.")); + "Scale step.")) GHT_Ballard_PosScale::GHT_Ballard_PosScale() { @@ -631,7 +631,7 @@ namespace obj.info()->addParam(obj, "maxAngle", obj.maxAngle, false, 0, 0, "Maximal rotation angle to detect in degrees."); obj.info()->addParam(obj, "angleStep", obj.angleStep, false, 0, 0, - "Angle step in degrees.")); + "Angle step in degrees.")) GHT_Ballard_PosRotation::GHT_Ballard_PosRotation() { @@ -878,7 +878,7 @@ namespace obj.info()->addParam(obj, "dp", obj.dp, false, 0, 0, "Inverse ratio of the accumulator resolution to the image resolution."); obj.info()->addParam(obj, "posThresh", obj.posThresh, false, 0, 0, - "Position threshold.")); + "Position threshold.")) GHT_Guil_Full::GHT_Guil_Full() { diff --git a/modules/imgproc/test/test_cvtyuv.cpp b/modules/imgproc/test/test_cvtyuv.cpp index bd8d95dc7..0cce64cdb 100644 --- a/modules/imgproc/test/test_cvtyuv.cpp +++ b/modules/imgproc/test/test_cvtyuv.cpp @@ -603,7 +603,7 @@ CV_ENUM(YUVCVTS, CV_YUV2RGB_NV12, CV_YUV2BGR_NV12, CV_YUV2RGB_NV21, CV_YUV2BGR_N CV_YUV2RGBA_YUY2, CV_YUV2BGRA_YUY2, CV_YUV2RGBA_YVYU, CV_YUV2BGRA_YVYU, CV_YUV2GRAY_420, CV_YUV2GRAY_UYVY, CV_YUV2GRAY_YUY2, CV_YUV2BGR, CV_YUV2RGB, CV_RGB2YUV_YV12, CV_BGR2YUV_YV12, CV_RGBA2YUV_YV12, - CV_BGRA2YUV_YV12, CV_RGB2YUV_I420, CV_BGR2YUV_I420, CV_RGBA2YUV_I420, CV_BGRA2YUV_I420); + CV_BGRA2YUV_YV12, CV_RGB2YUV_I420, CV_BGR2YUV_I420, CV_RGBA2YUV_I420, CV_BGRA2YUV_I420) typedef ::testing::TestWithParam Imgproc_ColorYUV; diff --git a/modules/legacy/src/blobtrack.cpp b/modules/legacy/src/blobtrack.cpp index 48b83ef91..00e4905cc 100644 --- a/modules/legacy/src/blobtrack.cpp +++ b/modules/legacy/src/blobtrack.cpp @@ -205,7 +205,7 @@ double CvVSModule::GetParam(const char* name) if(p->pInt) return p->pInt[0]; } return 0; -}; +} const char* CvVSModule::GetParamStr(const char* name) { diff --git a/modules/legacy/src/enteringblobdetection.cpp b/modules/legacy/src/enteringblobdetection.cpp index d66a997a7..a383bcf67 100644 --- a/modules/legacy/src/enteringblobdetection.cpp +++ b/modules/legacy/src/enteringblobdetection.cpp @@ -209,7 +209,7 @@ public: CvBlobDetectorSimple(); ~CvBlobDetectorSimple(); int DetectNewBlob(IplImage* pImg, IplImage* pFGMask, CvBlobSeq* pNewBlobList, CvBlobSeq* pOldBlobList); - void Release(){delete this;}; + void Release(){delete this;} protected: IplImage* m_pMaskBlobNew; @@ -219,7 +219,7 @@ protected: }; /* Blob detector creator (sole interface function for this file) */ -CvBlobDetector* cvCreateBlobDetectorSimple(){return new CvBlobDetectorSimple;}; +CvBlobDetector* cvCreateBlobDetectorSimple(){return new CvBlobDetectorSimple;} /* Constructor of BlobDetector: */ CvBlobDetectorSimple::CvBlobDetectorSimple() diff --git a/modules/legacy/src/vecfacetracking.cpp b/modules/legacy/src/vecfacetracking.cpp index bcf309f70..b29b6b27f 100644 --- a/modules/legacy/src/vecfacetracking.cpp +++ b/modules/legacy/src/vecfacetracking.cpp @@ -52,7 +52,7 @@ enum { MOUTH = 0, LEYE = 1, - REYE = 2, + REYE = 2 }; #define MAX_LAYERS 64 diff --git a/modules/ml/src/ml_init.cpp b/modules/ml/src/ml_init.cpp index 276f6f5d4..c6cb594ef 100644 --- a/modules/ml/src/ml_init.cpp +++ b/modules/ml/src/ml_init.cpp @@ -52,7 +52,7 @@ CV_INIT_ALGORITHM(EM, "StatModel.EM", obj.info()->addParam(obj, "epsilon", obj.epsilon); obj.info()->addParam(obj, "weights", obj.weights, true); obj.info()->addParam(obj, "means", obj.means, true); - obj.info()->addParam(obj, "covs", obj.covs, true)); + obj.info()->addParam(obj, "covs", obj.covs, true)) bool initModule_ml(void) { diff --git a/modules/nonfree/src/nonfree_init.cpp b/modules/nonfree/src/nonfree_init.cpp index 3c530e325..f18e7d81d 100644 --- a/modules/nonfree/src/nonfree_init.cpp +++ b/modules/nonfree/src/nonfree_init.cpp @@ -52,7 +52,7 @@ CV_INIT_ALGORITHM(SURF, "Feature2D.SURF", obj.info()->addParam(obj, "nOctaves", obj.nOctaves); obj.info()->addParam(obj, "nOctaveLayers", obj.nOctaveLayers); obj.info()->addParam(obj, "extended", obj.extended); - obj.info()->addParam(obj, "upright", obj.upright)); + obj.info()->addParam(obj, "upright", obj.upright)) /////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -61,7 +61,7 @@ CV_INIT_ALGORITHM(SIFT, "Feature2D.SIFT", obj.info()->addParam(obj, "nOctaveLayers", obj.nOctaveLayers); obj.info()->addParam(obj, "contrastThreshold", obj.contrastThreshold); obj.info()->addParam(obj, "edgeThreshold", obj.edgeThreshold); - obj.info()->addParam(obj, "sigma", obj.sigma)); + obj.info()->addParam(obj, "sigma", obj.sigma)) /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/ocl/include/opencv2/ocl/ocl.hpp b/modules/ocl/include/opencv2/ocl/ocl.hpp index ff35d14e7..9ea5f6652 100644 --- a/modules/ocl/include/opencv2/ocl/ocl.hpp +++ b/modules/ocl/include/opencv2/ocl/ocl.hpp @@ -204,7 +204,7 @@ namespace cv CACHE_NONE = 0, // do not cache OpenCL binary CACHE_DEBUG = 0x1 << 0, // cache OpenCL binary when built in debug mode CACHE_RELEASE = 0x1 << 1, // default behavior, only cache when built in release mode - CACHE_ALL = CACHE_DEBUG | CACHE_RELEASE, // cache opencl binary + CACHE_ALL = CACHE_DEBUG | CACHE_RELEASE // cache opencl binary }; //! Enable or disable OpenCL program binary caching onto local disk // After a program (*.cl files in opencl/ folder) is built at runtime, we allow the diff --git a/modules/ocl/include/opencv2/ocl/private/opencl_utils.hpp b/modules/ocl/include/opencv2/ocl/private/opencl_utils.hpp index 70c45d3dd..a737f75a5 100644 --- a/modules/ocl/include/opencv2/ocl/private/opencl_utils.hpp +++ b/modules/ocl/include/opencv2/ocl/private/opencl_utils.hpp @@ -108,7 +108,7 @@ inline cl_int getStringInfo(Functor f, ObjectType obj, cl_uint name, std::string } return CL_SUCCESS; -}; +} } // namespace cl_utils diff --git a/modules/ocl/test/test_canny.cpp b/modules/ocl/test/test_canny.cpp index 82286031f..6bd7f26ad 100644 --- a/modules/ocl/test/test_canny.cpp +++ b/modules/ocl/test/test_canny.cpp @@ -48,8 +48,8 @@ //////////////////////////////////////////////////////// // Canny -IMPLEMENT_PARAM_CLASS(AppertureSize, int); -IMPLEMENT_PARAM_CLASS(L2gradient, bool); +IMPLEMENT_PARAM_CLASS(AppertureSize, int) +IMPLEMENT_PARAM_CLASS(L2gradient, bool) PARAM_TEST_CASE(Canny, AppertureSize, L2gradient) { diff --git a/modules/ocl/test/test_match_template.cpp b/modules/ocl/test/test_match_template.cpp index edbc36a3f..aa63f3d9e 100644 --- a/modules/ocl/test/test_match_template.cpp +++ b/modules/ocl/test/test_match_template.cpp @@ -50,7 +50,7 @@ // MatchTemplate #define ALL_TEMPLATE_METHODS testing::Values(TemplateMethod(cv::TM_SQDIFF), TemplateMethod(cv::TM_CCORR), TemplateMethod(cv::TM_CCOEFF), TemplateMethod(cv::TM_SQDIFF_NORMED), TemplateMethod(cv::TM_CCORR_NORMED), TemplateMethod(cv::TM_CCOEFF_NORMED)) -IMPLEMENT_PARAM_CLASS(TemplateSize, cv::Size); +IMPLEMENT_PARAM_CLASS(TemplateSize, cv::Size) #define MTEMP_SIZES testing::Values(cv::Size(128, 256), cv::Size(1024, 768)) diff --git a/modules/ocl/test/test_objdetect.cpp b/modules/ocl/test/test_objdetect.cpp index 89f45b07c..604a96a43 100644 --- a/modules/ocl/test/test_objdetect.cpp +++ b/modules/ocl/test/test_objdetect.cpp @@ -181,7 +181,7 @@ INSTANTIATE_TEST_CASE_P(OCL_ObjDetect, HOG, testing::Combine( testing::Values(MatType(CV_8UC1), MatType(CV_8UC4)))); ///////////////////////////// Haar ////////////////////////////// -IMPLEMENT_PARAM_CLASS(CascadeName, std::string); +IMPLEMENT_PARAM_CLASS(CascadeName, std::string) CascadeName cascade_frontalface_alt(std::string("haarcascade_frontalface_alt.xml")); CascadeName cascade_frontalface_alt2(std::string("haarcascade_frontalface_alt2.xml")); struct getRect diff --git a/modules/ocl/test/utility.hpp b/modules/ocl/test/utility.hpp index a1fe3ffb7..6591456ee 100644 --- a/modules/ocl/test/utility.hpp +++ b/modules/ocl/test/utility.hpp @@ -266,7 +266,7 @@ CV_ENUM(Interpolation, INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, INTER_AREA) CV_ENUM(Border, BORDER_REFLECT101, BORDER_REPLICATE, BORDER_CONSTANT, BORDER_REFLECT, BORDER_WRAP) CV_ENUM(TemplateMethod, TM_SQDIFF, TM_SQDIFF_NORMED, TM_CCORR, TM_CCORR_NORMED, TM_CCOEFF, TM_CCOEFF_NORMED) -CV_FLAGS(GemmFlags, GEMM_1_T, GEMM_2_T, GEMM_3_T); +CV_FLAGS(GemmFlags, GEMM_1_T, GEMM_2_T, GEMM_3_T) CV_FLAGS(WarpFlags, INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, WARP_INVERSE_MAP) CV_FLAGS(DftFlags, DFT_INVERSE, DFT_SCALE, DFT_ROWS, DFT_COMPLEX_OUTPUT, DFT_REAL_OUTPUT) diff --git a/modules/superres/src/btv_l1.cpp b/modules/superres/src/btv_l1.cpp index 0d96a9d17..d49bcf32b 100644 --- a/modules/superres/src/btv_l1.cpp +++ b/modules/superres/src/btv_l1.cpp @@ -488,7 +488,7 @@ namespace obj.info()->addParam(obj, "blurKernelSize", obj.blurKernelSize_, false, 0, 0, "Gaussian blur kernel size."); obj.info()->addParam(obj, "blurSigma", obj.blurSigma_, false, 0, 0, "Gaussian blur sigma."); obj.info()->addParam(obj, "temporalAreaRadius", obj.temporalAreaRadius_, false, 0, 0, "Radius of the temporal search area."); - obj.info()->addParam(obj, "opticalFlow", obj.opticalFlow_, false, 0, 0, "Dense optical flow algorithm.")); + obj.info()->addParam(obj, "opticalFlow", obj.opticalFlow_, false, 0, 0, "Dense optical flow algorithm.")) BTVL1::BTVL1() { diff --git a/modules/superres/src/btv_l1_ocl.cpp b/modules/superres/src/btv_l1_ocl.cpp index b4f4acdaf..69564ef0d 100644 --- a/modules/superres/src/btv_l1_ocl.cpp +++ b/modules/superres/src/btv_l1_ocl.cpp @@ -580,7 +580,7 @@ namespace obj.info()->addParam(obj, "blurKernelSize", obj.blurKernelSize_, false, 0, 0, "Gaussian blur kernel size."); obj.info()->addParam(obj, "blurSigma", obj.blurSigma_, false, 0, 0, "Gaussian blur sigma."); obj.info()->addParam(obj, "temporalAreaRadius", obj.temporalAreaRadius_, false, 0, 0, "Radius of the temporal search area."); - obj.info()->addParam(obj, "opticalFlow", obj.opticalFlow_, false, 0, 0, "Dense optical flow algorithm.")); + obj.info()->addParam(obj, "opticalFlow", obj.opticalFlow_, false, 0, 0, "Dense optical flow algorithm.")) BTVL1_OCL::BTVL1_OCL() { diff --git a/modules/superres/src/optical_flow.cpp b/modules/superres/src/optical_flow.cpp index 9df4c3b79..e1e8a1027 100644 --- a/modules/superres/src/optical_flow.cpp +++ b/modules/superres/src/optical_flow.cpp @@ -149,7 +149,7 @@ namespace obj.info()->addParam(obj, "numIters", obj.numIters_); obj.info()->addParam(obj, "polyN", obj.polyN_); obj.info()->addParam(obj, "polySigma", obj.polySigma_); - obj.info()->addParam(obj, "flags", obj.flags_)); + obj.info()->addParam(obj, "flags", obj.flags_)) Farneback::Farneback() : CpuOpticalFlow(CV_8UC1) { @@ -217,7 +217,7 @@ namespace obj.info()->addParam(obj, "upscaleAveragingRadius", obj.upscaleAveragingRadius_); obj.info()->addParam(obj, "upscaleSigmaDist", obj.upscaleSigmaDist_); obj.info()->addParam(obj, "upscaleSigmaColor", obj.upscaleSigmaColor_); - obj.info()->addParam(obj, "speedUpThr", obj.speedUpThr_)); + obj.info()->addParam(obj, "speedUpThr", obj.speedUpThr_)) Simple::Simple() : CpuOpticalFlow(CV_8UC3) { @@ -300,7 +300,7 @@ namespace obj.info()->addParam(obj, "warps", obj.warps_); obj.info()->addParam(obj, "epsilon", obj.epsilon_); obj.info()->addParam(obj, "iterations", obj.iterations_); - obj.info()->addParam(obj, "useInitialFlow", obj.useInitialFlow_)); + obj.info()->addParam(obj, "useInitialFlow", obj.useInitialFlow_)) DualTVL1::DualTVL1() : CpuOpticalFlow(CV_8UC1) { @@ -471,7 +471,7 @@ namespace obj.info()->addParam(obj, "scaleFactor", obj.scaleFactor_, false, 0, 0, "Pyramid scale factor"); obj.info()->addParam(obj, "innerIterations", obj.innerIterations_, false, 0, 0, "Number of lagged non-linearity iterations (inner loop)"); obj.info()->addParam(obj, "outerIterations", obj.outerIterations_, false, 0, 0, "Number of warping iterations (number of pyramid levels)"); - obj.info()->addParam(obj, "solverIterations", obj.solverIterations_, false, 0, 0, "Number of linear system solver iterations")); + obj.info()->addParam(obj, "solverIterations", obj.solverIterations_, false, 0, 0, "Number of linear system solver iterations")) Brox_GPU::Brox_GPU() : GpuOpticalFlow(CV_32FC1), alg_(0.197f, 50.0f, 0.8f, 10, 77, 10) { @@ -535,7 +535,7 @@ namespace CV_INIT_ALGORITHM(PyrLK_GPU, "DenseOpticalFlowExt.PyrLK_GPU", obj.info()->addParam(obj, "winSize", obj.winSize_); obj.info()->addParam(obj, "maxLevel", obj.maxLevel_); - obj.info()->addParam(obj, "iterations", obj.iterations_)); + obj.info()->addParam(obj, "iterations", obj.iterations_)) PyrLK_GPU::PyrLK_GPU() : GpuOpticalFlow(CV_8UC1) { @@ -602,7 +602,7 @@ namespace obj.info()->addParam(obj, "numIters", obj.numIters_); obj.info()->addParam(obj, "polyN", obj.polyN_); obj.info()->addParam(obj, "polySigma", obj.polySigma_); - obj.info()->addParam(obj, "flags", obj.flags_)); + obj.info()->addParam(obj, "flags", obj.flags_)) Farneback_GPU::Farneback_GPU() : GpuOpticalFlow(CV_8UC1) { @@ -678,7 +678,7 @@ namespace obj.info()->addParam(obj, "warps", obj.warps_); obj.info()->addParam(obj, "epsilon", obj.epsilon_); obj.info()->addParam(obj, "iterations", obj.iterations_); - obj.info()->addParam(obj, "useInitialFlow", obj.useInitialFlow_)); + obj.info()->addParam(obj, "useInitialFlow", obj.useInitialFlow_)) DualTVL1_GPU::DualTVL1_GPU() : GpuOpticalFlow(CV_8UC1) { @@ -800,7 +800,7 @@ namespace CV_INIT_ALGORITHM(PyrLK_OCL, "DenseOpticalFlowExt.PyrLK_OCL", obj.info()->addParam(obj, "winSize", obj.winSize_); obj.info()->addParam(obj, "maxLevel", obj.maxLevel_); - obj.info()->addParam(obj, "iterations", obj.iterations_)); + obj.info()->addParam(obj, "iterations", obj.iterations_)) PyrLK_OCL::PyrLK_OCL() : oclOpticalFlow(CV_8UC1) { @@ -869,7 +869,7 @@ namespace obj.info()->addParam(obj, "warps", obj.warps_); obj.info()->addParam(obj, "epsilon", obj.epsilon_); obj.info()->addParam(obj, "iterations", obj.iterations_); - obj.info()->addParam(obj, "useInitialFlow", obj.useInitialFlow_)); + obj.info()->addParam(obj, "useInitialFlow", obj.useInitialFlow_)) DualTVL1_OCL::DualTVL1_OCL() : oclOpticalFlow(CV_8UC1) { @@ -946,7 +946,7 @@ namespace obj.info()->addParam(obj, "numIters", obj.numIters_); obj.info()->addParam(obj, "polyN", obj.polyN_); obj.info()->addParam(obj, "polySigma", obj.polySigma_); - obj.info()->addParam(obj, "flags", obj.flags_)); + obj.info()->addParam(obj, "flags", obj.flags_)) FarneBack_OCL::FarneBack_OCL() : oclOpticalFlow(CV_8UC1) { diff --git a/modules/ts/include/opencv2/ts/ts_perf.hpp b/modules/ts/include/opencv2/ts/ts_perf.hpp index 9238b3e34..e32057de2 100644 --- a/modules/ts/include/opencv2/ts/ts_perf.hpp +++ b/modules/ts/include/opencv2/ts/ts_perf.hpp @@ -258,7 +258,7 @@ typedef struct CV_EXPORTS performance_metrics enum PERF_STRATEGY { PERF_STRATEGY_BASE = 0, - PERF_STRATEGY_SIMPLE = 1, + PERF_STRATEGY_SIMPLE = 1 }; diff --git a/modules/video/perf/perf_optflowpyrlk.cpp b/modules/video/perf/perf_optflowpyrlk.cpp index 8c53db03a..25310af0e 100644 --- a/modules/video/perf/perf_optflowpyrlk.cpp +++ b/modules/video/perf/perf_optflowpyrlk.cpp @@ -178,7 +178,7 @@ PERF_TEST_P(Path_Idx_Cn_NPoints_WSize_Deriv, OpticalFlowPyrLK_self, testing::Com SANITY_CHECK(err, 2); } -CV_ENUM(PyrBorderMode, BORDER_DEFAULT, BORDER_TRANSPARENT); +CV_ENUM(PyrBorderMode, BORDER_DEFAULT, BORDER_TRANSPARENT) typedef tr1::tuple Path_Win_Deriv_Border_Reuse_t; typedef TestBaseWithParam Path_Win_Deriv_Border_Reuse; diff --git a/modules/video/src/kalman.cpp b/modules/video/src/kalman.cpp index b4b4c7435..16ab7745f 100644 --- a/modules/video/src/kalman.cpp +++ b/modules/video/src/kalman.cpp @@ -297,4 +297,4 @@ const Mat& KalmanFilter::correct(const Mat& measurement) return statePost; } -}; +} diff --git a/modules/video/src/tvl1flow.cpp b/modules/video/src/tvl1flow.cpp index ddcdabdd3..eb0ff2351 100644 --- a/modules/video/src/tvl1flow.cpp +++ b/modules/video/src/tvl1flow.cpp @@ -928,7 +928,7 @@ CV_INIT_ALGORITHM(OpticalFlowDual_TVL1, "DenseOpticalFlow.DualTVL1", "Stopping criterion threshold used in the numerical scheme, which is a trade-off between precision and running time"); obj.info()->addParam(obj, "iterations", obj.iterations, false, 0, 0, "Stopping criterion iterations number used in the numerical scheme"); - obj.info()->addParam(obj, "useInitialFlow", obj.useInitialFlow)); + obj.info()->addParam(obj, "useInitialFlow", obj.useInitialFlow)) } // namespace diff --git a/modules/video/src/video_init.cpp b/modules/video/src/video_init.cpp index 7ec860fbd..69928c398 100644 --- a/modules/video/src/video_init.cpp +++ b/modules/video/src/video_init.cpp @@ -52,7 +52,7 @@ CV_INIT_ALGORITHM(BackgroundSubtractorMOG, "BackgroundSubtractor.MOG", obj.info()->addParam(obj, "history", obj.history); obj.info()->addParam(obj, "nmixtures", obj.nmixtures); obj.info()->addParam(obj, "backgroundRatio", obj.backgroundRatio); - obj.info()->addParam(obj, "noiseSigma", obj.noiseSigma)); + obj.info()->addParam(obj, "noiseSigma", obj.noiseSigma)) /////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -68,7 +68,7 @@ CV_INIT_ALGORITHM(BackgroundSubtractorMOG2, "BackgroundSubtractor.MOG2", obj.info()->addParam(obj, "fVarMax", obj.fVarMax); obj.info()->addParam(obj, "fCT", obj.fCT); obj.info()->addParam(obj, "nShadowDetection", obj.nShadowDetection); - obj.info()->addParam(obj, "fTau", obj.fTau)); + obj.info()->addParam(obj, "fTau", obj.fTau)) /////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -88,7 +88,7 @@ CV_INIT_ALGORITHM(BackgroundSubtractorGMG, "BackgroundSubtractor.GMG", obj.info()->addParam(obj, "decisionThreshold", obj.decisionThreshold,false,0,0, "Threshold for FG decision rule. Pixel is FG if posterior probability exceeds threshold."); obj.info()->addParam(obj, "updateBackgroundModel", obj.updateBackgroundModel,false,0,0, - "Perform background model update.")); + "Perform background model update.")) bool initModule_video(void) { diff --git a/samples/c/adaptiveskindetector.cpp b/samples/c/adaptiveskindetector.cpp index 37856bd4e..3ae10017d 100644 --- a/samples/c/adaptiveskindetector.cpp +++ b/samples/c/adaptiveskindetector.cpp @@ -126,12 +126,12 @@ ASDFrameHolder::ASDFrameHolder( ) { image = NULL; timeStamp = 0; -}; +} ASDFrameHolder::~ASDFrameHolder( ) { cvReleaseImage(&image); -}; +} void ASDFrameHolder::assignFrame(IplImage *sourceImage, double frameTime) { @@ -143,22 +143,22 @@ void ASDFrameHolder::assignFrame(IplImage *sourceImage, double frameTime) image = cvCloneImage(sourceImage); timeStamp = frameTime; -}; +} IplImage *ASDFrameHolder::getImage() { return image; -}; +} double ASDFrameHolder::getTimeStamp() { return timeStamp; -}; +} void ASDFrameHolder::setImage(IplImage *sourceImage) { image = sourceImage; -}; +} //-------------------- ASDFrameSequencer -----------------------// @@ -166,26 +166,26 @@ void ASDFrameHolder::setImage(IplImage *sourceImage) ASDFrameSequencer::~ASDFrameSequencer() { close(); -}; +} IplImage *ASDFrameSequencer::getNextImage() { return NULL; -}; +} void ASDFrameSequencer::close() { -}; +} bool ASDFrameSequencer::isOpen() { return false; -}; +} void ASDFrameSequencer::getFrameCaption(char* /*caption*/) { return; -}; +} IplImage* ASDCVFrameSequencer::getNextImage() { @@ -201,7 +201,7 @@ IplImage* ASDCVFrameSequencer::getNextImage() { return NULL; } -}; +} void ASDCVFrameSequencer::close() { @@ -209,12 +209,12 @@ void ASDCVFrameSequencer::close() { cvReleaseCapture(&capture); } -}; +} bool ASDCVFrameSequencer::isOpen() { return (capture != NULL); -}; +} //-------------------- ASDFrameSequencerWebCam -----------------------// @@ -233,7 +233,7 @@ bool ASDFrameSequencerWebCam::open(int cameraIndex) { return true; } -}; +} //-------------------- ASDFrameSequencerVideoFile -----------------------// @@ -251,7 +251,7 @@ bool ASDFrameSequencerVideoFile::open(const char *fileName) { return true; } -}; +} //-------------------- ASDFrameSequencerImageFile -----------------------// @@ -263,11 +263,11 @@ void ASDFrameSequencerImageFile::open(const char *fileNameMask, int startIndex, nEndIndex = endIndex; std::sprintf(sFileNameMask, "%s", fileNameMask); -}; +} void ASDFrameSequencerImageFile::getFrameCaption(char *caption) { std::sprintf(caption, sFileNameMask, nCurrentIndex); -}; +} IplImage* ASDFrameSequencerImageFile::getNextImage() { @@ -283,23 +283,23 @@ IplImage* ASDFrameSequencerImageFile::getNextImage() IplImage* img = cvLoadImage(fileName); return img; -}; +} void ASDFrameSequencerImageFile::close() { nCurrentIndex = nEndIndex+1; -}; +} bool ASDFrameSequencerImageFile::isOpen() { return (nCurrentIndex <= nEndIndex); -}; +} static void putTextWithShadow(IplImage *img, const char *str, CvPoint point, CvFont *font, CvScalar color = CV_RGB(255, 255, 128)) { cvPutText(img, str, cvPoint(point.x-1,point.y-1), font, CV_RGB(0, 0, 0)); cvPutText(img, str, point, font, color); -}; +} #define ASD_RGB_SET_PIXEL(pointer, r, g, b) { (*pointer) = (unsigned char)b; (*(pointer+1)) = (unsigned char)g; (*(pointer+2)) = (unsigned char)r; } @@ -336,7 +336,7 @@ static void displayBuffer(IplImage *rgbDestImage, IplImage *buffer, int rValue, destY = 0; destX += dx; } -}; +} int main(int argc, char** argv ) { diff --git a/samples/cpp/calibration_artificial.cpp b/samples/cpp/calibration_artificial.cpp index c22cb528f..7d443c1db 100644 --- a/samples/cpp/calibration_artificial.cpp +++ b/samples/cpp/calibration_artificial.cpp @@ -46,7 +46,7 @@ private: Point3f generateChessBoardCenter(const Mat& camMat, const Size& imgSize) const; Mat rvec, tvec; }; -}; +} diff --git a/samples/cpp/tutorial_code/ImgProc/Threshold.cpp b/samples/cpp/tutorial_code/ImgProc/Threshold.cpp index d98cc1182..96d5686a8 100644 --- a/samples/cpp/tutorial_code/ImgProc/Threshold.cpp +++ b/samples/cpp/tutorial_code/ImgProc/Threshold.cpp @@ -14,7 +14,7 @@ using namespace cv; /// Global variables int threshold_value = 0; -int threshold_type = 3;; +int threshold_type = 3; int const max_value = 255; int const max_type = 4; int const max_BINARY_value = 255; From bf4994554df10e9c070da5490b5c274fa152fe84 Mon Sep 17 00:00:00 2001 From: Nghia Ho Date: Thu, 9 Jan 2014 21:04:17 +1100 Subject: [PATCH 040/295] Removed unecessary initialisation of Mat centers. --- samples/cpp/kmeans.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/cpp/kmeans.cpp b/samples/cpp/kmeans.cpp index b74211205..19e998379 100644 --- a/samples/cpp/kmeans.cpp +++ b/samples/cpp/kmeans.cpp @@ -36,7 +36,7 @@ int main( int /*argc*/, char** /*argv*/ ) Mat points(sampleCount, 2, CV_32F), labels; clusterCount = MIN(clusterCount, sampleCount); - Mat centers(clusterCount, 1, points.type()); + Mat centers; /* generate random sample from multigaussian distribution */ for( k = 0; k < clusterCount; k++ ) From ae795e5797ba3b85812d56edc7fe497d05cc2d77 Mon Sep 17 00:00:00 2001 From: ComFreek Date: Thu, 9 Jan 2014 17:24:20 +0100 Subject: [PATCH 041/295] Corrected package name in tutorial See also #2101 --- doc/tutorials/introduction/linux_install/linux_install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorials/introduction/linux_install/linux_install.rst b/doc/tutorials/introduction/linux_install/linux_install.rst index 1e02b64c9..8e1409650 100644 --- a/doc/tutorials/introduction/linux_install/linux_install.rst +++ b/doc/tutorials/introduction/linux_install/linux_install.rst @@ -16,7 +16,7 @@ Required Packages * CMake 2.6 or higher; * Git; * GTK+2.x or higher, including headers (libgtk2.0-dev); - * pkgconfig; + * pkg-config; * Python 2.6 or later and Numpy 1.5 or later with developer packages (python-dev, python-numpy); * ffmpeg or libav development packages: libavcodec-dev, libavformat-dev, libswscale-dev; * [optional] libdc1394 2.x; From 2c0e24e9483bc368eadb43d9ab397c935b8960e9 Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Fri, 10 Jan 2014 00:08:15 +0400 Subject: [PATCH 042/295] adding Haar & LBP cascades perf test using UMat, removing old incomplete test --- .../objdetect/perf/opencl/perf_cascades.cpp | 53 ++++++++++++++++++ .../objdetect/perf/perf_cascadeclassifier.cpp | 56 ------------------- 2 files changed, 53 insertions(+), 56 deletions(-) create mode 100644 modules/objdetect/perf/opencl/perf_cascades.cpp delete mode 100644 modules/objdetect/perf/perf_cascadeclassifier.cpp diff --git a/modules/objdetect/perf/opencl/perf_cascades.cpp b/modules/objdetect/perf/opencl/perf_cascades.cpp new file mode 100644 index 000000000..4af2428f2 --- /dev/null +++ b/modules/objdetect/perf/opencl/perf_cascades.cpp @@ -0,0 +1,53 @@ +#include "perf_precomp.hpp" +#include + +using namespace std; +using namespace cv; +using namespace perf; +using std::tr1::make_tuple; +using std::tr1::get; + +typedef std::tr1::tuple Cascade_Image_MinSize_t; +typedef perf::TestBaseWithParam Cascade_Image_MinSize; + +PERF_TEST_P( Cascade_Image_MinSize, CascadeClassifier_UMat, + testing::Combine( + testing::Values( string("cv/cascadeandhog/cascades/haarcascade_frontalface_alt.xml"), + string("cv/cascadeandhog/cascades/lbpcascade_frontalface.xml") ), + testing::Values( string("cv/shared/lena.png"), + string("cv/cascadeandhog/images/bttf301.png"), + string("cv/cascadeandhog/images/class57.png") ), + testing::Values(30, 64, 90) ) ) +{ + const string cascasePath = get<0>(GetParam()); + const string imagePath = get<1>(GetParam()); + int min_size = get<2>(GetParam()); + Size minSize(min_size, min_size); + + CascadeClassifier cc( getDataPath(cascasePath) ); + if (cc.empty()) + FAIL() << "Can't load cascade file: " << getDataPath(cascasePath); + + Mat img = imread(getDataPath(imagePath), IMREAD_GRAYSCALE); + if (img.empty()) + FAIL() << "Can't load source image: " << getDataPath(imagePath); + + vector faces; + + equalizeHist(img, img); + declare.in(img).time(60); + + UMat uimg = img.getUMat(ACCESS_READ); + + while(next()) + { + faces.clear(); + + startTimer(); + cc.detectMultiScale(uimg, faces, 1.1, 3, 0, minSize); + stopTimer(); + } + + sort(faces.begin(), faces.end(), comparators::RectLess()); + SANITY_CHECK(faces, min_size/5); +} diff --git a/modules/objdetect/perf/perf_cascadeclassifier.cpp b/modules/objdetect/perf/perf_cascadeclassifier.cpp deleted file mode 100644 index cb5c0afe2..000000000 --- a/modules/objdetect/perf/perf_cascadeclassifier.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "perf_precomp.hpp" -#include - -using namespace std; -using namespace cv; -using namespace perf; -using std::tr1::make_tuple; -using std::tr1::get; - -typedef std::tr1::tuple ImageName_MinSize_t; -typedef perf::TestBaseWithParam ImageName_MinSize; - -PERF_TEST_P(ImageName_MinSize, CascadeClassifierLBPFrontalFace, - testing::Combine(testing::Values( std::string("cv/shared/lena.png"), - std::string("cv/shared/1_itseez-0000289.png"), - std::string("cv/shared/1_itseez-0000492.png"), - std::string("cv/shared/1_itseez-0000573.png")), - testing::Values(24, 30, 40, 50, 60, 70, 80, 90) - ) - ) -{ - const string filename = get<0>(GetParam()); - int min_size = get<1>(GetParam()); - Size minSize(min_size, min_size); - - CascadeClassifier cc(getDataPath("cv/cascadeandhog/cascades/lbpcascade_frontalface.xml")); - if (cc.empty()) - FAIL() << "Can't load cascade file"; - - Mat img = imread(getDataPath(filename), 0); - if (img.empty()) - FAIL() << "Can't load source image"; - - vector faces; - - equalizeHist(img, img); - declare.in(img); - - while(next()) - { - faces.clear(); - - startTimer(); - cc.detectMultiScale(img, faces, 1.1, 3, 0, minSize); - stopTimer(); - } - // for some reason OpenCL version detects the face, which CPU version does not detect, we just remove it - // TODO better solution: implement smart way of comparing two set of rectangles - if( filename == "cv/shared/1_itseez-0000492.png" && faces.size() == (size_t)3 ) - { - faces.erase(faces.begin()); - } - - std::sort(faces.begin(), faces.end(), comparators::RectLess()); - SANITY_CHECK(faces, 3.001 * faces.size()); -} From 4d28e8243c6fe78eeeef0a4f59d72c6812578f29 Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Fri, 10 Jan 2014 00:14:48 +0400 Subject: [PATCH 043/295] 'master'-like Haar perf test --- modules/ocl/perf/perf_haar.cpp | 50 ++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/modules/ocl/perf/perf_haar.cpp b/modules/ocl/perf/perf_haar.cpp index b7a1dd1a4..a6c107fe4 100644 --- a/modules/ocl/perf/perf_haar.cpp +++ b/modules/ocl/perf/perf_haar.cpp @@ -83,3 +83,53 @@ PERF_TEST(HaarFixture, Haar) else OCL_PERF_ELSE } + +using namespace std; +using namespace cv; +using namespace perf; +using std::tr1::make_tuple; +using std::tr1::get; + +typedef std::tr1::tuple Cascade_Image_MinSize_t; +typedef perf::TestBaseWithParam Cascade_Image_MinSize; + +PERF_TEST_P( Cascade_Image_MinSize, CascadeClassifier_UMat, + testing::Combine( + testing::Values( string("cv/cascadeandhog/cascades/haarcascade_frontalface_alt.xml") ), + testing::Values( string("cv/shared/lena.png"), + string("cv/cascadeandhog/images/bttf301.png"), + string("cv/cascadeandhog/images/class57.png") ), + testing::Values(30, 64, 90) ) ) +{ + const string cascasePath = get<0>(GetParam()); + const string imagePath = get<1>(GetParam()); + const int min_size = get<2>(GetParam()); + Size minSize(min_size, min_size); + + ocl::OclCascadeClassifier cc; + if (!cc.load( getDataPath(cascasePath) )) + FAIL() << "Can't load cascade file: " << getDataPath(cascasePath); + + Mat img = imread(getDataPath(imagePath), IMREAD_GRAYSCALE); + if (img.empty()) + FAIL() << "Can't load source image: " << getDataPath(imagePath); + + vector faces; + + equalizeHist(img, img); + declare.in(img).time(60); + + ocl::oclMat uimg(img); + + while(next()) + { + faces.clear(); + + startTimer(); + cc.detectMultiScale(uimg, faces, 1.1, 3, 0, minSize); + stopTimer(); + } + + //sort(faces.begin(), faces.end(), comparators::RectLess()); + SANITY_CHECK_NOTHING();//(faces, min_size/5); +} From f197d8b91c1b89037aaf81bfeb8217c0a7aa0f9c Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 10 Jan 2014 18:59:06 +0400 Subject: [PATCH 044/295] updated .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 46d3499e5..0d0dcf8b0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.autosave *.pyc *.user +*~ .*.swp .DS_Store .sw[a-z] From a7821c60e55be5968aec41f31349f58db789671e Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Mon, 13 Jan 2014 11:20:17 +0400 Subject: [PATCH 045/295] refactoring the test as it should be in 2.4 --- modules/ocl/perf/perf_haar.cpp | 52 +++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/modules/ocl/perf/perf_haar.cpp b/modules/ocl/perf/perf_haar.cpp index a6c107fe4..2fe01ee6e 100644 --- a/modules/ocl/perf/perf_haar.cpp +++ b/modules/ocl/perf/perf_haar.cpp @@ -105,31 +105,45 @@ PERF_TEST_P( Cascade_Image_MinSize, CascadeClassifier_UMat, const string imagePath = get<1>(GetParam()); const int min_size = get<2>(GetParam()); Size minSize(min_size, min_size); - - ocl::OclCascadeClassifier cc; - if (!cc.load( getDataPath(cascasePath) )) - FAIL() << "Can't load cascade file: " << getDataPath(cascasePath); - - Mat img = imread(getDataPath(imagePath), IMREAD_GRAYSCALE); - if (img.empty()) - FAIL() << "Can't load source image: " << getDataPath(imagePath); - vector faces; + Mat img = imread(getDataPath(imagePath), IMREAD_GRAYSCALE); + ASSERT_TRUE(!img.empty()) << "Can't load source image: " << getDataPath(imagePath); equalizeHist(img, img); - declare.in(img).time(60); + declare.in(img); - ocl::oclMat uimg(img); - - while(next()) + if (RUN_PLAIN_IMPL) { - faces.clear(); + CascadeClassifier cc; + ASSERT_TRUE(cc.load(getDataPath(cascasePath))) << "Can't load cascade file: " << getDataPath(cascasePath); - startTimer(); - cc.detectMultiScale(uimg, faces, 1.1, 3, 0, minSize); - stopTimer(); + while (next()) + { + faces.clear(); + + startTimer(); + cc.detectMultiScale(img, faces, 1.1, 3, 0, minSize); + stopTimer(); + } } + else if (RUN_OCL_IMPL) + { + ocl::oclMat uimg(img); + ocl::OclCascadeClassifier cc; + ASSERT_TRUE(cc.load(getDataPath(cascasePath))) << "Can't load cascade file: " << getDataPath(cascasePath); - //sort(faces.begin(), faces.end(), comparators::RectLess()); - SANITY_CHECK_NOTHING();//(faces, min_size/5); + while (next()) + { + faces.clear(); + + startTimer(); + cc.detectMultiScale(uimg, faces, 1.1, 3, 0, minSize); + stopTimer(); + } + } + else + OCL_PERF_ELSE + + //sort(faces.begin(), faces.end(), comparators::RectLess()); + SANITY_CHECK_NOTHING();//(faces, min_size/5); } From 6fbaff6d837a1f297d4e281e15aae8b7a72a59ed Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 13 Jan 2014 13:09:58 +0400 Subject: [PATCH 046/295] added perf tests for T-API warp operations --- modules/imgproc/perf/opencl/perf_imgwarp.cpp | 207 +++++++++++++++++++ modules/imgproc/src/opencl/resize.cl | 1 - 2 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 modules/imgproc/perf/opencl/perf_imgwarp.cpp diff --git a/modules/imgproc/perf/opencl/perf_imgwarp.cpp b/modules/imgproc/perf/opencl/perf_imgwarp.cpp new file mode 100644 index 000000000..a2fce368e --- /dev/null +++ b/modules/imgproc/perf/opencl/perf_imgwarp.cpp @@ -0,0 +1,207 @@ +/*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/ts/ocl_perf.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +///////////// WarpAffine //////////////////////// + +CV_ENUM(InterType, INTER_NEAREST, INTER_LINEAR) + +typedef tuple WarpAffineParams; +typedef TestBaseWithParam WarpAffineFixture; + +OCL_PERF_TEST_P(WarpAffineFixture, WarpAffine, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, InterType::all())) +{ + static const double coeffs[2][3] = + { + { cos(CV_PI / 6), -sin(CV_PI / 6), 100.0 }, + { sin(CV_PI / 6), cos(CV_PI / 6) , -100.0 } + }; + Mat M(2, 3, CV_64F, (void *)coeffs); + + const WarpAffineParams params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), interpolation = get<2>(params); + const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4; + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type), dst(srcSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::warpAffine(src, dst, M, srcSize, interpolation); + + SANITY_CHECK(dst, eps); +} + +///////////// WarpPerspective //////////////////////// + +typedef WarpAffineParams WarpPerspectiveParams; +typedef TestBaseWithParam WarpPerspectiveFixture; + +OCL_PERF_TEST_P(WarpPerspectiveFixture, WarpPerspective, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, InterType::all())) +{ + static const double coeffs[3][3] = + { + {cos(CV_PI / 6), -sin(CV_PI / 6), 100.0}, + {sin(CV_PI / 6), cos(CV_PI / 6), -100.0}, + {0.0, 0.0, 1.0} + }; + Mat M(3, 3, CV_64F, (void *)coeffs); + + const WarpPerspectiveParams params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), interpolation = get<2>(params); + const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4; + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type), dst(srcSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::warpPerspective(src, dst, M, srcSize, interpolation); + + SANITY_CHECK(dst, eps); +} + +///////////// Resize //////////////////////// + +typedef tuple ResizeParams; +typedef TestBaseWithParam ResizeFixture; + +OCL_PERF_TEST_P(ResizeFixture, Resize, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, + InterType::all(), ::testing::Values(0.5, 2.0))) +{ + const ResizeParams params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), interType = get<2>(params); + double scale = get<3>(params); + const Size dstSize(cvRound(srcSize.width * scale), cvRound(srcSize.height * scale)); + const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4; + + checkDeviceMaxMemoryAllocSize(srcSize, type); + checkDeviceMaxMemoryAllocSize(dstSize, type); + + UMat src(srcSize, type), dst(dstSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::resize(src, dst, Size(), scale, scale, interType); + + SANITY_CHECK(dst, eps); +} + +typedef tuple ResizeAreaParams; +typedef TestBaseWithParam ResizeAreaFixture; + +OCL_PERF_TEST_P(ResizeAreaFixture, Resize, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, ::testing::Values(0.3, 0.5, 0.6))) +{ + const ResizeAreaParams params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params); + double scale = get<2>(params); + const Size dstSize(cvRound(srcSize.width * scale), cvRound(srcSize.height * scale)); + const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4; + + checkDeviceMaxMemoryAllocSize(srcSize, type); + checkDeviceMaxMemoryAllocSize(dstSize, type); + + UMat src(srcSize, type), dst(dstSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::resize(src, dst, Size(), scale, scale, cv::INTER_AREA); + + SANITY_CHECK(dst, eps); +} + +///////////// Remap //////////////////////// + +typedef tuple RemapParams; +typedef TestBaseWithParam RemapFixture; + +OCL_PERF_TEST_P(RemapFixture, Remap, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, InterType::all())) +{ + const RemapParams params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), interpolation = get<2>(params), borderMode = BORDER_CONSTANT; + const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4; + + UMat src(srcSize, type), dst(srcSize, type); + UMat xmap(srcSize, CV_32FC1), ymap(srcSize, CV_32FC1); + + { + Mat _xmap = xmap.getMat(ACCESS_WRITE), _ymap = ymap.getMat(ACCESS_WRITE); + for (int i = 0; i < srcSize.height; ++i) + { + float * const xmap_row = _xmap.ptr(i); + float * const ymap_row = _ymap.ptr(i); + + for (int j = 0; j < srcSize.width; ++j) + { + xmap_row[j] = (j - srcSize.width * 0.5f) * 0.75f + srcSize.width * 0.5f; + ymap_row[j] = (i - srcSize.height * 0.5f) * 0.75f + srcSize.height * 0.5f; + } + } + } + declare.in(src, WARMUP_RNG).in(xmap, ymap, WARMUP_READ).out(dst); + + OCL_TEST_CYCLE() cv::remap(src, dst, xmap, ymap, interpolation, borderMode); + + SANITY_CHECK(dst, eps); +} + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL diff --git a/modules/imgproc/src/opencl/resize.cl b/modules/imgproc/src/opencl/resize.cl index 92491615e..ecab2faa5 100644 --- a/modules/imgproc/src/opencl/resize.cl +++ b/modules/imgproc/src/opencl/resize.cl @@ -50,7 +50,6 @@ #define INTER_RESIZE_COEF_BITS 11 #define INTER_RESIZE_COEF_SCALE (1 << INTER_RESIZE_COEF_BITS) #define CAST_BITS (INTER_RESIZE_COEF_BITS << 1) -#define CAST_SCALE (1.0f/(1< Date: Mon, 13 Jan 2014 11:41:54 +0400 Subject: [PATCH 047/295] Added throwing exception when saving untrained SVM model --- modules/ml/src/svm.cpp | 18 ++++++++++++------ modules/ml/test/test_save_load.cpp | 8 ++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/modules/ml/src/svm.cpp b/modules/ml/src/svm.cpp index 674365bb3..f15880521 100644 --- a/modules/ml/src/svm.cpp +++ b/modules/ml/src/svm.cpp @@ -2298,14 +2298,24 @@ void CvSVM::write_params( CvFileStorage* fs ) const } +static bool isSvmModelApplicable(int sv_total, int var_all, int var_count, int class_count) +{ + return (sv_total > 0 && var_count > 0 && var_count <= var_all && class_count >= 0); +} + + void CvSVM::write( CvFileStorage* fs, const char* name ) const { CV_FUNCNAME( "CvSVM::write" ); __BEGIN__; - int i, var_count = get_var_count(), df_count, class_count; + int i, var_count = get_var_count(), df_count; + int class_count = class_labels ? class_labels->cols : + params.svm_type == CvSVM::ONE_CLASS ? 1 : 0; const CvSVMDecisionFunc* df = decision_func; + if( !isSvmModelApplicable(sv_total, var_all, var_count, class_count) ) + CV_ERROR( CV_StsParseError, "SVM model data is invalid, check sv_count, var_* and class_count tags" ); cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_ML_SVM ); @@ -2314,9 +2324,6 @@ void CvSVM::write( CvFileStorage* fs, const char* name ) const cvWriteInt( fs, "var_all", var_all ); cvWriteInt( fs, "var_count", var_count ); - class_count = class_labels ? class_labels->cols : - params.svm_type == CvSVM::ONE_CLASS ? 1 : 0; - if( class_count ) { cvWriteInt( fs, "class_count", class_count ); @@ -2454,7 +2461,6 @@ void CvSVM::read_params( CvFileStorage* fs, CvFileNode* svm_node ) __END__; } - void CvSVM::read( CvFileStorage* fs, CvFileNode* svm_node ) { const double not_found_dbl = DBL_MAX; @@ -2483,7 +2489,7 @@ void CvSVM::read( CvFileStorage* fs, CvFileNode* svm_node ) var_count = cvReadIntByName( fs, svm_node, "var_count", var_all ); class_count = cvReadIntByName( fs, svm_node, "class_count", 0 ); - if( sv_total <= 0 || var_all <= 0 || var_count <= 0 || var_count > var_all || class_count < 0 ) + if( !isSvmModelApplicable(sv_total, var_all, var_count, class_count) ) CV_ERROR( CV_StsParseError, "SVM model data is invalid, check sv_count, var_* and class_count tags" ); CV_CALL( class_labels = (CvMat*)cvReadByName( fs, svm_node, "class_labels" )); diff --git a/modules/ml/test/test_save_load.cpp b/modules/ml/test/test_save_load.cpp index 9fd31b9f2..7300185b4 100644 --- a/modules/ml/test/test_save_load.cpp +++ b/modules/ml/test/test_save_load.cpp @@ -155,6 +155,14 @@ TEST(ML_RTrees, save_load) { CV_SLMLTest test( CV_RTREES ); test.safe_run(); } TEST(ML_ERTrees, save_load) { CV_SLMLTest test( CV_ERTREES ); test.safe_run(); } +TEST(ML_SVM, throw_exception_when_save_untrained_model) +{ + SVM svm; + string filename = tempfile("svm.xml"); + ASSERT_THROW(svm.save(filename.c_str()), Exception); + remove(filename.c_str()); +} + TEST(DISABLED_ML_SVM, linear_save_load) { CvSVM svm1, svm2, svm3; From 4bd4c8d12abfd6dbd5fedad477f71a34be00c0d1 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 13 Jan 2014 14:06:15 +0400 Subject: [PATCH 048/295] added perf tests for cv::blendLinear --- modules/imgproc/perf/opencl/perf_blend.cpp | 82 ++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 modules/imgproc/perf/opencl/perf_blend.cpp diff --git a/modules/imgproc/perf/opencl/perf_blend.cpp b/modules/imgproc/perf/opencl/perf_blend.cpp new file mode 100644 index 000000000..f595069bd --- /dev/null +++ b/modules/imgproc/perf/opencl/perf_blend.cpp @@ -0,0 +1,82 @@ +/*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/ts/ocl_perf.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +///////////// BlendLinear //////////////////////// + +typedef Size_MatType BlendLinearFixture; + +OCL_PERF_TEST_P(BlendLinearFixture, BlendLinear, ::testing::Combine(OCL_TEST_SIZES, OCL_PERF_ENUM(CV_32FC1, CV_32FC4))) +{ + Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int srcType = get<1>(params); + const double eps = CV_MAT_DEPTH(srcType) <= CV_32S ? 1.0 : 0.2; + + checkDeviceMaxMemoryAllocSize(srcSize, srcType); + + UMat src1(srcSize, srcType), src2(srcSize, srcType), dst(srcSize, srcType); + UMat weights1(srcSize, CV_32FC1), weights2(srcSize, CV_32FC1); + + declare.in(src1, src2, WARMUP_RNG).in(weights1, weights2, WARMUP_READ).out(dst); + randu(weights1, 0, 1); + randu(weights2, 0, 1); + + OCL_TEST_CYCLE() cv::blendLinear(src1, src2, weights1, weights2, dst); + + SANITY_CHECK(dst, eps); +} + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL From e76d51511ed27517210d2e5c28c439716ebbc4da Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 13 Jan 2014 14:14:22 +0400 Subject: [PATCH 049/295] added perf test for cv::cvtColor, pyr operations --- modules/imgproc/perf/opencl/perf_color.cpp | 104 +++++++++++++++++++ modules/imgproc/perf/opencl/perf_imgwarp.cpp | 2 + modules/imgproc/perf/opencl/perf_pyramid.cpp | 104 +++++++++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 modules/imgproc/perf/opencl/perf_color.cpp create mode 100644 modules/imgproc/perf/opencl/perf_pyramid.cpp diff --git a/modules/imgproc/perf/opencl/perf_color.cpp b/modules/imgproc/perf/opencl/perf_color.cpp new file mode 100644 index 000000000..1c6947082 --- /dev/null +++ b/modules/imgproc/perf/opencl/perf_color.cpp @@ -0,0 +1,104 @@ +/*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/ts/ocl_perf.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +using std::tr1::make_tuple; + +///////////// cvtColor//////////////////////// + +CV_ENUM(ConversionTypes, COLOR_RGB2GRAY, COLOR_RGB2BGR, COLOR_RGB2YUV, COLOR_YUV2RGB, COLOR_RGB2YCrCb, + COLOR_YCrCb2RGB, COLOR_RGB2XYZ, COLOR_XYZ2RGB, COLOR_RGB2HSV, COLOR_HSV2RGB, COLOR_RGB2HLS, + COLOR_HLS2RGB, COLOR_BGR5652BGR, COLOR_BGR2BGR565, COLOR_RGBA2mRGBA, COLOR_mRGBA2RGBA, COLOR_YUV2RGB_NV12) + +typedef tuple > CvtColorParams; +typedef TestBaseWithParam CvtColorFixture; + +OCL_PERF_TEST_P(CvtColorFixture, CvtColor, testing::Combine( + OCL_TEST_SIZES, + testing::Values( + make_tuple(ConversionTypes(COLOR_RGB2GRAY), 3, 1), + make_tuple(ConversionTypes(COLOR_RGB2BGR), 3, 3), + make_tuple(ConversionTypes(COLOR_RGB2YUV), 3, 3), + make_tuple(ConversionTypes(COLOR_YUV2RGB), 3, 3), + make_tuple(ConversionTypes(COLOR_RGB2YCrCb), 3, 3), + make_tuple(ConversionTypes(COLOR_YCrCb2RGB), 3, 3), + make_tuple(ConversionTypes(COLOR_RGB2XYZ), 3, 3), + make_tuple(ConversionTypes(COLOR_XYZ2RGB), 3, 3), + make_tuple(ConversionTypes(COLOR_RGB2HSV), 3, 3), + make_tuple(ConversionTypes(COLOR_HSV2RGB), 3, 3), + make_tuple(ConversionTypes(COLOR_RGB2HLS), 3, 3), + make_tuple(ConversionTypes(COLOR_HLS2RGB), 3, 3), + make_tuple(ConversionTypes(COLOR_BGR5652BGR), 2, 3), + make_tuple(ConversionTypes(COLOR_BGR2BGR565), 3, 2), + make_tuple(ConversionTypes(COLOR_RGBA2mRGBA), 4, 4), + make_tuple(ConversionTypes(COLOR_mRGBA2RGBA), 4, 4), + make_tuple(ConversionTypes(COLOR_YUV2RGB_NV12), 1, 3) + ))) +{ + CvtColorParams params = GetParam(); + const Size srcSize = get<0>(params); + const tuple conversionParams = get<1>(params); + const int code = get<0>(conversionParams), scn = get<1>(conversionParams), + dcn = get<2>(conversionParams); + + UMat src(srcSize, CV_8UC(scn)), dst(srcSize, CV_8UC(scn)); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::cvtColor(src, dst, code, dcn); + + SANITY_CHECK(dst, 1); +} + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL diff --git a/modules/imgproc/perf/opencl/perf_imgwarp.cpp b/modules/imgproc/perf/opencl/perf_imgwarp.cpp index a2fce368e..f309d283c 100644 --- a/modules/imgproc/perf/opencl/perf_imgwarp.cpp +++ b/modules/imgproc/perf/opencl/perf_imgwarp.cpp @@ -178,6 +178,8 @@ OCL_PERF_TEST_P(RemapFixture, Remap, const int type = get<1>(params), interpolation = get<2>(params), borderMode = BORDER_CONSTANT; const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-4; + checkDeviceMaxMemoryAllocSize(srcSize, type); + UMat src(srcSize, type), dst(srcSize, type); UMat xmap(srcSize, CV_32FC1), ymap(srcSize, CV_32FC1); diff --git a/modules/imgproc/perf/opencl/perf_pyramid.cpp b/modules/imgproc/perf/opencl/perf_pyramid.cpp new file mode 100644 index 000000000..c81ff1861 --- /dev/null +++ b/modules/imgproc/perf/opencl/perf_pyramid.cpp @@ -0,0 +1,104 @@ +/*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/ts/ocl_perf.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +///////////// PyrDown ////////////////////// + +typedef Size_MatType PyrDownFixture; + +OCL_PERF_TEST_P(PyrDownFixture, PyrDown, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params); + const Size dstSize((srcSize.height + 1) >> 1, (srcSize.width + 1) >> 1); + const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-5; + + checkDeviceMaxMemoryAllocSize(srcSize, type); + checkDeviceMaxMemoryAllocSize(dstSize, type); + + UMat src(srcSize, type), dst(dstSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::pyrDown(src, dst); + + SANITY_CHECK(dst, eps); +} + +///////////// PyrUp //////////////////////// + +typedef Size_MatType PyrUpFixture; + +OCL_PERF_TEST_P(PyrUpFixture, PyrUp, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params); + const Size dstSize(srcSize.height << 1, srcSize.width << 1); + const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-5; + + checkDeviceMaxMemoryAllocSize(srcSize, type); + checkDeviceMaxMemoryAllocSize(dstSize, type); + + UMat src(srcSize, type), dst(dstSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::pyrDown(src, dst); + + SANITY_CHECK(dst, eps); +} + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL From 04ae46e21c3c2df807764313b70a6e87bb2b082e Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 13 Jan 2014 15:01:52 +0400 Subject: [PATCH 050/295] added perf tests to some imgproc functions --- modules/imgproc/perf/opencl/perf_imgproc.cpp | 202 +++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 modules/imgproc/perf/opencl/perf_imgproc.cpp diff --git a/modules/imgproc/perf/opencl/perf_imgproc.cpp b/modules/imgproc/perf/opencl/perf_imgproc.cpp new file mode 100644 index 000000000..117fe1ad6 --- /dev/null +++ b/modules/imgproc/perf/opencl/perf_imgproc.cpp @@ -0,0 +1,202 @@ +/*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/ts/ocl_perf.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +///////////// equalizeHist //////////////////////// + +typedef TestBaseWithParam EqualizeHistFixture; + +OCL_PERF_TEST_P(EqualizeHistFixture, EqualizeHist, OCL_TEST_SIZES) +{ + const Size srcSize = GetParam(); + const double eps = 1; + + UMat src(srcSize, CV_8UC1), dst(srcSize, CV_8UC1); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::equalizeHist(src, dst); + + SANITY_CHECK(dst, eps); +} + +/////////// CopyMakeBorder ////////////////////// + +CV_ENUM(Border, BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT, BORDER_WRAP, BORDER_REFLECT_101) + +typedef tuple CopyMakeBorderParamType; +typedef TestBaseWithParam CopyMakeBorderFixture; + +OCL_PERF_TEST_P(CopyMakeBorderFixture, CopyMakeBorder, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, Border::all())) +{ + const CopyMakeBorderParamType params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), borderType = get<2>(params); + + UMat src(srcSize, type), dst; + const Size dstSize = srcSize + Size(12, 12); + dst.create(dstSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::copyMakeBorder(src, dst, 7, 5, 5, 7, borderType, cv::Scalar(1.0)); + + SANITY_CHECK(dst); +} + +///////////// CornerMinEigenVal //////////////////////// + +typedef Size_MatType CornerMinEigenValFixture; + +OCL_PERF_TEST_P(CornerMinEigenValFixture, CornerMinEigenVal, + ::testing::Combine(OCL_TEST_SIZES, OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), borderType = BORDER_REFLECT; + const int blockSize = 7, apertureSize = 1 + 2 * 3; + + UMat src(srcSize, type), dst(srcSize, CV_32FC1); + declare.in(src, WARMUP_RNG).out(dst); + + const int depth = CV_MAT_DEPTH(type); + const ERROR_TYPE errorType = depth == CV_8U ? ERROR_ABSOLUTE : ERROR_RELATIVE; + + OCL_TEST_CYCLE() cv::cornerMinEigenVal(src, dst, blockSize, apertureSize, borderType); + + SANITY_CHECK(dst, 1e-6, errorType); +} + +///////////// CornerHarris //////////////////////// + +typedef Size_MatType CornerHarrisFixture; + +OCL_PERF_TEST_P(CornerHarrisFixture, CornerHarris, + ::testing::Combine(OCL_TEST_SIZES, OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), borderType = BORDER_REFLECT; + + UMat src(srcSize, type), dst(srcSize, CV_32FC1); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::cornerHarris(src, dst, 5, 7, 0.1, borderType); + + SANITY_CHECK(dst, 3e-5); +} + +///////////// Integral //////////////////////// + +typedef tuple IntegralParams; +typedef TestBaseWithParam IntegralFixture; + +OCL_PERF_TEST_P(IntegralFixture, Integral1, ::testing::Combine(OCL_TEST_SIZES, OCL_PERF_ENUM(CV_32F, CV_64F))) +{ + const IntegralParams params = GetParam(); + const Size srcSize = get<0>(params); + const int ddepth = get<1>(params); + + UMat src(srcSize, CV_8UC1), dst(srcSize, ddepth); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::integral(src, dst, ddepth); + + SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); +} + +///////////// Threshold //////////////////////// + +CV_ENUM(ThreshType, THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO_INV) + +typedef tuple ThreshParams; +typedef TestBaseWithParam ThreshFixture; + +OCL_PERF_TEST_P(ThreshFixture, Threshold, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, ThreshType::all())) +{ + const ThreshParams params = GetParam(); + const Size srcSize = get<0>(params); + const int srcType = get<1>(params); + const int threshType = get<2>(params); + const double maxValue = 220.0, threshold = 50; + + UMat src(srcSize, srcType), dst(srcSize, srcType); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::threshold(src, dst, threshold, maxValue, threshType); + + SANITY_CHECK(dst); +} + +///////////// CLAHE //////////////////////// + +typedef TestBaseWithParam CLAHEFixture; + +OCL_PERF_TEST_P(CLAHEFixture, CLAHE, OCL_TEST_SIZES) +{ + const Size srcSize = GetParam(); + + UMat src(srcSize, CV_8UC1), dst(srcSize, CV_8UC1); + const double clipLimit = 40.0; + declare.in(src, WARMUP_RNG).out(dst); + + cv::Ptr clahe = cv::createCLAHE(clipLimit); + OCL_TEST_CYCLE() clahe->apply(src, dst); + + SANITY_CHECK(dst); +} + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL + From f61597dce845732e7adef4eafa654dc6530f3348 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 13 Jan 2014 15:26:50 +0400 Subject: [PATCH 051/295] added perf tests for filters --- modules/imgproc/perf/opencl/perf_filters.cpp | 231 +++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 modules/imgproc/perf/opencl/perf_filters.cpp diff --git a/modules/imgproc/perf/opencl/perf_filters.cpp b/modules/imgproc/perf/opencl/perf_filters.cpp new file mode 100644 index 000000000..93d0f2faa --- /dev/null +++ b/modules/imgproc/perf/opencl/perf_filters.cpp @@ -0,0 +1,231 @@ +/*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/ts/ocl_perf.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +///////////// Blur //////////////////////// + +typedef Size_MatType BlurFixture; + +OCL_PERF_TEST_P(BlurFixture, Blur, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params), ksize(3, 3); + const int type = get<1>(params), bordertype = BORDER_CONSTANT; + const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-5; + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type), dst(srcSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::blur(src, dst, ksize, Point(-1, -1), bordertype); + + SANITY_CHECK(dst, eps); +} + +///////////// Laplacian//////////////////////// + +typedef Size_MatType LaplacianFixture; + +OCL_PERF_TEST_P(LaplacianFixture, Laplacian, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), ksize = 3; + const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-5; + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type), dst(srcSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::Laplacian(src, dst, -1, ksize, 1); + + SANITY_CHECK(dst, eps); +} + +///////////// Erode //////////////////// + +typedef Size_MatType ErodeFixture; + +OCL_PERF_TEST_P(ErodeFixture, Erode, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), ksize = 3; + const Mat ker = getStructuringElement(MORPH_RECT, Size(ksize, ksize)); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type), dst(srcSize, type); + declare.in(src, WARMUP_RNG).out(dst).in(ker); + + OCL_TEST_CYCLE() cv::erode(src, dst, ker); + + SANITY_CHECK(dst); +} + +///////////// Sobel //////////////////////// + +typedef Size_MatType SobelFixture; + +OCL_PERF_TEST_P(SobelFixture, Sobel, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), dx = 1, dy = 1; + + checkDeviceMaxMemoryAllocSize(srcSize, type, sizeof(float) * 2); + + UMat src(srcSize, type), dst(srcSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::Sobel(src, dst, -1, dx, dy); + + SANITY_CHECK(dst); +} + +///////////// Scharr //////////////////////// + +typedef Size_MatType ScharrFixture; + +OCL_PERF_TEST_P(ScharrFixture, Scharr, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), dx = 1, dy = 0; + const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-5; + + checkDeviceMaxMemoryAllocSize(srcSize, type, sizeof(float) * 2); + + UMat src(srcSize, type), dst(srcSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::Scharr(src, dst, -1, dx, dy); + + SANITY_CHECK(dst, eps); +} + +///////////// GaussianBlur //////////////////////// + +typedef Size_MatType GaussianBlurFixture; + +OCL_PERF_TEST_P(GaussianBlurFixture, GaussianBlur, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), ksize = 7; + const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 + DBL_EPSILON : 3e-4; + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type), dst(srcSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::GaussianBlur(src, dst, Size(ksize, ksize), 0); + + SANITY_CHECK(dst, eps); +} + +///////////// Filter2D //////////////////////// + +typedef Size_MatType Filter2DFixture; + +OCL_PERF_TEST_P(Filter2DFixture, Filter2D, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), ksize = 3; + const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-5; + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type), dst(srcSize, type), kernel(ksize, ksize, CV_32SC1); + declare.in(src, WARMUP_RNG).in(kernel).out(dst); + randu(kernel, -3.0, 3.0); + + OCL_TEST_CYCLE() cv::filter2D(src, dst, -1, kernel); + + SANITY_CHECK(dst, eps); +} + +///////////// Bilateral //////////////////////// + +typedef TestBaseWithParam BilateralFixture; + +OCL_PERF_TEST_P(BilateralFixture, Bilateral, OCL_TEST_SIZES) +{ + const Size srcSize = GetParam(); + const int d = 7; + const double sigmacolor = 50.0, sigmaspace = 50.0; + + checkDeviceMaxMemoryAllocSize(srcSize, CV_8UC1); + + UMat src(srcSize, CV_8UC1), dst(srcSize, CV_8UC1); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::bilateralFilter(src, dst, d, sigmacolor, sigmaspace); + + SANITY_CHECK(dst); +} + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL From 5a2a0b326a47f647eec9b438e6d1789a3b3678fa Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 13 Jan 2014 15:30:35 +0400 Subject: [PATCH 052/295] added perf tests for cv::dilate --- modules/imgproc/perf/opencl/perf_filters.cpp | 22 ++++++++++++++++++++ modules/imgproc/perf/opencl/perf_imgproc.cpp | 1 - 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/modules/imgproc/perf/opencl/perf_filters.cpp b/modules/imgproc/perf/opencl/perf_filters.cpp index 93d0f2faa..27abe051f 100644 --- a/modules/imgproc/perf/opencl/perf_filters.cpp +++ b/modules/imgproc/perf/opencl/perf_filters.cpp @@ -118,6 +118,28 @@ OCL_PERF_TEST_P(ErodeFixture, Erode, SANITY_CHECK(dst); } +///////////// Dilate //////////////////// + +typedef Size_MatType DilateFixture; + +OCL_PERF_TEST_P(DilateFixture, Dilate, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), ksize = 3; + const Mat ker = getStructuringElement(MORPH_RECT, Size(ksize, ksize)); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type), dst(srcSize, type); + declare.in(src, WARMUP_RNG).out(dst).in(ker); + + OCL_TEST_CYCLE() cv::dilate(src, dst, ker); + + SANITY_CHECK(dst); +} + ///////////// Sobel //////////////////////// typedef Size_MatType SobelFixture; diff --git a/modules/imgproc/perf/opencl/perf_imgproc.cpp b/modules/imgproc/perf/opencl/perf_imgproc.cpp index 117fe1ad6..d7d03b7b3 100644 --- a/modules/imgproc/perf/opencl/perf_imgproc.cpp +++ b/modules/imgproc/perf/opencl/perf_imgproc.cpp @@ -199,4 +199,3 @@ OCL_PERF_TEST_P(CLAHEFixture, CLAHE, OCL_TEST_SIZES) } } // namespace cvtest::ocl #endif // HAVE_OPENCL - From 5e7fd8bd7e95ab4f8e146de85e9d5bbf3cf735b9 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 13 Jan 2014 15:43:09 +0400 Subject: [PATCH 053/295] added perf tests for cv::morphologyEx --- modules/imgproc/perf/opencl/perf_filters.cpp | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/modules/imgproc/perf/opencl/perf_filters.cpp b/modules/imgproc/perf/opencl/perf_filters.cpp index 27abe051f..96424ab04 100644 --- a/modules/imgproc/perf/opencl/perf_filters.cpp +++ b/modules/imgproc/perf/opencl/perf_filters.cpp @@ -140,6 +140,31 @@ OCL_PERF_TEST_P(DilateFixture, Dilate, SANITY_CHECK(dst); } +///////////// MorphologyEx //////////////////////// + +CV_ENUM(MorphOp, MORPH_OPEN, MORPH_CLOSE, MORPH_GRADIENT, MORPH_TOPHAT, MORPH_BLACKHAT) + +typedef tuple MorphologyExParams; +typedef TestBaseWithParam MorphologyExFixture; + +OCL_PERF_TEST_P(MorphologyExFixture, MorphologyEx, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, MorphOp::all())) +{ + const MorphologyExParams params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), op = get<2>(params), ksize = 3; + const Mat ker = getStructuringElement(MORPH_RECT, Size(ksize, ksize)); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type), dst(srcSize, type); + declare.in(src, WARMUP_RNG).out(dst).in(ker); + + OCL_TEST_CYCLE() cv::morphologyEx(src, dst, op, ker); + + SANITY_CHECK(dst); +} + ///////////// Sobel //////////////////////// typedef Size_MatType SobelFixture; From d8e5f1611b338290cc73b8c20a3076599d688fbd Mon Sep 17 00:00:00 2001 From: Max Khardin Date: Mon, 13 Jan 2014 15:55:49 +0400 Subject: [PATCH 054/295] Rewrite definition/declaration of variables to be more compact --- modules/core/perf/perf_arithm.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/core/perf/perf_arithm.cpp b/modules/core/perf/perf_arithm.cpp index d3a75ca9c..3598c8639 100644 --- a/modules/core/perf/perf_arithm.cpp +++ b/modules/core/perf/perf_arithm.cpp @@ -207,9 +207,7 @@ PERF_TEST_P(Size_MatType, multiply, TYPICAL_MATS_CORE_ARITHM) { Size sz = get<0>(GetParam()); int type = get<1>(GetParam()); - cv::Mat a = Mat(sz, type); - cv::Mat b = Mat(sz, type); - cv::Mat c = Mat(sz, type); + cv::Mat a(sz, type), b(sz, type), c(sz, type); declare.in(a, b, WARMUP_RNG).out(c); if (CV_MAT_DEPTH(type) == CV_32S) @@ -228,9 +226,7 @@ PERF_TEST_P(Size_MatType, multiplyScale, TYPICAL_MATS_CORE_ARITHM) { Size sz = get<0>(GetParam()); int type = get<1>(GetParam()); - cv::Mat a = Mat(sz, type); - cv::Mat b = Mat(sz, type); - cv::Mat c = Mat(sz, type); + cv::Mat a(sz, type), b(sz, type), c(sz, type); double scale = 0.5; declare.in(a, b, WARMUP_RNG).out(c); From 6fb878a65fc9603c9a2cfae955d08bdeaaf29864 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 13 Jan 2014 15:59:24 +0400 Subject: [PATCH 055/295] added perf tests for cv::medianBlur --- modules/imgproc/perf/opencl/perf_filters.cpp | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/modules/imgproc/perf/opencl/perf_filters.cpp b/modules/imgproc/perf/opencl/perf_filters.cpp index 96424ab04..fad50b0bf 100644 --- a/modules/imgproc/perf/opencl/perf_filters.cpp +++ b/modules/imgproc/perf/opencl/perf_filters.cpp @@ -273,6 +273,27 @@ OCL_PERF_TEST_P(BilateralFixture, Bilateral, OCL_TEST_SIZES) SANITY_CHECK(dst); } +///////////// MedianBlur //////////////////////// + +typedef tuple MedianBlurParams; +typedef TestBaseWithParam MedianBlurFixture; + +OCL_PERF_TEST_P(MedianBlurFixture, Bilateral, ::testing::Combine(OCL_TEST_SIZES, OCL_PERF_ENUM(3, 5))) +{ + MedianBlurParams params = GetParam(); + const Size srcSize = get<0>(params); + const int ksize = get<1>(params); + + checkDeviceMaxMemoryAllocSize(srcSize, CV_8UC1); + + UMat src(srcSize, CV_8UC1), dst(srcSize, CV_8UC1); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::medianBlur(src, dst, ksize); + + SANITY_CHECK(dst); +} + } } // namespace cvtest::ocl #endif // HAVE_OPENCL From 520a692fda29176efeaa7fc3c63676addaac841f Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Mon, 13 Jan 2014 16:58:36 +0400 Subject: [PATCH 056/295] switching to `CL_PERF_TEST_P`, adding `safeFinish()` to flush CL queue --- .../objdetect/perf/opencl/perf_cascades.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/modules/objdetect/perf/opencl/perf_cascades.cpp b/modules/objdetect/perf/opencl/perf_cascades.cpp index 4af2428f2..d20dd303c 100644 --- a/modules/objdetect/perf/opencl/perf_cascades.cpp +++ b/modules/objdetect/perf/opencl/perf_cascades.cpp @@ -1,6 +1,8 @@ #include "perf_precomp.hpp" #include +#include "opencv2/ts/ocl_perf.hpp" + using namespace std; using namespace cv; using namespace perf; @@ -10,14 +12,14 @@ using std::tr1::get; typedef std::tr1::tuple Cascade_Image_MinSize_t; typedef perf::TestBaseWithParam Cascade_Image_MinSize; -PERF_TEST_P( Cascade_Image_MinSize, CascadeClassifier_UMat, - testing::Combine( - testing::Values( string("cv/cascadeandhog/cascades/haarcascade_frontalface_alt.xml"), - string("cv/cascadeandhog/cascades/lbpcascade_frontalface.xml") ), - testing::Values( string("cv/shared/lena.png"), - string("cv/cascadeandhog/images/bttf301.png"), - string("cv/cascadeandhog/images/class57.png") ), - testing::Values(30, 64, 90) ) ) +OCL_PERF_TEST_P(Cascade_Image_MinSize, CascadeClassifier, + testing::Combine( + testing::Values( string("cv/cascadeandhog/cascades/haarcascade_frontalface_alt.xml"), + string("cv/cascadeandhog/cascades/lbpcascade_frontalface.xml") ), + testing::Values( string("cv/shared/lena.png"), + string("cv/cascadeandhog/images/bttf301.png"), + string("cv/cascadeandhog/images/class57.png") ), + testing::Values(30, 64, 90) ) ) { const string cascasePath = get<0>(GetParam()); const string imagePath = get<1>(GetParam()); @@ -42,6 +44,7 @@ PERF_TEST_P( Cascade_Image_MinSize, CascadeClassifier_UMat, while(next()) { faces.clear(); + cvtest::ocl::perf::safeFinish(); startTimer(); cc.detectMultiScale(uimg, faces, 1.1, 3, 0, minSize); From a7a7b80ff8602f7ff4a05eef2032a7e86379acea Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 13 Jan 2014 17:50:14 +0400 Subject: [PATCH 057/295] added perf test for cv::Moments --- modules/imgproc/perf/opencl/perf_imgwarp.cpp | 1 + modules/imgproc/perf/opencl/perf_moments.cpp | 78 ++++++++++++++++++++ modules/imgproc/perf/opencl/perf_pyramid.cpp | 1 + modules/ts/include/opencv2/ts/ts_perf.hpp | 2 + modules/ts/src/ts_perf.cpp | 8 ++ 5 files changed, 90 insertions(+) create mode 100644 modules/imgproc/perf/opencl/perf_moments.cpp diff --git a/modules/imgproc/perf/opencl/perf_imgwarp.cpp b/modules/imgproc/perf/opencl/perf_imgwarp.cpp index f309d283c..c2efda7e5 100644 --- a/modules/imgproc/perf/opencl/perf_imgwarp.cpp +++ b/modules/imgproc/perf/opencl/perf_imgwarp.cpp @@ -43,6 +43,7 @@ // the use of this software, even if advised of the possibility of such damage. // //M*/ + #include "perf_precomp.hpp" #include "opencv2/ts/ocl_perf.hpp" diff --git a/modules/imgproc/perf/opencl/perf_moments.cpp b/modules/imgproc/perf/opencl/perf_moments.cpp new file mode 100644 index 000000000..e77b76850 --- /dev/null +++ b/modules/imgproc/perf/opencl/perf_moments.cpp @@ -0,0 +1,78 @@ +/*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/ts/ocl_perf.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +///////////// Moments //////////////////////// + +typedef tuple MomentsParams; +typedef TestBaseWithParam MomentsFixture; + +OCL_PERF_TEST_P(MomentsFixture, Moments, + ::testing::Combine(OCL_TEST_SIZES, ::testing::Bool())) +{ + const MomentsParams params = GetParam(); + const Size srcSize = get<0>(params); + const bool binaryImage = get<1>(params); + + cv::Moments m; + UMat src(srcSize, CV_8UC1); + declare.in(src, WARMUP_RNG); + + OCL_TEST_CYCLE() m = cv::moments(src, binaryImage); + + SANITY_CHECK_MOMENTS(m, 1e-6, ERROR_RELATIVE); +} + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL diff --git a/modules/imgproc/perf/opencl/perf_pyramid.cpp b/modules/imgproc/perf/opencl/perf_pyramid.cpp index c81ff1861..4beba2280 100644 --- a/modules/imgproc/perf/opencl/perf_pyramid.cpp +++ b/modules/imgproc/perf/opencl/perf_pyramid.cpp @@ -43,6 +43,7 @@ // the use of this software, even if advised of the possibility of such damage. // //M*/ + #include "perf_precomp.hpp" #include "opencv2/ts/ocl_perf.hpp" diff --git a/modules/ts/include/opencv2/ts/ts_perf.hpp b/modules/ts/include/opencv2/ts/ts_perf.hpp index 499b53cad..fdee4e8bd 100644 --- a/modules/ts/include/opencv2/ts/ts_perf.hpp +++ b/modules/ts/include/opencv2/ts/ts_perf.hpp @@ -164,6 +164,7 @@ class CV_EXPORTS Regression { public: static Regression& add(TestBase* test, const std::string& name, cv::InputArray array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE); + static Regression& addMoments(TestBase* test, const std::string& name, const cv::Moments & array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE); static Regression& addKeypoints(TestBase* test, const std::string& name, const std::vector& array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE); static Regression& addMatches(TestBase* test, const std::string& name, const std::vector& array, double eps = DBL_EPSILON, ERROR_TYPE err = ERROR_ABSOLUTE); static void Init(const std::string& testSuitName, const std::string& ext = ".xml"); @@ -201,6 +202,7 @@ private: }; #define SANITY_CHECK(array, ...) ::perf::Regression::add(this, #array, array , ## __VA_ARGS__) +#define SANITY_CHECK_MOMENTS(array, ...) ::perf::Regression::addMoments(this, #array, array , ## __VA_ARGS__) #define SANITY_CHECK_KEYPOINTS(array, ...) ::perf::Regression::addKeypoints(this, #array, array , ## __VA_ARGS__) #define SANITY_CHECK_MATCHES(array, ...) ::perf::Regression::addMatches(this, #array, array , ## __VA_ARGS__) #define SANITY_CHECK_NOTHING() this->setVerified(); diff --git a/modules/ts/src/ts_perf.cpp b/modules/ts/src/ts_perf.cpp index 576c97f2e..35204c291 100644 --- a/modules/ts/src/ts_perf.cpp +++ b/modules/ts/src/ts_perf.cpp @@ -115,6 +115,14 @@ Regression& Regression::add(TestBase* test, const std::string& name, cv::InputAr return instance()(name, array, eps, err); } +Regression& Regression::addMoments(TestBase* test, const std::string& name, const cv::Moments& array, double eps, ERROR_TYPE err) +{ + int len = (int)sizeof(cv::Moments) / sizeof(double); + cv::Mat m(1, len, CV_64F, (void*)&array); + + return Regression::add(test, name, m, eps, err); +} + Regression& Regression::addKeypoints(TestBase* test, const std::string& name, const std::vector& array, double eps, ERROR_TYPE err) { int len = (int)array.size(); From 4c99196399288d2a97af37366c9a938d9092f0f1 Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Mon, 13 Jan 2014 18:12:30 +0400 Subject: [PATCH 058/295] adding `finish()` to flush CL queue, renaming the test to match 'master' branch --- modules/ocl/perf/perf_haar.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/ocl/perf/perf_haar.cpp b/modules/ocl/perf/perf_haar.cpp index 2fe01ee6e..86890a891 100644 --- a/modules/ocl/perf/perf_haar.cpp +++ b/modules/ocl/perf/perf_haar.cpp @@ -90,10 +90,10 @@ using namespace perf; using std::tr1::make_tuple; using std::tr1::get; -typedef std::tr1::tuple Cascade_Image_MinSize_t; -typedef perf::TestBaseWithParam Cascade_Image_MinSize; +typedef std::tr1::tuple OCL_Cascade_Image_MinSize_t; +typedef perf::TestBaseWithParam OCL_Cascade_Image_MinSize; -PERF_TEST_P( Cascade_Image_MinSize, CascadeClassifier_UMat, +PERF_TEST_P( OCL_Cascade_Image_MinSize, CascadeClassifier, testing::Combine( testing::Values( string("cv/cascadeandhog/cascades/haarcascade_frontalface_alt.xml") ), testing::Values( string("cv/shared/lena.png"), @@ -135,6 +135,7 @@ PERF_TEST_P( Cascade_Image_MinSize, CascadeClassifier_UMat, while (next()) { faces.clear(); + ocl::finish(); startTimer(); cc.detectMultiScale(uimg, faces, 1.1, 3, 0, minSize); @@ -146,4 +147,5 @@ PERF_TEST_P( Cascade_Image_MinSize, CascadeClassifier_UMat, //sort(faces.begin(), faces.end(), comparators::RectLess()); SANITY_CHECK_NOTHING();//(faces, min_size/5); + // using SANITY_CHECK_NOTHING() since OCL and PLAIN version may find different faces number } From 8702fceb4b609ed090a1a8dc6930aa4376dc157d Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 13 Jan 2014 18:36:25 +0400 Subject: [PATCH 059/295] fixed cv::integral perf test --- modules/imgproc/perf/opencl/perf_imgproc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/perf/opencl/perf_imgproc.cpp b/modules/imgproc/perf/opencl/perf_imgproc.cpp index d7d03b7b3..1b8ebc23f 100644 --- a/modules/imgproc/perf/opencl/perf_imgproc.cpp +++ b/modules/imgproc/perf/opencl/perf_imgproc.cpp @@ -140,7 +140,7 @@ OCL_PERF_TEST_P(CornerHarrisFixture, CornerHarris, typedef tuple IntegralParams; typedef TestBaseWithParam IntegralFixture; -OCL_PERF_TEST_P(IntegralFixture, Integral1, ::testing::Combine(OCL_TEST_SIZES, OCL_PERF_ENUM(CV_32F, CV_64F))) +OCL_PERF_TEST_P(IntegralFixture, Integral1, ::testing::Combine(OCL_TEST_SIZES, OCL_PERF_ENUM(CV_32S, CV_32F))) { const IntegralParams params = GetParam(); const Size srcSize = get<0>(params); From 30b5234e9afca8ad60a8a139e8bc5b25b6e2e0bb Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 13 Jan 2014 18:51:49 +0400 Subject: [PATCH 060/295] added perf test for cv::sqrBoxFilter --- modules/imgproc/perf/opencl/perf_imgproc.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/modules/imgproc/perf/opencl/perf_imgproc.cpp b/modules/imgproc/perf/opencl/perf_imgproc.cpp index 1b8ebc23f..d5de677d0 100644 --- a/modules/imgproc/perf/opencl/perf_imgproc.cpp +++ b/modules/imgproc/perf/opencl/perf_imgproc.cpp @@ -146,7 +146,7 @@ OCL_PERF_TEST_P(IntegralFixture, Integral1, ::testing::Combine(OCL_TEST_SIZES, O const Size srcSize = get<0>(params); const int ddepth = get<1>(params); - UMat src(srcSize, CV_8UC1), dst(srcSize, ddepth); + UMat src(srcSize, CV_8UC1), dst(srcSize + Size(1, 1), ddepth); declare.in(src, WARMUP_RNG).out(dst); OCL_TEST_CYCLE() cv::integral(src, dst, ddepth); @@ -196,6 +196,22 @@ OCL_PERF_TEST_P(CLAHEFixture, CLAHE, OCL_TEST_SIZES) SANITY_CHECK(dst); } +///////////// SqrBoxFilter //////////////////////// + +typedef TestBaseWithParam SqrBoxFilterFixture; + +OCL_PERF_TEST_P(SqrBoxFilterFixture, SqrBoxFilter, OCL_TEST_SIZES) +{ + const Size srcSize = GetParam(); + + UMat src(srcSize, CV_8UC1), dst(srcSize, CV_32SC1); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::sqrBoxFilter(src, dst, CV_32S, Size(3, 3)); + + SANITY_CHECK(dst); +} + } } // namespace cvtest::ocl #endif // HAVE_OPENCL From 49dfa5a17f00a82f0c160e20395c193b992d286e Mon Sep 17 00:00:00 2001 From: ahb Date: Mon, 13 Jan 2014 16:09:42 +0100 Subject: [PATCH 061/295] Fix the following error for ocl::getOpenCLPlatforms() on Ubuntu 12.04 with gcc 4.8 OpenCV Error: Unknown error code -6 (OpenCL function is not available: [clGetPlatformIDs]) in opencl_check_fn, file /home/ahb/software/opencv/modules/ocl/src/cl_runtime/cl_runtime.cpp, line 83 The issue results from modules/ocl/src/cl_runtime/cl_runtime.cpp checking for "linux" instead of "__linux__" (cp. http://sourceforge.net/p/predef/wiki/OperatingSystems/) Adjust all other occurrences of "defined(linux)" as well. --- 3rdparty/include/opencl/1.2/CL/cl.hpp | 2 +- modules/ocl/src/cl_runtime/cl_runtime.cpp | 2 +- modules/ocl/src/cl_runtime/clamdblas_runtime.cpp | 2 +- modules/ocl/src/cl_runtime/clamdfft_runtime.cpp | 2 +- .../src/cl_runtime/generator/template/clamdblas_runtime.cpp.in | 2 +- .../src/cl_runtime/generator/template/clamdfft_runtime.cpp.in | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/3rdparty/include/opencl/1.2/CL/cl.hpp b/3rdparty/include/opencl/1.2/CL/cl.hpp index 0480e3116..2502d4c52 100644 --- a/3rdparty/include/opencl/1.2/CL/cl.hpp +++ b/3rdparty/include/opencl/1.2/CL/cl.hpp @@ -210,7 +210,7 @@ #include #endif -#if defined(linux) || defined(__APPLE__) || defined(__MACOSX) +#if defined(__linux__) || defined(__APPLE__) || defined(__MACOSX) #include #include diff --git a/modules/ocl/src/cl_runtime/cl_runtime.cpp b/modules/ocl/src/cl_runtime/cl_runtime.cpp index a0d967c0b..c3a31ccc3 100644 --- a/modules/ocl/src/cl_runtime/cl_runtime.cpp +++ b/modules/ocl/src/cl_runtime/cl_runtime.cpp @@ -45,7 +45,7 @@ #define CV_CL_GET_PROC_ADDRESS(name) WinGetProcAddress(name) #endif // _WIN32 -#if defined(linux) +#if defined(__linux__) #include #include diff --git a/modules/ocl/src/cl_runtime/clamdblas_runtime.cpp b/modules/ocl/src/cl_runtime/clamdblas_runtime.cpp index 0a077db69..1256000c8 100644 --- a/modules/ocl/src/cl_runtime/clamdblas_runtime.cpp +++ b/modules/ocl/src/cl_runtime/clamdblas_runtime.cpp @@ -27,7 +27,7 @@ #define CV_CL_GET_PROC_ADDRESS(name) WinGetProcAddress(name) #endif // _WIN32 -#if defined(linux) +#if defined(__linux__) #include #include diff --git a/modules/ocl/src/cl_runtime/clamdfft_runtime.cpp b/modules/ocl/src/cl_runtime/clamdfft_runtime.cpp index 60cbecef2..f0fa769b7 100644 --- a/modules/ocl/src/cl_runtime/clamdfft_runtime.cpp +++ b/modules/ocl/src/cl_runtime/clamdfft_runtime.cpp @@ -27,7 +27,7 @@ #define CV_CL_GET_PROC_ADDRESS(name) WinGetProcAddress(name) #endif // _WIN32 -#if defined(linux) +#if defined(__linux__) #include #include diff --git a/modules/ocl/src/cl_runtime/generator/template/clamdblas_runtime.cpp.in b/modules/ocl/src/cl_runtime/generator/template/clamdblas_runtime.cpp.in index 8492edda9..0cf33bb7e 100644 --- a/modules/ocl/src/cl_runtime/generator/template/clamdblas_runtime.cpp.in +++ b/modules/ocl/src/cl_runtime/generator/template/clamdblas_runtime.cpp.in @@ -24,7 +24,7 @@ #define CV_CL_GET_PROC_ADDRESS(name) WinGetProcAddress(name) #endif // _WIN32 -#if defined(linux) +#if defined(__linux__) #include #include diff --git a/modules/ocl/src/cl_runtime/generator/template/clamdfft_runtime.cpp.in b/modules/ocl/src/cl_runtime/generator/template/clamdfft_runtime.cpp.in index aee6bd8ab..8e8fb42c4 100644 --- a/modules/ocl/src/cl_runtime/generator/template/clamdfft_runtime.cpp.in +++ b/modules/ocl/src/cl_runtime/generator/template/clamdfft_runtime.cpp.in @@ -24,7 +24,7 @@ #define CV_CL_GET_PROC_ADDRESS(name) WinGetProcAddress(name) #endif // _WIN32 -#if defined(linux) +#if defined(__linux__) #include #include From 9b7b360bf71c3602d4a52858b61139f2cf40930f Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Tue, 14 Jan 2014 17:50:00 +0400 Subject: [PATCH 062/295] fixing compilation if `WITH_OPENCL=OFF` --- modules/objdetect/perf/opencl/perf_cascades.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/objdetect/perf/opencl/perf_cascades.cpp b/modules/objdetect/perf/opencl/perf_cascades.cpp index d20dd303c..7d6c16f35 100644 --- a/modules/objdetect/perf/opencl/perf_cascades.cpp +++ b/modules/objdetect/perf/opencl/perf_cascades.cpp @@ -12,6 +12,8 @@ using std::tr1::get; typedef std::tr1::tuple Cascade_Image_MinSize_t; typedef perf::TestBaseWithParam Cascade_Image_MinSize; +#ifdef HAVE_OPENCL + OCL_PERF_TEST_P(Cascade_Image_MinSize, CascadeClassifier, testing::Combine( testing::Values( string("cv/cascadeandhog/cascades/haarcascade_frontalface_alt.xml"), @@ -54,3 +56,5 @@ OCL_PERF_TEST_P(Cascade_Image_MinSize, CascadeClassifier, sort(faces.begin(), faces.end(), comparators::RectLess()); SANITY_CHECK(faces, min_size/5); } + +#endif //HAVE_OPENCL From c7d90c8b326d4f47f371b63292158cce8b3834b0 Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Tue, 14 Jan 2014 23:15:50 +0400 Subject: [PATCH 063/295] adding old cascade --- modules/objdetect/perf/opencl/perf_cascades.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/objdetect/perf/opencl/perf_cascades.cpp b/modules/objdetect/perf/opencl/perf_cascades.cpp index 7d6c16f35..bf600a010 100644 --- a/modules/objdetect/perf/opencl/perf_cascades.cpp +++ b/modules/objdetect/perf/opencl/perf_cascades.cpp @@ -17,6 +17,7 @@ typedef perf::TestBaseWithParam Cascade_Image_MinSize; OCL_PERF_TEST_P(Cascade_Image_MinSize, CascadeClassifier, testing::Combine( testing::Values( string("cv/cascadeandhog/cascades/haarcascade_frontalface_alt.xml"), + string("cv/cascadeandhog/cascades/haarcascade_frontalface_alt_old.xml"), string("cv/cascadeandhog/cascades/lbpcascade_frontalface.xml") ), testing::Values( string("cv/shared/lena.png"), string("cv/cascadeandhog/images/bttf301.png"), From 9dc0bfc755b5ba074b9e7c23a311c132e6926f37 Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Sun, 5 Jan 2014 17:21:59 +0200 Subject: [PATCH 064/295] Small fix for extracting mouse coordinates on Windows, in a way that will always work with multiple monitors. This is the way recommended by Microsoft. --- modules/highgui/src/window_w32.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 6a5355c53..222f0b0ab 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -1474,8 +1474,8 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM if( uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONUP || uMsg == WM_MBUTTONUP ) ReleaseCapture(); - pt.x = LOWORD( lParam ); - pt.y = HIWORD( lParam ); + pt.x = GET_X_LPARAM( lParam ); + pt.y = GET_Y_LPARAM( lParam ); GetClientRect( window->hwnd, &rect ); icvGetBitmapData( window, &size, 0, 0 ); From fecd5c994b79f0480b5d893fd53e062edccef0ad Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Tue, 7 Jan 2014 21:17:57 +0200 Subject: [PATCH 065/295] Added support for mouse-wheel events on Windows. To be used in the mouse callback like this: if (CV_EVENT_MOUSEWHEEL == CV_GET_MOUSEWHEEL_EVENT(event)) { int delta= CV_GET_WHEEL_DELTA(event); // use delta... } --- .../include/opencv2/highgui/highgui_c.h | 9 ++++- modules/highgui/src/window_w32.cpp | 38 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index 1a42e5804..d1aa93b02 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -170,7 +170,9 @@ enum CV_EVENT_MBUTTONUP =6, CV_EVENT_LBUTTONDBLCLK =7, CV_EVENT_RBUTTONDBLCLK =8, - CV_EVENT_MBUTTONDBLCLK =9 + CV_EVENT_MBUTTONDBLCLK =9, + CV_EVENT_MOUSEWHEEL =10, + CV_EVENT_MOUSEHWHEEL =11 }; enum @@ -183,6 +185,11 @@ enum CV_EVENT_FLAG_ALTKEY =32 }; + +#define CV_GET_WHEEL_DELTA(event) ((short)((event >> 16) & 0xffff)) // upper 16 bits +#define CV_GET_MOUSEWHEEL_EVENT(event) (event & 0xffff) // lower 16 bits + + typedef void (CV_CDECL *CvMouseCallback )(int event, int x, int y, int flags, void* param); /* assign callback for mouse events */ diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 222f0b0ab..70a29d402 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -40,6 +40,7 @@ //M*/ #include "precomp.hpp" +#include // required for GET_X_LPARAM() and GET_Y_LPARAM() marco #if defined WIN32 || defined _WIN32 @@ -1377,6 +1378,43 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) SetFocus(window->hwnd); break; + case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: + if( window->on_mouse ) + { + int flags = (wParam & MK_LBUTTON ? CV_EVENT_FLAG_LBUTTON : 0)| + (wParam & MK_RBUTTON ? CV_EVENT_FLAG_RBUTTON : 0)| + (wParam & MK_MBUTTON ? CV_EVENT_FLAG_MBUTTON : 0)| + (wParam & MK_CONTROL ? CV_EVENT_FLAG_CTRLKEY : 0)| + (wParam & MK_SHIFT ? CV_EVENT_FLAG_SHIFTKEY : 0)| + (GetKeyState(VK_MENU) < 0 ? CV_EVENT_FLAG_ALTKEY : 0); + int event = (uMsg == WM_MOUSEWHEEL ? CV_EVENT_MOUSEWHEEL : CV_EVENT_MOUSEHWHEEL); + + // Set the wheel delta of mouse wheel to be in the upper word of 'event' + int delta = GET_WHEEL_DELTA_WPARAM(wParam); + event |= (delta << 16); + + POINT pt; + { + // since The coordinates are relative to screen so get screen size. + RECT windowRect; + ::GetWindowRect( window->hwnd, &windowRect ); + pt.x = GET_X_LPARAM( lParam ) - windowRect.left; + pt.y = GET_Y_LPARAM( lParam ) - windowRect.top; + } + + RECT rect; + GetClientRect( window->hwnd, &rect ); + + SIZE size = {0,0}; + icvGetBitmapData( window, &size, 0, 0 ); + + window->on_mouse( event, pt.x*size.cx/MAX(rect.right - rect.left,1), + pt.y*size.cy/MAX(rect.bottom - rect.top,1), flags, + window->on_mouse_param ); + } + break; + case WM_ERASEBKGND: { RECT cr, tr, wrc; From e45cf2173f28c51eadfe799d18f342b7163f9590 Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Sun, 12 Jan 2014 09:33:08 +0200 Subject: [PATCH 066/295] [HighGUI] Updated mouse wheel delta to reside within the 'flags' variable. Updated C++ API. --- modules/highgui/include/opencv2/highgui.hpp | 6 +++++- modules/highgui/include/opencv2/highgui/highgui_c.h | 4 +--- modules/highgui/src/window.cpp | 5 +++++ modules/highgui/src/window_w32.cpp | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index eb4ee8c03..00e1ce427 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -76,7 +76,9 @@ enum { EVENT_MOUSEMOVE = 0, EVENT_MBUTTONUP = 6, EVENT_LBUTTONDBLCLK = 7, EVENT_RBUTTONDBLCLK = 8, - EVENT_MBUTTONDBLCLK = 9 + EVENT_MBUTTONDBLCLK =9, + EVENT_MOUSEWHEEL =10, + EVENT_MOUSEHWHEEL =11 }; enum { EVENT_FLAG_LBUTTON = 1, @@ -137,6 +139,8 @@ CV_EXPORTS_W double getWindowProperty(const String& winname, int prop_id); //! assigns callback for mouse events CV_EXPORTS void setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0); +CV_EXPORTS int getMouseWheelDelta(int flags); + CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname, int* value, int count, TrackbarCallback onChange = 0, diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index d1aa93b02..ac1262585 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -186,9 +186,7 @@ enum }; -#define CV_GET_WHEEL_DELTA(event) ((short)((event >> 16) & 0xffff)) // upper 16 bits -#define CV_GET_MOUSEWHEEL_EVENT(event) (event & 0xffff) // lower 16 bits - +#define CV_GET_WHEEL_DELTA(flags) ((short)((flags >> 16) & 0xffff)) // upper 16 bits typedef void (CV_CDECL *CvMouseCallback )(int event, int x, int y, int flags, void* param); diff --git a/modules/highgui/src/window.cpp b/modules/highgui/src/window.cpp index 428ef51ef..03ff988d7 100644 --- a/modules/highgui/src/window.cpp +++ b/modules/highgui/src/window.cpp @@ -216,6 +216,11 @@ void cv::setMouseCallback( const String& windowName, MouseCallback onMouse, void cvSetMouseCallback(windowName.c_str(), onMouse, param); } +int cv::getMouseWheelDelta( int flags ) +{ + return CV_GET_WHEEL_DELTA(flags); +} + int cv::startWindowThread() { return cvStartWindowThread(); diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 70a29d402..bb4704795 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -1392,7 +1392,7 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) // Set the wheel delta of mouse wheel to be in the upper word of 'event' int delta = GET_WHEEL_DELTA_WPARAM(wParam); - event |= (delta << 16); + flags |= (delta << 16); POINT pt; { From ab18c2d1323a58294db30b0eaac08917cf0aa4b8 Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Wed, 15 Jan 2014 15:08:09 +0400 Subject: [PATCH 067/295] changed testdata path for calib3d --- modules/calib3d/test/test_cameracalibration.cpp | 6 +++--- modules/calib3d/test/test_chesscorners.cpp | 6 +++--- modules/calib3d/test/test_chesscorners_timing.cpp | 2 +- modules/calib3d/test/test_main.cpp | 2 +- modules/calib3d/test/test_stereomatching.cpp | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib3d/test/test_cameracalibration.cpp index fb8238237..7262e61a1 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib3d/test/test_cameracalibration.cpp @@ -337,7 +337,7 @@ void CV_CameraCalibrationTest::run( int start_from ) int progress = 0; int values_read = -1; - sprintf( filepath, "%scameracalibration/", ts->get_data_path().c_str() ); + sprintf( filepath, "%scv/cameracalibration/", ts->get_data_path().c_str() ); sprintf( filename, "%sdatafiles.txt", filepath ); datafile = fopen( filename, "r" ); if( datafile == 0 ) @@ -1384,7 +1384,7 @@ void CV_StereoCalibrationTest::run( int ) { char filepath[1000]; char buf[1000]; - sprintf( filepath, "%sstereo/case%d/stereo_calib.txt", ts->get_data_path().c_str(), testcase ); + sprintf( filepath, "%scv/stereo/case%d/stereo_calib.txt", ts->get_data_path().c_str(), testcase ); f = fopen(filepath, "rt"); Size patternSize; vector imglist; @@ -1405,7 +1405,7 @@ void CV_StereoCalibrationTest::run( int ) buf[--len] = '\0'; if( buf[0] == '#') continue; - sprintf(filepath, "%sstereo/case%d/%s", ts->get_data_path().c_str(), testcase, buf ); + sprintf(filepath, "%scv/stereo/case%d/%s", ts->get_data_path().c_str(), testcase, buf ); imglist.push_back(string(filepath)); } fclose(f); diff --git a/modules/calib3d/test/test_chesscorners.cpp b/modules/calib3d/test/test_chesscorners.cpp index 6769e47c6..17ecb6717 100644 --- a/modules/calib3d/test/test_chesscorners.cpp +++ b/modules/calib3d/test/test_chesscorners.cpp @@ -185,13 +185,13 @@ void CV_ChessboardDetectorTest::run_batch( const string& filename ) switch( pattern ) { case CHESSBOARD: - folder = string(ts->get_data_path()) + "cameracalibration/"; + folder = string(ts->get_data_path()) + "cv/cameracalibration/"; break; case CIRCLES_GRID: - folder = string(ts->get_data_path()) + "cameracalibration/circles/"; + folder = string(ts->get_data_path()) + "cv/cameracalibration/circles/"; break; case ASYMMETRIC_CIRCLES_GRID: - folder = string(ts->get_data_path()) + "cameracalibration/asymmetric_circles/"; + folder = string(ts->get_data_path()) + "cv/cameracalibration/asymmetric_circles/"; break; } diff --git a/modules/calib3d/test/test_chesscorners_timing.cpp b/modules/calib3d/test/test_chesscorners_timing.cpp index 47653f88d..a990aea84 100644 --- a/modules/calib3d/test/test_chesscorners_timing.cpp +++ b/modules/calib3d/test/test_chesscorners_timing.cpp @@ -75,7 +75,7 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) int idx, max_idx; int progress = 0; - sprintf( filepath, "%scameracalibration/", ts->get_data_path().c_str() ); + sprintf( filepath, "%scv/cameracalibration/", ts->get_data_path().c_str() ); sprintf( filename, "%schessboard_timing_list.dat", filepath ); CvFileStorage* fs = cvOpenFileStorage( filename, 0, CV_STORAGE_READ ); CvFileNode* board_list = fs ? cvGetFileNodeByName( fs, 0, "boards" ) : 0; diff --git a/modules/calib3d/test/test_main.cpp b/modules/calib3d/test/test_main.cpp index 6b2499344..6f9ac2e0d 100644 --- a/modules/calib3d/test/test_main.cpp +++ b/modules/calib3d/test/test_main.cpp @@ -1,3 +1,3 @@ #include "test_precomp.hpp" -CV_TEST_MAIN("cv") +CV_TEST_MAIN("") diff --git a/modules/calib3d/test/test_stereomatching.cpp b/modules/calib3d/test/test_stereomatching.cpp index 8e1120e47..8beb9f905 100644 --- a/modules/calib3d/test/test_stereomatching.cpp +++ b/modules/calib3d/test/test_stereomatching.cpp @@ -398,7 +398,7 @@ protected: void CV_StereoMatchingTest::run(int) { - string dataPath = ts->get_data_path(); + string dataPath = ts->get_data_path() + "cv/"; string algorithmName = name; assert( !algorithmName.empty() ); if( dataPath.empty() ) From 82d3efc6c053455f1217e5af32732b69ef834a51 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 13 Jan 2014 19:46:00 +0400 Subject: [PATCH 068/295] added perf test for cv::Canny --- modules/imgproc/perf/opencl/perf_filters.cpp | 61 ++++++++++---------- modules/imgproc/perf/opencl/perf_imgproc.cpp | 28 ++++++++- modules/ts/include/opencv2/ts/ocl_perf.hpp | 32 +++++++--- 3 files changed, 82 insertions(+), 39 deletions(-) diff --git a/modules/imgproc/perf/opencl/perf_filters.cpp b/modules/imgproc/perf/opencl/perf_filters.cpp index fad50b0bf..25b11caad 100644 --- a/modules/imgproc/perf/opencl/perf_filters.cpp +++ b/modules/imgproc/perf/opencl/perf_filters.cpp @@ -52,16 +52,19 @@ namespace cvtest { namespace ocl { +typedef tuple FilterParams; +typedef TestBaseWithParam FilterFixture; + ///////////// Blur //////////////////////// -typedef Size_MatType BlurFixture; +typedef FilterFixture BlurFixture; OCL_PERF_TEST_P(BlurFixture, Blur, - ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, OCL_PERF_ENUM(3, 5))) { - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params), ksize(3, 3); - const int type = get<1>(params), bordertype = BORDER_CONSTANT; + const FilterParams params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), ksize = get<2>(params), bordertype = BORDER_CONSTANT; const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-5; checkDeviceMaxMemoryAllocSize(srcSize, type); @@ -69,21 +72,21 @@ OCL_PERF_TEST_P(BlurFixture, Blur, UMat src(srcSize, type), dst(srcSize, type); declare.in(src, WARMUP_RNG).out(dst); - OCL_TEST_CYCLE() cv::blur(src, dst, ksize, Point(-1, -1), bordertype); + OCL_TEST_CYCLE() cv::blur(src, dst, Size(ksize, ksize), Point(-1, -1), bordertype); SANITY_CHECK(dst, eps); } ///////////// Laplacian//////////////////////// -typedef Size_MatType LaplacianFixture; +typedef FilterFixture LaplacianFixture; OCL_PERF_TEST_P(LaplacianFixture, Laplacian, - ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, OCL_PERF_ENUM(3, 5))) { - const Size_MatType_t params = GetParam(); + const FilterParams params = GetParam(); const Size srcSize = get<0>(params); - const int type = get<1>(params), ksize = 3; + const int type = get<1>(params), ksize = get<2>(params); const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-5; checkDeviceMaxMemoryAllocSize(srcSize, type); @@ -98,14 +101,14 @@ OCL_PERF_TEST_P(LaplacianFixture, Laplacian, ///////////// Erode //////////////////// -typedef Size_MatType ErodeFixture; +typedef FilterFixture ErodeFixture; OCL_PERF_TEST_P(ErodeFixture, Erode, - ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, OCL_PERF_ENUM(3, 5))) { - const Size_MatType_t params = GetParam(); + const FilterParams params = GetParam(); const Size srcSize = get<0>(params); - const int type = get<1>(params), ksize = 3; + const int type = get<1>(params), ksize = get<2>(params); const Mat ker = getStructuringElement(MORPH_RECT, Size(ksize, ksize)); checkDeviceMaxMemoryAllocSize(srcSize, type); @@ -120,14 +123,14 @@ OCL_PERF_TEST_P(ErodeFixture, Erode, ///////////// Dilate //////////////////// -typedef Size_MatType DilateFixture; +typedef FilterFixture DilateFixture; OCL_PERF_TEST_P(DilateFixture, Dilate, - ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, OCL_PERF_ENUM(3, 5))) { - const Size_MatType_t params = GetParam(); + const FilterParams params = GetParam(); const Size srcSize = get<0>(params); - const int type = get<1>(params), ksize = 3; + const int type = get<1>(params), ksize = get<2>(params); const Mat ker = getStructuringElement(MORPH_RECT, Size(ksize, ksize)); checkDeviceMaxMemoryAllocSize(srcSize, type); @@ -144,15 +147,15 @@ OCL_PERF_TEST_P(DilateFixture, Dilate, CV_ENUM(MorphOp, MORPH_OPEN, MORPH_CLOSE, MORPH_GRADIENT, MORPH_TOPHAT, MORPH_BLACKHAT) -typedef tuple MorphologyExParams; +typedef tuple MorphologyExParams; typedef TestBaseWithParam MorphologyExFixture; OCL_PERF_TEST_P(MorphologyExFixture, MorphologyEx, - ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, MorphOp::all())) + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, MorphOp::all(), OCL_PERF_ENUM(3, 5))) { const MorphologyExParams params = GetParam(); const Size srcSize = get<0>(params); - const int type = get<1>(params), op = get<2>(params), ksize = 3; + const int type = get<1>(params), op = get<2>(params), ksize = get<3>(params); const Mat ker = getStructuringElement(MORPH_RECT, Size(ksize, ksize)); checkDeviceMaxMemoryAllocSize(srcSize, type); @@ -210,14 +213,14 @@ OCL_PERF_TEST_P(ScharrFixture, Scharr, ///////////// GaussianBlur //////////////////////// -typedef Size_MatType GaussianBlurFixture; +typedef FilterFixture GaussianBlurFixture; OCL_PERF_TEST_P(GaussianBlurFixture, GaussianBlur, - ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, OCL_PERF_ENUM(3, 5, 7))) { - const Size_MatType_t params = GetParam(); + const FilterParams params = GetParam(); const Size srcSize = get<0>(params); - const int type = get<1>(params), ksize = 7; + const int type = get<1>(params), ksize = get<2>(params); const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 + DBL_EPSILON : 3e-4; checkDeviceMaxMemoryAllocSize(srcSize, type); @@ -232,14 +235,14 @@ OCL_PERF_TEST_P(GaussianBlurFixture, GaussianBlur, ///////////// Filter2D //////////////////////// -typedef Size_MatType Filter2DFixture; +typedef FilterFixture Filter2DFixture; OCL_PERF_TEST_P(Filter2DFixture, Filter2D, - ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES, OCL_PERF_ENUM(3, 5))) { - const Size_MatType_t params = GetParam(); + const FilterParams params = GetParam(); const Size srcSize = get<0>(params); - const int type = get<1>(params), ksize = 3; + const int type = get<1>(params), ksize = get<2>(params); const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-5; checkDeviceMaxMemoryAllocSize(srcSize, type); diff --git a/modules/imgproc/perf/opencl/perf_imgproc.cpp b/modules/imgproc/perf/opencl/perf_imgproc.cpp index d5de677d0..7c102fa21 100644 --- a/modules/imgproc/perf/opencl/perf_imgproc.cpp +++ b/modules/imgproc/perf/opencl/perf_imgproc.cpp @@ -132,7 +132,7 @@ OCL_PERF_TEST_P(CornerHarrisFixture, CornerHarris, OCL_TEST_CYCLE() cv::cornerHarris(src, dst, 5, 7, 0.1, borderType); - SANITY_CHECK(dst, 3e-5); + SANITY_CHECK(dst, 5e-5); } ///////////// Integral //////////////////////// @@ -212,6 +212,32 @@ OCL_PERF_TEST_P(SqrBoxFilterFixture, SqrBoxFilter, OCL_TEST_SIZES) SANITY_CHECK(dst); } +///////////// Canny //////////////////////// + +typedef tuple CannyParams; +typedef TestBaseWithParam CannyFixture; + +OCL_PERF_TEST_P(CannyFixture, Canny, ::testing::Combine(OCL_PERF_ENUM(3, 5), Bool())) +{ + const CannyParams params = GetParam(); + int apertureSize = get<0>(params); + bool L2Grad = get<1>(params); + + Mat _img = imread(getDataPath("gpu/stereobm/aloe-L.png"), cv::IMREAD_GRAYSCALE); + ASSERT_TRUE(!_img.empty()) << "can't open aloe-L.png"; + + UMat img; + _img.copyTo(img); + UMat edges(img.size(), CV_8UC1); + + declare.in(img, WARMUP_RNG).out(edges); + + OCL_TEST_CYCLE() cv::Canny(img, edges, 50.0, 100.0, apertureSize, L2Grad); + + SANITY_CHECK(edges); +} + + } } // namespace cvtest::ocl #endif // HAVE_OPENCL diff --git a/modules/ts/include/opencv2/ts/ocl_perf.hpp b/modules/ts/include/opencv2/ts/ocl_perf.hpp index 0024377df..37d28862e 100644 --- a/modules/ts/include/opencv2/ts/ocl_perf.hpp +++ b/modules/ts/include/opencv2/ts/ocl_perf.hpp @@ -57,19 +57,33 @@ using std::tr1::tuple; #define OCL_PERF_STRATEGY PERF_STRATEGY_SIMPLE +#define OCL_PERF_TEST(fixture, name) SIMPLE_PERF_TEST(fixture, name) #define OCL_PERF_TEST_P(fixture, name, params) SIMPLE_PERF_TEST_P(fixture, name, params) -#define SIMPLE_PERF_TEST_P(fixture, name, params)\ - class OCL##_##fixture##_##name : public fixture {\ - public:\ - OCL##_##fixture##_##name() {}\ - protected:\ - virtual void PerfTestBody();\ - };\ - TEST_P(OCL##_##fixture##_##name, name){ declare.strategy(OCL_PERF_STRATEGY); RunPerfTestBody(); }\ - INSTANTIATE_TEST_CASE_P(/*none*/, OCL##_##fixture##_##name, params);\ +#define SIMPLE_PERF_TEST(fixture, name) \ + class OCL##_##fixture##_##name : \ + public ::perf::TestBase \ + { \ + public: \ + OCL##_##fixture##_##name() { } \ + protected: \ + virtual void PerfTestBody(); \ + }; \ + TEST_F(OCL##_##fixture##_##name, name) { declare.strategy(OCL_PERF_STRATEGY); RunPerfTestBody(); } \ void OCL##_##fixture##_##name::PerfTestBody() +#define SIMPLE_PERF_TEST_P(fixture, name, params) \ + class OCL##_##fixture##_##name : \ + public fixture \ + { \ + public: \ + OCL##_##fixture##_##name() { } \ + protected: \ + virtual void PerfTestBody(); \ + }; \ + TEST_P(OCL##_##fixture##_##name, name) { declare.strategy(OCL_PERF_STRATEGY); RunPerfTestBody(); } \ + INSTANTIATE_TEST_CASE_P(/*none*/, OCL##_##fixture##_##name, params); \ + void OCL##_##fixture##_##name::PerfTestBody() #define OCL_SIZE_1 szVGA #define OCL_SIZE_2 sz720p From 24333569aa8096f863b115814c10f0917630040c Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Thu, 16 Jan 2014 11:09:25 +0200 Subject: [PATCH 069/295] Small fixes: typo, spacing and using ::ScreenToClient() instead of ::GetWindowRect() --- modules/highgui/include/opencv2/highgui.hpp | 6 +++--- modules/highgui/src/window_w32.cpp | 12 ++++-------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index 00e1ce427..068747068 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -76,9 +76,9 @@ enum { EVENT_MOUSEMOVE = 0, EVENT_MBUTTONUP = 6, EVENT_LBUTTONDBLCLK = 7, EVENT_RBUTTONDBLCLK = 8, - EVENT_MBUTTONDBLCLK =9, - EVENT_MOUSEWHEEL =10, - EVENT_MOUSEHWHEEL =11 + EVENT_MBUTTONDBLCLK = 9, + EVENT_MOUSEWHEEL = 10, + EVENT_MOUSEHWHEEL = 11 }; enum { EVENT_FLAG_LBUTTON = 1, diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index bb4704795..1e665ed02 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -40,7 +40,7 @@ //M*/ #include "precomp.hpp" -#include // required for GET_X_LPARAM() and GET_Y_LPARAM() marco +#include // required for GET_X_LPARAM() and GET_Y_LPARAM() macros #if defined WIN32 || defined _WIN32 @@ -1395,13 +1395,9 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) flags |= (delta << 16); POINT pt; - { - // since The coordinates are relative to screen so get screen size. - RECT windowRect; - ::GetWindowRect( window->hwnd, &windowRect ); - pt.x = GET_X_LPARAM( lParam ) - windowRect.left; - pt.y = GET_Y_LPARAM( lParam ) - windowRect.top; - } + pt.x = GET_X_LPARAM( lParam ); + pt.y = GET_Y_LPARAM( lParam ); + ::ScreenToClient(hwnd, &pt); // Convert screen coordinates to client coordinates. RECT rect; GetClientRect( window->hwnd, &rect ); From 8802d62cc5afd16987947ff4c0334e528141a4a4 Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Thu, 16 Jan 2014 11:25:57 +0200 Subject: [PATCH 070/295] Updated docs. --- modules/highgui/doc/user_interface.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/modules/highgui/doc/user_interface.rst b/modules/highgui/doc/user_interface.rst index 8b655a1c8..58b040b3f 100644 --- a/modules/highgui/doc/user_interface.rst +++ b/modules/highgui/doc/user_interface.rst @@ -208,6 +208,24 @@ Sets mouse handler for the specified window :param userdata: The optional parameter passed to the callback. +getMouseWheelDelta +------------------ +Gets the mouse-wheel motion delta, when handling mouse-wheel events EVENT_MOUSEWHEEL and EVENT_MOUSEHWHEEL. + +.. ocv:function:: int getMouseWheelDelta(int flags) + +.. ocv:cfunction:: CV_GET_WHEEL_DELTA(flags) + + :param flags: The mouse callback flags parameter. + + +For EVENT_MOUSEWHEEL positive and negative values mean forward and backward scrolling, respectively. +For EVENT_MOUSEHWHEEL, where available, positive and negative values mean right and left scrolling, respectively. + +.. note:: + + Mouse-wheel event are currently available only on Windows. On Windows Units are usually multiples of 120. + setTrackbarPos ------------------ Sets the trackbar position. From 46f06d82c9775b8572ded9cefd02c68cce61be00 Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Thu, 16 Jan 2014 12:51:14 +0200 Subject: [PATCH 071/295] Update docs. --- modules/highgui/doc/user_interface.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/highgui/doc/user_interface.rst b/modules/highgui/doc/user_interface.rst index 58b040b3f..2be7a67b3 100644 --- a/modules/highgui/doc/user_interface.rst +++ b/modules/highgui/doc/user_interface.rst @@ -218,13 +218,15 @@ Gets the mouse-wheel motion delta, when handling mouse-wheel events EVENT_MOUSEW :param flags: The mouse callback flags parameter. +For regular mice with a scroll-wheel, delta will be a multiple of 120. The value 120 corresponds to a one notch rotation of the wheel or the threshold for action to be taken and one such action should occur for each delta. +Some high-precision mice with higher-resolution freely-rotating wheels may generate smaller values. For EVENT_MOUSEWHEEL positive and negative values mean forward and backward scrolling, respectively. For EVENT_MOUSEHWHEEL, where available, positive and negative values mean right and left scrolling, respectively. .. note:: - Mouse-wheel event are currently available only on Windows. On Windows Units are usually multiples of 120. + Mouse-wheel events are currently supported only on Windows. setTrackbarPos ------------------ From b83eff7ecf0a3a8a9d706168150d569c94f0b71e Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Thu, 16 Jan 2014 16:18:02 +0400 Subject: [PATCH 072/295] replaced sprintf with cv::format --- .../calib3d/test/test_cameracalibration.cpp | 22 +++++++++---------- .../calib3d/test/test_chesscorners_timing.cpp | 12 +++++----- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib3d/test/test_cameracalibration.cpp index 7262e61a1..e9f58767b 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib3d/test/test_cameracalibration.cpp @@ -290,8 +290,8 @@ int CV_CameraCalibrationTest::compare(double* val, double* ref_val, int len, void CV_CameraCalibrationTest::run( int start_from ) { int code = cvtest::TS::OK; - char filepath[200]; - char filename[200]; + cv::String filepath; + cv::String filename; CvSize imageSize; CvSize etalonSize; @@ -337,9 +337,9 @@ void CV_CameraCalibrationTest::run( int start_from ) int progress = 0; int values_read = -1; - sprintf( filepath, "%scv/cameracalibration/", ts->get_data_path().c_str() ); - sprintf( filename, "%sdatafiles.txt", filepath ); - datafile = fopen( filename, "r" ); + filepath = cv::format("%scv/cameracalibration/", ts->get_data_path().c_str() ); + filename = cv::format("%sdatafiles.txt", filepath.c_str() ); + datafile = fopen( filename.c_str(), "r" ); if( datafile == 0 ) { ts->printf( cvtest::TS::LOG, "Could not open file with list of test files: %s\n", filename ); @@ -354,8 +354,8 @@ void CV_CameraCalibrationTest::run( int start_from ) { values_read = fscanf(datafile,"%s",i_dat_file); CV_Assert(values_read == 1); - sprintf(filename, "%s%s", filepath, i_dat_file); - file = fopen(filename,"r"); + filename = cv::format("%s%s", filepath.c_str(), i_dat_file); + file = fopen(filename.c_str(),"r"); ts->update_context( this, currTest, true ); @@ -1382,10 +1382,10 @@ void CV_StereoCalibrationTest::run( int ) for(int testcase = 1; testcase <= ntests; testcase++) { - char filepath[1000]; + cv::String filepath; char buf[1000]; - sprintf( filepath, "%scv/stereo/case%d/stereo_calib.txt", ts->get_data_path().c_str(), testcase ); - f = fopen(filepath, "rt"); + filepath = cv::format("%scv/stereo/case%d/stereo_calib.txt", ts->get_data_path().c_str(), testcase ); + f = fopen(filepath.c_str(), "rt"); Size patternSize; vector imglist; @@ -1405,7 +1405,7 @@ void CV_StereoCalibrationTest::run( int ) buf[--len] = '\0'; if( buf[0] == '#') continue; - sprintf(filepath, "%scv/stereo/case%d/%s", ts->get_data_path().c_str(), testcase, buf ); + filepath = cv::format("%scv/stereo/case%d/%s", ts->get_data_path().c_str(), testcase, buf ); imglist.push_back(string(filepath)); } fclose(f); diff --git a/modules/calib3d/test/test_chesscorners_timing.cpp b/modules/calib3d/test/test_chesscorners_timing.cpp index a990aea84..309e1efd6 100644 --- a/modules/calib3d/test/test_chesscorners_timing.cpp +++ b/modules/calib3d/test/test_chesscorners_timing.cpp @@ -62,8 +62,8 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) int code = cvtest::TS::OK; /* test parameters */ - char filepath[1000]; - char filename[1000]; + std::string filepath; + std::string filename; CvMat* _v = 0; CvPoint2D32f* v; @@ -75,9 +75,9 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) int idx, max_idx; int progress = 0; - sprintf( filepath, "%scv/cameracalibration/", ts->get_data_path().c_str() ); - sprintf( filename, "%schessboard_timing_list.dat", filepath ); - CvFileStorage* fs = cvOpenFileStorage( filename, 0, CV_STORAGE_READ ); + filepath = cv::format("%scv/cameracalibration/", ts->get_data_path().c_str() ); + filename = cv::format("%schessboard_timing_list.dat", filepath.c_str() ); + CvFileStorage* fs = cvOpenFileStorage( filename.c_str(), 0, CV_STORAGE_READ ); CvFileNode* board_list = fs ? cvGetFileNodeByName( fs, 0, "boards" ) : 0; if( !fs || !board_list || !CV_NODE_IS_SEQ(board_list->tag) || @@ -105,7 +105,7 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) ts->update_context( this, idx-1, true ); /* read the image */ - sprintf( filename, "%s%s", filepath, imgname ); + filename = cv::format("%s%s", filepath.c_str(), imgname ); cv::Mat img2 = cv::imread( filename ); img = img2; From 63c61b4b988d27aab04a994a4573ecaaae9b6242 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Thu, 16 Jan 2014 17:58:26 +0400 Subject: [PATCH 073/295] Revert "replaced sprintf with cv::format" Fixing build breakage. This reverts commit b83eff7ecf0a3a8a9d706168150d569c94f0b71e. --- .../calib3d/test/test_cameracalibration.cpp | 22 +++++++++---------- .../calib3d/test/test_chesscorners_timing.cpp | 12 +++++----- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib3d/test/test_cameracalibration.cpp index e9f58767b..7262e61a1 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib3d/test/test_cameracalibration.cpp @@ -290,8 +290,8 @@ int CV_CameraCalibrationTest::compare(double* val, double* ref_val, int len, void CV_CameraCalibrationTest::run( int start_from ) { int code = cvtest::TS::OK; - cv::String filepath; - cv::String filename; + char filepath[200]; + char filename[200]; CvSize imageSize; CvSize etalonSize; @@ -337,9 +337,9 @@ void CV_CameraCalibrationTest::run( int start_from ) int progress = 0; int values_read = -1; - filepath = cv::format("%scv/cameracalibration/", ts->get_data_path().c_str() ); - filename = cv::format("%sdatafiles.txt", filepath.c_str() ); - datafile = fopen( filename.c_str(), "r" ); + sprintf( filepath, "%scv/cameracalibration/", ts->get_data_path().c_str() ); + sprintf( filename, "%sdatafiles.txt", filepath ); + datafile = fopen( filename, "r" ); if( datafile == 0 ) { ts->printf( cvtest::TS::LOG, "Could not open file with list of test files: %s\n", filename ); @@ -354,8 +354,8 @@ void CV_CameraCalibrationTest::run( int start_from ) { values_read = fscanf(datafile,"%s",i_dat_file); CV_Assert(values_read == 1); - filename = cv::format("%s%s", filepath.c_str(), i_dat_file); - file = fopen(filename.c_str(),"r"); + sprintf(filename, "%s%s", filepath, i_dat_file); + file = fopen(filename,"r"); ts->update_context( this, currTest, true ); @@ -1382,10 +1382,10 @@ void CV_StereoCalibrationTest::run( int ) for(int testcase = 1; testcase <= ntests; testcase++) { - cv::String filepath; + char filepath[1000]; char buf[1000]; - filepath = cv::format("%scv/stereo/case%d/stereo_calib.txt", ts->get_data_path().c_str(), testcase ); - f = fopen(filepath.c_str(), "rt"); + sprintf( filepath, "%scv/stereo/case%d/stereo_calib.txt", ts->get_data_path().c_str(), testcase ); + f = fopen(filepath, "rt"); Size patternSize; vector imglist; @@ -1405,7 +1405,7 @@ void CV_StereoCalibrationTest::run( int ) buf[--len] = '\0'; if( buf[0] == '#') continue; - filepath = cv::format("%scv/stereo/case%d/%s", ts->get_data_path().c_str(), testcase, buf ); + sprintf(filepath, "%scv/stereo/case%d/%s", ts->get_data_path().c_str(), testcase, buf ); imglist.push_back(string(filepath)); } fclose(f); diff --git a/modules/calib3d/test/test_chesscorners_timing.cpp b/modules/calib3d/test/test_chesscorners_timing.cpp index 309e1efd6..a990aea84 100644 --- a/modules/calib3d/test/test_chesscorners_timing.cpp +++ b/modules/calib3d/test/test_chesscorners_timing.cpp @@ -62,8 +62,8 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) int code = cvtest::TS::OK; /* test parameters */ - std::string filepath; - std::string filename; + char filepath[1000]; + char filename[1000]; CvMat* _v = 0; CvPoint2D32f* v; @@ -75,9 +75,9 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) int idx, max_idx; int progress = 0; - filepath = cv::format("%scv/cameracalibration/", ts->get_data_path().c_str() ); - filename = cv::format("%schessboard_timing_list.dat", filepath.c_str() ); - CvFileStorage* fs = cvOpenFileStorage( filename.c_str(), 0, CV_STORAGE_READ ); + sprintf( filepath, "%scv/cameracalibration/", ts->get_data_path().c_str() ); + sprintf( filename, "%schessboard_timing_list.dat", filepath ); + CvFileStorage* fs = cvOpenFileStorage( filename, 0, CV_STORAGE_READ ); CvFileNode* board_list = fs ? cvGetFileNodeByName( fs, 0, "boards" ) : 0; if( !fs || !board_list || !CV_NODE_IS_SEQ(board_list->tag) || @@ -105,7 +105,7 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) ts->update_context( this, idx-1, true ); /* read the image */ - filename = cv::format("%s%s", filepath.c_str(), imgname ); + sprintf( filename, "%s%s", filepath, imgname ); cv::Mat img2 = cv::imread( filename ); img = img2; From 8fd0fd538d567828bfd12861493c69f407b9dc23 Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Thu, 16 Jan 2014 16:30:54 +0200 Subject: [PATCH 074/295] Doc fix. --- modules/highgui/doc/user_interface.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/highgui/doc/user_interface.rst b/modules/highgui/doc/user_interface.rst index 2be7a67b3..0d0ccde94 100644 --- a/modules/highgui/doc/user_interface.rst +++ b/modules/highgui/doc/user_interface.rst @@ -214,8 +214,6 @@ Gets the mouse-wheel motion delta, when handling mouse-wheel events EVENT_MOUSEW .. ocv:function:: int getMouseWheelDelta(int flags) -.. ocv:cfunction:: CV_GET_WHEEL_DELTA(flags) - :param flags: The mouse callback flags parameter. For regular mice with a scroll-wheel, delta will be a multiple of 120. The value 120 corresponds to a one notch rotation of the wheel or the threshold for action to be taken and one such action should occur for each delta. @@ -224,6 +222,8 @@ Some high-precision mice with higher-resolution freely-rotating wheels may gener For EVENT_MOUSEWHEEL positive and negative values mean forward and backward scrolling, respectively. For EVENT_MOUSEHWHEEL, where available, positive and negative values mean right and left scrolling, respectively. +With the C API, the macro CV_GET_WHEEL_DELTA(flags) can be used alternatively. + .. note:: Mouse-wheel events are currently supported only on Windows. From 8ce691e67966954cbab1e61f123f8206a42b1e90 Mon Sep 17 00:00:00 2001 From: Daniil Osokin Date: Mon, 13 Jan 2014 14:20:42 +0400 Subject: [PATCH 075/295] Fixed cvtColor alpha channel docs --- modules/imgproc/doc/miscellaneous_transformations.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/imgproc/doc/miscellaneous_transformations.rst b/modules/imgproc/doc/miscellaneous_transformations.rst index e3c459d68..515d6128f 100644 --- a/modules/imgproc/doc/miscellaneous_transformations.rst +++ b/modules/imgproc/doc/miscellaneous_transformations.rst @@ -113,6 +113,8 @@ But in case of a non-linear transformation, an input RGB image should be normali If you use ``cvtColor`` with 8-bit images, the conversion will have some information lost. For many applications, this will not be noticeable but it is recommended to use 32-bit images in applications that need the full range of colors or that convert an image before an operation and then convert back. +If conversion adds the alpha channel, its value will set to the maximum of corresponding channel range: 255 for ``CV_8U``, 65535 for ``CV_16U``, 1 for ``CV_32F``. + The function can do the following transformations: * @@ -127,7 +129,7 @@ The function can do the following transformations: .. math:: - \text{Gray to RGB[A]:} \quad R \leftarrow Y, G \leftarrow Y, B \leftarrow Y, A \leftarrow 0 + \text{Gray to RGB[A]:} \quad R \leftarrow Y, G \leftarrow Y, B \leftarrow Y, A \leftarrow \max (ChannelRange) The conversion from a RGB image to gray is done with: From 63a5e39e2cb9aad19695c29e3e4c480659ff18c8 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 16 Jan 2014 20:52:45 +0400 Subject: [PATCH 076/295] added cv::reduce to T-API --- modules/core/src/matrix.cpp | 72 +++++++++++-- modules/core/src/opencl/reduce2.cl | 148 ++++++++++++++++++++++++++ modules/core/src/umatrix.cpp | 3 +- modules/core/test/ocl/test_arithm.cpp | 136 +++++++++++++++++++++++ 4 files changed, 350 insertions(+), 9 deletions(-) create mode 100644 modules/core/src/opencl/reduce2.cl diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 595a62dd5..f51391985 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -2976,23 +2976,79 @@ typedef void (*ReduceFunc)( const Mat& src, Mat& dst ); #define reduceMinC32f reduceC_ > #define reduceMinC64f reduceC_ > +namespace cv { + +static bool ocl_reduce(InputArray _src, OutputArray _dst, + int dim, int op, int op0, int stype, int dtype) +{ + int sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype), + ddepth = CV_MAT_DEPTH(dtype), ddepth0 = ddepth; + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; + + if (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F)) + return false; + + if (op == CV_REDUCE_AVG) + { + op = CV_REDUCE_SUM; + if (sdepth < CV_32S && ddepth < CV_32S) + ddepth = CV_32S; + } + + const char * const ops[4] = { "OCL_CV_REDUCE_SUM", "OCL_CV_REDUCE_AVG", + "OCL_CV_REDUCE_MAX", "OCL_CV_REDUCE_MIN" }; + char cvt[40]; + ocl::Kernel k("reduce", ocl::core::reduce2_oclsrc, + format("-D %s -D dim=%d -D cn=%d -D ddepth=%d -D srcT=%s -D dstT=%s -D convertToDT=%s%s", + ops[op], dim, cn, ddepth, ocl::typeToStr(sdepth), ocl::typeToStr(ddepth), + ocl::convertTypeStr(sdepth, ddepth, 1, cvt), + doubleSupport ? " -D DOUBLE_SUPPORT" : "")); + if (k.empty()) + return false; + + UMat src = _src.getUMat(); + Size dsize(dim == 0 ? src.cols : 1, dim == 0 ? 1 : src.rows); + _dst.create(dsize, dtype); + UMat dst = _dst.getUMat(), temp = dst; + + if (op0 == CV_REDUCE_AVG && sdepth < CV_32S && ddepth0 < CV_32S) + temp.create(dsize, CV_32SC(cn)); + + size_t globalsize = std::max(dsize.width, dsize.height); + + k.args(ocl::KernelArg::ReadOnly(src), + ocl::KernelArg::WriteOnlyNoSize(temp)); + if (!k.run(1, &globalsize, NULL, false)) + return false; + + if (op0 == CV_REDUCE_AVG) + temp.convertTo(dst, ddepth0, 1. / (dim == 0 ? src.rows : src.cols)); + + return true; +} + +} + void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype) { - Mat src = _src.getMat(); - CV_Assert( src.dims <= 2 ); + CV_Assert( _src.dims() <= 2 ); int op0 = op; - int stype = src.type(), sdepth = src.depth(), cn = src.channels(); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if( dtype < 0 ) dtype = _dst.fixedType() ? _dst.type() : stype; int ddepth = CV_MAT_DEPTH(dtype); - _dst.create(dim == 0 ? 1 : src.rows, dim == 0 ? src.cols : 1, - CV_MAKETYPE(dtype >= 0 ? dtype : stype, cn)); - Mat dst = _dst.getMat(), temp = dst; - + CV_Assert( cn == CV_MAT_CN(dtype) ); CV_Assert( op == CV_REDUCE_SUM || op == CV_REDUCE_MAX || op == CV_REDUCE_MIN || op == CV_REDUCE_AVG ); - CV_Assert( src.channels() == dst.channels() ); + + if (ocl::useOpenCL() && _dst.isUMat() && + ocl_reduce(_src, _dst, dim, op, op0, stype, dtype)) + return; + + Mat src = _src.getMat(); + _dst.create(dim == 0 ? 1 : src.rows, dim == 0 ? src.cols : 1, dtype); + Mat dst = _dst.getMat(), temp = dst; if( op == CV_REDUCE_AVG ) { diff --git a/modules/core/src/opencl/reduce2.cl b/modules/core/src/opencl/reduce2.cl new file mode 100644 index 000000000..f8ff6a2e1 --- /dev/null +++ b/modules/core/src/opencl/reduce2.cl @@ -0,0 +1,148 @@ +/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// 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 copyright holders 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*/ + +#ifdef DOUBLE_SUPPORT +#ifdef cl_amd_fp64 +#pragma OPENCL EXTENSION cl_amd_fp64:enable +#elif defined (cl_khr_fp64) +#pragma OPENCL EXTENSION cl_khr_fp64:enable +#endif +#endif + +#if ddepth == 0 +#define MIN_VAL 0 +#define MAX_VAL 255 +#elif ddepth == 1 +#define MIN_VAL -128 +#define MAX_VAL 127 +#elif ddepth == 2 +#define MIN_VAL 0 +#define MAX_VAL 65535 +#elif ddepth == 3 +#define MIN_VAL -32768 +#define MAX_VAL 32767 +#elif ddepth == 4 +#define MIN_VAL INT_MIN +#define MAX_VAL INT_MAX +#elif ddepth == 5 +#define MIN_VAL (-FLT_MAX) +#define MAX_VAL FLT_MAX +#elif ddepth == 6 +#define MIN_VAL (-DBL_MAX) +#define MAX_VAL DBL_MAX +#else +#error "Unsupported depth" +#endif + +#define noconvert + +#ifdef OCL_CV_REDUCE_SUM +#define INIT_VALUE 0 +#define PROCESS_ELEM(acc, value) acc += value +#elif defined(OCL_CV_REDUCE_MAX) +#define INIT_VALUE MIN_VAL +#define PROCESS_ELEM(acc, value) acc = value > acc ? value : acc +#elif defined(OCL_CV_REDUCE_MIN) +#define INIT_VALUE MAX_VAL +#define PROCESS_ELEM(acc, value) acc = value < acc ? value : acc +#elif defined(OCL_CV_REDUCE_AVG) +#error "This operation should be implemented through OCL_CV_REDUCE_SUM" +#else +#error "No operation is specified" +#endif + +__kernel void reduce(__global const uchar * srcptr, int src_step, int src_offset, int rows, int cols, + __global uchar * dstptr, int dst_step, int dst_offset) +{ +#if dim == 0 // reduce to a single row + int x = get_global_id(0); + if (x < cols) + { + int src_index = x * (int)sizeof(srcT) * cn + src_offset; + __global dstT * dst = (__global dstT *)(dstptr + dst_offset) + x * cn; + dstT tmp[cn] = { INIT_VALUE }; + + for (int y = 0; y < rows; ++y, src_index += src_step) + { + __global const srcT * src = (__global const srcT *)(srcptr + src_index); + #pragma unroll + for (int c = 0; c < cn; ++c) + { + dstT value = convertToDT(src[c]); + PROCESS_ELEM(tmp[c], value); + } + } + + #pragma unroll + for (int c = 0; c < cn; ++c) + dst[c] = tmp[c]; + } +#elif dim == 1 // reduce to a single column + int y = get_global_id(0); + if (y < rows) + { + int src_index = mad24(y, src_step, src_offset); + int dst_index = mad24(y, dst_step, dst_offset); + + __global const srcT * src = (__global const srcT *)(srcptr + src_index); + __global dstT * dst = (__global dstT *)(dstptr + dst_index); + dstT tmp[cn] = { INIT_VALUE }; + + for (int x = 0; x < cols; ++x, src += cn) + { + #pragma unroll + for (int c = 0; c < cn; ++c) + { + dstT value = convertToDT(src[c]); + PROCESS_ELEM(tmp[c], value); + } + } + + #pragma unroll + for (int c = 0; c < cn; ++c) + dst[c] = tmp[c]; + } +#else +#error "Dims must be either 0 or 1" +#endif +} diff --git a/modules/core/src/umatrix.cpp b/modules/core/src/umatrix.cpp index 95e203be9..997c88117 100644 --- a/modules/core/src/umatrix.cpp +++ b/modules/core/src/umatrix.cpp @@ -729,11 +729,12 @@ void UMat::convertTo(OutputArray _dst, int _type, double alpha, double beta) con doubleSupport ? " -D DOUBLE_SUPPORT" : "")); if (!k.empty()) { + UMat src = *this; _dst.create( size(), _type ); UMat dst = _dst.getUMat(); float alphaf = (float)alpha, betaf = (float)beta; - k.args(ocl::KernelArg::ReadOnlyNoSize(*this), ocl::KernelArg::WriteOnly(dst, cn), alphaf, betaf); + k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst, cn), alphaf, betaf); size_t globalsize[2] = { dst.cols * cn, dst.rows }; if (k.run(2, globalsize, NULL, false)) diff --git a/modules/core/test/ocl/test_arithm.cpp b/modules/core/test/ocl/test_arithm.cpp index ff85e6c24..87442bbee 100644 --- a/modules/core/test/ocl/test_arithm.cpp +++ b/modules/core/test/ocl/test_arithm.cpp @@ -1566,6 +1566,106 @@ OCL_TEST_P(Psnr, Mat) } } +//////////////////////////////////////// Reduce ///////////////////////////////////////////// + +PARAM_TEST_CASE(Reduce, std::pair, Channels, int, bool) +{ + int sdepth, ddepth, cn, dim, dtype; + bool use_roi; + + TEST_DECLARE_INPUT_PARAMETER(src) + TEST_DECLARE_OUTPUT_PARAMETER(dst) + + virtual void SetUp() + { + const std::pair p = GET_PARAM(0); + sdepth = p.first; + ddepth = p.second; + cn = GET_PARAM(1); + dim = GET_PARAM(2); + use_roi = GET_PARAM(3); + } + + virtual void generateTestData() + { + const int stype = CV_MAKE_TYPE(sdepth, cn); + dtype = CV_MAKE_TYPE(ddepth, cn); + + Size roiSize = randomSize(1, MAX_VALUE); + Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, stype, -40, 40); + + Size dstRoiSize = Size(dim == 0 ? roiSize.width : 1, dim == 0 ? 1 : roiSize.height); + Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst, dst_roi, dstRoiSize, dstBorder, dtype, 5, 16); + + UMAT_UPLOAD_INPUT_PARAMETER(src) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst) + } +}; + +typedef Reduce ReduceSum; + +OCL_TEST_P(ReduceSum, Mat) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::reduce(src_roi, dst_roi, dim, CV_REDUCE_SUM, dtype)); + OCL_ON(cv::reduce(usrc_roi, udst_roi, dim, CV_REDUCE_SUM, dtype)); + + double eps = ddepth <= CV_32S ? 1 : 5e-5; + OCL_EXPECT_MATS_NEAR(dst, eps) + } +} + +typedef Reduce ReduceMax; + +OCL_TEST_P(ReduceMax, Mat) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::reduce(src_roi, dst_roi, dim, CV_REDUCE_MAX, dtype)); + OCL_ON(cv::reduce(usrc_roi, udst_roi, dim, CV_REDUCE_MAX, dtype)); + + OCL_EXPECT_MATS_NEAR(dst, 0) + } +} + +typedef Reduce ReduceMin; + +OCL_TEST_P(ReduceMin, Mat) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::reduce(src_roi, dst_roi, dim, CV_REDUCE_MIN, dtype)); + OCL_ON(cv::reduce(usrc_roi, udst_roi, dim, CV_REDUCE_MIN, dtype)); + + OCL_EXPECT_MATS_NEAR(dst, 0) + } +} + +typedef Reduce ReduceAvg; + +OCL_TEST_P(ReduceAvg, Mat) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::reduce(src_roi, dst_roi, dim, CV_REDUCE_AVG, dtype)); + OCL_ON(cv::reduce(usrc_roi, udst_roi, dim, CV_REDUCE_AVG, dtype)); + + double eps = ddepth <= CV_32S ? 1 : 5e-6; + OCL_EXPECT_MATS_NEAR(dst, eps) + } +} + //////////////////////////////////////// Instantiation ///////////////////////////////////////// OCL_INSTANTIATE_TEST_CASE_P(Arithm, Lut, Combine(::testing::Values(CV_8U, CV_8S), OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool(), Bool())); @@ -1607,6 +1707,42 @@ OCL_INSTANTIATE_TEST_CASE_P(Arithm, ScaleAdd, Combine(OCL_ALL_DEPTHS, OCL_ALL_CH OCL_INSTANTIATE_TEST_CASE_P(Arithm, PatchNaNs, Combine(OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Arithm, Psnr, Combine(::testing::Values((MatDepth)CV_8U), OCL_ALL_CHANNELS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Arithm, ReduceSum, Combine(testing::Values(std::make_pair(CV_8U, CV_32S), + std::make_pair(CV_8U, CV_32F), + std::make_pair(CV_8U, CV_64F), + std::make_pair(CV_16U, CV_32F), + std::make_pair(CV_16U, CV_64F), + std::make_pair(CV_16S, CV_32F), + std::make_pair(CV_16S, CV_64F), + std::make_pair(CV_32F, CV_32F), + std::make_pair(CV_32F, CV_64F), + std::make_pair(CV_64F, CV_64F)), + OCL_ALL_CHANNELS, testing::Values(0, 1), Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Arithm, ReduceAvg, Combine(testing::Values(std::make_pair(CV_8U, CV_32S), + std::make_pair(CV_8U, CV_32F), + std::make_pair(CV_8U, CV_64F), + std::make_pair(CV_16U, CV_32F), + std::make_pair(CV_16U, CV_64F), + std::make_pair(CV_16S, CV_32F), + std::make_pair(CV_16S, CV_64F), + std::make_pair(CV_32F, CV_32F), + std::make_pair(CV_32F, CV_64F), + std::make_pair(CV_64F, CV_64F)), + OCL_ALL_CHANNELS, testing::Values(0, 1), Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Arithm, ReduceMax, Combine(testing::Values(std::make_pair(CV_8U, CV_8U), + std::make_pair(CV_16U, CV_16U), + std::make_pair(CV_16S, CV_16S), + std::make_pair(CV_32F, CV_32F), + std::make_pair(CV_64F, CV_64F)), + OCL_ALL_CHANNELS, testing::Values(0, 1), Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Arithm, ReduceMin, Combine(testing::Values(std::make_pair(CV_8U, CV_8U), + std::make_pair(CV_16U, CV_16U), + std::make_pair(CV_16S, CV_16S), + std::make_pair(CV_32F, CV_32F), + std::make_pair(CV_64F, CV_64F)), + OCL_ALL_CHANNELS, testing::Values(0, 1), Bool())); + + } } // namespace cvtest::ocl #endif // HAVE_OPENCL From 711f07a34ceb504e8f75e978692201efa58268ca Mon Sep 17 00:00:00 2001 From: Dinar Valeev Date: Thu, 16 Jan 2014 21:53:49 +0100 Subject: [PATCH 077/295] Use __vector instead of vector as suggests Eigen This fixes build on PowerPC where Eigen unsets vector, bool and pixel Signed-off-by: Dinar Valeev --- 3rdparty/include/opencl/1.2/CL/cl_platform.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/3rdparty/include/opencl/1.2/CL/cl_platform.h b/3rdparty/include/opencl/1.2/CL/cl_platform.h index e94949a31..42c35d5ce 100644 --- a/3rdparty/include/opencl/1.2/CL/cl_platform.h +++ b/3rdparty/include/opencl/1.2/CL/cl_platform.h @@ -332,13 +332,13 @@ typedef unsigned int cl_GLenum; /* Define basic vector types */ #if defined( __VEC__ ) #include /* may be omitted depending on compiler. AltiVec spec provides no way to detect whether the header is required. */ - typedef vector unsigned char __cl_uchar16; - typedef vector signed char __cl_char16; - typedef vector unsigned short __cl_ushort8; - typedef vector signed short __cl_short8; - typedef vector unsigned int __cl_uint4; - typedef vector signed int __cl_int4; - typedef vector float __cl_float4; + typedef __vector unsigned char __cl_uchar16; + typedef __vector signed char __cl_char16; + typedef __vector unsigned short __cl_ushort8; + typedef __vector signed short __cl_short8; + typedef __vector unsigned int __cl_uint4; + typedef __vector signed int __cl_int4; + typedef __vector float __cl_float4; #define __CL_UCHAR16__ 1 #define __CL_CHAR16__ 1 #define __CL_USHORT8__ 1 From 93a818684cd0d2403dcafec392c0e44aba6bf1ed Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 14 Jan 2014 14:10:24 +0400 Subject: [PATCH 078/295] ported cv::Canny to T-API --- modules/core/include/opencv2/core/mat.hpp | 1 + modules/core/include/opencv2/core/mat.inl.hpp | 6 + .../core/include/opencv2/core/operations.hpp | 6 + modules/core/src/matrix.cpp | 31 ++ modules/core/src/umatrix.cpp | 3 +- modules/imgproc/perf/opencl/perf_imgproc.cpp | 5 +- modules/imgproc/src/canny.cpp | 171 +++++- modules/imgproc/src/opencl/canny.cl | 514 ++++++++++++++++++ modules/imgproc/test/ocl/test_canny.cpp | 117 ++++ modules/ts/include/opencv2/ts/ocl_test.hpp | 20 +- 10 files changed, 852 insertions(+), 22 deletions(-) create mode 100644 modules/imgproc/src/opencl/canny.cl create mode 100644 modules/imgproc/test/ocl/test_canny.cpp diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 401467534..a7a4f1b8e 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -127,6 +127,7 @@ public: virtual int depth(int i=-1) const; virtual int channels(int i=-1) const; virtual bool isContinuous(int i=-1) const; + virtual bool isSubmatrix(int i=-1) const; virtual bool empty() const; virtual void copyTo(const _OutputArray& arr) const; virtual size_t offset(int i=-1) const; diff --git a/modules/core/include/opencv2/core/mat.inl.hpp b/modules/core/include/opencv2/core/mat.inl.hpp index 307954896..10eac9141 100644 --- a/modules/core/include/opencv2/core/mat.inl.hpp +++ b/modules/core/include/opencv2/core/mat.inl.hpp @@ -186,6 +186,12 @@ inline _OutputArray::_OutputArray(const Mat& m) inline _OutputArray::_OutputArray(const std::vector& vec) { init(FIXED_SIZE + STD_VECTOR_MAT + ACCESS_WRITE, &vec); } +inline _OutputArray::_OutputArray(const UMat& m) +{ init(FIXED_TYPE + FIXED_SIZE + UMAT + ACCESS_WRITE, &m); } + +inline _OutputArray::_OutputArray(const std::vector& vec) +{ init(FIXED_SIZE + STD_VECTOR_UMAT + ACCESS_WRITE, &vec); } + inline _OutputArray::_OutputArray(const cuda::GpuMat& d_mat) { init(FIXED_TYPE + FIXED_SIZE + GPU_MAT + ACCESS_WRITE, &d_mat); } diff --git a/modules/core/include/opencv2/core/operations.hpp b/modules/core/include/opencv2/core/operations.hpp index 5895e4c4a..d2f49d7ee 100644 --- a/modules/core/include/opencv2/core/operations.hpp +++ b/modules/core/include/opencv2/core/operations.hpp @@ -423,6 +423,12 @@ int print(const Mat& mtx, FILE* stream = stdout) return print(Formatter::get()->format(mtx), stream); } +static inline +int print(const UMat& mtx, FILE* stream = stdout) +{ + return print(Formatter::get()->format(mtx.getMat(ACCESS_READ)), stream); +} + template static inline int print(const std::vector >& vec, FILE* stream = stdout) { diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 595a62dd5..ade9e3522 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -1808,6 +1808,37 @@ bool _InputArray::isContinuous(int i) const return false; } +bool _InputArray::isSubmatrix(int i) const +{ + int k = kind(); + + if( k == MAT ) + return i < 0 ? ((const Mat*)obj)->isSubmatrix() : false; + + if( k == UMAT ) + return i < 0 ? ((const UMat*)obj)->isSubmatrix() : false; + + if( k == EXPR || k == MATX || k == STD_VECTOR || k == NONE || k == STD_VECTOR_VECTOR) + return false; + + if( k == STD_VECTOR_MAT ) + { + const std::vector& vv = *(const std::vector*)obj; + CV_Assert((size_t)i < vv.size()); + return vv[i].isSubmatrix(); + } + + if( k == STD_VECTOR_UMAT ) + { + const std::vector& vv = *(const std::vector*)obj; + CV_Assert((size_t)i < vv.size()); + return vv[i].isSubmatrix(); + } + + CV_Error(CV_StsNotImplemented, ""); + return false; +} + size_t _InputArray::offset(int i) const { int k = kind(); diff --git a/modules/core/src/umatrix.cpp b/modules/core/src/umatrix.cpp index 95e203be9..997c88117 100644 --- a/modules/core/src/umatrix.cpp +++ b/modules/core/src/umatrix.cpp @@ -729,11 +729,12 @@ void UMat::convertTo(OutputArray _dst, int _type, double alpha, double beta) con doubleSupport ? " -D DOUBLE_SUPPORT" : "")); if (!k.empty()) { + UMat src = *this; _dst.create( size(), _type ); UMat dst = _dst.getUMat(); float alphaf = (float)alpha, betaf = (float)beta; - k.args(ocl::KernelArg::ReadOnlyNoSize(*this), ocl::KernelArg::WriteOnly(dst, cn), alphaf, betaf); + k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst, cn), alphaf, betaf); size_t globalsize[2] = { dst.cols * cn, dst.rows }; if (k.run(2, globalsize, NULL, false)) diff --git a/modules/imgproc/perf/opencl/perf_imgproc.cpp b/modules/imgproc/perf/opencl/perf_imgproc.cpp index 7c102fa21..fa82b7aa4 100644 --- a/modules/imgproc/perf/opencl/perf_imgproc.cpp +++ b/modules/imgproc/perf/opencl/perf_imgproc.cpp @@ -234,7 +234,10 @@ OCL_PERF_TEST_P(CannyFixture, Canny, ::testing::Combine(OCL_PERF_ENUM(3, 5), Boo OCL_TEST_CYCLE() cv::Canny(img, edges, 50.0, 100.0, apertureSize, L2Grad); - SANITY_CHECK(edges); + if (apertureSize == 3) + SANITY_CHECK(edges); + else + SANITY_CHECK_NOTHING(); } diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 44fd42a2a..b52ca46de 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -40,6 +40,7 @@ //M*/ #include "precomp.hpp" +#include "opencl_kernels.hpp" /* #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) @@ -48,9 +49,11 @@ #undef USE_IPP_CANNY #endif */ -#ifdef USE_IPP_CANNY + namespace cv { + +#ifdef USE_IPP_CANNY static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high) { int size = 0, size1 = 0; @@ -83,22 +86,165 @@ static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high) return false; return true; } -} #endif +static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float high_thresh, + int aperture_size, bool L2gradient, int cn, const Size & size) +{ + UMat dx(size, CV_16SC(cn)), dy(size, CV_16SC(cn)); + + if (L2gradient) + { + low_thresh = std::min(32767.0f, low_thresh); + high_thresh = std::min(32767.0f, high_thresh); + + if (low_thresh > 0) low_thresh *= low_thresh; + if (high_thresh > 0) high_thresh *= high_thresh; + } + int low = cvFloor(low_thresh), high = cvFloor(high_thresh); + Size esize(size.width + 2, size.height + 2); + + UMat mag; + size_t globalsize[2] = { size.width * cn, size.height }, localsize[2] = { 16, 16 }; + + if (aperture_size == 3 && !_src.isSubmatrix()) + { + // Sobel calculation + ocl::Kernel calcSobelRowPassKernel("calcSobelRowPass", ocl::imgproc::canny_oclsrc); + if (calcSobelRowPassKernel.empty()) + return false; + + UMat src = _src.getUMat(), dxBuf(size, CV_16SC(cn)), dyBuf(size, CV_16SC(cn)); + calcSobelRowPassKernel.args(ocl::KernelArg::ReadOnly(src), + ocl::KernelArg::WriteOnlyNoSize(dxBuf), + ocl::KernelArg::WriteOnlyNoSize(dyBuf)); + + if (!calcSobelRowPassKernel.run(2, globalsize, localsize, false)) + return false; + + // magnitude calculation + ocl::Kernel magnitudeKernel("calcMagnitude_buf", ocl::imgproc::canny_oclsrc, + L2gradient ? " -D L2GRAD" : ""); + if (magnitudeKernel.empty()) + return false; + + mag = UMat(esize, CV_32SC(cn), Scalar::all(0)); + dx.create(size, CV_16SC(cn)); + dy.create(size, CV_16SC(cn)); + + magnitudeKernel.args(ocl::KernelArg::ReadOnlyNoSize(dxBuf), ocl::KernelArg::ReadOnlyNoSize(dyBuf), + ocl::KernelArg::WriteOnlyNoSize(dx), ocl::KernelArg::WriteOnlyNoSize(dy), + ocl::KernelArg::WriteOnlyNoSize(mag, cn), size.height, size.width); + + if (!magnitudeKernel.run(2, globalsize, localsize, false)) + return false; + } + else + { + dx.create(size, CV_16SC(cn)); + dy.create(size, CV_16SC(cn)); + + Sobel(_src, dx, CV_16SC1, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE); + Sobel(_src, dy, CV_16SC1, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE); + + // magnitude calculation + ocl::Kernel magnitudeKernel("calcMagnitude", ocl::imgproc::canny_oclsrc, + L2gradient ? " -D L2GRAD" : ""); + if (magnitudeKernel.empty()) + return false; + + mag = UMat(esize, CV_32SC(cn), Scalar::all(0)); + magnitudeKernel.args(ocl::KernelArg::ReadOnlyNoSize(dx), ocl::KernelArg::ReadOnlyNoSize(dy), + ocl::KernelArg::WriteOnlyNoSize(mag, cn), size.height, size.width); + + if (!magnitudeKernel.run(2, globalsize, NULL, false)) + return false; + } + + // map calculation + ocl::Kernel calcMapKernel("calcMap", ocl::imgproc::canny_oclsrc); + if (calcMapKernel.empty()) + return false; + + UMat map(esize, CV_32SC(cn)); + calcMapKernel.args(ocl::KernelArg::ReadOnlyNoSize(dx), ocl::KernelArg::ReadOnlyNoSize(dy), + ocl::KernelArg::ReadOnlyNoSize(mag), ocl::KernelArg::WriteOnlyNoSize(map, cn), + size.height, size.width, low, high); + + if (!calcMapKernel.run(2, globalsize, localsize, false)) + return false; + + // local hysteresis thresholding + ocl::Kernel edgesHysteresisLocalKernel("edgesHysteresisLocal", ocl::imgproc::canny_oclsrc); + if (edgesHysteresisLocalKernel.empty()) + return false; + + UMat stack(1, size.area(), CV_16UC2), counter(1, 1, CV_32SC1, Scalar::all(0)); + edgesHysteresisLocalKernel.args(ocl::KernelArg::ReadOnlyNoSize(map), ocl::KernelArg::PtrReadWrite(stack), + ocl::KernelArg::PtrReadWrite(counter), size.height, size.width); + if (!edgesHysteresisLocalKernel.run(2, globalsize, localsize, false)) + return false; + + // global hysteresis thresholding + UMat stack2(1, size.area(), CV_16UC2); + int count; + + for ( ; ; ) + { + ocl::Kernel edgesHysteresisGlobalKernel("edgesHysteresisGlobal", ocl::imgproc::canny_oclsrc); + if (edgesHysteresisGlobalKernel.empty()) + return false; + + { + Mat _counter = counter.getMat(ACCESS_RW); + count = _counter.at(0, 0); + if (count == 0) + break; + + _counter.at(0, 0) = 0; + } + + edgesHysteresisGlobalKernel.args(ocl::KernelArg::ReadOnlyNoSize(map), ocl::KernelArg::PtrReadWrite(stack), + ocl::KernelArg::PtrReadWrite(stack2), ocl::KernelArg::PtrReadWrite(counter), + size.height, size.width, count); + +#define divUp(total, grain) ((total + grain - 1) / grain) + size_t localsize2[2] = { 128, 1 }, globalsize2[2] = { std::min(count, 65535) * 128, divUp(count, 65535) }; +#undef divUp + + if (!edgesHysteresisGlobalKernel.run(2, globalsize2, localsize2, false)) + return false; + + std::swap(stack, stack2); + } + + // get edges + ocl::Kernel getEdgesKernel("getEdges", ocl::imgproc::canny_oclsrc); + if (getEdgesKernel.empty()) + return false; + + _dst.create(size, CV_8UC(cn)); + UMat dst = _dst.getUMat(); + + getEdgesKernel.args(ocl::KernelArg::ReadOnlyNoSize(map), ocl::KernelArg::WriteOnly(dst)); + return getEdgesKernel.run(2, globalsize, NULL, false); +} + +} + void cv::Canny( InputArray _src, OutputArray _dst, double low_thresh, double high_thresh, int aperture_size, bool L2gradient ) { - Mat src = _src.getMat(); - CV_Assert( src.depth() == CV_8U ); + const int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + const Size size = _src.size(); - _dst.create(src.size(), CV_8U); - Mat dst = _dst.getMat(); + CV_Assert( depth == CV_8U ); + _dst.create(size, CV_8U); if (!L2gradient && (aperture_size & CV_CANNY_L2_GRADIENT) == CV_CANNY_L2_GRADIENT) { - //backward compatibility + // backward compatibility aperture_size &= ~CV_CANNY_L2_GRADIENT; L2gradient = true; } @@ -109,6 +255,12 @@ void cv::Canny( InputArray _src, OutputArray _dst, if (low_thresh > high_thresh) std::swap(low_thresh, high_thresh); + if (ocl::useOpenCL() && _dst.isUMat() && cn == 1 && + ocl_Canny(_src, _dst, (float)low_thresh, (float)high_thresh, aperture_size, L2gradient, cn, size)) + return; + + Mat src = _src.getMat(), dst = _dst.getMat(); + #ifdef HAVE_TEGRA_OPTIMIZATION if (tegra::canny(src, dst, low_thresh, high_thresh, aperture_size, L2gradient)) return; @@ -120,12 +272,11 @@ void cv::Canny( InputArray _src, OutputArray _dst, return; #endif - const int cn = src.channels(); Mat dx(src.rows, src.cols, CV_16SC(cn)); Mat dy(src.rows, src.cols, CV_16SC(cn)); - Sobel(src, dx, CV_16S, 1, 0, aperture_size, 1, 0, cv::BORDER_REPLICATE); - Sobel(src, dy, CV_16S, 0, 1, aperture_size, 1, 0, cv::BORDER_REPLICATE); + Sobel(src, dx, CV_16S, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE); + Sobel(src, dy, CV_16S, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE); if (L2gradient) { diff --git a/modules/imgproc/src/opencl/canny.cl b/modules/imgproc/src/opencl/canny.cl new file mode 100644 index 000000000..88b406f40 --- /dev/null +++ b/modules/imgproc/src/opencl/canny.cl @@ -0,0 +1,514 @@ +/*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 +// Peng Xiao, pengxiao@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*/ + +// Smoothing perpendicular to the derivative direction with a triangle filter +// only support 3x3 Sobel kernel +// h (-1) = 1, h (0) = 2, h (1) = 1 +// h'(-1) = -1, h'(0) = 0, h'(1) = 1 +// thus sobel 2D operator can be calculated as: +// h'(x, y) = h'(x)h(y) for x direction +// +// src input 8bit single channel image data +// dx_buf output dx buffer +// dy_buf output dy buffer + +__kernel void __attribute__((reqd_work_group_size(16, 16, 1))) +calcSobelRowPass + (__global const uchar * src, int src_step, int src_offset, int rows, int cols, + __global uchar * dx_buf, int dx_buf_step, int dx_buf_offset, + __global uchar * dy_buf, int dy_buf_step, int dy_buf_offset) +{ + int gidx = get_global_id(0); + int gidy = get_global_id(1); + + int lidx = get_local_id(0); + int lidy = get_local_id(1); + + __local int smem[16][18]; + + smem[lidy][lidx + 1] = src[mad24(src_step, min(gidy, rows - 1), gidx + src_offset)]; + if (lidx == 0) + { + smem[lidy][0] = src[mad24(src_step, min(gidy, rows - 1), max(gidx - 1, 0) + src_offset)]; + smem[lidy][17] = src[mad24(src_step, min(gidy, rows - 1), min(gidx + 16, cols - 1) + src_offset)]; + } + barrier(CLK_LOCAL_MEM_FENCE); + + if (gidy < rows && gidx < cols) + { + *(__global short *)(dx_buf + mad24(gidy, dx_buf_step, gidx * (int)sizeof(short) + dx_buf_offset)) = + smem[lidy][lidx + 2] - smem[lidy][lidx]; + *(__global short *)(dy_buf + mad24(gidy, dy_buf_step, gidx * (int)sizeof(short) + dy_buf_offset)) = + smem[lidy][lidx] + 2 * smem[lidy][lidx + 1] + smem[lidy][lidx + 2]; + } +} + +inline int calc(short x, short y) +{ +#ifdef L2GRAD + return x * x + y * y; +#else + return (x >= 0 ? x : -x) + (y >= 0 ? y : -y); +#endif +} + +// calculate the magnitude of the filter pass combining both x and y directions +// This is the non-buffered version(non-3x3 sobel) +// +// dx_buf dx buffer, calculated from calcSobelRowPass +// dy_buf dy buffer, calculated from calcSobelRowPass +// dx direvitive in x direction output +// dy direvitive in y direction output +// mag magnitude direvitive of xy output + +__kernel void calcMagnitude(__global const uchar * dxptr, int dx_step, int dx_offset, + __global const uchar * dyptr, int dy_step, int dy_offset, + __global uchar * magptr, int mag_step, int mag_offset, int rows, int cols) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if (y < rows && x < cols) + { + int dx_index = mad24(dx_step, y, x * (int)sizeof(short) + dx_offset); + int dy_index = mad24(dy_step, y, x * (int)sizeof(short) + dy_offset); + int mag_index = mad24(mag_step, y + 1, (x + 1) * (int)sizeof(int) + mag_offset); + + __global const short * dx = (__global const short *)(dxptr + dx_index); + __global const short * dy = (__global const short *)(dyptr + dy_index); + __global int * mag = (__global int *)(magptr + mag_index); + + mag[0] = calc(dx[0], dy[0]); + } +} + +// calculate the magnitude of the filter pass combining both x and y directions +// This is the buffered version(3x3 sobel) +// +// dx_buf dx buffer, calculated from calcSobelRowPass +// dy_buf dy buffer, calculated from calcSobelRowPass +// dx direvitive in x direction output +// dy direvitive in y direction output +// mag magnitude direvitive of xy output +__kernel void __attribute__((reqd_work_group_size(16, 16, 1))) +calcMagnitude_buf + (__global const short * dx_buf, int dx_buf_step, int dx_buf_offset, + __global const short * dy_buf, int dy_buf_step, int dy_buf_offset, + __global short * dx, int dx_step, int dx_offset, + __global short * dy, int dy_step, int dy_offset, + __global int * mag, int mag_step, int mag_offset, + int rows, int cols) +{ + dx_buf_step /= sizeof(*dx_buf); + dx_buf_offset /= sizeof(*dx_buf); + dy_buf_step /= sizeof(*dy_buf); + dy_buf_offset /= sizeof(*dy_buf); + dx_step /= sizeof(*dx); + dx_offset /= sizeof(*dx); + dy_step /= sizeof(*dy); + dy_offset /= sizeof(*dy); + mag_step /= sizeof(*mag); + mag_offset /= sizeof(*mag); + + int gidx = get_global_id(0); + int gidy = get_global_id(1); + + int lidx = get_local_id(0); + int lidy = get_local_id(1); + + __local short sdx[18][16]; + __local short sdy[18][16]; + + sdx[lidy + 1][lidx] = dx_buf[gidx + min(gidy, rows - 1) * dx_buf_step + dx_buf_offset]; + sdy[lidy + 1][lidx] = dy_buf[gidx + min(gidy, rows - 1) * dy_buf_step + dy_buf_offset]; + if (lidy == 0) + { + sdx[0][lidx] = dx_buf[gidx + min(max(gidy - 1, 0), rows - 1) * dx_buf_step + dx_buf_offset]; + sdx[17][lidx] = dx_buf[gidx + min(gidy + 16, rows - 1) * dx_buf_step + dx_buf_offset]; + + sdy[0][lidx] = dy_buf[gidx + min(max(gidy - 1, 0), rows - 1) * dy_buf_step + dy_buf_offset]; + sdy[17][lidx] = dy_buf[gidx + min(gidy + 16, rows - 1) * dy_buf_step + dy_buf_offset]; + } + barrier(CLK_LOCAL_MEM_FENCE); + + if (gidx < cols && gidy < rows) + { + short x = sdx[lidy][lidx] + 2 * sdx[lidy + 1][lidx] + sdx[lidy + 2][lidx]; + short y = -sdy[lidy][lidx] + sdy[lidy + 2][lidx]; + + dx[gidx + gidy * dx_step + dx_offset] = x; + dy[gidx + gidy * dy_step + dy_offset] = y; + + mag[(gidx + 1) + (gidy + 1) * mag_step + mag_offset] = calc(x, y); + } +} + + +////////////////////////////////////////////////////////////////////////////////////////// +// 0.4142135623730950488016887242097 is tan(22.5) + +#define CANNY_SHIFT 15 +#define TG22 (int)(0.4142135623730950488016887242097f*(1< low_thresh) + { + short xs = *(__global const short *)(dx + mad24(gidy, dx_step, dx_offset + (int)sizeof(short) * gidx)); + short ys = *(__global const short *)(dy + mad24(gidy, dy_step, dy_offset + (int)sizeof(short) * gidx)); + int x = abs(xs), y = abs(ys); + + int tg22x = x * TG22; + y <<= CANNY_SHIFT; + + if (y < tg22x) + { + if (m > smem[lidy + 1][lidx] && m >= smem[lidy + 1][lidx + 2]) + edge_type = 1 + (int)(m > high_thresh); + } + else + { + int tg67x = tg22x + (x << (1 + CANNY_SHIFT)); + if (y > tg67x) + { + if (m > smem[lidy][lidx + 1]&& m >= smem[lidy + 2][lidx + 1]) + edge_type = 1 + (int)(m > high_thresh); + } + else + { + int s = (xs ^ ys) < 0 ? -1 : 1; + if (m > smem[lidy][lidx + 1 - s]&& m > smem[lidy + 2][lidx + 1 + s]) + edge_type = 1 + (int)(m > high_thresh); + } + } + } + *(__global int *)(map + mad24(map_step, gidy + 1, (gidx + 1) * (int)sizeof(int) + map_offset)) = edge_type; + } +} + +#undef CANNY_SHIFT +#undef TG22 + +struct PtrStepSz +{ + __global uchar * ptr; + int step, rows, cols; +}; + +inline int get(struct PtrStepSz data, int y, int x) +{ + return *(__global int *)(data.ptr + mad24(data.step, y + 1, (int)sizeof(int) * (x + 1))); +} + +inline void set(struct PtrStepSz data, int y, int x, int value) +{ + *(__global int *)(data.ptr + mad24(data.step, y + 1, (int)sizeof(int) * (x + 1))) = value; +} + +// perform Hysteresis for pixel whose edge type is 1 +// +// If candidate pixel (edge type is 1) has a neighbour pixel (in 3x3 area) with type 2, it is believed to be part of an edge and +// marked as edge. Each thread will iterate for 16 times to connect local edges. +// Candidate pixel being identified as edge will then be tested if there is nearby potiential edge points. If there is, counter will +// be incremented by 1 and the point location is stored. These potiential candidates will be processed further in next kernel. +// +// map raw edge type results calculated from calcMap. +// stack the potiential edge points found in this kernel call +// counter the number of potiential edge points + +__kernel void __attribute__((reqd_work_group_size(16,16,1))) +edgesHysteresisLocal + (__global uchar * map_ptr, int map_step, int map_offset, + __global ushort2 * st, __global unsigned int * counter, + int rows, int cols) +{ + struct PtrStepSz map = { map_ptr + map_offset, map_step, rows + 1, cols + 1 }; + + __local int smem[18][18]; + + int2 blockIdx = (int2)(get_group_id(0), get_group_id(1)); + int2 blockDim = (int2)(get_local_size(0), get_local_size(1)); + int2 threadIdx = (int2)(get_local_id(0), get_local_id(1)); + + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + smem[threadIdx.y + 1][threadIdx.x + 1] = x < map.cols && y < map.rows ? get(map, y, x) : 0; + if (threadIdx.y == 0) + smem[0][threadIdx.x + 1] = x < map.cols ? get(map, y - 1, x) : 0; + if (threadIdx.y == blockDim.y - 1) + smem[blockDim.y + 1][threadIdx.x + 1] = y + 1 < map.rows ? get(map, y + 1, x) : 0; + if (threadIdx.x == 0) + smem[threadIdx.y + 1][0] = y < map.rows ? get(map, y, x - 1) : 0; + if (threadIdx.x == blockDim.x - 1) + smem[threadIdx.y + 1][blockDim.x + 1] = x + 1 < map.cols && y < map.rows ? get(map, y, x + 1) : 0; + if (threadIdx.x == 0 && threadIdx.y == 0) + smem[0][0] = y > 0 && x > 0 ? get(map, y - 1, x - 1) : 0; + if (threadIdx.x == blockDim.x - 1 && threadIdx.y == 0) + smem[0][blockDim.x + 1] = y > 0 && x + 1 < map.cols ? get(map, y - 1, x + 1) : 0; + if (threadIdx.x == 0 && threadIdx.y == blockDim.y - 1) + smem[blockDim.y + 1][0] = y + 1 < map.rows && x > 0 ? get(map, y + 1, x - 1) : 0; + if (threadIdx.x == blockDim.x - 1 && threadIdx.y == blockDim.y - 1) + smem[blockDim.y + 1][blockDim.x + 1] = y + 1 < map.rows && x + 1 < map.cols ? get(map, y + 1, x + 1) : 0; + + barrier(CLK_LOCAL_MEM_FENCE); + + if (x >= cols || y >= rows) + return; + + int n; + + #pragma unroll + for (int k = 0; k < 16; ++k) + { + n = 0; + + if (smem[threadIdx.y + 1][threadIdx.x + 1] == 1) + { + n += smem[threadIdx.y ][threadIdx.x ] == 2; + n += smem[threadIdx.y ][threadIdx.x + 1] == 2; + n += smem[threadIdx.y ][threadIdx.x + 2] == 2; + + n += smem[threadIdx.y + 1][threadIdx.x ] == 2; + n += smem[threadIdx.y + 1][threadIdx.x + 2] == 2; + + n += smem[threadIdx.y + 2][threadIdx.x ] == 2; + n += smem[threadIdx.y + 2][threadIdx.x + 1] == 2; + n += smem[threadIdx.y + 2][threadIdx.x + 2] == 2; + } + + if (n > 0) + smem[threadIdx.y + 1][threadIdx.x + 1] = 2; + } + + const int e = smem[threadIdx.y + 1][threadIdx.x + 1]; + set(map, y, x, e); + n = 0; + + if (e == 2) + { + n += smem[threadIdx.y ][threadIdx.x ] == 1; + n += smem[threadIdx.y ][threadIdx.x + 1] == 1; + n += smem[threadIdx.y ][threadIdx.x + 2] == 1; + + n += smem[threadIdx.y + 1][threadIdx.x ] == 1; + n += smem[threadIdx.y + 1][threadIdx.x + 2] == 1; + + n += smem[threadIdx.y + 2][threadIdx.x ] == 1; + n += smem[threadIdx.y + 2][threadIdx.x + 1] == 1; + n += smem[threadIdx.y + 2][threadIdx.x + 2] == 1; + } + + if (n > 0) + { + const int ind = atomic_inc(counter); + st[ind] = (ushort2)(x + 1, y + 1); + } +} + +__constant int c_dx[8] = {-1, 0, 1, -1, 1, -1, 0, 1}; +__constant int c_dy[8] = {-1, -1, -1, 0, 0, 1, 1, 1}; + + +#define stack_size 512 +#define map_index mad24(map_step, pos.y, pos.x * (int)sizeof(int)) + +__kernel void __attribute__((reqd_work_group_size(128, 1, 1))) +edgesHysteresisGlobal(__global uchar * map, int map_step, int map_offset, + __global ushort2 * st1, __global ushort2 * st2, __global int * counter, + int rows, int cols, int count) +{ + map += map_offset; + + int lidx = get_local_id(0); + + int grp_idx = get_group_id(0); + int grp_idy = get_group_id(1); + + __local unsigned int s_counter, s_ind; + __local ushort2 s_st[stack_size]; + + if (lidx == 0) + s_counter = 0; + barrier(CLK_LOCAL_MEM_FENCE); + + int ind = mad24(grp_idy, (int)get_local_size(0), grp_idx); + + if (ind < count) + { + ushort2 pos = st1[ind]; + if (lidx < 8) + { + pos.x += c_dx[lidx]; + pos.y += c_dy[lidx]; + if (pos.x > 0 && pos.x <= cols && pos.y > 0 && pos.y <= rows && *(__global int *)(map + map_index) == 1) + { + *(__global int *)(map + map_index) = 2; + ind = atomic_inc(&s_counter); + s_st[ind] = pos; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + + while (s_counter > 0 && s_counter <= stack_size - get_local_size(0)) + { + const int subTaskIdx = lidx >> 3; + const int portion = min(s_counter, (uint)(get_local_size(0)>> 3)); + + if (subTaskIdx < portion) + pos = s_st[s_counter - 1 - subTaskIdx]; + barrier(CLK_LOCAL_MEM_FENCE); + + if (lidx == 0) + s_counter -= portion; + barrier(CLK_LOCAL_MEM_FENCE); + + if (subTaskIdx < portion) + { + pos.x += c_dx[lidx & 7]; + pos.y += c_dy[lidx & 7]; + if (pos.x > 0 && pos.x <= cols && pos.y > 0 && pos.y <= rows && *(__global int *)(map + map_index) == 1) + { + *(__global int *)(map + map_index) = 2; + ind = atomic_inc(&s_counter); + s_st[ind] = pos; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + } + + if (s_counter > 0) + { + if (lidx == 0) + { + ind = atomic_add(counter, s_counter); + s_ind = ind - s_counter; + } + barrier(CLK_LOCAL_MEM_FENCE); + + ind = s_ind; + for (int i = lidx; i < (int)s_counter; i += get_local_size(0)) + st2[ind + i] = s_st[i]; + } + } +} + +#undef map_index +#undef stack_size + +// Get the edge result. egde type of value 2 will be marked as an edge point and set to 255. Otherwise 0. +// map edge type mappings +// dst edge output + +__kernel void getEdges(__global const uchar * mapptr, int map_step, int map_offset, + __global uchar * dst, int dst_step, int dst_offset, int rows, int cols) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if (y < rows && x < cols) + { + int map_index = mad24(map_step, y + 1, (x + 1) * (int)sizeof(int) + map_offset); + int dst_index = mad24(dst_step, y, x + dst_offset); + + __global const int * map = (__global const int *)(mapptr + map_index); + + dst[dst_index] = (uchar)(-(map[0] >> 1)); + } +} diff --git a/modules/imgproc/test/ocl/test_canny.cpp b/modules/imgproc/test/ocl/test_canny.cpp new file mode 100644 index 000000000..e328d2a2f --- /dev/null +++ b/modules/imgproc/test/ocl/test_canny.cpp @@ -0,0 +1,117 @@ +/*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 +// Peng Xiao, pengxiao@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 "test_precomp.hpp" +#include "opencv2/ts/ocl_test.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +//////////////////////////////////////////////////////// +// Canny + +IMPLEMENT_PARAM_CLASS(AppertureSize, int) +IMPLEMENT_PARAM_CLASS(L2gradient, bool) +IMPLEMENT_PARAM_CLASS(UseRoi, bool) + +PARAM_TEST_CASE(Canny, AppertureSize, L2gradient, UseRoi) +{ + int apperture_size; + bool useL2gradient, use_roi; + + TEST_DECLARE_INPUT_PARAMETER(src) + TEST_DECLARE_OUTPUT_PARAMETER(dst) + + virtual void SetUp() + { + apperture_size = GET_PARAM(0); + useL2gradient = GET_PARAM(1); + use_roi = GET_PARAM(2); + } + + void generateTestData() + { + Mat img = readImage("shared/fruits.png", IMREAD_GRAYSCALE); + ASSERT_FALSE(img.empty()) << "cann't load shared/fruits.png"; + + Size roiSize = img.size(); + int type = img.type(); + ASSERT_EQ(CV_8UC1, type); + + Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, type, 2, 100); + img.copyTo(src_roi); + + Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst, dst_roi, roiSize, dstBorder, type, 5, 16); + + UMAT_UPLOAD_INPUT_PARAMETER(src) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst) + } +}; + +OCL_TEST_P(Canny, Accuracy) +{ + generateTestData(); + + const double low_thresh = 50.0, high_thresh = 100.0; + + OCL_OFF(cv::Canny(src_roi, dst_roi, low_thresh, high_thresh, apperture_size, useL2gradient)); + OCL_ON(cv::Canny(usrc_roi, udst_roi, low_thresh, high_thresh, apperture_size, useL2gradient)); + + EXPECT_MAT_SIMILAR(dst_roi, udst_roi, 1e-2); + EXPECT_MAT_SIMILAR(dst, udst, 1e-2); +} + +OCL_INSTANTIATE_TEST_CASE_P(ImgProc, Canny, testing::Combine( + testing::Values(AppertureSize(3), AppertureSize(5)), + testing::Values(L2gradient(false), L2gradient(true)), + testing::Values(UseRoi(false), UseRoi(true)))); + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL diff --git a/modules/ts/include/opencv2/ts/ocl_test.hpp b/modules/ts/include/opencv2/ts/ocl_test.hpp index 2fea52a95..a4b2ec38c 100644 --- a/modules/ts/include/opencv2/ts/ocl_test.hpp +++ b/modules/ts/include/opencv2/ts/ocl_test.hpp @@ -96,18 +96,18 @@ extern int test_loop_times; #define EXPECT_MAT_NEAR(mat1, mat2, eps) \ { \ - ASSERT_EQ(mat1.type(), mat2.type()); \ - ASSERT_EQ(mat1.size(), mat2.size()); \ - EXPECT_LE(checkNorm(mat1, mat2), eps) \ - << cv::format("Size: %d x %d", mat1.size().width, mat1.size().height) << std::endl; \ + ASSERT_EQ(mat1.type(), mat2.type()); \ + ASSERT_EQ(mat1.size(), mat2.size()); \ + EXPECT_LE(checkNorm(mat1, mat2), eps) \ + << "Size: " << mat1.size() << std::endl; \ } #define EXPECT_MAT_NEAR_RELATIVE(mat1, mat2, eps) \ { \ - ASSERT_EQ(mat1.type(), mat2.type()); \ - ASSERT_EQ(mat1.size(), mat2.size()); \ - EXPECT_LE(checkNormRelative(mat1, mat2), eps) \ - << cv::format("Size: %d x %d", mat1.size().width, mat1.size().height) << std::endl; \ + ASSERT_EQ(mat1.type(), mat2.type()); \ + ASSERT_EQ(mat1.size(), mat2.size()); \ + EXPECT_LE(checkNormRelative(mat1, mat2), eps) \ + << "Size: " << mat1.size() << std::endl; \ } #define OCL_EXPECT_MATS_NEAR(name, eps) \ @@ -134,8 +134,8 @@ extern int test_loop_times; { \ ASSERT_EQ(mat1.type(), mat2.type()); \ ASSERT_EQ(mat1.size(), mat2.size()); \ - EXPECT_LE(checkSimilarity(mat1, mat2), eps); \ - << cv::format("Size: %d x %d", mat1.size().width, mat1.size().height) << std::endl; \ + EXPECT_LE(checkSimilarity(mat1, mat2), eps) \ + << "Size: " << mat1.size() << std::endl; \ } using perf::MatDepth; From 092f916db94186758027dd0fc56655ea2e7b4a98 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Fri, 17 Jan 2014 12:51:52 +0400 Subject: [PATCH 079/295] Revert 4f9c081 That commit introduces problems, as it breaks certain use cases of OpenCV functions; for example, convertTo of an Nx1 matrix to an std::vector. Since vectors can't store separate width and height values, OpenCV considers them to always be 1xN. So even though the vector is created with .create(N, 1), the Mat passed to getContinousSize has dimensions 1xN, and the size comparison fails, even though the operation itself is safe. This is a use case we probably don't want to break, at the very least for backwards compatibility. So I'm reverting the commit. This will also unfix bug #3319; I'll submit a less intrusive solution as a PR to 2.4, which will also revert 4f9c081 there. --- modules/core/src/precomp.hpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index ad4fd592e..3727b2f15 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -153,14 +153,12 @@ template struct OpMax inline Size getContinuousSize( const Mat& m1, int widthScale=1 ) { - CV_Assert(m1.dims <= 2); return m1.isContinuous() ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } inline Size getContinuousSize( const Mat& m1, const Mat& m2, int widthScale=1 ) { - CV_Assert(m1.dims <= 2 && m1.size() == m2.size()); return (m1.flags & m2.flags & Mat::CONTINUOUS_FLAG) != 0 ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } @@ -168,7 +166,6 @@ inline Size getContinuousSize( const Mat& m1, const Mat& m2, int widthScale=1 ) inline Size getContinuousSize( const Mat& m1, const Mat& m2, const Mat& m3, int widthScale=1 ) { - CV_Assert(m1.dims <= 2 && m1.size() == m2.size() && m1.size() == m3.size()); return (m1.flags & m2.flags & m3.flags & Mat::CONTINUOUS_FLAG) != 0 ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } @@ -177,7 +174,6 @@ inline Size getContinuousSize( const Mat& m1, const Mat& m2, const Mat& m3, const Mat& m4, int widthScale=1 ) { - CV_Assert(m1.dims <= 2 && m1.size() == m2.size() && m1.size() == m3.size() && m1.size() == m4.size()); return (m1.flags & m2.flags & m3.flags & m4.flags & Mat::CONTINUOUS_FLAG) != 0 ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } @@ -186,7 +182,6 @@ inline Size getContinuousSize( const Mat& m1, const Mat& m2, const Mat& m3, const Mat& m4, const Mat& m5, int widthScale=1 ) { - CV_Assert(m1.dims <= 2 && m1.size() == m2.size() && m1.size() == m3.size() && m1.size() == m4.size() && m1.size() == m5.size()); return (m1.flags & m2.flags & m3.flags & m4.flags & m5.flags & Mat::CONTINUOUS_FLAG) != 0 ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } From e9e9e00d45ab206e59aff30eab7d38e073dad789 Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Thu, 16 Jan 2014 16:18:02 +0400 Subject: [PATCH 080/295] replaced sprintf with cv::format --- .../calib3d/test/test_cameracalibration.cpp | 28 +++++++++---------- .../calib3d/test/test_chesscorners_timing.cpp | 14 +++++----- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib3d/test/test_cameracalibration.cpp index 7262e61a1..d1cbdb231 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib3d/test/test_cameracalibration.cpp @@ -290,8 +290,8 @@ int CV_CameraCalibrationTest::compare(double* val, double* ref_val, int len, void CV_CameraCalibrationTest::run( int start_from ) { int code = cvtest::TS::OK; - char filepath[200]; - char filename[200]; + cv::String filepath; + cv::String filename; CvSize imageSize; CvSize etalonSize; @@ -337,12 +337,12 @@ void CV_CameraCalibrationTest::run( int start_from ) int progress = 0; int values_read = -1; - sprintf( filepath, "%scv/cameracalibration/", ts->get_data_path().c_str() ); - sprintf( filename, "%sdatafiles.txt", filepath ); - datafile = fopen( filename, "r" ); + filepath = cv::format("%scv/cameracalibration/", ts->get_data_path().c_str() ); + filename = cv::format("%sdatafiles.txt", filepath.c_str() ); + datafile = fopen( filename.c_str(), "r" ); if( datafile == 0 ) { - ts->printf( cvtest::TS::LOG, "Could not open file with list of test files: %s\n", filename ); + ts->printf( cvtest::TS::LOG, "Could not open file with list of test files: %s\n", filename.c_str() ); code = cvtest::TS::FAIL_MISSING_TEST_DATA; goto _exit_; } @@ -354,15 +354,15 @@ void CV_CameraCalibrationTest::run( int start_from ) { values_read = fscanf(datafile,"%s",i_dat_file); CV_Assert(values_read == 1); - sprintf(filename, "%s%s", filepath, i_dat_file); - file = fopen(filename,"r"); + filename = cv::format("%s%s", filepath.c_str(), i_dat_file); + file = fopen(filename.c_str(),"r"); ts->update_context( this, currTest, true ); if( file == 0 ) { ts->printf( cvtest::TS::LOG, - "Can't open current test file: %s\n",filename); + "Can't open current test file: %s\n",filename.c_str()); if( numTests == 1 ) { code = cvtest::TS::FAIL_MISSING_TEST_DATA; @@ -1382,16 +1382,16 @@ void CV_StereoCalibrationTest::run( int ) for(int testcase = 1; testcase <= ntests; testcase++) { - char filepath[1000]; + cv::String filepath; char buf[1000]; - sprintf( filepath, "%scv/stereo/case%d/stereo_calib.txt", ts->get_data_path().c_str(), testcase ); - f = fopen(filepath, "rt"); + filepath = cv::format("%scv/stereo/case%d/stereo_calib.txt", ts->get_data_path().c_str(), testcase ); + f = fopen(filepath.c_str(), "rt"); Size patternSize; vector imglist; if( !f || !fgets(buf, sizeof(buf)-3, f) || sscanf(buf, "%d%d", &patternSize.width, &patternSize.height) != 2 ) { - ts->printf( cvtest::TS::LOG, "The file %s can not be opened or has invalid content\n", filepath ); + ts->printf( cvtest::TS::LOG, "The file %s can not be opened or has invalid content\n", filepath.c_str() ); ts->set_failed_test_info( f ? cvtest::TS::FAIL_INVALID_TEST_DATA : cvtest::TS::FAIL_MISSING_TEST_DATA ); return; } @@ -1405,7 +1405,7 @@ void CV_StereoCalibrationTest::run( int ) buf[--len] = '\0'; if( buf[0] == '#') continue; - sprintf(filepath, "%scv/stereo/case%d/%s", ts->get_data_path().c_str(), testcase, buf ); + filepath = cv::format("%scv/stereo/case%d/%s", ts->get_data_path().c_str(), testcase, buf ); imglist.push_back(string(filepath)); } fclose(f); diff --git a/modules/calib3d/test/test_chesscorners_timing.cpp b/modules/calib3d/test/test_chesscorners_timing.cpp index a990aea84..61287ab67 100644 --- a/modules/calib3d/test/test_chesscorners_timing.cpp +++ b/modules/calib3d/test/test_chesscorners_timing.cpp @@ -62,8 +62,8 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) int code = cvtest::TS::OK; /* test parameters */ - char filepath[1000]; - char filename[1000]; + std::string filepath; + std::string filename; CvMat* _v = 0; CvPoint2D32f* v; @@ -75,9 +75,9 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) int idx, max_idx; int progress = 0; - sprintf( filepath, "%scv/cameracalibration/", ts->get_data_path().c_str() ); - sprintf( filename, "%schessboard_timing_list.dat", filepath ); - CvFileStorage* fs = cvOpenFileStorage( filename, 0, CV_STORAGE_READ ); + filepath = cv::format("%scv/cameracalibration/", ts->get_data_path().c_str() ); + filename = cv::format("%schessboard_timing_list.dat", filepath.c_str() ); + CvFileStorage* fs = cvOpenFileStorage( filename.c_str(), 0, CV_STORAGE_READ ); CvFileNode* board_list = fs ? cvGetFileNodeByName( fs, 0, "boards" ) : 0; if( !fs || !board_list || !CV_NODE_IS_SEQ(board_list->tag) || @@ -105,14 +105,14 @@ void CV_ChessboardDetectorTimingTest::run( int start_from ) ts->update_context( this, idx-1, true ); /* read the image */ - sprintf( filename, "%s%s", filepath, imgname ); + filename = cv::format("%s%s", filepath.c_str(), imgname ); cv::Mat img2 = cv::imread( filename ); img = img2; if( img2.empty() ) { - ts->printf( cvtest::TS::LOG, "one of chessboard images can't be read: %s\n", filename ); + ts->printf( cvtest::TS::LOG, "one of chessboard images can't be read: %s\n", filename.c_str() ); if( max_idx == 1 ) { code = cvtest::TS::FAIL_MISSING_TEST_DATA; From f02204847af64656a8bff7a4b5ec1f55df11643b Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Fri, 17 Jan 2014 13:02:35 +0400 Subject: [PATCH 081/295] Revert "fixed bug #3319" See 092f916 for explanation. This reverts commit 4f9c081dc313f8fdfee3f0a4572779ae13e27e40. --- modules/core/src/precomp.hpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index ec8dcc9f2..c53224e0a 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -129,14 +129,12 @@ template struct OpMax inline Size getContinuousSize( const Mat& m1, int widthScale=1 ) { - CV_Assert(m1.dims <= 2); return m1.isContinuous() ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } inline Size getContinuousSize( const Mat& m1, const Mat& m2, int widthScale=1 ) { - CV_Assert(m1.dims <= 2 && m1.size() == m2.size()); return (m1.flags & m2.flags & Mat::CONTINUOUS_FLAG) != 0 ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } @@ -144,7 +142,6 @@ inline Size getContinuousSize( const Mat& m1, const Mat& m2, int widthScale=1 ) inline Size getContinuousSize( const Mat& m1, const Mat& m2, const Mat& m3, int widthScale=1 ) { - CV_Assert(m1.dims <= 2 && m1.size() == m2.size() && m1.size() == m3.size()); return (m1.flags & m2.flags & m3.flags & Mat::CONTINUOUS_FLAG) != 0 ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } @@ -153,7 +150,6 @@ inline Size getContinuousSize( const Mat& m1, const Mat& m2, const Mat& m3, const Mat& m4, int widthScale=1 ) { - CV_Assert(m1.dims <= 2 && m1.size() == m2.size() && m1.size() == m3.size() && m1.size() == m4.size()); return (m1.flags & m2.flags & m3.flags & m4.flags & Mat::CONTINUOUS_FLAG) != 0 ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } @@ -162,7 +158,6 @@ inline Size getContinuousSize( const Mat& m1, const Mat& m2, const Mat& m3, const Mat& m4, const Mat& m5, int widthScale=1 ) { - CV_Assert(m1.dims <= 2 && m1.size() == m2.size() && m1.size() == m3.size() && m1.size() == m4.size() && m1.size() == m5.size()); return (m1.flags & m2.flags & m3.flags & m4.flags & m5.flags & Mat::CONTINUOUS_FLAG) != 0 ? Size(m1.cols*m1.rows*widthScale, 1) : Size(m1.cols*widthScale, m1.rows); } From ee97a5e7573e292ea0d029a257fea0542c38e4a5 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Fri, 17 Jan 2014 14:13:21 +0400 Subject: [PATCH 082/295] Re-fix bug #3319 with less side effects. --- modules/core/src/copy.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index 894776bb3..b87d080de 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -286,6 +286,7 @@ void Mat::copyTo( OutputArray _dst, InputArray _mask ) const if( dims <= 2 ) { + CV_Assert( size() == mask.size() ); Size sz = getContinuousSize(*this, dst, mask, mcn); copymask(data, step, mask.data, mask.step, dst.data, dst.step, sz, &esz); return; From 4e4a7d035335b8db373f479335abd095fc582446 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Fri, 17 Jan 2014 14:16:22 +0400 Subject: [PATCH 083/295] Removed an unnecessary workaround for matrix-to-vector copyTo. --- modules/core/src/copy.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index b87d080de..b8d87fc22 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -232,10 +232,7 @@ void Mat::copyTo( OutputArray _dst ) const const uchar* sptr = data; uchar* dptr = dst.data; - // to handle the copying 1xn matrix => nx1 std vector. - Size sz = size() == dst.size() ? - getContinuousSize(*this, dst) : - getContinuousSize(*this); + Size sz = getContinuousSize(*this, dst); size_t len = sz.width*elemSize(); for( ; sz.height--; sptr += step, dptr += dst.step ) From 5f8d8c0069a715dd3dfbbcd6a01a6715e74571b2 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Fri, 17 Jan 2014 14:18:31 +0400 Subject: [PATCH 084/295] Added a test for matrix-to-vector copy and convert. --- modules/core/test/test_mat.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index 514b587d7..a6ebe152d 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -897,3 +897,24 @@ TEST(Core_Mat, reshape_1942) ); ASSERT_EQ(1, cn); } + +TEST(Core_Mat, copyNx1ToVector) +{ + cv::Mat_ src(5, 1); + cv::Mat_ ref_dst8; + cv::Mat_ ref_dst16; + std::vector dst8; + std::vector dst16; + + src << 1, 2, 3, 4, 5; + + src.copyTo(ref_dst8); + src.copyTo(dst8); + + ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), ref_dst8, cv::Mat_(dst8)); + + src.convertTo(ref_dst16, CV_16U); + src.convertTo(dst16, CV_16U); + + ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), ref_dst16, cv::Mat_(dst16)); +} From e9805e444f66487a177b91032ee6eced7fccb0c8 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Fri, 17 Jan 2014 14:49:42 +0400 Subject: [PATCH 085/295] Fixed an overly-narrow assertion in cv::norm. size() requires that the matrix is two-dimensional, and norm() works on higher dimensions. --- modules/core/src/stat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index eac823995..050716268 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -2295,7 +2295,7 @@ static bool ocl_norm( InputArray _src1, InputArray _src2, int normType, double & double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask ) { - CV_Assert( _src1.size() == _src2.size() && _src1.type() == _src2.type() ); + CV_Assert( _src1.sameSize(_src2) && _src1.type() == _src2.type() ); double _result = 0; if (ocl::useOpenCL() && _mask.empty() && _src1.isUMat() && _src2.isUMat() && From a502ffbd2caac45adabf94e593709f71397f404a Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Fri, 17 Jan 2014 14:50:40 +0400 Subject: [PATCH 086/295] Updated required CMake version in docs to match reality. --- doc/tutorials/introduction/linux_install/linux_install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorials/introduction/linux_install/linux_install.rst b/doc/tutorials/introduction/linux_install/linux_install.rst index 1e02b64c9..831793024 100644 --- a/doc/tutorials/introduction/linux_install/linux_install.rst +++ b/doc/tutorials/introduction/linux_install/linux_install.rst @@ -13,7 +13,7 @@ Required Packages sudo apt-get install build-essential - * CMake 2.6 or higher; + * CMake 2.8.7 or higher; * Git; * GTK+2.x or higher, including headers (libgtk2.0-dev); * pkgconfig; From 3b0fa68a973113f398c217ca8402e82cc3e8867f Mon Sep 17 00:00:00 2001 From: vbystricky Date: Thu, 9 Jan 2014 16:34:01 +0400 Subject: [PATCH 087/295] Move OpticalFlowFarneback from ocl module to video module --- .../src/opencl/optical_flow_farneback.cl | 434 +++++++++++++++ modules/video/src/optflowgf.cpp | 526 +++++++++++++++++- modules/video/src/precomp.hpp | 1 + .../video/test/ocl/test_optflow_farneback.cpp | 110 ++++ 4 files changed, 1053 insertions(+), 18 deletions(-) create mode 100644 modules/video/src/opencl/optical_flow_farneback.cl create mode 100644 modules/video/test/ocl/test_optflow_farneback.cpp diff --git a/modules/video/src/opencl/optical_flow_farneback.cl b/modules/video/src/opencl/optical_flow_farneback.cl new file mode 100644 index 000000000..0ef48d2c0 --- /dev/null +++ b/modules/video/src/opencl/optical_flow_farneback.cl @@ -0,0 +1,434 @@ +/*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 +// Sen Liu, swjtuls1987@126.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*/ + + +#define tx (int)get_local_id(0) +#define ty get_local_id(1) +#define bx get_group_id(0) +#define bdx (int)get_local_size(0) + +#define BORDER_SIZE 5 +#define MAX_KSIZE_HALF 100 + +#ifndef polyN +#define polyN 5 +#endif + +#if USE_DOUBLE +#ifdef cl_amd_fp64 +#pragma OPENCL EXTENSION cl_amd_fp64:enable +#elif defined (cl_khr_fp64) +#pragma OPENCL EXTENSION cl_khr_fp64:enable +#endif +#define TYPE double +#define VECTYPE double4 +#else +#define TYPE float +#define VECTYPE float4 +#endif + +__kernel void polynomialExpansion(__global __const float * src, int srcStep, + __global float * dst, int dstStep, + const int rows, const int cols, + __global __const float * c_g, + __global __const float * c_xg, + __global __const float * c_xxg, + __local float * smem, + const VECTYPE ig) +{ + const int y = get_global_id(1); + const int x = bx * (bdx - 2*polyN) + tx - polyN; + + int xWarped; + __local float *row = smem + tx; + + if (y < rows && y >= 0) + { + xWarped = min(max(x, 0), cols - 1); + + row[0] = src[mad24(y, srcStep, xWarped)] * c_g[0]; + row[bdx] = 0.f; + row[2*bdx] = 0.f; + +#pragma unroll + for (int k = 1; k <= polyN; ++k) + { + float t0 = src[mad24(max(y - k, 0), srcStep, xWarped)]; + float t1 = src[mad24(min(y + k, rows - 1), srcStep, xWarped)]; + + row[0] += c_g[k] * (t0 + t1); + row[bdx] += c_xg[k] * (t1 - t0); + row[2*bdx] += c_xxg[k] * (t0 + t1); + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (y < rows && y >= 0 && tx >= polyN && tx + polyN < bdx && x < cols) + { + TYPE b1 = c_g[0] * row[0]; + TYPE b3 = c_g[0] * row[bdx]; + TYPE b5 = c_g[0] * row[2*bdx]; + TYPE b2 = 0, b4 = 0, b6 = 0; + +#pragma unroll + for (int k = 1; k <= polyN; ++k) + { + b1 += (row[k] + row[-k]) * c_g[k]; + b4 += (row[k] + row[-k]) * c_xxg[k]; + b2 += (row[k] - row[-k]) * c_xg[k]; + b3 += (row[k + bdx] + row[-k + bdx]) * c_g[k]; + b6 += (row[k + bdx] - row[-k + bdx]) * c_xg[k]; + b5 += (row[k + 2*bdx] + row[-k + 2*bdx]) * c_g[k]; + } + + dst[mad24(y, dstStep, xWarped)] = (float)(b3*ig.s0); + dst[mad24(rows + y, dstStep, xWarped)] = (float)(b2*ig.s0); + dst[mad24(2*rows + y, dstStep, xWarped)] = (float)(b1*ig.s1 + b5*ig.s2); + dst[mad24(3*rows + y, dstStep, xWarped)] = (float)(b1*ig.s1 + b4*ig.s2); + dst[mad24(4*rows + y, dstStep, xWarped)] = (float)(b6*ig.s3); + } +} + +inline int idx_row_low(const int y, const int last_row) +{ + return abs(y) % (last_row + 1); +} + +inline int idx_row_high(const int y, const int last_row) +{ + return abs(last_row - abs(last_row - y)) % (last_row + 1); +} + +inline int idx_row(const int y, const int last_row) +{ + return idx_row_low(idx_row_high(y, last_row), last_row); +} + +inline int idx_col_low(const int x, const int last_col) +{ + return abs(x) % (last_col + 1); +} + +inline int idx_col_high(const int x, const int last_col) +{ + return abs(last_col - abs(last_col - x)) % (last_col + 1); +} + +inline int idx_col(const int x, const int last_col) +{ + return idx_col_low(idx_col_high(x, last_col), last_col); +} + +__kernel void gaussianBlur(__global const float * src, int srcStep, + __global float * dst, int dstStep, const int rows, const int cols, + __global const float * c_gKer, const int ksizeHalf, + __local float * smem) +{ + const int y = get_global_id(1); + const int x = get_global_id(0); + + __local float *row = smem + ty * (bdx + 2*ksizeHalf); + + if (y < rows) + { + // Vertical pass + for (int i = tx; i < bdx + 2*ksizeHalf; i += bdx) + { + int xExt = (int)(bx * bdx) + i - ksizeHalf; + xExt = idx_col(xExt, cols - 1); + row[i] = src[mad24(y, srcStep, xExt)] * c_gKer[0]; + for (int j = 1; j <= ksizeHalf; ++j) + row[i] += (src[mad24(idx_row_low(y - j, rows - 1), srcStep, xExt)] + + src[mad24(idx_row_high(y + j, rows - 1), srcStep, xExt)]) * c_gKer[j]; + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (y < rows && y >= 0 && x < cols && x >= 0) + { + // Horizontal pass + row += tx + ksizeHalf; + float res = row[0] * c_gKer[0]; + for (int i = 1; i <= ksizeHalf; ++i) + res += (row[-i] + row[i]) * c_gKer[i]; + + dst[mad24(y, dstStep, x)] = res; + } +} + +__kernel void gaussianBlur5(__global const float * src, int srcStep, + __global float * dst, int dstStep, + const int rows, const int cols, + __global const float * c_gKer, const int ksizeHalf, + __local float * smem) +{ + const int y = get_global_id(1); + const int x = get_global_id(0); + + const int smw = bdx + 2*ksizeHalf; // shared memory "cols" + __local volatile float *row = smem + 5 * ty * smw; + + if (y < rows) + { + // Vertical pass + for (int i = tx; i < bdx + 2*ksizeHalf; i += bdx) + { + int xExt = (int)(bx * bdx) + i - ksizeHalf; + xExt = idx_col(xExt, cols - 1); + +#pragma unroll + for (int k = 0; k < 5; ++k) + row[k*smw + i] = src[mad24(k*rows + y, srcStep, xExt)] * c_gKer[0]; + + for (int j = 1; j <= ksizeHalf; ++j) +#pragma unroll + for (int k = 0; k < 5; ++k) + row[k*smw + i] += + (src[mad24(k*rows + idx_row_low(y - j, rows - 1), srcStep, xExt)] + + src[mad24(k*rows + idx_row_high(y + j, rows - 1), srcStep, xExt)]) * c_gKer[j]; + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (y < rows && y >= 0 && x < cols && x >= 0) + { + // Horizontal pass + + row += tx + ksizeHalf; + float res[5]; + +#pragma unroll + for (int k = 0; k < 5; ++k) + res[k] = row[k*smw] * c_gKer[0]; + + for (int i = 1; i <= ksizeHalf; ++i) +#pragma unroll + for (int k = 0; k < 5; ++k) + res[k] += (row[k*smw - i] + row[k*smw + i]) * c_gKer[i]; + +#pragma unroll + for (int k = 0; k < 5; ++k) + dst[mad24(k*rows + y, dstStep, x)] = res[k]; + } +} +__constant float c_border[BORDER_SIZE + 1] = { 0.14f, 0.14f, 0.4472f, 0.4472f, 0.4472f, 1.f }; + +__kernel void updateMatrices(__global const float * flowx, int xStep, + __global const float * flowy, int yStep, + const int rows, const int cols, + __global const float * R0, int R0Step, + __global const float * R1, int R1Step, + __global float * M, int mStep) +{ + const int y = get_global_id(1); + const int x = get_global_id(0); + + if (y < rows && y >= 0 && x < cols && x >= 0) + { + float dx = flowx[mad24(y, xStep, x)]; + float dy = flowy[mad24(y, yStep, x)]; + float fx = x + dx; + float fy = y + dy; + + int x1 = convert_int(floor(fx)); + int y1 = convert_int(floor(fy)); + fx -= x1; + fy -= y1; + + float r2, r3, r4, r5, r6; + + if (x1 >= 0 && y1 >= 0 && x1 < cols - 1 && y1 < rows - 1) + { + float a00 = (1.f - fx) * (1.f - fy); + float a01 = fx * (1.f - fy); + float a10 = (1.f - fx) * fy; + float a11 = fx * fy; + + r2 = a00 * R1[mad24(y1, R1Step, x1)] + + a01 * R1[mad24(y1, R1Step, x1 + 1)] + + a10 * R1[mad24(y1 + 1, R1Step, x1)] + + a11 * R1[mad24(y1 + 1, R1Step, x1 + 1)]; + + r3 = a00 * R1[mad24(rows + y1, R1Step, x1)] + + a01 * R1[mad24(rows + y1, R1Step, x1 + 1)] + + a10 * R1[mad24(rows + y1 + 1, R1Step, x1)] + + a11 * R1[mad24(rows + y1 + 1, R1Step, x1 + 1)]; + + r4 = a00 * R1[mad24(2*rows + y1, R1Step, x1)] + + a01 * R1[mad24(2*rows + y1, R1Step, x1 + 1)] + + a10 * R1[mad24(2*rows + y1 + 1, R1Step, x1)] + + a11 * R1[mad24(2*rows + y1 + 1, R1Step, x1 + 1)]; + + r5 = a00 * R1[mad24(3*rows + y1, R1Step, x1)] + + a01 * R1[mad24(3*rows + y1, R1Step, x1 + 1)] + + a10 * R1[mad24(3*rows + y1 + 1, R1Step, x1)] + + a11 * R1[mad24(3*rows + y1 + 1, R1Step, x1 + 1)]; + + r6 = a00 * R1[mad24(4*rows + y1, R1Step, x1)] + + a01 * R1[mad24(4*rows + y1, R1Step, x1 + 1)] + + a10 * R1[mad24(4*rows + y1 + 1, R1Step, x1)] + + a11 * R1[mad24(4*rows + y1 + 1, R1Step, x1 + 1)]; + + r4 = (R0[mad24(2*rows + y, R0Step, x)] + r4) * 0.5f; + r5 = (R0[mad24(3*rows + y, R0Step, x)] + r5) * 0.5f; + r6 = (R0[mad24(4*rows + y, R0Step, x)] + r6) * 0.25f; + } + else + { + r2 = r3 = 0.f; + r4 = R0[mad24(2*rows + y, R0Step, x)]; + r5 = R0[mad24(3*rows + y, R0Step, x)]; + r6 = R0[mad24(4*rows + y, R0Step, x)] * 0.5f; + } + + r2 = (R0[mad24(y, R0Step, x)] - r2) * 0.5f; + r3 = (R0[mad24(rows + y, R0Step, x)] - r3) * 0.5f; + + r2 += r4*dy + r6*dx; + r3 += r6*dy + r5*dx; + + float scale = + c_border[min(x, BORDER_SIZE)] * + c_border[min(y, BORDER_SIZE)] * + c_border[min(cols - x - 1, BORDER_SIZE)] * + c_border[min(rows - y - 1, BORDER_SIZE)]; + + r2 *= scale; + r3 *= scale; + r4 *= scale; + r5 *= scale; + r6 *= scale; + + M[mad24(y, mStep, x)] = r4*r4 + r6*r6; + M[mad24(rows + y, mStep, x)] = (r4 + r5)*r6; + M[mad24(2*rows + y, mStep, x)] = r5*r5 + r6*r6; + M[mad24(3*rows + y, mStep, x)] = r4*r2 + r6*r3; + M[mad24(4*rows + y, mStep, x)] = r6*r2 + r5*r3; + } +} + +__kernel void boxFilter5(__global const float * src, int srcStep, + __global float * dst, int dstStep, + const int rows, const int cols, + const int ksizeHalf, + __local float * smem) +{ + const int y = get_global_id(1); + const int x = get_global_id(0); + + const float boxAreaInv = 1.f / ((1 + 2*ksizeHalf) * (1 + 2*ksizeHalf)); + const int smw = bdx + 2*ksizeHalf; // shared memory "width" + __local float *row = smem + 5 * ty * smw; + + if (y < rows) + { + // Vertical pass + for (int i = tx; i < bdx + 2*ksizeHalf; i += bdx) + { + int xExt = (int)(bx * bdx) + i - ksizeHalf; + xExt = min(max(xExt, 0), cols - 1); + +#pragma unroll + for (int k = 0; k < 5; ++k) + row[k*smw + i] = src[mad24(k*rows + y, srcStep, xExt)]; + + for (int j = 1; j <= ksizeHalf; ++j) +#pragma unroll + for (int k = 0; k < 5; ++k) + row[k*smw + i] += + src[mad24(k*rows + max(y - j, 0), srcStep, xExt)] + + src[mad24(k*rows + min(y + j, rows - 1), srcStep, xExt)]; + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + if (y < rows && y >= 0 && x < cols && x >= 0) + { + // Horizontal pass + + row += tx + ksizeHalf; + float res[5]; + +#pragma unroll + for (int k = 0; k < 5; ++k) + res[k] = row[k*smw]; + + for (int i = 1; i <= ksizeHalf; ++i) +#pragma unroll + for (int k = 0; k < 5; ++k) + res[k] += row[k*smw - i] + row[k*smw + i]; + +#pragma unroll + for (int k = 0; k < 5; ++k) + dst[mad24(k*rows + y, dstStep, x)] = res[k] * boxAreaInv; + } +} + +__kernel void updateFlow(__global const float * M, int mStep, + __global float * flowx, int xStep, + __global float * flowy, int yStep, + const int rows, const int cols) +{ + const int y = get_global_id(1); + const int x = get_global_id(0); + + if (y < rows && y >= 0 && x < cols && x >= 0) + { + float g11 = M[mad24(y, mStep, x)]; + float g12 = M[mad24(rows + y, mStep, x)]; + float g22 = M[mad24(2*rows + y, mStep, x)]; + float h1 = M[mad24(3*rows + y, mStep, x)]; + float h2 = M[mad24(4*rows + y, mStep, x)]; + + float detInv = 1.f / (g11*g22 - g12*g12 + 1e-3f); + + flowx[mad24(y, xStep, x)] = (g11*h2 - g12*h1) * detInv; + flowy[mad24(y, yStep, x)] = (g22*h1 - g12*h2) * detInv; + } +} \ No newline at end of file diff --git a/modules/video/src/optflowgf.cpp b/modules/video/src/optflowgf.cpp index 19e96885b..f4664ae8e 100644 --- a/modules/video/src/optflowgf.cpp +++ b/modules/video/src/optflowgf.cpp @@ -41,6 +41,7 @@ //M*/ #include "precomp.hpp" +#include "opencl_kernels.hpp" // // 2D dense optical flow algorithm from the following paper: @@ -52,47 +53,40 @@ namespace cv { static void -FarnebackPolyExp( const Mat& src, Mat& dst, int n, double sigma ) +FarnebackPrepareGaussian(int n, double sigma, float *g, float *xg, float *xxg, + double &ig11, double &ig03, double &ig33, double &ig55) { - int k, x, y; - - CV_Assert( src.type() == CV_32FC1 ); - int width = src.cols; - int height = src.rows; - AutoBuffer kbuf(n*6 + 3), _row((width + n*2)*3); - float* g = kbuf + n; - float* xg = g + n*2 + 1; - float* xxg = xg + n*2 + 1; - float *row = (float*)_row + n*3; - if( sigma < FLT_EPSILON ) sigma = n*0.3; double s = 0.; - for( x = -n; x <= n; x++ ) + for (int x = -n; x <= n; x++) { g[x] = (float)std::exp(-x*x/(2*sigma*sigma)); s += g[x]; } s = 1./s; - for( x = -n; x <= n; x++ ) + for (int x = -n; x <= n; x++) { g[x] = (float)(g[x]*s); xg[x] = (float)(x*g[x]); xxg[x] = (float)(x*x*g[x]); } - Mat_ G = Mat_::zeros(6, 6); + Mat_ G(6, 6); + G.setTo(0); - for( y = -n; y <= n; y++ ) - for( x = -n; x <= n; x++ ) + for (int y = -n; y <= n; y++) + { + for (int x = -n; x <= n; x++) { G(0,0) += g[y]*g[x]; G(1,1) += g[y]*g[x]*x*x; G(3,3) += g[y]*g[x]*x*x*x*x; G(5,5) += g[y]*g[x]*x*x*y*y; } + } //G[0][0] = 1.; G(2,2) = G(0,3) = G(0,4) = G(3,0) = G(4,0) = G(1,1); @@ -107,7 +101,29 @@ FarnebackPolyExp( const Mat& src, Mat& dst, int n, double sigma ) // [ e z ] // [ u ] Mat_ invG = G.inv(DECOMP_CHOLESKY); - double ig11 = invG(1,1), ig03 = invG(0,3), ig33 = invG(3,3), ig55 = invG(5,5); + + ig11 = invG(1,1); + ig03 = invG(0,3); + ig33 = invG(3,3); + ig55 = invG(5,5); +} + +static void +FarnebackPolyExp( const Mat& src, Mat& dst, int n, double sigma ) +{ + int k, x, y; + + CV_Assert( src.type() == CV_32FC1 ); + int width = src.cols; + int height = src.rows; + AutoBuffer kbuf(n*6 + 3), _row((width + n*2)*3); + float* g = kbuf + n; + float* xg = g + n*2 + 1; + float* xxg = xg + n*2 + 1; + float *row = (float*)_row + n*3; + double ig11, ig03, ig33, ig55; + + FarnebackPrepareGaussian(n, sigma, g, xg, xxg, ig11, ig03, ig33, ig55); dst.create( height, width, CV_32FC(5)); @@ -563,10 +579,484 @@ FarnebackUpdateFlow_GaussianBlur( const Mat& _R0, const Mat& _R1, } +namespace cv +{ +class FarnebackOpticalFlow +{ +public: + FarnebackOpticalFlow() + { + numLevels = 5; + pyrScale = 0.5; + fastPyramids = false; + winSize = 13; + numIters = 10; + polyN = 5; + polySigma = 1.1; + flags = 0; + } + + int numLevels; + double pyrScale; + bool fastPyramids; + int winSize; + int numIters; + int polyN; + double polySigma; + int flags; + + void operator ()(const UMat &frame0, const UMat &frame1, UMat &flowx, UMat &flowy) + { + CV_Assert(frame0.channels() == 1 && frame1.channels() == 1); + CV_Assert(frame0.size() == frame1.size()); + CV_Assert(polyN == 5 || polyN == 7); + CV_Assert(!fastPyramids || std::abs(pyrScale - 0.5) < 1e-6); + + const int min_size = 32; + + Size size = frame0.size(); + UMat prevFlowX, prevFlowY, curFlowX, curFlowY; + + flowx.create(size, CV_32F); + flowy.create(size, CV_32F); + UMat flowx0 = flowx; + UMat flowy0 = flowy; + + // Crop unnecessary levels + double scale = 1; + int numLevelsCropped = 0; + for (; numLevelsCropped < numLevels; numLevelsCropped++) + { + scale *= pyrScale; + if (size.width*scale < min_size || size.height*scale < min_size) + break; + } + + frame0.convertTo(frames_[0], CV_32F); + frame1.convertTo(frames_[1], CV_32F); + + if (fastPyramids) + { + // Build Gaussian pyramids using pyrDown() + pyramid0_.resize(numLevelsCropped + 1); + pyramid1_.resize(numLevelsCropped + 1); + pyramid0_[0] = frames_[0]; + pyramid1_[0] = frames_[1]; + for (int i = 1; i <= numLevelsCropped; ++i) + { + pyrDown(pyramid0_[i - 1], pyramid0_[i]); + pyrDown(pyramid1_[i - 1], pyramid1_[i]); + } + } + + setPolynomialExpansionConsts(polyN, polySigma); + + for (int k = numLevelsCropped; k >= 0; k--) + { + scale = 1; + for (int i = 0; i < k; i++) + scale *= pyrScale; + + double sigma = (1./scale - 1) * 0.5; + int smoothSize = cvRound(sigma*5) | 1; + smoothSize = std::max(smoothSize, 3); + + int width = cvRound(size.width*scale); + int height = cvRound(size.height*scale); + + if (fastPyramids) + { + width = pyramid0_[k].cols; + height = pyramid0_[k].rows; + } + + if (k > 0) + { + curFlowX.create(height, width, CV_32F); + curFlowY.create(height, width, CV_32F); + } + else + { + curFlowX = flowx0; + curFlowY = flowy0; + } + + if (prevFlowX.empty()) + { + if (flags & cv::OPTFLOW_USE_INITIAL_FLOW) + { + resize(flowx0, curFlowX, Size(width, height), 0, 0, INTER_LINEAR); + resize(flowy0, curFlowY, Size(width, height), 0, 0, INTER_LINEAR); + multiply(scale, curFlowX, curFlowX); + multiply(scale, curFlowY, curFlowY); + } + else + { + curFlowX.setTo(0); + curFlowY.setTo(0); + } + } + else + { + resize(prevFlowX, curFlowX, Size(width, height), 0, 0, INTER_LINEAR); + resize(prevFlowY, curFlowY, Size(width, height), 0, 0, INTER_LINEAR); + multiply(1./pyrScale, curFlowX, curFlowX); + multiply(1./pyrScale, curFlowY, curFlowY); + } + + UMat M = allocMatFromBuf(5*height, width, CV_32F, M_); + UMat bufM = allocMatFromBuf(5*height, width, CV_32F, bufM_); + UMat R[2] = + { + allocMatFromBuf(5*height, width, CV_32F, R_[0]), + allocMatFromBuf(5*height, width, CV_32F, R_[1]) + }; + + if (fastPyramids) + { + polynomialExpansionOcl(pyramid0_[k], polyN, R[0]); + polynomialExpansionOcl(pyramid1_[k], polyN, R[1]); + } + else + { + UMat blurredFrame[2] = + { + allocMatFromBuf(size.height, size.width, CV_32F, blurredFrame_[0]), + allocMatFromBuf(size.height, size.width, CV_32F, blurredFrame_[1]) + }; + UMat pyrLevel[2] = + { + allocMatFromBuf(height, width, CV_32F, pyrLevel_[0]), + allocMatFromBuf(height, width, CV_32F, pyrLevel_[1]) + }; + + setGaussianBlurKernel(smoothSize, sigma); + + for (int i = 0; i < 2; i++) + { + gaussianBlurOcl(frames_[i], smoothSize/2, blurredFrame[i]); + resize(blurredFrame[i], pyrLevel[i], Size(width, height), INTER_LINEAR); + polynomialExpansionOcl(pyrLevel[i], polyN, R[i]); + } + } + + updateMatricesOcl(curFlowX, curFlowY, R[0], R[1], M); + + if (flags & OPTFLOW_FARNEBACK_GAUSSIAN) + setGaussianBlurKernel(winSize, winSize/2*0.3f); + for (int i = 0; i < numIters; i++) + { + if (flags & OPTFLOW_FARNEBACK_GAUSSIAN) + updateFlow_gaussianBlur(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize, i < numIters-1); + else + updateFlow_boxFilter(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize, i < numIters-1); + } + + prevFlowX = curFlowX; + prevFlowY = curFlowY; + } + + flowx = curFlowX; + flowy = curFlowY; + } + + void releaseMemory() + { + frames_[0].release(); + frames_[1].release(); + pyrLevel_[0].release(); + pyrLevel_[1].release(); + M_.release(); + bufM_.release(); + R_[0].release(); + R_[1].release(); + blurredFrame_[0].release(); + blurredFrame_[1].release(); + pyramid0_.clear(); + pyramid1_.clear(); + } +private: + UMat m_g; + UMat m_xg; + UMat m_xxg; + + double m_igd[4]; + float m_ig[4]; + void setPolynomialExpansionConsts(int n, double sigma) + { + std::vector buf(n*6 + 3); + float* g = &buf[0] + n; + float* xg = g + n*2 + 1; + float* xxg = xg + n*2 + 1; + + FarnebackPrepareGaussian(n, sigma, g, xg, xxg, m_igd[0], m_igd[1], m_igd[2], m_igd[3]); + + cv::Mat t_g(1, n + 1, CV_32FC1, g); t_g.copyTo(m_g); + cv::Mat t_xg(1, n + 1, CV_32FC1, xg); t_xg.copyTo(m_xg); + cv::Mat t_xxg(1, n + 1, CV_32FC1, xxg); t_xxg.copyTo(m_xxg); + + m_ig[0] = static_cast(m_igd[0]); + m_ig[1] = static_cast(m_igd[1]); + m_ig[2] = static_cast(m_igd[2]); + m_ig[3] = static_cast(m_igd[3]); + } +private: + UMat m_gKer; + inline void setGaussianBlurKernel(int smoothSize, double sigma) + { + Mat g = getGaussianKernel(smoothSize, sigma, CV_32F); + Mat gKer(1, smoothSize/2 + 1, CV_32FC1, g.ptr(smoothSize/2)); + gKer.copyTo(m_gKer); + } +private: + UMat frames_[2]; + UMat pyrLevel_[2], M_, bufM_, R_[2], blurredFrame_[2]; + std::vector pyramid0_, pyramid1_; + + static UMat allocMatFromBuf(int rows, int cols, int type, UMat &mat) + { + if (!mat.empty() && mat.type() == type && mat.rows >= rows && mat.cols >= cols) + return mat(Rect(0, 0, cols, rows)); + return mat = UMat(rows, cols, type); + } +private: +#define DIVUP(total, grain) (((total) + (grain) - 1) / (grain)) + + bool gaussianBlurOcl(const UMat &src, int ksizeHalf, UMat &dst) + { +#ifdef ANDROID + size_t localsize[2] = { 128, 1}; +#else + size_t localsize[2] = { 256, 1}; +#endif + size_t globalsize[2] = { src.cols, src.rows}; + int smem_size = (int)((localsize[0] + 2*ksizeHalf) * sizeof(float)); + ocl::Kernel kernel; + if (!kernel.create("gaussianBlur", cv::ocl::video::optical_flow_farneback_oclsrc, "")) + return false; + + CV_Assert(dst.size() == src.size()); + int idxArg = 0; + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(src)); + idxArg = kernel.set(idxArg, (int)(src.step / src.elemSize())); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrWriteOnly(dst)); + idxArg = kernel.set(idxArg, (int)(dst.step / dst.elemSize())); + idxArg = kernel.set(idxArg, dst.rows); + idxArg = kernel.set(idxArg, dst.cols); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(m_gKer)); + idxArg = kernel.set(idxArg, (int)ksizeHalf); + idxArg = kernel.set(idxArg, (void *)NULL, smem_size); + return kernel.run(2, globalsize, localsize, false); + } + bool gaussianBlur5Ocl(const UMat &src, int ksizeHalf, UMat &dst) + { + int height = src.rows / 5; +#ifdef ANDROID + size_t localsize[2] = { 128, 1}; +#else + size_t localsize[2] = { 256, 1}; +#endif + size_t globalsize[2] = { src.cols, height}; + int smem_size = (int)((localsize[0] + 2*ksizeHalf) * 5 * sizeof(float)); + ocl::Kernel kernel; + if (!kernel.create("gaussianBlur5", cv::ocl::video::optical_flow_farneback_oclsrc, "")) + return false; + + int idxArg = 0; + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(src)); + idxArg = kernel.set(idxArg, (int)(src.step / src.elemSize())); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrWriteOnly(dst)); + idxArg = kernel.set(idxArg, (int)(dst.step / dst.elemSize())); + idxArg = kernel.set(idxArg, height); + idxArg = kernel.set(idxArg, src.cols); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(m_gKer)); + idxArg = kernel.set(idxArg, (int)ksizeHalf); + idxArg = kernel.set(idxArg, (void *)NULL, smem_size); + return kernel.run(2, globalsize, localsize, false); + } + bool polynomialExpansionOcl(const UMat &src, int polyN, UMat &dst) + { +#ifdef ANDROID + size_t localsize[2] = { 128, 1}; +#else + size_t localsize[2] = { 256, 1}; +#endif + size_t globalsize[2] = { DIVUP(src.cols, localsize[0] - 2*polyN) * localsize[0], src.rows}; + + const cv::ocl::Device &device = cv::ocl::Device::getDefault(); + int useDouble = (0 != device.doubleFPConfig()); + + cv::String build_options = cv::format("-D polyN=%d -D USE_DOUBLE=%d", polyN, useDouble ? 1 : 0); + ocl::Kernel kernel; + if (!kernel.create("polynomialExpansion", cv::ocl::video::optical_flow_farneback_oclsrc, build_options)) + return false; + + int smem_size = (int)(3 * localsize[0] * sizeof(float)); + int idxArg = 0; + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(src)); + idxArg = kernel.set(idxArg, (int)(src.step / src.elemSize())); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrWriteOnly(dst)); + idxArg = kernel.set(idxArg, (int)(dst.step / dst.elemSize())); + idxArg = kernel.set(idxArg, src.rows); + idxArg = kernel.set(idxArg, src.cols); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(m_g)); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(m_xg)); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(m_xxg)); + idxArg = kernel.set(idxArg, (void *)NULL, smem_size); + if (useDouble) + idxArg = kernel.set(idxArg, (void *)m_igd, 4 * sizeof(double)); + else + idxArg = kernel.set(idxArg, (void *)m_ig, 4 * sizeof(float)); + return kernel.run(2, globalsize, localsize, false); + } + bool boxFilter5Ocl(const UMat &src, int ksizeHalf, UMat &dst) + { + int height = src.rows / 5; +#ifdef ANDROID + size_t localsize[2] = { 128, 1}; +#else + size_t localsize[2] = { 256, 1}; +#endif + size_t globalsize[2] = { src.cols, height}; + + ocl::Kernel kernel; + if (!kernel.create("boxFilter5", cv::ocl::video::optical_flow_farneback_oclsrc, "")) + return false; + + int smem_size = (int)((localsize[0] + 2*ksizeHalf) * 5 * sizeof(float)); + + int idxArg = 0; + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(src)); + idxArg = kernel.set(idxArg, (int)(src.step / src.elemSize())); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrWriteOnly(dst)); + idxArg = kernel.set(idxArg, (int)(dst.step / dst.elemSize())); + idxArg = kernel.set(idxArg, height); + idxArg = kernel.set(idxArg, src.cols); + idxArg = kernel.set(idxArg, (int)ksizeHalf); + idxArg = kernel.set(idxArg, (void *)NULL, smem_size); + return kernel.run(2, globalsize, localsize, false); + } + + bool updateFlowOcl(const UMat &M, UMat &flowx, UMat &flowy) + { +#ifdef ANDROID + size_t localsize[2] = { 32, 4}; +#else + size_t localsize[2] = { 32, 8}; +#endif + size_t globalsize[2] = { flowx.cols, flowx.rows}; + + ocl::Kernel kernel; + if (!kernel.create("updateFlow", cv::ocl::video::optical_flow_farneback_oclsrc, "")) + return false; + + int idxArg = 0; + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrWriteOnly(M)); + idxArg = kernel.set(idxArg, (int)(M.step / M.elemSize())); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(flowx)); + idxArg = kernel.set(idxArg, (int)(flowx.step / flowx.elemSize())); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(flowy)); + idxArg = kernel.set(idxArg, (int)(flowy.step / flowy.elemSize())); + idxArg = kernel.set(idxArg, (int)flowy.rows); + idxArg = kernel.set(idxArg, (int)flowy.cols); + return kernel.run(2, globalsize, localsize, false); + } + bool updateMatricesOcl(const UMat &flowx, const UMat &flowy, const UMat &R0, const UMat &R1, UMat &M) + { +#ifdef ANDROID + size_t localsize[2] = { 32, 4}; +#else + size_t localsize[2] = { 32, 8}; +#endif + size_t globalsize[2] = { flowx.cols, flowx.rows}; + + ocl::Kernel kernel; + if (!kernel.create("updateMatrices", cv::ocl::video::optical_flow_farneback_oclsrc, "")) + return false; + + int idxArg = 0; + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(flowx)); + idxArg = kernel.set(idxArg, (int)(flowx.step / flowx.elemSize())); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(flowy)); + idxArg = kernel.set(idxArg, (int)(flowy.step / flowy.elemSize())); + idxArg = kernel.set(idxArg, (int)flowx.rows); + idxArg = kernel.set(idxArg, (int)flowx.cols); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(R0)); + idxArg = kernel.set(idxArg, (int)(R0.step / R0.elemSize())); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(R1)); + idxArg = kernel.set(idxArg, (int)(R1.step / R1.elemSize())); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrWriteOnly(M)); + idxArg = kernel.set(idxArg, (int)(M.step / M.elemSize())); + return kernel.run(2, globalsize, localsize, false); + } + + void updateFlow_boxFilter( + const UMat& R0, const UMat& R1, UMat& flowx, UMat &flowy, + UMat& M, UMat &bufM, int blockSize, bool updateMatrices) + { + boxFilter5Ocl(M, blockSize/2, bufM); + swap(M, bufM); + updateFlowOcl(M, flowx, flowy); + if (updateMatrices) + updateMatricesOcl(flowx, flowy, R0, R1, M); + } + void updateFlow_gaussianBlur( + const UMat& R0, const UMat& R1, UMat& flowx, UMat& flowy, + UMat& M, UMat &bufM, int blockSize, bool updateMatrices) + { + gaussianBlur5Ocl(M, blockSize/2, bufM); + swap(M, bufM); + updateFlowOcl(M, flowx, flowy); + if (updateMatrices) + updateMatricesOcl(flowx, flowy, R0, R1, M); + } +}; + +static bool ocl_calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0, + InputOutputArray _flow0, double pyr_scale, int levels, int winsize, + int iterations, int poly_n, double poly_sigma, int flags ) +{ + if ((5 != poly_n) && (7 != poly_n)) + return false; + if (_next0.size() != _prev0.size()) + return false; + int typePrev = _prev0.type(); + int typeNext = _next0.type(); + if ((1 != CV_MAT_CN(typePrev)) || (1 != CV_MAT_CN(typeNext))) + return false; + + FarnebackOpticalFlow opticalFlow; + opticalFlow.numLevels = levels; + opticalFlow.pyrScale = pyr_scale; + opticalFlow.fastPyramids= false; + opticalFlow.winSize = winsize; + opticalFlow.numIters = iterations; + opticalFlow.polyN = poly_n; + opticalFlow.polySigma = poly_sigma; + opticalFlow.flags = flags; + + std::vector flowar; + if (!_flow0.empty()) + split(_flow0, flowar); + else + { + flowar.push_back(UMat()); + flowar.push_back(UMat()); + } + opticalFlow(_prev0.getUMat(), _next0.getUMat(), flowar[0], flowar[1]); + merge(flowar, _flow0); + return true; +} +} + void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0, InputOutputArray _flow0, double pyr_scale, int levels, int winsize, int iterations, int poly_n, double poly_sigma, int flags ) { + bool use_opencl = ocl::useOpenCL() && _flow0.isUMat(); + if( use_opencl && ocl_calcOpticalFlowFarneback(_prev0, _next0, _flow0, pyr_scale, levels, winsize, iterations, poly_n, poly_sigma, flags)) + return; + Mat prev0 = _prev0.getMat(), next0 = _next0.getMat(); const int min_size = 32; const Mat* img[2] = { &prev0, &next0 }; diff --git a/modules/video/src/precomp.hpp b/modules/video/src/precomp.hpp index 43ff772cc..ba0c93112 100644 --- a/modules/video/src/precomp.hpp +++ b/modules/video/src/precomp.hpp @@ -46,6 +46,7 @@ #include "opencv2/video.hpp" #include "opencv2/core/utility.hpp" #include "opencv2/core/private.hpp" +#include "opencv2/core/ocl.hpp" #ifdef HAVE_TEGRA_OPTIMIZATION #include "opencv2/video/video_tegra.hpp" diff --git a/modules/video/test/ocl/test_optflow_farneback.cpp b/modules/video/test/ocl/test_optflow_farneback.cpp new file mode 100644 index 000000000..bb3575885 --- /dev/null +++ b/modules/video/test/ocl/test_optflow_farneback.cpp @@ -0,0 +1,110 @@ +/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Copyright (C) 2010-2012, Multicoreware, Inc., 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*/ + +#include "test_precomp.hpp" +#include "opencv2/ts/ocl_test.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +///////////////////////////////////////////////////////////////////////////////////////////////// +// FarnebackOpticalFlow +namespace +{ + IMPLEMENT_PARAM_CLASS(PyrScale, double) + IMPLEMENT_PARAM_CLASS(PolyN, int) + CV_FLAGS(FarnebackOptFlowFlags, 0, OPTFLOW_FARNEBACK_GAUSSIAN) +} + +PARAM_TEST_CASE(FarnebackOpticalFlow, PyrScale, PolyN, FarnebackOptFlowFlags) +{ + int numLevels; + int winSize; + int numIters; + double pyrScale; + int polyN; + int flags; + + virtual void SetUp() + { + numLevels = 5; + winSize = 13; + numIters = 10; + pyrScale = GET_PARAM(0); + polyN = GET_PARAM(1); + flags = GET_PARAM(2); + } +}; + +OCL_TEST_P(FarnebackOpticalFlow, Accuracy) +{ + cv::Mat frame0 = readImage("optflow/RubberWhale1.png", cv::IMREAD_GRAYSCALE); + ASSERT_FALSE(frame0.empty()); + + cv::Mat frame1 = readImage("optflow/RubberWhale2.png", cv::IMREAD_GRAYSCALE); + ASSERT_FALSE(frame1.empty()); + + double polySigma = polyN <= 5 ? 1.1 : 1.5; + + cv::Mat flow; cv::UMat uflow; + OCL_OFF(cv::calcOpticalFlowFarneback(frame0, frame1, flow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags)); + OCL_ON(cv::calcOpticalFlowFarneback(frame0, frame1, uflow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags)); + + EXPECT_MAT_SIMILAR(flow, uflow, 0.1) +} + + +OCL_INSTANTIATE_TEST_CASE_P(Video, FarnebackOpticalFlow, + Combine( + Values(PyrScale(0.3), PyrScale(0.5), PyrScale(0.8)), + Values(PolyN(5), PolyN(7)), + Values(FarnebackOptFlowFlags(0), FarnebackOptFlowFlags(cv::OPTFLOW_FARNEBACK_GAUSSIAN)) + ) + ); + + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL \ No newline at end of file From 3762036b0814e7cc27bd9d68ce9760708174fbab Mon Sep 17 00:00:00 2001 From: vbystricky Date: Fri, 10 Jan 2014 12:44:21 +0400 Subject: [PATCH 088/295] Fix compiler warnings. Add additional test case for UseInitFlow --- modules/video/src/optflowgf.cpp | 8 ++++---- .../video/test/ocl/test_optflow_farneback.cpp | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/modules/video/src/optflowgf.cpp b/modules/video/src/optflowgf.cpp index f4664ae8e..9d156e921 100644 --- a/modules/video/src/optflowgf.cpp +++ b/modules/video/src/optflowgf.cpp @@ -714,8 +714,8 @@ public: if (fastPyramids) { - polynomialExpansionOcl(pyramid0_[k], polyN, R[0]); - polynomialExpansionOcl(pyramid1_[k], polyN, R[1]); + polynomialExpansionOcl(pyramid0_[k], R[0]); + polynomialExpansionOcl(pyramid1_[k], R[1]); } else { @@ -736,7 +736,7 @@ public: { gaussianBlurOcl(frames_[i], smoothSize/2, blurredFrame[i]); resize(blurredFrame[i], pyrLevel[i], Size(width, height), INTER_LINEAR); - polynomialExpansionOcl(pyrLevel[i], polyN, R[i]); + polynomialExpansionOcl(pyrLevel[i], R[i]); } } @@ -874,7 +874,7 @@ private: idxArg = kernel.set(idxArg, (void *)NULL, smem_size); return kernel.run(2, globalsize, localsize, false); } - bool polynomialExpansionOcl(const UMat &src, int polyN, UMat &dst) + bool polynomialExpansionOcl(const UMat &src, UMat &dst) { #ifdef ANDROID size_t localsize[2] = { 128, 1}; diff --git a/modules/video/test/ocl/test_optflow_farneback.cpp b/modules/video/test/ocl/test_optflow_farneback.cpp index bb3575885..c2d13e006 100644 --- a/modules/video/test/ocl/test_optflow_farneback.cpp +++ b/modules/video/test/ocl/test_optflow_farneback.cpp @@ -56,9 +56,10 @@ namespace IMPLEMENT_PARAM_CLASS(PyrScale, double) IMPLEMENT_PARAM_CLASS(PolyN, int) CV_FLAGS(FarnebackOptFlowFlags, 0, OPTFLOW_FARNEBACK_GAUSSIAN) + IMPLEMENT_PARAM_CLASS(UseInitFlow, bool) } -PARAM_TEST_CASE(FarnebackOpticalFlow, PyrScale, PolyN, FarnebackOptFlowFlags) +PARAM_TEST_CASE(FarnebackOpticalFlow, PyrScale, PolyN, FarnebackOptFlowFlags, UseInitFlow) { int numLevels; int winSize; @@ -66,6 +67,7 @@ PARAM_TEST_CASE(FarnebackOpticalFlow, PyrScale, PolyN, FarnebackOptFlowFlags) double pyrScale; int polyN; int flags; + bool useInitFlow; virtual void SetUp() { @@ -75,10 +77,11 @@ PARAM_TEST_CASE(FarnebackOpticalFlow, PyrScale, PolyN, FarnebackOptFlowFlags) pyrScale = GET_PARAM(0); polyN = GET_PARAM(1); flags = GET_PARAM(2); + useInitFlow = GET_PARAM(3); } }; -OCL_TEST_P(FarnebackOpticalFlow, Accuracy) +OCL_TEST_P(FarnebackOpticalFlow, Mat) { cv::Mat frame0 = readImage("optflow/RubberWhale1.png", cv::IMREAD_GRAYSCALE); ASSERT_FALSE(frame0.empty()); @@ -89,6 +92,12 @@ OCL_TEST_P(FarnebackOpticalFlow, Accuracy) double polySigma = polyN <= 5 ? 1.1 : 1.5; cv::Mat flow; cv::UMat uflow; + if (useInitFlow) + { + OCL_ON(cv::calcOpticalFlowFarneback(frame0, frame1, uflow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags)); + uflow.copyTo(flow); + flags |= cv::OPTFLOW_USE_INITIAL_FLOW; + } OCL_OFF(cv::calcOpticalFlowFarneback(frame0, frame1, flow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags)); OCL_ON(cv::calcOpticalFlowFarneback(frame0, frame1, uflow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags)); @@ -100,7 +109,8 @@ OCL_INSTANTIATE_TEST_CASE_P(Video, FarnebackOpticalFlow, Combine( Values(PyrScale(0.3), PyrScale(0.5), PyrScale(0.8)), Values(PolyN(5), PolyN(7)), - Values(FarnebackOptFlowFlags(0), FarnebackOptFlowFlags(cv::OPTFLOW_FARNEBACK_GAUSSIAN)) + Values(FarnebackOptFlowFlags(0), FarnebackOptFlowFlags(cv::OPTFLOW_FARNEBACK_GAUSSIAN)), + Values(UseInitFlow(false), UseInitFlow(true)) ) ); From fc8b385ff6c6e02fb3c696dda65c244878fdab0a Mon Sep 17 00:00:00 2001 From: vbystricky Date: Tue, 14 Jan 2014 17:53:28 +0400 Subject: [PATCH 089/295] Return false if ocl version not properly worked --- modules/video/src/optflowgf.cpp | 57 ++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/modules/video/src/optflowgf.cpp b/modules/video/src/optflowgf.cpp index 9d156e921..b237e5432 100644 --- a/modules/video/src/optflowgf.cpp +++ b/modules/video/src/optflowgf.cpp @@ -605,7 +605,7 @@ public: double polySigma; int flags; - void operator ()(const UMat &frame0, const UMat &frame1, UMat &flowx, UMat &flowy) + bool operator ()(const UMat &frame0, const UMat &frame1, UMat &flowx, UMat &flowy) { CV_Assert(frame0.channels() == 1 && frame1.channels() == 1); CV_Assert(frame0.size() == frame1.size()); @@ -714,8 +714,10 @@ public: if (fastPyramids) { - polynomialExpansionOcl(pyramid0_[k], R[0]); - polynomialExpansionOcl(pyramid1_[k], R[1]); + if (!polynomialExpansionOcl(pyramid0_[k], R[0])) + return false; + if (!polynomialExpansionOcl(pyramid1_[k], R[1])) + return false; } else { @@ -734,22 +736,31 @@ public: for (int i = 0; i < 2; i++) { - gaussianBlurOcl(frames_[i], smoothSize/2, blurredFrame[i]); + if (!gaussianBlurOcl(frames_[i], smoothSize/2, blurredFrame[i])) + return false; resize(blurredFrame[i], pyrLevel[i], Size(width, height), INTER_LINEAR); - polynomialExpansionOcl(pyrLevel[i], R[i]); + if (!polynomialExpansionOcl(pyrLevel[i], R[i])) + return false; } } - updateMatricesOcl(curFlowX, curFlowY, R[0], R[1], M); + if (!updateMatricesOcl(curFlowX, curFlowY, R[0], R[1], M)) + return false; if (flags & OPTFLOW_FARNEBACK_GAUSSIAN) setGaussianBlurKernel(winSize, winSize/2*0.3f); for (int i = 0; i < numIters; i++) { if (flags & OPTFLOW_FARNEBACK_GAUSSIAN) - updateFlow_gaussianBlur(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize, i < numIters-1); + { + if (!updateFlow_gaussianBlur(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize, i < numIters-1)) + return false; + } else - updateFlow_boxFilter(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize, i < numIters-1); + { + if (!updateFlow_boxFilter(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize, i < numIters-1)) + return false; + } } prevFlowX = curFlowX; @@ -758,6 +769,7 @@ public: flowx = curFlowX; flowy = curFlowY; + return true; } void releaseMemory() @@ -884,7 +896,7 @@ private: size_t globalsize[2] = { DIVUP(src.cols, localsize[0] - 2*polyN) * localsize[0], src.rows}; const cv::ocl::Device &device = cv::ocl::Device::getDefault(); - int useDouble = (0 != device.doubleFPConfig()); + bool useDouble = (0 != device.doubleFPConfig()); cv::String build_options = cv::format("-D polyN=%d -D USE_DOUBLE=%d", polyN, useDouble ? 1 : 0); ocl::Kernel kernel; @@ -990,25 +1002,33 @@ private: return kernel.run(2, globalsize, localsize, false); } - void updateFlow_boxFilter( + bool updateFlow_boxFilter( const UMat& R0, const UMat& R1, UMat& flowx, UMat &flowy, UMat& M, UMat &bufM, int blockSize, bool updateMatrices) { - boxFilter5Ocl(M, blockSize/2, bufM); + if (!boxFilter5Ocl(M, blockSize/2, bufM)) + return false; swap(M, bufM); - updateFlowOcl(M, flowx, flowy); + if (!updateFlowOcl(M, flowx, flowy)) + return false; if (updateMatrices) - updateMatricesOcl(flowx, flowy, R0, R1, M); + if (!updateMatricesOcl(flowx, flowy, R0, R1, M)) + return false; + return true; } - void updateFlow_gaussianBlur( + bool updateFlow_gaussianBlur( const UMat& R0, const UMat& R1, UMat& flowx, UMat& flowy, UMat& M, UMat &bufM, int blockSize, bool updateMatrices) { - gaussianBlur5Ocl(M, blockSize/2, bufM); + if (!gaussianBlur5Ocl(M, blockSize/2, bufM)) + return false; swap(M, bufM); - updateFlowOcl(M, flowx, flowy); + if (!updateFlowOcl(M, flowx, flowy)) + return false; if (updateMatrices) - updateMatricesOcl(flowx, flowy, R0, R1, M); + if (!updateMatricesOcl(flowx, flowy, R0, R1, M)) + return false; + return true; } }; @@ -1043,7 +1063,8 @@ static bool ocl_calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0, flowar.push_back(UMat()); flowar.push_back(UMat()); } - opticalFlow(_prev0.getUMat(), _next0.getUMat(), flowar[0], flowar[1]); + if (!opticalFlow(_prev0.getUMat(), _next0.getUMat(), flowar[0], flowar[1])) + return false; merge(flowar, _flow0); return true; } From f1541b528712c07343e9916380d845ac8afd1443 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Fri, 17 Jan 2014 15:23:16 +0400 Subject: [PATCH 090/295] Add perfomance test --- .../perf/opencl/perf_optflow_farneback.cpp | 114 ++++++++++++++++++ modules/video/src/optflowgf.cpp | 6 + 2 files changed, 120 insertions(+) create mode 100644 modules/video/perf/opencl/perf_optflow_farneback.cpp diff --git a/modules/video/perf/opencl/perf_optflow_farneback.cpp b/modules/video/perf/opencl/perf_optflow_farneback.cpp new file mode 100644 index 000000000..2b968aaf4 --- /dev/null +++ b/modules/video/perf/opencl/perf_optflow_farneback.cpp @@ -0,0 +1,114 @@ +/*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/ts/ocl_perf.hpp" + +using std::tr1::make_tuple; + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +///////////// FarnebackOpticalFlow //////////////////////// +CV_ENUM(farneFlagType, 0, OPTFLOW_FARNEBACK_GAUSSIAN) + +typedef tuple< tuple, farneFlagType, bool > FarnebackOpticalFlowParams; +typedef TestBaseWithParam FarnebackOpticalFlowFixture; + +OCL_PERF_TEST_P(FarnebackOpticalFlowFixture, FarnebackOpticalFlow, + ::testing::Combine( + ::testing::Values( + make_tuple(5, 1.1), + make_tuple(7, 1.5) + ), + farneFlagType::all(), + ::testing::Bool() + ) + ) +{ + Mat frame0 = imread(getDataPath("gpu/opticalflow/rubberwhale1.png"), cv::IMREAD_GRAYSCALE); + ASSERT_FALSE(frame0.empty()) << "can't load rubberwhale1.png"; + + Mat frame1 = imread(getDataPath("gpu/opticalflow/rubberwhale2.png"), cv::IMREAD_GRAYSCALE); + ASSERT_FALSE(frame1.empty()) << "can't load rubberwhale2.png"; + + const Size srcSize = frame0.size(); + + const int numLevels = 5; + const int winSize = 13; + const int numIters = 10; + + const FarnebackOpticalFlowParams params = GetParam(); + const tuple polyParams = get<0>(params); + const int polyN = get<0>(polyParams); + const double polySigma = get<1>(polyParams); + const double pyrScale = 0.5; + int flags = get<1>(params); + const bool useInitFlow = get<2>(params); + const double eps = 1.5; + + UMat uFrame0; frame0.copyTo(uFrame0); + UMat uFrame1; frame1.copyTo(uFrame1); + UMat uFlow(srcSize, CV_32FC2); + declare.in(uFrame0, uFrame1, WARMUP_READ).out(uFlow, WARMUP_READ); + if (useInitFlow) + { + cv::calcOpticalFlowFarneback(uFrame0, uFrame1, uFlow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags); + flags |= OPTFLOW_USE_INITIAL_FLOW; + } + + OCL_TEST_CYCLE() + cv::calcOpticalFlowFarneback(uFrame0, uFrame1, uFlow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags); + + + SANITY_CHECK(uFlow, eps); +} + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL \ No newline at end of file diff --git a/modules/video/src/optflowgf.cpp b/modules/video/src/optflowgf.cpp index b237e5432..73aedeccc 100644 --- a/modules/video/src/optflowgf.cpp +++ b/modules/video/src/optflowgf.cpp @@ -895,10 +895,14 @@ private: #endif size_t globalsize[2] = { DIVUP(src.cols, localsize[0] - 2*polyN) * localsize[0], src.rows}; +#if 0 const cv::ocl::Device &device = cv::ocl::Device::getDefault(); bool useDouble = (0 != device.doubleFPConfig()); cv::String build_options = cv::format("-D polyN=%d -D USE_DOUBLE=%d", polyN, useDouble ? 1 : 0); +#else + cv::String build_options = cv::format("-D polyN=%d", polyN); +#endif ocl::Kernel kernel; if (!kernel.create("polynomialExpansion", cv::ocl::video::optical_flow_farneback_oclsrc, build_options)) return false; @@ -915,9 +919,11 @@ private: idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(m_xg)); idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(m_xxg)); idxArg = kernel.set(idxArg, (void *)NULL, smem_size); +#if 0 if (useDouble) idxArg = kernel.set(idxArg, (void *)m_igd, 4 * sizeof(double)); else +#endif idxArg = kernel.set(idxArg, (void *)m_ig, 4 * sizeof(float)); return kernel.run(2, globalsize, localsize, false); } From 0de799b3b03c1320b84d2c702a629867362b9fc3 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Fri, 17 Jan 2014 18:25:28 +0400 Subject: [PATCH 091/295] Removed some duplicate assertions. --- modules/core/src/stat.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 050716268..d74de29fc 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -2307,8 +2307,6 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat(); - CV_Assert( src1.size == src2.size && src1.type() == src2.type() ); - normType &= 7; CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR || ((normType == NORM_HAMMING || normType == NORM_HAMMING2) && src1.type() == CV_8U) ); @@ -2387,8 +2385,6 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat(); int depth = src1.depth(), cn = src1.channels(); - CV_Assert( src1.size == src2.size ); - normType &= 7; CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR || From 37789f015af3909e66f47c866ee505b754d71c36 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 18 Jan 2014 01:30:29 +0400 Subject: [PATCH 092/295] deleted excess semicolons, commas --- .../include/opencv2/bioinspired/retina.hpp | 4 +- modules/bioinspired/src/basicretinafilter.hpp | 65 +++++--- .../bioinspired/src/imagelogpolprojection.hpp | 15 +- modules/bioinspired/src/magnoretinafilter.hpp | 11 +- modules/bioinspired/src/parvoretinafilter.hpp | 19 ++- modules/bioinspired/src/retina.cpp | 50 +++--- modules/bioinspired/src/retina_ocl.cpp | 2 +- modules/bioinspired/src/retina_ocl.hpp | 154 +++++++++--------- modules/bioinspired/src/retinacolor.hpp | 27 +-- .../bioinspired/src/retinafasttonemapping.cpp | 66 ++++---- modules/bioinspired/src/retinafilter.hpp | 82 +++++----- modules/bioinspired/src/templatebuffer.hpp | 22 +-- modules/calib3d/src/levmarq.cpp | 4 +- modules/calib3d/src/ptsetreg.cpp | 4 +- .../test/test_cameracalibration_badarg.cpp | 10 +- modules/contrib/include/opencv2/contrib.hpp | 4 +- modules/core/include/opencv2/core/ocl.hpp | 4 +- modules/core/src/arithm.cpp | 8 +- modules/core/src/glob.cpp | 2 +- modules/core/src/ocl.cpp | 2 +- modules/core/test/test_io.cpp | 2 +- modules/core/test/test_mat.cpp | 2 +- modules/core/test/test_operations.cpp | 2 +- modules/core/test/test_umat.cpp | 2 +- modules/cuda/src/cuda/ccomponetns.cu | 6 +- modules/cuda/test/test_labeling.cpp | 2 +- .../src/cuda/NCVPixelOperations.hpp | 2 +- .../include/opencv2/flann/autotuned_index.h | 4 +- modules/flann/test/test_lshtable_badarg.cpp | 2 +- modules/highgui/src/cap_ios_video_camera.mm | 2 +- modules/highgui/src/grfmt_base.hpp | 10 +- modules/highgui/src/rgbe.cpp | 2 +- modules/highgui/test/test_positioning.cpp | 4 +- modules/imgproc/include/opencv2/imgproc.hpp | 2 +- modules/imgproc/src/color.cpp | 2 +- .../imgproc/src/min_enclosing_triangle.cpp | 4 +- modules/imgproc/test/test_filter.cpp | 4 +- modules/imgproc/test/test_lsd.cpp | 8 +- modules/legacy/src/blobtrackgen1.cpp | 6 +- modules/legacy/src/blobtrackgenyml.cpp | 6 +- modules/legacy/src/blobtrackingauto.cpp | 14 +- modules/legacy/src/blobtrackingcc.cpp | 32 ++-- modules/legacy/src/blobtrackingccwithcr.cpp | 22 +-- modules/legacy/src/blobtrackinglist.cpp | 26 +-- modules/legacy/src/blobtrackingmsfg.cpp | 22 +-- modules/legacy/src/blobtrackingmsfgs.cpp | 6 +- modules/legacy/src/blobtrackpostproclist.cpp | 12 +- modules/legacy/src/enteringblobdetection.cpp | 2 +- .../legacy/src/enteringblobdetectionreal.cpp | 2 +- modules/legacy/src/facetemplate.h | 2 +- modules/legacy/src/oneway.cpp | 4 +- modules/ml/include/opencv2/ml.hpp | 4 +- modules/objdetect/doc/erfilter.rst | 4 +- .../objdetect/include/opencv2/objdetect.hpp | 2 +- .../include/opencv2/objdetect/erfilter.hpp | 4 +- modules/objdetect/src/cascadedetect.hpp | 2 +- modules/objdetect/src/erfilter.cpp | 32 ++-- modules/ocl/test/test_fft.cpp | 4 +- modules/photo/src/hdr_common.cpp | 2 +- modules/photo/src/hdr_common.hpp | 2 +- modules/softcascade/src/cuda_invoker.hpp | 2 +- .../src/integral_channel_builder.cpp | 2 +- modules/softcascade/src/octave.cpp | 2 +- modules/softcascade/src/softcascade_init.cpp | 4 +- .../stitching/doc/exposure_compensation.rst | 4 +- .../stitching/detail/exposure_compensate.hpp | 4 +- modules/video/test/test_accum.cpp | 2 +- modules/video/test/test_ecc.cpp | 6 +- 68 files changed, 442 insertions(+), 413 deletions(-) diff --git a/modules/bioinspired/include/opencv2/bioinspired/retina.hpp b/modules/bioinspired/include/opencv2/bioinspired/retina.hpp index b4fda7038..c9655c4a9 100644 --- a/modules/bioinspired/include/opencv2/bioinspired/retina.hpp +++ b/modules/bioinspired/include/opencv2/bioinspired/retina.hpp @@ -122,7 +122,7 @@ public: horizontalCellsGain(0.01f), hcellsTemporalConstant(0.5f), hcellsSpatialConstant(7.f), - ganglionCellsSensitivity(0.75f){};// default setup + ganglionCellsSensitivity(0.75f) { } // default setup bool colorMode, normaliseOutput; float photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, hcellsTemporalConstant, hcellsSpatialConstant, ganglionCellsSensitivity; }; @@ -135,7 +135,7 @@ public: amacrinCellsTemporalCutFrequency(2.0f), V0CompressionParameter(0.95f), localAdaptintegration_tau(0.f), - localAdaptintegration_k(7.f){};// default setup + localAdaptintegration_k(7.f) { } // default setup bool normaliseOutput; float parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k; }; diff --git a/modules/bioinspired/src/basicretinafilter.hpp b/modules/bioinspired/src/basicretinafilter.hpp index 323bff940..4986352bf 100644 --- a/modules/bioinspired/src/basicretinafilter.hpp +++ b/modules/bioinspired/src/basicretinafilter.hpp @@ -137,17 +137,17 @@ namespace bioinspired /** * function which clears the output buffer of the object */ - inline void clearOutputBuffer(){_filterOutput=0;}; + inline void clearOutputBuffer() { _filterOutput = 0; } /** * function which clears the secondary buffer of the object */ - inline void clearSecondaryBuffer(){_localBuffer=0;}; + inline void clearSecondaryBuffer() { _localBuffer = 0; } /** * function which clears the output and the secondary buffer of the object */ - inline void clearAllBuffers(){clearOutputBuffer();clearSecondaryBuffer();}; + inline void clearAllBuffers() { clearOutputBuffer(); clearSecondaryBuffer(); } /** * resize basic retina filter object (resize all allocated buffers @@ -160,7 +160,7 @@ namespace bioinspired * forbiden method inherited from parent std::valarray * prefer not to use this method since the filter matrix become vectors */ - void resize(const unsigned int){std::cerr<<"error, not accessible method"< &inputFrame, const unsigned int filterIndex=0){_spatiotemporalLPfilter_Irregular(&inputFrame[0], filterIndex);}; + inline void runProgressiveFilter(std::valarray &inputFrame, const unsigned int filterIndex=0) { _spatiotemporalLPfilter_Irregular(&inputFrame[0], filterIndex); } /** * run low pass filtering with progressive parameters (models the retina log sampling of the photoreceptors and its low pass filtering effect consequence: more powerfull low pass filtering effect on the corners) @@ -232,7 +232,7 @@ namespace bioinspired inline void runProgressiveFilter(const std::valarray &inputFrame, std::valarray &outputFrame, const unsigned int filterIndex=0) - {_spatiotemporalLPfilter_Irregular(get_data(inputFrame), &outputFrame[0], filterIndex);}; + {_spatiotemporalLPfilter_Irregular(get_data(inputFrame), &outputFrame[0], filterIndex); } /** * first order spatio-temporal low pass filter setup function @@ -268,20 +268,31 @@ namespace bioinspired * @param maxInputValue: the maximum amplitude value measured after local adaptation processing (c.f. function runFilter_LocalAdapdation & runFilter_LocalAdapdation_autonomous) * @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI) */ - void setV0CompressionParameter(const float v0, const float maxInputValue, const float){ _v0=v0*maxInputValue; _localLuminanceFactor=v0; _localLuminanceAddon=maxInputValue*(1.0f-v0); _maxInputValue=maxInputValue;}; + void setV0CompressionParameter(const float v0, const float maxInputValue, const float) + { + _v0=v0*maxInputValue; + _localLuminanceFactor=v0; + _localLuminanceAddon=maxInputValue*(1.0f-v0); + _maxInputValue=maxInputValue; + } /** * update local luminance adaptation setup, initial maxInputValue is kept. This function should be applied for normal local adaptation (not for tone mapping operation) * @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect * @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI) */ - void setV0CompressionParameter(const float v0, const float meanLuminance){ this->setV0CompressionParameter(v0, _maxInputValue, meanLuminance);}; + void setV0CompressionParameter(const float v0, const float meanLuminance) { this->setV0CompressionParameter(v0, _maxInputValue, meanLuminance); } /** * local luminance adaptation setup, this function should be applied for normal local adaptation (not for tone mapping operation) * @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect */ - void setV0CompressionParameter(const float v0){ _v0=v0*_maxInputValue; _localLuminanceFactor=v0; _localLuminanceAddon=_maxInputValue*(1.0f-v0);}; + void setV0CompressionParameter(const float v0) + { + _v0=v0*_maxInputValue; + _localLuminanceFactor=v0; + _localLuminanceAddon=_maxInputValue*(1.0f-v0); + } /** * local luminance adaptation setup, this function should be applied for local adaptation applied to tone mapping operation @@ -289,66 +300,76 @@ namespace bioinspired * @param maxInputValue: the maximum amplitude value measured after local adaptation processing (c.f. function runFilter_LocalAdapdation & runFilter_LocalAdapdation_autonomous) * @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI) */ - void setV0CompressionParameterToneMapping(const float v0, const float maxInputValue, const float meanLuminance=128.0f){ _v0=v0*maxInputValue; _localLuminanceFactor=1.0f; _localLuminanceAddon=meanLuminance*v0; _maxInputValue=maxInputValue;}; + void setV0CompressionParameterToneMapping(const float v0, const float maxInputValue, const float meanLuminance=128.0f) + { + _v0=v0*maxInputValue; + _localLuminanceFactor=1.0f; + _localLuminanceAddon=meanLuminance*v0; + _maxInputValue=maxInputValue; + } /** * update compression parameters while keeping v0 parameter value * @param meanLuminance the input frame mean luminance */ - inline void updateCompressionParameter(const float meanLuminance){_localLuminanceFactor=1; _localLuminanceAddon=meanLuminance*_v0;}; + inline void updateCompressionParameter(const float meanLuminance) + { + _localLuminanceFactor=1; + _localLuminanceAddon=meanLuminance*_v0; + } /** * @return the v0 compression parameter used to compute the local adaptation */ - float getV0CompressionParameter(){ return _v0/_maxInputValue;}; + float getV0CompressionParameter() { return _v0/_maxInputValue; } /** * @return the output result of the object */ - inline const std::valarray &getOutput() const {return _filterOutput;}; + inline const std::valarray &getOutput() const { return _filterOutput; } /** * @return number of rows of the filter */ - inline unsigned int getNBrows(){return _filterOutput.getNBrows();}; + inline unsigned int getNBrows() { return _filterOutput.getNBrows(); } /** * @return number of columns of the filter */ - inline unsigned int getNBcolumns(){return _filterOutput.getNBcolumns();}; + inline unsigned int getNBcolumns() { return _filterOutput.getNBcolumns(); } /** * @return number of pixels of the filter */ - inline unsigned int getNBpixels(){return _filterOutput.getNBpixels();}; + inline unsigned int getNBpixels() { return _filterOutput.getNBpixels(); } /** * force filter output to be normalized between 0 and maxValue * @param maxValue: the maximum output value that is required */ - inline void normalizeGrayOutput_0_maxOutputValue(const float maxValue){_filterOutput.normalizeGrayOutput_0_maxOutputValue(maxValue);}; + inline void normalizeGrayOutput_0_maxOutputValue(const float maxValue) { _filterOutput.normalizeGrayOutput_0_maxOutputValue(maxValue); } /** * force filter output to be normalized around 0 and rescaled with a sigmoide effect (extrem values saturation) * @param maxValue: the maximum output value that is required */ - inline void normalizeGrayOutputCentredSigmoide(){_filterOutput.normalizeGrayOutputCentredSigmoide();}; + inline void normalizeGrayOutputCentredSigmoide() { _filterOutput.normalizeGrayOutputCentredSigmoide(); } /** * force filter output to be normalized : data centering and std normalisation * @param maxValue: the maximum output value that is required */ - inline void centerReductImageLuminance(){_filterOutput.centerReductImageLuminance();}; + inline void centerReductImageLuminance() { _filterOutput.centerReductImageLuminance(); } /** * @return the maximum input buffer value */ - inline float getMaxInputValue(){return this->_maxInputValue;}; + inline float getMaxInputValue() { return _maxInputValue; } /** * @return the maximum input buffer value */ - inline void setMaxInputValue(const float newMaxInputValue){this->_maxInputValue=newMaxInputValue;}; + inline void setMaxInputValue(const float newMaxInputValue) { this->_maxInputValue=newMaxInputValue; } protected: @@ -577,7 +598,7 @@ namespace bioinspired float localLuminanceFactor, localLuminanceAddon, maxInputValue; public: Parallel_localAdaptation(const float *localLum, const float *inputImg, float *bufferToProcess, const float localLuminanceFact, const float localLuminanceAdd, const float maxInputVal) - :localLuminance(localLum), inputFrame(inputImg),outputFrame(bufferToProcess), localLuminanceFactor(localLuminanceFact), localLuminanceAddon(localLuminanceAdd), maxInputValue(maxInputVal) {}; + :localLuminance(localLum), inputFrame(inputImg),outputFrame(bufferToProcess), localLuminanceFactor(localLuminanceFact), localLuminanceAddon(localLuminanceAdd), maxInputValue(maxInputVal) {} virtual void operator()( const Range& r ) const { const float *localLuminancePTR=localLuminance+r.start; diff --git a/modules/bioinspired/src/imagelogpolprojection.hpp b/modules/bioinspired/src/imagelogpolprojection.hpp index 41ecd5eaf..e63990c83 100644 --- a/modules/bioinspired/src/imagelogpolprojection.hpp +++ b/modules/bioinspired/src/imagelogpolprojection.hpp @@ -158,38 +158,39 @@ public: /** * @return the numbers of rows (height) of the images OUTPUTS of the object */ - inline unsigned int getOutputNBrows(){return _outputNBrows;}; + inline unsigned int getOutputNBrows() { return _outputNBrows; } /** * @return the numbers of columns (width) of the images OUTPUTS of the object */ - inline unsigned int getOutputNBcolumns(){return _outputNBcolumns;}; + inline unsigned int getOutputNBcolumns() { return _outputNBcolumns; } /** * main funtion of the class: run projection function * @param size: one of the input frame initial dimensions to be processed * @return the output frame dimension */ - inline static unsigned int predictOutputSize(const unsigned int size, const double reductionFactor){return (unsigned int)((double)size/reductionFactor);}; + inline static unsigned int predictOutputSize(const unsigned int size, const double reductionFactor){return (unsigned int)((double)size/reductionFactor); } /** * @return the output of the filter which applies an irregular Low Pass spatial filter to the imag input (see function */ - inline const std::valarray &getIrregularLPfilteredInputFrame() const {return _irregularLPfilteredFrame;}; + inline const std::valarray &getIrregularLPfilteredInputFrame() const { return _irregularLPfilteredFrame; } /** * function which allows to retrieve the output frame which was updated after the "runProjection(...) function BasicRetinaFilter::runProgressiveFilter(...) * @return the projection result */ - inline const std::valarray &getSampledFrame() const {return _sampledFrame;}; + inline const std::valarray &getSampledFrame() const { return _sampledFrame; } /** * function which allows gives the tranformation table, its size is (getNBrows()*getNBcolumns()*2) * @return the transformation matrix [outputPixIndex_i, inputPixIndex_i, outputPixIndex_i+1, inputPixIndex_i+1....] */ - inline const std::valarray &getSamplingMap() const {return _transformTable;}; + inline const std::valarray &getSamplingMap() const { return _transformTable; } - inline double getOriginalRadiusLength(const double projectedRadiusLength){return _azero/(_alim-projectedRadiusLength*2.0/_minDimension);}; + inline double getOriginalRadiusLength(const double projectedRadiusLength) + { return _azero/(_alim-projectedRadiusLength*2.0/_minDimension); } // unsigned int getInputPixelIndex(const unsigned int ){ return _transformTable[index*2+1]}; diff --git a/modules/bioinspired/src/magnoretinafilter.hpp b/modules/bioinspired/src/magnoretinafilter.hpp index e06d14ddc..723537de8 100644 --- a/modules/bioinspired/src/magnoretinafilter.hpp +++ b/modules/bioinspired/src/magnoretinafilter.hpp @@ -151,27 +151,28 @@ namespace bioinspired /** * @return the Magnocellular ON channel filtering output */ - inline const std::valarray &getMagnoON() const {return _magnoXOutputON;}; + inline const std::valarray &getMagnoON() const { return _magnoXOutputON; } /** * @return the Magnocellular OFF channel filtering output */ - inline const std::valarray &getMagnoOFF() const {return _magnoXOutputOFF;}; + inline const std::valarray &getMagnoOFF() const { return _magnoXOutputOFF; } /** * @return the Magnocellular Y (sum of the ON and OFF magno channels) filtering output */ - inline const std::valarray &getMagnoYsaturated() const {return *_magnoYsaturated;}; + inline const std::valarray &getMagnoYsaturated() const { return *_magnoYsaturated; } /** * applies an image normalization which saturates the high output values by the use of an assymetric sigmoide */ - inline void normalizeGrayOutputNearZeroCentreredSigmoide(){_filterOutput.normalizeGrayOutputNearZeroCentreredSigmoide(&(*_magnoYOutput)[0], &(*_magnoYsaturated)[0]);}; + inline void normalizeGrayOutputNearZeroCentreredSigmoide() + { _filterOutput.normalizeGrayOutputNearZeroCentreredSigmoide(&(*_magnoYOutput)[0], &(*_magnoYsaturated)[0]); } /** * @return the horizontal cells' temporal constant */ - inline float getTemporalConstant(){return this->_filteringCoeficientsTable[2];}; + inline float getTemporalConstant() { return _filteringCoeficientsTable[2]; } private: diff --git a/modules/bioinspired/src/parvoretinafilter.hpp b/modules/bioinspired/src/parvoretinafilter.hpp index f5ffa1a06..0fc184792 100644 --- a/modules/bioinspired/src/parvoretinafilter.hpp +++ b/modules/bioinspired/src/parvoretinafilter.hpp @@ -150,7 +150,8 @@ public: * @param tau: time constant of the filter (unit is frame for video processing) * @param k: spatial constant of the filter (unit is pixels) */ - void setGanglionCellsLocalAdaptationLPfilterParameters(const float tau, const float k){BasicRetinaFilter::setLPfilterParameters(0, tau, k, 2);}; // change the parameters of the filter + void setGanglionCellsLocalAdaptationLPfilterParameters(const float tau, const float k) + { BasicRetinaFilter::setLPfilterParameters(0, tau, k, 2); } // change the parameters of the filter /** @@ -167,42 +168,42 @@ public: /** * @return the output of the photoreceptors filtering step (high cut frequency spatio-temporal low pass filter) */ - inline const std::valarray &getPhotoreceptorsLPfilteringOutput() const {return _photoreceptorsOutput;}; + inline const std::valarray &getPhotoreceptorsLPfilteringOutput() const { return _photoreceptorsOutput; } /** * @return the output of the photoreceptors filtering step (low cut frequency spatio-temporal low pass filter) */ - inline const std::valarray &getHorizontalCellsOutput() const { return _horizontalCellsOutput;}; + inline const std::valarray &getHorizontalCellsOutput() const { return _horizontalCellsOutput; } /** * @return the output Parvocellular ON channel of the retina model */ - inline const std::valarray &getParvoON() const {return _parvocellularOutputON;}; + inline const std::valarray &getParvoON() const { return _parvocellularOutputON; } /** * @return the output Parvocellular OFF channel of the retina model */ - inline const std::valarray &getParvoOFF() const {return _parvocellularOutputOFF;}; + inline const std::valarray &getParvoOFF() const { return _parvocellularOutputOFF; } /** * @return the output of the Bipolar cells of the ON channel of the retina model same as function getParvoON() but without luminance local adaptation */ - inline const std::valarray &getBipolarCellsON() const {return _bipolarCellsOutputON;}; + inline const std::valarray &getBipolarCellsON() const { return _bipolarCellsOutputON; } /** * @return the output of the Bipolar cells of the OFF channel of the retina model same as function getParvoON() but without luminance local adaptation */ - inline const std::valarray &getBipolarCellsOFF() const {return _bipolarCellsOutputOFF;}; + inline const std::valarray &getBipolarCellsOFF() const { return _bipolarCellsOutputOFF; } /** * @return the photoreceptors's temporal constant */ - inline float getPhotoreceptorsTemporalConstant(){return this->_filteringCoeficientsTable[2];}; + inline float getPhotoreceptorsTemporalConstant() { return _filteringCoeficientsTable[2]; } /** * @return the horizontal cells' temporal constant */ - inline float getHcellsTemporalConstant(){return this->_filteringCoeficientsTable[5];}; + inline float getHcellsTemporalConstant(){return _filteringCoeficientsTable[5]; } private: // template buffers diff --git a/modules/bioinspired/src/retina.cpp b/modules/bioinspired/src/retina.cpp index 303a7f32b..e43224028 100644 --- a/modules/bioinspired/src/retina.cpp +++ b/modules/bioinspired/src/retina.cpp @@ -101,14 +101,14 @@ public: virtual ~RetinaImpl(); /** - * retreive retina input buffer size - */ - Size getInputSize(); + * retreive retina input buffer size + */ + Size getInputSize(); /** - * retreive retina output buffer size - */ - Size getOutputSize(); + * retreive retina output buffer size + */ + Size getOutputSize(); /** * try to open an XML retina parameters file to adjust current retina instance setup @@ -127,7 +127,7 @@ public: * @param fs : the open Filestorage which contains retina parameters * @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error */ - void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure=true); + void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure=true); /** * try to open an XML retina parameters file to adjust current retina instance setup @@ -248,17 +248,17 @@ public: */ void clearBuffers(); - /** - * Activate/desactivate the Magnocellular pathway processing (motion information extraction), by default, it is activated - * @param activate: true if Magnocellular output should be activated, false if not - */ - void activateMovingContoursProcessing(const bool activate); + /** + * Activate/desactivate the Magnocellular pathway processing (motion information extraction), by default, it is activated + * @param activate: true if Magnocellular output should be activated, false if not + */ + void activateMovingContoursProcessing(const bool activate); - /** - * Activate/desactivate the Parvocellular pathway processing (contours information extraction), by default, it is activated - * @param activate: true if Parvocellular (contours information extraction) output should be activated, false if not - */ - void activateContoursProcessing(const bool activate); + /** + * Activate/desactivate the Parvocellular pathway processing (contours information extraction), by default, it is activated + * @param activate: true if Parvocellular (contours information extraction) output should be activated, false if not + */ + void activateContoursProcessing(const bool activate); private: // Parameteres setup members @@ -399,7 +399,8 @@ void RetinaImpl::setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailur setupIPLMagnoChannel(_retinaParameters.IplMagno.normaliseOutput, _retinaParameters.IplMagno.parasolCells_beta, _retinaParameters.IplMagno.parasolCells_tau, _retinaParameters.IplMagno.parasolCells_k, _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency,_retinaParameters.IplMagno.V0CompressionParameter, _retinaParameters.IplMagno.localAdaptintegration_tau, _retinaParameters.IplMagno.localAdaptintegration_k); - }catch(Exception &e) + } + catch(Exception &e) { printf("RetinaImpl::setup: resetting retina with default parameters\n"); if (applyDefaultSetupOnFailure) @@ -657,7 +658,8 @@ void RetinaImpl::_convertValarrayBuffer2cvMat(const std::valarray &grayMa outMat.at(pixel)=(unsigned char)*(valarrayPTR++); } } - }else + } + else { const unsigned int nbPixels=nbColumns*nbRows; const unsigned int doubleNBpixels=nbColumns*nbRows*2; @@ -727,17 +729,17 @@ bool RetinaImpl::_convertCvMat2ValarrayBuffer(InputArray inputMat, std::valarray cv::Mat dst(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]); inputMatToConvert.convertTo(dst, dsttype); } - else - CV_Error(Error::StsUnsupportedFormat, "input image must be single channel (gray levels), bgr format (color) or bgra (color with transparency which won't be considered"); + else + CV_Error(Error::StsUnsupportedFormat, "input image must be single channel (gray levels), bgr format (color) or bgra (color with transparency which won't be considered"); return imageNumberOfChannels>1; // return bool : false for gray level image processing, true for color mode } -void RetinaImpl::clearBuffers() {_retinaFilter->clearAllBuffers();} +void RetinaImpl::clearBuffers() { _retinaFilter->clearAllBuffers(); } -void RetinaImpl::activateMovingContoursProcessing(const bool activate){_retinaFilter->activateMovingContoursProcessing(activate);} +void RetinaImpl::activateMovingContoursProcessing(const bool activate) { _retinaFilter->activateMovingContoursProcessing(activate); } -void RetinaImpl::activateContoursProcessing(const bool activate){_retinaFilter->activateContoursProcessing(activate);} +void RetinaImpl::activateContoursProcessing(const bool activate) { _retinaFilter->activateContoursProcessing(activate); } }// end of namespace bioinspired }// end of namespace cv diff --git a/modules/bioinspired/src/retina_ocl.cpp b/modules/bioinspired/src/retina_ocl.cpp index 5d2b4bd15..51f43f38b 100644 --- a/modules/bioinspired/src/retina_ocl.cpp +++ b/modules/bioinspired/src/retina_ocl.cpp @@ -122,7 +122,7 @@ RetinaOCLImpl::RetinaOCLImpl(const cv::Size inputSz, const bool colorMode, int c { _retinaFilter = 0; _init(inputSz, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); -}; +} RetinaOCLImpl::~RetinaOCLImpl() { diff --git a/modules/bioinspired/src/retina_ocl.hpp b/modules/bioinspired/src/retina_ocl.hpp index 90df0601c..11da48b93 100644 --- a/modules/bioinspired/src/retina_ocl.hpp +++ b/modules/bioinspired/src/retina_ocl.hpp @@ -70,16 +70,16 @@ public: inline void clearOutputBuffer() { _filterOutput = 0; - }; + } inline void clearSecondaryBuffer() { _localBuffer = 0; - }; + } inline void clearAllBuffers() { clearOutputBuffer(); clearSecondaryBuffer(); - }; + } void resize(const unsigned int NBrows, const unsigned int NBcolumns); const cv::ocl::oclMat &runFilter_LPfilter(const cv::ocl::oclMat &inputFrame, const unsigned int filterIndex = 0); void runFilter_LPfilter(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &outputFrame, const unsigned int filterIndex = 0); @@ -95,69 +95,69 @@ public: _localLuminanceFactor = v0; _localLuminanceAddon = maxInputValue * (1.0f - v0); _maxInputValue = maxInputValue; - }; + } inline void setV0CompressionParameter(const float v0, const float meanLuminance) { this->setV0CompressionParameter(v0, _maxInputValue, meanLuminance); - }; + } inline void setV0CompressionParameter(const float v0) { _v0 = v0 * _maxInputValue; _localLuminanceFactor = v0; _localLuminanceAddon = _maxInputValue * (1.0f - v0); - }; + } inline void setV0CompressionParameterToneMapping(const float v0, const float maxInputValue, const float meanLuminance = 128.0f) { _v0 = v0 * maxInputValue; _localLuminanceFactor = 1.0f; _localLuminanceAddon = meanLuminance * _v0; _maxInputValue = maxInputValue; - }; + } inline void updateCompressionParameter(const float meanLuminance) { _localLuminanceFactor = 1; _localLuminanceAddon = meanLuminance * _v0; - }; + } inline float getV0CompressionParameter() { return _v0 / _maxInputValue; - }; + } inline const cv::ocl::oclMat &getOutput() const { return _filterOutput; - }; + } inline unsigned int getNBrows() { return _filterOutput.rows; - }; + } inline unsigned int getNBcolumns() { return _filterOutput.cols; - }; + } inline unsigned int getNBpixels() { return _filterOutput.size().area(); - }; + } inline void normalizeGrayOutput_0_maxOutputValue(const float maxValue) { ocl::normalizeGrayOutput_0_maxOutputValue(_filterOutput, maxValue); - }; + } inline void normalizeGrayOutputCentredSigmoide() { ocl::normalizeGrayOutputCentredSigmoide(0.0, 2.0, _filterOutput, _filterOutput); - }; + } inline void centerReductImageLuminance() { ocl::centerReductImageLuminance(_filterOutput); - }; + } inline float getMaxInputValue() { return this->_maxInputValue; - }; + } inline void setMaxInputValue(const float newMaxInputValue) { this->_maxInputValue = newMaxInputValue; - }; + } protected: @@ -209,23 +209,23 @@ public: inline const cv::ocl::oclMat &getMagnoON() const { return _magnoXOutputON; - }; + } inline const cv::ocl::oclMat &getMagnoOFF() const { return _magnoXOutputOFF; - }; + } inline const cv::ocl::oclMat &getMagnoYsaturated() const { return _magnoYsaturated; - }; + } inline void normalizeGrayOutputNearZeroCentreredSigmoide() { ocl::normalizeGrayOutputNearZeroCentreredSigmoide(_magnoYOutput, _magnoYsaturated); - }; + } inline float getTemporalConstant() { return this->_filteringCoeficientsTable[2]; - }; + } private: cv::ocl::oclMat _previousInput_ON; cv::ocl::oclMat _previousInput_OFF; @@ -254,48 +254,48 @@ public: inline void setGanglionCellsLocalAdaptationLPfilterParameters(const float tau, const float k) { BasicRetinaFilter::setLPfilterParameters(0, tau, k, 2); - }; + } const cv::ocl::oclMat &runFilter(const cv::ocl::oclMat &inputFrame, const bool useParvoOutput = true); inline const cv::ocl::oclMat &getPhotoreceptorsLPfilteringOutput() const { return _photoreceptorsOutput; - }; + } inline const cv::ocl::oclMat &getHorizontalCellsOutput() const { return _horizontalCellsOutput; - }; + } inline const cv::ocl::oclMat &getParvoON() const { return _parvocellularOutputON; - }; + } inline const cv::ocl::oclMat &getParvoOFF() const { return _parvocellularOutputOFF; - }; + } inline const cv::ocl::oclMat &getBipolarCellsON() const { return _bipolarCellsOutputON; - }; + } inline const cv::ocl::oclMat &getBipolarCellsOFF() const { return _bipolarCellsOutputOFF; - }; + } inline float getPhotoreceptorsTemporalConstant() { return this->_filteringCoeficientsTable[2]; - }; + } inline float getHcellsTemporalConstant() { return this->_filteringCoeficientsTable[5]; - }; + } private: cv::ocl::oclMat _photoreceptorsOutput; cv::ocl::oclMat _horizontalCellsOutput; @@ -319,7 +319,7 @@ public: inline void runColorMultiplexing(const cv::ocl::oclMat &inputRGBFrame) { runColorMultiplexing(inputRGBFrame, _multiplexedFrame); - }; + } void runColorMultiplexing(const cv::ocl::oclMat &demultiplexedInputFrame, cv::ocl::oclMat &multiplexedFrame); void runColorDemultiplexing(const cv::ocl::oclMat &multiplexedColorFrame, const bool adaptiveFiltering = false, const float maxInputValue = 255.0); @@ -327,39 +327,39 @@ public: { _saturateColors = saturateColors; _colorSaturationValue = colorSaturationValue; - }; + } void setChrominanceLPfilterParameters(const float beta, const float tau, const float k) { setLPfilterParameters(beta, tau, k); - }; + } bool applyKrauskopfLMS2Acr1cr2Transform(cv::ocl::oclMat &result); bool applyLMS2LabTransform(cv::ocl::oclMat &result); inline const cv::ocl::oclMat &getMultiplexedFrame() const { return _multiplexedFrame; - }; + } inline const cv::ocl::oclMat &getDemultiplexedColorFrame() const { return _demultiplexedColorFrame; - }; + } inline const cv::ocl::oclMat &getLuminance() const { return _luminance; - }; + } inline const cv::ocl::oclMat &getChrominance() const { return _chrominance; - }; + } void clipRGBOutput_0_maxInputValue(cv::ocl::oclMat &inputOutputBuffer, const float maxOutputValue = 255.0); void normalizeRGBOutput_0_maxOutputValue(const float maxOutputValue = 255.0); inline void setDemultiplexedColorFrame(const cv::ocl::oclMat &demultiplexedImage) { _demultiplexedColorFrame = demultiplexedImage; - }; + } protected: inline unsigned int bayerSampleOffset(unsigned int index) { @@ -410,13 +410,13 @@ public: { _photoreceptorsPrefilter.setV0CompressionParameter(1 - V0CompressionParameter); _setInitPeriodCount(); - }; + } inline void setParvoGanglionCellsLocalAdaptationSensitivity(const float V0CompressionParameter) { _ParvoRetinaFilter.setV0CompressionParameter(V0CompressionParameter); _setInitPeriodCount(); - }; + } inline void setGanglionCellsLocalAdaptationLPfilterParameters(const float spatialResponse, const float temporalResponse) { @@ -428,137 +428,137 @@ public: { _MagnoRetinaFilter.setV0CompressionParameter(V0CompressionParameter); _setInitPeriodCount(); - }; + } void setOPLandParvoParameters(const float beta1, const float tau1, const float k1, const float beta2, const float tau2, const float k2, const float V0CompressionParameter) { _ParvoRetinaFilter.setOPLandParvoFiltersParameters(beta1, tau1, k1, beta2, tau2, k2); _ParvoRetinaFilter.setV0CompressionParameter(V0CompressionParameter); _setInitPeriodCount(); - }; + } void setMagnoCoefficientsTable(const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float V0CompressionParameter, const float localAdaptintegration_tau, const float localAdaptintegration_k) { _MagnoRetinaFilter.setCoefficientsTable(parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, localAdaptintegration_tau, localAdaptintegration_k); _MagnoRetinaFilter.setV0CompressionParameter(V0CompressionParameter); _setInitPeriodCount(); - }; + } inline void activateNormalizeParvoOutput_0_maxOutputValue(const bool normalizeParvoOutput_0_maxOutputValue) { _normalizeParvoOutput_0_maxOutputValue = normalizeParvoOutput_0_maxOutputValue; - }; + } inline void activateNormalizeMagnoOutput_0_maxOutputValue(const bool normalizeMagnoOutput_0_maxOutputValue) { _normalizeMagnoOutput_0_maxOutputValue = normalizeMagnoOutput_0_maxOutputValue; - }; + } inline void setMaxOutputValue(const float maxOutputValue) { _maxOutputValue = maxOutputValue; - }; + } void setColorMode(const bool desiredColorMode) { _useColorMode = desiredColorMode; - }; + } inline void setColorSaturation(const bool saturateColors = true, const float colorSaturationValue = 4.0) { _colorEngine.setColorSaturation(saturateColors, colorSaturationValue); - }; + } inline const cv::ocl::oclMat &getLocalAdaptation() const { return _photoreceptorsPrefilter.getOutput(); - }; + } inline const cv::ocl::oclMat &getPhotoreceptors() const { return _ParvoRetinaFilter.getPhotoreceptorsLPfilteringOutput(); - }; + } inline const cv::ocl::oclMat &getHorizontalCells() const { return _ParvoRetinaFilter.getHorizontalCellsOutput(); - }; + } inline bool areContoursProcessed() { return _useParvoOutput; - }; + } bool getParvoFoveaResponse(cv::ocl::oclMat &parvoFovealResponse); inline void activateContoursProcessing(const bool useParvoOutput) { _useParvoOutput = useParvoOutput; - }; + } const cv::ocl::oclMat &getContours(); inline const cv::ocl::oclMat &getContoursON() const { return _ParvoRetinaFilter.getParvoON(); - }; + } inline const cv::ocl::oclMat &getContoursOFF() const { return _ParvoRetinaFilter.getParvoOFF(); - }; + } inline bool areMovingContoursProcessed() { return _useMagnoOutput; - }; + } inline void activateMovingContoursProcessing(const bool useMagnoOutput) { _useMagnoOutput = useMagnoOutput; - }; + } inline const cv::ocl::oclMat &getMovingContours() const { return _MagnoRetinaFilter.getOutput(); - }; + } inline const cv::ocl::oclMat &getMovingContoursSaturated() const { return _MagnoRetinaFilter.getMagnoYsaturated(); - }; + } inline const cv::ocl::oclMat &getMovingContoursON() const { return _MagnoRetinaFilter.getMagnoON(); - }; + } inline const cv::ocl::oclMat &getMovingContoursOFF() const { return _MagnoRetinaFilter.getMagnoOFF(); - }; + } inline const cv::ocl::oclMat &getRetinaParvoMagnoMappedOutput() const { return _retinaParvoMagnoMappedFrame; - }; + } inline const cv::ocl::oclMat &getParvoContoursChannel() const { return _colorEngine.getLuminance(); - }; + } inline const cv::ocl::oclMat &getParvoChrominance() const { return _colorEngine.getChrominance(); - }; + } inline const cv::ocl::oclMat &getColorOutput() const { return _colorEngine.getDemultiplexedColorFrame(); - }; + } inline bool isColorMode() { return _useColorMode; - }; + } bool getColorMode() { return _useColorMode; - }; + } inline bool isInitTransitionDone() { @@ -567,41 +567,41 @@ public: return false; } return true; - }; + } inline float getRetinaSamplingBackProjection(const float projectedRadiusLength) { return projectedRadiusLength; - }; + } inline unsigned int getInputNBrows() { return _photoreceptorsPrefilter.getNBrows(); - }; + } inline unsigned int getInputNBcolumns() { return _photoreceptorsPrefilter.getNBcolumns(); - }; + } inline unsigned int getInputNBpixels() { return _photoreceptorsPrefilter.getNBpixels(); - }; + } inline unsigned int getOutputNBrows() { return _photoreceptorsPrefilter.getNBrows(); - }; + } inline unsigned int getOutputNBcolumns() { return _photoreceptorsPrefilter.getNBcolumns(); - }; + } inline unsigned int getOutputNBpixels() { return _photoreceptorsPrefilter.getNBpixels(); - }; + } private: bool _useParvoOutput; bool _useMagnoOutput; diff --git a/modules/bioinspired/src/retinacolor.hpp b/modules/bioinspired/src/retinacolor.hpp index 3fb6be8f9..ff7990638 100644 --- a/modules/bioinspired/src/retinacolor.hpp +++ b/modules/bioinspired/src/retinacolor.hpp @@ -125,7 +125,7 @@ namespace bioinspired * @param inputRGBFrame: the input RGB frame to be processed * @return, nothing but the multiplexed frame is available by the use of the getMultiplexedFrame() function */ - inline void runColorMultiplexing(const std::valarray &inputRGBFrame){runColorMultiplexing(inputRGBFrame, *_multiplexedFrame);}; + inline void runColorMultiplexing(const std::valarray &inputRGBFrame) { runColorMultiplexing(inputRGBFrame, *_multiplexedFrame); } /** * color multiplexing function: a demultipleed RGB frame of size M*N*3 is transformed into a multiplexed M*N*1 pixels frame where each pixel is either Red, or Green or Blue if using RGB images @@ -149,7 +149,7 @@ namespace bioinspired * @param saturateColors: boolean that activates color saturation (if true) or desactivate (if false) * @param colorSaturationValue: the saturation factor * */ - void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0){_saturateColors=saturateColors; _colorSaturationValue=colorSaturationValue;}; + void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0) { _saturateColors=saturateColors; _colorSaturationValue=colorSaturationValue; } /** * set parameters of the low pass spatio-temporal filter used to retreive the low chrominance @@ -157,7 +157,7 @@ namespace bioinspired * @param tau: time constant of the filter (unit is frame for video processing), typically 0 when considering static processing, 1 or more if a temporal smoothing effect is required * @param k: spatial constant of the filter (unit is pixels), typical value is 2.5 */ - void setChrominanceLPfilterParameters(const float beta, const float tau, const float k){setLPfilterParameters(beta, tau, k);}; + void setChrominanceLPfilterParameters(const float beta, const float tau, const float k) { setLPfilterParameters(beta, tau, k); } /** * apply to the retina color output the Krauskopf transformation which leads to an opponent color system: output colorspace if Acr1cr2 if input of the retina was LMS color space @@ -176,22 +176,22 @@ namespace bioinspired /** * @return the multiplexed frame result (use this after function runColorMultiplexing) */ - inline const std::valarray &getMultiplexedFrame() const {return *_multiplexedFrame;}; + inline const std::valarray &getMultiplexedFrame() const { return *_multiplexedFrame; } /** * @return the demultiplexed frame result (use this after function runColorDemultiplexing) */ - inline const std::valarray &getDemultiplexedColorFrame() const {return _demultiplexedColorFrame;}; + inline const std::valarray &getDemultiplexedColorFrame() const { return _demultiplexedColorFrame; } /** * @return the luminance of the processed frame (use this after function runColorDemultiplexing) */ - inline const std::valarray &getLuminance() const {return *_luminance;}; + inline const std::valarray &getLuminance() const { return *_luminance; } /** * @return the chrominance of the processed frame (use this after function runColorDemultiplexing) */ - inline const std::valarray &getChrominance() const {return _chrominance;}; + inline const std::valarray &getChrominance() const { return _chrominance; } /** * standard 0 to 255 image clipping function appled to RGB images (of size M*N*3 pixels) @@ -209,13 +209,13 @@ namespace bioinspired /** * return the color sampling map: a Nrows*Mcolumns image in which each pixel value is the ofsset adress which gives the adress of the sampled pixel on an Nrows*Mcolumns*3 color image ordered by layers: layer1, layer2, layer3 */ - inline const std::valarray &getSamplingMap() const {return _colorSampling;}; + inline const std::valarray &getSamplingMap() const { return _colorSampling; } /** * function used (to bypass processing) to manually set the color output * @param demultiplexedImage: the color image (luminance+chrominance) which has to be written in the object buffer */ - inline void setDemultiplexedColorFrame(const std::valarray &demultiplexedImage){_demultiplexedColorFrame=demultiplexedImage;}; + inline void setDemultiplexedColorFrame(const std::valarray &demultiplexedImage) { _demultiplexedColorFrame=demultiplexedImage; } protected: @@ -287,9 +287,10 @@ namespace bioinspired unsigned int nbColumns; public: Parallel_adaptiveHorizontalCausalFilter_addInput(const float *inputImg, float *bufferToProcess, const float *imageGrad, const unsigned int nbCols) - :outputFrame(bufferToProcess), inputFrame(inputImg), imageGradient(imageGrad), nbColumns(nbCols) {}; + :outputFrame(bufferToProcess), inputFrame(inputImg), imageGradient(imageGrad), nbColumns(nbCols) { } - virtual void operator()( const Range& r ) const { + virtual void operator()( const Range& r ) const + { register float* outputPTR=outputFrame+r.start*nbColumns; register const float* inputPTR=inputFrame+r.start*nbColumns; register const float *imageGradientPTR= imageGradient+r.start*nbColumns; @@ -314,7 +315,7 @@ namespace bioinspired float filterParam_gain; public: Parallel_adaptiveVerticalAnticausalFilter_multGain(float *bufferToProcess, const float *imageGrad, const unsigned int nbRws, const unsigned int nbCols, const float gain) - :outputFrame(bufferToProcess), imageGradient(imageGrad), nbRows(nbRws), nbColumns(nbCols), filterParam_gain(gain){} + :outputFrame(bufferToProcess), imageGradient(imageGrad), nbRows(nbRws), nbColumns(nbCols), filterParam_gain(gain) { } virtual void operator()( const Range& r ) const { float* offset=outputFrame+nbColumns*nbRows-nbColumns; @@ -343,7 +344,7 @@ namespace bioinspired unsigned int nbColumns, doubleNbColumns, nbRows, nbPixels; public: Parallel_computeGradient(const unsigned int nbCols, const unsigned int nbRws, const float *lum, float *imageGrad) - :imageGradient(imageGrad), luminance(lum), nbColumns(nbCols), doubleNbColumns(2*nbCols), nbRows(nbRws), nbPixels(nbRws*nbCols){}; + :imageGradient(imageGrad), luminance(lum), nbColumns(nbCols), doubleNbColumns(2*nbCols), nbRows(nbRws), nbPixels(nbRws*nbCols) { } virtual void operator()( const Range& r ) const { for (int idLine=r.start;idLine!=r.end;++idLine) diff --git a/modules/bioinspired/src/retinafasttonemapping.cpp b/modules/bioinspired/src/retinafasttonemapping.cpp index 2713d7449..776e68c90 100644 --- a/modules/bioinspired/src/retinafasttonemapping.cpp +++ b/modules/bioinspired/src/retinafasttonemapping.cpp @@ -124,7 +124,7 @@ public: /** * basic destructor */ - virtual ~RetinaFastToneMappingImpl(){}; + virtual ~RetinaFastToneMappingImpl() { } /** * method that applies a luminance correction (initially High Dynamic Range (HDR) tone mapping) using only the 2 local adaptation stages of the retina parvocellular channel : photoreceptors level and ganlion cells level. Spatio temporal filtering is applied but limited to temporal smoothing and eventually high frequencies attenuation. This is a lighter method than the one available using the regular retina::run method. It is then faster but it does not include complete temporal filtering nor retina spectral whitening. Then, it can have a more limited effect on images with a very high dynamic range. This is an adptation of the original still image HDR tone mapping algorithm of David Alleyson, Sabine Susstruck and Laurence Meylan's work, please cite: @@ -142,7 +142,8 @@ public: { _runRGBToneMapping(_inputBuffer, _imageOutput, true); _convertValarrayBuffer2cvMat(_imageOutput, _multiuseFilter->getNBrows(), _multiuseFilter->getNBcolumns(), true, outputToneMappedImage); - }else + } + else { _runGrayToneMapping(_inputBuffer, _imageOutput); _convertValarrayBuffer2cvMat(_imageOutput, _multiuseFilter->getNBrows(), _multiuseFilter->getNBcolumns(), false, outputToneMappedImage); @@ -193,7 +194,8 @@ void _convertValarrayBuffer2cvMat(const std::valarray &grayMatrixToConver outMat.at(pixel)=(unsigned char)*(valarrayPTR++); } } - }else + } + else { const unsigned int nbPixels=nbColumns*nbRows; const unsigned int doubleNBpixels=nbColumns*nbRows*2; @@ -263,47 +265,47 @@ bool _convertCvMat2ValarrayBuffer(InputArray inputMat, std::valarray &out cv::Mat dst(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]); inputMatToConvert.convertTo(dst, dsttype); } - else - CV_Error(Error::StsUnsupportedFormat, "input image must be single channel (gray levels), bgr format (color) or bgra (color with transparency which won't be considered"); + else + CV_Error(Error::StsUnsupportedFormat, "input image must be single channel (gray levels), bgr format (color) or bgra (color with transparency which won't be considered"); return imageNumberOfChannels>1; // return bool : false for gray level image processing, true for color mode } - // run the initilized retina filter in order to perform gray image tone mapping, after this call all retina outputs are updated - void _runGrayToneMapping(const std::valarray &grayImageInput, std::valarray &grayImageOutput) - { - // apply tone mapping on the multiplexed image - // -> photoreceptors local adaptation (large area adaptation) - _multiuseFilter->runFilter_LPfilter(grayImageInput, grayImageOutput, 0); // compute low pass filtering modeling the horizontal cells filtering to acess local luminance - _multiuseFilter->setV0CompressionParameterToneMapping(1.f, grayImageOutput.max(), _meanLuminanceModulatorK*grayImageOutput.sum()/(float)_multiuseFilter->getNBpixels()); - _multiuseFilter->runFilter_LocalAdapdation(grayImageInput, grayImageOutput, _temp2); // adapt contrast to local luminance +// run the initilized retina filter in order to perform gray image tone mapping, after this call all retina outputs are updated +void _runGrayToneMapping(const std::valarray &grayImageInput, std::valarray &grayImageOutput) +{ + // apply tone mapping on the multiplexed image + // -> photoreceptors local adaptation (large area adaptation) + _multiuseFilter->runFilter_LPfilter(grayImageInput, grayImageOutput, 0); // compute low pass filtering modeling the horizontal cells filtering to acess local luminance + _multiuseFilter->setV0CompressionParameterToneMapping(1.f, grayImageOutput.max(), _meanLuminanceModulatorK*grayImageOutput.sum()/(float)_multiuseFilter->getNBpixels()); + _multiuseFilter->runFilter_LocalAdapdation(grayImageInput, grayImageOutput, _temp2); // adapt contrast to local luminance - // -> ganglion cells local adaptation (short area adaptation) - _multiuseFilter->runFilter_LPfilter(_temp2, grayImageOutput, 1); // compute low pass filtering (high cut frequency (remove spatio-temporal noise) - _multiuseFilter->setV0CompressionParameterToneMapping(1.f, _temp2.max(), _meanLuminanceModulatorK*grayImageOutput.sum()/(float)_multiuseFilter->getNBpixels()); - _multiuseFilter->runFilter_LocalAdapdation(_temp2, grayImageOutput, grayImageOutput); // adapt contrast to local luminance + // -> ganglion cells local adaptation (short area adaptation) + _multiuseFilter->runFilter_LPfilter(_temp2, grayImageOutput, 1); // compute low pass filtering (high cut frequency (remove spatio-temporal noise) + _multiuseFilter->setV0CompressionParameterToneMapping(1.f, _temp2.max(), _meanLuminanceModulatorK*grayImageOutput.sum()/(float)_multiuseFilter->getNBpixels()); + _multiuseFilter->runFilter_LocalAdapdation(_temp2, grayImageOutput, grayImageOutput); // adapt contrast to local luminance - } +} - // run the initilized retina filter in order to perform color tone mapping, after this call all retina outputs are updated - void _runRGBToneMapping(const std::valarray &RGBimageInput, std::valarray &RGBimageOutput, const bool useAdaptiveFiltering) - { - // multiplex the image with the color sampling method specified in the constructor - _colorEngine->runColorMultiplexing(RGBimageInput); +// run the initilized retina filter in order to perform color tone mapping, after this call all retina outputs are updated +void _runRGBToneMapping(const std::valarray &RGBimageInput, std::valarray &RGBimageOutput, const bool useAdaptiveFiltering) +{ + // multiplex the image with the color sampling method specified in the constructor + _colorEngine->runColorMultiplexing(RGBimageInput); - // apply tone mapping on the multiplexed image - _runGrayToneMapping(_colorEngine->getMultiplexedFrame(), RGBimageOutput); + // apply tone mapping on the multiplexed image + _runGrayToneMapping(_colorEngine->getMultiplexedFrame(), RGBimageOutput); - // demultiplex tone maped image - _colorEngine->runColorDemultiplexing(RGBimageOutput, useAdaptiveFiltering, _multiuseFilter->getMaxInputValue());//_ColorEngine->getMultiplexedFrame());//_ParvoRetinaFilter->getPhotoreceptorsLPfilteringOutput()); + // demultiplex tone maped image + _colorEngine->runColorDemultiplexing(RGBimageOutput, useAdaptiveFiltering, _multiuseFilter->getMaxInputValue());//_ColorEngine->getMultiplexedFrame());//_ParvoRetinaFilter->getPhotoreceptorsLPfilteringOutput()); - // rescaling result between 0 and 255 - _colorEngine->normalizeRGBOutput_0_maxOutputValue(255.0); + // rescaling result between 0 and 255 + _colorEngine->normalizeRGBOutput_0_maxOutputValue(255.0); - // return the result - RGBimageOutput=_colorEngine->getDemultiplexedColorFrame(); - } + // return the result + RGBimageOutput=_colorEngine->getDemultiplexedColorFrame(); +} }; diff --git a/modules/bioinspired/src/retinafilter.hpp b/modules/bioinspired/src/retinafilter.hpp index 3e204885f..5b254c8ac 100644 --- a/modules/bioinspired/src/retinafilter.hpp +++ b/modules/bioinspired/src/retinafilter.hpp @@ -222,26 +222,26 @@ public: * setup the local luminance adaptation capability * @param V0CompressionParameter: the compression strengh of the photoreceptors local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 160 */ - inline void setPhotoreceptorsLocalAdaptationSensitivity(const float V0CompressionParameter){_photoreceptorsPrefilter.setV0CompressionParameter(1-V0CompressionParameter);_setInitPeriodCount();}; + inline void setPhotoreceptorsLocalAdaptationSensitivity(const float V0CompressionParameter) { _photoreceptorsPrefilter.setV0CompressionParameter(1-V0CompressionParameter);_setInitPeriodCount(); } /** * setup the local luminance adaptation capability * @param V0CompressionParameter: the compression strengh of the parvocellular pathway (details) local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 160 */ - inline void setParvoGanglionCellsLocalAdaptationSensitivity(const float V0CompressionParameter){_ParvoRetinaFilter.setV0CompressionParameter(V0CompressionParameter);_setInitPeriodCount();}; + inline void setParvoGanglionCellsLocalAdaptationSensitivity(const float V0CompressionParameter) { _ParvoRetinaFilter.setV0CompressionParameter(V0CompressionParameter);_setInitPeriodCount(); } /** * setup the local luminance adaptation area of integration * @param spatialResponse: the spatial constant of the low pass filter applied on the bipolar cells output in order to compute local contrast mean values * @param temporalResponse: the spatial constant of the low pass filter applied on the bipolar cells output in order to compute local contrast mean values (generally set to zero: immediate response) */ - inline void setGanglionCellsLocalAdaptationLPfilterParameters(const float spatialResponse, const float temporalResponse){_ParvoRetinaFilter.setGanglionCellsLocalAdaptationLPfilterParameters(temporalResponse, spatialResponse);_setInitPeriodCount();}; + inline void setGanglionCellsLocalAdaptationLPfilterParameters(const float spatialResponse, const float temporalResponse) { _ParvoRetinaFilter.setGanglionCellsLocalAdaptationLPfilterParameters(temporalResponse, spatialResponse);_setInitPeriodCount(); } /** * setup the local luminance adaptation capability * @param V0CompressionParameter: the compression strengh of the magnocellular pathway (motion) local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 160 */ - inline void setMagnoGanglionCellsLocalAdaptationSensitivity(const float V0CompressionParameter){_MagnoRetinaFilter.setV0CompressionParameter(V0CompressionParameter);_setInitPeriodCount();}; + inline void setMagnoGanglionCellsLocalAdaptationSensitivity(const float V0CompressionParameter) { _MagnoRetinaFilter.setV0CompressionParameter(V0CompressionParameter);_setInitPeriodCount(); } /** * setup the OPL and IPL parvo channels @@ -253,7 +253,7 @@ public: * @param k2: the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model) * @param V0CompressionParameter: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 230 */ - void setOPLandParvoParameters(const float beta1, const float tau1, const float k1, const float beta2, const float tau2, const float k2, const float V0CompressionParameter){_ParvoRetinaFilter.setOPLandParvoFiltersParameters(beta1, tau1, k1, beta2, tau2, k2);_ParvoRetinaFilter.setV0CompressionParameter(V0CompressionParameter);_setInitPeriodCount();}; + void setOPLandParvoParameters(const float beta1, const float tau1, const float k1, const float beta2, const float tau2, const float k2, const float V0CompressionParameter) { _ParvoRetinaFilter.setOPLandParvoFiltersParameters(beta1, tau1, k1, beta2, tau2, k2);_ParvoRetinaFilter.setV0CompressionParameter(V0CompressionParameter);_setInitPeriodCount(); } /** * set parameters values for the Inner Plexiform Layer (IPL) magnocellular channel @@ -265,31 +265,31 @@ public: * @param localAdaptintegration_tau: specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation * @param localAdaptintegration_k: specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation */ - void setMagnoCoefficientsTable(const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float V0CompressionParameter, const float localAdaptintegration_tau, const float localAdaptintegration_k){_MagnoRetinaFilter.setCoefficientsTable(parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, localAdaptintegration_tau, localAdaptintegration_k);_MagnoRetinaFilter.setV0CompressionParameter(V0CompressionParameter);_setInitPeriodCount();}; + void setMagnoCoefficientsTable(const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float V0CompressionParameter, const float localAdaptintegration_tau, const float localAdaptintegration_k) { _MagnoRetinaFilter.setCoefficientsTable(parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, localAdaptintegration_tau, localAdaptintegration_k);_MagnoRetinaFilter.setV0CompressionParameter(V0CompressionParameter);_setInitPeriodCount(); } /** * set if the parvo output should be or not normalized between 0 and 255 (for display purpose generally) * @param normalizeParvoOutput_0_maxOutputValue: true if normalization should be done */ - inline void activateNormalizeParvoOutput_0_maxOutputValue(const bool normalizeParvoOutput_0_maxOutputValue){_normalizeParvoOutput_0_maxOutputValue=normalizeParvoOutput_0_maxOutputValue;}; + inline void activateNormalizeParvoOutput_0_maxOutputValue(const bool normalizeParvoOutput_0_maxOutputValue) { _normalizeParvoOutput_0_maxOutputValue=normalizeParvoOutput_0_maxOutputValue; } /** * set if the magno output should be or not normalized between 0 and 255 (for display purpose generally), take care, if nothing is moving, then, the noise will be enanced !!! * @param normalizeMagnoOutput_0_maxOutputValue: true if normalization should be done */ - inline void activateNormalizeMagnoOutput_0_maxOutputValue(const bool normalizeMagnoOutput_0_maxOutputValue){_normalizeMagnoOutput_0_maxOutputValue=normalizeMagnoOutput_0_maxOutputValue;}; + inline void activateNormalizeMagnoOutput_0_maxOutputValue(const bool normalizeMagnoOutput_0_maxOutputValue) { _normalizeMagnoOutput_0_maxOutputValue=normalizeMagnoOutput_0_maxOutputValue; } /** * setup the maximum amplitude value of the normalized outputs (generally 255 for 8bit per channel pictures) * @param maxOutputValue: maximum amplitude value of the normalized outputs (generally 255 for 8bit per channel pictures) */ - inline void setMaxOutputValue(const float maxOutputValue){_maxOutputValue=maxOutputValue;}; + inline void setMaxOutputValue(const float maxOutputValue) { _maxOutputValue=maxOutputValue; } /** * sets the color mode of the frame grabber * @param desiredColorMode: true if the user needs color information, false for graylevels */ - void setColorMode(const bool desiredColorMode){_useColorMode=desiredColorMode;}; + void setColorMode(const bool desiredColorMode) { _useColorMode=desiredColorMode; } /** * activate color saturation as the final step of the color demultiplexing process @@ -297,7 +297,7 @@ public: * @param saturateColors: boolean that activates color saturation (if true) or desactivate (if false) * @param colorSaturationValue: the saturation factor * */ - inline void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0){_colorEngine.setColorSaturation(saturateColors, colorSaturationValue);}; + inline void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0) { _colorEngine.setColorSaturation(saturateColors, colorSaturationValue); } ///////////////////////////////////////////////////////////////// // function that retrieve the main retina outputs, one by one, or all in a structure @@ -314,23 +314,23 @@ public: /** * @return photoreceptors output, locally adapted luminance only, no high frequency spatio-temporal noise reduction at the next retina processing stages, use getPhotoreceptors method to get complete photoreceptors output */ - inline const std::valarray &getLocalAdaptation() const {return _photoreceptorsPrefilter.getOutput();}; + inline const std::valarray &getLocalAdaptation() const {return _photoreceptorsPrefilter.getOutput(); } /** * @return photoreceptors output: locally adapted luminance and high frequency spatio-temporal noise reduction, high luminance is a little saturated at this stage, but this is corrected naturally at the next retina processing stages */ - inline const std::valarray &getPhotoreceptors() const {return _ParvoRetinaFilter.getPhotoreceptorsLPfilteringOutput();}; + inline const std::valarray &getPhotoreceptors() const {return _ParvoRetinaFilter.getPhotoreceptorsLPfilteringOutput(); } /** * @return the local luminance of the processed frame (it is the horizontal cells output) */ - inline const std::valarray &getHorizontalCells() const {return _ParvoRetinaFilter.getHorizontalCellsOutput();}; + inline const std::valarray &getHorizontalCells() const {return _ParvoRetinaFilter.getHorizontalCellsOutput(); } ///////// CONTOURS part, PARVOCELLULAR RETINA PATHWAY /** * @return true if Parvocellular output is activated, false if not */ - inline bool areContoursProcessed(){return _useParvoOutput;}; + inline bool areContoursProcessed() { return _useParvoOutput; } /** * method to retrieve the foveal parvocellular pathway response (no details energy in parafovea) @@ -342,7 +342,7 @@ public: /** * @param useParvoOutput: true if Parvocellular output should be activated, false if not */ - inline void activateContoursProcessing(const bool useParvoOutput){_useParvoOutput=useParvoOutput;}; + inline void activateContoursProcessing(const bool useParvoOutput) { _useParvoOutput=useParvoOutput; } /** * @return the parvocellular contours information (details), should be used at the fovea level @@ -352,18 +352,18 @@ public: /** * @return the parvocellular contours ON information (details), should be used at the fovea level */ - inline const std::valarray &getContoursON() const {return _ParvoRetinaFilter.getParvoON();};// Parvocellular ON output + inline const std::valarray &getContoursON() const {return _ParvoRetinaFilter.getParvoON(); } // Parvocellular ON output /** * @return the parvocellular contours OFF information (details), should be used at the fovea level */ - inline const std::valarray &getContoursOFF() const {return _ParvoRetinaFilter.getParvoOFF();};// Parvocellular OFF output + inline const std::valarray &getContoursOFF() const {return _ParvoRetinaFilter.getParvoOFF(); } // Parvocellular OFF output ///////// MOVING CONTOURS part, MAGNOCELLULAR RETINA PATHWAY /** * @return true if Magnocellular output is activated, false if not */ - inline bool areMovingContoursProcessed(){return _useMagnoOutput;}; + inline bool areMovingContoursProcessed() { return _useMagnoOutput; } /** * method to retrieve the parafoveal magnocellular pathway response (no motion energy in fovea) @@ -375,87 +375,87 @@ public: /** * @param useMagnoOutput: true if Magnoocellular output should be activated, false if not */ - inline void activateMovingContoursProcessing(const bool useMagnoOutput){_useMagnoOutput=useMagnoOutput;}; + inline void activateMovingContoursProcessing(const bool useMagnoOutput) { _useMagnoOutput=useMagnoOutput; } /** * @return the magnocellular moving contours information (motion), should be used at the parafovea level without post-processing */ - inline const std::valarray &getMovingContours() const {return _MagnoRetinaFilter.getOutput();};// Magnocellular output + inline const std::valarray &getMovingContours() const {return _MagnoRetinaFilter.getOutput(); } // Magnocellular output /** * @return the magnocellular moving contours information (motion), should be used at the parafovea level with assymetric sigmoide post-processing which saturates motion information */ - inline const std::valarray &getMovingContoursSaturated() const {return _MagnoRetinaFilter.getMagnoYsaturated();};// Saturated Magnocellular output + inline const std::valarray &getMovingContoursSaturated() const {return _MagnoRetinaFilter.getMagnoYsaturated(); } // Saturated Magnocellular output /** * @return the magnocellular moving contours ON information (motion), should be used at the parafovea level without post-processing */ - inline const std::valarray &getMovingContoursON() const {return _MagnoRetinaFilter.getMagnoON();};// Magnocellular ON output + inline const std::valarray &getMovingContoursON() const {return _MagnoRetinaFilter.getMagnoON(); } // Magnocellular ON output /** * @return the magnocellular moving contours OFF information (motion), should be used at the parafovea level without post-processing */ - inline const std::valarray &getMovingContoursOFF() const {return _MagnoRetinaFilter.getMagnoOFF();};// Magnocellular OFF output + inline const std::valarray &getMovingContoursOFF() const {return _MagnoRetinaFilter.getMagnoOFF(); } // Magnocellular OFF output /** * @return a gray level image with center Parvo and peripheral Magno X channels, WARNING, the result will be ok if you called previously fucntion runFilter(imageInput, processRetinaParvoMagnoMapping=true); * -> will be accessible even if color mode is activated (but the image is color sampled so quality is poor), but get the same thing but in color by the use of function getParvoColor() */ - inline const std::valarray &getRetinaParvoMagnoMappedOutput() const {return _retinaParvoMagnoMappedFrame;};// return image with center Parvo and peripheral Magno channels + inline const std::valarray &getRetinaParvoMagnoMappedOutput() const {return _retinaParvoMagnoMappedFrame; } // return image with center Parvo and peripheral Magno channels /** * color processing dedicated functions * @return the parvo channel (contours, details) of the processed frame, grayscale output */ - inline const std::valarray &getParvoContoursChannel() const {return _colorEngine.getLuminance();}; + inline const std::valarray &getParvoContoursChannel() const {return _colorEngine.getLuminance(); } /** * color processing dedicated functions * @return the chrominance of the processed frame (same colorspace as the input output, usually RGB) */ - inline const std::valarray &getParvoChrominance() const {return _colorEngine.getChrominance();}; // only retreive chrominance + inline const std::valarray &getParvoChrominance() const {return _colorEngine.getChrominance(); } // only retreive chrominance /** * color processing dedicated functions * @return the parvo + chrominance channels of the processed frame (same colorspace as the input output, usually RGB) */ - inline const std::valarray &getColorOutput() const {return _colorEngine.getDemultiplexedColorFrame();};// retrieve luminance+chrominance + inline const std::valarray &getColorOutput() const {return _colorEngine.getDemultiplexedColorFrame(); } // retrieve luminance+chrominance /** * apply to the retina color output the Krauskopf transformation which leads to an opponent color system: output colorspace if Acr1cr2 if input of the retina was LMS color space * @param result: the input buffer to fill with the transformed colorspace retina output * @return true if process ended successfully */ - inline bool applyKrauskopfLMS2Acr1cr2Transform(std::valarray &result){return _colorEngine.applyKrauskopfLMS2Acr1cr2Transform(result);}; + inline bool applyKrauskopfLMS2Acr1cr2Transform(std::valarray &result) { return _colorEngine.applyKrauskopfLMS2Acr1cr2Transform(result); } /** * apply to the retina color output the Krauskopf transformation which leads to an opponent color system: output colorspace if Acr1cr2 if input of the retina was LMS color space * @param result: the input buffer to fill with the transformed colorspace retina output * @return true if process ended successfully */ - inline bool applyLMS2LabTransform(std::valarray &result){return _colorEngine.applyLMS2LabTransform(result);}; + inline bool applyLMS2LabTransform(std::valarray &result) { return _colorEngine.applyLMS2LabTransform(result); } /** * color processing dedicated functions * @return the retina initialized mode, true if color mode (RGB), false if grayscale */ - inline bool isColorMode(){return _useColorMode;}; // return true if RGB mode, false if gray level mode + inline bool isColorMode() { return _useColorMode; } // return true if RGB mode, false if gray level mode /** * @return the irregular low pass filter ouput at the photoreceptors level */ - inline const std::valarray &getIrregularLPfilteredInputFrame() const {return _photoreceptorsLogSampling->getIrregularLPfilteredInputFrame();}; + inline const std::valarray &getIrregularLPfilteredInputFrame() const {return _photoreceptorsLogSampling->getIrregularLPfilteredInputFrame(); } /** * @return true if color mode is activated, false if gray levels processing */ - bool getColorMode(){return _useColorMode;}; + bool getColorMode() { return _useColorMode; } /** * * @return true if a sufficient number of processed frames has been done since the last parameters update in order to get the stable state (r�gime permanent) */ - inline bool isInitTransitionDone(){if (_ellapsedFramesSinceLastReset<_globalTemporalConstant)return false; return true;}; + inline bool isInitTransitionDone() { if (_ellapsedFramesSinceLastReset<_globalTemporalConstant)return false; return true; } /** * find a distance in the image input space when the distance is known in the retina log sampled space...read again if it is not clear enough....sorry, i should sleep @@ -467,7 +467,7 @@ public: if (_photoreceptorsLogSampling) return (float)_photoreceptorsLogSampling->getOriginalRadiusLength(projectedRadiusLength); return projectedRadiusLength; - }; + } /////////////////: // retina dimensions getters @@ -475,32 +475,32 @@ public: /** * @return number of rows of the filter */ - inline unsigned int getInputNBrows(){if (_photoreceptorsLogSampling) return _photoreceptorsLogSampling->getNBrows();else return _photoreceptorsPrefilter.getNBrows();}; + inline unsigned int getInputNBrows() { if (_photoreceptorsLogSampling) return _photoreceptorsLogSampling->getNBrows();else return _photoreceptorsPrefilter.getNBrows(); } /** * @return number of columns of the filter */ - inline unsigned int getInputNBcolumns(){if (_photoreceptorsLogSampling) return _photoreceptorsLogSampling->getNBcolumns();else return _photoreceptorsPrefilter.getNBcolumns();}; + inline unsigned int getInputNBcolumns() { if (_photoreceptorsLogSampling) return _photoreceptorsLogSampling->getNBcolumns();else return _photoreceptorsPrefilter.getNBcolumns(); } /** * @return number of pixels of the filter */ - inline unsigned int getInputNBpixels(){if (_photoreceptorsLogSampling) return _photoreceptorsLogSampling->getNBpixels();else return _photoreceptorsPrefilter.getNBpixels();}; + inline unsigned int getInputNBpixels() { if (_photoreceptorsLogSampling) return _photoreceptorsLogSampling->getNBpixels();else return _photoreceptorsPrefilter.getNBpixels(); } /** * @return the height of the frame output */ - inline unsigned int getOutputNBrows(){return _photoreceptorsPrefilter.getNBrows();}; + inline unsigned int getOutputNBrows() { return _photoreceptorsPrefilter.getNBrows(); } /** * @return the width of the frame output */ - inline unsigned int getOutputNBcolumns(){return _photoreceptorsPrefilter.getNBcolumns();}; + inline unsigned int getOutputNBcolumns() { return _photoreceptorsPrefilter.getNBcolumns(); } /** * @return the numbers of output pixels (width*height) of the images used by the object */ - inline unsigned int getOutputNBpixels(){return _photoreceptorsPrefilter.getNBpixels();}; + inline unsigned int getOutputNBpixels() { return _photoreceptorsPrefilter.getNBpixels(); } private: diff --git a/modules/bioinspired/src/templatebuffer.hpp b/modules/bioinspired/src/templatebuffer.hpp index 827eb709f..a95102d5c 100644 --- a/modules/bioinspired/src/templatebuffer.hpp +++ b/modules/bioinspired/src/templatebuffer.hpp @@ -92,7 +92,7 @@ private: public: Parallel_clipBufferValues(type* bufferToProcess, const type min, const type max) - : bufferToClip(bufferToProcess), minValue(min), maxValue(max){} + : bufferToClip(bufferToProcess), minValue(min), maxValue(max) { } virtual void operator()( const cv::Range &r ) const { register type *inputOutputBufferPTR=bufferToClip+r.start; @@ -194,32 +194,32 @@ public: /** * delete the buffer content (set zeros) */ - inline void setZero(){std::valarray::operator=(0);};//memset(Buffer(), 0, sizeof(type)*_NBpixels);}; + inline void setZero() { std::valarray::operator=(0); } //memset(Buffer(), 0, sizeof(type)*_NBpixels); } /** * @return the numbers of rows (height) of the images used by the object */ - inline unsigned int getNBrows(){return (unsigned int)_NBrows;}; + inline unsigned int getNBrows() { return (unsigned int)_NBrows; } /** * @return the numbers of columns (width) of the images used by the object */ - inline unsigned int getNBcolumns(){return (unsigned int)_NBcolumns;}; + inline unsigned int getNBcolumns() { return (unsigned int)_NBcolumns; } /** * @return the numbers of pixels (width*height) of the images used by the object */ - inline unsigned int getNBpixels(){return (unsigned int)_NBpixels;}; + inline unsigned int getNBpixels() { return (unsigned int)_NBpixels; } /** * @return the numbers of pixels (width*height) of the images used by the object */ - inline unsigned int getDoubleNBpixels(){return (unsigned int)_doubleNBpixels;}; + inline unsigned int getDoubleNBpixels() { return (unsigned int)_doubleNBpixels; } /** * @return the numbers of depths (3rd dimension: 1 for gray images, 3 for rgb images) of the images used by the object */ - inline unsigned int getDepthSize(){return (unsigned int)_NBdepths;}; + inline unsigned int getDepthSize() { return (unsigned int)_NBdepths; } /** * resize the buffer and recompute table index etc. @@ -275,7 +275,7 @@ public: * @param nbPixels: specifies the number of pixel on which the normalization should be performed, if 0, then all pixels specified in the constructor are processed * @param maxOutputValue: the maximum output value */ - void normalizeGrayOutput_0_maxOutputValue(const type maxOutputValue=(type)255.0){normalizeGrayOutput_0_maxOutputValue(this->Buffer(), this->size(), maxOutputValue);}; + void normalizeGrayOutput_0_maxOutputValue(const type maxOutputValue=(type)255.0) { normalizeGrayOutput_0_maxOutputValue(this->Buffer(), this->size(), maxOutputValue); } /** * sigmoide image normalization function (saturates min and max values) @@ -293,7 +293,7 @@ public: * @param sensitivity: strenght of the sigmoide * @param maxOutputValue: the maximum output value */ - inline void normalizeGrayOutputCentredSigmoide(const type meanValue=(type)0.0, const type sensitivity=(type)2.0, const type maxOutputValue=(type)255.0){ (void)maxOutputValue; normalizeGrayOutputCentredSigmoide(meanValue, sensitivity, 255.0, this->Buffer(), this->Buffer(), this->getNBpixels());}; + inline void normalizeGrayOutputCentredSigmoide(const type meanValue=(type)0.0, const type sensitivity=(type)2.0, const type maxOutputValue=(type)255.0) { (void)maxOutputValue; normalizeGrayOutputCentredSigmoide(meanValue, sensitivity, 255.0, this->Buffer(), this->Buffer(), this->getNBpixels()); } /** * sigmoide image normalization function (saturates min and max values), in this function, the sigmoide is centered on low values (high saturation of the medium and high values @@ -325,7 +325,7 @@ public: standardDeviation+=diff*diff; } return std::sqrt(standardDeviation/this->size()); - }; + } /** * Clip buffer histogram @@ -409,7 +409,7 @@ public: /** * @return the mean value of the vector */ - inline double getMean(){return this->sum()/this->size();}; + inline double getMean() { return this->sum()/this->size(); } protected: size_t _NBrows; diff --git a/modules/calib3d/src/levmarq.cpp b/modules/calib3d/src/levmarq.cpp index 55704132c..d3eb7b556 100644 --- a/modules/calib3d/src/levmarq.cpp +++ b/modules/calib3d/src/levmarq.cpp @@ -80,7 +80,7 @@ namespace cv class LMSolverImpl : public LMSolver { public: - LMSolverImpl() : maxIters(100) { init(); }; + LMSolverImpl() : maxIters(100) { init(); } LMSolverImpl(const Ptr& _cb, int _maxIters) : cb(_cb), maxIters(_maxIters) { init(); } void init() @@ -215,7 +215,7 @@ CV_INIT_ALGORITHM(LMSolverImpl, "LMSolver", obj.info()->addParam(obj, "epsx", obj.epsx); obj.info()->addParam(obj, "epsf", obj.epsf); obj.info()->addParam(obj, "maxIters", obj.maxIters); - obj.info()->addParam(obj, "printInterval", obj.printInterval)); + obj.info()->addParam(obj, "printInterval", obj.printInterval)) Ptr createLMSolver(const Ptr& cb, int maxIters) { diff --git a/modules/calib3d/src/ptsetreg.cpp b/modules/calib3d/src/ptsetreg.cpp index aa361a911..1bf35ebc1 100644 --- a/modules/calib3d/src/ptsetreg.cpp +++ b/modules/calib3d/src/ptsetreg.cpp @@ -386,11 +386,11 @@ public: CV_INIT_ALGORITHM(RANSACPointSetRegistrator, "PointSetRegistrator.RANSAC", obj.info()->addParam(obj, "threshold", obj.threshold); obj.info()->addParam(obj, "confidence", obj.confidence); - obj.info()->addParam(obj, "maxIters", obj.maxIters)); + obj.info()->addParam(obj, "maxIters", obj.maxIters)) CV_INIT_ALGORITHM(LMeDSPointSetRegistrator, "PointSetRegistrator.LMeDS", obj.info()->addParam(obj, "confidence", obj.confidence); - obj.info()->addParam(obj, "maxIters", obj.maxIters)); + obj.info()->addParam(obj, "maxIters", obj.maxIters)) Ptr createRANSACPointSetRegistrator(const Ptr& _cb, int _modelPoints, double _threshold, diff --git a/modules/calib3d/test/test_cameracalibration_badarg.cpp b/modules/calib3d/test/test_cameracalibration_badarg.cpp index 3edab8bec..f8443d1ec 100644 --- a/modules/calib3d/test/test_cameracalibration_badarg.cpp +++ b/modules/calib3d/test/test_cameracalibration_badarg.cpp @@ -55,7 +55,7 @@ public: ~CV_CameraCalibrationBadArgTest() {} protected: void run(int); - void run_func(void) {}; + void run_func(void) {} const static int M = 1; @@ -334,7 +334,7 @@ public: CV_Rodrigues2BadArgTest() {} ~CV_Rodrigues2BadArgTest() {} protected: - void run_func(void) {}; + void run_func(void) {} struct C_Caller { @@ -459,10 +459,10 @@ public: Size imsSize(800, 600); camMat << 300.f, 0.f, imsSize.width/2.f, 0, 300.f, imsSize.height/2.f, 0.f, 0.f, 1.f; distCoeffs << 1.2f, 0.2f, 0.f, 0.f, 0.f; - }; - ~CV_ProjectPoints2BadArgTest() {} ; + } + ~CV_ProjectPoints2BadArgTest() {} protected: - void run_func(void) {}; + void run_func(void) {} Mat_ camMat; Mat_ distCoeffs; diff --git a/modules/contrib/include/opencv2/contrib.hpp b/modules/contrib/include/opencv2/contrib.hpp index 75c6f3db0..f5a432315 100644 --- a/modules/contrib/include/opencv2/contrib.hpp +++ b/modules/contrib/include/opencv2/contrib.hpp @@ -523,7 +523,7 @@ public: // Initializes a LDA with num_components (default 0) and specifies how // samples are aligned (default dataAsRow=true). LDA(int num_components = 0) : - _num_components(num_components) {}; + _num_components(num_components) { } // Initializes and performs a Discriminant Analysis with Fisher's // Optimization Criterion on given data in src and corresponding labels @@ -561,7 +561,7 @@ public: Mat reconstruct(InputArray src); // Returns the eigenvectors of this LDA. - Mat eigenvectors() const { return _eigenvectors; }; + Mat eigenvectors() const { return _eigenvectors; } // Returns the eigenvalues of this LDA. Mat eigenvalues() const { return _eigenvalues; } diff --git a/modules/core/include/opencv2/core/ocl.hpp b/modules/core/include/opencv2/core/ocl.hpp index e3805bcdc..fb9f0282b 100644 --- a/modules/core/include/opencv2/core/ocl.hpp +++ b/modules/core/include/opencv2/core/ocl.hpp @@ -221,7 +221,7 @@ public: void* ptr() const; struct Impl; - inline struct Impl* _getImpl() const { return p; }; + inline struct Impl* _getImpl() const { return p; } protected: Impl* p; }; @@ -242,7 +242,7 @@ public: static Platform& getDefault(); struct Impl; - inline struct Impl* _getImpl() const { return p; }; + inline struct Impl* _getImpl() const { return p; } protected: Impl* p; }; diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index f93d56fde..d176e3263 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -251,16 +251,16 @@ void vBinOp64(const T* src1, size_t step1, const T* src2, size_t step2, template <> \ struct name{ \ typedef register_type reg_type; \ - static reg_type load(const template_arg * p) { return load_body ((const reg_type *)p);}; \ - static void store(template_arg * p, reg_type v) { store_body ((reg_type *)p, v);}; \ + static reg_type load(const template_arg * p) { return load_body ((const reg_type *)p); } \ + static void store(template_arg * p, reg_type v) { store_body ((reg_type *)p, v); } \ } #define FUNCTOR_LOADSTORE(name, template_arg, register_type, load_body, store_body)\ template <> \ struct name{ \ typedef register_type reg_type; \ - static reg_type load(const template_arg * p) { return load_body (p);}; \ - static void store(template_arg * p, reg_type v) { store_body (p, v);}; \ + static reg_type load(const template_arg * p) { return load_body (p); } \ + static void store(template_arg * p, reg_type v) { store_body (p, v); } \ } #define FUNCTOR_CLOSURE_2arg(name, template_arg, body)\ diff --git a/modules/core/src/glob.cpp b/modules/core/src/glob.cpp index c75bd2e66..93dc72ff8 100644 --- a/modules/core/src/glob.cpp +++ b/modules/core/src/glob.cpp @@ -64,7 +64,7 @@ namespace HANDLE handle; dirent ent; #ifdef HAVE_WINRT - DIR() {}; + DIR() { } ~DIR() { if (ent.d_name) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index cf3b1dcab..e35c7c944 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -1928,7 +1928,7 @@ inline cl_int getStringInfo(Functor f, ObjectType obj, cl_uint name, std::string } return CL_SUCCESS; -}; +} static void split(const std::string &s, char delim, std::vector &elems) { elems.clear(); diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index ba6656761..23c0aad62 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -83,7 +83,7 @@ static bool cvTsCheckSparse(const CvSparseMat* m1, const CvSparseMat* m2, double class Core_IOTest : public cvtest::BaseTest { public: - Core_IOTest() {}; + Core_IOTest() { } protected: void run(int) { diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index 3c8ae8bf9..6d72f9ea2 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -9,7 +9,7 @@ using namespace std; class Core_ReduceTest : public cvtest::BaseTest { public: - Core_ReduceTest() {}; + Core_ReduceTest() {} protected: void run( int); int checkOp( const Mat& src, int dstType, int opType, const Mat& opRes, int dim ); diff --git a/modules/core/test/test_operations.cpp b/modules/core/test/test_operations.cpp index 8d3341e59..8215ea93f 100644 --- a/modules/core/test/test_operations.cpp +++ b/modules/core/test/test_operations.cpp @@ -63,7 +63,7 @@ protected: struct test_excep { - test_excep(const string& _s=string("")) : s(_s) {}; + test_excep(const string& _s=string("")) : s(_s) { } string s; }; diff --git a/modules/core/test/test_umat.cpp b/modules/core/test/test_umat.cpp index 1dfe1d79a..cfea5c593 100644 --- a/modules/core/test/test_umat.cpp +++ b/modules/core/test/test_umat.cpp @@ -59,7 +59,7 @@ protected: struct test_excep { - test_excep(const string& _s=string("")) : s(_s) {}; + test_excep(const string& _s=string("")) : s(_s) { } string s; }; diff --git a/modules/cuda/src/cuda/ccomponetns.cu b/modules/cuda/src/cuda/ccomponetns.cu index 681ca8fe4..441413c34 100644 --- a/modules/cuda/src/cuda/ccomponetns.cu +++ b/modules/cuda/src/cuda/ccomponetns.cu @@ -133,7 +133,7 @@ namespace cv { namespace cuda { namespace device template struct InInterval { typedef typename VecTraits::elem_type E; - __host__ __device__ __forceinline__ InInterval(const float4& _lo, const float4& _hi) : lo((E)(-_lo.x)), hi((E)_hi.x) {}; + __host__ __device__ __forceinline__ InInterval(const float4& _lo, const float4& _hi) : lo((E)(-_lo.x)), hi((E)_hi.x) { } T lo, hi; template __device__ __forceinline__ bool operator() (const I& a, const I& b) const @@ -148,7 +148,7 @@ namespace cv { namespace cuda { namespace device { typedef typename VecTraits::elem_type E; __host__ __device__ __forceinline__ InInterval(const float4& _lo, const float4& _hi) - : lo (VecTraits::make((E)(-_lo.x), (E)(-_lo.y), (E)(-_lo.z))), hi (VecTraits::make((E)_hi.x, (E)_hi.y, (E)_hi.z)){}; + : lo (VecTraits::make((E)(-_lo.x), (E)(-_lo.y), (E)(-_lo.z))), hi (VecTraits::make((E)_hi.x, (E)_hi.y, (E)_hi.z)) { } T lo, hi; template __device__ __forceinline__ bool operator() (const I& a, const I& b) const @@ -164,7 +164,7 @@ namespace cv { namespace cuda { namespace device { typedef typename VecTraits::elem_type E; __host__ __device__ __forceinline__ InInterval(const float4& _lo, const float4& _hi) - : lo (VecTraits::make((E)(-_lo.x), (E)(-_lo.y), (E)(-_lo.z), (E)(-_lo.w))), hi (VecTraits::make((E)_hi.x, (E)_hi.y, (E)_hi.z, (E)_hi.w)){}; + : lo (VecTraits::make((E)(-_lo.x), (E)(-_lo.y), (E)(-_lo.z), (E)(-_lo.w))), hi (VecTraits::make((E)_hi.x, (E)_hi.y, (E)_hi.z, (E)_hi.w)) { } T lo, hi; template __device__ __forceinline__ bool operator() (const I& a, const I& b) const diff --git a/modules/cuda/test/test_labeling.cpp b/modules/cuda/test/test_labeling.cpp index fd6bfd631..8bc620aef 100644 --- a/modules/cuda/test/test_labeling.cpp +++ b/modules/cuda/test/test_labeling.cpp @@ -62,7 +62,7 @@ namespace struct InInterval { - InInterval(const int& _lo, const int& _hi) : lo(-_lo), hi(_hi) {}; + InInterval(const int& _lo, const int& _hi) : lo(-_lo), hi(_hi) {} const int lo, hi; bool operator() (const unsigned char a, const unsigned char b) const diff --git a/modules/cudalegacy/src/cuda/NCVPixelOperations.hpp b/modules/cudalegacy/src/cuda/NCVPixelOperations.hpp index e094f6bc0..2d06cda85 100644 --- a/modules/cudalegacy/src/cuda/NCVPixelOperations.hpp +++ b/modules/cudalegacy/src/cuda/NCVPixelOperations.hpp @@ -104,7 +104,7 @@ template<> struct TConvBase2Vec {typedef double3 TVec;}; template<> struct TConvBase2Vec {typedef double4 TVec;}; //TODO: consider using CUDA intrinsics to avoid branching -template static inline __host__ __device__ void _TDemoteClampZ(Tin &a, Ncv8u &out) {out = (Ncv8u)CLAMP_0_255(a);}; +template static inline __host__ __device__ void _TDemoteClampZ(Tin &a, Ncv8u &out) {out = (Ncv8u)CLAMP_0_255(a);} template static inline __host__ __device__ void _TDemoteClampZ(Tin &a, Ncv16u &out) {out = (Ncv16u)CLAMP(a, 0, USHRT_MAX);} template static inline __host__ __device__ void _TDemoteClampZ(Tin &a, Ncv32u &out) {out = (Ncv32u)CLAMP(a, 0, UINT_MAX);} template static inline __host__ __device__ void _TDemoteClampZ(Tin &a, Ncv32f &out) {out = (Ncv32f)a;} diff --git a/modules/flann/include/opencv2/flann/autotuned_index.h b/modules/flann/include/opencv2/flann/autotuned_index.h index 8d531753e..b0beac499 100644 --- a/modules/flann/include/opencv2/flann/autotuned_index.h +++ b/modules/flann/include/opencv2/flann/autotuned_index.h @@ -270,7 +270,7 @@ private: // struct KMeansSimpleDownhillFunctor { // // Autotune& autotuner; - // KMeansSimpleDownhillFunctor(Autotune& autotuner_) : autotuner(autotuner_) {}; + // KMeansSimpleDownhillFunctor(Autotune& autotuner_) : autotuner(autotuner_) {} // // float operator()(int* params) { // @@ -295,7 +295,7 @@ private: // struct KDTreeSimpleDownhillFunctor { // // Autotune& autotuner; - // KDTreeSimpleDownhillFunctor(Autotune& autotuner_) : autotuner(autotuner_) {}; + // KDTreeSimpleDownhillFunctor(Autotune& autotuner_) : autotuner(autotuner_) {} // // float operator()(int* params) { // float maxFloat = numeric_limits::max(); diff --git a/modules/flann/test/test_lshtable_badarg.cpp b/modules/flann/test/test_lshtable_badarg.cpp index 3b776668d..4c9ebf9fe 100644 --- a/modules/flann/test/test_lshtable_badarg.cpp +++ b/modules/flann/test/test_lshtable_badarg.cpp @@ -47,7 +47,7 @@ class CV_LshTableBadArgTest : public cvtest::BadArgTest { protected: void run(int); - void run_func(void) {}; + void run_func(void) { } struct Caller { diff --git a/modules/highgui/src/cap_ios_video_camera.mm b/modules/highgui/src/cap_ios_video_camera.mm index 99f8a75ae..20973c313 100644 --- a/modules/highgui/src/cap_ios_video_camera.mm +++ b/modules/highgui/src/cap_ios_video_camera.mm @@ -34,7 +34,7 @@ #import -static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;}; +static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} #pragma mark - Private Interface diff --git a/modules/highgui/src/grfmt_base.hpp b/modules/highgui/src/grfmt_base.hpp index f7fde90cf..8a534daa8 100644 --- a/modules/highgui/src/grfmt_base.hpp +++ b/modules/highgui/src/grfmt_base.hpp @@ -59,11 +59,11 @@ class BaseImageDecoder { public: BaseImageDecoder(); - virtual ~BaseImageDecoder() {}; + virtual ~BaseImageDecoder() {} - int width() const { return m_width; }; - int height() const { return m_height; }; - virtual int type() const { return m_type; }; + int width() const { return m_width; } + int height() const { return m_height; } + virtual int type() const { return m_type; } virtual bool setSource( const String& filename ); virtual bool setSource( const Mat& buf ); @@ -90,7 +90,7 @@ class BaseImageEncoder { public: BaseImageEncoder(); - virtual ~BaseImageEncoder() {}; + virtual ~BaseImageEncoder() {} virtual bool isFormatSupported( int depth ) const; virtual bool setDestination( const String& filename ); diff --git a/modules/highgui/src/rgbe.cpp b/modules/highgui/src/rgbe.cpp index a28100a60..c35197daa 100644 --- a/modules/highgui/src/rgbe.cpp +++ b/modules/highgui/src/rgbe.cpp @@ -79,7 +79,7 @@ enum rgbe_error_codes { rgbe_read_error, rgbe_write_error, rgbe_format_error, - rgbe_memory_error, + rgbe_memory_error }; /* default error routine. change this to change error handling */ diff --git a/modules/highgui/test/test_positioning.cpp b/modules/highgui/test/test_positioning.cpp index edc8dcf42..993a76cb4 100644 --- a/modules/highgui/test/test_positioning.cpp +++ b/modules/highgui/test/test_positioning.cpp @@ -67,7 +67,7 @@ private: class CV_VideoProgressivePositioningTest: public CV_VideoPositioningTest { public: - CV_VideoProgressivePositioningTest() : CV_VideoPositioningTest() {}; + CV_VideoProgressivePositioningTest() : CV_VideoPositioningTest() { } ~CV_VideoProgressivePositioningTest(); void run(int); }; @@ -75,7 +75,7 @@ public: class CV_VideoRandomPositioningTest: public CV_VideoPositioningTest { public: - CV_VideoRandomPositioningTest(): CV_VideoPositioningTest() {}; + CV_VideoRandomPositioningTest(): CV_VideoPositioningTest() { } ~CV_VideoRandomPositioningTest(); void run(int); }; diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 5a9450bf2..2b94e0de2 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -952,7 +952,7 @@ public: */ CV_WRAP virtual int compareSegments(const Size& size, InputArray lines1, InputArray lines2, InputOutputArray _image = noArray()) = 0; - virtual ~LineSegmentDetector() {}; + virtual ~LineSegmentDetector() { } }; //! Returns a pointer to a LineSegmentDetector class. diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 70ad0827c..1346f0a15 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -3658,7 +3658,7 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) int ustepIdx = 0; int vstepIdx = dstSz.height % 4 == 2 ? 1 : 0; - if(uIdx == 1) { std::swap(u ,v), std::swap(ustepIdx, vstepIdx); }; + if(uIdx == 1) { std::swap(u ,v), std::swap(ustepIdx, vstepIdx); } switch(dcn*10 + bIdx) { diff --git a/modules/imgproc/src/min_enclosing_triangle.cpp b/modules/imgproc/src/min_enclosing_triangle.cpp index 98bfd46e5..fb94fa0ba 100644 --- a/modules/imgproc/src/min_enclosing_triangle.cpp +++ b/modules/imgproc/src/min_enclosing_triangle.cpp @@ -287,7 +287,7 @@ static void updateSidesCA(const std::vector &polygon, cv::Point2f &sideAStartVertex, cv::Point2f &sideAEndVertex, cv::Point2f &sideCStartVertex, cv::Point2f &sideCEndVertex); -}; +} ///////////////////////////////////// Main functions ///////////////////////////////////// @@ -1560,4 +1560,4 @@ static bool lessOrEqual(double number1, double number2) { return ((number1 < number2) || (almostEqual(number1, number2))); } -}; \ No newline at end of file +} diff --git a/modules/imgproc/test/test_filter.cpp b/modules/imgproc/test/test_filter.cpp index efbad9974..f47e523d8 100644 --- a/modules/imgproc/test/test_filter.cpp +++ b/modules/imgproc/test/test_filter.cpp @@ -898,8 +898,8 @@ struct median_pair { int col; int val; - median_pair() {}; - median_pair( int _col, int _val ) : col(_col), val(_val) {}; + median_pair() { } + median_pair( int _col, int _val ) : col(_col), val(_val) { } }; diff --git a/modules/imgproc/test/test_lsd.cpp b/modules/imgproc/test/test_lsd.cpp index 82f5b0bce..50a353503 100644 --- a/modules/imgproc/test/test_lsd.cpp +++ b/modules/imgproc/test/test_lsd.cpp @@ -12,7 +12,7 @@ const int EPOCHS = 20; class LSDBase : public testing::Test { public: - LSDBase() {}; + LSDBase() { } protected: Mat test_image; @@ -30,7 +30,7 @@ protected: class Imgproc_LSD_ADV: public LSDBase { public: - Imgproc_LSD_ADV() {}; + Imgproc_LSD_ADV() { } protected: }; @@ -38,7 +38,7 @@ protected: class Imgproc_LSD_STD: public LSDBase { public: - Imgproc_LSD_STD() {}; + Imgproc_LSD_STD() { } protected: }; @@ -46,7 +46,7 @@ protected: class Imgproc_LSD_NONE: public LSDBase { public: - Imgproc_LSD_NONE() {}; + Imgproc_LSD_NONE() { } protected: }; diff --git a/modules/legacy/src/blobtrackgen1.cpp b/modules/legacy/src/blobtrackgen1.cpp index 7114f2b4c..af9c3b3a1 100644 --- a/modules/legacy/src/blobtrackgen1.cpp +++ b/modules/legacy/src/blobtrackgen1.cpp @@ -98,7 +98,7 @@ public: m_pFileName = NULL; SetModuleName("Gen1"); - }; + } ~CvBlobTrackGen1() { @@ -119,7 +119,7 @@ public: } /* Check next track. */ } /* Destructor. */ - void SetFileName(char* pFileName){m_pFileName = pFileName;}; + void SetFileName(char* pFileName){m_pFileName = pFileName;} void AddBlob(CvBlob* pBlob) { @@ -140,7 +140,7 @@ public: pTrack->FrameLast = m_Frame; assert(pTrack->pSeq); pTrack->pSeq->AddBlob(pBlob); - }; + } void Process(IplImage* /*pImg*/ = NULL, IplImage* /*pFG*/ = NULL) { diff --git a/modules/legacy/src/blobtrackgenyml.cpp b/modules/legacy/src/blobtrackgenyml.cpp index 0d9de45ee..c33d16d03 100644 --- a/modules/legacy/src/blobtrackgenyml.cpp +++ b/modules/legacy/src/blobtrackgenyml.cpp @@ -147,7 +147,7 @@ public: m_Size = cvSize(2,2); SetModuleName("YML"); - }; + } ~CvBlobTrackGenYML() { @@ -164,7 +164,7 @@ public: } /* Destructor. */ - void SetFileName(char* pFileName){m_pFileName = pFileName;}; + void SetFileName(char* pFileName){m_pFileName = pFileName;} void AddBlob(CvBlob* pBlob) { DefBlobTrack* pTrack = (DefBlobTrack*)m_TrackList.GetBlobByID(CV_BLOB_ID(pBlob)); @@ -184,7 +184,7 @@ public: pTrack->FrameLast = m_Frame; assert(pTrack->pSeq); pTrack->pSeq->AddBlob(pBlob); - }; + } void Process(IplImage* pImg = NULL, IplImage* /*pFG*/ = NULL) { int i; diff --git a/modules/legacy/src/blobtrackingauto.cpp b/modules/legacy/src/blobtrackingauto.cpp index ada0bdff4..1fd695310 100644 --- a/modules/legacy/src/blobtrackingauto.cpp +++ b/modules/legacy/src/blobtrackingauto.cpp @@ -97,16 +97,16 @@ class CvBlobTrackerAuto1: public CvBlobTrackerAuto public: CvBlobTrackerAuto1(CvBlobTrackerAutoParam1* param); ~CvBlobTrackerAuto1(); - CvBlob* GetBlob(int index){return m_BlobList.GetBlob(index);}; - CvBlob* GetBlobByID(int ID){return m_BlobList.GetBlobByID(ID);}; - int GetBlobNum(){return m_BlobList.GetBlobNum();}; - virtual IplImage* GetFGMask(){return m_pFGMask;}; - float GetState(int BlobID){return m_pBTA?m_pBTA->GetState(BlobID):0;}; - const char* GetStateDesc(int BlobID){return m_pBTA?m_pBTA->GetStateDesc(BlobID):NULL;}; + CvBlob* GetBlob(int index){return m_BlobList.GetBlob(index);} + CvBlob* GetBlobByID(int ID){return m_BlobList.GetBlobByID(ID);} + int GetBlobNum(){return m_BlobList.GetBlobNum();} + virtual IplImage* GetFGMask(){return m_pFGMask;} + float GetState(int BlobID){return m_pBTA?m_pBTA->GetState(BlobID):0;} + const char* GetStateDesc(int BlobID){return m_pBTA?m_pBTA->GetStateDesc(BlobID):NULL;} /* Return 0 if trajectory is normal; return >0 if trajectory abnormal. */ void Process(IplImage* pImg, IplImage* pMask = NULL); - void Release(){delete this;}; + void Release(){delete this;} private: IplImage* m_pFGMask; diff --git a/modules/legacy/src/blobtrackingcc.cpp b/modules/legacy/src/blobtrackingcc.cpp index c2279a20b..1a72c7e47 100644 --- a/modules/legacy/src/blobtrackingcc.cpp +++ b/modules/legacy/src/blobtrackingcc.cpp @@ -125,23 +125,23 @@ public: CommentParam("ConfidenceType","Type of calculated Confidence (NearestBlob, AverFG, BC)"); SetModuleName("CC"); - }; + } ~CvBlobTrackerCC() { if(m_pMem)cvReleaseMemStorage(&m_pMem); - }; + } /* Blob functions: */ - virtual int GetBlobNum() {return m_BlobList.GetBlobNum();}; - virtual CvBlob* GetBlob(int BlobIndex){return m_BlobList.GetBlob(BlobIndex);}; + virtual int GetBlobNum() {return m_BlobList.GetBlobNum();} + virtual CvBlob* GetBlob(int BlobIndex){return m_BlobList.GetBlob(BlobIndex);} virtual void SetBlob(int BlobIndex, CvBlob* pBlob) { CvBlob* pB = m_BlobList.GetBlob(BlobIndex); if(pB) pB[0] = pBlob[0]; - }; + } - virtual CvBlob* GetBlobByID(int BlobID){return m_BlobList.GetBlobByID(BlobID);}; + virtual CvBlob* GetBlobByID(int BlobID){return m_BlobList.GetBlobByID(BlobID);} virtual void DelBlob(int BlobIndex) { DefBlobTracker* pBT = (DefBlobTracker*)m_BlobList.GetBlob(BlobIndex); @@ -156,7 +156,7 @@ public: } delete pBT->pBlobHyp; m_BlobList.DelBlob(BlobIndex); - }; + } #if 0 virtual void DelBlobByID(int BlobID) { @@ -166,7 +166,7 @@ public: m_BlobList.DelBlobByID(BlobID); }; #endif - virtual void Release(){delete this;}; + virtual void Release(){delete this;} /* Add new blob to track it and assign to this blob personal ID */ /* pBlob - pinter to structure with blob parameters (ID is ignored)*/ @@ -185,7 +185,7 @@ public: NewB.AverFG = pImgFG?CalcAverageMask(pB,pImgFG):0; m_BlobList.AddBlob((CvBlob*)&NewB); return m_BlobList.GetBlob(m_BlobList.GetBlobNum()-1); - }; + } virtual void Process(IplImage* pImg, IplImage* pImgFG = NULL) { @@ -390,7 +390,7 @@ public: pBlob[0] = pB[0]; pBlob->ID = ID; - }; + } virtual double GetConfidence(int BlobIndex, CvBlob* pBlob, IplImage* /*pImg*/, IplImage* pImgFG = NULL) { @@ -443,7 +443,7 @@ public: } /* Calculate sum of mask. */ return W; - }; + } virtual void UpdateBlob(int BlobIndex, CvBlob* /*pBlob*/, IplImage* /*pImg*/, IplImage* pImgFG = NULL) { @@ -455,7 +455,7 @@ public: { //pBT->AverFG = pBT->AverFG * (1-m_Alpha) + m_Alpha * CalcAverageMask(pBlob,pImgFG); } - }; + } virtual void ParamUpdate() { @@ -481,7 +481,7 @@ public: DefBlobTracker* pBT = (DefBlobTracker*)m_BlobList.GetBlob(BlobIdx); assert(pBT->pBlobHyp); return pBT->pBlobHyp->GetBlobNum(); - }; /* CvBlobtrackerList::GetBlobHypNum() */ + } /* CvBlobtrackerList::GetBlobHypNum() */ /* Return pointer to specified blob hypothesis by index blob: */ virtual CvBlob* GetBlobHyp(int BlobIndex, int hypothesis) @@ -489,7 +489,7 @@ public: DefBlobTracker* pBT = (DefBlobTracker*)m_BlobList.GetBlob(BlobIndex); assert(pBT->pBlobHyp); return pBT->pBlobHyp->GetBlob(hypothesis); - }; /* CvBlobtrackerList::GetBlobHyp() */ + } /* CvBlobtrackerList::GetBlobHyp() */ /* Set new parameters for specified (by index) blob hypothesis * (can be called several times for each hypothesis): @@ -512,7 +512,7 @@ public: assert(pBT->pBlobHyp); pBT->pBlobHyp->AddBlob(pBlob); } - }; + } private: CvBlob* GetNearestBlob(CvBlob* pB) @@ -542,7 +542,7 @@ private: return pBBest; - }; /* GetNearestBlob */ + } /* GetNearestBlob */ }; diff --git a/modules/legacy/src/blobtrackingccwithcr.cpp b/modules/legacy/src/blobtrackingccwithcr.cpp index ad00b9438..e8bd4dec8 100644 --- a/modules/legacy/src/blobtrackingccwithcr.cpp +++ b/modules/legacy/src/blobtrackingccwithcr.cpp @@ -110,23 +110,23 @@ public: pM->Release(); } SetParam("SizeVar",0); - }; + } ~CvBlobTrackerCCCR() { if(m_pMem)cvReleaseMemStorage(&m_pMem); - }; + } /* Blob functions: */ - virtual int GetBlobNum() {return m_BlobList.GetBlobNum();}; - virtual CvBlob* GetBlob(int BlobIndex){return m_BlobList.GetBlob(BlobIndex);}; + virtual int GetBlobNum() {return m_BlobList.GetBlobNum();} + virtual CvBlob* GetBlob(int BlobIndex){return m_BlobList.GetBlob(BlobIndex);} virtual void SetBlob(int BlobIndex, CvBlob* pBlob) { CvBlob* pB = m_BlobList.GetBlob(BlobIndex); if(pB) pB[0] = pBlob[0]; - }; + } - virtual CvBlob* GetBlobByID(int BlobID){return m_BlobList.GetBlobByID(BlobID);}; + virtual CvBlob* GetBlobByID(int BlobID){return m_BlobList.GetBlobByID(BlobID);} virtual void DelBlob(int BlobIndex) { DefBlobTrackerCR* pBT = (DefBlobTrackerCR*)m_BlobList.GetBlob(BlobIndex); @@ -134,7 +134,7 @@ public: if(pBT->pPredictor)pBT->pPredictor->Release(); delete pBT->pBlobHyp; m_BlobList.DelBlob(BlobIndex); - }; + } virtual void DelBlobByID(int BlobID) { @@ -143,9 +143,9 @@ public: if(pBT->pPredictor)pBT->pPredictor->Release(); delete pBT->pBlobHyp; m_BlobList.DelBlobByID(BlobID); - }; + } - virtual void Release(){delete this;}; + virtual void Release(){delete this;} /* Add new blob to track it and assign to this blob personal ID */ /* pBlob - pinter to structure with blob parameters (ID is ignored)*/ @@ -169,7 +169,7 @@ public: } m_BlobList.AddBlob((CvBlob*)&NewB); return m_BlobList.GetBlob(m_BlobList.GetBlobNum()-1); - }; + } virtual void Process(IplImage* pImg, IplImage* pImgFG = NULL) { @@ -480,7 +480,7 @@ public: } /* Read next blob. */ } /* CCwithCR LoadState */ - //void SetCollision(int Collision){m_Collision = Collision;}; + //void SetCollision(int Collision){m_Collision = Collision;} }; CvBlobTrackerOne* cvCreateBlobTrackerOneMSPF(); diff --git a/modules/legacy/src/blobtrackinglist.cpp b/modules/legacy/src/blobtrackinglist.cpp index e48f6593f..cbf007186 100644 --- a/modules/legacy/src/blobtrackinglist.cpp +++ b/modules/legacy/src/blobtrackinglist.cpp @@ -228,7 +228,7 @@ public: { m_BlobTrackerList.DelBlob(i-1); } - }; + } CvBlob* AddBlob(CvBlob* pBlob, IplImage* pImg, IplImage* pImgFG ) { /* Create new tracker: */ @@ -244,7 +244,7 @@ public: F.pTracker->Init(pBlob,pImg, pImgFG); m_BlobTrackerList.AddBlob((CvBlob*)&F); return m_BlobTrackerList.GetBlob(m_BlobTrackerList.GetBlobNum()-1); - }; + } void DelBlob(int BlobIndex) { @@ -404,7 +404,7 @@ public: } /* Update predictor. */ #endif m_ClearHyp = 1; - }; + } /* Process on blob (for multi hypothesis tracing) */ @@ -421,7 +421,7 @@ public: pBlob[0] = pF->blob; } pBlob->ID = ID; - }; + } virtual double GetConfidence(int BlobIndex, CvBlob* pBlob, IplImage* pImg, IplImage* pImgFG = NULL) { @@ -429,7 +429,7 @@ public: if(pF==NULL) return 0; if(pF->pTracker==NULL) return 0; return pF->pTracker->GetConfidence(pBlob?pBlob:(&pF->blob), pImg, pImgFG, NULL); - }; + } virtual double GetConfidenceList(CvBlobSeq* pBlobList, IplImage* pImg, IplImage* pImgFG = NULL) { @@ -460,7 +460,7 @@ public: // cvWaitKey(0); } return W; - }; + } virtual void UpdateBlob(int BlobIndex, CvBlob* pBlob, IplImage* pImg, IplImage* /*pImgFG*/ = NULL) { @@ -469,10 +469,10 @@ public: { pF->pTracker->Update(pBlob?pBlob:&(pF->blob),pImg,m_pImgFG); } - }; + } - int GetBlobNum(){return m_BlobTrackerList.GetBlobNum();}; - CvBlob* GetBlob(int index){return m_BlobTrackerList.GetBlob(index);}; + int GetBlobNum(){return m_BlobTrackerList.GetBlobNum();} + CvBlob* GetBlob(int index){return m_BlobTrackerList.GetBlob(index);} void SetBlob(int BlobIndex, CvBlob* pBlob) { @@ -485,7 +485,7 @@ public: } } - void Release(){delete this;}; + void Release(){delete this;} /* Additional functionality: */ CvBlob* GetBlobByID(int BlobID){return m_BlobTrackerList.GetBlobByID(BlobID);} @@ -497,7 +497,7 @@ public: DefBlobTrackerL* pF = (DefBlobTrackerL*)m_BlobTrackerList.GetBlob(BlobIdx); assert(pF->pBlobHyp); return pF->pBlobHyp->GetBlobNum(); - }; /* CvBlobtrackerList::GetBlobHypNum() */ + } /* CvBlobtrackerList::GetBlobHypNum() */ /* Return pointer to specified blob hypothesis by index blob: */ virtual CvBlob* GetBlobHyp(int BlobIndex, int hypothesis) @@ -505,7 +505,7 @@ public: DefBlobTrackerL* pF = (DefBlobTrackerL*)m_BlobTrackerList.GetBlob(BlobIndex); assert(pF->pBlobHyp); return pF->pBlobHyp->GetBlob(hypothesis); - }; /* CvBlobtrackerList::GetBlobHyp() */ + } /* CvBlobtrackerList::GetBlobHyp() */ /* Set new parameters for specified (by index) blob hyp (can be called several times for each hyp )*/ virtual void SetBlobHyp(int BlobIndex, CvBlob* pBlob) @@ -526,7 +526,7 @@ public: assert(pF->pBlobHyp); pF->pBlobHyp->AddBlob(pBlob); } - }; /* CvBlobtrackerList::SetBlobHyp */ + } /* CvBlobtrackerList::SetBlobHyp */ private: public: diff --git a/modules/legacy/src/blobtrackingmsfg.cpp b/modules/legacy/src/blobtrackingmsfg.cpp index 5fd9634d4..a26ce029f 100644 --- a/modules/legacy/src/blobtrackingmsfg.cpp +++ b/modules/legacy/src/blobtrackingmsfg.cpp @@ -260,7 +260,7 @@ private: pHist->m_HistVolume = Volume; - }; /* CollectHist */ + } /* CollectHist */ double calcBhattacharyya(DefHist* pHM = NULL, DefHist* pHC = NULL, DefHist* pHT = NULL) { @@ -370,7 +370,7 @@ public: if(pImg) CollectHist(pImg, pImgFG, pBlobInit, &m_HistModel); m_Blob = pBlobInit[0]; - }; + } virtual CvBlob* Process(CvBlob* pBlobPrev, IplImage* pImg, IplImage* pImgFG = NULL) { @@ -603,7 +603,7 @@ public: return &m_Blob; - }; /* CvBlobTrackerOneMSFG::Process */ + } /* CvBlobTrackerOneMSFG::Process */ virtual double GetConfidence(CvBlob* pBlob, IplImage* pImg, IplImage* /*pImgFG*/ = NULL, IplImage* pImgUnusedReg = NULL) { @@ -611,14 +611,14 @@ public: double B = GetBhattacharyya(pImg, pImgUnusedReg, pBlob, &m_HistTemp); return exp((B-1)/(2*S)); - }; /*CvBlobTrackerOneMSFG::*/ + } /*CvBlobTrackerOneMSFG::*/ virtual void Update(CvBlob* pBlob, IplImage* pImg, IplImage* pImgFG = NULL) { /* Update histogram: */ UpdateModelHist(pImg, pImgFG, pBlob?pBlob:&m_Blob); } /*CvBlobTrackerOneMSFG::*/ - virtual void Release(){delete this;}; + virtual void Release(){delete this;} virtual void SetCollision(int CollisionFlag) { m_Collision = CollisionFlag; @@ -629,7 +629,7 @@ public: cvWriteInt(fs,"Collision", m_Collision); cvWriteInt(fs,"HistVolume", cvRound(m_HistModel.m_HistVolume)); cvWrite(fs,"Hist", m_HistModel.m_pHist); - }; + } virtual void LoadState(CvFileStorage* fs, CvFileNode* node) { CvMat* pM; @@ -641,7 +641,7 @@ public: m_HistModel.m_pHist = pM; m_HistModel.m_HistVolume = (float)cvSum(pM).val[0]; } - }; + } }; /*CvBlobTrackerOneMSFG*/ @@ -782,7 +782,7 @@ public: cvWriteInt(fs,"ParticleNum",m_ParticleNum); cvWriteStruct(fs,"ParticlesPredicted",m_pParticlesPredicted,"ffffiffd",m_ParticleNum); cvWriteStruct(fs,"ParticlesResampled",m_pParticlesResampled,"ffffiffd",m_ParticleNum); - }; + } virtual void LoadState(CvFileStorage* fs, CvFileNode* node) { @@ -796,7 +796,7 @@ public: cvReadStructByName(fs,node,"ParticlesPredicted",m_pParticlesPredicted,"ffffiffd"); cvReadStructByName(fs,node,"ParticlesResampled",m_pParticlesResampled,"ffffiffd"); } - }; + } CvBlobTrackerOneMSPF() { m_pParticlesPredicted = NULL; @@ -847,7 +847,7 @@ private: if(m_pParticlesPredicted)cvFree(&m_pParticlesPredicted); m_pParticlesPredicted = (DefParticle*)cvAlloc(sizeof(DefParticle)*m_ParticleNum); m_pParticlesResampled = (DefParticle*)cvAlloc(sizeof(DefParticle)*m_ParticleNum); - }; /* Realloc*/ + } /* Realloc*/ void DrawDebug(IplImage* pImg, IplImage* /*pImgFG*/) { @@ -1161,7 +1161,7 @@ public: } } - virtual void Release(){delete this;}; + virtual void Release(){delete this;} virtual void ParamUpdate() { Realloc(); diff --git a/modules/legacy/src/blobtrackingmsfgs.cpp b/modules/legacy/src/blobtrackingmsfgs.cpp index f3b3cf375..afe33847f 100644 --- a/modules/legacy/src/blobtrackingmsfgs.cpp +++ b/modules/legacy/src/blobtrackingmsfgs.cpp @@ -210,7 +210,7 @@ private: if(pHistVolume)pHistVolume[0] = Volume; - }; /* calcHist */ + } /* calcHist */ double calcBhattacharyya() { @@ -440,9 +440,9 @@ public: return &m_Blob; - }; /* Process */ + } /* Process */ - virtual void Release(){delete this;}; + virtual void Release(){delete this;} }; /*CvBlobTrackerOneMSFGS*/ static CvBlobTrackerOne* cvCreateBlobTrackerOneMSFGS() diff --git a/modules/legacy/src/blobtrackpostproclist.cpp b/modules/legacy/src/blobtrackpostproclist.cpp index 33e68fe46..ed03d8e58 100644 --- a/modules/legacy/src/blobtrackpostproclist.cpp +++ b/modules/legacy/src/blobtrackpostproclist.cpp @@ -74,7 +74,7 @@ public: DefBlobFilter* pF = (DefBlobFilter*)m_BlobFilterList.GetBlob(i-1); pF->pFilter->Release(); } - }; + } virtual void AddBlob(CvBlob* pBlob) { @@ -93,7 +93,7 @@ public: assert(pF); pF->blob = pBlob[0]; pF->m_LastFrame = m_Frame; - }; + } virtual void Process() { @@ -115,11 +115,11 @@ public: } } /* Next blob. */ m_Frame++; - }; + } - int GetBlobNum(){return m_BlobFilterList.GetBlobNum();}; - CvBlob* GetBlob(int index){return m_BlobFilterList.GetBlob(index);}; - void Release(){delete this;}; + int GetBlobNum(){return m_BlobFilterList.GetBlobNum();} + CvBlob* GetBlob(int index){return m_BlobFilterList.GetBlob(index);} + void Release(){delete this;} /* Additional functionality: */ CvBlob* GetBlobByID(int BlobID){return m_BlobFilterList.GetBlobByID(BlobID);} diff --git a/modules/legacy/src/enteringblobdetection.cpp b/modules/legacy/src/enteringblobdetection.cpp index a383bcf67..a488e0881 100644 --- a/modules/legacy/src/enteringblobdetection.cpp +++ b/modules/legacy/src/enteringblobdetection.cpp @@ -544,7 +544,7 @@ public: CvBlobDetectorCC(); ~CvBlobDetectorCC(); int DetectNewBlob(IplImage* pImg, IplImage* pFGMask, CvBlobSeq* pNewBlobList, CvBlobSeq* pOldBlobList); - void Release(){delete this;}; + void Release(){delete this;} virtual void ParamUpdate() { diff --git a/modules/legacy/src/enteringblobdetectionreal.cpp b/modules/legacy/src/enteringblobdetectionreal.cpp index 9458ab53e..01a1c7604 100644 --- a/modules/legacy/src/enteringblobdetectionreal.cpp +++ b/modules/legacy/src/enteringblobdetectionreal.cpp @@ -156,7 +156,7 @@ public: } /* cvDetectNewBlob */ - void Release(){delete this;}; + void Release(){delete this;} }; /* Blob detector constructor: */ diff --git a/modules/legacy/src/facetemplate.h b/modules/legacy/src/facetemplate.h index 31a3a8303..83f5bc30e 100644 --- a/modules/legacy/src/facetemplate.h +++ b/modules/legacy/src/facetemplate.h @@ -98,7 +98,7 @@ inline void FaceFeature::SetWeight(double dWeight) class FaceTemplate { public: - FaceTemplate(long lFeatureCount) {m_lFeturesCount = lFeatureCount; m_lpFeaturesList = new FaceFeature[lFeatureCount];}; + FaceTemplate(long lFeatureCount) {m_lFeturesCount = lFeatureCount; m_lpFeaturesList = new FaceFeature[lFeatureCount];} virtual ~FaceTemplate(); inline long GetCount(); diff --git a/modules/legacy/src/oneway.cpp b/modules/legacy/src/oneway.cpp index 43ded8593..5eac273f4 100644 --- a/modules/legacy/src/oneway.cpp +++ b/modules/legacy/src/oneway.cpp @@ -57,8 +57,8 @@ namespace cv{ cvCopy(translation, m_translation); }; - CvMat* GetRotation() {return m_rotation;}; - CvMat* GetTranslation() {return m_translation;}; + CvMat* GetRotation() {return m_rotation;} + CvMat* GetTranslation() {return m_translation;} protected: CvMat* m_rotation; diff --git a/modules/ml/include/opencv2/ml.hpp b/modules/ml/include/opencv2/ml.hpp index 7325aa075..aca013e09 100644 --- a/modules/ml/include/opencv2/ml.hpp +++ b/modules/ml/include/opencv2/ml.hpp @@ -515,7 +515,7 @@ public: CV_WRAP virtual int get_support_vector_count() const; virtual const float* get_support_vector(int i) const; - virtual CvSVMParams get_params() const { return params; }; + virtual CvSVMParams get_params() const { return params; } CV_WRAP virtual void clear(); static CvParamGrid get_default_grid( int param_id ); @@ -1523,7 +1523,7 @@ public: // API // virtual bool train( CvMLData* data, CvGBTreesParams params=CvGBTreesParams(), - bool update=false ) {return false;}; + bool update=false ) {return false;} // INPUT // data - training set. diff --git a/modules/objdetect/doc/erfilter.rst b/modules/objdetect/doc/erfilter.rst index a8976fbcd..85d6bcc7f 100644 --- a/modules/objdetect/doc/erfilter.rst +++ b/modules/objdetect/doc/erfilter.rst @@ -46,7 +46,7 @@ An ER is a 4-connected set of pixels with all its grey-level values smaller than //! Constructor explicit ERStat(int level = 256, int pixel = 0, int x = 0, int y = 0); //! Destructor - ~ERStat(){}; + ~ERStat() { } //! seed point and threshold (max grey-level value) int pixel; @@ -105,7 +105,7 @@ Base class for 1st and 2nd stages of Neumann and Matas scene text detection algo class CV_EXPORTS Callback { public: - virtual ~Callback(){}; + virtual ~Callback() { } //! The classifier must return probability measure for the region. virtual double eval(const ERStat& stat) = 0; }; diff --git a/modules/objdetect/include/opencv2/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect.hpp index 0d5792124..b9ba2b935 100644 --- a/modules/objdetect/include/opencv2/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect.hpp @@ -190,7 +190,7 @@ public: public: virtual ~MaskGenerator() {} virtual Mat generateMask(const Mat& src)=0; - virtual void initializeMask(const Mat& /*src*/) {}; + virtual void initializeMask(const Mat& /*src*/) { } }; virtual void setMaskGenerator(const Ptr& maskGenerator) = 0; virtual Ptr getMaskGenerator() = 0; diff --git a/modules/objdetect/include/opencv2/objdetect/erfilter.hpp b/modules/objdetect/include/opencv2/objdetect/erfilter.hpp index 9dc919a41..d7e07d80d 100644 --- a/modules/objdetect/include/opencv2/objdetect/erfilter.hpp +++ b/modules/objdetect/include/opencv2/objdetect/erfilter.hpp @@ -67,7 +67,7 @@ public: //! Constructor explicit ERStat(int level = 256, int pixel = 0, int x = 0, int y = 0); //! Destructor - ~ERStat(){}; + ~ERStat() { } //! seed point and the threshold (max grey-level value) int pixel; @@ -123,7 +123,7 @@ public: class CV_EXPORTS Callback { public: - virtual ~Callback(){}; + virtual ~Callback() { } //! The classifier must return probability measure for the region. virtual double eval(const ERStat& stat) = 0; //const = 0; //TODO why cannot use const = 0 here? }; diff --git a/modules/objdetect/src/cascadedetect.hpp b/modules/objdetect/src/cascadedetect.hpp index ad96e5064..2d3f9064d 100644 --- a/modules/objdetect/src/cascadedetect.hpp +++ b/modules/objdetect/src/cascadedetect.hpp @@ -112,7 +112,7 @@ protected: struct Stump { - Stump() {}; + Stump() { } Stump(int _featureIdx, float _threshold, float _left, float _right) : featureIdx(_featureIdx), threshold(_threshold), left(_left), right(_right) {} diff --git a/modules/objdetect/src/erfilter.cpp b/modules/objdetect/src/erfilter.cpp index 52743afe9..43664645a 100644 --- a/modules/objdetect/src/erfilter.cpp +++ b/modules/objdetect/src/erfilter.cpp @@ -83,7 +83,7 @@ public: //Constructor ERFilterNM(); //Destructor - ~ERFilterNM() {}; + ~ERFilterNM() {} float minProbability; bool nonMaxSuppression; @@ -146,7 +146,7 @@ public: //Constructor ERClassifierNM1(const std::string& filename); // Destructor - ~ERClassifierNM1() {}; + ~ERClassifierNM1() {} // The classifier must return probability measure for the region. double eval(const ERStat& stat); @@ -162,7 +162,7 @@ public: //constructor ERClassifierNM2(const std::string& filename); // Destructor - ~ERClassifierNM2() {}; + ~ERClassifierNM2() {} // The classifier must return probability measure for the region. double eval(const ERStat& stat); @@ -933,14 +933,14 @@ ERStat* ERFilterNM::er_tree_nonmax_suppression ( ERStat * stat, ERStat *parent, void ERFilterNM::setCallback(const Ptr& cb) { classifier = cb; -}; +} void ERFilterNM::setMinArea(float _minArea) { CV_Assert( (_minArea >= 0) && (_minArea < maxArea) ); minArea = _minArea; return; -}; +} void ERFilterNM::setMaxArea(float _maxArea) { @@ -948,39 +948,39 @@ void ERFilterNM::setMaxArea(float _maxArea) CV_Assert(minArea < _maxArea); maxArea = _maxArea; return; -}; +} void ERFilterNM::setThresholdDelta(int _thresholdDelta) { CV_Assert( (_thresholdDelta > 0) && (_thresholdDelta <= 128) ); thresholdDelta = _thresholdDelta; return; -}; +} void ERFilterNM::setMinProbability(float _minProbability) { CV_Assert( (_minProbability >= 0.0) && (_minProbability <= 1.0) ); minProbability = _minProbability; return; -}; +} void ERFilterNM::setMinProbabilityDiff(float _minProbabilityDiff) { CV_Assert( (_minProbabilityDiff >= 0.0) && (_minProbabilityDiff <= 1.0) ); minProbabilityDiff = _minProbabilityDiff; return; -}; +} void ERFilterNM::setNonMaxSuppression(bool _nonMaxSuppression) { nonMaxSuppression = _nonMaxSuppression; return; -}; +} int ERFilterNM::getNumRejected() { return num_rejected_regions; -}; +} @@ -993,7 +993,7 @@ ERClassifierNM1::ERClassifierNM1(const std::string& filename) boost.load( filename.c_str(), "boost" ); else CV_Error(CV_StsBadArg, "Default classifier file not found!"); -}; +} double ERClassifierNM1::eval(const ERStat& stat) { @@ -1009,7 +1009,7 @@ double ERClassifierNM1::eval(const ERStat& stat) // Logistic Correction returns a probability value (in the range(0,1)) return (double)1-(double)1/(1+exp(-2*votes)); -}; +} // load default 2nd stage classifier if found @@ -1019,7 +1019,7 @@ ERClassifierNM2::ERClassifierNM2(const std::string& filename) boost.load( filename.c_str(), "boost" ); else CV_Error(CV_StsBadArg, "Default classifier file not found!"); -}; +} double ERClassifierNM2::eval(const ERStat& stat) { @@ -1036,7 +1036,7 @@ double ERClassifierNM2::eval(const ERStat& stat) // Logistic Correction returns a probability value (in the range(0,1)) return (double)1-(double)1/(1+exp(-2*votes)); -}; +} /*! @@ -2164,7 +2164,7 @@ public: unsigned char metric_; /// Constructor. - MaxMeaningfulClustering(unsigned char method, unsigned char metric){ method_=method; metric_=metric; }; + MaxMeaningfulClustering(unsigned char method, unsigned char metric){ method_=method; metric_=metric; } void operator()(double *data, unsigned int num, int dim, unsigned char method, unsigned char metric, vector< vector > *meaningful_clusters); diff --git a/modules/ocl/test/test_fft.cpp b/modules/ocl/test/test_fft.cpp index 1c2a1da47..ddc26e360 100644 --- a/modules/ocl/test/test_fft.cpp +++ b/modules/ocl/test/test_fft.cpp @@ -202,8 +202,8 @@ void static convolveDFT(const cv::Mat& A, const cv::Mat& B, cv::Mat& C, bool cco tempA(cv::Rect(0, 0, C.cols, C.rows)).copyTo(C); } -IMPLEMENT_PARAM_CLASS(KSize, int); -IMPLEMENT_PARAM_CLASS(Ccorr, bool); +IMPLEMENT_PARAM_CLASS(KSize, int) +IMPLEMENT_PARAM_CLASS(Ccorr, bool) PARAM_TEST_CASE(Convolve_DFT, cv::Size, KSize, Ccorr) { diff --git a/modules/photo/src/hdr_common.cpp b/modules/photo/src/hdr_common.cpp index 6b67a58e0..9a2d720e4 100644 --- a/modules/photo/src/hdr_common.cpp +++ b/modules/photo/src/hdr_common.cpp @@ -102,4 +102,4 @@ Mat linearResponse(int channels) return response; } -}; +} diff --git a/modules/photo/src/hdr_common.hpp b/modules/photo/src/hdr_common.hpp index b00227f90..26fb8e419 100644 --- a/modules/photo/src/hdr_common.hpp +++ b/modules/photo/src/hdr_common.hpp @@ -57,6 +57,6 @@ void mapLuminance(Mat src, Mat dst, Mat lum, Mat new_lum, float saturation); Mat RobertsonWeights(); Mat linearResponse(int channels); -}; +} #endif diff --git a/modules/softcascade/src/cuda_invoker.hpp b/modules/softcascade/src/cuda_invoker.hpp index 00b7fe4b9..81229dfb4 100644 --- a/modules/softcascade/src/cuda_invoker.hpp +++ b/modules/softcascade/src/cuda_invoker.hpp @@ -110,7 +110,7 @@ struct Detection Detection(){} __device_inline__ Detection(int _x, int _y, uchar _w, uchar _h, float c) - : x(static_cast(_x)), y(static_cast(_y)), w(_w), h(_h), confidence(c), kind(0) {}; + : x(static_cast(_x)), y(static_cast(_y)), w(_w), h(_h), confidence(c), kind(0) {} }; struct GK107PolicyX4 diff --git a/modules/softcascade/src/integral_channel_builder.cpp b/modules/softcascade/src/integral_channel_builder.cpp index 08f155e4c..540005b76 100644 --- a/modules/softcascade/src/integral_channel_builder.cpp +++ b/modules/softcascade/src/integral_channel_builder.cpp @@ -118,7 +118,7 @@ public: using cv::softcascade::ChannelFeatureBuilder; using cv::softcascade::ChannelFeature; -CV_INIT_ALGORITHM(HOG6MagLuv, "ChannelFeatureBuilder.HOG6MagLuv", ); +CV_INIT_ALGORITHM(HOG6MagLuv, "ChannelFeatureBuilder.HOG6MagLuv", ) ChannelFeatureBuilder::~ChannelFeatureBuilder() {} diff --git a/modules/softcascade/src/octave.cpp b/modules/softcascade/src/octave.cpp index 5c5aa2eec..96b8c6192 100644 --- a/modules/softcascade/src/octave.cpp +++ b/modules/softcascade/src/octave.cpp @@ -445,7 +445,7 @@ void BoostedSoftCascadeOctave::write( CvFileStorage* fs, cv::String _name) const } -CV_INIT_ALGORITHM(BoostedSoftCascadeOctave, "Octave.BoostedSoftCascadeOctave", ); +CV_INIT_ALGORITHM(BoostedSoftCascadeOctave, "Octave.BoostedSoftCascadeOctave", ) Octave::~Octave(){} diff --git a/modules/softcascade/src/softcascade_init.cpp b/modules/softcascade/src/softcascade_init.cpp index 6f3c8b6a5..59a33f8c0 100644 --- a/modules/softcascade/src/softcascade_init.cpp +++ b/modules/softcascade/src/softcascade_init.cpp @@ -49,12 +49,12 @@ CV_INIT_ALGORITHM(Detector, "SoftCascade.Detector", obj.info()->addParam(obj, "minScale", obj.minScale); obj.info()->addParam(obj, "maxScale", obj.maxScale); obj.info()->addParam(obj, "scales", obj.scales); - obj.info()->addParam(obj, "rejCriteria", obj.rejCriteria)); + obj.info()->addParam(obj, "rejCriteria", obj.rejCriteria)) CV_INIT_ALGORITHM(SCascade, "CascadeDetector.SCascade", obj.info()->addParam(obj, "minScale", obj.minScale); obj.info()->addParam(obj, "maxScale", obj.maxScale); - obj.info()->addParam(obj, "scales", obj.scales)); + obj.info()->addParam(obj, "scales", obj.scales)) bool initModule_softcascade(void) { diff --git a/modules/stitching/doc/exposure_compensation.rst b/modules/stitching/doc/exposure_compensation.rst index eff98c01c..ec0d5db32 100644 --- a/modules/stitching/doc/exposure_compensation.rst +++ b/modules/stitching/doc/exposure_compensation.rst @@ -62,8 +62,8 @@ Stub exposure compensator which does nothing. :: { public: void feed(const std::vector &/*corners*/, const std::vector &/*images*/, - const std::vector > &/*masks*/) {}; - void apply(int /*index*/, Point /*corner*/, Mat &/*image*/, const Mat &/*mask*/) {}; + const std::vector > &/*masks*/) { } + void apply(int /*index*/, Point /*corner*/, Mat &/*image*/, const Mat &/*mask*/) { } }; .. seealso:: :ocv:class:`detail::ExposureCompensator` diff --git a/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp b/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp index f39785f57..84a8ce4fe 100644 --- a/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp @@ -68,8 +68,8 @@ class CV_EXPORTS NoExposureCompensator : public ExposureCompensator { public: void feed(const std::vector &/*corners*/, const std::vector &/*images*/, - const std::vector > &/*masks*/) {}; - void apply(int /*index*/, Point /*corner*/, Mat &/*image*/, const Mat &/*mask*/) {}; + const std::vector > &/*masks*/) { } + void apply(int /*index*/, Point /*corner*/, Mat &/*image*/, const Mat &/*mask*/) { } }; diff --git a/modules/video/test/test_accum.cpp b/modules/video/test/test_accum.cpp index ef6c05f98..6895bb4ea 100644 --- a/modules/video/test/test_accum.cpp +++ b/modules/video/test/test_accum.cpp @@ -100,7 +100,7 @@ double CV_AccumBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i class CV_AccTest : public CV_AccumBaseTest { public: - CV_AccTest() {}; + CV_AccTest() { } protected: void run_func(); void prepare_to_validation( int ); diff --git a/modules/video/test/test_ecc.cpp b/modules/video/test/test_ecc.cpp index 4065e6182..6b60a181f 100644 --- a/modules/video/test/test_ecc.cpp +++ b/modules/video/test/test_ecc.cpp @@ -107,7 +107,7 @@ protected: bool testTranslation(int); }; -CV_ECC_Test_Translation::CV_ECC_Test_Translation(){}; +CV_ECC_Test_Translation::CV_ECC_Test_Translation(){} bool CV_ECC_Test_Translation::testTranslation(int from) { @@ -256,7 +256,7 @@ protected: bool testAffine(int); }; -CV_ECC_Test_Affine::CV_ECC_Test_Affine(){}; +CV_ECC_Test_Affine::CV_ECC_Test_Affine(){} bool CV_ECC_Test_Affine::testAffine(int from) @@ -332,7 +332,7 @@ protected: bool testHomography(int); }; -CV_ECC_Test_Homography::CV_ECC_Test_Homography(){}; +CV_ECC_Test_Homography::CV_ECC_Test_Homography(){} bool CV_ECC_Test_Homography::testHomography(int from) { From d270c9e8b611e200866a624b351f14999238fa41 Mon Sep 17 00:00:00 2001 From: Matthias Bady Date: Sat, 18 Jan 2014 11:12:13 +0100 Subject: [PATCH 093/295] Type conversions to fix warnings --- modules/ocl/perf/perf_brief.cpp | 6 +++--- modules/ocl/test/test_brief.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/ocl/perf/perf_brief.cpp b/modules/ocl/perf/perf_brief.cpp index b3784a66f..de1f4f9d2 100644 --- a/modules/ocl/perf/perf_brief.cpp +++ b/modules/ocl/perf/perf_brief.cpp @@ -78,11 +78,11 @@ PERF_TEST_P( OCL_BRIEF, extract, testing::Combine( if ( RUN_OCL_IMPL ) { - Mat kpMat( 2, keypoints.size( ), CV_32FC1 ); + Mat kpMat( 2, int( keypoints.size() ), CV_32FC1 ); for ( size_t i = 0; i < keypoints.size( ); ++i ) { - kpMat.col( i ).row( 0 ) = keypoints[i].pt.x; - kpMat.col( i ).row( 1 ) = keypoints[i].pt.y; + kpMat.col( int( i ) ).row( 0 ) = keypoints[i].pt.x; + kpMat.col( int( i ) ).row( 1 ) = keypoints[i].pt.y; } BRIEF_OCL brief( bytes ); oclMat imgCL( img ), keypointsCL(kpMat), mask; diff --git a/modules/ocl/test/test_brief.cpp b/modules/ocl/test/test_brief.cpp index 81c638a3f..369e6b53b 100644 --- a/modules/ocl/test/test_brief.cpp +++ b/modules/ocl/test/test_brief.cpp @@ -79,11 +79,11 @@ OCL_TEST_P( BRIEF, Accuracy ) BriefDescriptorExtractor brief( bytes ); brief.compute( img, keypoints, descriptorsGold ); - Mat kpMat( 2, keypoints.size( ), CV_32FC1 ); + Mat kpMat( 2, int( keypoints.size() ), CV_32FC1 ); for ( size_t i = 0; i < keypoints.size( ); ++i ) { - kpMat.col( i ).row( 0 ) = keypoints[i].pt.x; - kpMat.col( i ).row( 1 ) = keypoints[i].pt.y; + kpMat.col( i ).row( 0 ) = int( keypoints[i].pt.x ); + kpMat.col( i ).row( 1 ) = int( keypoints[i].pt.y ); } oclMat imgOcl( img ), keypointsOcl( kpMat ), descriptorsOcl, maskOcl; @@ -96,7 +96,7 @@ OCL_TEST_P( BRIEF, Accuracy ) const int numDesc = cv::countNonZero( mask ); if ( numDesc != descriptors.cols ) { - size_t idx = 0; + int idx = 0; Mat tmp( numDesc, bytes, CV_8UC1 ); for ( int i = 0; i < descriptors.rows; ++i ) { From 6b8bee6e0bc4afc21c991ba4f1030b393d4d2fc2 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 18 Jan 2014 22:37:47 +0400 Subject: [PATCH 094/295] fixed kernel compilation warnings --- modules/core/src/opencl/arithm.cl | 7 ++++--- modules/imgproc/src/color.cpp | 4 ++-- modules/imgproc/src/imgwarp.cpp | 2 +- modules/imgproc/src/opencl/cvtcolor.cl | 4 ++-- modules/imgproc/src/opencl/filterSepCol.cl | 2 +- modules/imgproc/src/opencl/filterSepRow.cl | 8 ++++---- modules/imgproc/src/opencl/resize.cl | 1 - 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/core/src/opencl/arithm.cl b/modules/core/src/opencl/arithm.cl index c8fd99eef..5b7373553 100644 --- a/modules/core/src/opencl/arithm.cl +++ b/modules/core/src/opencl/arithm.cl @@ -196,12 +196,12 @@ #elif defined OP_PHASE_RADIANS #define PROCESS_ELEM \ workT tmp = atan2(srcelem2, srcelem1); \ - if(tmp < 0) tmp += 6.283185307179586232; \ + if(tmp < 0) tmp += 6.283185307179586232f; \ dstelem = tmp #elif defined OP_PHASE_DEGREES #define PROCESS_ELEM \ - workT tmp = atan2(srcelem2, srcelem1)*57.29577951308232286465; \ + workT tmp = atan2(srcelem2, srcelem1)*57.29577951308232286465f; \ if(tmp < 0) tmp += 360; \ dstelem = tmp @@ -223,7 +223,6 @@ dstelem = v > (dstT)(0) ? log(v) : log(-v) #define dstT uchar #define srcT2 srcT1 #define convertToWT1 -#define convertToWT2 #define PROCESS_ELEM dstelem = convert_uchar(srcelem1 CMP_OPERATOR srcelem2 ? 255 : 0) #elif defined OP_CONVERT_SCALE_ABS @@ -313,7 +312,9 @@ __kernel void KF(__global const uchar* srcptr1, int srcstep1, int srcoffset1, if (x < cols && y < rows) { int src1_index = mad24(y, srcstep1, x*(int)sizeof(srcT1) + srcoffset1); +#if !(defined(OP_RECIP_SCALE) || defined(OP_NOT)) int src2_index = mad24(y, srcstep2, x*(int)sizeof(srcT2) + srcoffset2); +#endif int dst_index = mad24(y, dststep, x*(int)sizeof(dstT) + dstoffset); EXTRA_INDEX; diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 70ad0827c..53859dd07 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -2996,7 +2996,7 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) } else k.create(kernelName.c_str(), ocl::imgproc::cvtcolor_oclsrc, - format("-D depth=%d -D hscale=%f -D bidx=%d -D scn=%d -D dcn=3", depth, hrange*(1.f/360.f), bidx, scn)); + format("-D depth=%d -D hscale=%ff -D bidx=%d -D scn=%d -D dcn=3", depth, hrange*(1.f/360.f), bidx, scn)); break; } case COLOR_HSV2BGR: case COLOR_HSV2RGB: case COLOR_HSV2BGR_FULL: case COLOR_HSV2RGB_FULL: @@ -3014,7 +3014,7 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) String kernelName = String(is_hsv ? "HSV" : "HLS") + "2RGB"; k.create(kernelName.c_str(), ocl::imgproc::cvtcolor_oclsrc, - format("-D depth=%d -D dcn=%d -D scn=3 -D bidx=%d -D hrange=%d -D hscale=%f", + format("-D depth=%d -D dcn=%d -D scn=3 -D bidx=%d -D hrange=%d -D hscale=%ff", depth, dcn, bidx, hrange, 6.f/hrange)); break; } diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index a69ba8a2a..e9fd60d5d 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -2004,7 +2004,7 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize, { int wdepth2 = std::max(CV_32F, depth), wtype2 = CV_MAKE_TYPE(wdepth2, cn); buildOption = buildOption + format(" -D convertToT=%s -D WT2V=%s -D convertToWT2V=%s -D INTER_AREA_FAST" - " -D XSCALE=%d -D YSCALE=%d -D SCALE=%f", + " -D XSCALE=%d -D YSCALE=%d -D SCALE=%ff", ocl::convertTypeStr(wdepth2, depth, cn, cvt[0]), ocl::typeToStr(wtype2), ocl::convertTypeStr(wdepth, wdepth2, cn, cvt[1]), iscale_x, iscale_y, 1.0f / (iscale_x * iscale_y)); diff --git a/modules/imgproc/src/opencl/cvtcolor.cl b/modules/imgproc/src/opencl/cvtcolor.cl index ad7562f3d..1779c4fa7 100644 --- a/modules/imgproc/src/opencl/cvtcolor.cl +++ b/modules/imgproc/src/opencl/cvtcolor.cl @@ -472,7 +472,7 @@ __kernel void RGB(__global const uchar* srcptr, int src_step, int src_offset, dst[0] = src[2]; dst[1] = src[1]; dst[2] = src[0]; -#elif defined ORDER +#else dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; @@ -728,7 +728,7 @@ __kernel void RGB2HSV(__global const uchar* srcptr, int src_step, int src_offset diff = v - vmin; s = diff/(float)(fabs(v) + FLT_EPSILON); - diff = (float)(60./(diff + FLT_EPSILON)); + diff = (float)(60.f/(diff + FLT_EPSILON)); if( v == r ) h = (g - b)*diff; else if( v == g ) diff --git a/modules/imgproc/src/opencl/filterSepCol.cl b/modules/imgproc/src/opencl/filterSepCol.cl index c990a6ca1..e99fa6ee0 100644 --- a/modules/imgproc/src/opencl/filterSepCol.cl +++ b/modules/imgproc/src/opencl/filterSepCol.cl @@ -71,7 +71,7 @@ __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void col_filter const int dst_step_in_pixel, const int dst_cols, const int dst_rows, - __constant float * mat_kernel __attribute__((max_constant_size(4*(2*RADIUSY+1))))) + __constant float * mat_kernel) { int x = get_global_id(0); int y = get_global_id(1); diff --git a/modules/imgproc/src/opencl/filterSepRow.cl b/modules/imgproc/src/opencl/filterSepRow.cl index f276d0840..dfbf30099 100644 --- a/modules/imgproc/src/opencl/filterSepRow.cl +++ b/modules/imgproc/src/opencl/filterSepRow.cl @@ -154,7 +154,7 @@ __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_ int dst_step_in_pixel, int dst_cols, int dst_rows, int radiusy, - __constant float * mat_kernel __attribute__((max_constant_size(4*(2*RADIUSX+1))))) + __constant float * mat_kernel) { int x = get_global_id(0)<<2; int y = get_global_id(1); @@ -298,7 +298,7 @@ __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_ int dst_step_in_pixel, int dst_cols, int dst_rows, int radiusy, - __constant float * mat_kernel __attribute__((max_constant_size(4*(2*RADIUSX+1))))) + __constant float * mat_kernel) { int x = get_global_id(0); int y = get_global_id(1); @@ -392,7 +392,7 @@ __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_ int dst_step_in_pixel, int dst_cols, int dst_rows, int radiusy, - __constant float * mat_kernel __attribute__((max_constant_size(4*(2*RADIUSX+1))))) + __constant float * mat_kernel) { int x = get_global_id(0); int y = get_global_id(1); @@ -485,7 +485,7 @@ __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_ int dst_step_in_pixel, int dst_cols, int dst_rows, int radiusy, - __constant float * mat_kernel __attribute__((max_constant_size(4*(2*RADIUSX+1))))) + __constant float * mat_kernel) { int x = get_global_id(0); int y = get_global_id(1); diff --git a/modules/imgproc/src/opencl/resize.cl b/modules/imgproc/src/opencl/resize.cl index ecab2faa5..d4f238358 100644 --- a/modules/imgproc/src/opencl/resize.cl +++ b/modules/imgproc/src/opencl/resize.cl @@ -78,7 +78,6 @@ __kernel void resizeLN(__global const uchar* srcptr, int srcstep, int srcoffset, int y_ = INC(y,srcrows); int x_ = INC(x,srccols); - __global const PIXTYPE* src = (__global const PIXTYPE*)(srcptr + mad24(y, srcstep, srcoffset + x*PIXSIZE)); #if depth <= 4 From 0fc4ac4f1f9602fcb54beaa04e42a7c1b2befcb6 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 04:07:17 +0400 Subject: [PATCH 095/295] warnings and compilation with installed Windows 8.1 SDK --- modules/highgui/src/window_w32.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 97527345a..23aa02aad 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -1363,7 +1363,9 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) break; case WM_MOUSEWHEEL: +#if defined WM_MOUSEHWHEEL case WM_MOUSEHWHEEL: +#endif if( window->on_mouse ) { int flags = (wParam & MK_LBUTTON ? CV_EVENT_FLAG_LBUTTON : 0)| From 4e20e06ee7fd7aaff8be51613daf14e6f46ede26 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 04:07:24 +0400 Subject: [PATCH 096/295] warnings --- modules/imgproc/src/clahe.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/clahe.cpp b/modules/imgproc/src/clahe.cpp index 079e635f9..82474788d 100644 --- a/modules/imgproc/src/clahe.cpp +++ b/modules/imgproc/src/clahe.cpp @@ -88,7 +88,7 @@ namespace clahe return true; } - static bool transform(const cv::InputArray _src, cv::OutputArray _dst, const cv::InputArray _lut, + static bool transform(cv::InputArray _src, cv::OutputArray _dst, cv::InputArray _lut, const int tilesX, const int tilesY, const cv::Size & tileSize) { From 6bf599b1bca8a58c7a656ddc169f7be0fc3094c6 Mon Sep 17 00:00:00 2001 From: Drew Jetter Date: Sat, 18 Jan 2014 16:39:50 -0700 Subject: [PATCH 097/295] Fixed bug #3489: The code assumed that two global variables would be constructed in a particular order, but global variable initialization order is compiler-dependent. --- modules/core/src/system.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index ee0799ce0..ef45b9b5b 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -1131,17 +1131,24 @@ public: } } }; -static TLSContainerStorage tlsContainerStorage; + +// This is a wrapper function that will ensure 'tlsContainerStorage' is constructed on first use. +// For more information: http://www.parashift.com/c++-faq/static-init-order-on-first-use.html +static TLSContainerStorage& getTLSContainerStorage() +{ + static TLSContainerStorage *tlsContainerStorage = new TLSContainerStorage(); + return *tlsContainerStorage; +} TLSDataContainer::TLSDataContainer() : key_(-1) { - key_ = tlsContainerStorage.allocateKey(this); + key_ = getTLSContainerStorage().allocateKey(this); } TLSDataContainer::~TLSDataContainer() { - tlsContainerStorage.releaseKey(key_, this); + getTLSContainerStorage().releaseKey(key_, this); key_ = -1; } @@ -1166,7 +1173,7 @@ TLSStorage::~TLSStorage() void*& data = tlsData_[i]; if (data) { - tlsContainerStorage.destroyData(i, data); + getTLSContainerStorage().destroyData(i, data); data = NULL; } } From 5af2e6f1c9cbd35090faff359616326c2952f25a Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 18 Jan 2014 14:27:30 +0400 Subject: [PATCH 098/295] removed useless CRC calculation --- modules/core/src/ocl.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index cf3b1dcab..eb11aaf1a 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3525,7 +3525,7 @@ public: // we can do it in 2 cases: // 1. we overwrite the whole content // 2. we overwrite part of the matrix, but the GPU copy is out-of-date - if( u->data && (u->hostCopyObsolete() <= u->deviceCopyObsolete() || total == u->size)) + if( u->data && (u->hostCopyObsolete() < u->deviceCopyObsolete() || total == u->size)) { Mat::getStdAllocator()->upload(u, srcptr, dims, sz, dstofs, dststep, srcstep); u->markHostCopyObsolete(false); @@ -3538,9 +3538,6 @@ public: if( iscontinuous ) { - int crc = 0; - for( size_t i = 0; i < total; i++ ) - crc ^= ((uchar*)srcptr)[i]; CV_Assert( clEnqueueWriteBuffer(q, (cl_mem)u->handle, CL_TRUE, dstrawofs, total, srcptr, 0, 0, 0) >= 0 ); } @@ -3576,12 +3573,12 @@ public: UMatDataAutoLock src_autolock(src); UMatDataAutoLock dst_autolock(dst); - if( !src->handle || (src->data && src->hostCopyObsolete() <= src->deviceCopyObsolete()) ) + if( !src->handle || (src->data && src->hostCopyObsolete() < src->deviceCopyObsolete()) ) { upload(dst, src->data + srcrawofs, dims, sz, dstofs, dststep, srcstep); return; } - if( !dst->handle || (dst->data && dst->hostCopyObsolete() <= dst->deviceCopyObsolete()) ) + if( !dst->handle || (dst->data && dst->hostCopyObsolete() < dst->deviceCopyObsolete()) ) { download(src, dst->data + dstrawofs, dims, sz, srcofs, srcstep, dststep); dst->markHostCopyObsolete(false); From 3db33979e1a5f29a71fc42f5a3902eedc55f94e6 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 18 Jan 2014 23:41:49 +0400 Subject: [PATCH 099/295] added perf tests for stitching warpers --- .../stitching/perf/opencl/perf_warpers.cpp | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 modules/stitching/perf/opencl/perf_warpers.cpp diff --git a/modules/stitching/perf/opencl/perf_warpers.cpp b/modules/stitching/perf/opencl/perf_warpers.cpp new file mode 100644 index 000000000..4cb014126 --- /dev/null +++ b/modules/stitching/perf/opencl/perf_warpers.cpp @@ -0,0 +1,145 @@ +/*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-2013, Advanced Micro Devices, Inc., 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 OpenCV Foundation 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 "test_precomp.hpp" +#include "opencv2/stitching/warpers.hpp" +#include "opencv2/ts/ocl_perf.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +///////////////////////// Stitching Warpers /////////////////////////// + +enum +{ + SphericalWarperType = 0, + CylindricalWarperType = 1, + PlaneWarperType = 2 +}; + +class WarperBase +{ +public: + explicit WarperBase(int type) + { + Ptr creator; + if (cv::ocl::useOpenCL()) + { + if (type == SphericalWarperType) + creator = makePtr(); + else if (type == CylindricalWarperType) + creator = makePtr(); + else if (type == PlaneWarperType) + creator = makePtr(); + } + else + { + if (type == SphericalWarperType) + creator = makePtr(); + else if (type == CylindricalWarperType) + creator = makePtr(); + else if (type == PlaneWarperType) + creator = makePtr(); + } + CV_Assert(!creator.empty()); + + warper = creator->create(2.0); + + K = Mat::eye(3, 3, CV_32FC1); + R = Mat::eye(3, 3, CV_32FC1); + } + + Rect buildMaps(Size src_size, OutputArray xmap, OutputArray ymap) const + { + return warper->buildMaps(src_size, K, R, xmap, ymap); + } + + Point warp(InputArray src, int interp_mode, int border_mode, OutputArray dst) const + { + return warper->warp(src, K, R, interp_mode, border_mode, dst); + } + +private: + Ptr warper; + Mat K, R; +}; + +CV_ENUM(WarperType, SphericalWarperType, CylindricalWarperType, PlaneWarperType) + +typedef tuple StitchingWarpersParams; +typedef TestBaseWithParam StitchingWarpersFixture; + +OCL_PERF_TEST_P(StitchingWarpersFixture, StitchingWarpers_BuildMaps, + ::testing::Combine(OCL_TEST_SIZES, WarperType::all())) +{ + const StitchingWarpersParams params = GetParam(); + const Size srcSize = get<0>(params); + const WarperBase warper(get<1>(params)); + + UMat src(srcSize, CV_32FC1), xmap(srcSize, CV_32FC1), ymap(srcSize, CV_32FC1); + declare.in(src, WARMUP_RNG).out(xmap, ymap); + + OCL_TEST_CYCLE() warper.buildMaps(srcSize, xmap, ymap); + + SANITY_CHECK(xmap, 1e-3); + SANITY_CHECK(ymap, 1e-3); +} + +OCL_PERF_TEST_P(StitchingWarpersFixture, StitchingWarpers_Warp, + ::testing::Combine(OCL_TEST_SIZES, WarperType::all())) +{ + const StitchingWarpersParams params = GetParam(); + const Size srcSize = get<0>(params); + const WarperBase warper(get<1>(params)); + + UMat src(srcSize, CV_32FC1), dst(srcSize, CV_32FC1); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() warper.warp(src, INTER_LINEAR, BORDER_REPLICATE, dst); + + SANITY_CHECK(dst, 1e-5); +} + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL From 5ea3ecdc3b62f43d79bfbb706b77370a5efdff21 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 18:32:22 +0400 Subject: [PATCH 100/295] horisontal mwhell support --- modules/highgui/src/window_w32.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 23aa02aad..0c397fd14 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -90,6 +90,10 @@ static const char* trackbar_text = #endif +#ifndef WM_MOUSEHWHEEL + #define WM_MOUSEHWHEEL 0x020E +#endif + static void FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int origin ) { assert( bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32)); @@ -1363,9 +1367,7 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) break; case WM_MOUSEWHEEL: -#if defined WM_MOUSEHWHEEL case WM_MOUSEHWHEEL: -#endif if( window->on_mouse ) { int flags = (wParam & MK_LBUTTON ? CV_EVENT_FLAG_LBUTTON : 0)| From 2cbfb0414464053a20c9f2a6b2a93792a9a55b3c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 28 Nov 2013 12:45:22 +0400 Subject: [PATCH 101/295] viz: rich set of named colors --- modules/viz/include/opencv2/viz/types.hpp | 67 +++++++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 682006f95..780f200ed 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -77,6 +77,34 @@ namespace cv static Color white(); static Color gray(); + + static Color mlab(); + + static Color navy(); + static Color olive(); + static Color maroon(); + static Color teal(); + static Color rose(); + static Color azure(); + static Color lime(); + static Color gold(); + static Color brown(); + static Color orange(); + static Color chartreuse(); + static Color orange_red(); + static Color purple(); + static Color indigo(); + + static Color pink(); + static Color cherry(); + static Color bluberry(); + static Color raspberry(); + static Color silver(); + static Color violet(); + static Color apricot(); + static Color turquoise(); + static Color celestial_blue(); + static Color amethyst(); }; class CV_EXPORTS Mesh3d @@ -180,15 +208,46 @@ inline cv::viz::Color::Color(double _gray) : Scalar(_gray, _gray, _gray) {} inline cv::viz::Color::Color(double _blue, double _green, double _red) : Scalar(_blue, _green, _red) {} inline cv::viz::Color::Color(const Scalar& color) : Scalar(color) {} -inline cv::viz::Color cv::viz::Color::black() { return Color( 0, 0, 0); } -inline cv::viz::Color cv::viz::Color::green() { return Color( 0, 255, 0); } -inline cv::viz::Color cv::viz::Color::blue() { return Color(255, 0, 0); } -inline cv::viz::Color cv::viz::Color::cyan() { return Color(255, 255, 0); } +inline cv::viz::Color cv::viz::Color::black() { return Color( 0, 0, 0); } +inline cv::viz::Color cv::viz::Color::green() { return Color( 0, 255, 0); } +inline cv::viz::Color cv::viz::Color::blue() { return Color(255, 0, 0); } +inline cv::viz::Color cv::viz::Color::cyan() { return Color(255, 255, 0); } inline cv::viz::Color cv::viz::Color::red() { return Color( 0, 0, 255); } inline cv::viz::Color cv::viz::Color::yellow() { return Color( 0, 255, 255); } inline cv::viz::Color cv::viz::Color::magenta() { return Color(255, 0, 255); } inline cv::viz::Color cv::viz::Color::white() { return Color(255, 255, 255); } inline cv::viz::Color cv::viz::Color::gray() { return Color(128, 128, 128); } +inline cv::viz::Color cv::viz::Color::mlab() { return Color(235, 118, 118); } + +inline cv::viz::Color cv::viz::Color::navy() { return Color(0, 0, 128); } +inline cv::viz::Color cv::viz::Color::olive() { return Color(0, 128, 128); } +inline cv::viz::Color cv::viz::Color::maroon() { return Color(0, 0, 128); } +inline cv::viz::Color cv::viz::Color::teal() { return Color(128, 128, 0); } +inline cv::viz::Color cv::viz::Color::rose() { return Color(127, 0, 255); } +inline cv::viz::Color cv::viz::Color::azure() { return Color(255, 127, 0); } +inline cv::viz::Color cv::viz::Color::lime() { return Color(0, 255, 191); } +inline cv::viz::Color cv::viz::Color::gold() { return Color(0, 215, 255); } +inline cv::viz::Color cv::viz::Color::brown() { return Color(0, 75, 150); } +inline cv::viz::Color cv::viz::Color::orange() { return Color(0, 165, 255); } +inline cv::viz::Color cv::viz::Color::chartreuse() { return Color(0, 255, 127); } +inline cv::viz::Color cv::viz::Color::orange_red() { return Color(0, 69, 255); } +inline cv::viz::Color cv::viz::Color::purple() { return Color(128, 0, 128); } +inline cv::viz::Color cv::viz::Color::indigo() { return Color(130, 0, 75); } + +inline cv::viz::Color cv::viz::Color::pink() { return Color(203, 192, 255); } +inline cv::viz::Color cv::viz::Color::cherry() { return Color( 99, 29, 222); } +inline cv::viz::Color cv::viz::Color::bluberry() { return Color(247, 134, 79); } +inline cv::viz::Color cv::viz::Color::raspberry() { return Color( 92, 11, 227); } +inline cv::viz::Color cv::viz::Color::silver() { return Color(192, 192, 192); } +inline cv::viz::Color cv::viz::Color::violet() { return Color(226, 43, 138); } +inline cv::viz::Color cv::viz::Color::apricot() { return Color(177, 206, 251); } +inline cv::viz::Color cv::viz::Color::turquoise() { return Color(208, 224, 64); } +inline cv::viz::Color cv::viz::Color::celestial_blue() { return Color(208, 151, 73); } +inline cv::viz::Color cv::viz::Color::amethyst() { return Color(204, 102, 153); } + + + + #endif From 15fd3faa40bc5bc21283cab4414c67a452f03e1d Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 30 Nov 2013 19:00:10 +0400 Subject: [PATCH 102/295] support gray color clouds --- modules/viz/src/cloud_widgets.cpp | 9 ++- modules/viz/src/viz3d_impl.hpp | 108 ++++++++++++++---------------- 2 files changed, 56 insertions(+), 61 deletions(-) diff --git a/modules/viz/src/cloud_widgets.cpp b/modules/viz/src/cloud_widgets.cpp index 73cc26201..ab4d0c3d8 100644 --- a/modules/viz/src/cloud_widgets.cpp +++ b/modules/viz/src/cloud_widgets.cpp @@ -151,7 +151,7 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); - CV_Assert(colors.type() == CV_8UC3 && cloud.size() == colors.size()); + CV_Assert(colors.depth() == CV_8U && cloud.size() == colors.size()); if (cloud.isContinuous() && colors.isContinuous()) { @@ -388,7 +388,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); - CV_Assert(colors.type() == CV_8UC3 && cloud.size() == colors.size()); + CV_Assert(colors.depth() == CV_8U && cloud.size() == colors.size()); if (cloud.isContinuous() && colors.isContinuous()) { @@ -651,7 +651,7 @@ struct cv::viz::WMesh::CopyImpl cv::viz::WMesh::WMesh(const Mesh3d &mesh) { CV_Assert(mesh.cloud.rows == 1 && (mesh.cloud.type() == CV_32FC3 || mesh.cloud.type() == CV_64FC3 || mesh.cloud.type() == CV_32FC4 || mesh.cloud.type() == CV_64FC4)); - CV_Assert(mesh.colors.empty() || (mesh.colors.type() == CV_8UC3 && mesh.cloud.size() == mesh.colors.size())); + CV_Assert(mesh.colors.empty() || (mesh.colors.depth() == CV_8U && mesh.cloud.size() == mesh.colors.size())); CV_Assert(!mesh.polygons.empty() && mesh.polygons.type() == CV_32SC1); vtkSmartPointer points = vtkSmartPointer::New(); @@ -680,8 +680,7 @@ cv::viz::WMesh::WMesh(const Mesh3d &mesh) if (!mesh.colors.empty()) { - Vec3b * colors_data = 0; - colors_data = new Vec3b[nr_points]; + Vec3b *colors_data = new Vec3b[nr_points]; NanFilter::copyColor(mesh.colors, colors_data, mesh.cloud); scalars = vtkSmartPointer::New(); diff --git a/modules/viz/src/viz3d_impl.hpp b/modules/viz/src/viz3d_impl.hpp index 59f45a8fa..a7ef9c437 100644 --- a/modules/viz/src/viz3d_impl.hpp +++ b/modules/viz/src/viz3d_impl.hpp @@ -191,14 +191,29 @@ namespace cv vtkSmartPointer convertToVtkMatrix(const cv::Matx44f &m); cv::Matx44f convertToMatx(const vtkSmartPointer& vtk_matrix); + struct color_tag {}; + struct gray_tag {}; + + static Vec3b fetchRgb(const unsigned char* color, color_tag) { return Vec3b(color[2], color[1], color[0]); } + static Vec3b fetchRgb(const unsigned char* color, gray_tag) { return Vec3b(color[0], color[0], color[0]); } + + inline Vec3d vtkpoint(const Point3f& point) { return Vec3d(point.x, point.y, point.z); } + template inline _Tp normalized(const _Tp& v) { return v * 1/cv::norm(v); } + + inline Color vtkcolor(const Color& color) + { + Color scaled_color = color * (1.0/255.0); + std::swap(scaled_color[0], scaled_color[2]); + return scaled_color; + } + struct NanFilter { - template + template struct Impl { - typedef Vec<_Tp, 3> _Out; - - static _Out* copy(const Mat& source, _Out* output, const Mat& nan_mask) + template + static Vec<_Tp, 3>* copy(const Mat& source, Vec<_Tp, 3>* output, const Mat& nan_mask) { CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); @@ -214,14 +229,15 @@ namespace cv for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) - *output++ = _Out(srow); + *output++ = Vec<_Tp, 3>(srow); } return output; } - static _Out* copyColor(const Mat& source, _Out* output, const Mat& nan_mask) + template + static Vec3b* copyColor(const Mat& source, Vec3b* output, const Mat& nan_mask) { - CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); + CV_Assert(source.size() == nan_mask.size()); CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); CV_DbgAssert(DataDepth<_Msk>::value == nan_mask.depth()); @@ -230,16 +246,12 @@ namespace cv for (int y = 0; y < source.rows; ++y) { - const _Tp* srow = source.ptr<_Tp>(y); + const unsigned char* srow = source.ptr(y); const _Msk* mrow = nan_mask.ptr<_Msk>(y); for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) - { - *output = _Out(srow); - std::swap((*output)[0], (*output)[2]); // BGR -> RGB - ++output; - } + *output++ = fetchRgb(srow, _Tag()); } return output; } @@ -251,20 +263,23 @@ namespace cv CV_Assert(nan_mask.depth() == CV_32F || nan_mask.depth() == CV_64F); typedef Vec<_Tp, 3>* (*copy_func)(const Mat&, Vec<_Tp, 3>*, const Mat&); - const static copy_func table[2] = { &NanFilter::Impl<_Tp, float>::copy, &NanFilter::Impl<_Tp, double>::copy }; + const static copy_func table[2] = { &NanFilter::Impl::copy<_Tp>, &NanFilter::Impl::copy<_Tp> }; return table[nan_mask.depth() - 5](source, output, nan_mask); } - template - static inline Vec<_Tp, 3>* copyColor(const Mat& source, Vec<_Tp, 3>* output, const Mat& nan_mask) + static inline Vec3b* copyColor(const Mat& source, Vec3b* output, const Mat& nan_mask) { CV_Assert(nan_mask.depth() == CV_32F || nan_mask.depth() == CV_64F); - typedef Vec<_Tp, 3>* (*copy_func)(const Mat&, Vec<_Tp, 3>*, const Mat&); - const static copy_func table[2] = { &NanFilter::Impl<_Tp, float>::copyColor, &NanFilter::Impl<_Tp, double>::copyColor }; + typedef Vec3b* (*copy_func)(const Mat&, Vec3b*, const Mat&); + const static copy_func table[2][2] = + { + { &NanFilter::Impl::copyColor, &NanFilter::Impl ::copyColor }, + { &NanFilter::Impl::copyColor, &NanFilter::Impl::copyColor } + }; - return table[nan_mask.depth() - 5](source, output, nan_mask); + return table[nan_mask.depth() - 5][source.channels() == 1 ? 0 : 1](source, output, nan_mask); } }; @@ -292,47 +307,31 @@ namespace cv }; - inline Color vtkcolor(const Color& color) - { - Color scaled_color = color * (1.0/255.0); - std::swap(scaled_color[0], scaled_color[2]); - return scaled_color; - } - - inline Vec3d vtkpoint(const Point3f& point) { return Vec3d(point.x, point.y, point.z); } - template inline _Tp normalized(const _Tp& v) { return v * 1/cv::norm(v); } struct ConvertToVtkImage { struct Impl { - static void copyImageMultiChannel(const Mat &image, vtkSmartPointer output) - { - int i_chs = image.channels(); + typedef unsigned char uchar; - for (int i = 0; i < image.rows; ++i) + static void copyImage(const Mat &source, vtkSmartPointer output, color_tag tag) + { + for (int y = 0; y < source.rows; ++y) { - const unsigned char * irows = image.ptr(i); - for (int j = 0; j < image.cols; ++j, irows += i_chs) - { - unsigned char * vrows = static_cast(output->GetScalarPointer(j,i,0)); - memcpy(vrows, irows, i_chs); - std::swap(vrows[0], vrows[2]); // BGR -> RGB - } + const uchar *srow = source.ptr(y); + for (int x = 0; x < source.cols; ++x, srow += source.channels()) + *reinterpret_cast(output->GetScalarPointer(x,y,0)) = fetchRgb(srow, tag); } output->Modified(); } - static void copyImageSingleChannel(const Mat &image, vtkSmartPointer output) + static void copyImage(const Mat &source, vtkSmartPointer output, gray_tag) { - for (int i = 0; i < image.rows; ++i) + for (int y = 0; y < source.rows; ++y) { - const unsigned char * irows = image.ptr(i); - for (int j = 0; j < image.cols; ++j, ++irows) - { - unsigned char * vrows = static_cast(output->GetScalarPointer(j,i,0)); - *vrows = *irows; - } + const uchar *srow = source.ptr(y); + for (int x = 0; x < source.cols; ++x) + *reinterpret_cast(output->GetScalarPointer(x,y,0)) = *srow++; } output->Modified(); } @@ -349,16 +348,13 @@ namespace cv #else output->AllocateScalars(VTK_UNSIGNED_CHAR, image.channels()); #endif - - int i_chs = image.channels(); - if (i_chs > 1) + switch(image.channels()) { - // Multi channel images are handled differently because of BGR <-> RGB - Impl::copyImageMultiChannel(image, output); - } - else - { - Impl::copyImageSingleChannel(image, output); + case 1: Impl::copyImage(image, output, gray_tag()); break; + case 3: + case 4: Impl::copyImage(image, output, color_tag()); break; + default: + CV_Assert(!"Unsupported channel number"); } } }; From 2d63f60d435d7a7db0b79479b68c8051216ab8f6 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 30 Nov 2013 17:57:53 +0400 Subject: [PATCH 103/295] minor changes, opencv cross-branch code --- modules/viz/include/opencv2/viz/viz3d.hpp | 1 + modules/viz/include/opencv2/viz/widgets.hpp | 2 +- modules/viz/src/cloud_widgets.cpp | 12 +++--- modules/viz/src/interactor_style.cpp | 47 +++++---------------- 4 files changed, 19 insertions(+), 43 deletions(-) diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index f19709eb5..f57205919 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -64,6 +64,7 @@ namespace cv class CV_EXPORTS Viz3d { public: + typedef cv::viz::Color Color; typedef void (*KeyboardCallback)(const KeyboardEvent&, void*); typedef void (*MouseCallback)(const MouseEvent&, void*); diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 07b335899..f333c1d0b 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -219,7 +219,7 @@ namespace cv class CV_EXPORTS WText : public Widget2D { public: - WText(const String &text, const Point2i &pos, int font_size = 10, const Color &color = Color::white()); + WText(const String &text, const Point2i &pos, int font_size = 20, const Color &color = Color::white()); void setText(const String &text); String getText() const; diff --git a/modules/viz/src/cloud_widgets.cpp b/modules/viz/src/cloud_widgets.cpp index ab4d0c3d8..0f36ef976 100644 --- a/modules/viz/src/cloud_widgets.cpp +++ b/modules/viz/src/cloud_widgets.cpp @@ -124,7 +124,7 @@ struct cv::viz::WCloud::CreateCloudWidget cells->SetNumberOfTuples(nr_points); vtkIdType *cell = cells->GetPointer(0); // Fill it with 1s - std::fill_n(cell, nr_points * 2, 1); + std::fill(cell, cell + nr_points * 2, 1); cell++; for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) *cell = i; @@ -155,8 +155,8 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) if (cloud.isContinuous() && colors.isContinuous()) { - cloud.reshape(cloud.channels(), 1); - colors.reshape(colors.channels(), 1); + cloud = cloud.reshape(cloud.channels(), 1); + colors = colors.reshape(colors.channels(), 1); } vtkIdType nr_points; @@ -307,7 +307,7 @@ struct cv::viz::WCloudCollection::CreateCloudWidget cells->SetNumberOfTuples(nr_points); vtkIdType *cell = cells->GetPointer(0); // Fill it with 1s - std::fill_n(cell, nr_points * 2, 1); + std::fill(cell, cell + nr_points * 2, 1); cell++; for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) *cell = i; @@ -392,8 +392,8 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, if (cloud.isContinuous() && colors.isContinuous()) { - cloud.reshape(cloud.channels(), 1); - colors.reshape(colors.channels(), 1); + cloud = cloud.reshape(cloud.channels(), 1); + colors = colors.reshape(colors.channels(), 1); } vtkIdType nr_points; diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index ccf188ded..78f2ac680 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -236,7 +236,7 @@ cv::viz::InteractorStyle::OnKeyDown() "\n" " j, J : take a .PNG snapshot of the current window view\n" " c, C : display current camera/window parameters\n" - " f, F : fly to point mode\n" + " f, F : fly to point mode, hold the key and move mouse where to fly\n" "\n" " e, E : exit the interactor\n" " q, Q : stop and call VTK's TerminateApp\n" @@ -271,28 +271,8 @@ cv::viz::InteractorStyle::OnKeyDown() { unsigned int t = static_cast(time(0)); String png_file = cv::format("screenshot-%d.png", t); - String cam_file = cv::format("screenshot-%d.cam", t); - - vtkSmartPointer cam = Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetActiveCamera(); - Vec2d clip; - Vec3d focal, pos, view; - cam->GetClippingRange(clip.val); - cam->GetFocalPoint(focal.val); - cam->GetPosition(pos.val); - cam->GetViewUp(view.val); - Vec2i win_pos(Interactor->GetRenderWindow()->GetPosition()); - Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); - double angle = cam->GetViewAngle() / 180.0 * CV_PI; - - String data = cv::format("%f,%f/%f,%f,%f/%f,%f,%f/%f,%f,%f/%f/%d,%d/%d,%d", clip[0],clip[1], focal[0],focal[1],focal[2], - pos[0],pos[1],pos[2], view[0],view[1], view[2], angle , win_size[0],win_size[1], win_pos[0], win_pos[1]); - saveScreenshot(png_file); - ofstream ofs_cam(cam_file.c_str()); - ofs_cam << data.c_str() << endl; - ofs_cam.close(); - - cout << "Screenshot (" << png_file.c_str() << ") and camera information (" << cam_file.c_str() << ") successfully captured." << endl; + cout << "Screenshot (" << png_file.c_str() << ") successfully captured." << endl; break; } // display current camera settings/parameters @@ -301,26 +281,21 @@ cv::viz::InteractorStyle::OnKeyDown() vtkSmartPointer cam = Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetActiveCamera(); Vec2d clip; - Vec3d focal, pose, view; + Vec3d focal, pos, view; cam->GetClippingRange(clip.val); cam->GetFocalPoint(focal.val); - cam->GetPosition(pose.val); + cam->GetPosition(pos.val); cam->GetViewUp(view.val); Vec2i win_pos(Interactor->GetRenderWindow()->GetPosition()); Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); + double angle = cam->GetViewAngle () / 180.0 * CV_PI; + + String data = cv::format("clip(%f,%f) focal(%f,%f,%f) pos(%f,%f,%f) view(%f,%f,%f) angle(%f) winsz(%d,%d) winpos(%d,%d)", + clip[0], clip[1], focal[0], focal[1], focal[2], pos[0], pos[1], pos[2], view[0], view[1], view[2], + angle, win_size[0], win_size[1], win_pos[0], win_pos[1]); + + std::cout << data.c_str() << std::endl; - cv::print(Mat(clip, false).reshape(1, 1)); - std::cout << "/"; - cv::print(Mat(focal, false).reshape(1, 1)); - std::cout << "/"; - cv::print(Mat(pose, false).reshape(1, 1)); - std::cout << "/"; - cv::print(Mat(view, false).reshape(1, 1)); - std::cout << "/" << cam->GetViewAngle () / 180.0 * CV_PI; - cv::print(Mat(win_size, false).reshape(1, 1)); - std::cout << "/"; - cv::print(Mat(win_pos, false).reshape(1, 1)); - std::cout << std::endl; break; } case '=': From 44c1d4dfdc8fc14093966d08d48cbf3666b41680 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 1 Dec 2013 14:58:29 +0400 Subject: [PATCH 104/295] allow fast switch between actors (except mesh, cloud, cloud collection) --- modules/viz/src/cloud_widgets.cpp | 2 +- modules/viz/src/precomp.hpp | 4 ++++ modules/viz/src/shape_widgets.cpp | 20 ++++++++++---------- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/modules/viz/src/cloud_widgets.cpp b/modules/viz/src/cloud_widgets.cpp index 0f36ef976..894051e39 100644 --- a/modules/viz/src/cloud_widgets.cpp +++ b/modules/viz/src/cloud_widgets.cpp @@ -604,7 +604,7 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in mapper->SetColorModeToMapScalars(); mapper->SetScalarModeToUsePointData(); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); setColor(color); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index ab673b389..1beb43587 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -101,6 +101,7 @@ #include #include #include +#include #include #include #include @@ -120,6 +121,9 @@ namespace cv { namespace viz { + typedef vtkLODActor vizActor; + //typedef vtkActor vizActor; + typedef std::map > WidgetActorMap; typedef std::map VizMap; diff --git a/modules/viz/src/shape_widgets.cpp b/modules/viz/src/shape_widgets.cpp index 6e4f4c70f..aff3609c9 100644 --- a/modules/viz/src/shape_widgets.cpp +++ b/modules/viz/src/shape_widgets.cpp @@ -68,7 +68,7 @@ cv::viz::WLine::WLine(const Point3f &pt1, const Point3f &pt2, const Color &color vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(line->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -117,7 +117,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(SetSizeImpl::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -138,7 +138,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, float size, const vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(SetSizeImpl::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -167,7 +167,7 @@ cv::viz::WSphere::WSphere(const Point3f ¢er, float radius, int sphere_resolu vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(sphere->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -240,7 +240,7 @@ cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(transformPD->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -276,7 +276,7 @@ cv::viz::WCircle::WCircle(const Point3f& pt, float radius, float thickness, cons vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(tf->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -307,7 +307,7 @@ cv::viz::WCylinder::WCylinder(const Point3f& pt_on_axis, const Point3f& axis_dir vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(tuber->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -339,7 +339,7 @@ cv::viz::WCube::WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_fr mapper->SetInputConnection(cube->GetOutputPort()); } - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -391,7 +391,7 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(float scale) mapper->SetScalarModeToUsePointData(); mapper->SetInputConnection(axes_tubes->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -1068,7 +1068,7 @@ cv::viz::WCameraPosition::WCameraPosition(float scale) mapper->SetScalarModeToUsePointData(); mapper->SetInputConnection(axes_tubes->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); From f6e9b81188c634de6254136987d36c14e6fa4540 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 1 Dec 2013 15:25:44 +0400 Subject: [PATCH 105/295] reduced exported interface names (to make IntelliSense hints less littered) --- modules/viz/include/opencv2/viz/widgets.hpp | 29 -- modules/viz/src/cloud_widgets.cpp | 550 ++++++++++---------- modules/viz/src/shape_widgets.cpp | 309 +++++------ modules/viz/src/widget.cpp | 31 +- 4 files changed, 447 insertions(+), 472 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index f333c1d0b..42e0f1968 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -119,8 +119,6 @@ namespace cv Affine3f getPose() const; void setColor(const Color &color); - private: - struct MatrixConverter; }; @@ -145,8 +143,6 @@ namespace cv public: WPlane(const Vec4f& coefs, float size = 1.f, const Color &color = Color::white()); WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.f, const Color &color = Color::white()); - private: - struct SetSizeImpl; }; class CV_EXPORTS WSphere : public Widget3D @@ -189,9 +185,6 @@ namespace cv { public: WPolyLine(InputArray points, const Color &color = Color::white()); - - private: - struct CopyImpl; }; class CV_EXPORTS WGrid : public Widget3D @@ -201,10 +194,6 @@ namespace cv WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); //! Creates grid based on the plane equation WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); - - private: - struct GridImpl; - }; class CV_EXPORTS WText3D : public Widget3D @@ -257,9 +246,6 @@ namespace cv WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); - - private: - struct ProjectImage; }; class CV_EXPORTS WTrajectory : public Widget3D @@ -273,9 +259,6 @@ namespace cv WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums WTrajectory(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); - - private: - struct ApplyPath; }; class CV_EXPORTS WSpheresTrajectory: public Widget3D @@ -292,9 +275,6 @@ namespace cv WCloud(InputArray cloud, InputArray colors); //! All points in cloud have the same color WCloud(InputArray cloud, const Color &color = Color::white()); - - private: - struct CreateCloudWidget; }; class CV_EXPORTS WCloudCollection : public Widget3D @@ -306,27 +286,18 @@ namespace cv void addCloud(InputArray cloud, InputArray colors, const Affine3f &pose = Affine3f::Identity()); //! All points in cloud have the same color void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3f &pose = Affine3f::Identity()); - - private: - struct CreateCloudWidget; }; class CV_EXPORTS WCloudNormals : public Widget3D { public: WCloudNormals(InputArray cloud, InputArray normals, int level = 100, float scale = 0.02f, const Color &color = Color::white()); - - private: - struct ApplyCloudNormals; }; class CV_EXPORTS WMesh : public Widget3D { public: WMesh(const Mesh3d &mesh); - - private: - struct CopyImpl; }; template<> CV_EXPORTS Widget2D Widget::cast(); diff --git a/modules/viz/src/cloud_widgets.cpp b/modules/viz/src/cloud_widgets.cpp index 894051e39..27a0285fc 100644 --- a/modules/viz/src/cloud_widgets.cpp +++ b/modules/viz/src/cloud_widgets.cpp @@ -59,92 +59,96 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// /// Point Cloud Widget implementation -struct cv::viz::WCloud::CreateCloudWidget +namespace cv { namespace viz { namespace { - static inline vtkSmartPointer create(const Mat &cloud, vtkIdType &nr_points) + struct CloudUtils { - vtkSmartPointer polydata = vtkSmartPointer::New(); - vtkSmartPointer vertices = vtkSmartPointer::New(); - - polydata->SetVerts(vertices); - - vtkSmartPointer points = polydata->GetPoints(); - vtkSmartPointer initcells; - nr_points = cloud.total(); - - if (!points) + static inline vtkSmartPointer create(const Mat &cloud, vtkIdType &nr_points) { - points = vtkSmartPointer::New(); - if (cloud.depth() == CV_32F) - points->SetDataTypeToFloat(); - else if (cloud.depth() == CV_64F) - points->SetDataTypeToDouble(); - polydata->SetPoints(points); - } - points->SetNumberOfPoints(nr_points); + vtkSmartPointer polydata = vtkSmartPointer::New(); + vtkSmartPointer vertices = vtkSmartPointer::New(); - if (cloud.depth() == CV_32F) - { - // Get a pointer to the beginning of the data array - Vec3f *data_beg = vtkpoints_data(points); - Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - else if (cloud.depth() == CV_64F) - { - // Get a pointer to the beginning of the data array - Vec3d *data_beg = vtkpoints_data(points); - Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - points->SetNumberOfPoints(nr_points); + polydata->SetVerts(vertices); - // Update cells - vtkSmartPointer cells = vertices->GetData(); - // If no init cells and cells has not been initialized... - if (!cells) - cells = vtkSmartPointer::New(); + vtkSmartPointer points = polydata->GetPoints(); + vtkSmartPointer initcells; + nr_points = cloud.total(); - // If we have less values then we need to recreate the array - if (cells->GetNumberOfTuples() < nr_points) - { - cells = vtkSmartPointer::New(); - - // If init cells is given, and there's enough data in it, use it - if (initcells && initcells->GetNumberOfTuples() >= nr_points) + if (!points) { - cells->DeepCopy(initcells); - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); + points = vtkSmartPointer::New(); + if (cloud.depth() == CV_32F) + points->SetDataTypeToFloat(); + else if (cloud.depth() == CV_64F) + points->SetDataTypeToDouble(); + polydata->SetPoints(points); + } + points->SetNumberOfPoints(nr_points); + + if (cloud.depth() == CV_32F) + { + // Get a pointer to the beginning of the data array + Vec3f *data_beg = vtkpoints_data(points); + Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); + nr_points = data_end - data_beg; + } + else if (cloud.depth() == CV_64F) + { + // Get a pointer to the beginning of the data array + Vec3d *data_beg = vtkpoints_data(points); + Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); + nr_points = data_end - data_beg; + } + points->SetNumberOfPoints(nr_points); + + // Update cells + vtkSmartPointer cells = vertices->GetData(); + // If no init cells and cells has not been initialized... + if (!cells) + cells = vtkSmartPointer::New(); + + // If we have less values then we need to recreate the array + if (cells->GetNumberOfTuples() < nr_points) + { + cells = vtkSmartPointer::New(); + + // If init cells is given, and there's enough data in it, use it + if (initcells && initcells->GetNumberOfTuples() >= nr_points) + { + cells->DeepCopy(initcells); + cells->SetNumberOfComponents(2); + cells->SetNumberOfTuples(nr_points); + } + else + { + // If the number of tuples is still too small, we need to recreate the array + cells->SetNumberOfComponents(2); + cells->SetNumberOfTuples(nr_points); + vtkIdType *cell = cells->GetPointer(0); + // Fill it with 1s + std::fill(cell, cell + nr_points * 2, 1); + cell++; + for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) + *cell = i; + // Save the results in initcells + initcells = vtkSmartPointer::New(); + initcells->DeepCopy(cells); + } } else { - // If the number of tuples is still too small, we need to recreate the array + // The assumption here is that the current set of cells has more data than needed cells->SetNumberOfComponents(2); cells->SetNumberOfTuples(nr_points); - vtkIdType *cell = cells->GetPointer(0); - // Fill it with 1s - std::fill(cell, cell + nr_points * 2, 1); - cell++; - for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) - *cell = i; - // Save the results in initcells - initcells = vtkSmartPointer::New(); - initcells->DeepCopy(cells); } - } - else - { - // The assumption here is that the current set of cells has more data than needed - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - } - // Set the cells and the vertices - vertices->SetCells(nr_points, cells); - return polydata; - } -}; + // Set the cells and the vertices + vertices->SetCells(nr_points, cells); + return polydata; + } + }; +}}} + cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) { @@ -160,7 +164,7 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) } vtkIdType nr_points; - vtkSmartPointer polydata = CreateCloudWidget::create(cloud, nr_points); + vtkSmartPointer polydata = CloudUtils::create(cloud, nr_points); // Filter colors Vec3b* colors_data = new Vec3b[nr_points]; @@ -207,7 +211,7 @@ cv::viz::WCloud::WCloud(InputArray _cloud, const Color &color) CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); vtkIdType nr_points; - vtkSmartPointer polydata = CreateCloudWidget::create(cloud, nr_points); + vtkSmartPointer polydata = CloudUtils::create(cloud, nr_points); vtkSmartPointer mapper = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 @@ -242,139 +246,142 @@ template<> cv::viz::WCloud cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// Cloud Collection Widget implementation -struct cv::viz::WCloudCollection::CreateCloudWidget +namespace cv { namespace viz { namespace { - static inline vtkSmartPointer create(const Mat &cloud, vtkIdType &nr_points) + struct CloudCollectionUtils { - vtkSmartPointer polydata = vtkSmartPointer::New(); - vtkSmartPointer vertices = vtkSmartPointer::New(); - - polydata->SetVerts(vertices); - - vtkSmartPointer points = polydata->GetPoints(); - vtkSmartPointer initcells; - nr_points = cloud.total(); - - if (!points) + static inline vtkSmartPointer create(const Mat &cloud, vtkIdType &nr_points) { - points = vtkSmartPointer::New(); - if (cloud.depth() == CV_32F) - points->SetDataTypeToFloat(); - else if (cloud.depth() == CV_64F) - points->SetDataTypeToDouble(); - polydata->SetPoints(points); - } - points->SetNumberOfPoints(nr_points); + vtkSmartPointer polydata = vtkSmartPointer::New(); + vtkSmartPointer vertices = vtkSmartPointer::New(); - if (cloud.depth() == CV_32F) - { - // Get a pointer to the beginning of the data array - Vec3f *data_beg = vtkpoints_data(points); - Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - else if (cloud.depth() == CV_64F) - { - // Get a pointer to the beginning of the data array - Vec3d *data_beg = vtkpoints_data(points); - Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - points->SetNumberOfPoints(nr_points); + polydata->SetVerts(vertices); - // Update cells - vtkSmartPointer cells = vertices->GetData(); - // If no init cells and cells has not been initialized... - if (!cells) - cells = vtkSmartPointer::New(); + vtkSmartPointer points = polydata->GetPoints(); + vtkSmartPointer initcells; + nr_points = cloud.total(); - // If we have less values then we need to recreate the array - if (cells->GetNumberOfTuples() < nr_points) - { - cells = vtkSmartPointer::New(); - - // If init cells is given, and there's enough data in it, use it - if (initcells && initcells->GetNumberOfTuples() >= nr_points) + if (!points) { - cells->DeepCopy(initcells); - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); + points = vtkSmartPointer::New(); + if (cloud.depth() == CV_32F) + points->SetDataTypeToFloat(); + else if (cloud.depth() == CV_64F) + points->SetDataTypeToDouble(); + polydata->SetPoints(points); + } + points->SetNumberOfPoints(nr_points); + + if (cloud.depth() == CV_32F) + { + // Get a pointer to the beginning of the data array + Vec3f *data_beg = vtkpoints_data(points); + Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); + nr_points = data_end - data_beg; + } + else if (cloud.depth() == CV_64F) + { + // Get a pointer to the beginning of the data array + Vec3d *data_beg = vtkpoints_data(points); + Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); + nr_points = data_end - data_beg; + } + points->SetNumberOfPoints(nr_points); + + // Update cells + vtkSmartPointer cells = vertices->GetData(); + // If no init cells and cells has not been initialized... + if (!cells) + cells = vtkSmartPointer::New(); + + // If we have less values then we need to recreate the array + if (cells->GetNumberOfTuples() < nr_points) + { + cells = vtkSmartPointer::New(); + + // If init cells is given, and there's enough data in it, use it + if (initcells && initcells->GetNumberOfTuples() >= nr_points) + { + cells->DeepCopy(initcells); + cells->SetNumberOfComponents(2); + cells->SetNumberOfTuples(nr_points); + } + else + { + // If the number of tuples is still too small, we need to recreate the array + cells->SetNumberOfComponents(2); + cells->SetNumberOfTuples(nr_points); + vtkIdType *cell = cells->GetPointer(0); + // Fill it with 1s + std::fill(cell, cell + nr_points * 2, 1); + cell++; + for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) + *cell = i; + // Save the results in initcells + initcells = vtkSmartPointer::New(); + initcells->DeepCopy(cells); + } } else { - // If the number of tuples is still too small, we need to recreate the array + // The assumption here is that the current set of cells has more data than needed cells->SetNumberOfComponents(2); cells->SetNumberOfTuples(nr_points); - vtkIdType *cell = cells->GetPointer(0); - // Fill it with 1s - std::fill(cell, cell + nr_points * 2, 1); - cell++; - for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) - *cell = i; - // Save the results in initcells - initcells = vtkSmartPointer::New(); - initcells->DeepCopy(cells); } - } - else - { - // The assumption here is that the current set of cells has more data than needed - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); + + // Set the cells and the vertices + vertices->SetCells(nr_points, cells); + return polydata; } - // Set the cells and the vertices - vertices->SetCells(nr_points, cells); - return polydata; - } - - static void createMapper(vtkSmartPointer actor, vtkSmartPointer poly_data, Vec3d& minmax) - { - vtkDataSetMapper *mapper = vtkDataSetMapper::SafeDownCast(actor->GetMapper()); - if (!mapper) + static void createMapper(vtkSmartPointer actor, vtkSmartPointer poly_data, Vec3d& minmax) { - // This is the first cloud - vtkSmartPointer mapper_new = vtkSmartPointer::New(); + vtkDataSetMapper *mapper = vtkDataSetMapper::SafeDownCast(actor->GetMapper()); + if (!mapper) + { + // This is the first cloud + vtkSmartPointer mapper_new = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 - mapper_new->SetInputConnection(poly_data->GetProducerPort()); + mapper_new->SetInputConnection(poly_data->GetProducerPort()); #else - mapper_new->SetInputData(poly_data); + mapper_new->SetInputData(poly_data); #endif - mapper_new->SetScalarRange(minmax.val); - mapper_new->SetScalarModeToUsePointData(); + mapper_new->SetScalarRange(minmax.val); + mapper_new->SetScalarModeToUsePointData(); - bool interpolation = (poly_data && poly_data->GetNumberOfCells() != poly_data->GetNumberOfVerts()); + bool interpolation = (poly_data && poly_data->GetNumberOfCells() != poly_data->GetNumberOfVerts()); - mapper_new->SetInterpolateScalarsBeforeMapping(interpolation); - mapper_new->ScalarVisibilityOn(); - mapper_new->ImmediateModeRenderingOff(); + mapper_new->SetInterpolateScalarsBeforeMapping(interpolation); + mapper_new->ScalarVisibilityOn(); + mapper_new->ImmediateModeRenderingOff(); - actor->SetNumberOfCloudPoints(int(std::max(1, poly_data->GetNumberOfPoints() / 10))); - actor->GetProperty()->SetInterpolationToFlat(); - actor->GetProperty()->BackfaceCullingOn(); - actor->SetMapper(mapper_new); - return ; - } + actor->SetNumberOfCloudPoints(int(std::max(1, poly_data->GetNumberOfPoints() / 10))); + actor->GetProperty()->SetInterpolationToFlat(); + actor->GetProperty()->BackfaceCullingOn(); + actor->SetMapper(mapper_new); + return ; + } - vtkPolyData *data = vtkPolyData::SafeDownCast(mapper->GetInput()); - CV_Assert("Cloud Widget without data" && data); + vtkPolyData *data = vtkPolyData::SafeDownCast(mapper->GetInput()); + CV_Assert("Cloud Widget without data" && data); - vtkSmartPointer appendFilter = vtkSmartPointer::New(); + vtkSmartPointer appendFilter = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 - appendFilter->AddInputConnection(mapper->GetInput()->GetProducerPort()); - appendFilter->AddInputConnection(poly_data->GetProducerPort()); + appendFilter->AddInputConnection(mapper->GetInput()->GetProducerPort()); + appendFilter->AddInputConnection(poly_data->GetProducerPort()); #else - appendFilter->AddInputData(data); - appendFilter->AddInputData(poly_data); + appendFilter->AddInputData(data); + appendFilter->AddInputData(poly_data); #endif - mapper->SetInputConnection(appendFilter->GetOutputPort()); + mapper->SetInputConnection(appendFilter->GetOutputPort()); - // Update the number of cloud points - vtkIdType old_cloud_points = actor->GetNumberOfCloudPoints(); - actor->SetNumberOfCloudPoints(int(std::max(1, old_cloud_points+poly_data->GetNumberOfPoints() / 10))); - } -}; + // Update the number of cloud points + vtkIdType old_cloud_points = actor->GetNumberOfCloudPoints(); + actor->SetNumberOfCloudPoints(int(std::max(1, old_cloud_points+poly_data->GetNumberOfPoints() / 10))); + } + }; +}}} cv::viz::WCloudCollection::WCloudCollection() { @@ -397,7 +404,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, } vtkIdType nr_points; - vtkSmartPointer polydata = CreateCloudWidget::create(cloud, nr_points); + vtkSmartPointer polydata = CloudCollectionUtils::create(cloud, nr_points); // Filter colors Vec3b* colors_data = new Vec3b[nr_points]; @@ -429,7 +436,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, CV_Assert("Incompatible widget type." && actor); Vec3d minmax(scalars->GetRange()); - CreateCloudWidget::createMapper(actor, transform_filter->GetOutput(), minmax); + CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput(), minmax); } void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3f &pose) @@ -438,7 +445,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); vtkIdType nr_points; - vtkSmartPointer polydata = CreateCloudWidget::create(cloud, nr_points); + vtkSmartPointer polydata = CloudCollectionUtils::create(cloud, nr_points); vtkSmartPointer scalars = vtkSmartPointer::New(); scalars->SetNumberOfComponents(3); @@ -468,7 +475,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, CV_Assert("Incompatible widget type." && actor); Vec3d minmax(scalars->GetRange()); - CreateCloudWidget::createMapper(actor, transform_filter->GetOutput(), minmax); + CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput(), minmax); } template<> cv::viz::WCloudCollection cv::viz::Widget::cast() @@ -480,80 +487,84 @@ template<> cv::viz::WCloudCollection cv::viz::Widget::cast - struct Impl + struct CloudNormalsUtils { - static vtkSmartPointer applyOrganized(const Mat &cloud, const Mat& normals, double level, float scale, _Tp *&pts, vtkIdType &nr_normals) + template + struct Impl { - vtkIdType point_step = static_cast(std::sqrt(level)); - nr_normals = (static_cast((cloud.cols - 1) / point_step) + 1) * - (static_cast((cloud.rows - 1) / point_step) + 1); - vtkSmartPointer lines = vtkSmartPointer::New(); - - pts = new _Tp[2 * nr_normals * 3]; - - int cch = cloud.channels(); - vtkIdType cell_count = 0; - for (vtkIdType y = 0; y < cloud.rows; y += point_step) + static vtkSmartPointer applyOrganized(const Mat &cloud, const Mat& normals, double level, float scale, _Tp *&pts, vtkIdType &nr_normals) { - const _Tp *prow = cloud.ptr<_Tp>(y); - const _Tp *nrow = normals.ptr<_Tp>(y); - for (vtkIdType x = 0; x < cloud.cols; x += point_step * cch) + vtkIdType point_step = static_cast(std::sqrt(level)); + nr_normals = (static_cast((cloud.cols - 1) / point_step) + 1) * + (static_cast((cloud.rows - 1) / point_step) + 1); + vtkSmartPointer lines = vtkSmartPointer::New(); + + pts = new _Tp[2 * nr_normals * 3]; + + int cch = cloud.channels(); + vtkIdType cell_count = 0; + for (vtkIdType y = 0; y < cloud.rows; y += point_step) { - pts[2 * cell_count * 3 + 0] = prow[x]; - pts[2 * cell_count * 3 + 1] = prow[x+1]; - pts[2 * cell_count * 3 + 2] = prow[x+2]; - pts[2 * cell_count * 3 + 3] = prow[x] + nrow[x] * scale; - pts[2 * cell_count * 3 + 4] = prow[x+1] + nrow[x+1] * scale; - pts[2 * cell_count * 3 + 5] = prow[x+2] + nrow[x+2] * scale; + const _Tp *prow = cloud.ptr<_Tp>(y); + const _Tp *nrow = normals.ptr<_Tp>(y); + for (vtkIdType x = 0; x < cloud.cols; x += point_step * cch) + { + pts[2 * cell_count * 3 + 0] = prow[x]; + pts[2 * cell_count * 3 + 1] = prow[x+1]; + pts[2 * cell_count * 3 + 2] = prow[x+2]; + pts[2 * cell_count * 3 + 3] = prow[x] + nrow[x] * scale; + pts[2 * cell_count * 3 + 4] = prow[x+1] + nrow[x+1] * scale; + pts[2 * cell_count * 3 + 5] = prow[x+2] + nrow[x+2] * scale; + + lines->InsertNextCell(2); + lines->InsertCellPoint(2 * cell_count); + lines->InsertCellPoint(2 * cell_count + 1); + cell_count++; + } + } + return lines; + } + + static vtkSmartPointer applyUnorganized(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) + { + vtkSmartPointer lines = vtkSmartPointer::New(); + nr_normals = (cloud.size().area() - 1) / level + 1 ; + pts = new _Tp[2 * nr_normals * 3]; + + int cch = cloud.channels(); + const _Tp *p = cloud.ptr<_Tp>(); + const _Tp *n = normals.ptr<_Tp>(); + for (vtkIdType i = 0, j = 0; j < nr_normals; j++, i = j * level * cch) + { + + pts[2 * j * 3 + 0] = p[i]; + pts[2 * j * 3 + 1] = p[i+1]; + pts[2 * j * 3 + 2] = p[i+2]; + pts[2 * j * 3 + 3] = p[i] + n[i] * scale; + pts[2 * j * 3 + 4] = p[i+1] + n[i+1] * scale; + pts[2 * j * 3 + 5] = p[i+2] + n[i+2] * scale; lines->InsertNextCell(2); - lines->InsertCellPoint(2 * cell_count); - lines->InsertCellPoint(2 * cell_count + 1); - cell_count++; + lines->InsertCellPoint(2 * j); + lines->InsertCellPoint(2 * j + 1); } + return lines; } - return lines; - } + }; - static vtkSmartPointer applyUnorganized(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) + template + static inline vtkSmartPointer apply(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) { - vtkSmartPointer lines = vtkSmartPointer::New(); - nr_normals = (cloud.size().area() - 1) / level + 1 ; - pts = new _Tp[2 * nr_normals * 3]; - - int cch = cloud.channels(); - const _Tp *p = cloud.ptr<_Tp>(); - const _Tp *n = normals.ptr<_Tp>(); - for (vtkIdType i = 0, j = 0; j < nr_normals; j++, i = j * level * cch) - { - - pts[2 * j * 3 + 0] = p[i]; - pts[2 * j * 3 + 1] = p[i+1]; - pts[2 * j * 3 + 2] = p[i+2]; - pts[2 * j * 3 + 3] = p[i] + n[i] * scale; - pts[2 * j * 3 + 4] = p[i+1] + n[i+1] * scale; - pts[2 * j * 3 + 5] = p[i+2] + n[i+2] * scale; - - lines->InsertNextCell(2); - lines->InsertCellPoint(2 * j); - lines->InsertCellPoint(2 * j + 1); - } - return lines; + if (cloud.cols > 1 && cloud.rows > 1) + return CloudNormalsUtils::Impl<_Tp>::applyOrganized(cloud, normals, level, scale, pts, nr_normals); + else + return CloudNormalsUtils::Impl<_Tp>::applyUnorganized(cloud, normals, level, scale, pts, nr_normals); } }; - template - static inline vtkSmartPointer apply(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) - { - if (cloud.cols > 1 && cloud.rows > 1) - return ApplyCloudNormals::Impl<_Tp>::applyOrganized(cloud, normals, level, scale, pts, nr_normals); - else - return ApplyCloudNormals::Impl<_Tp>::applyUnorganized(cloud, normals, level, scale, pts, nr_normals); - } -}; +}}} cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, int level, float scale, const Color &color) { @@ -574,7 +585,7 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in data->SetNumberOfComponents(3); float* pts = 0; - lines = ApplyCloudNormals::apply(cloud, normals, level, scale, pts, nr_normals); + lines = CloudNormalsUtils::apply(cloud, normals, level, scale, pts, nr_normals); data->SetArray(&pts[0], 2 * nr_normals * 3, 0); points->SetData(data); } @@ -586,7 +597,7 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in data->SetNumberOfComponents(3); double* pts = 0; - lines = ApplyCloudNormals::apply(cloud, normals, level, scale, pts, nr_normals); + lines = CloudNormalsUtils::apply(cloud, normals, level, scale, pts, nr_normals); data->SetArray(&pts[0], 2 * nr_normals * 3, 0); points->SetData(data); } @@ -619,34 +630,37 @@ template<> cv::viz::WCloudNormals cv::viz::Widget::cast( /////////////////////////////////////////////////////////////////////////////////////////////// /// Mesh Widget implementation -struct cv::viz::WMesh::CopyImpl +namespace cv { namespace viz { namespace { - template - static Vec<_Tp, 3> * copy(const Mat &source, Vec<_Tp, 3> *output, int *look_up, const Mat &nan_mask) + struct MeshUtils { - CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); - CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); - CV_DbgAssert(DataDepth<_Tp>::value == nan_mask.depth()); - - int s_chs = source.channels(); - int m_chs = nan_mask.channels(); - - int index = 0; - const _Tp* srow = source.ptr<_Tp>(0); - const _Tp* mrow = nan_mask.ptr<_Tp>(0); - - for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) + template + static Vec<_Tp, 3> * copy(const Mat &source, Vec<_Tp, 3> *output, int *look_up, const Mat &nan_mask) { - if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) + CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); + CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); + CV_DbgAssert(DataDepth<_Tp>::value == nan_mask.depth()); + + int s_chs = source.channels(); + int m_chs = nan_mask.channels(); + + int index = 0; + const _Tp* srow = source.ptr<_Tp>(0); + const _Tp* mrow = nan_mask.ptr<_Tp>(0); + + for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) { - look_up[x] = index; - *output++ = Vec<_Tp, 3>(srow); - ++index; + if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) + { + look_up[x] = index; + *output++ = Vec<_Tp, 3>(srow); + ++index; + } } + return output; } - return output; - } -}; + }; +}}} cv::viz::WMesh::WMesh(const Mesh3d &mesh) { @@ -665,14 +679,14 @@ cv::viz::WMesh::WMesh(const Mesh3d &mesh) { points->SetDataTypeToFloat(); Vec3f *data_beg = vtkpoints_data(points); - Vec3f *data_end = CopyImpl::copy(mesh.cloud, data_beg, look_up, mesh.cloud); + Vec3f *data_end = MeshUtils::copy(mesh.cloud, data_beg, look_up, mesh.cloud); nr_points = data_end - data_beg; } else { points->SetDataTypeToDouble(); Vec3d *data_beg = vtkpoints_data(points); - Vec3d *data_end = CopyImpl::copy(mesh.cloud, data_beg, look_up, mesh.cloud); + Vec3d *data_end = MeshUtils::copy(mesh.cloud, data_beg, look_up, mesh.cloud); nr_points = data_end - data_beg; } diff --git a/modules/viz/src/shape_widgets.cpp b/modules/viz/src/shape_widgets.cpp index aff3609c9..482397251 100644 --- a/modules/viz/src/shape_widgets.cpp +++ b/modules/viz/src/shape_widgets.cpp @@ -84,25 +84,28 @@ template<> cv::viz::WLine cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// plane widget implementation -struct cv::viz::WPlane::SetSizeImpl +namespace cv { namespace viz { namespace { - template - static vtkSmartPointer setSize(const Vec<_Tp, 3> ¢er, vtkSmartPointer poly_data_port, double size) + struct PlaneUtils { - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->Translate(center[0], center[1], center[2]); - transform->Scale(size, size, size); - transform->Translate(-center[0], -center[1], -center[2]); + template + static vtkSmartPointer setSize(const Vec<_Tp, 3> ¢er, vtkSmartPointer poly_data_port, double size) + { + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->PreMultiply(); + transform->Translate(center[0], center[1], center[2]); + transform->Scale(size, size, size); + transform->Translate(-center[0], -center[1], -center[2]); - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetInputConnection(poly_data_port); - transform_filter->SetTransform(transform); - transform_filter->Update(); + vtkSmartPointer transform_filter = vtkSmartPointer::New(); + transform_filter->SetInputConnection(poly_data_port); + transform_filter->SetTransform(transform); + transform_filter->Update(); - return transform_filter; - } -}; + return transform_filter; + } + }; +}}} cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) { @@ -115,7 +118,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) plane->GetOrigin(p_center.val); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(SetSizeImpl::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); + mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -136,7 +139,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, float size, const plane->SetCenter(p_center[0], p_center[1], p_center[2]); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(SetSizeImpl::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); + mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -406,25 +409,28 @@ template<> cv::viz::WCoordinateSystem cv::viz::Widget::cast - static void copy(const Mat& source, Vec<_Tp, 3> *output, vtkSmartPointer polyLine) + struct PolyLineUtils { - int s_chs = source.channels(); - - for (int y = 0, id = 0; y < source.rows; ++y) + template + static void copy(const Mat& source, Vec<_Tp, 3> *output, vtkSmartPointer polyLine) { - const _Tp* srow = source.ptr<_Tp>(y); + int s_chs = source.channels(); - for (int x = 0; x < source.cols; ++x, srow += s_chs, ++id) + for (int y = 0, id = 0; y < source.rows; ++y) { - *output++ = Vec<_Tp, 3>(srow); - polyLine->GetPointIds()->SetId(id,id); + const _Tp* srow = source.ptr<_Tp>(y); + + for (int x = 0; x < source.cols; ++x, srow += s_chs, ++id) + { + *output++ = Vec<_Tp, 3>(srow); + polyLine->GetPointIds()->SetId(id,id); + } } } - } -}; + }; +}}} cv::viz::WPolyLine::WPolyLine(InputArray _pointData, const Color &color) { @@ -448,13 +454,13 @@ cv::viz::WPolyLine::WPolyLine(InputArray _pointData, const Color &color) { // Get a pointer to the beginning of the data array Vec3f *data_beg = vtkpoints_data(points); - CopyImpl::copy(pointData, data_beg, polyLine); + PolyLineUtils::copy(pointData, data_beg, polyLine); } else if (pointData.depth() == CV_64F) { // Get a pointer to the beginning of the data array Vec3d *data_beg = vtkpoints_data(points); - CopyImpl::copy(pointData, data_beg, polyLine); + PolyLineUtils::copy(pointData, data_beg, polyLine); } vtkSmartPointer cells = vtkSmartPointer::New(); @@ -486,36 +492,39 @@ template<> cv::viz::WPolyLine cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// grid widget implementation -struct cv::viz::WGrid::GridImpl +namespace cv { namespace viz { namespace { - static vtkSmartPointer createGrid(const Vec2i &dimensions, const Vec2d &spacing) + struct GridUtils { - // Create the grid using image data - vtkSmartPointer grid = vtkSmartPointer::New(); + static vtkSmartPointer createGrid(const Vec2i &dimensions, const Vec2d &spacing) + { + // Create the grid using image data + vtkSmartPointer grid = vtkSmartPointer::New(); - // Add 1 to dimensions because in ImageData dimensions is the number of lines - // - however here it means number of cells - grid->SetDimensions(dimensions[0]+1, dimensions[1]+1, 1); - grid->SetSpacing(spacing[0], spacing[1], 0.); + // Add 1 to dimensions because in ImageData dimensions is the number of lines + // - however here it means number of cells + grid->SetDimensions(dimensions[0]+1, dimensions[1]+1, 1); + grid->SetSpacing(spacing[0], spacing[1], 0.); - // Set origin of the grid to be the middle of the grid - grid->SetOrigin(dimensions[0] * spacing[0] * (-0.5), dimensions[1] * spacing[1] * (-0.5), 0); + // Set origin of the grid to be the middle of the grid + grid->SetOrigin(dimensions[0] * spacing[0] * (-0.5), dimensions[1] * spacing[1] * (-0.5), 0); - // Extract the edges so we have the grid - vtkSmartPointer filter = vtkSmartPointer::New(); + // Extract the edges so we have the grid + vtkSmartPointer filter = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 - filter->SetInputConnection(grid->GetProducerPort()); + filter->SetInputConnection(grid->GetProducerPort()); #else - filter->SetInputData(grid); + filter->SetInputData(grid); #endif - filter->Update(); - return filter->GetOutput(); - } -}; + filter->Update(); + return filter->GetOutput(); + } + }; +}}} cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color) { - vtkSmartPointer grid = GridImpl::createGrid(dimensions, spacing); + vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); vtkSmartPointer mapper = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 @@ -533,7 +542,7 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color cv::viz::WGrid::WGrid(const Vec4f &coefs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color) { - vtkSmartPointer grid = GridImpl::createGrid(dimensions, spacing); + vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); // Estimate the transform to set the normal based on the coefficients Vec3f normal(coefs[0], coefs[1], coefs[2]); @@ -938,99 +947,102 @@ template<> cv::viz::WImage3D cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// camera position widget implementation -struct cv::viz::WCameraPosition::ProjectImage +namespace cv { namespace viz { namespace { - static void projectImage(float fovy, float far_end_height, const Mat &image, - double scale, const Color &color, vtkSmartPointer actor) + struct CameraPositionUtils { - // Create a camera - vtkSmartPointer camera = vtkSmartPointer::New(); - float aspect_ratio = float(image.cols)/float(image.rows); + static void projectImage(float fovy, float far_end_height, const Mat &image, + double scale, const Color &color, vtkSmartPointer actor) + { + // Create a camera + vtkSmartPointer camera = vtkSmartPointer::New(); + float aspect_ratio = float(image.cols)/float(image.rows); - // Create the vtk image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + // Create the vtk image + vtkSmartPointer vtk_image = vtkSmartPointer::New(); + ConvertToVtkImage::convert(image, vtk_image); - // Adjust a pixel of the vtk_image - vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 0, color[2]); - vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 1, color[1]); - vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 2, color[0]); + // Adjust a pixel of the vtk_image + vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 0, color[2]); + vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 1, color[1]); + vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 2, color[0]); - // Need to flip the image as the coordinates are different in OpenCV and VTK - vtkSmartPointer flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip + // Need to flip the image as the coordinates are different in OpenCV and VTK + vtkSmartPointer flipFilter = vtkSmartPointer::New(); + flipFilter->SetFilteredAxis(1); // Vertical flip #if VTK_MAJOR_VERSION <= 5 - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(vtk_image->GetProducerPort()); #else - flipFilter->SetInputData(vtk_image); + flipFilter->SetInputData(vtk_image); #endif - flipFilter->Update(); + flipFilter->Update(); - Vec3d plane_center(0.0, 0.0, scale); + Vec3d plane_center(0.0, 0.0, scale); - vtkSmartPointer plane = vtkSmartPointer::New(); - plane->SetCenter(plane_center[0], plane_center[1], plane_center[2]); - plane->SetNormal(0.0, 0.0, 1.0); + vtkSmartPointer plane = vtkSmartPointer::New(); + plane->SetCenter(plane_center[0], plane_center[1], plane_center[2]); + plane->SetNormal(0.0, 0.0, 1.0); - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->Translate(plane_center[0], plane_center[1], plane_center[2]); - transform->Scale(far_end_height*aspect_ratio, far_end_height, 1.0); - transform->RotateY(180.0); - transform->Translate(-plane_center[0], -plane_center[1], -plane_center[2]); + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->PreMultiply(); + transform->Translate(plane_center[0], plane_center[1], plane_center[2]); + transform->Scale(far_end_height*aspect_ratio, far_end_height, 1.0); + transform->RotateY(180.0); + transform->Translate(-plane_center[0], -plane_center[1], -plane_center[2]); - // Apply the texture - vtkSmartPointer texture = vtkSmartPointer::New(); - texture->SetInputConnection(flipFilter->GetOutputPort()); + // Apply the texture + vtkSmartPointer texture = vtkSmartPointer::New(); + texture->SetInputConnection(flipFilter->GetOutputPort()); - vtkSmartPointer texturePlane = vtkSmartPointer::New(); - texturePlane->SetInputConnection(plane->GetOutputPort()); + vtkSmartPointer texturePlane = vtkSmartPointer::New(); + texturePlane->SetInputConnection(plane->GetOutputPort()); - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetTransform(transform); - transform_filter->SetInputConnection(texturePlane->GetOutputPort()); - transform_filter->Update(); + vtkSmartPointer transform_filter = vtkSmartPointer::New(); + transform_filter->SetTransform(transform); + transform_filter->SetInputConnection(texturePlane->GetOutputPort()); + transform_filter->Update(); - // Create frustum - camera->SetViewAngle(fovy); - camera->SetPosition(0.0,0.0,0.0); - camera->SetViewUp(0.0,1.0,0.0); - camera->SetFocalPoint(0.0,0.0,1.0); - camera->SetClippingRange(0.01, scale); + // Create frustum + camera->SetViewAngle(fovy); + camera->SetPosition(0.0,0.0,0.0); + camera->SetViewUp(0.0,1.0,0.0); + camera->SetFocalPoint(0.0,0.0,1.0); + camera->SetClippingRange(0.01, scale); - double planesArray[24]; - camera->GetFrustumPlanes(aspect_ratio, planesArray); + double planesArray[24]; + camera->GetFrustumPlanes(aspect_ratio, planesArray); - vtkSmartPointer planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); + vtkSmartPointer planes = vtkSmartPointer::New(); + planes->SetFrustumPlanes(planesArray); - vtkSmartPointer frustumSource = - vtkSmartPointer::New(); - frustumSource->SetPlanes(planes); - frustumSource->Update(); + vtkSmartPointer frustumSource = + vtkSmartPointer::New(); + frustumSource->SetPlanes(planes); + frustumSource->Update(); - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(frustumSource->GetOutputPort()); - filter->Update(); + vtkSmartPointer filter = vtkSmartPointer::New(); + filter->SetInputConnection(frustumSource->GetOutputPort()); + filter->Update(); - // Frustum needs to be textured or else it can't be combined with image - vtkSmartPointer frustum_texture = vtkSmartPointer::New(); - frustum_texture->SetInputConnection(filter->GetOutputPort()); - // Texture mapping with only one pixel from the image to have constant color - frustum_texture->SetSRange(0.0, 0.0); - frustum_texture->SetTRange(0.0, 0.0); + // Frustum needs to be textured or else it can't be combined with image + vtkSmartPointer frustum_texture = vtkSmartPointer::New(); + frustum_texture->SetInputConnection(filter->GetOutputPort()); + // Texture mapping with only one pixel from the image to have constant color + frustum_texture->SetSRange(0.0, 0.0); + frustum_texture->SetTRange(0.0, 0.0); - vtkSmartPointer appendFilter = vtkSmartPointer::New(); - appendFilter->AddInputConnection(frustum_texture->GetOutputPort()); - appendFilter->AddInputConnection(transform_filter->GetOutputPort()); + vtkSmartPointer appendFilter = vtkSmartPointer::New(); + appendFilter->AddInputConnection(frustum_texture->GetOutputPort()); + appendFilter->AddInputConnection(transform_filter->GetOutputPort()); - vtkSmartPointer planeMapper = vtkSmartPointer::New(); - planeMapper->SetInputConnection(appendFilter->GetOutputPort()); + vtkSmartPointer planeMapper = vtkSmartPointer::New(); + planeMapper->SetInputConnection(appendFilter->GetOutputPort()); - actor->SetMapper(planeMapper); - actor->SetTexture(texture); - } -}; + actor->SetMapper(planeMapper); + actor->SetTexture(texture); + } + }; +}}} cv::viz::WCameraPosition::WCameraPosition(float scale) { @@ -1164,7 +1176,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, const Mat &image, fl float far_end_height = 2.0f * c_y * scale / f_y; vtkSmartPointer actor = vtkSmartPointer::New(); - ProjectImage::projectImage(fovy, far_end_height, image, scale, color, actor); + CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); WidgetAccessor::setProp(*this, actor); } @@ -1175,7 +1187,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, const Mat &image, fl float far_end_height = 2.0 * scale * tan(fov[1] * 0.5); vtkSmartPointer actor = vtkSmartPointer::New(); - ProjectImage::projectImage(fovy, far_end_height, image, scale, color, actor); + CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); WidgetAccessor::setProp(*this, actor); } @@ -1188,37 +1200,40 @@ template<> cv::viz::WCameraPosition cv::viz::Widget::cast poly_data, vtkSmartPointer append_filter, const std::vector &path) + struct TrajectoryUtils { - vtkIdType nr_points = path.size(); - - for (vtkIdType i = 0; i < nr_points; ++i) + static void applyPath(vtkSmartPointer poly_data, vtkSmartPointer append_filter, const std::vector &path) { - vtkSmartPointer new_data = vtkSmartPointer::New(); - new_data->DeepCopy(poly_data); + vtkIdType nr_points = path.size(); - // Transform the default coordinate frame - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - vtkSmartPointer mat_trans = vtkSmartPointer::New(); - mat_trans = convertToVtkMatrix(path[i].matrix); - transform->SetMatrix(mat_trans); + for (vtkIdType i = 0; i < nr_points; ++i) + { + vtkSmartPointer new_data = vtkSmartPointer::New(); + new_data->DeepCopy(poly_data); - vtkSmartPointer filter = vtkSmartPointer::New(); + // Transform the default coordinate frame + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->PreMultiply(); + vtkSmartPointer mat_trans = vtkSmartPointer::New(); + mat_trans = convertToVtkMatrix(path[i].matrix); + transform->SetMatrix(mat_trans); + + vtkSmartPointer filter = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 - filter->SetInput(new_data); + filter->SetInput(new_data); #else - filter->SetInputData(new_data); + filter->SetInputData(new_data); #endif - filter->SetTransform(transform); - filter->Update(); + filter->SetTransform(transform); + filter->Update(); - append_filter->AddInputConnection(filter->GetOutputPort()); + append_filter->AddInputConnection(filter->GetOutputPort()); + } } - } -}; + }; +}}} cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, const Color &color, float scale) { @@ -1303,7 +1318,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display axes_tubes->SetNumberOfSides(6); axes_tubes->Update(); - ApplyPath::applyPath(axes_tubes->GetOutput(), appendFilter, path); + TrajectoryUtils::applyPath(axes_tubes->GetOutput(), appendFilter, path); } vtkSmartPointer mapper = vtkSmartPointer::New(); @@ -1348,7 +1363,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Matx3 filter->Update(); vtkSmartPointer appendFilter = vtkSmartPointer::New(); - ApplyPath::applyPath(filter->GetOutput(), appendFilter, path); + TrajectoryUtils::applyPath(filter->GetOutput(), appendFilter, path); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(appendFilter->GetOutputPort()); @@ -1388,7 +1403,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Vec2f filter->Update(); vtkSmartPointer appendFilter = vtkSmartPointer::New(); - ApplyPath::applyPath(filter->GetOutput(), appendFilter, path); + TrajectoryUtils::applyPath(filter->GetOutput(), appendFilter, path); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(appendFilter->GetOutputPort()); diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index 04abdcf7a..5c2df04dc 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -303,27 +303,6 @@ void cv::viz::WidgetAccessor::setProp(Widget& widget, vtkSmartPointer p /////////////////////////////////////////////////////////////////////////////////////////////// /// widget3D implementation -struct cv::viz::Widget3D::MatrixConverter -{ - static Matx44f convertToMatx(const vtkSmartPointer& vtk_matrix) - { - Matx44f m; - for (int i = 0; i < 4; i++) - for (int k = 0; k < 4; k++) - m(i, k) = vtk_matrix->GetElement(i, k); - return m; - } - - static vtkSmartPointer convertToVtkMatrix(const Matx44f& m) - { - vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); - for (int i = 0; i < 4; i++) - for (int k = 0; k < 4; k++) - vtk_matrix->SetElement(i, k, m(i, k)); - return vtk_matrix; - } -}; - void cv::viz::Widget3D::setPose(const Affine3f &pose) { vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); @@ -345,10 +324,9 @@ void cv::viz::Widget3D::updatePose(const Affine3f &pose) setPose(pose); return ; } - Matx44f matrix_cv = MatrixConverter::convertToMatx(matrix); - Affine3f updated_pose = pose * Affine3f(matrix_cv); - matrix = MatrixConverter::convertToVtkMatrix(updated_pose.matrix); + Affine3f updated_pose = pose * Affine3f(convertToMatx(matrix)); + matrix = convertToVtkMatrix(updated_pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); @@ -358,10 +336,7 @@ cv::Affine3f cv::viz::Widget3D::getPose() const { vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Widget is not 3D." && actor); - - vtkSmartPointer matrix = actor->GetUserMatrix(); - Matx44f matrix_cv = MatrixConverter::convertToMatx(matrix); - return Affine3f(matrix_cv); + return Affine3f(convertToMatx(actor->GetUserMatrix())); } void cv::viz::Widget3D::setColor(const Color &color) From c7ff13873d6e5e371f2658f128d7fbfc4ef77832 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 16:57:09 +0400 Subject: [PATCH 106/295] minor --- modules/viz/include/opencv2/viz/widgets.hpp | 12 ++++++++++++ modules/viz/src/precomp.hpp | 7 ++++++- modules/viz/src/viz3d_impl.cpp | 8 ++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 42e0f1968..ea43976dd 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -132,6 +132,9 @@ namespace cv void setColor(const Color &color); }; + ///////////////////////////////////////////////////////////////////////////// + /// Simple widgets + class CV_EXPORTS WLine : public Widget3D { public: @@ -175,6 +178,9 @@ namespace cv WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame = true, const Color &color = Color::white()); }; + ///////////////////////////////////////////////////////////////////////////// + /// Compond widgets + class CV_EXPORTS WCoordinateSystem : public Widget3D { public: @@ -268,6 +274,9 @@ namespace cv float sphere_radius = 0.007f, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; + ///////////////////////////////////////////////////////////////////////////// + /// Cloud widgets + class CV_EXPORTS WCloud: public Widget3D { public: @@ -300,6 +309,9 @@ namespace cv WMesh(const Mesh3d &mesh); }; + ///////////////////////////////////////////////////////////////////////////// + /// Utility exports + template<> CV_EXPORTS Widget2D Widget::cast(); template<> CV_EXPORTS Widget3D Widget::cast(); template<> CV_EXPORTS WLine Widget::cast(); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 1beb43587..5994aaa1b 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -94,7 +94,6 @@ #include #include #include -#include #include #include #include @@ -111,6 +110,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include diff --git a/modules/viz/src/viz3d_impl.cpp b/modules/viz/src/viz3d_impl.cpp index b1173f645..af3f93b71 100644 --- a/modules/viz/src/viz3d_impl.cpp +++ b/modules/viz/src/viz3d_impl.cpp @@ -48,9 +48,9 @@ #include "precomp.hpp" -vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew(); -#if 1 || !defined __APPLE__ +#if (1 || !defined __APPLE__) && !defined _MSC_VER +vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew(); vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew() { return vtkRenderWindowInteractor::New(); @@ -79,7 +79,11 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) style_->UseTimersOn(); ///////////////////////////////////////////////// +#if (1 || !defined __APPLE__) && !defined _MSC_VER interactor_ = vtkSmartPointer::Take(vtkRenderWindowInteractorFixNew()); +#else + interactor_ = vtkSmartPointer::New(); +#endif window_->AlphaBitPlanesOff(); window_->PointSmoothingOff(); From 54fa69cab2266ffe4ad8e0ad8a57bf29ee2b5979 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 17:12:02 +0400 Subject: [PATCH 107/295] renamed Spheres Trajectory, minor changes in Trajectory --- modules/viz/doc/widget.rst | 28 ++++++++++----------- modules/viz/include/opencv2/viz/widgets.hpp | 12 ++++----- modules/viz/src/shape_widgets.cpp | 10 ++++---- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index bbbfef63a..90147e441 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -729,10 +729,10 @@ This 3D Widget represents a trajectory. :: class CV_EXPORTS WTrajectory : public Widget3D { public: - enum {DISPLAY_FRAMES = 1, DISPLAY_PATH = 2}; + enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.0); + WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, const Color &color = Color::white(), float scale = 1.0); //! Displays trajectory of the given path by frustums WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums @@ -746,18 +746,18 @@ viz::WTrajectory::WTrajectory ----------------------------- Constructs a WTrajectory. -.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.0) +.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, const Color &color = Color::white(), float scale = 1.0) :param path: List of poses on a trajectory. - :param display_mode: Display mode. This can be DISPLAY_PATH, DISPLAY_FRAMES, DISPLAY_PATH & DISPLAY_FRAMES. + :param display_mode: Display mode. This can be PATH, FRAMES, and BOTH. :param color: :ocv:class:`Color` of the polyline that represents path. Frames are not affected. :param scale: Scale of the frames. Polyline is not affected. Displays trajectory of the given path as follows: - * DISPLAY_PATH : Displays a poly line that represents the path. - * DISPLAY_FRAMES : Displays coordinate frames at each pose. - * DISPLAY_PATH & DISPLAY_FRAMES : Displays both poly line and coordinate frames. + * PATH : Displays a poly line that represents the path. + * FRAMES : Displays coordinate frames at each pose. + * PATH & FRAMES : Displays both poly line and coordinate frames. .. ocv:function:: WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) @@ -777,26 +777,26 @@ Constructs a WTrajectory. Displays frustums at each pose of the trajectory. -viz::WSpheresTrajectory +viz::WTrajectorySpheres ----------------------- -.. ocv:class:: WSpheresTrajectory +.. ocv:class:: WTrajectorySpheres This 3D Widget represents a trajectory using spheres and lines, where spheres represent the positions of the camera, and lines represent the direction from previous position to the current. :: - class CV_EXPORTS WSpheresTrajectory : public Widget3D + class CV_EXPORTS WTrajectorySpheres : public Widget3D { public: - WSpheresTrajectory(const std::vector &path, float line_length = 0.05f, + WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, sphere_radius = 0.007, Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; -viz::WSpheresTrajectory::WSpheresTrajectory +viz::WTrajectorySpheres::WTrajectorySpheres ------------------------------------------- -Constructs a WSpheresTrajectory. +Constructs a WTrajectorySpheres. -.. ocv:function:: WSpheresTrajectory(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, float sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) +.. ocv:function:: WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, float sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) :param path: List of poses on a trajectory. :param line_length: Length of the lines. diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index ea43976dd..fb2783b17 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -257,21 +257,21 @@ namespace cv class CV_EXPORTS WTrajectory : public Widget3D { public: - enum {DISPLAY_FRAMES = 1, DISPLAY_PATH = 2}; + enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH }; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.f); + WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, const Color &color = Color::white(), float scale = 1.f); //! Displays trajectory of the given path by frustums WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums WTrajectory(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); }; - class CV_EXPORTS WSpheresTrajectory: public Widget3D + class CV_EXPORTS WTrajectorySpheres: public Widget3D { public: - WSpheresTrajectory(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021f, - float sphere_radius = 0.007f, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); + WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021f, + float sphere_radius = 0.007f, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; ///////////////////////////////////////////////////////////////////////////// @@ -330,7 +330,7 @@ namespace cv template<> CV_EXPORTS WImage3D Widget::cast(); template<> CV_EXPORTS WCameraPosition Widget::cast(); template<> CV_EXPORTS WTrajectory Widget::cast(); - template<> CV_EXPORTS WSpheresTrajectory Widget::cast(); + template<> CV_EXPORTS WTrajectorySpheres Widget::cast(); template<> CV_EXPORTS WCloud Widget::cast(); template<> CV_EXPORTS WCloudCollection Widget::cast(); template<> CV_EXPORTS WCloudNormals Widget::cast(); diff --git a/modules/viz/src/shape_widgets.cpp b/modules/viz/src/shape_widgets.cpp index 482397251..8d226ff66 100644 --- a/modules/viz/src/shape_widgets.cpp +++ b/modules/viz/src/shape_widgets.cpp @@ -1240,7 +1240,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display vtkSmartPointer appendFilter = vtkSmartPointer::New(); // Bitwise and with 3 in order to limit the domain to 2 bits - if ((~display_mode & 3) ^ WTrajectory::DISPLAY_PATH) + if ((~display_mode & 3) ^ WTrajectory::PATH) { // Create a poly line along the path vtkIdType nr_points = path.size(); @@ -1284,7 +1284,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display #endif } - if ((~display_mode & 3) ^ WTrajectory::DISPLAY_FRAMES) + if ((~display_mode & 3) ^ WTrajectory::FRAMES) { // Create frames and transform along the path vtkSmartPointer axes = vtkSmartPointer::New(); @@ -1424,7 +1424,7 @@ template<> cv::viz::WTrajectory cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// spheres trajectory widget implementation -cv::viz::WSpheresTrajectory::WSpheresTrajectory(const std::vector &path, float line_length, float init_sphere_radius, float sphere_radius, +cv::viz::WTrajectorySpheres::WTrajectorySpheres(const std::vector &path, float line_length, float init_sphere_radius, float sphere_radius, const Color &line_color, const Color &sphere_color) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); @@ -1505,8 +1505,8 @@ cv::viz::WSpheresTrajectory::WSpheresTrajectory(const std::vector &pat WidgetAccessor::setProp(*this, actor); } -template<> cv::viz::WSpheresTrajectory cv::viz::Widget::cast() +template<> cv::viz::WTrajectorySpheres cv::viz::Widget::cast() { Widget3D widget = this->cast(); - return static_cast(widget); + return static_cast(widget); } From 31d42ce18f55f4f42388eaa52e106a8733a099de Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 18:07:16 +0400 Subject: [PATCH 108/295] refactored Trajectory: split into Trajectory and TrajectoryFrustums) --- modules/viz/doc/widget.rst | 36 ++++++++++++++------- modules/viz/include/opencv2/viz/widgets.hpp | 20 ++++++++---- modules/viz/src/shape_widgets.cpp | 21 ++++++++---- 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 90147e441..a629b7bc9 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -732,26 +732,19 @@ This 3D Widget represents a trajectory. :: enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, const Color &color = Color::white(), float scale = 1.0); - //! Displays trajectory of the given path by frustums - WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); - //! Displays trajectory of the given path by frustums - WTrajectory(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); - - private: - /* hidden */ + WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white(),; }; viz::WTrajectory::WTrajectory ----------------------------- Constructs a WTrajectory. -.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, const Color &color = Color::white(), float scale = 1.0) +.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param display_mode: Display mode. This can be PATH, FRAMES, and BOTH. - :param color: :ocv:class:`Color` of the polyline that represents path. Frames are not affected. :param scale: Scale of the frames. Polyline is not affected. + :param color: :ocv:class:`Color` of the polyline that represents path. Frames are not affected. Displays trajectory of the given path as follows: @@ -759,7 +752,26 @@ Constructs a WTrajectory. * FRAMES : Displays coordinate frames at each pose. * PATH & FRAMES : Displays both poly line and coordinate frames. -.. ocv:function:: WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) +viz::WTrajectoryFrustums +---------------- +.. ocv:class:: WTrajectoryFrustums + +This 3D Widget represents a trajectory. :: + + class CV_EXPORTS WTrajectoryFrustums : public Widget3D + { + public: + //! Displays trajectory of the given path by frustums + WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); + //! Displays trajectory of the given path by frustums + WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); + }; + +viz::WTrajectoryFrustums::WTrajectoryFrustums +----------------------------- +Constructs a WTrajectoryFrustums. + +.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param K: Intrinsic matrix of the camera. @@ -768,7 +780,7 @@ Constructs a WTrajectory. Displays frustums at each pose of the trajectory. -.. ocv:function:: WTrajectory(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) +.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param fov: Field of view of the camera (horizontal, vertical). diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index fb2783b17..cb2dae20e 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -245,13 +245,13 @@ namespace cv //! Creates camera coordinate frame (axes) at the origin WCameraPosition(float scale = 1.f); //! Creates frustum based on the intrinsic marix K at the origin - WCameraPosition(const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + explicit WCameraPosition(const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum based on the field of view at the origin - WCameraPosition(const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + explicit WCameraPosition(const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white()); + explicit WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); + explicit WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectory : public Widget3D @@ -260,11 +260,16 @@ namespace cv enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH }; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, const Color &color = Color::white(), float scale = 1.f); + WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); + }; + + class CV_EXPORTS WTrajectoryFrustums : public Widget3D + { + public: //! Displays trajectory of the given path by frustums - WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + explicit WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectory(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + explicit WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectorySpheres: public Widget3D @@ -330,6 +335,7 @@ namespace cv template<> CV_EXPORTS WImage3D Widget::cast(); template<> CV_EXPORTS WCameraPosition Widget::cast(); template<> CV_EXPORTS WTrajectory Widget::cast(); + template<> CV_EXPORTS WTrajectoryFrustums Widget::cast(); template<> CV_EXPORTS WTrajectorySpheres Widget::cast(); template<> CV_EXPORTS WCloud Widget::cast(); template<> CV_EXPORTS WCloudCollection Widget::cast(); diff --git a/modules/viz/src/shape_widgets.cpp b/modules/viz/src/shape_widgets.cpp index 8d226ff66..3a2ba58f9 100644 --- a/modules/viz/src/shape_widgets.cpp +++ b/modules/viz/src/shape_widgets.cpp @@ -1235,7 +1235,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, const Color &color, float scale) +cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, float scale, const Color &color) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); @@ -1331,7 +1331,16 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display WidgetAccessor::setProp(*this, actor); } -cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Matx33f &K, float scale, const Color &color) +template<> cv::viz::WTrajectory cv::viz::Widget::cast() +{ + Widget3D widget = this->cast(); + return static_cast(widget); +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/// WTrajectoryFrustums widget implementation + +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); float f_x = K(0,0); @@ -1375,7 +1384,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Matx3 setColor(color); } -cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Vec2f &fov, float scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); @@ -1415,14 +1424,14 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Vec2f setColor(color); } -template<> cv::viz::WTrajectory cv::viz::Widget::cast() +template<> cv::viz::WTrajectoryFrustums cv::viz::Widget::cast() { Widget3D widget = this->cast(); - return static_cast(widget); + return static_cast(widget); } /////////////////////////////////////////////////////////////////////////////////////////////// -/// spheres trajectory widget implementation +/// WTrajectorySpheres widget implementation cv::viz::WTrajectorySpheres::WTrajectorySpheres(const std::vector &path, float line_length, float init_sphere_radius, float sphere_radius, const Color &line_color, const Color &sphere_color) From 4979f44cfa83a3fb0b18fec9a56fdb36efb97adb Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 18:11:19 +0400 Subject: [PATCH 109/295] minor --- modules/viz/include/opencv2/viz/viz3d.hpp | 3 - .../include/opencv2/viz/widget_accessor.hpp | 5 +- modules/viz/include/opencv2/viz/widgets.hpp | 57 ++++---- modules/viz/src/precomp.cpp | 3 - modules/viz/src/precomp.hpp | 3 - modules/viz/src/viz.cpp | 3 - modules/viz/src/viz3d_impl.hpp | 4 +- modules/viz/test/test_precomp.hpp | 3 - modules/viz/test/test_viz3d.cpp | 125 +----------------- 9 files changed, 40 insertions(+), 166 deletions(-) diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index f57205919..d3f5a109c 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_VIZ3D_HPP__ diff --git a/modules/viz/include/opencv2/viz/widget_accessor.hpp b/modules/viz/include/opencv2/viz/widget_accessor.hpp index 394cfa858..29352a214 100644 --- a/modules/viz/include/opencv2/viz/widget_accessor.hpp +++ b/modules/viz/include/opencv2/viz/widget_accessor.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_WIDGET_ACCESSOR_HPP__ @@ -69,4 +66,4 @@ namespace cv } } -#endif \ No newline at end of file +#endif diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index cb2dae20e..0b0c5fc28 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_WIDGETS_HPP__ @@ -178,28 +175,22 @@ namespace cv WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame = true, const Color &color = Color::white()); }; - ///////////////////////////////////////////////////////////////////////////// - /// Compond widgets - - class CV_EXPORTS WCoordinateSystem : public Widget3D - { - public: - WCoordinateSystem(float scale = 1.f); - }; - class CV_EXPORTS WPolyLine : public Widget3D { public: WPolyLine(InputArray points, const Color &color = Color::white()); }; - class CV_EXPORTS WGrid : public Widget3D + ///////////////////////////////////////////////////////////////////////////// + /// Text and image widgets + + class CV_EXPORTS WText : public Widget2D { public: - //! Creates grid at the origin - WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); - //! Creates grid based on the plane equation - WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + WText(const String &text, const Point2i &pos, int font_size = 20, const Color &color = Color::white()); + + void setText(const String &text); + String getText() const; }; class CV_EXPORTS WText3D : public Widget3D @@ -211,15 +202,6 @@ namespace cv String getText() const; }; - class CV_EXPORTS WText : public Widget2D - { - public: - WText(const String &text, const Point2i &pos, int font_size = 20, const Color &color = Color::white()); - - void setText(const String &text); - String getText() const; - }; - class CV_EXPORTS WImageOverlay : public Widget2D { public: @@ -239,6 +221,24 @@ namespace cv void setImage(const Mat &image); }; + ///////////////////////////////////////////////////////////////////////////// + /// Compond widgets + + class CV_EXPORTS WCoordinateSystem : public Widget3D + { + public: + WCoordinateSystem(float scale = 1.f); + }; + + class CV_EXPORTS WGrid : public Widget3D + { + public: + //! Creates grid at the origin + WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + //! Creates grid based on the plane equation + WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + }; + class CV_EXPORTS WCameraPosition : public Widget3D { public: @@ -254,6 +254,9 @@ namespace cv explicit WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); }; + ///////////////////////////////////////////////////////////////////////////// + /// Trajectories + class CV_EXPORTS WTrajectory : public Widget3D { public: @@ -280,7 +283,7 @@ namespace cv }; ///////////////////////////////////////////////////////////////////////////// - /// Cloud widgets + /// Clouds class CV_EXPORTS WCloud: public Widget3D { diff --git a/modules/viz/src/precomp.cpp b/modules/viz/src/precomp.cpp index 834648577..631a300da 100644 --- a/modules/viz/src/precomp.cpp +++ b/modules/viz/src/precomp.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 5994aaa1b..7f09ee076 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_PRECOMP_HPP__ diff --git a/modules/viz/src/viz.cpp b/modules/viz/src/viz.cpp index 6a08dfa34..445d483de 100644 --- a/modules/viz/src/viz.cpp +++ b/modules/viz/src/viz.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" diff --git a/modules/viz/src/viz3d_impl.hpp b/modules/viz/src/viz3d_impl.hpp index a7ef9c437..b38ad2966 100644 --- a/modules/viz/src/viz3d_impl.hpp +++ b/modules/viz/src/viz3d_impl.hpp @@ -73,10 +73,10 @@ public: double getDesiredUpdateRate(); /** \brief Returns true when the user tried to close the window */ - bool wasStopped() const { if (interactor_ != NULL) return (stopped_); else return true; } + bool wasStopped() const { return interactor_ ? stopped_ : true; } /** \brief Set the stopped flag back to false */ - void resetStoppedFlag() { if (interactor_ != NULL) stopped_ = false; } + void resetStoppedFlag() { if (interactor_) stopped_ = false; } /** \brief Stop the interaction and close the visualizaton window. */ void close() diff --git a/modules/viz/test/test_precomp.hpp b/modules/viz/test/test_precomp.hpp index 9b98f206b..ff7606ed9 100644 --- a/modules/viz/test/test_precomp.hpp +++ b/modules/viz/test/test_precomp.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifdef __GNUC__ diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 98811165a..29cf81ebb 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -41,141 +41,30 @@ //M*/ #include "test_precomp.hpp" - using namespace cv; static cv::Mat cvcloud_load() { cv::Mat cloud(1, 20000, CV_32FC3); - std::ifstream ifs("/Users/nerei/cloud_dragon.ply"); + std::ifstream ifs("d:/cloud_dragon.ply"); std::string str; for(size_t i = 0; i < 11; ++i) std::getline(ifs, str); cv::Point3f* data = cloud.ptr(); - for(size_t i = 0; i < 20000; ++i) + for(size_t i = 0; i < cloud.total(); ++i) ifs >> data[i].x >> data[i].y >> data[i].z; return cloud; } -bool constant_cam = true; -cv::viz::Widget cam_1, cam_coordinates; - -void keyboard_callback(const viz::KeyboardEvent & event, void * cookie) -{ - if (event.keyDown()) - { - if (event.getKeySym() == "space") - { - viz::Viz3d &viz = *((viz::Viz3d *) cookie); - constant_cam = !constant_cam; - if (constant_cam) - { - viz.showWidget("cam_1", cam_1); - viz.showWidget("cam_coordinate", cam_coordinates); - viz.showWidget("cam_text", viz::WText("Global View", Point2i(5,5), 28)); - viz.resetCamera(); - } - else - { - viz.showWidget("cam_text", viz::WText("Cam View", Point2i(5,5), 28)); - viz.removeWidget("cam_1"); - viz.removeWidget("cam_coordinate"); - } - } - } -} - TEST(Viz_viz3d, develop) { + cv::Mat cloud = cvcloud_load(); cv::viz::Viz3d viz("abc"); - - cv::viz::Mesh3d bunny_mesh = cv::viz::Mesh3d::loadMesh("bunny.ply"); - cv::viz::WMesh bunny_widget(bunny_mesh); - bunny_widget.setColor(cv::viz::Color::cyan()); - - cam_1 = cv::viz::WCameraPosition(cv::Vec2f(0.6f, 0.4f), 0.2, cv::viz::Color::green()); - cam_coordinates = cv::viz::WCameraPosition(0.2); - - viz.showWidget("bunny", bunny_widget); - viz.showWidget("cam_1", cam_1, viz::makeCameraPose(Point3f(1.f,0.f,0.f), Point3f(0.f,0.f,0.f), Point3f(0.f,1.f,0.f))); - viz.showWidget("cam_coordinate", cam_coordinates, viz::makeCameraPose(Point3f(1.f,0.f,0.f), Point3f(0.f,0.f,0.f), Point3f(0.f,1.f,0.f))); - - std::vector cam_path; - - for (int i = 0, j = 0; i <= 360; ++i, j+=5) - { - cam_path.push_back(viz::makeCameraPose(Vec3d(0.5*cos(i*CV_PI/180.0), 0.5*sin(j*CV_PI/180.0), 0.5*sin(i*CV_PI/180.0)), Vec3f(0.f, 0.f, 0.f), Vec3f(0.f, 1.f, 0.f))); - } - - int path_counter = 0; - int cam_path_size = cam_path.size(); - - // OTHER WIDGETS - cv::Mat img = imread("opencv.png"); - - int downSample = 4; - - int row_max = img.rows/downSample; - int col_max = img.cols/downSample; - - cv::Mat *clouds = new cv::Mat[img.cols/downSample]; - cv::Mat *colors = new cv::Mat[img.cols/downSample]; - - for (int col = 0; col < col_max; ++col) - { - clouds[col] = Mat::zeros(img.rows/downSample, 1, CV_32FC3); - colors[col] = Mat::zeros(img.rows/downSample, 1, CV_8UC3); - for (int row = 0; row < row_max; ++row) - { - clouds[col].at(row) = Vec3f(downSample * float(col) / img.cols, 1.f-(downSample * float(row) / img.rows), 0.f); - colors[col].at(row) = img.at(row*downSample,col*downSample); - } - } - - for (int col = 0; col < col_max; ++col) - { - std::stringstream strstrm; - strstrm << "cloud_" << col; - viz.showWidget(strstrm.str(), viz::WCloud(clouds[col], colors[col])); - viz.getWidget(strstrm.str()).setRenderingProperty(viz::POINT_SIZE, 3.0); - viz.getWidget(strstrm.str()).setRenderingProperty(viz::OPACITY, 0.45); - } - - viz.showWidget("trajectory", viz::WTrajectory(cam_path, viz::WTrajectory::DISPLAY_PATH, viz::Color::yellow())); - viz.showWidget("cam_text", viz::WText("Global View", Point2i(5,5), 28)); - viz.registerKeyboardCallback(keyboard_callback, (void *) &viz); - - int angle = 0; - - while(!viz.wasStopped()) - { - if (path_counter == cam_path_size) - { - path_counter = 0; - } - - if (!constant_cam) - { - viz.setViewerPose(cam_path[path_counter]); - } - - if (angle == 360) angle = 0; - - cam_1.cast().setPose(cam_path[path_counter]); - cam_coordinates.cast().setPose(cam_path[path_counter++]); - - for (int i = 0; i < col_max; ++i) - { - std::stringstream strstrm; - strstrm << "cloud_" << i; - viz.setWidgetPose(strstrm.str(), Affine3f().translate(Vec3f(-0.5f, 0.f, (float)(-0.7 + 0.2*sin((angle+i*10)*CV_PI / 180.0))))); - } - angle += 10; - viz.spinOnce(42, true); - } - - volatile void* a = (void*)&cvcloud_load; (void)a; //fixing warnings + cv::viz::WCloud c(cloud, cv::Mat(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0))); + //cv::viz::WCloud c(cloud, cv::viz::Color::bluberry()); + viz.showWidget("c", c); + viz.spin(); } From e048df51ced6ff5863c806104ae0019deafcbb38 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 18:31:04 +0400 Subject: [PATCH 110/295] for shapes switched vtkDataSetMapper to more efficient vtkPolyDataMapper --- modules/viz/src/shape_widgets.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/viz/src/shape_widgets.cpp b/modules/viz/src/shape_widgets.cpp index 3a2ba58f9..b7af4b760 100644 --- a/modules/viz/src/shape_widgets.cpp +++ b/modules/viz/src/shape_widgets.cpp @@ -65,7 +65,7 @@ cv::viz::WLine::WLine(const Point3f &pt1, const Point3f &pt2, const Color &color line->SetPoint2(pt2.x, pt2.y, pt2.z); line->Update(); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(line->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -117,7 +117,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) Vec3d p_center; plane->GetOrigin(p_center.val); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -138,7 +138,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, float size, const Vec3f p_center = pt - coefs3 * t * norm_sqr; plane->SetCenter(p_center[0], p_center[1], p_center[2]); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -167,7 +167,7 @@ cv::viz::WSphere::WSphere(const Point3f ¢er, float radius, int sphere_resolu sphere->LatLongTessellationOff(); sphere->Update(); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(sphere->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -240,7 +240,7 @@ cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, transformPD->SetTransform(transform); transformPD->SetInputConnection(arrowSource->GetOutputPort()); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(transformPD->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -276,7 +276,7 @@ cv::viz::WCircle::WCircle(const Point3f& pt, float radius, float thickness, cons tf->SetTransform(t); tf->SetInputConnection(disk->GetOutputPort()); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(tf->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -307,7 +307,7 @@ cv::viz::WCylinder::WCylinder(const Point3f& pt_on_axis, const Point3f& axis_dir tuber->SetRadius(radius); tuber->SetNumberOfSides(numsides); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(tuber->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -328,7 +328,7 @@ template<> cv::viz::WCylinder cv::viz::Widget::cast() cv::viz::WCube::WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame, const Color &color) { - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); if (wire_frame) { vtkSmartPointer cube = vtkSmartPointer::New(); @@ -390,7 +390,7 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(float scale) axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); axes_tubes->SetNumberOfSides(6); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUsePointData(); mapper->SetInputConnection(axes_tubes->GetOutputPort()); @@ -526,7 +526,7 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color { vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 mapper->SetInputConnection(grid->GetProducerPort()); #else @@ -583,7 +583,7 @@ cv::viz::WGrid::WGrid(const Vec4f &coefs, const Vec2i &dimensions, const Vec2d & #endif transform_filter->Update(); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(transform_filter->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -1076,7 +1076,7 @@ cv::viz::WCameraPosition::WCameraPosition(float scale) axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); axes_tubes->SetNumberOfSides(6); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUsePointData(); mapper->SetInputConnection(axes_tubes->GetOutputPort()); From e990d5b99913ac48da075d5f2048c797c31c6e8b Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 19:31:23 +0400 Subject: [PATCH 111/295] reading/writing trajectories --- modules/viz/include/opencv2/viz.hpp | 16 +++++ modules/viz/src/{viz.cpp => vizcore.cpp} | 82 ++++++++++++++++++++++++ 2 files changed, 98 insertions(+) rename modules/viz/src/{viz.cpp => vizcore.cpp} (67%) diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index d4f08af72..65ad10aac 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -91,6 +91,22 @@ namespace cv template inline bool isNan(const Point3_<_Tp>& p) { return isNan(p.x) || isNan(p.y) || isNan(p.z); } + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// Read/write poses and trajectories + + CV_EXPORTS bool readPose(const String& file, Affine3f& pose, const String& tag = "pose"); + CV_EXPORTS bool readPose(const String& file, Affine3d& pose, const String& tag = "pose"); + + CV_EXPORTS void writePose(const String& file, const Affine3f& pose, const String& tag = "pose"); + CV_EXPORTS void writePose(const String& file, const Affine3d& pose, const String& tag = "pose"); + + CV_EXPORTS void writeTrajectory(const std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, const String& tag = "pose"); + CV_EXPORTS void writeTrajectory(const std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, const String& tag = "pose"); + + CV_EXPORTS void readTrajectory(std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, int end = INT_MAX, const String& tag = "pose"); + CV_EXPORTS void readTrajectory(std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, int end = INT_MAX, const String& tag = "pose"); + } /* namespace viz */ } /* namespace cv */ diff --git a/modules/viz/src/viz.cpp b/modules/viz/src/vizcore.cpp similarity index 67% rename from modules/viz/src/viz.cpp rename to modules/viz/src/vizcore.cpp index 445d483de..dd998e7d9 100644 --- a/modules/viz/src/viz.cpp +++ b/modules/viz/src/vizcore.cpp @@ -160,3 +160,85 @@ cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) cv::viz::Viz3d cv::viz::get(const String &window_name) { return Viz3d (window_name); } void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } + + +/////////////////////////////////////////////////////////////////////////////////////////////// +/// Read/write poses and trajectories + +namespace cv { namespace viz { namespace impl +{ + template + bool readPose(const String& file, Affine3<_Tp>& pose, const String& tag) + { + FileStorage fs(file, FileStorage::READ); + if (!fs.isOpened()) + return false; + + Mat hdr(pose.matrix, false); + fs[tag] >> hdr; + return !hdr.empty() && hdr.depth() == DataDepth<_Tp>::value; + } + + template + void writePose(const String& file, const Affine3<_Tp>& pose, const String& tag) + { + FileStorage fs(file, FileStorage::WRITE); + fs << tag << Mat(pose.matrix, false); + } + + template + void readTrajectory(std::vector >& traj, const String& files_format, int start, int end, const String& tag) + { + start = max(0, std::min(start, end)); + end = std::max(start, end); + + std::vector< Affine3<_Tp> > temp; + + for(int i = start; i < end; ++i) + { + Affine3<_Tp> affine; + bool ok = readPose(cv::format(files_format.c_str(), i),affine, tag); + if (!ok) + break; + + temp.push_back(affine); + } + traj.swap(temp); + } + + template + void writeTrajectory(const std::vector >& traj, const String& files_format, int start, const String& tag) + { + for(size_t i = 0, index = max(0, start); i < traj.size(); ++i, ++index) + writePose(cv::format(files_format.c_str(), index), traj[i], tag); + } +}}} + + +bool cv::viz::readPose(const String& file, Affine3f& pose, const String& tag) { return impl::readPose(file, pose, tag); } +bool cv::viz::readPose(const String& file, Affine3d& pose, const String& tag) { return impl::readPose(file, pose, tag); } + +void cv::viz::writePose(const String& file, const Affine3f& pose, const String& tag) { impl::writePose(file, pose, tag); } +void cv::viz::writePose(const String& file, const Affine3d& pose, const String& tag) { impl::writePose(file, pose, tag); } + +void cv::viz::readTrajectory(std::vector& traj, const String& files_format, int start, int end, const String& tag) +{ impl::readTrajectory(traj, files_format, start, end, tag); } + +void cv::viz::readTrajectory(std::vector& traj, const String& files_format, int start, int end, const String& tag) +{ impl::readTrajectory(traj, files_format, start, end, tag); } + +void cv::viz::writeTrajectory(const std::vector& traj, const String& files_format, int start, const String& tag) +{ impl::writeTrajectory(traj, files_format, start, tag); } + +void cv::viz::writeTrajectory(const std::vector& traj, const String& files_format, int start, const String& tag) +{ impl::writeTrajectory(traj, files_format, start, tag); } + + + + + + + + + + From abc94657980594ac1aea311c194a3ceb2776f2dc Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 19:37:44 +0400 Subject: [PATCH 112/295] kinect camera CAD parameters --- modules/viz/src/types.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index 861a78318..f0be75f65 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -278,13 +278,6 @@ void cv::viz::Camera::computeProjectionMatrix(Matx44f &proj) const cv::viz::Camera cv::viz::Camera::KinectCamera(const Size &window_size) { - // Without distortion, RGB Camera - // Received from http://nicolas.burrus.name/index.php/Research/KinectCalibration - Matx33f K = Matx33f::zeros(); - K(0,0) = 5.2921508098293293e+02; - K(0,2) = 3.2894272028759258e+02; - K(1,1) = 5.2556393630057437e+02; - K(1,2) = 2.6748068171871557e+02; - K(2,2) = 1.0f; + Matx33f K(525.f, 0.f, 320.f, 0.f, 525.f, 240.f, 0.f, 0.f, 1.f) ; return Camera(K, window_size); } From 45aeecb0431f809fd5f4e1b27fd5f895cec6e588 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 20:33:53 +0400 Subject: [PATCH 113/295] renaming --- modules/viz/src/{cloud_widgets.cpp => clouds.cpp} | 0 modules/viz/src/precomp.hpp | 2 +- modules/viz/src/{shape_widgets.cpp => shapes.cpp} | 0 modules/viz/src/{viz3d_impl.cpp => vizimpl.cpp} | 0 modules/viz/src/{viz3d_impl.hpp => vizimpl.hpp} | 0 5 files changed, 1 insertion(+), 1 deletion(-) rename modules/viz/src/{cloud_widgets.cpp => clouds.cpp} (100%) rename modules/viz/src/{shape_widgets.cpp => shapes.cpp} (100%) rename modules/viz/src/{viz3d_impl.cpp => vizimpl.cpp} (100%) rename modules/viz/src/{viz3d_impl.hpp => vizimpl.hpp} (100%) diff --git a/modules/viz/src/cloud_widgets.cpp b/modules/viz/src/clouds.cpp similarity index 100% rename from modules/viz/src/cloud_widgets.cpp rename to modules/viz/src/clouds.cpp diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 7f09ee076..83e0b6f85 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -154,7 +154,7 @@ namespace cv } #include "interactor_style.hpp" -#include "viz3d_impl.hpp" +#include "vizimpl.hpp" #endif diff --git a/modules/viz/src/shape_widgets.cpp b/modules/viz/src/shapes.cpp similarity index 100% rename from modules/viz/src/shape_widgets.cpp rename to modules/viz/src/shapes.cpp diff --git a/modules/viz/src/viz3d_impl.cpp b/modules/viz/src/vizimpl.cpp similarity index 100% rename from modules/viz/src/viz3d_impl.cpp rename to modules/viz/src/vizimpl.cpp diff --git a/modules/viz/src/viz3d_impl.hpp b/modules/viz/src/vizimpl.hpp similarity index 100% rename from modules/viz/src/viz3d_impl.hpp rename to modules/viz/src/vizimpl.hpp From cad2f98007ea2e69157d8f300528b068e60635ff Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 20:58:55 +0400 Subject: [PATCH 114/295] removed vizActor (since unnecessarily in new design concept with simplified widgets) --- modules/viz/src/clouds.cpp | 2 +- modules/viz/src/precomp.hpp | 3 --- modules/viz/src/shapes.cpp | 20 ++++++++++---------- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 27a0285fc..d43ae2d4f 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -615,7 +615,7 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in mapper->SetColorModeToMapScalars(); mapper->SetScalarModeToUsePointData(); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); setColor(color); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 83e0b6f85..24b7e3f97 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -123,9 +123,6 @@ namespace cv { namespace viz { - typedef vtkLODActor vizActor; - //typedef vtkActor vizActor; - typedef std::map > WidgetActorMap; typedef std::map VizMap; diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index b7af4b760..0cf41bdec 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -68,7 +68,7 @@ cv::viz::WLine::WLine(const Point3f &pt1, const Point3f &pt2, const Color &color vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(line->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -120,7 +120,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -141,7 +141,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, float size, const vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -170,7 +170,7 @@ cv::viz::WSphere::WSphere(const Point3f ¢er, float radius, int sphere_resolu vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(sphere->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -243,7 +243,7 @@ cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(transformPD->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -279,7 +279,7 @@ cv::viz::WCircle::WCircle(const Point3f& pt, float radius, float thickness, cons vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(tf->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -310,7 +310,7 @@ cv::viz::WCylinder::WCylinder(const Point3f& pt_on_axis, const Point3f& axis_dir vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(tuber->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -342,7 +342,7 @@ cv::viz::WCube::WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_fr mapper->SetInputConnection(cube->GetOutputPort()); } - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -394,7 +394,7 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(float scale) mapper->SetScalarModeToUsePointData(); mapper->SetInputConnection(axes_tubes->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); @@ -1080,7 +1080,7 @@ cv::viz::WCameraPosition::WCameraPosition(float scale) mapper->SetScalarModeToUsePointData(); mapper->SetInputConnection(axes_tubes->GetOutputPort()); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); From 270506829055623504e6c7313524beaedfb44ebb Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 8 Dec 2013 21:00:00 +0400 Subject: [PATCH 115/295] refactored Keyboard and Mouse Events --- modules/viz/doc/viz3d.rst | 48 +++++-------- modules/viz/include/opencv2/viz/types.hpp | 84 +++++++++-------------- modules/viz/src/clouds.cpp | 2 +- modules/viz/src/interactor_style.cpp | 67 +++++++++--------- modules/viz/src/interactor_style.hpp | 9 +-- modules/viz/src/types.cpp | 59 ++++------------ modules/viz/src/vizimpl.cpp | 4 +- 7 files changed, 99 insertions(+), 174 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index 2f8dfcd9d..63c5ac34c 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -506,40 +506,28 @@ This class represents a keyboard event. :: class CV_EXPORTS KeyboardEvent { public: - static const unsigned int Alt = 1; - static const unsigned int Ctrl = 2; - static const unsigned int Shift = 4; + enum { ALT = 1, CTRL = 2, SHIFT = 4 }; + enum Action { KEY_UP = 0, KEY_DOWN = 1 }; - //! Create a keyboard event - //! - Note that action is true if key is pressed, false if released - KeyboardEvent (bool action, const std::string& key_sym, unsigned char key, bool alt, bool ctrl, bool shift); + KeyboardEvent(Action action, const String& symbol, unsigned char code, int modifiers); - bool isAltPressed () const; - bool isCtrlPressed () const; - bool isShiftPressed () const; - - unsigned char getKeyCode () const; - - const String& getKeySym () const; - bool keyDown () const; - bool keyUp () const; - - protected: - /* hidden */ + Action action; + String symbol; + unsigned char code; + int modifiers; }; viz::KeyboardEvent::KeyboardEvent --------------------------------- Constructs a KeyboardEvent. -.. ocv:function:: KeyboardEvent (bool action, const std::string& key_sym, unsigned char key, bool alt, bool ctrl, bool shift) +.. ocv:function:: KeyboardEvent (Action action, const String& symbol, unsigned char code, Modifiers modifiers) - :param action: If true, key is pressed. If false, key is released. - :param key_sym: Name of the key. - :param key: Code of the key. - :param alt: If true, ``alt`` is pressed. - :param ctrl: If true, ``ctrl`` is pressed. - :param shift: If true, ``shift`` is pressed. + :param action: Signals if key is pressed or released. + :param symbol: Name of the key. + :param code: Code of the key. + :param modifiers: Signals if ``alt``, ``ctrl`` or ``shift`` are pressed or their combination. + viz::MouseEvent --------------- @@ -553,26 +541,24 @@ This class represents a mouse event. :: enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ; enum MouseButton { NoButton = 0, LeftButton, MiddleButton, RightButton, VScroll } ; - MouseEvent (const Type& type, const MouseButton& button, const Point& p, bool alt, bool ctrl, bool shift); + MouseEvent(const Type& type, const MouseButton& button, const Point& pointer, int modifiers); Type type; MouseButton button; Point pointer; - unsigned int key_state; + int modifiers; }; viz::MouseEvent::MouseEvent --------------------------- Constructs a MouseEvent. -.. ocv:function:: MouseEvent (const Type& type, const MouseButton& button, const Point& p, bool alt, bool ctrl, bool shift) +.. ocv:function:: MouseEvent (const Type& type, const MouseButton& button, const Point& p, Modifiers modifiers) :param type: Type of the event. This can be **MouseMove**, **MouseButtonPress**, **MouseButtonRelease**, **MouseScrollDown**, **MouseScrollUp**, **MouseDblClick**. :param button: Mouse button. This can be **NoButton**, **LeftButton**, **MiddleButton**, **RightButton**, **VScroll**. :param p: Position of the event. - :param alt: If true, ``alt`` is pressed. - :param ctrl: If true, ``ctrl`` is pressed. - :param shift: If true, ``shift`` is pressed. + :param modifiers: Signals if ``alt``, ``ctrl`` or ``shift`` are pressed or their combination. viz::Camera ----------- diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 780f200ed..9a88b46ea 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_TYPES_HPP__ @@ -121,56 +118,13 @@ namespace cv struct loadMeshImpl; }; - class CV_EXPORTS KeyboardEvent - { - public: - static const unsigned int Alt = 1; - static const unsigned int Ctrl = 2; - static const unsigned int Shift = 4; - - //! Create a keyboard event - //! - Note that action is true if key is pressed, false if released - KeyboardEvent(bool action, const String& key_sym, unsigned char key, bool alt, bool ctrl, bool shift); - - bool isAltPressed() const; - bool isCtrlPressed() const; - bool isShiftPressed() const; - - unsigned char getKeyCode() const; - - const String& getKeySym() const; - bool keyDown() const; - bool keyUp() const; - - protected: - - bool action_; - unsigned int modifiers_; - unsigned char key_code_; - String key_sym_; - }; - - class CV_EXPORTS MouseEvent - { - public: - enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ; - enum MouseButton { NoButton = 0, LeftButton, MiddleButton, RightButton, VScroll } ; - - MouseEvent(const Type& type, const MouseButton& button, const Point& p, bool alt, bool ctrl, bool shift); - - Type type; - MouseButton button; - Point pointer; - unsigned int key_state; - }; - class CV_EXPORTS Camera { public: - Camera(float f_x, float f_y, float c_x, float c_y, const Size &window_size); - Camera(const Vec2f &fov, const Size &window_size); - Camera(const cv::Matx33f &K, const Size &window_size); - Camera(const cv::Matx44f &proj, const Size &window_size); + Camera(float fx, float fy, float cx, float cy, const Size &window_size); + explicit Camera(const Vec2f &fov, const Size &window_size); + explicit Camera(const cv::Matx33f &K, const Size &window_size); + explicit Camera(const cv::Matx44f &proj, const Size &window_size); inline const Vec2d & getClip() const { return clip_; } inline void setClip(const Vec2d &clip) { clip_ = clip; } @@ -189,7 +143,7 @@ namespace cv static Camera KinectCamera(const Size &window_size); private: - void init(float f_x, float f_y, float c_x, float c_y, const Size &window_size); + void init(float fx, float fy, float cx, float cy, const Size &window_size); Vec2d clip_; Vec2f fov_; @@ -197,6 +151,34 @@ namespace cv Vec2f principal_point_; Vec2f focal_; }; + + class CV_EXPORTS KeyboardEvent + { + public: + enum { NONE = 0, ALT = 1, CTRL = 2, SHIFT = 4 }; + enum Action { KEY_UP = 0, KEY_DOWN = 1 }; + + KeyboardEvent(Action action, const String& symbol, unsigned char code, int modifiers); + + Action action; + String symbol; + unsigned char code; + int modifiers; + }; + + class CV_EXPORTS MouseEvent + { + public: + enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ; + enum MouseButton { NoButton = 0, LeftButton, MiddleButton, RightButton, VScroll } ; + + MouseEvent(const Type& type, const MouseButton& button, const Point& pointer, int modifiers); + + Type type; + MouseButton button; + Point pointer; + int modifiers; + }; } /* namespace viz */ } /* namespace cv */ diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index d43ae2d4f..7da425c38 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -185,7 +185,7 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) mapper->SetInputData(polydata); #endif - Vec3d minmax(scalars->GetRange()); + Vec2d minmax(scalars->GetRange()); mapper->SetScalarRange(minmax.val); mapper->SetScalarModeToUsePointData(); diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 78f2ac680..74340ca8d 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -51,7 +51,6 @@ ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::InteractorStyle::Initialize() { - modifier_ = cv::viz::InteractorStyle::KB_MOD_ALT; // Set windows size (width, height) to unknown (-1) win_size_ = Vec2i(-1, -1); win_pos_ = Vec2i(0, 0); @@ -121,13 +120,7 @@ void cv::viz::InteractorStyle::OnChar() else if (key.find("XF86ZoomOut") != String::npos) zoomOut(); - int keymod = false; - switch (modifier_) - { - case KB_MOD_ALT: keymod = Interactor->GetAltKey(); break; - case KB_MOD_CTRL: keymod = Interactor->GetControlKey(); break; - case KB_MOD_SHIFT: keymod = Interactor->GetShiftKey(); break; - } + int keymod = Interactor->GetAltKey(); switch (Interactor->GetKeyCode()) { @@ -184,6 +177,21 @@ bool cv::viz::InteractorStyle::getAltKey() { return Interactor->GetAltKey() != 0 bool cv::viz::InteractorStyle::getShiftKey() { return Interactor->GetShiftKey()!= 0; } bool cv::viz::InteractorStyle::getControlKey() { return Interactor->GetControlKey()!= 0; } +int cv::viz::InteractorStyle::getModifiers() +{ + int modifiers = KeyboardEvent::NONE; + + if (Interactor->GetAltKey()) + modifiers |= KeyboardEvent::ALT; + + if (Interactor->GetControlKey()) + modifiers |= KeyboardEvent::CTRL; + + if (Interactor->GetShiftKey()) + modifiers |= KeyboardEvent::SHIFT; + return modifiers; +} + ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::InteractorStyle::OnKeyDown() @@ -204,19 +212,7 @@ cv::viz::InteractorStyle::OnKeyDown() if (win_size_[0] == -1 || win_size_[1] == -1) win_size_ = Vec2i(Interactor->GetRenderWindow()->GetSize()); - - // Get the status of special keys (Cltr+Alt+Shift) - bool shift = getShiftKey(); - bool ctrl = getControlKey(); - bool alt = getAltKey(); - - bool keymod = false; - switch (modifier_) - { - case KB_MOD_ALT: keymod = alt; break; - case KB_MOD_CTRL: keymod = ctrl; break; - case KB_MOD_SHIFT: keymod = shift; break; - } + bool alt = getAltKey(); std::string key(Interactor->GetKeySym()); if (key.find("XF86ZoomIn") != std::string::npos) @@ -344,7 +340,7 @@ cv::viz::InteractorStyle::OnKeyDown() // Switch between maximize and original window size case 'f': case 'F': { - if (keymod) + if (alt) { Vec2i screen_size(Interactor->GetRenderWindow()->GetScreenSize()); Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); @@ -386,7 +382,7 @@ cv::viz::InteractorStyle::OnKeyDown() // 's'/'S' w/out ALT case 's': case 'S': { - if (keymod) + if (alt) { int stereo_render = Interactor->GetRenderWindow()->GetStereoRender(); if (!stereo_render) @@ -423,7 +419,7 @@ cv::viz::InteractorStyle::OnKeyDown() // Overwrite the camera reset case 'r': case 'R': { - if (!keymod) + if (!alt) { Superclass::OnKeyDown(); break; @@ -491,7 +487,8 @@ cv::viz::InteractorStyle::OnKeyDown() } } - KeyboardEvent event(true, Interactor->GetKeySym(), Interactor->GetKeyCode(), getAltKey(), getControlKey(), getShiftKey()); + + KeyboardEvent event(KeyboardEvent::KEY_DOWN, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); // Check if there is a keyboard callback registered if (keyboardCallback_) keyboardCallback_(event, keyboard_callback_cookie_); @@ -503,7 +500,7 @@ cv::viz::InteractorStyle::OnKeyDown() ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::InteractorStyle::OnKeyUp() { - KeyboardEvent event(false, Interactor->GetKeySym(), Interactor->GetKeyCode(), getAltKey(), getControlKey(), getShiftKey()); + KeyboardEvent event(KeyboardEvent::KEY_UP, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); // Check if there is a keyboard callback registered if (keyboardCallback_) keyboardCallback_(event, keyboard_callback_cookie_); @@ -515,7 +512,7 @@ void cv::viz::InteractorStyle::OnKeyUp() void cv::viz::InteractorStyle::OnMouseMove() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseMove, MouseEvent::NoButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(MouseEvent::MouseMove, MouseEvent::NoButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnMouseMove(); @@ -526,7 +523,7 @@ void cv::viz::InteractorStyle::OnLeftButtonDown() { Vec2i p(Interactor->GetEventPosition()); MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; - MouseEvent event(type, MouseEvent::LeftButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(type, MouseEvent::LeftButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnLeftButtonDown(); @@ -536,7 +533,7 @@ void cv::viz::InteractorStyle::OnLeftButtonDown() void cv::viz::InteractorStyle::OnLeftButtonUp() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::LeftButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::LeftButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnLeftButtonUp(); @@ -548,7 +545,7 @@ void cv::viz::InteractorStyle::OnMiddleButtonDown() Vec2i p(Interactor->GetEventPosition()); MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; - MouseEvent event(type, MouseEvent::MiddleButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(type, MouseEvent::MiddleButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnMiddleButtonDown(); @@ -558,7 +555,7 @@ void cv::viz::InteractorStyle::OnMiddleButtonDown() void cv::viz::InteractorStyle::OnMiddleButtonUp() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::MiddleButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::MiddleButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnMiddleButtonUp(); @@ -570,7 +567,7 @@ void cv::viz::InteractorStyle::OnRightButtonDown() Vec2i p(Interactor->GetEventPosition()); MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; - MouseEvent event(type, MouseEvent::RightButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(type, MouseEvent::RightButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnRightButtonDown(); @@ -580,7 +577,7 @@ void cv::viz::InteractorStyle::OnRightButtonDown() void cv::viz::InteractorStyle::OnRightButtonUp() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::RightButton, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::RightButton, p, getModifiers()); if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); Superclass::OnRightButtonUp(); @@ -590,7 +587,7 @@ void cv::viz::InteractorStyle::OnRightButtonUp() void cv::viz::InteractorStyle::OnMouseWheelForward() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getModifiers()); // If a mouse callback registered, call it! if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); @@ -622,7 +619,7 @@ void cv::viz::InteractorStyle::OnMouseWheelForward() void cv::viz::InteractorStyle::OnMouseWheelBackward() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getAltKey(), getControlKey(), getShiftKey()); + MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getModifiers()); // If a mouse callback registered, call it! if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/interactor_style.hpp index 3af13fcc4..3141bbeaa 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/interactor_style.hpp @@ -56,9 +56,6 @@ namespace cv class InteractorStyle : public vtkInteractorStyleTrackballCamera { public: - - enum KeyboardModifier { KB_MOD_ALT, KB_MOD_CTRL, KB_MOD_SHIFT }; - static InteractorStyle *New(); virtual ~InteractorStyle() {} @@ -74,9 +71,6 @@ namespace cv void registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void * cookie = 0); void saveScreenshot(const String &file); - /** \brief Change the default keyboard modified from ALT to a different special key.*/ - inline void setKeyboardModifier(const KeyboardModifier &modifier) { modifier_ = modifier; } - private: /** \brief Set to true after initialization is complete. */ bool init_; @@ -121,8 +115,6 @@ namespace cv /** \brief True if we're using red-blue colors for anaglyphic stereo, false if magenta-green. */ bool stereo_anaglyph_mask_default_; - KeyboardModifier modifier_; - void (*keyboardCallback_)(const KeyboardEvent&, void*); void *keyboard_callback_cookie_; @@ -132,6 +124,7 @@ namespace cv bool getAltKey(); bool getControlKey(); bool getShiftKey(); + int getModifiers(); }; } } diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index f0be75f65..e3537c475 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -49,44 +49,13 @@ #include "precomp.hpp" //////////////////////////////////////////////////////////////////// -/// cv::viz::KeyboardEvent +/// Events -cv::viz::KeyboardEvent::KeyboardEvent(bool _action, const String& _key_sym, unsigned char key, bool alt, bool ctrl, bool shift) - : action_(_action), modifiers_(0), key_code_(key), key_sym_(_key_sym) -{ - if (alt) - modifiers_ = Alt; +cv::viz::KeyboardEvent::KeyboardEvent(Action _action, const String& _symbol, unsigned char _code, int _modifiers) + : action(_action), symbol(_symbol), code(_code), modifiers(_modifiers) {} - if (ctrl) - modifiers_ |= Ctrl; - - if (shift) - modifiers_ |= Shift; -} - -bool cv::viz::KeyboardEvent::isAltPressed() const { return (modifiers_ & Alt) != 0; } -bool cv::viz::KeyboardEvent::isCtrlPressed() const { return (modifiers_ & Ctrl) != 0; } -bool cv::viz::KeyboardEvent::isShiftPressed() const { return (modifiers_ & Shift) != 0; } -unsigned char cv::viz::KeyboardEvent::getKeyCode() const { return key_code_; } -const cv::String& cv::viz::KeyboardEvent::getKeySym() const { return key_sym_; } -bool cv::viz::KeyboardEvent::keyDown() const { return action_; } -bool cv::viz::KeyboardEvent::keyUp() const { return !action_; } - -//////////////////////////////////////////////////////////////////// -/// cv::viz::MouseEvent - -cv::viz::MouseEvent::MouseEvent(const Type& _type, const MouseButton& _button, const Point& _p, bool alt, bool ctrl, bool shift) - : type(_type), button(_button), pointer(_p), key_state(0) -{ - if (alt) - key_state = KeyboardEvent::Alt; - - if (ctrl) - key_state |= KeyboardEvent::Ctrl; - - if (shift) - key_state |= KeyboardEvent::Shift; -} +cv::viz::MouseEvent::MouseEvent(const Type& _type, const MouseButton& _button, const Point& _pointer, int _modifiers) + : type(_type), button(_button), pointer(_pointer), modifiers(_modifiers) {} //////////////////////////////////////////////////////////////////// /// cv::viz::Mesh3d @@ -167,9 +136,9 @@ cv::viz::Mesh3d cv::viz::Mesh3d::loadMesh(const String& file) //////////////////////////////////////////////////////////////////// /// Camera implementation -cv::viz::Camera::Camera(float f_x, float f_y, float c_x, float c_y, const Size &window_size) +cv::viz::Camera::Camera(float fx, float fy, float cx, float cy, const Size &window_size) { - init(f_x, f_y, c_x, c_y, window_size); + init(fx, fy, cx, cy, window_size); } cv::viz::Camera::Camera(const Vec2f &fov, const Size &window_size) @@ -220,19 +189,19 @@ cv::viz::Camera::Camera(const Matx44f &proj, const Size &window_size) window_size_ = window_size; } -void cv::viz::Camera::init(float f_x, float f_y, float c_x, float c_y, const Size &window_size) +void cv::viz::Camera::init(float fx, float fy, float cx, float cy, const Size &window_size) { CV_Assert(window_size.width > 0 && window_size.height > 0); setClip(Vec2d(0.01, 1000.01));// Default clipping - fov_[0] = (atan2(c_x,f_x) + atan2(window_size.width-c_x,f_x)); - fov_[1] = (atan2(c_y,f_y) + atan2(window_size.height-c_y,f_y)); + fov_[0] = (atan2(cx,fx) + atan2(window_size.width-cx,fx)); + fov_[1] = (atan2(cy,fy) + atan2(window_size.height-cy,fy)); - principal_point_[0] = c_x; - principal_point_[1] = c_y; + principal_point_[0] = cx; + principal_point_[1] = cy; - focal_[0] = f_x; - focal_[1] = f_y; + focal_[0] = fx; + focal_[1] = fy; window_size_ = window_size; } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index af3f93b71..7702d973d 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -247,9 +247,7 @@ void cv::viz::Viz3d::VizImpl::setDesiredUpdateRate(double rate) ///////////////////////////////////////////////////////////////////////////////////////////// double cv::viz::Viz3d::VizImpl::getDesiredUpdateRate() { - if (interactor_) - return interactor_->GetDesiredUpdateRate(); - return 0.0; + return interactor_ ? interactor_->GetDesiredUpdateRate() : 0.0; } ///////////////////////////////////////////////////////////////////////////////////////////// From 159de9cc477123429941f0ad7582f2c17a241b70 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 12 Dec 2013 22:05:10 +0400 Subject: [PATCH 116/295] fixed potential crash --- modules/viz/src/clouds.cpp | 11 +++++------ modules/viz/src/widget.cpp | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 7da425c38..ec83676ee 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -334,7 +334,7 @@ namespace cv { namespace viz { namespace return polydata; } - static void createMapper(vtkSmartPointer actor, vtkSmartPointer poly_data, Vec3d& minmax) + static void createMapper(vtkSmartPointer actor, vtkSmartPointer poly_data) { vtkDataSetMapper *mapper = vtkDataSetMapper::SafeDownCast(actor->GetMapper()); if (!mapper) @@ -347,7 +347,7 @@ namespace cv { namespace viz { namespace mapper_new->SetInputData(poly_data); #endif - mapper_new->SetScalarRange(minmax.val); + mapper_new->SetScalarRange(0, 255); mapper_new->SetScalarModeToUsePointData(); bool interpolation = (poly_data && poly_data->GetNumberOfCells() != poly_data->GetNumberOfVerts()); @@ -435,8 +435,8 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, vtkLODActor *actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Incompatible widget type." && actor); - Vec3d minmax(scalars->GetRange()); - CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput(), minmax); + + CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); } void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3f &pose) @@ -474,8 +474,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, vtkLODActor *actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Incompatible widget type." && actor); - Vec3d minmax(scalars->GetRange()); - CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput(), minmax); + CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); } template<> cv::viz::WCloudCollection cv::viz::Widget::cast() diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index 5c2df04dc..c16d27ae3 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -102,7 +102,7 @@ cv::viz::Widget cv::viz::Widget::fromPlyFile(const String &file_name) vtkSmartPointer scalars = data->GetPointData()->GetScalars(); if (scalars) { - cv::Vec3d minmax(scalars->GetRange()); + cv::Vec2d minmax(scalars->GetRange()); mapper->SetScalarRange(minmax.val); mapper->SetScalarModeToUsePointData(); From 7dbf6bc8df019240ff6f07bcb52e4d078c9a087c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 12 Dec 2013 23:21:55 +0400 Subject: [PATCH 117/295] rewrote cloud widget in vtk filters style Conflicts: modules/viz/src/clouds.cpp --- modules/viz/src/clouds.cpp | 153 ++-------------- modules/viz/src/precomp.hpp | 4 + .../viz/src/vtk/vtkCloudColorMatSource.cpp | 168 ++++++++++++++++++ modules/viz/src/vtk/vtkCloudColorMatSource.h | 88 +++++++++ modules/viz/src/vtk/vtkCloudMatSource.cpp | 105 +++++++++++ modules/viz/src/vtk/vtkCloudMatSource.h | 83 +++++++++ modules/viz/src/vtk/vtkColorMatSource.cpp | 132 ++++++++++++++ modules/viz/src/vtk/vtkColorMatSource.h | 82 +++++++++ 8 files changed, 675 insertions(+), 140 deletions(-) create mode 100644 modules/viz/src/vtk/vtkCloudColorMatSource.cpp create mode 100644 modules/viz/src/vtk/vtkCloudColorMatSource.h create mode 100644 modules/viz/src/vtk/vtkCloudMatSource.cpp create mode 100644 modules/viz/src/vtk/vtkCloudMatSource.h create mode 100644 modules/viz/src/vtk/vtkColorMatSource.cpp create mode 100644 modules/viz/src/vtk/vtkColorMatSource.h diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index ec83676ee..3d8105c3f 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -59,103 +59,10 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// /// Point Cloud Widget implementation -namespace cv { namespace viz { namespace -{ - struct CloudUtils - { - static inline vtkSmartPointer create(const Mat &cloud, vtkIdType &nr_points) - { - vtkSmartPointer polydata = vtkSmartPointer::New(); - vtkSmartPointer vertices = vtkSmartPointer::New(); - - polydata->SetVerts(vertices); - - vtkSmartPointer points = polydata->GetPoints(); - vtkSmartPointer initcells; - nr_points = cloud.total(); - - if (!points) - { - points = vtkSmartPointer::New(); - if (cloud.depth() == CV_32F) - points->SetDataTypeToFloat(); - else if (cloud.depth() == CV_64F) - points->SetDataTypeToDouble(); - polydata->SetPoints(points); - } - points->SetNumberOfPoints(nr_points); - - if (cloud.depth() == CV_32F) - { - // Get a pointer to the beginning of the data array - Vec3f *data_beg = vtkpoints_data(points); - Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - else if (cloud.depth() == CV_64F) - { - // Get a pointer to the beginning of the data array - Vec3d *data_beg = vtkpoints_data(points); - Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - points->SetNumberOfPoints(nr_points); - - // Update cells - vtkSmartPointer cells = vertices->GetData(); - // If no init cells and cells has not been initialized... - if (!cells) - cells = vtkSmartPointer::New(); - - // If we have less values then we need to recreate the array - if (cells->GetNumberOfTuples() < nr_points) - { - cells = vtkSmartPointer::New(); - - // If init cells is given, and there's enough data in it, use it - if (initcells && initcells->GetNumberOfTuples() >= nr_points) - { - cells->DeepCopy(initcells); - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - } - else - { - // If the number of tuples is still too small, we need to recreate the array - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - vtkIdType *cell = cells->GetPointer(0); - // Fill it with 1s - std::fill(cell, cell + nr_points * 2, 1); - cell++; - for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) - *cell = i; - // Save the results in initcells - initcells = vtkSmartPointer::New(); - initcells->DeepCopy(cells); - } - } - else - { - // The assumption here is that the current set of cells has more data than needed - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - } - - // Set the cells and the vertices - vertices->SetCells(nr_points, cells); - return polydata; - } - }; -}}} - - cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) { Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); - CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); - CV_Assert(colors.depth() == CV_8U && cloud.size() == colors.size()); if (cloud.isContinuous() && colors.isContinuous()) { @@ -163,41 +70,18 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) colors = colors.reshape(colors.channels(), 1); } - vtkIdType nr_points; - vtkSmartPointer polydata = CloudUtils::create(cloud, nr_points); - - // Filter colors - Vec3b* colors_data = new Vec3b[nr_points]; - NanFilter::copyColor(colors, colors_data, cloud); - - vtkSmartPointer scalars = vtkSmartPointer::New(); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(nr_points); - scalars->SetArray(colors_data->val, 3 * nr_points, 0); - - // Assign the colors - polydata->GetPointData()->SetScalars(scalars); + vtkSmartPointer cloud_source = vtkSmartPointer::New(); + cloud_source->SetCloud(cloud); + cloud_source->SetColors(colors, cloud); vtkSmartPointer mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(polydata); -#else - mapper->SetInputData(polydata); -#endif - - Vec2d minmax(scalars->GetRange()); - mapper->SetScalarRange(minmax.val); + mapper->SetInputConnection(cloud_source->GetOutputPort()); mapper->SetScalarModeToUsePointData(); - - bool interpolation = (polydata && polydata->GetNumberOfCells() != polydata->GetNumberOfVerts()); - - mapper->SetInterpolateScalarsBeforeMapping(interpolation); + mapper->ImmediateModeRenderingOff(); + mapper->SetScalarRange(0, 255); mapper->ScalarVisibilityOn(); - mapper->ImmediateModeRenderingOff(); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetNumberOfCloudPoints(int(std::max(1, polydata->GetNumberOfPoints() / 10))); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->GetProperty()->SetInterpolationToFlat(); actor->GetProperty()->BackfaceCullingOn(); actor->SetMapper(mapper); @@ -208,27 +92,16 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) cv::viz::WCloud::WCloud(InputArray _cloud, const Color &color) { Mat cloud = _cloud.getMat(); - CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); - vtkIdType nr_points; - vtkSmartPointer polydata = CloudUtils::create(cloud, nr_points); + vtkSmartPointer cloud_source = vtkSmartPointer::New(); + cloud_source->SetCloud(cloud); vtkSmartPointer mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(polydata); -#else - mapper->SetInputData(polydata); -#endif - - bool interpolation = (polydata && polydata->GetNumberOfCells() != polydata->GetNumberOfVerts()); - - mapper->SetInterpolateScalarsBeforeMapping(interpolation); + mapper->SetInputConnection(cloud_source->GetOutputPort()); + mapper->ImmediateModeRenderingOff(); mapper->ScalarVisibilityOff(); - mapper->ImmediateModeRenderingOff(); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetNumberOfCloudPoints(int(std::max(1, polydata->GetNumberOfPoints() / 10))); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->GetProperty()->SetInterpolationToFlat(); actor->GetProperty()->BackfaceCullingOn(); actor->SetMapper(mapper); @@ -435,8 +308,8 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, vtkLODActor *actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Incompatible widget type." && actor); - CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); + } void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3f &pose) diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 24b7e3f97..7741dc7df 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -114,6 +114,10 @@ #include #include +#include +#include +#include + #include #include #include diff --git a/modules/viz/src/vtk/vtkCloudColorMatSource.cpp b/modules/viz/src/vtk/vtkCloudColorMatSource.cpp new file mode 100644 index 000000000..8979873eb --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudColorMatSource.cpp @@ -0,0 +1,168 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkCloudColorMatSource); + + struct IsNotNan + { + template + bool operator()(const _Tp* data) const + { + return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); + } + }; +}} + +cv::viz::vtkCloudColorMatSource::vtkCloudColorMatSource() { SetNumberOfInputPorts(0); } +cv::viz::vtkCloudColorMatSource::~vtkCloudColorMatSource() {} + +void cv::viz::vtkCloudColorMatSource::SetCloud(const Mat& cloud) +{ + CV_Assert(cloud.depth() == CV_32F || cloud.depth() == CV_64F); + CV_Assert(cloud.channels() == 3 || cloud.channels() == 4); + + int total = cloud.depth() == CV_32F ? filterNanCopy(cloud, VTK_FLOAT) + : filterNanCopy(cloud, VTK_DOUBLE); + + vertices = vtkSmartPointer::New(); + vertices->Allocate(vertices->EstimateSize(1, total)); + vertices->InsertNextCell(total); + for(int i = 0; i < total; ++i) + vertices->InsertCellPoint(i); +} + +void cv::viz::vtkCloudColorMatSource::SetColors(const Mat &colors, const Mat &cloud_mask) +{ + CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); + CV_Assert(cloud_mask.depth() == CV_32F || cloud_mask.depth() == CV_64F); + CV_Assert(colors.size() == cloud_mask.size()); + + if (cloud_mask.depth() == CV_32F) + filterNanCopy(colors, cloud_mask); + else if (cloud_mask.depth() == CV_64F) + filterNanCopy(colors, cloud_mask); +} + +int cv::viz::vtkCloudColorMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->SetPoints(points); + output->SetVerts(vertices); + output->GetPointData()->SetScalars(scalars); + return 1; +} + +template +int cv::viz::vtkCloudColorMatSource::filterNanCopy(const Mat& source, int dataType) +{ + CV_DbgAssert(DataType<_Tp>::depth == source.depth()); + points = vtkSmartPointer::New(); + points->SetDataType(dataType); + points->Allocate(source.total()); + points->SetNumberOfPoints(source.total()); + + int cn = source.channels(); + int total = 0; + for (int y = 0; y < source.rows; ++y) + { + const _Tp* srow = source.ptr<_Tp>(y); + const _Tp* send = srow + source.cols * cn; + + for (; srow != send; srow += cn) + if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) + points->SetPoint(total++, srow); + } + points->SetNumberOfPoints(total); + points->Squeeze(); + return total; +} + +template +void cv::viz::vtkCloudColorMatSource::filterNanCopy(const Mat& colors, const Mat& mask) +{ + Mat buffer(colors.size(), CV_8UC3); + Vec3b* pos = buffer.ptr(); + + int s_chs = colors.channels(); + int m_chs = mask.channels(); + + _NanPred pred; + + for (int y = 0; y < colors.rows; ++y) + { + const unsigned char* srow = colors.ptr(y); + const unsigned char* send = srow + colors.cols * colors.channels(); + const _Msk* mrow = mask.empty() ? 0 : mask.ptr<_Msk>(y); + + if (colors.channels() == 1) + { + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[0], srow[0], srow[0]); + } + else + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[2], srow[1], srow[0]); + + } + + int total = pos - buffer.ptr(); + Vec3b* array = new Vec3b[total]; + std::copy(buffer.ptr(), pos, array); + + scalars = vtkSmartPointer::New(); + scalars->SetName("colors"); + scalars->SetNumberOfComponents(3); + scalars->SetNumberOfTuples(total); + scalars->SetArray(array->val, total * 3, 0); +} + + diff --git a/modules/viz/src/vtk/vtkCloudColorMatSource.h b/modules/viz/src/vtk/vtkCloudColorMatSource.h new file mode 100644 index 000000000..0aa5b87a3 --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudColorMatSource.h @@ -0,0 +1,88 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#ifndef __vtkCloudColorMatSource_h +#define __vtkCloudColorMatSource_h + +#include +#include +#include +#include +#include + +namespace cv +{ + namespace viz + { + class vtkCloudColorMatSource : public vtkPolyDataAlgorithm + { + public: + static vtkCloudColorMatSource *New(); + vtkTypeMacro(vtkCloudColorMatSource,vtkPolyDataAlgorithm); + + virtual void SetCloud(const Mat& cloud); + virtual void SetColors(const Mat &colors, const Mat &cloud_mask); + + protected: + vtkCloudColorMatSource(); + ~vtkCloudColorMatSource(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkSmartPointer points; + vtkSmartPointer vertices; + vtkSmartPointer scalars; + private: + vtkCloudColorMatSource(const vtkCloudColorMatSource&); // Not implemented. + void operator=(const vtkCloudColorMatSource&); // Not implemented. + + template int filterNanCopy(const Mat& source, int dataType); + + template + void filterNanCopy(const Mat& colors, const Mat& mask); + }; + } +} + +#endif diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp new file mode 100644 index 000000000..a27653a4f --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -0,0 +1,105 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkCloudMatSource); +}} + +cv::viz::vtkCloudMatSource::vtkCloudMatSource() { SetNumberOfInputPorts(0); } +cv::viz::vtkCloudMatSource::~vtkCloudMatSource() {} + +void cv::viz::vtkCloudMatSource::SetCloud(const Mat& cloud) +{ + CV_Assert(cloud.depth() == CV_32F || cloud.depth() == CV_64F); + CV_Assert(cloud.channels() == 3 || cloud.channels() == 4); + + int total = cloud.depth() == CV_32F ? filterNanCopy(cloud, VTK_FLOAT) + : filterNanCopy(cloud, VTK_DOUBLE); + + vertices = vtkSmartPointer::New(); + vertices->Allocate(vertices->EstimateSize(1, total)); + vertices->InsertNextCell(total); + for(int i = 0; i < total; ++i) + vertices->InsertCellPoint(i); +} + +int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->SetPoints(points); + output->SetVerts(vertices); + return 1; +} + +template +int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& source, int dataType) +{ + CV_DbgAssert(DataType<_Tp>::depth == source.depth()); + points = vtkSmartPointer::New(); + points->SetDataType(dataType); + points->Allocate(source.total()); + points->SetNumberOfPoints(source.total()); + + int cn = source.channels(); + int total = 0; + for (int y = 0; y < source.rows; ++y) + { + const _Tp* srow = source.ptr<_Tp>(y); + const _Tp* send = srow + source.cols * cn; + + for (; srow != send; srow += cn) + if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) + points->SetPoint(total++, srow); + } + points->SetNumberOfPoints(total); + points->Squeeze(); + return total; +} + + diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h new file mode 100644 index 000000000..6a8dbebd1 --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -0,0 +1,83 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#ifndef __vtkCloudMatSource_h +#define __vtkCloudMatSource_h + +#include +#include +#include +#include +#include + +namespace cv +{ + namespace viz + { + class vtkCloudMatSource : public vtkPolyDataAlgorithm + { + public: + static vtkCloudMatSource *New(); + vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm); + + virtual void SetCloud(const Mat& cloud); + + protected: + vtkCloudMatSource(); + ~vtkCloudMatSource(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkSmartPointer points; + vtkSmartPointer vertices; + private: + vtkCloudMatSource(const vtkCloudMatSource&); // Not implemented. + void operator=(const vtkCloudMatSource&); // Not implemented. + + template int filterNanCopy(const Mat& source, int dataType); + }; + } +} + +#endif diff --git a/modules/viz/src/vtk/vtkColorMatSource.cpp b/modules/viz/src/vtk/vtkColorMatSource.cpp new file mode 100644 index 000000000..aa09a2d49 --- /dev/null +++ b/modules/viz/src/vtk/vtkColorMatSource.cpp @@ -0,0 +1,132 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkColorMatSource); + + struct IsNotNan + { + template + bool operator()(const _Tp* data) const + { + return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); + } + }; + + struct AllOk + { + template + bool operator()(const _Tp*) const { return true; } + }; +}} + +cv::viz::vtkColorMatSource::vtkColorMatSource() { SetNumberOfInputPorts(0); } +cv::viz::vtkColorMatSource::~vtkColorMatSource() {} + +void cv::viz::vtkColorMatSource::SetColors(const Mat &colors, const Mat& mask) +{ + CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); + CV_Assert(mask.empty() || mask.depth() == CV_32F || mask.depth() == CV_64F); + + if (!mask.empty() && mask.depth() == CV_32F) + filterNanCopy(colors, mask); + else if (!mask.empty() && mask.depth() == CV_64F) + filterNanCopy(colors, mask); + else /* mask.empty() */ + filterNanCopy(colors, mask); +} + +int cv::viz::vtkColorMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->GetPointData()->SetScalars(scalars); + + return 1; +} + +template +void cv::viz::vtkColorMatSource::filterNanCopy(const Mat& colors, const Mat& cloud_mask) +{ + Mat buffer(colors.size(), CV_8UC3); + Vec3b* pos = buffer.ptr(); + + int s_chs = colors.channels(); + int m_chs = cloud_mask.channels(); + + _NanPred pred; + + for (int y = 0; y < colors.rows; ++y) + { + const unsigned char* srow = colors.ptr(y); + const unsigned char* send = srow + colors.cols * colors.channels(); + const _Msk* mrow = cloud_mask.empty() ? 0 : cloud_mask.ptr<_Msk>(y); + + if (colors.channels() == 1) + { + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[0], srow[0], srow[0]); + } + else + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[2], srow[1], srow[0]); + + } + + int total = pos - buffer.ptr(); + Vec3b* array = new Vec3b[total]; + std::copy(buffer.ptr(), pos, array); + + scalars = vtkSmartPointer::New(); + scalars->SetName("colors"); + scalars->SetNumberOfComponents(3); + scalars->SetNumberOfTuples(total); + scalars->SetArray(array->val, total * 3, 0); +} diff --git a/modules/viz/src/vtk/vtkColorMatSource.h b/modules/viz/src/vtk/vtkColorMatSource.h new file mode 100644 index 000000000..d1650faad --- /dev/null +++ b/modules/viz/src/vtk/vtkColorMatSource.h @@ -0,0 +1,82 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#ifndef __vtkColorMatSource_h +#define __vtkColorMatSource_h + +#include +#include +#include + +namespace cv +{ + namespace viz + { + class vtkColorMatSource : public vtkPolyDataAlgorithm + { + public: + static vtkColorMatSource *New(); + vtkTypeMacro(vtkColorMatSource,vtkPolyDataAlgorithm); + + virtual void SetColors(const Mat &colors, const Mat &cloud_mask = Mat()); + + + protected: + vtkColorMatSource(); + ~vtkColorMatSource(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkSmartPointer scalars; + private: + vtkColorMatSource(const vtkColorMatSource&); // Not implemented. + void operator=(const vtkColorMatSource&); // Not implemented. + + template + void filterNanCopy(const Mat& colors, const Mat& mask); + }; + } +} + +#endif From 80ab6e889fc30ef42dd5420e3f372db192284927 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 12 Dec 2013 23:46:41 +0400 Subject: [PATCH 118/295] refactoring --- modules/viz/include/opencv2/viz/types.hpp | 9 +- modules/viz/include/opencv2/viz/viz3d.hpp | 4 +- modules/viz/include/opencv2/viz/widgets.hpp | 12 +- modules/viz/src/clouds.cpp | 12 +- modules/viz/src/interactor_style.cpp | 58 +++++----- modules/viz/src/interactor_style.hpp | 6 - modules/viz/src/shapes.cpp | 46 ++------ modules/viz/src/types.cpp | 122 ++++++++++---------- modules/viz/src/viz3d.cpp | 7 +- modules/viz/src/vizimpl.cpp | 16 +-- modules/viz/src/vizimpl.hpp | 7 +- modules/viz/src/widget.cpp | 114 ++++-------------- 12 files changed, 147 insertions(+), 266 deletions(-) diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 9a88b46ea..ab5aafc38 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -112,10 +112,7 @@ namespace cv Mat polygons; //! Loads mesh from a given ply file - static cv::viz::Mesh3d loadMesh(const String& file); - - private: - struct loadMeshImpl; + static Mesh3d loadMesh(const String& file); }; class CV_EXPORTS Camera @@ -123,8 +120,8 @@ namespace cv public: Camera(float fx, float fy, float cx, float cy, const Size &window_size); explicit Camera(const Vec2f &fov, const Size &window_size); - explicit Camera(const cv::Matx33f &K, const Size &window_size); - explicit Camera(const cv::Matx44f &proj, const Size &window_size); + explicit Camera(const Matx33f &K, const Size &window_size); + explicit Camera(const Matx44f &proj, const Size &window_size); inline const Vec2d & getClip() const { return clip_; } inline void setClip(const Vec2d &clip) { clip_ = clip; } diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index d3f5a109c..1b31b2447 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -94,8 +94,8 @@ namespace cv void setWindowSize(const Size &window_size); String getWindowName() const; void saveScreenshot(const String &file); - void setWindowPosition(int x, int y); - void setFullScreen(bool mode); + void setWindowPosition(const Point& window_position); + void setFullScreen(bool mode = true); void setBackgroundColor(const Color& color = Color::black()); void spin(); diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 0b0c5fc28..1f48686f4 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -245,13 +245,13 @@ namespace cv //! Creates camera coordinate frame (axes) at the origin WCameraPosition(float scale = 1.f); //! Creates frustum based on the intrinsic marix K at the origin - explicit WCameraPosition(const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum based on the field of view at the origin - explicit WCameraPosition(const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - explicit WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - explicit WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); }; ///////////////////////////////////////////////////////////////////////////// @@ -270,9 +270,9 @@ namespace cv { public: //! Displays trajectory of the given path by frustums - explicit WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - explicit WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectorySpheres: public Widget3D diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 3d8105c3f..8549acafd 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" @@ -61,6 +58,8 @@ namespace cv cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) { + CV_Assert(!_cloud.empty() && !_colors.empty()); + Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); @@ -74,7 +73,7 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) cloud_source->SetCloud(cloud); cloud_source->SetColors(colors, cloud); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(cloud_source->GetOutputPort()); mapper->SetScalarModeToUsePointData(); mapper->ImmediateModeRenderingOff(); @@ -96,7 +95,7 @@ cv::viz::WCloud::WCloud(InputArray _cloud, const Color &color) vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetCloud(cloud); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(cloud_source->GetOutputPort()); mapper->ImmediateModeRenderingOff(); mapper->ScalarVisibilityOff(); @@ -213,7 +212,7 @@ namespace cv { namespace viz { namespace if (!mapper) { // This is the first cloud - vtkSmartPointer mapper_new = vtkSmartPointer::New(); + vtkSmartPointer mapper_new = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 mapper_new->SetInputConnection(poly_data->GetProducerPort()); #else @@ -309,7 +308,6 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, CV_Assert("Incompatible widget type." && actor); CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); - } void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3f &pose) diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 74340ca8d..1a7c8a4c1 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -48,6 +48,13 @@ #include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(InteractorStyle) +}} + + ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::InteractorStyle::Initialize() { @@ -173,10 +180,6 @@ void cv::viz::InteractorStyle::registerKeyboardCallback(void (*callback)(const K } ////////////////////////////////////////////////////////////////////////////////////////////// -bool cv::viz::InteractorStyle::getAltKey() { return Interactor->GetAltKey() != 0; } -bool cv::viz::InteractorStyle::getShiftKey() { return Interactor->GetShiftKey()!= 0; } -bool cv::viz::InteractorStyle::getControlKey() { return Interactor->GetControlKey()!= 0; } - int cv::viz::InteractorStyle::getModifiers() { int modifiers = KeyboardEvent::NONE; @@ -212,7 +215,7 @@ cv::viz::InteractorStyle::OnKeyDown() if (win_size_[0] == -1 || win_size_[1] == -1) win_size_ = Vec2i(Interactor->GetRenderWindow()->GetSize()); - bool alt = getAltKey(); + bool alt = Interactor->GetAltKey() != 0; std::string key(Interactor->GetKeySym()); if (key.find("XF86ZoomIn") != std::string::npos) @@ -245,7 +248,7 @@ cv::viz::InteractorStyle::OnKeyDown() " ALT + s, S : turn stereo mode on/off\n" " ALT + f, F : switch between maximized window mode and original size\n" "\n" - << std::endl; + << std::endl; break; } @@ -287,8 +290,8 @@ cv::viz::InteractorStyle::OnKeyDown() double angle = cam->GetViewAngle () / 180.0 * CV_PI; String data = cv::format("clip(%f,%f) focal(%f,%f,%f) pos(%f,%f,%f) view(%f,%f,%f) angle(%f) winsz(%d,%d) winpos(%d,%d)", - clip[0], clip[1], focal[0], focal[1], focal[2], pos[0], pos[1], pos[2], view[0], view[1], view[2], - angle, win_size[0], win_size[1], win_pos[0], win_pos[1]); + clip[0], clip[1], focal[0], focal[1], focal[2], pos[0], pos[1], pos[2], view[0], view[1], view[2], + angle, win_size[0], win_size[1], win_pos[0], win_pos[1]); std::cout << data.c_str() << std::endl; @@ -416,7 +419,7 @@ cv::viz::InteractorStyle::OnKeyDown() break; } - // Overwrite the camera reset + // Overwrite the camera reset case 'r': case 'R': { if (!alt) @@ -425,8 +428,6 @@ cv::viz::InteractorStyle::OnKeyDown() break; } - vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); - static WidgetActorMap::iterator it = widget_actor_map_->begin(); // it might be that some actors don't have a valid transformation set -> we skip them to avoid a seg fault. bool found_transformation = false; @@ -444,6 +445,8 @@ cv::viz::InteractorStyle::OnKeyDown() } } + vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); + // if a valid transformation was found, use it otherwise fall back to default view point. if (found_transformation) { @@ -487,11 +490,10 @@ cv::viz::InteractorStyle::OnKeyDown() } } - KeyboardEvent event(KeyboardEvent::KEY_DOWN, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); // Check if there is a keyboard callback registered if (keyboardCallback_) - keyboardCallback_(event, keyboard_callback_cookie_); + keyboardCallback_(event, keyboard_callback_cookie_); renderer_->Render(); Interactor->Render(); @@ -503,7 +505,7 @@ void cv::viz::InteractorStyle::OnKeyUp() KeyboardEvent event(KeyboardEvent::KEY_UP, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); // Check if there is a keyboard callback registered if (keyboardCallback_) - keyboardCallback_(event, keyboard_callback_cookie_); + keyboardCallback_(event, keyboard_callback_cookie_); Superclass::OnKeyUp(); } @@ -514,7 +516,7 @@ void cv::viz::InteractorStyle::OnMouseMove() Vec2i p(Interactor->GetEventPosition()); MouseEvent event(MouseEvent::MouseMove, MouseEvent::NoButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnMouseMove(); } @@ -525,7 +527,7 @@ void cv::viz::InteractorStyle::OnLeftButtonDown() MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; MouseEvent event(type, MouseEvent::LeftButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnLeftButtonDown(); } @@ -535,7 +537,7 @@ void cv::viz::InteractorStyle::OnLeftButtonUp() Vec2i p(Interactor->GetEventPosition()); MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::LeftButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnLeftButtonUp(); } @@ -547,7 +549,7 @@ void cv::viz::InteractorStyle::OnMiddleButtonDown() MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; MouseEvent event(type, MouseEvent::MiddleButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnMiddleButtonDown(); } @@ -557,7 +559,7 @@ void cv::viz::InteractorStyle::OnMiddleButtonUp() Vec2i p(Interactor->GetEventPosition()); MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::MiddleButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnMiddleButtonUp(); } @@ -569,7 +571,7 @@ void cv::viz::InteractorStyle::OnRightButtonDown() MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; MouseEvent event(type, MouseEvent::RightButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnRightButtonDown(); } @@ -579,7 +581,7 @@ void cv::viz::InteractorStyle::OnRightButtonUp() Vec2i p(Interactor->GetEventPosition()); MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::RightButton, p, getModifiers()); if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); Superclass::OnRightButtonUp(); } @@ -590,9 +592,9 @@ void cv::viz::InteractorStyle::OnMouseWheelForward() MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getModifiers()); // If a mouse callback registered, call it! if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); if (Interactor->GetRepeatCount() && mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); if (Interactor->GetAltKey()) { @@ -622,10 +624,10 @@ void cv::viz::InteractorStyle::OnMouseWheelBackward() MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getModifiers()); // If a mouse callback registered, call it! if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); if (Interactor->GetRepeatCount() && mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); + mouseCallback_(event, mouse_callback_cookie_); if (Interactor->GetAltKey()) { @@ -656,9 +658,3 @@ void cv::viz::InteractorStyle::OnTimer() renderer_->Render(); Interactor->Render(); } - -namespace cv { namespace viz -{ - //Standard VTK macro for *New() - vtkStandardNewMacro(InteractorStyle) -}} diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/interactor_style.hpp index 3141bbeaa..51f98635b 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/interactor_style.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_INTERACTOR_STYLE_H__ @@ -121,9 +118,6 @@ namespace cv void (*mouseCallback_)(const MouseEvent&, void*); void *mouse_callback_cookie_; - bool getAltKey(); - bool getControlKey(); - bool getShiftKey(); int getModifiers(); }; } diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 0cf41bdec..0450eb816 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" @@ -63,7 +60,6 @@ cv::viz::WLine::WLine(const Point3f &pt1, const Point3f &pt2, const Color &color vtkSmartPointer line = vtkSmartPointer::New(); line->SetPoint1(pt1.x, pt1.y, pt1.z); line->SetPoint2(pt2.x, pt2.y, pt2.z); - line->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(line->GetOutputPort()); @@ -165,7 +161,6 @@ cv::viz::WSphere::WSphere(const Point3f ¢er, float radius, int sphere_resolu sphere->SetPhiResolution(sphere_resolution); sphere->SetThetaResolution(sphere_resolution); sphere->LatLongTessellationOff(); - sphere->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(sphere->GetOutputPort()); @@ -194,44 +189,27 @@ cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, arrowSource->SetTipRadius(thickness * 3.0); arrowSource->SetTipLength(thickness * 10.0); - float startPoint[3], endPoint[3]; - startPoint[0] = pt1.x; - startPoint[1] = pt1.y; - startPoint[2] = pt1.z; - endPoint[0] = pt2.x; - endPoint[1] = pt2.y; - endPoint[2] = pt2.z; - float normalizedX[3], normalizedY[3], normalizedZ[3]; + Vec3f startPoint(pt1.x, pt1.y, pt1.z), endPoint(pt2.x, pt2.y, pt2.z); + Vec3f arbitrary(theRNG().uniform(-10.f, 10.f), theRNG().uniform(-10.f, 10.f), theRNG().uniform(-10.f, 10.f)); + double length = cv::norm(endPoint - startPoint); - // The X axis is a vector from start to end - vtkMath::Subtract(endPoint, startPoint, normalizedX); - float length = vtkMath::Norm(normalizedX); - vtkMath::Normalize(normalizedX); - - // The Z axis is an arbitrary vecotr cross X - float arbitrary[3]; - arbitrary[0] = vtkMath::Random(-10,10); - arbitrary[1] = vtkMath::Random(-10,10); - arbitrary[2] = vtkMath::Random(-10,10); - vtkMath::Cross(normalizedX, arbitrary, normalizedZ); - vtkMath::Normalize(normalizedZ); - - // The Y axis is Z cross X - vtkMath::Cross(normalizedZ, normalizedX, normalizedY); - vtkSmartPointer matrix = vtkSmartPointer::New(); + Vec3f xvec = normalized(endPoint - startPoint); + Vec3f zvec = normalized(xvec.cross(arbitrary)); + Vec3f yvec = zvec.cross(xvec); // Create the direction cosine matrix + vtkSmartPointer matrix = vtkSmartPointer::New(); matrix->Identity(); - for (unsigned int i = 0; i < 3; i++) + for (int i = 0; i < 3; ++i) { - matrix->SetElement(i, 0, normalizedX[i]); - matrix->SetElement(i, 1, normalizedY[i]); - matrix->SetElement(i, 2, normalizedZ[i]); + matrix->SetElement(i, 0, xvec[i]); + matrix->SetElement(i, 1, yvec[i]); + matrix->SetElement(i, 2, zvec[i]); } // Apply the transforms vtkSmartPointer transform = vtkSmartPointer::New(); - transform->Translate(startPoint); + transform->Translate(startPoint.val); transform->Concatenate(matrix); transform->Scale(length, length, length); diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index e3537c475..2c7f8e74b 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" @@ -60,77 +57,80 @@ cv::viz::MouseEvent::MouseEvent(const Type& _type, const MouseButton& _button, c //////////////////////////////////////////////////////////////////// /// cv::viz::Mesh3d -struct cv::viz::Mesh3d::loadMeshImpl +namespace cv { namespace viz { namespace { - static cv::viz::Mesh3d loadMesh(const String &file) + struct MeshUtils { - Mesh3d mesh; - - vtkSmartPointer reader = vtkSmartPointer::New(); - reader->SetFileName(file.c_str()); - reader->Update(); - - vtkSmartPointer poly_data = reader->GetOutput(); - CV_Assert("File does not exist or file format is not supported." && poly_data); - - vtkSmartPointer mesh_points = poly_data->GetPoints(); - vtkIdType nr_points = mesh_points->GetNumberOfPoints(); - - mesh.cloud.create(1, nr_points, CV_32FC3); - - Vec3f *mesh_cloud = mesh.cloud.ptr(); - for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints(); i++) + static Mesh3d loadMesh(const String &file) { - Vec3d point; - mesh_points->GetPoint(i, point.val); - mesh_cloud[i] = point; - } + Mesh3d mesh; - // Then the color information, if any - vtkUnsignedCharArray* poly_colors = 0; - if (poly_data->GetPointData()) - poly_colors = vtkUnsignedCharArray::SafeDownCast(poly_data->GetPointData()->GetScalars()); + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName(file.c_str()); + reader->Update(); - if (poly_colors && (poly_colors->GetNumberOfComponents() == 3)) - { - mesh.colors.create(1, nr_points, CV_8UC3); - Vec3b *mesh_colors = mesh.colors.ptr(); + vtkSmartPointer poly_data = reader->GetOutput(); + CV_Assert("File does not exist or file format is not supported." && poly_data); + vtkSmartPointer mesh_points = poly_data->GetPoints(); + vtkIdType nr_points = mesh_points->GetNumberOfPoints(); + + mesh.cloud.create(1, nr_points, CV_32FC3); + + Vec3f *mesh_cloud = mesh.cloud.ptr(); for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints(); i++) { - Vec3b point_color; - poly_colors->GetTupleValue(i, point_color.val); - - std::swap(point_color[0], point_color[2]); // RGB -> BGR - mesh_colors[i] = point_color; + Vec3d point; + mesh_points->GetPoint(i, point.val); + mesh_cloud[i] = point; } + + // Then the color information, if any + vtkUnsignedCharArray* poly_colors = 0; + if (poly_data->GetPointData()) + poly_colors = vtkUnsignedCharArray::SafeDownCast(poly_data->GetPointData()->GetScalars()); + + if (poly_colors && (poly_colors->GetNumberOfComponents() == 3)) + { + mesh.colors.create(1, nr_points, CV_8UC3); + Vec3b *mesh_colors = mesh.colors.ptr(); + + for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints(); i++) + { + Vec3b point_color; + poly_colors->GetTupleValue(i, point_color.val); + + std::swap(point_color[0], point_color[2]); // RGB -> BGR + mesh_colors[i] = point_color; + } + } + else + mesh.colors.release(); + + // Now handle the polygons + vtkIdType* cell_points; + vtkIdType nr_cell_points; + vtkCellArray * mesh_polygons = poly_data->GetPolys(); + mesh_polygons->InitTraversal(); + + mesh.polygons.create(1, mesh_polygons->GetSize(), CV_32SC1); + + int* polygons = mesh.polygons.ptr(); + while (mesh_polygons->GetNextCell(nr_cell_points, cell_points)) + { + *polygons++ = nr_cell_points; + for (int i = 0; i < nr_cell_points; ++i) + *polygons++ = static_cast(cell_points[i]); + } + + return mesh; } - else - mesh.colors.release(); - - // Now handle the polygons - vtkIdType* cell_points; - vtkIdType nr_cell_points; - vtkCellArray * mesh_polygons = poly_data->GetPolys(); - mesh_polygons->InitTraversal(); - - mesh.polygons.create(1, mesh_polygons->GetSize(), CV_32SC1); - - int* polygons = mesh.polygons.ptr(); - while (mesh_polygons->GetNextCell(nr_cell_points, cell_points)) - { - *polygons++ = nr_cell_points; - for (int i = 0; i < nr_cell_points; ++i) - *polygons++ = static_cast(cell_points[i]); - } - - return mesh; - } -}; + }; +}}} cv::viz::Mesh3d cv::viz::Mesh3d::loadMesh(const String& file) { - return loadMeshImpl::loadMesh(file); + return MeshUtils::loadMesh(file); } //////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 08cb880de..0f21e08cc 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" @@ -131,10 +128,10 @@ void cv::viz::Viz3d::convertToWindowCoordinates(const Point3d &pt, Point3d &wind void cv::viz::Viz3d::converTo3DRay(const Point3d &window_coord, Point3d &origin, Vec3d &direction) { impl_->converTo3DRay(window_coord, origin, direction); } cv::Size cv::viz::Viz3d::getWindowSize() const { return impl_->getWindowSize(); } -void cv::viz::Viz3d::setWindowSize(const Size &window_size) { impl_->setWindowSize(window_size.width, window_size.height); } +void cv::viz::Viz3d::setWindowSize(const Size &window_size) { impl_->setWindowSize(window_size); } cv::String cv::viz::Viz3d::getWindowName() const { return impl_->getWindowName(); } void cv::viz::Viz3d::saveScreenshot(const String &file) { impl_->saveScreenshot(file); } -void cv::viz::Viz3d::setWindowPosition(int x, int y) { impl_->setWindowPosition(x,y); } +void cv::viz::Viz3d::setWindowPosition(const Point& window_position) { impl_->setWindowPosition(window_position); } void cv::viz::Viz3d::setFullScreen(bool mode) { impl_->setFullScreen(mode); } void cv::viz::Viz3d::setBackgroundColor(const Color& color) { impl_->setBackgroundColor(color); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 7702d973d..c727a99d2 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" @@ -62,14 +59,11 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : s_lastDone_(0.0), style_(vtkSmartPointer::New()), widget_actor_map_(new WidgetActorMap) { renderer_ = vtkSmartPointer::New(); - - // Create a RendererWindow window_ = vtkSmartPointer::New(); // Set the window size as 1/2 of the screen size cv::Vec2i window_size = cv::Vec2i(window_->GetScreenSize()) / 2; window_->SetSize(window_size.val); - window_->AddRenderer(renderer_); // Create the interactor style @@ -100,11 +94,6 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) interactor_->Initialize(); timer_id_ = interactor_->CreateRepeatingTimer(5000L); - // Set a simple PointPicker - //vtkSmartPointer pp = vtkSmartPointer::New(); - //pp->SetTolerance(pp->GetTolerance() * 2); - //interactor_->SetPicker(pp); - exit_main_loop_timer_callback_ = vtkSmartPointer::New(); exit_main_loop_timer_callback_->viz_ = this; exit_main_loop_timer_callback_->right_timer_id = -1; @@ -116,7 +105,6 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) resetStoppedFlag(); - ////////////////////////////// String window_name = VizStorage::generateWindowName(name); window_->SetWindowName(window_name.c_str()); @@ -521,6 +509,6 @@ cv::String cv::viz::Viz3d::VizImpl::getWindowName() const } ////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setWindowPosition(int x, int y) { window_->SetPosition(x, y); } -void cv::viz::Viz3d::VizImpl::setWindowSize(int xw, int yw) { window_->SetSize(xw, yw); } +void cv::viz::Viz3d::VizImpl::setWindowPosition(const Point& position) { window_->SetPosition(position.x, position.y); } +void cv::viz::Viz3d::VizImpl::setWindowSize(const Size& window_size) { window_->SetSize(window_size.width, window_size.height); } cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(window_->GetSize()[0], window_->GetSize()[1]); } diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index b38ad2966..d958f4672 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_VIZ3D_IMPL_HPP__ @@ -105,9 +102,9 @@ public: void converTo3DRay(const Point3d &window_coord, Point3d &origin, Vec3d &direction); void saveScreenshot(const String &file); - void setWindowPosition(int x, int y); + void setWindowPosition(const Point& position); Size getWindowSize() const; - void setWindowSize(int xw, int yw); + void setWindowSize(const Size& window_size); void setFullScreen(bool mode); String getWindowName() const; void setBackgroundColor(const Color& color); diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index c16d27ae3..a70fb925a 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #include "precomp.hpp" @@ -55,7 +52,6 @@ class cv::viz::Widget::Impl { public: vtkSmartPointer prop; - Impl() : prop(0) {} }; @@ -63,13 +59,17 @@ cv::viz::Widget::Widget() : impl_( new Impl() ) { } cv::viz::Widget::Widget(const Widget& other) : impl_( new Impl() ) { - if (other.impl_ && other.impl_->prop) impl_->prop = other.impl_->prop; + if (other.impl_ && other.impl_->prop) + impl_->prop = other.impl_->prop; } cv::viz::Widget& cv::viz::Widget::operator=(const Widget& other) { - if (!impl_) impl_ = new Impl(); - if (other.impl_) impl_->prop = other.impl_->prop; + if (!impl_) + impl_ = new Impl(); + + if (other.impl_) + impl_->prop = other.impl_->prop; return *this; } @@ -84,45 +84,22 @@ cv::viz::Widget::~Widget() cv::viz::Widget cv::viz::Widget::fromPlyFile(const String &file_name) { + CV_Assert(vtkPLYReader::CanReadFile(file_name.c_str())); + vtkSmartPointer reader = vtkSmartPointer::New(); reader->SetFileName(file_name.c_str()); - vtkSmartPointer data = reader->GetOutput(); - CV_Assert("File does not exist or file format is not supported." && data); - - vtkSmartPointer actor = vtkSmartPointer::New(); - vtkSmartPointer mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(data); -#else - mapper->SetInputData(data); -#endif - - vtkSmartPointer scalars = data->GetPointData()->GetScalars(); - if (scalars) - { - cv::Vec2d minmax(scalars->GetRange()); - mapper->SetScalarRange(minmax.val); - mapper->SetScalarModeToUsePointData(); - - // interpolation OFF, if data is a vtkPolyData that contains only vertices, ON for anything else. - vtkPolyData* polyData = vtkPolyData::SafeDownCast(data); - bool interpolation = (polyData && polyData->GetNumberOfCells() != polyData->GetNumberOfVerts()); - - mapper->SetInterpolateScalarsBeforeMapping(interpolation); - mapper->ScalarVisibilityOn(); - } + mapper->SetInputConnection( reader->GetOutputPort() ); mapper->ImmediateModeRenderingOff(); - actor->SetNumberOfCloudPoints(int(std::max(1, data->GetNumberOfPoints() / 10))); + vtkSmartPointer actor = vtkSmartPointer::New(); actor->GetProperty()->SetInterpolationToFlat(); actor->GetProperty()->BackfaceCullingOn(); - actor->SetMapper(mapper); Widget widget; - widget.impl_->prop = actor; + WidgetAccessor::setProp(widget, actor); return widget; } @@ -133,37 +110,15 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) switch (property) { - case POINT_SIZE: - { - actor->GetProperty()->SetPointSize(float(value)); - actor->Modified(); - break; - } - case OPACITY: - { - actor->GetProperty()->SetOpacity(value); - actor->Modified(); - break; - } - case IMMEDIATE_RENDERING: - { - actor->GetMapper()->SetImmediateModeRendering(int(value)); - actor->Modified(); - break; - } - case LINE_WIDTH: - { - actor->GetProperty()->SetLineWidth(float(value)); - actor->Modified(); - break; - } + case POINT_SIZE: actor->GetProperty()->SetPointSize(float(value)); break; + case OPACITY: actor->GetProperty()->SetOpacity(value); break; + case LINE_WIDTH: actor->GetProperty()->SetLineWidth(float(value)); break; + case IMMEDIATE_RENDERING: actor->GetMapper()->SetImmediateModeRendering(int(value)); break; case FONT_SIZE: { vtkTextActor* text_actor = vtkTextActor::SafeDownCast(actor); CV_Assert("Widget does not have text content." && text_actor); - vtkSmartPointer tprop = text_actor->GetTextProperty(); - tprop->SetFontSize(int(value)); - text_actor->Modified(); + text_actor->GetTextProperty()->SetFontSize(int(value)); break; } case REPRESENTATION: @@ -174,7 +129,6 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) case REPRESENTATION_WIREFRAME: actor->GetProperty()->SetRepresentationToWireframe(); break; case REPRESENTATION_SURFACE: actor->GetProperty()->SetRepresentationToSurface(); break; } - actor->Modified(); break; } case SHADING: @@ -215,14 +169,12 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) break; } } - actor->Modified(); break; } - - default: CV_Assert("setPointCloudRenderingProperties: Unknown property"); } + actor->Modified(); } double cv::viz::Widget::getRenderingProperty(int property) const @@ -233,32 +185,16 @@ double cv::viz::Widget::getRenderingProperty(int property) const double value = 0.0; switch (property) { - case POINT_SIZE: - { - value = actor->GetProperty()->GetPointSize(); - break; - } - case OPACITY: - { - value = actor->GetProperty()->GetOpacity(); - break; - } - case IMMEDIATE_RENDERING: - { - value = actor->GetMapper()->GetImmediateModeRendering(); - break; - } - case LINE_WIDTH: - { - value = actor->GetProperty()->GetLineWidth(); - break; - } + case POINT_SIZE: value = actor->GetProperty()->GetPointSize(); break; + case OPACITY: value = actor->GetProperty()->GetOpacity(); break; + case LINE_WIDTH: value = actor->GetProperty()->GetLineWidth(); break; + case IMMEDIATE_RENDERING: value = actor->GetMapper()->GetImmediateModeRendering(); break; + case FONT_SIZE: { vtkTextActor* text_actor = vtkTextActor::SafeDownCast(actor); CV_Assert("Widget does not have text content." && text_actor); - vtkSmartPointer tprop = text_actor->GetTextProperty(); - value = tprop->GetFontSize(); + value = text_actor->GetTextProperty()->GetFontSize();; break; } case REPRESENTATION: @@ -322,7 +258,7 @@ void cv::viz::Widget3D::updatePose(const Affine3f &pose) if (!matrix) { setPose(pose); - return ; + return; } Affine3f updated_pose = pose * Affine3f(convertToMatx(matrix)); From 84d6fe397d90887c4a823d9e7e6666821aadf969 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 13 Dec 2013 19:20:20 +0400 Subject: [PATCH 119/295] reading/writing clouds functionality --- modules/viz/include/opencv2/viz.hpp | 6 + modules/viz/src/clouds.cpp | 5 +- modules/viz/src/precomp.hpp | 20 +- modules/viz/src/vizcore.cpp | 112 ++++++++ .../viz/src/vtk/vtkCloudColorMatSource.cpp | 168 ------------ modules/viz/src/vtk/vtkCloudMatSource.cpp | 68 +++++ modules/viz/src/vtk/vtkCloudMatSource.h | 5 + modules/viz/src/vtk/vtkColorMatSource.cpp | 132 ---------- modules/viz/src/vtk/vtkOBJWriter.cpp | 241 ++++++++++++++++++ .../{vtkColorMatSource.h => vtkOBJWriter.h} | 35 ++- modules/viz/src/vtk/vtkXYZWriter.cpp | 93 +++++++ ...tkCloudColorMatSource.h => vtkXYZWriter.h} | 42 ++- modules/viz/test/test_tutorial3.cpp | 24 +- 13 files changed, 578 insertions(+), 373 deletions(-) delete mode 100644 modules/viz/src/vtk/vtkCloudColorMatSource.cpp delete mode 100644 modules/viz/src/vtk/vtkColorMatSource.cpp create mode 100644 modules/viz/src/vtk/vtkOBJWriter.cpp rename modules/viz/src/vtk/{vtkColorMatSource.h => vtkOBJWriter.h} (71%) create mode 100644 modules/viz/src/vtk/vtkXYZWriter.cpp rename modules/viz/src/vtk/{vtkCloudColorMatSource.h => vtkXYZWriter.h} (65%) diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 65ad10aac..49b36a9b2 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -92,6 +92,12 @@ namespace cv { return isNan(p.x) || isNan(p.y) || isNan(p.z); } + /////////////////////////////////////////////////////////////////////////////////////////////// + /// Read/write clouds. Supported formats: ply, stl, xyz, obj + + CV_EXPORTS void writeCloud(const String& file, InputArray cloud, InputArray colors = noArray()); + CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = cv::noArray()); + /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 8549acafd..555da22d0 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -69,9 +69,8 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) colors = colors.reshape(colors.channels(), 1); } - vtkSmartPointer cloud_source = vtkSmartPointer::New(); - cloud_source->SetCloud(cloud); - cloud_source->SetColors(colors, cloud); + vtkSmartPointer cloud_source = vtkSmartPointer::New(); + cloud_source->SetColorCloud(cloud, colors); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(cloud_source->GetOutputPort()); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 7741dc7df..6b2c1478e 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -113,16 +114,31 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(_WIN32) || defined(__CYGWIN__) +# include /* unlink */ +#else +# include /* unlink */ +#endif #include -#include -#include +#include +#include #include #include #include #include + namespace cv { namespace viz diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index dd998e7d9..5a1a7a8fe 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -161,6 +161,118 @@ cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) cv::viz::Viz3d cv::viz::get(const String &window_name) { return Viz3d (window_name); } void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } +/////////////////////////////////////////////////////////////////////////////////////////////// +/// Read/write clouds. Supported formats: ply, stl, xyz, obj + +void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colors) +{ + CV_Assert(file.size() > 4 && "Extention is required"); + String extention = file.substr(file.size()-4); + + Mat cloud = _cloud.getMat(); + Mat colors = _colors.getMat(); + + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetColorCloud(cloud, colors); + + vtkSmartPointer writer; + if (extention == ".xyz") + { + writer = vtkSmartPointer::New(); + vtkPLYWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + } + else if (extention == ".ply") + { + writer = vtkSmartPointer::New(); + vtkPLYWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + } + else if (extention == ".obj") + { + writer = vtkSmartPointer::New(); + vtkOBJWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + } + else if (extention == ".stl") + { + writer = vtkSmartPointer::New(); + vtkSTLWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + } + else + CV_Assert(!"Unsupported format"); + + writer->SetInputConnection(source->GetOutputPort()); + writer->Write(); +} + +cv::Mat cv::viz::readCloud(const String& file, OutputArray colors) +{ + CV_Assert(file.size() > 4 && "Extention is required"); + String extention = file.substr(file.size()-4); + + vtkSmartPointer reader; + if (extention == ".xyz") + { + reader = vtkSmartPointer::New(); + vtkSimplePointsReader::SafeDownCast(reader)->SetFileName(file.c_str()); + } + else if (extention == ".ply") + { + reader = vtkSmartPointer::New(); + CV_Assert(vtkPLYReader::CanReadFile(file.c_str())); + vtkPLYReader::SafeDownCast(reader)->SetFileName(file.c_str()); + } + else if (extention == ".obj") + { + reader = vtkSmartPointer::New(); + vtkOBJReader::SafeDownCast(reader)->SetFileName(file.c_str()); + } + else if (extention == ".stl") + { + reader = vtkSmartPointer::New(); + vtkSTLReader::SafeDownCast(reader)->SetFileName(file.c_str()); + } + else + CV_Assert(!"Unsupported format"); + + reader->Update(); + vtkSmartPointer poly_data = reader->GetOutput(); + vtkSmartPointer points = poly_data->GetPoints(); + + int vtktype = points->GetDataType(); + CV_Assert(vtktype == VTK_FLOAT || vtktype == VTK_DOUBLE); + + Mat cloud(1, points->GetNumberOfPoints(), vtktype == VTK_FLOAT ? CV_32FC3 : CV_64FC3); + Vec3d *ddata = cloud.ptr(); + Vec3f *fdata = cloud.ptr(); + + if (cloud.depth() == CV_32F) + for(size_t i = 0; i < cloud.total(); ++i) + *fdata++ = Vec3d(points->GetPoint(i)); + + if (cloud.depth() == CV_64F) + for(size_t i = 0; i < cloud.total(); ++i) + *ddata++ = Vec3d(points->GetPoint(i)); + + vtkSmartPointer scalars = poly_data->GetPointData() ? poly_data->GetPointData()->GetScalars() : 0; + + if (colors.needed() && scalars) + { + int channels = scalars->GetNumberOfComponents(); + int vtktype = scalars->GetDataType(); + + CV_Assert((channels == 3 || channels == 4) && "Only 3- or 4-channel color data support is implemented"); + CV_Assert(cloud.total() == (size_t)scalars->GetNumberOfTuples()); + Mat buffer(cloud.size(), CV_64FC(channels)); + Vec3d *cptr = buffer.ptr(); + for(size_t i = 0; i < colors.total(); ++i) + *cptr++ = Vec3d(scalars->GetTuple(i)); + + buffer.convertTo(colors, CV_8U, vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE ? 255.0 : 1.0); + } + else + colors.release(); + + return cloud; +} /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/vtk/vtkCloudColorMatSource.cpp b/modules/viz/src/vtk/vtkCloudColorMatSource.cpp deleted file mode 100644 index 8979873eb..000000000 --- a/modules/viz/src/vtk/vtkCloudColorMatSource.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/*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. -// -// Authors: -// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com -// -//M*/ - -#include "precomp.hpp" - -namespace cv { namespace viz -{ - vtkStandardNewMacro(vtkCloudColorMatSource); - - struct IsNotNan - { - template - bool operator()(const _Tp* data) const - { - return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); - } - }; -}} - -cv::viz::vtkCloudColorMatSource::vtkCloudColorMatSource() { SetNumberOfInputPorts(0); } -cv::viz::vtkCloudColorMatSource::~vtkCloudColorMatSource() {} - -void cv::viz::vtkCloudColorMatSource::SetCloud(const Mat& cloud) -{ - CV_Assert(cloud.depth() == CV_32F || cloud.depth() == CV_64F); - CV_Assert(cloud.channels() == 3 || cloud.channels() == 4); - - int total = cloud.depth() == CV_32F ? filterNanCopy(cloud, VTK_FLOAT) - : filterNanCopy(cloud, VTK_DOUBLE); - - vertices = vtkSmartPointer::New(); - vertices->Allocate(vertices->EstimateSize(1, total)); - vertices->InsertNextCell(total); - for(int i = 0; i < total; ++i) - vertices->InsertCellPoint(i); -} - -void cv::viz::vtkCloudColorMatSource::SetColors(const Mat &colors, const Mat &cloud_mask) -{ - CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); - CV_Assert(cloud_mask.depth() == CV_32F || cloud_mask.depth() == CV_64F); - CV_Assert(colors.size() == cloud_mask.size()); - - if (cloud_mask.depth() == CV_32F) - filterNanCopy(colors, cloud_mask); - else if (cloud_mask.depth() == CV_64F) - filterNanCopy(colors, cloud_mask); -} - -int cv::viz::vtkCloudColorMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) -{ - vtkInformation *outInfo = outputVector->GetInformationObject(0); - vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); - - output->SetPoints(points); - output->SetVerts(vertices); - output->GetPointData()->SetScalars(scalars); - return 1; -} - -template -int cv::viz::vtkCloudColorMatSource::filterNanCopy(const Mat& source, int dataType) -{ - CV_DbgAssert(DataType<_Tp>::depth == source.depth()); - points = vtkSmartPointer::New(); - points->SetDataType(dataType); - points->Allocate(source.total()); - points->SetNumberOfPoints(source.total()); - - int cn = source.channels(); - int total = 0; - for (int y = 0; y < source.rows; ++y) - { - const _Tp* srow = source.ptr<_Tp>(y); - const _Tp* send = srow + source.cols * cn; - - for (; srow != send; srow += cn) - if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) - points->SetPoint(total++, srow); - } - points->SetNumberOfPoints(total); - points->Squeeze(); - return total; -} - -template -void cv::viz::vtkCloudColorMatSource::filterNanCopy(const Mat& colors, const Mat& mask) -{ - Mat buffer(colors.size(), CV_8UC3); - Vec3b* pos = buffer.ptr(); - - int s_chs = colors.channels(); - int m_chs = mask.channels(); - - _NanPred pred; - - for (int y = 0; y < colors.rows; ++y) - { - const unsigned char* srow = colors.ptr(y); - const unsigned char* send = srow + colors.cols * colors.channels(); - const _Msk* mrow = mask.empty() ? 0 : mask.ptr<_Msk>(y); - - if (colors.channels() == 1) - { - for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) - *pos++ = Vec3b(srow[0], srow[0], srow[0]); - } - else - for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) - *pos++ = Vec3b(srow[2], srow[1], srow[0]); - - } - - int total = pos - buffer.ptr(); - Vec3b* array = new Vec3b[total]; - std::copy(buffer.ptr(), pos, array); - - scalars = vtkSmartPointer::New(); - scalars->SetName("colors"); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(total); - scalars->SetArray(array->val, total * 3, 0); -} - - diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index a27653a4f..f533361bc 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -47,6 +47,14 @@ namespace cv { namespace viz { vtkStandardNewMacro(vtkCloudMatSource); + + struct IsNotNan + { + template bool operator()(const _Tp* data) const + { + return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); + } + }; }} cv::viz::vtkCloudMatSource::vtkCloudMatSource() { SetNumberOfInputPorts(0); } @@ -67,6 +75,22 @@ void cv::viz::vtkCloudMatSource::SetCloud(const Mat& cloud) vertices->InsertCellPoint(i); } +void cv::viz::vtkCloudMatSource::SetColorCloud(const Mat &cloud, const Mat &colors) +{ + vtkCloudMatSource::SetCloud(cloud); + + if (colors.empty()) + return; + + CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); + CV_Assert(colors.size() == cloud.size()); + + if (cloud.depth() == CV_32F) + filterNanColorsCopy(colors, cloud); + else if (cloud.depth() == CV_64F) + filterNanColorsCopy(colors, cloud); +} + int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) { vtkInformation *outInfo = outputVector->GetInformationObject(0); @@ -74,6 +98,8 @@ int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), output->SetPoints(points); output->SetVerts(vertices); + if (scalars) + output->GetPointData()->SetScalars(scalars); return 1; } @@ -103,3 +129,45 @@ int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& source, int dataType) } +template +void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& colors, const Mat& mask) +{ + Mat buffer(colors.size(), CV_8UC3); + Vec3b* pos = buffer.ptr(); + + int s_chs = colors.channels(); + int m_chs = mask.channels(); + + _NanPred pred; + + for (int y = 0; y < colors.rows; ++y) + { + const unsigned char* srow = colors.ptr(y); + const unsigned char* send = srow + colors.cols * colors.channels(); + const _Msk* mrow = mask.empty() ? 0 : mask.ptr<_Msk>(y); + + if (colors.channels() == 1) + { + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[0], srow[0], srow[0]); + } + else + for (; srow != send; srow += s_chs, mrow += m_chs) + if (pred(mrow)) + *pos++ = Vec3b(srow[2], srow[1], srow[0]); + + } + + int total = pos - buffer.ptr(); + Vec3b* array = new Vec3b[total]; + std::copy(buffer.ptr(), pos, array); + + scalars = vtkSmartPointer::New(); + scalars->SetName("colors"); + scalars->SetNumberOfComponents(3); + scalars->SetNumberOfTuples(total); + scalars->SetArray(array->val, total * 3, 0); +} + + diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index 6a8dbebd1..876ab994f 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -62,6 +62,7 @@ namespace cv vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm); virtual void SetCloud(const Mat& cloud); + virtual void SetColorCloud(const Mat &cloud, const Mat &colors = cv::Mat()); protected: vtkCloudMatSource(); @@ -71,11 +72,15 @@ namespace cv vtkSmartPointer points; vtkSmartPointer vertices; + vtkSmartPointer scalars; private: vtkCloudMatSource(const vtkCloudMatSource&); // Not implemented. void operator=(const vtkCloudMatSource&); // Not implemented. template int filterNanCopy(const Mat& source, int dataType); + + template + void filterNanColorsCopy(const Mat& colors, const Mat& mask); }; } } diff --git a/modules/viz/src/vtk/vtkColorMatSource.cpp b/modules/viz/src/vtk/vtkColorMatSource.cpp deleted file mode 100644 index aa09a2d49..000000000 --- a/modules/viz/src/vtk/vtkColorMatSource.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/*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. -// -// Authors: -// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com -// -//M*/ - -#include "precomp.hpp" - -namespace cv { namespace viz -{ - vtkStandardNewMacro(vtkColorMatSource); - - struct IsNotNan - { - template - bool operator()(const _Tp* data) const - { - return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); - } - }; - - struct AllOk - { - template - bool operator()(const _Tp*) const { return true; } - }; -}} - -cv::viz::vtkColorMatSource::vtkColorMatSource() { SetNumberOfInputPorts(0); } -cv::viz::vtkColorMatSource::~vtkColorMatSource() {} - -void cv::viz::vtkColorMatSource::SetColors(const Mat &colors, const Mat& mask) -{ - CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); - CV_Assert(mask.empty() || mask.depth() == CV_32F || mask.depth() == CV_64F); - - if (!mask.empty() && mask.depth() == CV_32F) - filterNanCopy(colors, mask); - else if (!mask.empty() && mask.depth() == CV_64F) - filterNanCopy(colors, mask); - else /* mask.empty() */ - filterNanCopy(colors, mask); -} - -int cv::viz::vtkColorMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) -{ - vtkInformation *outInfo = outputVector->GetInformationObject(0); - vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); - - output->GetPointData()->SetScalars(scalars); - - return 1; -} - -template -void cv::viz::vtkColorMatSource::filterNanCopy(const Mat& colors, const Mat& cloud_mask) -{ - Mat buffer(colors.size(), CV_8UC3); - Vec3b* pos = buffer.ptr(); - - int s_chs = colors.channels(); - int m_chs = cloud_mask.channels(); - - _NanPred pred; - - for (int y = 0; y < colors.rows; ++y) - { - const unsigned char* srow = colors.ptr(y); - const unsigned char* send = srow + colors.cols * colors.channels(); - const _Msk* mrow = cloud_mask.empty() ? 0 : cloud_mask.ptr<_Msk>(y); - - if (colors.channels() == 1) - { - for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) - *pos++ = Vec3b(srow[0], srow[0], srow[0]); - } - else - for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) - *pos++ = Vec3b(srow[2], srow[1], srow[0]); - - } - - int total = pos - buffer.ptr(); - Vec3b* array = new Vec3b[total]; - std::copy(buffer.ptr(), pos, array); - - scalars = vtkSmartPointer::New(); - scalars->SetName("colors"); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(total); - scalars->SetArray(array->val, total * 3, 0); -} diff --git a/modules/viz/src/vtk/vtkOBJWriter.cpp b/modules/viz/src/vtk/vtkOBJWriter.cpp new file mode 100644 index 000000000..452ad19a7 --- /dev/null +++ b/modules/viz/src/vtk/vtkOBJWriter.cpp @@ -0,0 +1,241 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkOBJWriter); +}} + +cv::viz::vtkOBJWriter::vtkOBJWriter() +{ + std::ofstream fout; // only used to extract the default precision + this->DecimalPrecision = fout.precision(); + this->FileName = NULL; + this->FileType = VTK_ASCII; +} + +cv::viz::vtkOBJWriter::~vtkOBJWriter(){} + +void cv::viz::vtkOBJWriter::WriteData() +{ + vtkPolyData *input = this->GetInput(); + if (!input) + return; + + std::ostream *outfilep = this->OpenVTKFile(); + if (!outfilep) + return; + + std::ostream& outfile = *outfilep; + + //write header + outfile << "# wavefront obj file written by the visualization toolkit" << std::endl << std::endl; + outfile << "mtllib NONE" << std::endl << std::endl; + + // write out the points + for (int i = 0; i < input->GetNumberOfPoints(); i++) + { + Vec3d p; + input->GetPoint(i, p.val); + outfile << std::setprecision(this->DecimalPrecision) << "v " << p[0] << " " << p[1] << " " << p[2] << std::endl; + } + + const int idStart = 1; + + // write out the point data + vtkSmartPointer normals = input->GetPointData()->GetNormals(); + if(normals) + { + for (int i = 0; i < normals->GetNumberOfTuples(); i++) + { + Vec3d p; + normals->GetTuple(i, p.val); + outfile << std::setprecision(this->DecimalPrecision) << "vn " << p[0] << " " << p[1] << " " << p[2] << std::endl; + } + } + + vtkSmartPointer tcoords = input->GetPointData()->GetTCoords(); + if (tcoords) + { + for (int i = 0; i < tcoords->GetNumberOfTuples(); i++) + { + Vec2d p; + tcoords->GetTuple(i, p.val); + outfile << std::setprecision(this->DecimalPrecision) << "vt " << p[0] << " " << p[1] << std::endl; + } + } + + // write out a group name and material + outfile << std::endl << "g grp" << idStart << std::endl; + outfile << "usemtl mtlNONE" << std::endl; + + // write out verts if any + if (input->GetNumberOfVerts() > 0) + { + vtkIdType npts = 0, *index = 0; + vtkCellArray *cells = input->GetVerts(); + for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) + { + outfile << "p "; + for (int i = 0; i < npts; i++) + outfile << index[i] + idStart << " "; + outfile << std::endl; + } + } + + // write out lines if any + if (input->GetNumberOfLines() > 0) + { + vtkIdType npts = 0, *index = 0; + vtkCellArray *cells = input->GetLines(); + for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) + { + outfile << "l "; + if (tcoords) + { + for (int i = 0; i < npts; i++) + outfile << index[i] + idStart << "/" << index[i] + idStart << " "; + } + else + for (int i = 0; i < npts; i++) + outfile << index[i] + idStart << " "; + + outfile << std::endl; + } + } + + // write out polys if any + if (input->GetNumberOfPolys() > 0) + { + vtkIdType npts = 0, *index = 0; + vtkCellArray *cells = input->GetPolys(); + for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) + { + outfile << "f "; + for (int i = 0; i < npts; i++) + { + if (normals) + { + if (tcoords) + outfile << index[i] + idStart << "/" << index[i] + idStart << "/" << index[i] + idStart << " "; + else + outfile << index[i] + idStart << "//" << index[i] + idStart << " "; + } + else + { + if (tcoords) + outfile << index[i] + idStart << " " << index[i] + idStart << " "; + else + outfile << index[i] + idStart << " "; + } + } + outfile << std::endl; + } + } + + // write out tstrips if any + if (input->GetNumberOfStrips() > 0) + { + vtkIdType npts = 0, *index = 0; + vtkCellArray *cells = input->GetStrips(); + for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) + { + for (int i = 2, i1, i2; i < npts; ++i) + { + if (i % 2) + { + i1 = i - 1; + i2 = i - 2; + } + else + { + i1 = i - 1; + i2 = i - 2; + } + + if(normals) + { + if (tcoords) + { + outfile << "f " << index[i1] + idStart << "/" << index[i1] + idStart << "/" << index[i1] + idStart << " " + << index[i2]+ idStart << "/" << index[i2] + idStart << "/" << index[i2] + idStart << " " + << index[i] + idStart << "/" << index[i] + idStart << "/" << index[i] + idStart << std::endl; + } + else + { + outfile << "f " << index[i1] + idStart << "//" << index[i1] + idStart << " " << index[i2] + idStart + << "//" << index[i2] + idStart << " " << index[i] + idStart << "//" << index[i] + idStart << std::endl; + } + } + else + { + if (tcoords) + { + outfile << "f " << index[i1] + idStart << "/" << index[i1] + idStart << " " << index[i2] + idStart + << "/" << index[i2] + idStart << " " << index[i] + idStart << "/" << index[i] + idStart << std::endl; + } + else + outfile << "f " << index[i1] + idStart << " " << index[i2] + idStart << " " << index[i] + idStart << std::endl; + } + } /* for (int i = 2; i < npts; ++i) */ + } + } /* if (input->GetNumberOfStrips() > 0) */ + + this->CloseVTKFile(outfilep); + + // Delete the file if an error occurred + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + unlink(this->FileName); + } +} + +void cv::viz::vtkOBJWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + Superclass::PrintSelf(os, indent); + os << indent << "DecimalPrecision: " << DecimalPrecision << "\n"; +} diff --git a/modules/viz/src/vtk/vtkColorMatSource.h b/modules/viz/src/vtk/vtkOBJWriter.h similarity index 71% rename from modules/viz/src/vtk/vtkColorMatSource.h rename to modules/viz/src/vtk/vtkOBJWriter.h index d1650faad..9bf5403e4 100644 --- a/modules/viz/src/vtk/vtkColorMatSource.h +++ b/modules/viz/src/vtk/vtkOBJWriter.h @@ -42,39 +42,36 @@ // //M*/ -#ifndef __vtkColorMatSource_h -#define __vtkColorMatSource_h +#ifndef __vtkOBJWriter_h +#define __vtkOBJWriter_h -#include -#include -#include +#include namespace cv { namespace viz { - class vtkColorMatSource : public vtkPolyDataAlgorithm + class vtkOBJWriter : public vtkPolyDataWriter { public: - static vtkColorMatSource *New(); - vtkTypeMacro(vtkColorMatSource,vtkPolyDataAlgorithm); - - virtual void SetColors(const Mat &colors, const Mat &cloud_mask = Mat()); + static vtkOBJWriter *New(); + vtkTypeMacro(vtkOBJWriter,vtkPolyDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + vtkGetMacro(DecimalPrecision, int); + vtkSetMacro(DecimalPrecision, int); protected: - vtkColorMatSource(); - ~vtkColorMatSource(); + vtkOBJWriter(); + ~vtkOBJWriter(); - int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void WriteData(); + + int DecimalPrecision; - vtkSmartPointer scalars; private: - vtkColorMatSource(const vtkColorMatSource&); // Not implemented. - void operator=(const vtkColorMatSource&); // Not implemented. - - template - void filterNanCopy(const Mat& colors, const Mat& mask); + vtkOBJWriter(const vtkOBJWriter&); // Not implemented. + void operator=(const vtkOBJWriter&); // Not implemented. }; } } diff --git a/modules/viz/src/vtk/vtkXYZWriter.cpp b/modules/viz/src/vtk/vtkXYZWriter.cpp new file mode 100644 index 000000000..4518a0103 --- /dev/null +++ b/modules/viz/src/vtk/vtkXYZWriter.cpp @@ -0,0 +1,93 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkXYZWriter); +}} + +cv::viz::vtkXYZWriter::vtkXYZWriter() +{ + std::ofstream fout; // only used to extract the default precision + this->DecimalPrecision = fout.precision(); +} + +void cv::viz::vtkXYZWriter::WriteData() +{ + vtkPolyData *input = this->GetInput(); + if (!input) + return; + + // OpenVTKFile() will report any errors that happen + ostream *outfilep = this->OpenVTKFile(); + if (!outfilep) + return; + + ostream &outfile = *outfilep; + + for(vtkIdType i = 0; i < input->GetNumberOfPoints(); ++i) + { + Vec3d p; + input->GetPoint(i, p.val); + outfile << std::setprecision(this->DecimalPrecision) << p[0] << " " << p[1] << " " << p[2] << std::endl; + } + + // Close the file + this->CloseVTKFile(outfilep); + + // Delete the file if an error occurred + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + unlink(this->FileName); + } +} + +void cv::viz::vtkXYZWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "DecimalPrecision: " << this->DecimalPrecision << "\n"; +} diff --git a/modules/viz/src/vtk/vtkCloudColorMatSource.h b/modules/viz/src/vtk/vtkXYZWriter.h similarity index 65% rename from modules/viz/src/vtk/vtkCloudColorMatSource.h rename to modules/viz/src/vtk/vtkXYZWriter.h index 0aa5b87a3..bc49d10ef 100644 --- a/modules/viz/src/vtk/vtkCloudColorMatSource.h +++ b/modules/viz/src/vtk/vtkXYZWriter.h @@ -42,47 +42,37 @@ // //M*/ -#ifndef __vtkCloudColorMatSource_h -#define __vtkCloudColorMatSource_h +#ifndef __vtkXYZWriter_h +#define __vtkXYZWriter_h -#include -#include -#include -#include -#include +#include "vtkPolyDataWriter.h" namespace cv { namespace viz { - class vtkCloudColorMatSource : public vtkPolyDataAlgorithm + class vtkXYZWriter : public vtkPolyDataWriter { public: - static vtkCloudColorMatSource *New(); - vtkTypeMacro(vtkCloudColorMatSource,vtkPolyDataAlgorithm); + static vtkXYZWriter *New(); + vtkTypeMacro(vtkXYZWriter,vtkPolyDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); - virtual void SetCloud(const Mat& cloud); - virtual void SetColors(const Mat &colors, const Mat &cloud_mask); + vtkGetMacro(DecimalPrecision, int); + vtkSetMacro(DecimalPrecision, int); protected: - vtkCloudColorMatSource(); - ~vtkCloudColorMatSource(); + vtkXYZWriter(); + ~vtkXYZWriter(){} - int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void WriteData(); + + int DecimalPrecision; - vtkSmartPointer points; - vtkSmartPointer vertices; - vtkSmartPointer scalars; private: - vtkCloudColorMatSource(const vtkCloudColorMatSource&); // Not implemented. - void operator=(const vtkCloudColorMatSource&); // Not implemented. - - template int filterNanCopy(const Mat& source, int dataType); - - template - void filterNanCopy(const Mat& colors, const Mat& mask); + vtkXYZWriter(const vtkXYZWriter&); // Not implemented. + void operator=(const vtkXYZWriter&); // Not implemented. }; } } - #endif diff --git a/modules/viz/test/test_tutorial3.cpp b/modules/viz/test/test_tutorial3.cpp index 6c63763df..12eca311c 100644 --- a/modules/viz/test/test_tutorial3.cpp +++ b/modules/viz/test/test_tutorial3.cpp @@ -3,28 +3,6 @@ using namespace cv; using namespace std; -/** - * @function cvcloud_load - * @brief load bunny.ply - */ -Mat cvcloud_load() -{ - Mat cloud(1, 20000, CV_32FC3); - ifstream ifs("d:/cloud_dragon.ply"); - - string str; - for(size_t i = 0; i < 12; ++i) - getline(ifs, str); - - Point3f* data = cloud.ptr(); - //float dummy1, dummy2; - for(size_t i = 0; i < 20000; ++i) - ifs >> data[i].x >> data[i].y >> data[i].z;// >> dummy1 >> dummy2; - - //cloud *= 5.0f; - return cloud; -} - /** * @function main */ @@ -47,7 +25,7 @@ void tutorial3(bool camera_pov) Affine3f transform = viz::makeTransformToGlobal(Vec3f(0.0f,-1.0f,0.0f), Vec3f(-1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), cam_pos); /// Create a cloud widget. - Mat bunny_cloud = cvcloud_load(); + Mat bunny_cloud = viz::readCloud("d:/cloud_dragon.ply"); viz::WCloud cloud_widget(bunny_cloud, viz::Color::green()); /// Pose of the widget in camera frame From b2cd526e6ab15b897a9935750a584c69715d3020 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 13 Dec 2013 19:35:48 +0400 Subject: [PATCH 120/295] removed extra code --- modules/viz/src/interactor_style.cpp | 28 +++++++++------------------- modules/viz/src/interactor_style.hpp | 6 ------ 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 1a7c8a4c1..5c2ee1cd1 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -63,11 +63,6 @@ void cv::viz::InteractorStyle::Initialize() win_pos_ = Vec2i(0, 0); max_win_size_ = Vec2i(-1, -1); - // Create the image filter and PNG writer objects - wif_ = vtkSmartPointer::New(); - snapshot_writer_ = vtkSmartPointer::New(); - snapshot_writer_->SetInputConnection(wif_->GetOutputPort()); - init_ = true; stereo_anaglyph_mask_default_ = true; @@ -84,11 +79,14 @@ void cv::viz::InteractorStyle::Initialize() void cv::viz::InteractorStyle::saveScreenshot(const String &file) { FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); - wif_->SetInput(Interactor->GetRenderWindow()); - wif_->Modified(); // Update the WindowToImageFilter - snapshot_writer_->Modified(); - snapshot_writer_->SetFileName(file.c_str()); - snapshot_writer_->Write(); + + vtkSmartPointer wif = vtkSmartPointer::New(); + wif->SetInput(Interactor->GetRenderWindow()); + + vtkSmartPointer snapshot_writer = vtkSmartPointer::New(); + snapshot_writer->SetInputConnection(wif->GetOutputPort()); + snapshot_writer->SetFileName(file.c_str()); + snapshot_writer->Write(); } ////////////////////////////////////////////////////////////////////////////////////////////// @@ -196,21 +194,13 @@ int cv::viz::InteractorStyle::getModifiers() } ////////////////////////////////////////////////////////////////////////////////////////////// -void -cv::viz::InteractorStyle::OnKeyDown() +void cv::viz::InteractorStyle::OnKeyDown() { CV_Assert("Interactor style not initialized. Please call Initialize() before continuing" && init_); CV_Assert("No renderer given! Use SetRendererCollection() before continuing." && renderer_); FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); - if (wif_->GetInput() == NULL) - { - wif_->SetInput(Interactor->GetRenderWindow()); - wif_->Modified(); - snapshot_writer_->Modified(); - } - // Save the initial windows width/height if (win_size_[0] == -1 || win_size_[1] == -1) win_size_ = Vec2i(Interactor->GetRenderWindow()->GetSize()); diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/interactor_style.hpp index 51f98635b..7ae4fa75c 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/interactor_style.hpp @@ -79,12 +79,6 @@ namespace cv Vec2i win_pos_; Vec2i max_win_size_; - /** \brief A PNG writer for screenshot captures. */ - vtkSmartPointer snapshot_writer_; - - /** \brief Internal window to image filter. Needed by \a snapshot_writer_. */ - vtkSmartPointer wif_; - /** \brief Interactor style internal method. Gets called whenever a key is pressed. */ virtual void OnChar(); From b131faa8f958e3eff8749a776c437984d3bd7108 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 13 Dec 2013 20:05:19 +0400 Subject: [PATCH 121/295] export scene to vrml and obj formats --- modules/viz/src/interactor_style.cpp | 39 ++++++++++++++++++++++++---- modules/viz/src/interactor_style.hpp | 1 + modules/viz/src/precomp.hpp | 2 ++ 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 5c2ee1cd1..4126d8c35 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -87,6 +87,29 @@ void cv::viz::InteractorStyle::saveScreenshot(const String &file) snapshot_writer->SetInputConnection(wif->GetOutputPort()); snapshot_writer->SetFileName(file.c_str()); snapshot_writer->Write(); + + cout << "Screenshot successfully captured (" << file.c_str() << ")" << endl; +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::InteractorStyle::exportScene(const String &file) +{ + vtkSmartPointer exporter; + if (file.size() > 5 && file.substr(file.size() - 5) == ".vrml") + { + exporter = vtkSmartPointer::New(); + vtkVRMLExporter::SafeDownCast(exporter)->SetFileName(file.c_str()); + } + else + { + exporter = vtkSmartPointer::New(); + vtkOBJExporter::SafeDownCast(exporter)->SetFilePrefix(file.c_str()); + } + + exporter->SetInput(Interactor->GetRenderWindow()); + exporter->Write(); + + cout << "Scene successfully exported (" << file.c_str() << ")" << endl; } ////////////////////////////////////////////////////////////////////////////////////////////// @@ -224,6 +247,8 @@ void cv::viz::InteractorStyle::OnKeyDown() " s, S : switch to a surface-based representation (where available)\n" "\n" " j, J : take a .PNG snapshot of the current window view\n" + " k, K : export scene to Wavefront .obj format\n" + " ALT + k, K : export scene to VRML format\n" " c, C : display current camera/window parameters\n" " f, F : fly to point mode, hold the key and move mouse where to fly\n" "\n" @@ -255,15 +280,19 @@ void cv::viz::InteractorStyle::OnKeyDown() } break; } - // Save a PNG snapshot with the current screen + + // Save a PNG snapshot case 'j': case 'J': + saveScreenshot(cv::format("screenshot-%d.png", (unsigned int)time(0))); break; + + // Export scene as in obj or vrml format + case 'k': case 'K': { - unsigned int t = static_cast(time(0)); - String png_file = cv::format("screenshot-%d.png", t); - saveScreenshot(png_file); - cout << "Screenshot (" << png_file.c_str() << ") successfully captured." << endl; + String format = alt ? "scene-%d.vrml" : "scene-%d"; + exportScene(cv::format(format.c_str(), (unsigned int)time(0))); break; } + // display current camera settings/parameters case 'c': case 'C': { diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/interactor_style.hpp index 7ae4fa75c..92876d894 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/interactor_style.hpp @@ -67,6 +67,7 @@ namespace cv void registerMouseCallback(void (*callback)(const MouseEvent&, void*), void* cookie = 0); void registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void * cookie = 0); void saveScreenshot(const String &file); + void exportScene(const String &file); private: /** \brief Set to true after initialization is complete. */ diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 6b2c1478e..83b779dd8 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -122,6 +122,8 @@ #include #include #include +#include +#include #if !defined(_WIN32) || defined(__CYGWIN__) # include /* unlink */ From bf30c33e6e3fd8c3735ba9e713419790acc05209 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 27 Dec 2013 18:10:51 +0400 Subject: [PATCH 122/295] getting data from opencv_extra --- modules/viz/test/test_main.cpp | 2 +- modules/viz/test/test_viz3d.cpp | 37 +++++++++++++++++---------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/modules/viz/test/test_main.cpp b/modules/viz/test/test_main.cpp index 6b2499344..e737d2db3 100644 --- a/modules/viz/test/test_main.cpp +++ b/modules/viz/test/test_main.cpp @@ -1,3 +1,3 @@ #include "test_precomp.hpp" -CV_TEST_MAIN("cv") +CV_TEST_MAIN("viz") diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 29cf81ebb..9fb291ce1 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -43,28 +43,29 @@ using namespace cv; -static cv::Mat cvcloud_load() -{ - cv::Mat cloud(1, 20000, CV_32FC3); - std::ifstream ifs("d:/cloud_dragon.ply"); - - std::string str; - for(size_t i = 0; i < 11; ++i) - std::getline(ifs, str); - - cv::Point3f* data = cloud.ptr(); - for(size_t i = 0; i < cloud.total(); ++i) - ifs >> data[i].x >> data[i].y >> data[i].z; - - return cloud; -} - TEST(Viz_viz3d, develop) { - cv::Mat cloud = cvcloud_load(); + std::cout << std::string(cvtest::TS::ptr()->get_data_path()) + "dragon.ply" << std::endl; + + cv::Mat cloud = cv::viz::readCloud(String(cvtest::TS::ptr()->get_data_path()) + "dragon.ply"); + cv::viz::Viz3d viz("abc"); - cv::viz::WCloud c(cloud, cv::Mat(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0))); + viz.showWidget("coo", cv::viz::WCoordinateSystem()); + + cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0)); + + //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); + + //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); + + cv::RNG rng; + rng.fill(colors, cv::RNG::UNIFORM, 0, 255); + cv::viz::WCloud c(cloud, colors); //cv::viz::WCloud c(cloud, cv::viz::Color::bluberry()); viz.showWidget("c", c); + + //viz.showWidget("l", cv::viz::WLine(Point3f(0,0,0), Point3f(1,1,1))); + //viz.showWidget("s", cv::viz::WSphere(Point3f(0,0,0), 1)); + //viz.showWidget("d", cv::viz::WCircle(Point3f(0,0,0), 1)); viz.spin(); } From 7e952e2f101c17aeceedad76534981211069a579 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 31 Dec 2013 18:52:10 +0400 Subject: [PATCH 123/295] removed incorrect and unnecessarily methods from Affine3f --- modules/core/include/opencv2/core/affine.hpp | 21 -------------------- 1 file changed, 21 deletions(-) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index fefcef8f1..0aaf57e0a 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -73,9 +73,6 @@ namespace cv //Combines all contructors above. Supports 4x4, 3x3, 1x3, 3x1 sizes of data matrix explicit Affine3(const cv::Mat& data, const Vec3& t = Vec3::all(0)); - //Euler angles - Affine3(float_type alpha, float_type beta, float_type gamma, const Vec3& t = Vec3::all(0)); - static Affine3 Identity(); //Rotation matrix @@ -87,9 +84,6 @@ namespace cv //Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix; void rotation(const Mat& data); - //Euler angles - void rotation(float_type alpha, float_type beta, float_type gamma); - void linear(const Mat3& L); void translation(const Vec3& t); @@ -186,15 +180,6 @@ cv::Affine3::Affine3(const cv::Mat& data, const Vec3& t) matrix.val[15] = 1; } -template inline -cv::Affine3::Affine3(float_type alpha, float_type beta, float_type gamma, const Vec3& t) -{ - rotation(alpha, beta, gamma); - translation(t); - matrix.val[12] = matrix.val[13] = matrix.val[14] = 0; - matrix.val[15] = 1; -} - template inline cv::Affine3 cv::Affine3::Identity() { @@ -261,12 +246,6 @@ void cv::Affine3::rotation(const cv::Mat& data) CV_Assert(!"Input marix can be 3x3, 1x3 or 3x1"); } -template inline -void cv::Affine3::rotation(float_type alpha, float_type beta, float_type gamma) -{ - rotation(Vec3(alpha, beta, gamma)); -} - template inline void cv::Affine3::linear(const Mat3& L) { From 1c4cfd8eaf2dee020303733f23532ed7cabf30d3 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 31 Dec 2013 21:03:10 +0400 Subject: [PATCH 124/295] normals support for CloudMatSource --- modules/viz/src/vtk/vtkCloudMatSource.cpp | 143 +++++++++++++++------- modules/viz/src/vtk/vtkCloudMatSource.h | 13 +- modules/viz/test/test_viz3d.cpp | 8 ++ 3 files changed, 116 insertions(+), 48 deletions(-) diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index f533361bc..b603a39b7 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -48,47 +48,86 @@ namespace cv { namespace viz { vtkStandardNewMacro(vtkCloudMatSource); - struct IsNotNan + template bool isNan(const _Tp* data) { - template bool operator()(const _Tp* data) const - { - return !isNan(data[0]) && !isNan(data[1]) && !isNan(data[2]); - } + return isNan(data[0]) || isNan(data[1]) || isNan(data[2]); + } + + template struct VtkDepthTraits; + + template<> struct VtkDepthTraits + { + const static int data_type = VTK_FLOAT; + typedef vtkFloatArray array_type; + }; + + template<> struct VtkDepthTraits + { + const static int data_type = VTK_DOUBLE; + typedef vtkDoubleArray array_type; }; }} cv::viz::vtkCloudMatSource::vtkCloudMatSource() { SetNumberOfInputPorts(0); } cv::viz::vtkCloudMatSource::~vtkCloudMatSource() {} -void cv::viz::vtkCloudMatSource::SetCloud(const Mat& cloud) +int cv::viz::vtkCloudMatSource::SetCloud(const Mat& cloud) { CV_Assert(cloud.depth() == CV_32F || cloud.depth() == CV_64F); CV_Assert(cloud.channels() == 3 || cloud.channels() == 4); - int total = cloud.depth() == CV_32F ? filterNanCopy(cloud, VTK_FLOAT) - : filterNanCopy(cloud, VTK_DOUBLE); + int total = cloud.depth() == CV_32F ? filterNanCopy(cloud) : filterNanCopy(cloud); vertices = vtkSmartPointer::New(); vertices->Allocate(vertices->EstimateSize(1, total)); vertices->InsertNextCell(total); for(int i = 0; i < total; ++i) vertices->InsertCellPoint(i); + + return total; } -void cv::viz::vtkCloudMatSource::SetColorCloud(const Mat &cloud, const Mat &colors) +int cv::viz::vtkCloudMatSource::SetColorCloud(const Mat &cloud, const Mat &colors) { - vtkCloudMatSource::SetCloud(cloud); + int total = SetCloud(cloud); if (colors.empty()) - return; + return total; CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); CV_Assert(colors.size() == cloud.size()); if (cloud.depth() == CV_32F) - filterNanColorsCopy(colors, cloud); + filterNanColorsCopy(colors, cloud, total); else if (cloud.depth() == CV_64F) - filterNanColorsCopy(colors, cloud); + filterNanColorsCopy(colors, cloud, total); + + return total; +} + +int cv::viz::vtkCloudMatSource::SetColorCloudNormals(const Mat &cloud, const Mat &colors, const Mat &normals) +{ + int total = SetColorCloud(cloud, colors); + + if (normals.empty()) + return total; + + CV_Assert(normals.depth() == CV_32F || normals.depth() == CV_64F); + CV_Assert(normals.channels() == 3 || normals.channels() == 4); + CV_Assert(normals.size() == cloud.size()); + + if (normals.depth() == CV_32F && cloud.depth() == CV_32F) + filterNanNormalsCopy(colors, cloud, total); + else if (normals.depth() == CV_32F && cloud.depth() == CV_64F) + filterNanNormalsCopy(colors, cloud, total); + else if (normals.depth() == CV_64F && cloud.depth() == CV_32F) + filterNanNormalsCopy(colors, cloud, total); + else if (normals.depth() == CV_64F && cloud.depth() == CV_64F) + filterNanNormalsCopy(colors, cloud, total); + else + CV_Assert(!"Unsupported normals type"); + + return total; } int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) @@ -100,27 +139,31 @@ int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), output->SetVerts(vertices); if (scalars) output->GetPointData()->SetScalars(scalars); + + if (normals) + output->GetPointData()->SetNormals(normals); + return 1; } template -int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& source, int dataType) +int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& cloud) { - CV_DbgAssert(DataType<_Tp>::depth == source.depth()); + CV_DbgAssert(DataType<_Tp>::depth == cloud.depth()); points = vtkSmartPointer::New(); - points->SetDataType(dataType); - points->Allocate(source.total()); - points->SetNumberOfPoints(source.total()); + points->SetDataType(VtkDepthTraits<_Tp>::data_type); + points->Allocate(cloud.total()); + points->SetNumberOfPoints(cloud.total()); - int cn = source.channels(); + int cn = cloud.channels(); int total = 0; - for (int y = 0; y < source.rows; ++y) + for (int y = 0; y < cloud.rows; ++y) { - const _Tp* srow = source.ptr<_Tp>(y); - const _Tp* send = srow + source.cols * cn; + const _Tp* srow = cloud.ptr<_Tp>(y); + const _Tp* send = srow + cloud.cols * cn; for (; srow != send; srow += cn) - if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) + if (!isNan(srow)) points->SetPoint(total++, srow); } points->SetNumberOfPoints(total); @@ -128,41 +171,33 @@ int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& source, int dataType) return total; } - -template -void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& colors, const Mat& mask) +template +void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& cloud_colors, const Mat& mask, int total) { - Mat buffer(colors.size(), CV_8UC3); - Vec3b* pos = buffer.ptr(); + Vec3b* array = new Vec3b[total]; + Vec3b* pos = array; - int s_chs = colors.channels(); + int s_chs = cloud_colors.channels(); int m_chs = mask.channels(); - - _NanPred pred; - - for (int y = 0; y < colors.rows; ++y) + for (int y = 0; y < cloud_colors.rows; ++y) { - const unsigned char* srow = colors.ptr(y); - const unsigned char* send = srow + colors.cols * colors.channels(); - const _Msk* mrow = mask.empty() ? 0 : mask.ptr<_Msk>(y); + const unsigned char* srow = cloud_colors.ptr(y); + const unsigned char* send = srow + cloud_colors.cols * cloud_colors.channels(); + const _Msk* mrow = mask.ptr<_Msk>(y); - if (colors.channels() == 1) + if (cloud_colors.channels() == 1) { for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) + if (!isNan(mrow)) *pos++ = Vec3b(srow[0], srow[0], srow[0]); } else for (; srow != send; srow += s_chs, mrow += m_chs) - if (pred(mrow)) + if (!isNan(mrow)) *pos++ = Vec3b(srow[2], srow[1], srow[0]); } - int total = pos - buffer.ptr(); - Vec3b* array = new Vec3b[total]; - std::copy(buffer.ptr(), pos, array); - scalars = vtkSmartPointer::New(); scalars->SetName("colors"); scalars->SetNumberOfComponents(3); @@ -170,4 +205,26 @@ void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& colors, const Ma scalars->SetArray(array->val, total * 3, 0); } +template +void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total) +{ + normals = vtkSmartPointer< VtkDepthTraits<_Tn>::array_type >::New(); + normals->SetNumberOfComponents(3); + normals->SetNumberOfTuples(total); + int s_chs = cloud_normals.channels(); + int m_chs = mask.channels(); + + int pos = 0; + for (int y = 0; y < cloud_normals.rows; ++y) + { + const _Tn* srow = cloud_normals.ptr<_Tn>(y); + const _Tn* send = srow + cloud_normals.cols * s_chs; + + const _Msk* mrow = mask.ptr<_Msk>(y); + + for (; srow != send; srow += s_chs, mrow += m_chs) + if (!isNan(mrow)) + normals->SetTuple(pos++, srow); + } +} diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index 876ab994f..023e72324 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -61,8 +61,9 @@ namespace cv static vtkCloudMatSource *New(); vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm); - virtual void SetCloud(const Mat& cloud); - virtual void SetColorCloud(const Mat &cloud, const Mat &colors = cv::Mat()); + virtual int SetCloud(const Mat& cloud); + virtual int SetColorCloud(const Mat &cloud, const Mat &colors = cv::Mat()); + virtual int SetColorCloudNormals(const Mat &cloud, const Mat &colors = cv::Mat(), const Mat &normals = cv::Mat()); protected: vtkCloudMatSource(); @@ -73,14 +74,16 @@ namespace cv vtkSmartPointer points; vtkSmartPointer vertices; vtkSmartPointer scalars; + vtkSmartPointer normals; private: vtkCloudMatSource(const vtkCloudMatSource&); // Not implemented. void operator=(const vtkCloudMatSource&); // Not implemented. - template int filterNanCopy(const Mat& source, int dataType); + template int filterNanCopy(const Mat& cloud); + template void filterNanColorsCopy(const Mat& cloud_colors, const Mat& mask, int total); - template - void filterNanColorsCopy(const Mat& colors, const Mat& mask); + template + void filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total); }; } } diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 9fb291ce1..ee9102399 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -49,6 +49,14 @@ TEST(Viz_viz3d, develop) cv::Mat cloud = cv::viz::readCloud(String(cvtest::TS::ptr()->get_data_path()) + "dragon.ply"); +// for(size_t i = 0; i < cloud.total(); ++i) +// { +// if (i % 15 == 0) +// continue; +// const static float qnan = std::numeric_limits::quiet_NaN(); +// cloud.at(i) = Vec3f(qnan, qnan, qnan); +// } + cv::viz::Viz3d viz("abc"); viz.showWidget("coo", cv::viz::WCoordinateSystem()); From c1b41caa7cec1bb42cfde238f0ba1ea7c178f1d2 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 31 Dec 2013 21:50:38 +0400 Subject: [PATCH 125/295] added vtkCloudMatSink, reworked cloud IO functions, added normals support --- modules/viz/include/opencv2/viz.hpp | 6 +- modules/viz/src/precomp.hpp | 1 + modules/viz/src/vizcore.cpp | 57 ++------- modules/viz/src/vtk/vtkCloudMatSink.cpp | 137 ++++++++++++++++++++++ modules/viz/src/vtk/vtkCloudMatSink.h | 76 ++++++++++++ modules/viz/src/vtk/vtkCloudMatSource.cpp | 2 +- modules/viz/test/test_viz3d.cpp | 7 +- 7 files changed, 233 insertions(+), 53 deletions(-) create mode 100644 modules/viz/src/vtk/vtkCloudMatSink.cpp create mode 100644 modules/viz/src/vtk/vtkCloudMatSink.h diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 49b36a9b2..cb399a8eb 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -93,10 +93,10 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// - /// Read/write clouds. Supported formats: ply, stl, xyz, obj + /// Read/write clouds. Supported formats: ply, xyz, obj and stl (readonly) - CV_EXPORTS void writeCloud(const String& file, InputArray cloud, InputArray colors = noArray()); - CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = cv::noArray()); + CV_EXPORTS void writeCloud(const String& file, InputArray cloud, InputArray colors = noArray(), InputArray normals = noArray(), bool binary = false); + CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = noArray(), OutputArray normals = noArray()); /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 83b779dd8..b10e83ad5 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -132,6 +132,7 @@ #endif #include +#include #include #include diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index 5a1a7a8fe..29f6be288 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -164,38 +164,36 @@ void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write clouds. Supported formats: ply, stl, xyz, obj -void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colors) +void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colors, InputArray _normals, bool binary) { CV_Assert(file.size() > 4 && "Extention is required"); String extention = file.substr(file.size()-4); Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); + Mat normals = _normals.getMat(); vtkSmartPointer source = vtkSmartPointer::New(); - source->SetColorCloud(cloud, colors); + source->SetColorCloudNormals(cloud, colors, normals); vtkSmartPointer writer; if (extention == ".xyz") { writer = vtkSmartPointer::New(); - vtkPLYWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + vtkXYZWriter::SafeDownCast(writer)->SetFileName(file.c_str()); } else if (extention == ".ply") { writer = vtkSmartPointer::New(); vtkPLYWriter::SafeDownCast(writer)->SetFileName(file.c_str()); + vtkPLYWriter::SafeDownCast(writer)->SetFileType(binary ? VTK_BINARY : VTK_ASCII); + vtkPLYWriter::SafeDownCast(writer)->SetArrayName("Colors"); } else if (extention == ".obj") { writer = vtkSmartPointer::New(); vtkOBJWriter::SafeDownCast(writer)->SetFileName(file.c_str()); } - else if (extention == ".stl") - { - writer = vtkSmartPointer::New(); - vtkSTLWriter::SafeDownCast(writer)->SetFileName(file.c_str()); - } else CV_Assert(!"Unsupported format"); @@ -203,7 +201,7 @@ void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colo writer->Write(); } -cv::Mat cv::viz::readCloud(const String& file, OutputArray colors) +cv::Mat cv::viz::readCloud(const String& file, OutputArray colors, OutputArray normals) { CV_Assert(file.size() > 4 && "Extention is required"); String extention = file.substr(file.size()-4); @@ -233,43 +231,12 @@ cv::Mat cv::viz::readCloud(const String& file, OutputArray colors) else CV_Assert(!"Unsupported format"); - reader->Update(); - vtkSmartPointer poly_data = reader->GetOutput(); - vtkSmartPointer points = poly_data->GetPoints(); + cv::Mat cloud; - int vtktype = points->GetDataType(); - CV_Assert(vtktype == VTK_FLOAT || vtktype == VTK_DOUBLE); - - Mat cloud(1, points->GetNumberOfPoints(), vtktype == VTK_FLOAT ? CV_32FC3 : CV_64FC3); - Vec3d *ddata = cloud.ptr(); - Vec3f *fdata = cloud.ptr(); - - if (cloud.depth() == CV_32F) - for(size_t i = 0; i < cloud.total(); ++i) - *fdata++ = Vec3d(points->GetPoint(i)); - - if (cloud.depth() == CV_64F) - for(size_t i = 0; i < cloud.total(); ++i) - *ddata++ = Vec3d(points->GetPoint(i)); - - vtkSmartPointer scalars = poly_data->GetPointData() ? poly_data->GetPointData()->GetScalars() : 0; - - if (colors.needed() && scalars) - { - int channels = scalars->GetNumberOfComponents(); - int vtktype = scalars->GetDataType(); - - CV_Assert((channels == 3 || channels == 4) && "Only 3- or 4-channel color data support is implemented"); - CV_Assert(cloud.total() == (size_t)scalars->GetNumberOfTuples()); - Mat buffer(cloud.size(), CV_64FC(channels)); - Vec3d *cptr = buffer.ptr(); - for(size_t i = 0; i < colors.total(); ++i) - *cptr++ = Vec3d(scalars->GetTuple(i)); - - buffer.convertTo(colors, CV_8U, vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE ? 255.0 : 1.0); - } - else - colors.release(); + vtkSmartPointer sink = vtkSmartPointer::New(); + sink->SetInputConnection(reader->GetOutputPort()); + sink->SetOutput(cloud, colors, normals); + sink->Write(); return cloud; } diff --git a/modules/viz/src/vtk/vtkCloudMatSink.cpp b/modules/viz/src/vtk/vtkCloudMatSink.cpp new file mode 100644 index 000000000..b96db385b --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudMatSink.cpp @@ -0,0 +1,137 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkCloudMatSink); +}} + +cv::viz::vtkCloudMatSink::vtkCloudMatSink() {} +cv::viz::vtkCloudMatSink::~vtkCloudMatSink() {} + +void cv::viz::vtkCloudMatSink::SetOutput(OutputArray _cloud, OutputArray _colors, OutputArray _normals) +{ + cloud = _cloud; + colors = _colors; + normals = _normals; +} + +void cv::viz::vtkCloudMatSink::WriteData() +{ + vtkPolyData *input = this->GetInput(); + if (!input) + return; + + vtkSmartPointer points_Data = input->GetPoints(); + + if (cloud.needed() && points_Data) + { + int vtktype = points_Data->GetDataType(); + CV_Assert(vtktype == VTK_FLOAT || vtktype == VTK_DOUBLE); + + cloud.create(1, points_Data->GetNumberOfPoints(), vtktype == VTK_FLOAT ? CV_32FC3 : CV_64FC3); + Vec3d *ddata = (Vec3d*)cloud.getMat().ptr(); + Vec3f *fdata = (Vec3f*)cloud.getMat().ptr(); + + if (cloud.depth() == CV_32F) + for(size_t i = 0; i < cloud.total(); ++i) + *fdata++ = Vec3d(points_Data->GetPoint(i)); + + if (cloud.depth() == CV_64F) + for(size_t i = 0; i < cloud.total(); ++i) + *ddata++ = Vec3d(points_Data->GetPoint(i)); + } + else + cloud.release(); + + vtkSmartPointer scalars_data = input->GetPointData() ? input->GetPointData()->GetScalars() : 0; + + if (colors.needed() && scalars_data) + { + int channels = scalars_data->GetNumberOfComponents(); + int vtktype = scalars_data->GetDataType(); + + CV_Assert((channels == 3 || channels == 4) && "Only 3- or 4-channel color data support is implemented"); + CV_Assert(cloud.total() == (size_t)scalars_data->GetNumberOfTuples()); + + Mat buffer(cloud.size(), CV_64FC(channels)); + Vec3d *cptr = buffer.ptr(); + for(size_t i = 0; i < buffer.total(); ++i) + *cptr++ = Vec3d(scalars_data->GetTuple(i)); + + buffer.convertTo(colors, CV_8U, vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE ? 255.0 : 1.0); + } + else + colors.release(); + + vtkSmartPointer normals_data = input->GetPointData() ? input->GetPointData()->GetNormals() : 0; + + if (normals.needed() && normals_data) + { + int channels = normals_data->GetNumberOfComponents(); + int vtktype = normals_data->GetDataType(); + + CV_Assert((vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE) && (channels == 3 || channels == 4)); + CV_Assert(cloud.total() == (size_t)normals_data->GetNumberOfTuples()); + + Mat buffer(cloud.size(), CV_64FC(channels)); + Vec3d *cptr = buffer.ptr(); + for(size_t i = 0; i < buffer.total(); ++i) + *cptr++ = Vec3d(scalars_data->GetTuple(i)); + + buffer.convertTo(normals, vtktype == VTK_FLOAT ? CV_32F : CV_64F); + } + else + normals.release(); +} + +void cv::viz::vtkCloudMatSink::PrintSelf(ostream& os, vtkIndent indent) +{ + Superclass::PrintSelf(os, indent); + os << indent << "Cloud: " << cloud.needed() << "\n"; + os << indent << "Colors: " << colors.needed() << "\n"; + os << indent << "Normals: " << normals.needed() << "\n"; +} diff --git a/modules/viz/src/vtk/vtkCloudMatSink.h b/modules/viz/src/vtk/vtkCloudMatSink.h new file mode 100644 index 000000000..e4a55f078 --- /dev/null +++ b/modules/viz/src/vtk/vtkCloudMatSink.h @@ -0,0 +1,76 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#ifndef __vtkCloudMatSink_h +#define __vtkCloudMatSink_h + +namespace cv +{ + namespace viz + { + class vtkCloudMatSink : public vtkPolyDataWriter + { + public: + static vtkCloudMatSink *New(); + vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray()); + + protected: + vtkCloudMatSink(); + ~vtkCloudMatSink(); + + void WriteData(); + + _OutputArray cloud, colors, normals; + + private: + vtkCloudMatSink(const vtkCloudMatSink&); // Not implemented. + void operator=(const vtkCloudMatSink&); // Not implemented. + }; + } +} + +#endif diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index b603a39b7..476e0d5ed 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -199,7 +199,7 @@ void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& cloud_colors, co } scalars = vtkSmartPointer::New(); - scalars->SetName("colors"); + scalars->SetName("Colors"); scalars->SetNumberOfComponents(3); scalars->SetNumberOfTuples(total); scalars->SetArray(array->val, total * 3, 0); diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index ee9102399..99476f675 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -49,6 +49,7 @@ TEST(Viz_viz3d, develop) cv::Mat cloud = cv::viz::readCloud(String(cvtest::TS::ptr()->get_data_path()) + "dragon.ply"); + // for(size_t i = 0; i < cloud.total(); ++i) // { // if (i % 15 == 0) @@ -63,14 +64,12 @@ TEST(Viz_viz3d, develop) cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0)); //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); - //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); cv::RNG rng; rng.fill(colors, cv::RNG::UNIFORM, 0, 255); - cv::viz::WCloud c(cloud, colors); - //cv::viz::WCloud c(cloud, cv::viz::Color::bluberry()); - viz.showWidget("c", c); + viz.showWidget("c", cv::viz::WCloud(cloud, colors)); + //viz.showWidget("c", cv::viz::WCloud(cloud, cv::viz::Color::bluberry())); //viz.showWidget("l", cv::viz::WLine(Point3f(0,0,0), Point3f(1,1,1))); //viz.showWidget("s", cv::viz::WSphere(Point3f(0,0,0), 1)); From e7791e1590a81010afb18a61fe913c90dbface74 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 16:35:16 +0400 Subject: [PATCH 126/295] colors minor --- modules/viz/include/opencv2/viz/types.hpp | 12 ++++-------- modules/viz/test/test_viz3d.cpp | 12 ++++++++++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index ab5aafc38..ff6bd5a68 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -197,19 +197,19 @@ inline cv::viz::Color cv::viz::Color::magenta() { return Color(255, 0, 255); } inline cv::viz::Color cv::viz::Color::white() { return Color(255, 255, 255); } inline cv::viz::Color cv::viz::Color::gray() { return Color(128, 128, 128); } -inline cv::viz::Color cv::viz::Color::mlab() { return Color(235, 118, 118); } +inline cv::viz::Color cv::viz::Color::mlab() { return Color(255, 128, 128); } inline cv::viz::Color cv::viz::Color::navy() { return Color(0, 0, 128); } inline cv::viz::Color cv::viz::Color::olive() { return Color(0, 128, 128); } inline cv::viz::Color cv::viz::Color::maroon() { return Color(0, 0, 128); } inline cv::viz::Color cv::viz::Color::teal() { return Color(128, 128, 0); } -inline cv::viz::Color cv::viz::Color::rose() { return Color(127, 0, 255); } -inline cv::viz::Color cv::viz::Color::azure() { return Color(255, 127, 0); } +inline cv::viz::Color cv::viz::Color::rose() { return Color(128, 0, 255); } +inline cv::viz::Color cv::viz::Color::azure() { return Color(255, 128, 0); } inline cv::viz::Color cv::viz::Color::lime() { return Color(0, 255, 191); } inline cv::viz::Color cv::viz::Color::gold() { return Color(0, 215, 255); } inline cv::viz::Color cv::viz::Color::brown() { return Color(0, 75, 150); } inline cv::viz::Color cv::viz::Color::orange() { return Color(0, 165, 255); } -inline cv::viz::Color cv::viz::Color::chartreuse() { return Color(0, 255, 127); } +inline cv::viz::Color cv::viz::Color::chartreuse() { return Color(0, 255, 128); } inline cv::viz::Color cv::viz::Color::orange_red() { return Color(0, 69, 255); } inline cv::viz::Color cv::viz::Color::purple() { return Color(128, 0, 128); } inline cv::viz::Color cv::viz::Color::indigo() { return Color(130, 0, 75); } @@ -225,8 +225,4 @@ inline cv::viz::Color cv::viz::Color::turquoise() { return Color(208, 224, inline cv::viz::Color cv::viz::Color::celestial_blue() { return Color(208, 151, 73); } inline cv::viz::Color cv::viz::Color::amethyst() { return Color(204, 102, 153); } - - - - #endif diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 99476f675..df66727d8 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -59,16 +59,24 @@ TEST(Viz_viz3d, develop) // } cv::viz::Viz3d viz("abc"); - viz.showWidget("coo", cv::viz::WCoordinateSystem()); + viz.setBackgroundColor(cv::viz::Color::mlab()); + viz.showWidget("coo", cv::viz::WCoordinateSystem(0.1)); cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0)); //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); + std::vector gt, es; + cv::viz::readTrajectory(gt, "d:/Datasets/trajs/gt%05d.xml"); + cv::viz::readTrajectory(es, "d:/Datasets/trajs/es%05d.xml"); + + viz.showWidget("gt", viz::WTrajectory(gt, viz::WTrajectory::PATH, 1.f, viz::Color::blue()), gt[0].inv()); + viz.showWidget("tr", viz::WTrajectory(es, viz::WTrajectory::PATH, 1.f, viz::Color::red()), gt[0].inv()); + cv::RNG rng; rng.fill(colors, cv::RNG::UNIFORM, 0, 255); - viz.showWidget("c", cv::viz::WCloud(cloud, colors)); + //viz.showWidget("c", cv::viz::WCloud(cloud, colors)); //viz.showWidget("c", cv::viz::WCloud(cloud, cv::viz::Color::bluberry())); //viz.showWidget("l", cv::viz::WLine(Point3f(0,0,0), Point3f(1,1,1))); From f610c295f2badb79386e81d0b4df4b594f5d4ced Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 17:55:18 +0400 Subject: [PATCH 127/295] more tests --- modules/viz/include/opencv2/viz/widgets.hpp | 4 +- modules/viz/src/clouds.cpp | 12 --- modules/viz/src/shapes.cpp | 12 +-- modules/viz/test/test_precomp.cpp | 23 ++++++ modules/viz/test/test_precomp.hpp | 16 ++++ modules/viz/test/test_tutorial2.cpp | 2 +- modules/viz/test/test_tutorial3.cpp | 16 ++-- modules/viz/test/tests_simple.cpp | 87 +++++++++++++++++++++ 8 files changed, 143 insertions(+), 29 deletions(-) create mode 100644 modules/viz/test/tests_simple.cpp diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 1f48686f4..5ca06800b 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -234,9 +234,9 @@ namespace cv { public: //! Creates grid at the origin - WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + WGrid(const Vec2i &dimensions, const Vec2f &spacing, const Color &color = Color::white()); //! Creates grid based on the plane equation - WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2f &spacing, const Color &color = Color::white()); }; class CV_EXPORTS WCameraPosition : public Widget3D diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 555da22d0..ce9acd346 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -63,12 +63,6 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); - if (cloud.isContinuous() && colors.isContinuous()) - { - cloud = cloud.reshape(cloud.channels(), 1); - colors = colors.reshape(colors.channels(), 1); - } - vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetColorCloud(cloud, colors); @@ -268,12 +262,6 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); CV_Assert(colors.depth() == CV_8U && cloud.size() == colors.size()); - if (cloud.isContinuous() && colors.isContinuous()) - { - cloud = cloud.reshape(cloud.channels(), 1); - colors = colors.reshape(colors.channels(), 1); - } - vtkIdType nr_points; vtkSmartPointer polydata = CloudCollectionUtils::create(cloud, nr_points); diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 0450eb816..e9102b728 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -474,7 +474,7 @@ namespace cv { namespace viz { namespace { struct GridUtils { - static vtkSmartPointer createGrid(const Vec2i &dimensions, const Vec2d &spacing) + static vtkSmartPointer createGrid(const Vec2i &dimensions, const Vec2f &spacing) { // Create the grid using image data vtkSmartPointer grid = vtkSmartPointer::New(); @@ -500,7 +500,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color) +cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2f &spacing, const Color &color) { vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); @@ -518,7 +518,7 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color setColor(color); } -cv::viz::WGrid::WGrid(const Vec4f &coefs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color) +cv::viz::WGrid::WGrid(const Vec4f &coefs, const Vec2i &dimensions, const Vec2f &spacing, const Color &color) { vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); @@ -1224,11 +1224,11 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display vtkIdType nr_points = path.size(); vtkSmartPointer points = vtkSmartPointer::New(); - vtkSmartPointer polyData = vtkSmartPointer::New(); - vtkSmartPointer polyLine = vtkSmartPointer::New(); - points->SetDataTypeToFloat(); points->SetNumberOfPoints(nr_points); + + vtkSmartPointer polyData = vtkSmartPointer::New(); + vtkSmartPointer polyLine = vtkSmartPointer::New(); polyLine->GetPointIds()->SetNumberOfIds(nr_points); Vec3f *data_beg = vtkpoints_data(points); diff --git a/modules/viz/test/test_precomp.cpp b/modules/viz/test/test_precomp.cpp index 5956e13e3..c2673fee6 100644 --- a/modules/viz/test/test_precomp.cpp +++ b/modules/viz/test/test_precomp.cpp @@ -1 +1,24 @@ #include "test_precomp.hpp" + +cv::String cv::Path::combine(const String& item1, const String& item2) +{ + if (item1.empty()) + return item2; + + if (item2.empty()) + return item1; + + char last = item1[item1.size()-1]; + + bool need_append = last != '/' && last != '\\'; + return item1 + (need_append ? "/" : "") + item2; +} + +cv::String cv::Path::combine(const String& item1, const String& item2, const String& item3) +{ return combine(combine(item1, item2), item3); } + +cv::String cv::Path::change_extension(const String& file, const String& ext) +{ + String::size_type pos = file.find_last_of('.'); + return pos == String::npos ? file : file.substr(0, pos+1) + ext; +} diff --git a/modules/viz/test/test_precomp.hpp b/modules/viz/test/test_precomp.hpp index ff7606ed9..efc89b27f 100644 --- a/modules/viz/test/test_precomp.hpp +++ b/modules/viz/test/test_precomp.hpp @@ -63,5 +63,21 @@ #include #include #include +#include + +namespace cv +{ + struct Path + { + static String combine(const String& item1, const String& item2); + static String combine(const String& item1, const String& item2, const String& item3); + static String change_extension(const String& file, const String& ext); + }; + + inline cv::String get_dragon_ply_file_path() + { + return Path::combine(cvtest::TS::ptr()->get_data_path(), "dragon.ply"); + } +} #endif diff --git a/modules/viz/test/test_tutorial2.cpp b/modules/viz/test/test_tutorial2.cpp index 6e9189b8f..cba24638b 100644 --- a/modules/viz/test/test_tutorial2.cpp +++ b/modules/viz/test/test_tutorial2.cpp @@ -48,7 +48,7 @@ void tutorial2() } -TEST(Viz_viz3d, DISABLED_tutorial2_pose_of_widget) +TEST(Viz, DISABLED_tutorial2_pose_of_widget) { tutorial2(); } diff --git a/modules/viz/test/test_tutorial3.cpp b/modules/viz/test/test_tutorial3.cpp index 12eca311c..8b4321548 100644 --- a/modules/viz/test/test_tutorial3.cpp +++ b/modules/viz/test/test_tutorial3.cpp @@ -15,21 +15,21 @@ void tutorial3(bool camera_pov) myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem()); /// Let's assume camera has the following properties - Point3f cam_pos(3.0f,3.0f,3.0f), cam_focal_point(3.0f,3.0f,2.0f), cam_y_dir(-1.0f,0.0f,0.0f); + Point3f cam_pos(3.f, 3.f, 3.f), cam_focal_point(3.f, 3.f, 2.f), cam_y_dir(-1.f, 0.f, 0.f); /// We can get the pose of the cam using makeCameraPose Affine3f cam_pose = viz::makeCameraPose(cam_pos, cam_focal_point, cam_y_dir); /// We can get the transformation matrix from camera coordinate system to global using /// - makeTransformToGlobal. We need the axes of the camera - Affine3f transform = viz::makeTransformToGlobal(Vec3f(0.0f,-1.0f,0.0f), Vec3f(-1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), cam_pos); + Affine3f transform = viz::makeTransformToGlobal(Vec3f(0.f, -1.f, 0.f), Vec3f(-1.f, 0.f, 0.f), Vec3f(0.f, 0.f, -1.f), cam_pos); /// Create a cloud widget. - Mat bunny_cloud = viz::readCloud("d:/cloud_dragon.ply"); - viz::WCloud cloud_widget(bunny_cloud, viz::Color::green()); + Mat dragon_cloud = viz::readCloud(get_dragon_ply_file_path()); + viz::WCloud cloud_widget(dragon_cloud, viz::Color::green()); /// Pose of the widget in camera frame - Affine3f cloud_pose = Affine3f().translate(Vec3f(0.0f,0.0f,3.0f)); + Affine3f cloud_pose = Affine3f().translate(Vec3f(0.f, 0.f, 3.f)); /// Pose of the widget in global frame Affine3f cloud_pose_global = transform * cloud_pose; @@ -37,7 +37,7 @@ void tutorial3(bool camera_pov) if (!camera_pov) { viz::WCameraPosition cpw(0.5); // Coordinate axes - viz::WCameraPosition cpw_frustum(Vec2f(0.889484, 0.523599)); // Camera frustum + viz::WCameraPosition cpw_frustum(Vec2f(0.889484f, 0.523599f)); // Camera frustum myWindow.showWidget("CPW", cpw, cam_pose); myWindow.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose); } @@ -53,12 +53,12 @@ void tutorial3(bool camera_pov) myWindow.spin(); } -TEST(Viz_viz3d, DISABLED_tutorial3_global_view) +TEST(Viz, DISABLED_tutorial3_global_view) { tutorial3(false); } -TEST(Viz_viz3d, DISABLED_tutorial3_camera_view) +TEST(Viz, DISABLED_tutorial3_camera_view) { tutorial3(true); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp new file mode 100644 index 000000000..1a2e9fc94 --- /dev/null +++ b/modules/viz/test/tests_simple.cpp @@ -0,0 +1,87 @@ +/*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) 2000-2008, Intel Corporation, all rights reserved. + // Copyright (C) 2008-2013, Willow Garage Inc., 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*/ + +#include "test_precomp.hpp" + +using namespace cv; +using namespace cv::viz; + +TEST(Viz, DISABLED_show_cloud_bluberry) +{ + Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); + + Viz3d viz("show_cloud_bluberry"); + viz.setBackgroundColor(); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("dragon", WCloud(dragon_cloud, Color::bluberry())); + viz.spin(); +} + +TEST(Viz, DISABLED_show_cloud_random_color) +{ + Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); + + Mat colors(dragon_cloud.size(), CV_8UC3); + theRNG().fill(colors, RNG::UNIFORM, 0, 255); + + Viz3d viz("show_cloud_random_color"); + viz.setBackgroundColor(); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("dragon", WCloud(dragon_cloud, colors)); + viz.spin(); +} + +TEST(Viz, DISABLED_show_cloud_masked) +{ + Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); + + Vec3f qnan = Vec3f::all(std::numeric_limits::quiet_NaN()); + for(size_t i = 0; i < dragon_cloud.total(); ++i) + if (i % 15 != 0) + dragon_cloud.at(i) = qnan; + + Viz3d viz("show_cloud_masked"); + viz.setBackgroundColor(); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("dragon", WCloud(dragon_cloud)); + viz.spin(); +} From 1615527426dab092712665f05610440432bfbcc7 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 18:21:23 +0400 Subject: [PATCH 128/295] switched source to InputArrays --- modules/viz/src/clouds.cpp | 11 ++---- modules/viz/src/vizcore.cpp | 6 +-- modules/viz/src/vtk/vtkCloudMatSource.cpp | 46 +++++++++++++---------- modules/viz/src/vtk/vtkCloudMatSource.h | 6 +-- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index ce9acd346..4746bc2e5 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -56,12 +56,9 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// /// Point Cloud Widget implementation -cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) +cv::viz::WCloud::WCloud(InputArray cloud, InputArray colors) { - CV_Assert(!_cloud.empty() && !_colors.empty()); - - Mat cloud = _cloud.getMat(); - Mat colors = _colors.getMat(); + CV_Assert(!cloud.empty() && !colors.empty()); vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetColorCloud(cloud, colors); @@ -81,10 +78,8 @@ cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) WidgetAccessor::setProp(*this, actor); } -cv::viz::WCloud::WCloud(InputArray _cloud, const Color &color) +cv::viz::WCloud::WCloud(InputArray cloud, const Color &color) { - Mat cloud = _cloud.getMat(); - vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetCloud(cloud); diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index 29f6be288..5029756c2 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -164,15 +164,11 @@ void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write clouds. Supported formats: ply, stl, xyz, obj -void cv::viz::writeCloud(const String& file, InputArray _cloud, InputArray _colors, InputArray _normals, bool binary) +void cv::viz::writeCloud(const String& file, InputArray cloud, InputArray colors, InputArray normals, bool binary) { CV_Assert(file.size() > 4 && "Extention is required"); String extention = file.substr(file.size()-4); - Mat cloud = _cloud.getMat(); - Mat colors = _colors.getMat(); - Mat normals = _normals.getMat(); - vtkSmartPointer source = vtkSmartPointer::New(); source->SetColorCloudNormals(cloud, colors, normals); diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index 476e0d5ed..46603a7b9 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -71,12 +71,14 @@ namespace cv { namespace viz cv::viz::vtkCloudMatSource::vtkCloudMatSource() { SetNumberOfInputPorts(0); } cv::viz::vtkCloudMatSource::~vtkCloudMatSource() {} -int cv::viz::vtkCloudMatSource::SetCloud(const Mat& cloud) +int cv::viz::vtkCloudMatSource::SetCloud(InputArray _cloud) { - CV_Assert(cloud.depth() == CV_32F || cloud.depth() == CV_64F); - CV_Assert(cloud.channels() == 3 || cloud.channels() == 4); + CV_Assert(_cloud.depth() == CV_32F || _cloud.depth() == CV_64F); + CV_Assert(_cloud.channels() == 3 || _cloud.channels() == 4); - int total = cloud.depth() == CV_32F ? filterNanCopy(cloud) : filterNanCopy(cloud); + Mat cloud = _cloud.getMat(); + + int total = _cloud.depth() == CV_32F ? filterNanCopy(cloud) : filterNanCopy(cloud); vertices = vtkSmartPointer::New(); vertices->Allocate(vertices->EstimateSize(1, total)); @@ -87,15 +89,18 @@ int cv::viz::vtkCloudMatSource::SetCloud(const Mat& cloud) return total; } -int cv::viz::vtkCloudMatSource::SetColorCloud(const Mat &cloud, const Mat &colors) +int cv::viz::vtkCloudMatSource::SetColorCloud(InputArray _cloud, InputArray _colors) { - int total = SetCloud(cloud); + int total = SetCloud(_cloud); - if (colors.empty()) + if (_colors.empty()) return total; - CV_Assert(colors.depth() == CV_8U && colors.channels() <= 4 && colors.channels() != 2); - CV_Assert(colors.size() == cloud.size()); + CV_Assert(_colors.depth() == CV_8U && _colors.channels() <= 4 && _colors.channels() != 2); + CV_Assert(_colors.size() == _cloud.size()); + + Mat cloud = _cloud.getMat(); + Mat colors = _colors.getMat(); if (cloud.depth() == CV_32F) filterNanColorsCopy(colors, cloud, total); @@ -105,25 +110,28 @@ int cv::viz::vtkCloudMatSource::SetColorCloud(const Mat &cloud, const Mat &color return total; } -int cv::viz::vtkCloudMatSource::SetColorCloudNormals(const Mat &cloud, const Mat &colors, const Mat &normals) +int cv::viz::vtkCloudMatSource::SetColorCloudNormals(InputArray _cloud, InputArray _colors, InputArray _normals) { - int total = SetColorCloud(cloud, colors); + int total = SetColorCloud(_cloud, _colors); - if (normals.empty()) + if (_normals.empty()) return total; - CV_Assert(normals.depth() == CV_32F || normals.depth() == CV_64F); - CV_Assert(normals.channels() == 3 || normals.channels() == 4); - CV_Assert(normals.size() == cloud.size()); + CV_Assert(_normals.depth() == CV_32F || _normals.depth() == CV_64F); + CV_Assert(_normals.channels() == 3 || _normals.channels() == 4); + CV_Assert(_normals.size() == _cloud.size()); + + Mat cloud = _cloud.getMat(); + Mat normals = _normals.getMat(); if (normals.depth() == CV_32F && cloud.depth() == CV_32F) - filterNanNormalsCopy(colors, cloud, total); + filterNanNormalsCopy(normals, cloud, total); else if (normals.depth() == CV_32F && cloud.depth() == CV_64F) - filterNanNormalsCopy(colors, cloud, total); + filterNanNormalsCopy(normals, cloud, total); else if (normals.depth() == CV_64F && cloud.depth() == CV_32F) - filterNanNormalsCopy(colors, cloud, total); + filterNanNormalsCopy(normals, cloud, total); else if (normals.depth() == CV_64F && cloud.depth() == CV_64F) - filterNanNormalsCopy(colors, cloud, total); + filterNanNormalsCopy(normals, cloud, total); else CV_Assert(!"Unsupported normals type"); diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index 023e72324..a1d854c32 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -61,9 +61,9 @@ namespace cv static vtkCloudMatSource *New(); vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm); - virtual int SetCloud(const Mat& cloud); - virtual int SetColorCloud(const Mat &cloud, const Mat &colors = cv::Mat()); - virtual int SetColorCloudNormals(const Mat &cloud, const Mat &colors = cv::Mat(), const Mat &normals = cv::Mat()); + virtual int SetCloud(InputArray cloud); + virtual int SetColorCloud(InputArray cloud, InputArray colors = noArray()); + virtual int SetColorCloudNormals(InputArray cloud, InputArray colors = noArray(), InputArray normals = noArray()); protected: vtkCloudMatSource(); From b1c0bf1fee85b37e52dbbf6e491a7fbab8639861 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 19:26:04 +0400 Subject: [PATCH 129/295] Affine::rotate(rvec) method --- modules/core/include/opencv2/core/affine.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index 0aaf57e0a..b4e7472a9 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -99,6 +99,9 @@ namespace cv // a.rotate(R) is equivalent to Affine(R, 0) * a; Affine3 rotate(const Mat3& R) const; + // a.rotate(R) is equivalent to Affine(rvec, 0) * a; + Affine3 rotate(const Vec3& rvec) const; + // a.translate(t) is equivalent to Affine(E, t) * a; Affine3 translate(const Vec3& t) const; @@ -361,6 +364,12 @@ cv::Affine3 cv::Affine3::rotate(const Mat3& R) const return result; } +template inline +cv::Affine3 cv::Affine3::rotate(const Vec3& _rvec) const +{ + return rotate(Affine3f(_rvec).rotation()); +} + template inline cv::Affine3 cv::Affine3::translate(const Vec3& t) const { From 186853a50fddc7a814433cb082956ace780a4f47 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 19:58:41 +0400 Subject: [PATCH 130/295] mass switch from Affine3f to Affine3d --- modules/viz/doc/viz3d.rst | 28 ++--- modules/viz/doc/widget.rst | 36 +++---- modules/viz/include/opencv2/viz.hpp | 7 +- modules/viz/include/opencv2/viz/viz3d.hpp | 12 +-- modules/viz/include/opencv2/viz/widgets.hpp | 17 +-- modules/viz/src/clouds.cpp | 4 +- modules/viz/src/shapes.cpp | 112 ++++++++++++++++++-- modules/viz/src/viz3d.cpp | 12 +-- modules/viz/src/vizcore.cpp | 62 ++++++----- modules/viz/src/vizimpl.cpp | 40 +++---- modules/viz/src/vizimpl.hpp | 37 ++----- modules/viz/src/widget.cpp | 10 +- modules/viz/test/test_tutorial2.cpp | 18 ++-- modules/viz/test/test_tutorial3.cpp | 10 +- modules/viz/test/test_viz3d.cpp | 2 +- 15 files changed, 238 insertions(+), 169 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index 63c5ac34c..ad1356e58 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -13,7 +13,7 @@ viz::makeTransformToGlobal -------------------------- Takes coordinate frame data and builds transform to global coordinate frame. -.. ocv:function:: Affine3f viz::makeTransformToGlobal(const Vec3f& axis_x, const Vec3f& axis_y, const Vec3f& axis_z, const Vec3f& origin = Vec3f::all(0)) +.. ocv:function:: Affine3d viz::makeTransformToGlobal(const Vec3f& axis_x, const Vec3f& axis_y, const Vec3f& axis_z, const Vec3f& origin = Vec3f::all(0)) :param axis_x: X axis vector in global coordinate frame. :param axis_y: Y axis vector in global coordinate frame. @@ -26,7 +26,7 @@ viz::makeCameraPose ------------------- Constructs camera pose from position, focal_point and up_vector (see gluLookAt() for more infromation). -.. ocv:function:: Affine3f makeCameraPose(const Vec3f& position, const Vec3f& focal_point, const Vec3f& y_dir) +.. ocv:function:: Affine3d makeCameraPose(const Vec3f& position, const Vec3f& focal_point, const Vec3f& y_dir) :param position: Position of the camera in global coordinate frame. :param focal_point: Focal point of the camera in global coordinate frame. @@ -94,19 +94,19 @@ The Viz3d class represents a 3D visualizer window. This class is implicitly shar Viz3d& operator=(const Viz3d&); ~Viz3d(); - void showWidget(const String &id, const Widget &widget, const Affine3f &pose = Affine3f::Identity()); + void showWidget(const String &id, const Widget &widget, const Affine3d &pose = Affine3d::Identity()); void removeWidget(const String &id); Widget getWidget(const String &id) const; void removeAllWidgets(); - void setWidgetPose(const String &id, const Affine3f &pose); - void updateWidgetPose(const String &id, const Affine3f &pose); - Affine3f getWidgetPose(const String &id) const; + void setWidgetPose(const String &id, const Affine3d &pose); + void updateWidgetPose(const String &id, const Affine3d &pose); + Affine3d getWidgetPose(const String &id) const; void setCamera(const Camera &camera); Camera getCamera() const; - Affine3f getViewerPose(); - void setViewerPose(const Affine3f &pose); + Affine3d getViewerPose(); + void setViewerPose(const Affine3d &pose); void resetCameraViewpoint (const String &id); void resetCamera(); @@ -152,7 +152,7 @@ viz::Viz3d::showWidget ---------------------- Shows a widget in the window. -.. ocv:function:: void Viz3d::showWidget(const String &id, const Widget &widget, const Affine3f &pose = Affine3f::Identity()) +.. ocv:function:: void Viz3d::showWidget(const String &id, const Widget &widget, const Affine3d &pose = Affine3d::Identity()) :param id: A unique id for the widget. :param widget: The widget to be displayed in the window. @@ -186,7 +186,7 @@ viz::Viz3d::setWidgetPose ------------------------- Sets pose of a widget in the window. -.. ocv:function:: void setWidgetPose(const String &id, const Affine3f &pose) +.. ocv:function:: void setWidgetPose(const String &id, const Affine3d &pose) :param id: The id of the widget whose pose will be set. :param pose: The new pose of the widget. @@ -195,7 +195,7 @@ viz::Viz3d::updateWidgetPose ---------------------------- Updates pose of a widget in the window by pre-multiplying its current pose. -.. ocv:function:: void updateWidgetPose(const String &id, const Affine3f &pose) +.. ocv:function:: void updateWidgetPose(const String &id, const Affine3d &pose) :param id: The id of the widget whose pose will be updated. :param pose: The pose that the current pose of the widget will be pre-multiplied by. @@ -204,7 +204,7 @@ viz::Viz3d::getWidgetPose ------------------------- Returns the current pose of a widget in the window. -.. ocv:function:: Affine3f getWidgetPose(const String &id) const +.. ocv:function:: Affine3d getWidgetPose(const String &id) const :param id: The id of the widget whose pose will be returned. @@ -226,13 +226,13 @@ viz::Viz3d::getViewerPose ------------------------- Returns the current pose of the viewer. -..ocv:function:: Affine3f getViewerPose() +..ocv:function:: Affine3d getViewerPose() viz::Viz3d::setViewerPose ------------------------- Sets pose of the viewer. -.. ocv:function:: void setViewerPose(const Affine3f &pose) +.. ocv:function:: void setViewerPose(const Affine3d &pose) :param pose: The new pose of the viewer. diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index a629b7bc9..c42079964 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -170,9 +170,9 @@ Base class of all 3D widgets. :: public: Widget3D() {} - void setPose(const Affine3f &pose); - void updatePose(const Affine3f &pose); - Affine3f getPose() const; + void setPose(const Affine3d &pose); + void updatePose(const Affine3d &pose); + Affine3d getPose() const; void setColor(const Color &color); private: @@ -183,7 +183,7 @@ viz::Widget3D::setPose ---------------------- Sets pose of the widget. -.. ocv:function:: void setPose(const Affine3f &pose) +.. ocv:function:: void setPose(const Affine3d &pose) :param pose: The new pose of the widget. @@ -191,7 +191,7 @@ viz::Widget3D::updateWidgetPose ------------------------------- Updates pose of the widget by pre-multiplying its current pose. -.. ocv:function:: void updateWidgetPose(const Affine3f &pose) +.. ocv:function:: void updateWidgetPose(const Affine3d &pose) :param pose: The pose that the current pose of the widget will be pre-multiplied by. @@ -199,7 +199,7 @@ viz::Widget3D::getPose ---------------------- Returns the current pose of the widget. -.. ocv:function:: Affine3f getWidgetPose() const +.. ocv:function:: Affine3d getWidgetPose() const viz::Widget3D::setColor ----------------------- @@ -732,14 +732,14 @@ This 3D Widget represents a trajectory. :: enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white(),; + WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white(),; }; viz::WTrajectory::WTrajectory ----------------------------- Constructs a WTrajectory. -.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()) +.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param display_mode: Display mode. This can be PATH, FRAMES, and BOTH. @@ -762,16 +762,16 @@ This 3D Widget represents a trajectory. :: { public: //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); }; viz::WTrajectoryFrustums::WTrajectoryFrustums ----------------------------- Constructs a WTrajectoryFrustums. -.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) +.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param K: Intrinsic matrix of the camera. @@ -780,7 +780,7 @@ Constructs a WTrajectoryFrustums. Displays frustums at each pose of the trajectory. -.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) +.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param fov: Field of view of the camera (horizontal, vertical). @@ -799,7 +799,7 @@ represent the direction from previous position to the current. :: class CV_EXPORTS WTrajectorySpheres : public Widget3D { public: - WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, + WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, sphere_radius = 0.007, Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; @@ -808,7 +808,7 @@ viz::WTrajectorySpheres::WTrajectorySpheres ------------------------------------------- Constructs a WTrajectorySpheres. -.. ocv:function:: WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, float sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) +.. ocv:function:: WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, float sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) :param path: List of poses on a trajectory. :param line_length: Length of the lines. @@ -867,9 +867,9 @@ This 3D Widget defines a collection of clouds. :: WCloudCollection(); //! Each point in cloud is mapped to a color in colors - void addCloud(InputArray cloud, InputArray colors, const Affine3f &pose = Affine3f::Identity()); + void addCloud(InputArray cloud, InputArray colors, const Affine3d &pose = Affine3d::Identity()); //! All points in cloud have the same color - void addCloud(InputArray cloud, const Color &color = Color::white(), Affine3f &pose = Affine3f::Identity()); + void addCloud(InputArray cloud, const Color &color = Color::white(), Affine3d &pose = Affine3d::Identity()); private: /* hidden */ @@ -885,7 +885,7 @@ viz::WCloudCollection::addCloud ------------------------------- Adds a cloud to the collection. -.. ocv:function:: void addCloud(InputArray cloud, InputArray colors, const Affine3f &pose = Affine3f::Identity()) +.. ocv:function:: void addCloud(InputArray cloud, InputArray colors, const Affine3d &pose = Affine3d::Identity()) :param cloud: Point set which can be of type: ``CV_32FC3``, ``CV_32FC4``, ``CV_64FC3``, ``CV_64FC4``. :param colors: Set of colors. It has to be of the same size with cloud. @@ -893,7 +893,7 @@ Adds a cloud to the collection. Points in the cloud belong to mask when they are set to (NaN, NaN, NaN). -.. ocv:function:: void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3f &pose = Affine3f::Identity()) +.. ocv:function:: void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3d &pose = Affine3d::Identity()) :param cloud: Point set which can be of type: ``CV_32FC3``, ``CV_32FC4``, ``CV_64FC3``, ``CV_64FC4``. :param colors: A single :ocv:class:`Color` for the whole cloud. diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index cb399a8eb..2724e921d 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -58,10 +58,10 @@ namespace cv namespace viz { //! takes coordiante frame data and builds transfrom to global coordinate frame - CV_EXPORTS Affine3f makeTransformToGlobal(const Vec3f& axis_x, const Vec3f& axis_y, const Vec3f& axis_z, const Vec3f& origin = Vec3f::all(0)); + CV_EXPORTS Affine3d makeTransformToGlobal(const Vec3d& axis_x, const Vec3d& axis_y, const Vec3d& axis_z, const Vec3d& origin = Vec3d::all(0)); //! constructs camera pose from position, focal_point and up_vector (see gluLookAt() for more infromation) - CV_EXPORTS Affine3f makeCameraPose(const Vec3f& position, const Vec3f& focal_point, const Vec3f& y_dir); + CV_EXPORTS Affine3d makeCameraPose(const Vec3d& position, const Vec3d& focal_point, const Vec3d& y_dir); //! retrieves a window by its name. If no window with such name, then it creates new. CV_EXPORTS Viz3d get(const String &window_name); @@ -101,10 +101,7 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories - CV_EXPORTS bool readPose(const String& file, Affine3f& pose, const String& tag = "pose"); CV_EXPORTS bool readPose(const String& file, Affine3d& pose, const String& tag = "pose"); - - CV_EXPORTS void writePose(const String& file, const Affine3f& pose, const String& tag = "pose"); CV_EXPORTS void writePose(const String& file, const Affine3d& pose, const String& tag = "pose"); CV_EXPORTS void writeTrajectory(const std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, const String& tag = "pose"); diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index 1b31b2447..7cd27eb61 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -70,19 +70,19 @@ namespace cv Viz3d& operator=(const Viz3d&); ~Viz3d(); - void showWidget(const String &id, const Widget &widget, const Affine3f &pose = Affine3f::Identity()); + void showWidget(const String &id, const Widget &widget, const Affine3d &pose = Affine3d::Identity()); void removeWidget(const String &id); Widget getWidget(const String &id) const; void removeAllWidgets(); - void setWidgetPose(const String &id, const Affine3f &pose); - void updateWidgetPose(const String &id, const Affine3f &pose); - Affine3f getWidgetPose(const String &id) const; + void setWidgetPose(const String &id, const Affine3d &pose); + void updateWidgetPose(const String &id, const Affine3d &pose); + Affine3d getWidgetPose(const String &id) const; void setCamera(const Camera &camera); Camera getCamera() const; - Affine3f getViewerPose(); - void setViewerPose(const Affine3f &pose); + Affine3d getViewerPose(); + void setViewerPose(const Affine3d &pose); void resetCameraViewpoint(const String &id); void resetCamera(); diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 5ca06800b..28a2acb0d 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -111,9 +111,9 @@ namespace cv public: Widget3D() {} - void setPose(const Affine3f &pose); - void updatePose(const Affine3f &pose); - Affine3f getPose() const; + void setPose(const Affine3d &pose); + void updatePose(const Affine3d &pose); + Affine3d getPose() const; void setColor(const Color &color); @@ -264,21 +264,22 @@ namespace cv //! Displays trajectory of the given path either by coordinate frames or polyline WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); + WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectoryFrustums : public Widget3D { public: //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectorySpheres: public Widget3D { public: - WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021f, + WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021f, float sphere_radius = 0.007f, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; @@ -300,9 +301,9 @@ namespace cv WCloudCollection(); //! Each point in cloud is mapped to a color in colors - void addCloud(InputArray cloud, InputArray colors, const Affine3f &pose = Affine3f::Identity()); + void addCloud(InputArray cloud, InputArray colors, const Affine3d &pose = Affine3d::Identity()); //! All points in cloud have the same color - void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3f &pose = Affine3f::Identity()); + void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3d &pose = Affine3d::Identity()); }; class CV_EXPORTS WCloudNormals : public Widget3D diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 4746bc2e5..16f274cf2 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -250,7 +250,7 @@ cv::viz::WCloudCollection::WCloudCollection() WidgetAccessor::setProp(*this, actor); } -void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, const Affine3f &pose) +void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, const Affine3d &pose) { Mat cloud = _cloud.getMat(); Mat colors = _colors.getMat(); @@ -292,7 +292,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); } -void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3f &pose) +void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3d &pose) { Mat cloud = _cloud.getMat(); CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index e9102b728..7da4063f7 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1182,7 +1182,7 @@ namespace cv { namespace viz { namespace { struct TrajectoryUtils { - static void applyPath(vtkSmartPointer poly_data, vtkSmartPointer append_filter, const std::vector &path) + static void applyPath(vtkSmartPointer poly_data, vtkSmartPointer append_filter, const std::vector &path) { vtkIdType nr_points = path.size(); @@ -1213,7 +1213,105 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, float scale, const Color &color) +cv::viz::WTrajectory::WTrajectory(const std::vector &_path, int display_mode, float scale, const Color &color) +{ + std::vector path(_path.begin(), _path.end()); + + vtkSmartPointer appendFilter = vtkSmartPointer::New(); + + // Bitwise and with 3 in order to limit the domain to 2 bits + if ((~display_mode & 3) ^ WTrajectory::PATH) + { + // Create a poly line along the path + vtkIdType nr_points = path.size(); + + vtkSmartPointer points = vtkSmartPointer::New(); + points->SetDataTypeToFloat(); + points->SetNumberOfPoints(nr_points); + + vtkSmartPointer polyData = vtkSmartPointer::New(); + vtkSmartPointer polyLine = vtkSmartPointer::New(); + polyLine->GetPointIds()->SetNumberOfIds(nr_points); + + Vec3f *data_beg = vtkpoints_data(points); + + for (vtkIdType i = 0; i < nr_points; ++i) + { + Vec3f cam_pose = path[i].translation(); + *data_beg++ = cam_pose; + polyLine->GetPointIds()->SetId(i,i); + } + + vtkSmartPointer cells = vtkSmartPointer::New(); + cells->InsertNextCell(polyLine); + + polyData->SetPoints(points); + polyData->SetLines(cells); + + // Set the color for polyData + vtkSmartPointer colors = vtkSmartPointer::New(); + colors->SetNumberOfComponents(3); + colors->SetNumberOfTuples(nr_points); + colors->FillComponent(0, color[2]); + colors->FillComponent(1, color[1]); + colors->FillComponent(2, color[0]); + + polyData->GetPointData()->SetScalars(colors); +#if VTK_MAJOR_VERSION <= 5 + appendFilter->AddInputConnection(polyData->GetProducerPort()); +#else + appendFilter->AddInputData(polyData); +#endif + } + + if ((~display_mode & 3) ^ WTrajectory::FRAMES) + { + // Create frames and transform along the path + vtkSmartPointer axes = vtkSmartPointer::New(); + axes->SetOrigin(0, 0, 0); + axes->SetScaleFactor(scale); + + vtkSmartPointer axes_colors = vtkSmartPointer::New(); + axes_colors->SetNumberOfComponents(3); + axes_colors->InsertNextTuple3(255,0,0); + axes_colors->InsertNextTuple3(255,0,0); + axes_colors->InsertNextTuple3(0,255,0); + axes_colors->InsertNextTuple3(0,255,0); + axes_colors->InsertNextTuple3(0,0,255); + axes_colors->InsertNextTuple3(0,0,255); + + vtkSmartPointer axes_data = axes->GetOutput(); +#if VTK_MAJOR_VERSION <= 5 + axes_data->Update(); +#else + axes->Update(); +#endif + axes_data->GetPointData()->SetScalars(axes_colors); + + vtkSmartPointer axes_tubes = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 + axes_tubes->SetInput(axes_data); +#else + axes_tubes->SetInputData(axes_data); +#endif + axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); + axes_tubes->SetNumberOfSides(6); + axes_tubes->Update(); + + TrajectoryUtils::applyPath(axes_tubes->GetOutput(), appendFilter, path); + } + + vtkSmartPointer mapper = vtkSmartPointer::New(); + mapper->SetScalarModeToUsePointData(); + mapper->SetInputConnection(appendFilter->GetOutputPort()); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->SetMapper(mapper); + + WidgetAccessor::setProp(*this, actor); +} + +cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, float scale, const Color &color) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); @@ -1318,7 +1416,7 @@ template<> cv::viz::WTrajectory cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// WTrajectoryFrustums widget implementation -cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); float f_x = K(0,0); @@ -1362,7 +1460,7 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &p setColor(color); } -cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); @@ -1411,7 +1509,7 @@ template<> cv::viz::WTrajectoryFrustums cv::viz::Widget::cast &path, float line_length, float init_sphere_radius, float sphere_radius, +cv::viz::WTrajectorySpheres::WTrajectorySpheres(const std::vector &path, float line_length, float init_sphere_radius, float sphere_radius, const Color &line_color, const Color &sphere_color) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); @@ -1469,8 +1567,8 @@ cv::viz::WTrajectorySpheres::WTrajectorySpheres(const std::vector &pat } - Affine3f relativeAffine = path[i].inv() * path[i-1]; - Vec3f v = path[i].rotation() * relativeAffine.translation(); + Affine3d relativeAffine = path[i].inv() * path[i-1]; + Vec3d v = path[i].rotation() * relativeAffine.translation(); v = normalize(v) * line_length; vtkSmartPointer line_source = vtkSmartPointer::New(); diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 0f21e08cc..33d851d64 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -108,18 +108,18 @@ void cv::viz::Viz3d::registerKeyboardCallback(KeyboardCallback callback, void* c void cv::viz::Viz3d::registerMouseCallback(MouseCallback callback, void* cookie) { impl_->registerMouseCallback(callback, cookie); } -void cv::viz::Viz3d::showWidget(const String &id, const Widget &widget, const Affine3f &pose) { impl_->showWidget(id, widget, pose); } +void cv::viz::Viz3d::showWidget(const String &id, const Widget &widget, const Affine3d &pose) { impl_->showWidget(id, widget, pose); } void cv::viz::Viz3d::removeWidget(const String &id) { impl_->removeWidget(id); } cv::viz::Widget cv::viz::Viz3d::getWidget(const String &id) const { return impl_->getWidget(id); } void cv::viz::Viz3d::removeAllWidgets() { impl_->removeAllWidgets(); } -void cv::viz::Viz3d::setWidgetPose(const String &id, const Affine3f &pose) { impl_->setWidgetPose(id, pose); } -void cv::viz::Viz3d::updateWidgetPose(const String &id, const Affine3f &pose) { impl_->updateWidgetPose(id, pose); } -cv::Affine3f cv::viz::Viz3d::getWidgetPose(const String &id) const { return impl_->getWidgetPose(id); } +void cv::viz::Viz3d::setWidgetPose(const String &id, const Affine3d &pose) { impl_->setWidgetPose(id, pose); } +void cv::viz::Viz3d::updateWidgetPose(const String &id, const Affine3d &pose) { impl_->updateWidgetPose(id, pose); } +cv::Affine3d cv::viz::Viz3d::getWidgetPose(const String &id) const { return impl_->getWidgetPose(id); } void cv::viz::Viz3d::setCamera(const Camera &camera) { impl_->setCamera(camera); } cv::viz::Camera cv::viz::Viz3d::getCamera() const { return impl_->getCamera(); } -void cv::viz::Viz3d::setViewerPose(const Affine3f &pose) { impl_->setViewerPose(pose); } -cv::Affine3f cv::viz::Viz3d::getViewerPose() { return impl_->getViewerPose(); } +void cv::viz::Viz3d::setViewerPose(const Affine3d &pose) { impl_->setViewerPose(pose); } +cv::Affine3d cv::viz::Viz3d::getViewerPose() { return impl_->getViewerPose(); } void cv::viz::Viz3d::resetCameraViewpoint(const String &id) { impl_->resetCameraViewpoint(id); } void cv::viz::Viz3d::resetCamera() { impl_->resetCamera(); } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index 5029756c2..c26b04301 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -45,21 +45,21 @@ #include "precomp.hpp" -cv::Affine3f cv::viz::makeTransformToGlobal(const Vec3f& axis_x, const Vec3f& axis_y, const Vec3f& axis_z, const Vec3f& origin) +cv::Affine3d cv::viz::makeTransformToGlobal(const Vec3d& axis_x, const Vec3d& axis_y, const Vec3d& axis_z, const Vec3d& origin) { - Affine3f::Mat3 R(axis_x[0], axis_y[0], axis_z[0], + Affine3d::Mat3 R(axis_x[0], axis_y[0], axis_z[0], axis_x[1], axis_y[1], axis_z[1], axis_x[2], axis_y[2], axis_z[2]); - return Affine3f(R, origin); + return Affine3d(R, origin); } -cv::Affine3f cv::viz::makeCameraPose(const Vec3f& position, const Vec3f& focal_point, const Vec3f& y_dir) +cv::Affine3d cv::viz::makeCameraPose(const Vec3d& position, const Vec3d& focal_point, const Vec3d& y_dir) { // Compute the transformation matrix for drawing the camera frame in a scene - Vec3f n = normalize(focal_point - position); - Vec3f u = normalize(y_dir.cross(n)); - Vec3f v = n.cross(u); + Vec3d n = normalize(focal_point - position); + Vec3d u = normalize(y_dir.cross(n)); + Vec3d v = n.cross(u); return makeTransformToGlobal(u, v, n, position); } @@ -240,27 +240,29 @@ cv::Mat cv::viz::readCloud(const String& file, OutputArray colors, OutputArray n /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories +bool cv::viz::readPose(const String& file, Affine3d& pose, const String& tag) +{ + FileStorage fs(file, FileStorage::READ); + if (!fs.isOpened()) + return false; + + Mat hdr(pose.matrix, false); + fs[tag] >> hdr; + if (hdr.empty() || hdr.cols != pose.matrix.cols || hdr.rows != pose.matrix.rows) + return false; + + hdr.convertTo(pose.matrix, CV_64F); + return true; +} + +void cv::viz::writePose(const String& file, const Affine3d& pose, const String& tag) +{ + FileStorage fs(file, FileStorage::WRITE); + fs << tag << Mat(pose.matrix, false); +} + namespace cv { namespace viz { namespace impl { - template - bool readPose(const String& file, Affine3<_Tp>& pose, const String& tag) - { - FileStorage fs(file, FileStorage::READ); - if (!fs.isOpened()) - return false; - - Mat hdr(pose.matrix, false); - fs[tag] >> hdr; - return !hdr.empty() && hdr.depth() == DataDepth<_Tp>::value; - } - - template - void writePose(const String& file, const Affine3<_Tp>& pose, const String& tag) - { - FileStorage fs(file, FileStorage::WRITE); - fs << tag << Mat(pose.matrix, false); - } - template void readTrajectory(std::vector >& traj, const String& files_format, int start, int end, const String& tag) { @@ -271,8 +273,8 @@ namespace cv { namespace viz { namespace impl for(int i = start; i < end; ++i) { - Affine3<_Tp> affine; - bool ok = readPose(cv::format(files_format.c_str(), i),affine, tag); + Affine3d affine; + bool ok = readPose(cv::format(files_format.c_str(), i), affine, tag); if (!ok) break; @@ -290,11 +292,7 @@ namespace cv { namespace viz { namespace impl }}} -bool cv::viz::readPose(const String& file, Affine3f& pose, const String& tag) { return impl::readPose(file, pose, tag); } -bool cv::viz::readPose(const String& file, Affine3d& pose, const String& tag) { return impl::readPose(file, pose, tag); } -void cv::viz::writePose(const String& file, const Affine3f& pose, const String& tag) { impl::writePose(file, pose, tag); } -void cv::viz::writePose(const String& file, const Affine3d& pose, const String& tag) { impl::writePose(file, pose, tag); } void cv::viz::readTrajectory(std::vector& traj, const String& files_format, int start, int end, const String& tag) { impl::readTrajectory(traj, files_format, start, end, tag); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index c727a99d2..cac58350b 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -120,7 +120,7 @@ cv::viz::Viz3d::VizImpl::~VizImpl() } ///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::showWidget(const String &id, const Widget &widget, const Affine3f &pose) +void cv::viz::Viz3d::VizImpl::showWidget(const String &id, const Widget &widget, const Affine3d &pose) { WidgetActorMap::iterator wam_itr = widget_actor_map_->find(id); bool exists = wam_itr != widget_actor_map_->end(); @@ -172,7 +172,7 @@ cv::viz::Widget cv::viz::Viz3d::VizImpl::getWidget(const String &id) const } ///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setWidgetPose(const String &id, const Affine3f &pose) +void cv::viz::Viz3d::VizImpl::setWidgetPose(const String &id, const Affine3d &pose) { WidgetActorMap::iterator wam_itr = widget_actor_map_->find(id); bool exists = wam_itr != widget_actor_map_->end(); @@ -187,7 +187,7 @@ void cv::viz::Viz3d::VizImpl::setWidgetPose(const String &id, const Affine3f &po } ///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::updateWidgetPose(const String &id, const Affine3f &pose) +void cv::viz::Viz3d::VizImpl::updateWidgetPose(const String &id, const Affine3d &pose) { WidgetActorMap::iterator wam_itr = widget_actor_map_->find(id); bool exists = wam_itr != widget_actor_map_->end(); @@ -202,8 +202,8 @@ void cv::viz::Viz3d::VizImpl::updateWidgetPose(const String &id, const Affine3f setWidgetPose(id, pose); return ; } - Matx44f matrix_cv = convertToMatx(matrix); - Affine3f updated_pose = pose * Affine3f(matrix_cv); + Matx44d matrix_cv = convertToMatx(matrix); + Affine3d updated_pose = pose * Affine3d(matrix_cv); matrix = convertToVtkMatrix(updated_pose.matrix); actor->SetUserMatrix(matrix); @@ -211,7 +211,7 @@ void cv::viz::Viz3d::VizImpl::updateWidgetPose(const String &id, const Affine3f } ///////////////////////////////////////////////////////////////////////////////////////////// -cv::Affine3f cv::viz::Viz3d::VizImpl::getWidgetPose(const String &id) const +cv::Affine3d cv::viz::Viz3d::VizImpl::getWidgetPose(const String &id) const { WidgetActorMap::const_iterator wam_itr = widget_actor_map_->find(id); bool exists = wam_itr != widget_actor_map_->end(); @@ -221,8 +221,8 @@ cv::Affine3f cv::viz::Viz3d::VizImpl::getWidgetPose(const String &id) const CV_Assert("Widget is not 3D." && actor); vtkSmartPointer matrix = actor->GetUserMatrix(); - Matx44f matrix_cv = convertToMatx(matrix); - return Affine3f(matrix_cv); + Matx44d matrix_cv = convertToMatx(matrix); + return Affine3d(matrix_cv); } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -350,32 +350,32 @@ cv::viz::Camera cv::viz::Viz3d::VizImpl::getCamera() const } ///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setViewerPose(const Affine3f &pose) +void cv::viz::Viz3d::VizImpl::setViewerPose(const Affine3d &pose) { vtkCamera& camera = *renderer_->GetActiveCamera(); // Position = extrinsic translation - cv::Vec3f pos_vec = pose.translation(); + cv::Vec3d pos_vec = pose.translation(); // Rotate the view vector - cv::Matx33f rotation = pose.rotation(); - cv::Vec3f y_axis(0.f, 1.f, 0.f); - cv::Vec3f up_vec(rotation * y_axis); + cv::Matx33d rotation = pose.rotation(); + cv::Vec3d y_axis(0.0, 1.0, 0.0); + cv::Vec3d up_vec(rotation * y_axis); // Compute the new focal point - cv::Vec3f z_axis(0.f, 0.f, 1.f); - cv::Vec3f focal_vec = pos_vec + rotation * z_axis; + cv::Vec3d z_axis(0.0, 0.0, 1.0); + cv::Vec3d focal_vec = pos_vec + rotation * z_axis; - camera.SetPosition(pos_vec[0], pos_vec[1], pos_vec[2]); - camera.SetFocalPoint(focal_vec[0], focal_vec[1], focal_vec[2]); - camera.SetViewUp(up_vec[0], up_vec[1], up_vec[2]); + camera.SetPosition(pos_vec.val); + camera.SetFocalPoint(focal_vec.val); + camera.SetViewUp(up_vec.val); renderer_->ResetCameraClippingRange(); renderer_->Render(); } ///////////////////////////////////////////////////////////////////////////////////////////// -cv::Affine3f cv::viz::Viz3d::VizImpl::getViewerPose() +cv::Affine3d cv::viz::Viz3d::VizImpl::getViewerPose() { vtkCamera& camera = *renderer_->GetActiveCamera(); @@ -400,7 +400,7 @@ cv::Affine3f cv::viz::Viz3d::VizImpl::getViewerPose() R(2, 1) = y_axis[2]; R(2, 2) = z_axis[2]; - return cv::Affine3f(R, pos); + return cv::Affine3d(R, pos); } ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index d958f4672..0cfb40309 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -57,14 +57,14 @@ public: VizImpl(const String &name); virtual ~VizImpl(); - void showWidget(const String &id, const Widget &widget, const Affine3f &pose = Affine3f::Identity()); + void showWidget(const String &id, const Widget &widget, const Affine3d &pose = Affine3d::Identity()); void removeWidget(const String &id); Widget getWidget(const String &id) const; void removeAllWidgets(); - void setWidgetPose(const String &id, const Affine3f &pose); - void updateWidgetPose(const String &id, const Affine3f &pose); - Affine3f getWidgetPose(const String &id) const; + void setWidgetPose(const String &id, const Affine3d &pose); + void updateWidgetPose(const String &id, const Affine3d &pose); + Affine3d getWidgetPose(const String &id) const; void setDesiredUpdateRate(double rate); double getDesiredUpdateRate(); @@ -95,8 +95,8 @@ public: void resetCameraViewpoint(const String& id); void resetCamera(); - void setViewerPose(const Affine3f &pose); - Affine3f getViewerPose(); + void setViewerPose(const Affine3d &pose); + Affine3d getViewerPose(); void convertToWindowCoordinates(const Point3d &pt, Point3d &window_coord); void converTo3DRay(const Point3d &window_coord, Point3d &origin, Vec3d &direction); @@ -280,31 +280,6 @@ namespace cv } }; - struct ApplyAffine - { - const Affine3f& affine_; - ApplyAffine(const Affine3f& affine) : affine_(affine) {} - - template Point3_<_Tp> operator()(const Point3_<_Tp>& p) const { return affine_ * p; } - - template Vec<_Tp, 3> operator()(const Vec<_Tp, 3>& v) const - { - const float* m = affine_.matrix.val; - - Vec<_Tp, 3> result; - result[0] = (_Tp)(m[0] * v[0] + m[1] * v[1] + m[ 2] * v[2] + m[ 3]); - result[1] = (_Tp)(m[4] * v[0] + m[5] * v[1] + m[ 6] * v[2] + m[ 7]); - result[2] = (_Tp)(m[8] * v[0] + m[9] * v[1] + m[10] * v[2] + m[11]); - return result; - } - - private: - ApplyAffine(const ApplyAffine&); - ApplyAffine& operator=(const ApplyAffine&); - }; - - - struct ConvertToVtkImage { struct Impl diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index a70fb925a..839ea2014 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -239,7 +239,7 @@ void cv::viz::WidgetAccessor::setProp(Widget& widget, vtkSmartPointer p /////////////////////////////////////////////////////////////////////////////////////////////// /// widget3D implementation -void cv::viz::Widget3D::setPose(const Affine3f &pose) +void cv::viz::Widget3D::setPose(const Affine3d &pose) { vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Widget is not 3D." && actor); @@ -249,7 +249,7 @@ void cv::viz::Widget3D::setPose(const Affine3f &pose) actor->Modified(); } -void cv::viz::Widget3D::updatePose(const Affine3f &pose) +void cv::viz::Widget3D::updatePose(const Affine3d &pose) { vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Widget is not 3D." && actor); @@ -261,18 +261,18 @@ void cv::viz::Widget3D::updatePose(const Affine3f &pose) return; } - Affine3f updated_pose = pose * Affine3f(convertToMatx(matrix)); + Affine3d updated_pose = pose * Affine3d(convertToMatx(matrix)); matrix = convertToVtkMatrix(updated_pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); } -cv::Affine3f cv::viz::Widget3D::getPose() const +cv::Affine3d cv::viz::Widget3D::getPose() const { vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Widget is not 3D." && actor); - return Affine3f(convertToMatx(actor->GetUserMatrix())); + return Affine3d(convertToMatx(actor->GetUserMatrix())); } void cv::viz::Widget3D::setColor(const Color &color) diff --git a/modules/viz/test/test_tutorial2.cpp b/modules/viz/test/test_tutorial2.cpp index cba24638b..a901adc2c 100644 --- a/modules/viz/test/test_tutorial2.cpp +++ b/modules/viz/test/test_tutorial2.cpp @@ -12,34 +12,34 @@ void tutorial2() myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem()); /// Add line to represent (1,1,1) axis - viz::WLine axis(Point3f(-1.0f,-1.0f,-1.0f), Point3f(1.0f,1.0f,1.0f)); + viz::WLine axis(Point3f(-1.0, -1.0, -1.0), Point3d(1.0, 1.0, 1.0)); axis.setRenderingProperty(viz::LINE_WIDTH, 4.0); myWindow.showWidget("Line Widget", axis); /// Construct a cube widget - viz::WCube cube_widget(Point3f(0.5,0.5,0.0), Point3f(0.0,0.0,-0.5), true, viz::Color::blue()); + viz::WCube cube_widget(Point3d(0.5, 0.5, 0.0), Point3d(0.0, 0.0, -0.5), true, viz::Color::blue()); cube_widget.setRenderingProperty(viz::LINE_WIDTH, 4.0); /// Display widget (update if already displayed) myWindow.showWidget("Cube Widget", cube_widget); /// Rodrigues vector - Mat rot_vec = Mat::zeros(1,3,CV_32F); - float translation_phase = 0.0, translation = 0.0; + Vec3d rot_vec = Vec3d::all(0); + double translation_phase = 0.0, translation = 0.0; while(!myWindow.wasStopped()) { /* Rotation using rodrigues */ /// Rotate around (1,1,1) - rot_vec.at(0,0) += CV_PI * 0.01f; - rot_vec.at(0,1) += CV_PI * 0.01f; - rot_vec.at(0,2) += CV_PI * 0.01f; + rot_vec[0] += CV_PI * 0.01; + rot_vec[1] += CV_PI * 0.01; + rot_vec[2] += CV_PI * 0.01; /// Shift on (1,1,1) - translation_phase += CV_PI * 0.01f; + translation_phase += CV_PI * 0.01; translation = sin(translation_phase); /// Construct pose - Affine3f pose(rot_vec, Vec3f(translation, translation, translation)); + Affine3d pose(rot_vec, Vec3d(translation, translation, translation)); myWindow.setWidgetPose("Cube Widget", pose); diff --git a/modules/viz/test/test_tutorial3.cpp b/modules/viz/test/test_tutorial3.cpp index 8b4321548..590e29ebf 100644 --- a/modules/viz/test/test_tutorial3.cpp +++ b/modules/viz/test/test_tutorial3.cpp @@ -15,23 +15,23 @@ void tutorial3(bool camera_pov) myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem()); /// Let's assume camera has the following properties - Point3f cam_pos(3.f, 3.f, 3.f), cam_focal_point(3.f, 3.f, 2.f), cam_y_dir(-1.f, 0.f, 0.f); + Point3d cam_pos(3.0, 3.0, 3.0), cam_focal_point(3.0, 3.0, 2.0), cam_y_dir(-1.0, 0.0, 0.0); /// We can get the pose of the cam using makeCameraPose - Affine3f cam_pose = viz::makeCameraPose(cam_pos, cam_focal_point, cam_y_dir); + Affine3d cam_pose = viz::makeCameraPose(cam_pos, cam_focal_point, cam_y_dir); /// We can get the transformation matrix from camera coordinate system to global using /// - makeTransformToGlobal. We need the axes of the camera - Affine3f transform = viz::makeTransformToGlobal(Vec3f(0.f, -1.f, 0.f), Vec3f(-1.f, 0.f, 0.f), Vec3f(0.f, 0.f, -1.f), cam_pos); + Affine3d transform = viz::makeTransformToGlobal(Vec3d(0.0, -1.0, 0.0), Vec3d(-1.0, 0.0, 0.0), Vec3d(0.0, 0.0, -1.0), cam_pos); /// Create a cloud widget. Mat dragon_cloud = viz::readCloud(get_dragon_ply_file_path()); viz::WCloud cloud_widget(dragon_cloud, viz::Color::green()); /// Pose of the widget in camera frame - Affine3f cloud_pose = Affine3f().translate(Vec3f(0.f, 0.f, 3.f)); + Affine3d cloud_pose = Affine3d().translate(Vec3d(0.0, 0.0, 3.0)); /// Pose of the widget in global frame - Affine3f cloud_pose_global = transform * cloud_pose; + Affine3d cloud_pose_global = transform * cloud_pose; /// Visualize camera frame if (!camera_pov) diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index df66727d8..ce0344f1e 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -67,7 +67,7 @@ TEST(Viz_viz3d, develop) //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); - std::vector gt, es; + std::vector gt, es; cv::viz::readTrajectory(gt, "d:/Datasets/trajs/gt%05d.xml"); cv::viz::readTrajectory(es, "d:/Datasets/trajs/es%05d.xml"); From cb5806164946379b77f328cbb7bf00959b194f6f Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 20:13:39 +0400 Subject: [PATCH 131/295] getViewerPose implementation simplified (and error seems to be fixed) --- modules/viz/src/vizimpl.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index cac58350b..34f78c64c 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -387,20 +387,7 @@ cv::Affine3d cv::viz::Viz3d::VizImpl::getViewerPose() Vec3d z_axis = normalized(focal - pos); Vec3d x_axis = normalized(y_axis.cross(z_axis)); - cv::Matx33d R; - R(0, 0) = x_axis[0]; - R(0, 1) = y_axis[0]; - R(0, 2) = z_axis[0]; - - R(1, 0) = x_axis[1]; - R(1, 1) = y_axis[1]; - R(1, 2) = z_axis[1]; - - R(2, 0) = x_axis[2]; - R(2, 1) = y_axis[2]; - R(2, 2) = z_axis[2]; - - return cv::Affine3d(R, pos); + return makeTransformToGlobal(x_axis, y_axis, z_axis, pos); } ///////////////////////////////////////////////////////////////////////////////////////////// From 70a81db5672b17f14ffdd461cf9f5f75cb55f751 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 20:51:04 +0400 Subject: [PATCH 132/295] fixed bugs in cloud collection and added test --- modules/viz/doc/viz3d.rst | 8 +- modules/viz/include/opencv2/viz/types.hpp | 2 +- modules/viz/src/clouds.cpp | 250 +++++----------------- modules/viz/src/types.cpp | 2 +- modules/viz/test/tests_simple.cpp | 15 ++ 5 files changed, 69 insertions(+), 208 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index ad1356e58..b57e04118 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -482,19 +482,19 @@ This class wraps mesh attributes, and it can load a mesh from a ``ply`` file. :: Mat polygons; //! Loads mesh from a given ply file - static Mesh3d loadMesh(const String& file); + static Mesh3d load(const String& file); private: /* hidden */ }; -viz::Mesh3d::loadMesh +viz::Mesh3d::load --------------------- Loads a mesh from a ``ply`` file. -.. ocv:function:: static Mesh3d loadMesh(const String& file) +.. ocv:function:: static Mesh3d load(const String& file) - :param file: File name. + :param file: File name (for no only PLY is supported) viz::KeyboardEvent diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index ff6bd5a68..0a1fc1469 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -112,7 +112,7 @@ namespace cv Mat polygons; //! Loads mesh from a given ply file - static Mesh3d loadMesh(const String& file); + static Mesh3d load(const String& file); }; class CV_EXPORTS Camera diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 16f274cf2..014f79921 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -106,143 +106,6 @@ template<> cv::viz::WCloud cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// Cloud Collection Widget implementation -namespace cv { namespace viz { namespace -{ - struct CloudCollectionUtils - { - static inline vtkSmartPointer create(const Mat &cloud, vtkIdType &nr_points) - { - vtkSmartPointer polydata = vtkSmartPointer::New(); - vtkSmartPointer vertices = vtkSmartPointer::New(); - - polydata->SetVerts(vertices); - - vtkSmartPointer points = polydata->GetPoints(); - vtkSmartPointer initcells; - nr_points = cloud.total(); - - if (!points) - { - points = vtkSmartPointer::New(); - if (cloud.depth() == CV_32F) - points->SetDataTypeToFloat(); - else if (cloud.depth() == CV_64F) - points->SetDataTypeToDouble(); - polydata->SetPoints(points); - } - points->SetNumberOfPoints(nr_points); - - if (cloud.depth() == CV_32F) - { - // Get a pointer to the beginning of the data array - Vec3f *data_beg = vtkpoints_data(points); - Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - else if (cloud.depth() == CV_64F) - { - // Get a pointer to the beginning of the data array - Vec3d *data_beg = vtkpoints_data(points); - Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); - nr_points = data_end - data_beg; - } - points->SetNumberOfPoints(nr_points); - - // Update cells - vtkSmartPointer cells = vertices->GetData(); - // If no init cells and cells has not been initialized... - if (!cells) - cells = vtkSmartPointer::New(); - - // If we have less values then we need to recreate the array - if (cells->GetNumberOfTuples() < nr_points) - { - cells = vtkSmartPointer::New(); - - // If init cells is given, and there's enough data in it, use it - if (initcells && initcells->GetNumberOfTuples() >= nr_points) - { - cells->DeepCopy(initcells); - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - } - else - { - // If the number of tuples is still too small, we need to recreate the array - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - vtkIdType *cell = cells->GetPointer(0); - // Fill it with 1s - std::fill(cell, cell + nr_points * 2, 1); - cell++; - for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) - *cell = i; - // Save the results in initcells - initcells = vtkSmartPointer::New(); - initcells->DeepCopy(cells); - } - } - else - { - // The assumption here is that the current set of cells has more data than needed - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - } - - // Set the cells and the vertices - vertices->SetCells(nr_points, cells); - return polydata; - } - - static void createMapper(vtkSmartPointer actor, vtkSmartPointer poly_data) - { - vtkDataSetMapper *mapper = vtkDataSetMapper::SafeDownCast(actor->GetMapper()); - if (!mapper) - { - // This is the first cloud - vtkSmartPointer mapper_new = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper_new->SetInputConnection(poly_data->GetProducerPort()); -#else - mapper_new->SetInputData(poly_data); -#endif - - mapper_new->SetScalarRange(0, 255); - mapper_new->SetScalarModeToUsePointData(); - - bool interpolation = (poly_data && poly_data->GetNumberOfCells() != poly_data->GetNumberOfVerts()); - - mapper_new->SetInterpolateScalarsBeforeMapping(interpolation); - mapper_new->ScalarVisibilityOn(); - mapper_new->ImmediateModeRenderingOff(); - - actor->SetNumberOfCloudPoints(int(std::max(1, poly_data->GetNumberOfPoints() / 10))); - actor->GetProperty()->SetInterpolationToFlat(); - actor->GetProperty()->BackfaceCullingOn(); - actor->SetMapper(mapper_new); - return ; - } - - vtkPolyData *data = vtkPolyData::SafeDownCast(mapper->GetInput()); - CV_Assert("Cloud Widget without data" && data); - - vtkSmartPointer appendFilter = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - appendFilter->AddInputConnection(mapper->GetInput()->GetProducerPort()); - appendFilter->AddInputConnection(poly_data->GetProducerPort()); -#else - appendFilter->AddInputData(data); - appendFilter->AddInputData(poly_data); -#endif - mapper->SetInputConnection(appendFilter->GetOutputPort()); - - // Update the number of cloud points - vtkIdType old_cloud_points = actor->GetNumberOfCloudPoints(); - actor->SetNumberOfCloudPoints(int(std::max(1, old_cloud_points+poly_data->GetNumberOfPoints() / 10))); - } - }; -}}} - cv::viz::WCloudCollection::WCloudCollection() { // Just create the actor @@ -250,84 +113,67 @@ cv::viz::WCloudCollection::WCloudCollection() WidgetAccessor::setProp(*this, actor); } -void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, const Affine3d &pose) +void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, const Affine3d &pose) { - Mat cloud = _cloud.getMat(); - Mat colors = _colors.getMat(); - CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); - CV_Assert(colors.depth() == CV_8U && cloud.size() == colors.size()); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetColorCloud(cloud, colors); - vtkIdType nr_points; - vtkSmartPointer polydata = CloudCollectionUtils::create(cloud, nr_points); - - // Filter colors - Vec3b* colors_data = new Vec3b[nr_points]; - NanFilter::copyColor(colors, colors_data, cloud); - - vtkSmartPointer scalars = vtkSmartPointer::New(); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(nr_points); - scalars->SetArray(colors_data->val, 3 * nr_points, 0); - - // Assign the colors - polydata->GetPointData()->SetScalars(scalars); - - // Transform the poly data based on the pose vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->SetMatrix(convertToVtkMatrix(pose.matrix)); + transform->SetMatrix(pose.matrix.val); vtkSmartPointer transform_filter = vtkSmartPointer::New(); + transform_filter->SetInputConnection(source->GetOutputPort()); transform_filter->SetTransform(transform); -#if VTK_MAJOR_VERSION <= 5 - transform_filter->SetInputConnection(polydata->GetProducerPort()); -#else - transform_filter->SetInputData(polydata); -#endif transform_filter->Update(); - vtkLODActor *actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); + vtkSmartPointer actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Incompatible widget type." && actor); - CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); + vtkSmartPointer poly_data = transform_filter->GetOutput(); + + vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); + + if (!mapper) + { + // This is the first cloud + mapper = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 + mapper->SetInput(poly_data); +#else + mapper->SetInputData(poly_data); +#endif + mapper->SetScalarRange(0, 255); + mapper->SetScalarModeToUsePointData(); + mapper->ScalarVisibilityOn(); + mapper->ImmediateModeRenderingOff(); + + actor->SetNumberOfCloudPoints(std::max(1, poly_data->GetNumberOfPoints()/10)); + actor->GetProperty()->SetInterpolationToFlat(); + actor->GetProperty()->BackfaceCullingOn(); + actor->SetMapper(mapper); + return; + } + + vtkPolyData *data = vtkPolyData::SafeDownCast(mapper->GetInput()); + CV_Assert("Cloud Widget without data" && data); + + vtkSmartPointer appendFilter = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 + appendFilter->AddInput(data); + appendFilter->AddInput(poly_data); + mapper->SetInput(appendFilter->GetOutput()); +#else + appendFilter->AddInputData(data); + appendFilter->AddInputData(poly_data); + mapper->SetInputData(appendFilter->GetOutput()); +#endif + + actor->SetNumberOfCloudPoints(std::max(1, actor->GetNumberOfCloudPoints() + poly_data->GetNumberOfPoints()/10)); } -void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3d &pose) +void cv::viz::WCloudCollection::addCloud(InputArray cloud, const Color &color, const Affine3d &pose) { - Mat cloud = _cloud.getMat(); - CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); - - vtkIdType nr_points; - vtkSmartPointer polydata = CloudCollectionUtils::create(cloud, nr_points); - - vtkSmartPointer scalars = vtkSmartPointer::New(); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(nr_points); - scalars->FillComponent(0, color[2]); - scalars->FillComponent(1, color[1]); - scalars->FillComponent(2, color[0]); - - // Assign the colors - polydata->GetPointData()->SetScalars(scalars); - - // Transform the poly data based on the pose - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->SetMatrix(convertToVtkMatrix(pose.matrix)); - - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetTransform(transform); -#if VTK_MAJOR_VERSION <= 5 - transform_filter->SetInputConnection(polydata->GetProducerPort()); -#else - transform_filter->SetInputData(polydata); -#endif - transform_filter->Update(); - - vtkLODActor *actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); - CV_Assert("Incompatible widget type." && actor); - - CloudCollectionUtils::createMapper(actor, transform_filter->GetOutput()); + addCloud(cloud, Mat(cloud.size(), CV_8UC3, color), pose); } template<> cv::viz::WCloudCollection cv::viz::Widget::cast() diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index 2c7f8e74b..63b9a0214 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -128,7 +128,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::Mesh3d cv::viz::Mesh3d::loadMesh(const String& file) +cv::viz::Mesh3d cv::viz::Mesh3d::load(const String& file) { return MeshUtils::loadMesh(file); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 1a2e9fc94..76e448da6 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -85,3 +85,18 @@ TEST(Viz, DISABLED_show_cloud_masked) viz.showWidget("dragon", WCloud(dragon_cloud)); viz.spin(); } + +TEST(Viz, DISABLED_show_cloud_collection) +{ + Mat cloud = readCloud(get_dragon_ply_file_path()); + + WCloudCollection ccol; + ccol.addCloud(cloud, Color::white(), Affine3d().translate(Vec3d(0, 0, 0)).rotate(Vec3d(1.57, 0, 0))); + ccol.addCloud(cloud, Color::blue(), Affine3d().translate(Vec3d(1, 0, 0))); + ccol.addCloud(cloud, Color::red(), Affine3d().translate(Vec3d(2, 0, 0))); + + Viz3d viz("show_cloud_collection"); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("ccol", ccol); + viz.spin(); +} From baee8c3aa58fb88ec25b231ac41c65df122531f1 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 1 Jan 2014 22:36:08 +0400 Subject: [PATCH 133/295] refactored Mesh, added tests, added failing "twice spin()" test --- modules/viz/include/opencv2/viz/widgets.hpp | 4 +- modules/viz/src/clouds.cpp | 196 ++++++-------------- modules/viz/src/vtk/vtkCloudMatSource.cpp | 6 +- modules/viz/test/tests_simple.cpp | 34 ++++ 4 files changed, 100 insertions(+), 140 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 28a2acb0d..27f211cd6 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -65,14 +65,14 @@ namespace cv SHADING }; - enum RenderingRepresentationProperties + enum RepresentationValues { REPRESENTATION_POINTS, REPRESENTATION_WIREFRAME, REPRESENTATION_SURFACE }; - enum ShadingRepresentationProperties + enum ShadingValues { SHADING_FLAT, SHADING_GOURAUD, diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 014f79921..2247dffe9 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -126,49 +126,47 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co transform_filter->SetTransform(transform); transform_filter->Update(); + vtkSmartPointer polydata = transform_filter->GetOutput(); vtkSmartPointer actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Incompatible widget type." && actor); - vtkSmartPointer poly_data = transform_filter->GetOutput(); - vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); - if (!mapper) { // This is the first cloud mapper = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(poly_data); + mapper->SetInput(polydata); #else - mapper->SetInputData(poly_data); + mapper->SetInputData(polydata); #endif mapper->SetScalarRange(0, 255); mapper->SetScalarModeToUsePointData(); mapper->ScalarVisibilityOn(); mapper->ImmediateModeRenderingOff(); - actor->SetNumberOfCloudPoints(std::max(1, poly_data->GetNumberOfPoints()/10)); + actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints()/10)); actor->GetProperty()->SetInterpolationToFlat(); actor->GetProperty()->BackfaceCullingOn(); actor->SetMapper(mapper); return; } - vtkPolyData *data = vtkPolyData::SafeDownCast(mapper->GetInput()); - CV_Assert("Cloud Widget without data" && data); + vtkPolyData *currdata = vtkPolyData::SafeDownCast(mapper->GetInput()); + CV_Assert("Cloud Widget without data" && currdata); vtkSmartPointer appendFilter = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 - appendFilter->AddInput(data); - appendFilter->AddInput(poly_data); + appendFilter->AddInput(currdata); + appendFilter->AddInput(polydata); mapper->SetInput(appendFilter->GetOutput()); #else - appendFilter->AddInputData(data); - appendFilter->AddInputData(poly_data); + appendFilter->AddInputData(currdata); + appendFilter->AddInputData(polydata); mapper->SetInputData(appendFilter->GetOutput()); #endif - actor->SetNumberOfCloudPoints(std::max(1, actor->GetNumberOfCloudPoints() + poly_data->GetNumberOfPoints()/10)); + actor->SetNumberOfCloudPoints(std::max(1, actor->GetNumberOfCloudPoints() + polydata->GetNumberOfPoints()/10)); } void cv::viz::WCloudCollection::addCloud(InputArray cloud, const Color &color, const Affine3d &pose) @@ -328,150 +326,78 @@ template<> cv::viz::WCloudNormals cv::viz::Widget::cast( /////////////////////////////////////////////////////////////////////////////////////////////// /// Mesh Widget implementation -namespace cv { namespace viz { namespace -{ - struct MeshUtils - { - template - static Vec<_Tp, 3> * copy(const Mat &source, Vec<_Tp, 3> *output, int *look_up, const Mat &nan_mask) - { - CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); - CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); - CV_DbgAssert(DataDepth<_Tp>::value == nan_mask.depth()); - - int s_chs = source.channels(); - int m_chs = nan_mask.channels(); - - int index = 0; - const _Tp* srow = source.ptr<_Tp>(0); - const _Tp* mrow = nan_mask.ptr<_Tp>(0); - - for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) - { - if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) - { - look_up[x] = index; - *output++ = Vec<_Tp, 3>(srow); - ++index; - } - } - return output; - } - }; -}}} - cv::viz::WMesh::WMesh(const Mesh3d &mesh) { - CV_Assert(mesh.cloud.rows == 1 && (mesh.cloud.type() == CV_32FC3 || mesh.cloud.type() == CV_64FC3 || mesh.cloud.type() == CV_32FC4 || mesh.cloud.type() == CV_64FC4)); - CV_Assert(mesh.colors.empty() || (mesh.colors.depth() == CV_8U && mesh.cloud.size() == mesh.colors.size())); - CV_Assert(!mesh.polygons.empty() && mesh.polygons.type() == CV_32SC1); + CV_Assert(mesh.cloud.rows == 1 && mesh.polygons.type() == CV_32SC1); - vtkSmartPointer points = vtkSmartPointer::New(); - vtkIdType nr_points = mesh.cloud.total(); - Mat look_up_mat(1, nr_points, CV_32SC1); - int * look_up = look_up_mat.ptr(); - points->SetNumberOfPoints(nr_points); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetColorCloud(mesh.cloud, mesh.colors); + source->Update(); - // Copy data from cloud to vtkPoints - if (mesh.cloud.depth() == CV_32F) + Mat lookup_buffer(1, mesh.cloud.total(), CV_32SC1); + int *lookup = lookup_buffer.ptr(); + for(int y = 0, index = 0; y < mesh.cloud.rows; ++y) { - points->SetDataTypeToFloat(); - Vec3f *data_beg = vtkpoints_data(points); - Vec3f *data_end = MeshUtils::copy(mesh.cloud, data_beg, look_up, mesh.cloud); - nr_points = data_end - data_beg; - } - else - { - points->SetDataTypeToDouble(); - Vec3d *data_beg = vtkpoints_data(points); - Vec3d *data_end = MeshUtils::copy(mesh.cloud, data_beg, look_up, mesh.cloud); - nr_points = data_end - data_beg; - } + int s_chs = mesh.cloud.channels(); - vtkSmartPointer scalars; - - if (!mesh.colors.empty()) - { - Vec3b *colors_data = new Vec3b[nr_points]; - NanFilter::copyColor(mesh.colors, colors_data, mesh.cloud); - - scalars = vtkSmartPointer::New(); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(nr_points); - scalars->SetArray(colors_data->val, 3 * nr_points, 0); - } - - points->SetNumberOfPoints(nr_points); - - vtkSmartPointer data; - - if (mesh.polygons.size().area() > 1) - { - vtkSmartPointer cell_array = vtkSmartPointer::New(); - const int * polygons = mesh.polygons.ptr(); - - int idx = 0; - int poly_size = mesh.polygons.total(); - for (int i = 0; i < poly_size; ++idx) + if (mesh.cloud.depth() == CV_32F) { - int n_points = polygons[i++]; + const float* srow = mesh.cloud.ptr(y); + const float* send = srow + mesh.cloud.cols * s_chs; - cell_array->InsertNextCell(n_points); - for (int j = 0; j < n_points; ++j, ++idx) - cell_array->InsertCellPoint(look_up[polygons[i++]]); + for (; srow != send; srow += s_chs, ++lookup) + if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) + *lookup = index++; } - vtkSmartPointer polydata = vtkSmartPointer::New(); - cell_array->GetData()->SetNumberOfValues(idx); - cell_array->Squeeze(); - polydata->SetStrips(cell_array); - polydata->SetPoints(points); - if (scalars) - polydata->GetPointData()->SetScalars(scalars); + if (mesh.cloud.depth() == CV_64F) + { + const double* srow = mesh.cloud.ptr(y); + const double* send = srow + mesh.cloud.cols * s_chs; - data = polydata; + for (; srow != send; srow += s_chs, ++lookup) + if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) + *lookup = index++; + } } - else + lookup = lookup_buffer.ptr(); + + vtkSmartPointer polydata = source->GetOutput(); + polydata->SetVerts(0); + + const int * polygons = mesh.polygons.ptr(); + vtkSmartPointer cell_array = vtkSmartPointer::New(); + + int idx = 0; + int poly_size = mesh.polygons.total(); + for (int i = 0; i < poly_size; ++idx) { - // Only one polygon - vtkSmartPointer polygon = vtkSmartPointer::New(); - const int * polygons = mesh.polygons.ptr(); - int n_points = polygons[0]; + int n_points = polygons[i++]; - polygon->GetPointIds()->SetNumberOfIds(n_points); - - for (int j = 1; j < n_points+1; ++j) - polygon->GetPointIds()->SetId(j, look_up[polygons[j]]); - - vtkSmartPointer poly_grid = vtkSmartPointer::New(); - poly_grid->Allocate(1, 1); - poly_grid->InsertNextCell(polygon->GetCellType(), polygon->GetPointIds()); - poly_grid->SetPoints(points); - - if (scalars) - poly_grid->GetPointData()->SetScalars(scalars); - - data = poly_grid; + cell_array->InsertNextCell(n_points); + for (int j = 0; j < n_points; ++j, ++idx) + cell_array->InsertCellPoint(lookup[polygons[i++]]); } + cell_array->GetData()->SetNumberOfValues(idx); + cell_array->Squeeze(); + polydata->SetStrips(cell_array); - vtkSmartPointer actor = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); + mapper->SetScalarModeToUsePointData(); + mapper->ImmediateModeRenderingOff(); +#if VTK_MAJOR_VERSION <= 5 + mapper->SetInput(polydata); +#else + mapper->SetInputData(polydata); +#endif + vtkSmartPointer actor = vtkSmartPointer::New(); + //actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints() / 10)); actor->GetProperty()->SetRepresentationToSurface(); actor->GetProperty()->BackfaceCullingOff(); // Backface culling is off for higher efficiency actor->GetProperty()->SetInterpolationToFlat(); actor->GetProperty()->EdgeVisibilityOff(); actor->GetProperty()->ShadingOff(); - - vtkSmartPointer mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(data); -#else - mapper->SetInputData(data); -#endif - mapper->ImmediateModeRenderingOff(); - - vtkIdType numberOfCloudPoints = nr_points * 0.1; - actor->SetNumberOfCloudPoints(int(numberOfCloudPoints > 1 ? numberOfCloudPoints : 1)); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index 46603a7b9..cf3d21e6d 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -163,14 +163,14 @@ int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& cloud) points->Allocate(cloud.total()); points->SetNumberOfPoints(cloud.total()); - int cn = cloud.channels(); + int s_chs = cloud.channels(); int total = 0; for (int y = 0; y < cloud.rows; ++y) { const _Tp* srow = cloud.ptr<_Tp>(y); - const _Tp* send = srow + cloud.cols * cn; + const _Tp* send = srow + cloud.cols * s_chs; - for (; srow != send; srow += cn) + for (; srow != send; srow += s_chs) if (!isNan(srow)) points->SetPoint(total++, srow); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 76e448da6..ece1370d5 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -100,3 +100,37 @@ TEST(Viz, DISABLED_show_cloud_collection) viz.showWidget("ccol", ccol); viz.spin(); } + +TEST(Viz, DISABLED_show_mesh) +{ + Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + + Viz3d viz("show_mesh"); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("mesh", WMesh(mesh)); + viz.spin(); +} + +TEST(Viz, DISABLED_show_mesh_random_colors) +{ + Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); + + Viz3d viz("show_mesh_random_color"); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("mesh", WMesh(mesh)); + viz.setRenderingProperty("mesh", SHADING, SHADING_PHONG); + viz.spin(); +} + +TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) +{ + Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + + Viz3d viz("spin_twice"); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("mesh", WMesh(mesh)); + viz.spin(); + viz.spin(); +} + From 3e071491c93e22c7bd5bead117fae196738ba759 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 2 Jan 2014 16:10:08 +0400 Subject: [PATCH 134/295] added Affine3 ctor from array --- modules/core/include/opencv2/core/affine.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index b4e7472a9..55b3f8fb0 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -73,6 +73,9 @@ namespace cv //Combines all contructors above. Supports 4x4, 3x3, 1x3, 3x1 sizes of data matrix explicit Affine3(const cv::Mat& data, const Vec3& t = Vec3::all(0)); + //From 16th element array + Affine3(const float_type* vals); + static Affine3 Identity(); //Rotation matrix @@ -183,6 +186,10 @@ cv::Affine3::Affine3(const cv::Mat& data, const Vec3& t) matrix.val[15] = 1; } +template inline +cv::Affine3::Affine3(const float_type* vals) : matrix(vals) +{} + template inline cv::Affine3 cv::Affine3::Identity() { From a76a34d28e9e0cb6b15c419181dccee77078d6fb Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 2 Jan 2014 16:16:29 +0400 Subject: [PATCH 135/295] added Affine3: 3x4 input Mat support --- modules/core/include/opencv2/core/affine.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index 55b3f8fb0..3f072e78f 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -179,6 +179,12 @@ cv::Affine3::Affine3(const cv::Mat& data, const Vec3& t) data.copyTo(matrix); return; } + else if (data.cols == 4 && data.rows == 3) + { + rotation(data(Rect(0, 0, 3, 3))); + translation(data(Rect(3, 0, 1, 3))); + return; + } rotation(data); translation(t); From b7cb3fe8e0a3cd210ed47b9d09ab53fed0c5cb8c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 2 Jan 2014 16:33:47 +0400 Subject: [PATCH 136/295] switched more to doubles --- modules/viz/doc/viz3d.rst | 34 ++++----- modules/viz/include/opencv2/viz/types.hpp | 26 +++---- modules/viz/src/interactor_style.cpp | 2 +- modules/viz/src/shapes.cpp | 2 +- modules/viz/src/types.cpp | 40 +++++----- modules/viz/src/vizcore.cpp | 18 ----- modules/viz/src/vizimpl.cpp | 36 +++++---- modules/viz/src/vizimpl.hpp | 89 ++--------------------- modules/viz/src/widget.cpp | 8 +- modules/viz/test/tests_simple.cpp | 3 - 10 files changed, 80 insertions(+), 178 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index b57e04118..1cb9b5dc3 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -571,24 +571,24 @@ that can extract the intrinsic parameters from ``field of view``, ``intrinsic ma class CV_EXPORTS Camera { public: - Camera(float f_x, float f_y, float c_x, float c_y, const Size &window_size); - Camera(const Vec2f &fov, const Size &window_size); - Camera(const cv::Matx33f &K, const Size &window_size); - Camera(const cv::Matx44f &proj, const Size &window_size); + Camera(double f_x, double f_y, double c_x, double c_y, const Size &window_size); + Camera(const Vec2d &fov, const Size &window_size); + Camera(const Matx33d &K, const Size &window_size); + Camera(const Matx44d &proj, const Size &window_size); - inline const Vec2d & getClip() const { return clip_; } - inline void setClip(const Vec2d &clip) { clip_ = clip; } + inline const Vec2d & getClip() const; + inline void setClip(const Vec2d &clip); - inline const Size & getWindowSize() const { return window_size_; } + inline const Size & getWindowSize() const; void setWindowSize(const Size &window_size); - inline const Vec2f & getFov() const { return fov_; } - inline void setFov(const Vec2f & fov) { fov_ = fov; } + inline const Vec2d & getFov() const; + inline void setFov(const Vec2d & fov); - inline const Vec2f & getPrincipalPoint() const { return principal_point_; } - inline const Vec2f & getFocalLength() const { return focal_; } + inline const Vec2d & getPrincipalPoint() const; + inline const Vec2d & getFocalLength() const; - void computeProjectionMatrix(Matx44f &proj) const; + void computeProjectionMatrix(Matx44d &proj) const; static Camera KinectCamera(const Size &window_size); @@ -600,7 +600,7 @@ viz::Camera::Camera ------------------- Constructs a Camera. -.. ocv:function:: Camera(float f_x, float f_y, float c_x, float c_y, const Size &window_size) +.. ocv:function:: Camera(double f_x, double f_y, double c_x, double c_y, const Size &window_size) :param f_x: Horizontal focal length. :param f_y: Vertical focal length. @@ -608,19 +608,19 @@ Constructs a Camera. :param c_y: y coordinate of the principal point. :param window_size: Size of the window. This together with focal length and principal point determines the field of view. -.. ocv:function:: Camera(const Vec2f &fov, const Size &window_size) +.. ocv:function:: Camera(const Vec2d &fov, const Size &window_size) :param fov: Field of view (horizontal, vertical) :param window_size: Size of the window. Principal point is at the center of the window by default. -.. ocv:function:: Camera(const cv::Matx33f &K, const Size &window_size) +.. ocv:function:: Camera(const Matx33d &K, const Size &window_size) :param K: Intrinsic matrix of the camera. :param window_size: Size of the window. This together with intrinsic matrix determines the field of view. -.. ocv:function:: Camera(const cv::Matx44f &proj, const Size &window_size) +.. ocv:function:: Camera(const Matx44d &proj, const Size &window_size) :param proj: Projection matrix of the camera. :param window_size: Size of the window. This together with projection matrix determines the field of view. @@ -629,7 +629,7 @@ viz::Camera::computeProjectionMatrix ------------------------------------ Computes projection matrix using intrinsic parameters of the camera. -.. ocv:function:: void computeProjectionMatrix(Matx44f &proj) const +.. ocv:function:: void computeProjectionMatrix(Matx44d &proj) const :param proj: Output projection matrix. diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 0a1fc1469..8393550f8 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -118,10 +118,10 @@ namespace cv class CV_EXPORTS Camera { public: - Camera(float fx, float fy, float cx, float cy, const Size &window_size); - explicit Camera(const Vec2f &fov, const Size &window_size); - explicit Camera(const Matx33f &K, const Size &window_size); - explicit Camera(const Matx44f &proj, const Size &window_size); + Camera(double fx, double fy, double cx, double cy, const Size &window_size); + explicit Camera(const Vec2d &fov, const Size &window_size); + explicit Camera(const Matx33d &K, const Size &window_size); + explicit Camera(const Matx44d &proj, const Size &window_size); inline const Vec2d & getClip() const { return clip_; } inline void setClip(const Vec2d &clip) { clip_ = clip; } @@ -129,24 +129,24 @@ namespace cv inline const Size & getWindowSize() const { return window_size_; } void setWindowSize(const Size &window_size); - inline const Vec2f & getFov() const { return fov_; } - inline void setFov(const Vec2f & fov) { fov_ = fov; } + inline const Vec2d& getFov() const { return fov_; } + inline void setFov(const Vec2d& fov) { fov_ = fov; } - inline const Vec2f & getPrincipalPoint() const { return principal_point_; } - inline const Vec2f & getFocalLength() const { return focal_; } + inline const Vec2d& getPrincipalPoint() const { return principal_point_; } + inline const Vec2d& getFocalLength() const { return focal_; } - void computeProjectionMatrix(Matx44f &proj) const; + void computeProjectionMatrix(Matx44d &proj) const; static Camera KinectCamera(const Size &window_size); private: - void init(float fx, float fy, float cx, float cy, const Size &window_size); + void init(double fx, double fy, double cx, double cy, const Size &window_size); Vec2d clip_; - Vec2f fov_; + Vec2d fov_; Size window_size_; - Vec2f principal_point_; - Vec2f focal_; + Vec2d principal_point_; + Vec2d focal_; }; class CV_EXPORTS KeyboardEvent diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 4126d8c35..19a3476a8 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -469,7 +469,7 @@ void cv::viz::InteractorStyle::OnKeyDown() // if a valid transformation was found, use it otherwise fall back to default view point. if (found_transformation) { - const vtkMatrix4x4* m = vtkProp3D::SafeDownCast(it->second)->GetUserMatrix(); + vtkMatrix4x4* m = vtkProp3D::SafeDownCast(it->second)->GetUserMatrix(); cam->SetFocalPoint(m->GetElement(0, 3) - m->GetElement(0, 2), m->GetElement(1, 3) - m->GetElement(1, 2), diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 7da4063f7..fa6662862 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1195,7 +1195,7 @@ namespace cv { namespace viz { namespace vtkSmartPointer transform = vtkSmartPointer::New(); transform->PreMultiply(); vtkSmartPointer mat_trans = vtkSmartPointer::New(); - mat_trans = convertToVtkMatrix(path[i].matrix); + mat_trans = vtkmatrix(path[i].matrix); transform->SetMatrix(mat_trans); vtkSmartPointer filter = vtkSmartPointer::New(); diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index 63b9a0214..a6ea95ab5 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -136,12 +136,12 @@ cv::viz::Mesh3d cv::viz::Mesh3d::load(const String& file) //////////////////////////////////////////////////////////////////// /// Camera implementation -cv::viz::Camera::Camera(float fx, float fy, float cx, float cy, const Size &window_size) +cv::viz::Camera::Camera(double fx, double fy, double cx, double cy, const Size &window_size) { init(fx, fy, cx, cy, window_size); } -cv::viz::Camera::Camera(const Vec2f &fov, const Size &window_size) +cv::viz::Camera::Camera(const Vec2d &fov, const Size &window_size) { CV_Assert(window_size.width > 0 && window_size.height > 0); setClip(Vec2d(0.01, 1000.01)); // Default clipping @@ -152,16 +152,16 @@ cv::viz::Camera::Camera(const Vec2f &fov, const Size &window_size) focal_ = Vec2f(principal_point_[0] / tan(fov_[0]*0.5f), principal_point_[1] / tan(fov_[1]*0.5f)); } -cv::viz::Camera::Camera(const cv::Matx33f & K, const Size &window_size) +cv::viz::Camera::Camera(const cv::Matx33d & K, const Size &window_size) { - float f_x = K(0,0); - float f_y = K(1,1); - float c_x = K(0,2); - float c_y = K(1,2); + double f_x = K(0,0); + double f_y = K(1,1); + double c_x = K(0,2); + double c_y = K(1,2); init(f_x, f_y, c_x, c_y, window_size); } -cv::viz::Camera::Camera(const Matx44f &proj, const Size &window_size) +cv::viz::Camera::Camera(const Matx44d &proj, const Size &window_size) { CV_Assert(window_size.width > 0 && window_size.height > 0); @@ -174,28 +174,26 @@ cv::viz::Camera::Camera(const Matx44f &proj, const Size &window_size) double epsilon = 2.2204460492503131e-16; - if (fabs(left-right) < epsilon) principal_point_[0] = static_cast(window_size.width) * 0.5f; - else principal_point_[0] = (left * static_cast(window_size.width)) / (left - right); - focal_[0] = -near * principal_point_[0] / left; + principal_point_[0] = fabs(left-right) < epsilon ? window_size.width * 0.5 : (left * window_size.width) / (left - right); + principal_point_[1] = fabs(top-bottom) < epsilon ? window_size.height * 0.5 : (top * window_size.height) / (top - bottom); - if (fabs(top-bottom) < epsilon) principal_point_[1] = static_cast(window_size.height) * 0.5f; - else principal_point_[1] = (top * static_cast(window_size.height)) / (top - bottom); - focal_[1] = near * principal_point_[1] / top; + focal_[0] = -near * principal_point_[0] / left; + focal_[1] = near * principal_point_[1] / top; setClip(Vec2d(near, far)); - fov_[0] = (atan2(principal_point_[0],focal_[0]) + atan2(window_size.width-principal_point_[0],focal_[0])); - fov_[1] = (atan2(principal_point_[1],focal_[1]) + atan2(window_size.height-principal_point_[1],focal_[1])); + fov_[0] = atan2(principal_point_[0], focal_[0]) + atan2(window_size.width-principal_point_[0], focal_[0]); + fov_[1] = atan2(principal_point_[1], focal_[1]) + atan2(window_size.height-principal_point_[1], focal_[1]); window_size_ = window_size; } -void cv::viz::Camera::init(float fx, float fy, float cx, float cy, const Size &window_size) +void cv::viz::Camera::init(double fx, double fy, double cx, double cy, const Size &window_size) { CV_Assert(window_size.width > 0 && window_size.height > 0); setClip(Vec2d(0.01, 1000.01));// Default clipping - fov_[0] = (atan2(cx,fx) + atan2(window_size.width-cx,fx)); - fov_[1] = (atan2(cy,fy) + atan2(window_size.height-cy,fy)); + fov_[0] = atan2(cx, fx) + atan2(window_size.width - cx, fx); + fov_[1] = atan2(cy, fy) + atan2(window_size.height - cy, fy); principal_point_[0] = cx; principal_point_[1] = cy; @@ -223,7 +221,7 @@ void cv::viz::Camera::setWindowSize(const Size &window_size) window_size_ = window_size; } -void cv::viz::Camera::computeProjectionMatrix(Matx44f &proj) const +void cv::viz::Camera::computeProjectionMatrix(Matx44d &proj) const { double top = clip_[0] * principal_point_[1] / focal_[1]; double left = -clip_[0] * principal_point_[0] / focal_[0]; @@ -247,6 +245,6 @@ void cv::viz::Camera::computeProjectionMatrix(Matx44f &proj) const cv::viz::Camera cv::viz::Camera::KinectCamera(const Size &window_size) { - Matx33f K(525.f, 0.f, 320.f, 0.f, 525.f, 240.f, 0.f, 0.f, 1.f) ; + Matx33d K(525.0, 0.0, 320.0, 0.0, 525.0, 240.0, 0.0, 0.0, 1.0) ; return Camera(K, window_size); } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index c26b04301..39f34b35d 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -64,24 +64,6 @@ cv::Affine3d cv::viz::makeCameraPose(const Vec3d& position, const Vec3d& focal_p return makeTransformToGlobal(u, v, n, position); } -vtkSmartPointer cv::viz::convertToVtkMatrix(const cv::Matx44f &m) -{ - vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); - for (int i = 0; i < 4; i++) - for (int k = 0; k < 4; k++) - vtk_matrix->SetElement(i, k, m(i, k)); - return vtk_matrix; -} - -cv::Matx44f cv::viz::convertToMatx(const vtkSmartPointer& vtk_matrix) -{ - cv::Matx44f m; - for (int i = 0; i < 4; i++) - for (int k = 0; k < 4; k++) - m(i, k) = vtk_matrix->GetElement(i, k); - return m; -} - namespace cv { namespace viz { template Vec<_Tp, 3>* vtkpoints_data(vtkSmartPointer& points); diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 34f78c64c..4b9d65b43 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -134,7 +134,7 @@ void cv::viz::Viz3d::VizImpl::showWidget(const String &id, const Widget &widget, if (actor) { // If the actor is 3D, apply pose - vtkSmartPointer matrix = convertToVtkMatrix(pose.matrix); + vtkSmartPointer matrix = vtkmatrix(pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); } @@ -181,7 +181,7 @@ void cv::viz::Viz3d::VizImpl::setWidgetPose(const String &id, const Affine3d &po vtkProp3D *actor = vtkProp3D::SafeDownCast(wam_itr->second); CV_Assert("Widget is not 3D." && actor); - vtkSmartPointer matrix = convertToVtkMatrix(pose.matrix); + vtkSmartPointer matrix = vtkmatrix(pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); } @@ -202,9 +202,8 @@ void cv::viz::Viz3d::VizImpl::updateWidgetPose(const String &id, const Affine3d setWidgetPose(id, pose); return ; } - Matx44d matrix_cv = convertToMatx(matrix); - Affine3d updated_pose = pose * Affine3d(matrix_cv); - matrix = convertToVtkMatrix(updated_pose.matrix); + Affine3d updated_pose = pose * Affine3d(*matrix->Element); + matrix = vtkmatrix(updated_pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); @@ -220,9 +219,7 @@ cv::Affine3d cv::viz::Viz3d::VizImpl::getWidgetPose(const String &id) const vtkProp3D *actor = vtkProp3D::SafeDownCast(wam_itr->second); CV_Assert("Widget is not 3D." && actor); - vtkSmartPointer matrix = actor->GetUserMatrix(); - Matx44d matrix_cv = convertToMatx(matrix); - return Affine3d(matrix_cv); + return Affine3d(*actor->GetUserMatrix()->Element); } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -315,21 +312,23 @@ void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color) ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setCamera(const Camera &camera) { - vtkCamera& active_camera = *renderer_->GetActiveCamera(); + vtkSmartPointer active_camera = renderer_->GetActiveCamera(); // Set the intrinsic parameters of the camera window_->SetSize(camera.getWindowSize().width, camera.getWindowSize().height); double aspect_ratio = static_cast(camera.getWindowSize().width)/static_cast(camera.getWindowSize().height); - Matx44f proj_mat; + Matx44d proj_mat; camera.computeProjectionMatrix(proj_mat); + // Use the intrinsic parameters of the camera to simulate more realistically - Matx44f old_proj_mat = convertToMatx(active_camera.GetProjectionTransformMatrix(aspect_ratio, -1.0, 1.0)); - vtkTransform *transform = vtkTransform::New(); + vtkSmartPointer vtk_matrix = active_camera->GetProjectionTransformMatrix(aspect_ratio, -1.0, 1.0); + Matx44d old_proj_mat(*vtk_matrix->Element); + // This is a hack around not being able to set Projection Matrix - transform->SetMatrix(convertToVtkMatrix(proj_mat * old_proj_mat.inv())); - active_camera.SetUserTransform(transform); - transform->Delete(); + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->SetMatrix(vtkmatrix(proj_mat * old_proj_mat.inv())); + active_camera->SetUserTransform(transform); renderer_->ResetCameraClippingRange(); renderer_->Render(); @@ -338,15 +337,14 @@ void cv::viz::Viz3d::VizImpl::setCamera(const Camera &camera) ///////////////////////////////////////////////////////////////////////////////////////////// cv::viz::Camera cv::viz::Viz3d::VizImpl::getCamera() const { - vtkCamera& active_camera = *renderer_->GetActiveCamera(); + vtkSmartPointer active_camera = renderer_->GetActiveCamera(); Size window_size(renderer_->GetRenderWindow()->GetSize()[0], renderer_->GetRenderWindow()->GetSize()[1]); double aspect_ratio = window_size.width / (double)window_size.height; - Matx44f proj_matrix = convertToMatx(active_camera.GetProjectionTransformMatrix(aspect_ratio, -1.0f, 1.0f)); - Camera camera(proj_matrix, window_size); - return camera; + vtkSmartPointer proj_matrix = active_camera->GetProjectionTransformMatrix(aspect_ratio, -1.0f, 1.0f); + return Camera(Matx44d(*proj_matrix->Element), window_size); } ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index 0cfb40309..d5274b49c 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -180,19 +180,22 @@ private: }; - namespace cv { namespace viz { - vtkSmartPointer convertToVtkMatrix(const cv::Matx44f &m); - cv::Matx44f convertToMatx(const vtkSmartPointer& vtk_matrix); + inline vtkSmartPointer vtkmatrix(const cv::Matx44d &matrix) + { + vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); + vtk_matrix->DeepCopy(matrix.val); + return vtk_matrix; + } struct color_tag {}; struct gray_tag {}; - static Vec3b fetchRgb(const unsigned char* color, color_tag) { return Vec3b(color[2], color[1], color[0]); } - static Vec3b fetchRgb(const unsigned char* color, gray_tag) { return Vec3b(color[0], color[0], color[0]); } + inline Vec3b fetchRgb(const unsigned char* color, color_tag) { return Vec3b(color[2], color[1], color[0]); } + inline Vec3b fetchRgb(const unsigned char* color, gray_tag) { return Vec3b(color[0], color[0], color[0]); } inline Vec3d vtkpoint(const Point3f& point) { return Vec3d(point.x, point.y, point.z); } template inline _Tp normalized(const _Tp& v) { return v * 1/cv::norm(v); } @@ -204,82 +207,6 @@ namespace cv return scaled_color; } - struct NanFilter - { - template - struct Impl - { - template - static Vec<_Tp, 3>* copy(const Mat& source, Vec<_Tp, 3>* output, const Mat& nan_mask) - { - CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); - CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); - CV_DbgAssert(DataDepth<_Msk>::value == nan_mask.depth()); - - int s_chs = source.channels(); - int m_chs = nan_mask.channels(); - - for (int y = 0; y < source.rows; ++y) - { - const _Tp* srow = source.ptr<_Tp>(y); - const _Msk* mrow = nan_mask.ptr<_Msk>(y); - - for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) - if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) - *output++ = Vec<_Tp, 3>(srow); - } - return output; - } - - template - static Vec3b* copyColor(const Mat& source, Vec3b* output, const Mat& nan_mask) - { - CV_Assert(source.size() == nan_mask.size()); - CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); - CV_DbgAssert(DataDepth<_Msk>::value == nan_mask.depth()); - - int s_chs = source.channels(); - int m_chs = nan_mask.channels(); - - for (int y = 0; y < source.rows; ++y) - { - const unsigned char* srow = source.ptr(y); - const _Msk* mrow = nan_mask.ptr<_Msk>(y); - - for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) - if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) - *output++ = fetchRgb(srow, _Tag()); - } - return output; - } - }; - - template - static inline Vec<_Tp, 3>* copy(const Mat& source, Vec<_Tp, 3>* output, const Mat& nan_mask) - { - CV_Assert(nan_mask.depth() == CV_32F || nan_mask.depth() == CV_64F); - - typedef Vec<_Tp, 3>* (*copy_func)(const Mat&, Vec<_Tp, 3>*, const Mat&); - const static copy_func table[2] = { &NanFilter::Impl::copy<_Tp>, &NanFilter::Impl::copy<_Tp> }; - - return table[nan_mask.depth() - 5](source, output, nan_mask); - } - - static inline Vec3b* copyColor(const Mat& source, Vec3b* output, const Mat& nan_mask) - { - CV_Assert(nan_mask.depth() == CV_32F || nan_mask.depth() == CV_64F); - - typedef Vec3b* (*copy_func)(const Mat&, Vec3b*, const Mat&); - const static copy_func table[2][2] = - { - { &NanFilter::Impl::copyColor, &NanFilter::Impl ::copyColor }, - { &NanFilter::Impl::copyColor, &NanFilter::Impl::copyColor } - }; - - return table[nan_mask.depth() - 5][source.channels() == 1 ? 0 : 1](source, output, nan_mask); - } - }; - struct ConvertToVtkImage { struct Impl diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index 839ea2014..23099ba72 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -244,7 +244,7 @@ void cv::viz::Widget3D::setPose(const Affine3d &pose) vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Widget is not 3D." && actor); - vtkSmartPointer matrix = convertToVtkMatrix(pose.matrix); + vtkSmartPointer matrix = vtkmatrix(pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); } @@ -261,8 +261,8 @@ void cv::viz::Widget3D::updatePose(const Affine3d &pose) return; } - Affine3d updated_pose = pose * Affine3d(convertToMatx(matrix)); - matrix = convertToVtkMatrix(updated_pose.matrix); + Affine3d updated_pose = pose * Affine3d(*matrix->Element); + matrix = vtkmatrix(updated_pose.matrix); actor->SetUserMatrix(matrix); actor->Modified(); @@ -272,7 +272,7 @@ cv::Affine3d cv::viz::Widget3D::getPose() const { vtkProp3D *actor = vtkProp3D::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Widget is not 3D." && actor); - return Affine3d(convertToMatx(actor->GetUserMatrix())); + return Affine3d(*actor->GetUserMatrix()->Element); } void cv::viz::Widget3D::setColor(const Color &color) diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index ece1370d5..9f76bb2a2 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -50,7 +50,6 @@ TEST(Viz, DISABLED_show_cloud_bluberry) Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); Viz3d viz("show_cloud_bluberry"); - viz.setBackgroundColor(); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud, Color::bluberry())); viz.spin(); @@ -64,7 +63,6 @@ TEST(Viz, DISABLED_show_cloud_random_color) theRNG().fill(colors, RNG::UNIFORM, 0, 255); Viz3d viz("show_cloud_random_color"); - viz.setBackgroundColor(); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud, colors)); viz.spin(); @@ -80,7 +78,6 @@ TEST(Viz, DISABLED_show_cloud_masked) dragon_cloud.at(i) = qnan; Viz3d viz("show_cloud_masked"); - viz.setBackgroundColor(); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud)); viz.spin(); From cd57c4e189cb70318875534dadae1dcf10a35e89 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 10:53:04 +0400 Subject: [PATCH 137/295] refactored CloudNormals and added test for it --- modules/viz/include/opencv2/viz/types.hpp | 2 +- modules/viz/src/clouds.cpp | 157 +++++++--------------- modules/viz/src/precomp.hpp | 5 + modules/viz/src/vtk/vtkCloudMatSink.cpp | 4 +- modules/viz/src/vtk/vtkCloudMatSource.cpp | 7 +- modules/viz/test/tests_simple.cpp | 15 ++- 6 files changed, 72 insertions(+), 118 deletions(-) diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 8393550f8..1e222c800 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -108,7 +108,7 @@ namespace cv { public: - Mat cloud, colors; + Mat cloud, colors, normals; Mat polygons; //! Loads mesh from a given ply file diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 2247dffe9..3c28624f3 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -45,14 +45,6 @@ #include "precomp.hpp" -namespace cv -{ - namespace viz - { - template Vec<_Tp, 3>* vtkpoints_data(vtkSmartPointer& points); - } -} - /////////////////////////////////////////////////////////////////////////////////////////////// /// Point Cloud Widget implementation @@ -183,119 +175,67 @@ template<> cv::viz::WCloudCollection cv::viz::Widget::cast - struct Impl - { - static vtkSmartPointer applyOrganized(const Mat &cloud, const Mat& normals, double level, float scale, _Tp *&pts, vtkIdType &nr_normals) - { - vtkIdType point_step = static_cast(std::sqrt(level)); - nr_normals = (static_cast((cloud.cols - 1) / point_step) + 1) * - (static_cast((cloud.rows - 1) / point_step) + 1); - vtkSmartPointer lines = vtkSmartPointer::New(); - - pts = new _Tp[2 * nr_normals * 3]; - - int cch = cloud.channels(); - vtkIdType cell_count = 0; - for (vtkIdType y = 0; y < cloud.rows; y += point_step) - { - const _Tp *prow = cloud.ptr<_Tp>(y); - const _Tp *nrow = normals.ptr<_Tp>(y); - for (vtkIdType x = 0; x < cloud.cols; x += point_step * cch) - { - pts[2 * cell_count * 3 + 0] = prow[x]; - pts[2 * cell_count * 3 + 1] = prow[x+1]; - pts[2 * cell_count * 3 + 2] = prow[x+2]; - pts[2 * cell_count * 3 + 3] = prow[x] + nrow[x] * scale; - pts[2 * cell_count * 3 + 4] = prow[x+1] + nrow[x+1] * scale; - pts[2 * cell_count * 3 + 5] = prow[x+2] + nrow[x+2] * scale; - - lines->InsertNextCell(2); - lines->InsertCellPoint(2 * cell_count); - lines->InsertCellPoint(2 * cell_count + 1); - cell_count++; - } - } - return lines; - } - - static vtkSmartPointer applyUnorganized(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) - { - vtkSmartPointer lines = vtkSmartPointer::New(); - nr_normals = (cloud.size().area() - 1) / level + 1 ; - pts = new _Tp[2 * nr_normals * 3]; - - int cch = cloud.channels(); - const _Tp *p = cloud.ptr<_Tp>(); - const _Tp *n = normals.ptr<_Tp>(); - for (vtkIdType i = 0, j = 0; j < nr_normals; j++, i = j * level * cch) - { - - pts[2 * j * 3 + 0] = p[i]; - pts[2 * j * 3 + 1] = p[i+1]; - pts[2 * j * 3 + 2] = p[i+2]; - pts[2 * j * 3 + 3] = p[i] + n[i] * scale; - pts[2 * j * 3 + 4] = p[i+1] + n[i+1] * scale; - pts[2 * j * 3 + 5] = p[i+2] + n[i+2] * scale; - - lines->InsertNextCell(2); - lines->InsertCellPoint(2 * j); - lines->InsertCellPoint(2 * j + 1); - } - return lines; - } - }; - - template - static inline vtkSmartPointer apply(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) - { - if (cloud.cols > 1 && cloud.rows > 1) - return CloudNormalsUtils::Impl<_Tp>::applyOrganized(cloud, normals, level, scale, pts, nr_normals); - else - return CloudNormalsUtils::Impl<_Tp>::applyUnorganized(cloud, normals, level, scale, pts, nr_normals); - } - }; - -}}} - cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, int level, float scale, const Color &color) { Mat cloud = _cloud.getMat(); Mat normals = _normals.getMat(); + CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); CV_Assert(cloud.size() == normals.size() && cloud.type() == normals.type()); + int sqlevel = (int)std::sqrt((double)level); + int ystep = (cloud.cols > 1 && cloud.rows > 1) ? sqlevel : 1; + int xstep = (cloud.cols > 1 && cloud.rows > 1) ? sqlevel : level; + vtkSmartPointer points = vtkSmartPointer::New(); + points->SetDataType(cloud.depth() == CV_32F ? VTK_FLOAT : VTK_DOUBLE); + vtkSmartPointer lines = vtkSmartPointer::New(); - vtkIdType nr_normals = 0; - if (cloud.depth() == CV_32F) + int s_chs = cloud.channels(); + int n_chs = normals.channels(); + int total = 0; + + for(int y = 0; y < cloud.rows; y += ystep) { - points->SetDataTypeToFloat(); + if (cloud.depth() == CV_32F) + { + const float *srow = cloud.ptr(y); + const float *send = srow + cloud.cols * s_chs; + const float *nrow = normals.ptr(y); - vtkSmartPointer data = vtkSmartPointer::New(); - data->SetNumberOfComponents(3); + for (; srow < send; srow += xstep * s_chs, nrow += xstep * n_chs) + if (!isNan(srow) && !isNan(nrow)) + { + Vec3f endp = Vec3f(srow) + Vec3f(nrow) * scale; - float* pts = 0; - lines = CloudNormalsUtils::apply(cloud, normals, level, scale, pts, nr_normals); - data->SetArray(&pts[0], 2 * nr_normals * 3, 0); - points->SetData(data); - } - else - { - points->SetDataTypeToDouble(); + points->InsertNextPoint(srow); + points->InsertNextPoint(endp.val); - vtkSmartPointer data = vtkSmartPointer::New(); - data->SetNumberOfComponents(3); + lines->InsertNextCell(2); + lines->InsertCellPoint(total++); + lines->InsertCellPoint(total++); + } + } + else + { + const double *srow = cloud.ptr(y); + const double *send = srow + cloud.cols * s_chs; + const double *nrow = normals.ptr(y); - double* pts = 0; - lines = CloudNormalsUtils::apply(cloud, normals, level, scale, pts, nr_normals); - data->SetArray(&pts[0], 2 * nr_normals * 3, 0); - points->SetData(data); + for (; srow < send; srow += xstep * s_chs, nrow += xstep * n_chs) + if (!isNan(srow) && !isNan(nrow)) + { + Vec3d endp = Vec3d(srow) + Vec3d(nrow) * (double)scale; + + points->InsertNextPoint(srow); + points->InsertNextPoint(endp.val); + + lines->InsertNextCell(2); + lines->InsertCellPoint(total++); + lines->InsertCellPoint(total++); + } + } } vtkSmartPointer polyData = vtkSmartPointer::New(); @@ -303,16 +243,17 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in polyData->SetLines(lines); vtkSmartPointer mapper = vtkSmartPointer::New(); + mapper->SetColorModeToMapScalars(); + mapper->SetScalarModeToUsePointData(); #if VTK_MAJOR_VERSION <= 5 mapper->SetInput(polyData); #else mapper->SetInputData(polyData); #endif - mapper->SetColorModeToMapScalars(); - mapper->SetScalarModeToUsePointData(); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); + WidgetAccessor::setProp(*this, actor); setColor(color); } diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index b10e83ad5..5bb0a5cd4 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -170,6 +170,11 @@ namespace cv static VizMap storage; friend class Viz3d; }; + + template bool isNan(const _Tp* data) + { + return isNan(data[0]) || isNan(data[1]) || isNan(data[2]); + } } } diff --git a/modules/viz/src/vtk/vtkCloudMatSink.cpp b/modules/viz/src/vtk/vtkCloudMatSink.cpp index b96db385b..cf1eb4648 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSink.cpp @@ -73,8 +73,8 @@ void cv::viz::vtkCloudMatSink::WriteData() CV_Assert(vtktype == VTK_FLOAT || vtktype == VTK_DOUBLE); cloud.create(1, points_Data->GetNumberOfPoints(), vtktype == VTK_FLOAT ? CV_32FC3 : CV_64FC3); - Vec3d *ddata = (Vec3d*)cloud.getMat().ptr(); - Vec3f *fdata = (Vec3f*)cloud.getMat().ptr(); + Vec3d *ddata = cloud.getMat().ptr(); + Vec3f *fdata = cloud.getMat().ptr(); if (cloud.depth() == CV_32F) for(size_t i = 0; i < cloud.total(); ++i) diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index cf3d21e6d..f1dabe66b 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -48,11 +48,6 @@ namespace cv { namespace viz { vtkStandardNewMacro(vtkCloudMatSource); - template bool isNan(const _Tp* data) - { - return isNan(data[0]) || isNan(data[1]) || isNan(data[2]); - } - template struct VtkDepthTraits; template<> struct VtkDepthTraits @@ -190,7 +185,7 @@ void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& cloud_colors, co for (int y = 0; y < cloud_colors.rows; ++y) { const unsigned char* srow = cloud_colors.ptr(y); - const unsigned char* send = srow + cloud_colors.cols * cloud_colors.channels(); + const unsigned char* send = srow + cloud_colors.cols * s_chs; const _Msk* mrow = mask.ptr<_Msk>(y); if (cloud_colors.channels() == 1) diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 9f76bb2a2..b183f7bb5 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -120,6 +120,20 @@ TEST(Viz, DISABLED_show_mesh_random_colors) viz.spin(); } +TEST(Viz, DISABLED_show_sampled_normals) +{ + Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + computeNormals(mesh, mesh.normals); + + Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); + + Viz3d viz("show_sampled_normals"); + viz.showWidget("mesh", WMesh(mesh), pose); + viz.showWidget("normals", WCloudNormals(mesh.cloud, mesh.normals, 30, 0.1f, Color::green()), pose); + viz.setRenderingProperty("normals", LINE_WIDTH, 2.0); + viz.spin(); +} + TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) { Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); @@ -130,4 +144,3 @@ TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) viz.spin(); viz.spin(); } - From 7b28f730f42c419bc9d17e394a91e5df4a65a20b Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 12:32:33 +0400 Subject: [PATCH 138/295] traits for Affine3 --- modules/core/include/opencv2/core/affine.hpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index 3f072e78f..62720b572 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -134,8 +134,24 @@ namespace cv static cv::Vec3f operator*(const cv::Affine3f& affine, const cv::Vec3f& vector); static cv::Vec3d operator*(const cv::Affine3d& affine, const cv::Vec3d& vector); -} + template class DataType< Affine3<_Tp> > + { + public: + typedef Affine3<_Tp> value_type; + typedef Affine3::work_type> work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 16, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; + }; +} /////////////////////////////////////////////////////////////////////////////////// From e26b7e1e4fa855a30798fdd11ad92b7cd87aa518 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 12:34:42 +0400 Subject: [PATCH 139/295] ported some trajectories functionality to InputArray style --- modules/viz/doc/widget.rst | 6 +- modules/viz/include/opencv2/viz.hpp | 14 ++- modules/viz/include/opencv2/viz/widgets.hpp | 7 +- modules/viz/src/shapes.cpp | 105 ++----------------- modules/viz/src/vizcore.cpp | 108 ++++++++++++++------ modules/viz/test/tests_simple.cpp | 20 +++- 6 files changed, 120 insertions(+), 140 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index c42079964..159e4ba80 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -732,16 +732,16 @@ This 3D Widget represents a trajectory. :: enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white(),; + WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white(),; }; viz::WTrajectory::WTrajectory ----------------------------- Constructs a WTrajectory. -.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()) +.. ocv:function:: WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()) - :param path: List of poses on a trajectory. + :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] :param display_mode: Display mode. This can be PATH, FRAMES, and BOTH. :param scale: Scale of the frames. Polyline is not affected. :param color: :ocv:class:`Color` of the polyline that represents path. Frames are not affected. diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 2724e921d..b281635a6 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -104,11 +104,17 @@ namespace cv CV_EXPORTS bool readPose(const String& file, Affine3d& pose, const String& tag = "pose"); CV_EXPORTS void writePose(const String& file, const Affine3d& pose, const String& tag = "pose"); - CV_EXPORTS void writeTrajectory(const std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, const String& tag = "pose"); - CV_EXPORTS void writeTrajectory(const std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, const String& tag = "pose"); + //! takes vector> with T = float/dobule and writes to a sequence of files with given filename format + CV_EXPORTS void writeTrajectory(InputArray traj, const String& files_format = "pose%05d.xml", int start = 0, const String& tag = "pose"); - CV_EXPORTS void readTrajectory(std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, int end = INT_MAX, const String& tag = "pose"); - CV_EXPORTS void readTrajectory(std::vector& traj, const String& files_format = "pose%05d.xml", int start = 0, int end = INT_MAX, const String& tag = "pose"); + //! takes vector> with T = float/dobule and loads poses from sequence of files + CV_EXPORTS void readTrajectory(OutputArray traj, const String& files_format = "pose%05d.xml", int start = 0, int end = INT_MAX, const String& tag = "pose"); + + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// Computing normals for mesh + + CV_EXPORTS void computeNormals(const Mesh3d& mesh, OutputArray normals); } /* namespace viz */ } /* namespace cv */ diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 27f211cd6..2868880ec 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -262,9 +262,8 @@ namespace cv public: enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH }; - //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); - WTrajectory(const std::vector &path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); + //! Takes vector> and displays trajectory of the given path either by coordinate frames or polyline + WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectoryFrustums : public Widget3D @@ -309,7 +308,7 @@ namespace cv class CV_EXPORTS WCloudNormals : public Widget3D { public: - WCloudNormals(InputArray cloud, InputArray normals, int level = 100, float scale = 0.02f, const Color &color = Color::white()); + WCloudNormals(InputArray cloud, InputArray normals, int level = 64, float scale = 0.1f, const Color &color = Color::white()); }; class CV_EXPORTS WMesh : public Widget3D diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index fa6662862..490be3b3b 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1213,106 +1213,21 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WTrajectory::WTrajectory(const std::vector &_path, int display_mode, float scale, const Color &color) +cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, float scale, const Color &color) { - std::vector path(_path.begin(), _path.end()); + CV_Assert(_path.kind() == _InputArray::STD_VECTOR || _path.kind() == _InputArray::MAT); + CV_Assert(_path.type() == CV_32FC(16) || _path.type() == CV_64FC(16)); - vtkSmartPointer appendFilter = vtkSmartPointer::New(); + const Affine3d* dpath = _path.getMat().ptr(), *dend = dpath + _path.total(); + const Affine3f* fpath = _path.getMat().ptr(), *fend = fpath + _path.total(); + std::vector path; - // Bitwise and with 3 in order to limit the domain to 2 bits - if ((~display_mode & 3) ^ WTrajectory::PATH) - { - // Create a poly line along the path - vtkIdType nr_points = path.size(); + if (_path.depth() == CV_32F) + path.assign(fpath, fend); - vtkSmartPointer points = vtkSmartPointer::New(); - points->SetDataTypeToFloat(); - points->SetNumberOfPoints(nr_points); + if (_path.depth() == CV_64F) + path.assign(dpath, dend); - vtkSmartPointer polyData = vtkSmartPointer::New(); - vtkSmartPointer polyLine = vtkSmartPointer::New(); - polyLine->GetPointIds()->SetNumberOfIds(nr_points); - - Vec3f *data_beg = vtkpoints_data(points); - - for (vtkIdType i = 0; i < nr_points; ++i) - { - Vec3f cam_pose = path[i].translation(); - *data_beg++ = cam_pose; - polyLine->GetPointIds()->SetId(i,i); - } - - vtkSmartPointer cells = vtkSmartPointer::New(); - cells->InsertNextCell(polyLine); - - polyData->SetPoints(points); - polyData->SetLines(cells); - - // Set the color for polyData - vtkSmartPointer colors = vtkSmartPointer::New(); - colors->SetNumberOfComponents(3); - colors->SetNumberOfTuples(nr_points); - colors->FillComponent(0, color[2]); - colors->FillComponent(1, color[1]); - colors->FillComponent(2, color[0]); - - polyData->GetPointData()->SetScalars(colors); -#if VTK_MAJOR_VERSION <= 5 - appendFilter->AddInputConnection(polyData->GetProducerPort()); -#else - appendFilter->AddInputData(polyData); -#endif - } - - if ((~display_mode & 3) ^ WTrajectory::FRAMES) - { - // Create frames and transform along the path - vtkSmartPointer axes = vtkSmartPointer::New(); - axes->SetOrigin(0, 0, 0); - axes->SetScaleFactor(scale); - - vtkSmartPointer axes_colors = vtkSmartPointer::New(); - axes_colors->SetNumberOfComponents(3); - axes_colors->InsertNextTuple3(255,0,0); - axes_colors->InsertNextTuple3(255,0,0); - axes_colors->InsertNextTuple3(0,255,0); - axes_colors->InsertNextTuple3(0,255,0); - axes_colors->InsertNextTuple3(0,0,255); - axes_colors->InsertNextTuple3(0,0,255); - - vtkSmartPointer axes_data = axes->GetOutput(); -#if VTK_MAJOR_VERSION <= 5 - axes_data->Update(); -#else - axes->Update(); -#endif - axes_data->GetPointData()->SetScalars(axes_colors); - - vtkSmartPointer axes_tubes = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - axes_tubes->SetInput(axes_data); -#else - axes_tubes->SetInputData(axes_data); -#endif - axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); - axes_tubes->SetNumberOfSides(6); - axes_tubes->Update(); - - TrajectoryUtils::applyPath(axes_tubes->GetOutput(), appendFilter, path); - } - - vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetScalarModeToUsePointData(); - mapper->SetInputConnection(appendFilter->GetOutputPort()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(mapper); - - WidgetAccessor::setProp(*this, actor); -} - -cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, float scale, const Color &color) -{ vtkSmartPointer appendFilter = vtkSmartPointer::New(); // Bitwise and with 3 in order to limit the domain to 2 bits diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index 39f34b35d..d01b947a4 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -243,53 +243,103 @@ void cv::viz::writePose(const String& file, const Affine3d& pose, const String& fs << tag << Mat(pose.matrix, false); } -namespace cv { namespace viz { namespace impl +void cv::viz::readTrajectory(OutputArray _traj, const String& files_format, int start, int end, const String& tag) { - template - void readTrajectory(std::vector >& traj, const String& files_format, int start, int end, const String& tag) + CV_Assert(_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT); + + start = max(0, std::min(start, end)); + end = std::max(start, end); + + std::vector traj; + + for(int i = start; i < end; ++i) { - start = max(0, std::min(start, end)); - end = std::max(start, end); + Affine3d affine; + bool ok = readPose(cv::format(files_format.c_str(), i), affine, tag); + if (!ok) + break; - std::vector< Affine3<_Tp> > temp; + traj.push_back(affine); + } - for(int i = start; i < end; ++i) + Mat(traj).convertTo(_traj, _traj.depth()); +} + +void cv::viz::writeTrajectory(InputArray _traj, const String& files_format, int start, const String& tag) +{ + if (_traj.kind() == _InputArray::STD_VECTOR_MAT) + { + std::vector& v = *(std::vector*)_traj.getObj(); + + for(size_t i = 0, index = max(0, start); i < v.size(); ++i, ++index) { Affine3d affine; - bool ok = readPose(cv::format(files_format.c_str(), i), affine, tag); - if (!ok) - break; - - temp.push_back(affine); + Mat pose = v[i]; + CV_Assert(pose.type() == CV_32FC(16) || pose.type() == CV_64FC(16)); + pose.copyTo(affine.matrix); + writePose(cv::format(files_format.c_str(), index), affine, tag); } - traj.swap(temp); + return; } - template - void writeTrajectory(const std::vector >& traj, const String& files_format, int start, const String& tag) + if (_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT) { - for(size_t i = 0, index = max(0, start); i < traj.size(); ++i, ++index) - writePose(cv::format(files_format.c_str(), index), traj[i], tag); + CV_Assert(_traj.type() == CV_32FC(16) || _traj.type() == CV_64FC(16)); + + Mat traj = _traj.getMat(); + + if (traj.depth() == CV_32F) + for(size_t i = 0, index = max(0, start); i < traj.total(); ++i, ++index) + writePose(cv::format(files_format.c_str(), index), traj.at(i), tag); + + if (traj.depth() == CV_64F) + for(size_t i = 0, index = max(0, start); i < traj.total(); ++i, ++index) + writePose(cv::format(files_format.c_str(), index), traj.at(i), tag); } -}}} + CV_Assert(!"Unsupported array kind"); +} +/////////////////////////////////////////////////////////////////////////////////////////////// +/// Computing normals for mesh +void cv::viz::computeNormals(const Mesh3d& mesh, OutputArray _normals) +{ + vtkSmartPointer prop = WidgetAccessor::getProp(WMesh(mesh)); + vtkSmartPointer mapper = vtkActor::SafeDownCast(prop)->GetMapper(); + vtkSmartPointer polydata = vtkPolyData::SafeDownCast(mapper->GetInput()); -void cv::viz::readTrajectory(std::vector& traj, const String& files_format, int start, int end, const String& tag) -{ impl::readTrajectory(traj, files_format, start, end, tag); } - -void cv::viz::readTrajectory(std::vector& traj, const String& files_format, int start, int end, const String& tag) -{ impl::readTrajectory(traj, files_format, start, end, tag); } - -void cv::viz::writeTrajectory(const std::vector& traj, const String& files_format, int start, const String& tag) -{ impl::writeTrajectory(traj, files_format, start, tag); } - -void cv::viz::writeTrajectory(const std::vector& traj, const String& files_format, int start, const String& tag) -{ impl::writeTrajectory(traj, files_format, start, tag); } + vtkSmartPointer normal_generator = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 + normal_generator->SetInput(polydata); +#else + normal_generator->SetInputData(polydata); +#endif + normal_generator->ComputePointNormalsOn(); + normal_generator->ComputeCellNormalsOff(); + normal_generator->SetFeatureAngle(0.1); + normal_generator->SetSplitting(0); + normal_generator->SetConsistency(1); + normal_generator->SetAutoOrientNormals(0); + normal_generator->SetFlipNormals(0); + normal_generator->SetNonManifoldTraversal(1); + normal_generator->Update(); + vtkSmartPointer generic_normals = normal_generator->GetOutput()->GetPointData()->GetNormals(); + if(generic_normals) + { + Mat normals(1, generic_normals->GetNumberOfTuples(), CV_64FC3); + Vec3d *optr = normals.ptr(); + for(int i = 0; i < generic_normals->GetNumberOfTuples(); ++i, ++optr) + generic_normals->GetTuple(i, optr->val); + + normals.convertTo(_normals, mesh.cloud.type()); + } + else + _normals.release(); +} diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index b183f7bb5..f311ff2b7 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -49,9 +49,11 @@ TEST(Viz, DISABLED_show_cloud_bluberry) { Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); + Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); + Viz3d viz("show_cloud_bluberry"); viz.showWidget("coosys", WCoordinateSystem()); - viz.showWidget("dragon", WCloud(dragon_cloud, Color::bluberry())); + viz.showWidget("dragon", WCloud(dragon_cloud, Color::bluberry()), pose); viz.spin(); } @@ -62,9 +64,11 @@ TEST(Viz, DISABLED_show_cloud_random_color) Mat colors(dragon_cloud.size(), CV_8UC3); theRNG().fill(colors, RNG::UNIFORM, 0, 255); + Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); + Viz3d viz("show_cloud_random_color"); viz.showWidget("coosys", WCoordinateSystem()); - viz.showWidget("dragon", WCloud(dragon_cloud, colors)); + viz.showWidget("dragon", WCloud(dragon_cloud, colors), pose); viz.spin(); } @@ -77,9 +81,11 @@ TEST(Viz, DISABLED_show_cloud_masked) if (i % 15 != 0) dragon_cloud.at(i) = qnan; + Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); + Viz3d viz("show_cloud_masked"); viz.showWidget("coosys", WCoordinateSystem()); - viz.showWidget("dragon", WCloud(dragon_cloud)); + viz.showWidget("dragon", WCloud(dragon_cloud), pose); viz.spin(); } @@ -102,9 +108,11 @@ TEST(Viz, DISABLED_show_mesh) { Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); + Viz3d viz("show_mesh"); viz.showWidget("coosys", WCoordinateSystem()); - viz.showWidget("mesh", WMesh(mesh)); + viz.showWidget("mesh", WMesh(mesh), pose); viz.spin(); } @@ -113,9 +121,11 @@ TEST(Viz, DISABLED_show_mesh_random_colors) Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); + Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); + Viz3d viz("show_mesh_random_color"); viz.showWidget("coosys", WCoordinateSystem()); - viz.showWidget("mesh", WMesh(mesh)); + viz.showWidget("mesh", WMesh(mesh), pose); viz.setRenderingProperty("mesh", SHADING, SHADING_PHONG); viz.spin(); } From b100299644d8c2c486fcbe4e5e281056de056d82 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 14:51:32 +0400 Subject: [PATCH 140/295] code beatification --- modules/viz/src/interactor_style.hpp | 2 +- modules/viz/src/precomp.hpp | 1 + modules/viz/src/shapes.cpp | 81 ++++++++-------------------- 3 files changed, 23 insertions(+), 61 deletions(-) diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/interactor_style.hpp index 92876d894..583860911 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/interactor_style.hpp @@ -63,7 +63,7 @@ namespace cv virtual void Initialize(); void setWidgetActorMap(const Ptr& actors) { widget_actor_map_ = actors; } - void setRenderer(vtkSmartPointer& ren) { renderer_ = ren; } + void setRenderer(vtkSmartPointer& renderer) { renderer_ = renderer; } void registerMouseCallback(void (*callback)(const MouseEvent&, void*), void* cookie = 0); void registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void * cookie = 0); void saveScreenshot(const String &file); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 5bb0a5cd4..85977a800 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -124,6 +124,7 @@ #include #include #include +#include #if !defined(_WIN32) || defined(__CYGWIN__) # include /* unlink */ diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 490be3b3b..2088e7d40 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -189,28 +189,22 @@ cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, arrowSource->SetTipRadius(thickness * 3.0); arrowSource->SetTipLength(thickness * 10.0); - Vec3f startPoint(pt1.x, pt1.y, pt1.z), endPoint(pt2.x, pt2.y, pt2.z); - Vec3f arbitrary(theRNG().uniform(-10.f, 10.f), theRNG().uniform(-10.f, 10.f), theRNG().uniform(-10.f, 10.f)); + RNG rng = theRNG(); + Vec3d arbitrary(rng.uniform(-10.0, 10.0), rng.uniform(-10.0, 10.0), rng.uniform(-10.0, 10.0)); + Vec3d startPoint(pt1.x, pt1.y, pt1.z), endPoint(pt2.x, pt2.y, pt2.z); + double length = cv::norm(endPoint - startPoint); - Vec3f xvec = normalized(endPoint - startPoint); - Vec3f zvec = normalized(xvec.cross(arbitrary)); - Vec3f yvec = zvec.cross(xvec); + Vec3d xvec = normalized(endPoint - startPoint); + Vec3d zvec = normalized(xvec.cross(arbitrary)); + Vec3d yvec = zvec.cross(xvec); - // Create the direction cosine matrix - vtkSmartPointer matrix = vtkSmartPointer::New(); - matrix->Identity(); - for (int i = 0; i < 3; ++i) - { - matrix->SetElement(i, 0, xvec[i]); - matrix->SetElement(i, 1, yvec[i]); - matrix->SetElement(i, 2, zvec[i]); - } + Affine3d pose = makeTransformToGlobal(xvec, yvec, zvec); // Apply the transforms vtkSmartPointer transform = vtkSmartPointer::New(); transform->Translate(startPoint.val); - transform->Concatenate(matrix); + transform->Concatenate(vtkmatrix(pose.matrix)); transform->Scale(length, length, length); // Transform the polydata @@ -523,34 +517,18 @@ cv::viz::WGrid::WGrid(const Vec4f &coefs, const Vec2i &dimensions, const Vec2f & vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); // Estimate the transform to set the normal based on the coefficients - Vec3f normal(coefs[0], coefs[1], coefs[2]); - Vec3f up_vector(0.0f, 1.0f, 0.0f); // Just set as default + Vec3d normal(coefs[0], coefs[1], coefs[2]); + Vec3d up_vector(0.0, 1.0, 0.0); // Just set as default double push_distance = -coefs[3]/cv::norm(Vec3f(coefs.val)); - Vec3f u,v,n; - n = normalize(normal); - u = normalize(up_vector.cross(n)); - v = n.cross(u); + Vec3d n = normalize(normal); + Vec3d u = normalize(up_vector.cross(n)); + Vec3d v = n.cross(u); - vtkSmartPointer mat_trans = vtkSmartPointer::New(); - mat_trans->SetElement(0,0,u[0]); - mat_trans->SetElement(0,1,u[1]); - mat_trans->SetElement(0,2,u[2]); - mat_trans->SetElement(1,0,v[0]); - mat_trans->SetElement(1,1,v[1]); - mat_trans->SetElement(1,2,v[2]); - mat_trans->SetElement(2,0,n[0]); - mat_trans->SetElement(2,1,n[1]); - mat_trans->SetElement(2,2,n[2]); - // Inverse rotation (orthogonal, so just take transpose) - mat_trans->Transpose(); - mat_trans->SetElement(0,3,n[0] * push_distance); - mat_trans->SetElement(1,3,n[1] * push_distance); - mat_trans->SetElement(2,3,n[2] * push_distance); - mat_trans->SetElement(3,3,1); + Affine3d pose = makeTransformToGlobal(u, v, n, n * push_distance); vtkSmartPointer transform = vtkSmartPointer::New(); transform->PreMultiply(); - transform->SetMatrix(mat_trans); + transform->SetMatrix(vtkmatrix(pose.matrix)); vtkSmartPointer transform_filter = vtkSmartPointer::New(); transform_filter->SetTransform(transform); @@ -837,28 +815,11 @@ cv::viz::WImage3D::WImage3D(const Vec3f &position, const Vec3f &normal, const Ve plane->SetNormal(0.0, 0.0, 1.0); // Compute the transformation matrix for drawing the camera frame in a scene - Vec3f u,v,n; - n = normalize(normal); - u = normalize(up_vector.cross(n)); - v = n.cross(u); + Vec3d n = normalize(normal); + Vec3d u = normalize(up_vector.cross(n)); + Vec3d v = n.cross(u); - vtkSmartPointer mat_trans = vtkSmartPointer::New(); - mat_trans->SetElement(0,0,u[0]); - mat_trans->SetElement(0,1,u[1]); - mat_trans->SetElement(0,2,u[2]); - mat_trans->SetElement(1,0,v[0]); - mat_trans->SetElement(1,1,v[1]); - mat_trans->SetElement(1,2,v[2]); - mat_trans->SetElement(2,0,n[0]); - mat_trans->SetElement(2,1,n[1]); - mat_trans->SetElement(2,2,n[2]); - // Inverse rotation (orthogonal, so just take transpose) - mat_trans->Transpose(); - // Then translate the coordinate frame to camera position - mat_trans->SetElement(0,3,position[0]); - mat_trans->SetElement(1,3,position[1]); - mat_trans->SetElement(2,3,position[2]); - mat_trans->SetElement(3,3,1); + Affine3d pose = makeTransformToGlobal(u, v, n, position); // Apply the texture vtkSmartPointer texture = vtkSmartPointer::New(); @@ -870,7 +831,7 @@ cv::viz::WImage3D::WImage3D(const Vec3f &position, const Vec3f &normal, const Ve // Apply the transform after texture mapping vtkSmartPointer transform = vtkSmartPointer::New(); transform->PreMultiply(); - transform->SetMatrix(mat_trans); + transform->SetMatrix(vtkmatrix(pose)); transform->Scale(size.width, size.height, 1.0); vtkSmartPointer transform_filter = vtkSmartPointer::New(); From 406444037d9e03ed7a5136cc4fcf8d8a1df86ec0 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 18:18:06 +0400 Subject: [PATCH 141/295] refactored polyline --- modules/viz/src/shapes.cpp | 81 +++++++++---------------------- modules/viz/test/tests_simple.cpp | 12 +++++ 2 files changed, 36 insertions(+), 57 deletions(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 2088e7d40..b1ef3de5e 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -381,72 +381,39 @@ template<> cv::viz::WCoordinateSystem cv::viz::Widget::cast - static void copy(const Mat& source, Vec<_Tp, 3> *output, vtkSmartPointer polyLine) - { - int s_chs = source.channels(); + CV_Assert(_points.type() == CV_32FC3 || _points.type() == CV_32FC4 || _points.type() == CV_64FC3 || _points.type() == CV_64FC4); - for (int y = 0, id = 0; y < source.rows; ++y) - { - const _Tp* srow = source.ptr<_Tp>(y); - - for (int x = 0; x < source.cols; ++x, srow += s_chs, ++id) - { - *output++ = Vec<_Tp, 3>(srow); - polyLine->GetPointIds()->SetId(id,id); - } - } - } - }; -}}} - -cv::viz::WPolyLine::WPolyLine(InputArray _pointData, const Color &color) -{ - Mat pointData = _pointData.getMat(); - CV_Assert(pointData.type() == CV_32FC3 || pointData.type() == CV_32FC4 || pointData.type() == CV_64FC3 || pointData.type() == CV_64FC4); - vtkIdType nr_points = pointData.total(); + const float *fpoints = _points.getMat().ptr(); + const double *dpoints = _points.getMat().ptr(); + size_t total = _points.total(); + int s_chs = _points.channels(); vtkSmartPointer points = vtkSmartPointer::New(); - vtkSmartPointer polyData = vtkSmartPointer::New(); - vtkSmartPointer polyLine = vtkSmartPointer::New(); + points->SetDataType(_points.depth() == CV_32F ? VTK_FLOAT : VTK_DOUBLE); + points->SetNumberOfPoints(total); - if (pointData.depth() == CV_32F) - points->SetDataTypeToFloat(); - else - points->SetDataTypeToDouble(); + if (_points.depth() == CV_32F) + for(size_t i = 0; i < total; ++i, fpoints += s_chs) + points->SetPoint(i, fpoints); - points->SetNumberOfPoints(nr_points); - polyLine->GetPointIds()->SetNumberOfIds(nr_points); + if (_points.depth() == CV_64F) + for(size_t i = 0; i < total; ++i, dpoints += s_chs) + points->SetPoint(i, dpoints); - if (pointData.depth() == CV_32F) - { - // Get a pointer to the beginning of the data array - Vec3f *data_beg = vtkpoints_data(points); - PolyLineUtils::copy(pointData, data_beg, polyLine); - } - else if (pointData.depth() == CV_64F) - { - // Get a pointer to the beginning of the data array - Vec3d *data_beg = vtkpoints_data(points); - PolyLineUtils::copy(pointData, data_beg, polyLine); - } + vtkSmartPointer cell_array = vtkSmartPointer::New(); + cell_array->Allocate(cell_array->EstimateSize(1, total)); + cell_array->InsertNextCell(total); + for(size_t i = 0; i < total; ++i) + cell_array->InsertCellPoint(i); - vtkSmartPointer cells = vtkSmartPointer::New(); - cells->InsertNextCell(polyLine); - - polyData->SetPoints(points); - polyData->SetLines(cells); + vtkSmartPointer polydata = vtkSmartPointer::New(); + polydata->SetPoints(points); + polydata->SetLines(cell_array); vtkSmartPointer mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(polyData); -#else - mapper->SetInputData(polyData); -#endif + mapper->SetInputConnection(polydata->GetProducerPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -831,7 +798,7 @@ cv::viz::WImage3D::WImage3D(const Vec3f &position, const Vec3f &normal, const Ve // Apply the transform after texture mapping vtkSmartPointer transform = vtkSmartPointer::New(); transform->PreMultiply(); - transform->SetMatrix(vtkmatrix(pose)); + transform->SetMatrix(vtkmatrix(pose.matrix)); transform->Scale(size.width, size.height, 1.0); vtkSmartPointer transform_filter = vtkSmartPointer::New(); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index f311ff2b7..6f61a806c 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -130,6 +130,18 @@ TEST(Viz, DISABLED_show_mesh_random_colors) viz.spin(); } +TEST(Viz, DISABLED_show_polyline) +{ + Mat polyline(1, 32, CV_64FC3); + for(size_t i = 0; i < polyline.total(); ++i) + polyline.at(i) = Vec3d(i/16.0, cos(i * CV_PI/6), sin(i * CV_PI/6)); + + Viz3d viz("show_polyline"); + viz.showWidget("polyline", WPolyLine(Mat(polyline), Color::apricot())); + viz.showWidget("coosys", WCoordinateSystem()); + viz.spin(); +} + TEST(Viz, DISABLED_show_sampled_normals) { Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); From d26446542248d4d3442a761a46bcd77e36a8e45c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 21:13:15 +0400 Subject: [PATCH 142/295] more refactoring --- modules/viz/include/opencv2/viz/widgets.hpp | 4 +- modules/viz/src/precomp.hpp | 32 +++++++++++++- modules/viz/src/vizcore.cpp | 4 +- modules/viz/test/test_viz3d.cpp | 46 ++++++++++++++------- 4 files changed, 64 insertions(+), 22 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 2868880ec..b48795290 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -227,7 +227,7 @@ namespace cv class CV_EXPORTS WCoordinateSystem : public Widget3D { public: - WCoordinateSystem(float scale = 1.f); + WCoordinateSystem(double scale = 1.f); }; class CV_EXPORTS WGrid : public Widget3D @@ -263,7 +263,7 @@ namespace cv enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH }; //! Takes vector> and displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()); + WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectoryFrustums : public Widget3D diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 85977a800..b91e50c6e 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -172,10 +172,40 @@ namespace cv friend class Viz3d; }; - template bool isNan(const _Tp* data) + template inline bool isNan(const _Tp* data) { return isNan(data[0]) || isNan(data[1]) || isNan(data[2]); } + + inline vtkSmartPointer getPolyData(const Widget3D& widget) + { + vtkSmartPointer prop = WidgetAccessor::getProp(widget); + vtkSmartPointer mapper = vtkActor::SafeDownCast(prop)->GetMapper(); + return vtkPolyData::SafeDownCast(mapper->GetInput()); + } + + struct VtkUtils + { + template + static inline void SetInputData(vtkSmartPointer filter, vtkPolyData *polydata) + { + #if VTK_MAJOR_VERSION <= 5 + filter->SetInput(polydata); + #else + filter->SetInputData(polydata); + #endif + } + + template + static inline void AddInputData(vtkSmartPointer filter, vtkPolyData *polydata) + { + #if VTK_MAJOR_VERSION <= 5 + filter->AddInput(polydata); + #else + filter->AddInputData(polydata); + #endif + } + }; } } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index d01b947a4..ffb2d84f5 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -305,9 +305,7 @@ void cv::viz::writeTrajectory(InputArray _traj, const String& files_format, int void cv::viz::computeNormals(const Mesh3d& mesh, OutputArray _normals) { - vtkSmartPointer prop = WidgetAccessor::getProp(WMesh(mesh)); - vtkSmartPointer mapper = vtkActor::SafeDownCast(prop)->GetMapper(); - vtkSmartPointer polydata = vtkPolyData::SafeDownCast(mapper->GetInput()); + vtkSmartPointer polydata = getPolyData(WMesh(mesh)); vtkSmartPointer normal_generator = vtkSmartPointer::New(); #if VTK_MAJOR_VERSION <= 5 diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index ce0344f1e..6bc3622c6 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -45,37 +45,51 @@ using namespace cv; TEST(Viz_viz3d, develop) { - std::cout << std::string(cvtest::TS::ptr()->get_data_path()) + "dragon.ply" << std::endl; + cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); - cv::Mat cloud = cv::viz::readCloud(String(cvtest::TS::ptr()->get_data_path()) + "dragon.ply"); + //cv::viz::Mesh3d mesh = cv::viz::Mesh3d::load(get_dragon_ply_file_path()); - -// for(size_t i = 0; i < cloud.total(); ++i) -// { -// if (i % 15 == 0) -// continue; -// const static float qnan = std::numeric_limits::quiet_NaN(); -// cloud.at(i) = Vec3f(qnan, qnan, qnan); -// } + //theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); cv::viz::Viz3d viz("abc"); viz.setBackgroundColor(cv::viz::Color::mlab()); viz.showWidget("coo", cv::viz::WCoordinateSystem(0.1)); - cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0)); + +// double c = cos(CV_PI/6); +// std::vector pts; +// pts.push_back(Vec3d(0, 0.0, -1.0)); +// pts.push_back(Vec3d(1, c, -0.5)); +// pts.push_back(Vec3d(2, c, 0.5)); +// pts.push_back(Vec3d(3, 0.0, 1.0)); +// pts.push_back(Vec3d(4, -c, 0.5)); +// pts.push_back(Vec3d(5, -c, -0.5)); + +// viz.showWidget("pl", cv::viz::WPolyLine(Mat(pts), cv::viz::Color::green())); + + //viz.showWidget("pl", cv::viz::WPolyLine(cloud.colRange(0, 100), cv::viz::Color::green())); + //viz.spin(); + + //cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0)); //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); std::vector gt, es; cv::viz::readTrajectory(gt, "d:/Datasets/trajs/gt%05d.xml"); - cv::viz::readTrajectory(es, "d:/Datasets/trajs/es%05d.xml"); + //cv::viz::readTrajectory(es, "d:/Datasets/trajs/es%05d.xml"); + gt.resize(20); - viz.showWidget("gt", viz::WTrajectory(gt, viz::WTrajectory::PATH, 1.f, viz::Color::blue()), gt[0].inv()); - viz.showWidget("tr", viz::WTrajectory(es, viz::WTrajectory::PATH, 1.f, viz::Color::red()), gt[0].inv()); + Affine3d inv = gt[0].inv(); + for(size_t i = 0; i < gt.size(); ++i) + gt[i] = inv * gt[i]; - cv::RNG rng; - rng.fill(colors, cv::RNG::UNIFORM, 0, 255); + //viz.showWidget("gt", viz::WTrajectory(gt, viz::WTrajectory::PATH, 1.f, viz::Color::blue()), gt[0].inv()); + viz.showWidget("gt", viz::WTrajectory(gt, viz::WTrajectory::BOTH, 0.01f, viz::Color::blue())); + + //viz.showWidget("tr", viz::WTrajectory(es, viz::WTrajectory::PATH, 1.f, viz::Color::red()), gt[0].inv()); + + //theRNG().fill(colors, cv::RNG::UNIFORM, 0, 255); //viz.showWidget("c", cv::viz::WCloud(cloud, colors)); //viz.showWidget("c", cv::viz::WCloud(cloud, cv::viz::Color::bluberry())); From 56819eaf198ddcca5ebab5039676e84ac8f0250b Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 21:27:11 +0400 Subject: [PATCH 143/295] switched completer API to doubles, updated docs --- modules/viz/doc/widget.rst | 82 +++++++-------- modules/viz/include/opencv2/viz/widgets.hpp | 44 ++++---- modules/viz/src/clouds.cpp | 4 +- modules/viz/src/shapes.cpp | 109 ++++++++++---------- 4 files changed, 119 insertions(+), 120 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 159e4ba80..936cc5a9d 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -262,8 +262,8 @@ This 3D Widget defines a finite plane. :: class CV_EXPORTS WPlane : public Widget3D { public: - WPlane(const Vec4f& coefs, float size = 1.0, const Color &color = Color::white()); - WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.0, const Color &color = Color::white()); + WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()); + WPlane(const Vec4d& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()); private: /* hidden */ }; @@ -272,13 +272,13 @@ viz::WPlane::WPlane ------------------- Constructs a WPlane. -.. ocv:function:: WPlane(const Vec4f& coefs, float size = 1.0, const Color &color = Color::white()) +.. ocv:function:: WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()) :param coefs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. :param size: Size of the plane. :param color: :ocv:class:`Color` of the plane. -.. ocv:function:: WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.0, const Color &color = Color::white()) +.. ocv:function:: WPlane(const Vec4d& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()) :param coefs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. :param pt: Position of the plane. @@ -294,14 +294,14 @@ This 3D Widget defines a sphere. :: class CV_EXPORTS WSphere : public Widget3D { public: - WSphere(const cv::Point3f ¢er, float radius, int sphere_resolution = 10, const Color &color = Color::white()) + WSphere(const cv::Point3f ¢er, double radius, int sphere_resolution = 10, const Color &color = Color::white()) }; viz::WSphere::WSphere --------------------- Constructs a WSphere. -.. ocv:function:: WSphere(const cv::Point3f ¢er, float radius, int sphere_resolution = 10, const Color &color = Color::white()) +.. ocv:function:: WSphere(const cv::Point3f ¢er, double radius, int sphere_resolution = 10, const Color &color = Color::white()) :param center: Center of the sphere. :param radius: Radius of the sphere. @@ -317,14 +317,14 @@ This 3D Widget defines an arrow. :: class CV_EXPORTS WArrow : public Widget3D { public: - WArrow(const Point3f& pt1, const Point3f& pt2, float thickness = 0.03, const Color &color = Color::white()); + WArrow(const Point3f& pt1, const Point3f& pt2, double thickness = 0.03, const Color &color = Color::white()); }; viz::WArrow::WArrow ----------------------------- Constructs an WArrow. -.. ocv:function:: WArrow(const Point3f& pt1, const Point3f& pt2, float thickness = 0.03, const Color &color = Color::white()) +.. ocv:function:: WArrow(const Point3f& pt1, const Point3f& pt2, double thickness = 0.03, const Color &color = Color::white()) :param pt1: Start point of the arrow. :param pt2: End point of the arrow. @@ -342,14 +342,14 @@ This 3D Widget defines a circle. :: class CV_EXPORTS WCircle : public Widget3D { public: - WCircle(const Point3f& pt, float radius, float thickness = 0.01, const Color &color = Color::white()); + WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white()); }; viz::WCircle::WCircle ------------------------------- Constructs a WCircle. -.. ocv:function:: WCircle(const Point3f& pt, float radius, float thickness = 0.01, const Color &color = Color::white()) +.. ocv:function:: WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white()) :param pt: Center of the circle. :param radius: Radius of the circle. @@ -365,14 +365,14 @@ This 3D Widget defines a cylinder. :: class CV_EXPORTS WCylinder : public Widget3D { public: - WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides = 30, const Color &color = Color::white()); + WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()); }; viz::WCylinder::WCylinder ----------------------------------- Constructs a WCylinder. -.. ocv:function:: WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides = 30, const Color &color = Color::white()) +.. ocv:function:: WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()) :param pt_on_axis: A point on the axis of the cylinder. :param axis_direction: Direction of the axis of the cylinder. @@ -416,14 +416,14 @@ This 3D Widget represents a coordinate system. :: class CV_EXPORTS WCoordinateSystem : public Widget3D { public: - WCoordinateSystem(float scale = 1.0); + WCoordinateSystem(double scale = 1.0); }; viz::WCoordinateSystem::WCoordinateSystem --------------------------------------------------- Constructs a WCoordinateSystem. -.. ocv:function:: WCoordinateSystem(float scale = 1.0) +.. ocv:function:: WCoordinateSystem(double scale = 1.0) :param scale: Determines the size of the axes. @@ -463,7 +463,7 @@ This 3D Widget defines a grid. :: //! Creates grid at the origin WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); //! Creates grid based on the plane equation - WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); private: /* hidden */ }; @@ -478,7 +478,7 @@ Constructs a WGrid. :param spacing: Size of each column and row, respectively. :param color: :ocv:class:`Color` of the grid. -.. ocv:function: WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()) +.. ocv:function: WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()) :param coeffs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. :param dimensions: Number of columns and rows, respectively. @@ -494,7 +494,7 @@ This 3D Widget represents 3D text. The text always faces the camera. :: class CV_EXPORTS WText3D : public Widget3D { public: - WText3D(const String &text, const Point3f &position, float text_scale = 1.0, bool face_camera = true, const Color &color = Color::white()); + WText3D(const String &text, const Point3f &position, double text_scale = 1.0, bool face_camera = true, const Color &color = Color::white()); void setText(const String &text); String getText() const; @@ -504,7 +504,7 @@ viz::WText3D::WText3D ------------------------------- Constructs a WText3D. -.. ocv:function:: WText3D(const String &text, const Point3f &position, float text_scale = 1.0, bool face_camera = true, const Color &color = Color::white()) +.. ocv:function:: WText3D(const String &text, const Point3f &position, double text_scale = 1.0, bool face_camera = true, const Color &color = Color::white()) :param text: Text content of the widget. :param position: Position of the text. @@ -609,7 +609,7 @@ This 3D Widget represents an image in 3D space. :: //! Creates 3D image at the origin WImage3D(const Mat &image, const Size &size); //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(const Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size); + WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size); void setImage(const Mat &image); }; @@ -623,7 +623,7 @@ Constructs an WImage3D. :param image: BGR or Gray-Scale image. :param size: Size of the image. -.. ocv:function:: WImage3D(const Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size) +.. ocv:function:: WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size) :param position: Position of the image. :param normal: Normal of the plane that represents the image. @@ -649,15 +649,15 @@ This 3D Widget represents camera position in a scene by its axes or viewing frus { public: //! Creates camera coordinate frame (axes) at the origin - WCameraPosition(float scale = 1.0); + WCameraPosition(double scale = 1.0); //! Creates frustum based on the intrinsic marix K at the origin - WCameraPosition(const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Matx33d &K, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum based on the field of view at the origin - WCameraPosition(const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Matx33d &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Vec2d &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()); }; viz::WCameraPosition::WCameraPosition @@ -666,7 +666,7 @@ Constructs a WCameraPosition. - **Display camera coordinate frame.** - .. ocv:function:: WCameraPosition(float scale = 1.0) + .. ocv:function:: WCameraPosition(double scale = 1.0) Creates camera coordinate frame at the origin. @@ -676,7 +676,7 @@ Constructs a WCameraPosition. - **Display the viewing frustum.** - .. ocv:function:: WCameraPosition(const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Matx33d &K, double scale = 1.0, const Color &color = Color::white()) :param K: Intrinsic matrix of the camera. :param scale: Scale of the frustum. @@ -684,7 +684,7 @@ Constructs a WCameraPosition. Creates viewing frustum of the camera based on its intrinsic matrix K. - .. ocv:function:: WCameraPosition(const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()) :param fov: Field of view of the camera (horizontal, vertical). :param scale: Scale of the frustum. @@ -698,7 +698,7 @@ Constructs a WCameraPosition. - **Display image on the far plane of the viewing frustum.** - .. ocv:function:: WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Matx33d &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()) :param K: Intrinsic matrix of the camera. :param img: BGR or Gray-Scale image that is going to be displayed on the far plane of the frustum. @@ -707,7 +707,7 @@ Constructs a WCameraPosition. Creates viewing frustum of the camera based on its intrinsic matrix K, and displays image on the far end plane. - .. ocv:function:: WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Vec2d &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()) :param fov: Field of view of the camera (horizontal, vertical). :param img: BGR or Gray-Scale image that is going to be displayed on the far plane of the frustum. @@ -732,14 +732,14 @@ This 3D Widget represents a trajectory. :: enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white(),; + WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.f, const Color &color = Color::white(),; }; viz::WTrajectory::WTrajectory ----------------------------- Constructs a WTrajectory. -.. ocv:function:: WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, float scale = 1.f, const Color &color = Color::white()) +.. ocv:function:: WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.f, const Color &color = Color::white()) :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] :param display_mode: Display mode. This can be PATH, FRAMES, and BOTH. @@ -762,16 +762,16 @@ This 3D Widget represents a trajectory. :: { public: //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()); }; viz::WTrajectoryFrustums::WTrajectoryFrustums ----------------------------- Constructs a WTrajectoryFrustums. -.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) +.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param K: Intrinsic matrix of the camera. @@ -780,7 +780,7 @@ Constructs a WTrajectoryFrustums. Displays frustums at each pose of the trajectory. -.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) +.. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param fov: Field of view of the camera (horizontal, vertical). @@ -799,8 +799,8 @@ represent the direction from previous position to the current. :: class CV_EXPORTS WTrajectorySpheres : public Widget3D { public: - WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, - float init_sphere_radius = 0.021, sphere_radius = 0.007, + WTrajectorySpheres(const std::vector &path, double line_length = 0.05f, + double init_sphere_radius = 0.021, sphere_radius = 0.007, Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; @@ -808,7 +808,7 @@ viz::WTrajectorySpheres::WTrajectorySpheres ------------------------------------------- Constructs a WTrajectorySpheres. -.. ocv:function:: WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, float sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) +.. ocv:function:: WTrajectorySpheres(const std::vector &path, double line_length = 0.05f, double init_sphere_radius = 0.021, double sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) :param path: List of poses on a trajectory. :param line_length: Length of the lines. @@ -912,7 +912,7 @@ This 3D Widget represents normals of a point cloud. :: class CV_EXPORTS WCloudNormals : public Widget3D { public: - WCloudNormals(InputArray cloud, InputArray normals, int level = 100, float scale = 0.02f, const Color &color = Color::white()); + WCloudNormals(InputArray cloud, InputArray normals, int level = 100, double scale = 0.02f, const Color &color = Color::white()); private: /* hidden */ @@ -922,7 +922,7 @@ viz::WCloudNormals::WCloudNormals --------------------------------- Constructs a WCloudNormals. -.. ocv:function:: WCloudNormals(InputArray cloud, InputArray normals, int level = 100, float scale = 0.02f, const Color &color = Color::white()) +.. ocv:function:: WCloudNormals(InputArray cloud, InputArray normals, int level = 100, double scale = 0.02f, const Color &color = Color::white()) :param cloud: Point set which can be of type: ``CV_32FC3``, ``CV_32FC4``, ``CV_64FC3``, ``CV_64FC4``. :param normals: A set of normals that has to be of same type with cloud. diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index b48795290..8fedb0c2c 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -135,44 +135,44 @@ namespace cv class CV_EXPORTS WLine : public Widget3D { public: - WLine(const Point3f &pt1, const Point3f &pt2, const Color &color = Color::white()); + WLine(const Point3d &pt1, const Point3d &pt2, const Color &color = Color::white()); }; class CV_EXPORTS WPlane : public Widget3D { public: - WPlane(const Vec4f& coefs, float size = 1.f, const Color &color = Color::white()); - WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.f, const Color &color = Color::white()); + WPlane(const Vec4d& coefs, double size = 1.f, const Color &color = Color::white()); + WPlane(const Vec4d& coefs, const Point3d& pt, double size = 1.f, const Color &color = Color::white()); }; class CV_EXPORTS WSphere : public Widget3D { public: - WSphere(const cv::Point3f ¢er, float radius, int sphere_resolution = 10, const Color &color = Color::white()); + WSphere(const cv::Point3d ¢er, double radius, int sphere_resolution = 10, const Color &color = Color::white()); }; class CV_EXPORTS WArrow : public Widget3D { public: - WArrow(const Point3f& pt1, const Point3f& pt2, float thickness = 0.03f, const Color &color = Color::white()); + WArrow(const Point3d& pt1, const Point3d& pt2, double thickness = 0.03, const Color &color = Color::white()); }; class CV_EXPORTS WCircle : public Widget3D { public: - WCircle(const Point3f& pt, float radius, float thickness = 0.01f, const Color &color = Color::white()); + WCircle(const Point3d& pt, double radius, double thickness = 0.01, const Color &color = Color::white()); }; class CV_EXPORTS WCylinder : public Widget3D { public: - WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides = 30, const Color &color = Color::white()); + WCylinder(const Point3d& pt_on_axis, const Point3d& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()); }; class CV_EXPORTS WCube : public Widget3D { public: - WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame = true, const Color &color = Color::white()); + WCube(const Point3d& pt_min, const Point3d& pt_max, bool wire_frame = true, const Color &color = Color::white()); }; class CV_EXPORTS WPolyLine : public Widget3D @@ -196,7 +196,7 @@ namespace cv class CV_EXPORTS WText3D : public Widget3D { public: - WText3D(const String &text, const Point3f &position, float text_scale = 1.f, bool face_camera = true, const Color &color = Color::white()); + WText3D(const String &text, const Point3d &position, double text_scale = 1., bool face_camera = true, const Color &color = Color::white()); void setText(const String &text); String getText() const; @@ -216,7 +216,7 @@ namespace cv //! Creates 3D image at the origin WImage3D(const Mat &image, const Size &size); //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(const Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size); + WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size); void setImage(const Mat &image); }; @@ -234,24 +234,24 @@ namespace cv { public: //! Creates grid at the origin - WGrid(const Vec2i &dimensions, const Vec2f &spacing, const Color &color = Color::white()); + WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); //! Creates grid based on the plane equation - WGrid(const Vec4f &coeffs, const Vec2i &dimensions, const Vec2f &spacing, const Color &color = Color::white()); + WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); }; class CV_EXPORTS WCameraPosition : public Widget3D { public: //! Creates camera coordinate frame (axes) at the origin - WCameraPosition(float scale = 1.f); + WCameraPosition(double scale = 1.0); //! Creates frustum based on the intrinsic marix K at the origin - WCameraPosition(const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Matx33d &K, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum based on the field of view at the origin - WCameraPosition(const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Matx33d &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); + WCameraPosition(const Vec2d &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()); }; ///////////////////////////////////////////////////////////////////////////// @@ -270,16 +270,16 @@ namespace cv { public: //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1., const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); + WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale = 1., const Color &color = Color::white()); }; class CV_EXPORTS WTrajectorySpheres: public Widget3D { public: - WTrajectorySpheres(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021f, - float sphere_radius = 0.007f, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); + WTrajectorySpheres(const std::vector &path, double line_length = 0.05, double init_sphere_radius = 0.021, + double sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; ///////////////////////////////////////////////////////////////////////////// @@ -308,7 +308,7 @@ namespace cv class CV_EXPORTS WCloudNormals : public Widget3D { public: - WCloudNormals(InputArray cloud, InputArray normals, int level = 64, float scale = 0.1f, const Color &color = Color::white()); + WCloudNormals(InputArray cloud, InputArray normals, int level = 64, double scale = 0.1, const Color &color = Color::white()); }; class CV_EXPORTS WMesh : public Widget3D diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 3c28624f3..15e9d4a61 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -175,7 +175,7 @@ template<> cv::viz::WCloudCollection cv::viz::Widget::castInsertNextPoint(srow); points->InsertNextPoint(endp.val); diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index b1ef3de5e..8afe64957 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -55,7 +55,7 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// /// line widget implementation -cv::viz::WLine::WLine(const Point3f &pt1, const Point3f &pt2, const Color &color) +cv::viz::WLine::WLine(const Point3d &pt1, const Point3d &pt2, const Color &color) { vtkSmartPointer line = vtkSmartPointer::New(); line->SetPoint1(pt1.x, pt1.y, pt1.z); @@ -103,11 +103,11 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) +cv::viz::WPlane::WPlane(const Vec4d& coefs, double size, const Color &color) { vtkSmartPointer plane = vtkSmartPointer::New(); plane->SetNormal(coefs[0], coefs[1], coefs[2]); - double norm = cv::norm(Vec3f(coefs.val)); + double norm = cv::norm(Vec3d(coefs.val)); plane->Push(-coefs[3] / norm); Vec3d p_center; @@ -123,15 +123,15 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) setColor(color); } -cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, float size, const Color &color) +cv::viz::WPlane::WPlane(const Vec4d& coefs, const Point3d& pt, double size, const Color &color) { vtkSmartPointer plane = vtkSmartPointer::New(); - Point3f coefs3(coefs[0], coefs[1], coefs[2]); + Point3d coefs3(coefs[0], coefs[1], coefs[2]); double norm_sqr = 1.0 / coefs3.dot(coefs3); plane->SetNormal(coefs[0], coefs[1], coefs[2]); double t = coefs3.dot(pt) + coefs[3]; - Vec3f p_center = pt - coefs3 * t * norm_sqr; + Vec3d p_center = pt - coefs3 * t * norm_sqr; plane->SetCenter(p_center[0], p_center[1], p_center[2]); vtkSmartPointer mapper = vtkSmartPointer::New(); @@ -153,7 +153,7 @@ template<> cv::viz::WPlane cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// sphere widget implementation -cv::viz::WSphere::WSphere(const Point3f ¢er, float radius, int sphere_resolution, const Color &color) +cv::viz::WSphere::WSphere(const Point3d ¢er, double radius, int sphere_resolution, const Color &color) { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(radius); @@ -181,7 +181,7 @@ template<> cv::viz::WSphere cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// arrow widget implementation -cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, const Color &color) +cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness, const Color &color) { vtkSmartPointer arrowSource = vtkSmartPointer::New(); arrowSource->SetShaftRadius(thickness); @@ -231,7 +231,7 @@ template<> cv::viz::WArrow cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// circle widget implementation -cv::viz::WCircle::WCircle(const Point3f& pt, float radius, float thickness, const Color& color) +cv::viz::WCircle::WCircle(const Point3d& pt, double radius, double thickness, const Color& color) { vtkSmartPointer disk = vtkSmartPointer::New(); // Maybe the resolution should be lower e.g. 50 or 25 @@ -267,9 +267,9 @@ template<> cv::viz::WCircle cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// cylinder widget implementation -cv::viz::WCylinder::WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides, const Color &color) +cv::viz::WCylinder::WCylinder(const Point3d& pt_on_axis, const Point3d& axis_direction, double radius, int numsides, const Color &color) { - const Point3f pt2 = pt_on_axis + axis_direction; + const Point3d pt2 = pt_on_axis + axis_direction; vtkSmartPointer line = vtkSmartPointer::New(); line->SetPoint1(pt_on_axis.x, pt_on_axis.y, pt_on_axis.z); line->SetPoint2(pt2.x, pt2.y, pt2.z); @@ -298,7 +298,7 @@ template<> cv::viz::WCylinder cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// cylinder widget implementation -cv::viz::WCube::WCube(const Point3f& pt_min, const Point3f& pt_max, bool wire_frame, const Color &color) +cv::viz::WCube::WCube(const Point3d& pt_min, const Point3d& pt_max, bool wire_frame, const Color &color) { vtkSmartPointer mapper = vtkSmartPointer::New(); if (wire_frame) @@ -330,7 +330,7 @@ template<> cv::viz::WCube cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// coordinate system widget implementation -cv::viz::WCoordinateSystem::WCoordinateSystem(float scale) +cv::viz::WCoordinateSystem::WCoordinateSystem(double scale) { vtkSmartPointer axes = vtkSmartPointer::New(); axes->SetOrigin(0, 0, 0); @@ -461,7 +461,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2f &spacing, const Color &color) +cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color) { vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); @@ -479,14 +479,14 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2f &spacing, const Color setColor(color); } -cv::viz::WGrid::WGrid(const Vec4f &coefs, const Vec2i &dimensions, const Vec2f &spacing, const Color &color) +cv::viz::WGrid::WGrid(const Vec4d &coefs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color) { vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); // Estimate the transform to set the normal based on the coefficients Vec3d normal(coefs[0], coefs[1], coefs[2]); Vec3d up_vector(0.0, 1.0, 0.0); // Just set as default - double push_distance = -coefs[3]/cv::norm(Vec3f(coefs.val)); + double push_distance = -coefs[3]/cv::norm(Vec3d(coefs.val)); Vec3d n = normalize(normal); Vec3d u = normalize(up_vector.cross(n)); Vec3d v = n.cross(u); @@ -525,7 +525,7 @@ template<> cv::viz::WGrid cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// text3D widget implementation -cv::viz::WText3D::WText3D(const String &text, const Point3f &position, float text_scale, bool face_camera, const Color &color) +cv::viz::WText3D::WText3D(const String &text, const Point3d &position, double text_scale, bool face_camera, const Color &color) { vtkSmartPointer textSource = vtkSmartPointer::New(); textSource->SetText(text.c_str()); @@ -759,7 +759,7 @@ cv::viz::WImage3D::WImage3D(const Mat &image, const Size &size) WidgetAccessor::setProp(*this, actor); } -cv::viz::WImage3D::WImage3D(const Vec3f &position, const Vec3f &normal, const Vec3f &up_vector, const Mat &image, const Size &size) +cv::viz::WImage3D::WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size) { CV_Assert(!image.empty() && image.depth() == CV_8U); @@ -857,7 +857,7 @@ namespace cv { namespace viz { namespace { struct CameraPositionUtils { - static void projectImage(float fovy, float far_end_height, const Mat &image, + static void projectImage(double fovy, double far_end_height, const Mat &image, double scale, const Color &color, vtkSmartPointer actor) { // Create a camera @@ -950,7 +950,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WCameraPosition::WCameraPosition(float scale) +cv::viz::WCameraPosition::WCameraPosition(double scale) { vtkSmartPointer axes = vtkSmartPointer::New(); axes->SetOrigin(0, 0, 0); @@ -992,20 +992,20 @@ cv::viz::WCameraPosition::WCameraPosition(float scale) WidgetAccessor::setProp(*this, actor); } -cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, float scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); - float f_x = K(0,0); - float f_y = K(1,1); - float c_y = K(1,2); - float aspect_ratio = f_y / f_x; + double f_x = K(0,0); + double f_y = K(1,1); + double c_y = K(1,2); + double aspect_ratio = f_y / f_x; // Assuming that this is an ideal camera (c_y and c_x are at the center of the image) - float fovy = 2.0f * atan2(c_y,f_y) * 180 / CV_PI; + double fovy = 2.0 * atan2(c_y,f_y) * 180 / CV_PI; camera->SetViewAngle(fovy); - camera->SetPosition(0.0,0.0,0.0); - camera->SetViewUp(0.0,1.0,0.0); - camera->SetFocalPoint(0.0,0.0,1.0); + camera->SetPosition(0.0, 0.0, 0.0); + camera->SetViewUp(0.0, 1.0, 0.0); + camera->SetFocalPoint(0.0, 0.0, 1.0); camera->SetClippingRange(0.01, scale); double planesArray[24]; @@ -1014,8 +1014,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, float scale, const C vtkSmartPointer planes = vtkSmartPointer::New(); planes->SetFrustumPlanes(planesArray); - vtkSmartPointer frustumSource = - vtkSmartPointer::New(); + vtkSmartPointer frustumSource = vtkSmartPointer::New(); frustumSource->SetPlanes(planes); frustumSource->Update(); @@ -1034,14 +1033,14 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, float scale, const C } -cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, float scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); camera->SetViewAngle(fov[1] * 180 / CV_PI); // Vertical field of view - camera->SetPosition(0.0,0.0,0.0); - camera->SetViewUp(0.0,1.0,0.0); - camera->SetFocalPoint(0.0,0.0,1.0); + camera->SetPosition(0.0, 0.0, 0.0); + camera->SetViewUp(0.0, 1.0, 0.0); + camera->SetFocalPoint(0.0, 0.0, 1.0); camera->SetClippingRange(0.01, scale); double aspect_ratio = tan(fov[0] * 0.5) / tan(fov[1] * 0.5); @@ -1072,25 +1071,25 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, float scale, const C setColor(color); } -cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, const Mat &image, float scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, const Mat &image, double scale, const Color &color) { CV_Assert(!image.empty() && image.depth() == CV_8U); - float f_y = K(1,1); - float c_y = K(1,2); + double f_y = K(1,1); + double c_y = K(1,2); // Assuming that this is an ideal camera (c_y and c_x are at the center of the image) - float fovy = 2.0f * atan2(c_y,f_y) * 180.0f / CV_PI; - float far_end_height = 2.0f * c_y * scale / f_y; + double fovy = 2.0 * atan2(c_y,f_y) * 180.0 / CV_PI; + double far_end_height = 2.0f * c_y * scale / f_y; vtkSmartPointer actor = vtkSmartPointer::New(); CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); WidgetAccessor::setProp(*this, actor); } -cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, const Mat &image, float scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, const Mat &image, double scale, const Color &color) { CV_Assert(!image.empty() && image.depth() == CV_8U); - float fovy = fov[1] * 180.0f / CV_PI; - float far_end_height = 2.0 * scale * tan(fov[1] * 0.5); + double fovy = fov[1] * 180.0 / CV_PI; + double far_end_height = 2.0 * scale * tan(fov[1] * 0.5); vtkSmartPointer actor = vtkSmartPointer::New(); CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); @@ -1141,7 +1140,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, float scale, const Color &color) +cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double scale, const Color &color) { CV_Assert(_path.kind() == _InputArray::STD_VECTOR || _path.kind() == _InputArray::MAT); CV_Assert(_path.type() == CV_32FC(16) || _path.type() == CV_64FC(16)); @@ -1259,15 +1258,15 @@ template<> cv::viz::WTrajectory cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// WTrajectoryFrustums widget implementation -cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Matx33f &K, float scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); - float f_x = K(0,0); - float f_y = K(1,1); - float c_y = K(1,2); - float aspect_ratio = f_y / f_x; + double f_x = K(0,0); + double f_y = K(1,1); + double c_y = K(1,2); + double aspect_ratio = f_y / f_x; // Assuming that this is an ideal camera (c_y and c_x are at the center of the image) - float fovy = 2.0f * atan2(c_y,f_y) * 180 / CV_PI; + double fovy = 2.0 * atan2(c_y,f_y) * 180 / CV_PI; camera->SetViewAngle(fovy); camera->SetPosition(0.0,0.0,0.0); @@ -1303,14 +1302,14 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &p setColor(color); } -cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Vec2f &fov, float scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); camera->SetViewAngle(fov[1] * 180 / CV_PI); // Vertical field of view - camera->SetPosition(0.0,0.0,0.0); - camera->SetViewUp(0.0,1.0,0.0); - camera->SetFocalPoint(0.0,0.0,1.0); + camera->SetPosition(0.0, 0.0, 0.0); + camera->SetViewUp(0.0, 1.0, 0.0); + camera->SetFocalPoint(0.0, 0.0, 1.0); camera->SetClippingRange(0.01, scale); double aspect_ratio = tan(fov[0] * 0.5) / tan(fov[1] * 0.5); @@ -1352,7 +1351,7 @@ template<> cv::viz::WTrajectoryFrustums cv::viz::Widget::cast &path, float line_length, float init_sphere_radius, float sphere_radius, +cv::viz::WTrajectorySpheres::WTrajectorySpheres(const std::vector &path, double line_length, double init_sphere_radius, double sphere_radius, const Color &line_color, const Color &sphere_color) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); From e94ee94be329e40bdd32cf08e2748529838d45f6 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 21:28:29 +0400 Subject: [PATCH 144/295] refactored WCoordinateSystem widget --- modules/viz/src/shapes.cpp | 42 +++++++++++++++----------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 8afe64957..c8395c664 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -335,36 +335,28 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(double scale) vtkSmartPointer axes = vtkSmartPointer::New(); axes->SetOrigin(0, 0, 0); axes->SetScaleFactor(scale); - - vtkSmartPointer axes_colors = vtkSmartPointer::New(); - axes_colors->Allocate(6); - axes_colors->InsertNextValue(0.0); - axes_colors->InsertNextValue(0.0); - axes_colors->InsertNextValue(0.5); - axes_colors->InsertNextValue(0.5); - axes_colors->InsertNextValue(1.0); - axes_colors->InsertNextValue(1.0); - - vtkSmartPointer axes_data = axes->GetOutput(); -#if VTK_MAJOR_VERSION <= 5 - axes_data->Update(); -#else axes->Update(); -#endif - axes_data->GetPointData()->SetScalars(axes_colors); - vtkSmartPointer axes_tubes = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - axes_tubes->SetInput(axes_data); -#else - axes_tubes->SetInputData(axes_data); -#endif - axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); - axes_tubes->SetNumberOfSides(6); + vtkSmartPointer colors = vtkSmartPointer::New(); + colors->SetNumberOfComponents(3); + colors->InsertNextTuple3(255, 0, 0); + colors->InsertNextTuple3(255, 0, 0); + colors->InsertNextTuple3(0, 255, 0); + colors->InsertNextTuple3(0, 255, 0); + colors->InsertNextTuple3(0, 0, 255); + colors->InsertNextTuple3(0, 0, 255); + + vtkSmartPointer polydata = axes->GetOutput(); + polydata->GetPointData()->SetScalars(colors); + + vtkSmartPointer tube_filter = vtkSmartPointer::New(); + VtkUtils::SetInputData(tube_filter, polydata); + tube_filter->SetRadius(axes->GetScaleFactor() / 50.0); + tube_filter->SetNumberOfSides(6); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUsePointData(); - mapper->SetInputConnection(axes_tubes->GetOutputPort()); + VtkUtils::SetInputData(mapper, tube_filter->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); From 771d9509a8dcf50b84ecd60c1340e49a4c62cf81 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 21:32:54 +0400 Subject: [PATCH 145/295] polyline now uses scalars for color data (for reuse by other widgets) --- modules/viz/src/shapes.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index c8395c664..67fa43cf7 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -400,18 +400,29 @@ cv::viz::WPolyLine::WPolyLine(InputArray _points, const Color &color) for(size_t i = 0; i < total; ++i) cell_array->InsertCellPoint(i); + Vec3b rgb = Vec3d(color[2], color[1], color[0]); + Vec3b* color_data = new Vec3b[total]; + std::fill(color_data, color_data + total, rgb); + + vtkSmartPointer scalars = vtkSmartPointer::New(); + scalars->SetName("Colors"); + scalars->SetNumberOfComponents(3); + scalars->SetNumberOfTuples(total); + scalars->SetArray(color_data->val, total * 3, 0); + vtkSmartPointer polydata = vtkSmartPointer::New(); polydata->SetPoints(points); polydata->SetLines(cell_array); + polydata->GetPointData()->SetScalars(scalars); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection(polydata->GetProducerPort()); + mapper->SetScalarRange(0, 255); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } template<> cv::viz::WPolyLine cv::viz::Widget::cast() From a8556134aef1c1c9a5ea90b3d97eaf20dd67b77f Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 21:37:33 +0400 Subject: [PATCH 146/295] refactored simple trajectory to use TensorGlyph --- modules/viz/src/precomp.hpp | 5 +- modules/viz/src/shapes.cpp | 113 ++++---------------- modules/viz/src/vtk/vtkCloudMatSink.h | 3 + modules/viz/src/vtk/vtkCloudMatSource.h | 2 +- modules/viz/src/vtk/vtkTrajectorySource.cpp | 112 +++++++++++++++++++ modules/viz/src/vtk/vtkTrajectorySource.h | 84 +++++++++++++++ 6 files changed, 226 insertions(+), 93 deletions(-) create mode 100644 modules/viz/src/vtk/vtkTrajectorySource.cpp create mode 100644 modules/viz/src/vtk/vtkTrajectorySource.h diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index b91e50c6e..d57e677c5 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -132,10 +132,11 @@ # include /* unlink */ #endif -#include -#include #include #include +#include +#include +#include #include #include diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 67fa43cf7..cd649ad23 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1145,106 +1145,39 @@ namespace cv { namespace viz { namespace cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double scale, const Color &color) { - CV_Assert(_path.kind() == _InputArray::STD_VECTOR || _path.kind() == _InputArray::MAT); - CV_Assert(_path.type() == CV_32FC(16) || _path.type() == CV_64FC(16)); - - const Affine3d* dpath = _path.getMat().ptr(), *dend = dpath + _path.total(); - const Affine3f* fpath = _path.getMat().ptr(), *fend = fpath + _path.total(); - std::vector path; - - if (_path.depth() == CV_32F) - path.assign(fpath, fend); - - if (_path.depth() == CV_64F) - path.assign(dpath, dend); - vtkSmartPointer appendFilter = vtkSmartPointer::New(); // Bitwise and with 3 in order to limit the domain to 2 bits - if ((~display_mode & 3) ^ WTrajectory::PATH) + if (display_mode & WTrajectory::PATH) { - // Create a poly line along the path - vtkIdType nr_points = path.size(); - - vtkSmartPointer points = vtkSmartPointer::New(); - points->SetDataTypeToFloat(); - points->SetNumberOfPoints(nr_points); - - vtkSmartPointer polyData = vtkSmartPointer::New(); - vtkSmartPointer polyLine = vtkSmartPointer::New(); - polyLine->GetPointIds()->SetNumberOfIds(nr_points); - - Vec3f *data_beg = vtkpoints_data(points); - - for (vtkIdType i = 0; i < nr_points; ++i) - { - Vec3f cam_pose = path[i].translation(); - *data_beg++ = cam_pose; - polyLine->GetPointIds()->SetId(i,i); - } - - vtkSmartPointer cells = vtkSmartPointer::New(); - cells->InsertNextCell(polyLine); - - polyData->SetPoints(points); - polyData->SetLines(cells); - - // Set the color for polyData - vtkSmartPointer colors = vtkSmartPointer::New(); - colors->SetNumberOfComponents(3); - colors->SetNumberOfTuples(nr_points); - colors->FillComponent(0, color[2]); - colors->FillComponent(1, color[1]); - colors->FillComponent(2, color[0]); - - polyData->GetPointData()->SetScalars(colors); -#if VTK_MAJOR_VERSION <= 5 - appendFilter->AddInputConnection(polyData->GetProducerPort()); -#else - appendFilter->AddInputData(polyData); -#endif + Mat points = vtkTrajectorySource::ExtractPoints(_path); + vtkSmartPointer polydata = getPolyData(WPolyLine(points, color)); + appendFilter->AddInputConnection(polydata->GetProducerPort()); } - if ((~display_mode & 3) ^ WTrajectory::FRAMES) + vtkSmartPointer tensor_glyph; + if (display_mode & WTrajectory::FRAMES) { - // Create frames and transform along the path - vtkSmartPointer axes = vtkSmartPointer::New(); - axes->SetOrigin(0, 0, 0); - axes->SetScaleFactor(scale); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetTrajectory(_path); - vtkSmartPointer axes_colors = vtkSmartPointer::New(); - axes_colors->SetNumberOfComponents(3); - axes_colors->InsertNextTuple3(255,0,0); - axes_colors->InsertNextTuple3(255,0,0); - axes_colors->InsertNextTuple3(0,255,0); - axes_colors->InsertNextTuple3(0,255,0); - axes_colors->InsertNextTuple3(0,0,255); - axes_colors->InsertNextTuple3(0,0,255); + vtkSmartPointer glyph = getPolyData(WCoordinateSystem(scale)); - vtkSmartPointer axes_data = axes->GetOutput(); -#if VTK_MAJOR_VERSION <= 5 - axes_data->Update(); -#else - axes->Update(); -#endif - axes_data->GetPointData()->SetScalars(axes_colors); + tensor_glyph = vtkSmartPointer::New(); + tensor_glyph->SetInputConnection(source->GetOutputPort()); + tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); + tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues + tensor_glyph->ThreeGlyphsOff(); + tensor_glyph->SymmetricOff(); + tensor_glyph->ColorGlyphsOff(); - vtkSmartPointer axes_tubes = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - axes_tubes->SetInput(axes_data); -#else - axes_tubes->SetInputData(axes_data); -#endif - axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); - axes_tubes->SetNumberOfSides(6); - axes_tubes->Update(); - - TrajectoryUtils::applyPath(axes_tubes->GetOutput(), appendFilter, path); + appendFilter->AddInputConnection(tensor_glyph->GetOutputPort()); } vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, appendFilter->GetOutput()); mapper->SetScalarModeToUsePointData(); - mapper->SetInputConnection(appendFilter->GetOutputPort()); + mapper->SetScalarRange(0, 255); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1269,12 +1202,12 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &p double c_y = K(1,2); double aspect_ratio = f_y / f_x; // Assuming that this is an ideal camera (c_y and c_x are at the center of the image) - double fovy = 2.0 * atan2(c_y,f_y) * 180 / CV_PI; + double fovy = 2.0 * atan2(c_y, f_y) * 180 / CV_PI; camera->SetViewAngle(fovy); - camera->SetPosition(0.0,0.0,0.0); - camera->SetViewUp(0.0,1.0,0.0); - camera->SetFocalPoint(0.0,0.0,1.0); + camera->SetPosition(0.0, 0.0, 0.0); + camera->SetViewUp(0.0, 1.0, 0.0); + camera->SetFocalPoint(0.0, 0.0, 1.0); camera->SetClippingRange(0.01, scale); double planesArray[24]; diff --git a/modules/viz/src/vtk/vtkCloudMatSink.h b/modules/viz/src/vtk/vtkCloudMatSink.h index e4a55f078..1d299f47c 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.h +++ b/modules/viz/src/vtk/vtkCloudMatSink.h @@ -45,6 +45,9 @@ #ifndef __vtkCloudMatSink_h #define __vtkCloudMatSink_h +#include +#include + namespace cv { namespace viz diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index a1d854c32..00e6adf1e 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -45,7 +45,7 @@ #ifndef __vtkCloudMatSource_h #define __vtkCloudMatSource_h -#include +#include #include #include #include diff --git a/modules/viz/src/vtk/vtkTrajectorySource.cpp b/modules/viz/src/vtk/vtkTrajectorySource.cpp new file mode 100644 index 000000000..151020881 --- /dev/null +++ b/modules/viz/src/vtk/vtkTrajectorySource.cpp @@ -0,0 +1,112 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkTrajectorySource); +}} + +cv::viz::vtkTrajectorySource::vtkTrajectorySource() { SetNumberOfInputPorts(0); } +cv::viz::vtkTrajectorySource::~vtkTrajectorySource() {} + +void cv::viz::vtkTrajectorySource::SetTrajectory(InputArray _traj) +{ + CV_Assert(_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT); + CV_Assert(_traj.type() == CV_32FC(16) || _traj.type() == CV_64FC(16)); + + Mat traj; + _traj.getMat().convertTo(traj, CV_64F); + const Affine3d* dpath = _traj.getMat().ptr(); + + size_t total = _traj.total(); + + points = vtkSmartPointer::New(); + points->SetDataType(VTK_DOUBLE); + points->SetNumberOfPoints(total); + + tensors = vtkSmartPointer::New(); + tensors->SetNumberOfComponents(9); + tensors->SetNumberOfTuples(total); + + for(size_t i = 0; i < total; ++i, ++dpath) + { + Matx33d R = dpath->rotation().t(); // transposed because of + tensors->SetTuple(i, R.val); // column major order + + Vec3d p = dpath->translation(); + points->SetPoint(i, p.val); + } +} + + +cv::Mat cv::viz::vtkTrajectorySource::ExtractPoints(InputArray _traj) +{ + CV_Assert(_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT); + CV_Assert(_traj.type() == CV_32FC(16) || _traj.type() == CV_64FC(16)); + + Mat points(1, _traj.total(), CV_MAKETYPE(_traj.depth(), 3)); + const Affine3d* dpath = _traj.getMat().ptr(); + const Affine3f* fpath = _traj.getMat().ptr(); + + if (_traj.depth() == CV_32F) + for(int i = 0; i < points.cols; ++i) + points.at(i) = fpath[i].translation(); + + if (_traj.depth() == CV_64F) + for(int i = 0; i < points.cols; ++i) + points.at(i) = dpath[i].translation(); + + return points; +} + +int cv::viz::vtkTrajectorySource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + output->SetPoints(points); + output->GetPointData()->SetTensors(tensors); + return 1; +} diff --git a/modules/viz/src/vtk/vtkTrajectorySource.h b/modules/viz/src/vtk/vtkTrajectorySource.h new file mode 100644 index 000000000..918250965 --- /dev/null +++ b/modules/viz/src/vtk/vtkTrajectorySource.h @@ -0,0 +1,84 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#ifndef __vtkTrajectorySource_h +#define __vtkTrajectorySource_h + +#include +#include +#include +#include +#include + +namespace cv +{ + namespace viz + { + class vtkTrajectorySource : public vtkPolyDataAlgorithm + { + public: + static vtkTrajectorySource *New(); + vtkTypeMacro(vtkTrajectorySource,vtkPolyDataAlgorithm); + + virtual void SetTrajectory(InputArray trajectory); + + static Mat ExtractPoints(InputArray trajectory); + + protected: + vtkTrajectorySource(); + ~vtkTrajectorySource(); + + vtkSmartPointer points; + vtkSmartPointer tensors; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + private: + vtkTrajectorySource(const vtkTrajectorySource&); // Not implemented. + void operator=(const vtkTrajectorySource&); // Not implemented. + + }; + } +} + +#endif From 45879fb9db59701f9f57e25224860a70ee05b1a6 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 21:48:32 +0400 Subject: [PATCH 147/295] more refactoring --- modules/viz/src/precomp.hpp | 18 ++++++++-- modules/viz/src/shapes.cpp | 69 ++++++------------------------------- 2 files changed, 27 insertions(+), 60 deletions(-) diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index d57e677c5..155612724 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -188,7 +188,7 @@ namespace cv struct VtkUtils { template - static inline void SetInputData(vtkSmartPointer filter, vtkPolyData *polydata) + static void SetInputData(vtkSmartPointer filter, vtkPolyData *polydata) { #if VTK_MAJOR_VERSION <= 5 filter->SetInput(polydata); @@ -198,7 +198,7 @@ namespace cv } template - static inline void AddInputData(vtkSmartPointer filter, vtkPolyData *polydata) + static void AddInputData(vtkSmartPointer filter, vtkPolyData *polydata) { #if VTK_MAJOR_VERSION <= 5 filter->AddInput(polydata); @@ -206,6 +206,20 @@ namespace cv filter->AddInputData(polydata); #endif } + + static vtkSmartPointer FillScalars(size_t size, const Color& color) + { + Vec3b rgb = Vec3d(color[2], color[1], color[0]); + Vec3b* color_data = new Vec3b[size]; + std::fill(color_data, color_data + size, rgb); + + vtkSmartPointer scalars = vtkSmartPointer::New(); + scalars->SetName("Colors"); + scalars->SetNumberOfComponents(3); + scalars->SetNumberOfTuples(size); + scalars->SetArray(color_data->val, size * 3, 0); + return scalars; + } }; } } diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index cd649ad23..a4401869e 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -400,15 +400,7 @@ cv::viz::WPolyLine::WPolyLine(InputArray _points, const Color &color) for(size_t i = 0; i < total; ++i) cell_array->InsertCellPoint(i); - Vec3b rgb = Vec3d(color[2], color[1], color[0]); - Vec3b* color_data = new Vec3b[total]; - std::fill(color_data, color_data + total, rgb); - - vtkSmartPointer scalars = vtkSmartPointer::New(); - scalars->SetName("Colors"); - scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(total); - scalars->SetArray(color_data->val, total * 3, 0); + vtkSmartPointer scalars = VtkUtils::FillScalars(total, color); vtkSmartPointer polydata = vtkSmartPointer::New(); polydata->SetPoints(points); @@ -913,9 +905,9 @@ namespace cv { namespace viz { namespace // Create frustum camera->SetViewAngle(fovy); - camera->SetPosition(0.0,0.0,0.0); - camera->SetViewUp(0.0,1.0,0.0); - camera->SetFocalPoint(0.0,0.0,1.0); + camera->SetPosition(0.0, 0.0, 0.0); + camera->SetViewUp(0.0, 1.0, 0.0); + camera->SetFocalPoint(0.0, 0.0, 1.0); camera->SetClippingRange(0.01, scale); double planesArray[24]; @@ -955,39 +947,10 @@ namespace cv { namespace viz { namespace cv::viz::WCameraPosition::WCameraPosition(double scale) { - vtkSmartPointer axes = vtkSmartPointer::New(); - axes->SetOrigin(0, 0, 0); - axes->SetScaleFactor(scale); - - vtkSmartPointer axes_colors = vtkSmartPointer::New(); - axes_colors->Allocate(6); - axes_colors->InsertNextValue(0.0); - axes_colors->InsertNextValue(0.0); - axes_colors->InsertNextValue(0.5); - axes_colors->InsertNextValue(0.5); - axes_colors->InsertNextValue(1.0); - axes_colors->InsertNextValue(1.0); - - vtkSmartPointer axes_data = axes->GetOutput(); -#if VTK_MAJOR_VERSION <= 5 - axes_data->Update(); -#else - axes->Update(); -#endif - axes_data->GetPointData()->SetScalars(axes_colors); - - vtkSmartPointer axes_tubes = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - axes_tubes->SetInput(axes_data); -#else - axes_tubes->SetInputData(axes_data); -#endif - axes_tubes->SetRadius(axes->GetScaleFactor() / 50.0); - axes_tubes->SetNumberOfSides(6); - vtkSmartPointer mapper = vtkSmartPointer::New(); + + VtkUtils::SetInputData(mapper, getPolyData(WCoordinateSystem(scale))); mapper->SetScalarModeToUsePointData(); - mapper->SetInputConnection(axes_tubes->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1035,7 +998,6 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const setColor(color); } - cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); @@ -1299,28 +1261,19 @@ cv::viz::WTrajectorySpheres::WTrajectorySpheres(const std::vector &pat line_scalars->InsertNextTuple3(line_color[2], line_color[1], line_color[0]); // Create color array for sphere - vtkSphereSource * dummy_sphere = vtkSphereSource::New(); + vtkSmartPointer dummy_sphere = vtkSmartPointer::New(); // Create the array for big sphere dummy_sphere->SetRadius(init_sphere_radius); dummy_sphere->Update(); vtkIdType nr_points = dummy_sphere->GetOutput()->GetNumberOfCells(); - vtkSmartPointer sphere_scalars_init = vtkSmartPointer::New(); - sphere_scalars_init->SetNumberOfComponents(3); - sphere_scalars_init->SetNumberOfTuples(nr_points); - sphere_scalars_init->FillComponent(0, sphere_color[2]); - sphere_scalars_init->FillComponent(1, sphere_color[1]); - sphere_scalars_init->FillComponent(2, sphere_color[0]); + vtkSmartPointer sphere_scalars_init = VtkUtils::FillScalars(nr_points, sphere_color); + // Create the array for small sphere dummy_sphere->SetRadius(sphere_radius); dummy_sphere->Update(); nr_points = dummy_sphere->GetOutput()->GetNumberOfCells(); - vtkSmartPointer sphere_scalars = vtkSmartPointer::New(); - sphere_scalars->SetNumberOfComponents(3); - sphere_scalars->SetNumberOfTuples(nr_points); - sphere_scalars->FillComponent(0, sphere_color[2]); - sphere_scalars->FillComponent(1, sphere_color[1]); - sphere_scalars->FillComponent(2, sphere_color[0]); - dummy_sphere->Delete(); + vtkSmartPointer sphere_scalars = VtkUtils::FillScalars(nr_points, sphere_color); + for (vtkIdType i = 0; i < nr_poses; ++i) { From 42dc90295dc6cc179939605cad170f5f957ba37a Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 22:21:42 +0400 Subject: [PATCH 148/295] refactored camera position - simplified frustum creation --- modules/viz/src/shapes.cpp | 94 ++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 54 deletions(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index a4401869e..df383337c 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -942,6 +942,32 @@ namespace cv { namespace viz { namespace actor->SetMapper(planeMapper); actor->SetTexture(texture); } + + static vtkSmartPointer createFrustrum(double aspect_ratio, double fovy, double scale) + { + vtkSmartPointer camera = vtkSmartPointer::New(); + camera->SetViewAngle(fovy); + camera->SetPosition(0.0, 0.0, 0.0); + camera->SetViewUp(0.0, 1.0, 0.0); + camera->SetFocalPoint(0.0, 0.0, 1.0); + camera->SetClippingRange(0.01, scale); + + double planesArray[24]; + camera->GetFrustumPlanes(aspect_ratio, planesArray); + + vtkSmartPointer planes = vtkSmartPointer::New(); + planes->SetFrustumPlanes(planesArray); + + vtkSmartPointer frustumSource = vtkSmartPointer::New(); + frustumSource->SetPlanes(planes); + + vtkSmartPointer extract_edges = vtkSmartPointer::New(); + extract_edges->SetInputConnection(frustumSource->GetOutputPort()); + extract_edges->Update(); + + return extract_edges->GetOutput(); + } + }; }}} @@ -960,36 +986,16 @@ cv::viz::WCameraPosition::WCameraPosition(double scale) cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const Color &color) { - vtkSmartPointer camera = vtkSmartPointer::New(); - double f_x = K(0,0); - double f_y = K(1,1); - double c_y = K(1,2); - double aspect_ratio = f_y / f_x; + double f_x = K(0,0), f_y = K(1,1), c_y = K(1,2); + // Assuming that this is an ideal camera (c_y and c_x are at the center of the image) - double fovy = 2.0 * atan2(c_y,f_y) * 180 / CV_PI; + double fovy = 2.0 * atan2(c_y, f_y) * 180 / CV_PI; + double aspect_ratio = f_y / f_x; - camera->SetViewAngle(fovy); - camera->SetPosition(0.0, 0.0, 0.0); - camera->SetViewUp(0.0, 1.0, 0.0); - camera->SetFocalPoint(0.0, 0.0, 1.0); - camera->SetClippingRange(0.01, scale); - - double planesArray[24]; - camera->GetFrustumPlanes(aspect_ratio, planesArray); - - vtkSmartPointer planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); - - vtkSmartPointer frustumSource = vtkSmartPointer::New(); - frustumSource->SetPlanes(planes); - frustumSource->Update(); - - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(frustumSource->GetOutputPort()); - filter->Update(); + vtkSmartPointer polydata = CameraPositionUtils::createFrustrum(aspect_ratio, fovy, scale); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(filter->GetOutputPort()); + mapper->SetInputConnection(polydata->GetProducerPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1000,34 +1006,13 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const Color &color) { - vtkSmartPointer camera = vtkSmartPointer::New(); - - camera->SetViewAngle(fov[1] * 180 / CV_PI); // Vertical field of view - camera->SetPosition(0.0, 0.0, 0.0); - camera->SetViewUp(0.0, 1.0, 0.0); - camera->SetFocalPoint(0.0, 0.0, 1.0); - camera->SetClippingRange(0.01, scale); - double aspect_ratio = tan(fov[0] * 0.5) / tan(fov[1] * 0.5); + double fovy = fov[1] * 180 / CV_PI; - double planesArray[24]; - camera->GetFrustumPlanes(aspect_ratio, planesArray); - - vtkSmartPointer planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); - - vtkSmartPointer frustumSource = - vtkSmartPointer::New(); - frustumSource->SetPlanes(planes); - frustumSource->Update(); - - // Extract the edges so we have the grid - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(frustumSource->GetOutputPort()); - filter->Update(); + vtkSmartPointer polydata = CameraPositionUtils::createFrustrum(aspect_ratio, fovy, scale); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(filter->GetOutputPort()); + mapper->SetInputConnection(polydata->GetProducerPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1039,11 +1024,12 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, const Mat &image, double scale, const Color &color) { CV_Assert(!image.empty() && image.depth() == CV_8U); - double f_y = K(1,1); - double c_y = K(1,2); + + double f_y = K(1,1), c_y = K(1,2); + // Assuming that this is an ideal camera (c_y and c_x are at the center of the image) - double fovy = 2.0 * atan2(c_y,f_y) * 180.0 / CV_PI; - double far_end_height = 2.0f * c_y * scale / f_y; + double fovy = 2.0 * atan2(c_y, f_y) * 180.0 / CV_PI; + double far_end_height = 2.00 * c_y * scale / f_y; vtkSmartPointer actor = vtkSmartPointer::New(); CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); From 4833976a0c7fce492cf69a33f2815fcedd3a2890 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 22:35:21 +0400 Subject: [PATCH 149/295] refactored frustum trajectory to use glyphs --- modules/viz/doc/widget.rst | 8 +- modules/viz/include/opencv2/viz/widgets.hpp | 9 +- modules/viz/src/shapes.cpp | 122 +++++--------------- modules/viz/src/types.cpp | 2 +- 4 files changed, 39 insertions(+), 102 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 936cc5a9d..4119df083 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -762,9 +762,9 @@ This 3D Widget represents a trajectory. :: { public: //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white()); + WTrajectoryFrustums(InputArray path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()); + WTrajectoryFrustums(InputArray path, const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()); }; viz::WTrajectoryFrustums::WTrajectoryFrustums @@ -773,7 +773,7 @@ Constructs a WTrajectoryFrustums. .. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white()) - :param path: List of poses on a trajectory. + :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] :param K: Intrinsic matrix of the camera. :param scale: Scale of the frustums. :param color: :ocv:class:`Color` of the frustums. @@ -782,7 +782,7 @@ Constructs a WTrajectoryFrustums. .. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()) - :param path: List of poses on a trajectory. + :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] :param fov: Field of view of the camera (horizontal, vertical). :param scale: Scale of the frustums. :param color: :ocv:class:`Color` of the frustums. diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 8fedb0c2c..ad75199f8 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -269,10 +269,11 @@ namespace cv class CV_EXPORTS WTrajectoryFrustums : public Widget3D { public: - //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1., const Color &color = Color::white()); - //! Displays trajectory of the given path by frustums - WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale = 1., const Color &color = Color::white()); + //! Takes vector> and displays trajectory of the given path by frustums + WTrajectoryFrustums(InputArray path, const Matx33d &K, double scale = 1., const Color &color = Color::white()); + + //! Takes vector> and displays trajectory of the given path by frustums + WTrajectoryFrustums(InputArray path, const Vec2d &fov, double scale = 1., const Color &color = Color::white()); }; class CV_EXPORTS WTrajectorySpheres: public Widget3D diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index df383337c..c177a9b67 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1056,41 +1056,6 @@ template<> cv::viz::WCameraPosition cv::viz::Widget::cast poly_data, vtkSmartPointer append_filter, const std::vector &path) - { - vtkIdType nr_points = path.size(); - - for (vtkIdType i = 0; i < nr_points; ++i) - { - vtkSmartPointer new_data = vtkSmartPointer::New(); - new_data->DeepCopy(poly_data); - - // Transform the default coordinate frame - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - vtkSmartPointer mat_trans = vtkSmartPointer::New(); - mat_trans = vtkmatrix(path[i].matrix); - transform->SetMatrix(mat_trans); - - vtkSmartPointer filter = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - filter->SetInput(new_data); -#else - filter->SetInputData(new_data); -#endif - filter->SetTransform(transform); - filter->Update(); - - append_filter->AddInputConnection(filter->GetOutputPort()); - } - } - }; -}}} - cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double scale, const Color &color) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); @@ -1103,7 +1068,6 @@ cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double sca appendFilter->AddInputConnection(polydata->GetProducerPort()); } - vtkSmartPointer tensor_glyph; if (display_mode & WTrajectory::FRAMES) { vtkSmartPointer source = vtkSmartPointer::New(); @@ -1111,7 +1075,7 @@ cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double sca vtkSmartPointer glyph = getPolyData(WCoordinateSystem(scale)); - tensor_glyph = vtkSmartPointer::New(); + vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); tensor_glyph->SetInputConnection(source->GetOutputPort()); tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues @@ -1142,42 +1106,26 @@ template<> cv::viz::WTrajectory cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// WTrajectoryFrustums widget implementation -cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Matx33d &K, double scale, const Color &color) { - vtkSmartPointer camera = vtkSmartPointer::New(); - double f_x = K(0,0); - double f_y = K(1,1); - double c_y = K(1,2); - double aspect_ratio = f_y / f_x; - // Assuming that this is an ideal camera (c_y and c_x are at the center of the image) - double fovy = 2.0 * atan2(c_y, f_y) * 180 / CV_PI; + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetTrajectory(_path); - camera->SetViewAngle(fovy); - camera->SetPosition(0.0, 0.0, 0.0); - camera->SetViewUp(0.0, 1.0, 0.0); - camera->SetFocalPoint(0.0, 0.0, 1.0); - camera->SetClippingRange(0.01, scale); + vtkSmartPointer glyph = getPolyData(WCameraPosition(K, scale)); - double planesArray[24]; - camera->GetFrustumPlanes(aspect_ratio, planesArray); + vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); + tensor_glyph->SetInputConnection(source->GetOutputPort()); + tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); + tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues + tensor_glyph->ThreeGlyphsOff(); + tensor_glyph->SymmetricOff(); + tensor_glyph->ColorGlyphsOff(); + tensor_glyph->Update(); - vtkSmartPointer planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); - - vtkSmartPointer frustumSource = vtkSmartPointer::New(); - frustumSource->SetPlanes(planes); - frustumSource->Update(); - - // Extract the edges - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(frustumSource->GetOutputPort()); - filter->Update(); - - vtkSmartPointer appendFilter = vtkSmartPointer::New(); - TrajectoryUtils::applyPath(filter->GetOutput(), appendFilter, path); + vtkSmartPointer polydata = tensor_glyph->GetOutput(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(appendFilter->GetOutputPort()); + mapper->SetInputConnection(polydata->GetProducerPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1186,38 +1134,26 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &p setColor(color); } -cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(const std::vector &path, const Vec2d &fov, double scale, const Color &color) +cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d &fov, double scale, const Color &color) { - vtkSmartPointer camera = vtkSmartPointer::New(); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetTrajectory(_path); - camera->SetViewAngle(fov[1] * 180 / CV_PI); // Vertical field of view - camera->SetPosition(0.0, 0.0, 0.0); - camera->SetViewUp(0.0, 1.0, 0.0); - camera->SetFocalPoint(0.0, 0.0, 1.0); - camera->SetClippingRange(0.01, scale); + vtkSmartPointer glyph = getPolyData(WCameraPosition(fov, scale)); - double aspect_ratio = tan(fov[0] * 0.5) / tan(fov[1] * 0.5); + vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); + tensor_glyph->SetInputConnection(source->GetOutputPort()); + tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); + tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues + tensor_glyph->ThreeGlyphsOff(); + tensor_glyph->SymmetricOff(); + tensor_glyph->ColorGlyphsOff(); + tensor_glyph->Update(); - double planesArray[24]; - camera->GetFrustumPlanes(aspect_ratio, planesArray); - - vtkSmartPointer planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); - - vtkSmartPointer frustumSource = vtkSmartPointer::New(); - frustumSource->SetPlanes(planes); - frustumSource->Update(); - - // Extract the edges - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(frustumSource->GetOutputPort()); - filter->Update(); - - vtkSmartPointer appendFilter = vtkSmartPointer::New(); - TrajectoryUtils::applyPath(filter->GetOutput(), appendFilter, path); + vtkSmartPointer polydata = tensor_glyph->GetOutput(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(appendFilter->GetOutputPort()); + mapper->SetInputConnection(polydata->GetProducerPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index a6ea95ab5..d233e735d 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -245,6 +245,6 @@ void cv::viz::Camera::computeProjectionMatrix(Matx44d &proj) const cv::viz::Camera cv::viz::Camera::KinectCamera(const Size &window_size) { - Matx33d K(525.0, 0.0, 320.0, 0.0, 525.0, 240.0, 0.0, 0.0, 1.0) ; + Matx33d K(525.0, 0.0, 320.0, 0.0, 525.0, 240.0, 0.0, 0.0, 1.0); return Camera(K, window_size); } From 38c9fa4a92edbce45265ce92b3f79d87962defb4 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 7 Jan 2014 22:59:40 +0400 Subject: [PATCH 150/295] more refactoring --- modules/viz/src/shapes.cpp | 18 +----------------- modules/viz/src/vizcore.cpp | 27 +-------------------------- 2 files changed, 2 insertions(+), 43 deletions(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index c177a9b67..bcd6870df 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -45,14 +45,6 @@ #include "precomp.hpp" -namespace cv -{ - namespace viz - { - template Vec<_Tp, 3>* vtkpoints_data(vtkSmartPointer& points); - } -} - /////////////////////////////////////////////////////////////////////////////////////////////// /// line widget implementation cv::viz::WLine::WLine(const Point3d &pt1, const Point3d &pt2, const Color &color) @@ -350,7 +342,7 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(double scale) polydata->GetPointData()->SetScalars(colors); vtkSmartPointer tube_filter = vtkSmartPointer::New(); - VtkUtils::SetInputData(tube_filter, polydata); + tube_filter->SetInputConnection(polydata->GetProducerPort()); tube_filter->SetRadius(axes->GetScaleFactor() / 50.0); tube_filter->SetNumberOfSides(6); @@ -445,11 +437,7 @@ namespace cv { namespace viz { namespace // Extract the edges so we have the grid vtkSmartPointer filter = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 filter->SetInputConnection(grid->GetProducerPort()); -#else - filter->SetInputData(grid); -#endif filter->Update(); return filter->GetOutput(); } @@ -461,11 +449,7 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); vtkSmartPointer mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 mapper->SetInputConnection(grid->GetProducerPort()); -#else - mapper->SetInputData(grid); -#endif vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index ffb2d84f5..a6b2fffaa 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -64,27 +64,6 @@ cv::Affine3d cv::viz::makeCameraPose(const Vec3d& position, const Vec3d& focal_p return makeTransformToGlobal(u, v, n, position); } -namespace cv { namespace viz -{ - template Vec<_Tp, 3>* vtkpoints_data(vtkSmartPointer& points); - - template<> Vec3f* vtkpoints_data(vtkSmartPointer& points) - { - CV_Assert(points->GetDataType() == VTK_FLOAT); - vtkDataArray *data = points->GetData(); - float *pointer = static_cast(data)->GetPointer(0); - return reinterpret_cast(pointer); - } - - template<> Vec3d* vtkpoints_data(vtkSmartPointer& points) - { - CV_Assert(points->GetDataType() == VTK_DOUBLE); - vtkDataArray *data = points->GetData(); - double *pointer = static_cast(data)->GetPointer(0); - return reinterpret_cast(pointer); - } -}} - /////////////////////////////////////////////////////////////////////////////////////////////// /// VizStorage implementation @@ -308,11 +287,7 @@ void cv::viz::computeNormals(const Mesh3d& mesh, OutputArray _normals) vtkSmartPointer polydata = getPolyData(WMesh(mesh)); vtkSmartPointer normal_generator = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - normal_generator->SetInput(polydata); -#else - normal_generator->SetInputData(polydata); -#endif + normal_generator->SetInputConnection(polydata->GetProducerPort()); normal_generator->ComputePointNormalsOn(); normal_generator->ComputeCellNormalsOff(); From a3b1f29d23de60b4eaec656489d69e02e510ad33 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 8 Jan 2014 16:25:14 +0400 Subject: [PATCH 151/295] refactored spheres trajectory --- modules/viz/doc/widget.rst | 18 ++-- modules/viz/include/opencv2/viz/widgets.hpp | 4 +- modules/viz/src/shapes.cpp | 91 +++++++++------------ 3 files changed, 49 insertions(+), 64 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 4119df083..55dca7679 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -799,23 +799,21 @@ represent the direction from previous position to the current. :: class CV_EXPORTS WTrajectorySpheres : public Widget3D { public: - WTrajectorySpheres(const std::vector &path, double line_length = 0.05f, - double init_sphere_radius = 0.021, sphere_radius = 0.007, - Color &line_color = Color::white(), const Color &sphere_color = Color::white()); + WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007, + const Color &from = Color::red(), const Color &to = Color::white()); }; viz::WTrajectorySpheres::WTrajectorySpheres ------------------------------------------- Constructs a WTrajectorySpheres. -.. ocv:function:: WTrajectorySpheres(const std::vector &path, double line_length = 0.05f, double init_sphere_radius = 0.021, double sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) +.. ocv:function:: WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007, const Color &from = Color::red(), const Color &to = Color::white()); - :param path: List of poses on a trajectory. - :param line_length: Length of the lines. - :param init_sphere_radius: Radius of the first sphere which represents the initial position of the camera. - :param sphere_radius: Radius of the rest of the spheres. - :param line_color: :ocv:class:`Color` of the lines. - :param sphere_color: :ocv:class:`Color` of the spheres. + :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] + :param line_length: Max length of the lines which point to previous position + :param sphere_radius: Radius of the spheres. + :param from: :ocv:class:`Color` for first sphere. + :param to: :ocv:class:`Color` for last sphere. Intermediate spheres will have interpolated color. viz::WCloud ----------- diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index ad75199f8..32665e74a 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -279,8 +279,8 @@ namespace cv class CV_EXPORTS WTrajectorySpheres: public Widget3D { public: - WTrajectorySpheres(const std::vector &path, double line_length = 0.05, double init_sphere_radius = 0.021, - double sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); + WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007, + const Color &from = Color::red(), const Color &to = Color::white()); }; ///////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index bcd6870df..347a58b6e 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1155,71 +1155,58 @@ template<> cv::viz::WTrajectoryFrustums cv::viz::Widget::cast &path, double line_length, double init_sphere_radius, double sphere_radius, - const Color &line_color, const Color &sphere_color) +cv::viz::WTrajectorySpheres::WTrajectorySpheres(InputArray _path, double line_length, double radius, const Color &from, const Color &to) { - vtkSmartPointer appendFilter = vtkSmartPointer::New(); - vtkIdType nr_poses = path.size(); + CV_Assert(_path.kind() == _InputArray::STD_VECTOR || _path.kind() == _InputArray::MAT); + CV_Assert(_path.type() == CV_32FC(16) || _path.type() == CV_64FC(16)); - // Create color arrays - vtkSmartPointer line_scalars = vtkSmartPointer::New(); - line_scalars->SetNumberOfComponents(3); - line_scalars->InsertNextTuple3(line_color[2], line_color[1], line_color[0]); + Mat path64; + _path.getMat().convertTo(path64, CV_64F); + Affine3d *traj = path64.ptr(); + size_t total = path64.total(); - // Create color array for sphere - vtkSmartPointer dummy_sphere = vtkSmartPointer::New(); - // Create the array for big sphere - dummy_sphere->SetRadius(init_sphere_radius); - dummy_sphere->Update(); - vtkIdType nr_points = dummy_sphere->GetOutput()->GetNumberOfCells(); - vtkSmartPointer sphere_scalars_init = VtkUtils::FillScalars(nr_points, sphere_color); + vtkSmartPointer append_filter = vtkSmartPointer::New(); - // Create the array for small sphere - dummy_sphere->SetRadius(sphere_radius); - dummy_sphere->Update(); - nr_points = dummy_sphere->GetOutput()->GetNumberOfCells(); - vtkSmartPointer sphere_scalars = VtkUtils::FillScalars(nr_points, sphere_color); - - - for (vtkIdType i = 0; i < nr_poses; ++i) + for(size_t i = 0; i < total; ++i) { - Point3f new_pos = path[i].translation(); + Vec3d curr = traj[i].translation(); vtkSmartPointer sphere_source = vtkSmartPointer::New(); - sphere_source->SetCenter(new_pos.x, new_pos.y, new_pos.z); - if (i == 0) + sphere_source->SetCenter(curr.val); + sphere_source->SetRadius( (i == 0) ? 2 * radius : radius ); + sphere_source->Update(); + + double alpha = static_cast(i)/total; + Color c = from * (1 - alpha) + to * alpha; + + vtkSmartPointer polydata = sphere_source->GetOutput(); + polydata->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata->GetNumberOfCells(), c)); + append_filter->AddInputConnection(polydata->GetProducerPort()); + + if (i > 0) { - sphere_source->SetRadius(init_sphere_radius); - sphere_source->Update(); - sphere_source->GetOutput()->GetCellData()->SetScalars(sphere_scalars_init); - appendFilter->AddInputConnection(sphere_source->GetOutputPort()); - continue; + Vec3d prev = traj[i-1].translation(); + Vec3d lvec = prev - curr; + + if(norm(lvec) > line_length) + lvec = normalize(lvec) * line_length; + + Vec3d lend = curr + lvec; + + vtkSmartPointer line_source = vtkSmartPointer::New(); + line_source->SetPoint1(curr.val); + line_source->SetPoint2(lend.val); + line_source->Update(); + vtkSmartPointer polydata = line_source->GetOutput(); + polydata->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata->GetNumberOfCells(), c)); + append_filter->AddInputConnection(polydata->GetProducerPort()); } - else - { - sphere_source->SetRadius(sphere_radius); - sphere_source->Update(); - sphere_source->GetOutput()->GetCellData()->SetScalars(sphere_scalars); - appendFilter->AddInputConnection(sphere_source->GetOutputPort()); - } - - - Affine3d relativeAffine = path[i].inv() * path[i-1]; - Vec3d v = path[i].rotation() * relativeAffine.translation(); - v = normalize(v) * line_length; - - vtkSmartPointer line_source = vtkSmartPointer::New(); - line_source->SetPoint1(new_pos.x + v[0], new_pos.y + v[1], new_pos.z + v[2]); - line_source->SetPoint2(new_pos.x, new_pos.y, new_pos.z); - line_source->Update(); - line_source->GetOutput()->GetCellData()->SetScalars(line_scalars); - - appendFilter->AddInputConnection(line_source->GetOutputPort()); } + append_filter->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUseCellData(); - mapper->SetInputConnection(appendFilter->GetOutputPort()); + VtkUtils::SetInputData(mapper, append_filter->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); From 0d702b83f4bbcdcaed1f3463e21c7bbe89445dee Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 8 Jan 2014 17:16:25 +0400 Subject: [PATCH 152/295] updated code to use mapper->SetInput instead of SetInputConnection. All widgets except plane, images ans texts --- modules/core/include/opencv2/core/affine.hpp | 8 ++ modules/viz/include/opencv2/viz.hpp | 3 - modules/viz/src/clouds.cpp | 40 +++------ modules/viz/src/interactor_style.cpp | 2 - modules/viz/src/shapes.cpp | 89 ++++++++------------ 5 files changed, 54 insertions(+), 88 deletions(-) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index 62720b572..0ee6fabe9 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -113,6 +113,8 @@ namespace cv template operator Affine3() const; + template Affine3 cast() const; + Mat4 matrix; #if defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H @@ -421,6 +423,12 @@ cv::Affine3::operator Affine3() const return Affine3(matrix); } +template template inline +cv::Affine3 cv::Affine3::cast() const +{ + return Affine3(matrix); +} + template inline cv::Affine3 cv::operator*(const cv::Affine3& affine1, const cv::Affine3& affine2) { diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index b281635a6..9ceed0850 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -41,9 +41,6 @@ // * Ozan Tonkal, ozantonkal@gmail.com // * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// //M*/ #ifndef __OPENCV_VIZ_HPP__ diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 15e9d4a61..4b4010eef 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -54,9 +54,10 @@ cv::viz::WCloud::WCloud(InputArray cloud, InputArray colors) vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetColorCloud(cloud, colors); + cloud_source->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(cloud_source->GetOutputPort()); + VtkUtils::SetInputData(mapper, cloud_source->GetOutput()); mapper->SetScalarModeToUsePointData(); mapper->ImmediateModeRenderingOff(); mapper->SetScalarRange(0, 255); @@ -74,9 +75,10 @@ cv::viz::WCloud::WCloud(InputArray cloud, const Color &color) { vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetCloud(cloud); + cloud_source->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(cloud_source->GetOutputPort()); + VtkUtils::SetInputData(mapper, cloud_source->GetOutput()); mapper->ImmediateModeRenderingOff(); mapper->ScalarVisibilityOff(); @@ -127,15 +129,11 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co { // This is the first cloud mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(polydata); -#else - mapper->SetInputData(polydata); -#endif mapper->SetScalarRange(0, 255); mapper->SetScalarModeToUsePointData(); mapper->ScalarVisibilityOn(); mapper->ImmediateModeRenderingOff(); + VtkUtils::SetInputData(mapper, polydata); actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints()/10)); actor->GetProperty()->SetInterpolationToFlat(); @@ -147,16 +145,12 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co vtkPolyData *currdata = vtkPolyData::SafeDownCast(mapper->GetInput()); CV_Assert("Cloud Widget without data" && currdata); - vtkSmartPointer appendFilter = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - appendFilter->AddInput(currdata); - appendFilter->AddInput(polydata); - mapper->SetInput(appendFilter->GetOutput()); -#else - appendFilter->AddInputData(currdata); - appendFilter->AddInputData(polydata); - mapper->SetInputData(appendFilter->GetOutput()); -#endif + vtkSmartPointer append_filter = vtkSmartPointer::New(); + append_filter->AddInputConnection(currdata->GetProducerPort()); + append_filter->AddInputConnection(polydata->GetProducerPort()); + append_filter->Update(); + + VtkUtils::SetInputData(mapper, append_filter->GetOutput()); actor->SetNumberOfCloudPoints(std::max(1, actor->GetNumberOfCloudPoints() + polydata->GetNumberOfPoints()/10)); } @@ -245,11 +239,7 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetColorModeToMapScalars(); mapper->SetScalarModeToUsePointData(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(polyData); -#else - mapper->SetInputData(polyData); -#endif + VtkUtils::SetInputData(mapper, polyData); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -326,11 +316,7 @@ cv::viz::WMesh::WMesh(const Mesh3d &mesh) vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUsePointData(); mapper->ImmediateModeRenderingOff(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(polydata); -#else - mapper->SetInputData(polydata); -#endif + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); //actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints() / 10)); diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 19a3476a8..2e948e660 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -564,7 +564,6 @@ void cv::viz::InteractorStyle::OnLeftButtonUp() void cv::viz::InteractorStyle::OnMiddleButtonDown() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; MouseEvent event(type, MouseEvent::MiddleButton, p, getModifiers()); if (mouseCallback_) @@ -586,7 +585,6 @@ void cv::viz::InteractorStyle::OnMiddleButtonUp() void cv::viz::InteractorStyle::OnRightButtonDown() { Vec2i p(Interactor->GetEventPosition()); - MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; MouseEvent event(type, MouseEvent::RightButton, p, getModifiers()); if (mouseCallback_) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 347a58b6e..cc674dcf4 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -52,9 +52,10 @@ cv::viz::WLine::WLine(const Point3d &pt1, const Point3d &pt2, const Color &color vtkSmartPointer line = vtkSmartPointer::New(); line->SetPoint1(pt1.x, pt1.y, pt1.z); line->SetPoint2(pt2.x, pt2.y, pt2.z); + line->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(line->GetOutputPort()); + VtkUtils::SetInputData(mapper, line->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -153,9 +154,10 @@ cv::viz::WSphere::WSphere(const Point3d ¢er, double radius, int sphere_resol sphere->SetPhiResolution(sphere_resolution); sphere->SetThetaResolution(sphere_resolution); sphere->LatLongTessellationOff(); + sphere->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(sphere->GetOutputPort()); + VtkUtils::SetInputData(mapper, sphere->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -203,9 +205,10 @@ cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness vtkSmartPointer transformPD = vtkSmartPointer::New(); transformPD->SetTransform(transform); transformPD->SetInputConnection(arrowSource->GetOutputPort()); + transformPD->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(transformPD->GetOutputPort()); + VtkUtils::SetInputData(mapper, transformPD->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -239,9 +242,10 @@ cv::viz::WCircle::WCircle(const Point3d& pt, double radius, double thickness, co vtkSmartPointer tf = vtkSmartPointer::New(); tf->SetTransform(t); tf->SetInputConnection(disk->GetOutputPort()); + tf->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(tf->GetOutputPort()); + VtkUtils::SetInputData(mapper, tf->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -270,9 +274,10 @@ cv::viz::WCylinder::WCylinder(const Point3d& pt_on_axis, const Point3d& axis_dir tuber->SetInputConnection(line->GetOutputPort()); tuber->SetRadius(radius); tuber->SetNumberOfSides(numsides); + tuber->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(tuber->GetOutputPort()); + VtkUtils::SetInputData(mapper, tuber->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -292,19 +297,21 @@ template<> cv::viz::WCylinder cv::viz::Widget::cast() cv::viz::WCube::WCube(const Point3d& pt_min, const Point3d& pt_max, bool wire_frame, const Color &color) { - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer cube; if (wire_frame) { - vtkSmartPointer cube = vtkSmartPointer::New(); - cube->SetBounds(pt_min.x, pt_max.x, pt_min.y, pt_max.y, pt_min.z, pt_max.z); - mapper->SetInputConnection(cube->GetOutputPort()); + cube = vtkSmartPointer::New(); + vtkOutlineSource::SafeDownCast(cube)->SetBounds(pt_min.x, pt_max.x, pt_min.y, pt_max.y, pt_min.z, pt_max.z); } else { - vtkSmartPointer cube = vtkSmartPointer::New(); - cube->SetBounds(pt_min.x, pt_max.x, pt_min.y, pt_max.y, pt_min.z, pt_max.z); - mapper->SetInputConnection(cube->GetOutputPort()); + cube = vtkSmartPointer::New(); + vtkCubeSource::SafeDownCast(cube)->SetBounds(pt_min.x, pt_max.x, pt_min.y, pt_max.y, pt_min.z, pt_max.z); } + cube->Update(); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, cube->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -345,6 +352,7 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(double scale) tube_filter->SetInputConnection(polydata->GetProducerPort()); tube_filter->SetRadius(axes->GetScaleFactor() / 50.0); tube_filter->SetNumberOfSides(6); + tube_filter->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUsePointData(); @@ -400,7 +408,7 @@ cv::viz::WPolyLine::WPolyLine(InputArray _points, const Color &color) polydata->GetPointData()->SetScalars(scalars); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(polydata->GetProducerPort()); + VtkUtils::SetInputData(mapper, polydata); mapper->SetScalarRange(0, 255); vtkSmartPointer actor = vtkSmartPointer::New(); @@ -449,7 +457,7 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(grid->GetProducerPort()); + VtkUtils::SetInputData(mapper, grid); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -478,15 +486,11 @@ cv::viz::WGrid::WGrid(const Vec4d &coefs, const Vec2i &dimensions, const Vec2d & vtkSmartPointer transform_filter = vtkSmartPointer::New(); transform_filter->SetTransform(transform); -#if VTK_MAJOR_VERSION <= 5 transform_filter->SetInputConnection(grid->GetProducerPort()); -#else - transform_filter->SetInputData(grid); -#endif transform_filter->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(transform_filter->GetOutputPort()); + VtkUtils::SetInputData(mapper, transform_filter->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -544,6 +548,7 @@ void cv::viz::WText3D::setText(const String &text) CV_Assert("This widget does not support text." && textSource); textSource->SetText(text.c_str()); + textSource->Modified(); textSource->Update(); } @@ -620,11 +625,7 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip -#if VTK_MAJOR_VERSION <= 5 flipFilter->SetInputConnection(vtk_image->GetProducerPort()); -#else - flipFilter->SetInputData(vtk_image); -#endif flipFilter->Update(); // Scale the image based on the Rect @@ -667,11 +668,7 @@ void cv::viz::WImageOverlay::setImage(const Mat &image) // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip -#if VTK_MAJOR_VERSION <= 5 flipFilter->SetInputConnection(vtk_image->GetProducerPort()); -#else - flipFilter->SetInputData(vtk_image); -#endif flipFilter->Update(); mapper->SetInputConnection(flipFilter->GetOutputPort()); @@ -697,11 +694,7 @@ cv::viz::WImage3D::WImage3D(const Mat &image, const Size &size) // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip -#if VTK_MAJOR_VERSION <= 5 flipFilter->SetInputConnection(vtk_image->GetProducerPort()); -#else - flipFilter->SetInputData(vtk_image); -#endif flipFilter->Update(); Vec3d plane_center(size.width * 0.5, size.height * 0.5, 0.0); @@ -749,11 +742,7 @@ cv::viz::WImage3D::WImage3D(const Vec3d &position, const Vec3d &normal, const Ve // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip -#if VTK_MAJOR_VERSION <= 5 flipFilter->SetInputConnection(vtk_image->GetProducerPort()); -#else - flipFilter->SetInputData(vtk_image); -#endif flipFilter->Update(); vtkSmartPointer plane = vtkSmartPointer::New(); @@ -809,11 +798,7 @@ void cv::viz::WImage3D::setImage(const Mat &image) // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip -#if VTK_MAJOR_VERSION <= 5 flipFilter->SetInputConnection(vtk_image->GetProducerPort()); -#else - flipFilter->SetInputData(vtk_image); -#endif flipFilter->Update(); // Apply the texture @@ -855,11 +840,7 @@ namespace cv { namespace viz { namespace // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip -#if VTK_MAJOR_VERSION <= 5 flipFilter->SetInputConnection(vtk_image->GetProducerPort()); -#else - flipFilter->SetInputData(vtk_image); -#endif flipFilter->Update(); Vec3d plane_center(0.0, 0.0, scale); @@ -958,7 +939,6 @@ namespace cv { namespace viz { namespace cv::viz::WCameraPosition::WCameraPosition(double scale) { vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, getPolyData(WCoordinateSystem(scale))); mapper->SetScalarModeToUsePointData(); @@ -979,7 +959,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const vtkSmartPointer polydata = CameraPositionUtils::createFrustrum(aspect_ratio, fovy, scale); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(polydata->GetProducerPort()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -996,7 +976,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const vtkSmartPointer polydata = CameraPositionUtils::createFrustrum(aspect_ratio, fovy, scale); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(polydata->GetProducerPort()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1042,14 +1022,14 @@ template<> cv::viz::WCameraPosition cv::viz::Widget::cast appendFilter = vtkSmartPointer::New(); + vtkSmartPointer append_filter = vtkSmartPointer::New(); // Bitwise and with 3 in order to limit the domain to 2 bits if (display_mode & WTrajectory::PATH) { Mat points = vtkTrajectorySource::ExtractPoints(_path); vtkSmartPointer polydata = getPolyData(WPolyLine(points, color)); - appendFilter->AddInputConnection(polydata->GetProducerPort()); + append_filter->AddInputConnection(polydata->GetProducerPort()); } if (display_mode & WTrajectory::FRAMES) @@ -1067,11 +1047,12 @@ cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double sca tensor_glyph->SymmetricOff(); tensor_glyph->ColorGlyphsOff(); - appendFilter->AddInputConnection(tensor_glyph->GetOutputPort()); + append_filter->AddInputConnection(tensor_glyph->GetOutputPort()); } + append_filter->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, appendFilter->GetOutput()); + VtkUtils::SetInputData(mapper, append_filter->GetOutput()); mapper->SetScalarModeToUsePointData(); mapper->SetScalarRange(0, 255); @@ -1106,10 +1087,8 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Matx33 tensor_glyph->ColorGlyphsOff(); tensor_glyph->Update(); - vtkSmartPointer polydata = tensor_glyph->GetOutput(); - vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(polydata->GetProducerPort()); + VtkUtils::SetInputData(mapper, tensor_glyph->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -1134,10 +1113,8 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d tensor_glyph->ColorGlyphsOff(); tensor_glyph->Update(); - vtkSmartPointer polydata = tensor_glyph->GetOutput(); - vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(polydata->GetProducerPort()); + VtkUtils::SetInputData(mapper, tensor_glyph->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); From 64566e617805e28d25d213539d7097bc04ad5764 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 8 Jan 2014 17:46:32 +0400 Subject: [PATCH 153/295] minor --- modules/viz/src/interactor_style.cpp | 8 ++----- modules/viz/src/vizimpl.cpp | 31 ++++------------------------ 2 files changed, 6 insertions(+), 33 deletions(-) diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 2e948e660..c2583f936 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -298,12 +298,8 @@ void cv::viz::InteractorStyle::OnKeyDown() { vtkSmartPointer cam = Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetActiveCamera(); - Vec2d clip; - Vec3d focal, pos, view; - cam->GetClippingRange(clip.val); - cam->GetFocalPoint(focal.val); - cam->GetPosition(pos.val); - cam->GetViewUp(view.val); + Vec2d clip(cam->GetClippingRange()); + Vec3d focal(cam->GetFocalPoint()), pos(cam->GetPosition()), view(cam->GetViewUp()); Vec2i win_pos(Interactor->GetRenderWindow()->GetPosition()); Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); double angle = cam->GetViewAngle () / 180.0 * CV_PI; diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 4b9d65b43..5974cc6e0 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -45,18 +45,9 @@ #include "precomp.hpp" - -#if (1 || !defined __APPLE__) && !defined _MSC_VER -vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew(); -vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew() -{ - return vtkRenderWindowInteractor::New(); -} -#endif - ///////////////////////////////////////////////////////////////////////////////////////////// cv::viz::Viz3d::VizImpl::VizImpl(const String &name) - : s_lastDone_(0.0), style_(vtkSmartPointer::New()), widget_actor_map_(new WidgetActorMap) + : s_lastDone_(0.0), style_(vtkSmartPointer::New()), widget_actor_map_(new WidgetActorMap) { renderer_ = vtkSmartPointer::New(); window_ = vtkSmartPointer::New(); @@ -72,12 +63,7 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) style_->setWidgetActorMap(widget_actor_map_); style_->UseTimersOn(); - ///////////////////////////////////////////////// -#if (1 || !defined __APPLE__) && !defined _MSC_VER - interactor_ = vtkSmartPointer::Take(vtkRenderWindowInteractorFixNew()); -#else interactor_ = vtkSmartPointer::New(); -#endif window_->AlphaBitPlanesOff(); window_->PointSmoothingOff(); @@ -88,7 +74,7 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) interactor_->SetRenderWindow(window_); interactor_->SetInteractorStyle(style_); - interactor_->SetDesiredUpdateRate(30.0); + interactor_->SetDesiredUpdateRate(24.0); // Initialize and create timer, also create window interactor_->Initialize(); @@ -401,10 +387,7 @@ void cv::viz::Viz3d::VizImpl::converTo3DRay(const Point3d &window_coord, Point3d { Vec4d world_pt; vtkInteractorObserver::ComputeDisplayToWorld(renderer_, window_coord.x, window_coord.y, window_coord.z, world_pt.val); - - vtkCamera &active_camera = *renderer_->GetActiveCamera(); - Vec3d cam_pos; - active_camera.GetPosition(cam_pos.val); + Vec3d cam_pos(renderer_->GetActiveCamera()->GetPosition()); origin = cam_pos; direction = normalize(Vec3d(world_pt.val) - cam_pos); } @@ -479,7 +462,6 @@ void cv::viz::Viz3d::VizImpl::setRepresentation(int representation) } } - ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) { @@ -488,12 +470,7 @@ void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) } ////////////////////////////////////////////////////////////////////////////////////////////// -cv::String cv::viz::Viz3d::VizImpl::getWindowName() const -{ - return (window_ ? window_->GetWindowName() : ""); -} - -////////////////////////////////////////////////////////////////////////////////////////////// +cv::String cv::viz::Viz3d::VizImpl::getWindowName() const { return window_ ? window_->GetWindowName() : ""; } void cv::viz::Viz3d::VizImpl::setWindowPosition(const Point& position) { window_->SetPosition(position.x, position.y); } void cv::viz::Viz3d::VizImpl::setWindowSize(const Size& window_size) { window_->SetSize(window_size.width, window_size.height); } cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(window_->GetSize()[0], window_->GetSize()[1]); } From 25b417e8b27ee6d6007c97ff56992551d103e2d1 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 8 Jan 2014 19:43:20 +0400 Subject: [PATCH 154/295] added test for trajectories and fixed bug with float type --- modules/viz/include/opencv2/viz/widgets.hpp | 1 + modules/viz/src/precomp.hpp | 16 +++++ modules/viz/src/shapes.cpp | 79 ++++++++++----------- modules/viz/src/vizimpl.hpp | 18 ----- modules/viz/src/vtk/vtkTrajectorySource.cpp | 6 +- modules/viz/src/widget.cpp | 18 ++--- modules/viz/test/test_precomp.hpp | 15 ++++ modules/viz/test/test_viz3d.cpp | 37 ++-------- modules/viz/test/tests_simple.cpp | 43 +++++++++++ 9 files changed, 128 insertions(+), 105 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 32665e74a..12373cd13 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -279,6 +279,7 @@ namespace cv class CV_EXPORTS WTrajectorySpheres: public Widget3D { public: + //! Takes vector> and displays trajectory of the given path WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007, const Color &from = Color::red(), const Color &to = Color::white()); }; diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 155612724..3f4feaf04 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -221,6 +221,22 @@ namespace cv return scalars; } }; + + inline vtkSmartPointer vtkmatrix(const cv::Matx44d &matrix) + { + vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); + vtk_matrix->DeepCopy(matrix.val); + return vtk_matrix; + } + + inline Color vtkcolor(const Color& color) + { + Color scaled_color = color * (1.0/255.0); + std::swap(scaled_color[0], scaled_color[2]); + return scaled_color; + } + + template inline _Tp normalized(const _Tp& v) { return v * 1/norm(v); } } } diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index cc674dcf4..f4b68a9fb 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -70,6 +70,35 @@ template<> cv::viz::WLine cv::viz::Widget::cast() return static_cast(widget); } +/////////////////////////////////////////////////////////////////////////////////////////////// +/// sphere widget implementation + +cv::viz::WSphere::WSphere(const Point3d ¢er, double radius, int sphere_resolution, const Color &color) +{ + vtkSmartPointer sphere = vtkSmartPointer::New(); + sphere->SetRadius(radius); + sphere->SetCenter(center.x, center.y, center.z); + sphere->SetPhiResolution(sphere_resolution); + sphere->SetThetaResolution(sphere_resolution); + sphere->LatLongTessellationOff(); + sphere->Update(); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, sphere->GetOutput()); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->SetMapper(mapper); + + WidgetAccessor::setProp(*this, actor); + setColor(color); +} + +template<> cv::viz::WSphere cv::viz::Widget::cast() +{ + Widget3D widget = this->cast(); + return static_cast(widget); +} + /////////////////////////////////////////////////////////////////////////////////////////////// /// plane widget implementation @@ -143,51 +172,21 @@ template<> cv::viz::WPlane cv::viz::Widget::cast() return static_cast(widget); } -/////////////////////////////////////////////////////////////////////////////////////////////// -/// sphere widget implementation - -cv::viz::WSphere::WSphere(const Point3d ¢er, double radius, int sphere_resolution, const Color &color) -{ - vtkSmartPointer sphere = vtkSmartPointer::New(); - sphere->SetRadius(radius); - sphere->SetCenter(center.x, center.y, center.z); - sphere->SetPhiResolution(sphere_resolution); - sphere->SetThetaResolution(sphere_resolution); - sphere->LatLongTessellationOff(); - sphere->Update(); - - vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, sphere->GetOutput()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(mapper); - - WidgetAccessor::setProp(*this, actor); - setColor(color); -} - -template<> cv::viz::WSphere cv::viz::Widget::cast() -{ - Widget3D widget = this->cast(); - return static_cast(widget); -} - /////////////////////////////////////////////////////////////////////////////////////////////// /// arrow widget implementation cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness, const Color &color) { - vtkSmartPointer arrowSource = vtkSmartPointer::New(); - arrowSource->SetShaftRadius(thickness); - // The thickness and radius of the tip are adjusted based on the thickness of the arrow - arrowSource->SetTipRadius(thickness * 3.0); - arrowSource->SetTipLength(thickness * 10.0); + vtkSmartPointer arrow_source = vtkSmartPointer::New(); + arrow_source->SetShaftRadius(thickness); + arrow_source->SetTipRadius(thickness * 3.0); + arrow_source->SetTipLength(thickness * 10.0); RNG rng = theRNG(); Vec3d arbitrary(rng.uniform(-10.0, 10.0), rng.uniform(-10.0, 10.0), rng.uniform(-10.0, 10.0)); Vec3d startPoint(pt1.x, pt1.y, pt1.z), endPoint(pt2.x, pt2.y, pt2.z); - double length = cv::norm(endPoint - startPoint); + double length = norm(endPoint - startPoint); Vec3d xvec = normalized(endPoint - startPoint); Vec3d zvec = normalized(xvec.cross(arbitrary)); @@ -204,7 +203,7 @@ cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness // Transform the polydata vtkSmartPointer transformPD = vtkSmartPointer::New(); transformPD->SetTransform(transform); - transformPD->SetInputConnection(arrowSource->GetOutputPort()); + transformPD->SetInputConnection(arrow_source->GetOutputPort()); transformPD->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); @@ -908,14 +907,14 @@ namespace cv { namespace viz { namespace actor->SetTexture(texture); } - static vtkSmartPointer createFrustrum(double aspect_ratio, double fovy, double scale) + static vtkSmartPointer createFrustum(double aspect_ratio, double fovy, double scale) { vtkSmartPointer camera = vtkSmartPointer::New(); camera->SetViewAngle(fovy); camera->SetPosition(0.0, 0.0, 0.0); camera->SetViewUp(0.0, 1.0, 0.0); camera->SetFocalPoint(0.0, 0.0, 1.0); - camera->SetClippingRange(0.01, scale); + camera->SetClippingRange(1e-9, scale); double planesArray[24]; camera->GetFrustumPlanes(aspect_ratio, planesArray); @@ -956,7 +955,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const double fovy = 2.0 * atan2(c_y, f_y) * 180 / CV_PI; double aspect_ratio = f_y / f_x; - vtkSmartPointer polydata = CameraPositionUtils::createFrustrum(aspect_ratio, fovy, scale); + vtkSmartPointer polydata = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); vtkSmartPointer mapper = vtkSmartPointer::New(); VtkUtils::SetInputData(mapper, polydata); @@ -973,7 +972,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const double aspect_ratio = tan(fov[0] * 0.5) / tan(fov[1] * 0.5); double fovy = fov[1] * 180 / CV_PI; - vtkSmartPointer polydata = CameraPositionUtils::createFrustrum(aspect_ratio, fovy, scale); + vtkSmartPointer polydata = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); vtkSmartPointer mapper = vtkSmartPointer::New(); VtkUtils::SetInputData(mapper, polydata); diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index d5274b49c..03d5c0325 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -179,34 +179,16 @@ private: bool removeActorFromRenderer(const vtkSmartPointer &actor); }; - namespace cv { namespace viz { - inline vtkSmartPointer vtkmatrix(const cv::Matx44d &matrix) - { - vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); - vtk_matrix->DeepCopy(matrix.val); - return vtk_matrix; - } - struct color_tag {}; struct gray_tag {}; inline Vec3b fetchRgb(const unsigned char* color, color_tag) { return Vec3b(color[2], color[1], color[0]); } inline Vec3b fetchRgb(const unsigned char* color, gray_tag) { return Vec3b(color[0], color[0], color[0]); } - inline Vec3d vtkpoint(const Point3f& point) { return Vec3d(point.x, point.y, point.z); } - template inline _Tp normalized(const _Tp& v) { return v * 1/cv::norm(v); } - - inline Color vtkcolor(const Color& color) - { - Color scaled_color = color * (1.0/255.0); - std::swap(scaled_color[0], scaled_color[2]); - return scaled_color; - } - struct ConvertToVtkImage { struct Impl diff --git a/modules/viz/src/vtk/vtkTrajectorySource.cpp b/modules/viz/src/vtk/vtkTrajectorySource.cpp index 151020881..e098a1d55 100644 --- a/modules/viz/src/vtk/vtkTrajectorySource.cpp +++ b/modules/viz/src/vtk/vtkTrajectorySource.cpp @@ -59,9 +59,8 @@ void cv::viz::vtkTrajectorySource::SetTrajectory(InputArray _traj) Mat traj; _traj.getMat().convertTo(traj, CV_64F); - const Affine3d* dpath = _traj.getMat().ptr(); - - size_t total = _traj.total(); + const Affine3d* dpath = traj.ptr(); + size_t total = traj.total(); points = vtkSmartPointer::New(); points->SetDataType(VTK_DOUBLE); @@ -81,7 +80,6 @@ void cv::viz::vtkTrajectorySource::SetTrajectory(InputArray _traj) } } - cv::Mat cv::viz::vtkTrajectorySource::ExtractPoints(InputArray _traj) { CV_Assert(_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT); diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index 23099ba72..b0e84037f 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -140,14 +140,11 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) { if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals()) { + vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); vtkSmartPointer normals = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - normals->SetInput(actor->GetMapper()->GetInput()); -#else - normals->SetInputData(actor->GetMapper()->GetInput()); -#endif + VtkUtils::SetInputData(normals, mapper->GetInput()); normals->Update(); - vtkDataSetMapper::SafeDownCast(actor->GetMapper())->SetInputConnection(normals->GetOutputPort()); + VtkUtils::SetInputData(mapper, normals->GetOutput()); } actor->GetProperty()->SetInterpolationToGouraud(); break; @@ -156,14 +153,11 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) { if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals()) { + vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); vtkSmartPointer normals = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - normals->SetInput(actor->GetMapper()->GetInput()); -#else - normals->SetInputData(actor->GetMapper()->GetInput()); -#endif + VtkUtils::SetInputData(normals, mapper->GetInput()); normals->Update(); - vtkDataSetMapper::SafeDownCast(actor->GetMapper())->SetInputConnection(normals->GetOutputPort()); + VtkUtils::SetInputData(mapper, normals->GetOutput()); } actor->GetProperty()->SetInterpolationToPhong(); break; diff --git a/modules/viz/test/test_precomp.hpp b/modules/viz/test/test_precomp.hpp index efc89b27f..e4fe78420 100644 --- a/modules/viz/test/test_precomp.hpp +++ b/modules/viz/test/test_precomp.hpp @@ -78,6 +78,21 @@ namespace cv { return Path::combine(cvtest::TS::ptr()->get_data_path(), "dragon.ply"); } + + template + inline std::vector< Affine3<_Tp> > generate_test_trajectory() + { + std::vector< Affine3<_Tp> > result; + + for (int i = 0, j = 0; i <= 270; i += 3, j += 10) + { + double x = 2 * cos(i * 3 * CV_PI/180.0) * (1.0 + 0.5 * cos(1.2 + i * 1.2 * CV_PI/180.0)); + double y = 0.25 + i/270.0 + sin(j * CV_PI/180.0) * 0.2 * sin(0.6 + j * 1.5 * CV_PI/180.0); + double z = 2 * sin(i * 3 * CV_PI/180.0) * (1.0 + 0.5 * cos(1.2 + i * CV_PI/180.0)); + result.push_back(viz::makeCameraPose(Vec3d(x, y, z), Vec3d::all(0.0), Vec3d(0.0, 1.0, 0.0))); + } + return result; + } } #endif diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 6bc3622c6..aec326508 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -48,46 +48,21 @@ TEST(Viz_viz3d, develop) cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); //cv::viz::Mesh3d mesh = cv::viz::Mesh3d::load(get_dragon_ply_file_path()); - //theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); cv::viz::Viz3d viz("abc"); viz.setBackgroundColor(cv::viz::Color::mlab()); - viz.showWidget("coo", cv::viz::WCoordinateSystem(0.1)); - - -// double c = cos(CV_PI/6); -// std::vector pts; -// pts.push_back(Vec3d(0, 0.0, -1.0)); -// pts.push_back(Vec3d(1, c, -0.5)); -// pts.push_back(Vec3d(2, c, 0.5)); -// pts.push_back(Vec3d(3, 0.0, 1.0)); -// pts.push_back(Vec3d(4, -c, 0.5)); -// pts.push_back(Vec3d(5, -c, -0.5)); - -// viz.showWidget("pl", cv::viz::WPolyLine(Mat(pts), cv::viz::Color::green())); - - //viz.showWidget("pl", cv::viz::WPolyLine(cloud.colRange(0, 100), cv::viz::Color::green())); - //viz.spin(); - - //cv::Mat colors(cloud.size(), CV_8UC3, cv::Scalar(0, 255, 0)); + viz.showWidget("coo", cv::viz::WCoordinateSystem(1)); //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); - std::vector gt, es; - cv::viz::readTrajectory(gt, "d:/Datasets/trajs/gt%05d.xml"); + //---->>>>> + //std::vector gt, es; + //cv::viz::readTrajectory(gt, "d:/Datasets/trajs/gt%05d.xml"); //cv::viz::readTrajectory(es, "d:/Datasets/trajs/es%05d.xml"); - gt.resize(20); - - Affine3d inv = gt[0].inv(); - for(size_t i = 0; i < gt.size(); ++i) - gt[i] = inv * gt[i]; - - //viz.showWidget("gt", viz::WTrajectory(gt, viz::WTrajectory::PATH, 1.f, viz::Color::blue()), gt[0].inv()); - viz.showWidget("gt", viz::WTrajectory(gt, viz::WTrajectory::BOTH, 0.01f, viz::Color::blue())); - - //viz.showWidget("tr", viz::WTrajectory(es, viz::WTrajectory::PATH, 1.f, viz::Color::red()), gt[0].inv()); + //cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); + //---->>>>> //theRNG().fill(colors, cv::RNG::UNIFORM, 0, 255); //viz.showWidget("c", cv::viz::WCloud(cloud, colors)); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 6f61a806c..93428c6b9 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -156,6 +156,49 @@ TEST(Viz, DISABLED_show_sampled_normals) viz.spin(); } +TEST(Viz, DISABLED_show_trajectories) +{ + std::vector path = generate_test_trajectory(), sub0, sub1, sub2, sub3, sub4, sub5; + + Mat(path).rowRange(0, path.size()/10+1).copyTo(sub0); + Mat(path).rowRange(path.size()/10, path.size()/5+1).copyTo(sub1); + Mat(path).rowRange(path.size()/5, 11*path.size()/12).copyTo(sub2); + Mat(path).rowRange(11*path.size()/12, path.size()).copyTo(sub3); + Mat(path).rowRange(3*path.size()/4, 33*path.size()/40).copyTo(sub4); + Mat(path).rowRange(33*path.size()/40, 9*path.size()/10).copyTo(sub5); + Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0); + + Viz3d viz("show_trajectories"); + viz.showWidget("coos", WCoordinateSystem()); + viz.showWidget("sub0", WTrajectorySpheres(sub0, 0.25, 0.07)); + viz.showWidget("sub1", WTrajectory(sub1, WTrajectory::PATH, 0.2, Color::brown())); + viz.showWidget("sub2", WTrajectory(sub2, WTrajectory::FRAMES, 0.2)); + viz.showWidget("sub3", WTrajectory(sub3, WTrajectory::BOTH, 0.2, Color::green())); + viz.showWidget("sub4", WTrajectoryFrustums(sub4, K, 0.3)); + viz.showWidget("sub5", WTrajectoryFrustums(sub5, Vec2d(0.78, 0.78), 0.15)); + + int i = 0; + while(!viz.wasStopped()) + { + double a = --i % 360; + Vec3d pose(sin(a * CV_PI/180), 0.7, cos(a * CV_PI/180)); + viz.setViewerPose(makeCameraPose(pose * 7.5, Vec3d(0.0, 0.5, 0.0), Vec3d(0.0, 0.1, 0.0))); + viz.spinOnce(20, true); + } + //viz.spin(); +} + +TEST(Viz, DISABLED_show_trajectory_reposition) +{ + std::vector path = generate_test_trajectory(); + + Viz3d viz("show_trajectory_reposition_to_origin"); + viz.showWidget("coos", WCoordinateSystem()); + viz.showWidget("sub3", WTrajectory(Mat(path).rowRange(0, path.size()/3), WTrajectory::BOTH, 0.2, Color::brown()), path.front().inv()); + viz.spin(); +} + + TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) { Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); From e478d6b1e9d7eabc1901875b75da945dcba114f9 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 9 Jan 2014 19:08:06 +0400 Subject: [PATCH 155/295] renamed cv::viz::get() to getWindowByName() --- modules/viz/doc/viz3d.rst | 8 ++++---- modules/viz/include/opencv2/viz.hpp | 4 ++-- modules/viz/include/opencv2/viz/widgets.hpp | 8 ++++---- modules/viz/src/vizcore.cpp | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index 1cb9b5dc3..215437eda 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -34,11 +34,11 @@ Constructs camera pose from position, focal_point and up_vector (see gluLookAt() This function returns pose of the camera in global coordinate frame. -viz::get +viz::getWindowByName -------- Retrieves a window by its name. -.. ocv:function:: Viz3d get(const String &window_name) +.. ocv:function:: Viz3d getWindowByName(const String &window_name) :param window_name: Name of the window that is to be retrieved. @@ -51,8 +51,8 @@ This function returns a :ocv:class:`Viz3d` object with the given name. .. code-block:: cpp /// window and window_2 are the same windows. - viz::Viz3d window = viz::get("myWindow"); - viz::Viz3d window_2 = viz::get("Viz - myWindow"); + viz::Viz3d window = viz::getWindowByName("myWindow"); + viz::Viz3d window_2 = viz::getWindowByName("Viz - myWindow"); viz::isNan ---------- diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 9ceed0850..d2b46dd0e 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -61,9 +61,9 @@ namespace cv CV_EXPORTS Affine3d makeCameraPose(const Vec3d& position, const Vec3d& focal_point, const Vec3d& y_dir); //! retrieves a window by its name. If no window with such name, then it creates new. - CV_EXPORTS Viz3d get(const String &window_name); + CV_EXPORTS Viz3d getWindowByName(const String &window_name); - //! Unregisters all Viz windows from internal database. After it 'get()' will create new windows instead getting existing from the database. + //! Unregisters all Viz windows from internal database. After it 'getWindowByName()' will create new windows instead getting existing from the database. CV_EXPORTS void unregisterAllWindows(); //! checks float value for Nan diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 12373cd13..5b575774f 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -141,8 +141,8 @@ namespace cv class CV_EXPORTS WPlane : public Widget3D { public: - WPlane(const Vec4d& coefs, double size = 1.f, const Color &color = Color::white()); - WPlane(const Vec4d& coefs, const Point3d& pt, double size = 1.f, const Color &color = Color::white()); + WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()); + WPlane(const Vec4d& coefs, const Point3d& pt, double size = 1.0, const Color &color = Color::white()); }; class CV_EXPORTS WSphere : public Widget3D @@ -227,7 +227,7 @@ namespace cv class CV_EXPORTS WCoordinateSystem : public Widget3D { public: - WCoordinateSystem(double scale = 1.f); + WCoordinateSystem(double scale = 1.0); }; class CV_EXPORTS WGrid : public Widget3D @@ -263,7 +263,7 @@ namespace cv enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH }; //! Takes vector> and displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.f, const Color &color = Color::white()); + WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.0, const Color &color = Color::white()); }; class CV_EXPORTS WTrajectoryFrustums : public Widget3D diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index a6b2fffaa..bf01ff5a5 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -119,7 +119,7 @@ cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) return output; } -cv::viz::Viz3d cv::viz::get(const String &window_name) { return Viz3d (window_name); } +cv::viz::Viz3d cv::viz::getWindowByName(const String &window_name) { return Viz3d (window_name); } void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } /////////////////////////////////////////////////////////////////////////////////////////////// From d591bd875b659d6128d47e3b1cbd52e906d7d762 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 9 Jan 2014 19:34:55 +0400 Subject: [PATCH 156/295] fixed crash in enabling shading for polydata widgets --- modules/viz/src/clouds.cpp | 2 +- modules/viz/src/precomp.hpp | 16 ++++++++++++++++ modules/viz/src/vizcore.cpp | 16 ++-------------- modules/viz/src/widget.cpp | 16 ++++++++-------- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 4b4010eef..ceb4d9c0b 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -313,7 +313,7 @@ cv::viz::WMesh::WMesh(const Mesh3d &mesh) cell_array->Squeeze(); polydata->SetStrips(cell_array); - vtkSmartPointer mapper = vtkSmartPointer::New(); + vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetScalarModeToUsePointData(); mapper->ImmediateModeRenderingOff(); VtkUtils::SetInputData(mapper, polydata); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 3f4feaf04..425502d64 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -220,6 +220,22 @@ namespace cv scalars->SetArray(color_data->val, size * 3, 0); return scalars; } + + static vtkSmartPointer ComputeNormals(vtkSmartPointer polydata) + { + vtkSmartPointer normals_generator = vtkSmartPointer::New(); + normals_generator->ComputePointNormalsOn(); + normals_generator->ComputeCellNormalsOff(); + normals_generator->SetFeatureAngle(0.1); + normals_generator->SetSplitting(0); + normals_generator->SetConsistency(1); + normals_generator->SetAutoOrientNormals(0); + normals_generator->SetFlipNormals(0); + normals_generator->SetNonManifoldTraversal(1); + VtkUtils::SetInputData(normals_generator, polydata); + normals_generator->Update(); + return normals_generator->GetOutput(); + } }; inline vtkSmartPointer vtkmatrix(const cv::Matx44d &matrix) diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index bf01ff5a5..19e2b9394 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -285,21 +285,9 @@ void cv::viz::writeTrajectory(InputArray _traj, const String& files_format, int void cv::viz::computeNormals(const Mesh3d& mesh, OutputArray _normals) { vtkSmartPointer polydata = getPolyData(WMesh(mesh)); + vtkSmartPointer with_normals = VtkUtils::ComputeNormals(polydata); - vtkSmartPointer normal_generator = vtkSmartPointer::New(); - normal_generator->SetInputConnection(polydata->GetProducerPort()); - normal_generator->ComputePointNormalsOn(); - normal_generator->ComputeCellNormalsOff(); - - normal_generator->SetFeatureAngle(0.1); - normal_generator->SetSplitting(0); - normal_generator->SetConsistency(1); - normal_generator->SetAutoOrientNormals(0); - normal_generator->SetFlipNormals(0); - normal_generator->SetNonManifoldTraversal(1); - normal_generator->Update(); - - vtkSmartPointer generic_normals = normal_generator->GetOutput()->GetPointData()->GetNormals(); + vtkSmartPointer generic_normals = with_normals->GetPointData()->GetNormals(); if(generic_normals) { Mat normals(1, generic_normals->GetNumberOfTuples(), CV_64FC3); diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index b0e84037f..a633f24ba 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -141,10 +141,10 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals()) { vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); - vtkSmartPointer normals = vtkSmartPointer::New(); - VtkUtils::SetInputData(normals, mapper->GetInput()); - normals->Update(); - VtkUtils::SetInputData(mapper, normals->GetOutput()); + CV_Assert("Can't set shading property for such type of widget" && mapper); + + vtkSmartPointer with_normals = VtkUtils::ComputeNormals(mapper->GetInput()); + VtkUtils::SetInputData(mapper, with_normals); } actor->GetProperty()->SetInterpolationToGouraud(); break; @@ -154,10 +154,10 @@ void cv::viz::Widget::setRenderingProperty(int property, double value) if (!actor->GetMapper()->GetInput()->GetPointData()->GetNormals()) { vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); - vtkSmartPointer normals = vtkSmartPointer::New(); - VtkUtils::SetInputData(normals, mapper->GetInput()); - normals->Update(); - VtkUtils::SetInputData(mapper, normals->GetOutput()); + CV_Assert("Can't set shading property for such type of widget" && mapper); + + vtkSmartPointer with_normals = VtkUtils::ComputeNormals(mapper->GetInput()); + VtkUtils::SetInputData(mapper, with_normals); } actor->GetProperty()->SetInterpolationToPhong(); break; From 8309d19f319df0ac23aa7e27f859d6bf2e40b0e5 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 9 Jan 2014 20:26:51 +0400 Subject: [PATCH 157/295] renamed Mesh3d -> Mesh --- modules/viz/doc/viz3d.rst | 20 +++++------ modules/viz/doc/widget.rst | 38 ++++++++------------- modules/viz/include/opencv2/viz.hpp | 2 +- modules/viz/include/opencv2/viz/types.hpp | 22 ++++++------ modules/viz/include/opencv2/viz/widgets.hpp | 3 +- modules/viz/src/clouds.cpp | 16 +++++++-- modules/viz/src/types.cpp | 6 ++-- modules/viz/src/vizcore.cpp | 2 +- modules/viz/test/tests_simple.cpp | 8 ++--- 9 files changed, 60 insertions(+), 57 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index 215437eda..9d4bb674d 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -468,31 +468,31 @@ This class a represents BGR color. :: static Color gray(); }; -viz::Mesh3d +viz::Mesh ----------- -.. ocv:class:: Mesh3d +.. ocv:class:: Mesh This class wraps mesh attributes, and it can load a mesh from a ``ply`` file. :: - class CV_EXPORTS Mesh3d + class CV_EXPORTS Mesh { public: - Mat cloud, colors; + Mat cloud, colors, normals; + + //! Raw integer list of the form: (n,id1,id2,...,idn, n,id1,id2,...,idn, ...) + //! where n is the number of points in the poligon, and id is a zero-offset index into an associated cloud. Mat polygons; //! Loads mesh from a given ply file - static Mesh3d load(const String& file); - - private: - /* hidden */ + static Mesh load(const String& file); }; -viz::Mesh3d::load +viz::Mesh::load --------------------- Loads a mesh from a ``ply`` file. -.. ocv:function:: static Mesh3d load(const String& file) +.. ocv:function:: static Mesh load(const String& file) :param file: File name (for no only PLY is supported) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 55dca7679..a8dcedd4b 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -264,8 +264,6 @@ This 3D Widget defines a finite plane. :: public: WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()); WPlane(const Vec4d& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()); - private: - /* hidden */ }; viz::WPlane::WPlane @@ -437,9 +435,6 @@ This 3D Widget defines a poly line. :: { public: WPolyLine(InputArray points, const Color &color = Color::white()); - - private: - /* hidden */ }; viz::WPolyLine::WPolyLine @@ -464,8 +459,6 @@ This 3D Widget defines a grid. :: WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); //! Creates grid based on the plane equation WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); - private: - /* hidden */ }; viz::WGrid::WGrid @@ -732,14 +725,14 @@ This 3D Widget represents a trajectory. :: enum {FRAMES = 1, PATH = 2, BOTH = FRAMES + PATH}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.f, const Color &color = Color::white(),; + WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.0, const Color &color = Color::white(),; }; viz::WTrajectory::WTrajectory ----------------------------- Constructs a WTrajectory. -.. ocv:function:: WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.f, const Color &color = Color::white()) +.. ocv:function:: WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] :param display_mode: Display mode. This can be PATH, FRAMES, and BOTH. @@ -828,9 +821,6 @@ This 3D Widget defines a point cloud. :: WCloud(InputArray cloud, InputArray colors); //! All points in cloud have the same color WCloud(InputArray cloud, const Color &color = Color::white()); - - private: - /* hidden */ }; viz::WCloud::WCloud @@ -868,9 +858,6 @@ This 3D Widget defines a collection of clouds. :: void addCloud(InputArray cloud, InputArray colors, const Affine3d &pose = Affine3d::Identity()); //! All points in cloud have the same color void addCloud(InputArray cloud, const Color &color = Color::white(), Affine3d &pose = Affine3d::Identity()); - - private: - /* hidden */ }; viz::WCloudCollection::WCloudCollection @@ -911,9 +898,6 @@ This 3D Widget represents normals of a point cloud. :: { public: WCloudNormals(InputArray cloud, InputArray normals, int level = 100, double scale = 0.02f, const Color &color = Color::white()); - - private: - /* hidden */ }; viz::WCloudNormals::WCloudNormals @@ -939,16 +923,22 @@ This 3D Widget defines a mesh. :: class CV_EXPORTS WMesh : public Widget3D { public: - WMesh(const Mesh3d &mesh); - - private: - /* hidden */ + WMesh(const Mesh &mesh); + WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()); }; viz::WMesh::WMesh ----------------- Constructs a WMesh. -.. ocv:function:: WMesh(const Mesh3d &mesh) +.. ocv:function:: WMesh(const Mesh &mesh) - :param mesh: :ocv:class:`Mesh3d` object that will be displayed. + :param mesh: :ocv:class:`Mesh` object that will be displayed. + +.. ocv:function:: WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()); + + :param cloud: Points of the mesh object. + :param polygons: Points of the mesh object. + :param colors: Point colors. + :param normals: Point normals. + diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index d2b46dd0e..9b1f21a8d 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -111,7 +111,7 @@ namespace cv /////////////////////////////////////////////////////////////////////////////////////////////// /// Computing normals for mesh - CV_EXPORTS void computeNormals(const Mesh3d& mesh, OutputArray normals); + CV_EXPORTS void computeNormals(const Mesh& mesh, OutputArray normals); } /* namespace viz */ } /* namespace cv */ diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 1e222c800..01ddd0289 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -104,15 +104,17 @@ namespace cv static Color amethyst(); }; - class CV_EXPORTS Mesh3d + class CV_EXPORTS Mesh { public: - Mat cloud, colors, normals; + + //! Raw integer list of the form: (n,id1,id2,...,idn, n,id1,id2,...,idn, ...) + //! where n is the number of points in the poligon, and id is a zero-offset index into an associated cloud. Mat polygons; //! Loads mesh from a given ply file - static Mesh3d load(const String& file); + static Mesh load(const String& file); }; class CV_EXPORTS Camera @@ -123,17 +125,17 @@ namespace cv explicit Camera(const Matx33d &K, const Size &window_size); explicit Camera(const Matx44d &proj, const Size &window_size); - inline const Vec2d & getClip() const { return clip_; } - inline void setClip(const Vec2d &clip) { clip_ = clip; } + const Vec2d & getClip() const { return clip_; } + void setClip(const Vec2d &clip) { clip_ = clip; } - inline const Size & getWindowSize() const { return window_size_; } + const Size & getWindowSize() const { return window_size_; } void setWindowSize(const Size &window_size); - inline const Vec2d& getFov() const { return fov_; } - inline void setFov(const Vec2d& fov) { fov_ = fov; } + const Vec2d& getFov() const { return fov_; } + void setFov(const Vec2d& fov) { fov_ = fov; } - inline const Vec2d& getPrincipalPoint() const { return principal_point_; } - inline const Vec2d& getFocalLength() const { return focal_; } + const Vec2d& getPrincipalPoint() const { return principal_point_; } + const Vec2d& getFocalLength() const { return focal_; } void computeProjectionMatrix(Matx44d &proj) const; diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 5b575774f..4dde94df6 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -316,7 +316,8 @@ namespace cv class CV_EXPORTS WMesh : public Widget3D { public: - WMesh(const Mesh3d &mesh); + WMesh(const Mesh &mesh); + WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()); }; ///////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index ceb4d9c0b..e7759e323 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -257,7 +257,7 @@ template<> cv::viz::WCloudNormals cv::viz::Widget::cast( /////////////////////////////////////////////////////////////////////////////////////////////// /// Mesh Widget implementation -cv::viz::WMesh::WMesh(const Mesh3d &mesh) +cv::viz::WMesh::WMesh(const Mesh &mesh) { CV_Assert(mesh.cloud.rows == 1 && mesh.polygons.type() == CV_32SC1); @@ -300,8 +300,8 @@ cv::viz::WMesh::WMesh(const Mesh3d &mesh) vtkSmartPointer cell_array = vtkSmartPointer::New(); int idx = 0; - int poly_size = mesh.polygons.total(); - for (int i = 0; i < poly_size; ++idx) + size_t polygons_size = mesh.polygons.total(); + for (size_t i = 0; i < polygons_size; ++idx) { int n_points = polygons[i++]; @@ -330,6 +330,16 @@ cv::viz::WMesh::WMesh(const Mesh3d &mesh) WidgetAccessor::setProp(*this, actor); } +cv::viz::WMesh::WMesh(InputArray cloud, InputArray polygons, InputArray colors, InputArray normals) +{ + Mesh mesh; + mesh.cloud = cloud.getMat(); + mesh.colors = colors.getMat(); + mesh.normals = normals.getMat(); + mesh.polygons = polygons.getMat(); + *this = WMesh(mesh); +} + template<> CV_EXPORTS cv::viz::WMesh cv::viz::Widget::cast() { Widget3D widget = this->cast(); diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index d233e735d..09a2f4d0f 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -61,9 +61,9 @@ namespace cv { namespace viz { namespace { struct MeshUtils { - static Mesh3d loadMesh(const String &file) + static Mesh loadMesh(const String &file) { - Mesh3d mesh; + Mesh mesh; vtkSmartPointer reader = vtkSmartPointer::New(); reader->SetFileName(file.c_str()); @@ -128,7 +128,7 @@ namespace cv { namespace viz { namespace }; }}} -cv::viz::Mesh3d cv::viz::Mesh3d::load(const String& file) +cv::viz::Mesh cv::viz::Mesh::load(const String& file) { return MeshUtils::loadMesh(file); } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index 19e2b9394..d00a22b4c 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -282,7 +282,7 @@ void cv::viz::writeTrajectory(InputArray _traj, const String& files_format, int /////////////////////////////////////////////////////////////////////////////////////////////// /// Computing normals for mesh -void cv::viz::computeNormals(const Mesh3d& mesh, OutputArray _normals) +void cv::viz::computeNormals(const Mesh& mesh, OutputArray _normals) { vtkSmartPointer polydata = getPolyData(WMesh(mesh)); vtkSmartPointer with_normals = VtkUtils::ComputeNormals(polydata); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 93428c6b9..4fd0dc4fc 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -106,7 +106,7 @@ TEST(Viz, DISABLED_show_cloud_collection) TEST(Viz, DISABLED_show_mesh) { - Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + Mesh mesh = Mesh::load(get_dragon_ply_file_path()); Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); @@ -118,7 +118,7 @@ TEST(Viz, DISABLED_show_mesh) TEST(Viz, DISABLED_show_mesh_random_colors) { - Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + Mesh mesh = Mesh::load(get_dragon_ply_file_path()); theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); @@ -144,7 +144,7 @@ TEST(Viz, DISABLED_show_polyline) TEST(Viz, DISABLED_show_sampled_normals) { - Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + Mesh mesh = Mesh::load(get_dragon_ply_file_path()); computeNormals(mesh, mesh.normals); Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); @@ -201,7 +201,7 @@ TEST(Viz, DISABLED_show_trajectory_reposition) TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) { - Mesh3d mesh = Mesh3d::load(get_dragon_ply_file_path()); + Mesh mesh = Mesh::load(get_dragon_ply_file_path()); Viz3d viz("spin_twice"); viz.showWidget("coosys", WCoordinateSystem()); From 462d516743bf9bc5d6fc8eabe1a250828e6b8bae Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 10 Jan 2014 00:31:27 +0400 Subject: [PATCH 158/295] added test for camera positions, slightly refactored the widgets --- modules/viz/src/shapes.cpp | 188 +++++++++++++----------------- modules/viz/test/tests_simple.cpp | 27 +++++ 2 files changed, 110 insertions(+), 105 deletions(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index f4b68a9fb..422ea9be3 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -622,29 +622,29 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) ConvertToVtkImage::convert(image, vtk_image); // Need to flip the image as the coordinates are different in OpenCV and VTK - vtkSmartPointer flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); - flipFilter->Update(); + vtkSmartPointer flip_filter = vtkSmartPointer::New(); + flip_filter->SetFilteredAxis(1); // Vertical flip + flip_filter->SetInputConnection(vtk_image->GetProducerPort()); + flip_filter->Update(); // Scale the image based on the Rect vtkSmartPointer transform = vtkSmartPointer::New(); - transform->Scale(double(image.cols)/rect.width,double(image.rows)/rect.height,1.0); + transform->Scale(image.cols/(double)rect.width, image.rows/(double)rect.height, 1.0); vtkSmartPointer image_reslice = vtkSmartPointer::New(); image_reslice->SetResliceTransform(transform); - image_reslice->SetInputConnection(flipFilter->GetOutputPort()); + image_reslice->SetInputConnection(flip_filter->GetOutputPort()); image_reslice->SetOutputDimensionality(2); image_reslice->InterpolateOn(); image_reslice->AutoCropOutputOn(); - vtkSmartPointer imageMapper = vtkSmartPointer::New(); - imageMapper->SetInputConnection(image_reslice->GetOutputPort()); - imageMapper->SetColorWindow(255); // OpenCV color - imageMapper->SetColorLevel(127.5); + vtkSmartPointer image_mapper = vtkSmartPointer::New(); + image_mapper->SetInputConnection(image_reslice->GetOutputPort()); + image_mapper->SetColorWindow(255); // OpenCV color + image_mapper->SetColorLevel(127.5); vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(imageMapper); + actor->SetMapper(image_mapper); actor->SetPosition(rect.x, rect.y); WidgetAccessor::setProp(*this, actor); @@ -820,93 +820,6 @@ namespace cv { namespace viz { namespace { struct CameraPositionUtils { - static void projectImage(double fovy, double far_end_height, const Mat &image, - double scale, const Color &color, vtkSmartPointer actor) - { - // Create a camera - vtkSmartPointer camera = vtkSmartPointer::New(); - float aspect_ratio = float(image.cols)/float(image.rows); - - // Create the vtk image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); - - // Adjust a pixel of the vtk_image - vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 0, color[2]); - vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 1, color[1]); - vtk_image->SetScalarComponentFromDouble(0, image.rows-1, 0, 2, color[0]); - - // Need to flip the image as the coordinates are different in OpenCV and VTK - vtkSmartPointer flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); - flipFilter->Update(); - - Vec3d plane_center(0.0, 0.0, scale); - - vtkSmartPointer plane = vtkSmartPointer::New(); - plane->SetCenter(plane_center[0], plane_center[1], plane_center[2]); - plane->SetNormal(0.0, 0.0, 1.0); - - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->Translate(plane_center[0], plane_center[1], plane_center[2]); - transform->Scale(far_end_height*aspect_ratio, far_end_height, 1.0); - transform->RotateY(180.0); - transform->Translate(-plane_center[0], -plane_center[1], -plane_center[2]); - - // Apply the texture - vtkSmartPointer texture = vtkSmartPointer::New(); - texture->SetInputConnection(flipFilter->GetOutputPort()); - - vtkSmartPointer texturePlane = vtkSmartPointer::New(); - texturePlane->SetInputConnection(plane->GetOutputPort()); - - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetTransform(transform); - transform_filter->SetInputConnection(texturePlane->GetOutputPort()); - transform_filter->Update(); - - // Create frustum - camera->SetViewAngle(fovy); - camera->SetPosition(0.0, 0.0, 0.0); - camera->SetViewUp(0.0, 1.0, 0.0); - camera->SetFocalPoint(0.0, 0.0, 1.0); - camera->SetClippingRange(0.01, scale); - - double planesArray[24]; - camera->GetFrustumPlanes(aspect_ratio, planesArray); - - vtkSmartPointer planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); - - vtkSmartPointer frustumSource = - vtkSmartPointer::New(); - frustumSource->SetPlanes(planes); - frustumSource->Update(); - - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(frustumSource->GetOutputPort()); - filter->Update(); - - // Frustum needs to be textured or else it can't be combined with image - vtkSmartPointer frustum_texture = vtkSmartPointer::New(); - frustum_texture->SetInputConnection(filter->GetOutputPort()); - // Texture mapping with only one pixel from the image to have constant color - frustum_texture->SetSRange(0.0, 0.0); - frustum_texture->SetTRange(0.0, 0.0); - - vtkSmartPointer appendFilter = vtkSmartPointer::New(); - appendFilter->AddInputConnection(frustum_texture->GetOutputPort()); - appendFilter->AddInputConnection(transform_filter->GetOutputPort()); - - vtkSmartPointer planeMapper = vtkSmartPointer::New(); - planeMapper->SetInputConnection(appendFilter->GetOutputPort()); - - actor->SetMapper(planeMapper); - actor->SetTexture(texture); - } - static vtkSmartPointer createFrustum(double aspect_ratio, double fovy, double scale) { vtkSmartPointer camera = vtkSmartPointer::New(); @@ -916,11 +829,11 @@ namespace cv { namespace viz { namespace camera->SetFocalPoint(0.0, 0.0, 1.0); camera->SetClippingRange(1e-9, scale); - double planesArray[24]; - camera->GetFrustumPlanes(aspect_ratio, planesArray); + double planes_array[24]; + camera->GetFrustumPlanes(aspect_ratio, planes_array); vtkSmartPointer planes = vtkSmartPointer::New(); - planes->SetFrustumPlanes(planesArray); + planes->SetFrustumPlanes(planes_array); vtkSmartPointer frustumSource = vtkSmartPointer::New(); frustumSource->SetPlanes(planes); @@ -932,6 +845,73 @@ namespace cv { namespace viz { namespace return extract_edges->GetOutput(); } + static vtkSmartPointer projectImage(double fovy, double far_end_height, const Mat &image, double scale, const Color &color) + { + float aspect_ratio = float(image.cols)/float(image.rows); + + // Create the vtk image + vtkSmartPointer vtk_image = vtkSmartPointer::New(); + ConvertToVtkImage::convert(image, vtk_image); + + // Adjust a pixel of the vtk_image + if(image.channels() == 1) + { + double gray = color[2] * 0.299 + color[1] * 0.578 + color[0] * 0.144; + vtk_image->SetScalarComponentFromDouble(0, 0, 0, 0, gray); + } + else + { + vtk_image->SetScalarComponentFromDouble(0, 0, 0, 0, color[2]); + vtk_image->SetScalarComponentFromDouble(0, 0, 0, 1, color[1]); + vtk_image->SetScalarComponentFromDouble(0, 0, 0, 2, color[0]); + } + + Vec3d plane_center(0.0, 0.0, scale); + + vtkSmartPointer plane = vtkSmartPointer::New(); + plane->SetCenter(plane_center.val); + plane->SetNormal(0.0, 0.0, 1.0); + + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->PreMultiply(); + transform->Translate(plane_center.val); + transform->Scale(far_end_height*aspect_ratio, far_end_height, 1.0); + transform->RotateY(180.0); + transform->Translate(-plane_center[0], -plane_center[1], -plane_center[2]); + + // Apply the texture + vtkSmartPointer texture = vtkSmartPointer::New(); + texture->SetInputConnection(vtk_image->GetProducerPort()); + + vtkSmartPointer texture_plane = vtkSmartPointer::New(); + texture_plane->SetInputConnection(plane->GetOutputPort()); + + vtkSmartPointer transform_filter = vtkSmartPointer::New(); + transform_filter->SetInputConnection(texture_plane->GetOutputPort()); + transform_filter->SetTransform(transform); + + vtkSmartPointer frustum = createFrustum(aspect_ratio, fovy, scale); + + // Frustum needs to be textured or else it can't be combined with image + vtkSmartPointer frustum_texture = vtkSmartPointer::New(); + frustum_texture->SetInputConnection(frustum->GetProducerPort()); + // Texture mapping with only one pixel from the image to have constant color + frustum_texture->SetSRange(0.0, 0.0); + frustum_texture->SetTRange(0.0, 0.0); + + vtkSmartPointer appendFilter = vtkSmartPointer::New(); + appendFilter->AddInputConnection(frustum_texture->GetOutputPort()); + appendFilter->AddInputConnection(transform_filter->GetOutputPort()); + + vtkSmartPointer planeMapper = vtkSmartPointer::New(); + planeMapper->SetInputConnection(appendFilter->GetOutputPort()); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->SetMapper(planeMapper); + actor->SetTexture(texture); + + return actor; + } }; }}} @@ -994,8 +974,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, const Mat &image, do double fovy = 2.0 * atan2(c_y, f_y) * 180.0 / CV_PI; double far_end_height = 2.00 * c_y * scale / f_y; - vtkSmartPointer actor = vtkSmartPointer::New(); - CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); + vtkSmartPointer actor = CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color); WidgetAccessor::setProp(*this, actor); } @@ -1005,8 +984,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, const Mat &image, do double fovy = fov[1] * 180.0 / CV_PI; double far_end_height = 2.0 * scale * tan(fov[1] * 0.5); - vtkSmartPointer actor = vtkSmartPointer::New(); - CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color, actor); + vtkSmartPointer actor = CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color); WidgetAccessor::setProp(*this, actor); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 4fd0dc4fc..4f37f3221 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -199,6 +199,33 @@ TEST(Viz, DISABLED_show_trajectory_reposition) } + +TEST(Viz, show_camera_positions) +{ + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + Mat chs[3]; split(lena, chs); + Mat gray = 0.114 * chs[0] + 0.58 * chs[1] + 0.3 * chs[2]; + + Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0); + + Affine3d poses[2]; + for(int i = 0; i < 2; ++i) + { + Vec3d pose = 5 * Vec3d(sin(3.14 + 2.7 + i*60 * CV_PI/180), 0.4 - i*0.3, cos(3.14 + 2.7 + i*60 * CV_PI/180)); + poses[i] = makeCameraPose(pose, Vec3d(0.0, 0.0, 0.0), Vec3d(0.0, -0.1, 0.0)); + } + + Viz3d viz("show_camera_positions"); + viz.showWidget("sphe", WSphere(Point3d(0,0,0), 1.0)); + viz.showWidget("coos", WCoordinateSystem(1.5)); + viz.showWidget("pos1", WCameraPosition(0.75), poses[0]); + viz.showWidget("pos2", WCameraPosition(Vec2d(0.78, 0.78), lena, 2.2, Color::green()), poses[0]); + + viz.showWidget("pos3", WCameraPosition(0.75), poses[1]); + viz.showWidget("pos4", WCameraPosition(K, gray, 3, Color::indigo()), poses[1]); + viz.spin(); +} + TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); From f37c31742ae6a94f8d4bd2f9cda0725ed39e5c3d Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 10 Jan 2014 01:57:11 +0400 Subject: [PATCH 159/295] created tests for images, created vtk/vtkImageMatSource, and switched all images to that class --- modules/viz/src/precomp.hpp | 2 + modules/viz/src/shapes.cpp | 41 ++++--- modules/viz/src/vizimpl.hpp | 63 ---------- modules/viz/src/vtk/vtkCloudMatSink.h | 2 +- modules/viz/src/vtk/vtkCloudMatSource.h | 2 +- modules/viz/src/vtk/vtkImageMatSource.cpp | 140 ++++++++++++++++++++++ modules/viz/src/vtk/vtkImageMatSource.h | 84 +++++++++++++ modules/viz/src/vtk/vtkOBJWriter.h | 2 +- modules/viz/src/vtk/vtkTrajectorySource.h | 2 +- modules/viz/src/vtk/vtkXYZWriter.h | 6 +- modules/viz/test/test_precomp.hpp | 6 + modules/viz/test/tests_simple.cpp | 33 ++++- 12 files changed, 286 insertions(+), 97 deletions(-) create mode 100644 modules/viz/src/vtk/vtkImageMatSource.cpp create mode 100644 modules/viz/src/vtk/vtkImageMatSource.h diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 425502d64..3b4e3619d 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -125,6 +125,7 @@ #include #include #include +#include #if !defined(_WIN32) || defined(__CYGWIN__) # include /* unlink */ @@ -137,6 +138,7 @@ #include #include #include +#include #include #include diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 422ea9be3..6f4392b0f 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -617,15 +617,13 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) { CV_Assert(!image.empty() && image.depth() == CV_8U); - // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flip_filter = vtkSmartPointer::New(); flip_filter->SetFilteredAxis(1); // Vertical flip - flip_filter->SetInputConnection(vtk_image->GetProducerPort()); - flip_filter->Update(); + flip_filter->SetInputConnection(source->GetOutputPort()); // Scale the image based on the Rect vtkSmartPointer transform = vtkSmartPointer::New(); @@ -637,6 +635,7 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) image_reslice->SetOutputDimensionality(2); image_reslice->InterpolateOn(); image_reslice->AutoCropOutputOn(); + image_reslice->Update(); vtkSmartPointer image_mapper = vtkSmartPointer::New(); image_mapper->SetInputConnection(image_reslice->GetOutputPort()); @@ -661,13 +660,13 @@ void cv::viz::WImageOverlay::setImage(const Mat &image) CV_Assert("This widget does not support overlay image." && mapper); // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(source->GetOutputPort()); flipFilter->Update(); mapper->SetInputConnection(flipFilter->GetOutputPort()); @@ -686,14 +685,13 @@ cv::viz::WImage3D::WImage3D(const Mat &image, const Size &size) { CV_Assert(!image.empty() && image.depth() == CV_8U); - // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(source->GetOutputPort()); flipFilter->Update(); Vec3d plane_center(size.width * 0.5, size.height * 0.5, 0.0); @@ -735,13 +733,13 @@ cv::viz::WImage3D::WImage3D(const Vec3d &position, const Vec3d &normal, const Ve CV_Assert(!image.empty() && image.depth() == CV_8U); // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(source->GetOutputPort()); flipFilter->Update(); vtkSmartPointer plane = vtkSmartPointer::New(); @@ -790,14 +788,13 @@ void cv::viz::WImage3D::setImage(const Mat &image) vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("This widget does not support 3D image." && actor); - // Create the vtk image and set its parameters based on input image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flipFilter = vtkSmartPointer::New(); flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(vtk_image->GetProducerPort()); + flipFilter->SetInputConnection(source->GetOutputPort()); flipFilter->Update(); // Apply the texture @@ -850,8 +847,10 @@ namespace cv { namespace viz { namespace float aspect_ratio = float(image.cols)/float(image.rows); // Create the vtk image - vtkSmartPointer vtk_image = vtkSmartPointer::New(); - ConvertToVtkImage::convert(image, vtk_image); + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); + source->Update(); + vtkSmartPointer vtk_image = source->GetOutput(); // Adjust a pixel of the vtk_image if(image.channels() == 1) diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index 03d5c0325..f9ccf0944 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -179,67 +179,4 @@ private: bool removeActorFromRenderer(const vtkSmartPointer &actor); }; -namespace cv -{ - namespace viz - { - struct color_tag {}; - struct gray_tag {}; - - inline Vec3b fetchRgb(const unsigned char* color, color_tag) { return Vec3b(color[2], color[1], color[0]); } - inline Vec3b fetchRgb(const unsigned char* color, gray_tag) { return Vec3b(color[0], color[0], color[0]); } - - struct ConvertToVtkImage - { - struct Impl - { - typedef unsigned char uchar; - - static void copyImage(const Mat &source, vtkSmartPointer output, color_tag tag) - { - for (int y = 0; y < source.rows; ++y) - { - const uchar *srow = source.ptr(y); - for (int x = 0; x < source.cols; ++x, srow += source.channels()) - *reinterpret_cast(output->GetScalarPointer(x,y,0)) = fetchRgb(srow, tag); - } - output->Modified(); - } - - static void copyImage(const Mat &source, vtkSmartPointer output, gray_tag) - { - for (int y = 0; y < source.rows; ++y) - { - const uchar *srow = source.ptr(y); - for (int x = 0; x < source.cols; ++x) - *reinterpret_cast(output->GetScalarPointer(x,y,0)) = *srow++; - } - output->Modified(); - } - }; - - static void convert(const Mat &image, vtkSmartPointer output) - { - // Create the vtk image - output->SetDimensions(image.cols, image.rows, 1); -#if VTK_MAJOR_VERSION <= 5 - output->SetNumberOfScalarComponents(image.channels()); - output->SetScalarTypeToUnsignedChar(); - output->AllocateScalars(); -#else - output->AllocateScalars(VTK_UNSIGNED_CHAR, image.channels()); -#endif - switch(image.channels()) - { - case 1: Impl::copyImage(image, output, gray_tag()); break; - case 3: - case 4: Impl::copyImage(image, output, color_tag()); break; - default: - CV_Assert(!"Unsupported channel number"); - } - } - }; - } -} - #endif diff --git a/modules/viz/src/vtk/vtkCloudMatSink.h b/modules/viz/src/vtk/vtkCloudMatSink.h index 1d299f47c..69262f247 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.h +++ b/modules/viz/src/vtk/vtkCloudMatSink.h @@ -56,7 +56,7 @@ namespace cv { public: static vtkCloudMatSink *New(); - vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter); + vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter) void PrintSelf(ostream& os, vtkIndent indent); void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray()); diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index 00e6adf1e..a7f9fff89 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -59,7 +59,7 @@ namespace cv { public: static vtkCloudMatSource *New(); - vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm); + vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm) virtual int SetCloud(InputArray cloud); virtual int SetColorCloud(InputArray cloud, InputArray colors = noArray()); diff --git a/modules/viz/src/vtk/vtkImageMatSource.cpp b/modules/viz/src/vtk/vtkImageMatSource.cpp new file mode 100644 index 000000000..2147039d7 --- /dev/null +++ b/modules/viz/src/vtk/vtkImageMatSource.cpp @@ -0,0 +1,140 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkImageMatSource); +}} + +cv::viz::vtkImageMatSource::vtkImageMatSource() +{ + this->SetNumberOfInputPorts(0); + this->ImageData = vtkImageData::New(); +} + +int cv::viz::vtkImageMatSource::RequestInformation(vtkInformation *, vtkInformationVector**, vtkInformationVector *outputVector) +{ + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->ImageData->GetExtent(), 6); + outInfo->Set(vtkDataObject::SPACING(), 1.0, 1.0, 1.0); + outInfo->Set(vtkDataObject::ORIGIN(), 0.0, 0.0, 0.0); + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->ImageData->GetScalarType(), this->ImageData->GetNumberOfScalarComponents()); + return 1; +} + +int cv::viz::vtkImageMatSource::RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkImageData *output = vtkImageData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()) ); + output->ShallowCopy(this->ImageData); + return 1; +} + +void cv::viz::vtkImageMatSource::SetImage(InputArray _image) +{ + CV_Assert(_image.depth() == CV_8U && _image.channels() == 1 || _image.channels() == 3 || _image.channels() == 4); + + Mat image = _image.getMat(); + + this->ImageData->SetDimensions(image.cols, image.rows, 1); +#if VTK_MAJOR_VERSION <= 5 + this->ImageData->SetNumberOfScalarComponents(std::min(3, image.channels())); + this->ImageData->SetScalarTypeToUnsignedChar(); + this->ImageData->AllocateScalars(); +#else + this->ImageData->AllocateScalars(VTK_UNSIGNED_CHAR, std::min(3, image.channels())); +#endif + + switch(image.channels()) + { + case 1: copyGrayImage(image, this->ImageData); + case 3: copyRGBImage (image, this->ImageData); + case 4: copyRGBAImage(image, this->ImageData); + } + this->ImageData->Modified(); +} + +void cv::viz::vtkImageMatSource::copyGrayImage(const Mat &source, vtkSmartPointer output) +{ + for (int y = 0; y < source.rows; ++y) + { + const unsigned char *srow = source.ptr(y); + for (int x = 0; x < source.cols; ++x) + *reinterpret_cast(output->GetScalarPointer(x,y,0)) = *srow++; + } +} + +void cv::viz::vtkImageMatSource::copyRGBImage(const Mat &source, vtkSmartPointer output) +{ + for (int y = 0; y < source.rows; ++y) + { + const unsigned char *srow = source.ptr(y); + for (int x = 0; x < source.cols; ++x, srow += source.channels()) + *reinterpret_cast(output->GetScalarPointer(x,y,0)) = Vec3b(srow[2], srow[1], srow[0]); + } +} + +void cv::viz::vtkImageMatSource::copyRGBAImage(const Mat &source, vtkSmartPointer output) +{ + for (int y = 0; y < source.rows; ++y) + { + const unsigned char *srow = source.ptr(y); + for (int x = 0; x < source.cols; ++x, srow += source.channels()) + *reinterpret_cast(output->GetScalarPointer(x,y,0)) = Vec4b(srow[2], srow[1], srow[0], srow[3]); + } +} diff --git a/modules/viz/src/vtk/vtkImageMatSource.h b/modules/viz/src/vtk/vtkImageMatSource.h new file mode 100644 index 000000000..a4340346c --- /dev/null +++ b/modules/viz/src/vtk/vtkImageMatSource.h @@ -0,0 +1,84 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +#ifndef __vtkImageMatSource_h +#define __vtkImageMatSource_h + +namespace cv +{ + namespace viz + { + class vtkImageMatSource : public vtkImageAlgorithm + { + public: + static vtkImageMatSource *New(); + vtkTypeMacro(vtkImageMatSource,vtkImageAlgorithm); + + void SetImage(InputArray image); + + protected: + vtkImageMatSource(); + ~vtkImageMatSource() {} + + vtkSmartPointer ImageData; + + int RequestInformation(vtkInformation*, vtkInformationVector**, vtkInformationVector*); + int RequestData (vtkInformation*, vtkInformationVector**, vtkInformationVector*); + private: + vtkImageMatSource(const vtkImageMatSource&); // Not implemented. + void operator=(const vtkImageMatSource&); // Not implemented. + + static void copyGrayImage(const Mat &source, vtkSmartPointer output); + static void copyRGBImage (const Mat &source, vtkSmartPointer output); + static void copyRGBAImage(const Mat &source, vtkSmartPointer output); + }; + } +} + + +#endif + + diff --git a/modules/viz/src/vtk/vtkOBJWriter.h b/modules/viz/src/vtk/vtkOBJWriter.h index 9bf5403e4..f8889884d 100644 --- a/modules/viz/src/vtk/vtkOBJWriter.h +++ b/modules/viz/src/vtk/vtkOBJWriter.h @@ -55,7 +55,7 @@ namespace cv { public: static vtkOBJWriter *New(); - vtkTypeMacro(vtkOBJWriter,vtkPolyDataWriter); + vtkTypeMacro(vtkOBJWriter,vtkPolyDataWriter) void PrintSelf(ostream& os, vtkIndent indent); vtkGetMacro(DecimalPrecision, int); diff --git a/modules/viz/src/vtk/vtkTrajectorySource.h b/modules/viz/src/vtk/vtkTrajectorySource.h index 918250965..f6c9c77b9 100644 --- a/modules/viz/src/vtk/vtkTrajectorySource.h +++ b/modules/viz/src/vtk/vtkTrajectorySource.h @@ -59,7 +59,7 @@ namespace cv { public: static vtkTrajectorySource *New(); - vtkTypeMacro(vtkTrajectorySource,vtkPolyDataAlgorithm); + vtkTypeMacro(vtkTrajectorySource,vtkPolyDataAlgorithm) virtual void SetTrajectory(InputArray trajectory); diff --git a/modules/viz/src/vtk/vtkXYZWriter.h b/modules/viz/src/vtk/vtkXYZWriter.h index bc49d10ef..3db18b793 100644 --- a/modules/viz/src/vtk/vtkXYZWriter.h +++ b/modules/viz/src/vtk/vtkXYZWriter.h @@ -55,11 +55,11 @@ namespace cv { public: static vtkXYZWriter *New(); - vtkTypeMacro(vtkXYZWriter,vtkPolyDataWriter); + vtkTypeMacro(vtkXYZWriter,vtkPolyDataWriter) void PrintSelf(ostream& os, vtkIndent indent); - vtkGetMacro(DecimalPrecision, int); - vtkSetMacro(DecimalPrecision, int); + vtkGetMacro(DecimalPrecision, int) + vtkSetMacro(DecimalPrecision, int) protected: vtkXYZWriter(); diff --git a/modules/viz/test/test_precomp.hpp b/modules/viz/test/test_precomp.hpp index e4fe78420..1a5c4fe1c 100644 --- a/modules/viz/test/test_precomp.hpp +++ b/modules/viz/test/test_precomp.hpp @@ -93,6 +93,12 @@ namespace cv } return result; } + + inline Mat make_gray(const Mat& image) + { + Mat chs[3]; split(image, chs); + return 0.114 * chs[0] + 0.58 * chs[1] + 0.3 * chs[2]; + } } #endif diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 4f37f3221..8ded955ed 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -198,15 +198,11 @@ TEST(Viz, DISABLED_show_trajectory_reposition) viz.spin(); } - - TEST(Viz, show_camera_positions) { - Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); - Mat chs[3]; split(lena, chs); - Mat gray = 0.114 * chs[0] + 0.58 * chs[1] + 0.3 * chs[2]; - Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0); + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + Mat gray = make_gray(lena); Affine3d poses[2]; for(int i = 0; i < 2; ++i) @@ -226,6 +222,31 @@ TEST(Viz, show_camera_positions) viz.spin(); } +TEST(Viz, show_overlay_image) +{ + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + Mat gray = make_gray(lena); + + Viz3d viz("show_overlay_image"); + viz.showWidget("coos", WCoordinateSystem()); + viz.showWidget("img1", WImageOverlay(lena, Rect(Point(0, 0), Size_(viz.getWindowSize()) * 0.5))); + viz.showWidget("img2", WImageOverlay(gray, Rect(Point(640, 0), Size_(viz.getWindowSize()) * 0.5))); + viz.spin(); +} + +TEST(Viz, show_image_3d) +{ + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + Mat gray = make_gray(lena); + + Viz3d viz("show_image_3d"); + viz.showWidget("coos", WCoordinateSystem(100)); + viz.showWidget("img1", WImage3D(lena, Size(lena.cols, lena.rows/2)), makeCameraPose(Vec3d(1.0, 1.0, 1.0), Vec3d::all(0.0), Vec3d(0.0, -1.0, 0.0))); + viz.showWidget("img2", WImage3D(Vec3d(1.0, -1.0, 1.0), Vec3d(-1, 1, -1), Vec3d(0.0, -1.0, 0.0), gray, lena.size())); + + viz.spin(); +} + TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); From e3ff28dacc312d86b236c2e32848b3cdc6fe138f Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 10 Jan 2014 19:57:16 +0400 Subject: [PATCH 160/295] refactored WImage3D --- modules/viz/doc/widget.rst | 34 ++++-- modules/viz/include/opencv2/viz/widgets.hpp | 15 ++- modules/viz/src/precomp.hpp | 47 +++++--- modules/viz/src/shapes.cpp | 119 +++++--------------- modules/viz/src/vizcore.cpp | 3 - modules/viz/src/vizimpl.cpp | 2 +- modules/viz/src/vizimpl.hpp | 2 +- modules/viz/src/vtk/vtkCloudMatSource.cpp | 1 + modules/viz/src/widget.cpp | 11 ++ modules/viz/test/tests_simple.cpp | 36 ++++-- 10 files changed, 134 insertions(+), 136 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index a8dcedd4b..54b740b0b 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -170,13 +170,16 @@ Base class of all 3D widgets. :: public: Widget3D() {} + //! widget position manipulation, i.e. place where it is rendered. void setPose(const Affine3d &pose); void updatePose(const Affine3d &pose); Affine3d getPose() const; + //! updates internal widget data, i.e. points, normals, etc. + void applyTransform(const Affine3d &transform); + void setColor(const Color &color); - private: - /* hidden */ + }; viz::Widget3D::setPose @@ -201,6 +204,15 @@ Returns the current pose of the widget. .. ocv:function:: Affine3d getWidgetPose() const + +viz::Widget3D::applyTransform +------------------------------- +Transforms internal widget data (i.e. points, normals) using the given transform. + +.. ocv:function:: void applyTransform(const Affine3d &transform); + + :param transform: Specified transformation to apply. + viz::Widget3D::setColor ----------------------- Sets the color of the widget. @@ -598,25 +610,25 @@ This 3D Widget represents an image in 3D space. :: class CV_EXPORTS WImage3D : public Widget3D { - public: - //! Creates 3D image at the origin - WImage3D(const Mat &image, const Size &size); - //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size); + public: + //! Creates 3D image at the origin + WImage3D(const Mat &image, const Size2d &size); + //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation + WImage3D(const Mat &image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector); - void setImage(const Mat &image); - }; + void setImage(const Mat &image); + }; viz::WImage3D::WImage3D ----------------------- Constructs an WImage3D. -.. ocv:function:: WImage3D(const Mat &image, const Size &size) +.. ocv:function:: WImage3D(const Mat &image, const Size2d &size) :param image: BGR or Gray-Scale image. :param size: Size of the image. -.. ocv:function:: WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size) +.. ocv:function:: WImage3D(const Mat &image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector) :param position: Position of the image. :param normal: Normal of the plane that represents the image. diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 4dde94df6..49a0512cc 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -111,10 +111,14 @@ namespace cv public: Widget3D() {} + //! widget position manipulation, i.e. place where it is rendered void setPose(const Affine3d &pose); void updatePose(const Affine3d &pose); Affine3d getPose() const; + //! update internal widget data, i.e. points, normals, etc. + void applyTransform(const Affine3d &transform); + void setColor(const Color &color); }; @@ -172,7 +176,8 @@ namespace cv class CV_EXPORTS WCube : public Widget3D { public: - WCube(const Point3d& pt_min, const Point3d& pt_max, bool wire_frame = true, const Color &color = Color::white()); + WCube(const Point3d& min_point = Vec3d::all(-0.5), const Point3d& max_point = Vec3d::all(0.5), + bool wire_frame = true, const Color &color = Color::white()); }; class CV_EXPORTS WPolyLine : public Widget3D @@ -213,10 +218,12 @@ namespace cv class CV_EXPORTS WImage3D : public Widget3D { public: - //! Creates 3D image at the origin - WImage3D(const Mat &image, const Size &size); + //! Creates 3D image in a plane centered at the origin with normal orientaion along z-axis, + //! image x- and y-axes are oriented along x- and y-axes of 3d world + WImage3D(const Mat &image, const Size2d &size); + //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size); + WImage3D(const Mat &image, const Size2d &size, const Vec3d ¢er, const Vec3d &normal, const Vec3d &up_vector); void setImage(const Mat &image); }; diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 3b4e3619d..98de7b7f6 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -126,6 +126,7 @@ #include #include #include +#include #if !defined(_WIN32) || defined(__CYGWIN__) # include /* unlink */ @@ -175,6 +176,8 @@ namespace cv friend class Viz3d; }; + template inline _Tp normalized(const _Tp& v) { return v * 1/norm(v); } + template inline bool isNan(const _Tp* data) { return isNan(data[0]) || isNan(data[1]) || isNan(data[2]); @@ -187,10 +190,24 @@ namespace cv return vtkPolyData::SafeDownCast(mapper->GetInput()); } + inline vtkSmartPointer vtkmatrix(const cv::Matx44d &matrix) + { + vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); + vtk_matrix->DeepCopy(matrix.val); + return vtk_matrix; + } + + inline Color vtkcolor(const Color& color) + { + Color scaled_color = color * (1.0/255.0); + std::swap(scaled_color[0], scaled_color[2]); + return scaled_color; + } + struct VtkUtils { template - static void SetInputData(vtkSmartPointer filter, vtkPolyData *polydata) + static void SetInputData(vtkSmartPointer filter, vtkPolyData* polydata) { #if VTK_MAJOR_VERSION <= 5 filter->SetInput(polydata); @@ -238,23 +255,19 @@ namespace cv normals_generator->Update(); return normals_generator->GetOutput(); } + + static vtkSmartPointer TransformPolydata(vtkSmartPointer polydata, const Affine3d& pose) + { + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->SetMatrix(vtkmatrix(pose.matrix)); + + vtkSmartPointer transform_filter = vtkSmartPointer::New(); + transform_filter->SetTransform(transform); + transform_filter->SetInputConnection(polydata->GetProducerPort()); + transform_filter->Update(); + return transform_filter->GetOutput(); + } }; - - inline vtkSmartPointer vtkmatrix(const cv::Matx44d &matrix) - { - vtkSmartPointer vtk_matrix = vtkSmartPointer::New(); - vtk_matrix->DeepCopy(matrix.val); - return vtk_matrix; - } - - inline Color vtkcolor(const Color& color) - { - Color scaled_color = color * (1.0/255.0); - std::swap(scaled_color[0], scaled_color[2]); - return scaled_color; - } - - template inline _Tp normalized(const _Tp& v) { return v * 1/norm(v); } } } diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 6f4392b0f..9a9b2fccd 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -294,18 +294,18 @@ template<> cv::viz::WCylinder cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// cylinder widget implementation -cv::viz::WCube::WCube(const Point3d& pt_min, const Point3d& pt_max, bool wire_frame, const Color &color) +cv::viz::WCube::WCube(const Point3d& min_point, const Point3d& max_point, bool wire_frame, const Color &color) { vtkSmartPointer cube; if (wire_frame) { cube = vtkSmartPointer::New(); - vtkOutlineSource::SafeDownCast(cube)->SetBounds(pt_min.x, pt_max.x, pt_min.y, pt_max.y, pt_min.z, pt_max.z); + vtkOutlineSource::SafeDownCast(cube)->SetBounds(min_point.x, max_point.x, min_point.y, max_point.y, min_point.z, max_point.z); } else { cube = vtkSmartPointer::New(); - vtkCubeSource::SafeDownCast(cube)->SetBounds(pt_min.x, pt_max.x, pt_min.y, pt_max.y, pt_min.z, pt_max.z); + vtkCubeSource::SafeDownCast(cube)->SetBounds(min_point.x, max_point.x, min_point.y, max_point.y, min_point.z, max_point.z); } cube->Update(); @@ -620,10 +620,9 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); - // Need to flip the image as the coordinates are different in OpenCV and VTK vtkSmartPointer flip_filter = vtkSmartPointer::New(); - flip_filter->SetFilteredAxis(1); // Vertical flip flip_filter->SetInputConnection(source->GetOutputPort()); + flip_filter->SetFilteredAxis(1); // Scale the image based on the Rect vtkSmartPointer transform = vtkSmartPointer::New(); @@ -663,13 +662,11 @@ void cv::viz::WImageOverlay::setImage(const Mat &image) vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); - // Need to flip the image as the coordinates are different in OpenCV and VTK - vtkSmartPointer flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(source->GetOutputPort()); - flipFilter->Update(); + vtkSmartPointer flip_filter = vtkSmartPointer::New(); + flip_filter->SetInputConnection(source->GetOutputPort()); + flip_filter->SetFilteredAxis(1); - mapper->SetInputConnection(flipFilter->GetOutputPort()); + mapper->SetInputConnection(flip_filter->GetOutputPort()); } template<> cv::viz::WImageOverlay cv::viz::Widget::cast() @@ -681,104 +678,49 @@ template<> cv::viz::WImageOverlay cv::viz::Widget::cast( /////////////////////////////////////////////////////////////////////////////////////////////// /// image 3D widget implementation -cv::viz::WImage3D::WImage3D(const Mat &image, const Size &size) +cv::viz::WImage3D::WImage3D(const Mat &image, const Size2d &size) { CV_Assert(!image.empty() && image.depth() == CV_8U); vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); - // Need to flip the image as the coordinates are different in OpenCV and VTK - vtkSmartPointer flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(source->GetOutputPort()); - flipFilter->Update(); - - Vec3d plane_center(size.width * 0.5, size.height * 0.5, 0.0); + vtkSmartPointer texture = vtkSmartPointer::New(); + texture->SetInputConnection(source->GetOutputPort()); vtkSmartPointer plane = vtkSmartPointer::New(); - plane->SetCenter(plane_center[0], plane_center[1], plane_center[2]); - plane->SetNormal(0.0, 0.0, 1.0); + plane->SetOrigin(-0.5 * size.width, -0.5 * size.height, 0.0); + plane->SetPoint1( 0.5 * size.width, -0.5 * size.height, 0.0); + plane->SetPoint2(-0.5 * size.width, 0.5 * size.height, 0.0); - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->Translate(plane_center[0], plane_center[1], plane_center[2]); - transform->Scale(size.width, size.height, 1.0); - transform->Translate(-plane_center[0], -plane_center[1], -plane_center[2]); + vtkSmartPointer textured_plane = vtkSmartPointer::New(); + textured_plane->SetInputConnection(plane->GetOutputPort()); - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetTransform(transform); - transform_filter->SetInputConnection(plane->GetOutputPort()); - transform_filter->Update(); - - // Apply the texture - vtkSmartPointer texture = vtkSmartPointer::New(); - texture->SetInputConnection(flipFilter->GetOutputPort()); - - vtkSmartPointer texturePlane = vtkSmartPointer::New(); - texturePlane->SetInputConnection(transform_filter->GetOutputPort()); - - vtkSmartPointer planeMapper = vtkSmartPointer::New(); - planeMapper->SetInputConnection(texturePlane->GetOutputPort()); + vtkSmartPointer mapper = vtkSmartPointer::New(); + mapper->SetInputConnection(textured_plane->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(planeMapper); + actor->SetMapper(mapper); actor->SetTexture(texture); + actor->GetProperty()->ShadingOff(); + actor->GetProperty()->LightingOff(); WidgetAccessor::setProp(*this, actor); } -cv::viz::WImage3D::WImage3D(const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector, const Mat &image, const Size &size) +cv::viz::WImage3D::WImage3D(const Mat &image, const Size2d &size, const Vec3d ¢er, const Vec3d &normal, const Vec3d &up_vector) { CV_Assert(!image.empty() && image.depth() == CV_8U); - // Create the vtk image and set its parameters based on input image - vtkSmartPointer source = vtkSmartPointer::New(); - source->SetImage(image); - - // Need to flip the image as the coordinates are different in OpenCV and VTK - vtkSmartPointer flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(source->GetOutputPort()); - flipFilter->Update(); - - vtkSmartPointer plane = vtkSmartPointer::New(); - plane->SetCenter(0.0, 0.0, 0.0); - plane->SetNormal(0.0, 0.0, 1.0); - // Compute the transformation matrix for drawing the camera frame in a scene Vec3d n = normalize(normal); Vec3d u = normalize(up_vector.cross(n)); Vec3d v = n.cross(u); + Affine3d pose = makeTransformToGlobal(u, v, n, center); - Affine3d pose = makeTransformToGlobal(u, v, n, position); - - // Apply the texture - vtkSmartPointer texture = vtkSmartPointer::New(); - texture->SetInputConnection(flipFilter->GetOutputPort()); - - vtkSmartPointer texturePlane = vtkSmartPointer::New(); - texturePlane->SetInputConnection(plane->GetOutputPort()); - - // Apply the transform after texture mapping - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->SetMatrix(vtkmatrix(pose.matrix)); - transform->Scale(size.width, size.height, 1.0); - - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetTransform(transform); - transform_filter->SetInputConnection(texturePlane->GetOutputPort()); - transform_filter->Update(); - - vtkSmartPointer planeMapper = vtkSmartPointer::New(); - planeMapper->SetInputConnection(transform_filter->GetOutputPort()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(planeMapper); - actor->SetTexture(texture); - - WidgetAccessor::setProp(*this, actor); + WImage3D image3d(image, size); + image3d.applyTransform(pose); + *this = image3d; } void cv::viz::WImage3D::setImage(const Mat &image) @@ -791,15 +733,8 @@ void cv::viz::WImage3D::setImage(const Mat &image) vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); - // Need to flip the image as the coordinates are different in OpenCV and VTK - vtkSmartPointer flipFilter = vtkSmartPointer::New(); - flipFilter->SetFilteredAxis(1); // Vertical flip - flipFilter->SetInputConnection(source->GetOutputPort()); - flipFilter->Update(); - - // Apply the texture vtkSmartPointer texture = vtkSmartPointer::New(); - texture->SetInputConnection(flipFilter->GetOutputPort()); + texture->SetInputConnection(source->GetOutputPort()); actor->SetTexture(texture); } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index d00a22b4c..21c7e0d70 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -305,6 +305,3 @@ void cv::viz::computeNormals(const Mesh& mesh, OutputArray _normals) - - - diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 5974cc6e0..dd568c940 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -271,7 +271,7 @@ void cv::viz::Viz3d::VizImpl::removeAllWidgets() } ///////////////////////////////////////////////////////////////////////////////////////////// -bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(const vtkSmartPointer &actor) +bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(vtkSmartPointer actor) { vtkProp* actor_to_remove = vtkProp::SafeDownCast(actor); diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index f9ccf0944..b6ae54927 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -176,7 +176,7 @@ private: /** \brief Boolean that holds whether or not the camera parameters were manually initialized*/ bool camera_set_; - bool removeActorFromRenderer(const vtkSmartPointer &actor); + bool removeActorFromRenderer(vtkSmartPointer actor); }; #endif diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index f1dabe66b..7884f1a9a 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -212,6 +212,7 @@ template void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total) { normals = vtkSmartPointer< VtkDepthTraits<_Tn>::array_type >::New(); + normals->SetName("Normals"); normals->SetNumberOfComponents(3); normals->SetNumberOfTuples(total); diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index a633f24ba..6c1463b76 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -269,6 +269,17 @@ cv::Affine3d cv::viz::Widget3D::getPose() const return Affine3d(*actor->GetUserMatrix()->Element); } +void cv::viz::Widget3D::applyTransform(const Affine3d &transform) +{ + vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this)); + CV_Assert("Widget is not 3D actor." && actor); + + vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); + CV_Assert("Widget doesn't have a polydata mapper" && mapper); + + VtkUtils::SetInputData(mapper, VtkUtils::TransformPolydata(mapper->GetInput(), transform)); +} + void cv::viz::Widget3D::setColor(const Color &color) { // Cast to actor instead of prop3d since prop3d doesn't provide getproperty diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 8ded955ed..e31585b09 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -229,22 +229,44 @@ TEST(Viz, show_overlay_image) Viz3d viz("show_overlay_image"); viz.showWidget("coos", WCoordinateSystem()); - viz.showWidget("img1", WImageOverlay(lena, Rect(Point(0, 0), Size_(viz.getWindowSize()) * 0.5))); + viz.showWidget("cube", WCube(Vec3d::all(-0.5), Vec3d::all(0.5))); + viz.showWidget("img1", WImageOverlay(lena, Rect(Point(0, 400), Size_(viz.getWindowSize()) * 0.5))); viz.showWidget("img2", WImageOverlay(gray, Rect(Point(640, 0), Size_(viz.getWindowSize()) * 0.5))); - viz.spin(); + + int i = 0; + while(!viz.wasStopped()) + { + double a = ++i % 360; + Vec3d pose(sin(a * CV_PI/180), 0.7, cos(a * CV_PI/180)); + viz.setViewerPose(makeCameraPose(pose * 3, Vec3d(0.0, 0.5, 0.0), Vec3d(0.0, 0.1, 0.0))); + + viz.getWidget("img1").cast().setImage(lena * pow(sin(i*10*CV_PI/180) * 0.5 + 0.5, 1.0)); + //viz.getWidget("img1").cast().setImage(gray); + viz.spinOnce(1, true); + } + //viz.spin(); } -TEST(Viz, show_image_3d) +TEST(Viz, DISABLED_show_image_3d) { Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); Mat gray = make_gray(lena); Viz3d viz("show_image_3d"); - viz.showWidget("coos", WCoordinateSystem(100)); - viz.showWidget("img1", WImage3D(lena, Size(lena.cols, lena.rows/2)), makeCameraPose(Vec3d(1.0, 1.0, 1.0), Vec3d::all(0.0), Vec3d(0.0, -1.0, 0.0))); - viz.showWidget("img2", WImage3D(Vec3d(1.0, -1.0, 1.0), Vec3d(-1, 1, -1), Vec3d(0.0, -1.0, 0.0), gray, lena.size())); + viz.showWidget("coos", WCoordinateSystem()); + viz.showWidget("cube", WCube(Vec3d::all(-0.5), Vec3d::all(0.5))); + viz.showWidget("arr0", WArrow(Vec3d(0.5, 0.0, 0.0), Vec3d(1.5, 0.0, 0.0), 0.009, Color::raspberry())); + viz.showWidget("img0", WImage3D(lena, Size2d(1.0, 1.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(.5, 0.0, 0.0))); + viz.showWidget("arr1", WArrow(Vec3d(-0.5, -0.5, 0.0), Vec3d(0.2, 0.2, 0.0), 0.009, Color::raspberry())); + viz.showWidget("img1", WImage3D(gray, Size2d(1.0, 1.0), Vec3d(-0.5, -0.5, 0.0), Vec3d(1.0, 1.0, 0.0), Vec3d(0.0, 1.0, 0.0))); - viz.spin(); + int i = 0; + while(!viz.wasStopped()) + { + viz.getWidget("img0").cast().setImage(lena * pow(sin(i++*7.5*CV_PI/180) * 0.5 + 0.5, 1.0)); + viz.spinOnce(1, true); + } + //viz.spin(); } TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) From f930f2f19d115c89efb4790f342deb4f9814af1c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 16:44:01 +0400 Subject: [PATCH 161/295] simplification of cloud collection --- modules/viz/src/clouds.cpp | 9 +-------- modules/viz/src/precomp.hpp | 9 +++++++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index e7759e323..9ea1d76fe 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -112,15 +112,8 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co vtkSmartPointer source = vtkSmartPointer::New(); source->SetColorCloud(cloud, colors); - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->SetMatrix(pose.matrix.val); + vtkSmartPointer polydata = VtkUtils::TransformPolydata(source->GetOutputPort(), pose); - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetInputConnection(source->GetOutputPort()); - transform_filter->SetTransform(transform); - transform_filter->Update(); - - vtkSmartPointer polydata = transform_filter->GetOutput(); vtkSmartPointer actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("Incompatible widget type." && actor); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 98de7b7f6..df46f7048 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -256,17 +256,22 @@ namespace cv return normals_generator->GetOutput(); } - static vtkSmartPointer TransformPolydata(vtkSmartPointer polydata, const Affine3d& pose) + static vtkSmartPointer TransformPolydata(vtkSmartPointer algorithm_output_port, const Affine3d& pose) { vtkSmartPointer transform = vtkSmartPointer::New(); transform->SetMatrix(vtkmatrix(pose.matrix)); vtkSmartPointer transform_filter = vtkSmartPointer::New(); transform_filter->SetTransform(transform); - transform_filter->SetInputConnection(polydata->GetProducerPort()); + transform_filter->SetInputConnection(algorithm_output_port); transform_filter->Update(); return transform_filter->GetOutput(); } + + static vtkSmartPointer TransformPolydata(vtkSmartPointer polydata, const Affine3d& pose) + { + return TransformPolydata(polydata->GetProducerPort(), pose); + } }; } } From a23f1447a8005c0d85a82b4afccd7c6e5bc0408b Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 20:01:57 +0400 Subject: [PATCH 162/295] minor --- modules/viz/src/precomp.hpp | 8 +++-- modules/viz/src/shapes.cpp | 50 ++++++++++++++++++------------- modules/viz/test/tests_simple.cpp | 4 +-- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index df46f7048..98ab3ce63 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -183,10 +183,14 @@ namespace cv return isNan(data[0]) || isNan(data[1]) || isNan(data[2]); } + inline vtkSmartPointer getActor(const Widget3D& widget) + { + return vtkActor::SafeDownCast(WidgetAccessor::getProp(widget)); + } + inline vtkSmartPointer getPolyData(const Widget3D& widget) { - vtkSmartPointer prop = WidgetAccessor::getProp(widget); - vtkSmartPointer mapper = vtkActor::SafeDownCast(prop)->GetMapper(); + vtkSmartPointer mapper = getActor(widget)->GetMapper(); return vtkPolyData::SafeDownCast(mapper->GetInput()); } diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 9a9b2fccd..3295a5238 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -777,28 +777,34 @@ namespace cv { namespace viz { namespace return extract_edges->GetOutput(); } - static vtkSmartPointer projectImage(double fovy, double far_end_height, const Mat &image, double scale, const Color &color) + static vtkSmartPointer projectImage(vtkSmartPointer frustum, double far_end_height, const Mat &image, double scale, const Color &color) { - float aspect_ratio = float(image.cols)/float(image.rows); + Mat color_image = image; + if (color_image.channels() == 1) + { + color_image.create(image.size(), CV_8UC3); + Vec3b *drow = color_image.ptr(); + for(int y = 0; y < image.rows; ++y) + { + const unsigned char *srow = image.ptr(y); + const unsigned char *send = srow + image.cols; + for(;srow < send;) + *drow++ = Vec3b::all(*srow++); + } + } + + + double aspect_ratio = color_image.cols/(double)color_image.rows; // Create the vtk image vtkSmartPointer source = vtkSmartPointer::New(); - source->SetImage(image); + source->SetImage(color_image); source->Update(); vtkSmartPointer vtk_image = source->GetOutput(); - // Adjust a pixel of the vtk_image - if(image.channels() == 1) - { - double gray = color[2] * 0.299 + color[1] * 0.578 + color[0] * 0.144; - vtk_image->SetScalarComponentFromDouble(0, 0, 0, 0, gray); - } - else - { - vtk_image->SetScalarComponentFromDouble(0, 0, 0, 0, color[2]); - vtk_image->SetScalarComponentFromDouble(0, 0, 0, 1, color[1]); - vtk_image->SetScalarComponentFromDouble(0, 0, 0, 2, color[0]); - } + vtk_image->SetScalarComponentFromDouble(0, 0, 0, 0, color[2]); + vtk_image->SetScalarComponentFromDouble(0, 0, 0, 1, color[1]); + vtk_image->SetScalarComponentFromDouble(0, 0, 0, 2, color[0]); Vec3d plane_center(0.0, 0.0, scale); @@ -824,7 +830,7 @@ namespace cv { namespace viz { namespace transform_filter->SetInputConnection(texture_plane->GetOutputPort()); transform_filter->SetTransform(transform); - vtkSmartPointer frustum = createFrustum(aspect_ratio, fovy, scale); + // Frustum needs to be textured or else it can't be combined with image vtkSmartPointer frustum_texture = vtkSmartPointer::New(); @@ -901,14 +907,15 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, const Mat &image, double scale, const Color &color) { CV_Assert(!image.empty() && image.depth() == CV_8U); - double f_y = K(1,1), c_y = K(1,2); - // Assuming that this is an ideal camera (c_y and c_x are at the center of the image) double fovy = 2.0 * atan2(c_y, f_y) * 180.0 / CV_PI; double far_end_height = 2.00 * c_y * scale / f_y; + double aspect_ratio = image.cols/(double)image.rows; - vtkSmartPointer actor = CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color); + vtkSmartPointer frustum = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); + + vtkSmartPointer actor = CameraPositionUtils::projectImage(frustum, far_end_height, image, scale, color); WidgetAccessor::setProp(*this, actor); } @@ -917,8 +924,11 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, const Mat &image, do CV_Assert(!image.empty() && image.depth() == CV_8U); double fovy = fov[1] * 180.0 / CV_PI; double far_end_height = 2.0 * scale * tan(fov[1] * 0.5); + double aspect_ratio = image.cols/(double)image.rows; - vtkSmartPointer actor = CameraPositionUtils::projectImage(fovy, far_end_height, image, scale, color); + vtkSmartPointer frustum = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); + + vtkSmartPointer actor = CameraPositionUtils::projectImage(frustum, far_end_height, image, scale, color); WidgetAccessor::setProp(*this, actor); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index e31585b09..ea8a0b038 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -174,7 +174,7 @@ TEST(Viz, DISABLED_show_trajectories) viz.showWidget("sub1", WTrajectory(sub1, WTrajectory::PATH, 0.2, Color::brown())); viz.showWidget("sub2", WTrajectory(sub2, WTrajectory::FRAMES, 0.2)); viz.showWidget("sub3", WTrajectory(sub3, WTrajectory::BOTH, 0.2, Color::green())); - viz.showWidget("sub4", WTrajectoryFrustums(sub4, K, 0.3)); + viz.showWidget("sub4", WTrajectoryFrustums(sub4, K, 0.3, Color::yellow())); viz.showWidget("sub5", WTrajectoryFrustums(sub5, Vec2d(0.78, 0.78), 0.15)); int i = 0; @@ -212,7 +212,7 @@ TEST(Viz, show_camera_positions) } Viz3d viz("show_camera_positions"); - viz.showWidget("sphe", WSphere(Point3d(0,0,0), 1.0)); + viz.showWidget("sphe", WSphere(Point3d(0,0,0), 1.0, 10, Color::orange_red())); viz.showWidget("coos", WCoordinateSystem(1.5)); viz.showWidget("pos1", WCameraPosition(0.75), poses[0]); viz.showWidget("pos2", WCameraPosition(Vec2d(0.78, 0.78), lena, 2.2, Color::green()), poses[0]); From e21f2a81fff4a21a5bf9ef6a3b71588da24e28d9 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 20:40:10 +0400 Subject: [PATCH 163/295] factored camera postions with image --- modules/viz/doc/widget.rst | 8 +- modules/viz/include/opencv2/viz/widgets.hpp | 4 +- modules/viz/src/shapes.cpp | 127 +++++++++----------- 3 files changed, 60 insertions(+), 79 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 54b740b0b..ec4a858e2 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -660,9 +660,9 @@ This 3D Widget represents camera position in a scene by its axes or viewing frus //! Creates frustum based on the field of view at the origin WCameraPosition(const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Matx33d &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Matx33d &K, InputArray image, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Vec2d &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Vec2d &fov, InputArray image, double scale = 1.0, const Color &color = Color::white()); }; viz::WCameraPosition::WCameraPosition @@ -703,7 +703,7 @@ Constructs a WCameraPosition. - **Display image on the far plane of the viewing frustum.** - .. ocv:function:: WCameraPosition(const Matx33d &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Matx33d &K, InputArray image, double scale = 1.0, const Color &color = Color::white()) :param K: Intrinsic matrix of the camera. :param img: BGR or Gray-Scale image that is going to be displayed on the far plane of the frustum. @@ -712,7 +712,7 @@ Constructs a WCameraPosition. Creates viewing frustum of the camera based on its intrinsic matrix K, and displays image on the far end plane. - .. ocv:function:: WCameraPosition(const Vec2d &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Vec2d &fov, InputArray image, double scale = 1.0, const Color &color = Color::white()) :param fov: Field of view of the camera (horizontal, vertical). :param img: BGR or Gray-Scale image that is going to be displayed on the far plane of the frustum. diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 49a0512cc..44cb50074 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -256,9 +256,9 @@ namespace cv //! Creates frustum based on the field of view at the origin WCameraPosition(const Vec2d &fov, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Matx33d &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Matx33d &K, InputArray image, double scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Vec2d &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Vec2d &fov, InputArray image, double scale = 1.0, const Color &color = Color::white()); }; ///////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 3295a5238..2067c5c9e 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -777,80 +777,23 @@ namespace cv { namespace viz { namespace return extract_edges->GetOutput(); } - static vtkSmartPointer projectImage(vtkSmartPointer frustum, double far_end_height, const Mat &image, double scale, const Color &color) + static Mat ensureColorImage(InputArray image) { - Mat color_image = image; - if (color_image.channels() == 1) + Mat color(image.size(), CV_8UC3); + if (image.channels() == 1) { - color_image.create(image.size(), CV_8UC3); - Vec3b *drow = color_image.ptr(); - for(int y = 0; y < image.rows; ++y) + Vec3b *drow = color.ptr(); + for(int y = 0; y < color.rows; ++y) { - const unsigned char *srow = image.ptr(y); - const unsigned char *send = srow + image.cols; + const unsigned char *srow = image.getMat().ptr(y); + const unsigned char *send = srow + color.cols; for(;srow < send;) *drow++ = Vec3b::all(*srow++); } } - - - double aspect_ratio = color_image.cols/(double)color_image.rows; - - // Create the vtk image - vtkSmartPointer source = vtkSmartPointer::New(); - source->SetImage(color_image); - source->Update(); - vtkSmartPointer vtk_image = source->GetOutput(); - - vtk_image->SetScalarComponentFromDouble(0, 0, 0, 0, color[2]); - vtk_image->SetScalarComponentFromDouble(0, 0, 0, 1, color[1]); - vtk_image->SetScalarComponentFromDouble(0, 0, 0, 2, color[0]); - - Vec3d plane_center(0.0, 0.0, scale); - - vtkSmartPointer plane = vtkSmartPointer::New(); - plane->SetCenter(plane_center.val); - plane->SetNormal(0.0, 0.0, 1.0); - - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->Translate(plane_center.val); - transform->Scale(far_end_height*aspect_ratio, far_end_height, 1.0); - transform->RotateY(180.0); - transform->Translate(-plane_center[0], -plane_center[1], -plane_center[2]); - - // Apply the texture - vtkSmartPointer texture = vtkSmartPointer::New(); - texture->SetInputConnection(vtk_image->GetProducerPort()); - - vtkSmartPointer texture_plane = vtkSmartPointer::New(); - texture_plane->SetInputConnection(plane->GetOutputPort()); - - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetInputConnection(texture_plane->GetOutputPort()); - transform_filter->SetTransform(transform); - - - - // Frustum needs to be textured or else it can't be combined with image - vtkSmartPointer frustum_texture = vtkSmartPointer::New(); - frustum_texture->SetInputConnection(frustum->GetProducerPort()); - // Texture mapping with only one pixel from the image to have constant color - frustum_texture->SetSRange(0.0, 0.0); - frustum_texture->SetTRange(0.0, 0.0); - - vtkSmartPointer appendFilter = vtkSmartPointer::New(); - appendFilter->AddInputConnection(frustum_texture->GetOutputPort()); - appendFilter->AddInputConnection(transform_filter->GetOutputPort()); - - vtkSmartPointer planeMapper = vtkSmartPointer::New(); - planeMapper->SetInputConnection(appendFilter->GetOutputPort()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(planeMapper); - actor->SetTexture(texture); - - return actor; + else + image.copyTo(color); + return color; } }; }}} @@ -904,31 +847,69 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const setColor(color); } -cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, const Mat &image, double scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, InputArray _image, double scale, const Color &color) { - CV_Assert(!image.empty() && image.depth() == CV_8U); + CV_Assert(!_image.empty() && _image.depth() == CV_8U); + Mat image = CameraPositionUtils::ensureColorImage(_image); + image.at(0, 0) = Vec3d(color.val); //workaround of VTK limitation + double f_y = K(1,1), c_y = K(1,2); // Assuming that this is an ideal camera (c_y and c_x are at the center of the image) double fovy = 2.0 * atan2(c_y, f_y) * 180.0 / CV_PI; double far_end_height = 2.00 * c_y * scale / f_y; double aspect_ratio = image.cols/(double)image.rows; + double image_scale = far_end_height/image.rows; + + WImage3D image_widget(image, Size2d(image.size()) * image_scale); + image_widget.applyTransform(Affine3d().translate(Vec3d(0, 0, scale))); + vtkSmartPointer plane = getPolyData(image_widget); vtkSmartPointer frustum = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); - vtkSmartPointer actor = CameraPositionUtils::projectImage(frustum, far_end_height, image, scale, color); + // Frustum needs to be textured or else it can't be combined with image + vtkSmartPointer frustum_texture = vtkSmartPointer::New(); + frustum_texture->SetInputConnection(frustum->GetProducerPort()); + frustum_texture->SetSRange(0.0, 0.0); // Texture mapping with only one pixel + frustum_texture->SetTRange(0.0, 0.0); // from the image to have constant color + + vtkSmartPointer append_filter = vtkSmartPointer::New(); + append_filter->AddInputConnection(frustum_texture->GetOutputPort()); + append_filter->AddInputConnection(plane->GetProducerPort()); + + vtkSmartPointer actor = getActor(image_widget); + actor->GetMapper()->SetInputConnection(append_filter->GetOutputPort()); WidgetAccessor::setProp(*this, actor); } -cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, const Mat &image, double scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, InputArray _image, double scale, const Color &color) { - CV_Assert(!image.empty() && image.depth() == CV_8U); + CV_Assert(!_image.empty() && _image.depth() == CV_8U); + Mat image = CameraPositionUtils::ensureColorImage(_image); + image.at(0, 0) = Vec3d(color.val); //workaround of VTK limitation + double fovy = fov[1] * 180.0 / CV_PI; double far_end_height = 2.0 * scale * tan(fov[1] * 0.5); double aspect_ratio = image.cols/(double)image.rows; + double image_scale = far_end_height/image.rows; + + WImage3D image_widget(image, Size2d(image.size()) * image_scale); + image_widget.applyTransform(Affine3d().translate(Vec3d(0, 0, scale))); + vtkSmartPointer plane = getPolyData(image_widget); vtkSmartPointer frustum = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); - vtkSmartPointer actor = CameraPositionUtils::projectImage(frustum, far_end_height, image, scale, color); + // Frustum needs to be textured or else it can't be combined with image + vtkSmartPointer frustum_texture = vtkSmartPointer::New(); + frustum_texture->SetInputConnection(frustum->GetProducerPort()); + frustum_texture->SetSRange(0.0, 0.0); // Texture mapping with only one pixel + frustum_texture->SetTRange(0.0, 0.0); // from the image to have constant color + + vtkSmartPointer append_filter = vtkSmartPointer::New(); + append_filter->AddInputConnection(frustum_texture->GetOutputPort()); + append_filter->AddInputConnection(plane->GetProducerPort()); + + vtkSmartPointer actor = getActor(image_widget); + actor->GetMapper()->SetInputConnection(append_filter->GetOutputPort()); WidgetAccessor::setProp(*this, actor); } From cad9a786c4d64b9a4df0686e2f4cea345fea3f3c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 22:00:28 +0400 Subject: [PATCH 164/295] optimized Mat to vtkImageData conversion --- modules/viz/src/precomp.hpp | 1 + modules/viz/src/vtk/vtkImageMatSource.cpp | 37 ++++++++++++----------- modules/viz/test/tests_simple.cpp | 12 ++++---- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 98ab3ce63..9c76d9dea 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -127,6 +127,7 @@ #include #include #include +#include #if !defined(_WIN32) || defined(__CYGWIN__) # include /* unlink */ diff --git a/modules/viz/src/vtk/vtkImageMatSource.cpp b/modules/viz/src/vtk/vtkImageMatSource.cpp index 2147039d7..54500cb4b 100644 --- a/modules/viz/src/vtk/vtkImageMatSource.cpp +++ b/modules/viz/src/vtk/vtkImageMatSource.cpp @@ -44,15 +44,6 @@ #include "precomp.hpp" - -#include "vtkImageData.h" -#include "vtkImageProgressIterator.h" -#include "vtkMath.h" -#include "vtkInformation.h" -#include "vtkInformationVector.h" -#include "vtkObjectFactory.h" -#include "vtkStreamingDemandDrivenPipeline.h" - namespace cv { namespace viz { vtkStandardNewMacro(vtkImageMatSource); @@ -93,48 +84,60 @@ void cv::viz::vtkImageMatSource::SetImage(InputArray _image) this->ImageData->SetDimensions(image.cols, image.rows, 1); #if VTK_MAJOR_VERSION <= 5 - this->ImageData->SetNumberOfScalarComponents(std::min(3, image.channels())); + this->ImageData->SetNumberOfScalarComponents(image.channels()); this->ImageData->SetScalarTypeToUnsignedChar(); this->ImageData->AllocateScalars(); #else - this->ImageData->AllocateScalars(VTK_UNSIGNED_CHAR, std::min(3, image.channels())); + this->ImageData->AllocateScalars(VTK_UNSIGNED_CHAR, image.channels()); #endif switch(image.channels()) { - case 1: copyGrayImage(image, this->ImageData); - case 3: copyRGBImage (image, this->ImageData); - case 4: copyRGBAImage(image, this->ImageData); + case 1: copyGrayImage(image, this->ImageData); break; + case 3: copyRGBImage (image, this->ImageData); break; + case 4: copyRGBAImage(image, this->ImageData); break; } this->ImageData->Modified(); } void cv::viz::vtkImageMatSource::copyGrayImage(const Mat &source, vtkSmartPointer output) { + unsigned char* dptr = reinterpret_cast(output->GetScalarPointer()); + size_t elem_step = output->GetIncrements()[1]/sizeof(unsigned char); + for (int y = 0; y < source.rows; ++y) { + unsigned char* drow = dptr + elem_step * y; const unsigned char *srow = source.ptr(y); for (int x = 0; x < source.cols; ++x) - *reinterpret_cast(output->GetScalarPointer(x,y,0)) = *srow++; + drow[x] = *srow++; } } void cv::viz::vtkImageMatSource::copyRGBImage(const Mat &source, vtkSmartPointer output) { + Vec3b* dptr = reinterpret_cast(output->GetScalarPointer()); + size_t elem_step = output->GetIncrements()[1]/sizeof(Vec3b); + for (int y = 0; y < source.rows; ++y) { + Vec3b* drow = dptr + elem_step * y; const unsigned char *srow = source.ptr(y); for (int x = 0; x < source.cols; ++x, srow += source.channels()) - *reinterpret_cast(output->GetScalarPointer(x,y,0)) = Vec3b(srow[2], srow[1], srow[0]); + drow[x] = Vec3b(srow[2], srow[1], srow[0]); } } void cv::viz::vtkImageMatSource::copyRGBAImage(const Mat &source, vtkSmartPointer output) { + Vec4b* dptr = reinterpret_cast(output->GetScalarPointer()); + size_t elem_step = output->GetIncrements()[1]/sizeof(Vec4b); + for (int y = 0; y < source.rows; ++y) { + Vec4b* drow = dptr + elem_step * y; const unsigned char *srow = source.ptr(y); for (int x = 0; x < source.cols; ++x, srow += source.channels()) - *reinterpret_cast(output->GetScalarPointer(x,y,0)) = Vec4b(srow[2], srow[1], srow[0], srow[3]); + drow[x] = Vec4b(srow[2], srow[1], srow[0], srow[3]); } } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index ea8a0b038..6bca25588 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -198,7 +198,7 @@ TEST(Viz, DISABLED_show_trajectory_reposition) viz.spin(); } -TEST(Viz, show_camera_positions) +TEST(Viz, DISABLED_show_camera_positions) { Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0); Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); @@ -216,7 +216,6 @@ TEST(Viz, show_camera_positions) viz.showWidget("coos", WCoordinateSystem(1.5)); viz.showWidget("pos1", WCameraPosition(0.75), poses[0]); viz.showWidget("pos2", WCameraPosition(Vec2d(0.78, 0.78), lena, 2.2, Color::green()), poses[0]); - viz.showWidget("pos3", WCameraPosition(0.75), poses[1]); viz.showWidget("pos4", WCameraPosition(K, gray, 3, Color::indigo()), poses[1]); viz.spin(); @@ -229,9 +228,10 @@ TEST(Viz, show_overlay_image) Viz3d viz("show_overlay_image"); viz.showWidget("coos", WCoordinateSystem()); - viz.showWidget("cube", WCube(Vec3d::all(-0.5), Vec3d::all(0.5))); - viz.showWidget("img1", WImageOverlay(lena, Rect(Point(0, 400), Size_(viz.getWindowSize()) * 0.5))); - viz.showWidget("img2", WImageOverlay(gray, Rect(Point(640, 0), Size_(viz.getWindowSize()) * 0.5))); + viz.showWidget("cube", WCube()); + viz.showWidget("img1", WImageOverlay(lena, Rect(Point(0, 400), Size2d(viz.getWindowSize()) * 0.5))); + viz.showWidget("img2", WImageOverlay(gray, Rect(Point(640, 0), Size2d(viz.getWindowSize()) * 0.5))); + viz.spin(); int i = 0; while(!viz.wasStopped()) @@ -254,7 +254,7 @@ TEST(Viz, DISABLED_show_image_3d) Viz3d viz("show_image_3d"); viz.showWidget("coos", WCoordinateSystem()); - viz.showWidget("cube", WCube(Vec3d::all(-0.5), Vec3d::all(0.5))); + viz.showWidget("cube", WCube()); viz.showWidget("arr0", WArrow(Vec3d(0.5, 0.0, 0.0), Vec3d(1.5, 0.0, 0.0), 0.009, Color::raspberry())); viz.showWidget("img0", WImage3D(lena, Size2d(1.0, 1.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(.5, 0.0, 0.0))); viz.showWidget("arr1", WArrow(Vec3d(-0.5, -0.5, 0.0), Vec3d(0.2, 0.2, 0.0), 0.009, Color::raspberry())); From d90a068e0e725ff0c23c9379f3c3aac1350da0a5 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 22:13:45 +0400 Subject: [PATCH 165/295] fixed bug with setImage --- modules/viz/include/opencv2/viz/widgets.hpp | 1 - modules/viz/src/shapes.cpp | 31 +++++++++++++-------- modules/viz/test/tests_simple.cpp | 15 ++++++---- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 44cb50074..455c96557 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -211,7 +211,6 @@ namespace cv { public: WImageOverlay(const Mat &image, const Rect &rect); - void setImage(const Mat &image); }; diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 2067c5c9e..5dffbfa0e 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -616,21 +616,17 @@ cv::String cv::viz::WText::getText() const cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) { CV_Assert(!image.empty() && image.depth() == CV_8U); - vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); - vtkSmartPointer flip_filter = vtkSmartPointer::New(); - flip_filter->SetInputConnection(source->GetOutputPort()); - flip_filter->SetFilteredAxis(1); - - // Scale the image based on the Rect + // Scale the image based on the Rect, and flip to match y-ais orientation vtkSmartPointer transform = vtkSmartPointer::New(); transform->Scale(image.cols/(double)rect.width, image.rows/(double)rect.height, 1.0); + transform->RotateX(180); vtkSmartPointer image_reslice = vtkSmartPointer::New(); image_reslice->SetResliceTransform(transform); - image_reslice->SetInputConnection(flip_filter->GetOutputPort()); + image_reslice->SetInputConnection(source->GetOutputPort()); image_reslice->SetOutputDimensionality(2); image_reslice->InterpolateOn(); image_reslice->AutoCropOutputOn(); @@ -657,16 +653,29 @@ void cv::viz::WImageOverlay::setImage(const Mat &image) vtkImageMapper *mapper = vtkImageMapper::SafeDownCast(actor->GetMapper()); CV_Assert("This widget does not support overlay image." && mapper); + \ + Vec6i extent; + mapper->GetInput()->GetExtent(extent.val); + Size size(extent[1], extent[3]); // Create the vtk image and set its parameters based on input image vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); - vtkSmartPointer flip_filter = vtkSmartPointer::New(); - flip_filter->SetInputConnection(source->GetOutputPort()); - flip_filter->SetFilteredAxis(1); + // Scale the image based on the Rect, and flip to match y-ais orientation + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->Scale(image.cols/(double)size.width, image.rows/(double)size.height, 1.0); + transform->RotateX(180); - mapper->SetInputConnection(flip_filter->GetOutputPort()); + vtkSmartPointer image_reslice = vtkSmartPointer::New(); + image_reslice->SetResliceTransform(transform); + image_reslice->SetInputConnection(source->GetOutputPort()); + image_reslice->SetOutputDimensionality(2); + image_reslice->InterpolateOn(); + image_reslice->AutoCropOutputOn(); + image_reslice->Update(); + + mapper->SetInputConnection(image_reslice->GetOutputPort()); } template<> cv::viz::WImageOverlay cv::viz::Widget::cast() diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 6bca25588..ff35bd416 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -221,17 +221,22 @@ TEST(Viz, DISABLED_show_camera_positions) viz.spin(); } -TEST(Viz, show_overlay_image) +TEST(Viz, DISABLED_show_overlay_image) { Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); Mat gray = make_gray(lena); + Size2d half_lsize = Size2d(lena.size()) * 0.5; + Viz3d viz("show_overlay_image"); + Size vsz = viz.getWindowSize(); + viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); - viz.showWidget("img1", WImageOverlay(lena, Rect(Point(0, 400), Size2d(viz.getWindowSize()) * 0.5))); - viz.showWidget("img2", WImageOverlay(gray, Rect(Point(640, 0), Size2d(viz.getWindowSize()) * 0.5))); - viz.spin(); + viz.showWidget("img1", WImageOverlay(lena, Rect(Point(10, 10), half_lsize))); + viz.showWidget("img2", WImageOverlay(gray, Rect(Point(vsz.width-10-lena.cols/2, 10), half_lsize))); + viz.showWidget("img3", WImageOverlay(gray, Rect(Point(10, vsz.height-10-lena.rows/2), half_lsize))); + viz.showWidget("img5", WImageOverlay(lena, Rect(Point(vsz.width-10-lena.cols/2, vsz.height-10-lena.rows/2), half_lsize))); int i = 0; while(!viz.wasStopped()) @@ -239,9 +244,7 @@ TEST(Viz, show_overlay_image) double a = ++i % 360; Vec3d pose(sin(a * CV_PI/180), 0.7, cos(a * CV_PI/180)); viz.setViewerPose(makeCameraPose(pose * 3, Vec3d(0.0, 0.5, 0.0), Vec3d(0.0, 0.1, 0.0))); - viz.getWidget("img1").cast().setImage(lena * pow(sin(i*10*CV_PI/180) * 0.5 + 0.5, 1.0)); - //viz.getWidget("img1").cast().setImage(gray); viz.spinOnce(1, true); } //viz.spin(); From 1449823bcd5a1fd396bd90426fdf046fb232e4ac Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 22:43:58 +0400 Subject: [PATCH 166/295] implemented showImage --- .../viz/launching_viz/launching_viz.rst | 2 +- modules/viz/doc/viz3d.rst | 11 ++++++++++ modules/viz/doc/widget.rst | 20 +++++++++---------- modules/viz/include/opencv2/viz.hpp | 3 +++ modules/viz/include/opencv2/viz/viz3d.hpp | 2 ++ modules/viz/include/opencv2/viz/widgets.hpp | 10 +++++----- modules/viz/src/shapes.cpp | 17 +++++++++------- modules/viz/src/viz3d.cpp | 11 ++++++++++ modules/viz/src/vizcore.cpp | 7 +++++++ modules/viz/test/tests_simple.cpp | 14 +++++++++++++ 10 files changed, 74 insertions(+), 23 deletions(-) diff --git a/doc/tutorials/viz/launching_viz/launching_viz.rst b/doc/tutorials/viz/launching_viz/launching_viz.rst index 0bf31977d..a507a7f27 100644 --- a/doc/tutorials/viz/launching_viz/launching_viz.rst +++ b/doc/tutorials/viz/launching_viz/launching_viz.rst @@ -43,7 +43,7 @@ You can download the code from :download:`here <../../../../samples/cpp/tutorial cout << "First event loop is over" << endl; /// Access window via its name - viz::Viz3d sameWindow = viz::get("Viz Demo"); + viz::Viz3d sameWindow = viz::getWindowByName("Viz Demo"); /// Start event loop sameWindow.spin(); diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index 9d4bb674d..ec5b16e71 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -102,6 +102,8 @@ The Viz3d class represents a 3D visualizer window. This class is implicitly shar void setWidgetPose(const String &id, const Affine3d &pose); void updateWidgetPose(const String &id, const Affine3d &pose); Affine3d getWidgetPose(const String &id) const; + + void showImage(InputArray image, const Size& window_size = Size(-1, -1)); void setCamera(const Camera &camera); Camera getCamera() const; @@ -182,6 +184,15 @@ Removes all widgets from the window. .. ocv:function:: void removeAllWidgets() +viz::Viz3d::showImage +--------------------- +Removed all widgets and displays image scaled to whole window area. + +.. ocv:function:: void showImage(InputArray image, const Size& window_size = Size(-1, -1)); + + :param image: Image to be displayed. + :param size: Size of Viz3d window. Default value means no change. + viz::Viz3d::setWidgetPose ------------------------- Sets pose of a widget in the window. diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index ec4a858e2..c286339c2 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -580,16 +580,16 @@ This 2D Widget represents an image overlay. :: class CV_EXPORTS WImageOverlay : public Widget2D { public: - WImageOverlay(const Mat &image, const Rect &rect); + WImageOverlay(InputArray image, const Rect &rect); - void setImage(const Mat &image); + void setImage(InputArray image); }; viz::WImageOverlay::WImageOverlay --------------------------------- Constructs an WImageOverlay. -.. ocv:function:: WImageOverlay(const Mat &image, const Rect &rect) +.. ocv:function:: WImageOverlay(InputArray image, const Rect &rect) :param image: BGR or Gray-Scale image. :param rect: Image is scaled and positioned based on rect. @@ -598,7 +598,7 @@ viz::WImageOverlay::setImage ---------------------------- Sets the image content of the widget. -.. ocv:function:: void setImage(const Mat &image) +.. ocv:function:: void setImage(InputArray image) :param image: BGR or Gray-Scale image. @@ -612,23 +612,23 @@ This 3D Widget represents an image in 3D space. :: { public: //! Creates 3D image at the origin - WImage3D(const Mat &image, const Size2d &size); + WImage3D(InputArray image, const Size2d &size); //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(const Mat &image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector); + WImage3D(InputArray image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector); - void setImage(const Mat &image); + void setImage(InputArray image); }; viz::WImage3D::WImage3D ----------------------- Constructs an WImage3D. -.. ocv:function:: WImage3D(const Mat &image, const Size2d &size) +.. ocv:function:: WImage3D(InputArray image, const Size2d &size) :param image: BGR or Gray-Scale image. :param size: Size of the image. -.. ocv:function:: WImage3D(const Mat &image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector) +.. ocv:function:: WImage3D(InputArray image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector) :param position: Position of the image. :param normal: Normal of the plane that represents the image. @@ -640,7 +640,7 @@ viz::WImage3D::setImage ----------------------- Sets the image content of the widget. -.. ocv:function:: void setImage(const Mat &image) +.. ocv:function:: void setImage(InputArray image) :param image: BGR or Gray-Scale image. diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 9b1f21a8d..32e32a7a3 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -66,6 +66,9 @@ namespace cv //! Unregisters all Viz windows from internal database. After it 'getWindowByName()' will create new windows instead getting existing from the database. CV_EXPORTS void unregisterAllWindows(); + //! Displays image in specified window + CV_EXPORTS Viz3d imshow(const String& window_name, InputArray image, const Size& window_size = Size(-1, -1)); + //! checks float value for Nan inline bool isNan(float x) { diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index 7cd27eb61..4ffb6b3c5 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -75,6 +75,8 @@ namespace cv Widget getWidget(const String &id) const; void removeAllWidgets(); + void showImage(InputArray image, const Size& window_size = Size(-1, -1)); + void setWidgetPose(const String &id, const Affine3d &pose); void updateWidgetPose(const String &id, const Affine3d &pose); Affine3d getWidgetPose(const String &id) const; diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 455c96557..8ab95c92a 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -210,8 +210,8 @@ namespace cv class CV_EXPORTS WImageOverlay : public Widget2D { public: - WImageOverlay(const Mat &image, const Rect &rect); - void setImage(const Mat &image); + WImageOverlay(InputArray image, const Rect &rect); + void setImage(InputArray image); }; class CV_EXPORTS WImage3D : public Widget3D @@ -219,12 +219,12 @@ namespace cv public: //! Creates 3D image in a plane centered at the origin with normal orientaion along z-axis, //! image x- and y-axes are oriented along x- and y-axes of 3d world - WImage3D(const Mat &image, const Size2d &size); + WImage3D(InputArray image, const Size2d &size); //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(const Mat &image, const Size2d &size, const Vec3d ¢er, const Vec3d &normal, const Vec3d &up_vector); + WImage3D(InputArray image, const Size2d &size, const Vec3d ¢er, const Vec3d &normal, const Vec3d &up_vector); - void setImage(const Mat &image); + void setImage(InputArray image); }; ///////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 5dffbfa0e..611b1c3f9 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -613,15 +613,16 @@ cv::String cv::viz::WText::getText() const /////////////////////////////////////////////////////////////////////////////////////////////// /// image overlay widget implementation -cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) +cv::viz::WImageOverlay::WImageOverlay(InputArray image, const Rect &rect) { CV_Assert(!image.empty() && image.depth() == CV_8U); vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); + Size sz = image.size(); // Scale the image based on the Rect, and flip to match y-ais orientation vtkSmartPointer transform = vtkSmartPointer::New(); - transform->Scale(image.cols/(double)rect.width, image.rows/(double)rect.height, 1.0); + transform->Scale(sz.width/(double)rect.width, sz.height/(double)rect.height, 1.0); transform->RotateX(180); vtkSmartPointer image_reslice = vtkSmartPointer::New(); @@ -640,11 +641,12 @@ cv::viz::WImageOverlay::WImageOverlay(const Mat &image, const Rect &rect) vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(image_mapper); actor->SetPosition(rect.x, rect.y); + actor->GetProperty()->SetDisplayLocationToForeground(); WidgetAccessor::setProp(*this, actor); } -void cv::viz::WImageOverlay::setImage(const Mat &image) +void cv::viz::WImageOverlay::setImage(InputArray image) { CV_Assert(!image.empty() && image.depth() == CV_8U); @@ -661,10 +663,11 @@ void cv::viz::WImageOverlay::setImage(const Mat &image) // Create the vtk image and set its parameters based on input image vtkSmartPointer source = vtkSmartPointer::New(); source->SetImage(image); + Size sz = image.size(); // Scale the image based on the Rect, and flip to match y-ais orientation vtkSmartPointer transform = vtkSmartPointer::New(); - transform->Scale(image.cols/(double)size.width, image.rows/(double)size.height, 1.0); + transform->Scale(sz.width/(double)size.width, sz.height/(double)size.height, 1.0); transform->RotateX(180); vtkSmartPointer image_reslice = vtkSmartPointer::New(); @@ -687,7 +690,7 @@ template<> cv::viz::WImageOverlay cv::viz::Widget::cast( /////////////////////////////////////////////////////////////////////////////////////////////// /// image 3D widget implementation -cv::viz::WImage3D::WImage3D(const Mat &image, const Size2d &size) +cv::viz::WImage3D::WImage3D(InputArray image, const Size2d &size) { CV_Assert(!image.empty() && image.depth() == CV_8U); @@ -717,7 +720,7 @@ cv::viz::WImage3D::WImage3D(const Mat &image, const Size2d &size) WidgetAccessor::setProp(*this, actor); } -cv::viz::WImage3D::WImage3D(const Mat &image, const Size2d &size, const Vec3d ¢er, const Vec3d &normal, const Vec3d &up_vector) +cv::viz::WImage3D::WImage3D(InputArray image, const Size2d &size, const Vec3d ¢er, const Vec3d &normal, const Vec3d &up_vector) { CV_Assert(!image.empty() && image.depth() == CV_8U); @@ -732,7 +735,7 @@ cv::viz::WImage3D::WImage3D(const Mat &image, const Size2d &size, const Vec3d &c *this = image3d; } -void cv::viz::WImage3D::setImage(const Mat &image) +void cv::viz::WImage3D::setImage(InputArray image) { CV_Assert(!image.empty() && image.depth() == CV_8U); diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 33d851d64..a88632247 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -112,6 +112,17 @@ void cv::viz::Viz3d::showWidget(const String &id, const Widget &widget, const Af void cv::viz::Viz3d::removeWidget(const String &id) { impl_->removeWidget(id); } cv::viz::Widget cv::viz::Viz3d::getWidget(const String &id) const { return impl_->getWidget(id); } void cv::viz::Viz3d::removeAllWidgets() { impl_->removeAllWidgets(); } + + +void cv::viz::Viz3d::showImage(InputArray image, const Size& window_size) +{ + removeAllWidgets(); + if (window_size.width > 0 && window_size.height > 0) + setWindowSize(window_size); + + showWidget("showImage", WImageOverlay(image, Rect(Point(0,0), getWindowSize()))); +} + void cv::viz::Viz3d::setWidgetPose(const String &id, const Affine3d &pose) { impl_->setWidgetPose(id, pose); } void cv::viz::Viz3d::updateWidgetPose(const String &id, const Affine3d &pose) { impl_->updateWidgetPose(id, pose); } cv::Affine3d cv::viz::Viz3d::getWidgetPose(const String &id) const { return impl_->getWidgetPose(id); } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index 21c7e0d70..a553f8d72 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -122,6 +122,13 @@ cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) cv::viz::Viz3d cv::viz::getWindowByName(const String &window_name) { return Viz3d (window_name); } void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } +cv::viz::Viz3d cv::viz::imshow(const String& window_name, InputArray image, const Size& window_size) +{ + Viz3d viz = getWindowByName(window_name); + viz.showImage(image, window_size); + return viz; +} + /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write clouds. Supported formats: ply, stl, xyz, obj diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index ff35bd416..bb3f2009e 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -250,6 +250,20 @@ TEST(Viz, DISABLED_show_overlay_image) //viz.spin(); } + +TEST(Viz, DISABLED_show_image_method) +{ + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + + Viz3d viz("show_image_method"); + viz.showImage(lena); + viz.spinOnce(1500, true); + viz.showImage(lena, lena.size()); + viz.spinOnce(1500, true); + + cv::viz::imshow("show_image_method", make_gray(lena)).spin(); +} + TEST(Viz, DISABLED_show_image_3d) { Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); From dac27c99138ac2a578bbf2fd650b18b0704ccf5c Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 23:07:30 +0400 Subject: [PATCH 167/295] refactored arrow --- modules/viz/src/shapes.cpp | 17 ++++------------- modules/viz/test/tests_simple.cpp | 11 +++++++++++ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 611b1c3f9..6e0371a3f 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -192,22 +192,13 @@ cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness Vec3d zvec = normalized(xvec.cross(arbitrary)); Vec3d yvec = zvec.cross(xvec); - Affine3d pose = makeTransformToGlobal(xvec, yvec, zvec); + Matx33d R = makeTransformToGlobal(xvec, yvec, zvec).rotation(); + Affine3d transform_with_scale(R * length, startPoint); - // Apply the transforms - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->Translate(startPoint.val); - transform->Concatenate(vtkmatrix(pose.matrix)); - transform->Scale(length, length, length); - - // Transform the polydata - vtkSmartPointer transformPD = vtkSmartPointer::New(); - transformPD->SetTransform(transform); - transformPD->SetInputConnection(arrow_source->GetOutputPort()); - transformPD->Update(); + vtkSmartPointer polydata = VtkUtils::TransformPolydata(arrow_source->GetOutputPort(), transform_with_scale); vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, transformPD->GetOutput()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index bb3f2009e..4d9b1cfd1 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -277,6 +277,8 @@ TEST(Viz, DISABLED_show_image_3d) viz.showWidget("arr1", WArrow(Vec3d(-0.5, -0.5, 0.0), Vec3d(0.2, 0.2, 0.0), 0.009, Color::raspberry())); viz.showWidget("img1", WImage3D(gray, Size2d(1.0, 1.0), Vec3d(-0.5, -0.5, 0.0), Vec3d(1.0, 1.0, 0.0), Vec3d(0.0, 1.0, 0.0))); + viz.showWidget("arr3", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); + int i = 0; while(!viz.wasStopped()) { @@ -286,6 +288,15 @@ TEST(Viz, DISABLED_show_image_3d) //viz.spin(); } +TEST(Viz, show_simple_widgets) +{ + Viz3d viz("show_simple_widgets"); + viz.showWidget("coos", WCoordinateSystem()); + viz.showWidget("cube", WCube()); + viz.showWidget("arr3", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); + viz.spin(); +} + TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); From c0cc5512285caf038dd329f54f1e43a921aded6b Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 23:29:28 +0400 Subject: [PATCH 168/295] refactored circle --- modules/viz/doc/widget.rst | 27 ++++++++++--- modules/viz/include/opencv2/viz/widgets.hpp | 6 ++- modules/viz/src/precomp.hpp | 6 +++ modules/viz/src/shapes.cpp | 43 +++++++++++---------- modules/viz/test/tests_simple.cpp | 4 +- 5 files changed, 58 insertions(+), 28 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index c286339c2..f98039bbf 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -349,23 +349,38 @@ viz::WCircle This 3D Widget defines a circle. :: - class CV_EXPORTS WCircle : public Widget3D + class CV_EXPORTS WCircle : public Widget3D { public: - WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white()); + //! creates default planar circle centred at origin with plane normal along z-axis + WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()); + + //! creates repositioned circle + WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness = 0.01, const Color &color = Color::white()); }; viz::WCircle::WCircle ------------------------------- -Constructs a WCircle. +Constructs default planar circle centred at origin with plane normal along z-axis -.. ocv:function:: WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white()) +.. ocv:function:: WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()); - :param pt: Center of the circle. - :param radius: Radius of the circle. + :param radius: Radius of the circle. :param thickness: Thickness of the circle. :param color: :ocv:class:`Color` of the circle. +viz::WCircle::WCircle +------------------------------- +Constructs repositioned planar circle. + +.. ocv:function:: WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness = 0.01, const Color &color = Color::white()); + + :param radius: Radius of the circle. + :param center: Center of the circle. + :param normal: Normal of the plane in which the circle lies. + :param thickness: Thickness of the circle. + :param color: :ocv:class:`Color` of the circle. + viz::WCylinder -------------- .. ocv:class:: WCylinder diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 8ab95c92a..c58595635 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -164,7 +164,11 @@ namespace cv class CV_EXPORTS WCircle : public Widget3D { public: - WCircle(const Point3d& pt, double radius, double thickness = 0.01, const Color &color = Color::white()); + //! creates default circle centred at origin with normal along z-axis + WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()); + + //! creates repositioned circle + WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness = 0.01, const Color &color = Color::white()); }; class CV_EXPORTS WCylinder : public Widget3D diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 9c76d9dea..bc91191d1 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -209,6 +209,12 @@ namespace cv return scaled_color; } + inline Vec3d get_random_vec(double from = -10.0, double to = 10.0) + { + RNG& rng = theRNG(); + return Vec3d(rng.uniform(from, to), rng.uniform(from, to), rng.uniform(from, to)); + } + struct VtkUtils { template diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 6e0371a3f..6731087c0 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -182,18 +182,17 @@ cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness arrow_source->SetTipRadius(thickness * 3.0); arrow_source->SetTipLength(thickness * 10.0); - RNG rng = theRNG(); - Vec3d arbitrary(rng.uniform(-10.0, 10.0), rng.uniform(-10.0, 10.0), rng.uniform(-10.0, 10.0)); - Vec3d startPoint(pt1.x, pt1.y, pt1.z), endPoint(pt2.x, pt2.y, pt2.z); + Vec3d arbitrary = get_random_vec(); + Vec3d start_point(pt1.x, pt1.y, pt1.z), end_point(pt2.x, pt2.y, pt2.z); - double length = norm(endPoint - startPoint); + double length = norm(end_point - start_point); - Vec3d xvec = normalized(endPoint - startPoint); + Vec3d xvec = normalized(end_point - start_point); Vec3d zvec = normalized(xvec.cross(arbitrary)); Vec3d yvec = zvec.cross(xvec); Matx33d R = makeTransformToGlobal(xvec, yvec, zvec).rotation(); - Affine3d transform_with_scale(R * length, startPoint); + Affine3d transform_with_scale(R * length, start_point); vtkSmartPointer polydata = VtkUtils::TransformPolydata(arrow_source->GetOutputPort(), transform_with_scale); @@ -216,32 +215,36 @@ template<> cv::viz::WArrow cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// circle widget implementation -cv::viz::WCircle::WCircle(const Point3d& pt, double radius, double thickness, const Color& color) +cv::viz::WCircle::WCircle(double radius, double thickness, const Color &color) { vtkSmartPointer disk = vtkSmartPointer::New(); - // Maybe the resolution should be lower e.g. 50 or 25 - disk->SetCircumferentialResolution(50); + disk->SetCircumferentialResolution(30); disk->SetInnerRadius(radius - thickness); disk->SetOuterRadius(radius + thickness); - - // Set the circle origin - vtkSmartPointer t = vtkSmartPointer::New(); - t->Identity(); - t->Translate(pt.x, pt.y, pt.z); - - vtkSmartPointer tf = vtkSmartPointer::New(); - tf->SetTransform(t); - tf->SetInputConnection(disk->GetOutputPort()); - tf->Update(); + disk->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, tf->GetOutput()); + VtkUtils::SetInputData(mapper, disk->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); + actor->GetProperty()->LightingOff(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); setColor(color); + +} + +cv::viz::WCircle::WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness, const Color &color) +{ + Vec3d arbitrary = get_random_vec(); + Vec3d zvec = normalized(normal); + Vec3d xvec = normalized(zvec.cross(arbitrary)); + Vec3d yvec = zvec.cross(xvec); + + WCircle circle(radius, thickness, color); + circle.applyTransform(makeTransformToGlobal(xvec, yvec, zvec, center)); + *this = circle; } template<> cv::viz::WCircle cv::viz::Widget::cast() diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 4d9b1cfd1..794019432 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -293,7 +293,9 @@ TEST(Viz, show_simple_widgets) Viz3d viz("show_simple_widgets"); viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); - viz.showWidget("arr3", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); + viz.showWidget("arro", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); + viz.showWidget("cir1", WCircle(0.5, 0.01, Color::bluberry())); + viz.showWidget("cir2", WCircle(0.5, Point3d(0.5, 0.0, 0.0), Vec3d(1.0, 0.0, 0.0), 0.01, Color::apricot())); viz.spin(); } From 08f50314cb0b8ca484c2e91f28f4eb58807e7605 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 11 Jan 2014 23:40:56 +0400 Subject: [PATCH 169/295] updated cylinder and cube --- modules/viz/doc/widget.rst | 6 +++--- modules/viz/include/opencv2/viz/widgets.hpp | 4 ++-- modules/viz/src/shapes.cpp | 21 ++++++++++++++------- modules/viz/test/tests_simple.cpp | 3 +++ 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index f98039bbf..474e0f2fb 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -390,7 +390,7 @@ This 3D Widget defines a cylinder. :: class CV_EXPORTS WCylinder : public Widget3D { public: - WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()); + WCylinder(const Point3d& axis_point1, const Point3d& axis_point2, double radius, int numsides = 30, const Color &color = Color::white()); }; viz::WCylinder::WCylinder @@ -399,8 +399,8 @@ Constructs a WCylinder. .. ocv:function:: WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()) - :param pt_on_axis: A point on the axis of the cylinder. - :param axis_direction: Direction of the axis of the cylinder. + :param axis_point1: A point1 on the axis of the cylinder. + :param axis_point2: A point2 on the axis of the cylinder. :param radius: Radius of the cylinder. :param numsides: Resolution of the cylinder. :param color: :ocv:class:`Color` of the cylinder. diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index c58595635..3ebcd35c9 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -164,7 +164,7 @@ namespace cv class CV_EXPORTS WCircle : public Widget3D { public: - //! creates default circle centred at origin with normal along z-axis + //! creates default planar circle centred at origin with plane normal along z-axis WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()); //! creates repositioned circle @@ -174,7 +174,7 @@ namespace cv class CV_EXPORTS WCylinder : public Widget3D { public: - WCylinder(const Point3d& pt_on_axis, const Point3d& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()); + WCylinder(const Point3d& axis_point1, const Point3d& axis_point2, double radius, int numsides = 30, const Color &color = Color::white()); }; class CV_EXPORTS WCube : public Widget3D diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 6731087c0..89e3cd38b 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -256,17 +256,16 @@ template<> cv::viz::WCircle cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// cylinder widget implementation -cv::viz::WCylinder::WCylinder(const Point3d& pt_on_axis, const Point3d& axis_direction, double radius, int numsides, const Color &color) +cv::viz::WCylinder::WCylinder(const Point3d& axis_point1, const Point3d& axis_point2, double radius, int numsides, const Color &color) { - const Point3d pt2 = pt_on_axis + axis_direction; vtkSmartPointer line = vtkSmartPointer::New(); - line->SetPoint1(pt_on_axis.x, pt_on_axis.y, pt_on_axis.z); - line->SetPoint2(pt2.x, pt2.y, pt2.z); + line->SetPoint1(axis_point1.x, axis_point1.y, axis_point1.z); + line->SetPoint2(axis_point2.x, axis_point2.y, axis_point2.z); vtkSmartPointer tuber = vtkSmartPointer::New(); tuber->SetInputConnection(line->GetOutputPort()); - tuber->SetRadius(radius); tuber->SetNumberOfSides(numsides); + tuber->SetRadius(radius); tuber->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); @@ -290,16 +289,24 @@ template<> cv::viz::WCylinder cv::viz::Widget::cast() cv::viz::WCube::WCube(const Point3d& min_point, const Point3d& max_point, bool wire_frame, const Color &color) { + double bounds[6]; + bounds[0] = std::min(min_point.x, max_point.x); + bounds[1] = std::max(min_point.x, max_point.x); + bounds[2] = std::min(min_point.y, max_point.y); + bounds[3] = std::max(min_point.y, max_point.y); + bounds[4] = std::min(min_point.z, max_point.z); + bounds[5] = std::max(min_point.z, max_point.z); + vtkSmartPointer cube; if (wire_frame) { cube = vtkSmartPointer::New(); - vtkOutlineSource::SafeDownCast(cube)->SetBounds(min_point.x, max_point.x, min_point.y, max_point.y, min_point.z, max_point.z); + vtkOutlineSource::SafeDownCast(cube)->SetBounds(bounds); } else { cube = vtkSmartPointer::New(); - vtkCubeSource::SafeDownCast(cube)->SetBounds(min_point.x, max_point.x, min_point.y, max_point.y, min_point.z, max_point.z); + vtkCubeSource::SafeDownCast(cube)->SetBounds(bounds); } cube->Update(); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 794019432..f250d03a0 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -293,9 +293,12 @@ TEST(Viz, show_simple_widgets) Viz3d viz("show_simple_widgets"); viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); + viz.showWidget("cub0", WCube(Vec3d::all(-1.0), Vec3d::all(-0.5), false, Color::indigo())); viz.showWidget("arro", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); viz.showWidget("cir1", WCircle(0.5, 0.01, Color::bluberry())); viz.showWidget("cir2", WCircle(0.5, Point3d(0.5, 0.0, 0.0), Vec3d(1.0, 0.0, 0.0), 0.01, Color::apricot())); + + viz.showWidget("cyl0", WCylinder(Vec3d(-0.5, 0.5, -0.5), Vec3d(0.5, 0.5, -0.5), 0.125, 30, Color::brown())); viz.spin(); } From bb891f05702ef08f04d090a763af03063022b902 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 00:05:59 +0400 Subject: [PATCH 170/295] added cone implementation --- modules/viz/doc/widget.rst | 42 ++++++++++++++++++++- modules/viz/include/opencv2/viz/widgets.hpp | 11 ++++++ modules/viz/src/precomp.hpp | 1 + modules/viz/src/shapes.cpp | 40 ++++++++++++++++++++ modules/viz/test/tests_simple.cpp | 2 + 5 files changed, 95 insertions(+), 1 deletion(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 474e0f2fb..5b72adbd5 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -349,7 +349,7 @@ viz::WCircle This 3D Widget defines a circle. :: - class CV_EXPORTS WCircle : public Widget3D + class CV_EXPORTS WCircle : public Widget3D { public: //! creates default planar circle centred at origin with plane normal along z-axis @@ -381,6 +381,46 @@ Constructs repositioned planar circle. :param thickness: Thickness of the circle. :param color: :ocv:class:`Color` of the circle. + +viz::WCone +----------------- +.. ocv:class:: WCone + +This 3D Widget defines a cone. :: + + class CV_EXPORTS WCone : public Widget3D + { + public: + //! create default cone, oriented along x-axis with center of its base located at origin + WCone(double lenght, double radius, int resolution = 6.0, const Color &color = Color::white()); + + //! creates repositioned cone + WCone(double radius, const Point3d& center, const Point3d& tip, int resolution = 6.0, const Color &color = Color::white()); + }; + +viz::WCone::WCone +------------------------------- +Constructs default cone oriented along x-axis with center of its base located at origin + +.. ocv:function:: WCone(double length, double radius, int resolution = 6.0, const Color &color = Color::white()); + + :param length: Length of the cone. + :param radius: Radius of the cone. + :param resolution: Resolution of the cone. + :param color: :ocv:class:`Color` of the cone. + +viz::WCone::WCone +------------------------------- +Constructs repositioned planar cone. + +.. ocv:function:: WCone(double radius, const Point3d& center, const Point3d& tip, int resolution = 6.0, const Color &color = Color::white()); + + :param radius: Radius of the cone. + :param center: Center of the cone base. + :param tip: Tip of the cone. + :param resolution: Resolution of the cone. + :param color: :ocv:class:`Color` of the cone. + viz::WCylinder -------------- .. ocv:class:: WCylinder diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 3ebcd35c9..f745e5484 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -171,6 +171,16 @@ namespace cv WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness = 0.01, const Color &color = Color::white()); }; + class CV_EXPORTS WCone : public Widget3D + { + public: + //! create default cone, oriented along x-axis with center of its base located at origin + WCone(double length, double radius, int resolution = 6.0, const Color &color = Color::white()); + + //! creates repositioned cone + WCone(double radius, const Point3d& center, const Point3d& tip, int resolution = 6.0, const Color &color = Color::white()); + }; + class CV_EXPORTS WCylinder : public Widget3D { public: @@ -341,6 +351,7 @@ namespace cv template<> CV_EXPORTS WCylinder Widget::cast(); template<> CV_EXPORTS WArrow Widget::cast(); template<> CV_EXPORTS WCircle Widget::cast(); + template<> CV_EXPORTS WCone Widget::cast(); template<> CV_EXPORTS WCube Widget::cast(); template<> CV_EXPORTS WCoordinateSystem Widget::cast(); template<> CV_EXPORTS WPolyLine Widget::cast(); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index bc91191d1..4b963661d 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -127,6 +127,7 @@ #include #include #include +#include #include #if !defined(_WIN32) || defined(__CYGWIN__) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 89e3cd38b..5e76286c8 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -253,6 +253,46 @@ template<> cv::viz::WCircle cv::viz::Widget::cast() return static_cast(widget); } +/////////////////////////////////////////////////////////////////////////////////////////////// +/// WCone widget implementation + +cv::viz::WCone::WCone(double length, double radius, int resolution, const Color &color) +{ + vtkSmartPointer cone_source = vtkSmartPointer::New(); + cone_source->SetCenter(length*0.5, 0.0, 0.0); + cone_source->SetHeight(length); + cone_source->SetRadius(radius); + cone_source->SetResolution(resolution); + cone_source->Update(); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, cone_source->GetOutput()); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->SetMapper(mapper); + + WidgetAccessor::setProp(*this, actor); + setColor(color); +} + +cv::viz::WCone::WCone(double radius, const Point3d& center, const Point3d& tip, int resolution, const Color &color) +{ + Vec3d arbitrary = get_random_vec(); + Vec3d xvec = normalized(Vec3d(tip - center)); + Vec3d zvec = normalized(xvec.cross(arbitrary)); + Vec3d yvec = zvec.cross(xvec); + + WCone circle(norm(tip - center), radius, resolution, color); + circle.applyTransform(makeTransformToGlobal(xvec, yvec, zvec, center)); + *this = circle; +} + +template<> cv::viz::WCone cv::viz::Widget::cast() +{ + Widget3D widget = this->cast(); + return static_cast(widget); +} + /////////////////////////////////////////////////////////////////////////////////////////////// /// cylinder widget implementation diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index f250d03a0..58e909f5f 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -299,6 +299,8 @@ TEST(Viz, show_simple_widgets) viz.showWidget("cir2", WCircle(0.5, Point3d(0.5, 0.0, 0.0), Vec3d(1.0, 0.0, 0.0), 0.01, Color::apricot())); viz.showWidget("cyl0", WCylinder(Vec3d(-0.5, 0.5, -0.5), Vec3d(0.5, 0.5, -0.5), 0.125, 30, Color::brown())); + viz.showWidget("con0", WCone(0.25, 0.125, 6, Color::azure())); + viz.showWidget("con1", WCone(0.125, Point3d(0.5, -0.5, 0.5), Point3d(0.5, -1.0, 0.5), 6, Color::turquoise())); viz.spin(); } From 53b8218652536d58dd71eb8690fff263b6122b9a Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 00:31:45 +0400 Subject: [PATCH 171/295] addeed test for text 2d/3d --- modules/viz/include/opencv2/viz/widgets.hpp | 3 ++- modules/viz/src/shapes.cpp | 11 ++++++++--- modules/viz/test/tests_simple.cpp | 21 +++++++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index f745e5484..75f9670f3 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -206,7 +206,7 @@ namespace cv class CV_EXPORTS WText : public Widget2D { public: - WText(const String &text, const Point2i &pos, int font_size = 20, const Color &color = Color::white()); + WText(const String &text, const Point &pos, int font_size = 20, const Color &color = Color::white()); void setText(const String &text); String getText() const; @@ -215,6 +215,7 @@ namespace cv class CV_EXPORTS WText3D : public Widget3D { public: + //! creates text label in 3D. If face_camera = false, text plane normal is oriented along z-axis. Use widget pose to orient it properly WText3D(const String &text, const Point3d &position, double text_scale = 1., bool face_camera = true, const Color &color = Color::white()); void setText(const String &text); diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 5e76286c8..2e36a6d09 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -135,8 +135,12 @@ cv::viz::WPlane::WPlane(const Vec4d& coefs, double size, const Color &color) Vec3d p_center; plane->GetOrigin(p_center.val); + + vtkSmartPointer filter = PlaneUtils::setSize(p_center, plane->GetOutputPort(), size); + filter->Update(); + vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); + VtkUtils::SetInputData(mapper, filter->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -571,6 +575,7 @@ cv::viz::WText3D::WText3D(const String &text, const Point3d &position, double te actor->SetMapper(mapper); actor->SetPosition(position.x, position.y, position.z); actor->SetScale(text_scale); + actor->GetProperty()->LightingOff(); WidgetAccessor::setProp(*this, actor); } @@ -579,7 +584,7 @@ cv::viz::WText3D::WText3D(const String &text, const Point3d &position, double te void cv::viz::WText3D::setText(const String &text) { - vtkFollower *actor = vtkFollower::SafeDownCast(WidgetAccessor::getProp(*this)); + vtkActor *actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this)); CV_Assert("This widget does not support text." && actor); // Update text source @@ -613,7 +618,7 @@ template<> cv::viz::WText3D cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// text widget implementation -cv::viz::WText::WText(const String &text, const Point2i &pos, int font_size, const Color &color) +cv::viz::WText::WText(const String &text, const Point &pos, int font_size, const Color &color) { vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetPosition(pos.x, pos.y); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 58e909f5f..fe5cf33a0 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -291,6 +291,7 @@ TEST(Viz, DISABLED_show_image_3d) TEST(Viz, show_simple_widgets) { Viz3d viz("show_simple_widgets"); + viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); viz.showWidget("cub0", WCube(Vec3d::all(-1.0), Vec3d::all(-0.5), false, Color::indigo())); @@ -301,6 +302,26 @@ TEST(Viz, show_simple_widgets) viz.showWidget("cyl0", WCylinder(Vec3d(-0.5, 0.5, -0.5), Vec3d(0.5, 0.5, -0.5), 0.125, 30, Color::brown())); viz.showWidget("con0", WCone(0.25, 0.125, 6, Color::azure())); viz.showWidget("con1", WCone(0.125, Point3d(0.5, -0.5, 0.5), Point3d(0.5, -1.0, 0.5), 6, Color::turquoise())); + + viz.showWidget("text2d", WText("Simple text", Point(20, 20), 20, Color::green())); + + viz.showWidget("text3d", WText3D("Simple 3D text", Point3d( 0.5, 0.5, 0.5), 0.125, false, Color::green())); + + viz.spinOnce(1500, true); + viz.getWidget("text2d").cast().setText("New simple text"); + viz.getWidget("text3d").cast().setText("Updated text 3D"); + viz.spin(); +} + +TEST(Viz, show_follower) +{ + Viz3d viz("show_follower"); + + viz.showWidget("coos", WCoordinateSystem()); + viz.showWidget("cube", WCube()); + viz.showWidget("t3d_2", WText3D("Simple 3D follower", Point3d(-0.5, -0.5, 0.5), 0.125, true, Color::green())); + viz.spinOnce(1500, true); + //viz.getWidget("t3d_2").cast().setText("Updated follower 3D"); viz.spin(); } From 658f4a7d386cb2fd421494921944c592960ebd87 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 14:58:22 +0400 Subject: [PATCH 172/295] refactoed plane --- modules/viz/doc/widget.rst | 25 ++++++++++------- modules/viz/include/opencv2/viz/widgets.hpp | 7 +++-- modules/viz/src/shapes.cpp | 30 +++++++++++++++++++++ modules/viz/test/tests_simple.cpp | 6 +++-- 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 5b72adbd5..bec5188a3 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -274,25 +274,30 @@ This 3D Widget defines a finite plane. :: class CV_EXPORTS WPlane : public Widget3D { public: - WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()); - WPlane(const Vec4d& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()); + //! created default plane with center point at origin and normal oriented along z-axis + WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); + + //! repositioned plane + WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); }; viz::WPlane::WPlane ------------------- -Constructs a WPlane. +Constructs a default plane with center point at origin and normal oriented along z-axis. -.. ocv:function:: WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()) +.. ocv:function:: WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); - :param coefs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. - :param size: Size of the plane. + :param size: Size of the plane :param color: :ocv:class:`Color` of the plane. -.. ocv:function:: WPlane(const Vec4d& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()) +viz::WPlane::WPlane +Constructs a repositioned plane + +.. ocv:function:: WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); - :param coefs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. - :param pt: Position of the plane. - :param size: Size of the plane. + :param center: Center of the plane + :param normal: Plane normal orientation + :param new_plane_yaxis: Up-vector. New orientation of plane y-axis. :param color: :ocv:class:`Color` of the plane. viz::WSphere diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 75f9670f3..f740a6210 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -145,8 +145,11 @@ namespace cv class CV_EXPORTS WPlane : public Widget3D { public: - WPlane(const Vec4d& coefs, double size = 1.0, const Color &color = Color::white()); - WPlane(const Vec4d& coefs, const Point3d& pt, double size = 1.0, const Color &color = Color::white()); + //! created default plane with center point at origin and normal oriented along z-axis + WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); + + //! repositioned plane + WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); }; class CV_EXPORTS WSphere : public Widget3D diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 2e36a6d09..468022f97 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -125,6 +125,36 @@ namespace cv { namespace viz { namespace }; }}} +cv::viz::WPlane::WPlane(const Size2d& size, const Color &color) +{ + vtkSmartPointer plane = vtkSmartPointer::New(); + plane->SetOrigin(-0.5 * size.width, -0.5 * size.height, 0.0); + plane->SetPoint1( 0.5 * size.width, -0.5 * size.height, 0.0); + plane->SetPoint2(-0.5 * size.width, 0.5 * size.height, 0.0); + plane->Update(); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, plane->GetOutput()); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->SetMapper(mapper); + actor->GetProperty()->LightingOff(); + + WidgetAccessor::setProp(*this, actor); + setColor(color); +} + +cv::viz::WPlane::WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis, const Size2d& size, const Color &color) +{ + Vec3d zvec = normalize(normal); + Vec3d xvec = normalize(new_plane_yaxis.cross(zvec)); + Vec3d yvec = zvec.cross(xvec); + + WPlane plane(size, color); + plane.applyTransform(makeTransformToGlobal(xvec, yvec, zvec, center)); + *this = plane; +} + cv::viz::WPlane::WPlane(const Vec4d& coefs, double size, const Color &color) { vtkSmartPointer plane = vtkSmartPointer::New(); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index fe5cf33a0..85cdeacf1 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -304,16 +304,18 @@ TEST(Viz, show_simple_widgets) viz.showWidget("con1", WCone(0.125, Point3d(0.5, -0.5, 0.5), Point3d(0.5, -1.0, 0.5), 6, Color::turquoise())); viz.showWidget("text2d", WText("Simple text", Point(20, 20), 20, Color::green())); - viz.showWidget("text3d", WText3D("Simple 3D text", Point3d( 0.5, 0.5, 0.5), 0.125, false, Color::green())); + viz.showWidget("plane1", WPlane(Size2d(0.25, 0.75))); + viz.showWidget("plane2", WPlane(Vec3d(0.5, -0.5, -0.5), Vec3d(0.0, 1.0, 1.0), Vec3d(1.0, 1.0, 0.0), Size2d(1.0, 0.5), Color::gold())); + viz.spinOnce(1500, true); viz.getWidget("text2d").cast().setText("New simple text"); viz.getWidget("text3d").cast().setText("Updated text 3D"); viz.spin(); } -TEST(Viz, show_follower) +TEST(Viz, DISABLED_show_follower) { Viz3d viz("show_follower"); From e2ef558c8a85cc3258a87c0d525f286a37704097 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 15:22:26 +0400 Subject: [PATCH 173/295] refactored WGrid --- modules/viz/doc/widget.rst | 35 +++--- modules/viz/include/opencv2/viz/widgets.hpp | 13 +- modules/viz/src/shapes.cpp | 125 ++++---------------- modules/viz/test/tests_simple.cpp | 2 + 4 files changed, 53 insertions(+), 122 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index bec5188a3..13409974f 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -291,13 +291,14 @@ Constructs a default plane with center point at origin and normal oriented along :param color: :ocv:class:`Color` of the plane. viz::WPlane::WPlane +------------------- Constructs a repositioned plane -.. ocv:function:: WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); +.. ocv:function:: WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); :param center: Center of the plane :param normal: Plane normal orientation - :param new_plane_yaxis: Up-vector. New orientation of plane y-axis. + :param new_yaxis: Up-vector. New orientation of plane y-axis. :param color: :ocv:class:`Color` of the plane. viz::WSphere @@ -388,7 +389,7 @@ Constructs repositioned planar circle. viz::WCone ------------------ +------------------------------- .. ocv:class:: WCone This 3D Widget defines a cone. :: @@ -527,28 +528,32 @@ This 3D Widget defines a grid. :: class CV_EXPORTS WGrid : public Widget3D { public: - //! Creates grid at the origin - WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); - //! Creates grid based on the plane equation - WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + //! Creates grid at the origin and normal oriented along z-axis + WGrid(const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()); + + //! Creates repositioned grid + WGrid(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, + const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()); }; viz::WGrid::WGrid --------------------------- Constructs a WGrid. -.. ocv:function:: WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()) +.. ocv:function:: WGrid(const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()); - :param dimensions: Number of columns and rows, respectively. - :param spacing: Size of each column and row, respectively. + :param cells: Number of cell columns and rows, respectively. + :param cells_spacing: Size of each cell, respectively. :param color: :ocv:class:`Color` of the grid. -.. ocv:function: WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()) +.. ocv:function: WGrid(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, Vec2i &cells, const Vec2d &cells_spacing, const Color &color; - :param coeffs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. - :param dimensions: Number of columns and rows, respectively. - :param spacing: Size of each column and row, respectively. - :param color: :ocv:class:`Color` of the grid. + :param center: Center of the grid + :param normal: Grid normal orientation + :param new_yaxis: Up-vector. New orientation of grid y-axis. + :param cells: Number of cell columns and rows, respectively. + :param cells_spacing: Size of each cell, respectively. + :param color: :ocv:class:`Color` of the grid.. viz::WText3D ------------ diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index f740a6210..ec17f6576 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -149,7 +149,8 @@ namespace cv WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); //! repositioned plane - WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); + WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, + const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); }; class CV_EXPORTS WSphere : public Widget3D @@ -257,10 +258,12 @@ namespace cv class CV_EXPORTS WGrid : public Widget3D { public: - //! Creates grid at the origin - WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); - //! Creates grid based on the plane equation - WGrid(const Vec4d &coeffs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color = Color::white()); + //! Creates grid at the origin and normal oriented along z-axis + WGrid(const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()); + + //! Creates repositioned grid + WGrid(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, + const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()); }; class CV_EXPORTS WCameraPosition : public Widget3D diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 468022f97..7124d4021 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -144,10 +144,10 @@ cv::viz::WPlane::WPlane(const Size2d& size, const Color &color) setColor(color); } -cv::viz::WPlane::WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_plane_yaxis, const Size2d& size, const Color &color) +cv::viz::WPlane::WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, const Size2d& size, const Color &color) { Vec3d zvec = normalize(normal); - Vec3d xvec = normalize(new_plane_yaxis.cross(zvec)); + Vec3d xvec = normalize(new_yaxis.cross(zvec)); Vec3d yvec = zvec.cross(xvec); WPlane plane(size, color); @@ -155,51 +155,6 @@ cv::viz::WPlane::WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& *this = plane; } -cv::viz::WPlane::WPlane(const Vec4d& coefs, double size, const Color &color) -{ - vtkSmartPointer plane = vtkSmartPointer::New(); - plane->SetNormal(coefs[0], coefs[1], coefs[2]); - double norm = cv::norm(Vec3d(coefs.val)); - plane->Push(-coefs[3] / norm); - - Vec3d p_center; - plane->GetOrigin(p_center.val); - - - vtkSmartPointer filter = PlaneUtils::setSize(p_center, plane->GetOutputPort(), size); - filter->Update(); - - vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, filter->GetOutput()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(mapper); - - WidgetAccessor::setProp(*this, actor); - setColor(color); -} - -cv::viz::WPlane::WPlane(const Vec4d& coefs, const Point3d& pt, double size, const Color &color) -{ - vtkSmartPointer plane = vtkSmartPointer::New(); - Point3d coefs3(coefs[0], coefs[1], coefs[2]); - double norm_sqr = 1.0 / coefs3.dot(coefs3); - plane->SetNormal(coefs[0], coefs[1], coefs[2]); - - double t = coefs3.dot(pt) + coefs[3]; - Vec3d p_center = pt - coefs3 * t * norm_sqr; - plane->SetCenter(p_center[0], p_center[1], p_center[2]); - - vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(PlaneUtils::setSize(p_center, plane->GetOutputPort(), size)->GetOutputPort()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(mapper); - - WidgetAccessor::setProp(*this, actor); - setColor(color); -} - template<> cv::viz::WPlane cv::viz::Widget::cast() { Widget3D widget = this->cast(); @@ -500,38 +455,26 @@ template<> cv::viz::WPolyLine cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// grid widget implementation -namespace cv { namespace viz { namespace + +cv::viz::WGrid::WGrid(const Vec2i &cells, const Vec2d &cells_spacing, const Color &color) { - struct GridUtils - { - static vtkSmartPointer createGrid(const Vec2i &dimensions, const Vec2f &spacing) - { - // Create the grid using image data - vtkSmartPointer grid = vtkSmartPointer::New(); + vtkSmartPointer grid_data = vtkSmartPointer::New(); - // Add 1 to dimensions because in ImageData dimensions is the number of lines - // - however here it means number of cells - grid->SetDimensions(dimensions[0]+1, dimensions[1]+1, 1); - grid->SetSpacing(spacing[0], spacing[1], 0.); + // Add 1 to dimensions because in ImageData dimensions is the number of lines + // - however here it means number of cells + grid_data->SetDimensions(cells[0]+1, cells[1]+1, 1); + grid_data->SetSpacing(cells_spacing[0], cells_spacing[1], 0.); - // Set origin of the grid to be the middle of the grid - grid->SetOrigin(dimensions[0] * spacing[0] * (-0.5), dimensions[1] * spacing[1] * (-0.5), 0); + // Set origin of the grid to be the middle of the grid + grid_data->SetOrigin(cells[0] * cells_spacing[0] * (-0.5), cells[1] * cells_spacing[1] * (-0.5), 0); - // Extract the edges so we have the grid - vtkSmartPointer filter = vtkSmartPointer::New(); - filter->SetInputConnection(grid->GetProducerPort()); - filter->Update(); - return filter->GetOutput(); - } - }; -}}} - -cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color &color) -{ - vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); + // Extract the edges so we have the grid + vtkSmartPointer extract_edges = vtkSmartPointer::New(); + extract_edges->SetInputConnection(grid_data->GetProducerPort()); + extract_edges->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, grid); + VtkUtils::SetInputData(mapper, extract_edges->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); @@ -540,37 +483,15 @@ cv::viz::WGrid::WGrid(const Vec2i &dimensions, const Vec2d &spacing, const Color setColor(color); } -cv::viz::WGrid::WGrid(const Vec4d &coefs, const Vec2i &dimensions, const Vec2d &spacing, const Color &color) +cv::viz::WGrid::WGrid(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, const Vec2i &cells, const Vec2d &cells_spacing, const Color &color) { - vtkSmartPointer grid = GridUtils::createGrid(dimensions, spacing); + Vec3d zvec = normalize(normal); + Vec3d xvec = normalize(new_yaxis.cross(zvec)); + Vec3d yvec = zvec.cross(xvec); - // Estimate the transform to set the normal based on the coefficients - Vec3d normal(coefs[0], coefs[1], coefs[2]); - Vec3d up_vector(0.0, 1.0, 0.0); // Just set as default - double push_distance = -coefs[3]/cv::norm(Vec3d(coefs.val)); - Vec3d n = normalize(normal); - Vec3d u = normalize(up_vector.cross(n)); - Vec3d v = n.cross(u); - - Affine3d pose = makeTransformToGlobal(u, v, n, n * push_distance); - - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->SetMatrix(vtkmatrix(pose.matrix)); - - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetTransform(transform); - transform_filter->SetInputConnection(grid->GetProducerPort()); - transform_filter->Update(); - - vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, transform_filter->GetOutput()); - - vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetMapper(mapper); - - WidgetAccessor::setProp(*this, actor); - setColor(color); + WGrid grid(cells, cells_spacing, color); + grid.applyTransform(makeTransformToGlobal(xvec, yvec, zvec, center)); + *this = grid; } template<> cv::viz::WGrid cv::viz::Widget::cast() diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 85cdeacf1..db105d793 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -309,6 +309,8 @@ TEST(Viz, show_simple_widgets) viz.showWidget("plane1", WPlane(Size2d(0.25, 0.75))); viz.showWidget("plane2", WPlane(Vec3d(0.5, -0.5, -0.5), Vec3d(0.0, 1.0, 1.0), Vec3d(1.0, 1.0, 0.0), Size2d(1.0, 0.5), Color::gold())); + viz.showWidget("grid1", WGrid(Vec2i(7,7), Vec2d::all(0.75), Color::gray()), Affine3d().translate(Vec3d(0.0, 0.0, -1.0))); + viz.spinOnce(1500, true); viz.getWidget("text2d").cast().setText("New simple text"); viz.getWidget("text3d").cast().setText("Updated text 3D"); From d7c30281a587b6b136668e50cb37a6ee15389ca1 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 15:46:03 +0400 Subject: [PATCH 174/295] set background texture method --- modules/viz/include/opencv2/viz/viz3d.hpp | 2 + modules/viz/src/shapes.cpp | 23 --------- modules/viz/src/viz3d.cpp | 13 ++--- modules/viz/src/vizimpl.cpp | 58 +++++++++++++++++++++++ modules/viz/src/vizimpl.hpp | 5 ++ modules/viz/test/tests_simple.cpp | 13 +++-- 6 files changed, 78 insertions(+), 36 deletions(-) diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index 4ffb6b3c5..daebc5d0c 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -99,6 +99,8 @@ namespace cv void setWindowPosition(const Point& window_position); void setFullScreen(bool mode = true); void setBackgroundColor(const Color& color = Color::black()); + void setBackgroundTexture(InputArray image = noArray()); + void setBackgroundMeshLab(); void spin(); void spinOnce(int time = 1, bool force_redraw = false); diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 7124d4021..92ab3400b 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -102,29 +102,6 @@ template<> cv::viz::WSphere cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// plane widget implementation -namespace cv { namespace viz { namespace -{ - struct PlaneUtils - { - template - static vtkSmartPointer setSize(const Vec<_Tp, 3> ¢er, vtkSmartPointer poly_data_port, double size) - { - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->PreMultiply(); - transform->Translate(center[0], center[1], center[2]); - transform->Scale(size, size, size); - transform->Translate(-center[0], -center[1], -center[2]); - - vtkSmartPointer transform_filter = vtkSmartPointer::New(); - transform_filter->SetInputConnection(poly_data_port); - transform_filter->SetTransform(transform); - transform_filter->Update(); - - return transform_filter; - } - }; -}}} - cv::viz::WPlane::WPlane(const Size2d& size, const Color &color) { vtkSmartPointer plane = vtkSmartPointer::New(); diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index a88632247..7a6343513 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -113,15 +113,7 @@ void cv::viz::Viz3d::removeWidget(const String &id) { impl_->removeWidget(id); } cv::viz::Widget cv::viz::Viz3d::getWidget(const String &id) const { return impl_->getWidget(id); } void cv::viz::Viz3d::removeAllWidgets() { impl_->removeAllWidgets(); } - -void cv::viz::Viz3d::showImage(InputArray image, const Size& window_size) -{ - removeAllWidgets(); - if (window_size.width > 0 && window_size.height > 0) - setWindowSize(window_size); - - showWidget("showImage", WImageOverlay(image, Rect(Point(0,0), getWindowSize()))); -} +void cv::viz::Viz3d::showImage(InputArray image, const Size& window_size) { impl_->showImage(image, window_size); } void cv::viz::Viz3d::setWidgetPose(const String &id, const Affine3d &pose) { impl_->setWidgetPose(id, pose); } void cv::viz::Viz3d::updateWidgetPose(const String &id, const Affine3d &pose) { impl_->updateWidgetPose(id, pose); } @@ -146,6 +138,9 @@ void cv::viz::Viz3d::setWindowPosition(const Point& window_position) { impl_->se void cv::viz::Viz3d::setFullScreen(bool mode) { impl_->setFullScreen(mode); } void cv::viz::Viz3d::setBackgroundColor(const Color& color) { impl_->setBackgroundColor(color); } +void cv::viz::Viz3d::setBackgroundTexture(InputArray image) { impl_->setBackgroundTexture(image); } +void cv::viz::Viz3d::setBackgroundMeshLab() {impl_->setBackgroundMeshLab(); } + void cv::viz::Viz3d::setRenderingProperty(const String &id, int property, double value) { getWidget(id).setRenderingProperty(property, value); } double cv::viz::Viz3d::getRenderingProperty(const String &id, int property) { return getWidget(id).getRenderingProperty(property); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index dd568c940..5e497afb7 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -269,6 +269,15 @@ void cv::viz::Viz3d::VizImpl::removeAllWidgets() widget_actor_map_->clear(); renderer_->RemoveAllViewProps(); } +///////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::showImage(InputArray image, const Size& window_size) +{ + removeAllWidgets(); + if (window_size.width > 0 && window_size.height > 0) + setWindowSize(window_size); + + showWidget("showImage", WImageOverlay(image, Rect(Point(0,0), getWindowSize()))); +} ///////////////////////////////////////////////////////////////////////////////////////////// bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(vtkSmartPointer actor) @@ -295,6 +304,55 @@ void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color) renderer_->SetBackground(c.val); } +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::setBackgroundTexture(InputArray image) +{ + if (image.empty()) + { + renderer_->SetBackgroundTexture(0); + renderer_->TexturedBackgroundOff(); + return; + } + + vtkSmartPointer source = vtkSmartPointer::New(); + source->SetImage(image); + + vtkSmartPointer image_flip = vtkSmartPointer::New(); + image_flip->SetFilteredAxis(1); // Vertical flip + image_flip->SetInputConnection(source->GetOutputPort()); + + vtkSmartPointer texture = vtkSmartPointer::New(); + texture->SetInputConnection(image_flip->GetOutputPort()); + //texture->Update(); + + renderer_->SetBackgroundTexture(texture); + renderer_->TexturedBackgroundOn(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::setBackgroundMeshLab() +{ + static Color up(2, 1, 1), down(240, 120, 120); + static Mat meshlab_texture; + + if (meshlab_texture.empty()) + { + meshlab_texture.create(2048, 2048, CV_8UC4); + + for (int y = 0; y < meshlab_texture.rows; ++y) + { + double alpha = (y+1)/(double)meshlab_texture.rows; + Vec4b color = up * (1 - alpha) + down * alpha; + + Vec4b *row = meshlab_texture.ptr(y); + for(int x = 0; x < meshlab_texture.cols; ++x) + row[x] = color; + } + + } + setBackgroundTexture(meshlab_texture); +} + ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setCamera(const Camera &camera) { diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index b6ae54927..e7534ea70 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -62,6 +62,8 @@ public: Widget getWidget(const String &id) const; void removeAllWidgets(); + void showImage(InputArray image, const Size& window_size); + void setWidgetPose(const String &id, const Affine3d &pose); void updateWidgetPose(const String &id, const Affine3d &pose); Affine3d getWidgetPose(const String &id) const; @@ -109,6 +111,9 @@ public: String getWindowName() const; void setBackgroundColor(const Color& color); + void setBackgroundTexture(InputArray image); + void setBackgroundMeshLab(); + void spin(); void spinOnce(int time = 1, bool force_redraw = false); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index db105d793..a4f566eba 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -57,7 +57,7 @@ TEST(Viz, DISABLED_show_cloud_bluberry) viz.spin(); } -TEST(Viz, DISABLED_show_cloud_random_color) +TEST(Viz, show_cloud_random_color) { Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); @@ -67,6 +67,7 @@ TEST(Viz, DISABLED_show_cloud_random_color) Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); Viz3d viz("show_cloud_random_color"); + viz.setBackgroundMeshLab(); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud, colors), pose); viz.spin(); @@ -229,6 +230,7 @@ TEST(Viz, DISABLED_show_overlay_image) Size2d half_lsize = Size2d(lena.size()) * 0.5; Viz3d viz("show_overlay_image"); + viz.setBackgroundMeshLab(); Size vsz = viz.getWindowSize(); viz.showWidget("coos", WCoordinateSystem()); @@ -264,12 +266,13 @@ TEST(Viz, DISABLED_show_image_method) cv::viz::imshow("show_image_method", make_gray(lena)).spin(); } -TEST(Viz, DISABLED_show_image_3d) +TEST(Viz, show_image_3d) { Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); Mat gray = make_gray(lena); Viz3d viz("show_image_3d"); + viz.setBackgroundMeshLab(); viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); viz.showWidget("arr0", WArrow(Vec3d(0.5, 0.0, 0.0), Vec3d(1.5, 0.0, 0.0), 0.009, Color::raspberry())); @@ -291,6 +294,7 @@ TEST(Viz, DISABLED_show_image_3d) TEST(Viz, show_simple_widgets) { Viz3d viz("show_simple_widgets"); + viz.setBackgroundMeshLab(); viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); @@ -317,15 +321,16 @@ TEST(Viz, show_simple_widgets) viz.spin(); } -TEST(Viz, DISABLED_show_follower) +TEST(Viz, show_follower) { Viz3d viz("show_follower"); viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); viz.showWidget("t3d_2", WText3D("Simple 3D follower", Point3d(-0.5, -0.5, 0.5), 0.125, true, Color::green())); + viz.setBackgroundMeshLab(); viz.spinOnce(1500, true); - //viz.getWidget("t3d_2").cast().setText("Updated follower 3D"); + viz.getWidget("t3d_2").cast().setText("Updated follower 3D"); viz.spin(); } From b0ca93b22ca359ddb596e7eb7831d46b0b38c7c2 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 15:56:54 +0400 Subject: [PATCH 175/295] by default enabled tests vtk --- CMakeLists.txt | 2 +- modules/viz/test/tests_simple.cpp | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 171046774..7f9b1de9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,7 +116,7 @@ endif() OCV_OPTION(WITH_1394 "Include IEEE1394 support" ON IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O" ON IF IOS) OCV_OPTION(WITH_CARBON "Use Carbon for UI instead of Cocoa" OFF IF APPLE ) -OCV_OPTION(WITH_VTK "Include VTK library support (and build opencv_viz module eiher)" OFF IF (NOT ANDROID AND NOT IOS) ) +OCV_OPTION(WITH_VTK "Include VTK library support (and build opencv_viz module eiher)" ON IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_CUDA "Include NVidia Cuda Runtime support" ON IF (NOT IOS) ) OCV_OPTION(WITH_CUFFT "Include NVidia Cuda Fast Fourier Transform (FFT) library support" ON IF (NOT IOS) ) OCV_OPTION(WITH_CUBLAS "Include NVidia Cuda Basic Linear Algebra Subprograms (BLAS) library support" OFF IF (NOT IOS) ) diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index a4f566eba..5a685bb59 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -45,7 +45,7 @@ using namespace cv; using namespace cv::viz; -TEST(Viz, DISABLED_show_cloud_bluberry) +TEST(Viz, show_cloud_bluberry) { Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); @@ -73,7 +73,7 @@ TEST(Viz, show_cloud_random_color) viz.spin(); } -TEST(Viz, DISABLED_show_cloud_masked) +TEST(Viz, show_cloud_masked) { Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); @@ -90,7 +90,7 @@ TEST(Viz, DISABLED_show_cloud_masked) viz.spin(); } -TEST(Viz, DISABLED_show_cloud_collection) +TEST(Viz, show_cloud_collection) { Mat cloud = readCloud(get_dragon_ply_file_path()); @@ -105,7 +105,7 @@ TEST(Viz, DISABLED_show_cloud_collection) viz.spin(); } -TEST(Viz, DISABLED_show_mesh) +TEST(Viz, show_mesh) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); @@ -117,7 +117,7 @@ TEST(Viz, DISABLED_show_mesh) viz.spin(); } -TEST(Viz, DISABLED_show_mesh_random_colors) +TEST(Viz, show_mesh_random_colors) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); @@ -131,7 +131,7 @@ TEST(Viz, DISABLED_show_mesh_random_colors) viz.spin(); } -TEST(Viz, DISABLED_show_polyline) +TEST(Viz, show_polyline) { Mat polyline(1, 32, CV_64FC3); for(size_t i = 0; i < polyline.total(); ++i) @@ -143,7 +143,7 @@ TEST(Viz, DISABLED_show_polyline) viz.spin(); } -TEST(Viz, DISABLED_show_sampled_normals) +TEST(Viz, show_sampled_normals) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); computeNormals(mesh, mesh.normals); @@ -157,7 +157,7 @@ TEST(Viz, DISABLED_show_sampled_normals) viz.spin(); } -TEST(Viz, DISABLED_show_trajectories) +TEST(Viz, show_trajectories) { std::vector path = generate_test_trajectory(), sub0, sub1, sub2, sub3, sub4, sub5; @@ -189,7 +189,7 @@ TEST(Viz, DISABLED_show_trajectories) //viz.spin(); } -TEST(Viz, DISABLED_show_trajectory_reposition) +TEST(Viz, show_trajectory_reposition) { std::vector path = generate_test_trajectory(); @@ -199,7 +199,7 @@ TEST(Viz, DISABLED_show_trajectory_reposition) viz.spin(); } -TEST(Viz, DISABLED_show_camera_positions) +TEST(Viz, show_camera_positions) { Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0); Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); @@ -222,7 +222,7 @@ TEST(Viz, DISABLED_show_camera_positions) viz.spin(); } -TEST(Viz, DISABLED_show_overlay_image) +TEST(Viz, show_overlay_image) { Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); Mat gray = make_gray(lena); @@ -253,7 +253,7 @@ TEST(Viz, DISABLED_show_overlay_image) } -TEST(Viz, DISABLED_show_image_method) +TEST(Viz, show_image_method) { Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); From 3086095837e01f96ac43d40c11c813aa8fd206b2 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 16:40:41 +0400 Subject: [PATCH 176/295] improved background gradient --- modules/viz/include/opencv2/viz/viz3d.hpp | 1 + modules/viz/src/viz3d.cpp | 1 + modules/viz/src/vizimpl.cpp | 39 +++++++++-------------- modules/viz/src/vizimpl.hpp | 2 +- modules/viz/test/test_viz3d.cpp | 3 +- 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index daebc5d0c..b9712ef3e 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -100,6 +100,7 @@ namespace cv void setFullScreen(bool mode = true); void setBackgroundColor(const Color& color = Color::black()); void setBackgroundTexture(InputArray image = noArray()); + void setBackgroundGradient(const Color& up, const Color& down); void setBackgroundMeshLab(); void spin(); diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 7a6343513..503359f01 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -137,6 +137,7 @@ void cv::viz::Viz3d::saveScreenshot(const String &file) { impl_->saveScreenshot( void cv::viz::Viz3d::setWindowPosition(const Point& window_position) { impl_->setWindowPosition(window_position); } void cv::viz::Viz3d::setFullScreen(bool mode) { impl_->setFullScreen(mode); } void cv::viz::Viz3d::setBackgroundColor(const Color& color) { impl_->setBackgroundColor(color); } +void cv::viz::Viz3d::setBackgroundGradient(const Color& up, const Color& down) { impl_->setBackgroundGradient(up, down); } void cv::viz::Viz3d::setBackgroundTexture(InputArray image) { impl_->setBackgroundTexture(image); } void cv::viz::Viz3d::setBackgroundMeshLab() {impl_->setBackgroundMeshLab(); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 5e497afb7..61a0a01f6 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -302,6 +302,21 @@ void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color) { Color c = vtkcolor(color); renderer_->SetBackground(c.val); + renderer_->GradientBackgroundOff(); +} + +void cv::viz::Viz3d::VizImpl::setBackgroundGradient(const Color& up, const Color& down) +{ + Color vtkup = vtkcolor(up), vtkdown = vtkcolor(down); + renderer_->SetBackground(vtkdown.val); + renderer_->SetBackground2(vtkup.val); + renderer_->GradientBackgroundOn(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::setBackgroundMeshLab() +{ + setBackgroundGradient(Color(2, 1, 1), Color(240, 120, 120)); } ////////////////////////////////////////////////////////////////////////////////////////////// @@ -329,30 +344,6 @@ void cv::viz::Viz3d::VizImpl::setBackgroundTexture(InputArray image) renderer_->TexturedBackgroundOn(); } -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setBackgroundMeshLab() -{ - static Color up(2, 1, 1), down(240, 120, 120); - static Mat meshlab_texture; - - if (meshlab_texture.empty()) - { - meshlab_texture.create(2048, 2048, CV_8UC4); - - for (int y = 0; y < meshlab_texture.rows; ++y) - { - double alpha = (y+1)/(double)meshlab_texture.rows; - Vec4b color = up * (1 - alpha) + down * alpha; - - Vec4b *row = meshlab_texture.ptr(y); - for(int x = 0; x < meshlab_texture.cols; ++x) - row[x] = color; - } - - } - setBackgroundTexture(meshlab_texture); -} - ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setCamera(const Camera &camera) { diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index e7534ea70..11b8490a1 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -110,7 +110,7 @@ public: void setFullScreen(bool mode); String getWindowName() const; void setBackgroundColor(const Color& color); - + void setBackgroundGradient(const Color& up, const Color& down); void setBackgroundTexture(InputArray image); void setBackgroundMeshLab(); diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index aec326508..1fd1d4a33 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -51,8 +51,9 @@ TEST(Viz_viz3d, develop) //theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); cv::viz::Viz3d viz("abc"); - viz.setBackgroundColor(cv::viz::Color::mlab()); + viz.setBackgroundMeshLab(); viz.showWidget("coo", cv::viz::WCoordinateSystem(1)); + viz.showWidget("cloud", cv::viz::WCloud(cloud)); //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); From 74206e015956737d97b3a115f2de62e6e39a45df Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 12 Jan 2014 18:05:07 +0400 Subject: [PATCH 177/295] added painted cloud widget --- modules/viz/include/opencv2/viz/widgets.hpp | 14 ++++ modules/viz/src/clouds.cpp | 84 +++++++++++++++++++-- modules/viz/src/precomp.hpp | 2 + modules/viz/test/test_viz3d.cpp | 4 +- modules/viz/test/tests_simple.cpp | 16 +++- 5 files changed, 113 insertions(+), 7 deletions(-) diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index ec17f6576..2c49b9d0e 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -323,6 +323,19 @@ namespace cv WCloud(InputArray cloud, const Color &color = Color::white()); }; + class CV_EXPORTS WPaintedCloud: public Widget3D + { + public: + //! Paint cloud with default gradient between cloud bounds points + WPaintedCloud(InputArray cloud); + + //! Paint cloud with default gradient between given points + WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2); + + //! Paint cloud with gradient specified by given colors between given points + WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2, const Color& c1, const Color c2); + }; + class CV_EXPORTS WCloudCollection : public Widget3D { public: @@ -372,6 +385,7 @@ namespace cv template<> CV_EXPORTS WTrajectoryFrustums Widget::cast(); template<> CV_EXPORTS WTrajectorySpheres Widget::cast(); template<> CV_EXPORTS WCloud Widget::cast(); + template<> CV_EXPORTS WPaintedCloud Widget::cast(); template<> CV_EXPORTS WCloudCollection Widget::cast(); template<> CV_EXPORTS WCloudNormals Widget::cast(); template<> CV_EXPORTS WMesh Widget::cast(); diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 9ea1d76fe..d5283d430 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -72,15 +72,50 @@ cv::viz::WCloud::WCloud(InputArray cloud, InputArray colors) } cv::viz::WCloud::WCloud(InputArray cloud, const Color &color) +{ + WCloud cloud_widget(cloud, Mat(cloud.size(), CV_8UC3, color)); + *this = cloud_widget; +} + + +template<> cv::viz::WCloud cv::viz::Widget::cast() +{ + Widget3D widget = this->cast(); + return static_cast(widget); +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/// Painted Cloud Widget implementation + +cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud) { vtkSmartPointer cloud_source = vtkSmartPointer::New(); cloud_source->SetCloud(cloud); cloud_source->Update(); + Vec6d bounds(cloud_source->GetOutput()->GetPoints()->GetBounds()); + + WPaintedCloud cloud_widget(cloud, Vec3d(bounds[0], bounds[2], bounds[4]), Vec3d(bounds[1], bounds[3], bounds[5])); + *this = cloud_widget; +} + +cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2) +{ + vtkSmartPointer cloud_source = vtkSmartPointer::New(); + cloud_source->SetCloud(cloud); + + vtkSmartPointer elevation = vtkSmartPointer::New(); + elevation->SetInputConnection(cloud_source->GetOutputPort()); + elevation->SetLowPoint(p1.x, p1.y, p1.z); + elevation->SetHighPoint(p2.x, p2.y, p2.z); + elevation->SetScalarRange(0.0, 1.0); + elevation->Update(); + vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, cloud_source->GetOutput()); + VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput())); mapper->ImmediateModeRenderingOff(); - mapper->ScalarVisibilityOff(); + mapper->ScalarVisibilityOn(); + mapper->SetColorModeToMapScalars(); vtkSmartPointer actor = vtkSmartPointer::New(); actor->GetProperty()->SetInterpolationToFlat(); @@ -88,13 +123,52 @@ cv::viz::WCloud::WCloud(InputArray cloud, const Color &color) actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } -template<> cv::viz::WCloud cv::viz::Widget::cast() +cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2, const Color& c1, const Color c2) +{ + vtkSmartPointer cloud_source = vtkSmartPointer::New(); + cloud_source->SetCloud(cloud); + + vtkSmartPointer elevation = vtkSmartPointer::New(); + elevation->SetInputConnection(cloud_source->GetOutputPort()); + elevation->SetLowPoint(p1.x, p1.y, p1.z); + elevation->SetHighPoint(p2.x, p2.y, p2.z); + elevation->SetScalarRange(0.0, 1.0); + elevation->Update(); + + Color vc1 = vtkcolor(c1), vc2 = vtkcolor(c2); + vtkSmartPointer color_transfer = vtkSmartPointer::New(); + color_transfer->SetColorSpaceToRGB(); + color_transfer->AddRGBPoint(0.0, vc1[0], vc1[1], vc1[2]); + color_transfer->AddRGBPoint(1.0, vc2[0], vc2[1], vc2[2]); + color_transfer->SetScaleToLinear(); + color_transfer->Build(); + + //if in future some need to replace color table with real scalars, then this can be done usine next calls: + //vtkDataArray *float_scalars = vtkPolyData::SafeDownCast(elevation->GetOutput())->GetPointData()->GetArray("Elevation"); + //vtkSmartPointer polydata = cloud_source->GetOutput(); + //polydata->GetPointData()->SetScalars(color_transfer->MapScalars(float_scalars, VTK_COLOR_MODE_DEFAULT, 0)); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput())); + mapper->ImmediateModeRenderingOff(); + mapper->ScalarVisibilityOn(); + mapper->SetColorModeToMapScalars(); + mapper->SetLookupTable(color_transfer); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->GetProperty()->SetInterpolationToFlat(); + actor->GetProperty()->BackfaceCullingOn(); + actor->SetMapper(mapper); + + WidgetAccessor::setProp(*this, actor); +} + +template<> cv::viz::WPaintedCloud cv::viz::Widget::cast() { Widget3D widget = this->cast(); - return static_cast(widget); + return static_cast(widget); } /////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 4b963661d..d5f969a49 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -128,6 +128,8 @@ #include #include #include +#include +#include #include #if !defined(_WIN32) || defined(__CYGWIN__) diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 1fd1d4a33..66ec25db8 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -53,7 +53,9 @@ TEST(Viz_viz3d, develop) cv::viz::Viz3d viz("abc"); viz.setBackgroundMeshLab(); viz.showWidget("coo", cv::viz::WCoordinateSystem(1)); - viz.showWidget("cloud", cv::viz::WCloud(cloud)); + //viz.showWidget("cloud", cv::viz::WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0))); + //viz.showWidget("cloud", cv::viz::WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0), cv::viz::Color::green(), cv::viz::Color::red())); + viz.showWidget("cloud", cv::viz::WPaintedCloud(cloud)); //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 5a685bb59..3e25399b2 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -95,7 +95,7 @@ TEST(Viz, show_cloud_collection) Mat cloud = readCloud(get_dragon_ply_file_path()); WCloudCollection ccol; - ccol.addCloud(cloud, Color::white(), Affine3d().translate(Vec3d(0, 0, 0)).rotate(Vec3d(1.57, 0, 0))); + ccol.addCloud(cloud, Color::white(), Affine3d().translate(Vec3d(0, 0, 0)).rotate(Vec3d(CV_PI/2, 0, 0))); ccol.addCloud(cloud, Color::blue(), Affine3d().translate(Vec3d(1, 0, 0))); ccol.addCloud(cloud, Color::red(), Affine3d().translate(Vec3d(2, 0, 0))); @@ -105,6 +105,20 @@ TEST(Viz, show_cloud_collection) viz.spin(); } +TEST(Viz, show_painted_clouds) +{ + Mat cloud = readCloud(get_dragon_ply_file_path()); + + Viz3d viz("show_painted_clouds"); + viz.setBackgroundMeshLab(); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("cloud1", WPaintedCloud(cloud), Affine3d(Vec3d(0.0, -CV_PI/2, 0.0), Vec3d(-1.5, 0.0, 0.0))); + viz.showWidget("cloud2", WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(1.5, 0.0, 0.0))); + viz.showWidget("cloud3", WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0), Color::blue(), Color::red())); + viz.showWidget("arrow", WArrow(Vec3d(0.0, 1.0, -1.0), Vec3d(0.0, 1.0, 1.0), 0.009, Color::raspberry())); + viz.spin(); +} + TEST(Viz, show_mesh) { Mesh mesh = Mesh::load(get_dragon_ply_file_path()); From 625c35a9f9eccc73d37a353ec042c4c9ca77f9d6 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Mon, 13 Jan 2014 00:46:24 +0400 Subject: [PATCH 178/295] added support of texture for mesh --- modules/viz/include/opencv2/viz.hpp | 5 +++ modules/viz/include/opencv2/viz/types.hpp | 2 + modules/viz/src/clouds.cpp | 33 ++++++++++++-- modules/viz/src/vizcore.cpp | 2 + modules/viz/src/vtk/vtkCloudMatSource.cpp | 54 ++++++++++++++++++++++- modules/viz/src/vtk/vtkCloudMatSource.h | 9 +++- 6 files changed, 99 insertions(+), 6 deletions(-) diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 32e32a7a3..89810d547 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -98,6 +98,11 @@ namespace cv CV_EXPORTS void writeCloud(const String& file, InputArray cloud, InputArray colors = noArray(), InputArray normals = noArray(), bool binary = false); CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = noArray(), OutputArray normals = noArray()); + /////////////////////////////////////////////////////////////////////////////////////////////// + /// Read mesh. Only ply format is supported now + + CV_EXPORTS Mesh readMesh (const String& file); + /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 01ddd0289..cdd89d3a0 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -113,6 +113,8 @@ namespace cv //! where n is the number of points in the poligon, and id is a zero-offset index into an associated cloud. Mat polygons; + Mat texture, tcoords; + //! Loads mesh from a given ply file static Mesh load(const String& file); }; diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index d5283d430..ff8177546 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -95,8 +95,25 @@ cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud) Vec6d bounds(cloud_source->GetOutput()->GetPoints()->GetBounds()); - WPaintedCloud cloud_widget(cloud, Vec3d(bounds[0], bounds[2], bounds[4]), Vec3d(bounds[1], bounds[3], bounds[5])); - *this = cloud_widget; + vtkSmartPointer elevation = vtkSmartPointer::New(); + elevation->SetInputConnection(cloud_source->GetOutputPort()); + elevation->SetLowPoint(bounds[0], bounds[2], bounds[4]); + elevation->SetHighPoint(bounds[1], bounds[3], bounds[5]); + elevation->SetScalarRange(0.0, 1.0); + elevation->Update(); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput())); + mapper->ImmediateModeRenderingOff(); + mapper->ScalarVisibilityOn(); + mapper->SetColorModeToMapScalars(); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->GetProperty()->SetInterpolationToFlat(); + actor->GetProperty()->BackfaceCullingOn(); + actor->SetMapper(mapper); + + WidgetAccessor::setProp(*this, actor); } cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2) @@ -329,7 +346,7 @@ cv::viz::WMesh::WMesh(const Mesh &mesh) CV_Assert(mesh.cloud.rows == 1 && mesh.polygons.type() == CV_32SC1); vtkSmartPointer source = vtkSmartPointer::New(); - source->SetColorCloud(mesh.cloud, mesh.colors); + source->SetColorCloudNormalsTCoords(mesh.cloud, mesh.colors, mesh.normals, mesh.tcoords); source->Update(); Mat lookup_buffer(1, mesh.cloud.total(), CV_32SC1); @@ -394,6 +411,16 @@ cv::viz::WMesh::WMesh(const Mesh &mesh) actor->GetProperty()->ShadingOff(); actor->SetMapper(mapper); + if (!mesh.texture.empty()) + { + vtkSmartPointer image_source = vtkSmartPointer::New(); + image_source->SetImage(mesh.texture); + + vtkSmartPointer texture = vtkSmartPointer::New(); + texture->SetInputConnection(image_source->GetOutputPort()); + actor->SetTexture(texture); + } + WidgetAccessor::setProp(*this, actor); } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index a553f8d72..ee74f2a12 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -205,6 +205,8 @@ cv::Mat cv::viz::readCloud(const String& file, OutputArray colors, OutputArray n return cloud; } +cv::viz::Mesh cv::viz::readMesh(const String& file) { return Mesh::load(file); } + /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index 7884f1a9a..9a341b78c 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -128,7 +128,34 @@ int cv::viz::vtkCloudMatSource::SetColorCloudNormals(InputArray _cloud, InputArr else if (normals.depth() == CV_64F && cloud.depth() == CV_64F) filterNanNormalsCopy(normals, cloud, total); else - CV_Assert(!"Unsupported normals type"); + CV_Assert(!"Unsupported normals/cloud type"); + + return total; +} + +int cv::viz::vtkCloudMatSource::SetColorCloudNormalsTCoords(InputArray _cloud, InputArray _colors, InputArray _normals, InputArray _tcoords) +{ + int total = SetColorCloudNormals(_cloud, _colors, _normals); + + if (_tcoords.empty()) + return total; + + CV_Assert(_tcoords.depth() == CV_32F || _tcoords.depth() == CV_64F); + CV_Assert(_tcoords.channels() == 2 && _tcoords.size() == _cloud.size()); + + Mat cloud = _cloud.getMat(); + Mat tcoords = _tcoords.getMat(); + + if (tcoords.depth() == CV_32F && cloud.depth() == CV_32F) + filterNanTCoordsCopy(tcoords, cloud, total); + else if (tcoords.depth() == CV_32F && cloud.depth() == CV_64F) + filterNanTCoordsCopy(tcoords, cloud, total); + else if (tcoords.depth() == CV_64F && cloud.depth() == CV_32F) + filterNanTCoordsCopy(tcoords, cloud, total); + else if (tcoords.depth() == CV_64F && cloud.depth() == CV_64F) + filterNanTCoordsCopy(tcoords, cloud, total); + else + CV_Assert(!"Unsupported tcoords/cloud type"); return total; } @@ -146,6 +173,9 @@ int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), if (normals) output->GetPointData()->SetNormals(normals); + if (tcoords) + output->GetPointData()->SetTCoords(tcoords); + return 1; } @@ -232,3 +262,25 @@ void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals, normals->SetTuple(pos++, srow); } } + +template +void cv::viz::vtkCloudMatSource::filterNanTCoordsCopy(const Mat& _tcoords, const Mat& mask, int total) +{ + typedef Vec<_Tn, 2> Vec2; + tcoords = vtkSmartPointer< VtkDepthTraits<_Tn>::array_type >::New(); + tcoords->SetName("TextureCoordinates"); + tcoords->SetNumberOfComponents(2); + tcoords->SetNumberOfTuples(total); + + int pos = 0; + for (int y = 0; y < mask.rows; ++y) + { + const Vec2* srow = _tcoords.ptr(y); + const Vec2* send = srow + _tcoords.cols; + const _Msk* mrow = mask.ptr<_Msk>(y); + + for (; srow != send; ++srow, mrow += mask.channels()) + if (!isNan(mrow)) + tcoords->SetTuple(pos++, srow->val); + } +} diff --git a/modules/viz/src/vtk/vtkCloudMatSource.h b/modules/viz/src/vtk/vtkCloudMatSource.h index a7f9fff89..56bd93e06 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.h +++ b/modules/viz/src/vtk/vtkCloudMatSource.h @@ -62,8 +62,9 @@ namespace cv vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm) virtual int SetCloud(InputArray cloud); - virtual int SetColorCloud(InputArray cloud, InputArray colors = noArray()); - virtual int SetColorCloudNormals(InputArray cloud, InputArray colors = noArray(), InputArray normals = noArray()); + virtual int SetColorCloud(InputArray cloud, InputArray colors); + virtual int SetColorCloudNormals(InputArray cloud, InputArray colors, InputArray normals); + virtual int SetColorCloudNormalsTCoords(InputArray cloud, InputArray colors, InputArray normals, InputArray tcoords); protected: vtkCloudMatSource(); @@ -75,6 +76,7 @@ namespace cv vtkSmartPointer vertices; vtkSmartPointer scalars; vtkSmartPointer normals; + vtkSmartPointer tcoords; private: vtkCloudMatSource(const vtkCloudMatSource&); // Not implemented. void operator=(const vtkCloudMatSource&); // Not implemented. @@ -84,6 +86,9 @@ namespace cv template void filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total); + + template + void filterNanTCoordsCopy(const Mat& tcoords, const Mat& mask, int total); }; } } From e472d45d999bf3bcab5b5c7afe051d5854ef0d56 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Mon, 13 Jan 2014 13:30:34 +0400 Subject: [PATCH 179/295] updated mesh reading (texture support) --- modules/viz/include/opencv2/viz.hpp | 5 +- modules/viz/src/precomp.hpp | 1 + modules/viz/src/types.cpp | 120 ++++++++++-------------- modules/viz/src/vtk/vtkCloudMatSink.cpp | 25 ++++- modules/viz/src/vtk/vtkCloudMatSink.h | 4 +- 5 files changed, 77 insertions(+), 78 deletions(-) diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 89810d547..a532ba783 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -99,9 +99,10 @@ namespace cv CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = noArray(), OutputArray normals = noArray()); /////////////////////////////////////////////////////////////////////////////////////////////// - /// Read mesh. Only ply format is supported now + /// Reads mesh. Only ply format is supported now. The function tries to read texture from png-file, + /// and in case of faulure, just leaves the texture field empty. - CV_EXPORTS Mesh readMesh (const String& file); + CV_EXPORTS Mesh readMesh(const String& file); /////////////////////////////////////////////////////////////////////////////////////////////// /// Read/write poses and trajectories diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index d5f969a49..bf154e76e 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -122,6 +122,7 @@ #include #include #include +#include #include #include #include diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index 09a2f4d0f..bf61432cb 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -57,80 +57,56 @@ cv::viz::MouseEvent::MouseEvent(const Type& _type, const MouseButton& _button, c //////////////////////////////////////////////////////////////////// /// cv::viz::Mesh3d -namespace cv { namespace viz { namespace -{ - struct MeshUtils - { - static Mesh loadMesh(const String &file) - { - Mesh mesh; - - vtkSmartPointer reader = vtkSmartPointer::New(); - reader->SetFileName(file.c_str()); - reader->Update(); - - vtkSmartPointer poly_data = reader->GetOutput(); - CV_Assert("File does not exist or file format is not supported." && poly_data); - - vtkSmartPointer mesh_points = poly_data->GetPoints(); - vtkIdType nr_points = mesh_points->GetNumberOfPoints(); - - mesh.cloud.create(1, nr_points, CV_32FC3); - - Vec3f *mesh_cloud = mesh.cloud.ptr(); - for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints(); i++) - { - Vec3d point; - mesh_points->GetPoint(i, point.val); - mesh_cloud[i] = point; - } - - // Then the color information, if any - vtkUnsignedCharArray* poly_colors = 0; - if (poly_data->GetPointData()) - poly_colors = vtkUnsignedCharArray::SafeDownCast(poly_data->GetPointData()->GetScalars()); - - if (poly_colors && (poly_colors->GetNumberOfComponents() == 3)) - { - mesh.colors.create(1, nr_points, CV_8UC3); - Vec3b *mesh_colors = mesh.colors.ptr(); - - for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints(); i++) - { - Vec3b point_color; - poly_colors->GetTupleValue(i, point_color.val); - - std::swap(point_color[0], point_color[2]); // RGB -> BGR - mesh_colors[i] = point_color; - } - } - else - mesh.colors.release(); - - // Now handle the polygons - vtkIdType* cell_points; - vtkIdType nr_cell_points; - vtkCellArray * mesh_polygons = poly_data->GetPolys(); - mesh_polygons->InitTraversal(); - - mesh.polygons.create(1, mesh_polygons->GetSize(), CV_32SC1); - - int* polygons = mesh.polygons.ptr(); - while (mesh_polygons->GetNextCell(nr_cell_points, cell_points)) - { - *polygons++ = nr_cell_points; - for (int i = 0; i < nr_cell_points; ++i) - *polygons++ = static_cast(cell_points[i]); - } - - return mesh; - } - }; -}}} - cv::viz::Mesh cv::viz::Mesh::load(const String& file) { - return MeshUtils::loadMesh(file); + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName(file.c_str()); + reader->Update(); + + vtkSmartPointer polydata = reader->GetOutput(); + CV_Assert("File does not exist or file format is not supported." && polydata); + + Mesh mesh; + vtkSmartPointer sink = vtkSmartPointer::New(); + sink->SetOutput(mesh.cloud, mesh.colors, mesh.normals, mesh.tcoords); + sink->SetInputConnection(reader->GetOutputPort()); + sink->Write(); + + // Now handle the polygons + + vtkSmartPointer polygons = polydata->GetPolys(); + mesh.polygons.create(1, polygons->GetSize(), CV_32SC1); + int* poly_ptr = mesh.polygons.ptr(); + + polygons->InitTraversal(); + vtkIdType nr_cell_points, *cell_points; + while (polygons->GetNextCell(nr_cell_points, cell_points)) + { + *poly_ptr++ = nr_cell_points; + for (vtkIdType i = 0; i < nr_cell_points; ++i) + *poly_ptr++ = (int)cell_points[i]; + } + + String::size_type pos = file.find_last_of('.'); + String png = (pos == String::npos) ? file : file.substr(0, pos+1) + "png"; + + vtkSmartPointer png_reader = vtkSmartPointer::New(); + + if (png_reader->CanReadFile(png.c_str())) + { + png_reader->SetFileName(png.c_str()); + png_reader->Update(); + vtkSmartPointer imagedata = png_reader->GetOutput(); + + Size sz(imagedata->GetDimensions()[0], imagedata->GetDimensions()[1]); + int channels = imagedata->GetNumberOfScalarComponents(); + CV_Assert(imagedata->GetScalarType() == VTK_UNSIGNED_CHAR); + + void *ptr = imagedata->GetScalarPointer(0,0,0); + Mat(sz, CV_8UC(channels), ptr).copyTo(mesh.texture); + } + + return mesh; } //////////////////////////////////////////////////////////////////// diff --git a/modules/viz/src/vtk/vtkCloudMatSink.cpp b/modules/viz/src/vtk/vtkCloudMatSink.cpp index cf1eb4648..09ef0cca9 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSink.cpp @@ -52,11 +52,12 @@ namespace cv { namespace viz cv::viz::vtkCloudMatSink::vtkCloudMatSink() {} cv::viz::vtkCloudMatSink::~vtkCloudMatSink() {} -void cv::viz::vtkCloudMatSink::SetOutput(OutputArray _cloud, OutputArray _colors, OutputArray _normals) +void cv::viz::vtkCloudMatSink::SetOutput(OutputArray _cloud, OutputArray _colors, OutputArray _normals, OutputArray _tcoords) { cloud = _cloud; colors = _colors; normals = _normals; + tcoords = _tcoords; } void cv::viz::vtkCloudMatSink::WriteData() @@ -120,12 +121,32 @@ void cv::viz::vtkCloudMatSink::WriteData() Mat buffer(cloud.size(), CV_64FC(channels)); Vec3d *cptr = buffer.ptr(); for(size_t i = 0; i < buffer.total(); ++i) - *cptr++ = Vec3d(scalars_data->GetTuple(i)); + *cptr++ = Vec3d(normals_data->GetTuple(i)); buffer.convertTo(normals, vtktype == VTK_FLOAT ? CV_32F : CV_64F); } else normals.release(); + + vtkSmartPointer coords_data = input->GetPointData() ? input->GetPointData()->GetTCoords() : 0; + + if (tcoords.needed() && coords_data) + { + int vtktype = coords_data->GetDataType(); + + CV_Assert(vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE); + CV_Assert(cloud.total() == (size_t)coords_data->GetNumberOfTuples()); + + Mat buffer(cloud.size(), CV_64FC2); + Vec2d *cptr = buffer.ptr(); + for(size_t i = 0; i < buffer.total(); ++i) + *cptr++ = Vec2d(coords_data->GetTuple(i)); + + buffer.convertTo(tcoords, vtktype == VTK_FLOAT ? CV_32F : CV_64F); + + } + else + tcoords.release(); } void cv::viz::vtkCloudMatSink::PrintSelf(ostream& os, vtkIndent indent) diff --git a/modules/viz/src/vtk/vtkCloudMatSink.h b/modules/viz/src/vtk/vtkCloudMatSink.h index 69262f247..3af9e6544 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.h +++ b/modules/viz/src/vtk/vtkCloudMatSink.h @@ -59,7 +59,7 @@ namespace cv vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter) void PrintSelf(ostream& os, vtkIndent indent); - void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray()); + void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray(), OutputArray tcoords = noArray()); protected: vtkCloudMatSink(); @@ -67,7 +67,7 @@ namespace cv void WriteData(); - _OutputArray cloud, colors, normals; + _OutputArray cloud, colors, normals, tcoords; private: vtkCloudMatSink(const vtkCloudMatSink&); // Not implemented. From 8d327fa497123f2b2281bd0407253787be67bea1 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Mon, 13 Jan 2014 22:42:49 +0400 Subject: [PATCH 180/295] updated for compatibility with VTK6.0 --- cmake/OpenCVDetectVTK.cmake | 4 ++-- modules/viz/src/clouds.cpp | 4 ++-- modules/viz/src/precomp.hpp | 28 +++++++++++++++++++++++++++- modules/viz/src/shapes.cpp | 24 ++++++++++++------------ modules/viz/src/widget.cpp | 1 + modules/viz/test/tests_simple.cpp | 2 +- 6 files changed, 45 insertions(+), 18 deletions(-) diff --git a/cmake/OpenCVDetectVTK.cmake b/cmake/OpenCVDetectVTK.cmake index f0d28d552..ef9aa8043 100644 --- a/cmake/OpenCVDetectVTK.cmake +++ b/cmake/OpenCVDetectVTK.cmake @@ -2,7 +2,7 @@ if(NOT WITH_VTK OR ANDROID OR IOS) return() endif() -find_package(VTK 6.0 QUIET COMPONENTS vtkRenderingCore vtkInteractionWidgets vtkInteractionStyle vtkIOLegacy vtkIOPLY vtkRenderingFreeType vtkRenderingLOD vtkFiltersTexture NO_MODULE) +find_package(VTK 6.0 QUIET COMPONENTS vtkRenderingCore vtkInteractionWidgets vtkInteractionStyle vtkIOLegacy vtkIOPLY vtkRenderingFreeType vtkRenderingLOD vtkFiltersTexture vtkIOExport NO_MODULE) if(NOT DEFINED VTK_FOUND OR NOT VTK_FOUND) find_package(VTK 5.10 QUIET COMPONENTS vtkCommon vtkFiltering vtkRendering vtkWidgets vtkImaging NO_MODULE) @@ -18,4 +18,4 @@ if(VTK_FOUND) else() set(HAVE_VTK OFF) message(STATUS "VTK is not found. Please set -DVTK_DIR in CMake to VTK build directory, or set $VTK_DIR enviroment variable to VTK install subdirectory with VTKConfig.cmake file (for windows)") -endif() \ No newline at end of file +endif() diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index ff8177546..b8567dd66 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -230,8 +230,8 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co CV_Assert("Cloud Widget without data" && currdata); vtkSmartPointer append_filter = vtkSmartPointer::New(); - append_filter->AddInputConnection(currdata->GetProducerPort()); - append_filter->AddInputConnection(polydata->GetProducerPort()); + VtkUtils::AddInputData(append_filter, currdata); + VtkUtils::AddInputData(append_filter, polydata); append_filter->Update(); VtkUtils::SetInputData(mapper, append_filter->GetOutput()); diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index bf154e76e..7440f1ee8 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -230,6 +230,25 @@ namespace cv filter->SetInputData(polydata); #endif } + template + static void SetSourceData(vtkSmartPointer filter, vtkPolyData* polydata) + { + #if VTK_MAJOR_VERSION <= 5 + filter->SetSource(polydata); + #else + filter->SetSourceData(polydata); + #endif + } + + template + static void SetInputData(vtkSmartPointer filter, vtkImageData* polydata) + { + #if VTK_MAJOR_VERSION <= 5 + filter->SetInput(polydata); + #else + filter->SetInputData(polydata); + #endif + } template static void AddInputData(vtkSmartPointer filter, vtkPolyData *polydata) @@ -285,7 +304,14 @@ namespace cv static vtkSmartPointer TransformPolydata(vtkSmartPointer polydata, const Affine3d& pose) { - return TransformPolydata(polydata->GetProducerPort(), pose); + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->SetMatrix(vtkmatrix(pose.matrix)); + + vtkSmartPointer transform_filter = vtkSmartPointer::New(); + VtkUtils::SetInputData(transform_filter, polydata); + transform_filter->SetTransform(transform); + transform_filter->Update(); + return transform_filter->GetOutput(); } }; } diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 92ab3400b..323482fa4 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -355,7 +355,7 @@ cv::viz::WCoordinateSystem::WCoordinateSystem(double scale) polydata->GetPointData()->SetScalars(colors); vtkSmartPointer tube_filter = vtkSmartPointer::New(); - tube_filter->SetInputConnection(polydata->GetProducerPort()); + VtkUtils::SetInputData(tube_filter, polydata); tube_filter->SetRadius(axes->GetScaleFactor() / 50.0); tube_filter->SetNumberOfSides(6); tube_filter->Update(); @@ -447,7 +447,7 @@ cv::viz::WGrid::WGrid(const Vec2i &cells, const Vec2d &cells_spacing, const Colo // Extract the edges so we have the grid vtkSmartPointer extract_edges = vtkSmartPointer::New(); - extract_edges->SetInputConnection(grid_data->GetProducerPort()); + VtkUtils::SetInputData(extract_edges, grid_data); extract_edges->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); @@ -854,13 +854,13 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, InputArray _image, d // Frustum needs to be textured or else it can't be combined with image vtkSmartPointer frustum_texture = vtkSmartPointer::New(); - frustum_texture->SetInputConnection(frustum->GetProducerPort()); + VtkUtils::SetInputData(frustum_texture, frustum); frustum_texture->SetSRange(0.0, 0.0); // Texture mapping with only one pixel frustum_texture->SetTRange(0.0, 0.0); // from the image to have constant color vtkSmartPointer append_filter = vtkSmartPointer::New(); append_filter->AddInputConnection(frustum_texture->GetOutputPort()); - append_filter->AddInputConnection(plane->GetProducerPort()); + VtkUtils::AddInputData(append_filter, plane); vtkSmartPointer actor = getActor(image_widget); actor->GetMapper()->SetInputConnection(append_filter->GetOutputPort()); @@ -886,13 +886,13 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, InputArray _image, d // Frustum needs to be textured or else it can't be combined with image vtkSmartPointer frustum_texture = vtkSmartPointer::New(); - frustum_texture->SetInputConnection(frustum->GetProducerPort()); + VtkUtils::SetInputData(frustum_texture, frustum); frustum_texture->SetSRange(0.0, 0.0); // Texture mapping with only one pixel frustum_texture->SetTRange(0.0, 0.0); // from the image to have constant color vtkSmartPointer append_filter = vtkSmartPointer::New(); append_filter->AddInputConnection(frustum_texture->GetOutputPort()); - append_filter->AddInputConnection(plane->GetProducerPort()); + VtkUtils::AddInputData(append_filter, plane); vtkSmartPointer actor = getActor(image_widget); actor->GetMapper()->SetInputConnection(append_filter->GetOutputPort()); @@ -917,7 +917,7 @@ cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double sca { Mat points = vtkTrajectorySource::ExtractPoints(_path); vtkSmartPointer polydata = getPolyData(WPolyLine(points, color)); - append_filter->AddInputConnection(polydata->GetProducerPort()); + VtkUtils::AddInputData(append_filter, polydata); } if (display_mode & WTrajectory::FRAMES) @@ -929,7 +929,7 @@ cv::viz::WTrajectory::WTrajectory(InputArray _path, int display_mode, double sca vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); tensor_glyph->SetInputConnection(source->GetOutputPort()); - tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); + VtkUtils::SetSourceData(tensor_glyph, glyph); tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues tensor_glyph->ThreeGlyphsOff(); tensor_glyph->SymmetricOff(); @@ -968,7 +968,7 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Matx33 vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); tensor_glyph->SetInputConnection(source->GetOutputPort()); - tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); + VtkUtils::SetSourceData(tensor_glyph, glyph); tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues tensor_glyph->ThreeGlyphsOff(); tensor_glyph->SymmetricOff(); @@ -994,7 +994,7 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); tensor_glyph->SetInputConnection(source->GetOutputPort()); - tensor_glyph->SetSourceConnection(glyph->GetProducerPort()); + VtkUtils::SetSourceData(tensor_glyph, glyph); tensor_glyph->ExtractEigenvaluesOff(); // Treat as a rotation matrix, not as something with eigenvalues tensor_glyph->ThreeGlyphsOff(); tensor_glyph->SymmetricOff(); @@ -1046,7 +1046,7 @@ cv::viz::WTrajectorySpheres::WTrajectorySpheres(InputArray _path, double line_le vtkSmartPointer polydata = sphere_source->GetOutput(); polydata->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata->GetNumberOfCells(), c)); - append_filter->AddInputConnection(polydata->GetProducerPort()); + VtkUtils::AddInputData(append_filter, polydata); if (i > 0) { @@ -1064,7 +1064,7 @@ cv::viz::WTrajectorySpheres::WTrajectorySpheres(InputArray _path, double line_le line_source->Update(); vtkSmartPointer polydata = line_source->GetOutput(); polydata->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata->GetNumberOfCells(), c)); - append_filter->AddInputConnection(polydata->GetProducerPort()); + VtkUtils::AddInputData(append_filter, polydata); } } append_filter->Update(); diff --git a/modules/viz/src/widget.cpp b/modules/viz/src/widget.cpp index 6c1463b76..33b467ebc 100644 --- a/modules/viz/src/widget.cpp +++ b/modules/viz/src/widget.cpp @@ -276,6 +276,7 @@ void cv::viz::Widget3D::applyTransform(const Affine3d &transform) vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); CV_Assert("Widget doesn't have a polydata mapper" && mapper); + mapper->Update(); VtkUtils::SetInputData(mapper, VtkUtils::TransformPolydata(mapper->GetInput(), transform)); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 3e25399b2..7f91c899b 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -113,7 +113,7 @@ TEST(Viz, show_painted_clouds) viz.setBackgroundMeshLab(); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("cloud1", WPaintedCloud(cloud), Affine3d(Vec3d(0.0, -CV_PI/2, 0.0), Vec3d(-1.5, 0.0, 0.0))); - viz.showWidget("cloud2", WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(1.5, 0.0, 0.0))); + viz.showWidget("cloud2", WPaintedCloud(cloud, Vec3d(0.0, -0.75, -1.0), Vec3d(0.0, 0.75, 0.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(1.5, 0.0, 0.0))); viz.showWidget("cloud3", WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0), Color::blue(), Color::red())); viz.showWidget("arrow", WArrow(Vec3d(0.0, 1.0, -1.0), Vec3d(0.0, 1.0, 1.0), 0.009, Color::raspberry())); viz.spin(); From ffad7b699c0676a758233fe4e4fb9aaa5754eb18 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 14 Jan 2014 01:01:51 +0400 Subject: [PATCH 181/295] added test for textured mesh --- modules/viz/include/opencv2/viz.hpp | 3 +- modules/viz/include/opencv2/viz/types.hpp | 2 +- modules/viz/src/types.cpp | 20 ------------- modules/viz/test/test_viz3d.cpp | 15 ---------- modules/viz/test/tests_simple.cpp | 36 +++++++++++++++++++++++ 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index a532ba783..bf44a2c03 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -99,8 +99,7 @@ namespace cv CV_EXPORTS Mat readCloud (const String& file, OutputArray colors = noArray(), OutputArray normals = noArray()); /////////////////////////////////////////////////////////////////////////////////////////////// - /// Reads mesh. Only ply format is supported now. The function tries to read texture from png-file, - /// and in case of faulure, just leaves the texture field empty. + /// Reads mesh. Only ply format is supported now and no texture load support CV_EXPORTS Mesh readMesh(const String& file); diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index cdd89d3a0..e61c837be 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -115,7 +115,7 @@ namespace cv Mat texture, tcoords; - //! Loads mesh from a given ply file + //! Loads mesh from a given ply file (no texture load support for now) static Mesh load(const String& file); }; diff --git a/modules/viz/src/types.cpp b/modules/viz/src/types.cpp index bf61432cb..2e32a6327 100644 --- a/modules/viz/src/types.cpp +++ b/modules/viz/src/types.cpp @@ -73,7 +73,6 @@ cv::viz::Mesh cv::viz::Mesh::load(const String& file) sink->Write(); // Now handle the polygons - vtkSmartPointer polygons = polydata->GetPolys(); mesh.polygons.create(1, polygons->GetSize(), CV_32SC1); int* poly_ptr = mesh.polygons.ptr(); @@ -87,25 +86,6 @@ cv::viz::Mesh cv::viz::Mesh::load(const String& file) *poly_ptr++ = (int)cell_points[i]; } - String::size_type pos = file.find_last_of('.'); - String png = (pos == String::npos) ? file : file.substr(0, pos+1) + "png"; - - vtkSmartPointer png_reader = vtkSmartPointer::New(); - - if (png_reader->CanReadFile(png.c_str())) - { - png_reader->SetFileName(png.c_str()); - png_reader->Update(); - vtkSmartPointer imagedata = png_reader->GetOutput(); - - Size sz(imagedata->GetDimensions()[0], imagedata->GetDimensions()[1]); - int channels = imagedata->GetNumberOfScalarComponents(); - CV_Assert(imagedata->GetScalarType() == VTK_UNSIGNED_CHAR); - - void *ptr = imagedata->GetScalarPointer(0,0,0); - Mat(sz, CV_8UC(channels), ptr).copyTo(mesh.texture); - } - return mesh; } diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 66ec25db8..bdfda6d9b 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -47,19 +47,11 @@ TEST(Viz_viz3d, develop) { cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); - //cv::viz::Mesh3d mesh = cv::viz::Mesh3d::load(get_dragon_ply_file_path()); - //theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); - cv::viz::Viz3d viz("abc"); viz.setBackgroundMeshLab(); viz.showWidget("coo", cv::viz::WCoordinateSystem(1)); - //viz.showWidget("cloud", cv::viz::WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0))); - //viz.showWidget("cloud", cv::viz::WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0), cv::viz::Color::green(), cv::viz::Color::red())); viz.showWidget("cloud", cv::viz::WPaintedCloud(cloud)); - //viz.showWidget("h", cv::viz::Widget::fromPlyFile("d:/horse-red.ply")); - //viz.showWidget("a", cv::viz::WArrow(cv::Point3f(0,0,0), cv::Point3f(1,1,1))); - //---->>>>> //std::vector gt, es; //cv::viz::readTrajectory(gt, "d:/Datasets/trajs/gt%05d.xml"); @@ -67,12 +59,5 @@ TEST(Viz_viz3d, develop) //cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); //---->>>>> - //theRNG().fill(colors, cv::RNG::UNIFORM, 0, 255); - //viz.showWidget("c", cv::viz::WCloud(cloud, colors)); - //viz.showWidget("c", cv::viz::WCloud(cloud, cv::viz::Color::bluberry())); - - //viz.showWidget("l", cv::viz::WLine(Point3f(0,0,0), Point3f(1,1,1))); - //viz.showWidget("s", cv::viz::WSphere(Point3f(0,0,0), 1)); - //viz.showWidget("d", cv::viz::WCircle(Point3f(0,0,0), 1)); viz.spin(); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 7f91c899b..ec475580e 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -145,6 +145,42 @@ TEST(Viz, show_mesh_random_colors) viz.spin(); } +TEST(Viz, show_textured_mesh) +{ + Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); + + std::vector points; + std::vector tcoords; + std::vector polygons; + for(size_t i = 0; i < 64; ++i) + { + double angle = CV_PI/2 * i/64.0; + points.push_back(Vec3d(0.00, cos(angle), sin(angle))*0.75); + points.push_back(Vec3d(1.57, cos(angle), sin(angle))*0.75); + tcoords.push_back(Vec2d(0.0, i/64.0)); + tcoords.push_back(Vec2d(1.0, i/64.0)); + } + + for(size_t i = 0; i < points.size()/2-1; ++i) + { + int polys[] = {3, 2*i, 2*i+1, 2*i+2, 3, 2*i+1, 2*i+2, 2*i+3}; + polygons.insert(polygons.end(), polys, polys + sizeof(polys)/sizeof(polys[0])); + } + + cv::viz::Mesh mesh; + mesh.cloud = Mat(points, true).reshape(3, 1); + mesh.tcoords = Mat(tcoords, true).reshape(2, 1); + mesh.polygons = Mat(polygons, true).reshape(1, 1); + mesh.texture = lena; + + Viz3d viz("show_textured_mesh"); + viz.setBackgroundMeshLab(); + viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("mesh", WMesh(mesh)); + viz.setRenderingProperty("mesh", SHADING, SHADING_PHONG); + viz.spin(); +} + TEST(Viz, show_polyline) { Mat polyline(1, 32, CV_64FC3); From 57d5ad5131d400c349f5edf97cabb95ea3960b65 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 18 Jan 2014 17:19:17 +0400 Subject: [PATCH 182/295] minor iteractor refactoring --- modules/viz/src/interactor_style.cpp | 63 +++++++--------------------- 1 file changed, 16 insertions(+), 47 deletions(-) diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index c2583f936..42858f105 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -275,7 +275,7 @@ void cv::viz::InteractorStyle::OnKeyDown() for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); ) for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) { - vtkActor* apart = reinterpret_cast (path->GetLastNode()->GetViewProp()); + vtkActor* apart = vtkActor::SafeDownCast(path->GetLastNode()->GetViewProp()); apart->GetProperty()->SetRepresentationToPoints(); } break; @@ -328,7 +328,7 @@ void cv::viz::InteractorStyle::OnKeyDown() for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); ) for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) { - vtkActor* apart = reinterpret_cast (path->GetLastNode()->GetViewProp()); + vtkActor* apart = vtkActor::SafeDownCast(path->GetLastNode()->GetViewProp()); float psize = apart->GetProperty()->GetPointSize(); if (psize < 63.0f) apart->GetProperty()->SetPointSize(psize + 1.0f); @@ -347,7 +347,7 @@ void cv::viz::InteractorStyle::OnKeyDown() for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); ) for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) { - vtkActor* apart = static_cast(path->GetLastNode()->GetViewProp()); + vtkActor* apart = vtkActor::SafeDownCast(path->GetLastNode()->GetViewProp()); float psize = apart->GetProperty()->GetPointSize(); if (psize > 1.0f) apart->GetProperty()->SetPointSize(psize - 1.0f); @@ -386,13 +386,11 @@ void cv::viz::InteractorStyle::OnKeyDown() else { AnimState = VTKIS_ANIM_ON; - vtkAssemblyPath *path = NULL; Interactor->GetPicker()->Pick(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1], 0.0, CurrentRenderer); - vtkAbstractPropPicker *picker; - if ((picker = vtkAbstractPropPicker::SafeDownCast(Interactor->GetPicker()))) - path = picker->GetPath(); - if (path != NULL) - Interactor->FlyTo(CurrentRenderer, picker->GetPickPosition()); + vtkSmartPointer picker = vtkAbstractPropPicker::SafeDownCast(Interactor->GetPicker()); + if (picker) + if (picker->GetPath()) + Interactor->FlyTo(CurrentRenderer, picker->GetPickPosition()); AnimState = VTKIS_ANIM_OFF; } break; @@ -402,22 +400,14 @@ void cv::viz::InteractorStyle::OnKeyDown() { if (alt) { - int stereo_render = Interactor->GetRenderWindow()->GetStereoRender(); - if (!stereo_render) + vtkSmartPointer window = Interactor->GetRenderWindow(); + if (!window->GetStereoRender()) { - if (stereo_anaglyph_mask_default_) - { - Interactor->GetRenderWindow()->SetAnaglyphColorMask(4, 3); - stereo_anaglyph_mask_default_ = false; - } - else - { - Interactor->GetRenderWindow()->SetAnaglyphColorMask(2, 5); - stereo_anaglyph_mask_default_ = true; - } + static Vec2i default_mask(4, 3), alternative_mask(2, 5); + window->SetAnaglyphColorMask (stereo_anaglyph_mask_default_ ? default_mask.val : alternative_mask.val); + stereo_anaglyph_mask_default_ = !stereo_anaglyph_mask_default_; } - Interactor->GetRenderWindow()->SetStereoRender(!stereo_render); - Interactor->GetRenderWindow()->Render(); + window->SetStereoRender(!window->GetStereoRender()); Interactor->Render(); } else @@ -429,7 +419,6 @@ void cv::viz::InteractorStyle::OnKeyDown() { vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); cam->SetParallelProjection(!cam->GetParallelProjection()); - CurrentRenderer->SetActiveCamera(cam); CurrentRenderer->Render(); break; } @@ -443,27 +432,19 @@ void cv::viz::InteractorStyle::OnKeyDown() break; } - static WidgetActorMap::iterator it = widget_actor_map_->begin(); + WidgetActorMap::iterator it = widget_actor_map_->begin(); // it might be that some actors don't have a valid transformation set -> we skip them to avoid a seg fault. - bool found_transformation = false; - - for (size_t idx = 0; idx < widget_actor_map_->size(); ++idx, ++it) + for (; it != widget_actor_map_->end(); ++it) { - if (it == widget_actor_map_->end()) - it = widget_actor_map_->begin(); - vtkProp3D * actor = vtkProp3D::SafeDownCast(it->second); if (actor && actor->GetUserMatrix()) - { - found_transformation = true; break; - } } vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); // if a valid transformation was found, use it otherwise fall back to default view point. - if (found_transformation) + if (it != widget_actor_map_->end()) { vtkMatrix4x4* m = vtkProp3D::SafeDownCast(it->second)->GetUserMatrix(); @@ -506,11 +487,8 @@ void cv::viz::InteractorStyle::OnKeyDown() } KeyboardEvent event(KeyboardEvent::KEY_DOWN, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); - // Check if there is a keyboard callback registered if (keyboardCallback_) keyboardCallback_(event, keyboard_callback_cookie_); - - renderer_->Render(); Interactor->Render(); } @@ -518,10 +496,8 @@ void cv::viz::InteractorStyle::OnKeyDown() void cv::viz::InteractorStyle::OnKeyUp() { KeyboardEvent event(KeyboardEvent::KEY_UP, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); - // Check if there is a keyboard callback registered if (keyboardCallback_) keyboardCallback_(event, keyboard_callback_cookie_); - Superclass::OnKeyUp(); } @@ -603,7 +579,6 @@ void cv::viz::InteractorStyle::OnMouseWheelForward() { Vec2i p(Interactor->GetEventPosition()); MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getModifiers()); - // If a mouse callback registered, call it! if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); if (Interactor->GetRepeatCount() && mouseCallback_) @@ -619,11 +594,9 @@ void cv::viz::InteractorStyle::OnMouseWheelForward() cam->SetViewAngle(opening_angle); cam->Modified(); - CurrentRenderer->SetActiveCamera(cam); CurrentRenderer->ResetCameraClippingRange(); CurrentRenderer->Modified(); CurrentRenderer->Render(); - renderer_->Render(); Interactor->Render(); } else @@ -635,7 +608,6 @@ void cv::viz::InteractorStyle::OnMouseWheelBackward() { Vec2i p(Interactor->GetEventPosition()); MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getModifiers()); - // If a mouse callback registered, call it! if (mouseCallback_) mouseCallback_(event, mouse_callback_cookie_); @@ -652,11 +624,9 @@ void cv::viz::InteractorStyle::OnMouseWheelBackward() cam->SetViewAngle(opening_angle); cam->Modified(); - CurrentRenderer->SetActiveCamera(cam); CurrentRenderer->ResetCameraClippingRange(); CurrentRenderer->Modified(); CurrentRenderer->Render(); - renderer_->Render(); Interactor->Render(); } else @@ -668,6 +638,5 @@ void cv::viz::InteractorStyle::OnTimer() { CV_Assert("Interactor style not initialized." && init_); CV_Assert("Renderer has not been set." && renderer_); - renderer_->Render(); Interactor->Render(); } From 16281027af498e3e63ed270cfde7b826480c6885 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 18 Jan 2014 21:43:10 +0400 Subject: [PATCH 183/295] resolved problem with multiple spin()/spinOnce() --- modules/viz/doc/viz3d.rst | 16 -- modules/viz/include/opencv2/viz/viz3d.hpp | 3 - modules/viz/src/interactor_style.cpp | 7 +- modules/viz/src/interactor_style.hpp | 2 - modules/viz/src/viz3d.cpp | 3 - modules/viz/src/vizimpl.cpp | 194 ++++++++++------------ modules/viz/src/vizimpl.hpp | 88 +++------- modules/viz/test/tests_simple.cpp | 21 +-- 8 files changed, 117 insertions(+), 217 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index ec5b16e71..5b361ad84 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -134,8 +134,6 @@ The Viz3d class represents a 3D visualizer window. This class is implicitly shar void setRenderingProperty(const String &id, int property, double value); double getRenderingProperty(const String &id, int property); - void setDesiredUpdateRate(double rate); - double getDesiredUpdateRate(); void setRepresentation(int representation); private: @@ -425,20 +423,6 @@ Returns rendering property of a widget. * **SHADING_GOURAUD** * **SHADING_PHONG** -viz::Viz3d::setDesiredUpdateRate --------------------------------- -Sets desired update rate of the window. - -.. ocv:function:: void setDesiredUpdateRate(double rate) - - :param rate: Desired update rate. The default is 30. - -viz::Viz3d::getDesiredUpdateRate --------------------------------- -Returns desired update rate of the window. - -.. ocv:function:: double getDesiredUpdateRate() - viz::Viz3d::setRepresentation ----------------------------- Sets geometry representation of the widgets to surface, wireframe or points. diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index b9712ef3e..090c8b14e 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -113,9 +113,6 @@ namespace cv void setRenderingProperty(const String &id, int property, double value); double getRenderingProperty(const String &id, int property); - void setDesiredUpdateRate(double rate); - double getDesiredUpdateRate(); - void setRepresentation(int representation); private: diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp index 42858f105..75003a2b6 100644 --- a/modules/viz/src/interactor_style.cpp +++ b/modules/viz/src/interactor_style.cpp @@ -220,8 +220,6 @@ int cv::viz::InteractorStyle::getModifiers() void cv::viz::InteractorStyle::OnKeyDown() { CV_Assert("Interactor style not initialized. Please call Initialize() before continuing" && init_); - CV_Assert("No renderer given! Use SetRendererCollection() before continuing." && renderer_); - FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); // Save the initial windows width/height @@ -403,8 +401,8 @@ void cv::viz::InteractorStyle::OnKeyDown() vtkSmartPointer window = Interactor->GetRenderWindow(); if (!window->GetStereoRender()) { - static Vec2i default_mask(4, 3), alternative_mask(2, 5); - window->SetAnaglyphColorMask (stereo_anaglyph_mask_default_ ? default_mask.val : alternative_mask.val); + static Vec2i red_blue(4, 3), magenta_green(2, 5); + window->SetAnaglyphColorMask (stereo_anaglyph_mask_default_ ? red_blue.val : magenta_green.val); stereo_anaglyph_mask_default_ = !stereo_anaglyph_mask_default_; } window->SetStereoRender(!window->GetStereoRender()); @@ -637,6 +635,5 @@ void cv::viz::InteractorStyle::OnMouseWheelBackward() void cv::viz::InteractorStyle::OnTimer() { CV_Assert("Interactor style not initialized." && init_); - CV_Assert("Renderer has not been set." && renderer_); Interactor->Render(); } diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/interactor_style.hpp index 583860911..8d01697a8 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/interactor_style.hpp @@ -63,7 +63,6 @@ namespace cv virtual void Initialize(); void setWidgetActorMap(const Ptr& actors) { widget_actor_map_ = actors; } - void setRenderer(vtkSmartPointer& renderer) { renderer_ = renderer; } void registerMouseCallback(void (*callback)(const MouseEvent&, void*), void* cookie = 0); void registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void * cookie = 0); void saveScreenshot(const String &file); @@ -73,7 +72,6 @@ namespace cv /** \brief Set to true after initialization is complete. */ bool init_; - vtkSmartPointer renderer_; Ptr widget_actor_map_; Vec2i win_size_; diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 503359f01..237ef87c9 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -145,7 +145,4 @@ void cv::viz::Viz3d::setBackgroundMeshLab() {impl_->setBackgroundMeshLab(); } void cv::viz::Viz3d::setRenderingProperty(const String &id, int property, double value) { getWidget(id).setRenderingProperty(property, value); } double cv::viz::Viz3d::getRenderingProperty(const String &id, int property) { return getWidget(id).getRenderingProperty(property); } -void cv::viz::Viz3d::setDesiredUpdateRate(double rate) { impl_->setDesiredUpdateRate(rate); } -double cv::viz::Viz3d::getDesiredUpdateRate() { return impl_->getDesiredUpdateRate(); } - void cv::viz::Viz3d::setRepresentation(int representation) { impl_->setRepresentation(representation); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 61a0a01f6..e66b53823 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -46,25 +46,17 @@ #include "precomp.hpp" ///////////////////////////////////////////////////////////////////////////////////////////// -cv::viz::Viz3d::VizImpl::VizImpl(const String &name) - : s_lastDone_(0.0), style_(vtkSmartPointer::New()), widget_actor_map_(new WidgetActorMap) +cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : spin_once_state_(false), widget_actor_map_(new WidgetActorMap) { renderer_ = vtkSmartPointer::New(); - window_ = vtkSmartPointer::New(); - // Set the window size as 1/2 of the screen size + // Create render window + window_ = vtkSmartPointer::New(); + window_name_ = VizStorage::generateWindowName(name); + cv::Vec2i window_size = cv::Vec2i(window_->GetScreenSize()) / 2; window_->SetSize(window_size.val); window_->AddRenderer(renderer_); - - // Create the interactor style - style_->Initialize(); - style_->setRenderer(renderer_); - style_->setWidgetActorMap(widget_actor_map_); - style_->UseTimersOn(); - - interactor_ = vtkSmartPointer::New(); - window_->AlphaBitPlanesOff(); window_->PointSmoothingOff(); window_->LineSmoothingOff(); @@ -72,37 +64,89 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) window_->SwapBuffersOn(); window_->SetStereoTypeToAnaglyph(); - interactor_->SetRenderWindow(window_); - interactor_->SetInteractorStyle(style_); - interactor_->SetDesiredUpdateRate(24.0); - - // Initialize and create timer, also create window - interactor_->Initialize(); - timer_id_ = interactor_->CreateRepeatingTimer(5000L); - - exit_main_loop_timer_callback_ = vtkSmartPointer::New(); - exit_main_loop_timer_callback_->viz_ = this; - exit_main_loop_timer_callback_->right_timer_id = -1; - interactor_->AddObserver(vtkCommand::TimerEvent, exit_main_loop_timer_callback_); + // Create the interactor style + style_ = vtkSmartPointer::New(); + style_->setWidgetActorMap(widget_actor_map_); + style_->UseTimersOn(); + style_->Initialize(); + timer_callback_ = vtkSmartPointer::New(); exit_callback_ = vtkSmartPointer::New(); - exit_callback_->viz_ = this; - interactor_->AddObserver(vtkCommand::ExitEvent, exit_callback_); - - resetStoppedFlag(); - - ////////////////////////////// - String window_name = VizStorage::generateWindowName(name); - window_->SetWindowName(window_name.c_str()); + exit_callback_->viz = this; } ///////////////////////////////////////////////////////////////////////////////////////////// -cv::viz::Viz3d::VizImpl::~VizImpl() +void cv::viz::Viz3d::VizImpl::TimerCallback::Execute(vtkObject* caller, unsigned long event_id, void* cookie) { - if (interactor_) - interactor_->DestroyTimer(timer_id_); - if (renderer_) - renderer_->Clear(); + if (event_id == vtkCommand::TimerEvent && timer_id == *reinterpret_cast(cookie)) + { + vtkSmartPointer interactor = vtkRenderWindowInteractor::SafeDownCast(caller); + interactor->TerminateApp(); + } +} + +void cv::viz::Viz3d::VizImpl::ExitCallback::Execute(vtkObject*, unsigned long event_id, void*) +{ + if (event_id == vtkCommand::ExitEvent) + { + viz->interactor_->TerminateApp(); + viz->interactor_ = 0; + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// + +bool cv::viz::Viz3d::VizImpl::wasStopped() const +{ + bool stopped = spin_once_state_ ? interactor_ == 0 : false; + spin_once_state_ &= !stopped; + return stopped; +} + +void cv::viz::Viz3d::VizImpl::close() +{ + if (!interactor_) + return; + interactor_->GetRenderWindow()->Finalize(); + interactor_->TerminateApp(); // This tends to close the window... +} + +///////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::spin() +{ + interactor_ = vtkSmartPointer::New(); + interactor_->SetRenderWindow(window_); + interactor_->SetInteractorStyle(style_); + window_->Render(); + window_->SetWindowName(window_name_.c_str()); + interactor_->Start(); + interactor_ = 0; +} + +///////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) +{ + if (interactor_ == 0) + { + spin_once_state_ = true; + interactor_ = vtkSmartPointer::New(); + interactor_->SetRenderWindow(window_); + interactor_->SetInteractorStyle(style_); + interactor_->AddObserver(vtkCommand::TimerEvent, timer_callback_); + interactor_->AddObserver(vtkCommand::ExitEvent, exit_callback_); + window_->Render(); + window_->SetWindowName(window_name_.c_str()); + } + + vtkSmartPointer local = interactor_; + + if (force_redraw) + local->Render(); + + timer_callback_->timer_id = local->CreateOneShotTimer(std::max(1, time)); + local->Start(); + local->DestroyTimer(timer_callback_->timer_id); + } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -208,19 +252,6 @@ cv::Affine3d cv::viz::Viz3d::VizImpl::getWidgetPose(const String &id) const return Affine3d(*actor->GetUserMatrix()->Element); } -///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setDesiredUpdateRate(double rate) -{ - if (interactor_) - interactor_->SetDesiredUpdateRate(rate); -} - -///////////////////////////////////////////////////////////////////////////////////////////// -double cv::viz::Viz3d::VizImpl::getDesiredUpdateRate() -{ - return interactor_ ? interactor_->GetDesiredUpdateRate() : 0.0; -} - ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::saveScreenshot(const String &file) { style_->saveScreenshot(file.c_str()); } @@ -231,37 +262,6 @@ void cv::viz::Viz3d::VizImpl::registerMouseCallback(MouseCallback callback, void void cv::viz::Viz3d::VizImpl::registerKeyboardCallback(KeyboardCallback callback, void* cookie) { style_->registerKeyboardCallback(callback, cookie); } -///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::spin() -{ - resetStoppedFlag(); - window_->Render(); - interactor_->Start(); -} - -///////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) -{ - resetStoppedFlag(); - - if (time <= 0) - time = 1; - - if (force_redraw) - interactor_->Render(); - - double s_now_ = cv::getTickCount() / cv::getTickFrequency(); - if (s_lastDone_ > s_now_) - s_lastDone_ = s_now_; - - if ((s_now_ - s_lastDone_) > (1.0 / interactor_->GetDesiredUpdateRate())) - { - exit_main_loop_timer_callback_->right_timer_id = interactor_->CreateRepeatingTimer(time); - interactor_->Start(); - interactor_->DestroyTimer(exit_main_loop_timer_callback_->right_timer_id); - s_lastDone_ = s_now_; - } -} ////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::removeAllWidgets() @@ -282,18 +282,15 @@ void cv::viz::Viz3d::VizImpl::showImage(InputArray image, const Size& window_siz ///////////////////////////////////////////////////////////////////////////////////////////// bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(vtkSmartPointer actor) { - vtkProp* actor_to_remove = vtkProp::SafeDownCast(actor); - vtkPropCollection* actors = renderer_->GetViewProps(); actors->InitTraversal(); vtkProp* current_actor = NULL; while ((current_actor = actors->GetNextProp()) != NULL) - { - if (current_actor != actor_to_remove) - continue; - renderer_->RemoveActor(actor); - return true; - } + if (current_actor == actor) + { + renderer_->RemoveActor(actor); + return true; + } return false; } @@ -313,11 +310,8 @@ void cv::viz::Viz3d::VizImpl::setBackgroundGradient(const Color& up, const Colo renderer_->GradientBackgroundOn(); } -////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setBackgroundMeshLab() -{ - setBackgroundGradient(Color(2, 1, 1), Color(240, 120, 120)); -} +{ setBackgroundGradient(Color(2, 1, 1), Color(240, 120, 120)); } ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setBackgroundTexture(InputArray image) @@ -512,14 +506,8 @@ void cv::viz::Viz3d::VizImpl::setRepresentation(int representation) } ////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) -{ - if (window_) - window_->SetFullScreen(mode); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -cv::String cv::viz::Viz3d::VizImpl::getWindowName() const { return window_ ? window_->GetWindowName() : ""; } +cv::String cv::viz::Viz3d::VizImpl::getWindowName() const { return window_name_; } +void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) { window_->SetFullScreen(mode); } void cv::viz::Viz3d::VizImpl::setWindowPosition(const Point& position) { window_->SetPosition(position.x, position.y); } void cv::viz::Viz3d::VizImpl::setWindowSize(const Size& window_size) { window_->SetSize(window_size.width, window_size.height); } -cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(window_->GetSize()[0], window_->GetSize()[1]); } +cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(Point(Vec2i(window_->GetSize()))); } diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index 11b8490a1..1b9abea64 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -55,7 +55,13 @@ public: int ref_counter; VizImpl(const String &name); - virtual ~VizImpl(); + virtual ~VizImpl() {}; + + bool wasStopped() const; + void close(); + + void spin(); + void spinOnce(int time = 1, bool force_redraw = false); void showWidget(const String &id, const Widget &widget, const Affine3d &pose = Affine3d::Identity()); void removeWidget(const String &id); @@ -68,26 +74,6 @@ public: void updateWidgetPose(const String &id, const Affine3d &pose); Affine3d getWidgetPose(const String &id) const; - void setDesiredUpdateRate(double rate); - double getDesiredUpdateRate(); - - /** \brief Returns true when the user tried to close the window */ - bool wasStopped() const { return interactor_ ? stopped_ : true; } - - /** \brief Set the stopped flag back to false */ - void resetStoppedFlag() { if (interactor_) stopped_ = false; } - - /** \brief Stop the interaction and close the visualizaton window. */ - void close() - { - stopped_ = true; - if (interactor_) - { - interactor_->GetRenderWindow()->Finalize(); - interactor_->TerminateApp(); // This tends to close the window... - } - } - void setRepresentation(int representation); void setCamera(const Camera &camera); @@ -114,72 +100,36 @@ public: void setBackgroundTexture(InputArray image); void setBackgroundMeshLab(); - void spin(); - void spinOnce(int time = 1, bool force_redraw = false); - void registerKeyboardCallback(KeyboardCallback callback, void* cookie = 0); void registerMouseCallback(MouseCallback callback, void* cookie = 0); private: - vtkSmartPointer interactor_; - - struct ExitMainLoopTimerCallback : public vtkCommand + struct TimerCallback : public vtkCommand { - static ExitMainLoopTimerCallback* New() { return new ExitMainLoopTimerCallback; } - virtual void Execute(vtkObject* vtkNotUsed(caller), unsigned long event_id, void* call_data) - { - if (event_id != vtkCommand::TimerEvent) - return; - - int timer_id = *reinterpret_cast(call_data); - if (timer_id != right_timer_id) - return; - - // Stop vtk loop and send notification to app to wake it up - viz_->interactor_->TerminateApp(); - } - int right_timer_id; - VizImpl* viz_; + static TimerCallback* New() { return new TimerCallback; } + virtual void Execute(vtkObject* caller, unsigned long event_id, void* cookie); + int timer_id; }; struct ExitCallback : public vtkCommand { static ExitCallback* New() { return new ExitCallback; } - virtual void Execute(vtkObject*, unsigned long event_id, void*) - { - if (event_id == vtkCommand::ExitEvent) - { - viz_->stopped_ = true; - viz_->interactor_->GetRenderWindow()->Finalize(); - viz_->interactor_->TerminateApp(); - } - } - VizImpl* viz_; + virtual void Execute(vtkObject*, unsigned long event_id, void*); + VizImpl* viz; }; - /** \brief Set to false if the interaction loop is running. */ - bool stopped_; + mutable bool spin_once_state_; + vtkSmartPointer interactor_; - double s_lastDone_; + vtkSmartPointer window_; + String window_name_; - /** \brief Global timer ID. Used in destructor only. */ - int timer_id_; - - /** \brief Callback object enabling us to leave the main loop, when a timer fires. */ - vtkSmartPointer exit_main_loop_timer_callback_; + vtkSmartPointer timer_callback_; vtkSmartPointer exit_callback_; vtkSmartPointer renderer_; - vtkSmartPointer window_; - - /** \brief The render window interactor style. */ vtkSmartPointer style_; - - /** \brief Internal list with actor pointers and name IDs for all widget actors */ - cv::Ptr widget_actor_map_; - - /** \brief Boolean that holds whether or not the camera parameters were manually initialized*/ - bool camera_set_; + Ptr widget_actor_map_; bool removeActorFromRenderer(vtkSmartPointer actor); }; diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index ec475580e..dad4aacca 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -236,7 +236,7 @@ TEST(Viz, show_trajectories) viz.setViewerPose(makeCameraPose(pose * 7.5, Vec3d(0.0, 0.5, 0.0), Vec3d(0.0, 0.1, 0.0))); viz.spinOnce(20, true); } - //viz.spin(); + viz.spin(); } TEST(Viz, show_trajectory_reposition) @@ -299,7 +299,7 @@ TEST(Viz, show_overlay_image) viz.getWidget("img1").cast().setImage(lena * pow(sin(i*10*CV_PI/180) * 0.5 + 0.5, 1.0)); viz.spinOnce(1, true); } - //viz.spin(); + viz.spin(); } @@ -338,7 +338,7 @@ TEST(Viz, show_image_3d) viz.getWidget("img0").cast().setImage(lena * pow(sin(i++*7.5*CV_PI/180) * 0.5 + 0.5, 1.0)); viz.spinOnce(1, true); } - //viz.spin(); + viz.spin(); } TEST(Viz, show_simple_widgets) @@ -365,7 +365,7 @@ TEST(Viz, show_simple_widgets) viz.showWidget("grid1", WGrid(Vec2i(7,7), Vec2d::all(0.75), Color::gray()), Affine3d().translate(Vec3d(0.0, 0.0, -1.0))); - viz.spinOnce(1500, true); + viz.spin(); viz.getWidget("text2d").cast().setText("New simple text"); viz.getWidget("text3d").cast().setText("Updated text 3D"); viz.spin(); @@ -379,18 +379,7 @@ TEST(Viz, show_follower) viz.showWidget("cube", WCube()); viz.showWidget("t3d_2", WText3D("Simple 3D follower", Point3d(-0.5, -0.5, 0.5), 0.125, true, Color::green())); viz.setBackgroundMeshLab(); - viz.spinOnce(1500, true); + viz.spin(); viz.getWidget("t3d_2").cast().setText("Updated follower 3D"); viz.spin(); } - -TEST(Viz, DISABLED_spin_twice_____________________________TODO_UI_BUG) -{ - Mesh mesh = Mesh::load(get_dragon_ply_file_path()); - - Viz3d viz("spin_twice"); - viz.showWidget("coosys", WCoordinateSystem()); - viz.showWidget("mesh", WMesh(mesh)); - viz.spin(); - viz.spin(); -} From d7ca0bb757c38d4f54f5c8e565f211fdaa7dab66 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 18 Jan 2014 22:25:40 +0400 Subject: [PATCH 184/295] merged background color with background gradient methods, updated tests to show description of scene --- modules/viz/include/opencv2/viz/types.hpp | 4 +++ modules/viz/include/opencv2/viz/viz3d.hpp | 3 +-- modules/viz/src/shapes.cpp | 6 +++-- modules/viz/src/viz3d.cpp | 3 +-- modules/viz/src/vizimpl.cpp | 30 ++++++++++++----------- modules/viz/src/vizimpl.hpp | 3 +-- modules/viz/test/test_viz3d.cpp | 3 ++- modules/viz/test/tests_simple.cpp | 25 ++++++++++++++++--- 8 files changed, 51 insertions(+), 26 deletions(-) diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index e61c837be..3c3571b83 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -102,6 +102,8 @@ namespace cv static Color turquoise(); static Color celestial_blue(); static Color amethyst(); + + static Color not_set(); }; class CV_EXPORTS Mesh @@ -229,4 +231,6 @@ inline cv::viz::Color cv::viz::Color::turquoise() { return Color(208, 224, inline cv::viz::Color cv::viz::Color::celestial_blue() { return Color(208, 151, 73); } inline cv::viz::Color cv::viz::Color::amethyst() { return Color(204, 102, 153); } +inline cv::viz::Color cv::viz::Color::not_set() { return Color(-1, -1, -1); } + #endif diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index 090c8b14e..a83d8e8fc 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -98,9 +98,8 @@ namespace cv void saveScreenshot(const String &file); void setWindowPosition(const Point& window_position); void setFullScreen(bool mode = true); - void setBackgroundColor(const Color& color = Color::black()); + void setBackgroundColor(const Color& color = Color::black(), const Color& color2 = Color::not_set()); void setBackgroundTexture(InputArray image = noArray()); - void setBackgroundGradient(const Color& up, const Color& down); void setBackgroundMeshLab(); void spin(); diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 323482fa4..9011d0b18 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -549,12 +549,14 @@ template<> cv::viz::WText3D cv::viz::Widget::cast() cv::viz::WText::WText(const String &text, const Point &pos, int font_size, const Color &color) { vtkSmartPointer actor = vtkSmartPointer::New(); - actor->SetPosition(pos.x, pos.y); + actor->SetDisplayPosition(pos.x, pos.y); actor->SetInput(text.c_str()); + actor->GetProperty()->SetDisplayLocationToForeground(); + vtkSmartPointer tprop = actor->GetTextProperty(); tprop->SetFontSize(font_size); - tprop->SetFontFamilyToArial(); + tprop->SetFontFamilyToCourier(); tprop->SetJustificationToLeft(); tprop->BoldOn(); diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 237ef87c9..2d4aefc0b 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -136,8 +136,7 @@ cv::String cv::viz::Viz3d::getWindowName() const { return impl_->getWindowName() void cv::viz::Viz3d::saveScreenshot(const String &file) { impl_->saveScreenshot(file); } void cv::viz::Viz3d::setWindowPosition(const Point& window_position) { impl_->setWindowPosition(window_position); } void cv::viz::Viz3d::setFullScreen(bool mode) { impl_->setFullScreen(mode); } -void cv::viz::Viz3d::setBackgroundColor(const Color& color) { impl_->setBackgroundColor(color); } -void cv::viz::Viz3d::setBackgroundGradient(const Color& up, const Color& down) { impl_->setBackgroundGradient(up, down); } +void cv::viz::Viz3d::setBackgroundColor(const Color& color, const Color& color2) { impl_->setBackgroundColor(color, color2); } void cv::viz::Viz3d::setBackgroundTexture(InputArray image) { impl_->setBackgroundTexture(image); } void cv::viz::Viz3d::setBackgroundMeshLab() {impl_->setBackgroundMeshLab(); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index e66b53823..e50666ec8 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -143,10 +143,9 @@ void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) if (force_redraw) local->Render(); - timer_callback_->timer_id = local->CreateOneShotTimer(std::max(1, time)); + timer_callback_->timer_id = local->CreateRepeatingTimer(std::max(1, time)); local->Start(); local->DestroyTimer(timer_callback_->timer_id); - } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -295,23 +294,26 @@ bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(vtkSmartPointer a } ////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color) +void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color, const Color& color2) { - Color c = vtkcolor(color); - renderer_->SetBackground(c.val); - renderer_->GradientBackgroundOff(); -} + Color c = vtkcolor(color), c2 = vtkcolor(color2); + bool gradient = color2[0] >= 0 && color2[1] >= 0 && color2[2] >= 0; -void cv::viz::Viz3d::VizImpl::setBackgroundGradient(const Color& up, const Color& down) -{ - Color vtkup = vtkcolor(up), vtkdown = vtkcolor(down); - renderer_->SetBackground(vtkdown.val); - renderer_->SetBackground2(vtkup.val); - renderer_->GradientBackgroundOn(); + if (gradient) + { + renderer_->SetBackground(c2.val); + renderer_->SetBackground2(c.val); + renderer_->GradientBackgroundOn(); + } + else + { + renderer_->SetBackground(c.val); + renderer_->GradientBackgroundOff(); + } } void cv::viz::Viz3d::VizImpl::setBackgroundMeshLab() -{ setBackgroundGradient(Color(2, 1, 1), Color(240, 120, 120)); } +{ setBackgroundColor(Color(2, 1, 1), Color(240, 120, 120)); } ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setBackgroundTexture(InputArray image) diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index 1b9abea64..11e22ee5d 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -95,8 +95,7 @@ public: void setWindowSize(const Size& window_size); void setFullScreen(bool mode); String getWindowName() const; - void setBackgroundColor(const Color& color); - void setBackgroundGradient(const Color& up, const Color& down); + void setBackgroundColor(const Color& color, const Color& color2); void setBackgroundTexture(InputArray image); void setBackgroundMeshLab(); diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index bdfda6d9b..45d3cdc3c 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -43,7 +43,7 @@ using namespace cv; -TEST(Viz_viz3d, develop) +TEST(Viz_viz3d, DISABLED_develop) { cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); @@ -59,5 +59,6 @@ TEST(Viz_viz3d, develop) //cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); //---->>>>> + viz.spin(); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index dad4aacca..46f0e59b5 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -54,6 +54,8 @@ TEST(Viz, show_cloud_bluberry) Viz3d viz("show_cloud_bluberry"); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud, Color::bluberry()), pose); + + viz.showWidget("text2d", WText("Bluberry cloud", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -70,6 +72,7 @@ TEST(Viz, show_cloud_random_color) viz.setBackgroundMeshLab(); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud, colors), pose); + viz.showWidget("text2d", WText("Random color cloud", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -87,6 +90,7 @@ TEST(Viz, show_cloud_masked) Viz3d viz("show_cloud_masked"); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud), pose); + viz.showWidget("text2d", WText("Nan masked cloud", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -100,8 +104,10 @@ TEST(Viz, show_cloud_collection) ccol.addCloud(cloud, Color::red(), Affine3d().translate(Vec3d(2, 0, 0))); Viz3d viz("show_cloud_collection"); + viz.setBackgroundColor(Color::mlab()); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("ccol", ccol); + viz.showWidget("text2d", WText("Cloud collection", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -116,6 +122,7 @@ TEST(Viz, show_painted_clouds) viz.showWidget("cloud2", WPaintedCloud(cloud, Vec3d(0.0, -0.75, -1.0), Vec3d(0.0, 0.75, 0.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(1.5, 0.0, 0.0))); viz.showWidget("cloud3", WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0), Color::blue(), Color::red())); viz.showWidget("arrow", WArrow(Vec3d(0.0, 1.0, -1.0), Vec3d(0.0, 1.0, 1.0), 0.009, Color::raspberry())); + viz.showWidget("text2d", WText("Painted clouds", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -128,6 +135,7 @@ TEST(Viz, show_mesh) Viz3d viz("show_mesh"); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("mesh", WMesh(mesh), pose); + viz.showWidget("text2d", WText("Just mesh", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -142,6 +150,7 @@ TEST(Viz, show_mesh_random_colors) viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("mesh", WMesh(mesh), pose); viz.setRenderingProperty("mesh", SHADING, SHADING_PHONG); + viz.showWidget("text2d", WText("Random color mesh", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -178,6 +187,7 @@ TEST(Viz, show_textured_mesh) viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("mesh", WMesh(mesh)); viz.setRenderingProperty("mesh", SHADING, SHADING_PHONG); + viz.showWidget("text2d", WText("Textured mesh", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -190,6 +200,7 @@ TEST(Viz, show_polyline) Viz3d viz("show_polyline"); viz.showWidget("polyline", WPolyLine(Mat(polyline), Color::apricot())); viz.showWidget("coosys", WCoordinateSystem()); + viz.showWidget("text2d", WText("Polyline", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -204,6 +215,7 @@ TEST(Viz, show_sampled_normals) viz.showWidget("mesh", WMesh(mesh), pose); viz.showWidget("normals", WCloudNormals(mesh.cloud, mesh.normals, 30, 0.1f, Color::green()), pose); viz.setRenderingProperty("normals", LINE_WIDTH, 2.0); + viz.showWidget("text2d", WText("Cloud or mesh normals", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -227,6 +239,7 @@ TEST(Viz, show_trajectories) viz.showWidget("sub3", WTrajectory(sub3, WTrajectory::BOTH, 0.2, Color::green())); viz.showWidget("sub4", WTrajectoryFrustums(sub4, K, 0.3, Color::yellow())); viz.showWidget("sub5", WTrajectoryFrustums(sub5, Vec2d(0.78, 0.78), 0.15)); + viz.showWidget("text2d", WText("Different kinds of supported trajectories", Point(20, 20), 20, Color::green())); int i = 0; while(!viz.wasStopped()) @@ -236,6 +249,7 @@ TEST(Viz, show_trajectories) viz.setViewerPose(makeCameraPose(pose * 7.5, Vec3d(0.0, 0.5, 0.0), Vec3d(0.0, 0.1, 0.0))); viz.spinOnce(20, true); } + viz.resetCamera(); viz.spin(); } @@ -246,6 +260,7 @@ TEST(Viz, show_trajectory_reposition) Viz3d viz("show_trajectory_reposition_to_origin"); viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("sub3", WTrajectory(Mat(path).rowRange(0, path.size()/3), WTrajectory::BOTH, 0.2, Color::brown()), path.front().inv()); + viz.showWidget("text2d", WText("Trajectory resposition to origin", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -269,6 +284,7 @@ TEST(Viz, show_camera_positions) viz.showWidget("pos2", WCameraPosition(Vec2d(0.78, 0.78), lena, 2.2, Color::green()), poses[0]); viz.showWidget("pos3", WCameraPosition(0.75), poses[1]); viz.showWidget("pos4", WCameraPosition(K, gray, 3, Color::indigo()), poses[1]); + viz.showWidget("text2d", WText("Camera positions with images", Point(20, 20), 20, Color::green())); viz.spin(); } @@ -289,6 +305,7 @@ TEST(Viz, show_overlay_image) viz.showWidget("img2", WImageOverlay(gray, Rect(Point(vsz.width-10-lena.cols/2, 10), half_lsize))); viz.showWidget("img3", WImageOverlay(gray, Rect(Point(10, vsz.height-10-lena.rows/2), half_lsize))); viz.showWidget("img5", WImageOverlay(lena, Rect(Point(vsz.width-10-lena.cols/2, vsz.height-10-lena.rows/2), half_lsize))); + viz.showWidget("text2d", WText("Overlay images", Point(20, 20), 20, Color::green())); int i = 0; while(!viz.wasStopped()) @@ -299,7 +316,6 @@ TEST(Viz, show_overlay_image) viz.getWidget("img1").cast().setImage(lena * pow(sin(i*10*CV_PI/180) * 0.5 + 0.5, 1.0)); viz.spinOnce(1, true); } - viz.spin(); } @@ -332,6 +348,8 @@ TEST(Viz, show_image_3d) viz.showWidget("arr3", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); + viz.showWidget("text2d", WText("Images in 3D", Point(20, 20), 20, Color::green())); + int i = 0; while(!viz.wasStopped()) { @@ -357,7 +375,7 @@ TEST(Viz, show_simple_widgets) viz.showWidget("con0", WCone(0.25, 0.125, 6, Color::azure())); viz.showWidget("con1", WCone(0.125, Point3d(0.5, -0.5, 0.5), Point3d(0.5, -1.0, 0.5), 6, Color::turquoise())); - viz.showWidget("text2d", WText("Simple text", Point(20, 20), 20, Color::green())); + viz.showWidget("text2d", WText("Different simple widgets", Point(20, 20), 20, Color::green())); viz.showWidget("text3d", WText3D("Simple 3D text", Point3d( 0.5, 0.5, 0.5), 0.125, false, Color::green())); viz.showWidget("plane1", WPlane(Size2d(0.25, 0.75))); @@ -366,7 +384,7 @@ TEST(Viz, show_simple_widgets) viz.showWidget("grid1", WGrid(Vec2i(7,7), Vec2d::all(0.75), Color::gray()), Affine3d().translate(Vec3d(0.0, 0.0, -1.0))); viz.spin(); - viz.getWidget("text2d").cast().setText("New simple text"); + viz.getWidget("text2d").cast().setText("Different simple widgets (updated)"); viz.getWidget("text3d").cast().setText("Updated text 3D"); viz.spin(); } @@ -378,6 +396,7 @@ TEST(Viz, show_follower) viz.showWidget("coos", WCoordinateSystem()); viz.showWidget("cube", WCube()); viz.showWidget("t3d_2", WText3D("Simple 3D follower", Point3d(-0.5, -0.5, 0.5), 0.125, true, Color::green())); + viz.showWidget("text2d", WText("Follower: text always facing camera", Point(20, 20), 20, Color::green())); viz.setBackgroundMeshLab(); viz.spin(); viz.getWidget("t3d_2").cast().setText("Updated follower 3D"); From 7410593d55d09524cff5e9cd6584fa68a95a2996 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 00:13:47 +0400 Subject: [PATCH 185/295] fixed warnigns and compiler errors for Ubuntu --- modules/viz/src/clouds.cpp | 4 +-- modules/viz/src/shapes.cpp | 6 ++-- modules/viz/src/vtk/vtkCloudMatSource.cpp | 44 +++++++++++------------ modules/viz/src/vtk/vtkImageMatSource.cpp | 2 +- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index b8567dd66..4b84e8e9e 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -219,7 +219,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co mapper->ImmediateModeRenderingOff(); VtkUtils::SetInputData(mapper, polydata); - actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints()/10)); + actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints()/10)); actor->GetProperty()->SetInterpolationToFlat(); actor->GetProperty()->BackfaceCullingOn(); actor->SetMapper(mapper); @@ -236,7 +236,7 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co VtkUtils::SetInputData(mapper, append_filter->GetOutput()); - actor->SetNumberOfCloudPoints(std::max(1, actor->GetNumberOfCloudPoints() + polydata->GetNumberOfPoints()/10)); + actor->SetNumberOfCloudPoints(std::max(1, actor->GetNumberOfCloudPoints() + polydata->GetNumberOfPoints()/10)); } void cv::viz::WCloudCollection::addCloud(InputArray cloud, const Color &color, const Affine3d &pose) diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index 9011d0b18..cc3a51ce4 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -1064,9 +1064,9 @@ cv::viz::WTrajectorySpheres::WTrajectorySpheres(InputArray _path, double line_le line_source->SetPoint1(curr.val); line_source->SetPoint2(lend.val); line_source->Update(); - vtkSmartPointer polydata = line_source->GetOutput(); - polydata->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata->GetNumberOfCells(), c)); - VtkUtils::AddInputData(append_filter, polydata); + vtkSmartPointer polydata_ = line_source->GetOutput(); + polydata_->GetCellData()->SetScalars(VtkUtils::FillScalars(polydata_->GetNumberOfCells(), c)); + VtkUtils::AddInputData(append_filter, polydata_); } } append_filter->Update(); diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index 9a341b78c..e950a0d63 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -116,17 +116,17 @@ int cv::viz::vtkCloudMatSource::SetColorCloudNormals(InputArray _cloud, InputArr CV_Assert(_normals.channels() == 3 || _normals.channels() == 4); CV_Assert(_normals.size() == _cloud.size()); - Mat cloud = _cloud.getMat(); - Mat normals = _normals.getMat(); + Mat c = _cloud.getMat(); + Mat n = _normals.getMat(); - if (normals.depth() == CV_32F && cloud.depth() == CV_32F) - filterNanNormalsCopy(normals, cloud, total); - else if (normals.depth() == CV_32F && cloud.depth() == CV_64F) - filterNanNormalsCopy(normals, cloud, total); - else if (normals.depth() == CV_64F && cloud.depth() == CV_32F) - filterNanNormalsCopy(normals, cloud, total); - else if (normals.depth() == CV_64F && cloud.depth() == CV_64F) - filterNanNormalsCopy(normals, cloud, total); + if (n.depth() == CV_32F && c.depth() == CV_32F) + filterNanNormalsCopy(n, c, total); + else if (n.depth() == CV_32F && c.depth() == CV_64F) + filterNanNormalsCopy(n, c, total); + else if (n.depth() == CV_64F && c.depth() == CV_32F) + filterNanNormalsCopy(n, c, total); + else if (n.depth() == CV_64F && c.depth() == CV_64F) + filterNanNormalsCopy(n, c, total); else CV_Assert(!"Unsupported normals/cloud type"); @@ -143,17 +143,17 @@ int cv::viz::vtkCloudMatSource::SetColorCloudNormalsTCoords(InputArray _cloud, I CV_Assert(_tcoords.depth() == CV_32F || _tcoords.depth() == CV_64F); CV_Assert(_tcoords.channels() == 2 && _tcoords.size() == _cloud.size()); - Mat cloud = _cloud.getMat(); - Mat tcoords = _tcoords.getMat(); + Mat cl = _cloud.getMat(); + Mat tc = _tcoords.getMat(); - if (tcoords.depth() == CV_32F && cloud.depth() == CV_32F) - filterNanTCoordsCopy(tcoords, cloud, total); - else if (tcoords.depth() == CV_32F && cloud.depth() == CV_64F) - filterNanTCoordsCopy(tcoords, cloud, total); - else if (tcoords.depth() == CV_64F && cloud.depth() == CV_32F) - filterNanTCoordsCopy(tcoords, cloud, total); - else if (tcoords.depth() == CV_64F && cloud.depth() == CV_64F) - filterNanTCoordsCopy(tcoords, cloud, total); + if (tc.depth() == CV_32F && cl.depth() == CV_32F) + filterNanTCoordsCopy(tc, cl, total); + else if (tc.depth() == CV_32F && cl.depth() == CV_64F) + filterNanTCoordsCopy(tc, cl, total); + else if (tc.depth() == CV_64F && cl.depth() == CV_32F) + filterNanTCoordsCopy(tc, cl, total); + else if (tc.depth() == CV_64F && cl.depth() == CV_64F) + filterNanTCoordsCopy(tc, cl, total); else CV_Assert(!"Unsupported tcoords/cloud type"); @@ -241,7 +241,7 @@ void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& cloud_colors, co template void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total) { - normals = vtkSmartPointer< VtkDepthTraits<_Tn>::array_type >::New(); + normals = vtkSmartPointer< typename VtkDepthTraits<_Tn>::array_type >::New(); normals->SetName("Normals"); normals->SetNumberOfComponents(3); normals->SetNumberOfTuples(total); @@ -267,7 +267,7 @@ template void cv::viz::vtkCloudMatSource::filterNanTCoordsCopy(const Mat& _tcoords, const Mat& mask, int total) { typedef Vec<_Tn, 2> Vec2; - tcoords = vtkSmartPointer< VtkDepthTraits<_Tn>::array_type >::New(); + tcoords = vtkSmartPointer< typename VtkDepthTraits<_Tn>::array_type >::New(); tcoords->SetName("TextureCoordinates"); tcoords->SetNumberOfComponents(2); tcoords->SetNumberOfTuples(total); diff --git a/modules/viz/src/vtk/vtkImageMatSource.cpp b/modules/viz/src/vtk/vtkImageMatSource.cpp index 54500cb4b..58a5642d4 100644 --- a/modules/viz/src/vtk/vtkImageMatSource.cpp +++ b/modules/viz/src/vtk/vtkImageMatSource.cpp @@ -78,7 +78,7 @@ int cv::viz::vtkImageMatSource::RequestData(vtkInformation*, vtkInformationVecto void cv::viz::vtkImageMatSource::SetImage(InputArray _image) { - CV_Assert(_image.depth() == CV_8U && _image.channels() == 1 || _image.channels() == 3 || _image.channels() == 4); + CV_Assert(_image.depth() == CV_8U && (_image.channels() == 1 || _image.channels() == 3 || _image.channels() == 4)); Mat image = _image.getMat(); From 0d12fb0346b016f4207a4feaf37f6fe9767c48ac Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 01:55:40 +0400 Subject: [PATCH 186/295] implemented workaround of a problem with x-server for ubuntu --- modules/viz/src/precomp.hpp | 1 + modules/viz/src/vizimpl.cpp | 41 ++++++++++++++++++++++++++----------- modules/viz/src/vizimpl.hpp | 2 ++ 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 7440f1ee8..de5346ebf 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index e50666ec8..64222b49c 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -45,24 +45,18 @@ #include "precomp.hpp" + ///////////////////////////////////////////////////////////////////////////////////////////// -cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : spin_once_state_(false), widget_actor_map_(new WidgetActorMap) +cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : spin_once_state_(false), + window_position_(Vec2i(std::numeric_limits::min())), widget_actor_map_(new WidgetActorMap) { renderer_ = vtkSmartPointer::New(); + window_name_ = VizStorage::generateWindowName(name); // Create render window window_ = vtkSmartPointer::New(); - window_name_ = VizStorage::generateWindowName(name); - cv::Vec2i window_size = cv::Vec2i(window_->GetScreenSize()) / 2; window_->SetSize(window_size.val); - window_->AddRenderer(renderer_); - window_->AlphaBitPlanesOff(); - window_->PointSmoothingOff(); - window_->LineSmoothingOff(); - window_->PolygonSmoothingOff(); - window_->SwapBuffersOn(); - window_->SetStereoTypeToAnaglyph(); // Create the interactor style style_ = vtkSmartPointer::New(); @@ -111,9 +105,32 @@ void cv::viz::Viz3d::VizImpl::close() interactor_->TerminateApp(); // This tends to close the window... } +void cv::viz::Viz3d::VizImpl::recreateRenderWindow() +{ + //recreating is workaround for Ubuntu -- a crash in x-server + Vec2i window_size(window_->GetSize()); + int fullscreen = window_->GetFullScreen(); + + window_ = vtkSmartPointer::New(); + if (window_position_[0] != std::numeric_limits::min()) //also workaround + window_->SetPosition(window_position_.val); + + window_->SetSize(window_size.val); + window_->SetFullScreen(fullscreen); + window_->AddRenderer(renderer_); + window_->AlphaBitPlanesOff(); + window_->PointSmoothingOff(); + window_->LineSmoothingOff(); + window_->PolygonSmoothingOff(); + window_->SwapBuffersOn(); + window_->SetStereoTypeToAnaglyph(); +} + + ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::spin() { + recreateRenderWindow(); interactor_ = vtkSmartPointer::New(); interactor_->SetRenderWindow(window_); interactor_->SetInteractorStyle(style_); @@ -129,6 +146,7 @@ void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) if (interactor_ == 0) { spin_once_state_ = true; + recreateRenderWindow(); interactor_ = vtkSmartPointer::New(); interactor_->SetRenderWindow(window_); interactor_->SetInteractorStyle(style_); @@ -400,7 +418,6 @@ void cv::viz::Viz3d::VizImpl::setViewerPose(const Affine3d &pose) camera.SetViewUp(up_vec.val); renderer_->ResetCameraClippingRange(); - renderer_->Render(); } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -510,6 +527,6 @@ void cv::viz::Viz3d::VizImpl::setRepresentation(int representation) ////////////////////////////////////////////////////////////////////////////////////////////// cv::String cv::viz::Viz3d::VizImpl::getWindowName() const { return window_name_; } void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) { window_->SetFullScreen(mode); } -void cv::viz::Viz3d::VizImpl::setWindowPosition(const Point& position) { window_->SetPosition(position.x, position.y); } +void cv::viz::Viz3d::VizImpl::setWindowPosition(const Point& position) { window_position_ = position; window_->SetPosition(position.x, position.y); } void cv::viz::Viz3d::VizImpl::setWindowSize(const Size& window_size) { window_->SetSize(window_size.width, window_size.height); } cv::Size cv::viz::Viz3d::VizImpl::getWindowSize() const { return Size(Point(Vec2i(window_->GetSize()))); } diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index 11e22ee5d..9eb918af6 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -122,6 +122,7 @@ private: vtkSmartPointer window_; String window_name_; + Vec2i window_position_; vtkSmartPointer timer_callback_; vtkSmartPointer exit_callback_; @@ -131,6 +132,7 @@ private: Ptr widget_actor_map_; bool removeActorFromRenderer(vtkSmartPointer actor); + void recreateRenderWindow(); }; #endif From 8f15a8abdb93e5ca02d7c810766737ec35238e9e Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 02:16:59 +0400 Subject: [PATCH 187/295] disabled Ubuntu workaround code for Windows --- modules/viz/src/vizimpl.cpp | 21 +++++++++++++++------ modules/viz/test/tests_simple.cpp | 3 +++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 64222b49c..32c717c4f 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -57,6 +57,7 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : spin_once_state_(false), window_ = vtkSmartPointer::New(); cv::Vec2i window_size = cv::Vec2i(window_->GetScreenSize()) / 2; window_->SetSize(window_size.val); + window_->AddRenderer(renderer_); // Create the interactor style style_ = vtkSmartPointer::New(); @@ -107,6 +108,7 @@ void cv::viz::Viz3d::VizImpl::close() void cv::viz::Viz3d::VizImpl::recreateRenderWindow() { +#if !defined _MSC_VER //recreating is workaround for Ubuntu -- a crash in x-server Vec2i window_size(window_->GetSize()); int fullscreen = window_->GetFullScreen(); @@ -118,12 +120,7 @@ void cv::viz::Viz3d::VizImpl::recreateRenderWindow() window_->SetSize(window_size.val); window_->SetFullScreen(fullscreen); window_->AddRenderer(renderer_); - window_->AlphaBitPlanesOff(); - window_->PointSmoothingOff(); - window_->LineSmoothingOff(); - window_->PolygonSmoothingOff(); - window_->SwapBuffersOn(); - window_->SetStereoTypeToAnaglyph(); +#endif } @@ -134,6 +131,12 @@ void cv::viz::Viz3d::VizImpl::spin() interactor_ = vtkSmartPointer::New(); interactor_->SetRenderWindow(window_); interactor_->SetInteractorStyle(style_); + window_->AlphaBitPlanesOff(); + window_->PointSmoothingOff(); + window_->LineSmoothingOff(); + window_->PolygonSmoothingOff(); + window_->SwapBuffersOn(); + window_->SetStereoTypeToAnaglyph(); window_->Render(); window_->SetWindowName(window_name_.c_str()); interactor_->Start(); @@ -152,6 +155,12 @@ void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) interactor_->SetInteractorStyle(style_); interactor_->AddObserver(vtkCommand::TimerEvent, timer_callback_); interactor_->AddObserver(vtkCommand::ExitEvent, exit_callback_); + window_->AlphaBitPlanesOff(); + window_->PointSmoothingOff(); + window_->LineSmoothingOff(); + window_->PolygonSmoothingOff(); + window_->SwapBuffersOn(); + window_->SetStereoTypeToAnaglyph(); window_->Render(); window_->SetWindowName(window_name_.c_str()); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index 46f0e59b5..aae468ed9 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -316,6 +316,8 @@ TEST(Viz, show_overlay_image) viz.getWidget("img1").cast().setImage(lena * pow(sin(i*10*CV_PI/180) * 0.5 + 0.5, 1.0)); viz.spinOnce(1, true); } + viz.showWidget("text2d", WText("Overlay images (stopped)", Point(20, 20), 20, Color::green())); + viz.spin(); } @@ -356,6 +358,7 @@ TEST(Viz, show_image_3d) viz.getWidget("img0").cast().setImage(lena * pow(sin(i++*7.5*CV_PI/180) * 0.5 + 0.5, 1.0)); viz.spinOnce(1, true); } + viz.showWidget("text2d", WText("Images in 3D (stopped)", Point(20, 20), 20, Color::green())); viz.spin(); } From d29c3d2f0db141d0e2423cdda3b6a10f41f414e3 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 03:03:05 +0400 Subject: [PATCH 188/295] fixed documentation warnings --- modules/viz/doc/viz3d.rst | 4 ++-- modules/viz/doc/widget.rst | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index 5b361ad84..f0e57e5fa 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -35,7 +35,7 @@ Constructs camera pose from position, focal_point and up_vector (see gluLookAt() This function returns pose of the camera in global coordinate frame. viz::getWindowByName --------- +-------------------- Retrieves a window by its name. .. ocv:function:: Viz3d getWindowByName(const String &window_name) @@ -186,7 +186,7 @@ viz::Viz3d::showImage --------------------- Removed all widgets and displays image scaled to whole window area. -.. ocv:function:: void showImage(InputArray image, const Size& window_size = Size(-1, -1)); +.. ocv:function:: void showImage(InputArray image, const Size& window_size = Size(-1, -1)) :param image: Image to be displayed. :param size: Size of Viz3d window. Default value means no change. diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 13409974f..543daab5f 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -209,7 +209,7 @@ viz::Widget3D::applyTransform ------------------------------- Transforms internal widget data (i.e. points, normals) using the given transform. -.. ocv:function:: void applyTransform(const Affine3d &transform); +.. ocv:function:: void applyTransform(const Affine3d &transform) :param transform: Specified transformation to apply. @@ -285,7 +285,7 @@ viz::WPlane::WPlane ------------------- Constructs a default plane with center point at origin and normal oriented along z-axis. -.. ocv:function:: WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); +.. ocv:function:: WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()) :param size: Size of the plane :param color: :ocv:class:`Color` of the plane. @@ -294,7 +294,7 @@ viz::WPlane::WPlane ------------------- Constructs a repositioned plane -.. ocv:function:: WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()); +.. ocv:function:: WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()) :param center: Center of the plane :param normal: Plane normal orientation @@ -369,7 +369,7 @@ viz::WCircle::WCircle ------------------------------- Constructs default planar circle centred at origin with plane normal along z-axis -.. ocv:function:: WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()); +.. ocv:function:: WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()) :param radius: Radius of the circle. :param thickness: Thickness of the circle. @@ -379,7 +379,7 @@ viz::WCircle::WCircle ------------------------------- Constructs repositioned planar circle. -.. ocv:function:: WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness = 0.01, const Color &color = Color::white()); +.. ocv:function:: WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness = 0.01, const Color &color = Color::white()) :param radius: Radius of the circle. :param center: Center of the circle. @@ -408,7 +408,7 @@ viz::WCone::WCone ------------------------------- Constructs default cone oriented along x-axis with center of its base located at origin -.. ocv:function:: WCone(double length, double radius, int resolution = 6.0, const Color &color = Color::white()); +.. ocv:function:: WCone(double length, double radius, int resolution = 6.0, const Color &color = Color::white()) :param length: Length of the cone. :param radius: Radius of the cone. @@ -419,7 +419,7 @@ viz::WCone::WCone ------------------------------- Constructs repositioned planar cone. -.. ocv:function:: WCone(double radius, const Point3d& center, const Point3d& tip, int resolution = 6.0, const Color &color = Color::white()); +.. ocv:function:: WCone(double radius, const Point3d& center, const Point3d& tip, int resolution = 6.0, const Color &color = Color::white()) :param radius: Radius of the cone. :param center: Center of the cone base. @@ -540,7 +540,7 @@ viz::WGrid::WGrid --------------------------- Constructs a WGrid. -.. ocv:function:: WGrid(const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()); +.. ocv:function:: WGrid(const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white()) :param cells: Number of cell columns and rows, respectively. :param cells_spacing: Size of each cell, respectively. @@ -823,7 +823,7 @@ Constructs a WTrajectory. * PATH & FRAMES : Displays both poly line and coordinate frames. viz::WTrajectoryFrustums ----------------- +------------------------ .. ocv:class:: WTrajectoryFrustums This 3D Widget represents a trajectory. :: @@ -838,7 +838,7 @@ This 3D Widget represents a trajectory. :: }; viz::WTrajectoryFrustums::WTrajectoryFrustums ------------------------------ +--------------------------------------------- Constructs a WTrajectoryFrustums. .. ocv:function:: WTrajectoryFrustums(const std::vector &path, const Matx33d &K, double scale = 1.0, const Color &color = Color::white()) @@ -877,7 +877,7 @@ viz::WTrajectorySpheres::WTrajectorySpheres ------------------------------------------- Constructs a WTrajectorySpheres. -.. ocv:function:: WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007, const Color &from = Color::red(), const Color &to = Color::white()); +.. ocv:function:: WTrajectorySpheres(InputArray path, double line_length = 0.05, double radius = 0.007, const Color &from = Color::red(), const Color &to = Color::white()) :param path: List of poses on a trajectory. Takes std::vector> with T == [float | double] :param line_length: Max length of the lines which point to previous position @@ -1012,7 +1012,7 @@ Constructs a WMesh. :param mesh: :ocv:class:`Mesh` object that will be displayed. -.. ocv:function:: WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()); +.. ocv:function:: WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()) :param cloud: Points of the mesh object. :param polygons: Points of the mesh object. From 4e180070669008247920276ce057a69e5c8b428a Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 03:22:45 +0400 Subject: [PATCH 189/295] fixed white spaces --- modules/viz/doc/viz3d.rst | 6 +-- modules/viz/doc/widget.rst | 47 +++++++++++------------ modules/viz/src/vizcore.cpp | 4 -- modules/viz/src/vtk/vtkCloudMatSource.cpp | 2 +- modules/viz/src/vtk/vtkImageMatSource.h | 2 - 5 files changed, 27 insertions(+), 34 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index f0e57e5fa..d0e24ae8e 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -102,7 +102,7 @@ The Viz3d class represents a 3D visualizer window. This class is implicitly shar void setWidgetPose(const String &id, const Affine3d &pose); void updateWidgetPose(const String &id, const Affine3d &pose); Affine3d getWidgetPose(const String &id) const; - + void showImage(InputArray image, const Size& window_size = Size(-1, -1)); void setCamera(const Camera &camera); @@ -474,7 +474,7 @@ This class wraps mesh attributes, and it can load a mesh from a ``ply`` file. :: public: Mat cloud, colors, normals; - + //! Raw integer list of the form: (n,id1,id2,...,idn, n,id1,id2,...,idn, ...) //! where n is the number of points in the poligon, and id is a zero-offset index into an associated cloud. Mat polygons; @@ -522,7 +522,7 @@ Constructs a KeyboardEvent. :param symbol: Name of the key. :param code: Code of the key. :param modifiers: Signals if ``alt``, ``ctrl`` or ``shift`` are pressed or their combination. - + viz::MouseEvent --------------- diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 543daab5f..9ed28a775 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -207,7 +207,7 @@ Returns the current pose of the widget. viz::Widget3D::applyTransform ------------------------------- -Transforms internal widget data (i.e. points, normals) using the given transform. +Transforms internal widget data (i.e. points, normals) using the given transform. .. ocv:function:: void applyTransform(const Affine3d &transform) @@ -293,7 +293,7 @@ Constructs a default plane with center point at origin and normal oriented along viz::WPlane::WPlane ------------------- Constructs a repositioned plane - + .. ocv:function:: WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis,const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white()) :param center: Center of the plane @@ -371,7 +371,7 @@ Constructs default planar circle centred at origin with plane normal along z-axi .. ocv:function:: WCircle(double radius, double thickness = 0.01, const Color &color = Color::white()) - :param radius: Radius of the circle. + :param radius: Radius of the circle. :param thickness: Thickness of the circle. :param color: :ocv:class:`Color` of the circle. @@ -385,9 +385,9 @@ Constructs repositioned planar circle. :param center: Center of the circle. :param normal: Normal of the plane in which the circle lies. :param thickness: Thickness of the circle. - :param color: :ocv:class:`Color` of the circle. - - + :param color: :ocv:class:`Color` of the circle. + + viz::WCone ------------------------------- .. ocv:class:: WCone @@ -410,8 +410,8 @@ Constructs default cone oriented along x-axis with center of its base located at .. ocv:function:: WCone(double length, double radius, int resolution = 6.0, const Color &color = Color::white()) - :param length: Length of the cone. - :param radius: Radius of the cone. + :param length: Length of the cone. + :param radius: Radius of the cone. :param resolution: Resolution of the cone. :param color: :ocv:class:`Color` of the cone. @@ -421,12 +421,12 @@ Constructs repositioned planar cone. .. ocv:function:: WCone(double radius, const Point3d& center, const Point3d& tip, int resolution = 6.0, const Color &color = Color::white()) - :param radius: Radius of the cone. + :param radius: Radius of the cone. :param center: Center of the cone base. :param tip: Tip of the cone. :param resolution: Resolution of the cone. - :param color: :ocv:class:`Color` of the cone. - + :param color: :ocv:class:`Color` of the cone. + viz::WCylinder -------------- .. ocv:class:: WCylinder @@ -675,14 +675,14 @@ This 3D Widget represents an image in 3D space. :: class CV_EXPORTS WImage3D : public Widget3D { - public: - //! Creates 3D image at the origin - WImage3D(InputArray image, const Size2d &size); - //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation - WImage3D(InputArray image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector); + public: + //! Creates 3D image at the origin + WImage3D(InputArray image, const Size2d &size); + //! Creates 3D image at a given position, pointing in the direction of the normal, and having the up_vector orientation + WImage3D(InputArray image, const Size2d &size, const Vec3d &position, const Vec3d &normal, const Vec3d &up_vector); - void setImage(InputArray image); - }; + void setImage(InputArray image); + }; viz::WImage3D::WImage3D ----------------------- @@ -1001,7 +1001,7 @@ This 3D Widget defines a mesh. :: { public: WMesh(const Mesh &mesh); - WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()); + WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()); }; viz::WMesh::WMesh @@ -1011,11 +1011,10 @@ Constructs a WMesh. .. ocv:function:: WMesh(const Mesh &mesh) :param mesh: :ocv:class:`Mesh` object that will be displayed. - + .. ocv:function:: WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()) :param cloud: Points of the mesh object. - :param polygons: Points of the mesh object. - :param colors: Point colors. - :param normals: Point normals. - + :param polygons: Points of the mesh object. + :param colors: Point colors. + :param normals: Point normals. diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index ee74f2a12..29d4b4688 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -310,7 +310,3 @@ void cv::viz::computeNormals(const Mesh& mesh, OutputArray _normals) else _normals.release(); } - - - - diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index e950a0d63..74d01bbd0 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -265,7 +265,7 @@ void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals, template void cv::viz::vtkCloudMatSource::filterNanTCoordsCopy(const Mat& _tcoords, const Mat& mask, int total) -{ +{ typedef Vec<_Tn, 2> Vec2; tcoords = vtkSmartPointer< typename VtkDepthTraits<_Tn>::array_type >::New(); tcoords->SetName("TextureCoordinates"); diff --git a/modules/viz/src/vtk/vtkImageMatSource.h b/modules/viz/src/vtk/vtkImageMatSource.h index a4340346c..db0c093ed 100644 --- a/modules/viz/src/vtk/vtkImageMatSource.h +++ b/modules/viz/src/vtk/vtkImageMatSource.h @@ -80,5 +80,3 @@ namespace cv #endif - - From 4cc8f7012be67571daac483ca101987bd39c7314 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 19 Jan 2014 08:47:07 +0400 Subject: [PATCH 190/295] closing window --- modules/viz/include/opencv2/viz/viz3d.hpp | 1 + modules/viz/src/viz3d.cpp | 1 + modules/viz/src/vizimpl.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index a83d8e8fc..7cb7d0cea 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -105,6 +105,7 @@ namespace cv void spin(); void spinOnce(int time = 1, bool force_redraw = false); bool wasStopped() const; + void close(); void registerKeyboardCallback(KeyboardCallback callback, void* cookie = 0); void registerMouseCallback(MouseCallback callback, void* cookie = 0); diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 2d4aefc0b..56f978c0e 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -101,6 +101,7 @@ void cv::viz::Viz3d::release() void cv::viz::Viz3d::spin() { impl_->spin(); } void cv::viz::Viz3d::spinOnce(int time, bool force_redraw) { impl_->spinOnce(time, force_redraw); } bool cv::viz::Viz3d::wasStopped() const { return impl_->wasStopped(); } +void cv::viz::Viz3d::close() { impl_->close(); } void cv::viz::Viz3d::registerKeyboardCallback(KeyboardCallback callback, void* cookie) { impl_->registerKeyboardCallback(callback, cookie); } diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 32c717c4f..5fa49e2f9 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -104,6 +104,7 @@ void cv::viz::Viz3d::VizImpl::close() return; interactor_->GetRenderWindow()->Finalize(); interactor_->TerminateApp(); // This tends to close the window... + interactor_ = 0; } void cv::viz::Viz3d::VizImpl::recreateRenderWindow() From 5d18cf9989d36bc566a8ac1041e110793e110ce7 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 17 Jan 2014 23:31:03 +0400 Subject: [PATCH 191/295] added cv::[extract|insert]Channel to T-API --- modules/core/perf/opencl/perf_channels.cpp | 44 +++++++++ modules/core/src/convert.cpp | 35 +++++-- ...test_split_merge.cpp => test_channels.cpp} | 94 +++++++++++++++++++ modules/ts/include/opencv2/ts/ts_perf.hpp | 3 + 4 files changed, 169 insertions(+), 7 deletions(-) rename modules/core/test/ocl/{test_split_merge.cpp => test_channels.cpp} (82%) diff --git a/modules/core/perf/opencl/perf_channels.cpp b/modules/core/perf/opencl/perf_channels.cpp index 4856ed4c3..3a25bc309 100644 --- a/modules/core/perf/opencl/perf_channels.cpp +++ b/modules/core/perf/opencl/perf_channels.cpp @@ -154,6 +154,50 @@ OCL_PERF_TEST_P(MixChannelsFixture, MixChannels, SANITY_CHECK(dst1); } +///////////// InsertChannel //////////////////////// + +typedef Size_MatDepth InsertChannelFixture; + +OCL_PERF_TEST_P(InsertChannelFixture, InsertChannel, + ::testing::Combine(Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3), + OCL_PERF_ENUM(CV_8U, CV_32F))) +{ + const Size_MatDepth_t params = GetParam(); + const Size srcSize = get<0>(params); + const int depth = get<1>(params), type = CV_MAKE_TYPE(depth, 3); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, depth), dst(srcSize, type, Scalar::all(17)); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::insertChannel(src, dst, 1); + + SANITY_CHECK(dst); +} + +///////////// ExtractChannel //////////////////////// + +typedef Size_MatDepth ExtractChannelFixture; + +OCL_PERF_TEST_P(ExtractChannelFixture, ExtractChannel, + ::testing::Combine(Values(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3), + OCL_PERF_ENUM(CV_8U, CV_32F))) +{ + const Size_MatDepth_t params = GetParam(); + const Size srcSize = get<0>(params); + const int depth = get<1>(params), type = CV_MAKE_TYPE(depth, 3); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + UMat src(srcSize, type), dst(srcSize, depth); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::extractChannel(src, dst, 1); + + SANITY_CHECK(dst); +} + } } // namespace cvtest::ocl #endif // HAVE_OPENCL diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 9778da18e..4558d09d9 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -763,20 +763,41 @@ void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, void cv::extractChannel(InputArray _src, OutputArray _dst, int coi) { - Mat src = _src.getMat(); - CV_Assert( 0 <= coi && coi < src.channels() ); - _dst.create(src.dims, &src.size[0], src.depth()); - Mat dst = _dst.getMat(); + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + CV_Assert( 0 <= coi && coi < cn ); int ch[] = { coi, 0 }; + + if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat()) + { + UMat src = _src.getUMat(); + _dst.create(src.dims, &src.size[0], depth); + UMat dst = _dst.getUMat(); + mixChannels(std::vector(1, src), std::vector(1, dst), ch, 1); + return; + } + + Mat src = _src.getMat(); + _dst.create(src.dims, &src.size[0], depth); + Mat dst = _dst.getMat(); mixChannels(&src, 1, &dst, 1, ch, 1); } void cv::insertChannel(InputArray _src, InputOutputArray _dst, int coi) { - Mat src = _src.getMat(), dst = _dst.getMat(); - CV_Assert( src.size == dst.size && src.depth() == dst.depth() ); - CV_Assert( 0 <= coi && coi < dst.channels() && src.channels() == 1 ); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); + int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype); + CV_Assert( _src.sameSize(_dst) && sdepth == ddepth ); + CV_Assert( 0 <= coi && coi < dcn && scn == 1 ); + int ch[] = { 0, coi }; + if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat()) + { + UMat src = _src.getUMat(), dst = _dst.getUMat(); + mixChannels(std::vector(1, src), std::vector(1, dst), ch, 1); + return; + } + + Mat src = _src.getMat(), dst = _dst.getMat(); mixChannels(&src, 1, &dst, 1, ch, 1); } diff --git a/modules/core/test/ocl/test_split_merge.cpp b/modules/core/test/ocl/test_channels.cpp similarity index 82% rename from modules/core/test/ocl/test_split_merge.cpp rename to modules/core/test/ocl/test_channels.cpp index d7fdcea7c..09d709e91 100644 --- a/modules/core/test/ocl/test_split_merge.cpp +++ b/modules/core/test/ocl/test_channels.cpp @@ -353,11 +353,105 @@ OCL_TEST_P(MixChannels, Accuracy) } } +//////////////////////////////////////// InsertChannel /////////////////////////////////////////////// + +PARAM_TEST_CASE(InsertChannel, MatDepth, Channels, bool) +{ + int depth, cn, coi; + bool use_roi; + + TEST_DECLARE_INPUT_PARAMETER(src) + TEST_DECLARE_OUTPUT_PARAMETER(dst) + + virtual void SetUp() + { + depth = GET_PARAM(0); + cn = GET_PARAM(1); + use_roi = GET_PARAM(2); + } + + void generateTestData() + { + Size roiSize = randomSize(1, MAX_VALUE); + coi = randomInt(0, cn); + + Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, depth, 2, 11); + + Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst, dst_roi, roiSize, dstBorder, CV_MAKE_TYPE(depth, cn), 5, 16); + + UMAT_UPLOAD_INPUT_PARAMETER(src) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst) + } +}; + +OCL_TEST_P(InsertChannel, Accuracy) +{ + for(int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::insertChannel(src_roi, dst_roi, coi)); + OCL_ON(cv::insertChannel(usrc_roi, udst_roi, coi)); + + OCL_EXPECT_MATS_NEAR(dst, 0); + } +} + +//////////////////////////////////////// ExtractChannel /////////////////////////////////////////////// + +PARAM_TEST_CASE(ExtractChannel, MatDepth, Channels, bool) +{ + int depth, cn, coi; + bool use_roi; + + TEST_DECLARE_INPUT_PARAMETER(src) + TEST_DECLARE_OUTPUT_PARAMETER(dst) + + virtual void SetUp() + { + depth = GET_PARAM(0); + cn = GET_PARAM(1); + use_roi = GET_PARAM(2); + } + + void generateTestData() + { + Size roiSize = randomSize(1, MAX_VALUE); + coi = randomInt(0, cn); + + Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, CV_MAKE_TYPE(depth, cn), 2, 11); + + Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst, dst_roi, roiSize, dstBorder, depth, 5, 16); + + UMAT_UPLOAD_INPUT_PARAMETER(src) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst) + } +}; + +OCL_TEST_P(ExtractChannel, Accuracy) +{ + for(int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::extractChannel(src_roi, dst_roi, coi)); + OCL_ON(cv::extractChannel(usrc_roi, udst_roi, coi)); + + OCL_EXPECT_MATS_NEAR(dst, 0); + } +} + //////////////////////////////////////// Instantiation /////////////////////////////////////////////// OCL_INSTANTIATE_TEST_CASE_P(Channels, Merge, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Channels, Split, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Channels, MixChannels, Combine(OCL_ALL_DEPTHS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Channels, InsertChannel, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Channels, ExtractChannel, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); } } // namespace cvtest::ocl diff --git a/modules/ts/include/opencv2/ts/ts_perf.hpp b/modules/ts/include/opencv2/ts/ts_perf.hpp index fa0e5a257..de674b7f3 100644 --- a/modules/ts/include/opencv2/ts/ts_perf.hpp +++ b/modules/ts/include/opencv2/ts/ts_perf.hpp @@ -379,6 +379,9 @@ template class TestBaseWithParam: public TestBase, public ::testing: typedef std::tr1::tuple Size_MatType_t; typedef TestBaseWithParam Size_MatType; +typedef std::tr1::tuple Size_MatDepth_t; +typedef TestBaseWithParam Size_MatDepth; + /*****************************************************************************************\ * Print functions for googletest * \*****************************************************************************************/ From 52ed6d0d2780cd524310e338f01f47ef965eaf8d Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 17 Jan 2014 19:00:52 +0400 Subject: [PATCH 192/295] ported cv::goodFeaturesToTrack to T-API --- modules/imgproc/src/featureselect.cpp | 219 ++++++++++++++++++++----- modules/imgproc/src/morph.cpp | 11 +- modules/imgproc/src/opencl/gftt.cl | 81 +++++++++ modules/imgproc/test/ocl/test_gftt.cpp | 139 ++++++++++++++++ modules/ocl/src/gftt.cpp | 132 ++++----------- modules/ocl/src/opencl/imgproc_gftt.cl | 44 +---- 6 files changed, 439 insertions(+), 187 deletions(-) create mode 100644 modules/imgproc/src/opencl/gftt.cl create mode 100644 modules/imgproc/test/ocl/test_gftt.cpp diff --git a/modules/imgproc/src/featureselect.cpp b/modules/imgproc/src/featureselect.cpp index 8c740382f..47015b06a 100644 --- a/modules/imgproc/src/featureselect.cpp +++ b/modules/imgproc/src/featureselect.cpp @@ -38,18 +38,179 @@ // the use of this software, even if advised of the possibility of such damage. // //M*/ + #include "precomp.hpp" +#include "opencl_kernels.hpp" + #include #include +#include namespace cv { -template struct greaterThanPtr +struct greaterThanPtr : + public std::binary_function { - bool operator()(const T* a, const T* b) const { return *a > *b; } + bool operator () (const float * a, const float * b) const + { return *a > *b; } }; +struct Corner +{ + float val; + short y; + short x; + + bool operator < (const Corner & c) const + { return val > c.val; } +}; + +static bool ocl_goodFeaturesToTrack( InputArray _image, OutputArray _corners, + int maxCorners, double qualityLevel, double minDistance, + InputArray _mask, int blockSize, + bool useHarrisDetector, double harrisK ) +{ + UMat eig, tmp; + if( useHarrisDetector ) + cornerHarris( _image, eig, blockSize, 3, harrisK ); + else + cornerMinEigenVal( _image, eig, blockSize, 3 ); + + double maxVal = 0; + minMaxLoc( eig, NULL, &maxVal, NULL, NULL, _mask ); + threshold( eig, eig, maxVal*qualityLevel, 0, THRESH_TOZERO ); + dilate( eig, tmp, Mat()); + + Size imgsize = _image.size(); + std::vector tmpCorners; + size_t total, i, j, ncorners = 0, possibleCornersCount = + std::max(1024, static_cast(imgsize.area() * 0.1)); + bool haveMask = !_mask.empty(); + + // collect list of pointers to features - put them into temporary image + { + ocl::Kernel k("findCorners", ocl::imgproc::gftt_oclsrc, + format(haveMask ? "-D HAVE_MASK" : "")); + if (k.empty()) + return false; + + UMat counter(1, 1, CV_32SC1, Scalar::all(0)), + corners(1, possibleCornersCount * sizeof(Corner), CV_8UC1); + ocl::KernelArg eigarg = ocl::KernelArg::ReadOnlyNoSize(eig), + tmparg = ocl::KernelArg::ReadOnlyNoSize(tmp), + cornersarg = ocl::KernelArg::PtrWriteOnly(corners), + counterarg = ocl::KernelArg::PtrReadWrite(counter); + + if (!haveMask) + k.args(eigarg, tmparg, cornersarg, counterarg, + imgsize.height - 2, imgsize.width - 2); + else + { + UMat mask = _mask.getUMat(); + k.args(eigarg, ocl::KernelArg::ReadOnlyNoSize(mask), tmparg, + cornersarg, counterarg, imgsize.height - 2, imgsize.width - 2); + } + + size_t globalsize[2] = { imgsize.width - 2, imgsize.height - 2 }; + if (!k.run(2, globalsize, NULL, false)) + return false; + + total = counter.getMat(ACCESS_READ).at(0, 0); + size_t totalb = sizeof(Corner) * total; + + tmpCorners.resize(total); + Mat mcorners(1, totalb, CV_8UC1, &tmpCorners[0]); + corners.colRange(0, totalb).copyTo(mcorners); + } + + std::sort( tmpCorners.begin(), tmpCorners.end() ); + std::vector corners; + corners.reserve(total); + + if (minDistance >= 1) + { + // Partition the image into larger grids + int w = imgsize.width, h = imgsize.height; + + const int cell_size = cvRound(minDistance); + const int grid_width = (w + cell_size - 1) / cell_size; + const int grid_height = (h + cell_size - 1) / cell_size; + + std::vector > grid(grid_width*grid_height); + minDistance *= minDistance; + + for( i = 0; i < total; i++ ) + { + const Corner & c = tmpCorners[i]; + bool good = true; + + int x_cell = c.x / cell_size; + int y_cell = c.y / cell_size; + + int x1 = x_cell - 1; + int y1 = y_cell - 1; + int x2 = x_cell + 1; + int y2 = y_cell + 1; + + // boundary check + x1 = std::max(0, x1); + y1 = std::max(0, y1); + x2 = std::min(grid_width-1, x2); + y2 = std::min(grid_height-1, y2); + + for( int yy = y1; yy <= y2; yy++ ) + for( int xx = x1; xx <= x2; xx++ ) + { + std::vector &m = grid[yy*grid_width + xx]; + + if( m.size() ) + { + for(j = 0; j < m.size(); j++) + { + float dx = c.x - m[j].x; + float dy = c.y - m[j].y; + + if( dx*dx + dy*dy < minDistance ) + { + good = false; + goto break_out; + } + } + } + } + + break_out: + + if (good) + { + grid[y_cell*grid_width + x_cell].push_back(Point2f((float)c.x, (float)c.y)); + + corners.push_back(Point2f((float)c.x, (float)c.y)); + ++ncorners; + + if( maxCorners > 0 && (int)ncorners == maxCorners ) + break; + } + } + } + else + { + for( i = 0; i < total; i++ ) + { + const Corner & c = tmpCorners[i]; + + corners.push_back(Point2f((float)c.x, (float)c.y)); + ++ncorners; + if( maxCorners > 0 && (int)ncorners == maxCorners ) + break; + } + } + + Mat(corners).convertTo(_corners, _corners.fixedType() ? _corners.type() : CV_32F); + return true; +} + } void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, @@ -57,27 +218,32 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, InputArray _mask, int blockSize, bool useHarrisDetector, double harrisK ) { - Mat image = _image.getMat(), mask = _mask.getMat(); - CV_Assert( qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0 ); - CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) ); + CV_Assert( _mask.empty() || (_mask.type() == CV_8UC1 && _mask.sameSize(_image)) ); - Mat eig, tmp; + if (ocl::useOpenCL() && _image.dims() <= 2 && _image.isUMat()) + { + CV_Assert(ocl_goodFeaturesToTrack(_image, _corners, maxCorners, qualityLevel, minDistance, + _mask, blockSize, useHarrisDetector, harrisK)); + return; + } + + Mat image = _image.getMat(), eig, tmp; if( useHarrisDetector ) cornerHarris( image, eig, blockSize, 3, harrisK ); else cornerMinEigenVal( image, eig, blockSize, 3 ); double maxVal = 0; - minMaxLoc( eig, 0, &maxVal, 0, 0, mask ); + minMaxLoc( eig, 0, &maxVal, 0, 0, _mask ); threshold( eig, eig, maxVal*qualityLevel, 0, THRESH_TOZERO ); dilate( eig, tmp, Mat()); Size imgsize = image.size(); - std::vector tmpCorners; // collect list of pointers to features - put them into temporary image + Mat mask = _mask.getMat(); for( int y = 1; y < imgsize.height - 1; y++ ) { const float* eig_data = (const float*)eig.ptr(y); @@ -92,11 +258,11 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, } } - std::sort( tmpCorners.begin(), tmpCorners.end(), greaterThanPtr() ); + std::sort( tmpCorners.begin(), tmpCorners.end(), greaterThanPtr() ); std::vector corners; size_t i, j, total = tmpCorners.size(), ncorners = 0; - if(minDistance >= 1) + if (minDistance >= 1) { // Partition the image into larger grids int w = image.cols; @@ -133,7 +299,6 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, y2 = std::min(grid_height-1, y2); for( int yy = y1; yy <= y2; yy++ ) - { for( int xx = x1; xx <= x2; xx++ ) { std::vector &m = grid[yy*grid_width + xx]; @@ -153,14 +318,11 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, } } } - } break_out: - if(good) + if (good) { - // printf("%d: %d %d -> %d %d, %d, %d -- %d %d %d %d, %d %d, c=%d\n", - // i,x, y, x_cell, y_cell, (int)minDistance, cell_size,x1,y1,x2,y2, grid_width,grid_height,c); grid[y_cell*grid_width + x_cell].push_back(Point2f((float)x, (float)y)); corners.push_back(Point2f((float)x, (float)y)); @@ -187,33 +349,6 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, } Mat(corners).convertTo(_corners, _corners.fixedType() ? _corners.type() : CV_32F); - - /* - for( i = 0; i < total; i++ ) - { - int ofs = (int)((const uchar*)tmpCorners[i] - eig.data); - int y = (int)(ofs / eig.step); - int x = (int)((ofs - y*eig.step)/sizeof(float)); - - if( minDistance > 0 ) - { - for( j = 0; j < ncorners; j++ ) - { - float dx = x - corners[j].x; - float dy = y - corners[j].y; - if( dx*dx + dy*dy < minDistance ) - break; - } - if( j < ncorners ) - continue; - } - - corners.push_back(Point2f((float)x, (float)y)); - ++ncorners; - if( maxCorners > 0 && (int)ncorners == maxCorners ) - break; - } -*/ } CV_IMPL void diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index f024a521c..7ade970d9 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1404,10 +1404,10 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, int src_type = _src.type(), dst_type = _dst.type(), src_cn = CV_MAT_CN(src_type), src_depth = CV_MAT_DEPTH(src_type); - bool useOpenCL = cv::ocl::useOpenCL() && _src.isUMat() && _src.size() == _dst.size() && src_type == dst_type && - _src.dims()<=2 && (src_cn == 1 || src_cn == 4) && (anchor.x == -1) && (anchor.y == -1) && + bool useOpenCL = cv::ocl::useOpenCL() && _dst.isUMat() && _src.size() == _dst.size() && src_type == dst_type && + _src.dims() <= 2 && (src_cn == 1 || src_cn == 4) && anchor.x == -1 && anchor.y == -1 && (src_depth == CV_8U || src_depth == CV_32F || src_depth == CV_64F ) && - (borderType == cv::BORDER_CONSTANT) && (borderValue == morphologyDefaultBorderValue()) && + borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue() && (op == MORPH_ERODE || op == MORPH_DILATE); Mat kernel = _kernel.getMat(); @@ -1423,10 +1423,7 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, if( iterations == 0 || kernel.rows*kernel.cols == 1 ) { - Mat src = _src.getMat(); - _dst.create( src.size(), src.type() ); - Mat dst = _dst.getMat(); - src.copyTo(dst); + _src.copyTo(_dst); return; } diff --git a/modules/imgproc/src/opencl/gftt.cl b/modules/imgproc/src/opencl/gftt.cl new file mode 100644 index 000000000..534242656 --- /dev/null +++ b/modules/imgproc/src/opencl/gftt.cl @@ -0,0 +1,81 @@ +/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Zhang Ying, zhangying913@gmail.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*/ + +__kernel void findCorners(__global const uchar * eigptr, int eig_step, int eig_offset, +#ifdef HAVE_MASK + __global const uchar * mask, int mask_step, int mask_offset, +#endif + __global const uchar * tmpptr, int tmp_step, int tmp_offset, + __global uchar * cornersptr, __global int * counter, + int rows, int cols) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if (x < cols && y < rows) + { + ++x, ++y; + + int eig_index = mad24(y, eig_step, eig_offset + x * (int)sizeof(float)); + int tmp_index = mad24(y, tmp_step, tmp_offset + x * (int)sizeof(float)); +#ifdef HAVE_MASK + int mask_index = mad24(y, mask_step, mask_offset + x); + mask += mask_index; +#endif + + float val = *(__global const float *)(eigptr + eig_index); + float tmp = *(__global const float *)(tmpptr + tmp_index); + + if (val != 0 && val == tmp +#ifdef HAVE_MASK + && mask[0] != 0 +#endif + ) + { + __global float2 * corners = (cornersptr + (int)sizeof(float2) * atomic_inc(counter)); + corners[0] = (float2)(val, as_float( (x<<16) | y )); + } + } +} diff --git a/modules/imgproc/test/ocl/test_gftt.cpp b/modules/imgproc/test/ocl/test_gftt.cpp new file mode 100644 index 000000000..c92469612 --- /dev/null +++ b/modules/imgproc/test/ocl/test_gftt.cpp @@ -0,0 +1,139 @@ +/////////////////////////////////////////////////////////////////////////////////////// +// +// 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, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., 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*/ + +#include "test_precomp.hpp" +#include "opencv2/ts/ocl_test.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +//////////////////////////// GoodFeaturesToTrack ////////////////////////// + + +PARAM_TEST_CASE(GoodFeaturesToTrack, double, bool) +{ + double minDistance; + bool useRoi; + + static const int maxCorners; + static const double qualityLevel; + + TEST_DECLARE_INPUT_PARAMETER(src) + UMat points, upoints; + + virtual void SetUp() + { + minDistance = GET_PARAM(0); + useRoi = GET_PARAM(1); + } + + void generateTestData() + { + Mat frame = readImage("../gpu/opticalflow/rubberwhale1.png", IMREAD_GRAYSCALE); + ASSERT_FALSE(frame.empty()) << "could not load gpu/opticalflow/rubberwhale1.png"; + + Size roiSize = frame.size(); + Border srcBorder = randomBorder(0, useRoi ? 2 : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, frame.type(), 5, 256); + src_roi.copyTo(frame); + + UMAT_UPLOAD_INPUT_PARAMETER(src) + } +}; + +const int GoodFeaturesToTrack::maxCorners = 1000; +const double GoodFeaturesToTrack::qualityLevel = 0.01; + +OCL_TEST_P(GoodFeaturesToTrack, Accuracy) +{ + for (int j = 0; j < test_loop_times; ++j) + { + generateTestData(); + + std::vector upts, pts; + + OCL_OFF(cv::goodFeaturesToTrack(src_roi, points, maxCorners, qualityLevel, minDistance, noArray())); + ASSERT_FALSE(points.empty()); + pts.resize(points.cols); + points.copyTo(pts); + + OCL_ON(cv::goodFeaturesToTrack(usrc_roi, upoints, maxCorners, qualityLevel, minDistance)); + ASSERT_FALSE(upoints.empty()); + upts.resize(upoints.cols); + upoints.copyTo(upts); + + ASSERT_EQ(upts.size(), pts.size()); + + int mistmatch = 0; + for (size_t i = 0; i < pts.size(); ++i) + { + Point2i a = upts[i], b = pts[i]; + bool eq = std::abs(a.x - b.x) < 1 && std::abs(a.y - b.y) < 1; + + if (!eq) + ++mistmatch; + } + + double bad_ratio = static_cast(mistmatch) / pts.size(); + ASSERT_GE(1e-3, bad_ratio); + } +} + +OCL_TEST_P(GoodFeaturesToTrack, EmptyCorners) +{ + generateTestData(); + usrc_roi.setTo(Scalar::all(0)); + + OCL_ON(cv::goodFeaturesToTrack(usrc_roi, upoints, maxCorners, qualityLevel, minDistance)); + + ASSERT_TRUE(upoints.empty()); +} + +OCL_INSTANTIATE_TEST_CASE_P(Imgproc, GoodFeaturesToTrack, + ::testing::Combine(testing::Values(0.0, 3.0), Bool())); + +} } // namespace cvtest::ocl + +#endif diff --git a/modules/ocl/src/gftt.cpp b/modules/ocl/src/gftt.cpp index bf1036bb8..13d01942d 100644 --- a/modules/ocl/src/gftt.cpp +++ b/modules/ocl/src/gftt.cpp @@ -48,20 +48,18 @@ using namespace cv; using namespace cv::ocl; -// currently sort procedure on the host is more efficient -static bool use_cpu_sorter = true; - // compact structure for corners struct DefCorner { float eig; //eigenvalue of corner short x; //x coordinate of corner point short y; //y coordinate of corner point -} ; +}; // compare procedure for corner //it is used for sort on the host side -struct DefCornerCompare +struct DefCornerCompare : + public std::binary_function { bool operator()(const DefCorner a, const DefCorner b) const { @@ -69,37 +67,6 @@ struct DefCornerCompare } }; -// sort corner point using opencl bitonicosrt implementation -static void sortCorners_caller(oclMat& corners, const int count) -{ - Context * cxt = Context::getContext(); - int GS = count/2; - int LS = min(255,GS); - size_t globalThreads[3] = {GS, 1, 1}; - size_t localThreads[3] = {LS, 1, 1}; - - // 2^numStages should be equal to count or the output is invalid - int numStages = 0; - for(int i = count; i > 1; i >>= 1) - { - ++numStages; - } - const int argc = 4; - std::vector< std::pair > args(argc); - std::string kernelname = "sortCorners_bitonicSort"; - args[0] = std::make_pair(sizeof(cl_mem), (void *)&corners.data); - args[1] = std::make_pair(sizeof(cl_int), (void *)&count); - for(int stage = 0; stage < numStages; ++stage) - { - args[2] = std::make_pair(sizeof(cl_int), (void *)&stage); - for(int passOfStage = 0; passOfStage < stage + 1; ++passOfStage) - { - args[3] = std::make_pair(sizeof(cl_int), (void *)&passOfStage); - openCLExecuteKernel(cxt, &imgproc_gftt, kernelname, globalThreads, localThreads, args, -1, -1); - } - } -} - // find corners on matrix and put it into array static void findCorners_caller( const oclMat& eig_mat, //input matrix worth eigenvalues @@ -158,7 +125,8 @@ static void minMaxEig_caller(const oclMat &src, oclMat &dst, oclMat & tozero) int cols = all_cols - invalid_cols , elemnum = cols * src.rows; int offset = src.offset / src.elemSize(); - {// first parallel pass + { + // first parallel pass std::vector > args; args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst_data )); @@ -173,7 +141,8 @@ static void minMaxEig_caller(const oclMat &src, oclMat &dst, oclMat & tozero) args, -1, -1, "-D T=float -D DEPTH_5"); } - {// run final "serial" kernel to find accumulate results from threads and reset corner counter + { + // run final "serial" kernel to find accumulate results from threads and reset corner counter std::vector > args; args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst_data )); args.push_back( std::make_pair( sizeof(cl_int) , (void *)&groupnum )); @@ -200,80 +169,54 @@ void cv::ocl::GoodFeaturesToTrackDetector_OCL::operator ()(const oclMat& image, ensureSizeIsEnough(1,1, CV_32SC1, counter_); // find max eigenvalue and reset detected counters - minMaxEig_caller(eig_,eig_minmax_,counter_); + minMaxEig_caller(eig_, eig_minmax_, counter_); // allocate buffer for kernels int corner_array_size = std::max(1024, static_cast(image.size().area() * 0.05)); - - if(!use_cpu_sorter) - { // round to 2^n - unsigned int n=1; - for(n=1;n<(unsigned int)corner_array_size;n<<=1) ; - corner_array_size = (int)n; - - ensureSizeIsEnough(1, corner_array_size , CV_32FC2, tmpCorners_); - - // set to 0 to be able use bitonic sort on whole 2^n array - tmpCorners_.setTo(0); - } - else - { - ensureSizeIsEnough(1, corner_array_size , CV_32FC2, tmpCorners_); - } + ensureSizeIsEnough(1, corner_array_size , CV_32FC2, tmpCorners_); int total = tmpCorners_.cols; // by default the number of corner is full array - std::vector tmp(tmpCorners_.cols); // input buffer with corner for HOST part of algorithm + std::vector tmp(tmpCorners_.cols); // input buffer with corner for HOST part of algorithm - //find points with high eigenvalue and put it into the output array - findCorners_caller( - eig_, - eig_minmax_, - static_cast(qualityLevel), - mask, - tmpCorners_, - counter_); + // find points with high eigenvalue and put it into the output array + findCorners_caller(eig_, eig_minmax_, static_cast(qualityLevel), mask, tmpCorners_, counter_); - if(!use_cpu_sorter) - {// sort detected corners on deivce side - sortCorners_caller(tmpCorners_, corner_array_size); - } - else - {// send non-blocking request to read real non-zero number of corners to sort it on the HOST side - openCLVerifyCall(clEnqueueReadBuffer(getClCommandQueue(counter_.clCxt), (cl_mem)counter_.data, CL_FALSE, 0,sizeof(int), &total, 0, NULL, NULL)); - } - - //blocking read whole corners array (sorted or not sorted) - openCLReadBuffer(tmpCorners_.clCxt,(cl_mem)tmpCorners_.data,&tmp[0],tmpCorners_.cols*sizeof(DefCorner)); + // send non-blocking request to read real non-zero number of corners to sort it on the HOST side + openCLVerifyCall(clEnqueueReadBuffer(getClCommandQueue(counter_.clCxt), (cl_mem)counter_.data, CL_FALSE, 0, sizeof(int), &total, 0, NULL, NULL)); if (total == 0) - {// check for trivial case + { + // check for trivial case corners.release(); return; } - if(use_cpu_sorter) - {// sort detected corners on cpu side. - tmp.resize(total); - std::sort(tmp.begin(), tmp.end(), DefCornerCompare()); - } + // blocking read whole corners array (sorted or not sorted) + openCLReadBuffer(tmpCorners_.clCxt, (cl_mem)tmpCorners_.data, &tmp[0], tmpCorners_.cols * sizeof(DefCorner)); - //estimate maximal size of final output array + // sort detected corners on cpu side. + tmp.resize(total); + printf("total: %d\n", total); + std::sort(tmp.begin(), tmp.end(), DefCornerCompare()); + + // estimate maximal size of final output array int total_max = maxCorners > 0 ? std::min(maxCorners, total) : total; int D2 = (int)ceil(minDistance * minDistance); + // allocate output buffer std::vector tmp2; tmp2.reserve(total_max); if (minDistance < 1) - {// we have not distance restriction. then just copy with conversion maximal allowed points into output array - for(int i=0;i0.0f;++i) - { - tmp2.push_back(Point2f(tmp[i].x,tmp[i].y)); - } + { + // we have not distance restriction. then just copy with conversion maximal allowed points into output array + for (int i = 0; i < total_max; ++i) + tmp2.push_back(Point2f(tmp[i].x, tmp[i].y)); } else - {// we have distance restriction. then start coping to output array from the first element and check distance for each next one + { + // we have distance restriction. then start coping to output array from the first element and check distance for each next one const int cell_size = cvRound(minDistance); const int grid_width = (image.cols + cell_size - 1) / cell_size; const int grid_height = (image.rows + cell_size - 1) / cell_size; @@ -283,10 +226,6 @@ void cv::ocl::GoodFeaturesToTrackDetector_OCL::operator ()(const oclMat& image, for (int i = 0; i < total ; ++i) { DefCorner p = tmp[i]; - - if(p.eig<=0.0f) - break; // condition to stop that is needed for GPU bitonic sort usage. - bool good = true; int x_cell = static_cast(p.x / cell_size); @@ -328,9 +267,8 @@ void cv::ocl::GoodFeaturesToTrackDetector_OCL::operator ()(const oclMat& image, if(good) { - grid[y_cell * grid_width + x_cell].push_back(Point2i(p.x,p.y)); - - tmp2.push_back(Point2f(p.x,p.y)); + grid[y_cell * grid_width + x_cell].push_back(Point2i(p.x, p.y)); + tmp2.push_back(Point2f(p.x, p.y)); if (maxCorners > 0 && tmp2.size() == static_cast(maxCorners)) break; @@ -338,12 +276,14 @@ void cv::ocl::GoodFeaturesToTrackDetector_OCL::operator ()(const oclMat& image, } } + int final_size = static_cast(tmp2.size()); - if(final_size>0) + if (final_size > 0) corners.upload(Mat(1, final_size, CV_32FC2, &tmp2[0])); else corners.release(); } + void cv::ocl::GoodFeaturesToTrackDetector_OCL::downloadPoints(const oclMat &points, std::vector &points_v) { CV_DbgAssert(points.type() == CV_32FC2); diff --git a/modules/ocl/src/opencl/imgproc_gftt.cl b/modules/ocl/src/opencl/imgproc_gftt.cl index 4d5356cfb..9cd57678f 100644 --- a/modules/ocl/src/opencl/imgproc_gftt.cl +++ b/modules/ocl/src/opencl/imgproc_gftt.cl @@ -46,6 +46,7 @@ #ifndef WITH_MASK #define WITH_MASK 0 #endif + //macro to read eigenvalue matrix #define GET_SRC_32F(_x, _y) ((__global const float*)(eig + (_y)*eig_pitch))[_x] @@ -107,47 +108,6 @@ __kernel #undef GET_SRC_32F -//bitonic sort -__kernel - void sortCorners_bitonicSort - ( - __global float2 * corners, - const int count, - const int stage, - const int passOfStage - ) -{ - const int threadId = get_global_id(0); - if(threadId >= count / 2) - { - return; - } - - const int sortOrder = (((threadId/(1 << stage)) % 2)) == 1 ? 1 : 0; // 0 is descent - - const int pairDistance = 1 << (stage - passOfStage); - const int blockWidth = 2 * pairDistance; - - const int leftId = min( (threadId % pairDistance) - + (threadId / pairDistance) * blockWidth, count ); - - const int rightId = min( leftId + pairDistance, count ); - - const float2 leftPt = corners[leftId]; - const float2 rightPt = corners[rightId]; - - const float leftVal = leftPt.x; - const float rightVal = rightPt.x; - - const bool compareResult = leftVal > rightVal; - - float2 greater = compareResult ? leftPt:rightPt; - float2 lesser = compareResult ? rightPt:leftPt; - - corners[leftId] = sortOrder ? lesser : greater; - corners[rightId] = sortOrder ? greater : lesser; -} - // this is simple short serial kernel that makes some short reduction and initialization work // it makes HOST like work to avoid additional sync with HOST to do this short work // data - input/output float2. @@ -166,4 +126,4 @@ __kernel void arithm_op_minMax_final(__global float * data, int groupnum,__globa } data[0] = minVal; data[1] = maxVal; -} \ No newline at end of file +} From 5abfd40989674e37f398e8c00b1f2b32891d8531 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 18 Jan 2014 21:13:50 +0400 Subject: [PATCH 193/295] added perf test for cv::goodFeaturesToTrack --- modules/imgproc/perf/opencl/perf_gftt.cpp | 87 +++++++++++++++++++++++ modules/imgproc/src/featureselect.cpp | 12 ++-- modules/imgproc/src/opencl/gftt.cl | 2 +- modules/ocl/src/gftt.cpp | 1 - modules/ts/include/opencv2/ts/ts_perf.hpp | 1 + modules/ts/src/ts_perf.cpp | 7 +- 6 files changed, 100 insertions(+), 10 deletions(-) create mode 100644 modules/imgproc/perf/opencl/perf_gftt.cpp diff --git a/modules/imgproc/perf/opencl/perf_gftt.cpp b/modules/imgproc/perf/opencl/perf_gftt.cpp new file mode 100644 index 000000000..29626c62e --- /dev/null +++ b/modules/imgproc/perf/opencl/perf_gftt.cpp @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////////////////// +// +// 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, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., 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*/ + +#include "perf_precomp.hpp" +#include "opencv2/ts/ocl_perf.hpp" + +#include + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +//////////////////////////// GoodFeaturesToTrack ////////////////////////// + +typedef tuple GoodFeaturesToTrackParams; +typedef TestBaseWithParam GoodFeaturesToTrackFixture; + +OCL_PERF_TEST_P(GoodFeaturesToTrackFixture, GoodFeaturesToTrack, + ::testing::Combine(OCL_PERF_ENUM(String("gpu/opticalflow/rubberwhale1.png")), + OCL_PERF_ENUM(0.0, 3.0), Bool())) +{ + GoodFeaturesToTrackParams params = GetParam(); + const String fileName = get<0>(params); + const double minDistance = get<1>(params), qualityLevel = 0.01; + const bool harrisDetector = get<2>(params); + const int maxCorners = 1000; + + Mat img = imread(getDataPath(fileName), cv::IMREAD_GRAYSCALE); + ASSERT_FALSE(img.empty()) << "could not load " << fileName; + + checkDeviceMaxMemoryAllocSize(img.size(), img.type()); + + UMat src(img.size(), img.type()), dst(1, maxCorners, CV_32FC2); + img.copyTo(src); + + declare.in(src, WARMUP_READ).out(dst); + + OCL_TEST_CYCLE() cv::goodFeaturesToTrack(src, dst, maxCorners, qualityLevel, + minDistance, noArray(), 3, harrisDetector, 0.04); + + SANITY_CHECK(dst); +} + +} } // namespace cvtest::ocl + +#endif diff --git a/modules/imgproc/src/featureselect.cpp b/modules/imgproc/src/featureselect.cpp index 47015b06a..6d4f8c25e 100644 --- a/modules/imgproc/src/featureselect.cpp +++ b/modules/imgproc/src/featureselect.cpp @@ -96,7 +96,7 @@ static bool ocl_goodFeaturesToTrack( InputArray _image, OutputArray _corners, return false; UMat counter(1, 1, CV_32SC1, Scalar::all(0)), - corners(1, possibleCornersCount * sizeof(Corner), CV_8UC1); + corners(1, (int)(possibleCornersCount * sizeof(Corner)), CV_8UC1); ocl::KernelArg eigarg = ocl::KernelArg::ReadOnlyNoSize(eig), tmparg = ocl::KernelArg::ReadOnlyNoSize(tmp), cornersarg = ocl::KernelArg::PtrWriteOnly(corners), @@ -117,7 +117,7 @@ static bool ocl_goodFeaturesToTrack( InputArray _image, OutputArray _corners, return false; total = counter.getMat(ACCESS_READ).at(0, 0); - size_t totalb = sizeof(Corner) * total; + int totalb = (int)(sizeof(Corner) * total); tmpCorners.resize(total); Mat mcorners(1, totalb, CV_8UC1, &tmpCorners[0]); @@ -221,12 +221,10 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, CV_Assert( qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0 ); CV_Assert( _mask.empty() || (_mask.type() == CV_8UC1 && _mask.sameSize(_image)) ); - if (ocl::useOpenCL() && _image.dims() <= 2 && _image.isUMat()) - { - CV_Assert(ocl_goodFeaturesToTrack(_image, _corners, maxCorners, qualityLevel, minDistance, - _mask, blockSize, useHarrisDetector, harrisK)); + if (ocl::useOpenCL() && _image.dims() <= 2 && _image.isUMat() && + ocl_goodFeaturesToTrack(_image, _corners, maxCorners, qualityLevel, minDistance, + _mask, blockSize, useHarrisDetector, harrisK)) return; - } Mat image = _image.getMat(), eig, tmp; if( useHarrisDetector ) diff --git a/modules/imgproc/src/opencl/gftt.cl b/modules/imgproc/src/opencl/gftt.cl index 534242656..46e37990d 100644 --- a/modules/imgproc/src/opencl/gftt.cl +++ b/modules/imgproc/src/opencl/gftt.cl @@ -74,7 +74,7 @@ __kernel void findCorners(__global const uchar * eigptr, int eig_step, int eig_o #endif ) { - __global float2 * corners = (cornersptr + (int)sizeof(float2) * atomic_inc(counter)); + __global float2 * corners = (__global float2 *)(cornersptr + (int)sizeof(float2) * atomic_inc(counter)); corners[0] = (float2)(val, as_float( (x<<16) | y )); } } diff --git a/modules/ocl/src/gftt.cpp b/modules/ocl/src/gftt.cpp index 13d01942d..252313677 100644 --- a/modules/ocl/src/gftt.cpp +++ b/modules/ocl/src/gftt.cpp @@ -196,7 +196,6 @@ void cv::ocl::GoodFeaturesToTrackDetector_OCL::operator ()(const oclMat& image, // sort detected corners on cpu side. tmp.resize(total); - printf("total: %d\n", total); std::sort(tmp.begin(), tmp.end(), DefCornerCompare()); // estimate maximal size of final output array diff --git a/modules/ts/include/opencv2/ts/ts_perf.hpp b/modules/ts/include/opencv2/ts/ts_perf.hpp index fa0e5a257..a0c893499 100644 --- a/modules/ts/include/opencv2/ts/ts_perf.hpp +++ b/modules/ts/include/opencv2/ts/ts_perf.hpp @@ -389,6 +389,7 @@ CV_EXPORTS void PrintTo(const MatType& t, std::ostream* os); namespace cv { +CV_EXPORTS void PrintTo(const String& str, ::std::ostream* os); CV_EXPORTS void PrintTo(const Size& sz, ::std::ostream* os); } //namespace cv diff --git a/modules/ts/src/ts_perf.cpp b/modules/ts/src/ts_perf.cpp index 35204c291..68879225e 100644 --- a/modules/ts/src/ts_perf.cpp +++ b/modules/ts/src/ts_perf.cpp @@ -1199,7 +1199,7 @@ void TestBase::validateMetrics() double mean = metrics.mean * 1000.0f / metrics.frequency; double stddev = metrics.stddev * 1000.0f / metrics.frequency; double percents = stddev / mean * 100.f; - printf(" samples = %d, mean = %.2f, stddev = %.2f (%.1f%%)\n", (int)metrics.samples, mean, stddev, percents); + printf("[ PERFSTAT ] (samples = %d, mean = %.2f, stddev = %.2f (%.1f%%))\n", (int)metrics.samples, mean, stddev, percents); } else { @@ -1611,6 +1611,11 @@ void PrintTo(const MatType& t, ::std::ostream* os) \*****************************************************************************************/ namespace cv { +void PrintTo(const String& str, ::std::ostream* os) +{ + *os << str; +} + void PrintTo(const Size& sz, ::std::ostream* os) { *os << /*"Size:" << */sz.width << "x" << sz.height; From ac035b9b8e77ea6590995ab4651b90b3c6ae9593 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Mon, 20 Jan 2014 15:17:35 +0400 Subject: [PATCH 194/295] review comments --- modules/core/include/opencv2/core/affine.hpp | 16 +++---- modules/viz/src/precomp.cpp | 46 -------------------- 2 files changed, 8 insertions(+), 54 deletions(-) delete mode 100644 modules/viz/src/precomp.cpp diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index 0ee6fabe9..8a5476292 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -55,9 +55,9 @@ namespace cv { public: typedef T float_type; - typedef cv::Matx Mat3; - typedef cv::Matx Mat4; - typedef cv::Vec Vec3; + typedef Matx Mat3; + typedef Matx Mat4; + typedef Vec Vec3; Affine3(); @@ -70,11 +70,11 @@ namespace cv //Rodrigues vector Affine3(const Vec3& rvec, const Vec3& t = Vec3::all(0)); - //Combines all contructors above. Supports 4x4, 3x3, 1x3, 3x1 sizes of data matrix - explicit Affine3(const cv::Mat& data, const Vec3& t = Vec3::all(0)); + //Combines all contructors above. Supports 4x4, 3x4, 3x3, 1x3, 3x1 sizes of data matrix + explicit Affine3(const Mat& data, const Vec3& t = Vec3::all(0)); //From 16th element array - Affine3(const float_type* vals); + explicit Affine3(const float_type* vals); static Affine3 Identity(); @@ -134,8 +134,8 @@ namespace cv typedef Affine3 Affine3f; typedef Affine3 Affine3d; - static cv::Vec3f operator*(const cv::Affine3f& affine, const cv::Vec3f& vector); - static cv::Vec3d operator*(const cv::Affine3d& affine, const cv::Vec3d& vector); + static Vec3f operator*(const Affine3f& affine, const Vec3f& vector); + static Vec3d operator*(const Affine3d& affine, const Vec3d& vector); template class DataType< Affine3<_Tp> > { diff --git a/modules/viz/src/precomp.cpp b/modules/viz/src/precomp.cpp deleted file mode 100644 index 631a300da..000000000 --- a/modules/viz/src/precomp.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/*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. -// -// Authors: -// * Ozan Tonkal, ozantonkal@gmail.com -// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com -// -//M*/ - -#include "precomp.hpp" From e5130cf83f011ba13c2d20b34329d35a07a6f740 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 20 Jan 2014 18:09:43 +0400 Subject: [PATCH 195/295] enabled tests --- modules/imgproc/test/ocl/test_imgproc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/imgproc/test/ocl/test_imgproc.cpp b/modules/imgproc/test/ocl/test_imgproc.cpp index bf6f8e64a..7a6fb393e 100644 --- a/modules/imgproc/test/ocl/test_imgproc.cpp +++ b/modules/imgproc/test/ocl/test_imgproc.cpp @@ -195,7 +195,7 @@ struct CornerTestBase : { virtual void random_roi() { - Mat image = readImageType("gpu/stereobm/aloe-L.png", type); + Mat image = readImageType("../gpu/stereobm/aloe-L.png", type); ASSERT_FALSE(image.empty()); bool isFP = CV_MAT_DEPTH(type) >= CV_32F; @@ -224,7 +224,7 @@ struct CornerTestBase : typedef CornerTestBase CornerMinEigenVal; -OCL_TEST_P(CornerMinEigenVal, DISABLED_Mat) +OCL_TEST_P(CornerMinEigenVal, Mat) { for (int j = 0; j < test_loop_times; j++) { @@ -243,7 +243,7 @@ OCL_TEST_P(CornerMinEigenVal, DISABLED_Mat) typedef CornerTestBase CornerHarris; -OCL_TEST_P(CornerHarris, DISABLED_Mat) +OCL_TEST_P(CornerHarris, Mat) { for (int j = 0; j < test_loop_times; j++) { From 6cb90c0e976ff24af85167e71d88c9d9b2ed06c7 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Mon, 20 Jan 2014 10:23:46 +0100 Subject: [PATCH 196/295] fix cross-compilation issue with Numpy --- cmake/OpenCVDetectPython.cmake | 37 ++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/cmake/OpenCVDetectPython.cmake b/cmake/OpenCVDetectPython.cmake index 3326bcd98..8c488e656 100644 --- a/cmake/OpenCVDetectPython.cmake +++ b/cmake/OpenCVDetectPython.cmake @@ -80,14 +80,29 @@ if(PYTHON_EXECUTABLE) endif() SET(PYTHON_PACKAGES_PATH "${_PYTHON_PACKAGES_PATH}" CACHE PATH "Where to install the python packages.") - if(NOT PYTHON_NUMPY_INCLUDE_DIR) - # Attempt to discover the NumPy include directory. If this succeeds, then build python API with NumPy - execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import os; os.environ['DISTUTILS_USE_SDK']='1'; import numpy.distutils; print numpy.distutils.misc_util.get_numpy_include_dirs()[0]" - RESULT_VARIABLE PYTHON_NUMPY_PROCESS - OUTPUT_VARIABLE PYTHON_NUMPY_INCLUDE_DIR - OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT CMAKE_CROSSCOMPILING) + if(NOT PYTHON_NUMPY_INCLUDE_DIR) + # Attempt to discover the NumPy include directory. If this succeeds, then build python API with NumPy + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import os; os.environ['DISTUTILS_USE_SDK']='1'; import numpy.distutils; print numpy.distutils.misc_util.get_numpy_include_dirs()[0]" + RESULT_VARIABLE PYTHON_NUMPY_PROCESS + OUTPUT_VARIABLE PYTHON_NUMPY_INCLUDE_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) - if(PYTHON_NUMPY_PROCESS EQUAL 0) + if(PYTHON_NUMPY_PROCESS EQUAL 0) + file(TO_CMAKE_PATH "${PYTHON_NUMPY_INCLUDE_DIR}" _PYTHON_NUMPY_INCLUDE_DIR) + set(PYTHON_NUMPY_INCLUDE_DIR ${_PYTHON_NUMPY_INCLUDE_DIR} CACHE PATH "Path to numpy headers") + endif() + endif() + else() + if(NOT PYTHON_NUMPY_INCLUDE_DIR) + message(STATUS "Cannot probe for Python/Numpy support (because we are cross-compiling OpenCV)") + message(STATUS "If you want to enable Python/Numpy support, set the following variables:") + message(STATUS " PYTHON_EXECUTABLE") + message(STATUS " PYTHON_INCLUDE_DIR") + message(STATUS " PYTHON_LIBRARY") + message(STATUS " PYTHON_NUMPY_INCLUDE_DIR") + message(STATUS " PYTHON_NUMPY_VERSION") + else() file(TO_CMAKE_PATH "${PYTHON_NUMPY_INCLUDE_DIR}" _PYTHON_NUMPY_INCLUDE_DIR) set(PYTHON_NUMPY_INCLUDE_DIR ${_PYTHON_NUMPY_INCLUDE_DIR} CACHE PATH "Path to numpy headers") endif() @@ -95,10 +110,16 @@ if(PYTHON_EXECUTABLE) if(PYTHON_NUMPY_INCLUDE_DIR) set(PYTHON_USE_NUMPY TRUE) - execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import numpy; print numpy.version.version" + if(NOT CMAKE_CROSSCOMPILING) + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import numpy; print numpy.version.version" RESULT_VARIABLE PYTHON_NUMPY_PROCESS OUTPUT_VARIABLE PYTHON_NUMPY_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) + else() + if(NOT PYTHON_NUMPY_VERSION) + set(PYTHON_NUMPY_VERSION "undefined - cannot be probed because of the cross-compilation") + endif() + endif() endif() endif(NOT ANDROID AND NOT IOS) From ac2e61397503b55ba6f709deb6469d95b69a7aa1 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 20 Jan 2014 17:52:32 +0400 Subject: [PATCH 197/295] skip OCL tests if OpenCL isn't available --- modules/superres/test/test_precomp.hpp | 4 ++-- modules/superres/test/test_superres.cpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/superres/test/test_precomp.hpp b/modules/superres/test/test_precomp.hpp index 47334e324..553481818 100644 --- a/modules/superres/test/test_precomp.hpp +++ b/modules/superres/test/test_precomp.hpp @@ -52,9 +52,9 @@ #define __OPENCV_TEST_PRECOMP_HPP__ #include "opencv2/opencv_modules.hpp" -#include "opencv2/core.hpp" -#include "opencv2/imgproc.hpp" +#include "opencv2/core/ocl.hpp" #include "opencv2/ts.hpp" +#include "opencv2/imgproc.hpp" #include "opencv2/superres.hpp" #include "cvconfig.h" #include "input_array_utility.hpp" diff --git a/modules/superres/test/test_superres.cpp b/modules/superres/test/test_superres.cpp index 95baefda9..92d51fd9a 100644 --- a/modules/superres/test/test_superres.cpp +++ b/modules/superres/test/test_superres.cpp @@ -282,7 +282,8 @@ TEST_F(SuperResolution, BTVL1_CUDA) TEST_F(SuperResolution, BTVL1_OCL) { - RunTest(cv::superres::createSuperResolution_BTVL1_OCL()); + if (cv::ocl::useOpenCL()) + RunTest(cv::superres::createSuperResolution_BTVL1_OCL()); } #endif From eabcfa56527de1117f09665f9c6c18b8d4212d9d Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Tue, 21 Jan 2014 10:01:52 +0100 Subject: [PATCH 198/295] reorder the if's for clarity --- cmake/OpenCVDetectPython.cmake | 40 +++++++++++++++------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/cmake/OpenCVDetectPython.cmake b/cmake/OpenCVDetectPython.cmake index 8c488e656..618b0fd22 100644 --- a/cmake/OpenCVDetectPython.cmake +++ b/cmake/OpenCVDetectPython.cmake @@ -80,21 +80,8 @@ if(PYTHON_EXECUTABLE) endif() SET(PYTHON_PACKAGES_PATH "${_PYTHON_PACKAGES_PATH}" CACHE PATH "Where to install the python packages.") - if(NOT CMAKE_CROSSCOMPILING) - if(NOT PYTHON_NUMPY_INCLUDE_DIR) - # Attempt to discover the NumPy include directory. If this succeeds, then build python API with NumPy - execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import os; os.environ['DISTUTILS_USE_SDK']='1'; import numpy.distutils; print numpy.distutils.misc_util.get_numpy_include_dirs()[0]" - RESULT_VARIABLE PYTHON_NUMPY_PROCESS - OUTPUT_VARIABLE PYTHON_NUMPY_INCLUDE_DIR - OUTPUT_STRIP_TRAILING_WHITESPACE) - - if(PYTHON_NUMPY_PROCESS EQUAL 0) - file(TO_CMAKE_PATH "${PYTHON_NUMPY_INCLUDE_DIR}" _PYTHON_NUMPY_INCLUDE_DIR) - set(PYTHON_NUMPY_INCLUDE_DIR ${_PYTHON_NUMPY_INCLUDE_DIR} CACHE PATH "Path to numpy headers") - endif() - endif() - else() - if(NOT PYTHON_NUMPY_INCLUDE_DIR) + if(NOT PYTHON_NUMPY_INCLUDE_DIR) + if(CMAKE_CROSSCOMPILING) message(STATUS "Cannot probe for Python/Numpy support (because we are cross-compiling OpenCV)") message(STATUS "If you want to enable Python/Numpy support, set the following variables:") message(STATUS " PYTHON_EXECUTABLE") @@ -103,22 +90,31 @@ if(PYTHON_EXECUTABLE) message(STATUS " PYTHON_NUMPY_INCLUDE_DIR") message(STATUS " PYTHON_NUMPY_VERSION") else() - file(TO_CMAKE_PATH "${PYTHON_NUMPY_INCLUDE_DIR}" _PYTHON_NUMPY_INCLUDE_DIR) - set(PYTHON_NUMPY_INCLUDE_DIR ${_PYTHON_NUMPY_INCLUDE_DIR} CACHE PATH "Path to numpy headers") + # Attempt to discover the NumPy include directory. If this succeeds, then build python API with NumPy + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import os; os.environ['DISTUTILS_USE_SDK']='1'; import numpy.distutils; print numpy.distutils.misc_util.get_numpy_include_dirs()[0]" + RESULT_VARIABLE PYTHON_NUMPY_PROCESS + OUTPUT_VARIABLE PYTHON_NUMPY_INCLUDE_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(NOT PYTHON_NUMPY_PROCESS EQUAL 0) + unset(PYTHON_NUMPY_INCLUDE_DIR) + endif() endif() endif() if(PYTHON_NUMPY_INCLUDE_DIR) + file(TO_CMAKE_PATH "${PYTHON_NUMPY_INCLUDE_DIR}" _PYTHON_NUMPY_INCLUDE_DIR) + set(PYTHON_NUMPY_INCLUDE_DIR ${_PYTHON_NUMPY_INCLUDE_DIR} CACHE PATH "Path to numpy headers") set(PYTHON_USE_NUMPY TRUE) - if(NOT CMAKE_CROSSCOMPILING) + if(CMAKE_CROSSCOMPILING) + if(NOT PYTHON_NUMPY_VERSION) + set(PYTHON_NUMPY_VERSION "undefined - cannot be probed because of the cross-compilation") + endif() + else() execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import numpy; print numpy.version.version" RESULT_VARIABLE PYTHON_NUMPY_PROCESS OUTPUT_VARIABLE PYTHON_NUMPY_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) - else() - if(NOT PYTHON_NUMPY_VERSION) - set(PYTHON_NUMPY_VERSION "undefined - cannot be probed because of the cross-compilation") - endif() endif() endif() endif(NOT ANDROID AND NOT IOS) From ae4be413c3a6dda6eacad198a7cedb033640a3bd Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 17 Jan 2014 01:05:59 +0400 Subject: [PATCH 199/295] added perf tests for cv::reduce --- modules/core/perf/opencl/perf_arithm.cpp | 64 ++++++++++++++++++++++++ modules/core/src/matrix.cpp | 1 + modules/core/test/ocl/test_arithm.cpp | 2 +- 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/modules/core/perf/opencl/perf_arithm.cpp b/modules/core/perf/opencl/perf_arithm.cpp index 4eae4897e..dc5cc07a8 100644 --- a/modules/core/perf/opencl/perf_arithm.cpp +++ b/modules/core/perf/opencl/perf_arithm.cpp @@ -912,6 +912,70 @@ OCL_PERF_TEST_P(PSNRFixture, PSNR, SANITY_CHECK(psnr, 1e-4, ERROR_RELATIVE); } +///////////// Reduce //////////////////////// + +CV_ENUM(ReduceMinMaxOp, CV_REDUCE_MIN, CV_REDUCE_MAX) + +typedef tuple, int, ReduceMinMaxOp> ReduceMinMaxParams; +typedef TestBaseWithParam ReduceMinMaxFixture; + +OCL_PERF_TEST_P(ReduceMinMaxFixture, Reduce, + ::testing::Combine(OCL_TEST_SIZES, + OCL_PERF_ENUM(std::make_pair(CV_8UC1, CV_8UC1), + std::make_pair(CV_32FC4, CV_32FC4)), + OCL_PERF_ENUM(0, 1), + ReduceMinMaxOp::all())) +{ + const ReduceMinMaxParams params = GetParam(); + const std::pair types = get<1>(params); + const int stype = types.first, dtype = types.second, + dim = get<2>(params), op = get<3>(params); + const Size srcSize = get<0>(params), + dstSize(dim == 0 ? srcSize.width : 1, dim == 0 ? 1 : srcSize.height); + const double eps = CV_MAT_DEPTH(dtype) <= CV_32S ? 1 : 1e-5; + + checkDeviceMaxMemoryAllocSize(srcSize, stype); + checkDeviceMaxMemoryAllocSize(srcSize, dtype); + + UMat src(srcSize, stype), dst(dstSize, dtype); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::reduce(src, dst, dim, op, dtype); + + SANITY_CHECK(dst, eps); +} + +CV_ENUM(ReduceAccOp, CV_REDUCE_SUM, CV_REDUCE_AVG) + +typedef tuple, int, ReduceAccOp> ReduceAccParams; +typedef TestBaseWithParam ReduceAccFixture; + +OCL_PERF_TEST_P(ReduceAccFixture, Reduce, + ::testing::Combine(OCL_TEST_SIZES, + OCL_PERF_ENUM(std::make_pair(CV_8UC4, CV_32SC4), + std::make_pair(CV_32FC1, CV_32FC1)), + OCL_PERF_ENUM(0, 1), + ReduceAccOp::all())) +{ + const ReduceAccParams params = GetParam(); + const std::pair types = get<1>(params); + const int stype = types.first, dtype = types.second, + dim = get<2>(params), op = get<3>(params); + const Size srcSize = get<0>(params), + dstSize(dim == 0 ? srcSize.width : 1, dim == 0 ? 1 : srcSize.height); + const double eps = CV_MAT_DEPTH(dtype) <= CV_32S ? 1 : 3e-4; + + checkDeviceMaxMemoryAllocSize(srcSize, stype); + checkDeviceMaxMemoryAllocSize(srcSize, dtype); + + UMat src(srcSize, stype), dst(dstSize, dtype); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::reduce(src, dst, dim, op, dtype); + + SANITY_CHECK(dst, eps); +} + } } // namespace cvtest::ocl #endif // HAVE_OPENCL diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index f51391985..53db7e3bf 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -3036,6 +3036,7 @@ void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype) int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if( dtype < 0 ) dtype = _dst.fixedType() ? _dst.type() : stype; + dtype = CV_MAKETYPE(dtype >= 0 ? dtype : stype, cn); int ddepth = CV_MAT_DEPTH(dtype); CV_Assert( cn == CV_MAT_CN(dtype) ); diff --git a/modules/core/test/ocl/test_arithm.cpp b/modules/core/test/ocl/test_arithm.cpp index 87442bbee..2932fc82c 100644 --- a/modules/core/test/ocl/test_arithm.cpp +++ b/modules/core/test/ocl/test_arithm.cpp @@ -1615,7 +1615,7 @@ OCL_TEST_P(ReduceSum, Mat) OCL_OFF(cv::reduce(src_roi, dst_roi, dim, CV_REDUCE_SUM, dtype)); OCL_ON(cv::reduce(usrc_roi, udst_roi, dim, CV_REDUCE_SUM, dtype)); - double eps = ddepth <= CV_32S ? 1 : 5e-5; + double eps = ddepth <= CV_32S ? 1 : 1e-4; OCL_EXPECT_MATS_NEAR(dst, eps) } } From bfa382cf9d6126759990ba0688b9ef2998280cac Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 20 Jan 2014 16:46:20 +0400 Subject: [PATCH 200/295] fixed copying UMat -> std::vector --- modules/core/src/stat.cpp | 10 +++++----- modules/imgproc/src/featureselect.cpp | 2 +- modules/imgproc/test/ocl/test_gftt.cpp | 14 +++++++++----- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index eac823995..e067201a5 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -1238,8 +1238,8 @@ static bool ocl_minMaxIdx( InputArray _src, double* minVal, double* maxVal, int* wgs2_aligned <<= 1; wgs2_aligned >>= 1; - String opts = format("-D DEPTH_%d -D OP_MIN_MAX_LOC%s -D WGS=%d -D WGS2_ALIGNED=%d %s", - depth, _mask.empty() ? "" : "_MASK", (int)wgs, wgs2_aligned, doubleSupport ? "-D DOUBLE_SUPPORT" : ""); + String opts = format("-D DEPTH_%d -D OP_MIN_MAX_LOC%s -D WGS=%d -D WGS2_ALIGNED=%d%s", + depth, _mask.empty() ? "" : "_MASK", (int)wgs, wgs2_aligned, doubleSupport ? " -D DOUBLE_SUPPORT" : ""); ocl::Kernel k("reduce", ocl::core::reduce_oclsrc, opts); if (k.empty()) @@ -1248,13 +1248,13 @@ static bool ocl_minMaxIdx( InputArray _src, double* minVal, double* maxVal, int* UMat src = _src.getUMat(), minval(1, groupnum, src.type()), maxval(1, groupnum, src.type()), minloc( 1, groupnum, CV_32SC1), maxloc( 1, groupnum, CV_32SC1), mask; - if(!_mask.empty()) + if (!_mask.empty()) mask = _mask.getUMat(); - if(src.channels()>1) + if (src.channels() > 1) src = src.reshape(1); - if(mask.empty()) + if (mask.empty()) k.args(ocl::KernelArg::ReadOnlyNoSize(src), src.cols, (int)src.total(), groupnum, ocl::KernelArg::PtrWriteOnly(minval), ocl::KernelArg::PtrWriteOnly(maxval), ocl::KernelArg::PtrWriteOnly(minloc), ocl::KernelArg::PtrWriteOnly(maxloc)); diff --git a/modules/imgproc/src/featureselect.cpp b/modules/imgproc/src/featureselect.cpp index 6d4f8c25e..c8b65b1ef 100644 --- a/modules/imgproc/src/featureselect.cpp +++ b/modules/imgproc/src/featureselect.cpp @@ -121,7 +121,7 @@ static bool ocl_goodFeaturesToTrack( InputArray _image, OutputArray _corners, tmpCorners.resize(total); Mat mcorners(1, totalb, CV_8UC1, &tmpCorners[0]); - corners.colRange(0, totalb).copyTo(mcorners); + corners.colRange(0, totalb).getMat(ACCESS_READ).copyTo(mcorners); } std::sort( tmpCorners.begin(), tmpCorners.end() ); diff --git a/modules/imgproc/test/ocl/test_gftt.cpp b/modules/imgproc/test/ocl/test_gftt.cpp index c92469612..62bbce077 100644 --- a/modules/imgproc/test/ocl/test_gftt.cpp +++ b/modules/imgproc/test/ocl/test_gftt.cpp @@ -81,6 +81,12 @@ PARAM_TEST_CASE(GoodFeaturesToTrack, double, bool) UMAT_UPLOAD_INPUT_PARAMETER(src) } + + void UMatToVector(const UMat & um, std::vector & v) const + { + v.resize(points.cols); + um.getMat(ACCESS_READ).copyTo(v); + } }; const int GoodFeaturesToTrack::maxCorners = 1000; @@ -96,13 +102,11 @@ OCL_TEST_P(GoodFeaturesToTrack, Accuracy) OCL_OFF(cv::goodFeaturesToTrack(src_roi, points, maxCorners, qualityLevel, minDistance, noArray())); ASSERT_FALSE(points.empty()); - pts.resize(points.cols); - points.copyTo(pts); + UMatToVector(points, pts); OCL_ON(cv::goodFeaturesToTrack(usrc_roi, upoints, maxCorners, qualityLevel, minDistance)); ASSERT_FALSE(upoints.empty()); - upts.resize(upoints.cols); - upoints.copyTo(upts); + UMatToVector(upoints, upts); ASSERT_EQ(upts.size(), pts.size()); @@ -117,7 +121,7 @@ OCL_TEST_P(GoodFeaturesToTrack, Accuracy) } double bad_ratio = static_cast(mistmatch) / pts.size(); - ASSERT_GE(1e-3, bad_ratio); + ASSERT_GE(1e-2, bad_ratio); } } From d84738769422aad33038d90681c47486e47a0380 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Tue, 21 Jan 2014 14:35:34 +0400 Subject: [PATCH 201/295] split CUDA Hough sources --- modules/gpu/src/cuda/build_point_list.cu | 138 ++++ .../cuda/{hough.cu => generalized_hough.cu} | 638 +----------------- modules/gpu/src/cuda/hough_circles.cu | 254 +++++++ modules/gpu/src/cuda/hough_lines.cu | 212 ++++++ modules/gpu/src/cuda/hough_segments.cu | 249 +++++++ .../src/{hough.cpp => generalized_hough.cpp} | 303 --------- modules/gpu/src/hough_circles.cpp | 223 ++++++ modules/gpu/src/hough_lines.cpp | 142 ++++ modules/gpu/src/hough_segments.cpp | 110 +++ 9 files changed, 1330 insertions(+), 939 deletions(-) create mode 100644 modules/gpu/src/cuda/build_point_list.cu rename modules/gpu/src/cuda/{hough.cu => generalized_hough.cu} (65%) create mode 100644 modules/gpu/src/cuda/hough_circles.cu create mode 100644 modules/gpu/src/cuda/hough_lines.cu create mode 100644 modules/gpu/src/cuda/hough_segments.cu rename modules/gpu/src/{hough.cpp => generalized_hough.cpp} (79%) create mode 100644 modules/gpu/src/hough_circles.cpp create mode 100644 modules/gpu/src/hough_lines.cpp create mode 100644 modules/gpu/src/hough_segments.cpp diff --git a/modules/gpu/src/cuda/build_point_list.cu b/modules/gpu/src/cuda/build_point_list.cu new file mode 100644 index 000000000..8a9c73b3f --- /dev/null +++ b/modules/gpu/src/cuda/build_point_list.cu @@ -0,0 +1,138 @@ +/*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) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., 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 CUDA_DISABLER + +#include "opencv2/gpu/device/common.hpp" +#include "opencv2/gpu/device/emulation.hpp" + +namespace cv { namespace gpu { namespace device +{ + namespace hough + { + __device__ static int g_counter; + + template + __global__ void buildPointList(const PtrStepSzb src, unsigned int* list) + { + __shared__ unsigned int s_queues[4][32 * PIXELS_PER_THREAD]; + __shared__ int s_qsize[4]; + __shared__ int s_globStart[4]; + + const int x = blockIdx.x * blockDim.x * PIXELS_PER_THREAD + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (threadIdx.x == 0) + s_qsize[threadIdx.y] = 0; + __syncthreads(); + + if (y < src.rows) + { + // fill the queue + const uchar* srcRow = src.ptr(y); + for (int i = 0, xx = x; i < PIXELS_PER_THREAD && xx < src.cols; ++i, xx += blockDim.x) + { + if (srcRow[xx]) + { + const unsigned int val = (y << 16) | xx; + const int qidx = Emulation::smem::atomicAdd(&s_qsize[threadIdx.y], 1); + s_queues[threadIdx.y][qidx] = val; + } + } + } + + __syncthreads(); + + // let one thread reserve the space required in the global list + if (threadIdx.x == 0 && threadIdx.y == 0) + { + // find how many items are stored in each list + int totalSize = 0; + for (int i = 0; i < blockDim.y; ++i) + { + s_globStart[i] = totalSize; + totalSize += s_qsize[i]; + } + + // calculate the offset in the global list + const int globalOffset = atomicAdd(&g_counter, totalSize); + for (int i = 0; i < blockDim.y; ++i) + s_globStart[i] += globalOffset; + } + + __syncthreads(); + + // copy local queues to global queue + const int qsize = s_qsize[threadIdx.y]; + int gidx = s_globStart[threadIdx.y] + threadIdx.x; + for(int i = threadIdx.x; i < qsize; i += blockDim.x, gidx += blockDim.x) + list[gidx] = s_queues[threadIdx.y][i]; + } + + int buildPointList_gpu(PtrStepSzb src, unsigned int* list) + { + const int PIXELS_PER_THREAD = 16; + + void* counterPtr; + cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); + + cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); + + const dim3 block(32, 4); + const dim3 grid(divUp(src.cols, block.x * PIXELS_PER_THREAD), divUp(src.rows, block.y)); + + cudaSafeCall( cudaFuncSetCacheConfig(buildPointList, cudaFuncCachePreferShared) ); + + buildPointList<<>>(src, list); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + int totalCount; + cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); + + return totalCount; + } + } +}}} + +#endif /* CUDA_DISABLER */ diff --git a/modules/gpu/src/cuda/hough.cu b/modules/gpu/src/cuda/generalized_hough.cu similarity index 65% rename from modules/gpu/src/cuda/hough.cu rename to modules/gpu/src/cuda/generalized_hough.cu index 59eba2608..5e2041eae 100644 --- a/modules/gpu/src/cuda/hough.cu +++ b/modules/gpu/src/cuda/generalized_hough.cu @@ -43,651 +43,18 @@ #if !defined CUDA_DISABLER #include -#include +#include #include "opencv2/gpu/device/common.hpp" #include "opencv2/gpu/device/emulation.hpp" #include "opencv2/gpu/device/vec_math.hpp" #include "opencv2/gpu/device/functional.hpp" -#include "opencv2/gpu/device/limits.hpp" -#include "opencv2/gpu/device/dynamic_smem.hpp" namespace cv { namespace gpu { namespace device { namespace hough { - __device__ int g_counter; - - //////////////////////////////////////////////////////////////////////// - // buildPointList - - template - __global__ void buildPointList(const PtrStepSzb src, unsigned int* list) - { - __shared__ unsigned int s_queues[4][32 * PIXELS_PER_THREAD]; - __shared__ int s_qsize[4]; - __shared__ int s_globStart[4]; - - const int x = blockIdx.x * blockDim.x * PIXELS_PER_THREAD + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (threadIdx.x == 0) - s_qsize[threadIdx.y] = 0; - __syncthreads(); - - if (y < src.rows) - { - // fill the queue - const uchar* srcRow = src.ptr(y); - for (int i = 0, xx = x; i < PIXELS_PER_THREAD && xx < src.cols; ++i, xx += blockDim.x) - { - if (srcRow[xx]) - { - const unsigned int val = (y << 16) | xx; - const int qidx = Emulation::smem::atomicAdd(&s_qsize[threadIdx.y], 1); - s_queues[threadIdx.y][qidx] = val; - } - } - } - - __syncthreads(); - - // let one thread reserve the space required in the global list - if (threadIdx.x == 0 && threadIdx.y == 0) - { - // find how many items are stored in each list - int totalSize = 0; - for (int i = 0; i < blockDim.y; ++i) - { - s_globStart[i] = totalSize; - totalSize += s_qsize[i]; - } - - // calculate the offset in the global list - const int globalOffset = atomicAdd(&g_counter, totalSize); - for (int i = 0; i < blockDim.y; ++i) - s_globStart[i] += globalOffset; - } - - __syncthreads(); - - // copy local queues to global queue - const int qsize = s_qsize[threadIdx.y]; - int gidx = s_globStart[threadIdx.y] + threadIdx.x; - for(int i = threadIdx.x; i < qsize; i += blockDim.x, gidx += blockDim.x) - list[gidx] = s_queues[threadIdx.y][i]; - } - - int buildPointList_gpu(PtrStepSzb src, unsigned int* list) - { - const int PIXELS_PER_THREAD = 16; - - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(32, 4); - const dim3 grid(divUp(src.cols, block.x * PIXELS_PER_THREAD), divUp(src.rows, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(buildPointList, cudaFuncCachePreferShared) ); - - buildPointList<<>>(src, list); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - return totalCount; - } - - //////////////////////////////////////////////////////////////////////// - // linesAccum - - __global__ void linesAccumGlobal(const unsigned int* list, const int count, PtrStepi accum, const float irho, const float theta, const int numrho) - { - const int n = blockIdx.x; - const float ang = n * theta; - - float sinVal; - float cosVal; - sincosf(ang, &sinVal, &cosVal); - sinVal *= irho; - cosVal *= irho; - - const int shift = (numrho - 1) / 2; - - int* accumRow = accum.ptr(n + 1); - for (int i = threadIdx.x; i < count; i += blockDim.x) - { - const unsigned int val = list[i]; - - const int x = (val & 0xFFFF); - const int y = (val >> 16) & 0xFFFF; - - int r = __float2int_rn(x * cosVal + y * sinVal); - r += shift; - - ::atomicAdd(accumRow + r + 1, 1); - } - } - - __global__ void linesAccumShared(const unsigned int* list, const int count, PtrStepi accum, const float irho, const float theta, const int numrho) - { - int* smem = DynamicSharedMem(); - - for (int i = threadIdx.x; i < numrho + 1; i += blockDim.x) - smem[i] = 0; - - __syncthreads(); - - const int n = blockIdx.x; - const float ang = n * theta; - - float sinVal; - float cosVal; - sincosf(ang, &sinVal, &cosVal); - sinVal *= irho; - cosVal *= irho; - - const int shift = (numrho - 1) / 2; - - for (int i = threadIdx.x; i < count; i += blockDim.x) - { - const unsigned int val = list[i]; - - const int x = (val & 0xFFFF); - const int y = (val >> 16) & 0xFFFF; - - int r = __float2int_rn(x * cosVal + y * sinVal); - r += shift; - - Emulation::smem::atomicAdd(&smem[r + 1], 1); - } - - __syncthreads(); - - int* accumRow = accum.ptr(n + 1); - for (int i = threadIdx.x; i < numrho + 1; i += blockDim.x) - accumRow[i] = smem[i]; - } - - void linesAccum_gpu(const unsigned int* list, int count, PtrStepSzi accum, float rho, float theta, size_t sharedMemPerBlock, bool has20) - { - const dim3 block(has20 ? 1024 : 512); - const dim3 grid(accum.rows - 2); - - size_t smemSize = (accum.cols - 1) * sizeof(int); - - if (smemSize < sharedMemPerBlock - 1000) - linesAccumShared<<>>(list, count, accum, 1.0f / rho, theta, accum.cols - 2); - else - linesAccumGlobal<<>>(list, count, accum, 1.0f / rho, theta, accum.cols - 2); - - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - - //////////////////////////////////////////////////////////////////////// - // linesGetResult - - __global__ void linesGetResult(const PtrStepSzi accum, float2* out, int* votes, const int maxSize, const float rho, const float theta, const int threshold, const int numrho) - { - const int r = blockIdx.x * blockDim.x + threadIdx.x; - const int n = blockIdx.y * blockDim.y + threadIdx.y; - - if (r >= accum.cols - 2 || n >= accum.rows - 2) - return; - - const int curVotes = accum(n + 1, r + 1); - - if (curVotes > threshold && - curVotes > accum(n + 1, r) && - curVotes >= accum(n + 1, r + 2) && - curVotes > accum(n, r + 1) && - curVotes >= accum(n + 2, r + 1)) - { - const float radius = (r - (numrho - 1) * 0.5f) * rho; - const float angle = n * theta; - - const int ind = ::atomicAdd(&g_counter, 1); - if (ind < maxSize) - { - out[ind] = make_float2(radius, angle); - votes[ind] = curVotes; - } - } - } - - int linesGetResult_gpu(PtrStepSzi accum, float2* out, int* votes, int maxSize, float rho, float theta, int threshold, bool doSort) - { - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(32, 8); - const dim3 grid(divUp(accum.cols - 2, block.x), divUp(accum.rows - 2, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(linesGetResult, cudaFuncCachePreferL1) ); - - linesGetResult<<>>(accum, out, votes, maxSize, rho, theta, threshold, accum.cols - 2); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - totalCount = ::min(totalCount, maxSize); - - if (doSort && totalCount > 0) - { - thrust::device_ptr outPtr(out); - thrust::device_ptr votesPtr(votes); - thrust::sort_by_key(votesPtr, votesPtr + totalCount, outPtr, thrust::greater()); - } - - return totalCount; - } - - //////////////////////////////////////////////////////////////////////// - // houghLinesProbabilistic - - texture tex_mask(false, cudaFilterModePoint, cudaAddressModeClamp); - - __global__ void houghLinesProbabilistic(const PtrStepSzi accum, - int4* out, const int maxSize, - const float rho, const float theta, - const int lineGap, const int lineLength, - const int rows, const int cols) - { - const int r = blockIdx.x * blockDim.x + threadIdx.x; - const int n = blockIdx.y * blockDim.y + threadIdx.y; - - if (r >= accum.cols - 2 || n >= accum.rows - 2) - return; - - const int curVotes = accum(n + 1, r + 1); - - if (curVotes >= lineLength && - curVotes > accum(n, r) && - curVotes > accum(n, r + 1) && - curVotes > accum(n, r + 2) && - curVotes > accum(n + 1, r) && - curVotes > accum(n + 1, r + 2) && - curVotes > accum(n + 2, r) && - curVotes > accum(n + 2, r + 1) && - curVotes > accum(n + 2, r + 2)) - { - const float radius = (r - (accum.cols - 2 - 1) * 0.5f) * rho; - const float angle = n * theta; - - float cosa; - float sina; - sincosf(angle, &sina, &cosa); - - float2 p0 = make_float2(cosa * radius, sina * radius); - float2 dir = make_float2(-sina, cosa); - - float2 pb[4] = {make_float2(-1, -1), make_float2(-1, -1), make_float2(-1, -1), make_float2(-1, -1)}; - float a; - - if (dir.x != 0) - { - a = -p0.x / dir.x; - pb[0].x = 0; - pb[0].y = p0.y + a * dir.y; - - a = (cols - 1 - p0.x) / dir.x; - pb[1].x = cols - 1; - pb[1].y = p0.y + a * dir.y; - } - if (dir.y != 0) - { - a = -p0.y / dir.y; - pb[2].x = p0.x + a * dir.x; - pb[2].y = 0; - - a = (rows - 1 - p0.y) / dir.y; - pb[3].x = p0.x + a * dir.x; - pb[3].y = rows - 1; - } - - if (pb[0].x == 0 && (pb[0].y >= 0 && pb[0].y < rows)) - { - p0 = pb[0]; - if (dir.x < 0) - dir = -dir; - } - else if (pb[1].x == cols - 1 && (pb[0].y >= 0 && pb[0].y < rows)) - { - p0 = pb[1]; - if (dir.x > 0) - dir = -dir; - } - else if (pb[2].y == 0 && (pb[2].x >= 0 && pb[2].x < cols)) - { - p0 = pb[2]; - if (dir.y < 0) - dir = -dir; - } - else if (pb[3].y == rows - 1 && (pb[3].x >= 0 && pb[3].x < cols)) - { - p0 = pb[3]; - if (dir.y > 0) - dir = -dir; - } - - float2 d; - if (::fabsf(dir.x) > ::fabsf(dir.y)) - { - d.x = dir.x > 0 ? 1 : -1; - d.y = dir.y / ::fabsf(dir.x); - } - else - { - d.x = dir.x / ::fabsf(dir.y); - d.y = dir.y > 0 ? 1 : -1; - } - - float2 line_end[2]; - int gap; - bool inLine = false; - - float2 p1 = p0; - if (p1.x < 0 || p1.x >= cols || p1.y < 0 || p1.y >= rows) - return; - - for (;;) - { - if (tex2D(tex_mask, p1.x, p1.y)) - { - gap = 0; - - if (!inLine) - { - line_end[0] = p1; - line_end[1] = p1; - inLine = true; - } - else - { - line_end[1] = p1; - } - } - else if (inLine) - { - if (++gap > lineGap) - { - bool good_line = ::abs(line_end[1].x - line_end[0].x) >= lineLength || - ::abs(line_end[1].y - line_end[0].y) >= lineLength; - - if (good_line) - { - const int ind = ::atomicAdd(&g_counter, 1); - if (ind < maxSize) - out[ind] = make_int4(line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y); - } - - gap = 0; - inLine = false; - } - } - - p1 = p1 + d; - if (p1.x < 0 || p1.x >= cols || p1.y < 0 || p1.y >= rows) - { - if (inLine) - { - bool good_line = ::abs(line_end[1].x - line_end[0].x) >= lineLength || - ::abs(line_end[1].y - line_end[0].y) >= lineLength; - - if (good_line) - { - const int ind = ::atomicAdd(&g_counter, 1); - if (ind < maxSize) - out[ind] = make_int4(line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y); - } - - } - break; - } - } - } - } - - int houghLinesProbabilistic_gpu(PtrStepSzb mask, PtrStepSzi accum, int4* out, int maxSize, float rho, float theta, int lineGap, int lineLength) - { - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(32, 8); - const dim3 grid(divUp(accum.cols - 2, block.x), divUp(accum.rows - 2, block.y)); - - bindTexture(&tex_mask, mask); - - houghLinesProbabilistic<<>>(accum, - out, maxSize, - rho, theta, - lineGap, lineLength, - mask.rows, mask.cols); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - totalCount = ::min(totalCount, maxSize); - - return totalCount; - } - - //////////////////////////////////////////////////////////////////////// - // circlesAccumCenters - - __global__ void circlesAccumCenters(const unsigned int* list, const int count, const PtrStepi dx, const PtrStepi dy, - PtrStepi accum, const int width, const int height, const int minRadius, const int maxRadius, const float idp) - { - const int SHIFT = 10; - const int ONE = 1 << SHIFT; - - const int tid = blockIdx.x * blockDim.x + threadIdx.x; - - if (tid >= count) - return; - - const unsigned int val = list[tid]; - - const int x = (val & 0xFFFF); - const int y = (val >> 16) & 0xFFFF; - - const int vx = dx(y, x); - const int vy = dy(y, x); - - if (vx == 0 && vy == 0) - return; - - const float mag = ::sqrtf(vx * vx + vy * vy); - - const int x0 = __float2int_rn((x * idp) * ONE); - const int y0 = __float2int_rn((y * idp) * ONE); - - int sx = __float2int_rn((vx * idp) * ONE / mag); - int sy = __float2int_rn((vy * idp) * ONE / mag); - - // Step from minRadius to maxRadius in both directions of the gradient - for (int k1 = 0; k1 < 2; ++k1) - { - int x1 = x0 + minRadius * sx; - int y1 = y0 + minRadius * sy; - - for (int r = minRadius; r <= maxRadius; x1 += sx, y1 += sy, ++r) - { - const int x2 = x1 >> SHIFT; - const int y2 = y1 >> SHIFT; - - if (x2 < 0 || x2 >= width || y2 < 0 || y2 >= height) - break; - - ::atomicAdd(accum.ptr(y2 + 1) + x2 + 1, 1); - } - - sx = -sx; - sy = -sy; - } - } - - void circlesAccumCenters_gpu(const unsigned int* list, int count, PtrStepi dx, PtrStepi dy, PtrStepSzi accum, int minRadius, int maxRadius, float idp) - { - const dim3 block(256); - const dim3 grid(divUp(count, block.x)); - - cudaSafeCall( cudaFuncSetCacheConfig(circlesAccumCenters, cudaFuncCachePreferL1) ); - - circlesAccumCenters<<>>(list, count, dx, dy, accum, accum.cols - 2, accum.rows - 2, minRadius, maxRadius, idp); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - - //////////////////////////////////////////////////////////////////////// - // buildCentersList - - __global__ void buildCentersList(const PtrStepSzi accum, unsigned int* centers, const int threshold) - { - const int x = blockIdx.x * blockDim.x + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (x < accum.cols - 2 && y < accum.rows - 2) - { - const int top = accum(y, x + 1); - - const int left = accum(y + 1, x); - const int cur = accum(y + 1, x + 1); - const int right = accum(y + 1, x + 2); - - const int bottom = accum(y + 2, x + 1); - - if (cur > threshold && cur > top && cur >= bottom && cur > left && cur >= right) - { - const unsigned int val = (y << 16) | x; - const int idx = ::atomicAdd(&g_counter, 1); - centers[idx] = val; - } - } - } - - int buildCentersList_gpu(PtrStepSzi accum, unsigned int* centers, int threshold) - { - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(32, 8); - const dim3 grid(divUp(accum.cols - 2, block.x), divUp(accum.rows - 2, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(buildCentersList, cudaFuncCachePreferL1) ); - - buildCentersList<<>>(accum, centers, threshold); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - return totalCount; - } - - //////////////////////////////////////////////////////////////////////// - // circlesAccumRadius - - __global__ void circlesAccumRadius(const unsigned int* centers, const unsigned int* list, const int count, - float3* circles, const int maxCircles, const float dp, - const int minRadius, const int maxRadius, const int histSize, const int threshold) - { - int* smem = DynamicSharedMem(); - - for (int i = threadIdx.x; i < histSize + 2; i += blockDim.x) - smem[i] = 0; - __syncthreads(); - - unsigned int val = centers[blockIdx.x]; - - float cx = (val & 0xFFFF); - float cy = (val >> 16) & 0xFFFF; - - cx = (cx + 0.5f) * dp; - cy = (cy + 0.5f) * dp; - - for (int i = threadIdx.x; i < count; i += blockDim.x) - { - val = list[i]; - - const int x = (val & 0xFFFF); - const int y = (val >> 16) & 0xFFFF; - - const float rad = ::sqrtf((cx - x) * (cx - x) + (cy - y) * (cy - y)); - if (rad >= minRadius && rad <= maxRadius) - { - const int r = __float2int_rn(rad - minRadius); - - Emulation::smem::atomicAdd(&smem[r + 1], 1); - } - } - - __syncthreads(); - - for (int i = threadIdx.x; i < histSize; i += blockDim.x) - { - const int curVotes = smem[i + 1]; - - if (curVotes >= threshold && curVotes > smem[i] && curVotes >= smem[i + 2]) - { - const int ind = ::atomicAdd(&g_counter, 1); - if (ind < maxCircles) - circles[ind] = make_float3(cx, cy, i + minRadius); - } - } - } - - int circlesAccumRadius_gpu(const unsigned int* centers, int centersCount, const unsigned int* list, int count, - float3* circles, int maxCircles, float dp, int minRadius, int maxRadius, int threshold, bool has20) - { - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(has20 ? 1024 : 512); - const dim3 grid(centersCount); - - const int histSize = maxRadius - minRadius + 1; - size_t smemSize = (histSize + 2) * sizeof(int); - - circlesAccumRadius<<>>(centers, list, count, circles, maxCircles, dp, minRadius, maxRadius, histSize, threshold); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - totalCount = ::min(totalCount, maxCircles); - - return totalCount; - } - - //////////////////////////////////////////////////////////////////////// - // Generalized Hough + __device__ static int g_counter; template __global__ void buildEdgePointList(const PtrStepSzb edges, const PtrStep dx, const PtrStep dy, unsigned int* coordList, float* thetaList) @@ -1706,5 +1073,4 @@ namespace cv { namespace gpu { namespace device } }}} - #endif /* CUDA_DISABLER */ diff --git a/modules/gpu/src/cuda/hough_circles.cu b/modules/gpu/src/cuda/hough_circles.cu new file mode 100644 index 000000000..5df7887b0 --- /dev/null +++ b/modules/gpu/src/cuda/hough_circles.cu @@ -0,0 +1,254 @@ +/*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) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., 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 CUDA_DISABLER + +#include "opencv2/gpu/device/common.hpp" +#include "opencv2/gpu/device/emulation.hpp" +#include "opencv2/gpu/device/dynamic_smem.hpp" + +namespace cv { namespace gpu { namespace device +{ + namespace hough + { + __device__ static int g_counter; + + //////////////////////////////////////////////////////////////////////// + // circlesAccumCenters + + __global__ void circlesAccumCenters(const unsigned int* list, const int count, const PtrStepi dx, const PtrStepi dy, + PtrStepi accum, const int width, const int height, const int minRadius, const int maxRadius, const float idp) + { + const int SHIFT = 10; + const int ONE = 1 << SHIFT; + + const int tid = blockIdx.x * blockDim.x + threadIdx.x; + + if (tid >= count) + return; + + const unsigned int val = list[tid]; + + const int x = (val & 0xFFFF); + const int y = (val >> 16) & 0xFFFF; + + const int vx = dx(y, x); + const int vy = dy(y, x); + + if (vx == 0 && vy == 0) + return; + + const float mag = ::sqrtf(vx * vx + vy * vy); + + const int x0 = __float2int_rn((x * idp) * ONE); + const int y0 = __float2int_rn((y * idp) * ONE); + + int sx = __float2int_rn((vx * idp) * ONE / mag); + int sy = __float2int_rn((vy * idp) * ONE / mag); + + // Step from minRadius to maxRadius in both directions of the gradient + for (int k1 = 0; k1 < 2; ++k1) + { + int x1 = x0 + minRadius * sx; + int y1 = y0 + minRadius * sy; + + for (int r = minRadius; r <= maxRadius; x1 += sx, y1 += sy, ++r) + { + const int x2 = x1 >> SHIFT; + const int y2 = y1 >> SHIFT; + + if (x2 < 0 || x2 >= width || y2 < 0 || y2 >= height) + break; + + ::atomicAdd(accum.ptr(y2 + 1) + x2 + 1, 1); + } + + sx = -sx; + sy = -sy; + } + } + + void circlesAccumCenters_gpu(const unsigned int* list, int count, PtrStepi dx, PtrStepi dy, PtrStepSzi accum, int minRadius, int maxRadius, float idp) + { + const dim3 block(256); + const dim3 grid(divUp(count, block.x)); + + cudaSafeCall( cudaFuncSetCacheConfig(circlesAccumCenters, cudaFuncCachePreferL1) ); + + circlesAccumCenters<<>>(list, count, dx, dy, accum, accum.cols - 2, accum.rows - 2, minRadius, maxRadius, idp); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + } + + //////////////////////////////////////////////////////////////////////// + // buildCentersList + + __global__ void buildCentersList(const PtrStepSzi accum, unsigned int* centers, const int threshold) + { + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x < accum.cols - 2 && y < accum.rows - 2) + { + const int top = accum(y, x + 1); + + const int left = accum(y + 1, x); + const int cur = accum(y + 1, x + 1); + const int right = accum(y + 1, x + 2); + + const int bottom = accum(y + 2, x + 1); + + if (cur > threshold && cur > top && cur >= bottom && cur > left && cur >= right) + { + const unsigned int val = (y << 16) | x; + const int idx = ::atomicAdd(&g_counter, 1); + centers[idx] = val; + } + } + } + + int buildCentersList_gpu(PtrStepSzi accum, unsigned int* centers, int threshold) + { + void* counterPtr; + cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); + + cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); + + const dim3 block(32, 8); + const dim3 grid(divUp(accum.cols - 2, block.x), divUp(accum.rows - 2, block.y)); + + cudaSafeCall( cudaFuncSetCacheConfig(buildCentersList, cudaFuncCachePreferL1) ); + + buildCentersList<<>>(accum, centers, threshold); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + int totalCount; + cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); + + return totalCount; + } + + //////////////////////////////////////////////////////////////////////// + // circlesAccumRadius + + __global__ void circlesAccumRadius(const unsigned int* centers, const unsigned int* list, const int count, + float3* circles, const int maxCircles, const float dp, + const int minRadius, const int maxRadius, const int histSize, const int threshold) + { + int* smem = DynamicSharedMem(); + + for (int i = threadIdx.x; i < histSize + 2; i += blockDim.x) + smem[i] = 0; + __syncthreads(); + + unsigned int val = centers[blockIdx.x]; + + float cx = (val & 0xFFFF); + float cy = (val >> 16) & 0xFFFF; + + cx = (cx + 0.5f) * dp; + cy = (cy + 0.5f) * dp; + + for (int i = threadIdx.x; i < count; i += blockDim.x) + { + val = list[i]; + + const int x = (val & 0xFFFF); + const int y = (val >> 16) & 0xFFFF; + + const float rad = ::sqrtf((cx - x) * (cx - x) + (cy - y) * (cy - y)); + if (rad >= minRadius && rad <= maxRadius) + { + const int r = __float2int_rn(rad - minRadius); + + Emulation::smem::atomicAdd(&smem[r + 1], 1); + } + } + + __syncthreads(); + + for (int i = threadIdx.x; i < histSize; i += blockDim.x) + { + const int curVotes = smem[i + 1]; + + if (curVotes >= threshold && curVotes > smem[i] && curVotes >= smem[i + 2]) + { + const int ind = ::atomicAdd(&g_counter, 1); + if (ind < maxCircles) + circles[ind] = make_float3(cx, cy, i + minRadius); + } + } + } + + int circlesAccumRadius_gpu(const unsigned int* centers, int centersCount, const unsigned int* list, int count, + float3* circles, int maxCircles, float dp, int minRadius, int maxRadius, int threshold, bool has20) + { + void* counterPtr; + cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); + + cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); + + const dim3 block(has20 ? 1024 : 512); + const dim3 grid(centersCount); + + const int histSize = maxRadius - minRadius + 1; + size_t smemSize = (histSize + 2) * sizeof(int); + + circlesAccumRadius<<>>(centers, list, count, circles, maxCircles, dp, minRadius, maxRadius, histSize, threshold); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + int totalCount; + cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); + + totalCount = ::min(totalCount, maxCircles); + + return totalCount; + } + } +}}} + +#endif /* CUDA_DISABLER */ diff --git a/modules/gpu/src/cuda/hough_lines.cu b/modules/gpu/src/cuda/hough_lines.cu new file mode 100644 index 000000000..2f2fe9a7e --- /dev/null +++ b/modules/gpu/src/cuda/hough_lines.cu @@ -0,0 +1,212 @@ +/*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) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., 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 CUDA_DISABLER + +#include +#include + +#include "opencv2/gpu/device/common.hpp" +#include "opencv2/gpu/device/emulation.hpp" +#include "opencv2/gpu/device/dynamic_smem.hpp" + +namespace cv { namespace gpu { namespace device +{ + namespace hough + { + __device__ static int g_counter; + + //////////////////////////////////////////////////////////////////////// + // linesAccum + + __global__ void linesAccumGlobal(const unsigned int* list, const int count, PtrStepi accum, const float irho, const float theta, const int numrho) + { + const int n = blockIdx.x; + const float ang = n * theta; + + float sinVal; + float cosVal; + sincosf(ang, &sinVal, &cosVal); + sinVal *= irho; + cosVal *= irho; + + const int shift = (numrho - 1) / 2; + + int* accumRow = accum.ptr(n + 1); + for (int i = threadIdx.x; i < count; i += blockDim.x) + { + const unsigned int val = list[i]; + + const int x = (val & 0xFFFF); + const int y = (val >> 16) & 0xFFFF; + + int r = __float2int_rn(x * cosVal + y * sinVal); + r += shift; + + ::atomicAdd(accumRow + r + 1, 1); + } + } + + __global__ void linesAccumShared(const unsigned int* list, const int count, PtrStepi accum, const float irho, const float theta, const int numrho) + { + int* smem = DynamicSharedMem(); + + for (int i = threadIdx.x; i < numrho + 1; i += blockDim.x) + smem[i] = 0; + + __syncthreads(); + + const int n = blockIdx.x; + const float ang = n * theta; + + float sinVal; + float cosVal; + sincosf(ang, &sinVal, &cosVal); + sinVal *= irho; + cosVal *= irho; + + const int shift = (numrho - 1) / 2; + + for (int i = threadIdx.x; i < count; i += blockDim.x) + { + const unsigned int val = list[i]; + + const int x = (val & 0xFFFF); + const int y = (val >> 16) & 0xFFFF; + + int r = __float2int_rn(x * cosVal + y * sinVal); + r += shift; + + Emulation::smem::atomicAdd(&smem[r + 1], 1); + } + + __syncthreads(); + + int* accumRow = accum.ptr(n + 1); + for (int i = threadIdx.x; i < numrho + 1; i += blockDim.x) + accumRow[i] = smem[i]; + } + + void linesAccum_gpu(const unsigned int* list, int count, PtrStepSzi accum, float rho, float theta, size_t sharedMemPerBlock, bool has20) + { + const dim3 block(has20 ? 1024 : 512); + const dim3 grid(accum.rows - 2); + + size_t smemSize = (accum.cols - 1) * sizeof(int); + + if (smemSize < sharedMemPerBlock - 1000) + linesAccumShared<<>>(list, count, accum, 1.0f / rho, theta, accum.cols - 2); + else + linesAccumGlobal<<>>(list, count, accum, 1.0f / rho, theta, accum.cols - 2); + + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + } + + //////////////////////////////////////////////////////////////////////// + // linesGetResult + + __global__ void linesGetResult(const PtrStepSzi accum, float2* out, int* votes, const int maxSize, const float rho, const float theta, const int threshold, const int numrho) + { + const int r = blockIdx.x * blockDim.x + threadIdx.x; + const int n = blockIdx.y * blockDim.y + threadIdx.y; + + if (r >= accum.cols - 2 || n >= accum.rows - 2) + return; + + const int curVotes = accum(n + 1, r + 1); + + if (curVotes > threshold && + curVotes > accum(n + 1, r) && + curVotes >= accum(n + 1, r + 2) && + curVotes > accum(n, r + 1) && + curVotes >= accum(n + 2, r + 1)) + { + const float radius = (r - (numrho - 1) * 0.5f) * rho; + const float angle = n * theta; + + const int ind = ::atomicAdd(&g_counter, 1); + if (ind < maxSize) + { + out[ind] = make_float2(radius, angle); + votes[ind] = curVotes; + } + } + } + + int linesGetResult_gpu(PtrStepSzi accum, float2* out, int* votes, int maxSize, float rho, float theta, int threshold, bool doSort) + { + void* counterPtr; + cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); + + cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); + + const dim3 block(32, 8); + const dim3 grid(divUp(accum.cols - 2, block.x), divUp(accum.rows - 2, block.y)); + + cudaSafeCall( cudaFuncSetCacheConfig(linesGetResult, cudaFuncCachePreferL1) ); + + linesGetResult<<>>(accum, out, votes, maxSize, rho, theta, threshold, accum.cols - 2); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + int totalCount; + cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); + + totalCount = ::min(totalCount, maxSize); + + if (doSort && totalCount > 0) + { + thrust::device_ptr outPtr(out); + thrust::device_ptr votesPtr(votes); + thrust::sort_by_key(votesPtr, votesPtr + totalCount, outPtr, thrust::greater()); + } + + return totalCount; + } + } +}}} + + +#endif /* CUDA_DISABLER */ diff --git a/modules/gpu/src/cuda/hough_segments.cu b/modules/gpu/src/cuda/hough_segments.cu new file mode 100644 index 000000000..f55bb4de9 --- /dev/null +++ b/modules/gpu/src/cuda/hough_segments.cu @@ -0,0 +1,249 @@ +/*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) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., 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 CUDA_DISABLER + +#include "opencv2/gpu/device/common.hpp" +#include "opencv2/gpu/device/vec_math.hpp" + +namespace cv { namespace gpu { namespace device +{ + namespace hough + { + __device__ int g_counter; + + texture tex_mask(false, cudaFilterModePoint, cudaAddressModeClamp); + + __global__ void houghLinesProbabilistic(const PtrStepSzi accum, + int4* out, const int maxSize, + const float rho, const float theta, + const int lineGap, const int lineLength, + const int rows, const int cols) + { + const int r = blockIdx.x * blockDim.x + threadIdx.x; + const int n = blockIdx.y * blockDim.y + threadIdx.y; + + if (r >= accum.cols - 2 || n >= accum.rows - 2) + return; + + const int curVotes = accum(n + 1, r + 1); + + if (curVotes >= lineLength && + curVotes > accum(n, r) && + curVotes > accum(n, r + 1) && + curVotes > accum(n, r + 2) && + curVotes > accum(n + 1, r) && + curVotes > accum(n + 1, r + 2) && + curVotes > accum(n + 2, r) && + curVotes > accum(n + 2, r + 1) && + curVotes > accum(n + 2, r + 2)) + { + const float radius = (r - (accum.cols - 2 - 1) * 0.5f) * rho; + const float angle = n * theta; + + float cosa; + float sina; + sincosf(angle, &sina, &cosa); + + float2 p0 = make_float2(cosa * radius, sina * radius); + float2 dir = make_float2(-sina, cosa); + + float2 pb[4] = {make_float2(-1, -1), make_float2(-1, -1), make_float2(-1, -1), make_float2(-1, -1)}; + float a; + + if (dir.x != 0) + { + a = -p0.x / dir.x; + pb[0].x = 0; + pb[0].y = p0.y + a * dir.y; + + a = (cols - 1 - p0.x) / dir.x; + pb[1].x = cols - 1; + pb[1].y = p0.y + a * dir.y; + } + if (dir.y != 0) + { + a = -p0.y / dir.y; + pb[2].x = p0.x + a * dir.x; + pb[2].y = 0; + + a = (rows - 1 - p0.y) / dir.y; + pb[3].x = p0.x + a * dir.x; + pb[3].y = rows - 1; + } + + if (pb[0].x == 0 && (pb[0].y >= 0 && pb[0].y < rows)) + { + p0 = pb[0]; + if (dir.x < 0) + dir = -dir; + } + else if (pb[1].x == cols - 1 && (pb[0].y >= 0 && pb[0].y < rows)) + { + p0 = pb[1]; + if (dir.x > 0) + dir = -dir; + } + else if (pb[2].y == 0 && (pb[2].x >= 0 && pb[2].x < cols)) + { + p0 = pb[2]; + if (dir.y < 0) + dir = -dir; + } + else if (pb[3].y == rows - 1 && (pb[3].x >= 0 && pb[3].x < cols)) + { + p0 = pb[3]; + if (dir.y > 0) + dir = -dir; + } + + float2 d; + if (::fabsf(dir.x) > ::fabsf(dir.y)) + { + d.x = dir.x > 0 ? 1 : -1; + d.y = dir.y / ::fabsf(dir.x); + } + else + { + d.x = dir.x / ::fabsf(dir.y); + d.y = dir.y > 0 ? 1 : -1; + } + + float2 line_end[2]; + int gap; + bool inLine = false; + + float2 p1 = p0; + if (p1.x < 0 || p1.x >= cols || p1.y < 0 || p1.y >= rows) + return; + + for (;;) + { + if (tex2D(tex_mask, p1.x, p1.y)) + { + gap = 0; + + if (!inLine) + { + line_end[0] = p1; + line_end[1] = p1; + inLine = true; + } + else + { + line_end[1] = p1; + } + } + else if (inLine) + { + if (++gap > lineGap) + { + bool good_line = ::abs(line_end[1].x - line_end[0].x) >= lineLength || + ::abs(line_end[1].y - line_end[0].y) >= lineLength; + + if (good_line) + { + const int ind = ::atomicAdd(&g_counter, 1); + if (ind < maxSize) + out[ind] = make_int4(line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y); + } + + gap = 0; + inLine = false; + } + } + + p1 = p1 + d; + if (p1.x < 0 || p1.x >= cols || p1.y < 0 || p1.y >= rows) + { + if (inLine) + { + bool good_line = ::abs(line_end[1].x - line_end[0].x) >= lineLength || + ::abs(line_end[1].y - line_end[0].y) >= lineLength; + + if (good_line) + { + const int ind = ::atomicAdd(&g_counter, 1); + if (ind < maxSize) + out[ind] = make_int4(line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y); + } + + } + break; + } + } + } + } + + int houghLinesProbabilistic_gpu(PtrStepSzb mask, PtrStepSzi accum, int4* out, int maxSize, float rho, float theta, int lineGap, int lineLength) + { + void* counterPtr; + cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); + + cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); + + const dim3 block(32, 8); + const dim3 grid(divUp(accum.cols - 2, block.x), divUp(accum.rows - 2, block.y)); + + bindTexture(&tex_mask, mask); + + houghLinesProbabilistic<<>>(accum, + out, maxSize, + rho, theta, + lineGap, lineLength, + mask.rows, mask.cols); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + int totalCount; + cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); + + totalCount = ::min(totalCount, maxSize); + + return totalCount; + } + } +}}} + + +#endif /* CUDA_DISABLER */ diff --git a/modules/gpu/src/hough.cpp b/modules/gpu/src/generalized_hough.cpp similarity index 79% rename from modules/gpu/src/hough.cpp rename to modules/gpu/src/generalized_hough.cpp index 09cf01850..a92c37d1a 100644 --- a/modules/gpu/src/hough.cpp +++ b/modules/gpu/src/generalized_hough.cpp @@ -48,16 +48,6 @@ using namespace cv::gpu; #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) -void cv::gpu::HoughLines(const GpuMat&, GpuMat&, float, float, int, bool, int) { throw_nogpu(); } -void cv::gpu::HoughLines(const GpuMat&, GpuMat&, HoughLinesBuf&, float, float, int, bool, int) { throw_nogpu(); } -void cv::gpu::HoughLinesDownload(const GpuMat&, OutputArray, OutputArray) { throw_nogpu(); } - -void cv::gpu::HoughLinesP(const GpuMat&, GpuMat&, HoughLinesBuf&, float, float, int, int, int) { throw_nogpu(); } - -void cv::gpu::HoughCircles(const GpuMat&, GpuMat&, int, float, float, int, int, int, int, int) { throw_nogpu(); } -void cv::gpu::HoughCircles(const GpuMat&, GpuMat&, HoughCirclesBuf&, int, float, float, int, int, int, int, int) { throw_nogpu(); } -void cv::gpu::HoughCirclesDownload(const GpuMat&, OutputArray) { throw_nogpu(); } - Ptr cv::gpu::GeneralizedHough_GPU::create(int) { throw_nogpu(); return Ptr(); } cv::gpu::GeneralizedHough_GPU::~GeneralizedHough_GPU() {} void cv::gpu::GeneralizedHough_GPU::setTemplate(const GpuMat&, int, Point) { throw_nogpu(); } @@ -77,299 +67,6 @@ namespace cv { namespace gpu { namespace device } }}} -////////////////////////////////////////////////////////// -// HoughLines - -namespace cv { namespace gpu { namespace device -{ - namespace hough - { - void linesAccum_gpu(const unsigned int* list, int count, PtrStepSzi accum, float rho, float theta, size_t sharedMemPerBlock, bool has20); - int linesGetResult_gpu(PtrStepSzi accum, float2* out, int* votes, int maxSize, float rho, float theta, int threshold, bool doSort); - } -}}} - -void cv::gpu::HoughLines(const GpuMat& src, GpuMat& lines, float rho, float theta, int threshold, bool doSort, int maxLines) -{ - HoughLinesBuf buf; - HoughLines(src, lines, buf, rho, theta, threshold, doSort, maxLines); -} - -void cv::gpu::HoughLines(const GpuMat& src, GpuMat& lines, HoughLinesBuf& buf, float rho, float theta, int threshold, bool doSort, int maxLines) -{ - using namespace cv::gpu::device::hough; - - CV_Assert(src.type() == CV_8UC1); - CV_Assert(src.cols < std::numeric_limits::max()); - CV_Assert(src.rows < std::numeric_limits::max()); - - ensureSizeIsEnough(1, src.size().area(), CV_32SC1, buf.list); - unsigned int* srcPoints = buf.list.ptr(); - - const int pointsCount = buildPointList_gpu(src, srcPoints); - if (pointsCount == 0) - { - lines.release(); - return; - } - - const int numangle = cvRound(CV_PI / theta); - const int numrho = cvRound(((src.cols + src.rows) * 2 + 1) / rho); - CV_Assert(numangle > 0 && numrho > 0); - - ensureSizeIsEnough(numangle + 2, numrho + 2, CV_32SC1, buf.accum); - buf.accum.setTo(Scalar::all(0)); - - DeviceInfo devInfo; - linesAccum_gpu(srcPoints, pointsCount, buf.accum, rho, theta, devInfo.sharedMemPerBlock(), devInfo.supports(FEATURE_SET_COMPUTE_20)); - - ensureSizeIsEnough(2, maxLines, CV_32FC2, lines); - - int linesCount = linesGetResult_gpu(buf.accum, lines.ptr(0), lines.ptr(1), maxLines, rho, theta, threshold, doSort); - if (linesCount > 0) - lines.cols = linesCount; - else - lines.release(); -} - -void cv::gpu::HoughLinesDownload(const GpuMat& d_lines, OutputArray h_lines_, OutputArray h_votes_) -{ - if (d_lines.empty()) - { - h_lines_.release(); - if (h_votes_.needed()) - h_votes_.release(); - return; - } - - CV_Assert(d_lines.rows == 2 && d_lines.type() == CV_32FC2); - - h_lines_.create(1, d_lines.cols, CV_32FC2); - Mat h_lines = h_lines_.getMat(); - d_lines.row(0).download(h_lines); - - if (h_votes_.needed()) - { - h_votes_.create(1, d_lines.cols, CV_32SC1); - Mat h_votes = h_votes_.getMat(); - GpuMat d_votes(1, d_lines.cols, CV_32SC1, const_cast(d_lines.ptr(1))); - d_votes.download(h_votes); - } -} - -////////////////////////////////////////////////////////// -// HoughLinesP - -namespace cv { namespace gpu { namespace device -{ - namespace hough - { - int houghLinesProbabilistic_gpu(PtrStepSzb mask, PtrStepSzi accum, int4* out, int maxSize, float rho, float theta, int lineGap, int lineLength); - } -}}} - -void cv::gpu::HoughLinesP(const GpuMat& src, GpuMat& lines, HoughLinesBuf& buf, float rho, float theta, int minLineLength, int maxLineGap, int maxLines) -{ - using namespace cv::gpu::device::hough; - - CV_Assert( src.type() == CV_8UC1 ); - CV_Assert( src.cols < std::numeric_limits::max() ); - CV_Assert( src.rows < std::numeric_limits::max() ); - - ensureSizeIsEnough(1, src.size().area(), CV_32SC1, buf.list); - unsigned int* srcPoints = buf.list.ptr(); - - const int pointsCount = buildPointList_gpu(src, srcPoints); - if (pointsCount == 0) - { - lines.release(); - return; - } - - const int numangle = cvRound(CV_PI / theta); - const int numrho = cvRound(((src.cols + src.rows) * 2 + 1) / rho); - CV_Assert( numangle > 0 && numrho > 0 ); - - ensureSizeIsEnough(numangle + 2, numrho + 2, CV_32SC1, buf.accum); - buf.accum.setTo(Scalar::all(0)); - - DeviceInfo devInfo; - linesAccum_gpu(srcPoints, pointsCount, buf.accum, rho, theta, devInfo.sharedMemPerBlock(), devInfo.supports(FEATURE_SET_COMPUTE_20)); - - ensureSizeIsEnough(1, maxLines, CV_32SC4, lines); - - int linesCount = houghLinesProbabilistic_gpu(src, buf.accum, lines.ptr(), maxLines, rho, theta, maxLineGap, minLineLength); - - if (linesCount > 0) - lines.cols = linesCount; - else - lines.release(); -} - -////////////////////////////////////////////////////////// -// HoughCircles - -namespace cv { namespace gpu { namespace device -{ - namespace hough - { - void circlesAccumCenters_gpu(const unsigned int* list, int count, PtrStepi dx, PtrStepi dy, PtrStepSzi accum, int minRadius, int maxRadius, float idp); - int buildCentersList_gpu(PtrStepSzi accum, unsigned int* centers, int threshold); - int circlesAccumRadius_gpu(const unsigned int* centers, int centersCount, const unsigned int* list, int count, - float3* circles, int maxCircles, float dp, int minRadius, int maxRadius, int threshold, bool has20); - } -}}} - -void cv::gpu::HoughCircles(const GpuMat& src, GpuMat& circles, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles) -{ - HoughCirclesBuf buf; - HoughCircles(src, circles, buf, method, dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius, maxCircles); -} - -void cv::gpu::HoughCircles(const GpuMat& src, GpuMat& circles, HoughCirclesBuf& buf, int method, - float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles) -{ - using namespace cv::gpu::device::hough; - - CV_Assert(src.type() == CV_8UC1); - CV_Assert(src.cols < std::numeric_limits::max()); - CV_Assert(src.rows < std::numeric_limits::max()); - CV_Assert(method == CV_HOUGH_GRADIENT); - CV_Assert(dp > 0); - CV_Assert(minRadius > 0 && maxRadius > minRadius); - CV_Assert(cannyThreshold > 0); - CV_Assert(votesThreshold > 0); - CV_Assert(maxCircles > 0); - - const float idp = 1.0f / dp; - - cv::gpu::Canny(src, buf.cannyBuf, buf.edges, std::max(cannyThreshold / 2, 1), cannyThreshold); - - ensureSizeIsEnough(2, src.size().area(), CV_32SC1, buf.list); - unsigned int* srcPoints = buf.list.ptr(0); - unsigned int* centers = buf.list.ptr(1); - - const int pointsCount = buildPointList_gpu(buf.edges, srcPoints); - if (pointsCount == 0) - { - circles.release(); - return; - } - - ensureSizeIsEnough(cvCeil(src.rows * idp) + 2, cvCeil(src.cols * idp) + 2, CV_32SC1, buf.accum); - buf.accum.setTo(Scalar::all(0)); - - circlesAccumCenters_gpu(srcPoints, pointsCount, buf.cannyBuf.dx, buf.cannyBuf.dy, buf.accum, minRadius, maxRadius, idp); - - int centersCount = buildCentersList_gpu(buf.accum, centers, votesThreshold); - if (centersCount == 0) - { - circles.release(); - return; - } - - if (minDist > 1) - { - cv::AutoBuffer oldBuf_(centersCount); - cv::AutoBuffer newBuf_(centersCount); - int newCount = 0; - - ushort2* oldBuf = oldBuf_; - ushort2* newBuf = newBuf_; - - cudaSafeCall( cudaMemcpy(oldBuf, centers, centersCount * sizeof(ushort2), cudaMemcpyDeviceToHost) ); - - const int cellSize = cvRound(minDist); - const int gridWidth = (src.cols + cellSize - 1) / cellSize; - const int gridHeight = (src.rows + cellSize - 1) / cellSize; - - std::vector< std::vector > grid(gridWidth * gridHeight); - - const float minDist2 = minDist * minDist; - - for (int i = 0; i < centersCount; ++i) - { - ushort2 p = oldBuf[i]; - - bool good = true; - - int xCell = static_cast(p.x / cellSize); - int yCell = static_cast(p.y / cellSize); - - int x1 = xCell - 1; - int y1 = yCell - 1; - int x2 = xCell + 1; - int y2 = yCell + 1; - - // boundary check - x1 = std::max(0, x1); - y1 = std::max(0, y1); - x2 = std::min(gridWidth - 1, x2); - y2 = std::min(gridHeight - 1, y2); - - for (int yy = y1; yy <= y2; ++yy) - { - for (int xx = x1; xx <= x2; ++xx) - { - vector& m = grid[yy * gridWidth + xx]; - - for(size_t j = 0; j < m.size(); ++j) - { - float dx = (float)(p.x - m[j].x); - float dy = (float)(p.y - m[j].y); - - if (dx * dx + dy * dy < minDist2) - { - good = false; - goto break_out; - } - } - } - } - - break_out: - - if(good) - { - grid[yCell * gridWidth + xCell].push_back(p); - - newBuf[newCount++] = p; - } - } - - cudaSafeCall( cudaMemcpy(centers, newBuf, newCount * sizeof(unsigned int), cudaMemcpyHostToDevice) ); - centersCount = newCount; - } - - ensureSizeIsEnough(1, maxCircles, CV_32FC3, circles); - - const int circlesCount = circlesAccumRadius_gpu(centers, centersCount, srcPoints, pointsCount, circles.ptr(), maxCircles, - dp, minRadius, maxRadius, votesThreshold, deviceSupports(FEATURE_SET_COMPUTE_20)); - - if (circlesCount > 0) - circles.cols = circlesCount; - else - circles.release(); -} - -void cv::gpu::HoughCirclesDownload(const GpuMat& d_circles, cv::OutputArray h_circles_) -{ - if (d_circles.empty()) - { - h_circles_.release(); - return; - } - - CV_Assert(d_circles.rows == 1 && d_circles.type() == CV_32FC3); - - h_circles_.create(1, d_circles.cols, CV_32FC3); - Mat h_circles = h_circles_.getMat(); - d_circles.download(h_circles); -} - -////////////////////////////////////////////////////////// -// GeneralizedHough - namespace cv { namespace gpu { namespace device { namespace hough diff --git a/modules/gpu/src/hough_circles.cpp b/modules/gpu/src/hough_circles.cpp new file mode 100644 index 000000000..74aa7394f --- /dev/null +++ b/modules/gpu/src/hough_circles.cpp @@ -0,0 +1,223 @@ +/*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) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., 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*/ + +#include "precomp.hpp" + +using namespace std; +using namespace cv; +using namespace cv::gpu; + +#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) + +void cv::gpu::HoughCircles(const GpuMat&, GpuMat&, int, float, float, int, int, int, int, int) { throw_nogpu(); } +void cv::gpu::HoughCircles(const GpuMat&, GpuMat&, HoughCirclesBuf&, int, float, float, int, int, int, int, int) { throw_nogpu(); } +void cv::gpu::HoughCirclesDownload(const GpuMat&, OutputArray) { throw_nogpu(); } + +#else /* !defined (HAVE_CUDA) */ + +namespace cv { namespace gpu { namespace device +{ + namespace hough + { + int buildPointList_gpu(PtrStepSzb src, unsigned int* list); + } +}}} + +namespace cv { namespace gpu { namespace device +{ + namespace hough + { + void circlesAccumCenters_gpu(const unsigned int* list, int count, PtrStepi dx, PtrStepi dy, PtrStepSzi accum, int minRadius, int maxRadius, float idp); + int buildCentersList_gpu(PtrStepSzi accum, unsigned int* centers, int threshold); + int circlesAccumRadius_gpu(const unsigned int* centers, int centersCount, const unsigned int* list, int count, + float3* circles, int maxCircles, float dp, int minRadius, int maxRadius, int threshold, bool has20); + } +}}} + +void cv::gpu::HoughCircles(const GpuMat& src, GpuMat& circles, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles) +{ + HoughCirclesBuf buf; + HoughCircles(src, circles, buf, method, dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius, maxCircles); +} + +void cv::gpu::HoughCircles(const GpuMat& src, GpuMat& circles, HoughCirclesBuf& buf, int method, + float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles) +{ + using namespace cv::gpu::device::hough; + + CV_Assert(src.type() == CV_8UC1); + CV_Assert(src.cols < std::numeric_limits::max()); + CV_Assert(src.rows < std::numeric_limits::max()); + CV_Assert(method == CV_HOUGH_GRADIENT); + CV_Assert(dp > 0); + CV_Assert(minRadius > 0 && maxRadius > minRadius); + CV_Assert(cannyThreshold > 0); + CV_Assert(votesThreshold > 0); + CV_Assert(maxCircles > 0); + + const float idp = 1.0f / dp; + + cv::gpu::Canny(src, buf.cannyBuf, buf.edges, std::max(cannyThreshold / 2, 1), cannyThreshold); + + ensureSizeIsEnough(2, src.size().area(), CV_32SC1, buf.list); + unsigned int* srcPoints = buf.list.ptr(0); + unsigned int* centers = buf.list.ptr(1); + + const int pointsCount = buildPointList_gpu(buf.edges, srcPoints); + if (pointsCount == 0) + { + circles.release(); + return; + } + + ensureSizeIsEnough(cvCeil(src.rows * idp) + 2, cvCeil(src.cols * idp) + 2, CV_32SC1, buf.accum); + buf.accum.setTo(Scalar::all(0)); + + circlesAccumCenters_gpu(srcPoints, pointsCount, buf.cannyBuf.dx, buf.cannyBuf.dy, buf.accum, minRadius, maxRadius, idp); + + int centersCount = buildCentersList_gpu(buf.accum, centers, votesThreshold); + if (centersCount == 0) + { + circles.release(); + return; + } + + if (minDist > 1) + { + cv::AutoBuffer oldBuf_(centersCount); + cv::AutoBuffer newBuf_(centersCount); + int newCount = 0; + + ushort2* oldBuf = oldBuf_; + ushort2* newBuf = newBuf_; + + cudaSafeCall( cudaMemcpy(oldBuf, centers, centersCount * sizeof(ushort2), cudaMemcpyDeviceToHost) ); + + const int cellSize = cvRound(minDist); + const int gridWidth = (src.cols + cellSize - 1) / cellSize; + const int gridHeight = (src.rows + cellSize - 1) / cellSize; + + std::vector< std::vector > grid(gridWidth * gridHeight); + + const float minDist2 = minDist * minDist; + + for (int i = 0; i < centersCount; ++i) + { + ushort2 p = oldBuf[i]; + + bool good = true; + + int xCell = static_cast(p.x / cellSize); + int yCell = static_cast(p.y / cellSize); + + int x1 = xCell - 1; + int y1 = yCell - 1; + int x2 = xCell + 1; + int y2 = yCell + 1; + + // boundary check + x1 = std::max(0, x1); + y1 = std::max(0, y1); + x2 = std::min(gridWidth - 1, x2); + y2 = std::min(gridHeight - 1, y2); + + for (int yy = y1; yy <= y2; ++yy) + { + for (int xx = x1; xx <= x2; ++xx) + { + vector& m = grid[yy * gridWidth + xx]; + + for(size_t j = 0; j < m.size(); ++j) + { + float dx = (float)(p.x - m[j].x); + float dy = (float)(p.y - m[j].y); + + if (dx * dx + dy * dy < minDist2) + { + good = false; + goto break_out; + } + } + } + } + + break_out: + + if(good) + { + grid[yCell * gridWidth + xCell].push_back(p); + + newBuf[newCount++] = p; + } + } + + cudaSafeCall( cudaMemcpy(centers, newBuf, newCount * sizeof(unsigned int), cudaMemcpyHostToDevice) ); + centersCount = newCount; + } + + ensureSizeIsEnough(1, maxCircles, CV_32FC3, circles); + + const int circlesCount = circlesAccumRadius_gpu(centers, centersCount, srcPoints, pointsCount, circles.ptr(), maxCircles, + dp, minRadius, maxRadius, votesThreshold, deviceSupports(FEATURE_SET_COMPUTE_20)); + + if (circlesCount > 0) + circles.cols = circlesCount; + else + circles.release(); +} + +void cv::gpu::HoughCirclesDownload(const GpuMat& d_circles, cv::OutputArray h_circles_) +{ + if (d_circles.empty()) + { + h_circles_.release(); + return; + } + + CV_Assert(d_circles.rows == 1 && d_circles.type() == CV_32FC3); + + h_circles_.create(1, d_circles.cols, CV_32FC3); + Mat h_circles = h_circles_.getMat(); + d_circles.download(h_circles); +} + +#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpu/src/hough_lines.cpp b/modules/gpu/src/hough_lines.cpp new file mode 100644 index 000000000..4cc4067b2 --- /dev/null +++ b/modules/gpu/src/hough_lines.cpp @@ -0,0 +1,142 @@ +/*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) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., 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*/ + +#include "precomp.hpp" + +using namespace std; +using namespace cv; +using namespace cv::gpu; + +#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) + +void cv::gpu::HoughLines(const GpuMat&, GpuMat&, float, float, int, bool, int) { throw_nogpu(); } +void cv::gpu::HoughLines(const GpuMat&, GpuMat&, HoughLinesBuf&, float, float, int, bool, int) { throw_nogpu(); } +void cv::gpu::HoughLinesDownload(const GpuMat&, OutputArray, OutputArray) { throw_nogpu(); } + +#else /* !defined (HAVE_CUDA) */ + +namespace cv { namespace gpu { namespace device +{ + namespace hough + { + int buildPointList_gpu(PtrStepSzb src, unsigned int* list); + } +}}} + +namespace cv { namespace gpu { namespace device +{ + namespace hough + { + void linesAccum_gpu(const unsigned int* list, int count, PtrStepSzi accum, float rho, float theta, size_t sharedMemPerBlock, bool has20); + int linesGetResult_gpu(PtrStepSzi accum, float2* out, int* votes, int maxSize, float rho, float theta, int threshold, bool doSort); + } +}}} + +void cv::gpu::HoughLines(const GpuMat& src, GpuMat& lines, float rho, float theta, int threshold, bool doSort, int maxLines) +{ + HoughLinesBuf buf; + HoughLines(src, lines, buf, rho, theta, threshold, doSort, maxLines); +} + +void cv::gpu::HoughLines(const GpuMat& src, GpuMat& lines, HoughLinesBuf& buf, float rho, float theta, int threshold, bool doSort, int maxLines) +{ + using namespace cv::gpu::device::hough; + + CV_Assert(src.type() == CV_8UC1); + CV_Assert(src.cols < std::numeric_limits::max()); + CV_Assert(src.rows < std::numeric_limits::max()); + + ensureSizeIsEnough(1, src.size().area(), CV_32SC1, buf.list); + unsigned int* srcPoints = buf.list.ptr(); + + const int pointsCount = buildPointList_gpu(src, srcPoints); + if (pointsCount == 0) + { + lines.release(); + return; + } + + const int numangle = cvRound(CV_PI / theta); + const int numrho = cvRound(((src.cols + src.rows) * 2 + 1) / rho); + CV_Assert(numangle > 0 && numrho > 0); + + ensureSizeIsEnough(numangle + 2, numrho + 2, CV_32SC1, buf.accum); + buf.accum.setTo(Scalar::all(0)); + + DeviceInfo devInfo; + linesAccum_gpu(srcPoints, pointsCount, buf.accum, rho, theta, devInfo.sharedMemPerBlock(), devInfo.supports(FEATURE_SET_COMPUTE_20)); + + ensureSizeIsEnough(2, maxLines, CV_32FC2, lines); + + int linesCount = linesGetResult_gpu(buf.accum, lines.ptr(0), lines.ptr(1), maxLines, rho, theta, threshold, doSort); + if (linesCount > 0) + lines.cols = linesCount; + else + lines.release(); +} + +void cv::gpu::HoughLinesDownload(const GpuMat& d_lines, OutputArray h_lines_, OutputArray h_votes_) +{ + if (d_lines.empty()) + { + h_lines_.release(); + if (h_votes_.needed()) + h_votes_.release(); + return; + } + + CV_Assert(d_lines.rows == 2 && d_lines.type() == CV_32FC2); + + h_lines_.create(1, d_lines.cols, CV_32FC2); + Mat h_lines = h_lines_.getMat(); + d_lines.row(0).download(h_lines); + + if (h_votes_.needed()) + { + h_votes_.create(1, d_lines.cols, CV_32SC1); + Mat h_votes = h_votes_.getMat(); + GpuMat d_votes(1, d_lines.cols, CV_32SC1, const_cast(d_lines.ptr(1))); + d_votes.download(h_votes); + } +} + +#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpu/src/hough_segments.cpp b/modules/gpu/src/hough_segments.cpp new file mode 100644 index 000000000..c34f33a62 --- /dev/null +++ b/modules/gpu/src/hough_segments.cpp @@ -0,0 +1,110 @@ +/*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) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., 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*/ + +#include "precomp.hpp" + +using namespace std; +using namespace cv; +using namespace cv::gpu; + +#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) + +void cv::gpu::HoughLinesP(const GpuMat&, GpuMat&, HoughLinesBuf&, float, float, int, int, int) { throw_nogpu(); } + +#else /* !defined (HAVE_CUDA) */ + +namespace cv { namespace gpu { namespace device +{ + namespace hough + { + int buildPointList_gpu(PtrStepSzb src, unsigned int* list); + } +}}} + +namespace cv { namespace gpu { namespace device +{ + namespace hough + { + void linesAccum_gpu(const unsigned int* list, int count, PtrStepSzi accum, float rho, float theta, size_t sharedMemPerBlock, bool has20); + int houghLinesProbabilistic_gpu(PtrStepSzb mask, PtrStepSzi accum, int4* out, int maxSize, float rho, float theta, int lineGap, int lineLength); + } +}}} + +void cv::gpu::HoughLinesP(const GpuMat& src, GpuMat& lines, HoughLinesBuf& buf, float rho, float theta, int minLineLength, int maxLineGap, int maxLines) +{ + using namespace cv::gpu::device::hough; + + CV_Assert( src.type() == CV_8UC1 ); + CV_Assert( src.cols < std::numeric_limits::max() ); + CV_Assert( src.rows < std::numeric_limits::max() ); + + ensureSizeIsEnough(1, src.size().area(), CV_32SC1, buf.list); + unsigned int* srcPoints = buf.list.ptr(); + + const int pointsCount = buildPointList_gpu(src, srcPoints); + if (pointsCount == 0) + { + lines.release(); + return; + } + + const int numangle = cvRound(CV_PI / theta); + const int numrho = cvRound(((src.cols + src.rows) * 2 + 1) / rho); + CV_Assert( numangle > 0 && numrho > 0 ); + + ensureSizeIsEnough(numangle + 2, numrho + 2, CV_32SC1, buf.accum); + buf.accum.setTo(Scalar::all(0)); + + DeviceInfo devInfo; + linesAccum_gpu(srcPoints, pointsCount, buf.accum, rho, theta, devInfo.sharedMemPerBlock(), devInfo.supports(FEATURE_SET_COMPUTE_20)); + + ensureSizeIsEnough(1, maxLines, CV_32SC4, lines); + + int linesCount = houghLinesProbabilistic_gpu(src, buf.accum, lines.ptr(), maxLines, rho, theta, maxLineGap, minLineLength); + + if (linesCount > 0) + lines.cols = linesCount; + else + lines.release(); +} + +#endif /* !defined (HAVE_CUDA) */ From 33d42b740c6fe938b63a0b25c9ad51741aba48c3 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Tue, 21 Jan 2014 14:35:51 +0400 Subject: [PATCH 202/295] disable CUDA generalized Hough Transform --- modules/gpu/src/cuda/generalized_hough.cu | 2 ++ modules/gpu/src/generalized_hough.cpp | 2 ++ modules/gpu/test/test_hough.cpp | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/gpu/src/cuda/generalized_hough.cu b/modules/gpu/src/cuda/generalized_hough.cu index 5e2041eae..35451e7e2 100644 --- a/modules/gpu/src/cuda/generalized_hough.cu +++ b/modules/gpu/src/cuda/generalized_hough.cu @@ -40,6 +40,8 @@ // //M*/ +#define CUDA_DISABLER + #if !defined CUDA_DISABLER #include diff --git a/modules/gpu/src/generalized_hough.cpp b/modules/gpu/src/generalized_hough.cpp index a92c37d1a..867ba7ee7 100644 --- a/modules/gpu/src/generalized_hough.cpp +++ b/modules/gpu/src/generalized_hough.cpp @@ -40,6 +40,8 @@ // //M*/ +#define CUDA_DISABLER + #include "precomp.hpp" using namespace std; diff --git a/modules/gpu/test/test_hough.cpp b/modules/gpu/test/test_hough.cpp index f876a7a2b..6441fc69a 100644 --- a/modules/gpu/test/test_hough.cpp +++ b/modules/gpu/test/test_hough.cpp @@ -189,7 +189,7 @@ PARAM_TEST_CASE(GeneralizedHough, cv::gpu::DeviceInfo, UseRoi) { }; -GPU_TEST_P(GeneralizedHough, POSITION) +GPU_TEST_P(GeneralizedHough, DISABLED_POSITION) { const cv::gpu::DeviceInfo devInfo = GET_PARAM(0); cv::gpu::setDevice(devInfo.deviceID()); From 5d206059a8578499d5ed2f0d51f1f0d5e4876dd2 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 21 Jan 2014 18:02:53 +0400 Subject: [PATCH 203/295] moved bioinspired to opencv_contrib --- doc/CMakeLists.txt | 2 +- .../images/retina_TreeHdr_retina.jpg | Bin 150688 -> 0 bytes .../images/retina_TreeHdr_small.jpg | Bin 166872 -> 0 bytes .../images/studentsSample_input.jpg | Bin 80282 -> 0 bytes .../images/studentsSample_magno.jpg | Bin 28228 -> 0 bytes .../images/studentsSample_parvo.jpg | Bin 69443 -> 0 bytes .../bioinspired/retina_model/retina_model.rst | 418 ----- .../images/retina_TreeHdr_small.jpg | Bin 50051 -> 0 bytes .../table_of_content_bioinspired.rst | 36 - .../table_of_content_bioinspired.rst~ | 36 - doc/tutorials/tutorials.rst | 1 - include/opencv2/opencv.hpp | 1 - modules/bioinspired/CMakeLists.txt | 3 - modules/bioinspired/doc/bioinspired.rst | 10 - .../doc/retina/images/retinaInput.jpg | Bin 13646 -> 0 bytes .../retina/images/retinaOutput_default.jpg | Bin 22461 -> 0 bytes .../retina/images/retinaOutput_realistic.jpg | Bin 19131 -> 0 bytes modules/bioinspired/doc/retina/index.rst | 493 ----- .../include/opencv2/bioinspired.hpp | 50 - .../opencv2/bioinspired/bioinspired.hpp | 48 - .../include/opencv2/bioinspired/retina.hpp | 311 ---- .../bioinspired/retinafasttonemapping.hpp | 121 -- modules/bioinspired/src/basicretinafilter.cpp | 888 --------- modules/bioinspired/src/basicretinafilter.hpp | 678 ------- .../bioinspired/src/imagelogpolprojection.cpp | 451 ----- .../bioinspired/src/imagelogpolprojection.hpp | 244 --- modules/bioinspired/src/magnoretinafilter.cpp | 212 --- modules/bioinspired/src/magnoretinafilter.hpp | 246 --- .../bioinspired/src/opencl/retina_kernel.cl | 779 -------- modules/bioinspired/src/parvoretinafilter.cpp | 233 --- modules/bioinspired/src/parvoretinafilter.hpp | 264 --- modules/bioinspired/src/precomp.hpp | 68 - modules/bioinspired/src/retina.cpp | 745 -------- modules/bioinspired/src/retina_ocl.cpp | 1643 ----------------- modules/bioinspired/src/retina_ocl.hpp | 634 ------- modules/bioinspired/src/retinacolor.cpp | 725 -------- modules/bioinspired/src/retinacolor.hpp | 390 ---- .../bioinspired/src/retinafasttonemapping.cpp | 318 ---- modules/bioinspired/src/retinafilter.cpp | 526 ------ modules/bioinspired/src/retinafilter.hpp | 548 ------ modules/bioinspired/src/templatebuffer.hpp | 555 ------ modules/bioinspired/test/test_main.cpp | 3 - modules/bioinspired/test/test_precomp.hpp | 16 - modules/bioinspired/test/test_retina_ocl.cpp | 164 -- samples/cpp/CMakeLists.txt | 2 +- .../OpenEXRimages_HDR_Retina_toneMapping.cpp | 304 --- ...EXRimages_HDR_Retina_toneMapping_video.cpp | 365 ---- samples/cpp/retinaDemo.cpp | 158 -- .../bioinspired/retina_tutorial.cpp | 149 -- samples/ocl/CMakeLists.txt | 3 +- samples/ocl/retina_ocl.cpp | 119 -- 51 files changed, 3 insertions(+), 12957 deletions(-) delete mode 100644 doc/tutorials/bioinspired/retina_model/images/retina_TreeHdr_retina.jpg delete mode 100644 doc/tutorials/bioinspired/retina_model/images/retina_TreeHdr_small.jpg delete mode 100644 doc/tutorials/bioinspired/retina_model/images/studentsSample_input.jpg delete mode 100644 doc/tutorials/bioinspired/retina_model/images/studentsSample_magno.jpg delete mode 100644 doc/tutorials/bioinspired/retina_model/images/studentsSample_parvo.jpg delete mode 100644 doc/tutorials/bioinspired/retina_model/retina_model.rst delete mode 100644 doc/tutorials/bioinspired/table_of_content_bioinspired/images/retina_TreeHdr_small.jpg delete mode 100644 doc/tutorials/bioinspired/table_of_content_bioinspired/table_of_content_bioinspired.rst delete mode 100644 doc/tutorials/bioinspired/table_of_content_bioinspired/table_of_content_bioinspired.rst~ delete mode 100644 modules/bioinspired/CMakeLists.txt delete mode 100644 modules/bioinspired/doc/bioinspired.rst delete mode 100644 modules/bioinspired/doc/retina/images/retinaInput.jpg delete mode 100644 modules/bioinspired/doc/retina/images/retinaOutput_default.jpg delete mode 100644 modules/bioinspired/doc/retina/images/retinaOutput_realistic.jpg delete mode 100644 modules/bioinspired/doc/retina/index.rst delete mode 100644 modules/bioinspired/include/opencv2/bioinspired.hpp delete mode 100644 modules/bioinspired/include/opencv2/bioinspired/bioinspired.hpp delete mode 100644 modules/bioinspired/include/opencv2/bioinspired/retina.hpp delete mode 100644 modules/bioinspired/include/opencv2/bioinspired/retinafasttonemapping.hpp delete mode 100644 modules/bioinspired/src/basicretinafilter.cpp delete mode 100644 modules/bioinspired/src/basicretinafilter.hpp delete mode 100644 modules/bioinspired/src/imagelogpolprojection.cpp delete mode 100644 modules/bioinspired/src/imagelogpolprojection.hpp delete mode 100644 modules/bioinspired/src/magnoretinafilter.cpp delete mode 100644 modules/bioinspired/src/magnoretinafilter.hpp delete mode 100644 modules/bioinspired/src/opencl/retina_kernel.cl delete mode 100644 modules/bioinspired/src/parvoretinafilter.cpp delete mode 100644 modules/bioinspired/src/parvoretinafilter.hpp delete mode 100644 modules/bioinspired/src/precomp.hpp delete mode 100644 modules/bioinspired/src/retina.cpp delete mode 100644 modules/bioinspired/src/retina_ocl.cpp delete mode 100644 modules/bioinspired/src/retina_ocl.hpp delete mode 100644 modules/bioinspired/src/retinacolor.cpp delete mode 100644 modules/bioinspired/src/retinacolor.hpp delete mode 100644 modules/bioinspired/src/retinafasttonemapping.cpp delete mode 100644 modules/bioinspired/src/retinafilter.cpp delete mode 100644 modules/bioinspired/src/retinafilter.hpp delete mode 100644 modules/bioinspired/src/templatebuffer.hpp delete mode 100644 modules/bioinspired/test/test_main.cpp delete mode 100644 modules/bioinspired/test/test_precomp.hpp delete mode 100644 modules/bioinspired/test/test_retina_ocl.cpp delete mode 100644 samples/cpp/OpenEXRimages_HDR_Retina_toneMapping.cpp delete mode 100644 samples/cpp/OpenEXRimages_HDR_Retina_toneMapping_video.cpp delete mode 100644 samples/cpp/retinaDemo.cpp delete mode 100644 samples/cpp/tutorial_code/bioinspired/retina_tutorial.cpp delete mode 100644 samples/ocl/retina_ocl.cpp diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 217e4b6f6..2106c57e1 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -33,7 +33,7 @@ if(BUILD_DOCS AND HAVE_SPHINX) endif() endforeach() - set(FIXED_ORDER_MODULES core imgproc highgui video calib3d features2d objdetect ml flann photo stitching nonfree contrib legacy bioinspired) + set(FIXED_ORDER_MODULES core imgproc highgui video calib3d features2d objdetect ml flann photo stitching nonfree contrib legacy) list(REMOVE_ITEM BASE_MODULES ${FIXED_ORDER_MODULES}) diff --git a/doc/tutorials/bioinspired/retina_model/images/retina_TreeHdr_retina.jpg b/doc/tutorials/bioinspired/retina_model/images/retina_TreeHdr_retina.jpg deleted file mode 100644 index 251557e834b0ac025edfd1acf88509f016b11f39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150688 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 z 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�jh`XckekaO996v^dR}_F8^k&;MjkGafr&atjf(JO7v@OVO3pU1J9ZeH4W@xB zyKgpOq0QlaGB?D{mpf36B-+mEk(kt;_0Hqm_xk;amx}aUZ3kD+(los&B#MSyq->H% z<*WnwXaZ<`D*3*o93O57WUIVCtIw`ve2i-{V?d!;irnCW2qTi#Xi)u00?4Pu+DGvT z7bC)6AJf9iERQ?qW=7LO#3?ZwaHnVlf}q%7530vYW}7zy6i25>BO)lB6?hB{9(eCZ zpSq5y%hhtRuxFJrWqgzh?EA^#nwsp<_WtAP()e0+HV}DiFPFtL=-I;;#J&v2a@b{Y zr<)bxF%xHSqA!#0b-@7kDze9i;L~KrfwKm8nRN0YgeM)y7R3EU0rcmCvGu(CeIGR> z$(JRJk$HI2fanuzt9qF50Wl4=*^Lplh_8lq#goNrrooSkic&m`Y;j1E@)v57PSU{N zH$lJh-TW}5NGpt7c!!r7qPnc8xiN`G{{Zt=(%0E+n(xq_Tyo~g9z<%2Sh({40HmIM ztP$APf9=uQPMtmruAvJs^COUCpE8MVdE@GTx8I?Qk$fI5 z$JeRJD&S^C;n=-ykb*qe!M8l0((HTj$J3j1YzNBJVZq9XHu-ldUj+86_63*@J-TgC z38c3RsvB=}fW{%wnu6~qMn;&8H>0VB@?x-5) zHe0g4!8vP*Fw~lKw{ru=;axx=*<#g76?r_G{{Z#6we<}nA79VG((#>^X$~y7;g6^Q z$b=JS!v$*labCmd504gBQ^2LMPCCla&VX6-Ry~{&ESDe}p}U@k{xu$Ew;o#J$BbW4 zNf^Y(F*&T!VkL5RF=yq=Z1MN$Zkkn}{ue0=+5E8^18l3e)wp&%4h0j(aBHMGPs?EBLpD6K ztaoor3wp2gzBv7dSFGuZBsOHNWOmb&cXxR~zC67rUkEb942OM8i zuom4ZaRFK4MAv?FndioMa%J9w0fz)xt*R+N+<5KJew5-*7}S;J2;`EjB%rXa#E>tF z`d{hPq09N%-eE74z=nc4ChOY$fB<*o*HzCH`0$*JX<1ih;G%-q@Ao~gpQpcCOB^L3 zsPgSaKGQO^(}r_%^%5Xcw6H_J%ma!a(hYl>9_QPp7`on_qq?hNt5!w{{VFkYy^1Pwj|Nc zGuD_wPXO&=0H8qa#ST4%efql|*Wq22A8AZ=7&hd)!;s}m1Q94jb%~XD19LTB@9$iY zAvCk(;LE4Yr_9fd2INNpY6F%0FKG9`HWIM68~#NlwIYERcJ4>^<(T&k&SNK;dLwEOP4$g{J2=Oca-o znGPwCqkvUFOH#|Yg<>s$Ab@LWdy(M{cSMo=2k{5O8io#_l#i+&S?3DR#^`Vy*H1_P)8Ff`Ue(H(bn6+e;srW6Zm^S z!e11jZ9`TwPCty8xmoe%O5i9hGk_?u zU_oQ`Ab+ns^PeX#irXEr6@%>-8LP)4-U&HQ}vWSIvtajv$i+%D3v=1HAx!Yg}Ce zef_#ou0tLlfuMsIA!iv-HeC4ty0QLoKuKY2cs5VC?0b~dOQV5GL|i5Kvuap61ep^& zOg!?EKS9-jSn7?EvI~cDF(3tU2N!39XZw-WxcJEwZxpDz znTae1fBt{;>wvI9g(MFCxtvQQD)Yf$fPTTR+}Qeb^CdJuT;W2qN(TFkx^8kf;DgQk zP_CQjV<-^h%F%;te6<^aUgz@h-R-xo=al8%9zn0+D{e=@>VbS^V&*hAV zUo1%FVN>r_#~r)=_tLn@MWE?a!weW%P{%whM5JtcDi-^jqIvf<$M@@vO)*yuaxq$5 zj8=AIAZ?{BtlH5eU%vp?zg6nLGN>u35jU4(XK3V)`q$L;Qed=`Nskf)eYZ+zayuS< N$A8zN*huLs|JhAS^jrV{ diff --git a/doc/tutorials/bioinspired/retina_model/images/studentsSample_input.jpg b/doc/tutorials/bioinspired/retina_model/images/studentsSample_input.jpg deleted file mode 100644 index a0ac96dde92548ac453f39ec12e770ac42eaaaa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80282 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 diff --git a/doc/tutorials/bioinspired/retina_model/images/studentsSample_magno.jpg b/doc/tutorials/bioinspired/retina_model/images/studentsSample_magno.jpg deleted file mode 100644 index 935397869dace8b3fb00e8c1b287b8fa1250b36b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28228 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 diff --git a/doc/tutorials/bioinspired/retina_model/images/studentsSample_parvo.jpg b/doc/tutorials/bioinspired/retina_model/images/studentsSample_parvo.jpg deleted file mode 100644 index 3babfefc37466d5df9331bc45c6e714748e2b04e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69443 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�X5H(Zv{u3R+L3hvp=ysO@vDFuad9kFh5CLZz>i__6_Ox zyDUKQxk6>|@&Jh^@S=4dKalGK-iL0M$vr7+GhLHX?eoQCvh^Nh+QRW`rwKRZe6=O# z0K^kb#mv6YGWOD6sdtqDa1!}$Kl*GHV z{S>Mj`KVI*guX#MIA1cWzS>U_yzoZS(efRv7oVmbf1xr_?5Tx~IJL$1%@V}nwqAXu z4o2yb$!0Z*bY8q&mW;g5CZYu~(JW^ap87pD5xB&KP`ohWxdTlpK~I!CH=aoy$D+eU zVx0}-EKdb%hv~NQy(CWR+=yv7^KWl+FMxMIUvHWTCK!8_xI z>>FzEmX36tgPG+XqS#UoqMBs-c+mH~ZWZ?NH`F!l8T-aTJpuSh#9QtOk#&)3Rd!2j z!+fJGim6;5xzwV!Og!(j`g~cw^Ypw$x#nUVquudof2_gh8mn-w2w-EtLA>dF=j!Lp zZ2BC%o!;}k@HAL;dONm+f^SIVFx6J=zEfKYW$7BfzJ`L73rj4?4oLis5dKahs%dE= z)8SY>%u9|bFOCzsG5*3U(Asd&{WuTraPDyXcvfRlPb=O%9uU7+2#ceCKt?L( zVPBAal@e*5tXX5gTI-rS_aR|bpyrfg^T^*pf44iC922tF+1jutPjWRXj7+jMs2MXa z0Has;+R!(euP~ccO%NY`4I*?6CsvuR3xE4%iY!X1n+$hF6U7E6XM_)M)P|n((I4!; zf@$0D8qa}z8L-ewacb3@wd#KFBFd>{c&WgW@lkFmXHAxPz@KxT_)c!qSfL*QPSj(s zn46IK6KP2Vma)5kbmd5c0x+{1ChVu=tZpa0tVjulur`*kGRDKX2(}){9G#F4kN6>N zD>hMLZKK*W>I&}VAmg;8-~{?wol<4__t&ph=o@f4^vl|6XE9diWV)%NENK_qq0o!Q zK-KnTLo-+-6tak+K#IQ3huJ_S2+LSV>)H4Eor${2GPHmZtuY!rebKjkw)UfPaRZ#v;|3v21Y&>bTs`d5}rxo$@YS=SES-S`SAPP+DI$l`{ z1)9?$aM5nCNZxbcCZ!|5KZB;!vL&XV40(Q+Lz%K;ZoJN#vUzHIiB#`F{E#s)R)Zd{_ufXEmsY~F(K_EGJ{*OcyYJcbQm+1j0iM(0UqgQD6Fw_Q^71)tuIoDfrE=-I#$?jba|78(r1Y7lo-Q3 zfrlIzNN&7{05;xbV1s-!N|05%hF) zXK@&}?rX=v6MJQ9ZzxIg!4X7JnO5Z-Gl+suO&5`jDf3Wl{-}I2ShF%-H#kKbKU3qs zaS~_*=05C5rU&j?j_?it9G~n+9Vd{1zvssccJ*!I>3L1!O-6I@0R97D^wXFb?eX2w z{gB`smlsoPaT4a@o>K+xr87wPhJjX8sC)+Lu>9AGmRxm}XP2s&Ov;9C#6ATthoDxf zh>yOJt2k_u4|Q>N*$hr1tYDQzOqm9^Z9*-d7NEfTT_bx_D$t!$cYb&W-${wNt1Ki% zP+-QQkJuvm2)0F*RCMyfI61K&A&?JJO86%^=J2mY9gWG?qt9sW612@CM`>>9&oT7E z0aacVSAP%(09{LM0*rdZy3so3A+)+lHG<}{NELxlajSm-d?~nw?VpKUe*x&5WC_?K3zB8iQ#{Mt@eN{T%LfFjI=@6Gtmul1q;qg8Po!+ z2MaHHd_UU#v>lEuNlJ~+KQ#hdP5axF88E!(o7eXnyk&U9%|8OWh)BExgO^r+9jGkx!9 zec-=bF25;p(b1s#a|kvMq~y)YcLI9kYx!9FG>W75TZfpf$i^lk6c3DiV|Wiw{NYbt zytbw+u3-I+c64E)AeBWF?M0D0v!K(-muWOijkON?mZW30)__&rRw<7T+6C0JIt4Rn z`T4Gt6nP`KP|ONGnJhtoz2wxvQEQdjE{_!MycBc3QAs4o9TPq;3c*P(c+5#odATh> z(DT)Fj_ELqt1+#bI*c5d_plgC+%ndDB{?Y=6`FQF(g998VllwX@S9REKa`wM>v@}M z3bZq3&$~zaW0NYcsRiSq!LartusNWJ_+VhGZtNcb{Sy^<{s!rACP4=WnNY7ig7bR_ z#ywH^gec)X{@okl$_w>zAAXw(rgnR8xPB~JQV*G@Sj@&6V&9<)IZiPn;LXd7MrX>0easV=^g|u(q&CwCCyl8 zLIWr=#OnNeLd7|LDuNsyvfQL9rf64ib!NM)Y0asMka;!gbV)e{q>M^auR5%L&z0ko zg~fmC|Cr~cmpVE1Q@)yDPX3q+kMV4f-gk`mI-b+1Abre<%*6MRM&DnPXML;=4_H7E zr#bwq>Qsny~1oUCw;}Z#Z~a zunx@i@V5FM=n8J8j^P?qFyorm*f|O}9`IW^A5Nr46d5&V7+&l4mx>lTG6><;1sYAo ziGNt4$x*piCF;zC5Xw%%gSZn@SoDwV+HJ3EX}>5{N-Dz&6)gMUo5cG+*IJIQwUqq+ z16i+7?rx~7mPxUCn02hxN+nB|X*fx0EHCzVwC~cd)|ln{kkfv{{rFr}W+X=)!Y}eL zt5ddMSQ@xF@>{~|PE#?k5{Gl@{~K=%7}|$9*wm{=sJ|5@RCh;F#=MV0U9^FmDlri1?hF2qC+)k`* zS6P-q2>bQeK`~D4go~SKtJ@^$lmszx*qrOZtH78)OEcMLnE49kNezC1A#zs-ZQjlb z5_es@U%XJ!;}Fa+%IFs-cYOVvlGJ`}ib4lAp`MR3Hm|HTDE3X_-?bKpJkc}Sj^4O=jkY1d zMuMw@`S7Mjk)J$6xVO{2enj>5Z-AW(?pd!xactvFW98G6Tx@AEH7QwcgCJ8TlG=2~ zN8#8s*&_+xM|_;k?+QHy{;2oBCX|=p<)+ludEDPw5L?dQC9P#Ucn1$ZM;aU@k6q&b zpr^#BgAa;yh{Xj3Z{>*3cXTyJTAz7z@^>i`S-;5Rs&f9S(F-dXP`wWHdV(yURM>L`~AW{xJ8KvU*5@6(hD!9w^kpJ{-!oPPmVDWIWjVBJ13g~UWIoZ?m7~^^ zIPI)>F8OMeq7&8#;uDDRQbJdETC>VAcN7=euisi*yV(4-C!ow=mXBX`(p2AHVdPOY^sl@6ReP9CVj+`>fu@Alfx<&%-SyPb}4Jp~8Ee zQ;_(wS61P`+iFXy*TGOoo=OEbd9_qIXp=AL7?r9ZP$5qjU~WU_Q9#n=#oN%r+0!Y% zLZQR~+gVH&yhw>0h;TMi4_%s6!FgGO{2-nnKEaStsUTPE_9v!nW91weDpbki;Dj-m z7P}DtDE5+SMio3L1S+$JINN>cwceN$9LMl&l6x)r2RQgD2D8S)(uD47q(mrtBw7TV z3EMBQES~FEfSUbPxGMe-OjYPJ@+W|&*nvR;*A?)VS#D$($5LGXM%~ljwUD;OIQJ{ec(M|UJs*ukH3Ohh(md`gn7#ToZP(PkPQ7Uf zVLLFUW)%*Gjy}_Wf~!I0&RS%-82!C^z{<;Pt?`y^<6C7d4+SKauEhx_Y5_9P!yQwZ zxt!vZO7IDGmz=4aUg>)Mv{UXkIS=&;!e-qdB|8pxEznt}k1+l{^xB@fucP4YVkKhb zthhIthO<~oScmQNY8b${^r&3_*p!3wO1|L?jVsaTt4gIxNdZO%qYaxJwYFfgps4*U zjxn_XtscPhi^^u?Y1d;Ztt;_H!Eq=P-!19{_tAd%0H%n8p%YLt<_3fFDJR=8)K*|e za6<7Q`he)X^F91*K8(=KvTr`2apR^b{G8aSd7ceWH|hKoV2ek95T>X048UcR(!Xr$ChMz^rX zo*hF)UK+QxD<^G|AcH@G%_A8T7=QX=4VF7>N~8n!X-R}R=Xxh}>N$q`JChx6R~Xw8 zLWrli%ux2F`3kG07}~ny)&y^ffWV^>dpB|=Xo1LMpkI?r}I`W zz&_`Va_3|+GiT~lqtVblr5G{vaIC$saRPmc@s;4(&)sb$)IZrR)g;hn>sDlYr#ylj z1msJ??Na-4-_G@}p||=bv#ht70)15F&+&DRnYRs8gCuMGsWXcRz9daFIYb|>A-}XD z37+J&abQzx?DuKk$FWgQF}7I)n^XAcEDSQ-bhefh6n?8QCX)1Oeq3RBAy$exz=&K+j6Fm_N?*^bb8~2s>)H&vMD$O0I~Emp-i}aVD3$JK8*))0pOeGMQf48?FNVw z#)Yy+YAnOZ>Op(v=7LmF?-8z}FDT^6hT&QM_dmc52`RtjQd9k&TeDurvqQ_)M^ZRT z#xyzqqodafp3m-Eps;G$59rlwznMc4h>wf?7r#OO0l>?KadhAN%~5fmktYORei`)A z+r6e8Csc@4Ut(LQAd|vqd*5j&!MTi9NZf>Jw>HJTVf4`2Gy{xJgeUPVFICL4NBgn5 zj4RumvQ9Az$|AdY-Z_bBBS7`3=ojC8DrS zaMSY?`Ta8r6It?o%XM_=QUVt3ElQ=2nK4=7m-6O;H@>ncht0~-dv+!%)mv%~^rVhM z3fy8QY?=lP8U;`DlIo2GC|^j@aRRW)Mw?XeC;yi8x!35=_Yk zx(gr{G|%HWVdxcjHQ0VLIXwb&Eb~BH?>?E_PoxBp3>dsLiU~q>@1$@YA87Jyj7id+Jg~v(WA`_Y>Y}H*LZgKX%}E*M9k2mglyBKi+lvy>c1>sA`s`+hgC9hvpVY7gm#RX0#dPL@0hY zx?b$bu0^?HB5jp{J|uINZMhY|yqSwf(Y}ERWaiM_6^;_x%*nZs z3_Dzob@Z4Qz7ZYh){!d8XUF7i{LDp*MLlm|*+QaGCbKMU3<|Wdw4jqf0{_yQI-1;o zZA76>&dVFs2$H$3be1DiuOo93I9L|j#0kI0PGKQ}HZG3SJ91nV8|r(pC>`hu$|{_I zRs&ZI`-YgRn%l}Rb^jzS4X0Y2H;P_Wwu7s-$hna;UbiN}ryWrZRc$O@w2GGKf>f?S zNW8cEs4qx|YPb%I3>6{Rb_??Di9IG^lg9-QLrq0LIKf}9{e6u^YGuz;9n3J;oGn?r z96)`FLT@_LS0RWmg6===%12QseO*Ho|12Ld4!Iy0{rm+a;0}t{PieNKX5JtkLX&Io z^@%5xTS}bg-EvBLik|*8ha?qLmyVv4X;_fmyr_qcj{&5h_5f>+Z$WNZc?0Tn_d8it zIp277&qpY6AA)8}eG`pwHds8EOloEMF)-w>S^8Fam3(@|l)f`vfF4bOQQoLA6kYfa z89`qSdx~V_mjlSuA%tVQRCrx2AP63Ser_pf-sMz*a=cJ=Dv{(LAetcoJ!#Pz`gnqR zZJm)pYj<2l?toIyc3V0&R+}Q{w%6{RE&Xw3*B;YNiJ;ww0RtZw=u4zB!~_)MbBdg8RFmm=0zhj@Na8Nrj&!j7mNN?7uI)_J)Q z*)Bva*f4i|v+l2yZUoP>!XFH$fFauubr~cw6=ukP_=s46A?bmTk$~>n|;AIQ`V{ zapD0*Ro?I9zeb}Z3DQ(6Q?aAdi?;$A*TQ-$??F^6Ied>3Vm7AK;46_y-wO3!`Ca~n$ZeLlY$Z2fMmiZ9^%vcNYbQUa0q?i_?@(FHA0czVqU0xch*{Jx z?inBFSRWQz3YNa*5THx!5yYwK0eY*cz|pY77SJ*L8hm&3l-4|Th?3}ZPmJbA{CKg{ zmd%0VqbUmEf;SN{{>W;#@2r)j^yGDCzWEBMgp=jh3>cT6!q6$6YIsHv7|P3-hM zO?ETFH5{XhIJ>#hPyv`@`wbn08DDZ~c2#jTXFIvjaI#UWmDahM?Hi>Z&JkgzdBv>#(RJ4^bgqL%m3eif z38}Z9vB8cVsu}mNe7=I@bu^gR+wu}Q_=4BWCwgm|?Ur3rx7>Q3gDuvPunH>#;XB_a8TIt7>qloUG-K*t{R#wrG% z5~9cLqC(hz0L7;$>fm3G73jahc6>?|N>1e=0qk1?V-#4c1I=%2zBmCqmhGfH7HWAT zch;mtl(Np5KZ8-Ahv4HQ{Ip%D&nPD@l|a0!MT*Dk`p_%O*A)@UN@&sQ^^>QaA?}aQclZc=TPLI(vJ|)e^>Q z@3hduEku*8sF4jiDTiIk_!f4I3~XT@dL4;Jz3B3q2z^wPuG)QFK$4uAKN-}SrF?45 zmJLWyOAtfuUF@F~h~1&XfOLt#R@t!?KlzwL@`lyVyk+CIJ=Uz_I&SE&ukDNEr&1bS z{ZY#f_hZE{AQ>!PB|zQf7;^0KQ?W=dq>a@x7xt3~G=({jyou~=_gh`xJwcAKP|Go# zl3;mwm<{cY4~!Xb)pNeT9m=!eEB6`CW^IYasM{s}4*;w{Q@_xv%3XsFcn6%->oiTQ zO13r}`|(-r1jlsKxEVYE4Qc5L-)3~$3EFTmSvd49F_Xz|Ea82MSIb-O@SY0W3 zt(1=A9cmk0cEaY-1hZfyKmdM~9mc<6N7>Ob#AhT|>rr&Bd<2x1qvg?bR)-H_m?Mvp zvo3xXd_KLK`$}&OS{sM!Ka@AO9nV_POiV^Ukl zCx4Po-1FX_)hV)Fd85o%;0~)}x?L~Clca%mM#|VKo`CkLr}%gAUrvA>AH{ObE~=o=D$swqX3^wRQ*DXw@7OdQad(}C$!UkH))eFn^HGOI11zq zzmU)7X}6v`_@$%74ey2;Z!L0sly)btr(dA2S7&xqW&`Hrfk-XoX@7STuGC+YztOH>kmRZ~M=U*h*P)vm zc{3dLi;_9{Y9{dhmZ((Ot7o<=o~B8MmdMr_rD&~L$k=>W@TJoTC5~ibGIvMQ+O;h_ zbKwUHUs6=)K5`Uu#yK^4yaC}*?JSx+K4bp?5Kd~G-w6CMIV>y`Zf?V+VDc#2MrgBH zBSPC(@a)-W^(gu0nFmU@6xv*vWW9{%r_L*v)IJI5<~B&=kOF!G#ZhmAy0im+o#I=l z+aQgyV1ema%OjFnGgxNI`kk!tMIw@tDF=+^qgyB<=z!;~aYMlW01>QJ(#ynh$frAe z#^iD9QNstt{V@P0IsRN_+~j-lSxYCY6`{OyI&ylWw3@{RB^dx7)fus3bF(8n9M>r? ziasY=AZv{Q9|PvWJ!!D~PuE~&O-I8ruN_u4?RGIHex(eqWH1lTkGY8WoXq#Pneh)tYw0$6|7C6i>D`~ zi;bf!Q5jqPWAjkQVi`jS%T2=Mj-*rXA;+e1(z4}c+`_qp$_^I;JXCh+Bs1?T zwDcJ7TJ3JXEJ~Tl=qZxf?Qb#T!4zJkNA9u>Ggj3sF9gs|M$^@JBD>!T{8sTEmwO(j zy0qe0qQd4w>0C^9(e2*9#n&}77UZyWeh2GZwdlsOw2kRibiNb1@z2H&6Zopw#d+cz zorM1Ys!7-aIpFjDaa;}Fxp_Q{Zf@PdIm0$j=Sy}7K2ZDFs6NLOu35nZ4oL4&hr`pu zyTuh&wCe6#xA6tMBnDg@^(VDn8r`emmGE)N^{hE8QKBAF9m1hV_kQUSgLbc47}+Ie zaY~A8=~ng^Ln1npo&_u2u|TT8lkd{7QaNHk$2kMNLmk}fFJu3(MLhVNV=L5AmJ$#82Z6iN;o|SRL!SyB6k~a#vjiUr-y>s6d zbkVE$7WT$;>k%OOW1s0)M~KlFDOSNfjZWIGn|%vIG295j3_DeOSV`XD%PVYoSL~sA zc)DHwldq^I8Fs?Fle5(1amhSapm>cmO-dOwt34@acE~wi1#Ea{!=4k;1owJkKp~Y-cB(lp=WQIh{s*%GvB3q^lqt;S0ME`rD>yN z+R*}}^~Gl@DYBO_^1ikEKKv$@(JVi+XR;&&R(Ody`uDD0`}RTb=Am@9mU{Zh86#+R z3RCbVzQvzL({BM=t7IUaK^ z(DeyzU5-zdai2=fyYQ#Qi#bTp{8^RSPRT&S9Pl{@ABATsZ32_*dPA&t1nn5bM({Mp zVFwHC*0?Kg6Z}@uphVR4I4%kT9pPfTy$>YSt8a~qY=mpx9l5t;C0lCl41JAc;@NjQ zHh~l6RLRFQk=w?3C_&9)X}=YG6{(<+brBXvD=;d5TGzDkH;1oa5?Ja`NUXV1l7pID zvSYeKuNxZy8Y45Cay+`Nl^iB z_OnP8#^S0y!KimBSgkT_k18@xdZ{eZ#g>O5v(#0`N!1HKEAA?zrt{?!!99qj&ou3D zNmzZhwW`1riHiZ(HGbd5(u4^-ARP09S&mf!U6~5JFb}P2s!A@*mlX9n z$b4g_N~@RJLB};-9OnSj1=ZXP#w(T^dSKS7rlfM7o*j0E zZh7Mr@HdcI@V?dO7G5{iZ1Ngn;}`*rYS{cqg;7QFV3W=bQj%|RH0*sL`!@Ka!G0Xn zFAs?Ap$#-?<<8M$p&Pxp&PV<8RKI9j{{R8%9wGkI@WsF;Sbu!6##KXZ>z`a2@(l~( z9-k-AYk9PvQ;M;1t^K*neW*A+x7S+4LNK+CWky`rxhq_fFmaC6Q&iA2ZFbg8KUveE zxPnC@NTxu_!_b4lq&Et(1U!@IdQ+a`YkusUpIYQ{Tb(K_^Pdxb%)SrQCR?uy+)ty= z3xdP?uKtM&Wp=b5`7Hp0_;vPW__v>p0zfd#B5#x=Xf0EKRjLWSk6s zTvunL_`}0qAc8scy=vZNk|6Q4QicQ`gk!BUT=4gXylba6mEtWP8@L?&(9aNMKKM1k zYySYVHki7%{3Lz{)~C{L79for4BK5tLCN3)jyhI6@a$8G>0tSh;J7&VHE&IK3gDmv zX~6s|#m=MqL3j%CGc~jtuAYnKmr|<79bAHU4*X>PJu9y8zsAicQC5dqw3@;|gg=^` zXWE*CWvXK4Xw`i_A1Mn07{)S5thftFMmy zDKj&r=gZKOfz5uG8WmI39~AKvTG66emRT)}Mh;K5YCB77z}R^oBe)bVihMC5?0roJ zNXN`7W$_1xUCeg+%q#~{=8ivFrB1Y7%$HV-`wZK89He=tcV@*%FSRHfLT(P?-9=3e z#*=cu{{U&k!TJFpt0uz1qy*0y3Oa`dwo<5xY7c7>om)_hZFb4e-UgoryE@1N{M&l- z)}->SqXia38U8GaXZBX<14S~N_2!$aQEX2oH@Pf+E0s=6Curb%RPlJtvAN>F2dSzu zX~AP~&5{p5X{n?msSPe2bQw1sMqa$P!o4S)DeEuF)d!5PMCc>GUb*C9c`!QEW^ znrbY5R4IX;b4^_>t-*J3(<6@cO0y@}#hqMUBhs2uf^oPHn~s$4?Yk*ki=aF870Jb9 z@kGr<`evXkYN_pUHUaH+m9 z!1W_MREB*)V^vuK2E)!I7*nkEgF{HY6$LXJJ_k+#0numGKp8L39MsUQn3 zKvCBis#WP*QTrOH=yeWa@^Vxhp2DGPJ4XA~>w-GhJUmZua&X;pqZL2=B~I!Qlb*OM zQmRp7bn6;#;ms-X?_`a*{{VNI%x{L?6}Wa2X>okVJS|HXjG`qG*Pl#O@p!h?{mb631_iByDgM2%5a@u@ncl#rXiRRLIQMOhlD3yE<}Jz`j-iD}wy~hZWD-vt*ERnD3eQzn&98{ABgfst zQ{TdVIkkb7!^Bb+3PQVMBl8u_ET*E_nyh?Y=;&I~Q6XSIDp<6&E^Z`HPip4jKNEDc zQ6Y-&YGK+|Ib-X_255`M9yYUVUg!$QPw?cL=AK_(Ch^76XGcA%g#Zq7#X$Bd6k$MO zc{Pjw01GDSCSj=fdR6C*icb|`J|$=#SZS?iUr^B;iszOZvU?h;)ZbGX*q!S;N7+ekGW_S$^Q zx?6NTfW>oX#Fq&9+mHt}W)BwH{Jvq%4=YX7iv<_ZlKa3O7}n$_?@3MVz+@QyRjc98 z*ne60kA9kmge+yY2#kxUtl@l;ah&YVnB>D_{ zR}&tg@ry&1+Tz`BBRD27R}1V92lKCU_}TF?UmkeE=Uz9?@PXx8KyirBV4tZZcdi)R z#Qy*==RJL@D{{A?wG`BKICS{6u3O5mYhDkzj17fRwP##gu#?V^w_Zl>D_zC9;g=z?&T64}rIDBtKp4g;`!t=yn4*(O zZp_ilK?96QOt$fUx2DX-E0-!drH2;Bgrci9P-RLs!rRI_1NFG z_|*Dh887(*t2JzB-yJ+9t43v)RE|B1xyv>&Upn}+#ggk+Pi+K+B1R}S{{R=|SP2c@ zmoaFIvNkt?#~pjr&TzGvaf?3V@TbJ@0O}tPuk7_*E6>%Q`G2zY7$0iAyYrU$$4rrq z_#9N;Eb(TUsd!*`cE-Zl zp4a2gjI`xPR4xMmcY0R}!BeSIoi=oRW>JSNkE8VKyQpDRxC*X5@f9?>vxyGLbCF&p zrGCg1q?Y;oFM{Y+69X#-ug}Z^YE_d~eaDi4tkl zB7wBC{eA29s<@hWT&Vn-o(iWc=4V|m!e0l@;%Mvu0Z0l5A6}INzXp6EDx|U7d2(Ro zm9d=F4Ljqfhh$TmwA#E6oO@NN`wVXVs!nC0aPalMc6AAfq)wD_&z8IZ>%`Y8vGm~&I7#19Nh zKb7|Q&m4T?iof=Ey^P#3%Vy4UPldiEm6*fg$wMx7hU9%aestR(1AIz_l+UimyU1cy zWo8QffFul$em<4fpBH#@<&rH%K2JQ=gz+wb?p<{#&U$lA)5AZqjIWrktm5GCx5WEs z1lJdEy}?jqRg|*s?}LGn?}1Z6AH_5~9?k+n^R`2e!!_CsV@j0%<4{H*bAv)%S-A67 z=}u}suZ5S{MynN=Q|iu1=JEZsYVD*)Cp|-)pTeV?RPk#vJ;s8?7;gDNCmHTLS8D?a zGQvP|J!)i!a{S>z`qpm+h3smxEOErYif)mD+-S273CEOA6obWQQ#p-hD;~g4E!j^SDg+KcA zI{{${+T4#UuPK)9r17 zM{_q!GZq;?kgTPZ#b~5;!#JFk`E)BSrKpy7+L7(mQ*!WGtCSj! zyKfsw9=NU>qOjJ?kGbJ=h&hV#ng$O|$0cQz<8aBRHo+<8X}8%ca~e&Hn&AjZ3G9iX3XtxwR&% ze4{YA7~tg7Bi40w`MmGp=CeQHFVRCMnzE^L{85q3Or9ptB#omNSR{WCtX%8B-YSI6 z2)s>r7_XVYUtYB}uZeDAVkc3IaCod_);vDQ3^$5TY}BJx((Y3N?Fe2E%qtg(tc{f# zMzZ*~?A%Cz5_lX_-^GddO5mPzShI^p3o2ZpB=9pt;u#r2I&M+U4Px=tW4UV!PE6<` z@hz!brz8$(S6hL`B9siCRM$Lh)UhU9@yJ%|Ni11)2_YEmlUV-%Y0t5*)S%9$9Y)lg z8CN}NMg6N2Fg0c!~fP+r)Eq>gP1}@lgOMLbyLQJ|7sw>cnxh^H|EQ2^y+%L`K`kHc7S( zNJuSSO|XsQ#e{vx_~zr&Y@al6@*{8<$!)^vM>Q5D>HJq~eDTxq&2 z=woY0@Osrr{2!rRD(;UM{^70{PB+l&=4Q%0gDzvcMn1%IMClg5Qbqp&XlA+T{2^(L z_P5f;M?kD<6!50EY89>Z=}zOwbDCU(<~koG04^{X`_vb3A21vqaDJ7Kabx2PM*=(b zaC#Cci>r9T+C7HKIXS^O>r?E*nA>Yt10}a)WRXz|WeJ}w=R6Nu$!`+)hTQ{PXyo&P z6y~Fk$1A^N))GbsUC2!-DGun_c@$t|f!FC%TI!ef*f#UHRUW6B!JEZ;Y>|ADlqWq< z)9n01rb!p?E|g^S&N2DYyweLsnpZv`)LqPmcICMQ)qnU(wOc6(R@{XAywz6KwE2E$ zZV`hX21gXvduL^f%mg3yx>lEM1(Bf#jqgO5ka5+3Ju1oghi3$4S-?;^v#$w$o>CDMlZU^X)=*+*ZEFxm$c)@TBq;j{Om_^KNRt2aWVQ z^z&`C2-st@3i(C|uANNJcvYl44EC##>KeY3xU{~I{{XVBRm_?dne|+H-Gr_O+E9#o z&~G4fwk!}&Iq6?9S$NaMk$l#=gT8wc(zWgWF8H@iOk7M)BLao6k9XCrbX%s`acG3F z#uQdH_k#RAD(?FzR_s>1${&uJtT!tR@bBICy+N&e4~?*0A0k+eTaTfml?>?hF9A&& zsnhkTVlB=Uvx==Ik>hP9GxkkXO^$*=R8!);oNTbUJI74b4NK!ec`kQ@8Ibg-U*bizv~0Kb6G9a7#Sb;kOYvV)y17^iswwZ+HJz;Z-u7Mb z$bo|=%f@s5b4j((5@%-@#IFimv4i_fe9*rtpIYJkW8(Pr>!!1}l!ZnskUEZ?tCrMk z-u~z9Nop2Nz~x3deJe)J*%|{Zt^+9K4)q+WPUT;etz&MMPqZfRSdbf+_d7{DScd+UyP@hg z;vn}ot|Me6$$So({*{Gpf<^NZ433I1!L7|Cx~ADcA1BI+oQh8U0V9Hv`tfa{xw$x4 z(Ly$P$I~XOYTEVM%7QRiPd_JaYv>E#*~h}SwvhRwx zEO;F;U$CW3AD6dMOJl{qw=ZGR!!^sGk%mH?VDzi@+Kt+Xw(3$Q6Zo62y?VUgvzC_y zxU~~*UN>ZpqM)DldWKX+j&qbF88p+g(U{s!TApndy>^ouR@9nCBPx6GQy&oO(d_ay ztBu=mLlP^wpWqF|H!UnKti%z!9<@;X0N3rLQnH*Ak3Co_(xf^E`rGJ+Hy!Z9CoC!715-y_-S-Ut{>V*?24v& z)Z>GYDtmw0M#}4wY_;r9%(m_b0u4ec~?=c(Ts%W3{(t z%Y4N3L7tVj;jME~5JuM%u^$eJSxL;_$ohW#I7qs+UIHgb$U< zoN##^y4S^iCHUv@X4_kq$6VDVw{sve$p=Xo3}l=DdSbnG{7uchlUamHu8cuq!|F-SN%gM07GYX{yOGC_%P{bdv`pU9{wet0>qNJ`J}zaz-Laf< z2R-Z3z7u}g9um=@T_?scJkzNIWH@JYk;lz}-`BN#wX07Y2ke%2EX=tI!SDxe-%91R zy*}#PzNE5C9m}!Ig^K~saw%4=7dIAyl?g@(#hkfl7V$07RgC}x zf7jl=Up365gQ%jF&!@|9FA+6$ajciKjK=WqW2TD>Ph{g`}X zt$08F6Dw_A(I7}3Mzxf-_E0*82aboedDgF_OK8exn{G!!`Nw}+@+xOFIXSJN>C?-p zIa=m*_J!f;i6+W3&pBGoe+GC`W+ds!oOANxuE}ll5Z4{}%VQM<)558=-erehp19t4 z-$SWou|`Dy01tdCBYe7gsRM#5J-!-fDy)&SC?_KZw;NEiiAigfJoVpH-&oUMbV+rC z*E_2>n)5A<778&jWcXzSzdSmm$+X}A)fAosxwep)wfV;!bN>L=ttos(ra-v+aU=}z z)l%ohnq=rBX}~$>C#_*D!AnaTtTl=fcwb+FRd_Y_JaLdIhfVR2kb$Zr@xaDARhRK* znzHTtTHtowP``_G@XXQNF8;VJSUgSo8Y*RW{{V#AB3t(^M_-uKQ|n$Ti|1`NHvnTh zs&DvBwA6f=*XHb6qi+~#&AGnS835-Ss~J^`=u(SB5%{yjDurjzSnTG6H&t0YYvJYsH@l2v^UY@3DI!?@A!#N*GUC!?_A#2UJagg8 zmsUxcPBM2P6_q!P{3`OBf3(Gtybdaz&x?E^3hZ+cKDeUjEY6L5RpHq>-zO*TlTI41 zhxeVDgkyKBbgoKGf55jf`OdMZUVZB}_r(4IU|4_;sifKkbJ3u?(`9h+-Xj(tDGWMQ zn+<+lHbz*kxzF&wO7dwuUEw#{uo+dO?u=@c?~E)Vca!@@=|c~chN-@~6>jMEokvri z?R@ihxsUsG%y^^5uy}UR%RJ$nbWq&al-&6DSw#t9t;^RxKc!^qy5;_%IF|N*Ge3B- zCm)3lZos2+b5{7*;|VnvlEuoyoDZ6%UyuGMwRHyLAdYL3c8+*k?5YcH!sno-$pmIa zSm6c1$>N%lXc|2R!}gEy2*94nHj{ylq`%!Ouq1()qBrQL;w;xHH-eJf5cj@}uae7BQh1J=AXG>a5QlVWZJ zWrKC5$88*{&N6UufkKcqW_<%`@n^%At+8&@6&*>b$Buj_beQ{8Wr*qxeEwcNKG@8v z%ui5Su4&$Pl(HTBm>s0{p|xPPr?%YqtHLp;#L<>LeXBb6#9j?n`$UY4y&E0t%il4; z7D-0zKEwFeQlJtPt;EHYJi!7qr7y~XoVkuteEoNLkBJnPzW98mlJE%DyO3aQIXk+mnipC6%RC66Xiz0QRPsnk$GdXSfVy%O0TBfu=!j3cbb) zoaa3$Z|t(aX|@Fzob4Uy5)nB4q9Hq7UNntNGBX9m(i&kkCqNaT^cwjl!p$?Z|c z2~E)u8*$~cO}5>EBu8k^Z*Xkd;aDa}P`u)|G^?oHgIl8j6AV}mxUB0IN157a0<>sA zeDQWq(1t3ygRtjz;g%Wi+-9mv@c#hE4$Udh?YC_t{{W`9-p>P()8F*3 z-s4IOvHbk={2SMquaU{crrbtLd4%rj3!DQ|!KYr$m3eTAI%L-6*Mt5b+sat@a@p4- z0A9K8&+yg1_(VKR(W?zB3UQDoCkOPV=)rVB4EqN^`FPjJ<%XScv&>#{eNXsQpJbhW zc9GZtjB{NqUK8;QZtE73!)s#!i2k(X@UMtsIR46Qr}(#XQ|zhrNY)w77W!2=Z?ar$ zGKl{7KveNhh6y(+JVSooy9utLyg93+XZ|G&PhMN6>r9VC)V$zk(;Z12#&i1AdkSyt zoBsf8VblI9Irg`aRax!#4^4-ySGuv9UCAA$26;P3uCiMxqfi@8m+x_eC;HQTnJxnb z(&a)paPbk(=g-ts{azRNO_p(n{{Ww;aj?BT zX_s0o7U;8EsN6?5+9^v0)NOWDGdeC;y8F);@dv`)I^OBUy|)12n;mPxemPiJ==$M` z);EkI9I%Xz{{a1Q{zZMa27?Xl!!6WmQGwl(zvEnwj{g8=-vfBc>8@_{_@pErflhy4 zVOn8m!i4WM*kbWtSf-RDzVq|OK?-0jfV8h6AS>(vd4s-fde;WOg%f!v2+siD_ zsR|2@3GQp}4+eh6-UIN>{P%*+2aZrgN+VU+2*xrSnxWzk*pt9|ozcHtG9cTs2u1d; zd_`ImxunxN@Q%G_7)7tV@ITn|;lGF^@o4dC*$9#qK1(Bg*5e=7@~^HeFZ^&{4S6OQ zaZ~&)_$y)I8(6g4D8hhp=V<4e^_?%_>@O1RgXYIvSLRvXVM?|mnIEEMxJlEXlNs>S z_JsJG;7OcglD6h=xzlv+8p@n4HxSKX?(ZQS7X z6&v`k#bCLP`Nu{k&+H0!HKn$ye&bLX54;Y6#ExI48AR~e?SZ9_|y^y&4bCTshN zFnSV6re54?SX75m>UipSsfC^7?iS_ngkeT$Zfw5Do=l9tFv{TaD;EhjxuR;smbcFZ zyM3ZU%&W$IYLeYtNj6!VAn@C`0-tWI$UtJuPD<|o02*LahzQt`xrjTlPhM*=bP1%9 zW;am=W*rDTW}=enX=LAUry%eF>r%qoWig`-ig@{H_o%@`0foi`ZR=LpinlWA7cwA; z_C?XMI{sAq$aY2xVO7s=)TYjO)no^DPp&X2(IP67EQF}_Y>d=$%HwTVWvp^a46#TG zfJS?oWXAg8Q4pYsN6nNZ)r({jE2MvW*y94K-aXB{%!r$?e(Id&oR>i+Ox6go=gi4r z$?1xY;@v?->K}m0z|_eiNo>$u1G&fD$3anBxPn7$u`mnwayom_$=G*DY-w%_MD4Jy zOJ%c~b%oko&RQ7xP770}ibI#kU_S8&tv1rw>@N`8midpVrlQcBzN7CgrSroRgUJLB z)`@LPLavOh&(3jIK50L6_!|Z~^{9)XkXuBj1E|GSg>)s+(vs=nhy!ZaD!{rhqS^}VKoU6^n{O}!fCWy{7qocNEo; zZlqR(Z5igBHQA2sU|5Dv-E3zRtzqs-G_4(=Wwd8-eq~cjD{2z35I`dY3~r^kV+mBY zIcFT7dTLEHP4;$goUb|ULqMI&7Vq|TA8GyOI+}v+BDafm6SD4H6wOI(2a_AeIV87X zLPqgSnL^=*B=)CdE3ih67=A_0;etq{WPzgygDS1_b5h+QXu@0PhWW-gs`hCKo=Bv* z3%Go#+|p_}=NNU6MSkp=?)+xu>j- zBPanS*E^~!SGb->Nn_v+6pkuOb!80GO_nDZ+ePjsn2@AJytrc8-^AIbPYz}(vN4+(CxwRRd-<}c0j9b%Md|c?Mh<3v|Z5RK*!}if}@Jj zWnv_oEI4(~6>Lf(gsyO>|F=gj)IvPX)an4 zau<~&pfs;Es7y%xMh+=9tTZxZX1W{Ehywuh2AAzoTRNoC1~13ctv+dB7O3(uB~3vP zyP3_~z(`ya^r>yDXf%;BMRXx()eB_sNbOqQ9Ro~P&>Vn6K5Vpj*q6;X3KCCCS+<4RnRFJhAnrtPv{kgY&0ydeOKVdJoQv%eW_Dk7;VmcS0~aQYN2fxY-H-It)~bKsa>-;({^I0qsf3OQ~ADMzw{T zIAH>fpn=CqXw&QpfbfDx0OF*N1?{-xG0EBx<$z-yO5_>Hqo*&Ys0cEm`g%|*@O1c3Zai38` zGcmveuO^?gpK#cso)yqsE1fIa~$a!%ek zrsVC&9QUgB)jN`%j9C61_)gp~gGGT$ed4K%@sH)jMIXaI3L}P1A|(qMKov2CBLs2V z9Adf@lOHZlNar-YJ^k}Xx2U?C$5WV(;WvUIg)JfQ{jxx~+X_d8;N)@bQfi(N(R8gc z80{@~Aasl>4Dd)EhZWGa@W6)S9P?4?HZkfJvB2xNdCG7-h(3n7@fBq%Z<(J%!__MP z0BA-joY#l+K{lb~g(P*r_bu;UtKn|~NpTVxlWLyeVAe;4d_4qrih?}g0(tjudi8Av z$~dA?x1jA`iD$K1#x)cAS1yh4@od9?hPEd6$l1w6taV6c}w2cZ~e^IycB1{D=IppAeq*o&s#61dYwy|}QSraZ@4mx|)`zfg2!c`*P<+h4z zsry*A=klG5O9eEhq)tH~VuJl0XPjt+ZP5vON% zXytTNjbm0DfDgL|Wkw;6HY;#5hWSAqYEvJZA(}swXYU$oJkPaAU4Z@Ua!oMkRkngi z_YlAk$8zJXIXuhK!e{%Zg~v*r0`BrAjH|KEalxtD)-+P^mB1Ne=xSuO1$KxcnO7_2 zV;mA{q>)@tcJM~3vEUq&)~`Hq$r|ik;Eb`|gPM-w*`l`$qa5eo6?-vRv_T$i{{YoE z_sOR~T2~J2c|2ftrdvmCa9!LILBRy}t6GZ58Z1^Y02B|K6r1W6(2iLWIXu!C*mNF( znPn-|2}zZeixIm3aZxiuSd%DvGJ4QIA*&R2gvTK#AdCPy)HcRd z49*En-*AqVJl4-60?fHyppI!^w3Z?oTr!?VG_1gA`!w=pWh&ruGg7pcilIvrAsiJn z)P^ftv9Rt|1eWwPrp+#<`$;86ae+i`_Xg}o6c8-UDV#KfXP(BM%mXZhAS83gTACYJ z9J(UlllQ4s(W4xY{ebkVvL@`VM2{YAqTPF_g~98Nw9G*FVPsr05t0u|UDMmh49$frz&$DcSe?A| znRhSnlZs7^BFxQi0}#)WdkTqKc1Ce-S83p}ra>Ajm$+ihyMnY{#~^YY9}GTRQD*fE zrJzLb_E!;3tV>{$y($E^lgup|t4Iz5h0irSQ*A45q^{ABDbOlL#Kz+;a@8+ZG%_o4 zZZUAgpMI228hMKxaf6Pn-ml3FN(g1-rr_SSN@m*1PzK%ASFJmwg=>p6K?t{wZ@e=3 z9VwO%dbf=rIaT9vsU#38g6_bczgm{gG%(71+%pabwOT~BM>W`q*~VbJEMg`}AmdjL;H9DWqF zxF(6CbqLC%1*=y|AjW*grZ8!zaaqT4!I+Ve#VI^z z&~>B*N{yf%J!x^3Ag(@?bss>CE;oA8w%yoV`tm8HVSZ26fg@32UfK>ACqC5V^amoN z5AuWSN;0PdjyqClX^-CG?(&PeUjg8ACeat0$S#~!qKZVvY6C%qsDaLR*@2&FBtvY>u64O^%%8?%59(v9bD z3I-{B$B|Az$JUwk=bX~@HI2Fn&JGEy+FU+liaMRc`c*W^IRn2np`nns0D-_fewEFO zf4XPTaOJ2&14&f*5mA-^f}%G03X1-4-Brq`R9aYs-_mI?}T+wb)ir#fM7sj~Qt~ zM3ZEBAR6>-T0#N(S0As4*f#IdwxK4O6&241@qU0zuAWv8JuA(;SK;~Me?B<35!~0g z_}flbmG%w~rFo}`w7C?Q&1d1w#g3AZ#V+XBGp0rrm59gC5%|~1H-8VlAZXg<&Hb*Q1<0QwMA?Ed>G@aN zzZq_BG|vvTv}v@J{vOry-1j==)%4ERuNYjAO8x4()nyp+g$O69^QNnB;#*IM*0XA2 zO*+|Q+Cs=evB>u0y?P&pyiI%~T`O0TGR#iL5@#dQx*rzkI(LdRwwn6ftAm9=pEY^Z zR*k3liM%x>n|Y88_R>CbMRRlW#@0Hyd0FT%GKlstAO`fQZmnF#CPlypj%ufdFD@^1 z-P1>g2OluST)0y+DGqQCBeiGCXQ^sh5sQC1Rk*ogO0Pjn3P$YGNbD1D88qGgUj6(& zZ~(L26mB*)HSH@p;>M%?d3=|k{q0{?N6K{Vm~#TCzGDk^o`bcdE*5$ z@?=wHfriFAa!zr&n^pwd&}v#l5Q|3*yQn>l7Vu5xv^P>7oD9_8XN_HCSHly|ItqJR z+a$hllb-MDXtl!jE5~mH8AoG<=O_77McvGZqSg?M8$CN!nP6!?b1Lk{dU9!zFf3(| z?Aga1Dq2lgtBi$Y%S$r-=JdvDNn;WrWNd95FRe(*rXeCe@DHyTs3g63u7p?zCm~lI zIsX6(E}|`1#Z9cL#Dk7-c&Vn9AeuE+Vx;qdQ@5C9Q3M00IUQyVH40WpaSJ$#! z`2=M^8*xmE+EEyo%2b|6W7>xT9kMfLE%&Ln&@|k!6pHBPc<@NZ7p+0I>SX=I18i;g zoK*5$fg-$7DLp=3^w^&1B|FrJ+o&A{OM;NpoJ&^0ij|WGE5-#wEbv>rY#=8m1ZTA( zxJA!H9~)^GahOc1NiFHxo2Hm^63G>;=WE7Px82Wbjvdil2oR}O`S* zWa$;i5`pbiVs1H*+sMe|Gd}=lr9l*kjkbF-9DTw%QLI`Sr44TEK5XS&iY)I{!L(>{ z!-J4>Qtxr-ke0GbcwRShpqv3prdwcRMb6X6W5E>Wib+V0ID!oGgG^M0G?F*R-T*UE zs4Ek~je9tedSjLB4HpeGcJd9NlhD*j9ppux0s;~+$|+%MyM<+vAbxJ7P{9z}!@RW2 z<;Y%8Q|)dbNz8M^BS5^fVu)d#WRlX`90E=ky-I^>Aez}sfOEU0L%f~QS4(javOn%0 zKK;%+$E{pPDUwiOtVO=VhRAu6VjHVL$2N%bC&>y9Ac|Niiq=M zkVoCkL~j1gAxofJCn<#E6>7xCI-8gzS$O+{wL9E4E61dVlkIUlkH%M~KU&|?rgLUX zTd_DQ1_n5)Hj=?C4{aV|m(sNK9pPThc7;XG=O25Di%C1&u4K=?7kcSd>>Gm$@DH_A zX%&fP88vBSCrY;jf6FEQRZX^q&e77pXX<|>%b>==$papg(9BLZXCAcvqwjOvQxswG zo~N3%v4r;=vS4KtQ-}@=W2wy^P*39P*P23k#(2-IEiPJ4+KojD*k9J1LiOBpj+BHb zZOhzKRTPd-H1{KCu^>3$frCgR3NQvwts;ZecI{70F&R*M;*-#%xt^jbkZ|J|?MiXM zT32F7KDeaX&B7q->qWuGTOceKsLeRCFyb-wq;H)3!?g-QTn^ppMy`b!2PgT`1}@mg z=4cq@kF6>Yt&(%=K-S_i>^U3?c2R&OMG~*%d(uP%pC)>BptO>efmkmC)22A2$YaOp zQaDl6{#3+8Ly-MxT-7GD7z+dUdiJdyALS(Rp4|N^hdIq$(}@`b_5T3tRv49fO!xSD z(afRhZ>`~q;Rf-_is-bP!of~|AzXXRP11~>6kwmmxAd99fCJa#In6)zsd}H&7#Sx* zCsPf}AHa8~$s;(z^T(x7www??YMJFY`@nI2+Ak z<(oZgo7G~-E1%N3XxPqd;e1Y{$jz{jM_SkR2QM#0>1&y++^?4|4oaT+;O4%c zlamalwmc41D()|Ge~UjAEj6gTt0}>F+xLl_U{{l9zY#9Aje6@yme2-Lb}>DwjSCpx@d1;tlV_9WLipo;3<2 zI0`yfq7xjkZdTfJka1pB`yuG}dPl?m0JY7zjO~&L?OwMQ_8wS|Y7X_KO(kPE>Wa4L zCw2xgoc-fhhMQ}35NUwiypGjgHBmdfN-{?PnvzG#0;QCbh6lAqgS#qRNt5M90mmIW zQzbAYp;7~r)v;C>qyu1!d*i4yTu1>_elou>#XT5oM;uG`Gb0V8oB+qStt>G_!BO7; z4uYk(k{MGGIlveL9csMnvCLLalmWr@G>|r!G%;b=p*TM%%{pXOwfSStd1a=e?qD0{ zAKn!*TeHi(rrHPafzD|(II;*Lb%cZkcm37JN>YL*^JGxc4ulG_>Wv6g1TvlpIH+yl zoZJx65Ho^(Xo3u+91H_g!YsGT7~f_XqL ze($9;Cbb^kTiga|ih;s_I?_!P0erwq9-DJhv^MK1ub41RGV*&F0V>-_7}_z-5^=DS zcM>Qk`C4UApkyv7*H9_BGw&ucmR^?NLC| zMavFY;Npvx73+?a zvHg&2n9U0XhXgirnrk9YZl?ga9R(z9Kbs^kkf8ozi)ahnFzAQ4 zG=p|dE@g`r(*d*&c8aRgk#;|L%Nq5oj1n1$MDq}zPDMdAf_cX2m?JUbJkz+6)R;>u zFWRk1yMygahjX~MOKhBAJ5{!}ClHwxK60_tExD^e}tQObCaKV8Y+7BX=PraS)8r^Nck3TaJNsO@^*79N}Do9*yBA|jR zO*EE>n2Q{cqM0p&!F+BmXB%6f+HwAQt8$f<5hP_hPC@k)CfWxSg!^oAT<(H1y_beP z>q|#@8aEd)l2mn5&{i@ZGUGOhz&I_Ag0(E}ZIxdW7Ep(ABAF|5^a&81BH7r3m{+N) zGA<&JanqEV2(#x{h4lmB~HyEG*UkC$fXglP2GLPHF#_hnlP#l z9sMeZvas+J0JzQvdTV#!4)iA0IZ^r25?iUIVAY|@RDjRkoFf?Fx>RbLj?v9Hql|_8 zXbn=;4i2lFkEJY3rHd6E4>aAUjGWSyDbNa96r6yV#@(R(F;Xkw{NK)_Q=hs&F-{

3q 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 GvH#ifP8$0F diff --git a/doc/tutorials/bioinspired/retina_model/retina_model.rst b/doc/tutorials/bioinspired/retina_model/retina_model.rst deleted file mode 100644 index e8527ee8b..000000000 --- a/doc/tutorials/bioinspired/retina_model/retina_model.rst +++ /dev/null @@ -1,418 +0,0 @@ -.. _Retina_Model: - -Discovering the human retina and its use for image processing -************************************************************* - -Goal -===== - -I present here a model of human retina that shows some interesting properties for image preprocessing and enhancement. -In this tutorial you will learn how to: - -.. container:: enumeratevisibleitemswithsquare - - + discover the main two channels outing from your retina - - + see the basics to use the retina model - - + discover some parameters tweaks - - -General overview -================ - -The proposed model originates from Jeanny Herault's research [herault2010]_ at `Gipsa `_. It is involved in image processing applications with `Listic `_ (code maintainer and user) lab. This is not a complete model but it already present interesting properties that can be involved for enhanced image processing experience. The model allows the following human retina properties to be used : - -* spectral whitening that has 3 important effects: high spatio-temporal frequency signals canceling (noise), mid-frequencies details enhancement and low frequencies luminance energy reduction. This *all in one* property directly allows visual signals cleaning of classical undesired distortions introduced by image sensors and input luminance range. - -* local logarithmic luminance compression allows details to be enhanced even in low light conditions. - -* decorrelation of the details information (Parvocellular output channel) and transient information (events, motion made available at the Magnocellular output channel). - -The first two points are illustrated below : - -In the figure below, the OpenEXR image sample *CrissyField.exr*, a High Dynamic Range image is shown. In order to make it visible on this web-page, the original input image is linearly rescaled to the classical image luminance range [0-255] and is converted to 8bit/channel format. Such strong conversion hides many details because of too strong local contrasts. Furthermore, noise energy is also strong and pollutes visual information. - -.. image:: images/retina_TreeHdr_small.jpg - :alt: A High dynamic range image linearly rescaled within range [0-255]. - :align: center - -In the following image, applying the ideas proposed in [benoit2010]_, as your retina does, local luminance adaptation, spatial noise removal and spectral whitening work together and transmit accurate information on lower range 8bit data channels. On this picture, noise in significantly removed, local details hidden by strong luminance contrasts are enhanced. Output image keeps its naturalness and visual content is enhanced. Color processing is based on the color multiplexing/demultiplexing method proposed in [chaix2007]_. - -.. image:: images/retina_TreeHdr_retina.jpg - :alt: A High dynamic range image compressed within range [0-255] using the retina. - :align: center - - -*Note :* image sample can be downloaded from the `OpenEXR website `_. Regarding this demonstration, before retina processing, input image has been linearly rescaled within 0-255 keeping its channels float format. 5% of its histogram ends has been cut (mostly removes wrong HDR pixels). Check out the sample *opencv/samples/cpp/OpenEXRimages_HighDynamicRange_Retina_toneMapping.cpp* for similar processing. The following demonstration will only consider classical 8bit/channel images. - -The retina model output channels -================================ - -The retina model presents two outputs that benefit from the above cited behaviors. - -* The first one is called the Parvocellular channel. It is mainly active in the foveal retina area (high resolution central vision with color sensitive photo-receptors), its aim is to provide accurate color vision for visual details remaining static on the retina. On the other hand objects moving on the retina projection are blurred. - -* The second well known channel is the Magnocellular channel. It is mainly active in the retina peripheral vision and send signals related to change events (motion, transient events, etc.). These outing signals also help visual system to focus/center retina on 'transient'/moving areas for more detailed analysis thus improving visual scene context and object classification. - -**NOTE :** regarding the proposed model, contrary to the real retina, we apply these two channels on the entire input images using the same resolution. This allows enhanced visual details and motion information to be extracted on all the considered images... but remember, that these two channels are complementary. For example, if Magnocellular channel gives strong energy in an area, then, the Parvocellular channel is certainly blurred there since there is a transient event. - -As an illustration, we apply in the following the retina model on a webcam video stream of a dark visual scene. In this visual scene, captured in an amphitheater of the university, some students are moving while talking to the teacher. - -In this video sequence, because of the dark ambiance, signal to noise ratio is low and color artifacts are present on visual features edges because of the low quality image capture tool-chain. - -.. image:: images/studentsSample_input.jpg - :alt: an input video stream extract sample - :align: center - -Below is shown the retina foveal vision applied on the entire image. In the used retina configuration, global luminance is preserved and local contrasts are enhanced. Also, signal to noise ratio is improved : since high frequency spatio-temporal noise is reduced, enhanced details are not corrupted by any enhanced noise. - -.. image:: images/studentsSample_parvo.jpg - :alt: the retina Parvocellular output. Enhanced details, luminance adaptation and noise removal. A processing tool for image analysis. - :align: center - -Below is the output of the Magnocellular output of the retina model. Its signals are strong where transient events occur. Here, a student is moving at the bottom of the image thus generating high energy. The remaining of the image is static however, it is corrupted by a strong noise. Here, the retina filters out most of the noise thus generating low false motion area 'alarms'. This channel can be used as a transient/moving areas detector : it would provide relevant information for a low cost segmentation tool that would highlight areas in which an event is occurring. - -.. image:: images/studentsSample_magno.jpg - :alt: the retina Magnocellular output. Enhanced transient signals (motion, etc.). A preprocessing tool for event detection. - :align: center - -Retina use case -=============== - -This model can be used basically for spatio-temporal video effects but also in the aim of : - -* performing texture analysis with enhanced signal to noise ratio and enhanced details robust against input images luminance ranges (check out the Parvocellular retina channel output) - -* performing motion analysis also taking benefit of the previously cited properties. - -Literature -========== -For more information, refer to the following papers : - -.. [benoit2010] Benoit A., Caplier A., Durette B., Herault, J., "Using Human Visual System Modeling For Bio-Inspired Low Level Image Processing", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773. DOI - -* Please have a look at the reference work of Jeanny Herault that you can read in his book : - -.. [herault2010] Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. - -This retina filter code includes the research contributions of phd/research collegues from which code has been redrawn by the author : - -* take a look at the *retinacolor.hpp* module to discover Brice Chaix de Lavarene phD color mosaicing/demosaicing and his reference paper: - -.. [chaix2007] B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 - -* take a look at *imagelogpolprojection.hpp* to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. More informations in the above cited Jeanny Heraults's book. - -Code tutorial -============= - -Please refer to the original tutorial source code in file *opencv_folder/samples/cpp/tutorial_code/bioinspired/retina_tutorial.cpp*. - -**Note :** do not forget that the retina model is included in the following namespace : *cv::bioinspired*. - -To compile it, assuming OpenCV is correctly installed, use the following command. It requires the opencv_core *(cv::Mat and friends objects management)*, opencv_highgui *(display and image/video read)* and opencv_bioinspired *(Retina description)* libraries to compile. - -.. code-block:: cpp - - // compile - gcc retina_tutorial.cpp -o Retina_tuto -lopencv_core -lopencv_highgui -lopencv_bioinspired - - // Run commands : add 'log' as a last parameter to apply a spatial log sampling (simulates retina sampling) - // run on webcam - ./Retina_tuto -video - // run on video file - ./Retina_tuto -video myVideo.avi - // run on an image - ./Retina_tuto -image myPicture.jpg - // run on an image with log sampling - ./Retina_tuto -image myPicture.jpg log - -Here is a code explanation : - -Retina definition is present in the bioinspired package and a simple include allows to use it. You can rather use the specific header : *opencv2/bioinspired.hpp* if you prefer but then include the other required openv modules : *opencv2/core.hpp* and *opencv2/highgui.hpp* - -.. code-block:: cpp - - #include "opencv2/opencv.hpp" - -Provide user some hints to run the program with a help function - -.. code-block:: cpp - - // the help procedure - static void help(std::string errorMessage) - { - std::cout<<"Program init error : "< you can use this to fine tune parameters and load them if you save to file 'RetinaSpecificParameters.xml'"<= 3) - { - std::cout<<"RetinaDemo: processing image "<>inputFrame; - }else - { - // bad command parameter - help("bad command parameter"); - return -1; - } - -Once all input parameters are processed, a first image should have been loaded, if not, display error and stop program : - -.. code-block:: cpp - - if (inputFrame.empty()) - { - help("Input media could not be loaded, aborting"); - return -1; - } - -Now, everything is ready to run the retina model. I propose here to allocate a retina instance and to manage the eventual log sampling option. The Retina constructor expects at least a cv::Size object that shows the input data size that will have to be managed. One can activate other options such as color and its related color multiplexing strategy (here Bayer multiplexing is chosen using *enum cv::bioinspired::RETINA_COLOR_BAYER*). If using log sampling, the image reduction factor (smaller output images) and log sampling strengh can be adjusted. - -.. code-block:: cpp - - // pointer to a retina object - cv::Ptr myRetina; - - // if the last parameter is 'log', then activate log sampling (favour foveal vision and subsamples peripheral vision) - if (useLogSampling) - { - myRetina = cv::bioinspired::createRetina(inputFrame.size(), true, cv::bioinspired::RETINA_COLOR_BAYER, true, 2.0, 10.0); - } - else// -> else allocate "classical" retina : - myRetina = cv::bioinspired::createRetina(inputFrame.size()); - -Once done, the proposed code writes a default xml file that contains the default parameters of the retina. This is useful to make your own config using this template. Here generated template xml file is called *RetinaDefaultParameters.xml*. - -.. code-block:: cpp - - // save default retina parameters file in order to let you see this and maybe modify it and reload using method "setup" - myRetina->write("RetinaDefaultParameters.xml"); - -In the following line, the retina attempts to load another xml file called *RetinaSpecificParameters.xml*. If you created it and introduced your own setup, it will be loaded, in the other case, default retina parameters are used. - -.. code-block:: cpp - - // load parameters if file exists - myRetina->setup("RetinaSpecificParameters.xml"); - -It is not required here but just to show it is possible, you can reset the retina buffers to zero to force it to forget past events. - -.. code-block:: cpp - - // reset all retina buffers (imagine you close your eyes for a long time) - myRetina->clearBuffers(); - -Now, it is time to run the retina ! First create some output buffers ready to receive the two retina channels outputs - -.. code-block:: cpp - - // declare retina output buffers - cv::Mat retinaOutput_parvo; - cv::Mat retinaOutput_magno; - -Then, run retina in a loop, load new frames from video sequence if necessary and get retina outputs back to dedicated buffers. - -.. code-block:: cpp - - // processing loop with no stop condition - while(true) - { - // if using video stream, then, grabbing a new frame, else, input remains the same - if (videoCapture.isOpened()) - videoCapture>>inputFrame; - - // run retina filter on the loaded input frame - myRetina->run(inputFrame); - // Retrieve and display retina output - myRetina->getParvo(retinaOutput_parvo); - myRetina->getMagno(retinaOutput_magno); - cv::imshow("retina input", inputFrame); - cv::imshow("Retina Parvo", retinaOutput_parvo); - cv::imshow("Retina Magno", retinaOutput_magno); - cv::waitKey(10); - } - -That's done ! But if you want to secure the system, take care and manage Exceptions. The retina can throw some when it sees irrelevant data (no input frame, wrong setup, etc.). -Then, i recommend to surround all the retina code by a try/catch system like this : - -.. code-block:: cpp - - try{ - // pointer to a retina object - cv::Ptr myRetina; - [---] - // processing loop with no stop condition - while(true) - { - [---] - } - - }catch(cv::Exception e) - { - std::cerr<<"Error using Retina : "< - -Once done open the configuration file *RetinaDefaultParameters.xml* generated by the demo and let's have a look at it. - -.. code-block:: cpp - - - - - 1 - 1 - 7.5e-01 - 9.0e-01 - 5.7e-01 - 0.01 - 0.5 - 7. - 7.5e-01 - - 1 - 0. - 0. - 7. - 2.0e+00 - 9.5e-01 - 0. - 7. - - -Here are some hints but actually, the best parameter setup depends more on what you want to do with the retina rather than the images input that you give to retina. Apart from the more specific case of High Dynamic Range images (HDR) that require more specific setup for specific luminance compression objective, the retina behaviors should be rather stable from content to content. Note that OpenCV is able to manage such HDR format thanks to the OpenEXR images compatibility. - -Then, if the application target requires details enhancement prior to specific image processing, you need to know if mean luminance information is required or not. If not, the the retina can cancel or significantly reduce its energy thus giving more visibility to higher spatial frequency details. - - -Basic parameters ----------------- - -The most simple parameters are the following : - -* **colorMode** : let the retina process color information (if 1) or gray scale images (if 0). In this last case, only the first channel of the input will be processed. - -* **normaliseOutput** : each channel has this parameter, if value is 1, then the considered channel output is rescaled between 0 and 255. Take care in this case at the Magnocellular output level (motion/transient channel detection). Residual noise will also be rescaled ! - -**Note :** using color requires color channels multiplexing/demultipexing which requires more processing. You can expect much faster processing using gray levels : it would require around 30 product per pixel for all the retina processes and it has recently been parallelized for multicore architectures. - -Photo-receptors parameters --------------------------- - -The following parameters act on the entry point of the retina - photo-receptors - and impact all the following processes. These sensors are low pass spatio-temporal filters that smooth temporal and spatial data and also adjust there sensitivity to local luminance thus improving details extraction and high frequency noise canceling. - -* **photoreceptorsLocalAdaptationSensitivity** between 0 and 1. Values close to 1 allow high luminance log compression effect at the photo-receptors level. Values closer to 0 give a more linear sensitivity. Increased alone, it can burn the *Parvo (details channel)* output image. If adjusted in collaboration with **ganglionCellsSensitivity** images can be very contrasted whatever the local luminance there is... at the price of a naturalness decrease. - -* **photoreceptorsTemporalConstant** this setups the temporal constant of the low pass filter effect at the entry of the retina. High value lead to strong temporal smoothing effect : moving objects are blurred and can disappear while static object are favored. But when starting the retina processing, stable state is reached lately. - -* **photoreceptorsSpatialConstant** specifies the spatial constant related to photo-receptors low pass filter effect. This parameters specify the minimum allowed spatial signal period allowed in the following. Typically, this filter should cut high frequency noise. Then a 0 value doesn't cut anything noise while higher values start to cut high spatial frequencies and more and more lower frequencies... Then, do not go to high if you wanna see some details of the input images ! A good compromise for color images is 0.53 since this won't affect too much the color spectrum. Higher values would lead to gray and blurred output images. - -Horizontal cells parameters ---------------------------- - -This parameter set tunes the neural network connected to the photo-receptors, the horizontal cells. It modulates photo-receptors sensitivity and completes the processing for final spectral whitening (part of the spatial band pass effect thus favoring visual details enhancement). - -* **horizontalCellsGain** here is a critical parameter ! If you are not interested by the mean luminance and focus on details enhancement, then, set to zero. But if you want to keep some environment luminance data, let some low spatial frequencies pass into the system and set a higher value (<1). - -* **hcellsTemporalConstant** similar to photo-receptors, this acts on the temporal constant of a low pass temporal filter that smooths input data. Here, a high value generates a high retina after effect while a lower value makes the retina more reactive. This value should be lower than **photoreceptorsTemporalConstant** to limit strong retina after effects. - -* **hcellsSpatialConstant** is the spatial constant of the low pass filter of these cells filter. It specifies the lowest spatial frequency allowed in the following. Visually, a high value leads to very low spatial frequencies processing and leads to salient halo effects. Lower values reduce this effect but the limit is : do not go lower than the value of **photoreceptorsSpatialConstant**. Those 2 parameters actually specify the spatial band-pass of the retina. - -**NOTE** after the processing managed by the previous parameters, input data is cleaned from noise and luminance in already partly enhanced. The following parameters act on the last processing stages of the two outing retina signals. - -Parvo (details channel) dedicated parameter -------------------------------------------- - -* **ganglionCellsSensitivity** specifies the strength of the final local adaptation occurring at the output of this details dedicated channel. Parameter values remain between 0 and 1. Low value tend to give a linear response while higher values enforces the remaining low contrasted areas. - -**Note :** this parameter can correct eventual burned images by favoring low energetic details of the visual scene, even in bright areas. - -IPL Magno (motion/transient channel) parameters ------------------------------------------------ - -Once image information is cleaned, this channel acts as a high pass temporal filter that only selects signals related to transient signals (events, motion, etc.). A low pass spatial filter smooths extracted transient data and a final logarithmic compression enhances low transient events thus enhancing event sensitivity. - -* **parasolCells_beta** generally set to zero, can be considered as an amplifier gain at the entry point of this processing stage. Generally set to 0. - -* **parasolCells_tau** the temporal smoothing effect that can be added - -* **parasolCells_k** the spatial constant of the spatial filtering effect, set it at a high value to favor low spatial frequency signals that are lower subject to residual noise. - -* **amacrinCellsTemporalCutFrequency** specifies the temporal constant of the high pass filter. High values let slow transient events to be selected. - -* **V0CompressionParameter** specifies the strength of the log compression. Similar behaviors to previous description but here it enforces sensitivity of transient events. - -* **localAdaptintegration_tau** generally set to 0, no real use here actually - -* **localAdaptintegration_k** specifies the size of the area on which local adaptation is performed. Low values lead to short range local adaptation (higher sensitivity to noise), high values secure log compression. diff --git a/doc/tutorials/bioinspired/table_of_content_bioinspired/images/retina_TreeHdr_small.jpg b/doc/tutorials/bioinspired/table_of_content_bioinspired/images/retina_TreeHdr_small.jpg deleted file mode 100644 index 4ffb43ec47e421d5f59961dc6704d9407b69a967..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50051 zcmb4qRa6{Zu=Nluc+fCG!wfFL1Hs+h-QC?K5J-SwV940HC0uK70GW zf{KQYf${?LCD!w_z?~yK1d228waWBzMqNCDl{Guw!{5&ms+zB33-!A?5Qtp zJ7t{4(9}r0=PavhZX|MdRqWJ3!am9+!9Qi~WR;N`5f8WP~VYPi>1qm1H40wpO zu#WdAmh&t~B%rHtL5$-Yg$p?5X$Y*C&Y9Ln$(8}RkTq~Pg=+4RF>DgG0OvuiuqIj?n!$8zMcBLcOiK@aA!#o-x(MV0Vy zd2`~pWNa8g>#39Yrx!7!c|7IzIj`1z#wDk`+-Tu@8M8H1P*}1T_o?nEQjKWpkUTH@ z_4o|MOd&VdanQBfRMFHhIC8@x&RM95+W#~YTfrGy{-_=A+)d4NZ94lOKsdxH$HD`C zkr> zQnKOKVg({I=5e>mXCxSWQPo`%{VJ2YzZBZnw_VP+vxS)G9K^d}e^96@sOl2zHo}<3Dx+!tI+RCbW{~96 zjmgq$JV0=ds^+}xP2l5@i%Cpp5Sf`Ie`CK7n$stpfTm&@AR(+FnxL!FVeeNyjE;s7 zdMqsV%`>c_EiZ$Xder{BG-u*p8WaZ6%Tli$eP2r04%uY@ZVuwSx%B)dK5V@Y7necI@}cb4e{D9^~RtN2}Re%=JH4*MI^Walw=SCe#n@samo3{2+|~6B!Q$^ z2JF_F#5>8bqMZX7JFo>&dDXd&j!XpHgic^z$T6$$bgf|8RymbC`X~kC%akt^gxy)y zR4)N7sY`s={t1a*gX04K0AU}3@&;^dhou*#>PH~>A($0BO~3j^AvmdmnnL(qL;nE5 zQ)#v4ibSjYXaT~q1LGn1GOBnC-(Sq zbpR|=l!u_{m4-N%_*X11&XRsaMj{RK5s8E1@g#};2@TG3c`x%Ji|?8F$Nq>m{EWeg zX2L=RY(`}>3`jw)&u(rcHV?1dA z@wO0Hez|_%7$=(M5fcZwkcGiQ>6lyg;3GN%`>Q{^`og|TRzkEDH0)G(? z=R7fD9>jKd^XIu)lpuIiUe#MB`&aSY@{`9gG`Y-rXK$x`WJWxk!DvF9u?h-rd zJ?giw(|j;u`#G$$$k1DwAvA>Q7#<4&HG`BM*#OKvZPAi_Dq2%HO77v>!@#&CsGjAC zUgF1Y5WUCHlZRf}psTQve$vJQC2P`-QaE`NZG`@v|25tfsdwXN^}`?&>6pBxX=@3$ zci`nQ)^?8LQ5+XzCXGzbAc)Zp{mF!_AhRHVV1;{7{0Rt ziA0Qn_@2WO7S-K}An7Crh**Ct_lN*QKP-$TAQbEk`UqPRClINNkORI@>UHUPlr(lH zhjL~6-zAv+WmS=!!Z`xEaQOLiSCW_XzAH8lc_~19|BAKV{->;OP+Xn*v6F|Bu;qAVNyy;@4_R=OC%Bz7i8)AX z)1t1*lXE!cy~5&vP>v2t=LWt;4;TH05`NlH)0VmA7wkJ-aw+5zrs5=&W}j)@%Y75` zWx(T51b!_%JDMp$U&>+UCm7v>-PO!8GqQLRt_S=blhw z6HWRkPXr*S;PSf2>gU03uZBg4%ZvPMj+cq?y=jz*G_F{GQ+w6{?2U#lSy63E3x@q@ zo{e{$&FD}Rfg9QoX0Z)-aJo2#cDn=x;rKGMnHHR!#*z0gbx8%sS_`vd%J)0Mn!`84 zh7x=o1;z375?-#u(lFeJ+g_@%ArQ_)p(oF1*qhcjOfGqc@w7vp(Xv4$N+&jKeJ6u7 z>5Oh8sH?5ET_rb8i+*yKkzZpk%<+2F_Pb)%Upc`ugDjPuSS9((9uW6+3+1%^^j1h_6^m;0Nm^Sou#PKLLlW?6>eVF6K zaU+reUhFk@o4s>Bp$unreB-~og~e7!qh&j@myLJqT-g;%e_dMxzL5X@$VQ>84k{6@ z>9MsGbjv{{Wo2)?1xL*pkhiFt46+gInu~D+xVmF_EM-n~R3c|VxTvoaQw9+=pM`J0 z31NmdGlm^G%9q>s1(!*}x;5@NHao7vEu#7B!EN`t?M@Klk#%@#=)SADV4uu4f#%XL%J{G^(e6O*nf_re6Edbo_dx>3S0Py=OsXLA{Z`;_w@iU$1*m1@-^7UqEMh z3Y6RmWV?FnTj)IYR;Obq&8=Cs6ZQPSes{4Sp$Nl{IoFN%b5VNye})7JRj?^vV>$(B zqrpqMyB`;dbSurx%lzDXdaw(X6C~yC?q)+|&MS&uUvS$v#r|T`T`Dy(9Ky(PU?W`O zN)tcviv|?Vj?1sKD4=#82cl}4Fq8Jr+-Y{&tny12b~aZRlAp7r!c2eK{K`aM zvgtJjFbZ}HH05Pl2`pMY3b7($IO1Fz^4aHdml_L`>U|SSN8EtBa>`jT!xaacy%TrHW>0*&!BW!I^?!?}^Jb8?(F(t0Ts|1n5C=F=eT!ac#)V^Z%i_!WYkW`6WX}=Q zaLXx%2*7inrrv1kFZ6iR$J%8q@(;qu5mo_>*}{=EQ)Zo!*}*gywZFwOfD!^KV680^6? z&Py6K#7*HpKn011X-Io^0UKa@J#g+XP}hvqK>H%okMt}5c8xh_5h~S~!oFS%Fo~iV za@~*f0oI1*3wqGrAZ4~_C(O(+kax}qy$#mzaV6P9&!K$KiI_I1|E#P)?|IHZ_zRM? zaQY9BQMn>#PM?UFc=x$!s3myuTI^jGKmMpM@THzb8zRAM^*c_1QV{xZf#VffF&}Ht zdgC0DsX6EE0#x14Ii$@pn?n6vS5krRmmzg=Oo|rdIch>+LI0MF$7AjYT{ia3n5j22 zeOq1ZiAmHVf0BrM&||`I<$?1>L8DSq!_}P<>(AY_Ksoj0){q{p$c;vVrEHgcx5h`x zQnl3RX{blG*qEb!QXG@aJ*=@CLkNGNB0@8AXOJ(keh`jk{OMQV+$y!i<=xyZyucZQ z#eohlCA+Xw-feF6w*_)=G;91s?H>Tq)gdcdQQWR6J@3h_$k}}X`^(Zhvm(Mak8!G| z(m!sUK_4_` zzl|9Fd>0k{QZ$?(r$F0hOw&Ylor{7_`B=^E+ubzYSbgPIeI_g$t6Zycc6@=!J8HHl z-qRDCDYumDMJ&?~0B)vMYHijwjMV*%nWLx~9_TflHn62B`_@-dSdUErpcRLRAMz8H zryBua0+7t%T+oG~i3)zcingyUDkn?P1ddjXU&>=Z<0v}D+xT8Ns#_$}HMG#6Hy%`- z4|?DGjjK?2CW1ps=w-NFgxWrKkE^gJDgVBvx-jaeD~mXb0Z>8ZuFIDP-hLf;N$)Ra z=GNq>OiA56|3PSxy{Iq!RWJ79Pru~9Keu0D3hvP*)z`MPWNgqzftUn!sXC=ZZ_5qo z`)eh9tG5W+{6iI?FG0Wk%DBx8%h^58zBX9_!cA2%I59)7JTo@z2G0Is {4>dGUz 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 MFcIa(YyX-)haN_EaRCcqDhZUb8Z~&4?*Agj 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 OpenCV 2.4 - - *Author:* |Author_AlexB| - - You will learn how to process images and video streams with a model of retina filter for details enhancement, spatio-temporal noise removal, luminance correction and spatio-temporal events detection. - - =============== ====================================================== - - .. |RetinaDemoImg| image:: images/retina_TreeHdr_small.jpg - :height: 90pt - :width: 90pt - - .. raw:: latex - - \pagebreak - -.. toctree:: - :hidden: - - ../retina_model/retina_model diff --git a/doc/tutorials/bioinspired/table_of_content_bioinspired/table_of_content_bioinspired.rst~ b/doc/tutorials/bioinspired/table_of_content_bioinspired/table_of_content_bioinspired.rst~ deleted file mode 100644 index 61fe06b7c..000000000 --- a/doc/tutorials/bioinspired/table_of_content_bioinspired/table_of_content_bioinspired.rst~ +++ /dev/null @@ -1,36 +0,0 @@ -.. _Table-Of-Content-Contrib: - -*contrib* module. The additional contributions made available ! ----------------------------------------------------------------- - -Here you will learn how to use additional modules of OpenCV defined in the "contrib" module. - - .. include:: ../../definitions/tocDefinitions.rst - -+ - .. tabularcolumns:: m{100pt} m{300pt} - .. cssclass:: toctableopencv - - =============== ====================================================== - |RetinaDemoImg| **Title:** :ref:`Retina_Model` - - *Compatibility:* > OpenCV 2.4 - - *Author:* |Author_AlexB| - - You will learn how to process images and video streams with a model of retina filter for details enhancement, spatio-temporal noise removal, luminance correction and spatio-temporal events detection. - - =============== ====================================================== - - .. |RetinaDemoImg| image:: images/retina_TreeHdr_small.jpg - :height: 90pt - :width: 90pt - - .. raw:: latex - - \pagebreak - -.. toctree:: - :hidden: - - ../retina_model/retina_model diff --git a/doc/tutorials/tutorials.rst b/doc/tutorials/tutorials.rst index 4ce7491ec..8195daf7f 100644 --- a/doc/tutorials/tutorials.rst +++ b/doc/tutorials/tutorials.rst @@ -250,7 +250,6 @@ As always, we would be happy to hear your comments and receive your contribution ml/table_of_content_ml/table_of_content_ml photo/table_of_content_photo/table_of_content_photo gpu/table_of_content_gpu/table_of_content_gpu - bioinspired/table_of_content_bioinspired/table_of_content_bioinspired ios/table_of_content_ios/table_of_content_ios viz/table_of_content_viz/table_of_content_viz general/table_of_content_general/table_of_content_general diff --git a/include/opencv2/opencv.hpp b/include/opencv2/opencv.hpp index 3b96bdd36..020a45373 100644 --- a/include/opencv2/opencv.hpp +++ b/include/opencv2/opencv.hpp @@ -52,7 +52,6 @@ #include "opencv2/calib3d.hpp" #include "opencv2/highgui.hpp" #include "opencv2/contrib.hpp" -#include "opencv2/bioinspired.hpp" #include "opencv2/ml.hpp" #endif diff --git a/modules/bioinspired/CMakeLists.txt b/modules/bioinspired/CMakeLists.txt deleted file mode 100644 index c800d33ff..000000000 --- a/modules/bioinspired/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -set(the_description "Biologically inspired algorithms") -ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef) -ocv_define_module(bioinspired opencv_core OPTIONAL opencv_highgui opencv_ocl) diff --git a/modules/bioinspired/doc/bioinspired.rst b/modules/bioinspired/doc/bioinspired.rst deleted file mode 100644 index 6bffcdcf2..000000000 --- a/modules/bioinspired/doc/bioinspired.rst +++ /dev/null @@ -1,10 +0,0 @@ -******************************************************************** -bioinspired. Biologically inspired vision models and derivated tools -******************************************************************** - -The module provides biological visual systems models (human visual system and others). It also provides derivated objects that take advantage of those bio-inspired models. - -.. toctree:: - :maxdepth: 2 - - Human retina documentation diff --git a/modules/bioinspired/doc/retina/images/retinaInput.jpg b/modules/bioinspired/doc/retina/images/retinaInput.jpg deleted file mode 100644 index d3cdeeecbd3048191f733da0e072891d5ee1e123..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13646 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 diff --git a/modules/bioinspired/doc/retina/images/retinaOutput_default.jpg b/modules/bioinspired/doc/retina/images/retinaOutput_default.jpg deleted file mode 100644 index 0b14a5308f12c9773ba9fa6827b76a2cf5174d5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22461 zcmb5VWk4KFur|8*;)}aG!7V^=ch}(V?iSp2ad&qJ4#C|mf#B{CJUAbD&-w1Xe{aoB zP4`GmPjz?o*3;GR%kNtNkc@=11ONg80wDFV0p3>uq5#N`ECj?q4*8Fuq5g3gXlN*C zSQuE?|8_WdAS@g_94ssl5eSd)k3LdJhzLmkGXI49&!dnqP*5-kaIkRy-SYp7z4rsq zfPhN~At(qm03;d&6dJ_)AbjBuYq#h*E-ti;0ES+enF}f={0Q6GiQ&uJH9?NNZIofE3^e z2XG{>d}DCY2X4GCqfQK@}R4uu)82HGG?A_0GWYMf(0{8q5xO1x&1 zIq)g@H=x5&8(9xl(|PL9quOo3>-O>Sx9YV=IQ@?Yu|uadZ}&^Tp{tS-b)30D1_pWt z2Ey%3&FZWr<`VprSo6rGWa9djJ&XhhSjeDbxm;{wKUX>TMXy_{O{AA+3k%oLU1<}? z*LJa0h{JP|Shn-1Lw)rb=0a58?apf>H`K#(v>B!K_Fs)rnX_(rg#-gSnuE~qA-u!Y+}*viLG`@oHM^P z8t(zyt>mj2qJMK5LpquMa#%U=F*sN*lPAfuQ~eUj3QN1PFDD+^WIjJQFH$KcwR6Zl zqX(y(Ro%&9zF+KNnlovA%U6$;kl9R9M5kIIW+{8h-Z56<*}``_ceScEyko=Gb)0!H zm$sl1D=o9{DU1vDU~NTG??6K!r-W?;!1pS_0qFXuxZ$(_1wY?v;`upz-4?IfDyQnW zp}oJ~s6H;5HrcnQjL5<=TwI}53l)E1po7&>#f&q9rcFiWYa{mDsy4E4BACoT!YIC?A)aBFzXfYh;%ICIC~g zEzez10%_M`VI2@qT^r>sV^1!>6Lp6^DjktF(U!#p@x?G{|0iJb#jntuUJwlW4!HYv`*$YsJ#^hF%rF*Vmd%9M!14NA##{%hy@{}{L#4;pOSES0(pgQKN}fznYQYZG2P_g zSOp|HIybx%x^kOTL!fzoG2w;>r9kURjJ&bYftfzJvjZ(mEjJskM@iH=LGhyN6-v{j ziV{}JFkDy%g`!uq5H7RSk`}G9P(NPvd{558sqO}&|;^o+4}T&t-L?(4Han3DOExx`%Azb=z3+ujtmUp=uoMzTZn;zVCxr9S$e}0z z+VcE}6}$!XD(#xwtee|g_l8`rzk0i++Qrim089|XEw;Xn$@z@P?V-v!UtqG~PXy;u zT4?N4v|uQ4ZkBu@Xk&rO=Jedq!-a+Kcz^TMH*_R9Fi}GC6VeS&o~5T>ZkZ+dMXRqK z36PH=L_>_el9Cx-S_2B=Fkm|<=&Q}2vaoMX-vI(g-|Pl=Wf04?w5(z|h7-`!3Vtp8 zXz;zgS@1C#MZ@Em-s?j_Kq79FL2()({3MkFJrW$GjD;qwL+#NDGI+_mM^x4I|rAD13ZU@`hPVw4c2~bLANzv1+?q zZTo4zT8p$)kU!ET2ooHZR@I`~m)*Ro1#hO-GJ z*kQ226mt-vR=h{{B8lfxo$UGvQQi-MB_Rn8ZK!krFzwB$9^U0{!%Ea#EC4EGj>@*po|1(pd}2hOM_@1y6bhr&Gllr2rBBC>dAXKrEOS zoI*+Gv_R;@m9LDAR26ewkMN-J^wiL$Az ztsQy&NN{n@X^0<~J}SueXHN#{kVSD{iN1$9uMFEYNxEGS*4Ek!R0bn77)rIB^Da)xOWgCY{@(<%>FR{Dei|DAO)*+|10RSPc? zJyv+c8M7;t7B7SZ9Q0>DFrJ)rH1Mwiy+2pp<7tk%WU~_>@8+OqWiy|JP&N7GF+uqd$QosJF>>y#Hn1VE-rwevV!-)wVg3oBH zm^t3hdUJhKP>vTiauE(o8M}cI{yb1REJEnH3`;OeaQLN@nopjY+^l<>z1)El!XS~z zFWyyUe)s)xte(hnuC+qGjfV#+5 zd)0p9Y{?ETpFWiDum6$Na>p#6(b{zLY0C9+YGrm6!>AfhZ@QdCS&>%nWK=@a-4AfBbpEs|JL z{d)YQ)#03d>!XynB z5&qdrT0qBJAIiQ=Y9!dM%o-so3l~~AiJ|wo97|BcKU(GD*^4d496!h$ubLfM9hW|L zM8(KW*v(w{WS86>FG1I2jKySjR8?4tL=K{}ti-4T|K%6e$ob43WI&PJzC= z`W=96IrgloJW|66{0R}|F{=M?_ADFQ`9+lxg&FhVu>}lz=EkGsJ^})`Hd7Lbl-C-^f@0W-Gf*7bg?1H@fo+ z4ZC^s6{0Y$%45^{4qW-;H=?)>v>wrS8hRp2W$SgT5~A4+Iueme`=;r#kUIsD6UdJZ z>W-RHJp--)4=T*)s5GDnmksyA9KGIv)KnlTK#X*t}O|!)r&U z-oE+{@UK~1#3Yrd{Tj@vm!uA!7uGP9Ddr%|Oju=&?kC@dchGC=FTm_G_A2*{SJoJaYYMq}-ar5NBQgR-#C ztVsuD`T6==GV(~Q36A?`nRuJs^W5gx_7(l%&WIG82*2;7W~)z$kGN9r0D}|Xo{~FU z;pg(_%9onP-Ja+A`;x}GI=RWP})U@=WzWp9hFSrX4S z*C0MjnEV6YXLlqU2`G^EOx0!US88Cf8kdry!i z5u^#clAcAi%V}&OSl9F`s?O?pY4L)0Zn*y3OdW<{2E6iQaO@UC;G@4_Pp@IjfPtgH ziNHzEmn1KWuP2u3rsRE;Npgvjqa(#7kXBw)bkucA#7rdyICEo2Wr=z=Sz4UvYS*G` zYS^2V*h|I4;U}2m3%gcd3mLoDzPvWJ&1F8z+KanB%?Y$Z>Y7M>WhoNgg@uO-U=8d= zgYDjma#DYEZVOf(BP*>>WQfy(ZN8?-L9S|lV=3WI9I#U4;P?%a`6f{(Z{-7FPi95k zt&47i#8H2s!cbT!Vrvs>meZZyv>@=wgf5++xrH~D4UDbhY;wg(>3sc$XK2zQjBA4z zL=U667$yzD2+jcG?qOVOmde1^k|{u{q&89(J1R221Jr!ga!=fPo&`lyp=j1tg=9Zj z{hngEx&BI-d_UJeBrVf49lH3mqmX-9FRkvLS1`{xpG)x>QvwrH6mXMzjd<3b@%qsS zunaQt&?fQ2%i$+sb%k_8sOUX^NN5BBy$})kz;uKLu8FB@dk&u(xbtPC?otW-VOu9% z95%l4S&K(cxA>S85v=*y$(A-KD(v0sp5c?)0fp(WoI;1#6;IXY?H21F^5M;lV z;_X-&CLK%4BrhtZX6&S2{zBn!g^cT$EL_n@=18t7T`V+94l)YOYX}qlEwNKR1qVKc zy6K?(+;&&phc_6uO zas3W3_K47TT1|uuA5E@{Fqq_$;0|%(x-KqTR0)c?_E#v|+C?Bw$Sxfsszv9c?xa$- z6WhJGRAPe_8YLkc#0wsk3FZNPJAu(W5DDt;A$y5m%ej3iIai$O+0Cb zTiaU)mtpUj@-cK+{kpHfAh;++ngUH?Lc!@8ZsEG)g-WmyM+RF`B_ZbzQhHR9X+HYD z14w%`$LJ9s>BLI#7Xti)dY_qin7EmrF;gfPtBa{{1*pN-dvy!38SqCBt1W!2%whZ5 z%}L+rDm0R8=(L*GMFwN_s?4}+?5Y=2{~~G*tE24y)WWb6PoF>S&riP(BZv&dW(6;C z23J2N#mk$GGSZ|@qEQa3)fYWNkzf{o0@L}8%zZc89J@mW59M`JlOJTa34HHTpSoX4_5Db5v63)Ww9=b%lS{(N-!Qn;W^|Ar_A6L8R+v zlk8gWlgM9ztU#fvgVfW--AqLZ9PX-;BZ1otdjx{aVy}vl6sz&lz8FL@D3Si*O}>mpc&UBDG#+fOqFUb7lhf%$T#{l$pm2#lbAj`FL}YOx zCIvwy$m;lF+!9H3lIUD)2p}~!PE7lK47f8Di?a!V33@p>sOTixoN0Wgv*%<|r3g%c zjS&c?KoN##NG{=X`44zNqm64Q| zI;JC{BCVVk2Emi1w&8quEwpF=s1HCC8WQTm8TlW`5dsYo9Rx*6#)2V4&MIsK%_iy; z_@BS>;nfI2gpdIhb!k|#mET70wtfdMXQ*Y9NOw6`F4GirL$C`L)wNz9YG?X723cl_-NovS&>LP0VzuKHB1IEe>MC1Hq;JR1Txk@ALXbE8#bV z$R^u!VtZ8Tt1#_1eV8PPiv=3-q+DHvHEHgthRE?A5VC<4mv2W5)@ zL&%^b`_HAc76_%pcm~M0V-^=bs!YV`o zNwh=DKe)GIW_wKZ`PqNCL{&&2WbkTmt>FRMwc2t#Iod6>z5q|)A@X~m3|~$fhU8ny5xS; zBHr5{vOIrWhMeW5-5MNez40;Ykl29U(k^=FMybTcH(z!qN?cA^R+av6DY2?magesagH_xeZG z#YlXbd*U)3o+wsH?kuI|Umy`1eqOKfUo#hdpc9*v`=)s*Pe$lJIXY@e2LBs3{rpak zM6z6A0)sUn9NWnPV#kRLNP$7rJ!7jQdJ!@i#!SR|iP-BeLJ~01&xb-WxZ{M5e$uq5 z{o751fLqx!#xVq&k~@CbY+Eqje}v>}xr@PIM6j07Lu_K@UN2!Tt{py_0{l_X+<3`? zhVFzc<45y@V;R*X9`=mMJ!c*qMN7Zg=YH1_#`)wDrehhE(~lM_@&Pw}Oj*G~K?9*- z|EJCVgPYLMSz*Z7U_ltsa0yzi#CHRt`xrbHys!;`hV#HoZh{&wn2vQ0vY)$(n>O7Mj#a-b%u1$%g?Us z9iU|2*@%*X^K4%r`Gm_+Wy~s_@>X1L5o!BkgSi=vQamcRVsITZX@fu9P;T?DIJzH2 zX(+eGK^_ni<&NOp#~@JrWVW>U5{yfXjFQYXAeLE@Idene0+-&_)9kmfna(&nS~*Em zm(cc$6P}SyPz82jR<4FxyF@;rkiyJyAH0?V%sZq05i#%$R6%N^KSmn!fn1$3uc^eq z48P1__pJ4CA|qlU6}|(M(~~mZ0URSg@53=9D`)**B!9YJnXR-5zV&v;tkP=wf5uCa z{7a%a;yCowR`?o{9yyTv1`K{3rCjaPiJ*|12}IBC`cCL}7JQvuoKifq&(gM>6B|#x zs+Q^tHL<-qiEhGzJ3J*-L)qqrxv+-ri?N_QCUACxToVJa?CHiN6A}H_RD44+;|0R- zi@-|4;;Ei2J13L&hc=#(eiW{S+zWrGJyuj{krVmqU=Zk)ld%-Nz&i z6!&Ibt+J!IZQZB;Q%nDzVPaz9L`r5?T4cWG^!dD|Gl8~(`v+xweY?b$>QknK^FGCy zk@fEvbu>bLGwI@qtwM@*#Lz)8l^3&bM3{M;RGi+X0+E-jB>NBDG~pL@^wuxyW~;8R zX)j2U7z1K-;q7u2PM;b6>heSxgZZfOQ*4T-Re4-*_?Pg?b!9|!US#)*Dh69ZC{z}U zz-abSm*q|Z=&X*@PQdRf4$KUHnIVINqFq)WVx53y{%s;1g#zGAL{=HgFACU>EH5n5*C3eAEf$)s0zT2v6-zUYA=fJ`sxkI2 zifw~Vwl*jVc=(G5xO}`Fu~L=3s_H4Lqz5e5_Z3WZL!PeNN6`l}mYyzegCzzmoHh8Gx@Ofi^c?i8Gfm@GVJ82pTd;QLQB%v%auWF7?lk>y;&m z3J4v@usjaZLv)j+oAwKvGn^RCbz7r5at@D^sc=rI;K55%ArOQeG@f4_!Wy>vw6B{* zC)W`pA$U9~u8)HkVG~rI=YB7yUR^R-{bx_~<*Sbsp<;i_&Wb}c2N6AA8o%V}9vSB8 zsjM;qTlh5b_xx0QeZAq?PK-z~hJuz*U-Df%aA7eT#e-KF)1I(Wp3Ja>+P<#T;X@Qd zG~N9u1$6idu$t~zNh1ASOZti%CUl{B6_}Pig3H^KJckW|eW~;+$0c*At7Z zh~e*msMxlWOB1Y!hD7x0Dw!ULlwr;|v2zLXal;1M)b6L^@;zy)3bq5?pEu;7bQdSw zmF-;}=fYu~R4aLPQajO$kxpGcS7R;Z4j0=t{*{{>)MVH5u#%S*V zd1Hjjwn0%{EHURVU@TcWmrq|FLGfYCoffzeq9g-6Z--|f#!U#gT|GAeD3CpCE?TOM z*q$U?i!qL+XKgbEP$E&4TK@{}K|R%!Fgjp}l|eA3BiA01JuEcO3n&FGF2Uj`qf)S= z9m(cKU86g)#u?|?mS$jsLQB`RO=Lx-uDqXFw&)+kC#D$s4sb5M61a)+SxJD z)~S#&{u&<1L3aHKeWKg~DnO^oDyl+tSfYB-`bd0@29rCzjk~xoI5N;btc0c^A_jti z(RN5~N7uWKT{*VK~Q?rfz0T3Znv zUZ%e?-0kK(=!9K)NZ3hjMK>ub#Y&J4mVD|VUDF6GLKx%|=K9S*81MVBY#B2CV@Fek zx7@yiG>DsH2kazfQ=W!@XRRO(_A=!L1EZ{xw;Ju)2&XW4hK_2l*++@dxZ^D2cnjM$ zo+BSCF9b5o*%%L}ae|r$f9RR19egvY#)r43E47gB@cmsrQ&!GcS+ODb?1qChb8{!@E;xHp!xoEW8yzL9K;CdD;dx&p0} zveHZ8f@FwJH=wJ(Vhp(hU8n+o+$SLGzB_!EKCAaOf zs%+4rbp9l!n9*xIfJ^Qb^UeoH{IY3fdc3>U0B!!obA}Ua$VI&g5LqZ1y}bFLA_3%o~bE6TNzK671T=vEew8Z5pSebV1}oQzv$QZ>v)4_2dMD~w{9tVnzb zur8%&Y@REffN{2pF@Vr#WY@c*`$z+-SUI4D@1>OM4>#~ zJo!!R4f6$P;_3BUzNwK}rl*ZBG_-rU^%Hb}$7#b62Nq41n)q2GS(W}qER;u*Y+yapO+VbZ`CzXQh2 zEjHa=lkR0*M`~Y1GYl7#(hp9M)LAQglZ{tnWb;RzW5xU-NX@tJ5UKa{%~4r?!C?*2 zs)%Gq>S)TyE=>#7+vNnvBBfeUn{9?+J z$#BMDj$+vEuguZB#5XL>H&L)m^i?iQng=%_18r0_J0zC=F|L?L&6)5!v9SZ#SGYK) z8!Eg-N2naAwl+UkzO=uGe%~iLK=`HP%`CWl?M_q4@HH~`<+X54#LE=5o`P--J(~59 z%xGd+rFKA|h$$$={{bmdloKh!Y)!#SO2&iKPm(S^;1(`nge-Mus+g`wM(&z|w-j}` zwSoPfeNCr~@uhRm9|}&STcq$I;Xpl_ETB|tu&=x3AdP!rY2n%^sK_gc(^H&j_OkK^q-()#HHJVg|n|=o+9_tz6EDbya`L4 zAqlKw)FJEpwI?EJ5h_rCl5s@XC;OU%j5gxFyoTd>7S4S_XTyA@uiGP)(N)o9nh=r` zV3`Sby(pZAe~?VrQ5ct={D|bh#@;+aoRpRs^^#K;6h08ZLBBvOK#+SA$+Y#8Og)is zuFrE)aL2nNRl7sy#2TUZ{tKrfyoYBOf|e}D9^1}#Oy5%h`Wpi-8^w2g;H3NWm@0neu=Qchbd;@Krr0Nwe|-)W3@(g)lub$QK13)uiNDUJtrAW>xP6UNx}xO{VG`! zO@J~!Q$l4Zi2_Ag^`%+Sk**hpKj%%x{lq%+l;t`g$#~*a+EIlpX3;yKlnyYivFIfX z8&4Ni6$}&oFIKAVUewa>UFFoawkm5DP6Z zD@)_(4sje%)`rnA5Arw{52+n!-e6-)meOGhlF9Rcqhcw_>%r+1Ck&>>8NQ|rE*D69 z@IMvTMHt0j1)Yp|#g6b{!Nr!?_+l0Kuz??Db)EHFp-vUW9nJ~!qWYJ}_#;YoGM?qH zTce?^imo%R6|kujEPEzn6a92lH;nh#*x2_U_0PcA^AAV@eT08NLO^{0s{b3r2?0PO zV-;35asmZ{3mW?7wlDv$>kT1D)&omS)%2|w>MP@^kH+Vn-{Q8e~5e#muTIp?pc9}>>S37vC3>Z*VGCRpWL++aJf7EJ9UBo^b?>hs7pulOFXKL;yW zfclgUC4lWwRkXkw{Q`P#S*Z9%^nh&c`eErcX|kO#oVT&J7{5LLuK3ram-KQ8r2@&p zMZY4FahtM9!Q;HYTZk`*%8#jpUvy_*^1p`#-hA1ev}H)}6fle5;FWNrd1}Mar8aeL zJF#wR&!c|oJMkiGd9kVE5YG%fM=wtJ8%YzRIe%D~^~d;DzB^eb9BELwZm>f&No1<2 z$2;4z(kE#XmTAS8PQwh<@xuKa%Kbb0o=mU82?5#OzkixD=lBixDKj+tg6nw~(~8qB z0++ncvfljr7>{y@_bHhvBBJ%3yZ4r5)RT2pf$+^-c4kMLZXQtunm*A5IU4y39#{pj zeB@26uD*Sa7Xrgnz=l|Ta+ROV%wxCWm+?0yN@+o65N8pJ5zmHDggKihC|76a&1;sd zscar`yg3w2lO@3lsO9?hd46Z_0JLBGEI7m)Dg}eCOeymDP)TE9GtUPq!9FxQ!7#=0 z8zSsG)7LXFM`>nNU6Qqp9E?_ZMO_%_4X~k^e-O3$8fFKv4=<4OJ=wx4o6D)L=gQ>= zx|pUWXehV%3-5<|hj!>iPt$at<;0GtaZ0KN^Vb>gs`h4mk^ERwVO1aD@S;=Z`J-!LGOTa1JrSQ_R*+XMw1AdS=r4MmaAK~mo;3P&kQyZcRA4Z7ff(2U1R5T zE;bvbBKRhn5vPQr)%jRfFl648oA61tR`tK@=AjI4g_-K6QT_dezKDPVX8+z~kD#Hc znlA8y*ZX`gJjgZX1_m`Ej8jbu?eHOW=!yo9T$8={4*JAwxEfeiu{Lg-QSSK0rbEBf z29>uf%=r&&who>I4~Wn~lsaSV%V=6Ib4FLOnRJ~9#GOwo1P9fAm<5sUgoZdB)X)6e z)XMX8QUXDQBCw_EsXkMffw=C4_e{C-<7wc!NcFRi$tfBjSs$&ZPL(;K(z9ev6^ss& z-B^x=)6dAsvhYGHa$Y<$xn%hW+_@dA7>=O3O>sBuJ`b36iDi0GTK%78(Ir~ddwXxpX+!S$Y-fGUC2nY5|#) zPnv#u#`P@VPkD+tVT0ZVPdlz zLNjl~u5khJK_?@TiDzjaf$vvdf}uW*qOU&@7ckSSK6|=nCb1h|5y7^_?e*qY>Qzmi zh#44AAZ4@9raj|1YKC`x>MrQsVpj5o%_EMMTE^j)oib8%R;PI-fUQ-VXN+lA=909o zeO5EpY)jE*nl?{I6ldHk;wmc^9G-npm`MkXDmTH3o0wC(0|K2ax!Tg?%b!Z5a+jDT z$T}}Sd<#+zibQ0X(jgBzlz>&`>%-K3W!c-fK~1;GYUt??r;S4(rA;x*Y)1l@rFPBC zm?;)k*$vav!^pUg&jD8XJalkMPioXHTJCCMvNKp;ika$&pptX4ADO#~K*-LC+h}tG zV#tGO+ut>mOQNr1n)o;}E?c6~kr8|~Z=hOpC7>9l%hh-c4XvucFHmA8Kbja;T1 z)mhRQQbS6rw4#YI_WQ$!yaUjulkFbG$L+&kdq5uah-Gc}sclwn8|^)dATRZrb(Yqq z0z(F#7(pR_rQ5&}v<3{+^gL-V_KCSe_PDWdRn0tcZw$>y={V}h7$wjG9r}Al_)X%X=NdcZ|7B|13Nfl%YX(9 z$8rYtV0(WGIYL?QDohutmw2g4V14GKs)E_)+iBt?t0zU^Sza+~Yb}14uvT?w#;Uuc zhvnsSE;v+Y1rz$#^PB8;zKY=ye$c!1CNpPnEsQZct7ON-3^}_z$}!c>=vJq z+huI&F0y?gu)-$*(Iy_uj&mB$zs#zmGebNI%_+_i(-*_I`_g~zxD~00)LU(NKcshr z!r}%br@WAM%1doEEEi~!9;&yMbRX`kG=){NK8mRZ|MH1qo&nm+0A?7Exdh9B+1K~OkBThKH41cYlg(`dj} zqHAr=UzHkzVct#4MR;OyO=5@xu;mB9_u;kD?>|$2g9AONK*WWE$l^-Q?uaOz0ozJ{ z0{8UEvw3M$%vO3aOQ#A%X6Z5CD&pkf_m6vNv7tXQu`(4Lwm+wCxZu{%eBh2n->`PoLL z?2YUc4uWmF-%C7?`5C1~{v!Vv2YyKq8H{hzLvx+F%;b}?-q9R%9=!Skr)ZFBgNtWQ zbqTs6uBhjXh(%fu8k%I<~$do?^?c$Ntj<)e;6SK&usf zGpp{rKaMyqN(1sIJY_$dN(BAIgu9G0YQcUU+>9gox&zB>pV(qjx%C0;v^X(74{PHm zG$2mo28R}H#TA@mc!f9ZlKH3q1jqa$&0pdr93*RwFVEc3Kj-kw3(x5Rjc+=fxTN_? zEYXGjO>X)!5?3GU)jh|q4=m#E2>#hE*5^~M3Nz+MUCLSZmw>TUj98X*b>;%mVX*Zq z+TrWmVt`SPsj6yIe-R4%0Lz*P2NZ698a$w7AFS}fEponyD>~Yf=h3^Q0v}>Z#A;K7h z^_QJv7vQvTqqz*Z7(7Dt92o{ak0g_1Lv{n-CcO(h%am7ad6B;vn+oKBIoJbgxuAS8 znC{%r;3v&I{8PM5O@7pM{Xk7?a&yUx%$zW}UGsxk_sX!<$5~X`;}v@cuwGN3;^Kcf z<=ws;nB}Ijo>nOY3$XOa|?r>tzfD7y}9}e$+(_k5uQNZJbw?h&O>6#(|8z^Cjb>MH4hOa(UthapM^KJg2e7$T? zxniSK+>g3w6Cm+{->?fxcb*MijG~kU-=zuavbZ;3kBW7}I+oF?f$rzCR#{;{s zb_#V(56iRz$%mqEqZUj@Qt1XvhFBe7Nq@4$r@X;y)PHf0UTuJLrSCRt7LRH-6M)~~ zTP;!^aJUVLPQJn8P#QY2g$w5QrQ$@Vp6M`i2RF6qsgxr}z>l=ocNes2}9{rF_*re)HJM z7T20umJ||8=%X**9}?5M(w!pDmPO9sZhC6X4sImLPb_{OJS44}lo0QK^bd^EC-Q<~UQa0VxxN6N4ZWIbzQb zm5jJDC;@{)G&cbNxrI0;)(F3p_&=a8(g()EcoYN54pgaXgDat_Td`P3HYOGER!$L?Q z=m7Zu3?n|iAN@??8keLYfj?3)%-|F~L%#8Kn_z|{*)=ASAvQr2kep#be#n6!2>|eF z;8KQ`%7LUw0l+U|^89Cz-csn4A21#`uYb|2nB-s z8s`2NsQ4H51-cd__&mtI1$1QR=17ZW{9ocjy6o@om%AFA3HVFo2#T+1zj`}gZN)4i zQk)MULs#*;>#eiRKyir;4UNx&j@vb-w)SlkAw;=ajGGtw(PiosXx;BQ|7&g6WpePo zG4+>0z{O|J6FSSBnbw#mQ#rHjXv{EiRz~)=m_w`Wkr*u}rWdH}xQkZL6YhqgW20uI z?`8qZq+h^yk&pv{+Z!^BNey`PO~z*++EgwuP$*=jjCQQT24CdwRMK@e^FDKW=1ua>;PJ1g}2} zf$kk#js+*$L?H1VFPv_D-T}ptX7R65c1SP7g(Aas8>4!E%74x@w;7!YUKyS2vb-1% zV>HgSkyIITZr&01{_*=($SYVei>TPUDw^2&DhfUI!{F{6z!JUOxpuF5;#zVAj(stsVn4Ms;F*-={8##Ln6c>ULxxU!0q`THncR=-0&jZJJ5lWQLl z-(LN4N!7(W7UKlf)D8YFukWn!>5zzc;ncR5*1(4Vr>h1`(v{yaBbmEVhZtM9tF54G zTxX-+KYdAS4h-BFcC2ezV^A1rY?L@nJ0>jkkNid5#HBjC1Gy#V<(?a5J%A)`tdM&L z4AX{da_0oe3SlBqv9fP!=+fY5u`LWTYNzlxbLr^>VK|=8TV|skgHSyBkUn{H8Sb~H zzjpVJ`~I|TMsx$H`?6`iuzI3Ma>KPJZQ_1R0TBQ44}ngk>2)I-Q8|O=dTtvYN%Bo! zUWv~}UD20RUUS1(2v)QuFq%M-v$a(ub=S?UVPvETmX($MyWifI+s4Z<%GTS^5U)>= zbTK@+eS#eB3)}E#L`VD1W)FJwP9R~IgEZKdf$|c#EPdfenZz&yw+ics6tYkHFueAe z=n^&XuL)35pSZR8nD|A5Brz%CG~kAR*%4#u8e73nuc#L0>o_NJNm-=J(v@G?YT%;f z7?s_h*nmes8}HU$ms|70jM-U(*qyy%*Ol?5k;R`;?P9Tp^3$}6z!%URgMA{~Z#$h< z>v5nlTtG}Ps{Wft`RPnaXz_4Yy;fE_3q^!Kz&ozZ=L&hZe=-s#8v8}Z-4n$8VFM`s zvjP7Wj{o1Fw|_Q(jFt4C4G;=+0$=_=5pN)?8z}!A8={pBlg;tQ>46^VejeC?2T7Cx z20O+qv;>- zY}^+{qu&!Isc0KewjanTH%a*DU0g%DB=EIuozQ-RA++%Ga$Yz4!+uAXhwIiPm(JhOY9|W!UUcDu~BPN3z2kQ)$7+gnCHH5N8q+kI7P^dkk2DckI@UMFBItn zB5IDE9V4SaZ?IOHE~WF|JjiP(#_FA4zjWaOOwmQ=ku6RGZh3@I54d=qVw%Fw*nGa; zU$_zATRioo2)qMa^c1!mn`DO8{zCpS>A6i(V`y-prXA4D;94sCGto-0w-S>r8|)kA z@))jXx7dlB^Y>-o9nf+94#-<{((|jwc;2srn@04p@G&0BIggn@US=7C9X5qzafhpb z9bh}=ZI20X2bjhELIAiSCw3Y}Z?>?K#*Jyr2$r+X`6X zj$1``oG&sX)u_i2nnxJU=~~99q4x3Ooe6I`-he;I{j1CTsz+eS{|V|9 z73!ot*mL01fsXAC2e~^G;G3PPWV>+2@xb%(i-r~u*k>=2}^8tE@Pqroy zpBzI7dc;=G4x$wNkSqhG#5ll6bO*55t>x5+;0anUM71%fMkzM_EI1bITht@j9)-*GnW#AS@0gL2ls3|zKDxN;agki$Q?2SA+0 z69^L9^!*^eU`4x`yPdZqd!SA z8ZExlsb=Oqj2qM5;n?ztn5BJ8k^{Z0Oa`@OT`M?o8+A5`P|2sNaP==J)Ix_F!N59T z%;69fl_q;@s5}TO3qYn8>KtL@=N#9k?8ka&OSv&hgM7epGUnkk$L=kVS^%K}zR+N! zaLqBpUB)zpS)^D~u26LuHFKEHVMcAp)}jRHx*Dv?FHtmB$j-w2O8qTc%tqd=7Yo_! z$RwY*5QS#Jh5rD`e%M0+OI$EbzR7~mw6|U>i%*%D^*M;U>-b0TpG!b({{S=oqF~kT zAg}Ed!z2U@gnv&6^uXi5A~Z}Ngt9@<&55U@{{U1EdLuyH-T-#^yhEuWJ>Y?j0k&#~ z(l~e@j$Yxe!YdS@(zM_w1BIk#YGpDM`??4fm>YFN@=Bq6CAS<76HI1qYA3?I&LD?w#kD`>Qal5rmLXuIde0a+M3de?>X{^dB_v}$>p`lBebuWaRFS$zx z#Ee_{!EpdDq$iEcClvnRSHno}%_u{Kk&*UoPb>IM2$8nFPx*jCBVb>#)B{Ij^^UX zh_AT15g<>AI1~lrxKcQ$u+Wx0l!a~y>yios#HhI*nUt#e#HYL@NpB#sl%f9snw&Eq zjpuE)4Hsx4GjwmY03<^Nm2nH4Be&>(@>-+0b!QMb6v_Vpsy@-gG**%#xpy0@Y2IM< z!(%rEKs6)XG)cq-~A_y`NUPLc5@!o`(^Q);Ub zs{#6MQp+N_5fE;hWx}wmcQLGZ#j$CeKwDy?BynnPotqZ6mp*+Fhf7C5cPFs#@9v%WpW8pImNX;z>jyIx4- z(sq#{w19D?#3i3m2HJHTxcQQ}3W#SIS^{uoc4hn9IySS-MEAT+=bX`g+@% z$`EK-R$0#7U*-I#piD0uw*vVgs6`A0+@K{?FbFfaCXNQLGWn+MrIiACtK#SZ{BCvt zw}8+Ank{aG-n8wB=SCLE(SyqNh7A&ZkFMZey+$<_o2sA-C#`|EI zrj_Iai9m+;9NpSxm)n9EFdlyztUe_SJAxdh6s7o_^#-@kk)qGZy8f^MU(zIR`3!0N z)BqRcRN?Y`A1!i=tfF&Y!6viu{^1VAfQ1hs-3S|MiGZ(-k*GaFs{A7|A@-Qss>(F# zB3pZ@?z zK&f1%1Qk5n4_5T=7#zj}3RtyzK^ub>d{|-}M^z$~eTZ{KjKO@q4G?0M0YnvL-w!6PtvL zhaqME0J$3g^xG;iW9 zxB$bj7z->mhVY=kyB5A%(wExJT5#sl$m*&tzi9?0ufx zi<_&q6SsA!C75b)0V9N)wH&>qUfnS9sJm zJko1yut#?wpK0%6hffJ`-2N=1$^!u=LhhVMPTXx+OsOV zF_&6}z?n@Eegf_P0GWOMkkL(bFq7VuR+QU;~Tv%nd2Tx~+aL7Q(ow1P@w@q~px9PbI0{$1tNL z{{T5Tw}>U$iXcuk4sMdX!f>Vrj)F^R9qDc|V{5OmVHmuzjRl}|jgWap@JV5(sZ zgUWNxCd{H?jwNKiSky2Dypa0?esdz<5LCt(nQ?|uKnao%;cC=eBw!0Iyl4+W!ii)W zB`Mh2?Nkjq<~))1POUL`ifBPDquGfX4d-JQ`@O zp-=>OOnpehDLE0xu{fVG64LFA?;A8rSra(o9IIi}K7)!QtL?6dvtGenhH3e9GMKkJyL`FWf6g_Hp>`!);3x-phRgQ zOWBSgL@dhKWDX+D^gK9H>wUOEwY4Jb1}_@6wG=@_^SNbzp{P1G!}SvqoW-h~YAh&& zCG@O7Dy`HWAp(=>D6hT2h=CB4%%v4ZRz6w5a8|FiL=7xyf4>k!RC#4Zl|u6bTQW#l za&;{29SBudi-Pm6SeB}k%m(zJy=r1Izy8p}wfO+5)Wz`~OE-2S72$7J1bd^=l--VS zatzUM4G@uKYN3#1h4pu7L2agn2qo2ogClLQeGI)MXGKzVO3Q=&gmdmzLw4q81b$Nj zryRw1{^ePGp{}p}aVFlQQrGPaHu&ZWJsisx^!@^c8d0E$WE_})ZTA<1WtEd9?@$Xv z&0Ro;Lj-cbR0M3#^(z{@gIoB^9(h249l> zR@jBY-QZsYtHo4Dk*V}3(WjIJBg%V$Zl?26u+nIjccj@~TQgP|GP43~zGv3}h!T2O zk0?K+d4-aLBoD>qRZG2N`N3q2qTyQ3r|@5a&E!>{2hyJM)xLY#9mQZD_$0iQu} zF|SuHQw6^vUC(WF?~$|DjsEzBr73c2RD#JvtBR4;P4bD)SVk{Jj`A&!zx-gaRQlZ zkg1$iF4j3eu!VnX%qyQRIOG+132DT;=AjmVB*7)ptHh4Pu!{5tx3Oq3vSORfetA#`_Ylc}t+PV{ zh58B3G`l41DhK%4MYoLTLIjzSDz4U@QK@8+#wl?)X{RZvK^t0}sIW$xdPLtZ;D`>` zls`rH01;Cz-3@c%*m&OH*c8Fu z;d!%YtI8p6RZp$K=*38q8&b5YQx__ESuaQX%n87u4ybOi1yy484e*1=;Dt@p1119r z2QqVa!ZBdi)90}(NA0uFzqTD$bR5`)1#zkT|xWswejb*0a^nK1FUjk_DmzrBd zug4e`yzUYq7QCUP)-&7u!jpws)IJdzBB$}3{sjkywWnjB8!WKn^`rKBo~T*+{%=KlM==>S+Te+ zV!#6w_@wJ$saStluus$`!4IGKO0{&aBc)X4r53?kJirQ=7RB-)8iTeUmMj&I#3G-F zZKynqSYc?3@jh_?0W+diqzf##N9c-O8Os&wiZ&~9Nf_N7s6Cg^^{5;2j~95#X}!LS7tmy zZxxJ}*8|3)6==?6(=k&o@ZdkmKiZ&;(c_YgGUey~BP;&^!Z`r#54ib4yHEewr(=C4 diff --git a/modules/bioinspired/doc/retina/images/retinaOutput_realistic.jpg b/modules/bioinspired/doc/retina/images/retinaOutput_realistic.jpg deleted file mode 100644 index 1bd60f80cced8cf6afbf3f351caf3ae507b8d56c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19131 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 diff --git a/modules/bioinspired/doc/retina/index.rst b/modules/bioinspired/doc/retina/index.rst deleted file mode 100644 index fd487b7f9..000000000 --- a/modules/bioinspired/doc/retina/index.rst +++ /dev/null @@ -1,493 +0,0 @@ -Retina : a Bio mimetic human retina model -***************************************** - -.. highlight:: cpp - -Retina -====== -.. ocv:class:: Retina : public Algorithm - -**Note** : do not forget that the retina model is included in the following namespace : *cv::bioinspired*. - -Introduction -++++++++++++ - -Class which provides the main controls to the Gipsa/Listic labs human retina model. This is a non separable spatio-temporal filter modelling the two main retina information channels : - -* foveal vision for detailled color vision : the parvocellular pathway. - -* peripheral vision for sensitive transient signals detection (motion and events) : the magnocellular pathway. - -From a general point of view, this filter whitens the image spectrum and corrects luminance thanks to local adaptation. An other important property is its hability to filter out spatio-temporal noise while enhancing details. -This model originates from Jeanny Herault work [Herault2010]_. It has been involved in Alexandre Benoit phd and his current research [Benoit2010]_, [Strat2013]_ (he currently maintains this module within OpenCV). It includes the work of other Jeanny's phd student such as [Chaix2007]_ and the log polar transformations of Barthelemy Durette described in Jeanny's book. - -**NOTES :** - -* For ease of use in computer vision applications, the two retina channels are applied homogeneously on all the input images. This does not follow the real retina topology but this can still be done using the log sampling capabilities proposed within the class. - -* Extend the retina description and code use in the tutorial/contrib section for complementary explanations. - -Preliminary illustration -++++++++++++++++++++++++ - -As a preliminary presentation, let's start with a visual example. We propose to apply the filter on a low quality color jpeg image with backlight problems. Here is the considered input... *"Well, my eyes were able to see more that this strange black shadow..."* - -.. image:: images/retinaInput.jpg - :alt: a low quality color jpeg image with backlight problems. - :align: center - -Below, the retina foveal model applied on the entire image with default parameters. Here contours are enforced, halo effects are voluntary visible with this configuration. See parameters discussion below and increase horizontalCellsGain near 1 to remove them. - -.. image:: images/retinaOutput_default.jpg - :alt: the retina foveal model applied on the entire image with default parameters. Here contours are enforced, luminance is corrected and halo effects are voluntary visible with this configuration, increase horizontalCellsGain near 1 to remove them. - :align: center - -Below, a second retina foveal model output applied on the entire image with a parameters setup focused on naturalness perception. *"Hey, i now recognize my cat, looking at the mountains at the end of the day !"*. Here contours are enforced, luminance is corrected but halos are avoided with this configuration. The backlight effect is corrected and highlight details are still preserved. Then, even on a low quality jpeg image, if some luminance information remains, the retina is able to reconstruct a proper visual signal. Such configuration is also usefull for High Dynamic Range (*HDR*) images compression to 8bit images as discussed in [benoit2010]_ and in the demonstration codes discussed below. -As shown at the end of the page, parameters change from defaults are : - -* horizontalCellsGain=0.3 - -* photoreceptorsLocalAdaptationSensitivity=ganglioncellsSensitivity=0.89. - -.. image:: images/retinaOutput_realistic.jpg - :alt: the retina foveal model applied on the entire image with 'naturalness' parameters. Here contours are enforced but are avoided with this configuration, horizontalCellsGain is 0.3 and photoreceptorsLocalAdaptationSensitivity=ganglioncellsSensitivity=0.89. - :align: center - -As observed in this preliminary demo, the retina can be settled up with various parameters, by default, as shown on the figure above, the retina strongly reduces mean luminance energy and enforces all details of the visual scene. Luminance energy and halo effects can be modulated (exagerated to cancelled as shown on the two examples). In order to use your own parameters, you can use at least one time the *write(String fs)* method which will write a proper XML file with all default parameters. Then, tweak it on your own and reload them at any time using method *setup(String fs)*. These methods update a *Retina::RetinaParameters* member structure that is described hereafter. XML parameters file samples are shown at the end of the page. - -Here is an overview of the abstract Retina interface, allocate one instance with the *createRetina* functions.:: - - namespace cv{namespace bioinspired{ - - class Retina : public Algorithm - { - public: - // parameters setup instance - struct RetinaParameters; // this class is detailled later - - // main method for input frame processing (all use method, can also perform High Dynamic Range tone mapping) - void run (InputArray inputImage); - - // specific method aiming at correcting luminance only (faster High Dynamic Range tone mapping) - void applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage) - - // output buffers retreival methods - // -> foveal color vision details channel with luminance and noise correction - void getParvo (OutputArray retinaOutput_parvo); - void getParvoRAW (OutputArray retinaOutput_parvo);// retreive original output buffers without any normalisation - const Mat getParvoRAW () const;// retreive original output buffers without any normalisation - // -> peripheral monochrome motion and events (transient information) channel - void getMagno (OutputArray retinaOutput_magno); - void getMagnoRAW (OutputArray retinaOutput_magno); // retreive original output buffers without any normalisation - const Mat getMagnoRAW () const;// retreive original output buffers without any normalisation - - // reset retina buffers... equivalent to closing your eyes for some seconds - void clearBuffers (); - - // retreive input and output buffers sizes - Size getInputSize (); - Size getOutputSize (); - - // setup methods with specific parameters specification of global xml config file loading/write - void setup (String retinaParameterFile="", const bool applyDefaultSetupOnFailure=true); - void setup (FileStorage &fs, const bool applyDefaultSetupOnFailure=true); - void setup (RetinaParameters newParameters); - struct Retina::RetinaParameters getParameters (); - const String printSetup (); - virtual void write (String fs) const; - virtual void write (FileStorage &fs) const; - void setupOPLandIPLParvoChannel (const bool colorMode=true, const bool normaliseOutput=true, const float photoreceptorsLocalAdaptationSensitivity=0.7, const float photoreceptorsTemporalConstant=0.5, const float photoreceptorsSpatialConstant=0.53, const float horizontalCellsGain=0, const float HcellsTemporalConstant=1, const float HcellsSpatialConstant=7, const float ganglionCellsSensitivity=0.7); - void setupIPLMagnoChannel (const bool normaliseOutput=true, const float parasolCells_beta=0, const float parasolCells_tau=0, const float parasolCells_k=7, const float amacrinCellsTemporalCutFrequency=1.2, const float V0CompressionParameter=0.95, const float localAdaptintegration_tau=0, const float localAdaptintegration_k=7); - void setColorSaturation (const bool saturateColors=true, const float colorSaturationValue=4.0); - void activateMovingContoursProcessing (const bool activate); - void activateContoursProcessing (const bool activate); - }; - - // Allocators - cv::Ptr createRetina (Size inputSize); - cv::Ptr createRetina (Size inputSize, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); - }} // cv and bioinspired namespaces end - -.. Sample code:: - - * An example on retina tone mapping can be found at opencv_source_code/samples/cpp/OpenEXRimages_HDR_Retina_toneMapping.cpp - * An example on retina tone mapping on video input can be found at opencv_source_code/samples/cpp/OpenEXRimages_HDR_Retina_toneMapping.cpp - * A complete example illustrating the retina interface can be found at opencv_source_code/samples/cpp/retinaDemo.cpp - -Description -+++++++++++ - -Class which allows the `Gipsa `_ (preliminary work) / `Listic `_ (code maintainer and user) labs retina model to be used. This class allows human retina spatio-temporal image processing to be applied on still images, images sequences and video sequences. Briefly, here are the main human retina model properties: - -* spectral whithening (mid-frequency details enhancement) - -* high frequency spatio-temporal noise reduction (temporal noise and high frequency spatial noise are minimized) - -* low frequency luminance reduction (luminance range compression) : high luminance regions do not hide details in darker regions anymore - -* local logarithmic luminance compression allows details to be enhanced even in low light conditions - -Use : this model can be used basically for spatio-temporal video effects but also in the aim of : - -* performing texture analysis with enhanced signal to noise ratio and enhanced details robust against input images luminance ranges (check out the parvocellular retina channel output, by using the provided **getParvo** methods) - -* performing motion analysis also taking benefit of the previously cited properties (check out the magnocellular retina channel output, by using the provided **getMagno** methods) - -* general image/video sequence description using either one or both channels. An example of the use of Retina in a Bag of Words approach is given in [Strat2013]_. - -Literature -========== -For more information, refer to the following papers : - -* Model description : - -.. [Benoit2010] Benoit A., Caplier A., Durette B., Herault, J., "Using Human Visual System Modeling For Bio-Inspired Low Level Image Processing", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773. DOI - -* Model use in a Bag of Words approach : - -.. [Strat2013] Strat S., Benoit A., Lambert P., "Retina enhanced SIFT descriptors for video indexing", CBMI2013, Veszprém, Hungary, 2013. - -* Please have a look at the reference work of Jeanny Herault that you can read in his book : - -.. [Herault2010] Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. - -This retina filter code includes the research contributions of phd/research collegues from which code has been redrawn by the author : - -* take a look at the *retinacolor.hpp* module to discover Brice Chaix de Lavarene phD color mosaicing/demosaicing and his reference paper: - -.. [Chaix2007] B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 - -* take a look at *imagelogpolprojection.hpp* to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. More informations in the above cited Jeanny Heraults's book. - -* Meylan&al work on HDR tone mapping that is implemented as a specific method within the model : - -.. [Meylan2007] L. Meylan , D. Alleysson, S. Susstrunk, "A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images", Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 - -Demos and experiments ! -======================= - -**NOTE : Complementary to the following examples, have a look at the Retina tutorial in the tutorial/contrib section for complementary explanations.** - -Take a look at the provided C++ examples provided with OpenCV : - -* **samples/cpp/retinademo.cpp** shows how to use the retina module for details enhancement (Parvo channel output) and transient maps observation (Magno channel output). You can play with images, video sequences and webcam video. - Typical uses are (provided your OpenCV installation is situated in folder *OpenCVReleaseFolder*) - - * image processing : **OpenCVReleaseFolder/bin/retinademo -image myPicture.jpg** - - * video processing : **OpenCVReleaseFolder/bin/retinademo -video myMovie.avi** - - * webcam processing: **OpenCVReleaseFolder/bin/retinademo -video** - - **Note :** This demo generates the file *RetinaDefaultParameters.xml* which contains the default parameters of the retina. Then, rename this as *RetinaSpecificParameters.xml*, adjust the parameters the way you want and reload the program to check the effect. - - -* **samples/cpp/OpenEXRimages_HDR_Retina_toneMapping.cpp** shows how to use the retina to perform High Dynamic Range (HDR) luminance compression - - Then, take a HDR image using bracketing with your camera and generate an OpenEXR image and then process it using the demo. - - Typical use, supposing that you have the OpenEXR image such as *memorial.exr* (present in the samples/cpp/ folder) - - **OpenCVReleaseFolder/bin/OpenEXRimages_HDR_Retina_toneMapping memorial.exr [optional: 'fast']** - - Note that some sliders are made available to allow you to play with luminance compression. - - If not using the 'fast' option, then, tone mapping is performed using the full retina model [Benoit2010]_. It includes spectral whitening that allows luminance energy to be reduced. When using the 'fast' option, then, a simpler method is used, it is an adaptation of the algorithm presented in [Meylan2007]_. This method gives also good results and is faster to process but it sometimes requires some more parameters adjustement. - - -Methods description -=================== - -Here are detailled the main methods to control the retina model - -Ptr::createRetina -+++++++++++++++++++++++++ - -.. ocv:function:: Ptr createRetina(Size inputSize) -.. ocv:function:: Ptr createRetina(Size inputSize, const bool colorMode, cv::bioinspired::RETINA_COLORSAMPLINGMETHOD colorSamplingMethod = cv::bioinspired::RETINA_COLOR_BAYER, const bool useRetinaLogSampling = false, const double reductionFactor = 1.0, const double samplingStrenght = 10.0 ) - - Constructors from standardized interfaces : retreive a smart pointer to a Retina instance - - :param inputSize: the input frame size - :param colorMode: the chosen processing mode : with or without color processing - :param colorSamplingMethod: specifies which kind of color sampling will be used : - - * cv::bioinspired::RETINA_COLOR_RANDOM: each pixel position is either R, G or B in a random choice - - * cv::bioinspired::RETINA_COLOR_DIAGONAL: color sampling is RGBRGBRGB..., line 2 BRGBRGBRG..., line 3, GBRGBRGBR... - - * cv::bioinspired::RETINA_COLOR_BAYER: standard bayer sampling - - :param useRetinaLogSampling: activate retina log sampling, if true, the 2 following parameters can be used - :param reductionFactor: only usefull if param useRetinaLogSampling=true, specifies the reduction factor of the output frame (as the center (fovea) is high resolution and corners can be underscaled, then a reduction of the output is allowed without precision leak - :param samplingStrenght: only usefull if param useRetinaLogSampling=true, specifies the strenght of the log scale that is applied - -Retina::activateContoursProcessing -++++++++++++++++++++++++++++++++++ - -.. ocv:function:: void Retina::activateContoursProcessing(const bool activate) - - Activate/desactivate the Parvocellular pathway processing (contours information extraction), by default, it is activated - - :param activate: true if Parvocellular (contours information extraction) output should be activated, false if not... if activated, the Parvocellular output can be retrieved using the **getParvo** methods - -Retina::activateMovingContoursProcessing -++++++++++++++++++++++++++++++++++++++++ - -.. ocv:function:: void Retina::activateMovingContoursProcessing(const bool activate) - - Activate/desactivate the Magnocellular pathway processing (motion information extraction), by default, it is activated - - :param activate: true if Magnocellular output should be activated, false if not... if activated, the Magnocellular output can be retrieved using the **getMagno** methods - -Retina::clearBuffers -++++++++++++++++++++ - -.. ocv:function:: void Retina::clearBuffers() - - Clears all retina buffers (equivalent to opening the eyes after a long period of eye close ;o) whatchout the temporal transition occuring just after this method call. - -Retina::getParvo -++++++++++++++++ - -.. ocv:function:: void Retina::getParvo( OutputArray retinaOutput_parvo ) -.. ocv:function:: void Retina::getParvoRAW( OutputArray retinaOutput_parvo ) -.. ocv:function:: const Mat Retina::getParvoRAW() const - - Accessor of the details channel of the retina (models foveal vision). Warning, getParvoRAW methods return buffers that are not rescaled within range [0;255] while the non RAW method allows a normalized matrix to be retrieved. - - :param retinaOutput_parvo: the output buffer (reallocated if necessary), format can be : - - * a Mat, this output is rescaled for standard 8bits image processing use in OpenCV - - * RAW methods actually return a 1D matrix (encoding is R1, R2, ... Rn, G1, G2, ..., Gn, B1, B2, ...Bn), this output is the original retina filter model output, without any quantification or rescaling. - -Retina::getMagno -++++++++++++++++ - -.. ocv:function:: void Retina::getMagno( OutputArray retinaOutput_magno ) -.. ocv:function:: void Retina::getMagnoRAW( OutputArray retinaOutput_magno ) -.. ocv:function:: const Mat Retina::getMagnoRAW() const - - Accessor of the motion channel of the retina (models peripheral vision). Warning, getMagnoRAW methods return buffers that are not rescaled within range [0;255] while the non RAW method allows a normalized matrix to be retrieved. - - :param retinaOutput_magno: the output buffer (reallocated if necessary), format can be : - - * a Mat, this output is rescaled for standard 8bits image processing use in OpenCV - - * RAW methods actually return a 1D matrix (encoding is M1, M2,... Mn), this output is the original retina filter model output, without any quantification or rescaling. - -Retina::getInputSize -++++++++++++++++++++ - -.. ocv:function:: Size Retina::getInputSize() - - Retreive retina input buffer size - - :return: the retina input buffer size - -Retina::getOutputSize -+++++++++++++++++++++ - -.. ocv:function:: Size Retina::getOutputSize() - - Retreive retina output buffer size that can be different from the input if a spatial log transformation is applied - - :return: the retina output buffer size - -Retina::printSetup -++++++++++++++++++ - -.. ocv:function:: const String Retina::printSetup() - - Outputs a string showing the used parameters setup - - :return: a string which contains formated parameters information - -Retina::run -+++++++++++ - -.. ocv:function:: void Retina::run(InputArray inputImage) - - Method which allows retina to be applied on an input image, after run, encapsulated retina module is ready to deliver its outputs using dedicated acccessors, see getParvo and getMagno methods - - :param inputImage: the input Mat image to be processed, can be gray level or BGR coded in any format (from 8bit to 16bits) - -Retina::applyFastToneMapping -++++++++++++++++++++++++++++ - -.. ocv:function:: void Retina::applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage) - - Method which processes an image in the aim to correct its luminance : correct backlight problems, enhance details in shadows. This method is designed to perform High Dynamic Range image tone mapping (compress >8bit/pixel images to 8bit/pixel). This is a simplified version of the Retina Parvocellular model (simplified version of the run/getParvo methods call) since it does not include the spatio-temporal filter modelling the Outer Plexiform Layer of the retina that performs spectral whitening and many other stuff. However, it works great for tone mapping and in a faster way. - - Check the demos and experiments section to see examples and the way to perform tone mapping using the original retina model and the method. - - :param inputImage: the input image to process (should be coded in float format : CV_32F, CV_32FC1, CV_32F_C3, CV_32F_C4, the 4th channel won't be considered). - :param outputToneMappedImage: the output 8bit/channel tone mapped image (CV_8U or CV_8UC3 format). - -Retina::setColorSaturation -++++++++++++++++++++++++++ - -.. ocv:function:: void Retina::setColorSaturation(const bool saturateColors = true, const float colorSaturationValue = 4.0 ) - - Activate color saturation as the final step of the color demultiplexing process -> this saturation is a sigmoide function applied to each channel of the demultiplexed image. - - :param saturateColors: boolean that activates color saturation (if true) or desactivate (if false) - :param colorSaturationValue: the saturation factor : a simple factor applied on the chrominance buffers - - -Retina::setup -+++++++++++++ - -.. ocv:function:: void Retina::setup(String retinaParameterFile = "", const bool applyDefaultSetupOnFailure = true ) -.. ocv:function:: void Retina::setup(FileStorage & fs, const bool applyDefaultSetupOnFailure = true ) -.. ocv:function:: void Retina::setup(RetinaParameters newParameters) - - Try to open an XML retina parameters file to adjust current retina instance setup => if the xml file does not exist, then default setup is applied => warning, Exceptions are thrown if read XML file is not valid - - :param retinaParameterFile: the parameters filename - :param applyDefaultSetupOnFailure: set to true if an error must be thrown on error - :param fs: the open Filestorage which contains retina parameters - :param newParameters: a parameters structures updated with the new target configuration. You can retreive the current parameers structure using method *Retina::RetinaParameters Retina::getParameters()* and update it before running method *setup*. - -Retina::write -+++++++++++++ - -.. ocv:function:: void Retina::write( String fs ) const -.. ocv:function:: void Retina::write( FileStorage& fs ) const - - Write xml/yml formated parameters information - - :param fs: the filename of the xml file that will be open and writen with formatted parameters information - -Retina::setupIPLMagnoChannel -++++++++++++++++++++++++++++ - -.. ocv:function:: void Retina::setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta = 0, const float parasolCells_tau = 0, const float parasolCells_k = 7, const float amacrinCellsTemporalCutFrequency = 1.2, const float V0CompressionParameter = 0.95, const float localAdaptintegration_tau = 0, const float localAdaptintegration_k = 7 ) - - Set parameters values for the Inner Plexiform Layer (IPL) magnocellular channel this channel processes signals output from OPL processing stage in peripheral vision, it allows motion information enhancement. It is decorrelated from the details channel. See reference papers for more details. - - :param normaliseOutput: specifies if (true) output is rescaled between 0 and 255 of not (false) - :param parasolCells_beta: the low pass filter gain used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), typical value is 0 - :param parasolCells_tau: the low pass filter time constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is frame, typical value is 0 (immediate response) - :param parasolCells_k: the low pass filter spatial constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is pixels, typical value is 5 - :param amacrinCellsTemporalCutFrequency: the time constant of the first order high pass fiter of the magnocellular way (motion information channel), unit is frames, typical value is 1.2 - :param V0CompressionParameter: the compression strengh of the ganglion cells local adaptation output, set a value between 0.6 and 1 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 0.95 - :param localAdaptintegration_tau: specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation - :param localAdaptintegration_k: specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation - -Retina::setupOPLandIPLParvoChannel -++++++++++++++++++++++++++++++++++ - -.. ocv:function:: void Retina::setupOPLandIPLParvoChannel(const bool colorMode = true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity = 0.7, const float photoreceptorsTemporalConstant = 0.5, const float photoreceptorsSpatialConstant = 0.53, const float horizontalCellsGain = 0, const float HcellsTemporalConstant = 1, const float HcellsSpatialConstant = 7, const float ganglionCellsSensitivity = 0.7 ) - - Setup the OPL and IPL parvo channels (see biologocal model) OPL is referred as Outer Plexiform Layer of the retina, it allows the spatio-temporal filtering which withens the spectrum and reduces spatio-temporal noise while attenuating global luminance (low frequency energy) IPL parvo is the OPL next processing stage, it refers to a part of the Inner Plexiform layer of the retina, it allows high contours sensitivity in foveal vision. See reference papers for more informations. - - :param colorMode: specifies if (true) color is processed of not (false) to then processing gray level image - :param normaliseOutput: specifies if (true) output is rescaled between 0 and 255 of not (false) - :param photoreceptorsLocalAdaptationSensitivity: the photoreceptors sensitivity renage is 0-1 (more log compression effect when value increases) - :param photoreceptorsTemporalConstant: the time constant of the first order low pass filter of the photoreceptors, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 1 frame - :param photoreceptorsSpatialConstant: the spatial constant of the first order low pass filter of the photoreceptors, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 1 pixel - :param horizontalCellsGain: gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, then, the luminance is not filtered and is still reachable at the output, typicall value is 0 - :param HcellsTemporalConstant: the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors - :param HcellsSpatialConstant: the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model) - :param ganglionCellsSensitivity: the compression strengh of the ganglion cells local adaptation output, set a value between 0.6 and 1 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 0.7 - - -Retina::RetinaParameters -======================== - -.. ocv:struct:: Retina::RetinaParameters - - This structure merges all the parameters that can be adjusted threw the **Retina::setup()**, **Retina::setupOPLandIPLParvoChannel** and **Retina::setupIPLMagnoChannel** setup methods - Parameters structure for better clarity, check explenations on the comments of methods : setupOPLandIPLParvoChannel and setupIPLMagnoChannel. :: - - class RetinaParameters{ - struct OPLandIplParvoParameters{ // Outer Plexiform Layer (OPL) and Inner Plexiform Layer Parvocellular (IplParvo) parameters - OPLandIplParvoParameters():colorMode(true), - normaliseOutput(true), // specifies if (true) output is rescaled between 0 and 255 of not (false) - photoreceptorsLocalAdaptationSensitivity(0.7f), // the photoreceptors sensitivity renage is 0-1 (more log compression effect when value increases) - photoreceptorsTemporalConstant(0.5f),// the time constant of the first order low pass filter of the photoreceptors, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 1 frame - photoreceptorsSpatialConstant(0.53f),// the spatial constant of the first order low pass filter of the photoreceptors, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 1 pixel - horizontalCellsGain(0.0f),//gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, then, the luminance is not filtered and is still reachable at the output, typicall value is 0 - hcellsTemporalConstant(1.f),// the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors. Reduce to 0.5 to limit retina after effects. - hcellsSpatialConstant(7.f),//the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model) - ganglionCellsSensitivity(0.7f)//the compression strengh of the ganglion cells local adaptation output, set a value between 0.6 and 1 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 0.7 - {};// default setup - bool colorMode, normaliseOutput; - float photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, hcellsTemporalConstant, hcellsSpatialConstant, ganglionCellsSensitivity; - }; - struct IplMagnoParameters{ // Inner Plexiform Layer Magnocellular channel (IplMagno) - IplMagnoParameters(): - normaliseOutput(true), //specifies if (true) output is rescaled between 0 and 255 of not (false) - parasolCells_beta(0.f), // the low pass filter gain used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), typical value is 0 - parasolCells_tau(0.f), //the low pass filter time constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is frame, typical value is 0 (immediate response) - parasolCells_k(7.f), //the low pass filter spatial constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is pixels, typical value is 5 - amacrinCellsTemporalCutFrequency(1.2f), //the time constant of the first order high pass fiter of the magnocellular way (motion information channel), unit is frames, typical value is 1.2 - V0CompressionParameter(0.95f), the compression strengh of the ganglion cells local adaptation output, set a value between 0.6 and 1 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 0.95 - localAdaptintegration_tau(0.f), // specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation - localAdaptintegration_k(7.f) // specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation - {};// default setup - bool normaliseOutput; - float parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k; - }; - struct OPLandIplParvoParameters OPLandIplParvo; - struct IplMagnoParameters IplMagno; - }; - -Retina parameters files examples -++++++++++++++++++++++++++++++++ - -Here is the default configuration file of the retina module. It gives results such as the first retina output shown on the top of this page. - -.. code-block:: cpp - - - - - 1 - 1 - 7.5e-01 - 9.0e-01 - 5.3e-01 - 0.01 - 0.5 - 7. - 7.5e-01 - - 1 - 0. - 0. - 7. - 2.0e+00 - 9.5e-01 - 0. - 7. - - -Here is the 'realistic" setup used to obtain the second retina output shown on the top of this page. - -.. code-block:: cpp - - - - - 1 - 1 - 8.9e-01 - 9.0e-01 - 5.3e-01 - 0.3 - 0.5 - 7. - 8.9e-01 - - 1 - 0. - 0. - 7. - 2.0e+00 - 9.5e-01 - 0. - 7. - diff --git a/modules/bioinspired/include/opencv2/bioinspired.hpp b/modules/bioinspired/include/opencv2/bioinspired.hpp deleted file mode 100644 index 5f2f8644d..000000000 --- a/modules/bioinspired/include/opencv2/bioinspired.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/*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) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., 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_BIOINSPIRED_HPP__ -#define __OPENCV_BIOINSPIRED_HPP__ - -#include "opencv2/core.hpp" -#include "opencv2/bioinspired/retina.hpp" -#include "opencv2/bioinspired/retinafasttonemapping.hpp" - -#endif diff --git a/modules/bioinspired/include/opencv2/bioinspired/bioinspired.hpp b/modules/bioinspired/include/opencv2/bioinspired/bioinspired.hpp deleted file mode 100644 index 40be2854e..000000000 --- a/modules/bioinspired/include/opencv2/bioinspired/bioinspired.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/*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) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. -// 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*/ - -#ifdef __OPENCV_BUILD -#error this is a compatibility header which should not be used inside the OpenCV library -#endif - -#include "opencv2/bioinspired.hpp" diff --git a/modules/bioinspired/include/opencv2/bioinspired/retina.hpp b/modules/bioinspired/include/opencv2/bioinspired/retina.hpp deleted file mode 100644 index c9655c4a9..000000000 --- a/modules/bioinspired/include/opencv2/bioinspired/retina.hpp +++ /dev/null @@ -1,311 +0,0 @@ -/*#****************************************************************************** - ** 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. - ** - ** - ** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. - ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. - ** - ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) - ** - ** Creation - enhancement process 2007-2013 - ** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France - ** - ** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). - ** Refer to the following research paper for more information: - ** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 - ** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: - ** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. - ** - ** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : - ** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: - ** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 - ** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. - ** ====> more informations in the above cited Jeanny Heraults's book. - ** - ** License Agreement - ** For Open Source Computer Vision Library - ** - ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. - ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. - ** - ** For Human Visual System tools (bioinspired) - ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: - ** - ** * Redistributions of source code must retain the above copyright notice, - ** this list of conditions and the following disclaimer. - ** - ** * Redistributions 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. - *******************************************************************************/ - -#ifndef __OPENCV_BIOINSPIRED_RETINA_HPP__ -#define __OPENCV_BIOINSPIRED_RETINA_HPP__ - -/* - * Retina.hpp - * - * Created on: Jul 19, 2011 - * Author: Alexandre Benoit - */ - -#include "opencv2/core.hpp" // for all OpenCV core functionalities access, including cv::Exception support - - -namespace cv{ -namespace bioinspired{ - -enum { - RETINA_COLOR_RANDOM, //!< each pixel position is either R, G or B in a random choice - RETINA_COLOR_DIAGONAL,//!< color sampling is RGBRGBRGB..., line 2 BRGBRGBRG..., line 3, GBRGBRGBR... - RETINA_COLOR_BAYER//!< standard bayer sampling -}; - -/** - * @class Retina a wrapper class which allows the Gipsa/Listic Labs model to be used with OpenCV. - * This retina model allows spatio-temporal image processing (applied on still images, video sequences). - * As a summary, these are the retina model properties: - * => It applies a spectral whithening (mid-frequency details enhancement) - * => high frequency spatio-temporal noise reduction - * => low frequency luminance to be reduced (luminance range compression) - * => local logarithmic luminance compression allows details to be enhanced in low light conditions - * - * USE : this model can be used basically for spatio-temporal video effects but also for : - * _using the getParvo method output matrix : texture analysiswith enhanced signal to noise ratio and enhanced details robust against input images luminance ranges - * _using the getMagno method output matrix : motion analysis also with the previously cited properties - * - * for more information, reer to the following papers : - * Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 - * Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. - * - * The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : - * _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: - * ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 - * _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. - * ====> more informations in the above cited Jeanny Heraults's book. - */ -class CV_EXPORTS Retina : public Algorithm { - -public: - - // parameters structure for better clarity, check explenations on the comments of methods : setupOPLandIPLParvoChannel and setupIPLMagnoChannel - struct RetinaParameters{ - struct OPLandIplParvoParameters{ // Outer Plexiform Layer (OPL) and Inner Plexiform Layer Parvocellular (IplParvo) parameters - OPLandIplParvoParameters():colorMode(true), - normaliseOutput(true), - photoreceptorsLocalAdaptationSensitivity(0.75f), - photoreceptorsTemporalConstant(0.9f), - photoreceptorsSpatialConstant(0.53f), - horizontalCellsGain(0.01f), - hcellsTemporalConstant(0.5f), - hcellsSpatialConstant(7.f), - ganglionCellsSensitivity(0.75f) { } // default setup - bool colorMode, normaliseOutput; - float photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, hcellsTemporalConstant, hcellsSpatialConstant, ganglionCellsSensitivity; - }; - struct IplMagnoParameters{ // Inner Plexiform Layer Magnocellular channel (IplMagno) - IplMagnoParameters(): - normaliseOutput(true), - parasolCells_beta(0.f), - parasolCells_tau(0.f), - parasolCells_k(7.f), - amacrinCellsTemporalCutFrequency(2.0f), - V0CompressionParameter(0.95f), - localAdaptintegration_tau(0.f), - localAdaptintegration_k(7.f) { } // default setup - bool normaliseOutput; - float parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k; - }; - struct OPLandIplParvoParameters OPLandIplParvo; - struct IplMagnoParameters IplMagno; - }; - - /** - * retreive retina input buffer size - */ - virtual Size getInputSize()=0; - - /** - * retreive retina output buffer size - */ - virtual Size getOutputSize()=0; - - /** - * try to open an XML retina parameters file to adjust current retina instance setup - * => if the xml file does not exist, then default setup is applied - * => warning, Exceptions are thrown if read XML file is not valid - * @param retinaParameterFile : the parameters filename - * @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error - */ - virtual void setup(String retinaParameterFile="", const bool applyDefaultSetupOnFailure=true)=0; - - /** - * try to open an XML retina parameters file to adjust current retina instance setup - * => if the xml file does not exist, then default setup is applied - * => warning, Exceptions are thrown if read XML file is not valid - * @param fs : the open Filestorage which contains retina parameters - * @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error - */ - virtual void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure=true)=0; - - /** - * try to open an XML retina parameters file to adjust current retina instance setup - * => if the xml file does not exist, then default setup is applied - * => warning, Exceptions are thrown if read XML file is not valid - * @param newParameters : a parameters structures updated with the new target configuration - * @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error - */ - virtual void setup(RetinaParameters newParameters)=0; - - /** - * @return the current parameters setup - */ - virtual struct Retina::RetinaParameters getParameters()=0; - - /** - * parameters setup display method - * @return a string which contains formatted parameters information - */ - virtual const String printSetup()=0; - - /** - * write xml/yml formated parameters information - * @rparam fs : the filename of the xml file that will be open and writen with formatted parameters information - */ - virtual void write( String fs ) const=0; - - /** - * write xml/yml formated parameters information - * @param fs : a cv::Filestorage object ready to be filled - */ - virtual void write( FileStorage& fs ) const=0; - - /** - * setup the OPL and IPL parvo channels (see biologocal model) - * OPL is referred as Outer Plexiform Layer of the retina, it allows the spatio-temporal filtering which withens the spectrum and reduces spatio-temporal noise while attenuating global luminance (low frequency energy) - * IPL parvo is the OPL next processing stage, it refers to Inner Plexiform layer of the retina, it allows high contours sensitivity in foveal vision. - * for more informations, please have a look at the paper Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 - * @param colorMode : specifies if (true) color is processed of not (false) to then processing gray level image - * @param normaliseOutput : specifies if (true) output is rescaled between 0 and 255 of not (false) - * @param photoreceptorsLocalAdaptationSensitivity: the photoreceptors sensitivity renage is 0-1 (more log compression effect when value increases) - * @param photoreceptorsTemporalConstant: the time constant of the first order low pass filter of the photoreceptors, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 1 frame - * @param photoreceptorsSpatialConstant: the spatial constant of the first order low pass filter of the photoreceptors, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 1 pixel - * @param horizontalCellsGain: gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, then, the luminance is not filtered and is still reachable at the output, typicall value is 0 - * @param HcellsTemporalConstant: the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors - * @param HcellsSpatialConstant: the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model) - * @param ganglionCellsSensitivity: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 230 - */ - virtual void setupOPLandIPLParvoChannel(const bool colorMode=true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity=0.7, const float photoreceptorsTemporalConstant=0.5, const float photoreceptorsSpatialConstant=0.53, const float horizontalCellsGain=0, const float HcellsTemporalConstant=1, const float HcellsSpatialConstant=7, const float ganglionCellsSensitivity=0.7)=0; - - /** - * set parameters values for the Inner Plexiform Layer (IPL) magnocellular channel - * this channel processes signals outpint from OPL processing stage in peripheral vision, it allows motion information enhancement. It is decorrelated from the details channel. See reference paper for more details. - * @param normaliseOutput : specifies if (true) output is rescaled between 0 and 255 of not (false) - * @param parasolCells_beta: the low pass filter gain used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), typical value is 0 - * @param parasolCells_tau: the low pass filter time constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is frame, typical value is 0 (immediate response) - * @param parasolCells_k: the low pass filter spatial constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is pixels, typical value is 5 - * @param amacrinCellsTemporalCutFrequency: the time constant of the first order high pass fiter of the magnocellular way (motion information channel), unit is frames, tipicall value is 5 - * @param V0CompressionParameter: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 200 - * @param localAdaptintegration_tau: specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation - * @param localAdaptintegration_k: specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation - */ - virtual void setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta=0, const float parasolCells_tau=0, const float parasolCells_k=7, const float amacrinCellsTemporalCutFrequency=1.2, const float V0CompressionParameter=0.95, const float localAdaptintegration_tau=0, const float localAdaptintegration_k=7)=0; - - /** - * method which allows retina to be applied on an input image, after run, encapsulated retina module is ready to deliver its outputs using dedicated acccessors, see getParvo and getMagno methods - * @param inputImage : the input cv::Mat image to be processed, can be gray level or BGR coded in any format (from 8bit to 16bits) - */ - virtual void run(InputArray inputImage)=0; - - /** - * method that applies a luminance correction (initially High Dynamic Range (HDR) tone mapping) using only the 2 local adaptation stages of the retina parvo channel : photoreceptors level and ganlion cells level. Spatio temporal filtering is applied but limited to temporal smoothing and eventually high frequencies attenuation. This is a lighter method than the one available using the regular run method. It is then faster but it does not include complete temporal filtering nor retina spectral whitening. Then, it can have a more limited effect on images with a very high dynamic range. This is an adptation of the original still image HDR tone mapping algorithm of David Alleyson, Sabine Susstruck and Laurence Meylan's work, please cite: - * -> Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 - @param inputImage the input image to process RGB or gray levels - @param outputToneMappedImage the output tone mapped image - */ - virtual void applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage)=0; - - /** - * accessor of the details channel of the retina (models foveal vision) - * @param retinaOutput_parvo : the output buffer (reallocated if necessary), this output is rescaled for standard 8bits image processing use in OpenCV - */ - virtual void getParvo(OutputArray retinaOutput_parvo)=0; - - /** - * accessor of the details channel of the retina (models foveal vision) - * @param retinaOutput_parvo : a cv::Mat header filled with the internal parvo buffer of the retina module. This output is the original retina filter model output, without any quantification or rescaling - */ - virtual void getParvoRAW(OutputArray retinaOutput_parvo)=0; - - /** - * accessor of the motion channel of the retina (models peripheral vision) - * @param retinaOutput_magno : the output buffer (reallocated if necessary), this output is rescaled for standard 8bits image processing use in OpenCV - */ - virtual void getMagno(OutputArray retinaOutput_magno)=0; - - /** - * accessor of the motion channel of the retina (models peripheral vision) - * @param retinaOutput_magno : a cv::Mat header filled with the internal retina magno buffer of the retina module. This output is the original retina filter model output, without any quantification or rescaling - */ - virtual void getMagnoRAW(OutputArray retinaOutput_magno)=0; - - // original API level data accessors : get buffers addresses from a Mat header, similar to getParvoRAW and getMagnoRAW... - virtual const Mat getMagnoRAW() const=0; - virtual const Mat getParvoRAW() const=0; - - /** - * activate color saturation as the final step of the color demultiplexing process - * -> this saturation is a sigmoide function applied to each channel of the demultiplexed image. - * @param saturateColors: boolean that activates color saturation (if true) or desactivate (if false) - * @param colorSaturationValue: the saturation factor - */ - virtual void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0)=0; - - /** - * clear all retina buffers (equivalent to opening the eyes after a long period of eye close ;o) - */ - virtual void clearBuffers()=0; - - /** - * Activate/desactivate the Magnocellular pathway processing (motion information extraction), by default, it is activated - * @param activate: true if Magnocellular output should be activated, false if not - */ - virtual void activateMovingContoursProcessing(const bool activate)=0; - - /** - * Activate/desactivate the Parvocellular pathway processing (contours information extraction), by default, it is activated - * @param activate: true if Parvocellular (contours information extraction) output should be activated, false if not - */ - virtual void activateContoursProcessing(const bool activate)=0; -}; -CV_EXPORTS Ptr createRetina(Size inputSize); -CV_EXPORTS Ptr createRetina(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); - -CV_EXPORTS Ptr createRetina_OCL(Size inputSize); -CV_EXPORTS Ptr createRetina_OCL(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); -} -} -#endif /* __OPENCV_BIOINSPIRED_RETINA_HPP__ */ diff --git a/modules/bioinspired/include/opencv2/bioinspired/retinafasttonemapping.hpp b/modules/bioinspired/include/opencv2/bioinspired/retinafasttonemapping.hpp deleted file mode 100644 index 6c83f885c..000000000 --- a/modules/bioinspired/include/opencv2/bioinspired/retinafasttonemapping.hpp +++ /dev/null @@ -1,121 +0,0 @@ - -/*#****************************************************************************** - ** 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. - ** - ** - ** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. - ** - ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) - ** - ** Creation - enhancement process 2007-2013 - ** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France - ** - ** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). - ** Refer to the following research paper for more information: - ** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 - ** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: - ** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. - ** - ** - ** - ** - ** - ** This class is based on image processing tools of the author and already used within the Retina class (this is the same code as method retina::applyFastToneMapping, but in an independent class, it is ligth from a memory requirement point of view). It implements an adaptation of the efficient tone mapping algorithm propose by David Alleyson, Sabine Susstruck and Laurence Meylan's work, please cite: - ** -> Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 - ** - ** - ** License Agreement - ** For Open Source Computer Vision Library - ** - ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. - ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. - ** - ** For Human Visual System tools (bioinspired) - ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: - ** - ** * Redistributions of source code must retain the above copyright notice, - ** this list of conditions and the following disclaimer. - ** - ** * Redistributions 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. - *******************************************************************************/ - -#ifndef __OPENCV_BIOINSPIRED_RETINAFASTTONEMAPPING_HPP__ -#define __OPENCV_BIOINSPIRED_RETINAFASTTONEMAPPING_HPP__ - -/* - * retinafasttonemapping.hpp - * - * Created on: May 26, 2013 - * Author: Alexandre Benoit - */ - -#include "opencv2/core.hpp" // for all OpenCV core functionalities access, including cv::Exception support - -namespace cv{ -namespace bioinspired{ - -/** - * @class RetinaFastToneMappingImpl a wrapper class which allows the tone mapping algorithm of Meylan&al(2007) to be used with OpenCV. - * This algorithm is already implemented in thre Retina class (retina::applyFastToneMapping) but used it does not require all the retina model to be allocated. This allows a light memory use for low memory devices (smartphones, etc. - * As a summary, these are the model properties: - * => 2 stages of local luminance adaptation with a different local neighborhood for each. - * => first stage models the retina photorecetors local luminance adaptation - * => second stage models th ganglion cells local information adaptation - * => compared to the initial publication, this class uses spatio-temporal low pass filters instead of spatial only filters. - * ====> this can help noise robustness and temporal stability for video sequence use cases. - * for more information, read to the following papers : - * Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 - * regarding spatio-temporal filter and the bigger retina model : - * Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. - */ -class CV_EXPORTS RetinaFastToneMapping : public Algorithm -{ -public: - - /** - * method that applies a luminance correction (initially High Dynamic Range (HDR) tone mapping) using only the 2 local adaptation stages of the retina parvocellular channel : photoreceptors level and ganlion cells level. Spatio temporal filtering is applied but limited to temporal smoothing and eventually high frequencies attenuation. This is a lighter method than the one available using the regular retina::run method. It is then faster but it does not include complete temporal filtering nor retina spectral whitening. Then, it can have a more limited effect on images with a very high dynamic range. This is an adptation of the original still image HDR tone mapping algorithm of David Alleyson, Sabine Susstruck and Laurence Meylan's work, please cite: - * -> Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 - @param inputImage the input image to process RGB or gray levels - @param outputToneMappedImage the output tone mapped image - */ - virtual void applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage)=0; - - /** - * setup method that updates tone mapping behaviors by adjusing the local luminance computation area - * @param photoreceptorsNeighborhoodRadius the first stage local adaptation area - * @param ganglioncellsNeighborhoodRadius the second stage local adaptation area - * @param meanLuminanceModulatorK the factor applied to modulate the meanLuminance information (default is 1, see reference paper) - */ - virtual void setup(const float photoreceptorsNeighborhoodRadius=3.f, const float ganglioncellsNeighborhoodRadius=1.f, const float meanLuminanceModulatorK=1.f)=0; -}; - -CV_EXPORTS Ptr createRetinaFastToneMapping(Size inputSize); - -} -} -#endif /* __OPENCV_BIOINSPIRED_RETINAFASTTONEMAPPING_HPP__ */ diff --git a/modules/bioinspired/src/basicretinafilter.cpp b/modules/bioinspired/src/basicretinafilter.cpp deleted file mode 100644 index 7e7b467fa..000000000 --- a/modules/bioinspired/src/basicretinafilter.cpp +++ /dev/null @@ -1,888 +0,0 @@ -/*#****************************************************************************** -** 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. -** -** -** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. -** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. -** -** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) -** -** Creation - enhancement process 2007-2011 -** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France -** -** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). -** Refer to the following research paper for more information: -** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 -** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: -** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. -** -** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : -** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: -** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. -** ====> more informations in the above cited Jeanny Heraults's book. -** -** License Agreement -** For Open Source Computer Vision Library -** -** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** -** For Human Visual System tools (bioinspired) -** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions 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. -*******************************************************************************/ - -#include "precomp.hpp" - -#include -#include -#include "basicretinafilter.hpp" -#include - - -namespace cv -{ -namespace bioinspired -{ -// @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC : www.listic.univ-savoie.fr Gipsa-Lab, France: www.gipsa-lab.inpg.fr/ - -////////////////////////////////////////////////////////// -// BASIC RETINA FILTER -////////////////////////////////////////////////////////// - -// Constructor and Desctructor of the basic retina filter -BasicRetinaFilter::BasicRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns, const unsigned int parametersListSize, const bool useProgressiveFilter) -:_filterOutput(NBrows, NBcolumns), - _localBuffer(NBrows*NBcolumns), - _filteringCoeficientsTable(3*parametersListSize), - _progressiveSpatialConstant(0),// pointer to a local table containing local spatial constant (allocated with the object) - _progressiveGain(0) -{ -#ifdef T_BASIC_RETINA_ELEMENT_DEBUG - std::cout<<"BasicRetinaFilter::BasicRetinaFilter: new filter, size="<0) - { - _progressiveSpatialConstant.resize(_filterOutput.size()); - _progressiveGain.resize(_filterOutput.size()); - } - // reset buffers - clearAllBuffers(); -} - -// Change coefficients table -void BasicRetinaFilter::setLPfilterParameters(const float beta, const float tau, const float desired_k, const unsigned int filterIndex) -{ - float _beta = beta+tau; - float k=desired_k; - // check if the spatial constant is correct (avoid 0 value to avoid division by 0) - if (desired_k<=0) - { - k=0.001f; - std::cerr<<"BasicRetinaFilter::spatial constant of the low pass filter must be superior to zero !!! correcting parameter setting to 0,001"< old:"<<(1-a)*(1-a)*(1-a)*(1-a)/(1+_beta)<1.0f) - localSpatialConstantValue=1.0f; - - _progressiveSpatialConstant[_halfNBcolumns-1+idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1+idRow)]=localSpatialConstantValue; - _progressiveSpatialConstant[_halfNBcolumns-1-idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1+idRow)]=localSpatialConstantValue; - _progressiveSpatialConstant[_halfNBcolumns-1+idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1-idRow)]=localSpatialConstantValue; - _progressiveSpatialConstant[_halfNBcolumns-1-idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1-idRow)]=localSpatialConstantValue; - - // computing local gain - float localGain=(1-localSpatialConstantValue)*(1-localSpatialConstantValue)*(1-localSpatialConstantValue)*(1-localSpatialConstantValue)/(1+_beta); - _progressiveGain[_halfNBcolumns-1+idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1+idRow)]=localGain; - _progressiveGain[_halfNBcolumns-1-idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1+idRow)]=localGain; - _progressiveGain[_halfNBcolumns-1+idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1-idRow)]=localGain; - _progressiveGain[_halfNBcolumns-1-idColumn+_filterOutput.getNBcolumns()*(_halfNBrows-1-idRow)]=localGain; - - //std::cout< &accuracyMap, const unsigned int filterIndex) -{ - - if (accuracyMap.size()!=_filterOutput.size()) - { - std::cerr<<"BasicRetinaFilter::setProgressiveFilterConstants_CustomAccuracy: error: input accuracy map does not match filter size, init skept"<1) - localSpatialConstantValue=1; - - _progressiveSpatialConstant[index]=localSpatialConstantValue; - - // computing local gain - float localGain=(1.0f-localSpatialConstantValue)*(1.0f-localSpatialConstantValue)*(1.0f-localSpatialConstantValue)*(1.0f-localSpatialConstantValue)/(1.0f+_beta); - _progressiveGain[index]=localGain; - - //std::cout< &BasicRetinaFilter::runFilter_LocalAdapdation(const std::valarray &inputFrame, const std::valarray &localLuminance) -{ - _localLuminanceAdaptation(get_data(inputFrame), get_data(localLuminance), &_filterOutput[0]); - return _filterOutput; -} -// run local adaptation filter at a specific output adress -void BasicRetinaFilter::runFilter_LocalAdapdation(const std::valarray &inputFrame, const std::valarray &localLuminance, std::valarray &outputFrame) -{ - _localLuminanceAdaptation(get_data(inputFrame), get_data(localLuminance), &outputFrame[0]); -} -// run local adaptation filter and save result in _filterOutput with autonomous low pass filtering before adaptation -const std::valarray &BasicRetinaFilter::runFilter_LocalAdapdation_autonomous(const std::valarray &inputFrame) -{ - _spatiotemporalLPfilter(get_data(inputFrame), &_filterOutput[0]); - _localLuminanceAdaptation(get_data(inputFrame), &_filterOutput[0], &_filterOutput[0]); - return _filterOutput; -} -// run local adaptation filter at a specific output adress with autonomous low pass filtering before adaptation -void BasicRetinaFilter::runFilter_LocalAdapdation_autonomous(const std::valarray &inputFrame, std::valarray &outputFrame) -{ - _spatiotemporalLPfilter(get_data(inputFrame), &_filterOutput[0]); - _localLuminanceAdaptation(get_data(inputFrame), &_filterOutput[0], &outputFrame[0]); -} - -// local luminance adaptation of the input in regard of localLuminance buffer, the input is rewrited and becomes the output -void BasicRetinaFilter::_localLuminanceAdaptation(float *inputOutputFrame, const float *localLuminance) -{ - _localLuminanceAdaptation(inputOutputFrame, localLuminance, inputOutputFrame, false); - - /* const float *localLuminancePTR=localLuminance; - float *inputOutputFramePTR=inputOutputFrame; - - for (register unsigned int IDpixel=0 ; IDpixel<_filterOutput.getNBpixels() ; ++IDpixel, ++inputOutputFramePTR) - { - float X0=*(localLuminancePTR++)*_localLuminanceFactor+_localLuminanceAddon; - *(inputOutputFramePTR) = (_maxInputValue+X0)**inputOutputFramePTR/(*inputOutputFramePTR +X0+0.00000000001); - } - */ -} - -// local luminance adaptation of the input in regard of localLuminance buffer -void BasicRetinaFilter::_localLuminanceAdaptation(const float *inputFrame, const float *localLuminance, float *outputFrame, const bool updateLuminanceMean) -{ - if (updateLuminanceMean) - { float meanLuminance=0; - const float *luminancePTR=inputFrame; - for (unsigned int i=0;i<_filterOutput.getNBpixels();++i) - meanLuminance+=*(luminancePTR++); - meanLuminance/=_filterOutput.getNBpixels(); - //float tempMeanValue=meanLuminance+_meanInputValue*_tau; - updateCompressionParameter(meanLuminance); - } -#ifdef MAKE_PARALLEL - cv::parallel_for_(cv::Range(0,_filterOutput.getNBpixels()), Parallel_localAdaptation(localLuminance, inputFrame, outputFrame, _localLuminanceFactor, _localLuminanceAddon, _maxInputValue)); -#else - //std::cout< &BasicRetinaFilter::runFilter_LPfilter(const std::valarray &inputFrame, const unsigned int filterIndex) -{ - _spatiotemporalLPfilter(get_data(inputFrame), &_filterOutput[0], filterIndex); - return _filterOutput; -} - -// run LP filter for a new frame input and save result at a specific output adress -void BasicRetinaFilter::runFilter_LPfilter(const std::valarray &inputFrame, std::valarray &outputFrame, const unsigned int filterIndex) -{ - _spatiotemporalLPfilter(get_data(inputFrame), &outputFrame[0], filterIndex); -} - -// run LP filter on the input data and rewrite it -void BasicRetinaFilter::runFilter_LPfilter_Autonomous(std::valarray &inputOutputFrame, const unsigned int filterIndex) -{ - unsigned int coefTableOffset=filterIndex*3; - - /**********/ - _a=_filteringCoeficientsTable[coefTableOffset]; - _gain=_filteringCoeficientsTable[1+coefTableOffset]; - _tau=_filteringCoeficientsTable[2+coefTableOffset]; - - // launch the serie of 1D directional filters in order to compute the 2D low pass filter - _horizontalCausalFilter(&inputOutputFrame[0], 0, _filterOutput.getNBrows()); - _horizontalAnticausalFilter(&inputOutputFrame[0], 0, _filterOutput.getNBrows()); - _verticalCausalFilter(&inputOutputFrame[0], 0, _filterOutput.getNBcolumns()); - _verticalAnticausalFilter_multGain(&inputOutputFrame[0], 0, _filterOutput.getNBcolumns()); - -} -// run LP filter for a new frame input and save result at a specific output adress -void BasicRetinaFilter::_spatiotemporalLPfilter(const float *inputFrame, float *outputFrame, const unsigned int filterIndex) -{ - unsigned int coefTableOffset=filterIndex*3; - /**********/ - _a=_filteringCoeficientsTable[coefTableOffset]; - _gain=_filteringCoeficientsTable[1+coefTableOffset]; - _tau=_filteringCoeficientsTable[2+coefTableOffset]; - - // launch the serie of 1D directional filters in order to compute the 2D low pass filter - _horizontalCausalFilter_addInput(inputFrame, outputFrame, 0,_filterOutput.getNBrows()); - _horizontalAnticausalFilter(outputFrame, 0, _filterOutput.getNBrows()); - _verticalCausalFilter(outputFrame, 0, _filterOutput.getNBcolumns()); - _verticalAnticausalFilter_multGain(outputFrame, 0, _filterOutput.getNBcolumns()); - -} - -// run SQUARING LP filter for a new frame input and save result at a specific output adress -float BasicRetinaFilter::_squaringSpatiotemporalLPfilter(const float *inputFrame, float *outputFrame, const unsigned int filterIndex) -{ - unsigned int coefTableOffset=filterIndex*3; - /**********/ - _a=_filteringCoeficientsTable[coefTableOffset]; - _gain=_filteringCoeficientsTable[1+coefTableOffset]; - _tau=_filteringCoeficientsTable[2+coefTableOffset]; - - // launch the serie of 1D directional filters in order to compute the 2D low pass filter - - _squaringHorizontalCausalFilter(inputFrame, outputFrame, 0, _filterOutput.getNBrows()); - _horizontalAnticausalFilter(outputFrame, 0, _filterOutput.getNBrows()); - _verticalCausalFilter(outputFrame, 0, _filterOutput.getNBcolumns()); - return _verticalAnticausalFilter_returnMeanValue(outputFrame, 0, _filterOutput.getNBcolumns()); -} - -///////////////////////////////////////////////// -// standard version of the 1D low pass filters - -// horizontal causal filter which adds the input inside -void BasicRetinaFilter::_horizontalCausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd) -{ - - - //#pragma omp parallel for - for (unsigned int IDrow=IDrowStart; IDrow squaring horizontal causal filter -void BasicRetinaFilter::_squaringHorizontalCausalFilter(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd) -{ - register float* outputPTR=outputFrame+IDrowStart*_filterOutput.getNBcolumns(); - register const float* inputPTR=inputFrame+IDrowStart*_filterOutput.getNBcolumns(); - for (unsigned int IDrow=IDrowStart; IDrow USE IRREGULAR SPATIAL CONSTANT - -// irregular filter computed from a buffer and rewrites it -void BasicRetinaFilter::_spatiotemporalLPfilter_Irregular(float *inputOutputFrame, const unsigned int filterIndex) -{ - if (_progressiveGain.size()==0) - { - std::cerr<<"BasicRetinaFilter::runProgressiveFilter: cannot perform filtering, no progressive filter settled up"< B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. -** ====> more informations in the above cited Jeanny Heraults's book. -** -** License Agreement -** For Open Source Computer Vision Library -** -** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** -** For Human Visual System tools (bioinspired) -** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions 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. -*******************************************************************************/ - -#ifndef BASICRETINAELEMENT_HPP_ -#define BASICRETINAELEMENT_HPP_ - -#include - - -/** -* @class BasicRetinaFilter -* @brief Brief overview, this class provides tools for low level image processing: -* --> this class is able to perform: -* -> first order Low pass optimized filtering -* -> local luminance adaptation (able to correct back light problems and contrast enhancement) -* -> progressive low pass filter filtering (higher filtering on the borders than on the center) -* -> image data between 0 and 255 resampling with different options, linear rescaling, sigmoide) -* -* NOTE : initially the retina model was based on double format scalar values but -* a good memory/precision compromise is float... -* also the double format precision does not make so much sense from a biological point of view (neurons value coding is not so precise) -* -* TYPICAL USE: -* -* // create object at a specified picture size -* BasicRetinaFilter *_photoreceptorsPrefilter; -* _photoreceptorsPrefilter =new BasicRetinaFilter(sizeRows, sizeWindows); -* -* // init gain, spatial and temporal parameters: -* _photoreceptorsPrefilter->setCoefficientsTable(gain,temporalConstant, spatialConstant); -* -* // during program execution, call the filter for local luminance correction or low pass filtering for an input picture called "FrameBuffer": -* _photoreceptorsPrefilter->runFilter_LocalAdapdation(FrameBuffer); -* // or (Low pass first order filter) -* _photoreceptorsPrefilter->runFilter_LPfilter(FrameBuffer); -* // get output frame and its size: -* const unsigned int output_nbRows=_photoreceptorsPrefilter->getNBrows(); -* const unsigned int output_nbColumns=_photoreceptorsPrefilter->getNBcolumns(); -* const double *outputFrame=_photoreceptorsPrefilter->getOutput(); -* -* // at the end of the program, destroy object: -* delete _photoreceptorsPrefilter; - -* @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC : www.listic.univ-savoie.fr, Gipsa-Lab, France: www.gipsa-lab.inpg.fr/ -* Creation date 2007 -* synthesis of the work described in Alexandre BENOIT thesis: "Le systeme visuel humain au secours de la vision par ordinateur" -*/ - -#include -#include "templatebuffer.hpp" - -//#define __BASIC_RETINA_ELEMENT_DEBUG - -namespace cv -{ -namespace bioinspired -{ - class BasicRetinaFilter - { - public: - - /** - * constructor of the base bio-inspired toolbox, parameters are only linked to imae input size and number of filtering capabilities of the object - * @param NBrows: number of rows of the input image - * @param NBcolumns: number of columns of the input image - * @param parametersListSize: specifies the number of parameters set (each parameters set represents a specific low pass spatio-temporal filter) - * @param useProgressiveFilter: specifies if the filter has irreguar (progressive) filtering capabilities (this can be activated later using setProgressiveFilterConstants_xxx methods) - */ - BasicRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns, const unsigned int parametersListSize=1, const bool useProgressiveFilter=false); - - /** - * standrad destructore - */ - ~BasicRetinaFilter(); - - /** - * function which clears the output buffer of the object - */ - inline void clearOutputBuffer() { _filterOutput = 0; } - - /** - * function which clears the secondary buffer of the object - */ - inline void clearSecondaryBuffer() { _localBuffer = 0; } - - /** - * function which clears the output and the secondary buffer of the object - */ - inline void clearAllBuffers() { clearOutputBuffer(); clearSecondaryBuffer(); } - - /** - * resize basic retina filter object (resize all allocated buffers - * @param NBrows: the new height size - * @param NBcolumns: the new width size - */ - void resize(const unsigned int NBrows, const unsigned int NBcolumns); - - /** - * forbiden method inherited from parent std::valarray - * prefer not to use this method since the filter matrix become vectors - */ - void resize(const unsigned int) { std::cerr<<"error, not accessible method"< &runFilter_LPfilter(const std::valarray &inputFrame, const unsigned int filterIndex=0); // run the LP filter for a new frame input and save result in _filterOutput - - /** - * low pass filter call and run (models the homogeneous cells network at the retina level, for example horizontal cells or photoreceptors) - * @param inputFrame: the input image to be processed - * @param outputFrame: the output buffer in which the result is writed - * @param filterIndex: the offset which specifies the parameter set that should be used for the filtering - */ - void runFilter_LPfilter(const std::valarray &inputFrame, std::valarray &outputFrame, const unsigned int filterIndex=0); // run LP filter on a specific output adress - - /** - * low pass filter call and run (models the homogeneous cells network at the retina level, for example horizontal cells or photoreceptors) - * @param inputOutputFrame: the input image to be processed on which the result is rewrited - * @param filterIndex: the offset which specifies the parameter set that should be used for the filtering - */ - void runFilter_LPfilter_Autonomous(std::valarray &inputOutputFrame, const unsigned int filterIndex=0);// run LP filter on the input data and rewrite it - - /** - * local luminance adaptation call and run (contrast enhancement property of the photoreceptors) - * @param inputOutputFrame: the input image to be processed - * @param localLuminance: an image which represents the local luminance of the inputFrame parameter, in general, it is its low pass spatial filtering - * @return the processed image, the output is reachable later by using function getOutput() - */ - const std::valarray &runFilter_LocalAdapdation(const std::valarray &inputOutputFrame, const std::valarray &localLuminance);// run local adaptation filter and save result in _filterOutput - - /** - * local luminance adaptation call and run (contrast enhancement property of the photoreceptors) - * @param inputFrame: the input image to be processed - * @param localLuminance: an image which represents the local luminance of the inputFrame parameter, in general, it is its low pass spatial filtering - * @param outputFrame: the output buffer in which the result is writed - */ - void runFilter_LocalAdapdation(const std::valarray &inputFrame, const std::valarray &localLuminance, std::valarray &outputFrame); // run local adaptation filter on a specific output adress - - /** - * local luminance adaptation call and run (contrast enhancement property of the photoreceptors) - * @param inputFrame: the input image to be processed - * @return the processed image, the output is reachable later by using function getOutput() - */ - const std::valarray &runFilter_LocalAdapdation_autonomous(const std::valarray &inputFrame);// run local adaptation filter and save result in _filterOutput - - /** - * local luminance adaptation call and run (contrast enhancement property of the photoreceptors) - * @param inputFrame: the input image to be processed - * @param outputFrame: the output buffer in which the result is writen - */ - void runFilter_LocalAdapdation_autonomous(const std::valarray &inputFrame, std::valarray &outputFrame); // run local adaptation filter on a specific output adress - - /** - * run low pass filtering with progressive parameters (models the retina log sampling of the photoreceptors and its low pass filtering effect consequence: more powerfull low pass filtering effect on the corners) - * @param inputFrame: the input image to be processed - * @param filterIndex: the index which specifies the parameter set that should be used for the filtering - * @return the processed image, the output is reachable later by using function getOutput() if outputFrame is NULL - */ - inline void runProgressiveFilter(std::valarray &inputFrame, const unsigned int filterIndex=0) { _spatiotemporalLPfilter_Irregular(&inputFrame[0], filterIndex); } - - /** - * run low pass filtering with progressive parameters (models the retina log sampling of the photoreceptors and its low pass filtering effect consequence: more powerfull low pass filtering effect on the corners) - * @param inputFrame: the input image to be processed - * @param outputFrame: the output buffer in which the result is writen - * @param filterIndex: the index which specifies the parameter set that should be used for the filtering - */ - inline void runProgressiveFilter(const std::valarray &inputFrame, - std::valarray &outputFrame, - const unsigned int filterIndex=0) - {_spatiotemporalLPfilter_Irregular(get_data(inputFrame), &outputFrame[0], filterIndex); } - - /** - * first order spatio-temporal low pass filter setup function - * @param beta: gain of the filter (generally set to zero) - * @param tau: time constant of the filter (unit is frame for video processing) - * @param k: spatial constant of the filter (unit is pixels) - * @param filterIndex: the index which specifies the parameter set that should be used for the filtering - */ - void setLPfilterParameters(const float beta, const float tau, const float k, const unsigned int filterIndex=0); // change the parameters of the filter - - /** - * first order spatio-temporal low pass filter setup function - * @param beta: gain of the filter (generally set to zero) - * @param tau: time constant of the filter (unit is frame for video processing) - * @param alpha0: spatial constant of the filter (unit is pixels) on the border of the image - * @param filterIndex: the index which specifies the parameter set that should be used for the filtering - */ - void setProgressiveFilterConstants_CentredAccuracy(const float beta, const float tau, const float alpha0, const unsigned int filterIndex=0); - - /** - * first order spatio-temporal low pass filter setup function - * @param beta: gain of the filter (generally set to zero) - * @param tau: time constant of the filter (unit is frame for video processing) - * @param alpha0: spatial constant of the filter (unit is pixels) on the border of the image - * @param accuracyMap an image (float format) which values range is between 0 and 1, where 0 means, apply no filtering and 1 means apply the filtering as specified in the parameters set, intermediate values allow to smooth variations of the filtering strenght - * @param filterIndex: the index which specifies the parameter set that should be used for the filtering - */ - void setProgressiveFilterConstants_CustomAccuracy(const float beta, const float tau, const float alpha0, const std::valarray &accuracyMap, const unsigned int filterIndex=0); - - /** - * local luminance adaptation setup, this function should be applied for normal local adaptation (not for tone mapping operation) - * @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect - * @param maxInputValue: the maximum amplitude value measured after local adaptation processing (c.f. function runFilter_LocalAdapdation & runFilter_LocalAdapdation_autonomous) - * @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI) - */ - void setV0CompressionParameter(const float v0, const float maxInputValue, const float) - { - _v0=v0*maxInputValue; - _localLuminanceFactor=v0; - _localLuminanceAddon=maxInputValue*(1.0f-v0); - _maxInputValue=maxInputValue; - } - - /** - * update local luminance adaptation setup, initial maxInputValue is kept. This function should be applied for normal local adaptation (not for tone mapping operation) - * @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect - * @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI) - */ - void setV0CompressionParameter(const float v0, const float meanLuminance) { this->setV0CompressionParameter(v0, _maxInputValue, meanLuminance); } - - /** - * local luminance adaptation setup, this function should be applied for normal local adaptation (not for tone mapping operation) - * @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect - */ - void setV0CompressionParameter(const float v0) - { - _v0=v0*_maxInputValue; - _localLuminanceFactor=v0; - _localLuminanceAddon=_maxInputValue*(1.0f-v0); - } - - /** - * local luminance adaptation setup, this function should be applied for local adaptation applied to tone mapping operation - * @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect - * @param maxInputValue: the maximum amplitude value measured after local adaptation processing (c.f. function runFilter_LocalAdapdation & runFilter_LocalAdapdation_autonomous) - * @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI) - */ - void setV0CompressionParameterToneMapping(const float v0, const float maxInputValue, const float meanLuminance=128.0f) - { - _v0=v0*maxInputValue; - _localLuminanceFactor=1.0f; - _localLuminanceAddon=meanLuminance*v0; - _maxInputValue=maxInputValue; - } - - /** - * update compression parameters while keeping v0 parameter value - * @param meanLuminance the input frame mean luminance - */ - inline void updateCompressionParameter(const float meanLuminance) - { - _localLuminanceFactor=1; - _localLuminanceAddon=meanLuminance*_v0; - } - - /** - * @return the v0 compression parameter used to compute the local adaptation - */ - float getV0CompressionParameter() { return _v0/_maxInputValue; } - - /** - * @return the output result of the object - */ - inline const std::valarray &getOutput() const { return _filterOutput; } - - /** - * @return number of rows of the filter - */ - inline unsigned int getNBrows() { return _filterOutput.getNBrows(); } - - /** - * @return number of columns of the filter - */ - inline unsigned int getNBcolumns() { return _filterOutput.getNBcolumns(); } - - /** - * @return number of pixels of the filter - */ - inline unsigned int getNBpixels() { return _filterOutput.getNBpixels(); } - - /** - * force filter output to be normalized between 0 and maxValue - * @param maxValue: the maximum output value that is required - */ - inline void normalizeGrayOutput_0_maxOutputValue(const float maxValue) { _filterOutput.normalizeGrayOutput_0_maxOutputValue(maxValue); } - - /** - * force filter output to be normalized around 0 and rescaled with a sigmoide effect (extrem values saturation) - * @param maxValue: the maximum output value that is required - */ - inline void normalizeGrayOutputCentredSigmoide() { _filterOutput.normalizeGrayOutputCentredSigmoide(); } - - /** - * force filter output to be normalized : data centering and std normalisation - * @param maxValue: the maximum output value that is required - */ - inline void centerReductImageLuminance() { _filterOutput.centerReductImageLuminance(); } - - /** - * @return the maximum input buffer value - */ - inline float getMaxInputValue() { return _maxInputValue; } - - /** - * @return the maximum input buffer value - */ - inline void setMaxInputValue(const float newMaxInputValue) { this->_maxInputValue=newMaxInputValue; } - - protected: - - ///////////////////////// - // data buffers - TemplateBuffer _filterOutput; // primary buffer (contains processing outputs) - std::valarray _localBuffer; // local secondary buffer - ///////////////////////// - // PARAMETERS - unsigned int _halfNBrows; - unsigned int _halfNBcolumns; - - // parameters buffers - std::valarray _filteringCoeficientsTable; - std::valarray _progressiveSpatialConstant;// pointer to a local table containing local spatial constant (allocated with the object) - std::valarray _progressiveGain;// pointer to a local table containing local spatial constant (allocated with the object) - - // local adaptation filtering parameters - float _v0; //value used for local luminance adaptation function - float _maxInputValue; - float _meanInputValue; - float _localLuminanceFactor; - float _localLuminanceAddon; - - // protected data related to standard low pass filters parameters - float _a; - float _tau; - float _gain; - - ///////////////////////// - // FILTERS METHODS - - // Basic low pass spation temporal low pass filter used by each retina filters - void _spatiotemporalLPfilter(const float *inputFrame, float *LPfilterOutput, const unsigned int coefTableOffset=0); - float _squaringSpatiotemporalLPfilter(const float *inputFrame, float *outputFrame, const unsigned int filterIndex=0); - - // LP filter with an irregular spatial filtering - - // -> rewrites the input buffer - void _spatiotemporalLPfilter_Irregular(float *inputOutputFrame, const unsigned int filterIndex=0); - // writes the output on another buffer - void _spatiotemporalLPfilter_Irregular(const float *inputFrame, float *outputFrame, const unsigned int filterIndex=0); - // LP filter that squares the input and computes the output ONLY on the areas where the integrationAreas map are TRUE - void _localSquaringSpatioTemporalLPfilter(const float *inputFrame, float *LPfilterOutput, const unsigned int *integrationAreas, const unsigned int filterIndex=0); - - // local luminance adaptation of the input in regard of localLuminance buffer - void _localLuminanceAdaptation(const float *inputFrame, const float *localLuminance, float *outputFrame, const bool updateLuminanceMean=true); - // local luminance adaptation of the input in regard of localLuminance buffer, the input is rewrited and becomes the output - void _localLuminanceAdaptation(float *inputOutputFrame, const float *localLuminance); - // local adaptation applied on a range of values which can be positive and negative - void _localLuminanceAdaptationPosNegValues(const float *inputFrame, const float *localLuminance, float *outputFrame); - - - ////////////////////////////////////////////////////////////// - // 1D directional filters used for the 2D low pass filtering - - // 1D filters with image input - void _horizontalCausalFilter_addInput(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd); - // 1D filters with image input that is squared in the function // parallelized with TBB - void _squaringHorizontalCausalFilter(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd); - // vertical anticausal filter that returns the mean value of its result - float _verticalAnticausalFilter_returnMeanValue(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); - - // most simple functions: only perform 1D filtering with output=input (no add on) - void _horizontalCausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd); - void _horizontalAnticausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd); // parallelized with TBB - void _verticalCausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); // parallelized with TBB - void _verticalAnticausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); - - // perform 1D filtering with output with varrying spatial coefficient - void _horizontalCausalFilter_Irregular(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd); - void _horizontalCausalFilter_Irregular_addInput(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd); - void _horizontalAnticausalFilter_Irregular(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const float *spatialConstantBuffer); // parallelized with TBB - void _verticalCausalFilter_Irregular(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const float *spatialConstantBuffer); // parallelized with TBB - void _verticalAnticausalFilter_Irregular_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); - - - // 1D filters in which the output is multiplied by _gain - void _verticalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); // this functions affects _gain at the output // parallelized with TBB - void _horizontalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); // this functions affects _gain at the output - - // LP filter on specific parts of the picture instead of all the image - // same functions (some of them) but take a binary flag to allow integration, false flag means, 0 at the output... - void _local_squaringHorizontalCausalFilter(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const unsigned int *integrationAreas); - void _local_horizontalAnticausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const unsigned int *integrationAreas); - void _local_verticalCausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const unsigned int *integrationAreas); - void _local_verticalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const unsigned int *integrationAreas); // this functions affects _gain at the output - -#ifdef MAKE_PARALLEL - /****************************************************** - ** IF some parallelizing thread methods are available, then, main loops are parallelized using these functors - ** ==> main idea paralellise main filters loops, then, only the most used methods are parallelized... TODO : increase the number of parallelised methods as necessary - ** ==> functors names = Parallel_$$$ where $$$= the name of the serial method that is parallelised - ** ==> functors constructors can differ from the parameters used with their related serial functions - */ - -#define _DEBUG_TBB // define DEBUG_TBB in order to display additionnal data on stdout - class Parallel_horizontalAnticausalFilter: public cv::ParallelLoopBody - { - private: - float *outputFrame; - unsigned int IDrowEnd, nbColumns; - float filterParam_a; - public: - // constructor which takes the input image pointer reference reference and limits - Parallel_horizontalAnticausalFilter(float *bufferToProcess, const unsigned int idEnd, const unsigned int nbCols, const float a ) - :outputFrame(bufferToProcess), IDrowEnd(idEnd), nbColumns(nbCols), filterParam_a(a) - { -#ifdef DEBUG_TBB - std::cout<<"Parallel_horizontalAnticausalFilter::Parallel_horizontalAnticausalFilter :" - <<"\n\t idEnd="< B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. -** ====> more informations in the above cited Jeanny Heraults's book. -** -** License Agreement -** For Open Source Computer Vision Library -** -** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** -** For Human Visual System tools (bioinspired) -** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions 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. -*******************************************************************************/ - -#include "precomp.hpp" -#include "imagelogpolprojection.hpp" - -#include -#include - -// @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC : www.listic.univ-savoie.fr, Gipsa-Lab, France: www.gipsa-lab.inpg.fr/ - -namespace cv -{ -namespace bioinspired -{ -// constructor -ImageLogPolProjection::ImageLogPolProjection(const unsigned int nbRows, const unsigned int nbColumns, const PROJECTIONTYPE projection, const bool colorModeCapable) -:BasicRetinaFilter(nbRows, nbColumns), - _sampledFrame(0), - _tempBuffer(_localBuffer), - _transformTable(0), - _irregularLPfilteredFrame(_filterOutput) -{ - _inputDoubleNBpixels=nbRows*nbColumns*2; - _selectedProjection = projection; - _reductionFactor=0; - _initOK=false; - _usefullpixelIndex=0; - _colorModeCapable=colorModeCapable; -#ifdef IMAGELOGPOLPROJECTION_DEBUG - std::cout<<"ImageLogPolProjection::allocating"< private init functions dedicated to each projection -bool ImageLogPolProjection::_initLogRetinaSampling(const double reductionFactor, const double samplingStrenght) -{ - _initOK=false; - - if (_selectedProjection!=RETINALOGPROJECTION) - { - std::cerr<<"ImageLogPolProjection::initLogRetinaSampling: could not initialize logPolar projection for a log projection system\n -> you probably chose the wrong init function, use initLogPolarCortexSampling() instead"<getNBrows(), reductionFactor); - _outputNBcolumns=predictOutputSize(this->getNBcolumns(), reductionFactor); - _outputNBpixels=_outputNBrows*_outputNBcolumns; - _outputDoubleNBpixels=_outputNBrows*_outputNBcolumns*2; - -#ifdef IMAGELOGPOLPROJECTION_DEBUG - std::cout<<"ImageLogPolProjection::initLogRetinaSampling: Log resampled image resampling factor: "< ImageLogPolProjection::(u, v)="< ImageLogPolProjection::(u, v)="< "<<(halfInputRows-u)+_filterOutput.getNBrows()*(halfInputColumns+v)< you probably chose the wrong init function, use initLogRetinaSampling() instead"< radiusAxis(_outputNBcolumns); - double radiusStep=2.30/(double)_outputNBcolumns; - for (unsigned int i=0;i<_outputNBcolumns;++i) - { - radiusAxis[i]=i*radiusStep; - } - std::valarray orientationAxis(_outputNBrows); - double orientationStep=-2.0*CV_PI/(double)_outputNBrows; - for (unsigned int io=0;io<_outputNBrows;++io) - { - orientationAxis[io]=io*orientationStep; - } - // -> use a temporay transform table which is bigger than the final one, we only report pixels coordinates that are included in the sampled picture - std::valarray tempTransformTable(2*_outputNBpixels); // the structure would be: (pixelInputCoordinate n)(pixelOutputCoordinate n)(pixelInputCoordinate n+1)(pixelOutputCoordinate n+1) - _usefullpixelIndex=0; - - //std::cout<<"ImageLogPolProjection::Starting cortex projection"<0)&&(rowIndex<_filterOutput.getNBrows())&&(rowIndex>0)) - { - // set coordinate - tempTransformTable[_usefullpixelIndex++]=radiusIndex+orientationIndex*_outputNBcolumns; - tempTransformTable[_usefullpixelIndex++]= columnIndex+rowIndex*_filterOutput.getNBcolumns(); - } - } - - // (re)creating and filling the transform table - _transformTable.resize(_usefullpixelIndex); - memcpy(&_transformTable[0], &tempTransformTable[0], sizeof(unsigned int)*_usefullpixelIndex); - - // reset all buffers - clearAllBuffers(); - _initOK=true; - return true; -} - -// action function -std::valarray &ImageLogPolProjection::runProjection(const std::valarray &inputFrame, const bool colorMode) -{ - if (_colorModeCapable&&colorMode) - { - // progressive filtering and storage of the result in _tempBuffer - _spatiotemporalLPfilter_Irregular(get_data(inputFrame), &_irregularLPfilteredFrame[0]); - _spatiotemporalLPfilter_Irregular(&_irregularLPfilteredFrame[0], &_tempBuffer[0]); // warning, temporal issue may occur, if the temporal constant is not NULL !!! - - _spatiotemporalLPfilter_Irregular(get_data(inputFrame)+_filterOutput.getNBpixels(), &_irregularLPfilteredFrame[0]); - _spatiotemporalLPfilter_Irregular(&_irregularLPfilteredFrame[0], &_tempBuffer[0]+_filterOutput.getNBpixels()); - - _spatiotemporalLPfilter_Irregular(get_data(inputFrame)+_filterOutput.getNBpixels()*2, &_irregularLPfilteredFrame[0]); - _spatiotemporalLPfilter_Irregular(&_irregularLPfilteredFrame[0], &_tempBuffer[0]+_filterOutput.getNBpixels()*2); - - // applying image projection/resampling - register unsigned int *transformTablePTR=&_transformTable[0]; - for (unsigned int i=0 ; i<_usefullpixelIndex ; i+=2, transformTablePTR+=2) - { -#ifdef IMAGELOGPOLPROJECTION_DEBUG - std::cout<<"ImageLogPolProjection::i:"< B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. -** ====> more informations in the above cited Jeanny Heraults's book. -** -** License Agreement -** For Open Source Computer Vision Library -** -** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** -** For Human Visual System tools (bioinspired) -** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions 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. -*******************************************************************************/ - -#ifndef IMAGELOGPOLPROJECTION_H_ -#define IMAGELOGPOLPROJECTION_H_ - -/** -* @class ImageLogPolProjection -* @brief class able to perform a log sampling of an image input (models the log sampling of the photoreceptors of the retina) -* or a log polar projection which models the retina information projection on the primary visual cortex: a linear projection in the center for detail analysis and a log projection of the borders (low spatial frequency motion information in general) -* -* collaboration: Barthelemy DURETTE who experimented the retina log projection --> "Traitement visuels Bio mimtiques pour la supplance perceptive", internal technical report, May 2005, Gipsa-lab/DIS, Grenoble, FRANCE -* -* * TYPICAL USE: -* -* // create object, here for a log sampling (keyword:RETINALOGPROJECTION): (dynamic object allocation sample) -* ImageLogPolProjection *imageSamplingTool; -* imageSamplingTool = new ImageLogPolProjection(frameSizeRows, frameSizeColumns, RETINALOGPROJECTION); -* -* // init log projection: -* imageSamplingTool->initProjection(1.0, 15.0); -* -* // during program execution, call the log transform applied to a frame called "FrameBuffer" : -* imageSamplingTool->runProjection(FrameBuffer); -* // get output frame and its size: -* const unsigned int logSampledFrame_nbRows=imageSamplingTool->getOutputNBrows(); -* const unsigned int logSampledFrame_nbColumns=imageSamplingTool->getOutputNBcolumns(); -* const double *logSampledFrame=imageSamplingTool->getSampledFrame(); -* -* // at the end of the program, destroy object: -* delete imageSamplingTool; -* -* @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC : www.listic.univ-savoie.fr, Gipsa-Lab, France: www.gipsa-lab.inpg.fr/ -* Creation date 2007 -*/ - -//#define __IMAGELOGPOLPROJECTION_DEBUG // used for std output debug information - -#include "basicretinafilter.hpp" - - -namespace cv -{ -namespace bioinspired -{ - -class ImageLogPolProjection:public BasicRetinaFilter -{ -public: - - enum PROJECTIONTYPE{RETINALOGPROJECTION, CORTEXLOGPOLARPROJECTION}; - - /** - * constructor, just specifies the image input size and the projection type, no projection initialisation is done - * -> use initLogRetinaSampling() or initLogPolarCortexSampling() for that - * @param nbRows: number of rows of the input image - * @param nbColumns: number of columns of the input image - * @param projection: the type of projection, RETINALOGPROJECTION or CORTEXLOGPOLARPROJECTION - * @param colorMode: specifies if the projection is applied on a grayscale image (false) or color images (3 layers) (true) - */ - ImageLogPolProjection(const unsigned int nbRows, const unsigned int nbColumns, const PROJECTIONTYPE projection, const bool colorMode=false); - - /** - * standard destructor - */ - virtual ~ImageLogPolProjection(); - - /** - * function that clears all buffers of the object - */ - void clearAllBuffers(); - - /** - * resize retina color filter object (resize all allocated buffers) - * @param NBrows: the new height size - * @param NBcolumns: the new width size - */ - void resize(const unsigned int NBrows, const unsigned int NBcolumns); - - /** - * init function depending on the projection type - * @param reductionFactor: the size reduction factor of the ouptup image in regard of the size of the input image, must be superior to 1 - * @param samplingStrenght: specifies the strenght of the log compression effect (magnifying coefficient) - * @return true if the init was performed without any errors - */ - bool initProjection(const double reductionFactor, const double samplingStrenght); - - /** - * main funtion of the class: run projection function - * @param inputFrame: the input frame to be processed - * @param colorMode: the input buffer color mode: false=gray levels, true = 3 color channels mode - * @return the output frame - */ - std::valarray &runProjection(const std::valarray &inputFrame, const bool colorMode=false); - - /** - * @return the numbers of rows (height) of the images OUTPUTS of the object - */ - inline unsigned int getOutputNBrows() { return _outputNBrows; } - - /** - * @return the numbers of columns (width) of the images OUTPUTS of the object - */ - inline unsigned int getOutputNBcolumns() { return _outputNBcolumns; } - - /** - * main funtion of the class: run projection function - * @param size: one of the input frame initial dimensions to be processed - * @return the output frame dimension - */ - inline static unsigned int predictOutputSize(const unsigned int size, const double reductionFactor){return (unsigned int)((double)size/reductionFactor); } - - /** - * @return the output of the filter which applies an irregular Low Pass spatial filter to the imag input (see function - */ - inline const std::valarray &getIrregularLPfilteredInputFrame() const { return _irregularLPfilteredFrame; } - - /** - * function which allows to retrieve the output frame which was updated after the "runProjection(...) function BasicRetinaFilter::runProgressiveFilter(...) - * @return the projection result - */ - inline const std::valarray &getSampledFrame() const { return _sampledFrame; } - - /** - * function which allows gives the tranformation table, its size is (getNBrows()*getNBcolumns()*2) - * @return the transformation matrix [outputPixIndex_i, inputPixIndex_i, outputPixIndex_i+1, inputPixIndex_i+1....] - */ - inline const std::valarray &getSamplingMap() const { return _transformTable; } - - inline double getOriginalRadiusLength(const double projectedRadiusLength) - { return _azero/(_alim-projectedRadiusLength*2.0/_minDimension); } - - // unsigned int getInputPixelIndex(const unsigned int ){ return _transformTable[index*2+1]}; - -private: - PROJECTIONTYPE _selectedProjection; - - // size of the image output - unsigned int _outputNBrows; - unsigned int _outputNBcolumns; - unsigned int _outputNBpixels; - unsigned int _outputDoubleNBpixels; - unsigned int _inputDoubleNBpixels; - - // is the object able to manage color flag - bool _colorModeCapable; - // sampling strenght factor - double _samplingStrenght; - // sampling reduction factor - double _reductionFactor; - - // log sampling parameters - double _azero; - double _alim; - double _minDimension; - - // template buffers - std::valarray_sampledFrame; - std::valarray&_tempBuffer; - std::valarray_transformTable; - - std::valarray &_irregularLPfilteredFrame; // just a reference for easier understanding - unsigned int _usefullpixelIndex; - - // init transformation tables - bool _computeLogProjection(); - bool _computeLogPolarProjection(); - - // specifies if init was done correctly - bool _initOK; - // private init projections functions called by "initProjection(...)" function - bool _initLogRetinaSampling(const double reductionFactor, const double samplingStrenght); - bool _initLogPolarCortexSampling(const double reductionFactor, const double samplingStrenght); - - ImageLogPolProjection(const ImageLogPolProjection&); - ImageLogPolProjection& operator=(const ImageLogPolProjection&); - -}; - -}// end of namespace bioinspired -}// end of namespace cv -#endif /*IMAGELOGPOLPROJECTION_H_*/ diff --git a/modules/bioinspired/src/magnoretinafilter.cpp b/modules/bioinspired/src/magnoretinafilter.cpp deleted file mode 100644 index 81fdb1df5..000000000 --- a/modules/bioinspired/src/magnoretinafilter.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/*#****************************************************************************** -** 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. -** -** -** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. -** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. -** -** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) -** -** Creation - enhancement process 2007-2011 -** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France -** -** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). -** Refer to the following research paper for more information: -** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 -** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: -** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. -** -** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : -** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: -** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. -** ====> more informations in the above cited Jeanny Heraults's book. -** -** License Agreement -** For Open Source Computer Vision Library -** -** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** -** For Human Visual System tools (bioinspired) -** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions 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. -*******************************************************************************/ - -#include "precomp.hpp" - -#include - -#include "magnoretinafilter.hpp" - -#include - -namespace cv -{ -namespace bioinspired -{ -// Constructor and Desctructor of the OPL retina filter -MagnoRetinaFilter::MagnoRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns) -:BasicRetinaFilter(NBrows, NBcolumns, 2), - _previousInput_ON(NBrows*NBcolumns), - _previousInput_OFF(NBrows*NBcolumns), - _amacrinCellsTempOutput_ON(NBrows*NBcolumns), - _amacrinCellsTempOutput_OFF(NBrows*NBcolumns), - _magnoXOutputON(NBrows*NBcolumns), - _magnoXOutputOFF(NBrows*NBcolumns), - _localProcessBufferON(NBrows*NBcolumns), - _localProcessBufferOFF(NBrows*NBcolumns) -{ - _magnoYOutput=&_filterOutput; - _magnoYsaturated=&_localBuffer; - - - clearAllBuffers(); - -#ifdef IPL_RETINA_ELEMENT_DEBUG - std::cout<<"MagnoRetinaFilter::Init IPL retina filter at specified frame size OK"<getNBpixels(); ++IDpixel) - { - - /* Compute ON and OFF amacrin cells high pass temporal filter */ - float magnoXonPixelResult = _temporalCoefficient*(*amacrinCellsTempOutput_ON_PTR+ *OPL_ON_PTR-*previousInput_ON_PTR); - *(amacrinCellsTempOutput_ON_PTR++)=((float)(magnoXonPixelResult>0))*magnoXonPixelResult; - - float magnoXoffPixelResult = _temporalCoefficient*(*amacrinCellsTempOutput_OFF_PTR+ *OPL_OFF_PTR-*previousInput_OFF_PTR); - *(amacrinCellsTempOutput_OFF_PTR++)=((float)(magnoXoffPixelResult>0))*magnoXoffPixelResult; - - /* prepare next loop */ - *(previousInput_ON_PTR++)=*(OPL_ON_PTR++); - *(previousInput_OFF_PTR++)=*(OPL_OFF_PTR++); - - } -#endif -} - -// launch filter that runs all the IPL filter -const std::valarray &MagnoRetinaFilter::runFilter(const std::valarray &OPL_ON, const std::valarray &OPL_OFF) -{ - // Compute the high pass temporal filter - _amacrineCellsComputing(get_data(OPL_ON), get_data(OPL_OFF)); - - // apply low pass filtering on ON and OFF ways after temporal high pass filtering - _spatiotemporalLPfilter(&_amacrinCellsTempOutput_ON[0], &_magnoXOutputON[0], 0); - _spatiotemporalLPfilter(&_amacrinCellsTempOutput_OFF[0], &_magnoXOutputOFF[0], 0); - - // local adaptation of the ganglion cells to the local contrast of the moving contours - _spatiotemporalLPfilter(&_magnoXOutputON[0], &_localProcessBufferON[0], 1); - _localLuminanceAdaptation(&_magnoXOutputON[0], &_localProcessBufferON[0]); - _spatiotemporalLPfilter(&_magnoXOutputOFF[0], &_localProcessBufferOFF[0], 1); - _localLuminanceAdaptation(&_magnoXOutputOFF[0], &_localProcessBufferOFF[0]); - - /* Compute MagnoY */ - register float *magnoYOutput= &(*_magnoYOutput)[0]; - register float *magnoXOutputON_PTR= &_magnoXOutputON[0]; - register float *magnoXOutputOFF_PTR= &_magnoXOutputOFF[0]; - for (register unsigned int IDpixel=0 ; IDpixel<_filterOutput.getNBpixels() ; ++IDpixel) - *(magnoYOutput++)=*(magnoXOutputON_PTR++)+*(magnoXOutputOFF_PTR++); - - return (*_magnoYOutput); -} -}// end of namespace bioinspired -}// end of namespace cv diff --git a/modules/bioinspired/src/magnoretinafilter.hpp b/modules/bioinspired/src/magnoretinafilter.hpp deleted file mode 100644 index 723537de8..000000000 --- a/modules/bioinspired/src/magnoretinafilter.hpp +++ /dev/null @@ -1,246 +0,0 @@ -/*#****************************************************************************** -** 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. -** -** -** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. -** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. -** -** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) -** -** Creation - enhancement process 2007-2011 -** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France -** -** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). -** Refer to the following research paper for more information: -** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 -** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: -** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. -** -** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : -** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: -** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. -** ====> more informations in the above cited Jeanny Heraults's book. -** -** License Agreement -** For Open Source Computer Vision Library -** -** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** -** For Human Visual System tools (bioinspired) -** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions 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. -*******************************************************************************/ - -#ifndef MagnoRetinaFilter_H_ -#define MagnoRetinaFilter_H_ - -/** -* @class MagnoRetinaFilter -* @brief class which describes the magnocellular channel of the retina: -* -> performs a moving contours extraction with powerfull local data enhancement -* -* TYPICAL USE: -* -* // create object at a specified picture size -* MagnoRetinaFilter *movingContoursExtractor; -* movingContoursExtractor =new MagnoRetinaFilter(frameSizeRows, frameSizeColumns); -* -* // init gain, spatial and temporal parameters: -* movingContoursExtractor->setCoefficientsTable(0, 0.7, 5, 3); -* -* // during program execution, call the filter for contours extraction for an input picture called "FrameBuffer": -* movingContoursExtractor->runfilter(FrameBuffer); -* -* // get the output frame, check in the class description below for more outputs: -* const float *movingContours=movingContoursExtractor->getMagnoYsaturated(); -* -* // at the end of the program, destroy object: -* delete movingContoursExtractor; - -* @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC : www.listic.univ-savoie.fr, Gipsa-Lab, France: www.gipsa-lab.inpg.fr/ -* Creation date 2007 -* Based on Alexandre BENOIT thesis: "Le système visuel humain au secours de la vision par ordinateur" -*/ - -#include "basicretinafilter.hpp" - -//#define _IPL_RETINA_ELEMENT_DEBUG - -namespace cv -{ -namespace bioinspired -{ - class MagnoRetinaFilter: public BasicRetinaFilter - { - public: - /** - * constructor parameters are only linked to image input size - * @param NBrows: number of rows of the input image - * @param NBcolumns: number of columns of the input image - */ - MagnoRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns); - - - /** - * destructor - */ - virtual ~MagnoRetinaFilter(); - - /** - * function that clears all buffers of the object - */ - void clearAllBuffers(); - - /** - * resize retina magno filter object (resize all allocated buffers) - * @param NBrows: the new height size - * @param NBcolumns: the new width size - */ - void resize(const unsigned int NBrows, const unsigned int NBcolumns); - - /** - * set parameters values - * @param parasolCells_beta: the low pass filter gain used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), typical value is 0 - * @param parasolCells_tau: the low pass filter time constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is frame, typical value is 0 (immediate response) - * @param parasolCells_k: the low pass filter spatial constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is pixels, typical value is 5 - * @param amacrinCellsTemporalCutFrequency: the time constant of the first order high pass fiter of the magnocellular way (motion information channel), unit is frames, tipicall value is 5 - * @param localAdaptIntegration_tau: specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation - * @param localAdaptIntegration_k: specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation - */ - void setCoefficientsTable(const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float localAdaptIntegration_tau, const float localAdaptIntegration_k); - - /** - * launch filter that runs all the IPL magno filter (model of the magnocellular channel of the Inner Plexiform Layer of the retina) - * @param OPL_ON: the output of the bipolar ON cells of the retina (available from the ParvoRetinaFilter class (getBipolarCellsON() function) - * @param OPL_OFF: the output of the bipolar OFF cells of the retina (available from the ParvoRetinaFilter class (getBipolarCellsOFF() function) - * @return the processed result without post-processing - */ - const std::valarray &runFilter(const std::valarray &OPL_ON, const std::valarray &OPL_OFF); - - /** - * @return the Magnocellular ON channel filtering output - */ - inline const std::valarray &getMagnoON() const { return _magnoXOutputON; } - - /** - * @return the Magnocellular OFF channel filtering output - */ - inline const std::valarray &getMagnoOFF() const { return _magnoXOutputOFF; } - - /** - * @return the Magnocellular Y (sum of the ON and OFF magno channels) filtering output - */ - inline const std::valarray &getMagnoYsaturated() const { return *_magnoYsaturated; } - - /** - * applies an image normalization which saturates the high output values by the use of an assymetric sigmoide - */ - inline void normalizeGrayOutputNearZeroCentreredSigmoide() - { _filterOutput.normalizeGrayOutputNearZeroCentreredSigmoide(&(*_magnoYOutput)[0], &(*_magnoYsaturated)[0]); } - - /** - * @return the horizontal cells' temporal constant - */ - inline float getTemporalConstant() { return _filteringCoeficientsTable[2]; } - - private: - - // related pointers to these buffers - std::valarray _previousInput_ON; - std::valarray _previousInput_OFF; - std::valarray _amacrinCellsTempOutput_ON; - std::valarray _amacrinCellsTempOutput_OFF; - std::valarray _magnoXOutputON; - std::valarray _magnoXOutputOFF; - std::valarray _localProcessBufferON; - std::valarray _localProcessBufferOFF; - // reference to parent buffers and allow better readability - TemplateBuffer *_magnoYOutput; - std::valarray *_magnoYsaturated; - - // varialbles - float _temporalCoefficient; - - // amacrine cells filter : high pass temporal filter - void _amacrineCellsComputing(const float *ONinput, const float *OFFinput); -#ifdef MAKE_PARALLEL - /****************************************************** - ** IF some parallelizing thread methods are available, then, main loops are parallelized using these functors - ** ==> main idea paralellise main filters loops, then, only the most used methods are parallelized... TODO : increase the number of parallelised methods as necessary - ** ==> functors names = Parallel_$$$ where $$$= the name of the serial method that is parallelised - ** ==> functors constructors can differ from the parameters used with their related serial functions - */ - class Parallel_amacrineCellsComputing: public cv::ParallelLoopBody - { - private: - const float *OPL_ON, *OPL_OFF; - float *previousInput_ON, *previousInput_OFF, *amacrinCellsTempOutput_ON, *amacrinCellsTempOutput_OFF; - float temporalCoefficient; - public: - Parallel_amacrineCellsComputing(const float *OPL_ON_PTR, const float *OPL_OFF_PTR, float *previousInput_ON_PTR, float *previousInput_OFF_PTR, float *amacrinCellsTempOutput_ON_PTR, float *amacrinCellsTempOutput_OFF_PTR, float temporalCoefficientVal) - :OPL_ON(OPL_ON_PTR), OPL_OFF(OPL_OFF_PTR), previousInput_ON(previousInput_ON_PTR), previousInput_OFF(previousInput_OFF_PTR), amacrinCellsTempOutput_ON(amacrinCellsTempOutput_ON_PTR), amacrinCellsTempOutput_OFF(amacrinCellsTempOutput_OFF_PTR), temporalCoefficient(temporalCoefficientVal) {} - - virtual void operator()( const Range& r ) const { - register const float *OPL_ON_PTR=OPL_ON+r.start; - register const float *OPL_OFF_PTR=OPL_OFF+r.start; - register float *previousInput_ON_PTR= previousInput_ON+r.start; - register float *previousInput_OFF_PTR= previousInput_OFF+r.start; - register float *amacrinCellsTempOutput_ON_PTR= amacrinCellsTempOutput_ON+r.start; - register float *amacrinCellsTempOutput_OFF_PTR= amacrinCellsTempOutput_OFF+r.start; - - for (int IDpixel=r.start ; IDpixel!=r.end; ++IDpixel) - { - - /* Compute ON and OFF amacrin cells high pass temporal filter */ - float magnoXonPixelResult = temporalCoefficient*(*amacrinCellsTempOutput_ON_PTR+ *OPL_ON_PTR-*previousInput_ON_PTR); - *(amacrinCellsTempOutput_ON_PTR++)=((float)(magnoXonPixelResult>0))*magnoXonPixelResult; - - float magnoXoffPixelResult = temporalCoefficient*(*amacrinCellsTempOutput_OFF_PTR+ *OPL_OFF_PTR-*previousInput_OFF_PTR); - *(amacrinCellsTempOutput_OFF_PTR++)=((float)(magnoXoffPixelResult>0))*magnoXoffPixelResult; - - /* prepare next loop */ - *(previousInput_ON_PTR++)=*(OPL_ON_PTR++); - *(previousInput_OFF_PTR++)=*(OPL_OFF_PTR++); - - } - } - - }; -#endif - }; - -}// end of namespace bioinspired -}// end of namespace cv - -#endif /*MagnoRetinaFilter_H_*/ diff --git a/modules/bioinspired/src/opencl/retina_kernel.cl b/modules/bioinspired/src/opencl/retina_kernel.cl deleted file mode 100644 index 169be4d27..000000000 --- a/modules/bioinspired/src/opencl/retina_kernel.cl +++ /dev/null @@ -1,779 +0,0 @@ -/*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-2013, Multicoreware, Inc., all rights reserved. -// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Peng Xiao, pengxiao@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 oclMaterials 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*/ - -//data (which is float) is aligend in 32 bytes -#define WIDTH_MULTIPLE (32 >> 2) - -///////////////////////////////////////////////////////// -//******************************************************* -// basicretinafilter -//////////////// _spatiotemporalLPfilter //////////////// -//_horizontalCausalFilter_addInput -kernel void horizontalCausalFilter_addInput( - global const float * input, - global float * output, - const int cols, - const int rows, - const int elements_per_row, - const int in_offset, - const int out_offset, - const float _tau, - const float _a -) -{ - int gid = get_global_id(0); - if(gid >= rows) - { - return; - } - - global const float * iptr = - input + mad24(gid, elements_per_row, in_offset / 4); - global float * optr = - output + mad24(gid, elements_per_row, out_offset / 4); - - float res; - float4 in_v4, out_v4, res_v4 = (float4)(0); - //vectorize to increase throughput - for(int i = 0; i < cols / 4; ++i, iptr += 4, optr += 4) - { - in_v4 = vload4(0, iptr); - out_v4 = vload4(0, optr); - - res_v4.x = in_v4.x + _tau * out_v4.x + _a * res_v4.w; - res_v4.y = in_v4.y + _tau * out_v4.y + _a * res_v4.x; - res_v4.z = in_v4.z + _tau * out_v4.z + _a * res_v4.y; - res_v4.w = in_v4.w + _tau * out_v4.w + _a * res_v4.z; - - vstore4(res_v4, 0, optr); - } - res = res_v4.w; - // there may be left some - for(int i = 0; i < cols % 4; ++i, ++iptr, ++optr) - { - res = *iptr + _tau * *optr + _a * res; - *optr = res; - } -} - -//_horizontalAnticausalFilter -kernel void horizontalAnticausalFilter( - global float * output, - const int cols, - const int rows, - const int elements_per_row, - const int out_offset, - const float _a -) -{ - int gid = get_global_id(0); - if(gid >= rows) - { - return; - } - - global float * optr = output + - mad24(gid + 1, elements_per_row, - 1 + out_offset / 4); - - float4 result_v4 = (float4)(0), out_v4; - float result = 0; - // we assume elements_per_row is multple of WIDTH_MULTIPLE - for(int i = 0; i < WIDTH_MULTIPLE; ++ i, -- optr) - { - if(i >= elements_per_row - cols) - { - result = *optr + _a * result; - } - *optr = result; - } - result_v4.x = result; - optr -= 3; - for(int i = WIDTH_MULTIPLE / 4; i < elements_per_row / 4; ++i, optr -= 4) - { - // shift left, `offset` is type `size_t` so it cannot be negative - out_v4 = vload4(0, optr); - - result_v4.w = out_v4.w + _a * result_v4.x; - result_v4.z = out_v4.z + _a * result_v4.w; - result_v4.y = out_v4.y + _a * result_v4.z; - result_v4.x = out_v4.x + _a * result_v4.y; - - vstore4(result_v4, 0, optr); - } -} - -//_verticalCausalFilter -kernel void verticalCausalFilter( - global float * output, - const int cols, - const int rows, - const int elements_per_row, - const int out_offset, - const float _a -) -{ - int gid = get_global_id(0); - if(gid >= cols) - { - return; - } - - global float * optr = output + gid + out_offset / 4; - float result = 0; - for(int i = 0; i < rows; ++i, optr += elements_per_row) - { - result = *optr + _a * result; - *optr = result; - } -} - -//_verticalCausalFilter -kernel void verticalAnticausalFilter_multGain( - global float * output, - const int cols, - const int rows, - const int elements_per_row, - const int out_offset, - const float _a, - const float _gain -) -{ - int gid = get_global_id(0); - if(gid >= cols) - { - return; - } - - global float * optr = output + (rows - 1) * elements_per_row + gid + out_offset / 4; - float result = 0; - for(int i = 0; i < rows; ++i, optr -= elements_per_row) - { - result = *optr + _a * result; - *optr = _gain * result; - } -} -// -// end of _spatiotemporalLPfilter -///////////////////////////////////////////////////////////////////// - -//////////////// horizontalAnticausalFilter_Irregular //////////////// -kernel void horizontalAnticausalFilter_Irregular( - global float * output, - global float * buffer, - const int cols, - const int rows, - const int elements_per_row, - const int out_offset, - const int buffer_offset -) -{ - int gid = get_global_id(0); - if(gid >= rows) - { - return; - } - - global float * optr = - output + mad24(rows - gid, elements_per_row, -1 + out_offset / 4); - global float * bptr = - buffer + mad24(rows - gid, elements_per_row, -1 + buffer_offset / 4); - - float4 buf_v4, out_v4, res_v4 = (float4)(0); - float result = 0; - // we assume elements_per_row is multple of WIDTH_MULTIPLE - for(int i = 0; i < WIDTH_MULTIPLE; ++ i, -- optr, -- bptr) - { - if(i >= elements_per_row - cols) - { - result = *optr + *bptr * result; - } - *optr = result; - } - res_v4.x = result; - optr -= 3; - bptr -= 3; - for(int i = WIDTH_MULTIPLE / 4; i < elements_per_row / 4; ++i, optr -= 4, bptr -= 4) - { - buf_v4 = vload4(0, bptr); - out_v4 = vload4(0, optr); - - res_v4.w = out_v4.w + buf_v4.w * res_v4.x; - res_v4.z = out_v4.z + buf_v4.z * res_v4.w; - res_v4.y = out_v4.y + buf_v4.y * res_v4.z; - res_v4.x = out_v4.x + buf_v4.x * res_v4.y; - - vstore4(res_v4, 0, optr); - } -} - -//////////////// verticalCausalFilter_Irregular //////////////// -kernel void verticalCausalFilter_Irregular( - global float * output, - global float * buffer, - const int cols, - const int rows, - const int elements_per_row, - const int out_offset, - const int buffer_offset -) -{ - int gid = get_global_id(0); - if(gid >= cols) - { - return; - } - - global float * optr = output + gid + out_offset / 4; - global float * bptr = buffer + gid + buffer_offset / 4; - float result = 0; - for(int i = 0; i < rows; ++i, optr += elements_per_row, bptr += elements_per_row) - { - result = *optr + *bptr * result; - *optr = result; - } -} - -//////////////// _adaptiveHorizontalCausalFilter_addInput //////////////// -kernel void adaptiveHorizontalCausalFilter_addInput( - global const float * input, - global const float * gradient, - global float * output, - const int cols, - const int rows, - const int elements_per_row, - const int in_offset, - const int grad_offset, - const int out_offset -) -{ - int gid = get_global_id(0); - if(gid >= rows) - { - return; - } - - global const float * iptr = - input + mad24(gid, elements_per_row, in_offset / 4); - global const float * gptr = - gradient + mad24(gid, elements_per_row, grad_offset / 4); - global float * optr = - output + mad24(gid, elements_per_row, out_offset / 4); - - float4 in_v4, grad_v4, out_v4, res_v4 = (float4)(0); - for(int i = 0; i < cols / 4; ++i, iptr += 4, gptr += 4, optr += 4) - { - in_v4 = vload4(0, iptr); - grad_v4 = vload4(0, gptr); - - res_v4.x = in_v4.x + grad_v4.x * res_v4.w; - res_v4.y = in_v4.y + grad_v4.y * res_v4.x; - res_v4.z = in_v4.z + grad_v4.z * res_v4.y; - res_v4.w = in_v4.w + grad_v4.w * res_v4.z; - - vstore4(res_v4, 0, optr); - } - for(int i = 0; i < cols % 4; ++i, ++iptr, ++gptr, ++optr) - { - res_v4.w = *iptr + *gptr * res_v4.w; - *optr = res_v4.w; - } -} - -//////////////// _adaptiveVerticalAnticausalFilter_multGain //////////////// -kernel void adaptiveVerticalAnticausalFilter_multGain( - global const float * gradient, - global float * output, - const int cols, - const int rows, - const int elements_per_row, - const int grad_offset, - const int out_offset, - const float gain -) -{ - int gid = get_global_id(0); - if(gid >= cols) - { - return; - } - - int start_idx = mad24(rows - 1, elements_per_row, gid); - - global const float * gptr = gradient + start_idx + grad_offset / 4; - global float * optr = output + start_idx + out_offset / 4; - - float result = 0; - for(int i = 0; i < rows; ++i, gptr -= elements_per_row, optr -= elements_per_row) - { - result = *optr + *gptr * result; - *optr = gain * result; - } -} - -//////////////// _localLuminanceAdaptation //////////////// -// FIXME: -// This kernel seems to have precision problem on GPU -kernel void localLuminanceAdaptation( - global const float * luma, - global const float * input, - global float * output, - const int cols, - const int rows, - const int elements_per_row, - const float _localLuminanceAddon, - const float _localLuminanceFactor, - const float _maxInputValue -) -{ - int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx >= cols || gidy >= rows) - { - return; - } - int offset = mad24(gidy, elements_per_row, gidx); - - float X0 = luma[offset] * _localLuminanceFactor + _localLuminanceAddon; - float input_val = input[offset]; - // output of the following line may be different between GPU and CPU - output[offset] = (_maxInputValue + X0) * input_val / (input_val + X0 + 0.00000000001f); -} -// end of basicretinafilter -//******************************************************* -///////////////////////////////////////////////////////// - - - -///////////////////////////////////////////////////////// -//****************************************************** -// magno -// TODO: this kernel has too many buffer accesses, better to make it -// vector read/write for fetch efficiency -kernel void amacrineCellsComputing( - global const float * opl_on, - global const float * opl_off, - global float * prev_in_on, - global float * prev_in_off, - global float * out_on, - global float * out_off, - const int cols, - const int rows, - const int elements_per_row, - const float coeff -) -{ - int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx >= cols || gidy >= rows) - { - return; - } - - int offset = mad24(gidy, elements_per_row, gidx); - opl_on += offset; - opl_off += offset; - prev_in_on += offset; - prev_in_off += offset; - out_on += offset; - out_off += offset; - - float magnoXonPixelResult = coeff * (*out_on + *opl_on - *prev_in_on); - *out_on = fmax(magnoXonPixelResult, 0); - float magnoXoffPixelResult = coeff * (*out_off + *opl_off - *prev_in_off); - *out_off = fmax(magnoXoffPixelResult, 0); - - *prev_in_on = *opl_on; - *prev_in_off = *opl_off; -} - -///////////////////////////////////////////////////////// -//****************************************************** -// parvo -// TODO: this kernel has too many buffer accesses, needs optimization -kernel void OPL_OnOffWaysComputing( - global float4 * photo_out, - global float4 * horiz_out, - global float4 * bipol_on, - global float4 * bipol_off, - global float4 * parvo_on, - global float4 * parvo_off, - const int cols, - const int rows, - const int elements_per_row -) -{ - int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx * 4 >= cols || gidy >= rows) - { - return; - } - // we assume elements_per_row must be multiples of 4 - int offset = mad24(gidy, elements_per_row >> 2, gidx); - photo_out += offset; - horiz_out += offset; - bipol_on += offset; - bipol_off += offset; - parvo_on += offset; - parvo_off += offset; - - float4 diff = *photo_out - *horiz_out; - float4 isPositive;// = convert_float4(diff > (float4)(0.0f, 0.0f, 0.0f, 0.0f)); - isPositive.x = diff.x > 0.0f; - isPositive.y = diff.y > 0.0f; - isPositive.z = diff.z > 0.0f; - isPositive.w = diff.w > 0.0f; - float4 res_on = isPositive * diff; - float4 res_off = (isPositive - (float4)(1.0f)) * diff; - - *bipol_on = res_on; - *parvo_on = res_on; - - *bipol_off = res_off; - *parvo_off = res_off; -} - -///////////////////////////////////////////////////////// -//****************************************************** -// retinacolor -inline int bayerSampleOffset(int step, int rows, int x, int y) -{ - return mad24(y, step, x) + - ((y % 2) + (x % 2)) * rows * step; -} - - -/////// colorMultiplexing ////// -kernel void runColorMultiplexingBayer( - global const float * input, - global float * output, - const int cols, - const int rows, - const int elements_per_row -) -{ - int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx >= cols || gidy >= rows) - { - return; - } - - int offset = mad24(gidy, elements_per_row, gidx); - output[offset] = input[bayerSampleOffset(elements_per_row, rows, gidx, gidy)]; -} - -kernel void runColorDemultiplexingBayer( - global const float * input, - global float * output, - const int cols, - const int rows, - const int elements_per_row -) -{ - int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx >= cols || gidy >= rows) - { - return; - } - - int offset = mad24(gidy, elements_per_row, gidx); - output[bayerSampleOffset(elements_per_row, rows, gidx, gidy)] = input[offset]; -} - -kernel void demultiplexAssign( - global const float * input, - global float * output, - const int cols, - const int rows, - const int elements_per_row -) -{ - int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx >= cols || gidy >= rows) - { - return; - } - - int offset = bayerSampleOffset(elements_per_row, rows, gidx, gidy); - output[offset] = input[offset]; -} - - -//// normalizeGrayOutputCentredSigmoide -kernel void normalizeGrayOutputCentredSigmoide( - global const float * input, - global float * output, - const int cols, - const int rows, - const int elements_per_row, - const float meanval, - const float X0 -) - -{ - int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx >= cols || gidy >= rows) - { - return; - } - int offset = mad24(gidy, elements_per_row, gidx); - - float input_val = input[offset]; - output[offset] = meanval + - (meanval + X0) * (input_val - meanval) / (fabs(input_val - meanval) + X0); -} - -//// normalize by photoreceptors density -kernel void normalizePhotoDensity( - global const float * chroma, - global const float * colorDensity, - global const float * multiplex, - global float * luma, - global float * demultiplex, - const int cols, - const int rows, - const int elements_per_row, - const float pG -) -{ - const int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx >= cols || gidy >= rows) - { - return; - } - const int offset = mad24(gidy, elements_per_row, gidx); - int index = offset; - - float Cr = chroma[index] * colorDensity[index]; - index += elements_per_row * rows; - float Cg = chroma[index] * colorDensity[index]; - index += elements_per_row * rows; - float Cb = chroma[index] * colorDensity[index]; - - const float luma_res = (Cr + Cg + Cb) * pG; - luma[offset] = luma_res; - demultiplex[bayerSampleOffset(elements_per_row, rows, gidx, gidy)] = - multiplex[offset] - luma_res; -} - - - -//////// computeGradient /////// -// TODO: -// this function maybe accelerated by image2d_t or lds -kernel void computeGradient( - global const float * luma, - global float * gradient, - const int cols, - const int rows, - const int elements_per_row -) -{ - int gidx = get_global_id(0) + 2, gidy = get_global_id(1) + 2; - if(gidx >= cols - 2 || gidy >= rows - 2) - { - return; - } - int offset = mad24(gidy, elements_per_row, gidx); - luma += offset; - - // horizontal and vertical local gradients - const float v_grad = fabs(luma[elements_per_row] - luma[- elements_per_row]); - const float h_grad = fabs(luma[1] - luma[-1]); - - // neighborhood horizontal and vertical gradients - const float cur_val = luma[0]; - const float v_grad_p = fabs(cur_val - luma[- 2 * elements_per_row]); - const float h_grad_p = fabs(cur_val - luma[- 2]); - const float v_grad_n = fabs(cur_val - luma[2 * elements_per_row]); - const float h_grad_n = fabs(cur_val - luma[2]); - - const float horiz_grad = 0.5f * h_grad + 0.25f * (h_grad_p + h_grad_n); - const float verti_grad = 0.5f * v_grad + 0.25f * (v_grad_p + v_grad_n); - const bool is_vertical_greater = horiz_grad < verti_grad; - - gradient[offset + elements_per_row * rows] = is_vertical_greater ? 0.06f : 0.57f; - gradient[offset ] = is_vertical_greater ? 0.57f : 0.06f; -} - - -/////// substractResidual /////// -kernel void substractResidual( - global float * input, - const int cols, - const int rows, - const int elements_per_row, - const float pR, - const float pG, - const float pB -) -{ - const int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx >= cols || gidy >= rows) - { - return; - } - int indices [3] = - { - mad24(gidy, elements_per_row, gidx), - mad24(gidy + rows, elements_per_row, gidx), - mad24(gidy + 2 * rows, elements_per_row, gidx) - }; - float vals[3] = {input[indices[0]], input[indices[1]], input[indices[2]]}; - float residu = pR * vals[0] + pG * vals[1] + pB * vals[2]; - - input[indices[0]] = vals[0] - residu; - input[indices[1]] = vals[1] - residu; - input[indices[2]] = vals[2] - residu; -} - -///// clipRGBOutput_0_maxInputValue ///// -kernel void clipRGBOutput_0_maxInputValue( - global float * input, - const int cols, - const int rows, - const int elements_per_row, - const float maxVal -) -{ - const int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx >= cols || gidy >= rows) - { - return; - } - const int offset = mad24(gidy, elements_per_row, gidx); - float val = input[offset]; - val = clamp(val, 0.0f, maxVal); - input[offset] = val; -} - -//// normalizeGrayOutputNearZeroCentreredSigmoide //// -kernel void normalizeGrayOutputNearZeroCentreredSigmoide( - global float * input, - global float * output, - const int cols, - const int rows, - const int elements_per_row, - const float maxVal, - const float X0cube -) -{ - const int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx >= cols || gidy >= rows) - { - return; - } - const int offset = mad24(gidy, elements_per_row, gidx); - float currentCubeLuminance = input[offset]; - currentCubeLuminance = currentCubeLuminance * currentCubeLuminance * currentCubeLuminance; - output[offset] = currentCubeLuminance * X0cube / (X0cube + currentCubeLuminance); -} - -//// centerReductImageLuminance //// -kernel void centerReductImageLuminance( - global float * input, - const int cols, - const int rows, - const int elements_per_row, - const float mean, - const float std_dev -) -{ - const int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx >= cols || gidy >= rows) - { - return; - } - const int offset = mad24(gidy, elements_per_row, gidx); - - float val = input[offset]; - input[offset] = (val - mean) / std_dev; -} - -//// inverseValue //// -kernel void inverseValue( - global float * input, - const int cols, - const int rows, - const int elements_per_row -) -{ - const int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx >= cols || gidy >= rows) - { - return; - } - const int offset = mad24(gidy, elements_per_row, gidx); - input[offset] = 1.f / input[offset]; -} - -#define CV_PI 3.1415926535897932384626433832795 - -//// _processRetinaParvoMagnoMapping //// -kernel void processRetinaParvoMagnoMapping( - global float * parvo, - global float * magno, - global float * output, - const int cols, - const int rows, - const int halfCols, - const int halfRows, - const int elements_per_row, - const float minDistance -) -{ - const int gidx = get_global_id(0), gidy = get_global_id(1); - if(gidx >= cols || gidy >= rows) - { - return; - } - const int offset = mad24(gidy, elements_per_row, gidx); - - float distanceToCenter = - sqrt(((float)(gidy - halfRows) * (gidy - halfRows) + (gidx - halfCols) * (gidx - halfCols))); - - float a = distanceToCenter < minDistance ? - (0.5f + 0.5f * (float)cos(CV_PI * distanceToCenter / minDistance)) : 0; - float b = 1.f - a; - - output[offset] = parvo[offset] * a + magno[offset] * b; -} diff --git a/modules/bioinspired/src/parvoretinafilter.cpp b/modules/bioinspired/src/parvoretinafilter.cpp deleted file mode 100644 index a276d97a4..000000000 --- a/modules/bioinspired/src/parvoretinafilter.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/*#****************************************************************************** -** 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. -** -** -** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. -** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. -** -** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) -** -** Creation - enhancement process 2007-2011 -** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France -** -** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). -** Refer to the following research paper for more information: -** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 -** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: -** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. -** -** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : -** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: -** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. -** ====> more informations in the above cited Jeanny Heraults's book. -** -** License Agreement -** For Open Source Computer Vision Library -** -** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** -** For Human Visual System tools (bioinspired) -** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions 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. -*******************************************************************************/ - -#include "precomp.hpp" - -#include "parvoretinafilter.hpp" - -// @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC : www.listic.univ-savoie.fr, Gipsa-Lab, France: www.gipsa-lab.inpg.fr/ - -#include -#include - -namespace cv -{ -namespace bioinspired -{ -////////////////////////////////////////////////////////// -// OPL RETINA FILTER -////////////////////////////////////////////////////////// - -// Constructor and Desctructor of the OPL retina filter - -ParvoRetinaFilter::ParvoRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns) -:BasicRetinaFilter(NBrows, NBcolumns, 3), - _photoreceptorsOutput(NBrows*NBcolumns), - _horizontalCellsOutput(NBrows*NBcolumns), - _parvocellularOutputON(NBrows*NBcolumns), - _parvocellularOutputOFF(NBrows*NBcolumns), - _bipolarCellsOutputON(NBrows*NBcolumns), - _bipolarCellsOutputOFF(NBrows*NBcolumns), - _localAdaptationOFF(NBrows*NBcolumns) -{ - // link to the required local parent adaptation buffers - _localAdaptationON=&_localBuffer; - _parvocellularOutputONminusOFF=&_filterOutput; - // (*_localAdaptationON)=&_localBuffer; - // (*_parvocellularOutputONminusOFF)=&(BasicRetinaFilter::TemplateBuffer); - - // init: set all the values to 0 - clearAllBuffers(); - - -#ifdef OPL_RETINA_ELEMENT_DEBUG - std::cout<<"ParvoRetinaFilter::Init OPL retina filter at specified frame size OK\n"< &ParvoRetinaFilter::runFilter(const std::valarray &inputFrame, const bool useParvoOutput) -{ - _spatiotemporalLPfilter(get_data(inputFrame), &_photoreceptorsOutput[0]); - _spatiotemporalLPfilter(&_photoreceptorsOutput[0], &_horizontalCellsOutput[0], 1); - _OPL_OnOffWaysComputing(); - - if (useParvoOutput) - { - // local adaptation processes on ON and OFF ways - _spatiotemporalLPfilter(&_bipolarCellsOutputON[0], &(*_localAdaptationON)[0], 2); - _localLuminanceAdaptation(&_parvocellularOutputON[0], &(*_localAdaptationON)[0]); - - _spatiotemporalLPfilter(&_bipolarCellsOutputOFF[0], &_localAdaptationOFF[0], 2); - _localLuminanceAdaptation(&_parvocellularOutputOFF[0], &_localAdaptationOFF[0]); - - //// Final loop that computes the main output of this filter - // - //// loop that makes the difference between photoreceptor cells output and horizontal cells - //// positive part goes on the ON way, negative pat goes on the OFF way - register float *parvocellularOutputONminusOFF_PTR=&(*_parvocellularOutputONminusOFF)[0]; - register float *parvocellularOutputON_PTR=&_parvocellularOutputON[0]; - register float *parvocellularOutputOFF_PTR=&_parvocellularOutputOFF[0]; - - for (register unsigned int IDpixel=0 ; IDpixel<_filterOutput.getNBpixels() ; ++IDpixel) - *(parvocellularOutputONminusOFF_PTR++)= (*(parvocellularOutputON_PTR++)-*(parvocellularOutputOFF_PTR++)); - } - return (*_parvocellularOutputONminusOFF); -} - -void ParvoRetinaFilter::_OPL_OnOffWaysComputing() // WARNING : this method requires many buffer accesses, parallelizing can increase bandwith & core efficacy -{ - // loop that makes the difference between photoreceptor cells output and horizontal cells - // positive part goes on the ON way, negative pat goes on the OFF way - -#ifdef MAKE_PARALLEL - cv::parallel_for_(cv::Range(0,_filterOutput.getNBpixels()), Parallel_OPL_OnOffWaysComputing(&_photoreceptorsOutput[0], &_horizontalCellsOutput[0], &_bipolarCellsOutputON[0], &_bipolarCellsOutputOFF[0], &_parvocellularOutputON[0], &_parvocellularOutputOFF[0])); -#else - float *photoreceptorsOutput_PTR= &_photoreceptorsOutput[0]; - float *horizontalCellsOutput_PTR= &_horizontalCellsOutput[0]; - float *bipolarCellsON_PTR = &_bipolarCellsOutputON[0]; - float *bipolarCellsOFF_PTR = &_bipolarCellsOutputOFF[0]; - float *parvocellularOutputON_PTR= &_parvocellularOutputON[0]; - float *parvocellularOutputOFF_PTR= &_parvocellularOutputOFF[0]; - // compute bipolar cells response equal to photoreceptors minus horizontal cells response - // and copy the result on parvo cellular outputs... keeping time before their local contrast adaptation for final result - for (register unsigned int IDpixel=0 ; IDpixel<_filterOutput.getNBpixels() ; ++IDpixel) - { - float pixelDifference = *(photoreceptorsOutput_PTR++) -*(horizontalCellsOutput_PTR++); - // test condition to allow write pixelDifference in ON or OFF buffer and 0 in the over - float isPositive=(float) (pixelDifference>0.0f); - - // ON and OFF channels writing step - *(parvocellularOutputON_PTR++)=*(bipolarCellsON_PTR++) = isPositive*pixelDifference; - *(parvocellularOutputOFF_PTR++)=*(bipolarCellsOFF_PTR++)= (isPositive-1.0f)*pixelDifference; - } -#endif -} -}// end of namespace bioinspired -}// end of namespace cv diff --git a/modules/bioinspired/src/parvoretinafilter.hpp b/modules/bioinspired/src/parvoretinafilter.hpp deleted file mode 100644 index 0fc184792..000000000 --- a/modules/bioinspired/src/parvoretinafilter.hpp +++ /dev/null @@ -1,264 +0,0 @@ -/*#****************************************************************************** -** 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. -** -** -** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. -** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. -** -** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) -** -** Creation - enhancement process 2007-2011 -** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France -** -** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). -** Refer to the following research paper for more information: -** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 -** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: -** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. -** -** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : -** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: -** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. -** ====> more informations in the above cited Jeanny Heraults's book. -** -** License Agreement -** For Open Source Computer Vision Library -** -** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** -** For Human Visual System tools (bioinspired) -** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions 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. -*******************************************************************************/ - -#ifndef ParvoRetinaFilter_H_ -#define ParvoRetinaFilter_H_ - -/** -* @class ParvoRetinaFilter -* @brief class which describes the OPL retina model and the Inner Plexiform Layer parvocellular channel of the retina: -* -> performs a contours extraction with powerfull local data enhancement as at the retina level -* -> spectrum whitening occurs at the OPL (Outer Plexiform Layer) of the retina: corrects the 1/f spectrum tendancy of natural images -* ---> enhances details with mid spatial frequencies, attenuates low spatial frequencies (luminance), attenuates high temporal frequencies and high spatial frequencies, etc. -* -* TYPICAL USE: -* -* // create object at a specified picture size -* ParvoRetinaFilter *contoursExtractor; -* contoursExtractor =new ParvoRetinaFilter(frameSizeRows, frameSizeColumns); -* -* // init gain, spatial and temporal parameters: -* contoursExtractor->setCoefficientsTable(0, 0.7, 1, 0, 7, 1); -* -* // during program execution, call the filter for contours extraction for an input picture called "FrameBuffer": -* contoursExtractor->runfilter(FrameBuffer); -* -* // get the output frame, check in the class description below for more outputs: -* const float *contours=contoursExtractor->getParvoONminusOFF(); -* -* // at the end of the program, destroy object: -* delete contoursExtractor; - -* @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC : www.listic.univ-savoie.fr, Gipsa-Lab, France: www.gipsa-lab.inpg.fr/ -* Creation date 2007 -* Based on Alexandre BENOIT thesis: "Le système visuel humain au secours de la vision par ordinateur" -* -*/ - -#include "basicretinafilter.hpp" - - -//#define _OPL_RETINA_ELEMENT_DEBUG - -namespace cv -{ -namespace bioinspired -{ -//retina classes that derivate from the Basic Retrina class -class ParvoRetinaFilter: public BasicRetinaFilter -{ - -public: - /** - * constructor parameters are only linked to image input size - * @param NBrows: number of rows of the input image - * @param NBcolumns: number of columns of the input image - */ - ParvoRetinaFilter(const unsigned int NBrows=480, const unsigned int NBcolumns=640); - - /** - * standard desctructor - */ - virtual ~ParvoRetinaFilter(); - - /** - * resize method, keeps initial parameters, all buffers are flushed - * @param NBrows: number of rows of the input image - * @param NBcolumns: number of columns of the input image - */ - void resize(const unsigned int NBrows, const unsigned int NBcolumns); - - /** - * function that clears all buffers of the object - */ - void clearAllBuffers(); - - /** - * setup the OPL and IPL parvo channels - * @param beta1: gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, the amplitude is boosted but it should only be used for values rescaling... if needed - * @param tau1: the time constant of the first order low pass filter of the photoreceptors, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 1 frame - * @param k1: the spatial constant of the first order low pass filter of the photoreceptors, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 1 pixel - * @param beta2: gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, then, the luminance is not filtered and is still reachable at the output, typicall value is 0 - * @param tau2: the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors - * @param k2: the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model) - */ - void setOPLandParvoFiltersParameters(const float beta1, const float tau1, const float k1, const float beta2, const float tau2, const float k2); - - /** - * setup more precisely the low pass filter used for the ganglion cells low pass filtering (used for local luminance adaptation) - * @param tau: time constant of the filter (unit is frame for video processing) - * @param k: spatial constant of the filter (unit is pixels) - */ - void setGanglionCellsLocalAdaptationLPfilterParameters(const float tau, const float k) - { BasicRetinaFilter::setLPfilterParameters(0, tau, k, 2); } // change the parameters of the filter - - - /** - * launch filter that runs the OPL spatiotemporal filtering and optionally finalizes IPL Pagno filter (model of the Parvocellular channel of the Inner Plexiform Layer of the retina) - * @param inputFrame: the input image to be processed, this can be the direct gray level input frame, but a better efficacy is expected if the input is preliminary processed by the photoreceptors local adaptation possible to acheive with the help of a BasicRetinaFilter object - * @param useParvoOutput: set true if the final IPL filtering step has to be computed (local contrast enhancement) - * @return the processed Parvocellular channel output (updated only if useParvoOutput is true) - * @details: in any case, after this function call, photoreceptors and horizontal cells output are updated, use getPhotoreceptorsLPfilteringOutput() and getHorizontalCellsOutput() to get them - * also, bipolar cells output are accessible (difference between photoreceptors and horizontal cells, ON output has positive values, OFF ouput has negative values), use the following access methods: getBipolarCellsON() and getBipolarCellsOFF()if useParvoOutput is true, - * if useParvoOutput is true, the complete Parvocellular channel is computed, more outputs are updated and can be accessed threw: getParvoON(), getParvoOFF() and their difference with getOutput() - */ - const std::valarray &runFilter(const std::valarray &inputFrame, const bool useParvoOutput=true); // output return is _parvocellularOutputONminusOFF - - /** - * @return the output of the photoreceptors filtering step (high cut frequency spatio-temporal low pass filter) - */ - inline const std::valarray &getPhotoreceptorsLPfilteringOutput() const { return _photoreceptorsOutput; } - - /** - * @return the output of the photoreceptors filtering step (low cut frequency spatio-temporal low pass filter) - */ - inline const std::valarray &getHorizontalCellsOutput() const { return _horizontalCellsOutput; } - - /** - * @return the output Parvocellular ON channel of the retina model - */ - inline const std::valarray &getParvoON() const { return _parvocellularOutputON; } - - /** - * @return the output Parvocellular OFF channel of the retina model - */ - inline const std::valarray &getParvoOFF() const { return _parvocellularOutputOFF; } - - /** - * @return the output of the Bipolar cells of the ON channel of the retina model same as function getParvoON() but without luminance local adaptation - */ - inline const std::valarray &getBipolarCellsON() const { return _bipolarCellsOutputON; } - - /** - * @return the output of the Bipolar cells of the OFF channel of the retina model same as function getParvoON() but without luminance local adaptation - */ - inline const std::valarray &getBipolarCellsOFF() const { return _bipolarCellsOutputOFF; } - - /** - * @return the photoreceptors's temporal constant - */ - inline float getPhotoreceptorsTemporalConstant() { return _filteringCoeficientsTable[2]; } - - /** - * @return the horizontal cells' temporal constant - */ - inline float getHcellsTemporalConstant(){return _filteringCoeficientsTable[5]; } - -private: - // template buffers - std::valarray _photoreceptorsOutput; - std::valarray _horizontalCellsOutput; - std::valarray _parvocellularOutputON; - std::valarray _parvocellularOutputOFF; - std::valarray _bipolarCellsOutputON; - std::valarray _bipolarCellsOutputOFF; - std::valarray _localAdaptationOFF; - std::valarray *_localAdaptationON; - TemplateBuffer *_parvocellularOutputONminusOFF; - // private functions - void _OPL_OnOffWaysComputing(); - -#ifdef MAKE_PARALLEL -/****************************************************** -** IF some parallelizing thread methods are available, then, main loops are parallelized using these functors -** ==> main idea paralellise main filters loops, then, only the most used methods are parallelized... TODO : increase the number of parallelised methods as necessary -** ==> functors names = Parallel_$$$ where $$$= the name of the serial method that is parallelised -** ==> functors constructors can differ from the parameters used with their related serial functions -*/ - class Parallel_OPL_OnOffWaysComputing: public cv::ParallelLoopBody - { - private: - float *photoreceptorsOutput, *horizontalCellsOutput, *bipolarCellsON, *bipolarCellsOFF, *parvocellularOutputON, *parvocellularOutputOFF; - public: - Parallel_OPL_OnOffWaysComputing(float *photoreceptorsOutput_PTR, float *horizontalCellsOutput_PTR, float *bipolarCellsON_PTR, float *bipolarCellsOFF_PTR, float *parvocellularOutputON_PTR, float *parvocellularOutputOFF_PTR) - :photoreceptorsOutput(photoreceptorsOutput_PTR), horizontalCellsOutput(horizontalCellsOutput_PTR), bipolarCellsON(bipolarCellsON_PTR), bipolarCellsOFF(bipolarCellsOFF_PTR), parvocellularOutputON(parvocellularOutputON_PTR), parvocellularOutputOFF(parvocellularOutputOFF_PTR) {} - - virtual void operator()( const Range& r ) const { - // compute bipolar cells response equal to photoreceptors minus horizontal cells response - // and copy the result on parvo cellular outputs... keeping time before their local contrast adaptation for final result - float *photoreceptorsOutput_PTR= photoreceptorsOutput+r.start; - float *horizontalCellsOutput_PTR= horizontalCellsOutput+r.start; - float *bipolarCellsON_PTR = bipolarCellsON+r.start; - float *bipolarCellsOFF_PTR = bipolarCellsOFF+r.start; - float *parvocellularOutputON_PTR= parvocellularOutputON+r.start; - float *parvocellularOutputOFF_PTR= parvocellularOutputOFF+r.start; - - for (register int IDpixel=r.start ; IDpixel!=r.end ; ++IDpixel) - { - float pixelDifference = *(photoreceptorsOutput_PTR++) -*(horizontalCellsOutput_PTR++); - // test condition to allow write pixelDifference in ON or OFF buffer and 0 in the over - float isPositive=(float) (pixelDifference>0.0f); - - // ON and OFF channels writing step - *(parvocellularOutputON_PTR++)=*(bipolarCellsON_PTR++) = isPositive*pixelDifference; - *(parvocellularOutputOFF_PTR++)=*(bipolarCellsOFF_PTR++)= (isPositive-1.0f)*pixelDifference; - } - } - }; -#endif - -}; -}// end of namespace bioinspired -}// end of namespace cv -#endif diff --git a/modules/bioinspired/src/precomp.hpp b/modules/bioinspired/src/precomp.hpp deleted file mode 100644 index 61aeb5409..000000000 --- a/modules/bioinspired/src/precomp.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/*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) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., 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_PRECOMP_H__ -#define __OPENCV_PRECOMP_H__ - -#include "opencv2/opencv_modules.hpp" -#include "opencv2/bioinspired.hpp" -#include "opencv2/core/utility.hpp" -#include "opencv2/core/private.hpp" -#include "opencv2/core/ocl.hpp" - -#include - -#ifdef HAVE_OPENCV_OCL - #include "opencv2/ocl/private/util.hpp" -#endif - -namespace cv -{ - -// special function to get pointer to constant valarray elements, since -// simple &arr[0] does not compile on VS2005/VS2008. -template inline const T* get_data(const std::valarray& arr) -{ return &((std::valarray&)arr)[0]; } - -} - -#endif diff --git a/modules/bioinspired/src/retina.cpp b/modules/bioinspired/src/retina.cpp deleted file mode 100644 index e43224028..000000000 --- a/modules/bioinspired/src/retina.cpp +++ /dev/null @@ -1,745 +0,0 @@ -/*#****************************************************************************** - ** 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. - ** - ** - ** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. - ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. - ** - ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) - ** - ** Creation - enhancement process 2007-2011 - ** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France - ** - ** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). - ** Refer to the following research paper for more information: - ** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 - ** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: - ** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. - ** - ** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : - ** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: - ** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 - ** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. - ** ====> more informations in the above cited Jeanny Heraults's book. - ** - ** License Agreement - ** For Open Source Computer Vision Library - ** - ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. - ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. - ** - ** For Human Visual System tools (bioinspired) - ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: - ** - ** * Redistributions of source code must retain the above copyright notice, - ** this list of conditions and the following disclaimer. - ** - ** * Redistributions 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. - *******************************************************************************/ - -/* - * Retina.cpp - * - * Created on: Jul 19, 2011 - * Author: Alexandre Benoit - */ -#include "precomp.hpp" -#include "retinafilter.hpp" -#include -#include -#include - -namespace cv -{ -namespace bioinspired -{ - -class RetinaImpl : public Retina -{ -public: - /** - * Main constructor with most commun use setup : create an instance of color ready retina model - * @param inputSize : the input frame size - */ - RetinaImpl(Size inputSize); - - /** - * Complete Retina filter constructor which allows all basic structural parameters definition - * @param inputSize : the input frame size - * @param colorMode : the chosen processing mode : with or without color processing - * @param colorSamplingMethod: specifies which kind of color sampling will be used - * @param useRetinaLogSampling: activate retina log sampling, if true, the 2 following parameters can be used - * @param reductionFactor: only usefull if param useRetinaLogSampling=true, specifies the reduction factor of the output frame (as the center (fovea) is high resolution and corners can be underscaled, then a reduction of the output is allowed without precision leak - * @param samplingStrenght: only usefull if param useRetinaLogSampling=true, specifies the strenght of the log scale that is applied - */ - RetinaImpl(Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); - - virtual ~RetinaImpl(); - /** - * retreive retina input buffer size - */ - Size getInputSize(); - - /** - * retreive retina output buffer size - */ - Size getOutputSize(); - - /** - * try to open an XML retina parameters file to adjust current retina instance setup - * => if the xml file does not exist, then default setup is applied - * => warning, Exceptions are thrown if read XML file is not valid - * @param retinaParameterFile : the parameters filename - * @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error - */ - void setup(String retinaParameterFile="", const bool applyDefaultSetupOnFailure=true); - - - /** - * try to open an XML retina parameters file to adjust current retina instance setup - * => if the xml file does not exist, then default setup is applied - * => warning, Exceptions are thrown if read XML file is not valid - * @param fs : the open Filestorage which contains retina parameters - * @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error - */ - void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure=true); - - /** - * try to open an XML retina parameters file to adjust current retina instance setup - * => if the xml file does not exist, then default setup is applied - * => warning, Exceptions are thrown if read XML file is not valid - * @param newParameters : a parameters structures updated with the new target configuration - * @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error - */ - void setup(Retina::RetinaParameters newParameters); - - /** - * @return the current parameters setup - */ - struct Retina::RetinaParameters getParameters(); - - /** - * parameters setup display method - * @return a string which contains formatted parameters information - */ - const String printSetup(); - - /** - * write xml/yml formated parameters information - * @rparam fs : the filename of the xml file that will be open and writen with formatted parameters information - */ - virtual void write( String fs ) const; - - - /** - * write xml/yml formated parameters information - * @param fs : a cv::Filestorage object ready to be filled - */ - virtual void write( FileStorage& fs ) const; - - /** - * setup the OPL and IPL parvo channels (see biologocal model) - * OPL is referred as Outer Plexiform Layer of the retina, it allows the spatio-temporal filtering which withens the spectrum and reduces spatio-temporal noise while attenuating global luminance (low frequency energy) - * IPL parvo is the OPL next processing stage, it refers to Inner Plexiform layer of the retina, it allows high contours sensitivity in foveal vision. - * for more informations, please have a look at the paper Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 - * @param colorMode : specifies if (true) color is processed of not (false) to then processing gray level image - * @param normaliseOutput : specifies if (true) output is rescaled between 0 and 255 of not (false) - * @param photoreceptorsLocalAdaptationSensitivity: the photoreceptors sensitivity renage is 0-1 (more log compression effect when value increases) - * @param photoreceptorsTemporalConstant: the time constant of the first order low pass filter of the photoreceptors, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 1 frame - * @param photoreceptorsSpatialConstant: the spatial constant of the first order low pass filter of the photoreceptors, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 1 pixel - * @param horizontalCellsGain: gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, then, the luminance is not filtered and is still reachable at the output, typicall value is 0 - * @param HcellsTemporalConstant: the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors - * @param HcellsSpatialConstant: the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model) - * @param ganglionCellsSensitivity: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 230 - */ - void setupOPLandIPLParvoChannel(const bool colorMode=true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity=0.7, const float photoreceptorsTemporalConstant=0.5, const float photoreceptorsSpatialConstant=0.53, const float horizontalCellsGain=0, const float HcellsTemporalConstant=1, const float HcellsSpatialConstant=7, const float ganglionCellsSensitivity=0.7); - - /** - * set parameters values for the Inner Plexiform Layer (IPL) magnocellular channel - * this channel processes signals outpint from OPL processing stage in peripheral vision, it allows motion information enhancement. It is decorrelated from the details channel. See reference paper for more details. - * @param normaliseOutput : specifies if (true) output is rescaled between 0 and 255 of not (false) - * @param parasolCells_beta: the low pass filter gain used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), typical value is 0 - * @param parasolCells_tau: the low pass filter time constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is frame, typical value is 0 (immediate response) - * @param parasolCells_k: the low pass filter spatial constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is pixels, typical value is 5 - * @param amacrinCellsTemporalCutFrequency: the time constant of the first order high pass fiter of the magnocellular way (motion information channel), unit is frames, tipicall value is 5 - * @param V0CompressionParameter: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 200 - * @param localAdaptintegration_tau: specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation - * @param localAdaptintegration_k: specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation - */ - void setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta=0, const float parasolCells_tau=0, const float parasolCells_k=7, const float amacrinCellsTemporalCutFrequency=1.2, const float V0CompressionParameter=0.95, const float localAdaptintegration_tau=0, const float localAdaptintegration_k=7); - - /** - * method which allows retina to be applied on an input image, after run, encapsulated retina module is ready to deliver its outputs using dedicated acccessors, see getParvo and getMagno methods - * @param inputImage : the input cv::Mat image to be processed, can be gray level or BGR coded in any format (from 8bit to 16bits) - */ - void run(InputArray inputImage); - - /** - * method that applies a luminance correction (initially High Dynamic Range (HDR) tone mapping) using only the 2 local adaptation stages of the retina parvo channel : photoreceptors level and ganlion cells level. Spatio temporal filtering is applied but limited to temporal smoothing and eventually high frequencies attenuation. This is a lighter method than the one available using the regular run method. It is then faster but it does not include complete temporal filtering nor retina spectral whitening. This is an adptation of the original still image HDR tone mapping algorithm of David Alleyson, Sabine Susstruck and Laurence Meylan's work, please cite: - * -> Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 - @param inputImage the input image to process RGB or gray levels - @param outputToneMappedImage the output tone mapped image - */ - void applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage); - - /** - * accessor of the details channel of the retina (models foveal vision) - * @param retinaOutput_parvo : the output buffer (reallocated if necessary), this output is rescaled for standard 8bits image processing use in OpenCV - */ - void getParvo(OutputArray retinaOutput_parvo); - - /** - * accessor of the details channel of the retina (models foveal vision) - * @param retinaOutput_parvo : a cv::Mat header filled with the internal parvo buffer of the retina module. This output is the original retina filter model output, without any quantification or rescaling - */ - void getParvoRAW(OutputArray retinaOutput_parvo); - - /** - * accessor of the motion channel of the retina (models peripheral vision) - * @param retinaOutput_magno : the output buffer (reallocated if necessary), this output is rescaled for standard 8bits image processing use in OpenCV - */ - void getMagno(OutputArray retinaOutput_magno); - - /** - * accessor of the motion channel of the retina (models peripheral vision) - * @param retinaOutput_magno : a cv::Mat header filled with the internal retina magno buffer of the retina module. This output is the original retina filter model output, without any quantification or rescaling - */ - void getMagnoRAW(OutputArray retinaOutput_magno); - - // original API level data accessors : get buffers addresses from a Mat header, similar to getParvoRAW and getMagnoRAW... - const Mat getMagnoRAW() const; - const Mat getParvoRAW() const; - - /** - * activate color saturation as the final step of the color demultiplexing process - * -> this saturation is a sigmoide function applied to each channel of the demultiplexed image. - * @param saturateColors: boolean that activates color saturation (if true) or desactivate (if false) - * @param colorSaturationValue: the saturation factor - */ - void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0); - - /** - * clear all retina buffers (equivalent to opening the eyes after a long period of eye close ;o) - */ - void clearBuffers(); - - /** - * Activate/desactivate the Magnocellular pathway processing (motion information extraction), by default, it is activated - * @param activate: true if Magnocellular output should be activated, false if not - */ - void activateMovingContoursProcessing(const bool activate); - - /** - * Activate/desactivate the Parvocellular pathway processing (contours information extraction), by default, it is activated - * @param activate: true if Parvocellular (contours information extraction) output should be activated, false if not - */ - void activateContoursProcessing(const bool activate); -private: - - // Parameteres setup members - RetinaParameters _retinaParameters; // structure of parameters - - // Retina model related modules - std::valarray _inputBuffer; //!< buffer used to convert input cv::Mat to internal retina buffers format (valarrays) - - // pointer to retina model - RetinaFilter* _retinaFilter; //!< the pointer to the retina module, allocated with instance construction - - //! private method called by constructors, gathers their parameters and use them in a unified way - void _init(const Size inputSize, const bool colorMode, int colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); - - /** - * exports a valarray buffer outing from bioinspired objects to a cv::Mat in CV_8UC1 (gray level picture) or CV_8UC3 (color) format - * @param grayMatrixToConvert the valarray to export to OpenCV - * @param nbRows : the number of rows of the valarray flatten matrix - * @param nbColumns : the number of rows of the valarray flatten matrix - * @param colorMode : a flag which mentions if matrix is color (true) or graylevel (false) - * @param outBuffer : the output matrix which is reallocated to satisfy Retina output buffer dimensions - */ - void _convertValarrayBuffer2cvMat(const std::valarray &grayMatrixToConvert, const unsigned int nbRows, const unsigned int nbColumns, const bool colorMode, OutputArray outBuffer); - - /** - * convert a cv::Mat to a valarray buffer in float format - * @param inputMatToConvert : the OpenCV cv::Mat that has to be converted to gray or RGB valarray buffer that will be processed by the retina model - * @param outputValarrayMatrix : the output valarray - * @return the input image color mode (color=true, gray levels=false) - */ - bool _convertCvMat2ValarrayBuffer(InputArray inputMatToConvert, std::valarray &outputValarrayMatrix); - - -}; - -// smart pointers allocation : -Ptr createRetina(Size inputSize){ return makePtr(inputSize); } -Ptr createRetina(Size inputSize, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght){ - return makePtr(inputSize, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); -} - - -// RetinaImpl code -RetinaImpl::RetinaImpl(const cv::Size inputSz) -{ - _retinaFilter = 0; - _init(inputSz, true, RETINA_COLOR_BAYER, false); -} - -RetinaImpl::RetinaImpl(const cv::Size inputSz, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) -{ - _retinaFilter = 0; - _init(inputSz, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); -} - -RetinaImpl::~RetinaImpl() -{ - if (_retinaFilter) - delete _retinaFilter; -} - -/** -* retreive retina input buffer size -*/ -Size RetinaImpl::getInputSize(){return cv::Size(_retinaFilter->getInputNBcolumns(), _retinaFilter->getInputNBrows());} - -/** -* retreive retina output buffer size -*/ -Size RetinaImpl::getOutputSize(){return cv::Size(_retinaFilter->getOutputNBcolumns(), _retinaFilter->getOutputNBrows());} - - -void RetinaImpl::setColorSaturation(const bool saturateColors, const float colorSaturationValue) -{ - _retinaFilter->setColorSaturation(saturateColors, colorSaturationValue); -} - -struct Retina::RetinaParameters RetinaImpl::getParameters(){return _retinaParameters;} - -void RetinaImpl::setup(String retinaParameterFile, const bool applyDefaultSetupOnFailure) -{ - try - { - // opening retinaParameterFile in read mode - cv::FileStorage fs(retinaParameterFile, cv::FileStorage::READ); - setup(fs, applyDefaultSetupOnFailure); - } - catch(Exception &e) - { - printf("Retina::setup: wrong/unappropriate xml parameter file : error report :`n=>%s\n", e.what()); - if (applyDefaultSetupOnFailure) - { - printf("Retina::setup: resetting retina with default parameters\n"); - setupOPLandIPLParvoChannel(); - setupIPLMagnoChannel(); - } - else - { - printf("=> keeping current parameters\n"); - } - } -} - -void RetinaImpl::setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure) -{ - try - { - // read parameters file if it exists or apply default setup if asked for - if (!fs.isOpened()) - { - printf("Retina::setup: provided parameters file could not be open... skeeping configuration\n"); - return; - // implicit else case : retinaParameterFile could be open (it exists at least) - } - // OPL and Parvo init first... update at the same time the parameters structure and the retina core - cv::FileNode rootFn = fs.root(), currFn=rootFn["OPLandIPLparvo"]; - currFn["colorMode"]>>_retinaParameters.OPLandIplParvo.colorMode; - currFn["normaliseOutput"]>>_retinaParameters.OPLandIplParvo.normaliseOutput; - currFn["photoreceptorsLocalAdaptationSensitivity"]>>_retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity; - currFn["photoreceptorsTemporalConstant"]>>_retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant; - currFn["photoreceptorsSpatialConstant"]>>_retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant; - currFn["horizontalCellsGain"]>>_retinaParameters.OPLandIplParvo.horizontalCellsGain; - currFn["hcellsTemporalConstant"]>>_retinaParameters.OPLandIplParvo.hcellsTemporalConstant; - currFn["hcellsSpatialConstant"]>>_retinaParameters.OPLandIplParvo.hcellsSpatialConstant; - currFn["ganglionCellsSensitivity"]>>_retinaParameters.OPLandIplParvo.ganglionCellsSensitivity; - setupOPLandIPLParvoChannel(_retinaParameters.OPLandIplParvo.colorMode, _retinaParameters.OPLandIplParvo.normaliseOutput, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant, _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant, _retinaParameters.OPLandIplParvo.horizontalCellsGain, _retinaParameters.OPLandIplParvo.hcellsTemporalConstant, _retinaParameters.OPLandIplParvo.hcellsSpatialConstant, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity); - - // init retina IPL magno setup... update at the same time the parameters structure and the retina core - currFn=rootFn["IPLmagno"]; - currFn["normaliseOutput"]>>_retinaParameters.IplMagno.normaliseOutput; - currFn["parasolCells_beta"]>>_retinaParameters.IplMagno.parasolCells_beta; - currFn["parasolCells_tau"]>>_retinaParameters.IplMagno.parasolCells_tau; - currFn["parasolCells_k"]>>_retinaParameters.IplMagno.parasolCells_k; - currFn["amacrinCellsTemporalCutFrequency"]>>_retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency; - currFn["V0CompressionParameter"]>>_retinaParameters.IplMagno.V0CompressionParameter; - currFn["localAdaptintegration_tau"]>>_retinaParameters.IplMagno.localAdaptintegration_tau; - currFn["localAdaptintegration_k"]>>_retinaParameters.IplMagno.localAdaptintegration_k; - - setupIPLMagnoChannel(_retinaParameters.IplMagno.normaliseOutput, _retinaParameters.IplMagno.parasolCells_beta, _retinaParameters.IplMagno.parasolCells_tau, _retinaParameters.IplMagno.parasolCells_k, _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency,_retinaParameters.IplMagno.V0CompressionParameter, _retinaParameters.IplMagno.localAdaptintegration_tau, _retinaParameters.IplMagno.localAdaptintegration_k); - - } - catch(Exception &e) - { - printf("RetinaImpl::setup: resetting retina with default parameters\n"); - if (applyDefaultSetupOnFailure) - { - setupOPLandIPLParvoChannel(); - setupIPLMagnoChannel(); - } - printf("Retina::setup: wrong/unappropriate xml parameter file : error report :`n=>%s\n", e.what()); - printf("=> keeping current parameters\n"); - } - - // report current configuration - printf("%s\n", printSetup().c_str()); -} - -void RetinaImpl::setup(Retina::RetinaParameters newConfiguration) -{ - // simply copy structures - memcpy(&_retinaParameters, &newConfiguration, sizeof(Retina::RetinaParameters)); - // apply setup - setupOPLandIPLParvoChannel(_retinaParameters.OPLandIplParvo.colorMode, _retinaParameters.OPLandIplParvo.normaliseOutput, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant, _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant, _retinaParameters.OPLandIplParvo.horizontalCellsGain, _retinaParameters.OPLandIplParvo.hcellsTemporalConstant, _retinaParameters.OPLandIplParvo.hcellsSpatialConstant, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity); - setupIPLMagnoChannel(_retinaParameters.IplMagno.normaliseOutput, _retinaParameters.IplMagno.parasolCells_beta, _retinaParameters.IplMagno.parasolCells_tau, _retinaParameters.IplMagno.parasolCells_k, _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency,_retinaParameters.IplMagno.V0CompressionParameter, _retinaParameters.IplMagno.localAdaptintegration_tau, _retinaParameters.IplMagno.localAdaptintegration_k); - -} - -const String RetinaImpl::printSetup() -{ - std::stringstream outmessage; - - // displaying OPL and IPL parvo setup - outmessage<<"Current Retina instance setup :" - <<"\nOPLandIPLparvo"<<"{" - << "\n\t colorMode : " << _retinaParameters.OPLandIplParvo.colorMode - << "\n\t normalizeParvoOutput :" << _retinaParameters.OPLandIplParvo.normaliseOutput - << "\n\t photoreceptorsLocalAdaptationSensitivity : " << _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity - << "\n\t photoreceptorsTemporalConstant : " << _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant - << "\n\t photoreceptorsSpatialConstant : " << _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant - << "\n\t horizontalCellsGain : " << _retinaParameters.OPLandIplParvo.horizontalCellsGain - << "\n\t hcellsTemporalConstant : " << _retinaParameters.OPLandIplParvo.hcellsTemporalConstant - << "\n\t hcellsSpatialConstant : " << _retinaParameters.OPLandIplParvo.hcellsSpatialConstant - << "\n\t parvoGanglionCellsSensitivity : " << _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity - <<"}\n"; - - // displaying IPL magno setup - outmessage<<"Current Retina instance setup :" - <<"\nIPLmagno"<<"{" - << "\n\t normaliseOutput : " << _retinaParameters.IplMagno.normaliseOutput - << "\n\t parasolCells_beta : " << _retinaParameters.IplMagno.parasolCells_beta - << "\n\t parasolCells_tau : " << _retinaParameters.IplMagno.parasolCells_tau - << "\n\t parasolCells_k : " << _retinaParameters.IplMagno.parasolCells_k - << "\n\t amacrinCellsTemporalCutFrequency : " << _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency - << "\n\t V0CompressionParameter : " << _retinaParameters.IplMagno.V0CompressionParameter - << "\n\t localAdaptintegration_tau : " << _retinaParameters.IplMagno.localAdaptintegration_tau - << "\n\t localAdaptintegration_k : " << _retinaParameters.IplMagno.localAdaptintegration_k - <<"}"; - return outmessage.str().c_str(); -} - -void RetinaImpl::write( String fs ) const -{ - FileStorage parametersSaveFile(fs, cv::FileStorage::WRITE ); - write(parametersSaveFile); -} - -void RetinaImpl::write( FileStorage& fs ) const -{ - if (!fs.isOpened()) - return; // basic error case - fs<<"OPLandIPLparvo"<<"{"; - fs << "colorMode" << _retinaParameters.OPLandIplParvo.colorMode; - fs << "normaliseOutput" << _retinaParameters.OPLandIplParvo.normaliseOutput; - fs << "photoreceptorsLocalAdaptationSensitivity" << _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity; - fs << "photoreceptorsTemporalConstant" << _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant; - fs << "photoreceptorsSpatialConstant" << _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant; - fs << "horizontalCellsGain" << _retinaParameters.OPLandIplParvo.horizontalCellsGain; - fs << "hcellsTemporalConstant" << _retinaParameters.OPLandIplParvo.hcellsTemporalConstant; - fs << "hcellsSpatialConstant" << _retinaParameters.OPLandIplParvo.hcellsSpatialConstant; - fs << "ganglionCellsSensitivity" << _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity; - fs << "}"; - fs<<"IPLmagno"<<"{"; - fs << "normaliseOutput" << _retinaParameters.IplMagno.normaliseOutput; - fs << "parasolCells_beta" << _retinaParameters.IplMagno.parasolCells_beta; - fs << "parasolCells_tau" << _retinaParameters.IplMagno.parasolCells_tau; - fs << "parasolCells_k" << _retinaParameters.IplMagno.parasolCells_k; - fs << "amacrinCellsTemporalCutFrequency" << _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency; - fs << "V0CompressionParameter" << _retinaParameters.IplMagno.V0CompressionParameter; - fs << "localAdaptintegration_tau" << _retinaParameters.IplMagno.localAdaptintegration_tau; - fs << "localAdaptintegration_k" << _retinaParameters.IplMagno.localAdaptintegration_k; - fs<<"}"; -} - -void RetinaImpl::setupOPLandIPLParvoChannel(const bool colorMode, const bool normaliseOutput, const float photoreceptorsLocalAdaptationSensitivity, const float photoreceptorsTemporalConstant, const float photoreceptorsSpatialConstant, const float horizontalCellsGain, const float HcellsTemporalConstant, const float HcellsSpatialConstant, const float ganglionCellsSensitivity) -{ - // retina core parameters setup - _retinaFilter->setColorMode(colorMode); - _retinaFilter->setPhotoreceptorsLocalAdaptationSensitivity(photoreceptorsLocalAdaptationSensitivity); - _retinaFilter->setOPLandParvoParameters(0, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, HcellsTemporalConstant, HcellsSpatialConstant, ganglionCellsSensitivity); - _retinaFilter->setParvoGanglionCellsLocalAdaptationSensitivity(ganglionCellsSensitivity); - _retinaFilter->activateNormalizeParvoOutput_0_maxOutputValue(normaliseOutput); - - // update parameters struture - - _retinaParameters.OPLandIplParvo.colorMode = colorMode; - _retinaParameters.OPLandIplParvo.normaliseOutput = normaliseOutput; - _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity = photoreceptorsLocalAdaptationSensitivity; - _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant = photoreceptorsTemporalConstant; - _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant = photoreceptorsSpatialConstant; - _retinaParameters.OPLandIplParvo.horizontalCellsGain = horizontalCellsGain; - _retinaParameters.OPLandIplParvo.hcellsTemporalConstant = HcellsTemporalConstant; - _retinaParameters.OPLandIplParvo.hcellsSpatialConstant = HcellsSpatialConstant; - _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity = ganglionCellsSensitivity; - -} - -void RetinaImpl::setupIPLMagnoChannel(const bool normaliseOutput, const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float V0CompressionParameter, const float localAdaptintegration_tau, const float localAdaptintegration_k) -{ - - _retinaFilter->setMagnoCoefficientsTable(parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k); - _retinaFilter->activateNormalizeMagnoOutput_0_maxOutputValue(normaliseOutput); - - // update parameters struture - _retinaParameters.IplMagno.normaliseOutput = normaliseOutput; - _retinaParameters.IplMagno.parasolCells_beta = parasolCells_beta; - _retinaParameters.IplMagno.parasolCells_tau = parasolCells_tau; - _retinaParameters.IplMagno.parasolCells_k = parasolCells_k; - _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency = amacrinCellsTemporalCutFrequency; - _retinaParameters.IplMagno.V0CompressionParameter = V0CompressionParameter; - _retinaParameters.IplMagno.localAdaptintegration_tau = localAdaptintegration_tau; - _retinaParameters.IplMagno.localAdaptintegration_k = localAdaptintegration_k; -} - -void RetinaImpl::run(InputArray inputMatToConvert) -{ - // first convert input image to the compatible format : std::valarray - const bool colorMode = _convertCvMat2ValarrayBuffer(inputMatToConvert.getMat(), _inputBuffer); - // process the retina - if (!_retinaFilter->runFilter(_inputBuffer, colorMode, false, _retinaParameters.OPLandIplParvo.colorMode && colorMode, false)) - throw cv::Exception(-1, "RetinaImpl cannot be applied, wrong input buffer size", "RetinaImpl::run", "RetinaImpl.h", 0); -} - -void RetinaImpl::applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage) -{ - // first convert input image to the compatible format : - const bool colorMode = _convertCvMat2ValarrayBuffer(inputImage.getMat(), _inputBuffer); - const unsigned int nbPixels=_retinaFilter->getOutputNBrows()*_retinaFilter->getOutputNBcolumns(); - - // process tone mapping - if (colorMode) - { - std::valarray imageOutput(nbPixels*3); - _retinaFilter->runRGBToneMapping(_inputBuffer, imageOutput, true, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity); - _convertValarrayBuffer2cvMat(imageOutput, _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), true, outputToneMappedImage); - }else - { - std::valarray imageOutput(nbPixels); - _retinaFilter->runGrayToneMapping(_inputBuffer, imageOutput, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity); - _convertValarrayBuffer2cvMat(imageOutput, _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), false, outputToneMappedImage); - } - -} - -void RetinaImpl::getParvo(OutputArray retinaOutput_parvo) -{ - if (_retinaFilter->getColorMode()) - { - // reallocate output buffer (if necessary) - _convertValarrayBuffer2cvMat(_retinaFilter->getColorOutput(), _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), true, retinaOutput_parvo); - }else - { - // reallocate output buffer (if necessary) - _convertValarrayBuffer2cvMat(_retinaFilter->getContours(), _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), false, retinaOutput_parvo); - } - //retinaOutput_parvo/=255.0; -} -void RetinaImpl::getMagno(OutputArray retinaOutput_magno) -{ - // reallocate output buffer (if necessary) - _convertValarrayBuffer2cvMat(_retinaFilter->getMovingContours(), _retinaFilter->getOutputNBrows(), _retinaFilter->getOutputNBcolumns(), false, retinaOutput_magno); - //retinaOutput_magno/=255.0; -} - -// original API level data accessors : copy buffers if size matches, reallocate if required -void RetinaImpl::getMagnoRAW(OutputArray magnoOutputBufferCopy){ - // get magno channel header - const cv::Mat magnoChannel=cv::Mat(getMagnoRAW()); - // copy data - magnoChannel.copyTo(magnoOutputBufferCopy); -} - -void RetinaImpl::getParvoRAW(OutputArray parvoOutputBufferCopy){ - // get parvo channel header - const cv::Mat parvoChannel=cv::Mat(getMagnoRAW()); - // copy data - parvoChannel.copyTo(parvoOutputBufferCopy); -} - -// original API level data accessors : get buffers addresses... -const Mat RetinaImpl::getMagnoRAW() const { - // create a cv::Mat header for the valarray - return Mat((int)_retinaFilter->getMovingContours().size(),1, CV_32F, (void*)get_data(_retinaFilter->getMovingContours())); - -} - -const Mat RetinaImpl::getParvoRAW() const { - if (_retinaFilter->getColorMode()) // check if color mode is enabled - { - // create a cv::Mat table (for RGB planes as a single vector) - return Mat((int)_retinaFilter->getColorOutput().size(), 1, CV_32F, (void*)get_data(_retinaFilter->getColorOutput())); - } - // otherwise, output is gray level - // create a cv::Mat header for the valarray - return Mat((int)_retinaFilter->getContours().size(), 1, CV_32F, (void*)get_data(_retinaFilter->getContours())); -} - -// private method called by constructirs -void RetinaImpl::_init(const cv::Size inputSz, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) -{ - // basic error check - if (inputSz.height*inputSz.width <= 0) - throw cv::Exception(-1, "Bad retina size setup : size height and with must be superior to zero", "RetinaImpl::setup", "Retina.cpp", 0); - - unsigned int nbPixels=inputSz.height*inputSz.width; - // resize buffers if size does not match - _inputBuffer.resize(nbPixels*3); // buffer supports gray images but also 3 channels color buffers... (larger is better...) - - // allocate the retina model - if (_retinaFilter) - delete _retinaFilter; - _retinaFilter = new RetinaFilter(inputSz.height, inputSz.width, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); - - _retinaParameters.OPLandIplParvo.colorMode = colorMode; - // prepare the default parameter XML file with default setup - setup(_retinaParameters); - - // init retina - _retinaFilter->clearAllBuffers(); - - // report current configuration - printf("%s\n", printSetup().c_str()); -} - -void RetinaImpl::_convertValarrayBuffer2cvMat(const std::valarray &grayMatrixToConvert, const unsigned int nbRows, const unsigned int nbColumns, const bool colorMode, OutputArray outBuffer) -{ - // fill output buffer with the valarray buffer - const float *valarrayPTR=get_data(grayMatrixToConvert); - if (!colorMode) - { - outBuffer.create(cv::Size(nbColumns, nbRows), CV_8U); - Mat outMat = outBuffer.getMat(); - for (unsigned int i=0;i(pixel)=(unsigned char)*(valarrayPTR++); - } - } - } - else - { - const unsigned int nbPixels=nbColumns*nbRows; - const unsigned int doubleNBpixels=nbColumns*nbRows*2; - outBuffer.create(cv::Size(nbColumns, nbRows), CV_8UC3); - Mat outMat = outBuffer.getMat(); - for (unsigned int i=0;i(pixel)=pixelValues; - } - } - } -} - -bool RetinaImpl::_convertCvMat2ValarrayBuffer(InputArray inputMat, std::valarray &outputValarrayMatrix) -{ - const Mat inputMatToConvert=inputMat.getMat(); - // first check input consistency - if (inputMatToConvert.empty()) - throw cv::Exception(-1, "RetinaImpl cannot be applied, input buffer is empty", "RetinaImpl::run", "RetinaImpl.h", 0); - - // retreive color mode from image input - int imageNumberOfChannels = inputMatToConvert.channels(); - - // convert to float AND fill the valarray buffer - typedef float T; // define here the target pixel format, here, float - const int dsttype = DataType::depth; // output buffer is float format - - const unsigned int nbPixels=inputMat.getMat().rows*inputMat.getMat().cols; - const unsigned int doubleNBpixels=inputMat.getMat().rows*inputMat.getMat().cols*2; - - if(imageNumberOfChannels==4) - { - // create a cv::Mat table (for RGBA planes) - cv::Mat planes[4] = - { - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[doubleNBpixels]), - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[nbPixels]), - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]) - }; - planes[3] = cv::Mat(inputMatToConvert.size(), dsttype); // last channel (alpha) does not point on the valarray (not usefull in our case) - // split color cv::Mat in 4 planes... it fills valarray directely - cv::split(Mat_ >(inputMatToConvert), planes); - } - else if (imageNumberOfChannels==3) - { - // create a cv::Mat table (for RGB planes) - cv::Mat planes[] = - { - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[doubleNBpixels]), - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[nbPixels]), - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]) - }; - // split color cv::Mat in 3 planes... it fills valarray directely - cv::split(cv::Mat_ >(inputMatToConvert), planes); - } - else if(imageNumberOfChannels==1) - { - // create a cv::Mat header for the valarray - cv::Mat dst(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]); - inputMatToConvert.convertTo(dst, dsttype); - } - else - CV_Error(Error::StsUnsupportedFormat, "input image must be single channel (gray levels), bgr format (color) or bgra (color with transparency which won't be considered"); - - return imageNumberOfChannels>1; // return bool : false for gray level image processing, true for color mode -} - -void RetinaImpl::clearBuffers() { _retinaFilter->clearAllBuffers(); } - -void RetinaImpl::activateMovingContoursProcessing(const bool activate) { _retinaFilter->activateMovingContoursProcessing(activate); } - -void RetinaImpl::activateContoursProcessing(const bool activate) { _retinaFilter->activateContoursProcessing(activate); } - -}// end of namespace bioinspired -}// end of namespace cv diff --git a/modules/bioinspired/src/retina_ocl.cpp b/modules/bioinspired/src/retina_ocl.cpp deleted file mode 100644 index 51f43f38b..000000000 --- a/modules/bioinspired/src/retina_ocl.cpp +++ /dev/null @@ -1,1643 +0,0 @@ -/*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-2013, Multicoreware, Inc., all rights reserved. -// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Peng Xiao, pengxiao@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 oclMaterials 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 "precomp.hpp" -#include "retina_ocl.hpp" -#include -#include - -#ifdef HAVE_OPENCV_OCL - -#include "opencl_kernels.hpp" - -#define NOT_IMPLEMENTED CV_Error(cv::Error::StsNotImplemented, "Not implemented") - -namespace cv -{ -static ocl::ProgramEntry retina_kernel = ocl::bioinspired::retina_kernel; - -namespace bioinspired -{ -namespace ocl -{ -using namespace cv::ocl; - -class RetinaOCLImpl : public Retina -{ -public: - RetinaOCLImpl(Size getInputSize); - RetinaOCLImpl(Size getInputSize, const bool colorMode, int colorSamplingMethod = RETINA_COLOR_BAYER, const bool useRetinaLogSampling = false, const double reductionFactor = 1.0, const double samplingStrenght = 10.0); - virtual ~RetinaOCLImpl(); - - Size getInputSize(); - Size getOutputSize(); - - void setup(String retinaParameterFile = "", const bool applyDefaultSetupOnFailure = true); - void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure = true); - void setup(RetinaParameters newParameters); - - RetinaOCLImpl::RetinaParameters getParameters(); - - const String printSetup(); - virtual void write( String fs ) const; - virtual void write( FileStorage& fs ) const; - - void setupOPLandIPLParvoChannel(const bool colorMode = true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity = 0.7, const float photoreceptorsTemporalConstant = 0.5, const float photoreceptorsSpatialConstant = 0.53, const float horizontalCellsGain = 0, const float HcellsTemporalConstant = 1, const float HcellsSpatialConstant = 7, const float ganglionCellsSensitivity = 0.7); - void setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta = 0, const float parasolCells_tau = 0, const float parasolCells_k = 7, const float amacrinCellsTemporalCutFrequency = 1.2, const float V0CompressionParameter = 0.95, const float localAdaptintegration_tau = 0, const float localAdaptintegration_k = 7); - - void run(InputArray inputImage); - void getParvo(OutputArray retinaOutput_parvo); - void getMagno(OutputArray retinaOutput_magno); - - void setColorSaturation(const bool saturateColors = true, const float colorSaturationValue = 4.0); - void clearBuffers(); - void activateMovingContoursProcessing(const bool activate); - void activateContoursProcessing(const bool activate); - - // unimplemented interfaces: - void applyFastToneMapping(InputArray /*inputImage*/, OutputArray /*outputToneMappedImage*/) { NOT_IMPLEMENTED; } - void getParvoRAW(OutputArray /*retinaOutput_parvo*/) { NOT_IMPLEMENTED; } - void getMagnoRAW(OutputArray /*retinaOutput_magno*/) { NOT_IMPLEMENTED; } - const Mat getMagnoRAW() const { NOT_IMPLEMENTED; return Mat(); } - const Mat getParvoRAW() const { NOT_IMPLEMENTED; return Mat(); } - -protected: - RetinaParameters _retinaParameters; - cv::ocl::oclMat _inputBuffer; - RetinaFilter* _retinaFilter; - bool convertToColorPlanes(const cv::ocl::oclMat& input, cv::ocl::oclMat &output); - void convertToInterleaved(const cv::ocl::oclMat& input, bool colorMode, cv::ocl::oclMat &output); - void _init(const Size getInputSize, const bool colorMode, int colorSamplingMethod = RETINA_COLOR_BAYER, const bool useRetinaLogSampling = false, const double reductionFactor = 1.0, const double samplingStrenght = 10.0); -}; - -RetinaOCLImpl::RetinaOCLImpl(const cv::Size inputSz) -{ - _retinaFilter = 0; - _init(inputSz, true, RETINA_COLOR_BAYER, false); -} - -RetinaOCLImpl::RetinaOCLImpl(const cv::Size inputSz, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) -{ - _retinaFilter = 0; - _init(inputSz, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); -} - -RetinaOCLImpl::~RetinaOCLImpl() -{ - if (_retinaFilter) - { - delete _retinaFilter; - } -} - -/** -* retreive retina input buffer size -*/ -Size RetinaOCLImpl::getInputSize() -{ - return cv::Size(_retinaFilter->getInputNBcolumns(), _retinaFilter->getInputNBrows()); -} - -/** -* retreive retina output buffer size -*/ -Size RetinaOCLImpl::getOutputSize() -{ - return cv::Size(_retinaFilter->getOutputNBcolumns(), _retinaFilter->getOutputNBrows()); -} - - -void RetinaOCLImpl::setColorSaturation(const bool saturateColors, const float colorSaturationValue) -{ - _retinaFilter->setColorSaturation(saturateColors, colorSaturationValue); -} - -struct RetinaOCLImpl::RetinaParameters RetinaOCLImpl::getParameters() -{ - return _retinaParameters; -} - - -void RetinaOCLImpl::setup(String retinaParameterFile, const bool applyDefaultSetupOnFailure) -{ - try - { - // opening retinaParameterFile in read mode - cv::FileStorage fs(retinaParameterFile, cv::FileStorage::READ); - setup(fs, applyDefaultSetupOnFailure); - } - catch(Exception &e) - { - std::cout << "RetinaOCLImpl::setup: wrong/unappropriate xml parameter file : error report :`n=>" << e.what() << std::endl; - if (applyDefaultSetupOnFailure) - { - std::cout << "RetinaOCLImpl::setup: resetting retina with default parameters" << std::endl; - setupOPLandIPLParvoChannel(); - setupIPLMagnoChannel(); - } - else - { - std::cout << "=> keeping current parameters" << std::endl; - } - } -} - -void RetinaOCLImpl::setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure) -{ - try - { - // read parameters file if it exists or apply default setup if asked for - if (!fs.isOpened()) - { - std::cout << "RetinaOCLImpl::setup: provided parameters file could not be open... skeeping configuration" << std::endl; - return; - // implicit else case : retinaParameterFile could be open (it exists at least) - } - // OPL and Parvo init first... update at the same time the parameters structure and the retina core - cv::FileNode rootFn = fs.root(), currFn = rootFn["OPLandIPLparvo"]; - currFn["colorMode"] >> _retinaParameters.OPLandIplParvo.colorMode; - currFn["normaliseOutput"] >> _retinaParameters.OPLandIplParvo.normaliseOutput; - currFn["photoreceptorsLocalAdaptationSensitivity"] >> _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity; - currFn["photoreceptorsTemporalConstant"] >> _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant; - currFn["photoreceptorsSpatialConstant"] >> _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant; - currFn["horizontalCellsGain"] >> _retinaParameters.OPLandIplParvo.horizontalCellsGain; - currFn["hcellsTemporalConstant"] >> _retinaParameters.OPLandIplParvo.hcellsTemporalConstant; - currFn["hcellsSpatialConstant"] >> _retinaParameters.OPLandIplParvo.hcellsSpatialConstant; - currFn["ganglionCellsSensitivity"] >> _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity; - setupOPLandIPLParvoChannel(_retinaParameters.OPLandIplParvo.colorMode, _retinaParameters.OPLandIplParvo.normaliseOutput, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant, _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant, _retinaParameters.OPLandIplParvo.horizontalCellsGain, _retinaParameters.OPLandIplParvo.hcellsTemporalConstant, _retinaParameters.OPLandIplParvo.hcellsSpatialConstant, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity); - - // init retina IPL magno setup... update at the same time the parameters structure and the retina core - currFn = rootFn["IPLmagno"]; - currFn["normaliseOutput"] >> _retinaParameters.IplMagno.normaliseOutput; - currFn["parasolCells_beta"] >> _retinaParameters.IplMagno.parasolCells_beta; - currFn["parasolCells_tau"] >> _retinaParameters.IplMagno.parasolCells_tau; - currFn["parasolCells_k"] >> _retinaParameters.IplMagno.parasolCells_k; - currFn["amacrinCellsTemporalCutFrequency"] >> _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency; - currFn["V0CompressionParameter"] >> _retinaParameters.IplMagno.V0CompressionParameter; - currFn["localAdaptintegration_tau"] >> _retinaParameters.IplMagno.localAdaptintegration_tau; - currFn["localAdaptintegration_k"] >> _retinaParameters.IplMagno.localAdaptintegration_k; - - setupIPLMagnoChannel(_retinaParameters.IplMagno.normaliseOutput, _retinaParameters.IplMagno.parasolCells_beta, _retinaParameters.IplMagno.parasolCells_tau, _retinaParameters.IplMagno.parasolCells_k, _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency, _retinaParameters.IplMagno.V0CompressionParameter, _retinaParameters.IplMagno.localAdaptintegration_tau, _retinaParameters.IplMagno.localAdaptintegration_k); - - } - catch(Exception &e) - { - std::cout << "RetinaOCLImpl::setup: resetting retina with default parameters" << std::endl; - if (applyDefaultSetupOnFailure) - { - setupOPLandIPLParvoChannel(); - setupIPLMagnoChannel(); - } - std::cout << "RetinaOCLImpl::setup: wrong/unappropriate xml parameter file : error report :`n=>" << e.what() << std::endl; - std::cout << "=> keeping current parameters" << std::endl; - } -} - -void RetinaOCLImpl::setup(cv::bioinspired::Retina::RetinaParameters newConfiguration) -{ - // simply copy structures - memcpy(&_retinaParameters, &newConfiguration, sizeof(cv::bioinspired::Retina::RetinaParameters)); - // apply setup - setupOPLandIPLParvoChannel(_retinaParameters.OPLandIplParvo.colorMode, _retinaParameters.OPLandIplParvo.normaliseOutput, _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity, _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant, _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant, _retinaParameters.OPLandIplParvo.horizontalCellsGain, _retinaParameters.OPLandIplParvo.hcellsTemporalConstant, _retinaParameters.OPLandIplParvo.hcellsSpatialConstant, _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity); - setupIPLMagnoChannel(_retinaParameters.IplMagno.normaliseOutput, _retinaParameters.IplMagno.parasolCells_beta, _retinaParameters.IplMagno.parasolCells_tau, _retinaParameters.IplMagno.parasolCells_k, _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency, _retinaParameters.IplMagno.V0CompressionParameter, _retinaParameters.IplMagno.localAdaptintegration_tau, _retinaParameters.IplMagno.localAdaptintegration_k); -} - -const String RetinaOCLImpl::printSetup() -{ - std::stringstream outmessage; - - // displaying OPL and IPL parvo setup - outmessage << "Current Retina instance setup :" - << "\nOPLandIPLparvo" << "{" - << "\n==> colorMode : " << _retinaParameters.OPLandIplParvo.colorMode - << "\n==> normalizeParvoOutput :" << _retinaParameters.OPLandIplParvo.normaliseOutput - << "\n==> photoreceptorsLocalAdaptationSensitivity : " << _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity - << "\n==> photoreceptorsTemporalConstant : " << _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant - << "\n==> photoreceptorsSpatialConstant : " << _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant - << "\n==> horizontalCellsGain : " << _retinaParameters.OPLandIplParvo.horizontalCellsGain - << "\n==> hcellsTemporalConstant : " << _retinaParameters.OPLandIplParvo.hcellsTemporalConstant - << "\n==> hcellsSpatialConstant : " << _retinaParameters.OPLandIplParvo.hcellsSpatialConstant - << "\n==> parvoGanglionCellsSensitivity : " << _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity - << "}\n"; - - // displaying IPL magno setup - outmessage << "Current Retina instance setup :" - << "\nIPLmagno" << "{" - << "\n==> normaliseOutput : " << _retinaParameters.IplMagno.normaliseOutput - << "\n==> parasolCells_beta : " << _retinaParameters.IplMagno.parasolCells_beta - << "\n==> parasolCells_tau : " << _retinaParameters.IplMagno.parasolCells_tau - << "\n==> parasolCells_k : " << _retinaParameters.IplMagno.parasolCells_k - << "\n==> amacrinCellsTemporalCutFrequency : " << _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency - << "\n==> V0CompressionParameter : " << _retinaParameters.IplMagno.V0CompressionParameter - << "\n==> localAdaptintegration_tau : " << _retinaParameters.IplMagno.localAdaptintegration_tau - << "\n==> localAdaptintegration_k : " << _retinaParameters.IplMagno.localAdaptintegration_k - << "}"; - return outmessage.str().c_str(); -} - -void RetinaOCLImpl::write( String fs ) const -{ - FileStorage parametersSaveFile(fs, cv::FileStorage::WRITE ); - write(parametersSaveFile); -} - -void RetinaOCLImpl::write( FileStorage& fs ) const -{ - if (!fs.isOpened()) - { - return; // basic error case - } - fs << "OPLandIPLparvo" << "{"; - fs << "colorMode" << _retinaParameters.OPLandIplParvo.colorMode; - fs << "normaliseOutput" << _retinaParameters.OPLandIplParvo.normaliseOutput; - fs << "photoreceptorsLocalAdaptationSensitivity" << _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity; - fs << "photoreceptorsTemporalConstant" << _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant; - fs << "photoreceptorsSpatialConstant" << _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant; - fs << "horizontalCellsGain" << _retinaParameters.OPLandIplParvo.horizontalCellsGain; - fs << "hcellsTemporalConstant" << _retinaParameters.OPLandIplParvo.hcellsTemporalConstant; - fs << "hcellsSpatialConstant" << _retinaParameters.OPLandIplParvo.hcellsSpatialConstant; - fs << "ganglionCellsSensitivity" << _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity; - fs << "}"; - fs << "IPLmagno" << "{"; - fs << "normaliseOutput" << _retinaParameters.IplMagno.normaliseOutput; - fs << "parasolCells_beta" << _retinaParameters.IplMagno.parasolCells_beta; - fs << "parasolCells_tau" << _retinaParameters.IplMagno.parasolCells_tau; - fs << "parasolCells_k" << _retinaParameters.IplMagno.parasolCells_k; - fs << "amacrinCellsTemporalCutFrequency" << _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency; - fs << "V0CompressionParameter" << _retinaParameters.IplMagno.V0CompressionParameter; - fs << "localAdaptintegration_tau" << _retinaParameters.IplMagno.localAdaptintegration_tau; - fs << "localAdaptintegration_k" << _retinaParameters.IplMagno.localAdaptintegration_k; - fs << "}"; -} - -void RetinaOCLImpl::setupOPLandIPLParvoChannel(const bool colorMode, const bool normaliseOutput, const float photoreceptorsLocalAdaptationSensitivity, const float photoreceptorsTemporalConstant, const float photoreceptorsSpatialConstant, const float horizontalCellsGain, const float HcellsTemporalConstant, const float HcellsSpatialConstant, const float ganglionCellsSensitivity) -{ - // retina core parameters setup - _retinaFilter->setColorMode(colorMode); - _retinaFilter->setPhotoreceptorsLocalAdaptationSensitivity(photoreceptorsLocalAdaptationSensitivity); - _retinaFilter->setOPLandParvoParameters(0, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, HcellsTemporalConstant, HcellsSpatialConstant, ganglionCellsSensitivity); - _retinaFilter->setParvoGanglionCellsLocalAdaptationSensitivity(ganglionCellsSensitivity); - _retinaFilter->activateNormalizeParvoOutput_0_maxOutputValue(normaliseOutput); - - // update parameters struture - - _retinaParameters.OPLandIplParvo.colorMode = colorMode; - _retinaParameters.OPLandIplParvo.normaliseOutput = normaliseOutput; - _retinaParameters.OPLandIplParvo.photoreceptorsLocalAdaptationSensitivity = photoreceptorsLocalAdaptationSensitivity; - _retinaParameters.OPLandIplParvo.photoreceptorsTemporalConstant = photoreceptorsTemporalConstant; - _retinaParameters.OPLandIplParvo.photoreceptorsSpatialConstant = photoreceptorsSpatialConstant; - _retinaParameters.OPLandIplParvo.horizontalCellsGain = horizontalCellsGain; - _retinaParameters.OPLandIplParvo.hcellsTemporalConstant = HcellsTemporalConstant; - _retinaParameters.OPLandIplParvo.hcellsSpatialConstant = HcellsSpatialConstant; - _retinaParameters.OPLandIplParvo.ganglionCellsSensitivity = ganglionCellsSensitivity; -} - -void RetinaOCLImpl::setupIPLMagnoChannel(const bool normaliseOutput, const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float V0CompressionParameter, const float localAdaptintegration_tau, const float localAdaptintegration_k) -{ - - _retinaFilter->setMagnoCoefficientsTable(parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k); - _retinaFilter->activateNormalizeMagnoOutput_0_maxOutputValue(normaliseOutput); - - // update parameters struture - _retinaParameters.IplMagno.normaliseOutput = normaliseOutput; - _retinaParameters.IplMagno.parasolCells_beta = parasolCells_beta; - _retinaParameters.IplMagno.parasolCells_tau = parasolCells_tau; - _retinaParameters.IplMagno.parasolCells_k = parasolCells_k; - _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency = amacrinCellsTemporalCutFrequency; - _retinaParameters.IplMagno.V0CompressionParameter = V0CompressionParameter; - _retinaParameters.IplMagno.localAdaptintegration_tau = localAdaptintegration_tau; - _retinaParameters.IplMagno.localAdaptintegration_k = localAdaptintegration_k; -} - -void RetinaOCLImpl::run(const InputArray input) -{ - oclMat &inputMatToConvert = getOclMatRef(input); - bool colorMode = convertToColorPlanes(inputMatToConvert, _inputBuffer); - // first convert input image to the compatible format : std::valarray - // process the retina - if (!_retinaFilter->runFilter(_inputBuffer, colorMode, false, _retinaParameters.OPLandIplParvo.colorMode && colorMode, false)) - { - throw cv::Exception(-1, "Retina cannot be applied, wrong input buffer size", "RetinaOCLImpl::run", "Retina.h", 0); - } -} - -void RetinaOCLImpl::getParvo(OutputArray output) -{ - oclMat &retinaOutput_parvo = getOclMatRef(output); - if (_retinaFilter->getColorMode()) - { - // reallocate output buffer (if necessary) - convertToInterleaved(_retinaFilter->getColorOutput(), true, retinaOutput_parvo); - } - else - { - // reallocate output buffer (if necessary) - convertToInterleaved(_retinaFilter->getContours(), false, retinaOutput_parvo); - } - //retinaOutput_parvo/=255.0; -} -void RetinaOCLImpl::getMagno(OutputArray output) -{ - oclMat &retinaOutput_magno = getOclMatRef(output); - // reallocate output buffer (if necessary) - convertToInterleaved(_retinaFilter->getMovingContours(), false, retinaOutput_magno); - //retinaOutput_magno/=255.0; -} -// private method called by constructirs -void RetinaOCLImpl::_init(const cv::Size inputSz, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) -{ - // basic error check - if (inputSz.height*inputSz.width <= 0) - { - throw cv::Exception(-1, "Bad retina size setup : size height and with must be superior to zero", "RetinaOCLImpl::setup", "Retina.h", 0); - } - - // allocate the retina model - if (_retinaFilter) - { - delete _retinaFilter; - } - _retinaFilter = new RetinaFilter(inputSz.height, inputSz.width, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); - - // prepare the default parameter XML file with default setup - setup(_retinaParameters); - - // init retina - _retinaFilter->clearAllBuffers(); -} - -bool RetinaOCLImpl::convertToColorPlanes(const oclMat& input, oclMat &output) -{ - oclMat convert_input; - input.convertTo(convert_input, CV_32F); - if(convert_input.channels() == 3 || convert_input.channels() == 4) - { - ocl::ensureSizeIsEnough(int(_retinaFilter->getInputNBrows() * 4), - int(_retinaFilter->getInputNBcolumns()), CV_32FC1, output); - oclMat channel_splits[4] = - { - output(Rect(Point(0, _retinaFilter->getInputNBrows() * 2), getInputSize())), - output(Rect(Point(0, _retinaFilter->getInputNBrows()), getInputSize())), - output(Rect(Point(0, 0), getInputSize())), - output(Rect(Point(0, _retinaFilter->getInputNBrows() * 3), getInputSize())) - }; - ocl::split(convert_input, channel_splits); - return true; - } - else if(convert_input.channels() == 1) - { - convert_input.copyTo(output); - return false; - } - else - { - CV_Error(-1, "Retina ocl only support 1, 3, 4 channel input"); - return false; - } -} -void RetinaOCLImpl::convertToInterleaved(const oclMat& input, bool colorMode, oclMat &output) -{ - input.convertTo(output, CV_8U); - if(colorMode) - { - int numOfSplits = input.rows / getInputSize().height; - std::vector channel_splits(numOfSplits); - for(int i = 0; i < static_cast(channel_splits.size()); i ++) - { - channel_splits[i] = - output(Rect(Point(0, _retinaFilter->getInputNBrows() * (numOfSplits - i - 1)), getInputSize())); - } - merge(channel_splits, output); - } - else - { - //... - } -} - -void RetinaOCLImpl::clearBuffers() -{ - _retinaFilter->clearAllBuffers(); -} - -void RetinaOCLImpl::activateMovingContoursProcessing(const bool activate) -{ - _retinaFilter->activateMovingContoursProcessing(activate); -} - -void RetinaOCLImpl::activateContoursProcessing(const bool activate) -{ - _retinaFilter->activateContoursProcessing(activate); -} - -/////////////////////////////////////// -///////// BasicRetinaFilter /////////// -/////////////////////////////////////// -BasicRetinaFilter::BasicRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns, const unsigned int parametersListSize, const bool) - : _NBrows(NBrows), _NBcols(NBcolumns), - _filterOutput(NBrows, NBcolumns, CV_32FC1), - _localBuffer(NBrows, NBcolumns, CV_32FC1), - _filteringCoeficientsTable(3 * parametersListSize) -{ - _halfNBrows = _filterOutput.rows / 2; - _halfNBcolumns = _filterOutput.cols / 2; - - // set default values - _maxInputValue = 256.0; - - // reset all buffers - clearAllBuffers(); -} - -BasicRetinaFilter::~BasicRetinaFilter() -{ -} - -void BasicRetinaFilter::resize(const unsigned int NBrows, const unsigned int NBcolumns) -{ - // resizing buffers - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _filterOutput); - - // updating variables - _halfNBrows = _filterOutput.rows / 2; - _halfNBcolumns = _filterOutput.cols / 2; - - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _localBuffer); - // reset buffers - clearAllBuffers(); -} - -void BasicRetinaFilter::setLPfilterParameters(const float beta, const float tau, const float desired_k, const unsigned int filterIndex) -{ - float _beta = beta + tau; - float k = desired_k; - // check if the spatial constant is correct (avoid 0 value to avoid division by 0) - if (desired_k <= 0) - { - k = 0.001f; - std::cerr << "BasicRetinaFilter::spatial constant of the low pass filter must be superior to zero !!! correcting parameter setting to 0,001" << std::endl; - } - - float _alpha = k * k; - float _mu = 0.8f; - unsigned int tableOffset = filterIndex * 3; - if (k <= 0) - { - std::cerr << "BasicRetinaFilter::spatial filtering coefficient must be superior to zero, correcting value to 0.01" << std::endl; - _alpha = 0.0001f; - } - - float _temp = (1.0f + _beta) / (2.0f * _mu * _alpha); - float a = _filteringCoeficientsTable[tableOffset] = 1.0f + _temp - (float)sqrt( (1.0f + _temp) * (1.0f + _temp) - 1.0f); - _filteringCoeficientsTable[1 + tableOffset] = (1.0f - a) * (1.0f - a) * (1.0f - a) * (1.0f - a) / (1.0f + _beta); - _filteringCoeficientsTable[2 + tableOffset] = tau; -} -const oclMat &BasicRetinaFilter::runFilter_LocalAdapdation(const oclMat &inputFrame, const oclMat &localLuminance) -{ - _localLuminanceAdaptation(inputFrame, localLuminance, _filterOutput); - return _filterOutput; -} - - -void BasicRetinaFilter::runFilter_LocalAdapdation(const oclMat &inputFrame, const oclMat &localLuminance, oclMat &outputFrame) -{ - _localLuminanceAdaptation(inputFrame, localLuminance, outputFrame); -} - -const oclMat &BasicRetinaFilter::runFilter_LocalAdapdation_autonomous(const oclMat &inputFrame) -{ - _spatiotemporalLPfilter(inputFrame, _filterOutput); - _localLuminanceAdaptation(inputFrame, _filterOutput, _filterOutput); - return _filterOutput; -} -void BasicRetinaFilter::runFilter_LocalAdapdation_autonomous(const oclMat &inputFrame, oclMat &outputFrame) -{ - _spatiotemporalLPfilter(inputFrame, _filterOutput); - _localLuminanceAdaptation(inputFrame, _filterOutput, outputFrame); -} - -void BasicRetinaFilter::_localLuminanceAdaptation(oclMat &inputOutputFrame, const oclMat &localLuminance) -{ - _localLuminanceAdaptation(inputOutputFrame, localLuminance, inputOutputFrame, false); -} - -void BasicRetinaFilter::_localLuminanceAdaptation(const oclMat &inputFrame, const oclMat &localLuminance, oclMat &outputFrame, const bool updateLuminanceMean) -{ - if (updateLuminanceMean) - { - float meanLuminance = saturate_cast(ocl::sum(inputFrame)[0]) / getNBpixels(); - updateCompressionParameter(meanLuminance); - } - int elements_per_row = static_cast(inputFrame.step / inputFrame.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {_NBcols, _NBrows, 1}; - size_t localSize[] = {16, 16, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &localLuminance.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &inputFrame.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_float), &_localLuminanceAddon)); - args.push_back(std::make_pair(sizeof(cl_float), &_localLuminanceFactor)); - args.push_back(std::make_pair(sizeof(cl_float), &_maxInputValue)); - openCLExecuteKernel(ctx, &retina_kernel, "localLuminanceAdaptation", globalSize, localSize, args, -1, -1); -} - -const oclMat &BasicRetinaFilter::runFilter_LPfilter(const oclMat &inputFrame, const unsigned int filterIndex) -{ - _spatiotemporalLPfilter(inputFrame, _filterOutput, filterIndex); - return _filterOutput; -} -void BasicRetinaFilter::runFilter_LPfilter(const oclMat &inputFrame, oclMat &outputFrame, const unsigned int filterIndex) -{ - _spatiotemporalLPfilter(inputFrame, outputFrame, filterIndex); -} - -void BasicRetinaFilter::_spatiotemporalLPfilter(const oclMat &inputFrame, oclMat &LPfilterOutput, const unsigned int filterIndex) -{ - unsigned int coefTableOffset = filterIndex * 3; - - _a = _filteringCoeficientsTable[coefTableOffset]; - _gain = _filteringCoeficientsTable[1 + coefTableOffset]; - _tau = _filteringCoeficientsTable[2 + coefTableOffset]; - - _horizontalCausalFilter_addInput(inputFrame, LPfilterOutput); - _horizontalAnticausalFilter(LPfilterOutput); - _verticalCausalFilter(LPfilterOutput); - _verticalAnticausalFilter_multGain(LPfilterOutput); -} - -void BasicRetinaFilter::_horizontalCausalFilter_addInput(const oclMat &inputFrame, oclMat &outputFrame) -{ - int elements_per_row = static_cast(inputFrame.step / inputFrame.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {_NBrows, 1, 1}; - size_t localSize[] = {256, 1, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &inputFrame.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_int), &inputFrame.offset)); - args.push_back(std::make_pair(sizeof(cl_int), &inputFrame.offset)); - args.push_back(std::make_pair(sizeof(cl_float), &_tau)); - args.push_back(std::make_pair(sizeof(cl_float), &_a)); - openCLExecuteKernel(ctx, &retina_kernel, "horizontalCausalFilter_addInput", globalSize, localSize, args, -1, -1); -} - -void BasicRetinaFilter::_horizontalAnticausalFilter(oclMat &outputFrame) -{ - int elements_per_row = static_cast(outputFrame.step / outputFrame.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {_NBrows, 1, 1}; - size_t localSize[] = {256, 1, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); - args.push_back(std::make_pair(sizeof(cl_float), &_a)); - openCLExecuteKernel(ctx, &retina_kernel, "horizontalAnticausalFilter", globalSize, localSize, args, -1, -1); -} - -void BasicRetinaFilter::_verticalCausalFilter(oclMat &outputFrame) -{ - int elements_per_row = static_cast(outputFrame.step / outputFrame.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {_NBcols, 1, 1}; - size_t localSize[] = {256, 1, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); - args.push_back(std::make_pair(sizeof(cl_float), &_a)); - openCLExecuteKernel(ctx, &retina_kernel, "verticalCausalFilter", globalSize, localSize, args, -1, -1); -} - -void BasicRetinaFilter::_verticalAnticausalFilter_multGain(oclMat &outputFrame) -{ - int elements_per_row = static_cast(outputFrame.step / outputFrame.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {_NBcols, 1, 1}; - size_t localSize[] = {256, 1, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); - args.push_back(std::make_pair(sizeof(cl_float), &_a)); - args.push_back(std::make_pair(sizeof(cl_float), &_gain)); - openCLExecuteKernel(ctx, &retina_kernel, "verticalAnticausalFilter_multGain", globalSize, localSize, args, -1, -1); -} - -void BasicRetinaFilter::_horizontalAnticausalFilter_Irregular(oclMat &outputFrame, const oclMat &spatialConstantBuffer) -{ - int elements_per_row = static_cast(outputFrame.step / outputFrame.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {outputFrame.rows, 1, 1}; - size_t localSize[] = {256, 1, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &spatialConstantBuffer.data)); - args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.cols)); - args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); - args.push_back(std::make_pair(sizeof(cl_int), &spatialConstantBuffer.offset)); - openCLExecuteKernel(ctx, &retina_kernel, "horizontalAnticausalFilter_Irregular", globalSize, localSize, args, -1, -1); -} - -// vertical anticausal filter -void BasicRetinaFilter::_verticalCausalFilter_Irregular(oclMat &outputFrame, const oclMat &spatialConstantBuffer) -{ - int elements_per_row = static_cast(outputFrame.step / outputFrame.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {outputFrame.cols, 1, 1}; - size_t localSize[] = {256, 1, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &spatialConstantBuffer.data)); - args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.cols)); - args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); - args.push_back(std::make_pair(sizeof(cl_int), &spatialConstantBuffer.offset)); - openCLExecuteKernel(ctx, &retina_kernel, "verticalCausalFilter_Irregular", globalSize, localSize, args, -1, -1); -} - -void normalizeGrayOutput_0_maxOutputValue(oclMat &inputOutputBuffer, const float maxOutputValue) -{ - double min_val, max_val; - ocl::minMax(inputOutputBuffer, &min_val, &max_val); - float factor = maxOutputValue / static_cast(max_val - min_val); - float offset = - static_cast(min_val) * factor; - ocl::multiply(factor, inputOutputBuffer, inputOutputBuffer); - ocl::add(inputOutputBuffer, offset, inputOutputBuffer); -} - -void normalizeGrayOutputCentredSigmoide(const float meanValue, const float sensitivity, oclMat &in, oclMat &out, const float maxValue) -{ - if (sensitivity == 1.0f) - { - std::cerr << "TemplateBuffer::TemplateBuffer::normalizeGrayOutputCentredSigmoide error: 2nd parameter (sensitivity) must not equal 0, copying original data..." << std::endl; - in.copyTo(out); - return; - } - - float X0 = maxValue / (sensitivity - 1.0f); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {in.cols, out.rows, 1}; - size_t localSize[] = {16, 16, 1}; - - int elements_per_row = static_cast(out.step / out.elemSize()); - - args.push_back(std::make_pair(sizeof(cl_mem), &in.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &out.data)); - args.push_back(std::make_pair(sizeof(cl_int), &in.cols)); - args.push_back(std::make_pair(sizeof(cl_int), &in.rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_float), &meanValue)); - args.push_back(std::make_pair(sizeof(cl_float), &X0)); - openCLExecuteKernel(ctx, &retina_kernel, "normalizeGrayOutputCentredSigmoide", globalSize, localSize, args, -1, -1); -} - -void normalizeGrayOutputNearZeroCentreredSigmoide(oclMat &inputPicture, oclMat &outputBuffer, const float sensitivity, const float maxOutputValue) -{ - float X0cube = sensitivity * sensitivity * sensitivity; - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {inputPicture.cols, inputPicture.rows, 1}; - size_t localSize[] = {16, 16, 1}; - - int elements_per_row = static_cast(inputPicture.step / inputPicture.elemSize()); - args.push_back(std::make_pair(sizeof(cl_mem), &inputPicture.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &outputBuffer.data)); - args.push_back(std::make_pair(sizeof(cl_int), &inputPicture.cols)); - args.push_back(std::make_pair(sizeof(cl_int), &inputPicture.rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_float), &maxOutputValue)); - args.push_back(std::make_pair(sizeof(cl_float), &X0cube)); - openCLExecuteKernel(ctx, &retina_kernel, "normalizeGrayOutputNearZeroCentreredSigmoide", globalSize, localSize, args, -1, -1); -} - -void centerReductImageLuminance(oclMat &inputoutput) -{ - Scalar mean, stddev; - cv::meanStdDev((Mat)inputoutput, mean, stddev); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {inputoutput.cols, inputoutput.rows, 1}; - size_t localSize[] = {16, 16, 1}; - - float f_mean = static_cast(mean[0]); - float f_stddev = static_cast(stddev[0]); - int elements_per_row = static_cast(inputoutput.step / inputoutput.elemSize()); - args.push_back(std::make_pair(sizeof(cl_mem), &inputoutput.data)); - args.push_back(std::make_pair(sizeof(cl_int), &inputoutput.cols)); - args.push_back(std::make_pair(sizeof(cl_int), &inputoutput.rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_float), &f_mean)); - args.push_back(std::make_pair(sizeof(cl_float), &f_stddev)); - openCLExecuteKernel(ctx, &retina_kernel, "centerReductImageLuminance", globalSize, localSize, args, -1, -1); -} - -/////////////////////////////////////// -///////// ParvoRetinaFilter /////////// -/////////////////////////////////////// -ParvoRetinaFilter::ParvoRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns) - : BasicRetinaFilter(NBrows, NBcolumns, 3), - _photoreceptorsOutput(NBrows, NBcolumns, CV_32FC1), - _horizontalCellsOutput(NBrows, NBcolumns, CV_32FC1), - _parvocellularOutputON(NBrows, NBcolumns, CV_32FC1), - _parvocellularOutputOFF(NBrows, NBcolumns, CV_32FC1), - _bipolarCellsOutputON(NBrows, NBcolumns, CV_32FC1), - _bipolarCellsOutputOFF(NBrows, NBcolumns, CV_32FC1), - _localAdaptationOFF(NBrows, NBcolumns, CV_32FC1) -{ - // link to the required local parent adaptation buffers - _localAdaptationON = _localBuffer; - _parvocellularOutputONminusOFF = _filterOutput; - - // init: set all the values to 0 - clearAllBuffers(); -} - -ParvoRetinaFilter::~ParvoRetinaFilter() -{ -} - -void ParvoRetinaFilter::clearAllBuffers() -{ - BasicRetinaFilter::clearAllBuffers(); - _photoreceptorsOutput = 0; - _horizontalCellsOutput = 0; - _parvocellularOutputON = 0; - _parvocellularOutputOFF = 0; - _bipolarCellsOutputON = 0; - _bipolarCellsOutputOFF = 0; - _localAdaptationOFF = 0; -} -void ParvoRetinaFilter::resize(const unsigned int NBrows, const unsigned int NBcolumns) -{ - BasicRetinaFilter::resize(NBrows, NBcolumns); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _photoreceptorsOutput); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _horizontalCellsOutput); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _parvocellularOutputON); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _parvocellularOutputOFF); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _bipolarCellsOutputON); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _bipolarCellsOutputOFF); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _localAdaptationOFF); - - // link to the required local parent adaptation buffers - _localAdaptationON = _localBuffer; - _parvocellularOutputONminusOFF = _filterOutput; - - // clean buffers - clearAllBuffers(); -} - -void ParvoRetinaFilter::setOPLandParvoFiltersParameters(const float beta1, const float tau1, const float k1, const float beta2, const float tau2, const float k2) -{ - // init photoreceptors low pass filter - setLPfilterParameters(beta1, tau1, k1); - // init horizontal cells low pass filter - setLPfilterParameters(beta2, tau2, k2, 1); - // init parasol ganglion cells low pass filter (default parameters) - setLPfilterParameters(0, tau1, k1, 2); - -} -const oclMat &ParvoRetinaFilter::runFilter(const oclMat &inputFrame, const bool useParvoOutput) -{ - _spatiotemporalLPfilter(inputFrame, _photoreceptorsOutput); - _spatiotemporalLPfilter(_photoreceptorsOutput, _horizontalCellsOutput, 1); - _OPL_OnOffWaysComputing(); - - if (useParvoOutput) - { - // local adaptation processes on ON and OFF ways - _spatiotemporalLPfilter(_bipolarCellsOutputON, _localAdaptationON, 2); - _localLuminanceAdaptation(_parvocellularOutputON, _localAdaptationON); - _spatiotemporalLPfilter(_bipolarCellsOutputOFF, _localAdaptationOFF, 2); - _localLuminanceAdaptation(_parvocellularOutputOFF, _localAdaptationOFF); - ocl::subtract(_parvocellularOutputON, _parvocellularOutputOFF, _parvocellularOutputONminusOFF); - } - - return _parvocellularOutputONminusOFF; -} -void ParvoRetinaFilter::_OPL_OnOffWaysComputing() -{ - int elements_per_row = static_cast(_photoreceptorsOutput.step / _photoreceptorsOutput.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {(_photoreceptorsOutput.cols + 3) / 4, _photoreceptorsOutput.rows, 1}; - size_t localSize[] = {16, 16, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &_photoreceptorsOutput.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &_horizontalCellsOutput.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &_bipolarCellsOutputON.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &_bipolarCellsOutputOFF.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &_parvocellularOutputON.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &_parvocellularOutputOFF.data)); - args.push_back(std::make_pair(sizeof(cl_int), &_photoreceptorsOutput.cols)); - args.push_back(std::make_pair(sizeof(cl_int), &_photoreceptorsOutput.rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - openCLExecuteKernel(ctx, &retina_kernel, "OPL_OnOffWaysComputing", globalSize, localSize, args, -1, -1); -} - -/////////////////////////////////////// -//////////// MagnoFilter ////////////// -/////////////////////////////////////// -MagnoRetinaFilter::MagnoRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns) - : BasicRetinaFilter(NBrows, NBcolumns, 2), - _previousInput_ON(NBrows, NBcolumns, CV_32FC1), - _previousInput_OFF(NBrows, NBcolumns, CV_32FC1), - _amacrinCellsTempOutput_ON(NBrows, NBcolumns, CV_32FC1), - _amacrinCellsTempOutput_OFF(NBrows, NBcolumns, CV_32FC1), - _magnoXOutputON(NBrows, NBcolumns, CV_32FC1), - _magnoXOutputOFF(NBrows, NBcolumns, CV_32FC1), - _localProcessBufferON(NBrows, NBcolumns, CV_32FC1), - _localProcessBufferOFF(NBrows, NBcolumns, CV_32FC1) -{ - _magnoYOutput = _filterOutput; - _magnoYsaturated = _localBuffer; - - clearAllBuffers(); -} - -MagnoRetinaFilter::~MagnoRetinaFilter() -{ -} -void MagnoRetinaFilter::clearAllBuffers() -{ - BasicRetinaFilter::clearAllBuffers(); - _previousInput_ON = 0; - _previousInput_OFF = 0; - _amacrinCellsTempOutput_ON = 0; - _amacrinCellsTempOutput_OFF = 0; - _magnoXOutputON = 0; - _magnoXOutputOFF = 0; - _localProcessBufferON = 0; - _localProcessBufferOFF = 0; - -} -void MagnoRetinaFilter::resize(const unsigned int NBrows, const unsigned int NBcolumns) -{ - BasicRetinaFilter::resize(NBrows, NBcolumns); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _previousInput_ON); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _previousInput_OFF); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _amacrinCellsTempOutput_ON); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _amacrinCellsTempOutput_OFF); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _magnoXOutputON); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _magnoXOutputOFF); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _localProcessBufferON); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _localProcessBufferOFF); - - // to be sure, relink buffers - _magnoYOutput = _filterOutput; - _magnoYsaturated = _localBuffer; - - // reset all buffers - clearAllBuffers(); -} - -void MagnoRetinaFilter::setCoefficientsTable(const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float localAdaptIntegration_tau, const float localAdaptIntegration_k ) -{ - _temporalCoefficient = (float)std::exp(-1.0f / amacrinCellsTemporalCutFrequency); - // the first set of parameters is dedicated to the low pass filtering property of the ganglion cells - BasicRetinaFilter::setLPfilterParameters(parasolCells_beta, parasolCells_tau, parasolCells_k, 0); - // the second set of parameters is dedicated to the ganglion cells output intergartion for their local adaptation property - BasicRetinaFilter::setLPfilterParameters(0, localAdaptIntegration_tau, localAdaptIntegration_k, 1); -} - -void MagnoRetinaFilter::_amacrineCellsComputing( - const oclMat &OPL_ON, - const oclMat &OPL_OFF -) -{ - int elements_per_row = static_cast(OPL_ON.step / OPL_ON.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {OPL_ON.cols, OPL_ON.rows, 1}; - size_t localSize[] = {16, 16, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &OPL_ON.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &OPL_OFF.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &_previousInput_ON.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &_previousInput_OFF.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &_amacrinCellsTempOutput_ON.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &_amacrinCellsTempOutput_OFF.data)); - args.push_back(std::make_pair(sizeof(cl_int), &OPL_ON.cols)); - args.push_back(std::make_pair(sizeof(cl_int), &OPL_ON.rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_float), &_temporalCoefficient)); - openCLExecuteKernel(ctx, &retina_kernel, "amacrineCellsComputing", globalSize, localSize, args, -1, -1); -} - -const oclMat &MagnoRetinaFilter::runFilter(const oclMat &OPL_ON, const oclMat &OPL_OFF) -{ - // Compute the high pass temporal filter - _amacrineCellsComputing(OPL_ON, OPL_OFF); - - // apply low pass filtering on ON and OFF ways after temporal high pass filtering - _spatiotemporalLPfilter(_amacrinCellsTempOutput_ON, _magnoXOutputON, 0); - _spatiotemporalLPfilter(_amacrinCellsTempOutput_OFF, _magnoXOutputOFF, 0); - - // local adaptation of the ganglion cells to the local contrast of the moving contours - _spatiotemporalLPfilter(_magnoXOutputON, _localProcessBufferON, 1); - _localLuminanceAdaptation(_magnoXOutputON, _localProcessBufferON); - - _spatiotemporalLPfilter(_magnoXOutputOFF, _localProcessBufferOFF, 1); - _localLuminanceAdaptation(_magnoXOutputOFF, _localProcessBufferOFF); - - _magnoYOutput = _magnoXOutputON + _magnoXOutputOFF; - - return _magnoYOutput; -} - -/////////////////////////////////////// -//////////// RetinaColor ////////////// -/////////////////////////////////////// - -// define an array of ROI headers of input x -#define MAKE_OCLMAT_SLICES(x, n) \ - oclMat x##_slices[n];\ - for(int _SLICE_INDEX_ = 0; _SLICE_INDEX_ < n; _SLICE_INDEX_ ++)\ - {\ - x##_slices[_SLICE_INDEX_] = x(getROI(_SLICE_INDEX_));\ - } - -RetinaColor::RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const int samplingMethod) - : BasicRetinaFilter(NBrows, NBcolumns, 3), - _RGBmosaic(NBrows * 3, NBcolumns, CV_32FC1), - _tempMultiplexedFrame(NBrows, NBcolumns, CV_32FC1), - _demultiplexedTempBuffer(NBrows * 3, NBcolumns, CV_32FC1), - _demultiplexedColorFrame(NBrows * 3, NBcolumns, CV_32FC1), - _chrominance(NBrows * 3, NBcolumns, CV_32FC1), - _colorLocalDensity(NBrows * 3, NBcolumns, CV_32FC1), - _imageGradient(NBrows * 3, NBcolumns, CV_32FC1) -{ - // link to parent buffers (let's recycle !) - _luminance = _filterOutput; - _multiplexedFrame = _localBuffer; - - _objectInit = false; - _samplingMethod = samplingMethod; - _saturateColors = false; - _colorSaturationValue = 4.0; - - // set default spatio-temporal filter parameters - setLPfilterParameters(0.0, 0.0, 1.5); - setLPfilterParameters(0.0, 0.0, 10.5, 1);// for the low pass filter dedicated to contours energy extraction (demultiplexing process) - setLPfilterParameters(0.f, 0.f, 0.9f, 2); - - // init default value on image Gradient - _imageGradient = 0.57f; - - // init color sampling map - _initColorSampling(); - - // flush all buffers - clearAllBuffers(); -} - -RetinaColor::~RetinaColor() -{ - -} - -void RetinaColor::clearAllBuffers() -{ - BasicRetinaFilter::clearAllBuffers(); - _tempMultiplexedFrame = 0.f; - _demultiplexedTempBuffer = 0.f; - - _demultiplexedColorFrame = 0.f; - _chrominance = 0.f; - _imageGradient = 0.57f; -} - -void RetinaColor::resize(const unsigned int NBrows, const unsigned int NBcolumns) -{ - BasicRetinaFilter::clearAllBuffers(); - ensureSizeIsEnough(NBrows, NBcolumns, CV_32FC1, _tempMultiplexedFrame); - ensureSizeIsEnough(NBrows * 2, NBcolumns, CV_32FC1, _imageGradient); - ensureSizeIsEnough(NBrows * 3, NBcolumns, CV_32FC1, _RGBmosaic); - ensureSizeIsEnough(NBrows * 3, NBcolumns, CV_32FC1, _demultiplexedTempBuffer); - ensureSizeIsEnough(NBrows * 3, NBcolumns, CV_32FC1, _demultiplexedColorFrame); - ensureSizeIsEnough(NBrows * 3, NBcolumns, CV_32FC1, _chrominance); - ensureSizeIsEnough(NBrows * 3, NBcolumns, CV_32FC1, _colorLocalDensity); - - // link to parent buffers (let's recycle !) - _luminance = _filterOutput; - _multiplexedFrame = _localBuffer; - - // init color sampling map - _initColorSampling(); - - // clean buffers - clearAllBuffers(); -} - -static void inverseValue(oclMat &input) -{ - int elements_per_row = static_cast(input.step / input.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {input.cols, input.rows, 1}; - size_t localSize[] = {16, 16, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &input.data)); - args.push_back(std::make_pair(sizeof(cl_int), &input.cols)); - args.push_back(std::make_pair(sizeof(cl_int), &input.rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - openCLExecuteKernel(ctx, &retina_kernel, "inverseValue", globalSize, localSize, args, -1, -1); -} - -void RetinaColor::_initColorSampling() -{ - CV_Assert(_samplingMethod == RETINA_COLOR_BAYER); - _pR = _pB = 0.25; - _pG = 0.5; - // filling the mosaic buffer: - _RGBmosaic = 0; - Mat tmp_mat(_NBrows * 3, _NBcols, CV_32FC1); - float * tmp_mat_ptr = tmp_mat.ptr(); - tmp_mat.setTo(0); - for (unsigned int index = 0 ; index < getNBpixels(); ++index) - { - tmp_mat_ptr[bayerSampleOffset(index)] = 1.0; - } - _RGBmosaic.upload(tmp_mat); - // computing photoreceptors local density - MAKE_OCLMAT_SLICES(_RGBmosaic, 3); - MAKE_OCLMAT_SLICES(_colorLocalDensity, 3); - _colorLocalDensity.setTo(0); - _spatiotemporalLPfilter(_RGBmosaic_slices[0], _colorLocalDensity_slices[0]); - _spatiotemporalLPfilter(_RGBmosaic_slices[1], _colorLocalDensity_slices[1]); - _spatiotemporalLPfilter(_RGBmosaic_slices[2], _colorLocalDensity_slices[2]); - - //_colorLocalDensity = oclMat(_colorLocalDensity.size(), _colorLocalDensity.type(), 1.f) / _colorLocalDensity; - inverseValue(_colorLocalDensity); - - _objectInit = true; -} - -static void demultiplex(const oclMat &input, oclMat &ouput) -{ - int elements_per_row = static_cast(input.step / input.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {input.cols, input.rows, 1}; - size_t localSize[] = {16, 16, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &input.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &ouput.data)); - args.push_back(std::make_pair(sizeof(cl_int), &input.cols)); - args.push_back(std::make_pair(sizeof(cl_int), &input.rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - openCLExecuteKernel(ctx, &retina_kernel, "runColorDemultiplexingBayer", globalSize, localSize, args, -1, -1); -} - -static void normalizePhotoDensity( - const oclMat &chroma, - const oclMat &colorDensity, - const oclMat &multiplex, - oclMat &ocl_luma, - oclMat &demultiplex, - const float pG -) -{ - int elements_per_row = static_cast(ocl_luma.step / ocl_luma.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {ocl_luma.cols, ocl_luma.rows, 1}; - size_t localSize[] = {16, 16, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &chroma.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &colorDensity.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &multiplex.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &ocl_luma.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &demultiplex.data)); - args.push_back(std::make_pair(sizeof(cl_int), &ocl_luma.cols)); - args.push_back(std::make_pair(sizeof(cl_int), &ocl_luma.rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_float), &pG)); - openCLExecuteKernel(ctx, &retina_kernel, "normalizePhotoDensity", globalSize, localSize, args, -1, -1); -} - -static void substractResidual( - oclMat &colorDemultiplex, - float pR, - float pG, - float pB -) -{ - int elements_per_row = static_cast(colorDemultiplex.step / colorDemultiplex.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - int rows = colorDemultiplex.rows / 3, cols = colorDemultiplex.cols; - size_t globalSize[] = {cols, rows, 1}; - size_t localSize[] = {16, 16, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &colorDemultiplex.data)); - args.push_back(std::make_pair(sizeof(cl_int), &cols)); - args.push_back(std::make_pair(sizeof(cl_int), &rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_float), &pR)); - args.push_back(std::make_pair(sizeof(cl_float), &pG)); - args.push_back(std::make_pair(sizeof(cl_float), &pB)); - openCLExecuteKernel(ctx, &retina_kernel, "substractResidual", globalSize, localSize, args, -1, -1); -} - -static void demultiplexAssign(const oclMat& input, const oclMat& output) -{ - // only supports bayer - int elements_per_row = static_cast(input.step / input.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - int rows = input.rows / 3, cols = input.cols; - size_t globalSize[] = {cols, rows, 1}; - size_t localSize[] = {16, 16, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &input.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &output.data)); - args.push_back(std::make_pair(sizeof(cl_int), &cols)); - args.push_back(std::make_pair(sizeof(cl_int), &rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - openCLExecuteKernel(ctx, &retina_kernel, "demultiplexAssign", globalSize, localSize, args, -1, -1); -} - -void RetinaColor::runColorDemultiplexing( - const oclMat &ocl_multiplexed_input, - const bool adaptiveFiltering, - const float maxInputValue -) -{ - MAKE_OCLMAT_SLICES(_demultiplexedTempBuffer, 3); - MAKE_OCLMAT_SLICES(_chrominance, 3); - MAKE_OCLMAT_SLICES(_RGBmosaic, 3); - MAKE_OCLMAT_SLICES(_demultiplexedColorFrame, 3); - MAKE_OCLMAT_SLICES(_colorLocalDensity, 3); - - _demultiplexedTempBuffer.setTo(0); - demultiplex(ocl_multiplexed_input, _demultiplexedTempBuffer); - - // interpolate the demultiplexed frame depending on the color sampling method - if (!adaptiveFiltering) - { - CV_Assert(adaptiveFiltering == false); - } - - _spatiotemporalLPfilter(_demultiplexedTempBuffer_slices[0], _chrominance_slices[0]); - _spatiotemporalLPfilter(_demultiplexedTempBuffer_slices[1], _chrominance_slices[1]); - _spatiotemporalLPfilter(_demultiplexedTempBuffer_slices[2], _chrominance_slices[2]); - - if (!adaptiveFiltering)// compute the gradient on the luminance - { - // TODO: implement me! - CV_Assert(adaptiveFiltering == false); - } - else - { - normalizePhotoDensity(_chrominance, _colorLocalDensity, ocl_multiplexed_input, _luminance, _demultiplexedTempBuffer, _pG); - // compute the gradient of the luminance - _computeGradient(_luminance, _imageGradient); - - _adaptiveSpatialLPfilter(_RGBmosaic_slices[0], _imageGradient, _chrominance_slices[0]); - _adaptiveSpatialLPfilter(_RGBmosaic_slices[1], _imageGradient, _chrominance_slices[1]); - _adaptiveSpatialLPfilter(_RGBmosaic_slices[2], _imageGradient, _chrominance_slices[2]); - - _adaptiveSpatialLPfilter(_demultiplexedTempBuffer_slices[0], _imageGradient, _demultiplexedColorFrame_slices[0]); - _adaptiveSpatialLPfilter(_demultiplexedTempBuffer_slices[1], _imageGradient, _demultiplexedColorFrame_slices[1]); - _adaptiveSpatialLPfilter(_demultiplexedTempBuffer_slices[2], _imageGradient, _demultiplexedColorFrame_slices[2]); - - _demultiplexedColorFrame /= _chrominance; // per element division - substractResidual(_demultiplexedColorFrame, _pR, _pG, _pB); - runColorMultiplexing(_demultiplexedColorFrame, _tempMultiplexedFrame); - - _demultiplexedTempBuffer.setTo(0); - _luminance = ocl_multiplexed_input - _tempMultiplexedFrame; - demultiplexAssign(_demultiplexedColorFrame, _demultiplexedTempBuffer); - - for(int i = 0; i < 3; i ++) - { - _spatiotemporalLPfilter(_demultiplexedTempBuffer_slices[i], _demultiplexedTempBuffer_slices[i]); - _demultiplexedColorFrame_slices[i] = _demultiplexedTempBuffer_slices[i] * _colorLocalDensity_slices[i] + _luminance; - } - } - // eliminate saturated colors by simple clipping values to the input range - clipRGBOutput_0_maxInputValue(_demultiplexedColorFrame, maxInputValue); - - if (_saturateColors) - { - ocl::normalizeGrayOutputCentredSigmoide(128, maxInputValue, _demultiplexedColorFrame, _demultiplexedColorFrame); - } -} -void RetinaColor::runColorMultiplexing(const oclMat &demultiplexedInputFrame, oclMat &multiplexedFrame) -{ - int elements_per_row = static_cast(multiplexedFrame.step / multiplexedFrame.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {multiplexedFrame.cols, multiplexedFrame.rows, 1}; - size_t localSize[] = {16, 16, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &demultiplexedInputFrame.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &multiplexedFrame.data)); - args.push_back(std::make_pair(sizeof(cl_int), &multiplexedFrame.cols)); - args.push_back(std::make_pair(sizeof(cl_int), &multiplexedFrame.rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - openCLExecuteKernel(ctx, &retina_kernel, "runColorMultiplexingBayer", globalSize, localSize, args, -1, -1); -} - -void RetinaColor::clipRGBOutput_0_maxInputValue(oclMat &inputOutputBuffer, const float maxInputValue) -{ - // the kernel is equivalent to: - //ocl::threshold(inputOutputBuffer, inputOutputBuffer, maxInputValue, maxInputValue, THRESH_TRUNC); - //ocl::threshold(inputOutputBuffer, inputOutputBuffer, 0, 0, THRESH_TOZERO); - int elements_per_row = static_cast(inputOutputBuffer.step / inputOutputBuffer.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {_NBcols, inputOutputBuffer.rows, 1}; - size_t localSize[] = {16, 16, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &inputOutputBuffer.data)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); - args.push_back(std::make_pair(sizeof(cl_int), &inputOutputBuffer.rows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_float), &maxInputValue)); - openCLExecuteKernel(ctx, &retina_kernel, "clipRGBOutput_0_maxInputValue", globalSize, localSize, args, -1, -1); -} - -void RetinaColor::_adaptiveSpatialLPfilter(const oclMat &inputFrame, const oclMat &gradient, oclMat &outputFrame) -{ - /**********/ - _gain = (1 - 0.57f) * (1 - 0.57f) * (1 - 0.06f) * (1 - 0.06f); - - // launch the serie of 1D directional filters in order to compute the 2D low pass filter - // -> horizontal filters work with the first layer of imageGradient - _adaptiveHorizontalCausalFilter_addInput(inputFrame, gradient, outputFrame); - _horizontalAnticausalFilter_Irregular(outputFrame, gradient); - // -> horizontal filters work with the second layer of imageGradient - _verticalCausalFilter_Irregular(outputFrame, gradient(getROI(1))); - _adaptiveVerticalAnticausalFilter_multGain(gradient, outputFrame); -} - -void RetinaColor::_adaptiveHorizontalCausalFilter_addInput(const oclMat &inputFrame, const oclMat &gradient, oclMat &outputFrame) -{ - int elements_per_row = static_cast(inputFrame.step / inputFrame.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {_NBrows, 1, 1}; - size_t localSize[] = {256, 1, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &inputFrame.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &gradient.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_int), &inputFrame.offset)); - args.push_back(std::make_pair(sizeof(cl_int), &gradient.offset)); - args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); - openCLExecuteKernel(ctx, &retina_kernel, "adaptiveHorizontalCausalFilter_addInput", globalSize, localSize, args, -1, -1); -} - -void RetinaColor::_adaptiveVerticalAnticausalFilter_multGain(const oclMat &gradient, oclMat &outputFrame) -{ - int elements_per_row = static_cast(outputFrame.step / outputFrame.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {_NBcols, 1, 1}; - size_t localSize[] = {256, 1, 1}; - - int gradOffset = gradient.offset + static_cast(gradient.step * _NBrows); - - args.push_back(std::make_pair(sizeof(cl_mem), &gradient.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &outputFrame.data)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_int), &gradOffset)); - args.push_back(std::make_pair(sizeof(cl_int), &outputFrame.offset)); - args.push_back(std::make_pair(sizeof(cl_float), &_gain)); - openCLExecuteKernel(ctx, &retina_kernel, "adaptiveVerticalAnticausalFilter_multGain", globalSize, localSize, args, -1, -1); -} -void RetinaColor::_computeGradient(const oclMat &luminance, oclMat &gradient) -{ - int elements_per_row = static_cast(luminance.step / luminance.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {_NBcols, _NBrows, 1}; - size_t localSize[] = {16, 16, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &luminance.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &gradient.data)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBcols)); - args.push_back(std::make_pair(sizeof(cl_int), &_NBrows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - openCLExecuteKernel(ctx, &retina_kernel, "computeGradient", globalSize, localSize, args, -1, -1); -} - -/////////////////////////////////////// -//////////// RetinaFilter ///////////// -/////////////////////////////////////// -RetinaFilter::RetinaFilter(const unsigned int sizeRows, const unsigned int sizeColumns, const bool colorMode, const int samplingMethod, const bool useRetinaLogSampling, const double, const double) - : - _photoreceptorsPrefilter(sizeRows, sizeColumns, 4), - _ParvoRetinaFilter(sizeRows, sizeColumns), - _MagnoRetinaFilter(sizeRows, sizeColumns), - _colorEngine(sizeRows, sizeColumns, samplingMethod) -{ - CV_Assert(!useRetinaLogSampling); - - // set default processing activities - _useParvoOutput = true; - _useMagnoOutput = true; - - _useColorMode = colorMode; - - // set default parameters - setGlobalParameters(); - - // stability controls values init - _setInitPeriodCount(); - _globalTemporalConstant = 25; - - // reset all buffers - clearAllBuffers(); -} - -RetinaFilter::~RetinaFilter() -{ -} - -void RetinaFilter::clearAllBuffers() -{ - _photoreceptorsPrefilter.clearAllBuffers(); - _ParvoRetinaFilter.clearAllBuffers(); - _MagnoRetinaFilter.clearAllBuffers(); - _colorEngine.clearAllBuffers(); - // stability controls value init - _setInitPeriodCount(); -} - -void RetinaFilter::resize(const unsigned int NBrows, const unsigned int NBcolumns) -{ - unsigned int rows = NBrows, cols = NBcolumns; - - // resize optionnal member and adjust other modules size if required - _photoreceptorsPrefilter.resize(rows, cols); - _ParvoRetinaFilter.resize(rows, cols); - _MagnoRetinaFilter.resize(rows, cols); - _colorEngine.resize(rows, cols); - - // clean buffers - clearAllBuffers(); - -} - -void RetinaFilter::_setInitPeriodCount() -{ - // find out the maximum temporal constant value and apply a security factor - // false value (obviously too long) but appropriate for simple use - _globalTemporalConstant = (unsigned int)(_ParvoRetinaFilter.getPhotoreceptorsTemporalConstant() + _ParvoRetinaFilter.getHcellsTemporalConstant() + _MagnoRetinaFilter.getTemporalConstant()); - // reset frame counter - _ellapsedFramesSinceLastReset = 0; -} - -void RetinaFilter::setGlobalParameters(const float OPLspatialResponse1, const float OPLtemporalresponse1, const float OPLassymetryGain, const float OPLspatialResponse2, const float OPLtemporalresponse2, const float LPfilterSpatialResponse, const float LPfilterGain, const float LPfilterTemporalresponse, const float MovingContoursExtractorCoefficient, const bool normalizeParvoOutput_0_maxOutputValue, const bool normalizeMagnoOutput_0_maxOutputValue, const float maxOutputValue, const float maxInputValue, const float meanValue) -{ - _normalizeParvoOutput_0_maxOutputValue = normalizeParvoOutput_0_maxOutputValue; - _normalizeMagnoOutput_0_maxOutputValue = normalizeMagnoOutput_0_maxOutputValue; - _maxOutputValue = maxOutputValue; - _photoreceptorsPrefilter.setV0CompressionParameter(0.9f, maxInputValue, meanValue); - _photoreceptorsPrefilter.setLPfilterParameters(0, 0, 10, 3); // keeps low pass filter with low cut frequency in memory (usefull for the tone mapping function) - _ParvoRetinaFilter.setOPLandParvoFiltersParameters(0, OPLtemporalresponse1, OPLspatialResponse1, OPLassymetryGain, OPLtemporalresponse2, OPLspatialResponse2); - _ParvoRetinaFilter.setV0CompressionParameter(0.9f, maxInputValue, meanValue); - _MagnoRetinaFilter.setCoefficientsTable(LPfilterGain, LPfilterTemporalresponse, LPfilterSpatialResponse, MovingContoursExtractorCoefficient, 0, 2.0f * LPfilterSpatialResponse); - _MagnoRetinaFilter.setV0CompressionParameter(0.7f, maxInputValue, meanValue); - - // stability controls value init - _setInitPeriodCount(); -} - -bool RetinaFilter::checkInput(const oclMat &input, const bool) -{ - BasicRetinaFilter *inputTarget = &_photoreceptorsPrefilter; - - bool test = (input.rows == static_cast(inputTarget->getNBrows()) - || input.rows == static_cast(inputTarget->getNBrows()) * 3 - || input.rows == static_cast(inputTarget->getNBrows()) * 4) - && input.cols == static_cast(inputTarget->getNBcolumns()); - if (!test) - { - std::cerr << "RetinaFilter::checkInput: input buffer does not match retina buffer size, conversion aborted" << std::endl; - return false; - } - - return true; -} - -// main function that runs the filter for a given input frame -bool RetinaFilter::runFilter(const oclMat &imageInput, const bool useAdaptiveFiltering, const bool processRetinaParvoMagnoMapping, const bool useColorMode, const bool inputIsColorMultiplexed) -{ - // preliminary check - bool processSuccess = true; - if (!checkInput(imageInput, useColorMode)) - { - return false; - } - - // run the color multiplexing if needed and compute each suub filter of the retina: - // -> local adaptation - // -> contours OPL extraction - // -> moving contours extraction - - // stability controls value update - ++_ellapsedFramesSinceLastReset; - - _useColorMode = useColorMode; - - oclMat selectedPhotoreceptorsLocalAdaptationInput = imageInput; - oclMat selectedPhotoreceptorsColorInput = imageInput; - - //********** Following is input data specific photoreceptors processing - if (useColorMode && (!inputIsColorMultiplexed)) // not multiplexed color input case - { - _colorEngine.runColorMultiplexing(selectedPhotoreceptorsColorInput); - selectedPhotoreceptorsLocalAdaptationInput = _colorEngine.getMultiplexedFrame(); - } - //********** Following is generic Retina processing - - // photoreceptors local adaptation - _photoreceptorsPrefilter.runFilter_LocalAdapdation(selectedPhotoreceptorsLocalAdaptationInput, _ParvoRetinaFilter.getHorizontalCellsOutput()); - - // run parvo filter - _ParvoRetinaFilter.runFilter(_photoreceptorsPrefilter.getOutput(), _useParvoOutput); - - if (_useParvoOutput) - { - _ParvoRetinaFilter.normalizeGrayOutputCentredSigmoide(); // models the saturation of the cells, usefull for visualisation of the ON-OFF Parvo Output, Bipolar cells outputs do not change !!! - _ParvoRetinaFilter.centerReductImageLuminance(); // best for further spectrum analysis - - if (_normalizeParvoOutput_0_maxOutputValue) - { - _ParvoRetinaFilter.normalizeGrayOutput_0_maxOutputValue(_maxOutputValue); - } - } - - if (_useParvoOutput && _useMagnoOutput) - { - _MagnoRetinaFilter.runFilter(_ParvoRetinaFilter.getBipolarCellsON(), _ParvoRetinaFilter.getBipolarCellsOFF()); - if (_normalizeMagnoOutput_0_maxOutputValue) - { - _MagnoRetinaFilter.normalizeGrayOutput_0_maxOutputValue(_maxOutputValue); - } - _MagnoRetinaFilter.normalizeGrayOutputNearZeroCentreredSigmoide(); - } - - if (_useParvoOutput && _useMagnoOutput && processRetinaParvoMagnoMapping) - { - _processRetinaParvoMagnoMapping(); - if (_useColorMode) - { - _colorEngine.runColorDemultiplexing(_retinaParvoMagnoMappedFrame, useAdaptiveFiltering, _maxOutputValue); - } - return processSuccess; - } - - if (_useParvoOutput && _useColorMode) - { - _colorEngine.runColorDemultiplexing(_ParvoRetinaFilter.getOutput(), useAdaptiveFiltering, _maxOutputValue); - } - return processSuccess; -} - -const oclMat &RetinaFilter::getContours() -{ - if (_useColorMode) - { - return _colorEngine.getLuminance(); - } - else - { - return _ParvoRetinaFilter.getOutput(); - } -} -void RetinaFilter::_processRetinaParvoMagnoMapping() -{ - oclMat parvo = _ParvoRetinaFilter.getOutput(); - oclMat magno = _MagnoRetinaFilter.getOutput(); - - int halfRows = parvo.rows / 2; - int halfCols = parvo.cols / 2; - float minDistance = MIN(halfRows, halfCols) * 0.7f; - - int elements_per_row = static_cast(parvo.step / parvo.elemSize()); - - Context * ctx = Context::getContext(); - std::vector > args; - size_t globalSize[] = {parvo.cols, parvo.rows, 1}; - size_t localSize[] = {16, 16, 1}; - - args.push_back(std::make_pair(sizeof(cl_mem), &parvo.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &magno.data)); - args.push_back(std::make_pair(sizeof(cl_int), &parvo.cols)); - args.push_back(std::make_pair(sizeof(cl_int), &parvo.rows)); - args.push_back(std::make_pair(sizeof(cl_int), &halfCols)); - args.push_back(std::make_pair(sizeof(cl_int), &halfRows)); - args.push_back(std::make_pair(sizeof(cl_int), &elements_per_row)); - args.push_back(std::make_pair(sizeof(cl_float), &minDistance)); - openCLExecuteKernel(ctx, &retina_kernel, "processRetinaParvoMagnoMapping", globalSize, localSize, args, -1, -1); -} -} /* namespace ocl */ - -Ptr createRetina_OCL(Size getInputSize){ return makePtr(getInputSize); } -Ptr createRetina_OCL(Size getInputSize, const bool colorMode, int colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) -{ - return makePtr(getInputSize, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght); -} - -} /* namespace bioinspired */ -} /* namespace cv */ - -#endif /* #ifdef HAVE_OPENCV_OCL */ diff --git a/modules/bioinspired/src/retina_ocl.hpp b/modules/bioinspired/src/retina_ocl.hpp deleted file mode 100644 index 11da48b93..000000000 --- a/modules/bioinspired/src/retina_ocl.hpp +++ /dev/null @@ -1,634 +0,0 @@ -/*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-2013, Multicoreware, Inc., all rights reserved. -// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Peng Xiao, pengxiao@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 oclMaterials 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 __OCL_RETINA_HPP__ -#define __OCL_RETINA_HPP__ - -#include "precomp.hpp" - -#ifdef HAVE_OPENCV_OCL - -// please refer to c++ headers for API comments -namespace cv -{ -namespace bioinspired -{ -namespace ocl -{ -void normalizeGrayOutputCentredSigmoide(const float meanValue, const float sensitivity, cv::ocl::oclMat &in, cv::ocl::oclMat &out, const float maxValue = 255.f); -void normalizeGrayOutput_0_maxOutputValue(cv::ocl::oclMat &inputOutputBuffer, const float maxOutputValue = 255.0); -void normalizeGrayOutputNearZeroCentreredSigmoide(cv::ocl::oclMat &inputPicture, cv::ocl::oclMat &outputBuffer, const float sensitivity = 40, const float maxOutputValue = 255.0f); -void centerReductImageLuminance(cv::ocl::oclMat &inputOutputBuffer); - -class BasicRetinaFilter -{ -public: - BasicRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns, const unsigned int parametersListSize = 1, const bool useProgressiveFilter = false); - ~BasicRetinaFilter(); - inline void clearOutputBuffer() - { - _filterOutput = 0; - } - inline void clearSecondaryBuffer() - { - _localBuffer = 0; - } - inline void clearAllBuffers() - { - clearOutputBuffer(); - clearSecondaryBuffer(); - } - void resize(const unsigned int NBrows, const unsigned int NBcolumns); - const cv::ocl::oclMat &runFilter_LPfilter(const cv::ocl::oclMat &inputFrame, const unsigned int filterIndex = 0); - void runFilter_LPfilter(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &outputFrame, const unsigned int filterIndex = 0); - void runFilter_LPfilter_Autonomous(cv::ocl::oclMat &inputOutputFrame, const unsigned int filterIndex = 0); - const cv::ocl::oclMat &runFilter_LocalAdapdation(const cv::ocl::oclMat &inputOutputFrame, const cv::ocl::oclMat &localLuminance); - void runFilter_LocalAdapdation(const cv::ocl::oclMat &inputFrame, const cv::ocl::oclMat &localLuminance, cv::ocl::oclMat &outputFrame); - const cv::ocl::oclMat &runFilter_LocalAdapdation_autonomous(const cv::ocl::oclMat &inputFrame); - void runFilter_LocalAdapdation_autonomous(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &outputFrame); - void setLPfilterParameters(const float beta, const float tau, const float k, const unsigned int filterIndex = 0); - inline void setV0CompressionParameter(const float v0, const float maxInputValue, const float) - { - _v0 = v0 * maxInputValue; - _localLuminanceFactor = v0; - _localLuminanceAddon = maxInputValue * (1.0f - v0); - _maxInputValue = maxInputValue; - } - inline void setV0CompressionParameter(const float v0, const float meanLuminance) - { - this->setV0CompressionParameter(v0, _maxInputValue, meanLuminance); - } - inline void setV0CompressionParameter(const float v0) - { - _v0 = v0 * _maxInputValue; - _localLuminanceFactor = v0; - _localLuminanceAddon = _maxInputValue * (1.0f - v0); - } - inline void setV0CompressionParameterToneMapping(const float v0, const float maxInputValue, const float meanLuminance = 128.0f) - { - _v0 = v0 * maxInputValue; - _localLuminanceFactor = 1.0f; - _localLuminanceAddon = meanLuminance * _v0; - _maxInputValue = maxInputValue; - } - inline void updateCompressionParameter(const float meanLuminance) - { - _localLuminanceFactor = 1; - _localLuminanceAddon = meanLuminance * _v0; - } - inline float getV0CompressionParameter() - { - return _v0 / _maxInputValue; - } - inline const cv::ocl::oclMat &getOutput() const - { - return _filterOutput; - } - inline unsigned int getNBrows() - { - return _filterOutput.rows; - } - inline unsigned int getNBcolumns() - { - return _filterOutput.cols; - } - inline unsigned int getNBpixels() - { - return _filterOutput.size().area(); - } - inline void normalizeGrayOutput_0_maxOutputValue(const float maxValue) - { - ocl::normalizeGrayOutput_0_maxOutputValue(_filterOutput, maxValue); - } - inline void normalizeGrayOutputCentredSigmoide() - { - ocl::normalizeGrayOutputCentredSigmoide(0.0, 2.0, _filterOutput, _filterOutput); - } - inline void centerReductImageLuminance() - { - ocl::centerReductImageLuminance(_filterOutput); - } - inline float getMaxInputValue() - { - return this->_maxInputValue; - } - inline void setMaxInputValue(const float newMaxInputValue) - { - this->_maxInputValue = newMaxInputValue; - } - -protected: - - int _NBrows; - int _NBcols; - unsigned int _halfNBrows; - unsigned int _halfNBcolumns; - - cv::ocl::oclMat _filterOutput; - cv::ocl::oclMat _localBuffer; - - std::valarray _filteringCoeficientsTable; - float _v0; - float _maxInputValue; - float _meanInputValue; - float _localLuminanceFactor; - float _localLuminanceAddon; - - float _a; - float _tau; - float _gain; - - void _spatiotemporalLPfilter(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &LPfilterOutput, const unsigned int coefTableOffset = 0); - float _squaringSpatiotemporalLPfilter(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &outputFrame, const unsigned int filterIndex = 0); - void _spatiotemporalLPfilter_Irregular(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &outputFrame, const unsigned int filterIndex = 0); - void _localSquaringSpatioTemporalLPfilter(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &LPfilterOutput, const unsigned int *integrationAreas, const unsigned int filterIndex = 0); - void _localLuminanceAdaptation(const cv::ocl::oclMat &inputFrame, const cv::ocl::oclMat &localLuminance, cv::ocl::oclMat &outputFrame, const bool updateLuminanceMean = true); - void _localLuminanceAdaptation(cv::ocl::oclMat &inputOutputFrame, const cv::ocl::oclMat &localLuminance); - void _localLuminanceAdaptationPosNegValues(const cv::ocl::oclMat &inputFrame, const cv::ocl::oclMat &localLuminance, float *outputFrame); - void _horizontalCausalFilter_addInput(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &outputFrame); - void _horizontalAnticausalFilter(cv::ocl::oclMat &outputFrame); - void _verticalCausalFilter(cv::ocl::oclMat &outputFrame); - void _horizontalAnticausalFilter_Irregular(cv::ocl::oclMat &outputFrame, const cv::ocl::oclMat &spatialConstantBuffer); - void _verticalCausalFilter_Irregular(cv::ocl::oclMat &outputFrame, const cv::ocl::oclMat &spatialConstantBuffer); - void _verticalAnticausalFilter_multGain(cv::ocl::oclMat &outputFrame); -}; - -class MagnoRetinaFilter: public BasicRetinaFilter -{ -public: - MagnoRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns); - virtual ~MagnoRetinaFilter(); - void clearAllBuffers(); - void resize(const unsigned int NBrows, const unsigned int NBcolumns); - void setCoefficientsTable(const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float localAdaptIntegration_tau, const float localAdaptIntegration_k); - - const cv::ocl::oclMat &runFilter(const cv::ocl::oclMat &OPL_ON, const cv::ocl::oclMat &OPL_OFF); - - inline const cv::ocl::oclMat &getMagnoON() const - { - return _magnoXOutputON; - } - inline const cv::ocl::oclMat &getMagnoOFF() const - { - return _magnoXOutputOFF; - } - inline const cv::ocl::oclMat &getMagnoYsaturated() const - { - return _magnoYsaturated; - } - inline void normalizeGrayOutputNearZeroCentreredSigmoide() - { - ocl::normalizeGrayOutputNearZeroCentreredSigmoide(_magnoYOutput, _magnoYsaturated); - } - inline float getTemporalConstant() - { - return this->_filteringCoeficientsTable[2]; - } -private: - cv::ocl::oclMat _previousInput_ON; - cv::ocl::oclMat _previousInput_OFF; - cv::ocl::oclMat _amacrinCellsTempOutput_ON; - cv::ocl::oclMat _amacrinCellsTempOutput_OFF; - cv::ocl::oclMat _magnoXOutputON; - cv::ocl::oclMat _magnoXOutputOFF; - cv::ocl::oclMat _localProcessBufferON; - cv::ocl::oclMat _localProcessBufferOFF; - cv::ocl::oclMat _magnoYOutput; - cv::ocl::oclMat _magnoYsaturated; - - float _temporalCoefficient; - void _amacrineCellsComputing(const cv::ocl::oclMat &OPL_ON, const cv::ocl::oclMat &OPL_OFF); -}; - -class ParvoRetinaFilter: public BasicRetinaFilter -{ -public: - ParvoRetinaFilter(const unsigned int NBrows = 480, const unsigned int NBcolumns = 640); - virtual ~ParvoRetinaFilter(); - void resize(const unsigned int NBrows, const unsigned int NBcolumns); - void clearAllBuffers(); - void setOPLandParvoFiltersParameters(const float beta1, const float tau1, const float k1, const float beta2, const float tau2, const float k2); - - inline void setGanglionCellsLocalAdaptationLPfilterParameters(const float tau, const float k) - { - BasicRetinaFilter::setLPfilterParameters(0, tau, k, 2); - } - const cv::ocl::oclMat &runFilter(const cv::ocl::oclMat &inputFrame, const bool useParvoOutput = true); - - inline const cv::ocl::oclMat &getPhotoreceptorsLPfilteringOutput() const - { - return _photoreceptorsOutput; - } - - inline const cv::ocl::oclMat &getHorizontalCellsOutput() const - { - return _horizontalCellsOutput; - } - - inline const cv::ocl::oclMat &getParvoON() const - { - return _parvocellularOutputON; - } - - inline const cv::ocl::oclMat &getParvoOFF() const - { - return _parvocellularOutputOFF; - } - - inline const cv::ocl::oclMat &getBipolarCellsON() const - { - return _bipolarCellsOutputON; - } - - inline const cv::ocl::oclMat &getBipolarCellsOFF() const - { - return _bipolarCellsOutputOFF; - } - - inline float getPhotoreceptorsTemporalConstant() - { - return this->_filteringCoeficientsTable[2]; - } - - inline float getHcellsTemporalConstant() - { - return this->_filteringCoeficientsTable[5]; - } -private: - cv::ocl::oclMat _photoreceptorsOutput; - cv::ocl::oclMat _horizontalCellsOutput; - cv::ocl::oclMat _parvocellularOutputON; - cv::ocl::oclMat _parvocellularOutputOFF; - cv::ocl::oclMat _bipolarCellsOutputON; - cv::ocl::oclMat _bipolarCellsOutputOFF; - cv::ocl::oclMat _localAdaptationOFF; - cv::ocl::oclMat _localAdaptationON; - cv::ocl::oclMat _parvocellularOutputONminusOFF; - void _OPL_OnOffWaysComputing(); -}; -class RetinaColor: public BasicRetinaFilter -{ -public: - RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const int samplingMethod = RETINA_COLOR_DIAGONAL); - virtual ~RetinaColor(); - - void clearAllBuffers(); - void resize(const unsigned int NBrows, const unsigned int NBcolumns); - inline void runColorMultiplexing(const cv::ocl::oclMat &inputRGBFrame) - { - runColorMultiplexing(inputRGBFrame, _multiplexedFrame); - } - void runColorMultiplexing(const cv::ocl::oclMat &demultiplexedInputFrame, cv::ocl::oclMat &multiplexedFrame); - void runColorDemultiplexing(const cv::ocl::oclMat &multiplexedColorFrame, const bool adaptiveFiltering = false, const float maxInputValue = 255.0); - - void setColorSaturation(const bool saturateColors = true, const float colorSaturationValue = 4.0) - { - _saturateColors = saturateColors; - _colorSaturationValue = colorSaturationValue; - } - - void setChrominanceLPfilterParameters(const float beta, const float tau, const float k) - { - setLPfilterParameters(beta, tau, k); - } - - bool applyKrauskopfLMS2Acr1cr2Transform(cv::ocl::oclMat &result); - bool applyLMS2LabTransform(cv::ocl::oclMat &result); - inline const cv::ocl::oclMat &getMultiplexedFrame() const - { - return _multiplexedFrame; - } - - inline const cv::ocl::oclMat &getDemultiplexedColorFrame() const - { - return _demultiplexedColorFrame; - } - - inline const cv::ocl::oclMat &getLuminance() const - { - return _luminance; - } - inline const cv::ocl::oclMat &getChrominance() const - { - return _chrominance; - } - void clipRGBOutput_0_maxInputValue(cv::ocl::oclMat &inputOutputBuffer, const float maxOutputValue = 255.0); - void normalizeRGBOutput_0_maxOutputValue(const float maxOutputValue = 255.0); - inline void setDemultiplexedColorFrame(const cv::ocl::oclMat &demultiplexedImage) - { - _demultiplexedColorFrame = demultiplexedImage; - } -protected: - inline unsigned int bayerSampleOffset(unsigned int index) - { - return index + ((index / getNBcolumns()) % 2) * getNBpixels() + ((index % getNBcolumns()) % 2) * getNBpixels(); - } - inline Rect getROI(int idx) - { - return Rect(0, idx * _NBrows, _NBcols, _NBrows); - } - int _samplingMethod; - bool _saturateColors; - float _colorSaturationValue; - cv::ocl::oclMat _luminance; - cv::ocl::oclMat _multiplexedFrame; - cv::ocl::oclMat _RGBmosaic; - cv::ocl::oclMat _tempMultiplexedFrame; - cv::ocl::oclMat _demultiplexedTempBuffer; - cv::ocl::oclMat _demultiplexedColorFrame; - cv::ocl::oclMat _chrominance; - cv::ocl::oclMat _colorLocalDensity; - cv::ocl::oclMat _imageGradient; - - float _pR, _pG, _pB; - bool _objectInit; - - void _initColorSampling(); - void _adaptiveSpatialLPfilter(const cv::ocl::oclMat &inputFrame, const cv::ocl::oclMat &gradient, cv::ocl::oclMat &outputFrame); - void _adaptiveHorizontalCausalFilter_addInput(const cv::ocl::oclMat &inputFrame, const cv::ocl::oclMat &gradient, cv::ocl::oclMat &outputFrame); - void _adaptiveVerticalAnticausalFilter_multGain(const cv::ocl::oclMat &gradient, cv::ocl::oclMat &outputFrame); - void _computeGradient(const cv::ocl::oclMat &luminance, cv::ocl::oclMat &gradient); - void _normalizeOutputs_0_maxOutputValue(void); - void _applyImageColorSpaceConversion(const cv::ocl::oclMat &inputFrame, cv::ocl::oclMat &outputFrame, const float *transformTable); -}; -class RetinaFilter -{ -public: - RetinaFilter(const unsigned int sizeRows, const unsigned int sizeColumns, const bool colorMode = false, const int samplingMethod = RETINA_COLOR_BAYER, const bool useRetinaLogSampling = false, const double reductionFactor = 1.0, const double samplingStrenght = 10.0); - ~RetinaFilter(); - - void clearAllBuffers(); - void resize(const unsigned int NBrows, const unsigned int NBcolumns); - bool checkInput(const cv::ocl::oclMat &input, const bool colorMode); - bool runFilter(const cv::ocl::oclMat &imageInput, const bool useAdaptiveFiltering = true, const bool processRetinaParvoMagnoMapping = false, const bool useColorMode = false, const bool inputIsColorMultiplexed = false); - - void setGlobalParameters(const float OPLspatialResponse1 = 0.7, const float OPLtemporalresponse1 = 1, const float OPLassymetryGain = 0, const float OPLspatialResponse2 = 5, const float OPLtemporalresponse2 = 1, const float LPfilterSpatialResponse = 5, const float LPfilterGain = 0, const float LPfilterTemporalresponse = 0, const float MovingContoursExtractorCoefficient = 5, const bool normalizeParvoOutput_0_maxOutputValue = false, const bool normalizeMagnoOutput_0_maxOutputValue = false, const float maxOutputValue = 255.0, const float maxInputValue = 255.0, const float meanValue = 128.0); - - inline void setPhotoreceptorsLocalAdaptationSensitivity(const float V0CompressionParameter) - { - _photoreceptorsPrefilter.setV0CompressionParameter(1 - V0CompressionParameter); - _setInitPeriodCount(); - } - - inline void setParvoGanglionCellsLocalAdaptationSensitivity(const float V0CompressionParameter) - { - _ParvoRetinaFilter.setV0CompressionParameter(V0CompressionParameter); - _setInitPeriodCount(); - } - - inline void setGanglionCellsLocalAdaptationLPfilterParameters(const float spatialResponse, const float temporalResponse) - { - _ParvoRetinaFilter.setGanglionCellsLocalAdaptationLPfilterParameters(temporalResponse, spatialResponse); - _setInitPeriodCount(); - }; - - inline void setMagnoGanglionCellsLocalAdaptationSensitivity(const float V0CompressionParameter) - { - _MagnoRetinaFilter.setV0CompressionParameter(V0CompressionParameter); - _setInitPeriodCount(); - } - - void setOPLandParvoParameters(const float beta1, const float tau1, const float k1, const float beta2, const float tau2, const float k2, const float V0CompressionParameter) - { - _ParvoRetinaFilter.setOPLandParvoFiltersParameters(beta1, tau1, k1, beta2, tau2, k2); - _ParvoRetinaFilter.setV0CompressionParameter(V0CompressionParameter); - _setInitPeriodCount(); - } - - void setMagnoCoefficientsTable(const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float V0CompressionParameter, const float localAdaptintegration_tau, const float localAdaptintegration_k) - { - _MagnoRetinaFilter.setCoefficientsTable(parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, localAdaptintegration_tau, localAdaptintegration_k); - _MagnoRetinaFilter.setV0CompressionParameter(V0CompressionParameter); - _setInitPeriodCount(); - } - - inline void activateNormalizeParvoOutput_0_maxOutputValue(const bool normalizeParvoOutput_0_maxOutputValue) - { - _normalizeParvoOutput_0_maxOutputValue = normalizeParvoOutput_0_maxOutputValue; - } - - inline void activateNormalizeMagnoOutput_0_maxOutputValue(const bool normalizeMagnoOutput_0_maxOutputValue) - { - _normalizeMagnoOutput_0_maxOutputValue = normalizeMagnoOutput_0_maxOutputValue; - } - - inline void setMaxOutputValue(const float maxOutputValue) - { - _maxOutputValue = maxOutputValue; - } - - void setColorMode(const bool desiredColorMode) - { - _useColorMode = desiredColorMode; - } - inline void setColorSaturation(const bool saturateColors = true, const float colorSaturationValue = 4.0) - { - _colorEngine.setColorSaturation(saturateColors, colorSaturationValue); - } - inline const cv::ocl::oclMat &getLocalAdaptation() const - { - return _photoreceptorsPrefilter.getOutput(); - } - inline const cv::ocl::oclMat &getPhotoreceptors() const - { - return _ParvoRetinaFilter.getPhotoreceptorsLPfilteringOutput(); - } - - inline const cv::ocl::oclMat &getHorizontalCells() const - { - return _ParvoRetinaFilter.getHorizontalCellsOutput(); - } - inline bool areContoursProcessed() - { - return _useParvoOutput; - } - bool getParvoFoveaResponse(cv::ocl::oclMat &parvoFovealResponse); - inline void activateContoursProcessing(const bool useParvoOutput) - { - _useParvoOutput = useParvoOutput; - } - - const cv::ocl::oclMat &getContours(); - - inline const cv::ocl::oclMat &getContoursON() const - { - return _ParvoRetinaFilter.getParvoON(); - } - - inline const cv::ocl::oclMat &getContoursOFF() const - { - return _ParvoRetinaFilter.getParvoOFF(); - } - - inline bool areMovingContoursProcessed() - { - return _useMagnoOutput; - } - - inline void activateMovingContoursProcessing(const bool useMagnoOutput) - { - _useMagnoOutput = useMagnoOutput; - } - - inline const cv::ocl::oclMat &getMovingContours() const - { - return _MagnoRetinaFilter.getOutput(); - } - - inline const cv::ocl::oclMat &getMovingContoursSaturated() const - { - return _MagnoRetinaFilter.getMagnoYsaturated(); - } - - inline const cv::ocl::oclMat &getMovingContoursON() const - { - return _MagnoRetinaFilter.getMagnoON(); - } - - inline const cv::ocl::oclMat &getMovingContoursOFF() const - { - return _MagnoRetinaFilter.getMagnoOFF(); - } - - inline const cv::ocl::oclMat &getRetinaParvoMagnoMappedOutput() const - { - return _retinaParvoMagnoMappedFrame; - } - - inline const cv::ocl::oclMat &getParvoContoursChannel() const - { - return _colorEngine.getLuminance(); - } - - inline const cv::ocl::oclMat &getParvoChrominance() const - { - return _colorEngine.getChrominance(); - } - inline const cv::ocl::oclMat &getColorOutput() const - { - return _colorEngine.getDemultiplexedColorFrame(); - } - - inline bool isColorMode() - { - return _useColorMode; - } - bool getColorMode() - { - return _useColorMode; - } - - inline bool isInitTransitionDone() - { - if (_ellapsedFramesSinceLastReset < _globalTemporalConstant) - { - return false; - } - return true; - } - inline float getRetinaSamplingBackProjection(const float projectedRadiusLength) - { - return projectedRadiusLength; - } - - inline unsigned int getInputNBrows() - { - return _photoreceptorsPrefilter.getNBrows(); - } - - inline unsigned int getInputNBcolumns() - { - return _photoreceptorsPrefilter.getNBcolumns(); - } - - inline unsigned int getInputNBpixels() - { - return _photoreceptorsPrefilter.getNBpixels(); - } - - inline unsigned int getOutputNBrows() - { - return _photoreceptorsPrefilter.getNBrows(); - } - - inline unsigned int getOutputNBcolumns() - { - return _photoreceptorsPrefilter.getNBcolumns(); - } - - inline unsigned int getOutputNBpixels() - { - return _photoreceptorsPrefilter.getNBpixels(); - } -private: - bool _useParvoOutput; - bool _useMagnoOutput; - - unsigned int _ellapsedFramesSinceLastReset; - unsigned int _globalTemporalConstant; - - cv::ocl::oclMat _retinaParvoMagnoMappedFrame; - BasicRetinaFilter _photoreceptorsPrefilter; - ParvoRetinaFilter _ParvoRetinaFilter; - MagnoRetinaFilter _MagnoRetinaFilter; - RetinaColor _colorEngine; - - bool _useMinimalMemoryForToneMappingONLY; - bool _normalizeParvoOutput_0_maxOutputValue; - bool _normalizeMagnoOutput_0_maxOutputValue; - float _maxOutputValue; - bool _useColorMode; - - void _setInitPeriodCount(); - void _processRetinaParvoMagnoMapping(); - void _runGrayToneMapping(const cv::ocl::oclMat &grayImageInput, cv::ocl::oclMat &grayImageOutput , const float PhotoreceptorsCompression = 0.6, const float ganglionCellsCompression = 0.6); -}; - -} /* namespace ocl */ -} /* namespace bioinspired */ -} /* namespace cv */ - -#endif /* HAVE_OPENCV_OCL */ -#endif /* __OCL_RETINA_HPP__ */ diff --git a/modules/bioinspired/src/retinacolor.cpp b/modules/bioinspired/src/retinacolor.cpp deleted file mode 100644 index 3fbc55385..000000000 --- a/modules/bioinspired/src/retinacolor.cpp +++ /dev/null @@ -1,725 +0,0 @@ -/*#****************************************************************************** -** 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. -** -** -** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. -** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. -** -** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) -** -** Creation - enhancement process 2007-2011 -** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France -** -** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). -** Refer to the following research paper for more information: -** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 -** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: -** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. -** -** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : -** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: -** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. -** ====> more informations in the above cited Jeanny Heraults's book. -** -** License Agreement -** For Open Source Computer Vision Library -** -** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** -** For Human Visual System tools (bioinspired) -** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions 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. -*******************************************************************************/ - -#include "precomp.hpp" - -#include "retinacolor.hpp" - -// @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC : www.listic.univ-savoie.fr, Gipsa-Lab, France: www.gipsa-lab.inpg.fr/ - -#include -#include - -namespace cv -{ -namespace bioinspired -{ -// init static values -static float _LMStoACr1Cr2[]={1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -0.5, -0.5, 1.0}; -//static double _ACr1Cr2toLMS[]={0.5, 0.5, 0.0, 0.5, -0.5, 0.0, 0.5, 0.0, 1.0}; -static float _LMStoLab[]={0.5774f, 0.5774f, 0.5774f, 0.4082f, 0.4082f, -0.8165f, 0.7071f, -0.7071f, 0.f}; - -// constructor/desctructor -RetinaColor::RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const int samplingMethod) -:BasicRetinaFilter(NBrows, NBcolumns, 3), - _colorSampling(NBrows*NBcolumns), - _RGBmosaic(NBrows*NBcolumns*3), - _tempMultiplexedFrame(NBrows*NBcolumns), - _demultiplexedTempBuffer(NBrows*NBcolumns*3), - _demultiplexedColorFrame(NBrows*NBcolumns*3), - _chrominance(NBrows*NBcolumns*3), - _colorLocalDensity(NBrows*NBcolumns*3), - _imageGradient(NBrows*NBcolumns*2) -{ - // link to parent buffers (let's recycle !) - _luminance=&_filterOutput; - _multiplexedFrame=&_localBuffer; - - _objectInit=false; - _samplingMethod=samplingMethod; - _saturateColors=false; - _colorSaturationValue=4.0; - - // set default spatio-temporal filter parameters - setLPfilterParameters(0.0, 0.0, 1.5); - setLPfilterParameters(0.0, 0.0, 10.5, 1);// for the low pass filter dedicated to contours energy extraction (demultiplexing process) - setLPfilterParameters(0.f, 0.f, 0.9f, 2); - - // init default value on image Gradient - _imageGradient=0.57f; - - // init color sampling map - _initColorSampling(); - - // flush all buffers - clearAllBuffers(); -} - -RetinaColor::~RetinaColor() -{ - -} - -/** -* function that clears all buffers of the object -*/ -void RetinaColor::clearAllBuffers() -{ - BasicRetinaFilter::clearAllBuffers(); - _tempMultiplexedFrame=0.f; - _demultiplexedTempBuffer=0.f; - - _demultiplexedColorFrame=0.f; - _chrominance=0.f; - _imageGradient=0.57f; -} - -/** -* resize retina color filter object (resize all allocated buffers) -* @param NBrows: the new height size -* @param NBcolumns: the new width size -*/ -void RetinaColor::resize(const unsigned int NBrows, const unsigned int NBcolumns) -{ - BasicRetinaFilter::clearAllBuffers(); - _colorSampling.resize(NBrows*NBcolumns); - _RGBmosaic.resize(NBrows*NBcolumns*3); - _tempMultiplexedFrame.resize(NBrows*NBcolumns); - _demultiplexedTempBuffer.resize(NBrows*NBcolumns*3); - _demultiplexedColorFrame.resize(NBrows*NBcolumns*3); - _chrominance.resize(NBrows*NBcolumns*3); - _colorLocalDensity.resize(NBrows*NBcolumns*3); - _imageGradient.resize(NBrows*NBcolumns*2); - - // link to parent buffers (let's recycle !) - _luminance=&_filterOutput; - _multiplexedFrame=&_localBuffer; - - // init color sampling map - _initColorSampling(); - - // clean buffers - clearAllBuffers(); -} - - -void RetinaColor::_initColorSampling() -{ - - // filling the conversion table for multiplexed <=> demultiplexed frame - srand((unsigned)time(NULL)); - - // preInit cones probabilities - _pR=_pB=_pG=0; - switch (_samplingMethod) - { - case RETINA_COLOR_RANDOM: - for (unsigned int index=0 ; indexgetNBpixels(); ++index) - { - - // random RGB sampling - unsigned int colorIndex=rand()%24; - - if (colorIndex<8){ - colorIndex=0; - - ++_pR; - }else - { - if (colorIndex<21){ - colorIndex=1; - ++_pG; - }else{ - colorIndex=2; - ++_pB; - } - } - _colorSampling[index] = colorIndex*this->getNBpixels()+index; - } - _pR/=(float)this->getNBpixels(); - _pG/=(float)this->getNBpixels(); - _pB/=(float)this->getNBpixels(); - std::cout<<"Color channels proportions: pR, pG, pB= "<<_pR<<", "<<_pG<<", "<<_pB<<", "<getNBpixels(); ++index) - { - _colorSampling[index] = index+((index%3+(index%_filterOutput.getNBcolumns()))%3)*_filterOutput.getNBpixels(); - } - _pR=_pB=_pG=1.f/3; - break; - case RETINA_COLOR_BAYER: // default sets bayer sampling - for (unsigned int index=0 ; index<_filterOutput.getNBpixels(); ++index) - { - //First line: R G R G - _colorSampling[index] = index+((index/_filterOutput.getNBcolumns())%2)*_filterOutput.getNBpixels()+((index%_filterOutput.getNBcolumns())%2)*_filterOutput.getNBpixels(); - //First line: G R G R - //_colorSampling[index] = 3*index+((index/_filterOutput.getNBcolumns())%2)+((index%_filterOutput.getNBcolumns()+1)%2); - } - _pR=_pB=0.25; - _pG=0.5; - break; - default: -#ifdef RETINACOLORDEBUG - std::cerr<<"RetinaColor::No or wrong color sampling method, skeeping"< &multiplexedColorFrame, const bool adaptiveFiltering, const float maxInputValue) -{ - // demultiplex the grey frame to RGB frame - // -> first set demultiplexed frame to 0 - _demultiplexedTempBuffer=0; - // -> demultiplex process - register unsigned int *colorSamplingPRT=&_colorSampling[0]; - register const float *multiplexedColorFramePtr=get_data(multiplexedColorFrame); - for (unsigned int indexa=0; indexa<_filterOutput.getNBpixels() ; ++indexa) - _demultiplexedTempBuffer[*(colorSamplingPRT++)]=*(multiplexedColorFramePtr++); - - // interpolate the demultiplexed frame depending on the color sampling method - if (!adaptiveFiltering) - _interpolateImageDemultiplexedImage(&_demultiplexedTempBuffer[0]); - - // low pass filtering the demultiplexed frame - _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0], &_chrominance[0]); - _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getNBpixels(), &_chrominance[0]+_filterOutput.getNBpixels()); - _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getDoubleNBpixels(), &_chrominance[0]+_filterOutput.getDoubleNBpixels()); - - /*if (_samplingMethod=BAYER) - { - _applyRIFfilter(_chrominance, _chrominance); - _applyRIFfilter(_chrominance+_filterOutput.getNBpixels(), _chrominance+_filterOutput.getNBpixels()); - _applyRIFfilter(_chrominance+_filterOutput.getDoubleNBpixels(), _chrominance+_filterOutput.getDoubleNBpixels()); - }*/ - - // normalize by the photoreceptors local density and retrieve the local luminance - register float *chrominancePTR= &_chrominance[0]; - register float *colorLocalDensityPTR= &_colorLocalDensity[0]; - register float *luminance= &(*_luminance)[0]; - if (!adaptiveFiltering)// compute the gradient on the luminance - { - if (_samplingMethod==RETINA_COLOR_RANDOM) - for (unsigned int indexc=0; indexc<_filterOutput.getNBpixels() ; ++indexc, ++chrominancePTR, ++colorLocalDensityPTR, ++luminance) - { - // normalize by photoreceptors density - float Cr=*(chrominancePTR)*_colorLocalDensity[indexc]; - float Cg=*(chrominancePTR+_filterOutput.getNBpixels())*_colorLocalDensity[indexc+_filterOutput.getNBpixels()]; - float Cb=*(chrominancePTR+_filterOutput.getDoubleNBpixels())*_colorLocalDensity[indexc+_filterOutput.getDoubleNBpixels()]; - *luminance=(Cr+Cg+Cb)*_pG; - *(chrominancePTR)=Cr-*luminance; - *(chrominancePTR+_filterOutput.getNBpixels())=Cg-*luminance; - *(chrominancePTR+_filterOutput.getDoubleNBpixels())=Cb-*luminance; - } - else - for (unsigned int indexc=0; indexc<_filterOutput.getNBpixels() ; ++indexc, ++chrominancePTR, ++colorLocalDensityPTR, ++luminance) - { - float Cr=*(chrominancePTR); - float Cg=*(chrominancePTR+_filterOutput.getNBpixels()); - float Cb=*(chrominancePTR+_filterOutput.getDoubleNBpixels()); - *luminance=_pR*Cr+_pG*Cg+_pB*Cb; - *(chrominancePTR)=Cr-*luminance; - *(chrominancePTR+_filterOutput.getNBpixels())=Cg-*luminance; - *(chrominancePTR+_filterOutput.getDoubleNBpixels())=Cb-*luminance; - } - - // in order to get the color image, each colored map needs to be added the luminance - // -> to do so, compute: multiplexedColorFrame - remultiplexed chrominances - runColorMultiplexing(_chrominance, _tempMultiplexedFrame); - //lum = 1/3((f*(ImR))/(f*mR) + (f*(ImG))/(f*mG) + (f*(ImB))/(f*mB)); - float *luminancePTR= &(*_luminance)[0]; - chrominancePTR= &_chrominance[0]; - float *demultiplexedColorFramePTR= &_demultiplexedColorFrame[0]; - for (unsigned int indexp=0; indexp<_filterOutput.getNBpixels() ; ++indexp, ++luminancePTR, ++chrominancePTR, ++demultiplexedColorFramePTR) - { - *luminancePTR=(multiplexedColorFrame[indexp]-_tempMultiplexedFrame[indexp]); - *(demultiplexedColorFramePTR)=*(chrominancePTR)+*luminancePTR; - *(demultiplexedColorFramePTR+_filterOutput.getNBpixels())=*(chrominancePTR+_filterOutput.getNBpixels())+*luminancePTR; - *(demultiplexedColorFramePTR+_filterOutput.getDoubleNBpixels())=*(chrominancePTR+_filterOutput.getDoubleNBpixels())+*luminancePTR; - } - - }else - { - register const float *multiplexedColorFramePTR= get_data(multiplexedColorFrame); - for (unsigned int indexc=0; indexc<_filterOutput.getNBpixels() ; ++indexc, ++chrominancePTR, ++colorLocalDensityPTR, ++luminance, ++multiplexedColorFramePTR) - { - // normalize by photoreceptors density - float Cr=*(chrominancePTR)*_colorLocalDensity[indexc]; - float Cg=*(chrominancePTR+_filterOutput.getNBpixels())*_colorLocalDensity[indexc+_filterOutput.getNBpixels()]; - float Cb=*(chrominancePTR+_filterOutput.getDoubleNBpixels())*_colorLocalDensity[indexc+_filterOutput.getDoubleNBpixels()]; - *luminance=(Cr+Cg+Cb)*_pG; - _demultiplexedTempBuffer[_colorSampling[indexc]] = *multiplexedColorFramePTR - *luminance; - - } - - // compute the gradient of the luminance -#ifdef MAKE_PARALLEL // call the TemplateBuffer TBB clipping method - cv::parallel_for_(cv::Range(2,_filterOutput.getNBrows()-2), Parallel_computeGradient(_filterOutput.getNBcolumns(), _filterOutput.getNBrows(), &(*_luminance)[0], &_imageGradient[0])); -#else - _computeGradient(&(*_luminance)[0]); -#endif - // adaptively filter the submosaics to get the adaptive densities, here the buffer _chrominance is used as a temp buffer - _adaptiveSpatialLPfilter(&_RGBmosaic[0], &_chrominance[0]); - _adaptiveSpatialLPfilter(&_RGBmosaic[0]+_filterOutput.getNBpixels(), &_chrominance[0]+_filterOutput.getNBpixels()); - _adaptiveSpatialLPfilter(&_RGBmosaic[0]+_filterOutput.getDoubleNBpixels(), &_chrominance[0]+_filterOutput.getDoubleNBpixels()); - - _adaptiveSpatialLPfilter(&_demultiplexedTempBuffer[0], &_demultiplexedColorFrame[0]); - _adaptiveSpatialLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getNBpixels(), &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels()); - _adaptiveSpatialLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getDoubleNBpixels(), &_demultiplexedColorFrame[0]+_filterOutput.getDoubleNBpixels()); - -/* for (unsigned int index=0; index<_filterOutput.getNBpixels()*3 ; ++index) // cette boucle pourrait �tre supprimee en passant la densit� � la fonction de filtrage - _demultiplexedColorFrame[index] /= _chrominance[index];*/ - _demultiplexedColorFrame/=_chrominance; // more optimal ;o) - - // compute and substract the residual luminance - for (unsigned int index=0; index<_filterOutput.getNBpixels() ; ++index) - { - float residu = _pR*_demultiplexedColorFrame[index] + _pG*_demultiplexedColorFrame[index+_filterOutput.getNBpixels()] + _pB*_demultiplexedColorFrame[index+_filterOutput.getDoubleNBpixels()]; - _demultiplexedColorFrame[index] = _demultiplexedColorFrame[index] - residu; - _demultiplexedColorFrame[index+_filterOutput.getNBpixels()] = _demultiplexedColorFrame[index+_filterOutput.getNBpixels()] - residu; - _demultiplexedColorFrame[index+_filterOutput.getDoubleNBpixels()] = _demultiplexedColorFrame[index+_filterOutput.getDoubleNBpixels()] - residu; - } - - // multiplex the obtained chrominance - runColorMultiplexing(_demultiplexedColorFrame, _tempMultiplexedFrame); - _demultiplexedTempBuffer=0; - - // get the luminance, et and add it to each chrominance - for (unsigned int index=0; index<_filterOutput.getNBpixels() ; ++index) - { - (*_luminance)[index]=multiplexedColorFrame[index]-_tempMultiplexedFrame[index]; - _demultiplexedTempBuffer[_colorSampling[index]] = _demultiplexedColorFrame[_colorSampling[index]];//multiplexedColorFrame[index] - (*_luminance)[index]; - } - - _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0], &_demultiplexedTempBuffer[0]); - _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getNBpixels(), &_demultiplexedTempBuffer[0]+_filterOutput.getNBpixels()); - _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getDoubleNBpixels(), &_demultiplexedTempBuffer[0]+_filterOutput.getDoubleNBpixels()); - - // get the luminance and add it to each chrominance - for (unsigned int index=0; index<_filterOutput.getNBpixels() ; ++index) - { - _demultiplexedColorFrame[index] = _demultiplexedTempBuffer[index]*_colorLocalDensity[index]+ (*_luminance)[index]; - _demultiplexedColorFrame[index+_filterOutput.getNBpixels()] = _demultiplexedTempBuffer[index+_filterOutput.getNBpixels()]*_colorLocalDensity[index+_filterOutput.getNBpixels()]+ (*_luminance)[index]; - _demultiplexedColorFrame[index+_filterOutput.getDoubleNBpixels()] = _demultiplexedTempBuffer[index+_filterOutput.getDoubleNBpixels()]*_colorLocalDensity[index+_filterOutput.getDoubleNBpixels()]+ (*_luminance)[index]; - } - } - - // eliminate saturated colors by simple clipping values to the input range - clipRGBOutput_0_maxInputValue(NULL, maxInputValue); - - /* transfert image gradient in order to check validity - memcpy((*_luminance), _imageGradient, sizeof(float)*_filterOutput.getNBpixels()); - memcpy(_demultiplexedColorFrame, _imageGradient+_filterOutput.getNBpixels(), sizeof(float)*_filterOutput.getNBpixels()); - memcpy(_demultiplexedColorFrame+_filterOutput.getNBpixels(), _imageGradient+_filterOutput.getNBpixels(), sizeof(float)*_filterOutput.getNBpixels()); - memcpy(_demultiplexedColorFrame+2*_filterOutput.getNBpixels(), _imageGradient+_filterOutput.getNBpixels(), sizeof(float)*_filterOutput.getNBpixels()); - */ - - if (_saturateColors) - { - TemplateBuffer::normalizeGrayOutputCentredSigmoide(128, _colorSaturationValue, maxInputValue, &_demultiplexedColorFrame[0], &_demultiplexedColorFrame[0], _filterOutput.getNBpixels()); - TemplateBuffer::normalizeGrayOutputCentredSigmoide(128, _colorSaturationValue, maxInputValue, &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels(), &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels(), _filterOutput.getNBpixels()); - TemplateBuffer::normalizeGrayOutputCentredSigmoide(128, _colorSaturationValue, maxInputValue, &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels()*2, &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels()*2, _filterOutput.getNBpixels()); - } -} - -// color multiplexing: input frame size=_NBrows*_filterOutput.getNBcolumns()*3, multiplexedFrame output size=_NBrows*_filterOutput.getNBcolumns() -void RetinaColor::runColorMultiplexing(const std::valarray &demultiplexedInputFrame, std::valarray &multiplexedFrame) -{ - // multiply each color layer by its bayer mask - register unsigned int *colorSamplingPTR= &_colorSampling[0]; - register float *multiplexedFramePTR= &multiplexedFrame[0]; - for (unsigned int indexp=0; indexp<_filterOutput.getNBpixels(); ++indexp) - *(multiplexedFramePTR++)=demultiplexedInputFrame[*(colorSamplingPTR++)]; -} - -void RetinaColor::normalizeRGBOutput_0_maxOutputValue(const float maxOutputValue) -{ - //normalizeGrayOutputCentredSigmoide(0.0, 2, _chrominance); - TemplateBuffer::normalizeGrayOutput_0_maxOutputValue(&_demultiplexedColorFrame[0], 3*_filterOutput.getNBpixels(), maxOutputValue); - //normalizeGrayOutputCentredSigmoide(0.0, 2, _chrominance+_filterOutput.getNBpixels()); - //normalizeGrayOutput_0_maxOutputValue(_demultiplexedColorFrame+_filterOutput.getNBpixels(), _filterOutput.getNBpixels(), maxOutputValue); - //normalizeGrayOutputCentredSigmoide(0.0, 2, _chrominance+2*_filterOutput.getNBpixels()); - //normalizeGrayOutput_0_maxOutputValue(_demultiplexedColorFrame+_filterOutput.getDoubleNBpixels(), _filterOutput.getNBpixels(), maxOutputValue); - TemplateBuffer::normalizeGrayOutput_0_maxOutputValue(&(*_luminance)[0], _filterOutput.getNBpixels(), maxOutputValue); -} - -/// normalize output between 0 and maxOutputValue; -void RetinaColor::clipRGBOutput_0_maxInputValue(float *inputOutputBuffer, const float maxInputValue) -{ - //std::cout<<"RetinaColor::normalizing RGB frame..."<(inputOutputBuffer, 0, maxInputValue)); -#else - register float *inputOutputBufferPTR=inputOutputBuffer; - for (register unsigned int jf = 0; jf < _filterOutput.getNBpixels()*3; ++jf, ++inputOutputBufferPTR) - { - if (*inputOutputBufferPTR>maxInputValue) - *inputOutputBufferPTR=maxInputValue; - else if (*inputOutputBufferPTR<0) - *inputOutputBufferPTR=0; - } -#endif - //std::cout<<"RetinaColor::...normalizing RGB frame OK"<maxValue) - maxValue=outputFrame[index]; - } - } - normalisationFactor=1.f/maxValue; - // normalisation [0, 1] - for (unsigned int indexp=1 ; indexp<_filterOutput.getNBrows()-1; ++indexp) - outputFrame[indexp]=outputFrame[indexp]*normalisationFactor; -} - -////////////////////////////////////////////////////////// -// ADAPTIVE BASIC RETINA FILTER -////////////////////////////////////////////////////////// -// run LP filter for a new frame input and save result at a specific output adress -void RetinaColor::_adaptiveSpatialLPfilter(const float *inputFrame, float *outputFrame) -{ - - /**********/ - _gain = (1-0.57f)*(1-0.57f)*(1-0.06f)*(1-0.06f); - - // launch the serie of 1D directional filters in order to compute the 2D low pass filter - // -> horizontal filters work with the first layer of imageGradient - _adaptiveHorizontalCausalFilter_addInput(inputFrame, outputFrame, 0, _filterOutput.getNBrows()); - _horizontalAnticausalFilter_Irregular(outputFrame, 0, _filterOutput.getNBrows(), &_imageGradient[0]); - // -> horizontal filters work with the second layer of imageGradient - _verticalCausalFilter_Irregular(outputFrame, 0, _filterOutput.getNBcolumns(), &_imageGradient[0]+_filterOutput.getNBpixels()); - _adaptiveVerticalAnticausalFilter_multGain(outputFrame, 0, _filterOutput.getNBcolumns()); -} - -// horizontal causal filter which adds the input inside... replaces the parent _horizontalCausalFilter_Irregular_addInput by avoiding a product for each pixel -void RetinaColor::_adaptiveHorizontalCausalFilter_addInput(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd) -{ -#ifdef MAKE_PARALLEL - cv::parallel_for_(cv::Range(IDrowStart,IDrowEnd), Parallel_adaptiveHorizontalCausalFilter_addInput(inputFrame, outputFrame, &_imageGradient[0], _filterOutput.getNBcolumns())); -#else - register float* outputPTR=outputFrame+IDrowStart*_filterOutput.getNBcolumns(); - register const float* inputPTR=inputFrame+IDrowStart*_filterOutput.getNBcolumns(); - register const float *imageGradientPTR= &_imageGradient[0]+IDrowStart*_filterOutput.getNBcolumns(); - for (unsigned int IDrow=IDrowStart; IDrow &result) -{ - bool processSuccess=true; - // basic preliminary error check - if (result.size()!=_demultiplexedColorFrame.size()) - { - std::cerr<<"RetinaColor::applyKrauskopfLMS2Acr1cr2Transform: input buffer does not match retina buffer size, conversion aborted"< &result) -{ - bool processSuccess=true; - // basic preliminary error check - if (result.size()!=_demultiplexedColorFrame.size()) - { - std::cerr<<"RetinaColor::applyKrauskopfLMS2Acr1cr2Transform: input buffer does not match retina buffer size, conversion aborted"< &inputFrameBuffer, std::valarray &outputFrameBuffer, const float *transformTable) -{ - // two step methods in order to allow inputFrame and outputFrame to be the same - unsigned int nbPixels=(unsigned int)(inputFrameBuffer.size()/3), dbpixels=(unsigned int)(2*inputFrameBuffer.size()/3); - - const float *inputFrame=get_data(inputFrameBuffer); - float *outputFrame= &outputFrameBuffer[0]; - - for (unsigned int dataIndex=0; dataIndex B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. -** ====> more informations in the above cited Jeanny Heraults's book. -** -** License Agreement -** For Open Source Computer Vision Library -** -** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** -** For Human Visual System tools (bioinspired) -** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions 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. -*******************************************************************************/ - -/** -* @class RetinaColor a color multilexing/demultiplexing (demosaicing) based on a human vision inspiration. Different mosaicing strategies can be used, included random sampling ! -* => please take a look at the nice and efficient demosaicing strategy introduced by B.Chaix de Lavarene, take a look at the cited paper for more mathematical details -* @brief Retina color sampling model which allows classical bayer sampling, random and potentially several other method ! Low color errors on corners ! -* -> Based on the research of: -* .Brice Chaix Lavarene (chaix@lis.inpg.fr) -* .Jeanny Herault (herault@lis.inpg.fr) -* .David Alleyson (david.alleyson@upmf-grenoble.fr) -* .collaboration: alexandre benoit (benoit.alexandre.vision@gmail.com or benoit@lis.inpg.fr) -* Please cite: B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -* @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC / Gipsa-Lab, France: www.gipsa-lab.inpg.fr/ -* Creation date 2007 -*/ - -#ifndef RETINACOLOR_HPP_ -#define RETINACOLOR_HPP_ - -#include "basicretinafilter.hpp" - -//#define __RETINACOLORDEBUG //define RETINACOLORDEBUG in order to display debug data - -namespace cv -{ -namespace bioinspired -{ - class RetinaColor: public BasicRetinaFilter - { - public: - /** - * @typedef which allows to select the type of photoreceptors color sampling - */ - - /** - * constructor of the retina color processing model - * @param NBrows: number of rows of the input image - * @param NBcolumns: number of columns of the input image - * @param samplingMethod: the chosen color sampling method - */ - RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns, const int samplingMethod=RETINA_COLOR_BAYER); - - /** - * standard destructor - */ - virtual ~RetinaColor(); - - /** - * function that clears all buffers of the object - */ - void clearAllBuffers(); - - /** - * resize retina color filter object (resize all allocated buffers) - * @param NBrows: the new height size - * @param NBcolumns: the new width size - */ - void resize(const unsigned int NBrows, const unsigned int NBcolumns); - - - /** - * color multiplexing function: a demultiplexed RGB frame of size M*N*3 is transformed into a multiplexed M*N*1 pixels frame where each pixel is either Red, or Green or Blue - * @param inputRGBFrame: the input RGB frame to be processed - * @return, nothing but the multiplexed frame is available by the use of the getMultiplexedFrame() function - */ - inline void runColorMultiplexing(const std::valarray &inputRGBFrame) { runColorMultiplexing(inputRGBFrame, *_multiplexedFrame); } - - /** - * color multiplexing function: a demultipleed RGB frame of size M*N*3 is transformed into a multiplexed M*N*1 pixels frame where each pixel is either Red, or Green or Blue if using RGB images - * @param demultiplexedInputFrame: the demultiplexed input frame to be processed of size M*N*3 - * @param multiplexedFrame: the resulting multiplexed frame - */ - void runColorMultiplexing(const std::valarray &demultiplexedInputFrame, std::valarray &multiplexedFrame); - - /** - * color demultiplexing function: a multiplexed frame of size M*N*1 pixels is transformed into a RGB demultiplexed M*N*3 pixels frame - * @param multiplexedColorFrame: the input multiplexed frame to be processed - * @param adaptiveFiltering: specifies if an adaptive filtering has to be perform rather than standard filtering (adaptive filtering allows a better rendering) - * @param maxInputValue: the maximum input data value (should be 255 for 8 bits images but it can change in the case of High Dynamic Range Images (HDRI) - * @return, nothing but the output demultiplexed frame is available by the use of the getDemultiplexedColorFrame() function, also use getLuminance() and getChrominance() in order to retreive either luminance or chrominance - */ - void runColorDemultiplexing(const std::valarray &multiplexedColorFrame, const bool adaptiveFiltering=false, const float maxInputValue=255.0); - - /** - * activate color saturation as the final step of the color demultiplexing process - * -> this saturation is a sigmoide function applied to each channel of the demultiplexed image. - * @param saturateColors: boolean that activates color saturation (if true) or desactivate (if false) - * @param colorSaturationValue: the saturation factor - * */ - void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0) { _saturateColors=saturateColors; _colorSaturationValue=colorSaturationValue; } - - /** - * set parameters of the low pass spatio-temporal filter used to retreive the low chrominance - * @param beta: gain of the filter (generally set to zero) - * @param tau: time constant of the filter (unit is frame for video processing), typically 0 when considering static processing, 1 or more if a temporal smoothing effect is required - * @param k: spatial constant of the filter (unit is pixels), typical value is 2.5 - */ - void setChrominanceLPfilterParameters(const float beta, const float tau, const float k) { setLPfilterParameters(beta, tau, k); } - - /** - * apply to the retina color output the Krauskopf transformation which leads to an opponent color system: output colorspace if Acr1cr2 if input of the retina was LMS color space - * @param result: the input buffer to fill with the transformed colorspace retina output - * @return true if process ended successfully - */ - bool applyKrauskopfLMS2Acr1cr2Transform(std::valarray &result); - - /** - * apply to the retina color output the CIE Lab color transformation - * @param result: the input buffer to fill with the transformed colorspace retina output - * @return true if process ended successfully - */ - bool applyLMS2LabTransform(std::valarray &result); - - /** - * @return the multiplexed frame result (use this after function runColorMultiplexing) - */ - inline const std::valarray &getMultiplexedFrame() const { return *_multiplexedFrame; } - - /** - * @return the demultiplexed frame result (use this after function runColorDemultiplexing) - */ - inline const std::valarray &getDemultiplexedColorFrame() const { return _demultiplexedColorFrame; } - - /** - * @return the luminance of the processed frame (use this after function runColorDemultiplexing) - */ - inline const std::valarray &getLuminance() const { return *_luminance; } - - /** - * @return the chrominance of the processed frame (use this after function runColorDemultiplexing) - */ - inline const std::valarray &getChrominance() const { return _chrominance; } - - /** - * standard 0 to 255 image clipping function appled to RGB images (of size M*N*3 pixels) - * @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized - * @param maxOutputValue: the maximum value allowed at the output (values superior to it would be clipped - */ - void clipRGBOutput_0_maxInputValue(float *inputOutputBuffer, const float maxOutputValue=255.0); - - /** - * standard 0 to 255 image normalization function appled to RGB images (of size M*N*3 pixels) - * @param maxOutputValue: the maximum value allowed at the output (values superior to it would be clipped - */ - void normalizeRGBOutput_0_maxOutputValue(const float maxOutputValue=255.0); - - /** - * return the color sampling map: a Nrows*Mcolumns image in which each pixel value is the ofsset adress which gives the adress of the sampled pixel on an Nrows*Mcolumns*3 color image ordered by layers: layer1, layer2, layer3 - */ - inline const std::valarray &getSamplingMap() const { return _colorSampling; } - - /** - * function used (to bypass processing) to manually set the color output - * @param demultiplexedImage: the color image (luminance+chrominance) which has to be written in the object buffer - */ - inline void setDemultiplexedColorFrame(const std::valarray &demultiplexedImage) { _demultiplexedColorFrame=demultiplexedImage; } - - protected: - - // private functions - int _samplingMethod; - bool _saturateColors; - float _colorSaturationValue; - // links to parent buffers (more convienient names - TemplateBuffer *_luminance; - std::valarray *_multiplexedFrame; - // instance buffers - std::valarray _colorSampling; // table (size (_nbRows*_nbColumns) which specifies the color of each pixel - std::valarray _RGBmosaic; - std::valarray _tempMultiplexedFrame; - std::valarray _demultiplexedTempBuffer; - std::valarray _demultiplexedColorFrame; - std::valarray _chrominance; - std::valarray _colorLocalDensity;// buffer which contains the local density of the R, G and B photoreceptors for a normalization use - std::valarray _imageGradient; - - // variables - float _pR, _pG, _pB; // probabilities of color R, G and B - bool _objectInit; - - // protected functions - void _initColorSampling(); - void _interpolateImageDemultiplexedImage(float *inputOutputBuffer); - void _interpolateSingleChannelImage111(float *inputOutputBuffer); - void _interpolateBayerRGBchannels(float *inputOutputBuffer); - void _applyRIFfilter(const float *sourceBuffer, float *destinationBuffer); - void _getNormalizedContoursImage(const float *inputFrame, float *outputFrame); - // -> special adaptive filters dedicated to low pass filtering on the chrominance (skeeps filtering on the edges) - void _adaptiveSpatialLPfilter(const float *inputFrame, float *outputFrame); - void _adaptiveHorizontalCausalFilter_addInput(const float *inputFrame, float *outputFrame, const unsigned int IDrowStart, const unsigned int IDrowEnd); // TBB parallelized - void _adaptiveVerticalAnticausalFilter_multGain(float *outputFrame, const unsigned int IDcolumnStart, const unsigned int IDcolumnEnd); - void _computeGradient(const float *luminance); - void _normalizeOutputs_0_maxOutputValue(void); - - // color space transform - void _applyImageColorSpaceConversion(const std::valarray &inputFrame, std::valarray &outputFrame, const float *transformTable); - -#ifdef MAKE_PARALLEL - /****************************************************** - ** IF some parallelizing thread methods are available, then, main loops are parallelized using these functors - ** ==> main idea paralellise main filters loops, then, only the most used methods are parallelized... TODO : increase the number of parallelised methods as necessary - ** ==> functors names = Parallel_$$$ where $$$= the name of the serial method that is parallelised - ** ==> functors constructors can differ from the parameters used with their related serial functions - */ - - /* Template : - class Parallel_ : public cv::ParallelLoopBody - { - private: - - public: - Parallel_() - : {} - - virtual void operator()( const cv::Range& r ) const { - - } - }: - */ - class Parallel_adaptiveHorizontalCausalFilter_addInput: public cv::ParallelLoopBody - { - private: - float *outputFrame; - const float *inputFrame, *imageGradient; - unsigned int nbColumns; - public: - Parallel_adaptiveHorizontalCausalFilter_addInput(const float *inputImg, float *bufferToProcess, const float *imageGrad, const unsigned int nbCols) - :outputFrame(bufferToProcess), inputFrame(inputImg), imageGradient(imageGrad), nbColumns(nbCols) { } - - virtual void operator()( const Range& r ) const - { - register float* outputPTR=outputFrame+r.start*nbColumns; - register const float* inputPTR=inputFrame+r.start*nbColumns; - register const float *imageGradientPTR= imageGradient+r.start*nbColumns; - for (int IDrow=r.start; IDrow!=r.end; ++IDrow) - { - register float result=0; - for (unsigned int index=0; index Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 - ** - ** - ** License Agreement - ** For Open Source Computer Vision Library - ** - ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. - ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. - ** - ** For Human Visual System tools (bioinspired) - ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: - ** - ** * Redistributions of source code must retain the above copyright notice, - ** this list of conditions and the following disclaimer. - ** - ** * Redistributions 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. - *******************************************************************************/ - -/* - * retinafasttonemapping.cpp - * - * Created on: May 26, 2013 - * Author: Alexandre Benoit - */ - -#include "precomp.hpp" -#include "basicretinafilter.hpp" -#include "retinacolor.hpp" -#include -#include -#include - -namespace cv -{ -namespace bioinspired -{ -/** - * @class RetinaFastToneMappingImpl a wrapper class which allows the tone mapping algorithm of Meylan&al(2007) to be used with OpenCV. - * This algorithm is already implemented in thre Retina class (retina::applyFastToneMapping) but used it does not require all the retina model to be allocated. This allows a light memory use for low memory devices (smartphones, etc. - * As a summary, these are the model properties: - * => 2 stages of local luminance adaptation with a different local neighborhood for each. - * => first stage models the retina photorecetors local luminance adaptation - * => second stage models th ganglion cells local information adaptation - * => compared to the initial publication, this class uses spatio-temporal low pass filters instead of spatial only filters. - * ====> this can help noise robustness and temporal stability for video sequence use cases. - * for more information, read to the following papers : - * Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 - * regarding spatio-temporal filter and the bigger retina model : - * Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. - */ - -class RetinaFastToneMappingImpl : public RetinaFastToneMapping -{ -public: - /** - * constructor - * @param imageInput: the size of the images to process - */ - RetinaFastToneMappingImpl(Size imageInput) - { - unsigned int nbPixels=imageInput.height*imageInput.width; - - // basic error check - if (nbPixels <= 0) - throw cv::Exception(-1, "Bad retina size setup : size height and with must be superior to zero", "RetinaImpl::setup", "retinafasttonemapping.cpp", 0); - - // resize buffers - _inputBuffer.resize(nbPixels*3); // buffer supports gray images but also 3 channels color buffers... (larger is better...) - _imageOutput.resize(nbPixels*3); - _temp2.resize(nbPixels); - // allocate the main filter with 2 setup sets properties (one for each low pass filter - _multiuseFilter = makePtr(imageInput.height, imageInput.width, 2); - // allocate the color manager (multiplexer/demultiplexer - _colorEngine = makePtr(imageInput.height, imageInput.width); - // setup filter behaviors with default values - setup(); - } - - /** - * basic destructor - */ - virtual ~RetinaFastToneMappingImpl() { } - - /** - * method that applies a luminance correction (initially High Dynamic Range (HDR) tone mapping) using only the 2 local adaptation stages of the retina parvocellular channel : photoreceptors level and ganlion cells level. Spatio temporal filtering is applied but limited to temporal smoothing and eventually high frequencies attenuation. This is a lighter method than the one available using the regular retina::run method. It is then faster but it does not include complete temporal filtering nor retina spectral whitening. Then, it can have a more limited effect on images with a very high dynamic range. This is an adptation of the original still image HDR tone mapping algorithm of David Alleyson, Sabine Susstruck and Laurence Meylan's work, please cite: - * -> Meylan L., Alleysson D., and Susstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N 9, September, 1st, 2007, pp. 2807-2816 - @param inputImage the input image to process RGB or gray levels - @param outputToneMappedImage the output tone mapped image - */ - virtual void applyFastToneMapping(InputArray inputImage, OutputArray outputToneMappedImage) - { - // first convert input image to the compatible format : - const bool colorMode = _convertCvMat2ValarrayBuffer(inputImage.getMat(), _inputBuffer); - - // process tone mapping - if (colorMode) - { - _runRGBToneMapping(_inputBuffer, _imageOutput, true); - _convertValarrayBuffer2cvMat(_imageOutput, _multiuseFilter->getNBrows(), _multiuseFilter->getNBcolumns(), true, outputToneMappedImage); - } - else - { - _runGrayToneMapping(_inputBuffer, _imageOutput); - _convertValarrayBuffer2cvMat(_imageOutput, _multiuseFilter->getNBrows(), _multiuseFilter->getNBcolumns(), false, outputToneMappedImage); - } - - } - - /** - * setup method that updates tone mapping behaviors by adjusing the local luminance computation area - * @param photoreceptorsNeighborhoodRadius the first stage local adaptation area - * @param ganglioncellsNeighborhoodRadius the second stage local adaptation area - * @param meanLuminanceModulatorK the factor applied to modulate the meanLuminance information (default is 1, see reference paper) - */ - virtual void setup(const float photoreceptorsNeighborhoodRadius=3.f, const float ganglioncellsNeighborhoodRadius=1.f, const float meanLuminanceModulatorK=1.f) - { - // setup the spatio-temporal properties of each filter - _meanLuminanceModulatorK = meanLuminanceModulatorK; - _multiuseFilter->setV0CompressionParameter(1.f, 255.f, 128.f); - _multiuseFilter->setLPfilterParameters(0.f, 0.f, photoreceptorsNeighborhoodRadius, 1); - _multiuseFilter->setLPfilterParameters(0.f, 0.f, ganglioncellsNeighborhoodRadius, 2); - } - -private: - // a filter able to perform local adaptation and low pass spatio-temporal filtering - cv::Ptr _multiuseFilter; - cv::Ptr _colorEngine; - - //!< buffer used to convert input cv::Mat to internal retina buffers format (valarrays) - std::valarray _inputBuffer; - std::valarray _imageOutput; - std::valarray _temp2; - float _meanLuminanceModulatorK; - - -void _convertValarrayBuffer2cvMat(const std::valarray &grayMatrixToConvert, const unsigned int nbRows, const unsigned int nbColumns, const bool colorMode, OutputArray outBuffer) -{ - // fill output buffer with the valarray buffer - const float *valarrayPTR=get_data(grayMatrixToConvert); - if (!colorMode) - { - outBuffer.create(cv::Size(nbColumns, nbRows), CV_8U); - Mat outMat = outBuffer.getMat(); - for (unsigned int i=0;i(pixel)=(unsigned char)*(valarrayPTR++); - } - } - } - else - { - const unsigned int nbPixels=nbColumns*nbRows; - const unsigned int doubleNBpixels=nbColumns*nbRows*2; - outBuffer.create(cv::Size(nbColumns, nbRows), CV_8UC3); - Mat outMat = outBuffer.getMat(); - for (unsigned int i=0;i(pixel)=pixelValues; - } - } - } -} - -bool _convertCvMat2ValarrayBuffer(InputArray inputMat, std::valarray &outputValarrayMatrix) -{ - const Mat inputMatToConvert=inputMat.getMat(); - // first check input consistency - if (inputMatToConvert.empty()) - throw cv::Exception(-1, "RetinaImpl cannot be applied, input buffer is empty", "RetinaImpl::run", "RetinaImpl.h", 0); - - // retreive color mode from image input - int imageNumberOfChannels = inputMatToConvert.channels(); - - // convert to float AND fill the valarray buffer - typedef float T; // define here the target pixel format, here, float - const int dsttype = DataType::depth; // output buffer is float format - - const unsigned int nbPixels=inputMat.getMat().rows*inputMat.getMat().cols; - const unsigned int doubleNBpixels=inputMat.getMat().rows*inputMat.getMat().cols*2; - - if(imageNumberOfChannels==4) - { - // create a cv::Mat table (for RGBA planes) - cv::Mat planes[4] = - { - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[doubleNBpixels]), - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[nbPixels]), - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]) - }; - planes[3] = cv::Mat(inputMatToConvert.size(), dsttype); // last channel (alpha) does not point on the valarray (not usefull in our case) - // split color cv::Mat in 4 planes... it fills valarray directely - cv::split(Mat_ >(inputMatToConvert), planes); - } - else if (imageNumberOfChannels==3) - { - // create a cv::Mat table (for RGB planes) - cv::Mat planes[] = - { - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[doubleNBpixels]), - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[nbPixels]), - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]) - }; - // split color cv::Mat in 3 planes... it fills valarray directely - cv::split(cv::Mat_ >(inputMatToConvert), planes); - } - else if(imageNumberOfChannels==1) - { - // create a cv::Mat header for the valarray - cv::Mat dst(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[0]); - inputMatToConvert.convertTo(dst, dsttype); - } - else - CV_Error(Error::StsUnsupportedFormat, "input image must be single channel (gray levels), bgr format (color) or bgra (color with transparency which won't be considered"); - - return imageNumberOfChannels>1; // return bool : false for gray level image processing, true for color mode -} - - -// run the initilized retina filter in order to perform gray image tone mapping, after this call all retina outputs are updated -void _runGrayToneMapping(const std::valarray &grayImageInput, std::valarray &grayImageOutput) -{ - // apply tone mapping on the multiplexed image - // -> photoreceptors local adaptation (large area adaptation) - _multiuseFilter->runFilter_LPfilter(grayImageInput, grayImageOutput, 0); // compute low pass filtering modeling the horizontal cells filtering to acess local luminance - _multiuseFilter->setV0CompressionParameterToneMapping(1.f, grayImageOutput.max(), _meanLuminanceModulatorK*grayImageOutput.sum()/(float)_multiuseFilter->getNBpixels()); - _multiuseFilter->runFilter_LocalAdapdation(grayImageInput, grayImageOutput, _temp2); // adapt contrast to local luminance - - // -> ganglion cells local adaptation (short area adaptation) - _multiuseFilter->runFilter_LPfilter(_temp2, grayImageOutput, 1); // compute low pass filtering (high cut frequency (remove spatio-temporal noise) - _multiuseFilter->setV0CompressionParameterToneMapping(1.f, _temp2.max(), _meanLuminanceModulatorK*grayImageOutput.sum()/(float)_multiuseFilter->getNBpixels()); - _multiuseFilter->runFilter_LocalAdapdation(_temp2, grayImageOutput, grayImageOutput); // adapt contrast to local luminance - -} - -// run the initilized retina filter in order to perform color tone mapping, after this call all retina outputs are updated -void _runRGBToneMapping(const std::valarray &RGBimageInput, std::valarray &RGBimageOutput, const bool useAdaptiveFiltering) -{ - // multiplex the image with the color sampling method specified in the constructor - _colorEngine->runColorMultiplexing(RGBimageInput); - - // apply tone mapping on the multiplexed image - _runGrayToneMapping(_colorEngine->getMultiplexedFrame(), RGBimageOutput); - - // demultiplex tone maped image - _colorEngine->runColorDemultiplexing(RGBimageOutput, useAdaptiveFiltering, _multiuseFilter->getMaxInputValue());//_ColorEngine->getMultiplexedFrame());//_ParvoRetinaFilter->getPhotoreceptorsLPfilteringOutput()); - - // rescaling result between 0 and 255 - _colorEngine->normalizeRGBOutput_0_maxOutputValue(255.0); - - // return the result - RGBimageOutput=_colorEngine->getDemultiplexedColorFrame(); -} - -}; - -CV_EXPORTS Ptr createRetinaFastToneMapping(Size inputSize) -{ - return makePtr(inputSize); -} - -}// end of namespace bioinspired -}// end of namespace cv diff --git a/modules/bioinspired/src/retinafilter.cpp b/modules/bioinspired/src/retinafilter.cpp deleted file mode 100644 index e1e24c89b..000000000 --- a/modules/bioinspired/src/retinafilter.cpp +++ /dev/null @@ -1,526 +0,0 @@ -/*#****************************************************************************** -** 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. -** -** -** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. -** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. -** -** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) -** -** Creation - enhancement process 2007-2011 -** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France -** -** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). -** Refer to the following research paper for more information: -** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 -** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: -** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. -** -** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : -** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: -** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. -** ====> more informations in the above cited Jeanny Heraults's book. -** -** License Agreement -** For Open Source Computer Vision Library -** -** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** -** For Human Visual System tools (bioinspired) -** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions 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. -*******************************************************************************/ - -#include "precomp.hpp" - -#include "retinafilter.hpp" - -// @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC : www.listic.univ-savoie.fr, Gipsa-Lab, France: www.gipsa-lab.inpg.fr/ - -#include -#include - -namespace cv -{ -namespace bioinspired -{ - // standard constructor without any log sampling of the input frame - RetinaFilter::RetinaFilter(const unsigned int sizeRows, const unsigned int sizeColumns, const bool colorMode, const int samplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) - : - _retinaParvoMagnoMappedFrame(0), - _retinaParvoMagnoMapCoefTable(0), - _photoreceptorsPrefilter((1-(int)useRetinaLogSampling)*sizeRows+useRetinaLogSampling*ImageLogPolProjection::predictOutputSize(sizeRows, reductionFactor), (1-(int)useRetinaLogSampling)*sizeColumns+useRetinaLogSampling*ImageLogPolProjection::predictOutputSize(sizeColumns, reductionFactor), 4), - _ParvoRetinaFilter((1-(int)useRetinaLogSampling)*sizeRows+useRetinaLogSampling*ImageLogPolProjection::predictOutputSize(sizeRows, reductionFactor), (1-(int)useRetinaLogSampling)*sizeColumns+useRetinaLogSampling*ImageLogPolProjection::predictOutputSize(sizeColumns, reductionFactor)), - _MagnoRetinaFilter((1-(int)useRetinaLogSampling)*sizeRows+useRetinaLogSampling*ImageLogPolProjection::predictOutputSize(sizeRows, reductionFactor), (1-(int)useRetinaLogSampling)*sizeColumns+useRetinaLogSampling*ImageLogPolProjection::predictOutputSize(sizeColumns, reductionFactor)), - _colorEngine((1-(int)useRetinaLogSampling)*sizeRows+useRetinaLogSampling*ImageLogPolProjection::predictOutputSize(sizeRows, reductionFactor), (1-(int)useRetinaLogSampling)*sizeColumns+useRetinaLogSampling*ImageLogPolProjection::predictOutputSize(sizeColumns, reductionFactor), samplingMethod), - // configure retina photoreceptors log sampling... if necessary - _photoreceptorsLogSampling(NULL) - { - -#ifdef RETINADEBUG - std::cout<<"RetinaFilter::size( "<<_photoreceptorsPrefilter.getNBrows()<<", "<<_photoreceptorsPrefilter.getNBcolumns()<<")"<<" =? "<<_photoreceptorsPrefilter.getNBpixels()<initProjection(reductionFactor, samplingStrenght)) - { - std::cerr<<"RetinaFilter::Problem initializing photoreceptors log sampling, could not setup retina filter"<getNBrows()<<", "<<_photoreceptorsLogSampling->getNBcolumns()<<")"<<" =? "<<_photoreceptorsLogSampling->getNBpixels()<getNBrows()<<", "<getNBcolumns()<<")"<<_filterOutput.size()<<" =? "<<_filterOutput.getNBpixels()<clearAllBuffers(); - // stability controls value init - _setInitPeriodCount(); - } - - /** - * resize retina filter object (resize all allocated buffers - * @param NBrows: the new height size - * @param NBcolumns: the new width size - */ - void RetinaFilter::resize(const unsigned int NBrows, const unsigned int NBcolumns) - { - unsigned int rows=NBrows, cols=NBcolumns; - - // resize optionnal member and adjust other modules size if required - if (_photoreceptorsLogSampling) - { - _photoreceptorsLogSampling->resize(NBrows, NBcolumns); - rows=_photoreceptorsLogSampling->getOutputNBrows(); - cols=_photoreceptorsLogSampling->getOutputNBcolumns(); - } - - _photoreceptorsPrefilter.resize(rows, cols); - _ParvoRetinaFilter.resize(rows, cols); - _MagnoRetinaFilter.resize(rows, cols); - _colorEngine.resize(rows, cols); - - // reset parvo magno mapping - _createHybridTable(); - - // clean buffers - clearAllBuffers(); - - } - - // stability controls value init - void RetinaFilter::_setInitPeriodCount() - { - - // find out the maximum temporal constant value and apply a security factor - // false value (obviously too long) but appropriate for simple use - _globalTemporalConstant=(unsigned int)(_ParvoRetinaFilter.getPhotoreceptorsTemporalConstant()+_ParvoRetinaFilter.getHcellsTemporalConstant()+_MagnoRetinaFilter.getTemporalConstant()); - // reset frame counter - _ellapsedFramesSinceLastReset=0; - } - - void RetinaFilter::_createHybridTable() - { - // create hybrid output and related coefficient table - _retinaParvoMagnoMappedFrame.resize(_photoreceptorsPrefilter.getNBpixels()); - - _retinaParvoMagnoMapCoefTable.resize(_photoreceptorsPrefilter.getNBpixels()*2); - - // fill _hybridParvoMagnoCoefTable - int i, j, halfRows=_photoreceptorsPrefilter.getNBrows()/2, halfColumns=_photoreceptorsPrefilter.getNBcolumns()/2; - float *hybridParvoMagnoCoefTablePTR= &_retinaParvoMagnoMapCoefTable[0]; - float minDistance=MIN(halfRows, halfColumns)*0.7f; - for (i=0;i<(int)_photoreceptorsPrefilter.getNBrows();++i) - { - for (j=0;j<(int)_photoreceptorsPrefilter.getNBcolumns();++j) - { - float distanceToCenter=std::sqrt(((float)(i-halfRows)*(i-halfRows)+(j-halfColumns)*(j-halfColumns))); - if (distanceToCentersetV0CompressionParameter(0.6, maxInputValue, meanValue); // keeps log compression sensitivity parameter (usefull for the tone mapping function) - _ParvoRetinaFilter.setOPLandParvoFiltersParameters(0,OPLtemporalresponse1, OPLspatialResponse1, OPLassymetryGain, OPLtemporalresponse2, OPLspatialResponse2); - _ParvoRetinaFilter.setV0CompressionParameter(0.9f, maxInputValue, meanValue); - _MagnoRetinaFilter.setCoefficientsTable(LPfilterGain, LPfilterTemporalresponse, LPfilterSpatialResponse, MovingContoursExtractorCoefficient, 0, 2.0f*LPfilterSpatialResponse); - _MagnoRetinaFilter.setV0CompressionParameter(0.7f, maxInputValue, meanValue); - - // stability controls value init - _setInitPeriodCount(); - } - - bool RetinaFilter::checkInput(const std::valarray &input, const bool) - { - - BasicRetinaFilter *inputTarget=&_photoreceptorsPrefilter; - if (_photoreceptorsLogSampling) - inputTarget=_photoreceptorsLogSampling; - - bool test=input.size()==inputTarget->getNBpixels() || input.size()==(inputTarget->getNBpixels()*3) ; - if (!test) - { - std::cerr<<"RetinaFilter::checkInput: input buffer does not match retina buffer size, conversion aborted"< &bufferInput=checkInput(LMSimageInput, true); - if (!bufferInput) - return NULL; - - if (!_useColorMode) - std::cerr<<"RetinaFilter::Can not call tone mapping oeration if the retina filter was created for gray scale images"< lmsTempBuffer(LMSimageInput); - std::cout<<"RetinaFilter::--->min LMS value="<L - _spatiotemporalLPfilter(LMSimageInput, _filterOutput, 1); - setV0CompressionParameterToneMapping(PhotoreceptorsCompression, _maxInputValue, this->sum()/_NBpixels); - _localLuminanceAdaptation(LMSimageInput, _filterOutput, lmsTempBuffer.Buffer()); - // ->M - _spatiotemporalLPfilter(LMSimageInput+_NBpixels, _filterOutput, 1); - setV0CompressionParameterToneMapping(PhotoreceptorsCompression, _maxInputValue, this->sum()/_NBpixels); - _localLuminanceAdaptation(LMSimageInput+_NBpixels, _filterOutput, lmsTempBuffer.Buffer()+_NBpixels); - // ->S - _spatiotemporalLPfilter(LMSimageInput+_NBpixels*2, _filterOutput, 1); - setV0CompressionParameterToneMapping(PhotoreceptorsCompression, _maxInputValue, this->sum()/_NBpixels); - _localLuminanceAdaptation(LMSimageInput+_NBpixels*2, _filterOutput, lmsTempBuffer.Buffer()+_NBpixels*2); - - // eliminate negative values - for (unsigned int i=0;imin LMS value="< acr1cr2TempBuffer(_NBrows, _NBcolumns, 3); - memcpy(acr1cr2TempBuffer.Buffer(), lmsTempBuffer.Buffer(), sizeof(float)*_NBpixels*3); - - // compute A Cr1 Cr2 to LMS color space conversion - _applyImageColorSpaceConversion(acr1cr2TempBuffer.Buffer(), lmsTempBuffer.Buffer(), _ACr1Cr2toLMS); - - // eliminate negative values - for (unsigned int i=0;isetDemultiplexedColorFrame(lmsTempBuffer.Buffer()); - */ - } - - // return image with center Parvo and peripheral Magno channels - void RetinaFilter::_processRetinaParvoMagnoMapping() - { - register float *hybridParvoMagnoPTR= &_retinaParvoMagnoMappedFrame[0]; - register const float *parvoOutputPTR= get_data(_ParvoRetinaFilter.getOutput()); - register const float *magnoXOutputPTR= get_data(_MagnoRetinaFilter.getOutput()); - register float *hybridParvoMagnoCoefTablePTR= &_retinaParvoMagnoMapCoefTable[0]; - - for (unsigned int i=0 ; i<_photoreceptorsPrefilter.getNBpixels() ; ++i, hybridParvoMagnoCoefTablePTR+=2) - { - float hybridValue=*(parvoOutputPTR++)**(hybridParvoMagnoCoefTablePTR)+*(magnoXOutputPTR++)**(hybridParvoMagnoCoefTablePTR+1); - *(hybridParvoMagnoPTR++)=hybridValue; - } - - TemplateBuffer::normalizeGrayOutput_0_maxOutputValue(&_retinaParvoMagnoMappedFrame[0], _photoreceptorsPrefilter.getNBpixels()); - - } - - bool RetinaFilter::getParvoFoveaResponse(std::valarray &parvoFovealResponse) - { - if (!_useParvoOutput) - return false; - if (parvoFovealResponse.size() != _ParvoRetinaFilter.getNBpixels()) - return false; - - register const float *parvoOutputPTR= get_data(_ParvoRetinaFilter.getOutput()); - register float *fovealParvoResponsePTR= &parvoFovealResponse[0]; - register float *hybridParvoMagnoCoefTablePTR= &_retinaParvoMagnoMapCoefTable[0]; - - for (unsigned int i=0 ; i<_photoreceptorsPrefilter.getNBpixels() ; ++i, hybridParvoMagnoCoefTablePTR+=2) - { - *(fovealParvoResponsePTR++)=*(parvoOutputPTR++)**(hybridParvoMagnoCoefTablePTR); - } - - return true; - } - - // method to retrieve the parafoveal magnocellular pathway response (no energy motion in fovea) - bool RetinaFilter::getMagnoParaFoveaResponse(std::valarray &magnoParafovealResponse) - { - if (!_useMagnoOutput) - return false; - if (magnoParafovealResponse.size() != _MagnoRetinaFilter.getNBpixels()) - return false; - - register const float *magnoXOutputPTR= get_data(_MagnoRetinaFilter.getOutput()); - register float *parafovealMagnoResponsePTR=&magnoParafovealResponse[0]; - register float *hybridParvoMagnoCoefTablePTR=&_retinaParvoMagnoMapCoefTable[0]+1; - - for (unsigned int i=0 ; i<_photoreceptorsPrefilter.getNBpixels() ; ++i, hybridParvoMagnoCoefTablePTR+=2) - { - *(parafovealMagnoResponsePTR++)=*(magnoXOutputPTR++)**(hybridParvoMagnoCoefTablePTR); - } - - return true; - } -}// end of namespace bioinspired -}// end of namespace cv diff --git a/modules/bioinspired/src/retinafilter.hpp b/modules/bioinspired/src/retinafilter.hpp deleted file mode 100644 index 5b254c8ac..000000000 --- a/modules/bioinspired/src/retinafilter.hpp +++ /dev/null @@ -1,548 +0,0 @@ -/*#****************************************************************************** -** 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. -** -** -** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. -** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. -** -** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) -** -** Creation - enhancement process 2007-2011 -** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France -** -** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). -** Refer to the following research paper for more information: -** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 -** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: -** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. -** -** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : -** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: -** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. -** ====> more informations in the above cited Jeanny Heraults's book. -** -** License Agreement -** For Open Source Computer Vision Library -** -** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** -** For Human Visual System tools (bioinspired) -** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions 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. -*******************************************************************************/ - -/** -* @class RetinaFilter -* @brief class which describes the retina model developped at the LIS/GIPSA-LAB www.gipsa-lab.inpg.fr: -* -> performs a contours and moving contours extraction with powerfull local data enhancement as at the retina level -* Based on Alexandre BENOIT thesis: "Le systeme visuel humain au secours de la vision par ordinateur" -* -* => various optimisations and enhancements added after 2007 such as tone mapping capabilities, see reference paper cited in the licence and : -* Benoit A.,Alleysson D., Herault J., Le Callet P. (2009), "Spatio-Temporal Tone Mapping Operator based on a Retina model", Computational Color Imaging Workshop (CCIW09),pp 12-22, Saint Etienne, France -* -* TYPICAL USE: -* -* // create object at a specified picture size -* Retina *retina; -* retina =new Retina(frameSizeRows, frameSizeColumns, RGBmode); -* -* // init gain, spatial and temporal parameters: -* retina->setParameters(0.7, 1, 0, 7, 1, 5, 0, 0, 3 , true); -* -* // during program execution, call the filter for local luminance correction, contours extraction, moving contours extraction from an input picture called "FrameBuffer": -* retina->runfilter(FrameBuffer); -* -* // get the different output frames, check in the class description below for more outputs: -* const std::valarray correctedLuminance=retina->getLocalAdaptation(); -* const std::valarray contours=retina->getContours(); -* const std::valarray movingContours=retina->getMovingContours(); -* -* // at the end of the program, destroy object: -* delete retina; -* -* @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC / Gipsa-Lab, France: www.gipsa-lab.inpg.fr/ -* Creation date 2007 -*/ - -#ifndef RETINACLASSES_H_ -#define RETINACLASSES_H_ - -#include "basicretinafilter.hpp" -#include "parvoretinafilter.hpp" -#include "magnoretinafilter.hpp" - -// optional includes (depending on the related publications) -#include "imagelogpolprojection.hpp" - -#include "retinacolor.hpp" - -//#define __RETINADEBUG // define RETINADEBUG to display debug data -namespace cv -{ -namespace bioinspired -{ -// retina class that process the 3 outputs of the retina filtering stages -class RetinaFilter//: public BasicRetinaFilter -{ -public: - - /** - * constructor of the retina filter model with log sampling of the input frame (models the photoreceptors log sampling (central high resolution fovea and lower precision borders)) - * @param sizeRows: number of rows of the input image - * @param sizeColumns: number of columns of the input image - * @param colorMode: specifies if the retina works with color (true) of stays in grayscale processing (false), can be adjusted online by the use of setColorMode method - * @param samplingMethod: specifies which kind of color sampling will be used - * @param useRetinaLogSampling: activate retina log sampling, if true, the 2 following parameters can be used - * @param reductionFactor: only usefull if param useRetinaLogSampling=true, specifies the reduction factor of the output frame (as the center (fovea) is high resolution and corners can be underscaled, then a reduction of the output is allowed without precision leak - * @param samplingStrenght: only usefull if param useRetinaLogSampling=true, specifies the strenght of the log scale that is applied - */ - RetinaFilter(const unsigned int sizeRows, const unsigned int sizeColumns, const bool colorMode=false, const int samplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0); - - /** - * standard destructor - */ - ~RetinaFilter(); - - /** - * function that clears all buffers of the object - */ - void clearAllBuffers(); - - /** - * resize retina parvo filter object (resize all allocated buffers) - * @param NBrows: the new height size - * @param NBcolumns: the new width size - */ - void resize(const unsigned int NBrows, const unsigned int NBcolumns); - - /** - * Input buffer checker: allows to check if the passed image buffer corresponds to retina filter expectations - * @param input: the input image buffer - * @param colorMode: specifiy if the input should be considered by the retina as colored of not - * @return false if not compatible or it returns true if OK - */ - bool checkInput(const std::valarray &input, const bool colorMode); - - /** - * run the initilized retina filter, after this call all retina outputs are updated - * @param imageInput: image input buffer, can be grayscale or RGB image respecting the size specified at the constructor level - * @param useAdaptiveFiltering: set true if you want to use adaptive color demultilexing (solve some color artefact problems), see RetinaColor for citation references - * @param processRetinaParvoMagnoMapping: tels if the main outputs takes into account the mapping of the Parvo and Magno channels on the retina (centred parvo (fovea) and magno outside (parafovea)) - * @param useColorMode: color information is used if true, warning, if input is only gray level, a buffer overflow error will occur - -> note that if color mode is activated and processRetinaParvoMagnoMapping==true, then the demultiplexed color frame (accessible throw getColorOutput() will be a color contours frame in the fovea and gray level moving contours outside - @param inputIsColorMultiplexed: set trus if the input data is a multiplexed color image (using Bayer sampling for example), the color sampling method must correspond to the RETINA_COLORSAMPLINGMETHOD passed at constructor! - * @return true if process ran well, false in case of failure - */ - bool runFilter(const std::valarray &imageInput, const bool useAdaptiveFiltering=true, const bool processRetinaParvoMagnoMapping=false, const bool useColorMode=false, const bool inputIsColorMultiplexed=false); - - /** - * run the initilized retina filter in order to perform color tone mapping applied on an RGB image, after this call the color output of the retina is updated (use function getColorOutput() to grab it) - * the algorithm is based on David Alleyson, Sabine Susstruck and Laurence Meylan's work, please cite: - * -> Meylan L., Alleysson D., and S�sstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N� 9, September, 1st, 2007, pp. 2807-2816 - * get the resulting gray frame by calling function getParvoColor() - * @param grayImageInput: RGB image input buffer respecting the size specified at the constructor level - * @param PhotoreceptorsCompression: sets the log compression parameters applied at the photoreceptors level (enhance luminance in dark areas) - * @param ganglionCellsCompression: sets the log compression applied at the gnaglion cells output (enhance contrast) - */ - void runGrayToneMapping(const std::valarray &grayImageInput, std::valarray &grayImageOutput, const float PhotoreceptorsCompression=0.6, const float ganglionCellsCompression=0.6); - - /** - * run the initilized retina filter in order to perform color tone mapping applied on an RGB image, after this call the color output of the retina is updated (use function getColorOutput() to grab it) - * the algorithm is based on David Alleyson, Sabine Susstruck and Laurence Meylan's work, please cite: - * -> Meylan L., Alleysson D., and S�sstrunk S., A Model of Retinal Local Adaptation for the Tone Mapping of Color Filter Array Images, Journal of Optical Society of America, A, Vol. 24, N� 9, September, 1st, 2007, pp. 2807-2816 - * get the resulting RGB frame by calling function getParvoColor() - * @param RGBimageInput: RGB image input buffer respecting the size specified at the constructor level - * @param useAdaptiveFiltering: set true if you want to use adaptive color demultilexing (solve some color artefact problems), see RetinaColor for citation references - * @param PhotoreceptorsCompression: sets the log compression parameters applied at the photoreceptors level (enhance luminance in dark areas) - * @param ganglionCellsCompression: sets the log compression applied at the ganglion cells output (enhance contrast) - */ - void runRGBToneMapping(const std::valarray &RGBimageInput, std::valarray &imageOutput, const bool useAdaptiveFiltering, const float PhotoreceptorsCompression=0.6, const float ganglionCellsCompression=0.6); - - /** - * run the initilized retina filter in order to perform color tone mapping applied on an RGB image, after this call the color output of the retina is updated (use function getColorOutput() to grab it) - * get the resulting RGB frame by calling function getParvoColor() - * @param LMSimageInput: RGB image input buffer respecting the size specified at the constructor level - * @param useAdaptiveFiltering: set true if you want to use adaptive color demultilexing (solve some color artefact problems), see RetinaColor for citation references - * @param PhotoreceptorsCompression: sets the log compression parameters applied at the photoreceptors level (enhance luminance in dark areas) - * @param ganglionCellsCompression: sets the log compression applied at the gnaglion cells output (enhance contrast) - */ - void runLMSToneMapping(const std::valarray &LMSimageInput, std::valarray &imageOutput, const bool useAdaptiveFiltering, const float PhotoreceptorsCompression=0.6, const float ganglionCellsCompression=0.6); - - /** - * set up function of the retina filter: all the retina is initialized at this step, some specific parameters are set by default, use setOPLandParvoCoefficientsTable() and setMagnoCoefficientsTable in order to setup the retina with more options - * @param OPLspatialResponse1: (equal to k1 in setOPLandParvoCoefficientsTable() function) the spatial constant of the first order low pass filter of the photoreceptors, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 1 pixel - * @param OPLtemporalresponse1: (equal to tau1 in setOPLandParvoCoefficientsTable() function) the time constant of the first order low pass filter of the photoreceptors, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 1 frame - * @param OPLassymetryGain: (equal to beta2 in setOPLandParvoCoefficientsTable() function) gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, then, the luminance is not filtered and is still reachable at the output, typicall value is 0 - * @param OPLspatialResponse2: (equal to k2 in setOPLandParvoCoefficientsTable() function) the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel - * @param OPLtemporalresponse2: (equal to tau2 in setOPLandParvoCoefficientsTable() function) the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors - * @param LPfilterSpatialResponse: (equal to parasolCells_k in setMagnoCoefficientsTable() function) the low pass filter spatial constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is pixels, typical value is 5 - * @param LPfilterGain: (equal to parasolCells_beta in setMagnoCoefficientsTable() function) the low pass filter gain used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), typical value is 0 - * @param LPfilterTemporalresponse: (equal to parasolCells_tau in setMagnoCoefficientsTable() function) the low pass filter time constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is frame, typical value is 0 (immediate response) - * @param MovingContoursExtractorCoefficient: (equal to amacrinCellsTemporalCutFrequency in setMagnoCoefficientsTable() function)the time constant of the first order high pass fiter of the magnocellular way (motion information channel), unit is frames, tipicall value is 5 - * @param normalizeParvoOutput_0_maxOutputValue: specifies if the Parvo cellular output should be normalized between 0 and maxOutputValue (true) or not (false) in order to remain at a null mean value, true value is recommended for visualisation - * @param normalizeMagnoOutput_0_maxOutputValue: specifies if the Magno cellular output should be normalized between 0 and maxOutputValue (true) or not (false), setting true may be hazardous because it can enhace the noise response when nothing is moving - * @param maxOutputValue: the maximum amplitude value of the normalized outputs (generally 255 for 8bit per channel pictures) - * @param maxInputValue: the maximum pixel value of the input picture (generally 255 for 8bit per channel pictures), specify it in other case (for example High Dynamic Range Images) - * @param meanValue: the global mean value of the input data usefull for local adaptation setup - */ - void setGlobalParameters(const float OPLspatialResponse1=0.7, const float OPLtemporalresponse1=1, const float OPLassymetryGain=0, const float OPLspatialResponse2=5, const float OPLtemporalresponse2=1, const float LPfilterSpatialResponse=5, const float LPfilterGain=0, const float LPfilterTemporalresponse=0, const float MovingContoursExtractorCoefficient=5, const bool normalizeParvoOutput_0_maxOutputValue=false, const bool normalizeMagnoOutput_0_maxOutputValue=false, const float maxOutputValue=255.0, const float maxInputValue=255.0, const float meanValue=128.0); - - /** - * setup the local luminance adaptation capability - * @param V0CompressionParameter: the compression strengh of the photoreceptors local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 160 - */ - inline void setPhotoreceptorsLocalAdaptationSensitivity(const float V0CompressionParameter) { _photoreceptorsPrefilter.setV0CompressionParameter(1-V0CompressionParameter);_setInitPeriodCount(); } - - /** - * setup the local luminance adaptation capability - * @param V0CompressionParameter: the compression strengh of the parvocellular pathway (details) local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 160 - */ - inline void setParvoGanglionCellsLocalAdaptationSensitivity(const float V0CompressionParameter) { _ParvoRetinaFilter.setV0CompressionParameter(V0CompressionParameter);_setInitPeriodCount(); } - - /** - * setup the local luminance adaptation area of integration - * @param spatialResponse: the spatial constant of the low pass filter applied on the bipolar cells output in order to compute local contrast mean values - * @param temporalResponse: the spatial constant of the low pass filter applied on the bipolar cells output in order to compute local contrast mean values (generally set to zero: immediate response) - */ - inline void setGanglionCellsLocalAdaptationLPfilterParameters(const float spatialResponse, const float temporalResponse) { _ParvoRetinaFilter.setGanglionCellsLocalAdaptationLPfilterParameters(temporalResponse, spatialResponse);_setInitPeriodCount(); } - - /** - * setup the local luminance adaptation capability - * @param V0CompressionParameter: the compression strengh of the magnocellular pathway (motion) local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 160 - */ - inline void setMagnoGanglionCellsLocalAdaptationSensitivity(const float V0CompressionParameter) { _MagnoRetinaFilter.setV0CompressionParameter(V0CompressionParameter);_setInitPeriodCount(); } - - /** - * setup the OPL and IPL parvo channels - * @param beta1: gain of the horizontal cells network, if 0, then the mean value of the output is zero (default value), if the parameter is near 1, the amplitude is boosted but it should only be used for values rescaling... if needed - * @param tau1: the time constant of the first order low pass filter of the photoreceptors, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 1 frame - * @param k1: the spatial constant of the first order low pass filter of the photoreceptors, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 1 pixel - * @param beta2: gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, then, the luminance is not filtered and is still reachable at the output, typicall value is 0 - * @param tau2: the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors - * @param k2: the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model) - * @param V0CompressionParameter: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 230 - */ - void setOPLandParvoParameters(const float beta1, const float tau1, const float k1, const float beta2, const float tau2, const float k2, const float V0CompressionParameter) { _ParvoRetinaFilter.setOPLandParvoFiltersParameters(beta1, tau1, k1, beta2, tau2, k2);_ParvoRetinaFilter.setV0CompressionParameter(V0CompressionParameter);_setInitPeriodCount(); } - - /** - * set parameters values for the Inner Plexiform Layer (IPL) magnocellular channel - * @param parasolCells_beta: the low pass filter gain used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), typical value is 0 - * @param parasolCells_tau: the low pass filter time constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is frame, typical value is 0 (immediate response) - * @param parasolCells_k: the low pass filter spatial constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is pixels, typical value is 5 - * @param amacrinCellsTemporalCutFrequency: the time constant of the first order high pass fiter of the magnocellular way (motion information channel), unit is frames, tipicall value is 5 - * @param V0CompressionParameter: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 200 - * @param localAdaptintegration_tau: specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation - * @param localAdaptintegration_k: specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation - */ - void setMagnoCoefficientsTable(const float parasolCells_beta, const float parasolCells_tau, const float parasolCells_k, const float amacrinCellsTemporalCutFrequency, const float V0CompressionParameter, const float localAdaptintegration_tau, const float localAdaptintegration_k) { _MagnoRetinaFilter.setCoefficientsTable(parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, localAdaptintegration_tau, localAdaptintegration_k);_MagnoRetinaFilter.setV0CompressionParameter(V0CompressionParameter);_setInitPeriodCount(); } - - /** - * set if the parvo output should be or not normalized between 0 and 255 (for display purpose generally) - * @param normalizeParvoOutput_0_maxOutputValue: true if normalization should be done - */ - inline void activateNormalizeParvoOutput_0_maxOutputValue(const bool normalizeParvoOutput_0_maxOutputValue) { _normalizeParvoOutput_0_maxOutputValue=normalizeParvoOutput_0_maxOutputValue; } - - /** - * set if the magno output should be or not normalized between 0 and 255 (for display purpose generally), take care, if nothing is moving, then, the noise will be enanced !!! - * @param normalizeMagnoOutput_0_maxOutputValue: true if normalization should be done - */ - inline void activateNormalizeMagnoOutput_0_maxOutputValue(const bool normalizeMagnoOutput_0_maxOutputValue) { _normalizeMagnoOutput_0_maxOutputValue=normalizeMagnoOutput_0_maxOutputValue; } - - /** - * setup the maximum amplitude value of the normalized outputs (generally 255 for 8bit per channel pictures) - * @param maxOutputValue: maximum amplitude value of the normalized outputs (generally 255 for 8bit per channel pictures) - */ - inline void setMaxOutputValue(const float maxOutputValue) { _maxOutputValue=maxOutputValue; } - - /** - * sets the color mode of the frame grabber - * @param desiredColorMode: true if the user needs color information, false for graylevels - */ - void setColorMode(const bool desiredColorMode) { _useColorMode=desiredColorMode; } - - /** - * activate color saturation as the final step of the color demultiplexing process - * -> this saturation is a sigmoide function applied to each channel of the demultiplexed image. - * @param saturateColors: boolean that activates color saturation (if true) or desactivate (if false) - * @param colorSaturationValue: the saturation factor - * */ - inline void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0) { _colorEngine.setColorSaturation(saturateColors, colorSaturationValue); } - - ///////////////////////////////////////////////////////////////// - // function that retrieve the main retina outputs, one by one, or all in a structure - - /** - * @return the input image sampled by the photoreceptors spatial sampling - */ - inline const std::valarray &getPhotoreceptorsSampledFrame() const - { - CV_Assert(_photoreceptorsLogSampling); - return _photoreceptorsLogSampling->getSampledFrame(); - }; - - /** - * @return photoreceptors output, locally adapted luminance only, no high frequency spatio-temporal noise reduction at the next retina processing stages, use getPhotoreceptors method to get complete photoreceptors output - */ - inline const std::valarray &getLocalAdaptation() const {return _photoreceptorsPrefilter.getOutput(); } - - /** - * @return photoreceptors output: locally adapted luminance and high frequency spatio-temporal noise reduction, high luminance is a little saturated at this stage, but this is corrected naturally at the next retina processing stages - */ - inline const std::valarray &getPhotoreceptors() const {return _ParvoRetinaFilter.getPhotoreceptorsLPfilteringOutput(); } - - /** - * @return the local luminance of the processed frame (it is the horizontal cells output) - */ - inline const std::valarray &getHorizontalCells() const {return _ParvoRetinaFilter.getHorizontalCellsOutput(); } - - ///////// CONTOURS part, PARVOCELLULAR RETINA PATHWAY - /** - * @return true if Parvocellular output is activated, false if not - */ - inline bool areContoursProcessed() { return _useParvoOutput; } - - /** - * method to retrieve the foveal parvocellular pathway response (no details energy in parafovea) - * @param parvoParafovealResponse: buffer that will be filled with the response of the magnocellular pathway in the parafoveal area - * @return true if process succeeded (if buffer exists, is its size matches retina size, if magno channel is activated and if mapping is initialized - */ - bool getParvoFoveaResponse(std::valarray &parvoFovealResponse); - - /** - * @param useParvoOutput: true if Parvocellular output should be activated, false if not - */ - inline void activateContoursProcessing(const bool useParvoOutput) { _useParvoOutput=useParvoOutput; } - - /** - * @return the parvocellular contours information (details), should be used at the fovea level - */ - const std::valarray &getContours(); // Parvocellular output - - /** - * @return the parvocellular contours ON information (details), should be used at the fovea level - */ - inline const std::valarray &getContoursON() const {return _ParvoRetinaFilter.getParvoON(); } // Parvocellular ON output - - /** - * @return the parvocellular contours OFF information (details), should be used at the fovea level - */ - inline const std::valarray &getContoursOFF() const {return _ParvoRetinaFilter.getParvoOFF(); } // Parvocellular OFF output - - ///////// MOVING CONTOURS part, MAGNOCELLULAR RETINA PATHWAY - /** - * @return true if Magnocellular output is activated, false if not - */ - inline bool areMovingContoursProcessed() { return _useMagnoOutput; } - - /** - * method to retrieve the parafoveal magnocellular pathway response (no motion energy in fovea) - * @param magnoParafovealResponse: buffer that will be filled with the response of the magnocellular pathway in the parafoveal area - * @return true if process succeeded (if buffer exists, is its size matches retina size, if magno channel is activated and if mapping is initialized - */ - bool getMagnoParaFoveaResponse(std::valarray &magnoParafovealResponse); - - /** - * @param useMagnoOutput: true if Magnoocellular output should be activated, false if not - */ - inline void activateMovingContoursProcessing(const bool useMagnoOutput) { _useMagnoOutput=useMagnoOutput; } - - /** - * @return the magnocellular moving contours information (motion), should be used at the parafovea level without post-processing - */ - inline const std::valarray &getMovingContours() const {return _MagnoRetinaFilter.getOutput(); } // Magnocellular output - - /** - * @return the magnocellular moving contours information (motion), should be used at the parafovea level with assymetric sigmoide post-processing which saturates motion information - */ - inline const std::valarray &getMovingContoursSaturated() const {return _MagnoRetinaFilter.getMagnoYsaturated(); } // Saturated Magnocellular output - - /** - * @return the magnocellular moving contours ON information (motion), should be used at the parafovea level without post-processing - */ - inline const std::valarray &getMovingContoursON() const {return _MagnoRetinaFilter.getMagnoON(); } // Magnocellular ON output - - /** - * @return the magnocellular moving contours OFF information (motion), should be used at the parafovea level without post-processing - */ - inline const std::valarray &getMovingContoursOFF() const {return _MagnoRetinaFilter.getMagnoOFF(); } // Magnocellular OFF output - - /** - * @return a gray level image with center Parvo and peripheral Magno X channels, WARNING, the result will be ok if you called previously fucntion runFilter(imageInput, processRetinaParvoMagnoMapping=true); - * -> will be accessible even if color mode is activated (but the image is color sampled so quality is poor), but get the same thing but in color by the use of function getParvoColor() - */ - inline const std::valarray &getRetinaParvoMagnoMappedOutput() const {return _retinaParvoMagnoMappedFrame; } // return image with center Parvo and peripheral Magno channels - - /** - * color processing dedicated functions - * @return the parvo channel (contours, details) of the processed frame, grayscale output - */ - inline const std::valarray &getParvoContoursChannel() const {return _colorEngine.getLuminance(); } - - /** - * color processing dedicated functions - * @return the chrominance of the processed frame (same colorspace as the input output, usually RGB) - */ - inline const std::valarray &getParvoChrominance() const {return _colorEngine.getChrominance(); } // only retreive chrominance - - /** - * color processing dedicated functions - * @return the parvo + chrominance channels of the processed frame (same colorspace as the input output, usually RGB) - */ - inline const std::valarray &getColorOutput() const {return _colorEngine.getDemultiplexedColorFrame(); } // retrieve luminance+chrominance - - /** - * apply to the retina color output the Krauskopf transformation which leads to an opponent color system: output colorspace if Acr1cr2 if input of the retina was LMS color space - * @param result: the input buffer to fill with the transformed colorspace retina output - * @return true if process ended successfully - */ - inline bool applyKrauskopfLMS2Acr1cr2Transform(std::valarray &result) { return _colorEngine.applyKrauskopfLMS2Acr1cr2Transform(result); } - - /** - * apply to the retina color output the Krauskopf transformation which leads to an opponent color system: output colorspace if Acr1cr2 if input of the retina was LMS color space - * @param result: the input buffer to fill with the transformed colorspace retina output - * @return true if process ended successfully - */ - inline bool applyLMS2LabTransform(std::valarray &result) { return _colorEngine.applyLMS2LabTransform(result); } - - /** - * color processing dedicated functions - * @return the retina initialized mode, true if color mode (RGB), false if grayscale - */ - inline bool isColorMode() { return _useColorMode; } // return true if RGB mode, false if gray level mode - - /** - * @return the irregular low pass filter ouput at the photoreceptors level - */ - inline const std::valarray &getIrregularLPfilteredInputFrame() const {return _photoreceptorsLogSampling->getIrregularLPfilteredInputFrame(); } - - /** - * @return true if color mode is activated, false if gray levels processing - */ - bool getColorMode() { return _useColorMode; } - - /** - * - * @return true if a sufficient number of processed frames has been done since the last parameters update in order to get the stable state (r�gime permanent) - */ - inline bool isInitTransitionDone() { if (_ellapsedFramesSinceLastReset<_globalTemporalConstant)return false; return true; } - - /** - * find a distance in the image input space when the distance is known in the retina log sampled space...read again if it is not clear enough....sorry, i should sleep - * @param projectedRadiusLength: the distance to image center in the retina log sampled space - * @return the distance to image center in the input image space - */ - inline float getRetinaSamplingBackProjection(const float projectedRadiusLength) - { - if (_photoreceptorsLogSampling) - return (float)_photoreceptorsLogSampling->getOriginalRadiusLength(projectedRadiusLength); - return projectedRadiusLength; - } - - /////////////////: - // retina dimensions getters - - /** - * @return number of rows of the filter - */ - inline unsigned int getInputNBrows() { if (_photoreceptorsLogSampling) return _photoreceptorsLogSampling->getNBrows();else return _photoreceptorsPrefilter.getNBrows(); } - - /** - * @return number of columns of the filter - */ - inline unsigned int getInputNBcolumns() { if (_photoreceptorsLogSampling) return _photoreceptorsLogSampling->getNBcolumns();else return _photoreceptorsPrefilter.getNBcolumns(); } - - /** - * @return number of pixels of the filter - */ - inline unsigned int getInputNBpixels() { if (_photoreceptorsLogSampling) return _photoreceptorsLogSampling->getNBpixels();else return _photoreceptorsPrefilter.getNBpixels(); } - - /** - * @return the height of the frame output - */ - inline unsigned int getOutputNBrows() { return _photoreceptorsPrefilter.getNBrows(); } - - /** - * @return the width of the frame output - */ - inline unsigned int getOutputNBcolumns() { return _photoreceptorsPrefilter.getNBcolumns(); } - - /** - * @return the numbers of output pixels (width*height) of the images used by the object - */ - inline unsigned int getOutputNBpixels() { return _photoreceptorsPrefilter.getNBpixels(); } - - -private: - - // processing activation flags - bool _useParvoOutput; - bool _useMagnoOutput; - - - // filter stability controls - unsigned int _ellapsedFramesSinceLastReset; - unsigned int _globalTemporalConstant; - - // private template buffers and related access pointers - std::valarray _retinaParvoMagnoMappedFrame; - std::valarray _retinaParvoMagnoMapCoefTable; - // private objects of the class - BasicRetinaFilter _photoreceptorsPrefilter; - ParvoRetinaFilter _ParvoRetinaFilter; - MagnoRetinaFilter _MagnoRetinaFilter; - RetinaColor _colorEngine; - ImageLogPolProjection *_photoreceptorsLogSampling; - - bool _useMinimalMemoryForToneMappingONLY; - - bool _normalizeParvoOutput_0_maxOutputValue; - bool _normalizeMagnoOutput_0_maxOutputValue; - float _maxOutputValue; - bool _useColorMode; - - - - // private functions - void _setInitPeriodCount(); - void _createHybridTable(); - void _processRetinaParvoMagnoMapping(); - void _runGrayToneMapping(const std::valarray &grayImageInput, std::valarray &grayImageOutput ,const float PhotoreceptorsCompression=0.6, const float ganglionCellsCompression=0.6); - - -}; - -}// end of namespace bioinspired -}// end of namespace cv - -#endif /*RETINACLASSES_H_*/ diff --git a/modules/bioinspired/src/templatebuffer.hpp b/modules/bioinspired/src/templatebuffer.hpp deleted file mode 100644 index a95102d5c..000000000 --- a/modules/bioinspired/src/templatebuffer.hpp +++ /dev/null @@ -1,555 +0,0 @@ -/*#****************************************************************************** -** 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. -** -** -** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab. -** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping. -** -** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) -** -** Creation - enhancement process 2007-2011 -** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France -** -** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr). -** Refer to the following research paper for more information: -** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011 -** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book: -** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891. -** -** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : -** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: -** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 -** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions. -** ====> more informations in the above cited Jeanny Heraults's book. -** -** License Agreement -** For Open Source Computer Vision Library -** -** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** -** For Human Visual System tools (bioinspired) -** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, 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: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions 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. -*******************************************************************************/ - -#ifndef __TEMPLATEBUFFER_HPP__ -#define __TEMPLATEBUFFER_HPP__ - -#include -#include -#include -#include - - -//#define __TEMPLATEBUFFERDEBUG //define TEMPLATEBUFFERDEBUG in order to display debug information - -namespace cv -{ -namespace bioinspired -{ -//// If a parallelization method is available then, you should define MAKE_PARALLEL, in the other case, the classical serial code will be used -#define MAKE_PARALLEL -// ==> then include required includes -#ifdef MAKE_PARALLEL - -// ==> declare usefull generic tools -template -class Parallel_clipBufferValues: public cv::ParallelLoopBody -{ -private: - type *bufferToClip; - type minValue, maxValue; - -public: - Parallel_clipBufferValues(type* bufferToProcess, const type min, const type max) - : bufferToClip(bufferToProcess), minValue(min), maxValue(max) { } - - virtual void operator()( const cv::Range &r ) const { - register type *inputOutputBufferPTR=bufferToClip+r.start; - for (register int jf = r.start; jf != r.end; ++jf, ++inputOutputBufferPTR) - { - if (*inputOutputBufferPTR>maxValue) - *inputOutputBufferPTR=maxValue; - else if (*inputOutputBufferPTR class TemplateBuffer : public std::valarray - { - public: - - /** - * constructor for monodimensional array - * @param dim: the size of the vector - */ - TemplateBuffer(const size_t dim=0) - : std::valarray((type)0, dim) - { - _NBrows=1; - _NBcolumns=dim; - _NBdepths=1; - _NBpixels=dim; - _doubleNBpixels=2*dim; - } - - /** - * constructor by copy for monodimensional array - * @param pVal: the pointer to a buffer to copy - * @param dim: the size of the vector - */ - TemplateBuffer(const type* pVal, const size_t dim) - : std::valarray(pVal, dim) - { - _NBrows=1; - _NBcolumns=dim; - _NBdepths=1; - _NBpixels=dim; - _doubleNBpixels=2*dim; - } - - /** - * constructor for bidimensional array - * @param dimRows: the size of the vector - * @param dimColumns: the size of the vector - * @param depth: the number of layers of the buffer in its third dimension (3 of color images, 1 for gray images. - */ - TemplateBuffer(const size_t dimRows, const size_t dimColumns, const size_t depth=1) - : std::valarray((type)0, dimRows*dimColumns*depth) - { -#ifdef TEMPLATEBUFFERDEBUG - std::cout<<"TemplateBuffer::TemplateBuffer: new buffer, size="<(toCopy) - { - memcpy(Buffer(), toCopy.Buffer(), this->size()); - }*/ - /** - * destructor - */ - virtual ~TemplateBuffer() - { -#ifdef TEMPLATEBUFFERDEBUG - std::cout<<"~TemplateBuffer"<::operator=(0); } //memset(Buffer(), 0, sizeof(type)*_NBpixels); } - - /** - * @return the numbers of rows (height) of the images used by the object - */ - inline unsigned int getNBrows() { return (unsigned int)_NBrows; } - - /** - * @return the numbers of columns (width) of the images used by the object - */ - inline unsigned int getNBcolumns() { return (unsigned int)_NBcolumns; } - - /** - * @return the numbers of pixels (width*height) of the images used by the object - */ - inline unsigned int getNBpixels() { return (unsigned int)_NBpixels; } - - /** - * @return the numbers of pixels (width*height) of the images used by the object - */ - inline unsigned int getDoubleNBpixels() { return (unsigned int)_doubleNBpixels; } - - /** - * @return the numbers of depths (3rd dimension: 1 for gray images, 3 for rgb images) of the images used by the object - */ - inline unsigned int getDepthSize() { return (unsigned int)_NBdepths; } - - /** - * resize the buffer and recompute table index etc. - */ - void resizeBuffer(const size_t dimRows, const size_t dimColumns, const size_t depth=1) - { - this->resize(dimRows*dimColumns*depth); - _NBrows=dimRows; - _NBcolumns=dimColumns; - _NBdepths=depth; - _NBpixels=dimRows*dimColumns; - _doubleNBpixels=2*dimRows*dimColumns; - } - - inline TemplateBuffer & operator=(const std::valarray &b) - { - //std::cout<<"TemplateBuffer & operator= affect vector: "<::operator=(b); - return *this; - } - - inline TemplateBuffer & operator=(const type &b) - { - //std::cout<<"TemplateBuffer & operator= affect value: "<::operator=(b); - return *this; - } - - /* inline const type &operator[](const unsigned int &b) - { - return (*this)[b]; - } - */ - /** - * @return the buffer adress in non const mode - */ - inline type* Buffer() { return &(*this)[0]; } - - /////////////////////////////////////////////////////// - // Standard Image manipulation functions - - /** - * standard 0 to 255 image normalization function - * @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized - * @param nbPixels: specifies the number of pixel on which the normalization should be performed, if 0, then all pixels specified in the constructor are processed - * @param maxOutputValue: the maximum output value - */ - static void normalizeGrayOutput_0_maxOutputValue(type *inputOutputBuffer, const size_t nbPixels, const type maxOutputValue=(type)255.0); - - /** - * standard 0 to 255 image normalization function - * @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized - * @param nbPixels: specifies the number of pixel on which the normalization should be performed, if 0, then all pixels specified in the constructor are processed - * @param maxOutputValue: the maximum output value - */ - void normalizeGrayOutput_0_maxOutputValue(const type maxOutputValue=(type)255.0) { normalizeGrayOutput_0_maxOutputValue(this->Buffer(), this->size(), maxOutputValue); } - - /** - * sigmoide image normalization function (saturates min and max values) - * @param meanValue: specifies the mean value of th pixels to be processed - * @param sensitivity: strenght of the sigmoide - * @param inputPicture: the image to be normalized if no parameter, then, the built in buffer reachable by getOutput() function is normalized - * @param outputBuffer: the ouput buffer on which the result is writed, if no parameter, then, the built in buffer reachable by getOutput() function is normalized - * @param maxOutputValue: the maximum output value - */ - static void normalizeGrayOutputCentredSigmoide(const type meanValue, const type sensitivity, const type maxOutputValue, type *inputPicture, type *outputBuffer, const unsigned int nbPixels); - - /** - * sigmoide image normalization function on the current buffer (saturates min and max values) - * @param meanValue: specifies the mean value of th pixels to be processed - * @param sensitivity: strenght of the sigmoide - * @param maxOutputValue: the maximum output value - */ - inline void normalizeGrayOutputCentredSigmoide(const type meanValue=(type)0.0, const type sensitivity=(type)2.0, const type maxOutputValue=(type)255.0) { (void)maxOutputValue; normalizeGrayOutputCentredSigmoide(meanValue, sensitivity, 255.0, this->Buffer(), this->Buffer(), this->getNBpixels()); } - - /** - * sigmoide image normalization function (saturates min and max values), in this function, the sigmoide is centered on low values (high saturation of the medium and high values - * @param inputPicture: the image to be normalized if no parameter, then, the built in buffer reachable by getOutput() function is normalized - * @param outputBuffer: the ouput buffer on which the result is writed, if no parameter, then, the built in buffer reachable by getOutput() function is normalized - * @param sensitivity: strenght of the sigmoide - * @param maxOutputValue: the maximum output value - */ - void normalizeGrayOutputNearZeroCentreredSigmoide(type *inputPicture=(type*)NULL, type *outputBuffer=(type*)NULL, const type sensitivity=(type)40, const type maxOutputValue=(type)255.0); - - /** - * center and reduct the image (image-mean)/std - * @param inputOutputBuffer: the image to be normalized if no parameter, the result is rewrited on it - */ - void centerReductImageLuminance(type *inputOutputBuffer=(type*)NULL); - - /** - * @return standard deviation of the buffer - */ - double getStandardDeviation() - { - double standardDeviation=0; - double meanValue=getMean(); - - type *bufferPTR=Buffer(); - for (unsigned int i=0;isize();++i) - { - double diff=(*(bufferPTR++)-meanValue); - standardDeviation+=diff*diff; - } - return std::sqrt(standardDeviation/this->size()); - } - - /** - * Clip buffer histogram - * @param minRatio: the minimum ratio of the lower pixel values, range=[0,1] and lower than maxRatio - * @param maxRatio: the aximum ratio of the higher pixel values, range=[0,1] and higher than minRatio - */ - void clipHistogram(double minRatio, double maxRatio, double maxOutputValue) - { - - if (minRatio>=maxRatio) - { - std::cerr<<"TemplateBuffer::clipHistogram: minRatio must be inferior to maxRatio, buffer unchanged"<max()*maxRatio; - const double minThreshold=(this->max()-this->min())*minRatio+this->min(); - - type *bufferPTR=this->Buffer(); - - double deltaH=maxThreshold; - double deltaL=maxThreshold; - - double updatedHighValue=maxThreshold; - double updatedLowValue=maxThreshold; - - for (unsigned int i=0;isize();++i) - { - double curentValue=(double)*(bufferPTR++); - - // updating "closest to the high threshold" pixel value - double highValueTest=maxThreshold-curentValue; - if (highValueTest>0) - { - if (deltaH>highValueTest) - { - deltaH=highValueTest; - updatedHighValue=curentValue; - } - } - - // updating "closest to the low threshold" pixel value - double lowValueTest=curentValue-minThreshold; - if (lowValueTest>0) - { - if (deltaL>lowValueTest) - { - deltaL=lowValueTest; - updatedLowValue=curentValue; - } - } - } - - std::cout<<"Tdebug"<max()"<max()<<"maxThreshold="<min()"<min()<<"minThreshold="<Buffer(); -#ifdef MAKE_PARALLEL // call the TemplateBuffer multitreaded clipping method - parallel_for_(cv::Range(0,this->size()), Parallel_clipBufferValues(bufferPTR, updatedLowValue, updatedHighValue)); -#else - - for (unsigned int i=0;isize();++i, ++bufferPTR) - { - if (*bufferPTRupdatedHighValue) - *bufferPTR=updatedHighValue; - } -#endif - normalizeGrayOutput_0_maxOutputValue(this->Buffer(), this->size(), maxOutputValue); - - } - - /** - * @return the mean value of the vector - */ - inline double getMean() { return this->sum()/this->size(); } - - protected: - size_t _NBrows; - size_t _NBcolumns; - size_t _NBdepths; - size_t _NBpixels; - size_t _doubleNBpixels; - // utilities - static type _abs(const type x); - - }; - - /////////////////////////////////////////////////////////////////////// - /// normalize output between 0 and 255, can be applied on images of different size that the declared size if nbPixels parameters is setted up; - template - void TemplateBuffer::normalizeGrayOutput_0_maxOutputValue(type *inputOutputBuffer, const size_t processedPixels, const type maxOutputValue) - { - type maxValue=inputOutputBuffer[0], minValue=inputOutputBuffer[0]; - - // get the min and max value - register type *inputOutputBufferPTR=inputOutputBuffer; - for (register size_t j = 0; j pixValue) - minValue = pixValue; - } - // change the range of the data to 0->255 - - type factor = maxOutputValue/(maxValue-minValue); - type offset = (type)(-minValue*factor); - - inputOutputBufferPTR=inputOutputBuffer; - for (register size_t j = 0; j < processedPixels; ++j, ++inputOutputBufferPTR) - *inputOutputBufferPTR=*(inputOutputBufferPTR)*factor+offset; - - } - // normalize data with a sigmoide close to 0 (saturates values for those superior to 0) - template - void TemplateBuffer::normalizeGrayOutputNearZeroCentreredSigmoide(type *inputBuffer, type *outputBuffer, const type sensitivity, const type maxOutputValue) - { - if (inputBuffer==NULL) - inputBuffer=Buffer(); - if (outputBuffer==NULL) - outputBuffer=Buffer(); - - type X0cube=sensitivity*sensitivity*sensitivity; - - register type *inputBufferPTR=inputBuffer; - register type *outputBufferPTR=outputBuffer; - - for (register size_t j = 0; j < _NBpixels; ++j, ++inputBufferPTR) - { - - type currentCubeLuminance=*inputBufferPTR**inputBufferPTR**inputBufferPTR; - *(outputBufferPTR++)=maxOutputValue*currentCubeLuminance/(currentCubeLuminance+X0cube); - } - } - - // normalize and adjust luminance with a centered to 128 sigmode - template - void TemplateBuffer::normalizeGrayOutputCentredSigmoide(const type meanValue, const type sensitivity, const type maxOutputValue, type *inputBuffer, type *outputBuffer, const unsigned int nbPixels) - { - - if (sensitivity==1.0) - { - std::cerr<<"TemplateBuffer::TemplateBuffer::normalizeGrayOutputCentredSigmoide error: 2nd parameter (sensitivity) must not equal 0, copying original data..."< - void TemplateBuffer::centerReductImageLuminance(type *inputOutputBuffer) - { - // if outputBuffer unsassigned, the rewrite the buffer - if (inputOutputBuffer==NULL) - inputOutputBuffer=Buffer(); - type meanValue=0, stdValue=0; - - // compute mean value - for (register size_t j = 0; j < _NBpixels; ++j) - meanValue+=inputOutputBuffer[j]; - meanValue/=((type)_NBpixels); - - // compute std value - register type *inputOutputBufferPTR=inputOutputBuffer; - for (size_t index=0;index<_NBpixels;++index) - { - type inputMinusMean=*(inputOutputBufferPTR++)-meanValue; - stdValue+=inputMinusMean*inputMinusMean; - } - - stdValue=std::sqrt(stdValue/((type)_NBpixels)); - // adjust luminance in regard of mean and std value; - inputOutputBufferPTR=inputOutputBuffer; - for (size_t index=0;index<_NBpixels;++index, ++inputOutputBufferPTR) - *inputOutputBufferPTR=(*(inputOutputBufferPTR)-meanValue)/stdValue; - } - - - template - type TemplateBuffer::_abs(const type x) - { - - if (x>0) - return x; - else - return -x; - } - - template < > - inline int TemplateBuffer::_abs(const int x) - { - return std::abs(x); - } - template < > - inline double TemplateBuffer::_abs(const double x) - { - return std::fabs(x); - } - - template < > - inline float TemplateBuffer::_abs(const float x) - { - return std::fabs(x); - } - -}// end of namespace bioinspired -}// end of namespace cv -#endif diff --git a/modules/bioinspired/test/test_main.cpp b/modules/bioinspired/test/test_main.cpp deleted file mode 100644 index 6b2499344..000000000 --- a/modules/bioinspired/test/test_main.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "test_precomp.hpp" - -CV_TEST_MAIN("cv") diff --git a/modules/bioinspired/test/test_precomp.hpp b/modules/bioinspired/test/test_precomp.hpp deleted file mode 100644 index b1672149a..000000000 --- a/modules/bioinspired/test/test_precomp.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifdef __GNUC__ -# pragma GCC diagnostic ignored "-Wmissing-declarations" -# if defined __clang__ || defined __APPLE__ -# pragma GCC diagnostic ignored "-Wmissing-prototypes" -# pragma GCC diagnostic ignored "-Wextra" -# endif -#endif - -#ifndef __OPENCV_TEST_PRECOMP_HPP__ -#define __OPENCV_TEST_PRECOMP_HPP__ - -#include "opencv2/ts.hpp" -#include "opencv2/bioinspired.hpp" -#include - -#endif diff --git a/modules/bioinspired/test/test_retina_ocl.cpp b/modules/bioinspired/test/test_retina_ocl.cpp deleted file mode 100644 index bfccdd557..000000000 --- a/modules/bioinspired/test/test_retina_ocl.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/*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-2013, Multicoreware, Inc., all rights reserved. -// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Peng Xiao, pengxiao@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 oclMaterials 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 "test_precomp.hpp" -#include "opencv2/opencv_modules.hpp" -#include "opencv2/bioinspired.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" - -#include "opencv2/core/ocl.hpp" // cv::ocl::haveOpenCL - -#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; - -PARAM_TEST_CASE(Retina_OCL, bool, int, bool, double, double) -{ - bool colorMode; - int colorSamplingMethod; - bool useLogSampling; - double reductionFactor; - double 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; - } - } -}; - -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 ocl_retina = bioinspired::createRetina_OCL( - input.size(), - colorMode, - colorSamplingMethod, - useLogSampling, - reductionFactor, - samplingStrength); - - Ptr gold_retina = bioinspired::createRetina( - input.size(), - colorMode, - colorSamplingMethod, - useLogSampling, - reductionFactor, - samplingStrength); - - Mat gold_parvo; - Mat gold_magno; - ocl::oclMat ocl_parvo; - ocl::oclMat 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_retina->getParvo(ocl_parvo); - ocl_retina->getMagno(ocl_magno); - - int eps = colorMode ? 2 : 1; - - EXPECT_LE(checkNear(gold_parvo, (Mat)ocl_parvo), eps); - EXPECT_LE(checkNear(gold_magno, (Mat)ocl_magno), eps); - } -} - -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 diff --git a/samples/cpp/CMakeLists.txt b/samples/cpp/CMakeLists.txt index eaebcb96f..3ec3fcf39 100644 --- a/samples/cpp/CMakeLists.txt +++ b/samples/cpp/CMakeLists.txt @@ -5,7 +5,7 @@ SET(OPENCV_CPP_SAMPLES_REQUIRED_DEPS opencv_core opencv_flann opencv_imgproc opencv_highgui opencv_ml opencv_video opencv_objdetect opencv_photo opencv_nonfree opencv_softcascade - opencv_features2d opencv_calib3d opencv_legacy opencv_contrib opencv_stitching opencv_videostab opencv_bioinspired opencv_shape) + opencv_features2d opencv_calib3d opencv_legacy opencv_contrib opencv_stitching opencv_videostab opencv_shape) ocv_check_dependencies(${OPENCV_CPP_SAMPLES_REQUIRED_DEPS}) diff --git a/samples/cpp/OpenEXRimages_HDR_Retina_toneMapping.cpp b/samples/cpp/OpenEXRimages_HDR_Retina_toneMapping.cpp deleted file mode 100644 index 66cae7719..000000000 --- a/samples/cpp/OpenEXRimages_HDR_Retina_toneMapping.cpp +++ /dev/null @@ -1,304 +0,0 @@ - -//============================================================================ -// Name : OpenEXRimages_HDR_Retina_toneMapping.cpp -// Author : Alexandre Benoit (benoit.alexandre.vision@gmail.com) -// Version : 0.1 -// Copyright : Alexandre Benoit, LISTIC Lab, july 2011 -// Description : HighDynamicRange retina tone mapping with the help of the Gipsa/Listic's retina in C++, Ansi-style -//============================================================================ - -#include -#include - -#include "opencv2/bioinspired.hpp" // retina based algorithms -#include "opencv2/imgproc.hpp" // cvCvtcolor function -#include "opencv2/highgui.hpp" // display - -static void help(std::string errorMessage) -{ - std::cout<<"Program init error : "<(i))), - cv::Scalar::all(0), -1, 8, 0 ); - rectangle( displayedCurveImage, cv::Point(0, 0), - cv::Point((lowerLimit)*binW, 200), - cv::Scalar::all(128), -1, 8, 0 ); - rectangle( displayedCurveImage, cv::Point(displayedCurveImage.cols, 0), - cv::Point((upperLimit)*binW, 200), - cv::Scalar::all(128), -1, 8, 0 ); - - cv::imshow(figureTitle, displayedCurveImage); -} -/* - * objective : get the gray level map of the input image and rescale it to the range [0-255] - */ - static void rescaleGrayLevelMat(const cv::Mat &inputMat, cv::Mat &outputMat, const float histogramClippingLimit) - { - - // adjust output matrix wrt the input size but single channel - std::cout<<"Input image rescaling with histogram edges cutting (in order to eliminate bad pixels created during the HDR image creation) :"< image size (h,w,channels) = "< pixel coding (nbchannel, bytes per channel) = "<(0)=normalizedHist.at(0); - int histLowerLimit=0, histUpperLimit=0; - for (int i=1;i(i)=denseProb.at(i-1)+normalizedHist.at(i); - //std::cout<(i)<<", "<(i)<(i)(i)<1-histogramClippingLimit) - histUpperLimit=i; - } - // deduce min and max admitted gray levels - float minInputValue = (float)histLowerLimit/histSize*255; - float maxInputValue = (float)histUpperLimit/histSize*255; - - std::cout<<"=> Histogram limits " - <<"\n\t"< normalizedHist value = "<(histLowerLimit)<<" => input gray level = "< normalizedHist value = "<(histUpperLimit)<<" => input gray level = "< the main application is tone mapping of HDR images (i.e. see on a 8bit display a more than 8bits coded (up to 16bits) image with details in high and low luminance ranges"< It applies a spectral whithening (mid-frequency details enhancement)"< high frequency spatio-temporal noise reduction"< low frequency luminance to be reduced (luminance range compression)"< local logarithmic luminance compression allows details to be enhanced in low light conditions\n"< reports comments/remarks at benoit.alexandre.vision@gmail.com"< more informations and papers at : http://sites.google.com/site/benoitalexandrevision/"< 1. take a set of photos from the same viewpoint using bracketing ***"< 2. generate an OpenEXR image with tools like qtpfsgui.sourceforge.net ***"< 3. apply tone mapping with this program ***"< image size (h,w) = "<8bits linear rescaling ", inputImage); - imshow("EXR image with basic processing : 16bits=>8bits with gamma correction", gammaTransformedImage); - if (inputImage.empty()) - { - help("Input image could not be loaded, aborting"); - return -1; - } - - ////////////////////////////////////////////////////////////////////////////// - // Program start in a try/catch safety context (Retina may throw errors) - try - { - /* create a retina instance with default parameters setup, uncomment the initialisation you wanna test - * -> if the last parameter is 'log', then activate log sampling (favour foveal vision and subsamples peripheral vision) - */ - if (useLogSampling) - { - retina = cv::bioinspired::createRetina(inputImage.size(),true, cv::bioinspired::RETINA_COLOR_BAYER, true, 2.0, 10.0); - } - else// -> else allocate "classical" retina : - retina = cv::bioinspired::createRetina(inputImage.size()); - - // create a fast retina tone mapper (Meyla&al algorithm) - std::cout<<"Allocating fast tone mapper..."< fastToneMapper=createRetinaFastToneMapping(inputImage.size()); - std::cout<<"Fast tone mapper allocated"<write("RetinaDefaultParameters.xml"); - - // desactivate Magnocellular pathway processing (motion information extraction) since it is not usefull here - retina->activateMovingContoursProcessing(false); - - // declare retina output buffers - cv::Mat retinaOutput_parvo; - - ///////////////////////////////////////////// - // prepare displays and interactions - histogramClippingValue=0; // default value... updated with interface slider - //inputRescaleMat = inputImage; - //outputRescaleMat = imageInputRescaled; - cv::namedWindow("Processing configuration",1); - cv::createTrackbar("histogram edges clipping limit", "Processing configuration",&histogramClippingValue,50,callBack_rescaleGrayLevelMat); - - colorSaturationFactor=3; - cv::createTrackbar("Color saturation", "Processing configuration", &colorSaturationFactor,5,callback_saturateColors); - - retinaHcellsGain=40; - cv::createTrackbar("Hcells gain", "Processing configuration",&retinaHcellsGain,100,callBack_updateRetinaParams); - - localAdaptation_photoreceptors=197; - localAdaptation_Gcells=190; - cv::createTrackbar("Ph sensitivity", "Processing configuration", &localAdaptation_photoreceptors,199,callBack_updateRetinaParams); - cv::createTrackbar("Gcells sensitivity", "Processing configuration", &localAdaptation_Gcells,199,callBack_updateRetinaParams); - - - ///////////////////////////////////////////// - // apply default parameters of user interaction variables - rescaleGrayLevelMat(inputImage, imageInputRescaled, (float)histogramClippingValue/100); - retina->setColorSaturation(true,(float)colorSaturationFactor); - callBack_updateRetinaParams(1,NULL); // first call for default parameters setup - - // processing loop with stop condition - bool continueProcessing=true; - while(continueProcessing) - { - // run retina filter - if (!chosenMethod) - { - retina->run(imageInputRescaled); - // Retrieve and display retina output - retina->getParvo(retinaOutput_parvo); - cv::imshow("Retina input image (with cut edges histogram for basic pixels error avoidance)", imageInputRescaled/255.0); - cv::imshow("Retina Parvocellular pathway output : 16bit=>8bit image retina tonemapping", retinaOutput_parvo); - cv::imwrite("HDRinput.jpg",imageInputRescaled/255.0); - cv::imwrite("RetinaToneMapping.jpg",retinaOutput_parvo); - } - else - { - // apply the simplified hdr tone mapping method - cv::Mat fastToneMappingOutput; - retina->applyFastToneMapping(imageInputRescaled, fastToneMappingOutput); - cv::imshow("Retina fast tone mapping output : 16bit=>8bit image retina tonemapping", fastToneMappingOutput); - } - /*cv::Mat fastToneMappingOutput_specificObject; - fastToneMapper->setup(3.f, 1.5f, 1.f); - fastToneMapper->applyFastToneMapping(imageInputRescaled, fastToneMappingOutput_specificObject); - cv::imshow("### Retina fast tone mapping output : 16bit=>8bit image retina tonemapping", fastToneMappingOutput_specificObject); -*/ - cv::waitKey(10); - } - }catch(cv::Exception e) - { - std::cerr<<"Error using Retina : "< a simple method consists of cutting histogram edges (a slider for this on the UI is provided) -// => however, in image sequences, this histogramm cut must be done in an elegant way from frame to frame... still not done... -//============================================================================ - -#include -#include -#include - -#include "opencv2/bioinspired.hpp" // retina based algorithms -#include "opencv2/imgproc.hpp" // cvCvtcolor function -#include "opencv2/highgui.hpp" // display - -#ifndef _CRT_SECURE_NO_WARNINGS -# define _CRT_SECURE_NO_WARNINGS -#endif - -static void help(std::string errorMessage) -{ - std::cout<<"Program init error : "< WARNING : image index number of digits cannot exceed 10"< to process images from memorial020d.exr to memorial045d.exr"<(i))), - cv::Scalar::all(0), -1, 8, 0 ); - rectangle( displayedCurveImage, cv::Point(0, 0), - cv::Point((lowerLimit)*binW, 200), - cv::Scalar::all(128), -1, 8, 0 ); - rectangle( displayedCurveImage, cv::Point(displayedCurveImage.cols, 0), - cv::Point((upperLimit)*binW, 200), - cv::Scalar::all(128), -1, 8, 0 ); - - cv::imshow(figureTitle, displayedCurveImage); -} - -/* - * objective : get the gray level map of the input image and rescale it to the range [0-255] if rescale0_255=TRUE, simply trunks else - */ -static void rescaleGrayLevelMat(const cv::Mat &inputMat, cv::Mat &outputMat, const float histogramClippingLimit, const bool rescale0_255) - { - // adjust output matrix wrt the input size but single channel - std::cout<<"Input image rescaling with histogram edges cutting (in order to eliminate bad pixels created during the HDR image creation) :"< image size (h,w,channels) = "< pixel coding (nbchannel, bytes per channel) = "< scale, offset = "<(0)=normalizedHist.at(0); - int histLowerLimit=0, histUpperLimit=0; - for (int i=1;i(i)=denseProb.at(i-1)+normalizedHist.at(i); - //std::cout<(i)<<", "<(i)<(i)(i)<1.f-histogramClippingLimit) - histUpperLimit=i; - } - // deduce min and max admitted gray levels - float minInputValue = (float)histLowerLimit/histSize*255.f; - float maxInputValue = (float)histUpperLimit/histSize*255.f; - - std::cout<<"=> Histogram limits " - <<"\n\t"< normalizedHist value = "<(histLowerLimit)<<" => input gray level = "< normalizedHist value = "<(histUpperLimit)<<" => input gray level = "< Input Hist clipping values (max,min) = "< image size (h,w) = "< actually using a little less in order to let some more flexibility in range evolves... - */ - double maxInput1, minInput1; - minMaxLoc(inputImage, &minInput1, &maxInput1); - std::cout<<"FIRST IMAGE pixels values range (max,min) : "< the main application is tone mapping of HDR images (i.e. see on a 8bit display a more than 8bits coded (up to 16bits) image with details in high and low luminance ranges"< It applies a spectral whithening (mid-frequency details enhancement)"< high frequency spatio-temporal noise reduction"< low frequency luminance to be reduced (luminance range compression)"< local logarithmic luminance compression allows details to be enhanced in low light conditions\n"< reports comments/remarks at benoit.alexandre.vision@gmail.com"< more informations and papers at : http://sites.google.com/site/benoitalexandrevision/"< 1. take a set of photos from the same viewpoint using bracketing ***"< 2. generate an OpenEXR image with tools like qtpfsgui.sourceforge.net ***"< 3. apply tone mapping with this program ***"< if the last parameter is 'log', then activate log sampling (favour foveal vision and subsamples peripheral vision) - */ - if (useLogSampling) - { - retina = cv::bioinspired::createRetina(inputImage.size(),true, cv::bioinspired::RETINA_COLOR_BAYER, true, 2.0, 10.0); - } - else// -> else allocate "classical" retina : - retina = cv::bioinspired::createRetina(inputImage.size()); - - // save default retina parameters file in order to let you see this and maybe modify it and reload using method "setup" - retina->write("RetinaDefaultParameters.xml"); - - // desactivate Magnocellular pathway processing (motion information extraction) since it is not usefull here - retina->activateMovingContoursProcessing(false); - - // declare retina output buffers - cv::Mat retinaOutput_parvo; - - ///////////////////////////////////////////// - // prepare displays and interactions - histogramClippingValue=0; // default value... updated with interface slider - - std::string retinaInputCorrected("Retina input image (with cut edges histogram for basic pixels error avoidance)"); - cv::namedWindow(retinaInputCorrected,1); - cv::createTrackbar("histogram edges clipping limit", "Retina input image (with cut edges histogram for basic pixels error avoidance)",&histogramClippingValue,50,callBack_rescaleGrayLevelMat); - - std::string RetinaParvoWindow("Retina Parvocellular pathway output : 16bit=>8bit image retina tonemapping"); - cv::namedWindow(RetinaParvoWindow, 1); - colorSaturationFactor=3; - cv::createTrackbar("Color saturation", "Retina Parvocellular pathway output : 16bit=>8bit image retina tonemapping", &colorSaturationFactor,5,callback_saturateColors); - - retinaHcellsGain=40; - cv::createTrackbar("Hcells gain", "Retina Parvocellular pathway output : 16bit=>8bit image retina tonemapping",&retinaHcellsGain,100,callBack_updateRetinaParams); - - localAdaptation_photoreceptors=197; - localAdaptation_Gcells=190; - cv::createTrackbar("Ph sensitivity", "Retina Parvocellular pathway output : 16bit=>8bit image retina tonemapping", &localAdaptation_photoreceptors,199,callBack_updateRetinaParams); - cv::createTrackbar("Gcells sensitivity", "Retina Parvocellular pathway output : 16bit=>8bit image retina tonemapping", &localAdaptation_Gcells,199,callBack_updateRetinaParams); - - std::string powerTransformedInput("EXR image with basic processing : 16bits=>8bits with gamma correction"); - - ///////////////////////////////////////////// - // apply default parameters of user interaction variables - callBack_updateRetinaParams(1,NULL); // first call for default parameters setup - callback_saturateColors(1, NULL); - - // processing loop with stop condition - currentFrameIndex=startFrameIndex; - while(currentFrameIndex <= endFrameIndex) - { - loadNewFrame(inputImageNamePrototype, currentFrameIndex, false); - - if (inputImage.empty()) - { - std::cout<<"Could not load new image (index = "<8bits linear rescaling ", imageInputRescaled); - cv::Mat gammaTransformedImage; - cv::pow(imageInputRescaled, 1./5, gammaTransformedImage); // apply gamma curve: img = img ** (1./5) - imshow(powerTransformedInput, gammaTransformedImage); - // run retina filter - retina->run(imageInputRescaled); - // Retrieve and display retina output - retina->getParvo(retinaOutput_parvo); - cv::imshow(retinaInputCorrected, imageInputRescaled/255.f); - cv::imshow(RetinaParvoWindow, retinaOutput_parvo); - cv::waitKey(4); - // jump to next frame - ++currentFrameIndex; - } - }catch(cv::Exception e) - { - std::cerr<<"Error using Retina : "< -#include - -#include "opencv2/bioinspired.hpp" -#include "opencv2/highgui.hpp" - -static void help(std::string errorMessage) -{ - std::cout<<"Program init error : "< It applies a spectral whithening (mid-frequency details enhancement)"< high frequency spatio-temporal noise reduction"< low frequency luminance to be reduced (luminance range compression)"< local logarithmic luminance compression allows details to be enhanced in low light conditions\n"< reports comments/remarks at benoit.alexandre.vision@gmail.com"< more informations and papers at : http://sites.google.com/site/benoitalexandrevision/"< you can use this to fine tune parameters and load them if you save to file 'RetinaSpecificParameters.xml'"<= 3) - { - std::cout<<"RetinaDemo: processing image "<>inputFrame; - }else - { - // bad command parameter - help("bad command parameter"); - return -1; - } - - if (inputFrame.empty()) - { - help("Input media could not be loaded, aborting"); - return -1; - } - - - ////////////////////////////////////////////////////////////////////////////// - // Program start in a try/catch safety context (Retina may throw errors) - try - { - // create a retina instance with default parameters setup, uncomment the initialisation you wanna test - cv::Ptr myRetina; - - // if the last parameter is 'log', then activate log sampling (favour foveal vision and subsamples peripheral vision) - if (useLogSampling) - { - myRetina = cv::bioinspired::createRetina(inputFrame.size(), true, cv::bioinspired::RETINA_COLOR_BAYER, true, 2.0, 10.0); - } - else// -> else allocate "classical" retina : - myRetina = cv::bioinspired::createRetina(inputFrame.size()); - - // save default retina parameters file in order to let you see this and maybe modify it and reload using method "setup" - myRetina->write("RetinaDefaultParameters.xml"); - - // load parameters if file exists - myRetina->setup("RetinaSpecificParameters.xml"); - myRetina->clearBuffers(); - - // declare retina output buffers - cv::Mat retinaOutput_parvo; - cv::Mat retinaOutput_magno; - - // processing loop with stop condition - bool continueProcessing=true; // FIXME : not yet managed during process... - while(continueProcessing) - { - // if using video stream, then, grabbing a new frame, else, input remains the same - if (videoCapture.isOpened()) - videoCapture>>inputFrame; - - // run retina filter - myRetina->run(inputFrame); - // Retrieve and display retina output - myRetina->getParvo(retinaOutput_parvo); - myRetina->getMagno(retinaOutput_magno); - cv::imshow("retina input", inputFrame); - cv::imshow("Retina Parvo", retinaOutput_parvo); - cv::imshow("Retina Magno", retinaOutput_magno); - - cv::waitKey(5); - } - }catch(cv::Exception e) - { - std::cerr<<"Error using Retina : "< -#include - -#include "opencv2/bioinspired.hpp" -#include "opencv2/highgui.hpp" - -static void help(std::string errorMessage) -{ - std::cout<<"Program init error : "< you can use this to fine tune parameters and load them if you save to file 'RetinaSpecificParameters.xml'"<= 3) - { - std::cout<<"RetinaDemo: processing image "<>inputFrame; - }else - { - // bad command parameter - help("bad command parameter"); - return -1; - } - - if (inputFrame.empty()) - { - help("Input media could not be loaded, aborting"); - return -1; - } - - - ////////////////////////////////////////////////////////////////////////////// - // Program start in a try/catch safety context (Retina may throw errors) - try - { - // create a retina instance with default parameters setup, uncomment the initialisation you wanna test - cv::Ptr myRetina; - - // if the last parameter is 'log', then activate log sampling (favour foveal vision and subsamples peripheral vision) - if (useLogSampling) - { - myRetina = cv::bioinspired::createRetina(inputFrame.size(), true, cv::bioinspired::RETINA_COLOR_BAYER, true, 2.0, 10.0); - } - else// -> else allocate "classical" retina : - { - myRetina = cv::bioinspired::createRetina(inputFrame.size()); - } - - // save default retina parameters file in order to let you see this and maybe modify it and reload using method "setup" - myRetina->write("RetinaDefaultParameters.xml"); - - // load parameters if file exists - myRetina->setup("RetinaSpecificParameters.xml"); - - // reset all retina buffers (imagine you close your eyes for a long time) - myRetina->clearBuffers(); - - // declare retina output buffers - cv::Mat retinaOutput_parvo; - cv::Mat retinaOutput_magno; - - // processing loop with no stop condition - for(;;) - { - // if using video stream, then, grabbing a new frame, else, input remains the same - if (videoCapture.isOpened()) - videoCapture>>inputFrame; - - // run retina filter on the loaded input frame - myRetina->run(inputFrame); - // Retrieve and display retina output - myRetina->getParvo(retinaOutput_parvo); - myRetina->getMagno(retinaOutput_magno); - cv::imshow("retina input", inputFrame); - cv::imshow("Retina Parvo", retinaOutput_parvo); - cv::imshow("Retina Magno", retinaOutput_magno); - cv::waitKey(10); - } - }catch(cv::Exception e) - { - std::cerr<<"Error using Retina or end of video sequence reached : "< -#include - -#include "opencv2/core.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" -#include "opencv2/ocl.hpp" -#include "opencv2/bioinspired.hpp" - -using namespace cv; -using namespace cv::ocl; -using namespace std; - -const int total_loop_count = 50; - -static void help(CommandLineParser cmd, const String& errorMessage) -{ - cout << errorMessage << endl; - cout << "Avaible options:" << endl; - cmd.printMessage(); -} - -int main(int argc, char* argv[]) -{ - //set this to save kernel compile time from second time you run - ocl::setBinaryDiskCache(); - const char* keys = - "{ h | help | false | print help message }" - "{ c | cpu | false | use cpu (original version) or gpu(OpenCL) to process the image }" - "{ i | image | cat.jpg | specify the input image }"; - - CommandLineParser cmd(argc, argv, keys); - - if(cmd.get("help")) - { - help(cmd, "Usage: ./retina_ocl [options]"); - return EXIT_FAILURE; - } - - String fname = cmd.get("i"); - bool useCPU = cmd.get("c"); - - cv::Mat input = imread(fname); - if(input.empty()) - { - help(cmd, "Error opening: " + fname); - return EXIT_FAILURE; - } - ////////////////////////////////////////////////////////////////////////////// - // Program start in a try/catch safety context (Retina may throw errors) - try - { - // create a retina instance with default parameters setup, uncomment the initialisation you wanna test - cv::Ptr oclRetina; - cv::Ptr retina; - // declare retina output buffers - cv::ocl::oclMat retina_parvo_ocl; - cv::ocl::oclMat retina_magno_ocl; - cv::Mat retina_parvo; - cv::Mat retina_magno; - - if(useCPU) - { - retina = cv::bioinspired::createRetina(input.size()); - retina->clearBuffers(); - } - else - { - oclRetina = cv::bioinspired::createRetina_OCL(input.size()); - oclRetina->clearBuffers(); - } - - int64 temp_time = 0, total_time = 0; - - int loop_counter = 0; - for(; loop_counter <= total_loop_count; ++loop_counter) - { - if(useCPU) - { - temp_time = cv::getTickCount(); - retina->run(input); - retina->getParvo(retina_parvo); - retina->getMagno(retina_magno); - } - else - { - cv::ocl::oclMat input_ocl(input); - temp_time = cv::getTickCount(); - oclRetina->run(input_ocl); - oclRetina->getParvo(retina_parvo_ocl); - oclRetina->getMagno(retina_magno_ocl); - } - // will not count the first loop, which is considered as warm-up period - if(loop_counter > 0) - { - temp_time = (cv::getTickCount() - temp_time); - total_time += temp_time; - printf("Frame id %2d: %3.4fms\n", loop_counter, (double)temp_time / cv::getTickFrequency() * 1000.0); - } - if(!useCPU) - { - retina_parvo = retina_parvo_ocl; - retina_magno = retina_magno_ocl; - } - cv::imshow("retina input", input); - cv::imshow("Retina Parvo", retina_parvo); - cv::imshow("Retina Magno", retina_magno); - cv::waitKey(10); - } - printf("Average: %.4fms\n", (double)total_time / total_loop_count / cv::getTickFrequency() * 1000.0); - } - catch(cv::Exception e) - { - std::cerr << "Error using Retina : " << e.what() << std::endl; - } - // Program end message - std::cout << "Retina demo end" << std::endl; - return EXIT_SUCCESS; -} From c1172b83dd0feebd61797afeb508d8a94186d77d Mon Sep 17 00:00:00 2001 From: vbystricky Date: Tue, 21 Jan 2014 18:46:26 +0400 Subject: [PATCH 204/295] Change epsilon value to 0.01 --- modules/video/perf/opencl/perf_optflow_farneback.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/video/perf/opencl/perf_optflow_farneback.cpp b/modules/video/perf/opencl/perf_optflow_farneback.cpp index 2b968aaf4..bbd54cc4d 100644 --- a/modules/video/perf/opencl/perf_optflow_farneback.cpp +++ b/modules/video/perf/opencl/perf_optflow_farneback.cpp @@ -90,7 +90,7 @@ OCL_PERF_TEST_P(FarnebackOpticalFlowFixture, FarnebackOpticalFlow, const double pyrScale = 0.5; int flags = get<1>(params); const bool useInitFlow = get<2>(params); - const double eps = 1.5; + const double eps = 0.01; UMat uFrame0; frame0.copyTo(uFrame0); UMat uFrame1; frame1.copyTo(uFrame1); From 303c37a175ba81dd186880a9458ec1b886e400a3 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 21 Jan 2014 18:47:22 +0400 Subject: [PATCH 205/295] removed TOC --- doc/tutorials/tutorials.rst | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/doc/tutorials/tutorials.rst b/doc/tutorials/tutorials.rst index 8195daf7f..cd58c44e9 100644 --- a/doc/tutorials/tutorials.rst +++ b/doc/tutorials/tutorials.rst @@ -171,21 +171,6 @@ As always, we would be happy to hear your comments and receive your contribution :width: 80pt :alt: gpu icon -* :ref:`Table-Of-Content-Bioinspired` - - .. tabularcolumns:: m{100pt} m{300pt} - .. cssclass:: toctableopencv - - ============= ======================================================= - |Bioinspired| Algorithms inspired from biological models. - - ============= ======================================================= - - .. |Bioinspired| image:: images/retina.jpg - :height: 80pt - :width: 80pt - :alt: gpu icon - * :ref:`Table-Of-Content-iOS` .. tabularcolumns:: m{100pt} m{300pt} From 3177a683e93f9cbaad75e15d023842c535e3d945 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 20 Jan 2014 18:35:32 +0400 Subject: [PATCH 206/295] ported corners to T-API --- modules/imgproc/perf/opencl/perf_imgproc.cpp | 7 +- modules/imgproc/src/corner.cpp | 85 ++++++- modules/imgproc/src/opencl/corner.cl | 227 +++++++++++++++++++ modules/imgproc/test/ocl/test_imgproc.cpp | 19 +- 4 files changed, 312 insertions(+), 26 deletions(-) create mode 100644 modules/imgproc/src/opencl/corner.cl diff --git a/modules/imgproc/perf/opencl/perf_imgproc.cpp b/modules/imgproc/perf/opencl/perf_imgproc.cpp index 7c102fa21..cde3a699f 100644 --- a/modules/imgproc/perf/opencl/perf_imgproc.cpp +++ b/modules/imgproc/perf/opencl/perf_imgproc.cpp @@ -108,12 +108,9 @@ OCL_PERF_TEST_P(CornerMinEigenValFixture, CornerMinEigenVal, UMat src(srcSize, type), dst(srcSize, CV_32FC1); declare.in(src, WARMUP_RNG).out(dst); - const int depth = CV_MAT_DEPTH(type); - const ERROR_TYPE errorType = depth == CV_8U ? ERROR_ABSOLUTE : ERROR_RELATIVE; - OCL_TEST_CYCLE() cv::cornerMinEigenVal(src, dst, blockSize, apertureSize, borderType); - SANITY_CHECK(dst, 1e-6, errorType); + SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); } ///////////// CornerHarris //////////////////////// @@ -132,7 +129,7 @@ OCL_PERF_TEST_P(CornerHarrisFixture, CornerHarris, OCL_TEST_CYCLE() cv::cornerHarris(src, dst, 5, 7, 0.1, borderType); - SANITY_CHECK(dst, 5e-5); + SANITY_CHECK(dst, 5e-6, ERROR_RELATIVE); } ///////////// Integral //////////////////////// diff --git a/modules/imgproc/src/corner.cpp b/modules/imgproc/src/corner.cpp index 8f8c77006..e5d54c682 100644 --- a/modules/imgproc/src/corner.cpp +++ b/modules/imgproc/src/corner.cpp @@ -41,14 +41,12 @@ //M*/ #include "precomp.hpp" -#include - +#include "opencl_kernels.hpp" namespace cv { -static void -calcMinEigenVal( const Mat& _cov, Mat& _dst ) +static void calcMinEigenVal( const Mat& _cov, Mat& _dst ) { int i, j; Size size = _cov.size(); @@ -104,8 +102,7 @@ calcMinEigenVal( const Mat& _cov, Mat& _dst ) } -static void -calcHarris( const Mat& _cov, Mat& _dst, double k ) +static void calcHarris( const Mat& _cov, Mat& _dst, double k ) { int i, j; Size size = _cov.size(); @@ -219,8 +216,7 @@ static void eigen2x2( const float* cov, float* dst, int n ) } } -static void -calcEigenValsVecs( const Mat& _cov, Mat& _dst ) +static void calcEigenValsVecs( const Mat& _cov, Mat& _dst ) { Size size = _cov.size(); if( _cov.isContinuous() && _dst.isContinuous() ) @@ -306,12 +302,77 @@ cornerEigenValsVecs( const Mat& src, Mat& eigenv, int block_size, calcEigenValsVecs( cov, eigenv ); } +static bool ocl_cornerMinEigenValVecs(InputArray _src, OutputArray _dst, int block_size, + int aperture_size, double k, int borderType, int op_type) +{ + CV_Assert(op_type == HARRIS || op_type == MINEIGENVAL); + + if ( !(borderType == BORDER_CONSTANT || borderType == BORDER_REPLICATE || + borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101) ) + return false; + + int type = _src.type(), depth = CV_MAT_DEPTH(type); + double scale = (double)(1 << ((aperture_size > 0 ? aperture_size : 3) - 1)) * block_size; + if( aperture_size < 0 ) + scale *= 2.0; + if( depth == CV_8U ) + scale *= 255.0; + scale = 1.0 / scale; + + if ( !(type == CV_8UC1 || type == CV_32FC1) ) + return false; + + UMat Dx, Dy; + if (aperture_size > 0) + { + Sobel(_src, Dx, CV_32F, 1, 0, aperture_size, scale, 0, borderType); + Sobel(_src, Dy, CV_32F, 0, 1, aperture_size, scale, 0, borderType); + } + else + { + Scharr(_src, Dx, CV_32F, 1, 0, scale, 0, borderType); + Scharr(_src, Dy, CV_32F, 0, 1, scale, 0, borderType); + } + + const char * const borderTypes[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", + 0, "BORDER_REFLECT101" }; + const char * const cornerType[] = { "CORNER_MINEIGENVAL", "CORNER_HARRIS", 0 }; + + ocl::Kernel cornelKernel("corner", ocl::imgproc::corner_oclsrc, + format("-D anX=%d -D anY=%d -D ksX=%d -D ksY=%d -D %s -D %s", + block_size / 2, block_size / 2, block_size, block_size, + borderTypes[borderType], cornerType[op_type])); + if (cornelKernel.empty()) + return false; + + _dst.createSameSize(_src, CV_32FC1); + UMat dst = _dst.getUMat(); + + cornelKernel.args(ocl::KernelArg::ReadOnly(Dx), ocl::KernelArg::ReadOnly(Dy), + ocl::KernelArg::WriteOnly(dst), (float)k); + + size_t blockSizeX = 256, blockSizeY = 1; + size_t gSize = blockSizeX - block_size / 2 * 2; + size_t globalSizeX = (Dx.cols) % gSize == 0 ? Dx.cols / gSize * blockSizeX : (Dx.cols / gSize + 1) * blockSizeX; + size_t rows_per_thread = 2; + size_t globalSizeY = ((Dx.rows + rows_per_thread - 1) / rows_per_thread) % blockSizeY == 0 ? + ((Dx.rows + rows_per_thread - 1) / rows_per_thread) : + (((Dx.rows + rows_per_thread - 1) / rows_per_thread) / blockSizeY + 1) * blockSizeY; + + size_t globalsize[2] = { globalSizeX, globalSizeY }, localsize[2] = { blockSizeX, blockSizeY }; + return cornelKernel.run(2, globalsize, localsize, false); +} + } void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType ) { + if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() && + ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, 0.0, borderType, MINEIGENVAL)) + return; + Mat src = _src.getMat(); - _dst.create( src.size(), CV_32F ); + _dst.create( src.size(), CV_32FC1 ); Mat dst = _dst.getMat(); cornerEigenValsVecs( src, dst, blockSize, ksize, MINEIGENVAL, 0, borderType ); } @@ -319,8 +380,12 @@ void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, in void cv::cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksize, double k, int borderType ) { + if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() && + ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, k, borderType, HARRIS)) + return; + Mat src = _src.getMat(); - _dst.create( src.size(), CV_32F ); + _dst.create( src.size(), CV_32FC1 ); Mat dst = _dst.getMat(); cornerEigenValsVecs( src, dst, blockSize, ksize, HARRIS, k, borderType ); } diff --git a/modules/imgproc/src/opencl/corner.cl b/modules/imgproc/src/opencl/corner.cl new file mode 100644 index 000000000..563cb9808 --- /dev/null +++ b/modules/imgproc/src/opencl/corner.cl @@ -0,0 +1,227 @@ +/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Shengen Yan,yanshengen@gmail.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*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////Macro for border type//////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef BORDER_CONSTANT +#elif defined BORDER_REPLICATE +#define EXTRAPOLATE(x, maxV) \ + { \ + x = max(min(x, maxV - 1), 0); \ + } +#elif defined BORDER_WRAP +#define EXTRAPOLATE(x, maxV) \ + { \ + if (x < 0) \ + x -= ((x - maxV + 1) / maxV) * maxV; \ + if (x >= maxV) \ + x %= maxV; \ + } +#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT101) +#define EXTRAPOLATE_(x, maxV, delta) \ + { \ + if (maxV == 1) \ + x = 0; \ + else \ + do \ + { \ + if ( x < 0 ) \ + x = -x - 1 + delta; \ + else \ + x = maxV - 1 - (x - maxV) - delta; \ + } \ + while (x >= maxV || x < 0); \ + } +#ifdef BORDER_REFLECT +#define EXTRAPOLATE(x, maxV) EXTRAPOLATE_(x, maxV, 0) +#else +#define EXTRAPOLATE(x, maxV) EXTRAPOLATE_(x, maxV, 1) +#endif +#else +#error No extrapolation method +#endif + +#define THREADS 256 + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////calcHarris//////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////// + +__kernel void corner(__global const float * Dx, int dx_step, int dx_offset, int dx_whole_rows, int dx_whole_cols, + __global const float * Dy, int dy_step, int dy_offset, int dy_whole_rows, int dy_whole_cols, + __global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols, float k) +{ + int col = get_local_id(0); + int gX = get_group_id(0); + int gY = get_group_id(1); + int gly = get_global_id(1); + + int dx_x_off = (dx_offset % dx_step) >> 2; + int dx_y_off = dx_offset / dx_step; + int dy_x_off = (dy_offset % dy_step) >> 2; + int dy_y_off = dy_offset / dy_step; + int dst_x_off = (dst_offset % dst_step) >> 2; + int dst_y_off = dst_offset / dst_step; + + int dx_startX = gX * (THREADS-ksX+1) - anX + dx_x_off; + int dx_startY = (gY << 1) - anY + dx_y_off; + int dy_startX = gX * (THREADS-ksX+1) - anX + dy_x_off; + int dy_startY = (gY << 1) - anY + dy_y_off; + int dst_startX = gX * (THREADS-ksX+1) + dst_x_off; + int dst_startY = (gY << 1) + dst_y_off; + + float dx_data[ksY+1],dy_data[ksY+1], data[3][ksY+1]; + __local float temp[6][THREADS]; + +#ifdef BORDER_CONSTANT + for (int i=0; i < ksY+1; i++) + { + bool dx_con = dx_startX+col >= 0 && dx_startX+col < dx_whole_cols && dx_startY+i >= 0 && dx_startY+i < dx_whole_rows; + int indexDx = (dx_startY+i)*(dx_step>>2)+(dx_startX+col); + float dx_s = dx_con ? Dx[indexDx] : 0.0f; + dx_data[i] = dx_s; + + bool dy_con = dy_startX+col >= 0 && dy_startX+col < dy_whole_cols && dy_startY+i >= 0 && dy_startY+i < dy_whole_rows; + int indexDy = (dy_startY+i)*(dy_step>>2)+(dy_startX+col); + float dy_s = dy_con ? Dy[indexDy] : 0.0f; + dy_data[i] = dy_s; + + data[0][i] = dx_data[i] * dx_data[i]; + data[1][i] = dx_data[i] * dy_data[i]; + data[2][i] = dy_data[i] * dy_data[i]; + } +#else + int clamped_col = min(2*dst_cols, col); + for (int i=0; i < ksY+1; i++) + { + int dx_selected_row = dx_startY+i, dx_selected_col = dx_startX+clamped_col; + EXTRAPOLATE(dx_selected_row, dx_whole_rows) + EXTRAPOLATE(dx_selected_col, dx_whole_cols) + dx_data[i] = Dx[dx_selected_row * (dx_step>>2) + dx_selected_col]; + + int dy_selected_row = dy_startY+i, dy_selected_col = dy_startX+clamped_col; + EXTRAPOLATE(dy_selected_row, dy_whole_rows) + EXTRAPOLATE(dy_selected_col, dy_whole_cols) + dy_data[i] = Dy[dy_selected_row * (dy_step>>2) + dy_selected_col]; + + data[0][i] = dx_data[i] * dx_data[i]; + data[1][i] = dx_data[i] * dy_data[i]; + data[2][i] = dy_data[i] * dy_data[i]; + } +#endif + float sum0 = 0.0f, sum1 = 0.0f, sum2 = 0.0f; + for (int i=1; i < ksY; i++) + { + sum0 += data[0][i]; + sum1 += data[1][i]; + sum2 += data[2][i]; + } + + float sum01 = sum0 + data[0][0]; + float sum02 = sum0 + data[0][ksY]; + temp[0][col] = sum01; + temp[1][col] = sum02; + float sum11 = sum1 + data[1][0]; + float sum12 = sum1 + data[1][ksY]; + temp[2][col] = sum11; + temp[3][col] = sum12; + float sum21 = sum2 + data[2][0]; + float sum22 = sum2 + data[2][ksY]; + temp[4][col] = sum21; + temp[5][col] = sum22; + barrier(CLK_LOCAL_MEM_FENCE); + + if (col < (THREADS - (ksX - 1))) + { + col += anX; + int posX = dst_startX - dst_x_off + col - anX; + int posY = (gly << 1); + int till = (ksX + 1)%2; + float tmp_sum[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + for (int k=0; k<6; k++) + { + float temp_sum = 0; + for (int i=-anX; i<=anX - till; i++) + temp_sum += temp[k][col+i]; + tmp_sum[k] = temp_sum; + } + +#ifdef CORNER_HARRIS + if (posX < dst_cols && (posY) < dst_rows) + { + int dst_index = mad24(dst_step, dst_startY, (int)sizeof(float) * (dst_startX + col - anX)); + *(__global float *)(dst + dst_index) = + tmp_sum[0] * tmp_sum[4] - tmp_sum[2] * tmp_sum[2] - k * (tmp_sum[0] + tmp_sum[4]) * (tmp_sum[0] + tmp_sum[4]); + } + if (posX < dst_cols && (posY + 1) < dst_rows) + { + int dst_index = mad24(dst_step, dst_startY + 1, (int)sizeof(float) * (dst_startX + col - anX)); + *(__global float *)(dst + dst_index) = + tmp_sum[1] * tmp_sum[5] - tmp_sum[3] * tmp_sum[3] - k * (tmp_sum[1] + tmp_sum[5]) * (tmp_sum[1] + tmp_sum[5]); + } +#elif defined CORNER_MINEIGENVAL + if (posX < dst_cols && (posY) < dst_rows) + { + int dst_index = mad24(dst_step, dst_startY, (int)sizeof(float) * (dst_startX + col - anX)); + float a = tmp_sum[0] * 0.5f; + float b = tmp_sum[2]; + float c = tmp_sum[4] * 0.5f; + *(__global float *)(dst + dst_index) = (float)((a+c) - sqrt((a-c)*(a-c) + b*b)); + } + if (posX < dst_cols && (posY + 1) < dst_rows) + { + int dst_index = mad24(dst_step, dst_startY + 1, (int)sizeof(float) * (dst_startX + col - anX)); + float a = tmp_sum[1] * 0.5f; + float b = tmp_sum[3]; + float c = tmp_sum[5] * 0.5f; + *(__global float *)(dst + dst_index) = (float)((a+c) - sqrt((a-c)*(a-c) + b*b)); + } +#else +#error "No such corners type" +#endif + } +} diff --git a/modules/imgproc/test/ocl/test_imgproc.cpp b/modules/imgproc/test/ocl/test_imgproc.cpp index 7a6fb393e..2d34d7154 100644 --- a/modules/imgproc/test/ocl/test_imgproc.cpp +++ b/modules/imgproc/test/ocl/test_imgproc.cpp @@ -103,7 +103,7 @@ PARAM_TEST_CASE(ImgprocTestBase, MatType, } }; -////////////////////////////////copyMakeBorder//////////////////////////////////////////// +//////////////////////////////// copyMakeBorder //////////////////////////////////////////// PARAM_TEST_CASE(CopyMakeBorder, MatDepth, // depth Channels, // channels @@ -171,7 +171,7 @@ OCL_TEST_P(CopyMakeBorder, Mat) } } -////////////////////////////////equalizeHist////////////////////////////////////////////// +//////////////////////////////// equalizeHist ////////////////////////////////////////////// typedef ImgprocTestBase EqualizeHist; @@ -188,7 +188,7 @@ OCL_TEST_P(EqualizeHist, Mat) } } -////////////////////////////////cornerMinEigenVal////////////////////////////////////////// +//////////////////////////////// Corners test ////////////////////////////////////////// struct CornerTestBase : public ImgprocTestBase @@ -239,7 +239,7 @@ OCL_TEST_P(CornerMinEigenVal, Mat) } } -////////////////////////////////cornerHarris////////////////////////////////////////// +//////////////////////////////// cornerHarris ////////////////////////////////////////// typedef CornerTestBase CornerHarris; @@ -255,11 +255,11 @@ OCL_TEST_P(CornerHarris, Mat) OCL_OFF(cv::cornerHarris(src_roi, dst_roi, blockSize, apertureSize, k, borderType)); OCL_ON(cv::cornerHarris(usrc_roi, udst_roi, blockSize, apertureSize, k, borderType)); - Near(1e-5, true); + Near(1e-6, true); } } -//////////////////////////////////integral///////////////////////////////////////////////// +////////////////////////////////// integral ///////////////////////////////////////////////// struct Integral : public ImgprocTestBase @@ -331,8 +331,7 @@ OCL_TEST_P(Integral, Mat2) } } -/////////////////////////////////////////////////////////////////////////////////////////////////// -//// threshold +//////////////////////////////////////// threshold ////////////////////////////////////////////// struct Threshold : public ImgprocTestBase @@ -364,9 +363,7 @@ OCL_TEST_P(Threshold, Mat) } } - -///////////////////////////////////////////////////////////////////////////////////////////////////////// -//// CLAHE +/////////////////////////////////////////// CLAHE ////////////////////////////////////////////////// PARAM_TEST_CASE(CLAHETest, Size, double, bool) { From b75cbfde45c00fc956f033d0af7fe6d63312fd33 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 17 Jan 2014 16:30:31 +0400 Subject: [PATCH 207/295] All installed files marked with component names for install customization. --- 3rdparty/libjasper/CMakeLists.txt | 2 +- 3rdparty/libjpeg/CMakeLists.txt | 2 +- 3rdparty/libpng/CMakeLists.txt | 2 +- 3rdparty/libtiff/CMakeLists.txt | 2 +- 3rdparty/openexr/CMakeLists.txt | 2 +- 3rdparty/tbb/CMakeLists.txt | 6 ++--- 3rdparty/zlib/CMakeLists.txt | 2 +- apps/haartraining/CMakeLists.txt | 12 ++++----- apps/traincascade/CMakeLists.txt | 4 +-- cmake/OpenCVDetectAndroidSDK.cmake | 10 +++---- cmake/OpenCVGenAndroidMK.cmake | 2 +- cmake/OpenCVGenConfig.cmake | 26 +++++++++---------- cmake/OpenCVGenHeaders.cmake | 2 +- cmake/OpenCVGenPkgconfig.cmake | 2 +- cmake/OpenCVModule.cmake | 12 ++++----- data/CMakeLists.txt | 8 +++--- doc/CMakeLists.txt | 4 +-- include/CMakeLists.txt | 4 +-- modules/androidcamera/CMakeLists.txt | 2 +- .../camera_wrapper/CMakeLists.txt | 2 +- modules/gpu/CMakeLists.txt | 2 +- modules/highgui/CMakeLists.txt | 2 +- modules/java/CMakeLists.txt | 26 +++++++++---------- modules/python/CMakeLists.txt | 12 ++++----- platforms/android/libinfo/CMakeLists.txt | 2 +- platforms/android/package/CMakeLists.txt | 2 +- platforms/android/service/CMakeLists.txt | 2 +- samples/c/CMakeLists.txt | 4 +-- samples/cpp/CMakeLists.txt | 4 +-- samples/gpu/CMakeLists.txt | 4 +-- samples/gpu/performance/CMakeLists.txt | 2 +- samples/ocl/CMakeLists.txt | 4 +-- 32 files changed, 87 insertions(+), 87 deletions(-) diff --git a/3rdparty/libjasper/CMakeLists.txt b/3rdparty/libjasper/CMakeLists.txt index dda9cd255..7b3dcb08a 100644 --- a/3rdparty/libjasper/CMakeLists.txt +++ b/3rdparty/libjasper/CMakeLists.txt @@ -46,5 +46,5 @@ if(ENABLE_SOLUTION_FOLDERS) endif() if(NOT BUILD_SHARED_LIBS) - ocv_install_target(${JASPER_LIBRARY} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT main) + ocv_install_target(${JASPER_LIBRARY} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) endif() diff --git a/3rdparty/libjpeg/CMakeLists.txt b/3rdparty/libjpeg/CMakeLists.txt index 8d622f24f..02d71ade2 100644 --- a/3rdparty/libjpeg/CMakeLists.txt +++ b/3rdparty/libjpeg/CMakeLists.txt @@ -39,5 +39,5 @@ if(ENABLE_SOLUTION_FOLDERS) endif() if(NOT BUILD_SHARED_LIBS) - ocv_install_target(${JPEG_LIBRARY} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT main) + ocv_install_target(${JPEG_LIBRARY} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) endif() diff --git a/3rdparty/libpng/CMakeLists.txt b/3rdparty/libpng/CMakeLists.txt index 42b6263e5..8d3d5f497 100644 --- a/3rdparty/libpng/CMakeLists.txt +++ b/3rdparty/libpng/CMakeLists.txt @@ -55,5 +55,5 @@ if(ENABLE_SOLUTION_FOLDERS) endif() if(NOT BUILD_SHARED_LIBS) - ocv_install_target(${PNG_LIBRARY} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT main) + ocv_install_target(${PNG_LIBRARY} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) endif() diff --git a/3rdparty/libtiff/CMakeLists.txt b/3rdparty/libtiff/CMakeLists.txt index 6c34fb5e3..addbb5551 100644 --- a/3rdparty/libtiff/CMakeLists.txt +++ b/3rdparty/libtiff/CMakeLists.txt @@ -115,5 +115,5 @@ if(ENABLE_SOLUTION_FOLDERS) endif() if(NOT BUILD_SHARED_LIBS) - ocv_install_target(${TIFF_LIBRARY} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT main) + ocv_install_target(${TIFF_LIBRARY} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) endif() diff --git a/3rdparty/openexr/CMakeLists.txt b/3rdparty/openexr/CMakeLists.txt index 2b11436e1..c4facad2f 100644 --- a/3rdparty/openexr/CMakeLists.txt +++ b/3rdparty/openexr/CMakeLists.txt @@ -62,7 +62,7 @@ if(ENABLE_SOLUTION_FOLDERS) endif() if(NOT BUILD_SHARED_LIBS) - ocv_install_target(IlmImf EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT main) + ocv_install_target(IlmImf EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) endif() set(OPENEXR_INCLUDE_PATHS ${OPENEXR_INCLUDE_PATHS} PARENT_SCOPE) diff --git a/3rdparty/tbb/CMakeLists.txt b/3rdparty/tbb/CMakeLists.txt index 272c195b3..e16f6cd38 100644 --- a/3rdparty/tbb/CMakeLists.txt +++ b/3rdparty/tbb/CMakeLists.txt @@ -248,9 +248,9 @@ if(ENABLE_SOLUTION_FOLDERS) endif() ocv_install_target(tbb EXPORT OpenCVModules - RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT main - LIBRARY DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT main - ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT main + RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT libs + LIBRARY DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT libs + ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev ) # get TBB version diff --git a/3rdparty/zlib/CMakeLists.txt b/3rdparty/zlib/CMakeLists.txt index f1b28fd39..410f2420b 100644 --- a/3rdparty/zlib/CMakeLists.txt +++ b/3rdparty/zlib/CMakeLists.txt @@ -95,5 +95,5 @@ if(ENABLE_SOLUTION_FOLDERS) endif() if(NOT BUILD_SHARED_LIBS) - ocv_install_target(${ZLIB_LIBRARY} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT main) + ocv_install_target(${ZLIB_LIBRARY} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) endif() diff --git a/apps/haartraining/CMakeLists.txt b/apps/haartraining/CMakeLists.txt index cdc280556..d8a3c55c8 100644 --- a/apps/haartraining/CMakeLists.txt +++ b/apps/haartraining/CMakeLists.txt @@ -71,14 +71,14 @@ set_target_properties(opencv_performance PROPERTIES if(INSTALL_CREATE_DISTRIB) if(BUILD_SHARED_LIBS) - install(TARGETS opencv_haartraining RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} CONFIGURATIONS Release COMPONENT main) - install(TARGETS opencv_createsamples RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} CONFIGURATIONS Release COMPONENT main) - install(TARGETS opencv_performance RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} CONFIGURATIONS Release COMPONENT main) + install(TARGETS opencv_haartraining RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} CONFIGURATIONS Release COMPONENT dev) + install(TARGETS opencv_createsamples RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} CONFIGURATIONS Release COMPONENT dev) + install(TARGETS opencv_performance RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} CONFIGURATIONS Release COMPONENT dev) endif() else() - install(TARGETS opencv_haartraining RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT main) - install(TARGETS opencv_createsamples RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT main) - install(TARGETS opencv_performance RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT main) + install(TARGETS opencv_haartraining RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT dev) + install(TARGETS opencv_createsamples RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT dev) + install(TARGETS opencv_performance RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT dev) endif() if(ENABLE_SOLUTION_FOLDERS) diff --git a/apps/traincascade/CMakeLists.txt b/apps/traincascade/CMakeLists.txt index 8f6fbe034..941c0ec71 100644 --- a/apps/traincascade/CMakeLists.txt +++ b/apps/traincascade/CMakeLists.txt @@ -35,8 +35,8 @@ endif() if(INSTALL_CREATE_DISTRIB) if(BUILD_SHARED_LIBS) - install(TARGETS ${the_target} RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} CONFIGURATIONS Release COMPONENT main) + install(TARGETS ${the_target} RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} CONFIGURATIONS Release COMPONENT dev) endif() else() - install(TARGETS ${the_target} RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT main) + install(TARGETS ${the_target} RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT dev) endif() diff --git a/cmake/OpenCVDetectAndroidSDK.cmake b/cmake/OpenCVDetectAndroidSDK.cmake index 393dbb62d..7a37051e4 100644 --- a/cmake/OpenCVDetectAndroidSDK.cmake +++ b/cmake/OpenCVDetectAndroidSDK.cmake @@ -344,20 +344,20 @@ macro(add_android_project target path) add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${android_proj_bin_dir}/bin/${target}-debug.apk" "${OpenCV_BINARY_DIR}/bin/${target}.apk") if(INSTALL_ANDROID_EXAMPLES AND "${target}" MATCHES "^example-") #apk - install(FILES "${OpenCV_BINARY_DIR}/bin/${target}.apk" DESTINATION "samples" COMPONENT main) + install(FILES "${OpenCV_BINARY_DIR}/bin/${target}.apk" DESTINATION "samples" COMPONENT samples) get_filename_component(sample_dir "${path}" NAME) #java part list(REMOVE_ITEM android_proj_files ${ANDROID_MANIFEST_FILE}) foreach(f ${android_proj_files} ${ANDROID_MANIFEST_FILE}) get_filename_component(install_subdir "${f}" PATH) - install(FILES "${android_proj_bin_dir}/${f}" DESTINATION "samples/${sample_dir}/${install_subdir}" COMPONENT main) + install(FILES "${android_proj_bin_dir}/${f}" DESTINATION "samples/${sample_dir}/${install_subdir}" COMPONENT samples) endforeach() #jni part + eclipse files file(GLOB_RECURSE jni_files RELATIVE "${path}" "${path}/jni/*" "${path}/.cproject") ocv_list_filterout(jni_files "\\\\.svn") foreach(f ${jni_files} ".classpath" ".project" ".settings/org.eclipse.jdt.core.prefs") get_filename_component(install_subdir "${f}" PATH) - install(FILES "${path}/${f}" DESTINATION "samples/${sample_dir}/${install_subdir}" COMPONENT main) + install(FILES "${path}/${f}" DESTINATION "samples/${sample_dir}/${install_subdir}" COMPONENT samples) endforeach() #update proj if(android_proj_lib_deps_commands) @@ -365,9 +365,9 @@ macro(add_android_project target path) endif() install(CODE "EXECUTE_PROCESS(COMMAND ${ANDROID_EXECUTABLE} --silent update project --path . --target \"${android_proj_sdk_target}\" --name \"${target}\" ${inst_lib_opt} WORKING_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/samples/${sample_dir}\" - )" COMPONENT main) + )" COMPONENT dev) #empty 'gen' - install(CODE "MAKE_DIRECTORY(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/samples/${sample_dir}/gen\")" COMPONENT main) + install(CODE "MAKE_DIRECTORY(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/samples/${sample_dir}/gen\")" COMPONENT samples) endif() endif() endmacro() diff --git a/cmake/OpenCVGenAndroidMK.cmake b/cmake/OpenCVGenAndroidMK.cmake index eed47652b..45193a273 100644 --- a/cmake/OpenCVGenAndroidMK.cmake +++ b/cmake/OpenCVGenAndroidMK.cmake @@ -116,5 +116,5 @@ if(ANDROID) set(OPENCV_3RDPARTY_LIBS_DIR_CONFIGCMAKE "\$(OPENCV_THIS_DIR)/../3rdparty/libs/\$(OPENCV_TARGET_ARCH_ABI)") configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/OpenCV.mk.in" "${CMAKE_BINARY_DIR}/unix-install/OpenCV.mk" IMMEDIATE @ONLY) - install(FILES ${CMAKE_BINARY_DIR}/unix-install/OpenCV.mk DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}) + install(FILES ${CMAKE_BINARY_DIR}/unix-install/OpenCV.mk DESTINATION ${OPENCV_CONFIG_INSTALL_PATH} COMPONENT dev) endif(ANDROID) diff --git a/cmake/OpenCVGenConfig.cmake b/cmake/OpenCVGenConfig.cmake index 411d22582..18411e878 100644 --- a/cmake/OpenCVGenConfig.cmake +++ b/cmake/OpenCVGenConfig.cmake @@ -109,18 +109,18 @@ if(UNIX) # ANDROID configuration is created here also # /(share|lib)/*/ (U) # /(share|lib)/*/(cmake|CMake)/ (U) if(INSTALL_TO_MANGLED_PATHS) - install(FILES ${CMAKE_BINARY_DIR}/unix-install/OpenCVConfig.cmake DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}-${OPENCV_VERSION}/) - install(FILES ${CMAKE_BINARY_DIR}/unix-install/OpenCVConfig-version.cmake DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}-${OPENCV_VERSION}/) - install(EXPORT OpenCVModules DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}-${OPENCV_VERSION}/ FILE OpenCVModules${modules_file_suffix}.cmake) + install(FILES ${CMAKE_BINARY_DIR}/unix-install/OpenCVConfig.cmake DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}-${OPENCV_VERSION}/ COMPONENT dev) + install(FILES ${CMAKE_BINARY_DIR}/unix-install/OpenCVConfig-version.cmake DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}-${OPENCV_VERSION}/ COMPONENT dev) + install(EXPORT OpenCVModules DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}-${OPENCV_VERSION}/ FILE OpenCVModules${modules_file_suffix}.cmake COMPONENT dev) else() - install(FILES "${CMAKE_BINARY_DIR}/unix-install/OpenCVConfig.cmake" DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/) - install(FILES ${CMAKE_BINARY_DIR}/unix-install/OpenCVConfig-version.cmake DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/) - install(EXPORT OpenCVModules DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/ FILE OpenCVModules${modules_file_suffix}.cmake) + install(FILES "${CMAKE_BINARY_DIR}/unix-install/OpenCVConfig.cmake" DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/ COMPONENT dev) + install(FILES ${CMAKE_BINARY_DIR}/unix-install/OpenCVConfig-version.cmake DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/ COMPONENT dev) + install(EXPORT OpenCVModules DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/ FILE OpenCVModules${modules_file_suffix}.cmake COMPONENT dev) endif() endif() if(ANDROID) - install(FILES "${OpenCV_SOURCE_DIR}/platforms/android/android.toolchain.cmake" DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/) + install(FILES "${OpenCV_SOURCE_DIR}/platforms/android/android.toolchain.cmake" DESTINATION ${OPENCV_CONFIG_INSTALL_PATH}/ COMPONENT dev) endif() # -------------------------------------------------------------------------------------------- @@ -134,12 +134,12 @@ if(WIN32) configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/OpenCVConfig.cmake.in" "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig.cmake" IMMEDIATE @ONLY) configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/OpenCVConfig-version.cmake.in" "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig-version.cmake" IMMEDIATE @ONLY) if(BUILD_SHARED_LIBS) - install(FILES "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig.cmake" DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}lib") - install(EXPORT OpenCVModules DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}lib" FILE OpenCVModules${modules_file_suffix}.cmake) + install(FILES "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig.cmake" DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}lib" COMPONENT dev) + install(EXPORT OpenCVModules DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}lib" FILE OpenCVModules${modules_file_suffix}.cmake COMPONENT dev) else() - install(FILES "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig.cmake" DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}staticlib") - install(EXPORT OpenCVModules DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}staticlib" FILE OpenCVModules${modules_file_suffix}.cmake) + install(FILES "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig.cmake" DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}staticlib" COMPONENT dev) + install(EXPORT OpenCVModules DESTINATION "${OpenCV_INSTALL_BINARIES_PREFIX}staticlib" FILE OpenCVModules${modules_file_suffix}.cmake COMPONENT dev) endif() - install(FILES "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig-version.cmake" DESTINATION "${CMAKE_INSTALL_PREFIX}") - install(FILES "${OpenCV_SOURCE_DIR}/cmake/OpenCVConfig.cmake" DESTINATION "${CMAKE_INSTALL_PREFIX}/") + install(FILES "${CMAKE_BINARY_DIR}/win-install/OpenCVConfig-version.cmake" DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT dev) + install(FILES "${OpenCV_SOURCE_DIR}/cmake/OpenCVConfig.cmake" DESTINATION "${CMAKE_INSTALL_PREFIX}/" COMPONENT dev) endif() diff --git a/cmake/OpenCVGenHeaders.cmake b/cmake/OpenCVGenHeaders.cmake index 35da0fb4b..c892a929c 100644 --- a/cmake/OpenCVGenHeaders.cmake +++ b/cmake/OpenCVGenHeaders.cmake @@ -23,4 +23,4 @@ set(OPENCV_MODULE_DEFINITIONS_CONFIGMAKE "${OPENCV_MODULE_DEFINITIONS_CONFIGMAKE #endforeach() configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/opencv_modules.hpp.in" "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/opencv2/opencv_modules.hpp") -install(FILES "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/opencv2/opencv_modules.hpp" DESTINATION ${OPENCV_INCLUDE_INSTALL_PATH}/opencv2 COMPONENT main) +install(FILES "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/opencv2/opencv_modules.hpp" DESTINATION ${OPENCV_INCLUDE_INSTALL_PATH}/opencv2 COMPONENT dev) diff --git a/cmake/OpenCVGenPkgconfig.cmake b/cmake/OpenCVGenPkgconfig.cmake index cd54f11bf..13b1e4497 100644 --- a/cmake/OpenCVGenPkgconfig.cmake +++ b/cmake/OpenCVGenPkgconfig.cmake @@ -81,5 +81,5 @@ configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/opencv-XXX.pc.in" @ONLY IMMEDIATE) if(UNIX AND NOT ANDROID) - install(FILES ${CMAKE_BINARY_DIR}/unix-install/${OPENCV_PC_FILE_NAME} DESTINATION ${OPENCV_LIB_INSTALL_PATH}/pkgconfig) + install(FILES ${CMAKE_BINARY_DIR}/unix-install/${OPENCV_PC_FILE_NAME} DESTINATION ${OPENCV_LIB_INSTALL_PATH}/pkgconfig COMPONENT dev) endif() diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 3dd749b05..2f90a97f3 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -577,9 +577,9 @@ macro(ocv_create_module) endif() ocv_install_target(${the_module} EXPORT OpenCVModules - RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT main - LIBRARY DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT main - ARCHIVE DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT main + RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT dev + LIBRARY DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT libs + ARCHIVE DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT dev ) # only "public" headers need to be installed @@ -587,7 +587,7 @@ macro(ocv_create_module) foreach(hdr ${OPENCV_MODULE_${the_module}_HEADERS}) string(REGEX REPLACE "^.*opencv2/" "opencv2/" hdr2 "${hdr}") if(hdr2 MATCHES "^(opencv2/.*)/[^/]+.h(..)?$") - install(FILES ${hdr} DESTINATION "${OPENCV_INCLUDE_INSTALL_PATH}/${CMAKE_MATCH_1}" COMPONENT main) + install(FILES ${hdr} DESTINATION "${OPENCV_INCLUDE_INSTALL_PATH}/${CMAKE_MATCH_1}" COMPONENT dev) endif() endforeach() endif() @@ -795,7 +795,7 @@ function(ocv_add_samples) endif() if(WIN32) - install(TARGETS ${the_target} RUNTIME DESTINATION "samples/${module_id}" COMPONENT main) + install(TARGETS ${the_target} RUNTIME DESTINATION "samples/${module_id}" COMPONENT samples) endif() endforeach() endif() @@ -805,7 +805,7 @@ function(ocv_add_samples) file(GLOB sample_files "${samples_path}/*") install(FILES ${sample_files} DESTINATION share/OpenCV/samples/${module_id} - PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT samples) endif() endfunction() diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index 70efd6fd0..48094df40 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -2,9 +2,9 @@ file(GLOB HAAR_CASCADES haarcascades/*.xml) file(GLOB LBP_CASCADES lbpcascades/*.xml) if(ANDROID) - install(FILES ${HAAR_CASCADES} DESTINATION sdk/etc/haarcascades COMPONENT main) - install(FILES ${LBP_CASCADES} DESTINATION sdk/etc/lbpcascades COMPONENT main) + install(FILES ${HAAR_CASCADES} DESTINATION sdk/etc/haarcascades COMPONENT libs) + install(FILES ${LBP_CASCADES} DESTINATION sdk/etc/lbpcascades COMPONENT libs) elseif(NOT WIN32) - install(FILES ${HAAR_CASCADES} DESTINATION share/OpenCV/haarcascades COMPONENT main) - install(FILES ${LBP_CASCADES} DESTINATION share/OpenCV/lbpcascades COMPONENT main) + install(FILES ${HAAR_CASCADES} DESTINATION share/OpenCV/haarcascades COMPONENT libs) + install(FILES ${LBP_CASCADES} DESTINATION share/OpenCV/lbpcascades COMPONENT libs) endif() diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 5793f7298..3557a2bd2 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -143,11 +143,11 @@ if(BUILD_DOCS AND HAVE_SPHINX) endif() foreach(f ${DOC_LIST}) - install(FILES "${f}" DESTINATION "${OPENCV_DOC_INSTALL_PATH}" COMPONENT main) + install(FILES "${f}" DESTINATION "${OPENCV_DOC_INSTALL_PATH}" COMPONENT docs) endforeach() foreach(f ${OPTIONAL_DOC_LIST}) - install(FILES "${f}" DESTINATION "${OPENCV_DOC_INSTALL_PATH}" OPTIONAL) + install(FILES "${f}" DESTINATION "${OPENCV_DOC_INSTALL_PATH}" OPTIONAL COMPONENT docs) endforeach() endif() diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index ed3b85a8f..b4e48e6fa 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB old_hdrs "opencv/*.h*") install(FILES ${old_hdrs} DESTINATION ${OPENCV_INCLUDE_INSTALL_PATH}/opencv - COMPONENT main) + COMPONENT dev) install(FILES "opencv2/opencv.hpp" DESTINATION ${OPENCV_INCLUDE_INSTALL_PATH}/opencv2 - COMPONENT main) + COMPONENT dev) diff --git a/modules/androidcamera/CMakeLists.txt b/modules/androidcamera/CMakeLists.txt index 8ac8ced88..3858ba9f6 100644 --- a/modules/androidcamera/CMakeLists.txt +++ b/modules/androidcamera/CMakeLists.txt @@ -40,6 +40,6 @@ else() get_filename_component(wrapper_name "${wrapper}" NAME) install(FILES "${LIBRARY_OUTPUT_PATH}/${wrapper_name}" DESTINATION ${OPENCV_LIB_INSTALL_PATH} - COMPONENT main) + COMPONENT libs) endforeach() endif() diff --git a/modules/androidcamera/camera_wrapper/CMakeLists.txt b/modules/androidcamera/camera_wrapper/CMakeLists.txt index 21b9ee1ad..bc5585a7a 100644 --- a/modules/androidcamera/camera_wrapper/CMakeLists.txt +++ b/modules/androidcamera/camera_wrapper/CMakeLists.txt @@ -63,4 +63,4 @@ if (NOT (CMAKE_BUILD_TYPE MATCHES "debug")) endif() -install(TARGETS ${the_target} LIBRARY DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT main) +install(TARGETS ${the_target} LIBRARY DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT libs) diff --git a/modules/gpu/CMakeLists.txt b/modules/gpu/CMakeLists.txt index 9171febc7..6de3e0efa 100644 --- a/modules/gpu/CMakeLists.txt +++ b/modules/gpu/CMakeLists.txt @@ -82,7 +82,7 @@ ocv_create_module(${cuda_link_libs}) if(HAVE_CUDA) install(FILES src/nvidia/NPP_staging/NPP_staging.hpp src/nvidia/core/NCV.hpp DESTINATION ${OPENCV_INCLUDE_INSTALL_PATH}/opencv2/${name} - COMPONENT main) + COMPONENT dev) endif() ocv_add_precompiled_headers(${the_module}) diff --git a/modules/highgui/CMakeLists.txt b/modules/highgui/CMakeLists.txt index fd2eec6a1..7d2547bcf 100644 --- a/modules/highgui/CMakeLists.txt +++ b/modules/highgui/CMakeLists.txt @@ -315,7 +315,7 @@ if(WIN32 AND WITH_FFMPEG) COMMENT "Copying ${ffmpeg_path} to the output directory") endif() - install(FILES "${ffmpeg_path}" DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT main RENAME "${ffmpeg_bare_name_ver}") + install(FILES "${ffmpeg_path}" DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT libs RENAME "${ffmpeg_bare_name_ver}") endif() ocv_add_accuracy_tests() diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index 3a6ebe836..198048ebe 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -175,7 +175,7 @@ foreach(java_file ${step3_input_files}) if(ANDROID) get_filename_component(install_subdir "${java_file_name}" PATH) - install(FILES "${output_name}" DESTINATION "${JAVA_INSTALL_ROOT}/src/org/opencv/${install_subdir}" COMPONENT main) + install(FILES "${output_name}" DESTINATION "${JAVA_INSTALL_ROOT}/src/org/opencv/${install_subdir}" COMPONENT java) endif() endforeach() @@ -189,7 +189,7 @@ if(ANDROID) if(NOT file MATCHES "jni/.+") get_filename_component(install_subdir "${file}" PATH) - install(FILES "${OpenCV_BINARY_DIR}/${file}" DESTINATION "${JAVA_INSTALL_ROOT}/${install_subdir}" COMPONENT main) + install(FILES "${OpenCV_BINARY_DIR}/${file}" DESTINATION "${JAVA_INSTALL_ROOT}/${install_subdir}" COMPONENT java) endif() endforeach() @@ -225,11 +225,11 @@ if(ANDROID AND ANDROID_EXECUTABLE) list(APPEND copied_files ${lib_target_files} "${OpenCV_BINARY_DIR}/${ANDROID_MANIFEST_FILE}") list(APPEND step3_input_files "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}") - install(FILES "${OpenCV_BINARY_DIR}/${ANDROID_PROJECT_PROPERTIES_FILE}" DESTINATION ${JAVA_INSTALL_ROOT} COMPONENT main) - install(FILES "${OpenCV_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" DESTINATION ${JAVA_INSTALL_ROOT} COMPONENT main) + install(FILES "${OpenCV_BINARY_DIR}/${ANDROID_PROJECT_PROPERTIES_FILE}" DESTINATION ${JAVA_INSTALL_ROOT} COMPONENT java) + install(FILES "${OpenCV_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" DESTINATION ${JAVA_INSTALL_ROOT} COMPONENT java) # creating empty 'gen' and 'res' folders - install(CODE "MAKE_DIRECTORY(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${JAVA_INSTALL_ROOT}/gen\")" COMPONENT main) - install(CODE "MAKE_DIRECTORY(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${JAVA_INSTALL_ROOT}/res\")" COMPONENT main) + install(CODE "MAKE_DIRECTORY(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${JAVA_INSTALL_ROOT}/gen\")" COMPONENT java) + install(CODE "MAKE_DIRECTORY(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${JAVA_INSTALL_ROOT}/res\")" COMPONENT java) endif(ANDROID AND ANDROID_EXECUTABLE) set(step3_depends ${step2_depends} ${step3_input_files} ${copied_files}) @@ -282,7 +282,7 @@ else(ANDROID) else(WIN32) set(JAR_INSTALL_DIR share/OpenCV/java) endif(WIN32) - install(FILES ${JAR_FILE} DESTINATION ${JAR_INSTALL_DIR} COMPONENT main) + install(FILES ${JAR_FILE} DESTINATION ${JAR_INSTALL_DIR} COMPONENT java) endif(ANDROID) # step 5: build native part @@ -353,17 +353,17 @@ endif() if(ANDROID) ocv_install_target(${the_module} EXPORT OpenCVModules - LIBRARY DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT main - ARCHIVE DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT main) + LIBRARY DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT java + ARCHIVE DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT java) else() if(NOT INSTALL_CREATE_DISTRIB) ocv_install_target(${the_module} EXPORT OpenCVModules - RUNTIME DESTINATION ${JAR_INSTALL_DIR} COMPONENT main - LIBRARY DESTINATION ${JAR_INSTALL_DIR} COMPONENT main) + RUNTIME DESTINATION ${JAR_INSTALL_DIR} COMPONENT java + LIBRARY DESTINATION ${JAR_INSTALL_DIR} COMPONENT java) else() ocv_install_target(${the_module} EXPORT OpenCVModules - RUNTIME DESTINATION ${JAR_INSTALL_DIR}/${OpenCV_ARCH} COMPONENT main - LIBRARY DESTINATION ${JAR_INSTALL_DIR}/${OpenCV_ARCH} COMPONENT main) + RUNTIME DESTINATION ${JAR_INSTALL_DIR}/${OpenCV_ARCH} COMPONENT java + LIBRARY DESTINATION ${JAR_INSTALL_DIR}/${OpenCV_ARCH} COMPONENT java) endif() endif() diff --git a/modules/python/CMakeLists.txt b/modules/python/CMakeLists.txt index 2c44a3906..bab8b061b 100644 --- a/modules/python/CMakeLists.txt +++ b/modules/python/CMakeLists.txt @@ -108,17 +108,17 @@ endif() if(WIN32) set(PYTHON_INSTALL_ARCHIVE "") else() - set(PYTHON_INSTALL_ARCHIVE ARCHIVE DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT main) + set(PYTHON_INSTALL_ARCHIVE ARCHIVE DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python) endif() if(NOT INSTALL_CREATE_DISTRIB) install(TARGETS ${the_module} ${PYTHON_INSTALL_CONFIGURATIONS} - RUNTIME DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT main - LIBRARY DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT main + RUNTIME DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python + LIBRARY DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python ${PYTHON_INSTALL_ARCHIVE} ) - install(FILES src2/cv.py ${PYTHON_INSTALL_CONFIGURATIONS} DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT main) + install(FILES src2/cv.py ${PYTHON_INSTALL_CONFIGURATIONS} DESTINATION ${PYTHON_PACKAGES_PATH} COMPONENT python) else() if(DEFINED PYTHON_VERSION_MAJOR) set(__ver "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}") @@ -127,7 +127,7 @@ else() endif() install(TARGETS ${the_module} CONFIGURATIONS Release - RUNTIME DESTINATION python/${__ver}/${OpenCV_ARCH} COMPONENT main - LIBRARY DESTINATION python/${__ver}/${OpenCV_ARCH} COMPONENT main + RUNTIME DESTINATION python/${__ver}/${OpenCV_ARCH} COMPONENT python + LIBRARY DESTINATION python/${__ver}/${OpenCV_ARCH} COMPONENT python ) endif() diff --git a/platforms/android/libinfo/CMakeLists.txt b/platforms/android/libinfo/CMakeLists.txt index 028413ec6..55dd27859 100644 --- a/platforms/android/libinfo/CMakeLists.txt +++ b/platforms/android/libinfo/CMakeLists.txt @@ -36,4 +36,4 @@ set_target_properties(${the_module} PROPERTIES ) get_filename_component(lib_name "libopencv_info.so" NAME) -install(FILES "${LIBRARY_OUTPUT_PATH}/${lib_name}" DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT main) +install(FILES "${LIBRARY_OUTPUT_PATH}/${lib_name}" DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT libs) diff --git a/platforms/android/package/CMakeLists.txt b/platforms/android/package/CMakeLists.txt index 1382a078c..b48a55a6a 100644 --- a/platforms/android/package/CMakeLists.txt +++ b/platforms/android/package/CMakeLists.txt @@ -89,6 +89,6 @@ add_custom_command( DEPENDS "${OpenCV_BINARY_DIR}/bin/classes.jar.dephelper" "${PACKAGE_DIR}/res/values/strings.xml" "${PACKAGE_DIR}/res/drawable/icon.png" ${camera_wrappers} opencv_java ) -install(FILES "${APK_NAME}" DESTINATION "apk/" COMPONENT main) +install(FILES "${APK_NAME}" DESTINATION "apk/" COMPONENT libs) add_custom_target(android_package ALL SOURCES "${APK_NAME}" ) add_dependencies(android_package opencv_java) diff --git a/platforms/android/service/CMakeLists.txt b/platforms/android/service/CMakeLists.txt index dde145513..c99b71392 100644 --- a/platforms/android/service/CMakeLists.txt +++ b/platforms/android/service/CMakeLists.txt @@ -3,4 +3,4 @@ if(BUILD_ANDROID_SERVICE) #add_subdirectory(engine_test) endif() -install(FILES "readme.txt" DESTINATION "apk/" COMPONENT main) +install(FILES "readme.txt" DESTINATION "apk/" COMPONENT libs) diff --git a/samples/c/CMakeLists.txt b/samples/c/CMakeLists.txt index 77a42949d..ab6e15dbf 100644 --- a/samples/c/CMakeLists.txt +++ b/samples/c/CMakeLists.txt @@ -39,7 +39,7 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND) set_target_properties(${the_target} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /DEBUG") endif() install(TARGETS ${the_target} - RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/c" COMPONENT main) + RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/c" COMPONENT samples) endif() ENDMACRO() @@ -55,5 +55,5 @@ if (INSTALL_C_EXAMPLES AND NOT WIN32) file(GLOB C_SAMPLES *.c *.cpp *.jpg *.png *.data makefile.* build_all.sh *.dsp *.cmd ) install(FILES ${C_SAMPLES} DESTINATION share/OpenCV/samples/c - PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT samples) endif () diff --git a/samples/cpp/CMakeLists.txt b/samples/cpp/CMakeLists.txt index ebee5bd0a..e0842d9e4 100644 --- a/samples/cpp/CMakeLists.txt +++ b/samples/cpp/CMakeLists.txt @@ -68,7 +68,7 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND) set_target_properties(${the_target} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /DEBUG") endif() install(TARGETS ${the_target} - RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/${sample_subfolder}" COMPONENT main) + RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/${sample_subfolder}" COMPONENT samples) endif() ENDMACRO() @@ -92,5 +92,5 @@ if (INSTALL_C_EXAMPLES AND NOT WIN32) file(GLOB C_SAMPLES *.c *.cpp *.jpg *.png *.data makefile.* build_all.sh *.dsp *.cmd ) install(FILES ${C_SAMPLES} DESTINATION share/OpenCV/samples/cpp - PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT samples) endif() diff --git a/samples/gpu/CMakeLists.txt b/samples/gpu/CMakeLists.txt index 732a9172a..7093cf5d1 100644 --- a/samples/gpu/CMakeLists.txt +++ b/samples/gpu/CMakeLists.txt @@ -65,7 +65,7 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND) if(MSVC AND NOT BUILD_SHARED_LIBS) set_target_properties(${the_target} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /DEBUG") endif() - install(TARGETS ${the_target} RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/${project}" COMPONENT main) + install(TARGETS ${the_target} RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/${project}" COMPONENT samples) endif() ENDMACRO() @@ -84,5 +84,5 @@ if (INSTALL_C_EXAMPLES AND NOT WIN32) file(GLOB install_list *.c *.cpp *.jpg *.png *.data makefile.* build_all.sh *.dsp *.cmd ) install(FILES ${install_list} DESTINATION share/OpenCV/samples/${project} - PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT samples) endif() diff --git a/samples/gpu/performance/CMakeLists.txt b/samples/gpu/performance/CMakeLists.txt index 8f3caac5b..0b2346f91 100644 --- a/samples/gpu/performance/CMakeLists.txt +++ b/samples/gpu/performance/CMakeLists.txt @@ -23,7 +23,7 @@ if(ENABLE_SOLUTION_FOLDERS) endif() if(WIN32) - install(TARGETS ${the_target} RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/gpu" COMPONENT main) + install(TARGETS ${the_target} RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/gpu" COMPONENT samples) endif() if(INSTALL_C_EXAMPLES AND NOT WIN32) diff --git a/samples/ocl/CMakeLists.txt b/samples/ocl/CMakeLists.txt index 8db77d52c..413921100 100644 --- a/samples/ocl/CMakeLists.txt +++ b/samples/ocl/CMakeLists.txt @@ -38,7 +38,7 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND) if(MSVC AND NOT BUILD_SHARED_LIBS) set_target_properties(${the_target} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /DEBUG") endif() - install(TARGETS ${the_target} RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/${project}" COMPONENT main) + install(TARGETS ${the_target} RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/${project}" COMPONENT samples) endif() ENDMACRO() @@ -55,5 +55,5 @@ if (INSTALL_C_EXAMPLES AND NOT WIN32) file(GLOB install_list *.c *.cpp *.jpg *.png *.data makefile.* build_all.sh *.dsp *.cmd ) install(FILES ${install_list} DESTINATION share/OpenCV/samples/${project} - PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT samples) endif() From 7821fe2bde331c6b1abd612315ca9fc59da58619 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Sat, 18 Jan 2014 23:50:07 +0400 Subject: [PATCH 208/295] Initial Linux packages build rools for CPack. --- CMakeLists.txt | 6 +++ LICENSE | 33 ++++++++++++++ cmake/OpenCVModule.cmake | 2 +- cmake/OpenCVPackaging.cmake | 89 +++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 LICENSE create mode 100644 cmake/OpenCVPackaging.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index d7db8fd13..eb25cd347 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -975,3 +975,9 @@ ocv_finalize_status() if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") message(WARNING "The source directory is the same as binary directory. \"make clean\" may damage the source tree") endif() + +# ---------------------------------------------------------------------------- +# CPack stuff +# ---------------------------------------------------------------------------- + +include(cmake/OpenCVPackaging.cmake) diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..5e32d88b4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,33 @@ +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 + (3-clause BSD License) + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions 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. + + * Neither the names of the copyright holders nor the names of the contributors + may 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 copyright holders 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. diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 2f90a97f3..6734462fc 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -577,7 +577,7 @@ macro(ocv_create_module) endif() ocv_install_target(${the_module} EXPORT OpenCVModules - RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT dev + RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT libs LIBRARY DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT libs ARCHIVE DESTINATION ${OPENCV_LIB_INSTALL_PATH} COMPONENT dev ) diff --git a/cmake/OpenCVPackaging.cmake b/cmake/OpenCVPackaging.cmake new file mode 100644 index 000000000..4a81c255b --- /dev/null +++ b/cmake/OpenCVPackaging.cmake @@ -0,0 +1,89 @@ +if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") +set(CPACK_set_DESTDIR "on") + +if(NOT OPENCV_CUSTOM_PACKAGE_INFO) + set(CPACK_PACKAGE_DESCRIPTION "Open Computer Vision Library") + set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "OpenCV") + set(CPACK_PACKAGE_VENDOR "OpenCV Foundation") + set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") + set(CPACK_PACKAGE_CONTACT "admin@opencv.org") +endif(NOT OPENCV_CUSTOM_PACKAGE_INFO) + +set(CPACK_PACKAGE_VERSION_MAJOR "${OPENCV_VERSION_MAJOR}") +set(CPACK_PACKAGE_VERSION_MINOR "${OPENCV_VERSION_MINOR}") +set(CPACK_PACKAGE_VERSION_PATCH "${OPENCV_VERSION_PATCH}") + +#arch +if(X86) + set(CPACK_DEBIAN_ARCHITECTURE "i386") + set(CPACK_RPM_PACKAGE_ARCHITECTURE "i686") +elseif(X86_64) + set(CPACK_DEBIAN_ARCHITECTURE "amd64") + set(CPACK_RPM_PACKAGE_ARCHITECTURE "amd64") +elseif(ARM) + set(CPACK_DEBIAN_ARCHITECTURE "armhf") + set(CPACK_RPM_PACKAGE_ARCHITECTURE "armhf") +else() + set(CPACK_DEBIAN_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) + set(CPACK_RPM_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) +endif() + +if(CPACK_GENERATOR STREQUAL "DEB") + set(OPENCV_PACKAGE_ARCH_SUFFIX ${CPACK_DEBIAN_ARCHITECTURE}) +elseif(CPACK_GENERATOR STREQUAL "RPM") + set(OPENCV_PACKAGE_ARCH_SUFFIX ${CPACK_RPM_PACKAGE_ARCHITECTURE}) +else() + set(OPENCV_PACKAGE_ARCH_SUFFIX ${CMAKE_SYSTEM_PROCESSOR}) +endif() + +set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${OPENCV_VCSVERSION}-${OPENCV_PACKAGE_ARCH_SUFFIX}") +set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${OPENCV_VCSVERSION}-${OPENCV_PACKAGE_ARCH_SUFFIX}") + +#rpm options +set(CPACK_RPM_COMPONENT_INSTALL TRUE) +set(CPACK_RPM_PACKAGE_LICENSE ${CPACK_RESOURCE_FILE_LICENSE}) + +#deb options +set(CPACK_DEB_COMPONENT_INSTALL TRUE) +set(CPACK_DEBIAN_PACKAGE_PRIORITY "extra") + +#depencencies +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS TRUE) +set(CPACK_COMPONENT_samples_DEPENDS libs) +set(CPACK_COMPONENT_dev_DEPENDS libs) +set(CPACK_COMPONENT_docs_DEPENDS libs) +set(CPACK_COMPONENT_java_DEPENDS libs) +set(CPACK_COMPONENT_python_DEPENDS libs) + +if(NOT OPENCV_CUSTOM_PACKAGE_INFO) + set(CPACK_COMPONENT_libs_DISPLAY_NAME "lib${CMAKE_PROJECT_NAME}") + set(CPACK_COMPONENT_libs_DESCRIPTION "Open Computer Vision Library") + + set(CPACK_COMPONENT_python_DISPLAY_NAME "lib${CMAKE_PROJECT_NAME}-python") + set(CPACK_COMPONENT_python_DESCRIPTION "Python bindings for Open Computer Vision Library") + + set(CPACK_COMPONENT_java_DISPLAY_NAME "lib${CMAKE_PROJECT_NAME}-java") + set(CPACK_COMPONENT_java_DESCRIPTION "Java bindings for Open Computer Vision Library") + + set(CPACK_COMPONENT_dev_DISPLAY_NAME "lib${CMAKE_PROJECT_NAME}-dev") + set(CPACK_COMPONENT_dev_DESCRIPTION "Development files for Open Computer Vision Library") + + set(CPACK_COMPONENT_docs_DISPLAY_NAME "lib${CMAKE_PROJECT_NAME}-docs") + set(CPACK_COMPONENT_docs_DESCRIPTION "Documentation for Open Computer Vision Library") + + set(CPACK_COMPONENT_samples_DISPLAY_NAME "lib${CMAKE_PROJECT_NAME}-samples") + set(CPACK_COMPONENT_samples_DESCRIPTION "Samples for Open Computer Vision Library") +endif(NOT OPENCV_CUSTOM_PACKAGE_INFO) + +if(NOT OPENCV_CUSTOM_PACKAGE_LAYOUT) + set(CPACK_libs_COMPONENT_INSTALL TRUE) + set(CPACK_dev_COMPONENT_INSTALL TRUE) + set(CPACK_docs_COMPONENT_INSTALL TRUE) + set(CPACK_python_COMPONENT_INSTALL TRUE) + set(CPACK_java_COMPONENT_INSTALL TRUE) + set(CPACK_samples_COMPONENT_INSTALL TRUE) +endif(NOT OPENCV_CUSTOM_PACKAGE_LAYOUT) + +include(CPack) + +ENDif(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") \ No newline at end of file From e0c6377d58e229b741e67d8121ee348cce09bef1 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Wed, 22 Jan 2014 10:34:27 +0400 Subject: [PATCH 209/295] Change the sanity checking type to ERROR_RELATIVE --- modules/video/perf/opencl/perf_optflow_farneback.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/video/perf/opencl/perf_optflow_farneback.cpp b/modules/video/perf/opencl/perf_optflow_farneback.cpp index bbd54cc4d..a17ed4dd9 100644 --- a/modules/video/perf/opencl/perf_optflow_farneback.cpp +++ b/modules/video/perf/opencl/perf_optflow_farneback.cpp @@ -90,7 +90,7 @@ OCL_PERF_TEST_P(FarnebackOpticalFlowFixture, FarnebackOpticalFlow, const double pyrScale = 0.5; int flags = get<1>(params); const bool useInitFlow = get<2>(params); - const double eps = 0.01; + const double eps = 0.1; UMat uFrame0; frame0.copyTo(uFrame0); UMat uFrame1; frame1.copyTo(uFrame1); @@ -106,7 +106,7 @@ OCL_PERF_TEST_P(FarnebackOpticalFlowFixture, FarnebackOpticalFlow, cv::calcOpticalFlowFarneback(uFrame0, uFrame1, uFlow, pyrScale, numLevels, winSize, numIters, polyN, polySigma, flags); - SANITY_CHECK(uFlow, eps); + SANITY_CHECK(uFlow, eps, ERROR_RELATIVE); } } } // namespace cvtest::ocl From dda999545c9dd1cca56081a4b2d56755210b840a Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Wed, 22 Jan 2014 10:40:14 +0400 Subject: [PATCH 210/295] fix GpuMat::copyTo method with mask: fill destination matrix with zeros if it was reallocated --- modules/core/src/gpumat.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/core/src/gpumat.cpp b/modules/core/src/gpumat.cpp index ec26801dd..96691919f 100644 --- a/modules/core/src/gpumat.cpp +++ b/modules/core/src/gpumat.cpp @@ -620,11 +620,19 @@ void cv::gpu::GpuMat::copyTo(GpuMat& m) const void cv::gpu::GpuMat::copyTo(GpuMat& mat, const GpuMat& mask) const { if (mask.empty()) + { copyTo(mat); + } else { + uchar* data0 = mat.data; + mat.create(size(), type()); + // do not leave dst uninitialized + if (mat.data != data0) + mat.setTo(Scalar::all(0)); + gpuFuncTable()->copyWithMask(*this, mat, mask); } } From 059e6e43056a3eba051c8711d63d379df95d01a7 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 22 Jan 2014 13:40:48 +0400 Subject: [PATCH 211/295] fixed cv::sepFilter2D --- modules/imgproc/src/filter.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 00e633a7a..a94d99a3b 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -3510,8 +3510,8 @@ static bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, return false; int type = _src.type(); - if ((CV_8UC1 != type) && (CV_8UC4 == type) && - (CV_32FC1 != type) && (CV_32FC4 == type)) + if ( !( (CV_8UC1 == type || CV_8UC4 == type || CV_32FC1 == type || CV_32FC4 == type) && + (ddepth == CV_32F || ddepth == CV_8U) ) ) return false; int cn = CV_MAT_CN(type); @@ -3531,8 +3531,6 @@ static bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, if( ddepth < 0 ) ddepth = sdepth; - else if (ddepth != sdepth) - return false; UMat src = _src.getUMat(); Size srcWholeSize; Point srcOffset; @@ -3541,9 +3539,7 @@ static bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, (0 != (src.cols % 4)) || (0 != ((src.step / src.elemSize()) % 4)) ) - { return false; - } Size srcSize = src.size(); Size bufSize(srcSize.width, srcSize.height + kernelY.cols - 1); @@ -3723,7 +3719,7 @@ void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, double delta, int borderType ) { bool use_opencl = ocl::useOpenCL() && _dst.isUMat(); - if( use_opencl && ocl_sepFilter2D(_src, _dst, ddepth, _kernelX, _kernelY, anchor, delta, borderType)) + if (use_opencl && ocl_sepFilter2D(_src, _dst, ddepth, _kernelX, _kernelY, anchor, delta, borderType)) return; Mat src = _src.getMat(), kernelX = _kernelX.getMat(), kernelY = _kernelY.getMat(); From d2ffd8ed211c3ce814e7b1f37faee67080844596 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 20 Jan 2014 18:35:32 +0400 Subject: [PATCH 212/295] implemented OpenCL version of cv::preCornerDetect --- modules/imgproc/perf/opencl/perf_imgproc.cpp | 19 +++++ modules/imgproc/src/corner.cpp | 43 ++++++++++- modules/imgproc/src/opencl/precornerdetect.cl | 75 +++++++++++++++++++ modules/imgproc/test/ocl/test_imgproc.cpp | 28 ++++++- 4 files changed, 160 insertions(+), 5 deletions(-) create mode 100644 modules/imgproc/src/opencl/precornerdetect.cl diff --git a/modules/imgproc/perf/opencl/perf_imgproc.cpp b/modules/imgproc/perf/opencl/perf_imgproc.cpp index 6f0e46365..8d4b5c2cd 100644 --- a/modules/imgproc/perf/opencl/perf_imgproc.cpp +++ b/modules/imgproc/perf/opencl/perf_imgproc.cpp @@ -132,6 +132,25 @@ OCL_PERF_TEST_P(CornerHarrisFixture, CornerHarris, SANITY_CHECK(dst, 5e-6, ERROR_RELATIVE); } +///////////// PreCornerDetect //////////////////////// + +typedef Size_MatType PreCornerDetectFixture; + +OCL_PERF_TEST_P(PreCornerDetectFixture, PreCornerDetect, + ::testing::Combine(OCL_TEST_SIZES, OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), borderType = BORDER_REFLECT; + + UMat src(srcSize, type), dst(srcSize, CV_32FC1); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::preCornerDetect(src, dst, 3, borderType); + + SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); +} + ///////////// Integral //////////////////////// typedef tuple IntegralParams; diff --git a/modules/imgproc/src/corner.cpp b/modules/imgproc/src/corner.cpp index e5d54c682..fe7648191 100644 --- a/modules/imgproc/src/corner.cpp +++ b/modules/imgproc/src/corner.cpp @@ -363,6 +363,36 @@ static bool ocl_cornerMinEigenValVecs(InputArray _src, OutputArray _dst, int blo return cornelKernel.run(2, globalsize, localsize, false); } +static bool ocl_preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int borderType, int depth ) +{ + UMat Dx, Dy, D2x, D2y, Dxy; + + Sobel( _src, Dx, CV_32F, 1, 0, ksize, 1, 0, borderType ); + Sobel( _src, Dy, CV_32F, 0, 1, ksize, 1, 0, borderType ); + Sobel( _src, D2x, CV_32F, 2, 0, ksize, 1, 0, borderType ); + Sobel( _src, D2y, CV_32F, 0, 2, ksize, 1, 0, borderType ); + Sobel( _src, Dxy, CV_32F, 1, 1, ksize, 1, 0, borderType ); + + _dst.create( _src.size(), CV_32FC1 ); + UMat dst = _dst.getUMat(); + + double factor = 1 << (ksize - 1); + if( depth == CV_8U ) + factor *= 255; + factor = 1./(factor * factor * factor); + + ocl::Kernel k("preCornerDetect", ocl::imgproc::precornerdetect_oclsrc); + if (k.empty()) + return false; + + k.args(ocl::KernelArg::ReadOnlyNoSize(Dx), ocl::KernelArg::ReadOnlyNoSize(Dy), + ocl::KernelArg::ReadOnlyNoSize(D2x), ocl::KernelArg::ReadOnlyNoSize(D2y), + ocl::KernelArg::ReadOnlyNoSize(Dxy), ocl::KernelArg::WriteOnly(dst), (float)factor); + + size_t globalsize[2] = { dst.cols, dst.rows }; + return k.run(2, globalsize, NULL, false); +} + } void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType ) @@ -381,7 +411,7 @@ void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, in void cv::cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksize, double k, int borderType ) { if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() && - ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, k, borderType, HARRIS)) + ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, k, borderType, HARRIS)) return; Mat src = _src.getMat(); @@ -406,10 +436,15 @@ void cv::cornerEigenValsAndVecs( InputArray _src, OutputArray _dst, int blockSiz void cv::preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int borderType ) { - Mat Dx, Dy, D2x, D2y, Dxy, src = _src.getMat(); + int type = _src.type(); + CV_Assert( type == CV_8UC1 || type == CV_32FC1 ); - CV_Assert( src.type() == CV_8UC1 || src.type() == CV_32FC1 ); - _dst.create( src.size(), CV_32F ); + if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() && + ocl_preCornerDetect(_src, _dst, ksize, borderType, CV_MAT_DEPTH(type))) + return; + + Mat Dx, Dy, D2x, D2y, Dxy, src = _src.getMat(); + _dst.create( src.size(), CV_32FC1 ); Mat dst = _dst.getMat(); Sobel( src, Dx, CV_32F, 1, 0, ksize, 1, 0, borderType ); diff --git a/modules/imgproc/src/opencl/precornerdetect.cl b/modules/imgproc/src/opencl/precornerdetect.cl new file mode 100644 index 000000000..32e6c2ce5 --- /dev/null +++ b/modules/imgproc/src/opencl/precornerdetect.cl @@ -0,0 +1,75 @@ +/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Shengen Yan,yanshengen@gmail.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*/ + +__kernel void preCornerDetect(__global const uchar * Dxptr, int dx_step, int dx_offset, + __global const uchar * Dyptr, int dy_step, int dy_offset, + __global const uchar * D2xptr, int d2x_step, int d2x_offset, + __global const uchar * D2yptr, int d2y_step, int d2y_offset, + __global const uchar * Dxyptr, int dxy_step, int dxy_offset, + __global uchar * dstptr, int dst_step, int dst_offset, + int dst_rows, int dst_cols, float factor) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if (x < dst_cols && y < dst_rows) + { + int dx_index = mad24(dx_step, y, (int)sizeof(float) * x + dx_offset); + int dy_index = mad24(dy_step, y, (int)sizeof(float) * x + dy_offset); + int d2x_index = mad24(d2x_step, y, (int)sizeof(float) * x + d2x_offset); + int d2y_index = mad24(d2y_step, y, (int)sizeof(float) * x + d2y_offset); + int dxy_index = mad24(dxy_step, y, (int)sizeof(float) * x + dxy_offset); + int dst_index = mad24(dst_step, y, (int)sizeof(float) * x + dst_offset); + + float dx = *(__global const float *)(Dxptr + dx_index); + float dy = *(__global const float *)(Dyptr + dy_index); + float d2x = *(__global const float *)(D2xptr + d2x_index); + float d2y = *(__global const float *)(D2yptr + d2y_index); + float dxy = *(__global const float *)(Dxyptr + dxy_index); + __global float * dst = (__global float *)(dstptr + dst_index); + + dst[0] = factor * (dx*dx*d2y + dy*dy*d2x - 2*dx*dy*dxy); + } +} diff --git a/modules/imgproc/test/ocl/test_imgproc.cpp b/modules/imgproc/test/ocl/test_imgproc.cpp index 2d34d7154..78b2e573d 100644 --- a/modules/imgproc/test/ocl/test_imgproc.cpp +++ b/modules/imgproc/test/ocl/test_imgproc.cpp @@ -259,6 +259,26 @@ OCL_TEST_P(CornerHarris, Mat) } } +//////////////////////////////// preCornerDetect ////////////////////////////////////////// + +typedef ImgprocTestBase PreCornerDetect; + +OCL_TEST_P(PreCornerDetect, Mat) +{ + for (int j = 0; j < test_loop_times; j++) + { + random_roi(); + + const int apertureSize = blockSize; + + OCL_OFF(cv::preCornerDetect(src_roi, dst_roi, apertureSize, borderType)); + OCL_ON(cv::preCornerDetect(usrc_roi, udst_roi, apertureSize, borderType)); + + Near(1e-6, true); + } +} + + ////////////////////////////////// integral ///////////////////////////////////////////////// struct Integral : @@ -341,7 +361,6 @@ struct Threshold : virtual void SetUp() { type = GET_PARAM(0); - blockSize = GET_PARAM(1); thresholdType = GET_PARAM(2); useRoi = GET_PARAM(3); } @@ -437,6 +456,13 @@ OCL_INSTANTIATE_TEST_CASE_P(Imgproc, CornerHarris, Combine( (BorderType)BORDER_REFLECT, (BorderType)BORDER_REFLECT_101), Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Imgproc, PreCornerDetect, Combine( + Values((MatType)CV_8UC1, CV_32FC1), + Values(3, 5), + Values( (BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE, + (BorderType)BORDER_REFLECT, (BorderType)BORDER_REFLECT_101), + Bool())); + OCL_INSTANTIATE_TEST_CASE_P(Imgproc, Integral, Combine( Values((MatType)CV_8UC1), // TODO does not work with CV_32F, CV_64F Values(CV_32SC1, CV_32FC1), // desired sdepth From ca5689e0dbb2c91f3a9d3072074786f0dc66d054 Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Fri, 27 Dec 2013 13:04:02 +0400 Subject: [PATCH 213/295] BFMatcher match radiusMatch --- modules/core/include/opencv2/core/mat.hpp | 3 +- modules/core/include/opencv2/core/mat.inl.hpp | 2 +- modules/core/src/matrix.cpp | 36 + .../features2d/include/opencv2/features2d.hpp | 51 +- modules/features2d/src/matchers.cpp | 915 +++++++++++++++++- .../src/opencl/brute_force_match.cl | 789 +++++++++++++++ modules/features2d/src/precomp.hpp | 1 + .../test/ocl/test_brute_force_matcher.cpp | 213 ++++ 8 files changed, 1947 insertions(+), 63 deletions(-) create mode 100644 modules/features2d/src/opencl/brute_force_match.cl create mode 100644 modules/features2d/test/ocl/test_brute_force_matcher.cpp diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index a7a4f1b8e..6c09efdf8 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -113,6 +113,7 @@ public: virtual Mat getMat(int idx=-1) const; virtual UMat getUMat(int idx=-1) const; virtual void getMatVector(std::vector& mv) const; + virtual void getUMatVector(std::vector& umv) const; virtual cuda::GpuMat getGpuMat() const; virtual ogl::Buffer getOGlBuffer() const; void* getObj() const; @@ -134,7 +135,7 @@ public: virtual size_t step(int i=-1) const; bool isMat() const; bool isUMat() const; - bool isMatVectot() const; + bool isMatVector() const; bool isUMatVector() const; bool isMatx(); diff --git a/modules/core/include/opencv2/core/mat.inl.hpp b/modules/core/include/opencv2/core/mat.inl.hpp index ed0d18dfc..fd7b06126 100644 --- a/modules/core/include/opencv2/core/mat.inl.hpp +++ b/modules/core/include/opencv2/core/mat.inl.hpp @@ -110,7 +110,7 @@ inline _InputArray::~_InputArray() {} inline bool _InputArray::isMat() const { return kind() == _InputArray::MAT; } inline bool _InputArray::isUMat() const { return kind() == _InputArray::UMAT; } -inline bool _InputArray::isMatVectot() const { return kind() == _InputArray::STD_VECTOR_MAT; } +inline bool _InputArray::isMatVector() const { return kind() == _InputArray::STD_VECTOR_MAT; } inline bool _InputArray::isUMatVector() const { return kind() == _InputArray::STD_VECTOR_UMAT; } inline bool _InputArray::isMatx() { return kind() == _InputArray::MATX; } diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 2d97319e4..48576ccf7 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -1324,6 +1324,42 @@ void _InputArray::getMatVector(std::vector& mv) const CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); } +void _InputArray::getUMatVector(std::vector& umv) const +{ + int k = kind(); + int accessFlags = flags & ACCESS_MASK; + + if( k == NONE ) + { + umv.clear(); + return; + } + + if( k == STD_VECTOR_MAT ) + { + const std::vector& v = *(const std::vector*)obj; + size_t i, n = v.size(); + umv.resize(n); + + for( i = 0; i < n; i++ ) + umv[i] = v[i].getUMat(accessFlags); + return; + } + + if( k == STD_VECTOR_UMAT ) + { + const std::vector& v = *(const std::vector*)obj; + size_t i, n = v.size(); + umv.resize(n); + + for( i = 0; i < n; i++ ) + umv[i] = v[i]; + return; + } + + CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); +} + cuda::GpuMat _InputArray::getGpuMat() const { int k = kind(); diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index 6aad4beb2..5936d9331 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -998,7 +998,7 @@ public: * Add descriptors to train descriptor collection. * descriptors Descriptors to add. Each descriptors[i] is a descriptors set from one image. */ - CV_WRAP virtual void add( const std::vector& descriptors ); + CV_WRAP virtual void add( InputArray descriptors ); /* * Get train descriptors collection. */ @@ -1034,29 +1034,29 @@ public: * Method train() is run in this methods. */ // Find one best match for each query descriptor (if mask is empty). - CV_WRAP void match( const Mat& queryDescriptors, const Mat& trainDescriptors, - CV_OUT std::vector& matches, const Mat& mask=Mat() ) const; + CV_WRAP void match( InputArray queryDescriptors, InputArray trainDescriptors, + CV_OUT std::vector& matches, InputArray mask=Mat() ) const; // Find k best matches for each query descriptor (in increasing order of distances). // compactResult is used when mask is not empty. If compactResult is false matches // vector will have the same size as queryDescriptors rows. If compactResult is true // matches vector will not contain matches for fully masked out query descriptors. - CV_WRAP void knnMatch( const Mat& queryDescriptors, const Mat& trainDescriptors, + CV_WRAP void knnMatch( InputArray queryDescriptors, InputArray trainDescriptors, CV_OUT std::vector >& matches, int k, - const Mat& mask=Mat(), bool compactResult=false ) const; + InputArray mask=Mat(), bool compactResult=false ) const; // Find best matches for each query descriptor which have distance less than // maxDistance (in increasing order of distances). - void radiusMatch( const Mat& queryDescriptors, const Mat& trainDescriptors, + void radiusMatch( InputArray queryDescriptors, InputArray trainDescriptors, std::vector >& matches, float maxDistance, - const Mat& mask=Mat(), bool compactResult=false ) const; + InputArray mask=Mat(), bool compactResult=false ) const; /* * Group of methods to match descriptors from one image to image set. * See description of similar methods for matching image pair above. */ - CV_WRAP void match( const Mat& queryDescriptors, CV_OUT std::vector& matches, + CV_WRAP void match( InputArray queryDescriptors, CV_OUT std::vector& matches, const std::vector& masks=std::vector() ); - CV_WRAP void knnMatch( const Mat& queryDescriptors, CV_OUT std::vector >& matches, int k, + CV_WRAP void knnMatch( InputArray queryDescriptors, CV_OUT std::vector >& matches, int k, const std::vector& masks=std::vector(), bool compactResult=false ); - void radiusMatch( const Mat& queryDescriptors, std::vector >& matches, float maxDistance, + void radiusMatch( InputArray queryDescriptors, std::vector >& matches, float maxDistance, const std::vector& masks=std::vector(), bool compactResult=false ); // Reads matcher object from a file node @@ -1101,10 +1101,10 @@ protected: // In fact the matching is implemented only by the following two methods. These methods suppose // that the class object has been trained already. Public match methods call these methods // after calling train(). - virtual void knnMatchImpl( const Mat& queryDescriptors, std::vector >& matches, int k, - const std::vector& masks=std::vector(), bool compactResult=false ) = 0; - virtual void radiusMatchImpl( const Mat& queryDescriptors, std::vector >& matches, float maxDistance, - const std::vector& masks=std::vector(), bool compactResult=false ) = 0; + virtual void knnMatchImpl( InputArray queryDescriptors, std::vector >& matches, int k, + InputArrayOfArrays masks=std::vector(), bool compactResult=false ) = 0; + virtual void radiusMatchImpl( InputArray queryDescriptors, std::vector >& matches, float maxDistance, + InputArrayOfArrays masks=std::vector(), bool compactResult=false ) = 0; static bool isPossibleMatch( const Mat& mask, int queryIdx, int trainIdx ); static bool isMaskedOut( const std::vector& masks, int queryIdx ); @@ -1114,6 +1114,7 @@ protected: // Collection of descriptors from train images. std::vector trainDescCollection; + std::vector utrainDescCollection; }; /* @@ -1137,10 +1138,16 @@ public: AlgorithmInfo* info() const; protected: - virtual void knnMatchImpl( const Mat& queryDescriptors, std::vector >& matches, int k, - const std::vector& masks=std::vector(), bool compactResult=false ); - virtual void radiusMatchImpl( const Mat& queryDescriptors, std::vector >& matches, float maxDistance, - const std::vector& masks=std::vector(), bool compactResult=false ); + virtual void knnMatchImpl( InputArray queryDescriptors, std::vector >& matches, int k, + InputArrayOfArrays masks=std::vector(), bool compactResult=false ); + virtual void radiusMatchImpl( InputArray queryDescriptors, std::vector >& matches, float maxDistance, + InputArrayOfArrays masks=std::vector(), bool compactResult=false ); + + bool ocl_knnMatch(InputArray query, InputArray train, std::vector< std::vector > &matches, + int k, int dstType, bool compactResult=false); + bool ocl_radiusMatch(InputArray query, InputArray train, std::vector< std::vector > &matches, + float maxDistance, int dstType, bool compactResult=false); + bool ocl_match(InputArray query, InputArray train, std::vector< std::vector > &matches, int dstType); int normType; bool crossCheck; @@ -1175,10 +1182,10 @@ protected: const Mat& indices, const Mat& distances, std::vector >& matches ); - virtual void knnMatchImpl( const Mat& queryDescriptors, std::vector >& matches, int k, - const std::vector& masks=std::vector(), bool compactResult=false ); - virtual void radiusMatchImpl( const Mat& queryDescriptors, std::vector >& matches, float maxDistance, - const std::vector& masks=std::vector(), bool compactResult=false ); + virtual void knnMatchImpl( InputArray queryDescriptors, std::vector >& matches, int k, + InputArrayOfArrays masks=std::vector(), bool compactResult=false ); + virtual void radiusMatchImpl( InputArray queryDescriptors, std::vector >& matches, float maxDistance, + InputArrayOfArrays masks=std::vector(), bool compactResult=false ); Ptr indexParams; Ptr searchParams; diff --git a/modules/features2d/src/matchers.cpp b/modules/features2d/src/matchers.cpp index 087c6a78b..5b692b991 100644 --- a/modules/features2d/src/matchers.cpp +++ b/modules/features2d/src/matchers.cpp @@ -41,6 +41,7 @@ #include "precomp.hpp" #include +#include "opencl_kernels.hpp" #if defined(HAVE_EIGEN) && EIGEN_WORLD_VERSION == 2 #include @@ -68,6 +69,680 @@ Mat windowedMatchingMask( const std::vector& keypoints1, const std::ve return mask; } +//////////////////////////////////////////////////////////////////ocl functions for BFMatcher /////////////////////////////////////////////////////////////// + +static void ensureSizeIsEnough(int rows, int cols, int type, UMat &m) +{ + if (m.type() == type && m.rows >= rows && m.cols >= cols) + m = m(Rect(0, 0, cols, rows)); + else + m.create(rows, cols, type); +} + + +template < int BLOCK_SIZE, int MAX_DESC_LEN/*, typename Mask*/ > +static bool ocl_matchUnrolledCached(InputArray _query, InputArray _train, + const UMat &trainIdx, const UMat &distance, int distType) +{ + int depth = _query.depth(); + cv::String opts; + opts = cv::format("-D T=%s %s -D DIST_TYPE=%d -D BLOCK_SIZE=%d -D MAX_DESC_LEN=%d", + ocl::typeToStr(depth), depth == CV_32F ? "-D T_FLOAT" : "", distType, (int)BLOCK_SIZE, (int)MAX_DESC_LEN ); + ocl::Kernel k("BruteForceMatch_UnrollMatch", ocl::features2d::brute_force_match_oclsrc, opts); + if(k.empty()) + return false; + + size_t globalSize[] = {(_query.size().height + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; + size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; + const size_t smemSize = (BLOCK_SIZE * (MAX_DESC_LEN >= BLOCK_SIZE ? MAX_DESC_LEN : BLOCK_SIZE) + BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); + + if(globalSize[0] != 0) + { + UMat query = _query.getUMat(), train = _train.getUMat(); + + int idx = 0; + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(query)); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(train)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(trainIdx)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(distance)); + idx = k.set(idx, (void *)NULL, smemSize); + idx = k.set(idx, query.rows); + idx = k.set(idx, query.cols); + idx = k.set(idx, train.rows); + idx = k.set(idx, train.cols); + idx = k.set(idx, (int)query.step); + + return k.run(2, globalSize, localSize, false); + } + return true; +} + +template < int BLOCK_SIZE/*, typename Mask*/ > +static bool ocl_match(InputArray _query, InputArray _train, + const UMat &trainIdx, const UMat &distance, int distType) +{ + int depth = _query.depth(); + cv::String opts; + opts = cv::format("-D T=%s %s -D DIST_TYPE=%d -D BLOCK_SIZE=%d", + ocl::typeToStr(depth), depth == CV_32F ? "-D T_FLOAT" : "", distType, (int)BLOCK_SIZE); + ocl::Kernel k("BruteForceMatch_Match", ocl::features2d::brute_force_match_oclsrc, opts); + if(k.empty()) + return false; + + size_t globalSize[] = {(_query.size().height + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; + size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; + const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); + + if(globalSize[0] != 0) + { + UMat query = _query.getUMat(), train = _train.getUMat(); + + int idx = 0; + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(query)); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(train)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(trainIdx)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(distance)); + idx = k.set(idx, (void *)NULL, smemSize); + idx = k.set(idx, query.rows); + idx = k.set(idx, query.cols); + idx = k.set(idx, train.rows); + idx = k.set(idx, train.cols); + idx = k.set(idx, (int)query.step); + + return k.run(2, globalSize, localSize, false); + } + return true; +} + +static bool ocl_matchDispatcher(InputArray query, InputArray train, + const UMat &trainIdx, const UMat &distance, int distType) +{ + int query_cols = query.size().width; + bool is_cpu = ocl::Device::getDefault().type() == ocl::Device::TYPE_CPU; + if (query_cols <= 64) + { + if(!ocl_matchUnrolledCached<16, 64>(query, train, trainIdx, distance, distType)) return false; + } + else if (query_cols <= 128 && !is_cpu) + { + if(!ocl_matchUnrolledCached<16, 128>(query, train, trainIdx, distance, distType)) return false; + } + else + { + if(!ocl_match<16>(query, train, trainIdx, distance, distType)) return false; + } + return true; +} + +static bool ocl_matchSingle(InputArray query, InputArray train, + UMat &trainIdx, UMat &distance, int dstType) +{ + if (query.empty() || train.empty()) + return false; + + int query_rows = query.size().height; + + ensureSizeIsEnough(1, query_rows, CV_32S, trainIdx); + ensureSizeIsEnough(1, query_rows, CV_32F, distance); + + return ocl_matchDispatcher(query, train, trainIdx, distance, dstType); +} + +static bool ocl_matchConvert(const Mat &trainIdx, const Mat &distance, std::vector< std::vector > &matches) +{ + if (trainIdx.empty() || distance.empty()) + return false; + + if( (trainIdx.type() != CV_32SC1) || (distance.type() != CV_32FC1 || distance.cols != trainIdx.cols) ) + return false; + + const int nQuery = trainIdx.cols; + + matches.clear(); + matches.reserve(nQuery); + + const int *trainIdx_ptr = trainIdx.ptr(); + const float *distance_ptr = distance.ptr(); + for (int queryIdx = 0; queryIdx < nQuery; ++queryIdx, ++trainIdx_ptr, ++distance_ptr) + { + int trainIndex = *trainIdx_ptr; + + if (trainIndex == -1) + continue; + + float dst = *distance_ptr; + + DMatch m(queryIdx, trainIndex, 0, dst); + + std::vector temp; + temp.push_back(m); + matches.push_back(temp); + } + return true; +} + +static bool ocl_matchDownload(const UMat &trainIdx, const UMat &distance, std::vector< std::vector > &matches) +{ + if (trainIdx.empty() || distance.empty()) + return false; + + Mat trainIdxCPU = trainIdx.getMat(ACCESS_READ); + Mat distanceCPU = distance.getMat(ACCESS_READ); + + return ocl_matchConvert(trainIdxCPU, distanceCPU, matches); +} + +template < int BLOCK_SIZE, int MAX_DESC_LEN/*, typename Mask*/ > +static bool ocl_knn_matchUnrolledCached(InputArray _query, InputArray _train, + const UMat &trainIdx, const UMat &distance, int distType) +{ + int depth = _query.depth(); + cv::String opts; + opts = cv::format("-D T=%s %s -D DIST_TYPE=%d -D BLOCK_SIZE=%d -D MAX_DESC_LEN=%d", + ocl::typeToStr(depth), depth == CV_32F ? "-D T_FLOAT" : "", distType, (int)BLOCK_SIZE, (int)MAX_DESC_LEN ); + ocl::Kernel k("BruteForceMatch_knnUnrollMatch", ocl::features2d::brute_force_match_oclsrc, opts); + if(k.empty()) + return false; + + size_t globalSize[] = {(_query.size().height + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; + size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; + const size_t smemSize = (BLOCK_SIZE * (MAX_DESC_LEN >= BLOCK_SIZE ? MAX_DESC_LEN : BLOCK_SIZE) + BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); + + if(globalSize[0] != 0) + { + UMat query = _query.getUMat(), train = _train.getUMat(); + + int idx = 0; + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(query)); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(train)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(trainIdx)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(distance)); + idx = k.set(idx, (void *)NULL, smemSize); + idx = k.set(idx, query.rows); + idx = k.set(idx, query.cols); + idx = k.set(idx, train.rows); + idx = k.set(idx, train.cols); + idx = k.set(idx, (int)query.step); + + return k.run(2, globalSize, localSize, false); + } + return true; +} + +template < int BLOCK_SIZE/*, typename Mask*/ > +static bool ocl_knn_match(InputArray _query, InputArray _train, + const UMat &trainIdx, const UMat &distance, int distType) +{ + int depth = _query.depth(); + cv::String opts; + opts = format("-D T=%s %s -D DIST_TYPE=%d -D BLOCK_SIZE=%d", + ocl::typeToStr(depth), depth == CV_32F ? "-D T_FLOAT" : "", distType, (int)BLOCK_SIZE); + ocl::Kernel k("BruteForceMatch_knnMatch", ocl::features2d::brute_force_match_oclsrc, opts); + if(k.empty()) + return false; + + size_t globalSize[] = {(_query.size().height + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; + size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; + const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); + + if(globalSize[0] != 0) + { + UMat query = _query.getUMat(), train = _train.getUMat(); + + int idx = 0; + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(query)); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(train)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(trainIdx)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(distance)); + idx = k.set(idx, (void*)NULL, smemSize); + idx = k.set(idx, query.rows); + idx = k.set(idx, query.cols); + idx = k.set(idx, train.rows); + idx = k.set(idx, train.cols); + idx = k.set(idx, (int)query.step); + + return k.run(2, globalSize, localSize, false); + } + return true; +} + +static bool ocl_match2Dispatcher(InputArray query, InputArray train, const UMat &trainIdx, const UMat &distance, int distType) +{ + bool is_cpu = ocl::Device::getDefault().type() == ocl::Device::TYPE_CPU; + if (query.size().width <= 64) + { + if(!ocl_knn_matchUnrolledCached<16, 64>(query, train, trainIdx, distance, distType)) + return false; + } + else if (query.size().width <= 128 && !is_cpu) + { + if(!ocl_knn_matchUnrolledCached<16, 128>(query, train, trainIdx, distance, distType)) + return false; + } + else + { + if(!ocl_knn_match<16>(query, train, trainIdx, distance, distType)) + return false; + } + return true; +} + +template < int BLOCK_SIZE, int MAX_DESC_LEN/*, typename Mask*/ > +static bool ocl_calcDistanceUnrolled(InputArray _query, InputArray _train, const UMat &allDist, int distType) +{ + int depth = _query.depth(); + cv::String opts; + opts = format("-D T=%s %s -D DIST_TYPE=%d -D BLOCK_SIZE=%d -D MAX_DESC_LEN=%d", + ocl::typeToStr(depth), depth == CV_32F ? "-D T_FLOAT" : "", distType, (int)BLOCK_SIZE, (int)MAX_DESC_LEN); + ocl::Kernel k("BruteForceMatch_calcDistanceUnrolled", ocl::features2d::brute_force_match_oclsrc, opts); + if(k.empty()) + return false; + + size_t globalSize[] = {(_query.size().width + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; + size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; + const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); + + if(globalSize[0] != 0) + { + UMat query = _query.getUMat(), train = _train.getUMat(); + + int idx = 0; + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(query)); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(train)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(allDist)); + idx = k.set(idx, (void*)NULL, smemSize); + idx = k.set(idx, query.rows); + idx = k.set(idx, query.cols); + idx = k.set(idx, train.rows); + idx = k.set(idx, train.cols); + idx = k.set(idx, (int)query.step); + + k.run(2, globalSize, localSize, false); + } + return false;// TODO in KERNEL +} + +template < int BLOCK_SIZE/*, typename Mask*/ > +static bool ocl_calcDistance(InputArray _query, InputArray _train, const UMat &allDist, int distType) +{ + int depth = _query.depth(); + cv::String opts; + opts = format("-D T=%s %s -D DIST_TYPE=%d -D BLOCK_SIZE=%d", + ocl::typeToStr(depth), depth == CV_32F ? "-D T_FLOAT" : "", distType, (int)BLOCK_SIZE); + ocl::Kernel k("BruteForceMatch_calcDistance", ocl::features2d::brute_force_match_oclsrc, opts); + if(k.empty()) + return false; + + size_t globalSize[] = {(_query.size().width + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; + size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; + const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); + + if(globalSize[0] != 0) + { + UMat query = _query.getUMat(), train = _train.getUMat(); + + int idx = 0; + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(query)); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(train)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(allDist)); + idx = k.set(idx, (void*)NULL, smemSize); + idx = k.set(idx, query.rows); + idx = k.set(idx, query.cols); + idx = k.set(idx, train.rows); + idx = k.set(idx, train.cols); + idx = k.set(idx, (int)query.step); + + k.run(2, globalSize, localSize, false); + } + return false;// TODO in KERNEL +} + +static bool ocl_calcDistanceDispatcher(InputArray query, InputArray train, const UMat &allDist, int distType) +{ + if (query.size().width <= 64) + { + if(!ocl_calcDistanceUnrolled<16, 64>(query, train, allDist, distType)) return false; + } + else if (query.size().width <= 128) + { + if(!ocl_calcDistanceUnrolled<16, 128>(query, train, allDist, distType)) return false; + } + else + { + if(!ocl_calcDistance<16>(query, train, allDist, distType)) return false; + } + return true; +} + +template +static bool ocl_findKnnMatch(int k, const UMat &trainIdx, const UMat &distance, const UMat &allDist, int /*distType*/) +{ + return false;// TODO in KERNEL + + std::vector kernels; + for (int i = 0; i < k; ++i) + { + ocl::Kernel kernel("BruteForceMatch_findBestMatch", ocl::features2d::brute_force_match_oclsrc); + if(kernel.empty()) + return false; + kernels.push_back(kernel); + } + + size_t globalSize[] = {trainIdx.rows * BLOCK_SIZE, 1, 1}; + size_t localSize[] = {BLOCK_SIZE, 1, 1}; + int block_size = BLOCK_SIZE; + + for (int i = 0; i < k; ++i) + { + int idx = 0; + idx = kernels[i].set(idx, ocl::KernelArg::PtrReadOnly(allDist)); + idx = kernels[i].set(idx, ocl::KernelArg::PtrWriteOnly(trainIdx)); + idx = kernels[i].set(idx, ocl::KernelArg::PtrWriteOnly(distance)); + idx = kernels[i].set(idx, i); + idx = kernels[i].set(idx, block_size); +// idx = kernels[i].set(idx, train.rows); +// idx = kernels[i].set(idx, train.cols); +// idx = kernels[i].set(idx, query.step); + + if(!kernels[i].run(2, globalSize, localSize, false)) + return false; + } + return true; +} + +static bool ocl_findKnnMatchDispatcher(int k, const UMat &trainIdx, const UMat &distance, const UMat &allDist, int distType) +{ + return ocl_findKnnMatch<256>(k, trainIdx, distance, allDist, distType); +} + +static bool ocl_kmatchDispatcher(InputArray query, InputArray train, int k, const UMat &trainIdx, + const UMat &distance, const UMat &allDist, int distType) +{ + if(k == 2) + { + if( !ocl_match2Dispatcher(query, train, trainIdx, distance, distType) ) return false; + } + else + { + if( !ocl_calcDistanceDispatcher(query, train, allDist, distType) ) return false; + if( !ocl_findKnnMatchDispatcher(k, trainIdx, distance, allDist, distType) ) return false; + } + return true; +} + +static bool ocl_knnMatchSingle(InputArray query, InputArray train, UMat &trainIdx, + UMat &distance, UMat &allDist, int k, int dstType) +{ + if (query.empty() || train.empty()) + return false; + + const int nQuery = query.size().height; + const int nTrain = train.size().height; + + if (k == 2) + { + ensureSizeIsEnough(1, nQuery, CV_32SC2, trainIdx); + ensureSizeIsEnough(1, nQuery, CV_32FC2, distance); + } + else + { + ensureSizeIsEnough(nQuery, k, CV_32S, trainIdx); + ensureSizeIsEnough(nQuery, k, CV_32F, distance); + ensureSizeIsEnough(nQuery, nTrain, CV_32FC1, allDist); + } + + trainIdx.setTo(Scalar::all(-1)); + + return ocl_kmatchDispatcher(query, train, k, trainIdx, distance, allDist, dstType); +} + +static bool ocl_knnMatchConvert(const Mat &trainIdx, const Mat &distance, std::vector< std::vector > &matches, bool compactResult) +{ + if (trainIdx.empty() || distance.empty()) + return false; + + if(trainIdx.type() != CV_32SC2 && trainIdx.type() != CV_32SC1) return false; + if(distance.type() != CV_32FC2 && distance.type() != CV_32FC1)return false; + if(distance.size() != trainIdx.size()) return false; + if(!trainIdx.isContinuous() || !distance.isContinuous()) return false; + + const int nQuery = trainIdx.type() == CV_32SC2 ? trainIdx.cols : trainIdx.rows; + const int k = trainIdx.type() == CV_32SC2 ? 2 : trainIdx.cols; + + matches.clear(); + matches.reserve(nQuery); + + const int *trainIdx_ptr = trainIdx.ptr(); + const float *distance_ptr = distance.ptr(); + + for (int queryIdx = 0; queryIdx < nQuery; ++queryIdx) + { + matches.push_back(std::vector()); + std::vector &curMatches = matches.back(); + curMatches.reserve(k); + + for (int i = 0; i < k; ++i, ++trainIdx_ptr, ++distance_ptr) + { + int trainIndex = *trainIdx_ptr; + + if (trainIndex != -1) + { + float dst = *distance_ptr; + + DMatch m(queryIdx, trainIndex, 0, dst); + + curMatches.push_back(m); + } + } + + if (compactResult && curMatches.empty()) + matches.pop_back(); + } + return true; +} + +static bool ocl_knnMatchDownload(const UMat &trainIdx, const UMat &distance, std::vector< std::vector > &matches, bool compactResult) +{ + if (trainIdx.empty() || distance.empty()) + return false; + + Mat trainIdxCPU = trainIdx.getMat(ACCESS_READ); + Mat distanceCPU = distance.getMat(ACCESS_READ); + + if (ocl_knnMatchConvert(trainIdxCPU, distanceCPU, matches, compactResult) ) + return true; + return false; +} + +template < int BLOCK_SIZE, int MAX_DESC_LEN/*, typename Mask*/ > +static bool ocl_matchUnrolledCached(InputArray _query, InputArray _train, float maxDistance, + const UMat &trainIdx, const UMat &distance, const UMat &nMatches, int distType) +{ + int depth = _query.depth(); + cv::String opts; + opts = format("-D T=%s %s -D DIST_TYPE=%d -D BLOCK_SIZE=%d -D MAX_DESC_LEN=%d", + ocl::typeToStr(depth), depth == CV_32F ? "-D T_FLOAT" : "", distType, (int)BLOCK_SIZE, (int)MAX_DESC_LEN); + ocl::Kernel k("BruteForceMatch_RadiusUnrollMatch", ocl::features2d::brute_force_match_oclsrc, opts); + if(k.empty()) + return false; + + size_t globalSize[] = {(_train.size().height + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, (_query.size().height + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, 1}; + size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; + const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); + + if(globalSize[0] != 0) + { + UMat query = _query.getUMat(), train = _train.getUMat(); + + int idx = 0; + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(query)); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(train)); + idx = k.set(idx, maxDistance); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(trainIdx)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(distance)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(nMatches)); + idx = k.set(idx, (void*)NULL, smemSize); + idx = k.set(idx, query.rows); + idx = k.set(idx, query.cols); + idx = k.set(idx, train.rows); + idx = k.set(idx, train.cols); + idx = k.set(idx, trainIdx.cols); + idx = k.set(idx, (int)query.step); + idx = k.set(idx, (int)trainIdx.step); + + return k.run(2, globalSize, localSize, false); + } + return true; +} + +//radius_match +template < int BLOCK_SIZE/*, typename Mask*/ > +static bool ocl_radius_match(InputArray _query, InputArray _train, float maxDistance, + const UMat &trainIdx, const UMat &distance, const UMat &nMatches, int distType) +{ + int depth = _query.depth(); + cv::String opts; + opts = format("-D T=%s %s -D DIST_TYPE=%d -D BLOCK_SIZE=%d", ocl::typeToStr(depth), depth == CV_32F ? "-D T_FLOAT" : "", distType, (int)BLOCK_SIZE); + ocl::Kernel k("BruteForceMatch_RadiusMatch", ocl::features2d::brute_force_match_oclsrc, opts); + if(k.empty()) + return false; + + size_t globalSize[] = {(_train.size().height + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, (_query.size().height + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, 1}; + size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; + const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); + + if(globalSize[0] != 0) + { + UMat query = _query.getUMat(), train = _train.getUMat(); + + int idx = 0; + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(query)); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(train)); + idx = k.set(idx, maxDistance); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(trainIdx)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(distance)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(nMatches)); + idx = k.set(idx, (void*)NULL, smemSize); + idx = k.set(idx, query.rows); + idx = k.set(idx, query.cols); + idx = k.set(idx, train.rows); + idx = k.set(idx, train.cols); + idx = k.set(idx, trainIdx.cols); + idx = k.set(idx, (int)query.step); + idx = k.set(idx, (int)trainIdx.step); + + return k.run(2, globalSize, localSize, false); + } + return true; +} + +static bool ocl_rmatchDispatcher(InputArray query, InputArray train, + UMat &trainIdx, UMat &distance, UMat &nMatches, float maxDistance, int distType) +{ + bool is_cpu = ocl::Device::getDefault().type() == ocl::Device::TYPE_CPU; + int query_cols = query.size().width; + if (query_cols <= 64) + { + if(!ocl_matchUnrolledCached<16, 64>(query, train, maxDistance, trainIdx, distance, nMatches, distType)) return false; + } + else if (query_cols <= 128 && !is_cpu) + { + if(!ocl_matchUnrolledCached<16, 128>(query, train, maxDistance, trainIdx, distance, nMatches, distType)) return false; + } + else + { + if(!ocl_radius_match<16>(query, train, maxDistance, trainIdx, distance, nMatches, distType)) return false; + } + return true; +} + + +static bool ocl_radiusMatchSingle(InputArray query, InputArray train, + UMat &trainIdx, UMat &distance, UMat &nMatches, float maxDistance, int distType) +{ + if (query.empty() || train.empty()) + return false; + + const int nQuery = query.size().height; + const int nTrain = train.size().height; + + ensureSizeIsEnough(1, nQuery, CV_32SC1, nMatches); + + if (trainIdx.empty()) + { + ensureSizeIsEnough(nQuery, std::max((nTrain / 100), 10), CV_32SC1, trainIdx); + ensureSizeIsEnough(nQuery, std::max((nTrain / 100), 10), CV_32FC1, distance); + } + + nMatches.setTo(Scalar::all(0)); + + return ocl_rmatchDispatcher(query, train, trainIdx, distance, nMatches, maxDistance, distType); +} + +static bool ocl_radiusMatchConvert(const Mat &trainIdx, const Mat &distance, const Mat &_nMatches, + std::vector< std::vector > &matches, bool compactResult) +{ + if (trainIdx.empty() || distance.empty() || _nMatches.empty()) + return false; + + if( (trainIdx.type() != CV_32SC1) || + (distance.type() != CV_32FC1 || distance.size() != trainIdx.size()) || + (_nMatches.type() != CV_32SC1 || _nMatches.cols != trainIdx.rows) ) + return false; + + const int nQuery = trainIdx.rows; + + matches.clear(); + matches.reserve(nQuery); + + const int *nMatches_ptr = _nMatches.ptr(); + + for (int queryIdx = 0; queryIdx < nQuery; ++queryIdx) + { + const int *trainIdx_ptr = trainIdx.ptr(queryIdx); + const float *distance_ptr = distance.ptr(queryIdx); + + const int nMatches = std::min(nMatches_ptr[queryIdx], trainIdx.cols); + + if (nMatches == 0) + { + if (!compactResult) + matches.push_back(std::vector()); + continue; + } + + matches.push_back(std::vector(nMatches)); + std::vector &curMatches = matches.back(); + + for (int i = 0; i < nMatches; ++i, ++trainIdx_ptr, ++distance_ptr) + { + int trainIndex = *trainIdx_ptr; + + float dst = *distance_ptr; + + DMatch m(queryIdx, trainIndex, 0, dst); + + curMatches[i] = m; + } + + std::sort(curMatches.begin(), curMatches.end()); + } + return true; +} + +static bool ocl_radiusMatchDownload(const UMat &trainIdx, const UMat &distance, const UMat &nMatches, + std::vector< std::vector > &matches, bool compactResult) +{ + if (trainIdx.empty() || distance.empty() || nMatches.empty()) + return false; + + Mat trainIdxCPU = trainIdx.getMat(ACCESS_READ); + Mat distanceCPU = distance.getMat(ACCESS_READ); + Mat nMatchesCPU = nMatches.getMat(ACCESS_READ); + + return ocl_radiusMatchConvert(trainIdxCPU, distanceCPU, nMatchesCPU, matches, compactResult); +} + /****************************************************************************************\ * DescriptorMatcher * \****************************************************************************************/ @@ -190,9 +865,32 @@ static void convertMatches( const std::vector >& knnMatches, DescriptorMatcher::~DescriptorMatcher() {} -void DescriptorMatcher::add( const std::vector& descriptors ) +void DescriptorMatcher::add( InputArrayOfArrays _descriptors ) { - trainDescCollection.insert( trainDescCollection.end(), descriptors.begin(), descriptors.end() ); + if(_descriptors.isUMatVector()) + { + std::vector descriptors; + _descriptors.getUMatVector(descriptors); + utrainDescCollection.insert( utrainDescCollection.end(), descriptors.begin(), descriptors.end() ); + } + else if(_descriptors.isUMat()) + { + std::vector descriptors = std::vector(1, _descriptors.getUMat()); + utrainDescCollection.insert( utrainDescCollection.end(), descriptors.begin(), descriptors.end() ); + } + else if(_descriptors.isMatVector()) + { + std::vector descriptors; + _descriptors.getMatVector(descriptors); + trainDescCollection.insert( trainDescCollection.end(), descriptors.begin(), descriptors.end() ); + } + else if(_descriptors.isMat()) + { + std::vector descriptors = std::vector(1, _descriptors.getMat()); + trainDescCollection.insert( trainDescCollection.end(), descriptors.begin(), descriptors.end() ); + } + else + CV_Assert( _descriptors.isUMat() || _descriptors.isUMatVector() || _descriptors.isMat() || _descriptors.isMatVector() ); } const std::vector& DescriptorMatcher::getTrainDescriptors() const @@ -202,41 +900,45 @@ const std::vector& DescriptorMatcher::getTrainDescriptors() const void DescriptorMatcher::clear() { + utrainDescCollection.clear(); trainDescCollection.clear(); } bool DescriptorMatcher::empty() const { - return trainDescCollection.empty(); + return trainDescCollection.empty() && utrainDescCollection.empty(); } void DescriptorMatcher::train() {} -void DescriptorMatcher::match( const Mat& queryDescriptors, const Mat& trainDescriptors, std::vector& matches, const Mat& mask ) const +void DescriptorMatcher::match( InputArray queryDescriptors, InputArray trainDescriptors, + std::vector& matches, InputArray mask ) const { Ptr tempMatcher = clone(true); - tempMatcher->add( std::vector(1, trainDescriptors) ); - tempMatcher->match( queryDescriptors, matches, std::vector(1, mask) ); + tempMatcher->add(trainDescriptors); + tempMatcher->match( queryDescriptors, matches, std::vector(1, mask.getMat()) ); } -void DescriptorMatcher::knnMatch( const Mat& queryDescriptors, const Mat& trainDescriptors, std::vector >& matches, int knn, - const Mat& mask, bool compactResult ) const +void DescriptorMatcher::knnMatch( InputArray queryDescriptors, InputArray trainDescriptors, + std::vector >& matches, int knn, + InputArray mask, bool compactResult ) const { Ptr tempMatcher = clone(true); - tempMatcher->add( std::vector(1, trainDescriptors) ); - tempMatcher->knnMatch( queryDescriptors, matches, knn, std::vector(1, mask), compactResult ); + tempMatcher->add(trainDescriptors); + tempMatcher->knnMatch( queryDescriptors, matches, knn, std::vector(1, mask.getMat()), compactResult ); } -void DescriptorMatcher::radiusMatch( const Mat& queryDescriptors, const Mat& trainDescriptors, std::vector >& matches, float maxDistance, - const Mat& mask, bool compactResult ) const +void DescriptorMatcher::radiusMatch( InputArray queryDescriptors, InputArray trainDescriptors, + std::vector >& matches, float maxDistance, InputArray mask, + bool compactResult ) const { Ptr tempMatcher = clone(true); - tempMatcher->add( std::vector(1, trainDescriptors) ); - tempMatcher->radiusMatch( queryDescriptors, matches, maxDistance, std::vector(1, mask), compactResult ); + tempMatcher->add(trainDescriptors); + tempMatcher->radiusMatch( queryDescriptors, matches, maxDistance, std::vector(1, mask.getMat()), compactResult ); } -void DescriptorMatcher::match( const Mat& queryDescriptors, std::vector& matches, const std::vector& masks ) +void DescriptorMatcher::match( InputArray queryDescriptors, std::vector& matches, const std::vector& masks ) { std::vector > knnMatches; knnMatch( queryDescriptors, knnMatches, 1, masks, true /*compactResult*/ ); @@ -248,36 +950,36 @@ void DescriptorMatcher::checkMasks( const std::vector& masks, int queryDesc if( isMaskSupported() && !masks.empty() ) { // Check masks - size_t imageCount = trainDescCollection.size(); + size_t imageCount = std::max(trainDescCollection.size(), utrainDescCollection.size() ); CV_Assert( masks.size() == imageCount ); for( size_t i = 0; i < imageCount; i++ ) { - if( !masks[i].empty() && !trainDescCollection[i].empty() ) + if( !masks[i].empty() && (!trainDescCollection[i].empty() || !utrainDescCollection[i].empty() ) ) { + int rows = trainDescCollection[i].empty() ? utrainDescCollection[i].rows : trainDescCollection[i].rows; CV_Assert( masks[i].rows == queryDescriptorsCount && - masks[i].cols == trainDescCollection[i].rows && - masks[i].type() == CV_8UC1 ); + (masks[i].cols == rows || masks[i].cols == rows) && + masks[i].type() == CV_8UC1 ); } } } } -void DescriptorMatcher::knnMatch( const Mat& queryDescriptors, std::vector >& matches, int knn, +void DescriptorMatcher::knnMatch( InputArray queryDescriptors, std::vector >& matches, int knn, const std::vector& masks, bool compactResult ) { - matches.clear(); if( empty() || queryDescriptors.empty() ) return; CV_Assert( knn > 0 ); - checkMasks( masks, queryDescriptors.rows ); + checkMasks( masks, queryDescriptors.size().height ); train(); knnMatchImpl( queryDescriptors, matches, knn, masks, compactResult ); } -void DescriptorMatcher::radiusMatch( const Mat& queryDescriptors, std::vector >& matches, float maxDistance, +void DescriptorMatcher::radiusMatch( InputArray queryDescriptors, std::vector >& matches, float maxDistance, const std::vector& masks, bool compactResult ) { matches.clear(); @@ -286,7 +988,7 @@ void DescriptorMatcher::radiusMatch( const Mat& queryDescriptors, std::vector std::numeric_limits::epsilon() ); - checkMasks( masks, queryDescriptors.rows ); + checkMasks( masks, queryDescriptors.size().height ); train(); radiusMatchImpl( queryDescriptors, matches, maxDistance, masks, compactResult ); @@ -316,7 +1018,7 @@ bool DescriptorMatcher::isMaskedOut( const std::vector& masks, int queryIdx } -/////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////// BruteForceMatcher ///////////////////////////////////////////////// BFMatcher::BFMatcher( int _normType, bool _crossCheck ) { @@ -336,19 +1038,97 @@ Ptr BFMatcher::clone( bool emptyTrainData ) const return matcher; } - -void BFMatcher::knnMatchImpl( const Mat& queryDescriptors, std::vector >& matches, int knn, - const std::vector& masks, bool compactResult ) +bool BFMatcher::ocl_match(InputArray query, InputArray _train, std::vector< std::vector > &matches, int dstType) { + UMat trainIdx, distance; + if(!ocl_matchSingle(query, _train, trainIdx, distance, dstType)) return false; + if(!ocl_matchDownload(trainIdx, distance, matches)) return false; + return true; +} + +bool BFMatcher::ocl_knnMatch(InputArray query, InputArray _train, std::vector< std::vector > &matches, int k, int dstType, bool compactResult) +{ + UMat trainIdx, distance, allDist; + if (!ocl_knnMatchSingle(query, _train, trainIdx, distance, allDist, k, dstType)) return false; + if( !ocl_knnMatchDownload(trainIdx, distance, matches, compactResult) ) return false; + return true; +} + +void BFMatcher::knnMatchImpl( InputArray _queryDescriptors, std::vector >& matches, int knn, + InputArrayOfArrays _masks, bool compactResult ) +{ + int trainDescType = trainDescCollection.empty() ? utrainDescCollection[0].type() : trainDescCollection[0].type(); + CV_Assert( _queryDescriptors.type() == trainDescType ); + const int IMGIDX_SHIFT = 18; const int IMGIDX_ONE = (1 << IMGIDX_SHIFT); - if( queryDescriptors.empty() || trainDescCollection.empty() ) + if( _queryDescriptors.empty() || (trainDescCollection.empty() && utrainDescCollection.empty())) { matches.clear(); return; } - CV_Assert( queryDescriptors.type() == trainDescCollection[0].type() ); + + std::vector masks; + _masks.getMatVector(masks); + + if(!trainDescCollection.empty() && !utrainDescCollection.empty()) + { + for(int i = 0; i < (int)utrainDescCollection.size(); i++) + { + Mat tempMat; + utrainDescCollection[i].copyTo(tempMat); + trainDescCollection.push_back(tempMat); + } + utrainDescCollection.clear(); + } + + int trainDescVectorSize = trainDescCollection.empty() ? (int)utrainDescCollection.size() : (int)trainDescCollection.size(); + Size trainDescSize = trainDescCollection.empty() ? utrainDescCollection[0].size() : trainDescCollection[0].size(); + + if ( ocl::useOpenCL() && _queryDescriptors.isUMat() && _queryDescriptors.dims()<=2 && trainDescVectorSize == 1 && + _queryDescriptors.type() == CV_32FC1 && + trainDescSize.width == _queryDescriptors.size().width && masks.size() == 1 && masks[0].total() == 0 ) + { + if(knn == 1) + { + if(trainDescCollection.empty()) + { + if(ocl_match(_queryDescriptors, utrainDescCollection[0], matches, normType)) + return; + } + else + { + if(ocl_match(_queryDescriptors, trainDescCollection[0], matches, normType)) + return; + } + } + else + { + if(trainDescCollection.empty()) + { + if(ocl_knnMatch(_queryDescriptors, utrainDescCollection[0], matches, knn, normType, compactResult) ) + return; + } + else + { + if(ocl_knnMatch(_queryDescriptors, trainDescCollection[0], matches, knn, normType, compactResult) ) + return; + } + } + } + + Mat queryDescriptors = _queryDescriptors.getMat(); + if(trainDescCollection.empty() && !utrainDescCollection.empty()) + { + for(int i = 0; i < (int)utrainDescCollection.size(); i++) + { + Mat tempMat; + utrainDescCollection[i].copyTo(tempMat); + trainDescCollection.push_back(tempMat); + } + utrainDescCollection.clear(); + } matches.reserve(queryDescriptors.rows); @@ -397,16 +1177,71 @@ void BFMatcher::knnMatchImpl( const Mat& queryDescriptors, std::vector >& matches, - float maxDistance, const std::vector& masks, bool compactResult ) +bool BFMatcher::ocl_radiusMatch(InputArray query, InputArray _train, std::vector< std::vector > &matches, + float maxDistance, int dstType, bool compactResult) { - if( queryDescriptors.empty() || trainDescCollection.empty() ) + UMat trainIdx, distance, nMatches; + if(!ocl_radiusMatchSingle(query, _train, trainIdx, distance, nMatches, maxDistance, dstType)) return false; + if(!ocl_radiusMatchDownload(trainIdx, distance, nMatches, matches, compactResult)) return false; + return true; +} + +void BFMatcher::radiusMatchImpl( InputArray _queryDescriptors, std::vector >& matches, + float maxDistance, InputArrayOfArrays _masks, bool compactResult ) +{ + int trainDescType = trainDescCollection.empty() ? utrainDescCollection[0].type() : trainDescCollection[0].type(); + CV_Assert( _queryDescriptors.type() == trainDescType ); + + if( _queryDescriptors.empty() || (trainDescCollection.empty() && utrainDescCollection.empty())) { matches.clear(); return; } - CV_Assert( queryDescriptors.type() == trainDescCollection[0].type() ); + + std::vector masks; + _masks.getMatVector(masks); + + if(!trainDescCollection.empty() && !utrainDescCollection.empty()) + { + for(int i = 0; i < (int)utrainDescCollection.size(); i++) + { + Mat tempMat; + utrainDescCollection[i].copyTo(tempMat); + trainDescCollection.push_back(tempMat); + } + utrainDescCollection.clear(); + } + + int trainDescVectorSize = trainDescCollection.empty() ? (int)utrainDescCollection.size() : (int)trainDescCollection.size(); + Size trainDescSize = trainDescCollection.empty() ? utrainDescCollection[0].size() : trainDescCollection[0].size(); + + if ( ocl::useOpenCL() && _queryDescriptors.isUMat() && _queryDescriptors.dims()<=2 && trainDescVectorSize == 1 && + _queryDescriptors.type() == CV_32FC1 && + trainDescSize.width == _queryDescriptors.size().width && masks.size() == 1 && masks[0].total() == 0 ) + { + if(trainDescCollection.empty()) + { + if(ocl_radiusMatch(_queryDescriptors, utrainDescCollection[0], matches, maxDistance, normType, compactResult) ) + return; + } + else + { + if(ocl_radiusMatch(_queryDescriptors, trainDescCollection[0], matches, maxDistance, normType, compactResult) ) + return; + } + } + + Mat queryDescriptors = _queryDescriptors.getMat(); + if(trainDescCollection.empty() && !utrainDescCollection.empty()) + { + for(int i = 0; i < (int)utrainDescCollection.size(); i++) + { + Mat tempMat; + utrainDescCollection[i].copyTo(tempMat); + trainDescCollection.push_back(tempMat); + } + utrainDescCollection.clear(); + } matches.resize(queryDescriptors.rows); Mat dist, distf; @@ -763,9 +1598,10 @@ void FlannBasedMatcher::convertToDMatches( const DescriptorCollection& collectio } } -void FlannBasedMatcher::knnMatchImpl( const Mat& queryDescriptors, std::vector >& matches, int knn, - const std::vector& /*masks*/, bool /*compactResult*/ ) +void FlannBasedMatcher::knnMatchImpl( InputArray _queryDescriptors, std::vector >& matches, int knn, + InputArrayOfArrays /*masks*/, bool /*compactResult*/ ) { + Mat queryDescriptors = _queryDescriptors.getMat(); Mat indices( queryDescriptors.rows, knn, CV_32SC1 ); Mat dists( queryDescriptors.rows, knn, CV_32FC1); flannIndex->knnSearch( queryDescriptors, indices, dists, knn, *searchParams ); @@ -773,9 +1609,10 @@ void FlannBasedMatcher::knnMatchImpl( const Mat& queryDescriptors, std::vector >& matches, float maxDistance, - const std::vector& /*masks*/, bool /*compactResult*/ ) +void FlannBasedMatcher::radiusMatchImpl( InputArray _queryDescriptors, std::vector >& matches, float maxDistance, + InputArrayOfArrays /*masks*/, bool /*compactResult*/ ) { + Mat queryDescriptors = _queryDescriptors.getMat(); const int count = mergedDescriptors.size(); // TODO do count as param? Mat indices( queryDescriptors.rows, count, CV_32SC1, Scalar::all(-1) ); Mat dists( queryDescriptors.rows, count, CV_32FC1, Scalar::all(-1) ); diff --git a/modules/features2d/src/opencl/brute_force_match.cl b/modules/features2d/src/opencl/brute_force_match.cl new file mode 100644 index 000000000..e2757e172 --- /dev/null +++ b/modules/features2d/src/opencl/brute_force_match.cl @@ -0,0 +1,789 @@ +/*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 +// Nathan, liujun@multicorewareinc.com +// Peng Xiao, pengxiao@outlook.com +// Baichuan Su, baichuan@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*/ + +#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics:enable +#define MAX_FLOAT 3.40282e+038f + +#ifndef T +#define T float +#endif + +#ifndef BLOCK_SIZE +#define BLOCK_SIZE 16 +#endif +#ifndef MAX_DESC_LEN +#define MAX_DESC_LEN 64 +#endif + +#ifndef DIST_TYPE +#define DIST_TYPE 2 +#endif + +// dirty fix for non-template support +#if (DIST_TYPE == 2) // L1Dist +# ifdef T_FLOAT +# define DIST(x, y) fabs((x) - (y)) + typedef float value_type; + typedef float result_type; +# else +# define DIST(x, y) abs((x) - (y)) + typedef int value_type; + typedef int result_type; +# endif +#define DIST_RES(x) (x) +#elif (DIST_TYPE == 4) // L2Dist +#define DIST(x, y) (((x) - (y)) * ((x) - (y))) +typedef float value_type; +typedef float result_type; +#define DIST_RES(x) sqrt(x) +#elif (DIST_TYPE == 6) // Hamming +//http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel +inline int bit1Count(int v) +{ + v = v - ((v >> 1) & 0x55555555); // reuse input as temporary + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp + return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count +} +#define DIST(x, y) bit1Count( (x) ^ (y) ) +typedef int value_type; +typedef int result_type; +#define DIST_RES(x) (x) +#endif + +inline result_type reduce_block( + __local value_type *s_query, + __local value_type *s_train, + int lidx, + int lidy + ) +{ + result_type result = 0; + #pragma unroll + for (int j = 0 ; j < BLOCK_SIZE ; j++) + { + result += DIST( + s_query[lidy * BLOCK_SIZE + j], + s_train[j * BLOCK_SIZE + lidx]); + } + return DIST_RES(result); +} + +inline result_type reduce_block_match( + __local value_type *s_query, + __local value_type *s_train, + int lidx, + int lidy + ) +{ + result_type result = 0; + #pragma unroll + for (int j = 0 ; j < BLOCK_SIZE ; j++) + { + result += DIST( + s_query[lidy * BLOCK_SIZE + j], + s_train[j * BLOCK_SIZE + lidx]); + } + return (result); +} + +inline result_type reduce_multi_block( + __local value_type *s_query, + __local value_type *s_train, + int block_index, + int lidx, + int lidy + ) +{ + result_type result = 0; + #pragma unroll + for (int j = 0 ; j < BLOCK_SIZE ; j++) + { + result += DIST( + s_query[lidy * MAX_DESC_LEN + block_index * BLOCK_SIZE + j], + s_train[j * BLOCK_SIZE + lidx]); + } + return result; +} + +/* 2dim launch, global size: dim0 is (query rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, dim1 is BLOCK_SIZE +local size: dim0 is BLOCK_SIZE, dim1 is BLOCK_SIZE. +*/ +__kernel void BruteForceMatch_UnrollMatch( + __global T *query, + __global T *train, + //__global float *mask, + __global int *bestTrainIdx, + __global float *bestDistance, + __local float *sharebuffer, + int query_rows, + int query_cols, + int train_rows, + int train_cols, + int step +) +{ + const int lidx = get_local_id(0); + const int lidy = get_local_id(1); + const int groupidx = get_group_id(0); + + __local value_type *s_query = (__local value_type *)sharebuffer; + __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * MAX_DESC_LEN; + + int queryIdx = groupidx * BLOCK_SIZE + lidy; + // load the query into local memory. + #pragma unroll + for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE; i ++) + { + int loadx = lidx + i * BLOCK_SIZE; + s_query[lidy * MAX_DESC_LEN + loadx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx] : 0; + } + + float myBestDistance = MAX_FLOAT; + int myBestTrainIdx = -1; + + // loopUnrolledCached to find the best trainIdx and best distance. + for (int t = 0, endt = (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE; t < endt; t++) + { + result_type result = 0; + #pragma unroll + for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE ; i++) + { + //load a BLOCK_SIZE * BLOCK_SIZE block into local train. + const int loadx = lidx + i * BLOCK_SIZE; + s_train[lidx * BLOCK_SIZE + lidy] = loadx < train_cols ? train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx] : 0; + + //synchronize to make sure each elem for reduceIteration in share memory is written already. + barrier(CLK_LOCAL_MEM_FENCE); + + result += reduce_multi_block(s_query, s_train, i, lidx, lidy); + + barrier(CLK_LOCAL_MEM_FENCE); + } + + result = DIST_RES(result); + + int trainIdx = t * BLOCK_SIZE + lidx; + + if (queryIdx < query_rows && trainIdx < train_rows && result < myBestDistance/* && mask(queryIdx, trainIdx)*/) + { + myBestDistance = result; + myBestTrainIdx = trainIdx; + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + __local float *s_distance = (__local float*)(sharebuffer); + __local int* s_trainIdx = (__local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE); + + //find BestMatch + s_distance += lidy * BLOCK_SIZE; + s_trainIdx += lidy * BLOCK_SIZE; + s_distance[lidx] = myBestDistance; + s_trainIdx[lidx] = myBestTrainIdx; + + barrier(CLK_LOCAL_MEM_FENCE); + + //reduce -- now all reduce implement in each threads. + #pragma unroll + for (int k = 0 ; k < BLOCK_SIZE; k++) + { + if (myBestDistance > s_distance[k]) + { + myBestDistance = s_distance[k]; + myBestTrainIdx = s_trainIdx[k]; + } + } + + if (queryIdx < query_rows && lidx == 0) + { + bestTrainIdx[queryIdx] = myBestTrainIdx; + bestDistance[queryIdx] = myBestDistance; + } +} + +__kernel void BruteForceMatch_Match( + __global T *query, + __global T *train, + //__global float *mask, + __global int *bestTrainIdx, + __global float *bestDistance, + __local float *sharebuffer, + int query_rows, + int query_cols, + int train_rows, + int train_cols, + int step +) +{ + const int lidx = get_local_id(0); + const int lidy = get_local_id(1); + const int groupidx = get_group_id(0); + + const int queryIdx = groupidx * BLOCK_SIZE + lidy; + + float myBestDistance = MAX_FLOAT; + int myBestTrainIdx = -1; + + __local value_type *s_query = (__local value_type *)sharebuffer; + __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE; + + // loop + for (int t = 0 ; t < (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE ; t++) + { + result_type result = 0; + for (int i = 0 ; i < (query_cols + BLOCK_SIZE - 1) / BLOCK_SIZE ; i++) + { + const int loadx = lidx + i * BLOCK_SIZE; + //load query and train into local memory + s_query[lidy * BLOCK_SIZE + lidx] = 0; + s_train[lidx * BLOCK_SIZE + lidy] = 0; + + if (loadx < query_cols) + { + s_query[lidy * BLOCK_SIZE + lidx] = query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx]; + s_train[lidx * BLOCK_SIZE + lidy] = train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx]; + } + + barrier(CLK_LOCAL_MEM_FENCE); + + result += reduce_block_match(s_query, s_train, lidx, lidy); + + barrier(CLK_LOCAL_MEM_FENCE); + } + + result = DIST_RES(result); + + const int trainIdx = t * BLOCK_SIZE + lidx; + + if (queryIdx < query_rows && trainIdx < train_rows && result < myBestDistance /*&& mask(queryIdx, trainIdx)*/) + { + myBestDistance = result; + myBestTrainIdx = trainIdx; + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + __local float *s_distance = (__local float *)sharebuffer; + __local int *s_trainIdx = (__local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE); + + //findBestMatch + s_distance += lidy * BLOCK_SIZE; + s_trainIdx += lidy * BLOCK_SIZE; + s_distance[lidx] = myBestDistance; + s_trainIdx[lidx] = myBestTrainIdx; + + barrier(CLK_LOCAL_MEM_FENCE); + + //reduce -- now all reduce implement in each threads. + for (int k = 0 ; k < BLOCK_SIZE; k++) + { + if (myBestDistance > s_distance[k]) + { + myBestDistance = s_distance[k]; + myBestTrainIdx = s_trainIdx[k]; + } + } + + if (queryIdx < query_rows && lidx == 0) + { + bestTrainIdx[queryIdx] = myBestTrainIdx; + bestDistance[queryIdx] = myBestDistance; + } +} + +//radius_unrollmatch +__kernel void BruteForceMatch_RadiusUnrollMatch( + __global T *query, + __global T *train, + float maxDistance, + //__global float *mask, + __global int *bestTrainIdx, + __global float *bestDistance, + __global int *nMatches, + __local float *sharebuffer, + int query_rows, + int query_cols, + int train_rows, + int train_cols, + int bestTrainIdx_cols, + int step, + int ostep +) +{ + const int lidx = get_local_id(0); + const int lidy = get_local_id(1); + const int groupidx = get_group_id(0); + const int groupidy = get_group_id(1); + + const int queryIdx = groupidy * BLOCK_SIZE + lidy; + const int trainIdx = groupidx * BLOCK_SIZE + lidx; + + __local value_type *s_query = (__local value_type *)sharebuffer; + __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE; + + result_type result = 0; + for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE ; ++i) + { + //load a BLOCK_SIZE * BLOCK_SIZE block into local train. + const int loadx = lidx + i * BLOCK_SIZE; + + s_query[lidy * BLOCK_SIZE + lidx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx] : 0; + s_train[lidx * BLOCK_SIZE + lidy] = loadx < query_cols ? train[min(groupidx * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx] : 0; + + //synchronize to make sure each elem for reduceIteration in share memory is written already. + barrier(CLK_LOCAL_MEM_FENCE); + + result += reduce_block(s_query, s_train, lidx, lidy); + + barrier(CLK_LOCAL_MEM_FENCE); + } + + if (queryIdx < query_rows && trainIdx < train_rows && + convert_float(result) < maxDistance/* && mask(queryIdx, trainIdx)*/) + { + int ind = atom_inc(nMatches + queryIdx/*, (unsigned int) -1*/); + + if(ind < bestTrainIdx_cols) + { + bestTrainIdx[queryIdx * (ostep / sizeof(int)) + ind] = trainIdx; + bestDistance[queryIdx * (ostep / sizeof(float)) + ind] = result; + } + } +} + +//radius_match +__kernel void BruteForceMatch_RadiusMatch( + __global T *query, + __global T *train, + float maxDistance, + //__global float *mask, + __global int *bestTrainIdx, + __global float *bestDistance, + __global int *nMatches, + __local float *sharebuffer, + int query_rows, + int query_cols, + int train_rows, + int train_cols, + int bestTrainIdx_cols, + int step, + int ostep +) +{ + const int lidx = get_local_id(0); + const int lidy = get_local_id(1); + const int groupidx = get_group_id(0); + const int groupidy = get_group_id(1); + + const int queryIdx = groupidy * BLOCK_SIZE + lidy; + const int trainIdx = groupidx * BLOCK_SIZE + lidx; + + __local value_type *s_query = (__local value_type *)sharebuffer; + __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE; + + result_type result = 0; + for (int i = 0 ; i < (query_cols + BLOCK_SIZE - 1) / BLOCK_SIZE ; ++i) + { + //load a BLOCK_SIZE * BLOCK_SIZE block into local train. + const int loadx = lidx + i * BLOCK_SIZE; + + s_query[lidy * BLOCK_SIZE + lidx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx] : 0; + s_train[lidx * BLOCK_SIZE + lidy] = loadx < query_cols ? train[min(groupidx * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx] : 0; + + //synchronize to make sure each elem for reduceIteration in share memory is written already. + barrier(CLK_LOCAL_MEM_FENCE); + + result += reduce_block(s_query, s_train, lidx, lidy); + + barrier(CLK_LOCAL_MEM_FENCE); + } + + if (queryIdx < query_rows && trainIdx < train_rows && + convert_float(result) < maxDistance/* && mask(queryIdx, trainIdx)*/) + { + int ind = atom_inc(nMatches + queryIdx); + + if(ind < bestTrainIdx_cols) + { + bestTrainIdx[queryIdx * (ostep / sizeof(int)) + ind] = trainIdx; + bestDistance[queryIdx * (ostep / sizeof(float)) + ind] = result; + } + } +} + + +__kernel void BruteForceMatch_knnUnrollMatch( + __global T *query, + __global T *train, + //__global float *mask, + __global int2 *bestTrainIdx, + __global float2 *bestDistance, + __local float *sharebuffer, + int query_rows, + int query_cols, + int train_rows, + int train_cols, + int step +) +{ + const int lidx = get_local_id(0); + const int lidy = get_local_id(1); + const int groupidx = get_group_id(0); + + const int queryIdx = groupidx * BLOCK_SIZE + lidy; + __local value_type *s_query = (__local value_type *)sharebuffer; + __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * MAX_DESC_LEN; + + // load the query into local memory. + for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE; i ++) + { + int loadx = lidx + i * BLOCK_SIZE; + s_query[lidy * MAX_DESC_LEN + loadx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx] : 0; + } + + float myBestDistance1 = MAX_FLOAT; + float myBestDistance2 = MAX_FLOAT; + int myBestTrainIdx1 = -1; + int myBestTrainIdx2 = -1; + + //loopUnrolledCached + for (int t = 0 ; t < (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE ; t++) + { + result_type result = 0; + for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE ; i++) + { + //load a BLOCK_SIZE * BLOCK_SIZE block into local train. + const int loadx = lidx + i * BLOCK_SIZE; + s_train[lidx * BLOCK_SIZE + lidy] = loadx < train_cols ? train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx] : 0; + + //synchronize to make sure each elem for reduceIteration in share memory is written already. + barrier(CLK_LOCAL_MEM_FENCE); + + result += reduce_multi_block(s_query, s_train, i, lidx, lidy); + + barrier(CLK_LOCAL_MEM_FENCE); + } + + result = DIST_RES(result); + + const int trainIdx = t * BLOCK_SIZE + lidx; + + if (queryIdx < query_rows && trainIdx < train_rows) + { + if (result < myBestDistance1) + { + myBestDistance2 = myBestDistance1; + myBestTrainIdx2 = myBestTrainIdx1; + myBestDistance1 = result; + myBestTrainIdx1 = trainIdx; + } + else if (result < myBestDistance2) + { + myBestDistance2 = result; + myBestTrainIdx2 = trainIdx; + } + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + __local float *s_distance = (local float *)sharebuffer; + __local int *s_trainIdx = (local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE); + + // find BestMatch + s_distance += lidy * BLOCK_SIZE; + s_trainIdx += lidy * BLOCK_SIZE; + + s_distance[lidx] = myBestDistance1; + s_trainIdx[lidx] = myBestTrainIdx1; + + float bestDistance1 = MAX_FLOAT; + float bestDistance2 = MAX_FLOAT; + int bestTrainIdx1 = -1; + int bestTrainIdx2 = -1; + barrier(CLK_LOCAL_MEM_FENCE); + + if (lidx == 0) + { + for (int i = 0 ; i < BLOCK_SIZE ; i++) + { + float val = s_distance[i]; + if (val < bestDistance1) + { + bestDistance2 = bestDistance1; + bestTrainIdx2 = bestTrainIdx1; + + bestDistance1 = val; + bestTrainIdx1 = s_trainIdx[i]; + } + else if (val < bestDistance2) + { + bestDistance2 = val; + bestTrainIdx2 = s_trainIdx[i]; + } + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + s_distance[lidx] = myBestDistance2; + s_trainIdx[lidx] = myBestTrainIdx2; + + barrier(CLK_LOCAL_MEM_FENCE); + + if (lidx == 0) + { + for (int i = 0 ; i < BLOCK_SIZE ; i++) + { + float val = s_distance[i]; + + if (val < bestDistance2) + { + bestDistance2 = val; + bestTrainIdx2 = s_trainIdx[i]; + } + } + } + + myBestDistance1 = bestDistance1; + myBestDistance2 = bestDistance2; + + myBestTrainIdx1 = bestTrainIdx1; + myBestTrainIdx2 = bestTrainIdx2; + + if (queryIdx < query_rows && lidx == 0) + { + bestTrainIdx[queryIdx] = (int2)(myBestTrainIdx1, myBestTrainIdx2); + bestDistance[queryIdx] = (float2)(myBestDistance1, myBestDistance2); + } +} + +__kernel void BruteForceMatch_knnMatch( + __global T *query, + __global T *train, + //__global float *mask, + __global int2 *bestTrainIdx, + __global float2 *bestDistance, + __local float *sharebuffer, + int query_rows, + int query_cols, + int train_rows, + int train_cols, + int step +) +{ + const int lidx = get_local_id(0); + const int lidy = get_local_id(1); + const int groupidx = get_group_id(0); + + const int queryIdx = groupidx * BLOCK_SIZE + lidy; + __local value_type *s_query = (__local value_type *)sharebuffer; + __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE; + + float myBestDistance1 = MAX_FLOAT; + float myBestDistance2 = MAX_FLOAT; + int myBestTrainIdx1 = -1; + int myBestTrainIdx2 = -1; + + //loop + for (int t = 0 ; t < (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE ; t++) + { + result_type result = 0.0f; + for (int i = 0 ; i < (query_cols + BLOCK_SIZE -1) / BLOCK_SIZE ; i++) + { + const int loadx = lidx + i * BLOCK_SIZE; + //load query and train into local memory + s_query[lidy * BLOCK_SIZE + lidx] = 0; + s_train[lidx * BLOCK_SIZE + lidy] = 0; + + if (loadx < query_cols) + { + s_query[lidy * BLOCK_SIZE + lidx] = query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx]; + s_train[lidx * BLOCK_SIZE + lidy] = train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx]; + } + + barrier(CLK_LOCAL_MEM_FENCE); + + result += reduce_block_match(s_query, s_train, lidx, lidy); + + barrier(CLK_LOCAL_MEM_FENCE); + } + + result = DIST_RES(result); + + const int trainIdx = t * BLOCK_SIZE + lidx; + + if (queryIdx < query_rows && trainIdx < train_rows /*&& mask(queryIdx, trainIdx)*/) + { + if (result < myBestDistance1) + { + myBestDistance2 = myBestDistance1; + myBestTrainIdx2 = myBestTrainIdx1; + myBestDistance1 = result; + myBestTrainIdx1 = trainIdx; + } + else if (result < myBestDistance2) + { + myBestDistance2 = result; + myBestTrainIdx2 = trainIdx; + } + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + __local float *s_distance = (__local float *)sharebuffer; + __local int *s_trainIdx = (__local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE); + + //findBestMatch + s_distance += lidy * BLOCK_SIZE; + s_trainIdx += lidy * BLOCK_SIZE; + + s_distance[lidx] = myBestDistance1; + s_trainIdx[lidx] = myBestTrainIdx1; + + float bestDistance1 = MAX_FLOAT; + float bestDistance2 = MAX_FLOAT; + int bestTrainIdx1 = -1; + int bestTrainIdx2 = -1; + barrier(CLK_LOCAL_MEM_FENCE); + + if (lidx == 0) + { + for (int i = 0 ; i < BLOCK_SIZE ; i++) + { + float val = s_distance[i]; + if (val < bestDistance1) + { + bestDistance2 = bestDistance1; + bestTrainIdx2 = bestTrainIdx1; + + bestDistance1 = val; + bestTrainIdx1 = s_trainIdx[i]; + } + else if (val < bestDistance2) + { + bestDistance2 = val; + bestTrainIdx2 = s_trainIdx[i]; + } + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + s_distance[lidx] = myBestDistance2; + s_trainIdx[lidx] = myBestTrainIdx2; + + barrier(CLK_LOCAL_MEM_FENCE); + + if (lidx == 0) + { + for (int i = 0 ; i < BLOCK_SIZE ; i++) + { + float val = s_distance[i]; + + if (val < bestDistance2) + { + bestDistance2 = val; + bestTrainIdx2 = s_trainIdx[i]; + } + } + } + + myBestDistance1 = bestDistance1; + myBestDistance2 = bestDistance2; + + myBestTrainIdx1 = bestTrainIdx1; + myBestTrainIdx2 = bestTrainIdx2; + + if (queryIdx < query_rows && lidx == 0) + { + bestTrainIdx[queryIdx] = (int2)(myBestTrainIdx1, myBestTrainIdx2); + bestDistance[queryIdx] = (float2)(myBestDistance1, myBestDistance2); + } +} + +kernel void BruteForceMatch_calcDistanceUnrolled( + __global T *query, + __global T *train, + //__global float *mask, + __global float *allDist, + __local float *sharebuffer, + int query_rows, + int query_cols, + int train_rows, + int train_cols, + int step) +{ + /* Todo */ +} + +kernel void BruteForceMatch_calcDistance( + __global T *query, + __global T *train, + //__global float *mask, + __global float *allDist, + __local float *sharebuffer, + int query_rows, + int query_cols, + int train_rows, + int train_cols, + int step) +{ + /* Todo */ +} + +kernel void BruteForceMatch_findBestMatch( + __global float *allDist, + __global int *bestTrainIdx, + __global float *bestDistance, + int k +) +{ + /* Todo */ +} diff --git a/modules/features2d/src/precomp.hpp b/modules/features2d/src/precomp.hpp index 3c9073ec5..2f77d9270 100644 --- a/modules/features2d/src/precomp.hpp +++ b/modules/features2d/src/precomp.hpp @@ -48,6 +48,7 @@ #include "opencv2/core/utility.hpp" #include "opencv2/core/private.hpp" +#include "opencv2/core/ocl.hpp" #include diff --git a/modules/features2d/test/ocl/test_brute_force_matcher.cpp b/modules/features2d/test/ocl/test_brute_force_matcher.cpp new file mode 100644 index 000000000..0e1df784f --- /dev/null +++ b/modules/features2d/test/ocl/test_brute_force_matcher.cpp @@ -0,0 +1,213 @@ +/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Niko Li, newlife20080214@gmail.com +// Jia Haipeng, jiahaipeng95@gmail.com +// Zero Lin, Zero.Lin@amd.com +// Zhang Ying, zhangying913@gmail.com +// Yao Wang, bitwangyaoyao@gmail.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 "test_precomp.hpp" +#include "cvconfig.h" +#include "opencv2/ts/ocl_test.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { +PARAM_TEST_CASE(BruteForceMatcher, int, int) +{ + int distType; + int dim; + + int queryDescCount; + int countFactor; + + Mat query, train; + UMat uquery, utrain; + + virtual void SetUp() + { + distType = GET_PARAM(0); + dim = GET_PARAM(1); + + queryDescCount = 300; // must be even number because we split train data in some cases in two + countFactor = 4; // do not change it + + cv::Mat queryBuf, trainBuf; + + // Generate query descriptors randomly. + // Descriptor vector elements are integer values. + queryBuf.create(queryDescCount, dim, CV_32SC1); + rng.fill(queryBuf, cv::RNG::UNIFORM, cv::Scalar::all(0), cv::Scalar::all(3)); + queryBuf.convertTo(queryBuf, CV_32FC1); + + // Generate train decriptors as follows: + // copy each query descriptor to train set countFactor times + // and perturb some one element of the copied descriptors in + // in ascending order. General boundaries of the perturbation + // are (0.f, 1.f). + trainBuf.create(queryDescCount * countFactor, dim, CV_32FC1); + float step = 1.f / countFactor; + for (int qIdx = 0; qIdx < queryDescCount; qIdx++) + { + cv::Mat queryDescriptor = queryBuf.row(qIdx); + for (int c = 0; c < countFactor; c++) + { + int tIdx = qIdx * countFactor + c; + cv::Mat trainDescriptor = trainBuf.row(tIdx); + queryDescriptor.copyTo(trainDescriptor); + int elem = rng(dim); + float diff = rng.uniform(step * c, step * (c + 1)); + trainDescriptor.at(0, elem) += diff; + } + } + + queryBuf.convertTo(query, CV_32F); + trainBuf.convertTo(train, CV_32F); + query.copyTo(uquery); + train.copyTo(utrain); + } +}; + +#ifdef ANDROID +OCL_TEST_P(BruteForceMatcher, DISABLED_Match_Single) +#else +OCL_TEST_P(BruteForceMatcher, Match_Single) +#endif +{ + BFMatcher matcher(distType); + + std::vector matches; + matcher.match(uquery, utrain, matches); + + ASSERT_EQ(static_cast(queryDescCount), matches.size()); + + int badCount = 0; + for (size_t i = 0; i < matches.size(); i++) + { + cv::DMatch match = matches[i]; + if ((match.queryIdx != (int)i) || (match.trainIdx != (int)i * countFactor) || (match.imgIdx != 0)) + badCount++; + } + + ASSERT_EQ(0, badCount); +} + +#ifdef ANDROID +OCL_TEST_P(BruteForceMatcher, DISABLED_KnnMatch_2_Single) +#else +OCL_TEST_P(BruteForceMatcher, KnnMatch_2_Single) +#endif +{ + const int knn = 2; + + BFMatcher matcher(distType); + + std::vector< std::vector > matches; + matcher.knnMatch(uquery, utrain, matches, knn); + + ASSERT_EQ(static_cast(queryDescCount), matches.size()); + + int badCount = 0; + for (size_t i = 0; i < matches.size(); i++) + { + if ((int)matches[i].size() != knn) + badCount++; + else + { + int localBadCount = 0; + for (int k = 0; k < knn; k++) + { + cv::DMatch match = matches[i][k]; + if ((match.queryIdx != (int)i) || (match.trainIdx != (int)i * countFactor + k) || (match.imgIdx != 0)) + localBadCount++; + } + badCount += localBadCount > 0 ? 1 : 0; + } + } + + ASSERT_EQ(0, badCount); +} + +#ifdef ANDROID +OCL_TEST_P(BruteForceMatcher, DISABLED_RadiusMatch_Single) +#else +OCL_TEST_P(BruteForceMatcher, RadiusMatch_Single) +#endif +{ + float radius = 1.f / countFactor; + + BFMatcher matcher(distType); + + std::vector< std::vector > matches; + matcher.radiusMatch(uquery, utrain, matches, radius); + + ASSERT_EQ(static_cast(queryDescCount), matches.size()); + + int badCount = 0; + for (size_t i = 0; i < matches.size(); i++) + { + if ((int)matches[i].size() != 1) + { + badCount++; + } + else + { + cv::DMatch match = matches[i][0]; + if ((match.queryIdx != (int)i) || (match.trainIdx != (int)i * countFactor) || (match.imgIdx != 0)) + badCount++; + } + } + + ASSERT_EQ(0, badCount); +} + +OCL_INSTANTIATE_TEST_CASE_P(Matcher, BruteForceMatcher, Combine( Values((int)NORM_L1, (int)NORM_L2), + Values(57, 64, 83, 128, 179, 256, 304) ) ); + +}//ocl +}//cvtest + +#endif //HAVE_OPENCL From 3b7683e72f6314a6f8d17eeb75806c16859ddcea Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Wed, 15 Jan 2014 10:01:40 +0400 Subject: [PATCH 214/295] fixed docs --- ...mmon_interfaces_of_descriptor_matchers.rst | 41 ++++++++++--------- .../features2d/include/opencv2/features2d.hpp | 2 +- modules/features2d/src/matchers.cpp | 6 ++- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst b/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst index 2c2cf28f8..ea9e13fa5 100644 --- a/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst +++ b/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst @@ -28,7 +28,7 @@ with an image set. :: public: virtual ~DescriptorMatcher(); - virtual void add( const vector& descriptors ); + virtual void add( InputArray descriptors ); const vector& getTrainDescriptors() const; virtual void clear(); @@ -40,23 +40,23 @@ with an image set. :: /* * Group of methods to match descriptors from an image pair. */ - void match( const Mat& queryDescriptors, const Mat& trainDescriptors, - vector& matches, const Mat& mask=Mat() ) const; - void knnMatch( const Mat& queryDescriptors, const Mat& trainDescriptors, + void match( InputArray queryDescriptors, InputArray trainDescriptors, + vector& matches, InputArray mask=Mat() ) const; + void knnMatch( InputArray queryDescriptors, InputArray trainDescriptors, vector >& matches, int k, - const Mat& mask=Mat(), bool compactResult=false ) const; - void radiusMatch( const Mat& queryDescriptors, const Mat& trainDescriptors, + InputArray mask=Mat(), bool compactResult=false ) const; + void radiusMatch( InputArray queryDescriptors, InputArray trainDescriptors, vector >& matches, float maxDistance, - const Mat& mask=Mat(), bool compactResult=false ) const; + InputArray mask=Mat(), bool compactResult=false ) const; /* * Group of methods to match descriptors from one image to an image set. */ - void match( const Mat& queryDescriptors, vector& matches, + void match( InputArray queryDescriptors, vector& matches, const vector& masks=vector() ); - void knnMatch( const Mat& queryDescriptors, vector >& matches, + void knnMatch( InputArray queryDescriptors, vector >& matches, int k, const vector& masks=vector(), bool compactResult=false ); - void radiusMatch( const Mat& queryDescriptors, vector >& matches, + void radiusMatch( InputArray queryDescriptors, vector >& matches, float maxDistance, const vector& masks=vector(), bool compactResult=false ); @@ -69,15 +69,16 @@ with an image set. :: protected: vector trainDescCollection; + vector utrainDescCollection; ... }; DescriptorMatcher::add -------------------------- -Adds descriptors to train a descriptor collection. If the collection ``trainDescCollectionis`` is not empty, the new descriptors are added to existing train descriptors. +Adds descriptors to train a CPU(``trainDescCollectionis``) or GPU(``utrainDescCollectionis``) descriptor collection. If the collection is not empty, the new descriptors are added to existing train descriptors. -.. ocv:function:: void DescriptorMatcher::add( const vector& descriptors ) +.. ocv:function:: void DescriptorMatcher::add( InputArrayOfArrays descriptors ) :param descriptors: Descriptors to add. Each ``descriptors[i]`` is a set of descriptors from the same train image. @@ -94,7 +95,7 @@ Returns a constant link to the train descriptor collection ``trainDescCollection DescriptorMatcher::clear ---------------------------- -Clears the train descriptor collection. +Clears the train descriptor collections. .. ocv:function:: void DescriptorMatcher::clear() @@ -102,7 +103,7 @@ Clears the train descriptor collection. DescriptorMatcher::empty ---------------------------- -Returns true if there are no train descriptors in the collection. +Returns true if there are no train descriptors in the both collections. .. ocv:function:: bool DescriptorMatcher::empty() const @@ -130,9 +131,9 @@ DescriptorMatcher::match ---------------------------- Finds the best match for each descriptor from a query set. -.. ocv:function:: void DescriptorMatcher::match( const Mat& queryDescriptors, const Mat& trainDescriptors, vector& matches, const Mat& mask=Mat() ) const +.. ocv:function:: void DescriptorMatcher::match( InputArray queryDescriptors, InputArray trainDescriptors, vector& matches, InputArray mask=Mat() ) const -.. ocv:function:: void DescriptorMatcher::match( const Mat& queryDescriptors, vector& matches, const vector& masks=vector() ) +.. ocv:function:: void DescriptorMatcher::match(InputArray queryDescriptors, vector& matches, const vector& masks=vector() ) :param queryDescriptors: Query set of descriptors. @@ -152,9 +153,9 @@ DescriptorMatcher::knnMatch ------------------------------- Finds the k best matches for each descriptor from a query set. -.. ocv:function:: void DescriptorMatcher::knnMatch( const Mat& queryDescriptors, const Mat& trainDescriptors, vector >& matches, int k, const Mat& mask=Mat(), bool compactResult=false ) const +.. ocv:function:: void DescriptorMatcher::knnMatch(InputArray queryDescriptors, InputArray trainDescriptors, vector >& matches, int k, InputArray mask=Mat(), bool compactResult=false ) const -.. ocv:function:: void DescriptorMatcher::knnMatch( const Mat& queryDescriptors, vector >& matches, int k, const vector& masks=vector(), bool compactResult=false ) +.. ocv:function:: void DescriptorMatcher::knnMatch( InputArray queryDescriptors, vector >& matches, int k, const vector& masks=vector(), bool compactResult=false ) :param queryDescriptors: Query set of descriptors. @@ -178,9 +179,9 @@ DescriptorMatcher::radiusMatch ---------------------------------- For each query descriptor, finds the training descriptors not farther than the specified distance. -.. ocv:function:: void DescriptorMatcher::radiusMatch( const Mat& queryDescriptors, const Mat& trainDescriptors, vector >& matches, float maxDistance, const Mat& mask=Mat(), bool compactResult=false ) const +.. ocv:function:: void DescriptorMatcher::radiusMatch( InputArray queryDescriptors, InputArray trainDescriptors, vector >& matches, float maxDistance, InputArray mask=Mat(), bool compactResult=false ) const -.. ocv:function:: void DescriptorMatcher::radiusMatch( const Mat& queryDescriptors, vector >& matches, float maxDistance, const vector& masks=vector(), bool compactResult=false ) +.. ocv:function:: void DescriptorMatcher::radiusMatch( InputArray queryDescriptors, vector >& matches, float maxDistance, const vector& masks=vector(), bool compactResult=false ) :param queryDescriptors: Query set of descriptors. diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index 5936d9331..f43d85f41 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -998,7 +998,7 @@ public: * Add descriptors to train descriptor collection. * descriptors Descriptors to add. Each descriptors[i] is a descriptors set from one image. */ - CV_WRAP virtual void add( InputArray descriptors ); + CV_WRAP virtual void add( InputArrayOfArrays descriptors ); /* * Get train descriptors collection. */ diff --git a/modules/features2d/src/matchers.cpp b/modules/features2d/src/matchers.cpp index 5b692b991..d35ea0143 100644 --- a/modules/features2d/src/matchers.cpp +++ b/modules/features2d/src/matchers.cpp @@ -1085,9 +1085,10 @@ void BFMatcher::knnMatchImpl( InputArray _queryDescriptors, std::vector Date: Fri, 17 Jan 2014 10:09:44 +0400 Subject: [PATCH 215/295] removed unnecessary functions and variables --- modules/features2d/src/matchers.cpp | 179 +++------------------------- 1 file changed, 17 insertions(+), 162 deletions(-) diff --git a/modules/features2d/src/matchers.cpp b/modules/features2d/src/matchers.cpp index d35ea0143..b2001d97e 100644 --- a/modules/features2d/src/matchers.cpp +++ b/modules/features2d/src/matchers.cpp @@ -80,7 +80,7 @@ static void ensureSizeIsEnough(int rows, int cols, int type, UMat &m) } -template < int BLOCK_SIZE, int MAX_DESC_LEN/*, typename Mask*/ > +template < int BLOCK_SIZE, int MAX_DESC_LEN > static bool ocl_matchUnrolledCached(InputArray _query, InputArray _train, const UMat &trainIdx, const UMat &distance, int distType) { @@ -117,7 +117,7 @@ static bool ocl_matchUnrolledCached(InputArray _query, InputArray _train, return true; } -template < int BLOCK_SIZE/*, typename Mask*/ > +template < int BLOCK_SIZE > static bool ocl_match(InputArray _query, InputArray _train, const UMat &trainIdx, const UMat &distance, int distType) { @@ -232,7 +232,7 @@ static bool ocl_matchDownload(const UMat &trainIdx, const UMat &distance, std::v return ocl_matchConvert(trainIdxCPU, distanceCPU, matches); } -template < int BLOCK_SIZE, int MAX_DESC_LEN/*, typename Mask*/ > +template < int BLOCK_SIZE, int MAX_DESC_LEN > static bool ocl_knn_matchUnrolledCached(InputArray _query, InputArray _train, const UMat &trainIdx, const UMat &distance, int distType) { @@ -269,7 +269,7 @@ static bool ocl_knn_matchUnrolledCached(InputArray _query, InputArray _train, return true; } -template < int BLOCK_SIZE/*, typename Mask*/ > +template < int BLOCK_SIZE > static bool ocl_knn_match(InputArray _query, InputArray _train, const UMat &trainIdx, const UMat &distance, int distType) { @@ -327,173 +327,26 @@ static bool ocl_match2Dispatcher(InputArray query, InputArray train, const UMat return true; } -template < int BLOCK_SIZE, int MAX_DESC_LEN/*, typename Mask*/ > -static bool ocl_calcDistanceUnrolled(InputArray _query, InputArray _train, const UMat &allDist, int distType) +static bool ocl_kmatchDispatcher(InputArray query, InputArray train, const UMat &trainIdx, + const UMat &distance, int distType) { - int depth = _query.depth(); - cv::String opts; - opts = format("-D T=%s %s -D DIST_TYPE=%d -D BLOCK_SIZE=%d -D MAX_DESC_LEN=%d", - ocl::typeToStr(depth), depth == CV_32F ? "-D T_FLOAT" : "", distType, (int)BLOCK_SIZE, (int)MAX_DESC_LEN); - ocl::Kernel k("BruteForceMatch_calcDistanceUnrolled", ocl::features2d::brute_force_match_oclsrc, opts); - if(k.empty()) - return false; - - size_t globalSize[] = {(_query.size().width + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; - size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; - const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); - - if(globalSize[0] != 0) - { - UMat query = _query.getUMat(), train = _train.getUMat(); - - int idx = 0; - idx = k.set(idx, ocl::KernelArg::PtrReadOnly(query)); - idx = k.set(idx, ocl::KernelArg::PtrReadOnly(train)); - idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(allDist)); - idx = k.set(idx, (void*)NULL, smemSize); - idx = k.set(idx, query.rows); - idx = k.set(idx, query.cols); - idx = k.set(idx, train.rows); - idx = k.set(idx, train.cols); - idx = k.set(idx, (int)query.step); - - k.run(2, globalSize, localSize, false); - } - return false;// TODO in KERNEL -} - -template < int BLOCK_SIZE/*, typename Mask*/ > -static bool ocl_calcDistance(InputArray _query, InputArray _train, const UMat &allDist, int distType) -{ - int depth = _query.depth(); - cv::String opts; - opts = format("-D T=%s %s -D DIST_TYPE=%d -D BLOCK_SIZE=%d", - ocl::typeToStr(depth), depth == CV_32F ? "-D T_FLOAT" : "", distType, (int)BLOCK_SIZE); - ocl::Kernel k("BruteForceMatch_calcDistance", ocl::features2d::brute_force_match_oclsrc, opts); - if(k.empty()) - return false; - - size_t globalSize[] = {(_query.size().width + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; - size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; - const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); - - if(globalSize[0] != 0) - { - UMat query = _query.getUMat(), train = _train.getUMat(); - - int idx = 0; - idx = k.set(idx, ocl::KernelArg::PtrReadOnly(query)); - idx = k.set(idx, ocl::KernelArg::PtrReadOnly(train)); - idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(allDist)); - idx = k.set(idx, (void*)NULL, smemSize); - idx = k.set(idx, query.rows); - idx = k.set(idx, query.cols); - idx = k.set(idx, train.rows); - idx = k.set(idx, train.cols); - idx = k.set(idx, (int)query.step); - - k.run(2, globalSize, localSize, false); - } - return false;// TODO in KERNEL -} - -static bool ocl_calcDistanceDispatcher(InputArray query, InputArray train, const UMat &allDist, int distType) -{ - if (query.size().width <= 64) - { - if(!ocl_calcDistanceUnrolled<16, 64>(query, train, allDist, distType)) return false; - } - else if (query.size().width <= 128) - { - if(!ocl_calcDistanceUnrolled<16, 128>(query, train, allDist, distType)) return false; - } - else - { - if(!ocl_calcDistance<16>(query, train, allDist, distType)) return false; - } - return true; -} - -template -static bool ocl_findKnnMatch(int k, const UMat &trainIdx, const UMat &distance, const UMat &allDist, int /*distType*/) -{ - return false;// TODO in KERNEL - - std::vector kernels; - for (int i = 0; i < k; ++i) - { - ocl::Kernel kernel("BruteForceMatch_findBestMatch", ocl::features2d::brute_force_match_oclsrc); - if(kernel.empty()) - return false; - kernels.push_back(kernel); - } - - size_t globalSize[] = {trainIdx.rows * BLOCK_SIZE, 1, 1}; - size_t localSize[] = {BLOCK_SIZE, 1, 1}; - int block_size = BLOCK_SIZE; - - for (int i = 0; i < k; ++i) - { - int idx = 0; - idx = kernels[i].set(idx, ocl::KernelArg::PtrReadOnly(allDist)); - idx = kernels[i].set(idx, ocl::KernelArg::PtrWriteOnly(trainIdx)); - idx = kernels[i].set(idx, ocl::KernelArg::PtrWriteOnly(distance)); - idx = kernels[i].set(idx, i); - idx = kernels[i].set(idx, block_size); -// idx = kernels[i].set(idx, train.rows); -// idx = kernels[i].set(idx, train.cols); -// idx = kernels[i].set(idx, query.step); - - if(!kernels[i].run(2, globalSize, localSize, false)) - return false; - } - return true; -} - -static bool ocl_findKnnMatchDispatcher(int k, const UMat &trainIdx, const UMat &distance, const UMat &allDist, int distType) -{ - return ocl_findKnnMatch<256>(k, trainIdx, distance, allDist, distType); -} - -static bool ocl_kmatchDispatcher(InputArray query, InputArray train, int k, const UMat &trainIdx, - const UMat &distance, const UMat &allDist, int distType) -{ - if(k == 2) - { - if( !ocl_match2Dispatcher(query, train, trainIdx, distance, distType) ) return false; - } - else - { - if( !ocl_calcDistanceDispatcher(query, train, allDist, distType) ) return false; - if( !ocl_findKnnMatchDispatcher(k, trainIdx, distance, allDist, distType) ) return false; - } - return true; + return ocl_match2Dispatcher(query, train, trainIdx, distance, distType); } static bool ocl_knnMatchSingle(InputArray query, InputArray train, UMat &trainIdx, - UMat &distance, UMat &allDist, int k, int dstType) + UMat &distance, int dstType) { if (query.empty() || train.empty()) return false; const int nQuery = query.size().height; - const int nTrain = train.size().height; - if (k == 2) - { - ensureSizeIsEnough(1, nQuery, CV_32SC2, trainIdx); - ensureSizeIsEnough(1, nQuery, CV_32FC2, distance); - } - else - { - ensureSizeIsEnough(nQuery, k, CV_32S, trainIdx); - ensureSizeIsEnough(nQuery, k, CV_32F, distance); - ensureSizeIsEnough(nQuery, nTrain, CV_32FC1, allDist); - } + ensureSizeIsEnough(1, nQuery, CV_32SC2, trainIdx); + ensureSizeIsEnough(1, nQuery, CV_32FC2, distance); trainIdx.setTo(Scalar::all(-1)); - return ocl_kmatchDispatcher(query, train, k, trainIdx, distance, allDist, dstType); + return ocl_kmatchDispatcher(query, train, trainIdx, distance, dstType); } static bool ocl_knnMatchConvert(const Mat &trainIdx, const Mat &distance, std::vector< std::vector > &matches, bool compactResult) @@ -554,7 +407,7 @@ static bool ocl_knnMatchDownload(const UMat &trainIdx, const UMat &distance, std return false; } -template < int BLOCK_SIZE, int MAX_DESC_LEN/*, typename Mask*/ > +template < int BLOCK_SIZE, int MAX_DESC_LEN > static bool ocl_matchUnrolledCached(InputArray _query, InputArray _train, float maxDistance, const UMat &trainIdx, const UMat &distance, const UMat &nMatches, int distType) { @@ -596,7 +449,7 @@ static bool ocl_matchUnrolledCached(InputArray _query, InputArray _train, float } //radius_match -template < int BLOCK_SIZE/*, typename Mask*/ > +template < int BLOCK_SIZE > static bool ocl_radius_match(InputArray _query, InputArray _train, float maxDistance, const UMat &trainIdx, const UMat &distance, const UMat &nMatches, int distType) { @@ -1048,8 +901,10 @@ bool BFMatcher::ocl_match(InputArray query, InputArray _train, std::vector< std: bool BFMatcher::ocl_knnMatch(InputArray query, InputArray _train, std::vector< std::vector > &matches, int k, int dstType, bool compactResult) { - UMat trainIdx, distance, allDist; - if (!ocl_knnMatchSingle(query, _train, trainIdx, distance, allDist, k, dstType)) return false; + UMat trainIdx, distance; + if (k != 2) + return false; + if (!ocl_knnMatchSingle(query, _train, trainIdx, distance, dstType)) return false; if( !ocl_knnMatchDownload(trainIdx, distance, matches, compactResult) ) return false; return true; } From f90e41d54e12d92ac7f9c0f2cf665b30260b213b Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Wed, 22 Jan 2014 10:08:42 +0400 Subject: [PATCH 216/295] dumpinfo --- modules/core/include/opencv2/core/ocl.hpp | 21 +++++ modules/core/src/ocl.cpp | 107 ++++++++++++++++++++++ modules/ts/include/opencv2/ts/ts_perf.hpp | 10 ++ modules/ts/src/ocl_test.cpp | 26 ++---- 4 files changed, 148 insertions(+), 16 deletions(-) diff --git a/modules/core/include/opencv2/core/ocl.hpp b/modules/core/include/opencv2/core/ocl.hpp index fb9f0282b..5d339a488 100644 --- a/modules/core/include/opencv2/core/ocl.hpp +++ b/modules/core/include/opencv2/core/ocl.hpp @@ -59,6 +59,7 @@ class CV_EXPORTS Kernel; class CV_EXPORTS Program; class CV_EXPORTS ProgramSource2; class CV_EXPORTS Queue; +class CV_EXPORTS PlatformInform; class CV_EXPORTS Device { @@ -84,6 +85,7 @@ public: String name() const; String extensions() const; + String version() const; String vendor() const; String OpenCL_C_Version() const; String OpenCLVersion() const; @@ -549,9 +551,28 @@ protected: Impl* p; }; +class CV_EXPORTS PlatformInform +{ +public: + PlatformInform(); + explicit PlatformInform(void* id); + ~PlatformInform(); + + String name() const; + String vendor() const; + String version() const; + int deviceNumber() const; + void getDevice(Device& device, int d) const; + +protected: + struct Impl; + Impl* p; +}; + CV_EXPORTS const char* convertTypeStr(int sdepth, int ddepth, int cn, char* buf); CV_EXPORTS const char* typeToStr(int t); CV_EXPORTS const char* memopTypeToStr(int t); +CV_EXPORTS void getPlatfomsInfo(std::vector& platform_info); }} diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index e2f4d2c4b..c4859544d 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -1693,6 +1693,9 @@ String Device::name() const String Device::extensions() const { return p ? p->getStrProp(CL_DEVICE_EXTENSIONS) : String(); } +String Device::version() const +{ return p ? p->getStrProp(CL_DEVICE_VERSION) : String(); } + String Device::vendor() const { return p ? p->getStrProp(CL_DEVICE_VENDOR) : String(); } @@ -3621,6 +3624,110 @@ MatAllocator* getOpenCLAllocator() return &allocator; } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static void getDevices(std::vector& devices,cl_platform_id& platform) +{ + cl_int status = CL_SUCCESS; + cl_uint numDevices = 0; + status = clGetDeviceIDs(platform, (cl_device_type)Device::TYPE_ALL, 0, NULL, &numDevices); + CV_Assert(status == CL_SUCCESS); + if (numDevices == 0) + return; + devices.resize((size_t)numDevices); + status = clGetDeviceIDs(platform, (cl_device_type)Device::TYPE_ALL, numDevices, &devices[0], &numDevices); + CV_Assert(status == CL_SUCCESS); + devices.resize(numDevices); +} + +struct PlatformInform::Impl +{ + Impl(void* id) + { + handle = *(cl_platform_id*)id; + getDevices(devices, handle); + } + + String getStrProp(cl_device_info prop) const + { + char buf[1024]; + size_t sz=0; + return clGetPlatformInfo(handle, prop, sizeof(buf)-16, buf, &sz) >= 0 && + sz < sizeof(buf) ? String(buf) : String(); + } + + IMPLEMENT_REFCOUNTABLE(); + std::vector devices; + cl_platform_id handle; +}; + +PlatformInform::PlatformInform() +{ + p = 0; +} + +PlatformInform::PlatformInform(void* platform_id) +{ + p = new Impl(platform_id); +} + +PlatformInform::~PlatformInform() +{ + if(p) + p->release(); +} + +int PlatformInform::deviceNumber() const +{ + return p ? (int)p->devices.size() : 0; +} + +void PlatformInform::getDevice(Device& device, int d) const +{ + CV_Assert(d < (int)p->devices.size() ); + if(p) + device.set(p->devices[d]); +} + +String PlatformInform::name() const +{ + return p ? p->getStrProp(CL_PLATFORM_NAME) : String(); +} + +String PlatformInform::vendor() const +{ + return p ? p->getStrProp(CL_PLATFORM_VENDOR) : String(); +} + +String PlatformInform::version() const +{ + return p ? p->getStrProp(CL_PLATFORM_VERSION) : String(); +} + +static void getPlatforms(std::vector& platforms) +{ + cl_int status = CL_SUCCESS; + cl_uint numPlatforms = 0; + status = clGetPlatformIDs(0, NULL, &numPlatforms); + CV_Assert(status == CL_SUCCESS); + if (numPlatforms == 0) + return; + platforms.resize((size_t)numPlatforms); + status = clGetPlatformIDs(numPlatforms, &platforms[0], &numPlatforms); + CV_Assert(status == CL_SUCCESS); + platforms.resize(numPlatforms); +} + +void getPlatfomsInfo(std::vector& platformsInfo) +{ + std::vector platforms; + getPlatforms(platforms); + for (size_t i = 0; i < platforms.size(); i++) + { + platformsInfo.push_back( PlatformInform((void*)&platforms[i]) ); + } +} + const char* typeToStr(int t) { static const char* tab[]= diff --git a/modules/ts/include/opencv2/ts/ts_perf.hpp b/modules/ts/include/opencv2/ts/ts_perf.hpp index de674b7f3..bd3156930 100644 --- a/modules/ts/include/opencv2/ts/ts_perf.hpp +++ b/modules/ts/include/opencv2/ts/ts_perf.hpp @@ -509,6 +509,15 @@ CV_EXPORTS void PrintTo(const Size& sz, ::std::ostream* os); #endif #endif +#if defined(HAVE_OPENCL) && !defined(CV_BUILD_OCL_MODULE) +namespace cvtest { namespace ocl { +void dumpOpenCLDevice(); +}} +#define TEST_DUMP_OCL_INFO cvtest::ocl::dumpOpenCLDevice(); +#else +#define TEST_DUMP_OCL_INFO +#endif + #define CV_PERF_TEST_MAIN_INTERNALS(modulename, impls, ...) \ ::perf::Regression::Init(#modulename); \ ::perf::TestBase::Init(std::vector(impls, impls + sizeof impls / sizeof *impls), \ @@ -518,6 +527,7 @@ CV_EXPORTS void PrintTo(const Size& sz, ::std::ostream* os); ::testing::Test::RecordProperty("cv_module_name", #modulename); \ ::perf::TestBase::RecordRunParameters(); \ __CV_TEST_EXEC_ARGS(__VA_ARGS__) \ + TEST_DUMP_OCL_INFO \ return RUN_ALL_TESTS(); // impls must be an array, not a pointer; "plain" should always be one of the implementations diff --git a/modules/ts/src/ocl_test.cpp b/modules/ts/src/ocl_test.cpp index 201c5f459..7c9ca9c5c 100644 --- a/modules/ts/src/ocl_test.cpp +++ b/modules/ts/src/ocl_test.cpp @@ -98,28 +98,25 @@ void dumpOpenCLDevice() using namespace cv::ocl; try { -#if 0 - Platforms platforms; - getOpenCLPlatforms(platforms); + std::vector platforms; + cv::ocl::getPlatfomsInfo(platforms); if (platforms.size() > 0) { DUMP_MESSAGE_STDOUT("OpenCL Platforms: "); for (size_t i = 0; i < platforms.size(); i++) { - const Platform* platform = platforms.at(i); + const PlatformInform* platform = &platforms[i]; DUMP_MESSAGE_STDOUT(" " << platform->name().c_str()); - const Devices& devices = platform->devices(); - for (size_t j = 0; j < devices.size(); j++) + Device current_device; + for (int j = 0; j < platform->deviceNumber(); j++) { - const Device& current_device = *devices.at(j); + platform->getDevice(current_device, j); const char* deviceTypeStr = current_device.type() == Device::TYPE_CPU ? ("CPU") : (current_device.type() == Device::TYPE_GPU ? "GPU" : "unknown"); DUMP_MESSAGE_STDOUT( " " << deviceTypeStr << ": " << current_device.name().c_str() << " (" << current_device.version().c_str() << ")"); - DUMP_PROPERTY_XML(cv::format("cv_ocl_platform_%d_device_%d", (int)i, (int)j), - "(Platform=" << current_device.getPlatform().name().c_str() - << ")(Type=" << deviceTypeStr - << ")(Name=" << current_device.name().c_str() - << ")(Version=" << current_device.version().c_str() << ")"); + DUMP_PROPERTY_XML( cv::format("cv_ocl_platform_%d_device_%d", (int)i, (int)j ), + cv::format("(Platform=%sType=%sName=%sVersion=%s", + platform->name().c_str(), deviceTypeStr, current_device.name().c_str(), current_device.version().c_str()) ); } } } @@ -129,10 +126,9 @@ void dumpOpenCLDevice() DUMP_PROPERTY_XML("cv_ocl", "not available"); return; } -#endif - DUMP_MESSAGE_STDOUT("Current OpenCL device: "); const Device& device = Device::getDefault(); + DUMP_MESSAGE_STDOUT("Current OpenCL device: "); #if 0 DUMP_MESSAGE_STDOUT(" Platform = "<< device.getPlatform().name()); @@ -147,10 +143,8 @@ void dumpOpenCLDevice() DUMP_MESSAGE_STDOUT(" Name = "<< device.name()); DUMP_PROPERTY_XML("cv_ocl_current_deviceName", device.name()); -#if 0 DUMP_MESSAGE_STDOUT(" Version = " << device.version()); DUMP_PROPERTY_XML("cv_ocl_current_deviceVersion", device.version()); -#endif DUMP_MESSAGE_STDOUT(" Compute units = "<< device.maxComputeUnits()); DUMP_PROPERTY_XML("cv_ocl_current_maxComputeUnits", device.maxComputeUnits()); From 167a26642e58486a06517bdf6c1b3cdeae7152ac Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Wed, 22 Jan 2014 15:26:14 +0100 Subject: [PATCH 217/295] fix message sent to user during cross_compilation --- cmake/OpenCVDetectPython.cmake | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmake/OpenCVDetectPython.cmake b/cmake/OpenCVDetectPython.cmake index 618b0fd22..d02b7596a 100644 --- a/cmake/OpenCVDetectPython.cmake +++ b/cmake/OpenCVDetectPython.cmake @@ -84,11 +84,9 @@ if(PYTHON_EXECUTABLE) if(CMAKE_CROSSCOMPILING) message(STATUS "Cannot probe for Python/Numpy support (because we are cross-compiling OpenCV)") message(STATUS "If you want to enable Python/Numpy support, set the following variables:") - message(STATUS " PYTHON_EXECUTABLE") - message(STATUS " PYTHON_INCLUDE_DIR") - message(STATUS " PYTHON_LIBRARY") + message(STATUS " PYTHON_INCLUDE_PATH") + message(STATUS " PYTHON_LIBRARIES") message(STATUS " PYTHON_NUMPY_INCLUDE_DIR") - message(STATUS " PYTHON_NUMPY_VERSION") else() # Attempt to discover the NumPy include directory. If this succeeds, then build python API with NumPy execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import os; os.environ['DISTUTILS_USE_SDK']='1'; import numpy.distutils; print numpy.distutils.misc_util.get_numpy_include_dirs()[0]" From 133f91f3f25dbfb971150d91de613417a5b45ebc Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Fri, 17 Jan 2014 11:23:00 +0400 Subject: [PATCH 218/295] added perf test --- .../perf/opencl/perf_brute_force_matcher.cpp | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 modules/features2d/perf/opencl/perf_brute_force_matcher.cpp diff --git a/modules/features2d/perf/opencl/perf_brute_force_matcher.cpp b/modules/features2d/perf/opencl/perf_brute_force_matcher.cpp new file mode 100644 index 000000000..f7bd24cf5 --- /dev/null +++ b/modules/features2d/perf/opencl/perf_brute_force_matcher.cpp @@ -0,0 +1,129 @@ +/*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/ts/ocl_perf.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +//////////////////// BruteForceMatch ///////////////// + +typedef Size_MatType BruteForceMatcherFixture; + +OCL_PERF_TEST_P(BruteForceMatcherFixture, Match, ::testing::Combine(OCL_PERF_ENUM(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3), OCL_PERF_ENUM((MatType)CV_32FC1) ) ) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + vector matches; + UMat uquery(srcSize, type), utrain(srcSize, type); + + declare.in(uquery, utrain, WARMUP_RNG); + + BFMatcher matcher(NORM_L2); + + OCL_TEST_CYCLE() + matcher.match(uquery, utrain, matches); + + SANITY_CHECK_MATCHES(matches, 1e-3); +} + +OCL_PERF_TEST_P(BruteForceMatcherFixture, KnnMatch, ::testing::Combine(OCL_PERF_ENUM(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3), OCL_PERF_ENUM((MatType)CV_32FC1) ) ) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + vector< vector > matches; + UMat uquery(srcSize, type), utrain(srcSize, type); + + declare.in(uquery, utrain, WARMUP_RNG); + + BFMatcher matcher(NORM_L2); + + OCL_TEST_CYCLE() + matcher.knnMatch(uquery, utrain, matches, 2); + + vector & matches0 = matches[0], & matches1 = matches[1]; + SANITY_CHECK_MATCHES(matches0, 1e-3); + SANITY_CHECK_MATCHES(matches1, 1e-3); + +} + +OCL_PERF_TEST_P(BruteForceMatcherFixture, RadiusMatch, ::testing::Combine(OCL_PERF_ENUM(OCL_SIZE_1, OCL_SIZE_2, OCL_SIZE_3), OCL_PERF_ENUM((MatType)CV_32FC1) ) ) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params); + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + vector< vector > matches; + UMat uquery(srcSize, type), utrain(srcSize, type); + + declare.in(uquery, utrain, WARMUP_RNG); + + BFMatcher matcher(NORM_L2); + + OCL_TEST_CYCLE() + matcher.radiusMatch(uquery, utrain, matches, 2.0f); + + vector & matches0 = matches[0], & matches1 = matches[1]; + SANITY_CHECK_MATCHES(matches0, 1e-3); + SANITY_CHECK_MATCHES(matches1, 1e-3); +} + +}//ocl +}//cvtest + +#endif //HAVE_OPENCL From 86636dc265a0d2c5733293a433d15c0ad73e4b10 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Tue, 14 Jan 2014 14:45:01 +0400 Subject: [PATCH 219/295] Added ocl_matchTemplate( without dft) --- modules/imgproc/src/opencl/match_template.cl | 427 ++++++++++++++++++ modules/imgproc/src/templmatch.cpp | 377 +++++++++++++++- .../imgproc/test/ocl/test_match_template.cpp | 130 ++++++ 3 files changed, 927 insertions(+), 7 deletions(-) create mode 100644 modules/imgproc/src/opencl/match_template.cl create mode 100644 modules/imgproc/test/ocl/test_match_template.cpp diff --git a/modules/imgproc/src/opencl/match_template.cl b/modules/imgproc/src/opencl/match_template.cl new file mode 100644 index 000000000..b24ec2c48 --- /dev/null +++ b/modules/imgproc/src/opencl/match_template.cl @@ -0,0 +1,427 @@ +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., 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. + +#define DATA_TYPE type +#define DATA_SIZE ((int)sizeof(type)) +#define ELEM_TYPE elem_type +#define ELEM_SIZE ((int)sizeof(elem_type)) +#define CN cn + +#define SQSUMS_PTR(ox, oy) mad24(gidy + oy, img_sqsums_step, (gidx + img_sqsums_offset + ox) * CN) +#define SQSUMS(ox, oy) mad24(gidy + oy, img_sqsums_step, (gidx*CN + img_sqsums_offset + ox*CN)) +#define SUMS_PTR(ox, oy) mad24(gidy + oy, img_sums_step, (gidx*CN + img_sums_offset + ox*CN)) + +inline float normAcc(float num, float denum) +{ + if(fabs(num) < denum) + { + return num / denum; + } + if(fabs(num) < denum * 1.125f) + { + return num > 0 ? 1 : -1; + } + return 0; +} + +inline float normAcc_SQDIFF(float num, float denum) +{ + if(fabs(num) < denum) + { + return num / denum; + } + if(fabs(num) < denum * 1.125f) + { + return num > 0 ? 1 : -1; + } + return 1; +} + +//////////////////////////////////////////CCORR///////////////////////////////////////////////////////////////////////// + +__kernel void matchTemplate_Naive_CCORR (__global const uchar * img,int img_step,int img_offset, + __global const uchar * tpl,int tpl_step,int tpl_offset,int tpl_rows, int tpl_cols, + __global uchar * res,int res_step,int res_offset,int res_rows,int res_cols) +{ + int gidx = get_global_id(0); + int gidy = get_global_id(1); + int i,j; + float sum = 0; + + res_step /= sizeof(float); + res_offset /= sizeof(float); + + int res_idx = mad24(gidy, res_step, res_offset + gidx); + + if(gidx < res_cols && gidy < res_rows) + { + for(i = 0; i < tpl_rows; i ++) + { + __global const ELEM_TYPE * img_ptr = (__global const ELEM_TYPE *)(img + mad24(gidy + i, img_step, gidx*DATA_SIZE + img_offset)); + __global const ELEM_TYPE * tpl_ptr = (__global const ELEM_TYPE *)(tpl + mad24(i, tpl_step, tpl_offset)); + + for(j = 0; j < tpl_cols; j ++) + + for (int c = 0; c < CN; c++) + + sum += (float)(img_ptr[j*CN+c] * tpl_ptr[j*CN+c]); + + } + __global float * result = (__global float *)(res)+res_idx; + *result = sum; + } +} + +__kernel void matchTemplate_CCORR_NORMED ( __global const uchar * img_sqsums, int img_sqsums_step, int img_sqsums_offset, + __global uchar * res, int res_step, int res_offset, int res_rows, int res_cols, + int tpl_rows, int tpl_cols, ulong tpl_sqsum) +{ + int gidx = get_global_id(0); + int gidy = get_global_id(1); + + img_sqsums_step /= sizeof(float); + img_sqsums_offset /= sizeof(float); + res_step /= sizeof(float); + res_offset /= sizeof(float); + + int res_idx = mad24(gidy, res_step, res_offset + gidx); + + if(gidx < res_cols && gidy < res_rows) + { + __global float * sqsum = (__global float*)(img_sqsums); + float image_sqsum_ = (float)( + (sqsum[SQSUMS_PTR(tpl_cols, tpl_rows)] - sqsum[SQSUMS_PTR(tpl_cols, 0)]) - + (sqsum[SQSUMS_PTR(0, tpl_rows)] - sqsum[SQSUMS_PTR(0, 0)])); + + __global float * result = (__global float *)(res)+res_idx; + *result = normAcc(*result, sqrt(image_sqsum_ * tpl_sqsum)); + } +} + +////////////////////////////////////////////SQDIFF//////////////////////////////////////////////////////////////////////// + +__kernel void matchTemplate_Naive_SQDIFF(__global const uchar * img,int img_step,int img_offset, + __global const uchar * tpl,int tpl_step,int tpl_offset,int tpl_rows, int tpl_cols, + __global uchar * res,int res_step,int res_offset,int res_rows,int res_cols) +{ + int gidx = get_global_id(0); + int gidy = get_global_id(1); + int i,j; + float delta; + float sum = 0; + + res_step /= sizeof(float); + res_offset /= sizeof(float); + + int res_idx = mad24(gidy, res_step, res_offset + gidx); + + if(gidx < res_cols && gidy < res_rows) + { + for(i = 0; i < tpl_rows; i ++) + { + __global const ELEM_TYPE * img_ptr = (__global const ELEM_TYPE *)(img + mad24(gidy + i, img_step, gidx*DATA_SIZE + img_offset)); + __global const ELEM_TYPE * tpl_ptr = (__global const ELEM_TYPE *)(tpl + mad24(i, tpl_step, tpl_offset)); + + for(j = 0; j < tpl_cols; j ++) + + for (int c = 0; c < CN; c++) + { + delta = (float)(img_ptr[j*CN+c] - tpl_ptr[j*CN+c]); + sum += delta*delta; + } + } + __global float * result = (__global float *)(res)+res_idx; + *result = sum; + } +} + +__kernel void matchTemplate_SQDIFF_NORMED ( __global const uchar * img_sqsums, int img_sqsums_step, int img_sqsums_offset, + __global uchar * res, int res_step, int res_offset, int res_rows, int res_cols, + int tpl_rows, int tpl_cols, ulong tpl_sqsum) +{ + int gidx = get_global_id(0); + int gidy = get_global_id(1); + + img_sqsums_step /= sizeof(float); + img_sqsums_offset /= sizeof(float); + res_step /= sizeof(float); + res_offset /= sizeof(float); + + int res_idx = mad24(gidy, res_step, res_offset + gidx); + + if(gidx < res_cols && gidy < res_rows) + { + __global float * sqsum = (__global float*)(img_sqsums); + float image_sqsum_ = (float)( + (sqsum[SQSUMS_PTR(tpl_cols, tpl_rows)] - sqsum[SQSUMS_PTR(tpl_cols, 0)]) - + (sqsum[SQSUMS_PTR(0, tpl_rows)] - sqsum[SQSUMS_PTR(0, 0)])); + + __global float * result = (__global float *)(res)+res_idx; + + *result = normAcc_SQDIFF(image_sqsum_ - 2.f * result[0] + tpl_sqsum, sqrt(image_sqsum_ * tpl_sqsum)); + } +} + +////////////////////////////////////////////CCOEFF///////////////////////////////////////////////////////////////// + +__kernel void matchTemplate_Prepared_CCOEFF_C1 (__global const uchar * img_sums, int img_sums_step, int img_sums_offset, + __global uchar * res, int res_step, int res_offset, int res_rows, int res_cols, + int tpl_rows, int tpl_cols, float tpl_sum) +{ + int gidx = get_global_id(0); + int gidy = get_global_id(1); + + img_sums_step /= ELEM_SIZE; + img_sums_offset /= ELEM_SIZE; + res_step /= sizeof(float); + res_offset /= sizeof(float); + + int res_idx = mad24(gidy, res_step, res_offset + gidx); + float image_sum_ = 0; + + if(gidx < res_cols && gidy < res_rows) + { + __global ELEM_TYPE* sum = (__global ELEM_TYPE*)(img_sums); + + image_sum_ += (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)] - sum[SUMS_PTR(tpl_cols, 0)])- + (sum[SUMS_PTR(0, tpl_rows)] - sum[SUMS_PTR(0, 0)])) * tpl_sum; + + __global float * result = (__global float *)(res)+res_idx; + *result -= image_sum_; + } +} + +__kernel void matchTemplate_Prepared_CCOEFF_C2 (__global const uchar * img_sums, int img_sums_step, int img_sums_offset, + __global uchar * res, int res_step, int res_offset, int res_rows, int res_cols, + int tpl_rows, int tpl_cols, float tpl_sum_0,float tpl_sum_1) +{ + int gidx = get_global_id(0); + int gidy = get_global_id(1); + + img_sums_step /= ELEM_SIZE; + img_sums_offset /= ELEM_SIZE; + res_step /= sizeof(float); + res_offset /= sizeof(float); + + int res_idx = mad24(gidy, res_step, res_offset + gidx); + float image_sum_ = 0; + + if(gidx < res_cols && gidy < res_rows) + { + __global ELEM_TYPE* sum = (__global ELEM_TYPE*)(img_sums); + + image_sum_ += tpl_sum_0 * (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)] - sum[SUMS_PTR(tpl_cols, 0)]) -(sum[SUMS_PTR(0, tpl_rows)] - sum[SUMS_PTR(0, 0)])); + image_sum_ += tpl_sum_1 * (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)+1] - sum[SUMS_PTR(tpl_cols, 0)+1])-(sum[SUMS_PTR(0, tpl_rows)+1] - sum[SUMS_PTR(0, 0)+1])); + + __global float * result = (__global float *)(res)+res_idx; + + *result -= image_sum_; + } +} + +__kernel void matchTemplate_Prepared_CCOEFF_C4 (__global const uchar * img_sums, int img_sums_step, int img_sums_offset, + __global uchar * res, int res_step, int res_offset, int res_rows, int res_cols, + int tpl_rows, int tpl_cols, float tpl_sum_0,float tpl_sum_1,float tpl_sum_2,float tpl_sum_3) +{ + int gidx = get_global_id(0); + int gidy = get_global_id(1); + + img_sums_step /= ELEM_SIZE; + img_sums_offset /= ELEM_SIZE; + res_step /= sizeof(float); + res_offset /= sizeof(float); + + int res_idx = mad24(gidy, res_step, res_offset + gidx); + float image_sum_ = 0; + + if(gidx < res_cols && gidy < res_rows) + { + __global ELEM_TYPE* sum = (__global ELEM_TYPE*)(img_sums); + + image_sum_ += tpl_sum_0 * (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)] - sum[SUMS_PTR(tpl_cols, 0)]) -(sum[SUMS_PTR(0, tpl_rows)] - sum[SUMS_PTR(0, 0)])); + image_sum_ += tpl_sum_1 * (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)+1] - sum[SUMS_PTR(tpl_cols, 0)+1])-(sum[SUMS_PTR(0, tpl_rows)+1] - sum[SUMS_PTR(0, 0)+1])); + image_sum_ += tpl_sum_2 * (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)+2] - sum[SUMS_PTR(tpl_cols, 0)+2])-(sum[SUMS_PTR(0, tpl_rows)+2] - sum[SUMS_PTR(0, 0)+2])); + image_sum_ += tpl_sum_3 * (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)+3] - sum[SUMS_PTR(tpl_cols, 0)+3])-(sum[SUMS_PTR(0, tpl_rows)+3] - sum[SUMS_PTR(0, 0)+3])); + + __global float * result = (__global float *)(res)+res_idx; + + *result -= image_sum_; + } +} + +__kernel void matchTemplate_CCOEFF_NORMED_C1 (__global const uchar * img_sums, int img_sums_step, int img_sums_offset, + __global const uchar * img_sqsums, int img_sqsums_step, int img_sqsums_offset, + __global float * res, int res_step, int res_offset, int res_rows, int res_cols, + int t_rows, int t_cols, float weight, float tpl_sum, float tpl_sqsum) +{ + int gidx = get_global_id(0); + int gidy = get_global_id(1); + + img_sums_offset /= ELEM_SIZE; + img_sums_step /= ELEM_SIZE; + img_sqsums_step /= sizeof(float); + img_sqsums_offset /= sizeof(float); + res_step /= sizeof(*res); + res_offset /= sizeof(*res); + + + int res_idx = mad24(gidy, res_step, res_offset + gidx); + + if(gidx < res_cols && gidy < res_rows) + { + __global ELEM_TYPE* sum = (__global ELEM_TYPE*)(img_sums); + __global float * sqsum = (__global float*)(img_sqsums); + + float image_sum_ = (float)((sum[SUMS_PTR(t_cols, t_rows)] - sum[SUMS_PTR(t_cols, 0)]) - + (sum[SUMS_PTR(0, t_rows)] - sum[SUMS_PTR(0, 0)])); + + float image_sqsum_ = (float)((sqsum[SQSUMS_PTR(t_cols, t_rows)] - sqsum[SQSUMS_PTR(t_cols, 0)]) - + (sqsum[SQSUMS_PTR(0, t_rows)] - sqsum[SQSUMS_PTR(0, 0)])); + + __global float * result = (__global float *)(res)+res_idx; + + *result = normAcc((*result) - image_sum_ * tpl_sum, + sqrt(tpl_sqsum * (image_sqsum_ - weight * image_sum_ * image_sum_))); + } +} + +__kernel void matchTemplate_CCOEFF_NORMED_C2 (__global const uchar * img_sums, int img_sums_step, int img_sums_offset, + __global const uchar * img_sqsums, int img_sqsums_step, int img_sqsums_offset, + __global float * res, int res_step, int res_offset, int res_rows, int res_cols, + int t_rows, int t_cols, float weight, float tpl_sum_0, float tpl_sum_1, float tpl_sqsum) +{ + int gidx = get_global_id(0); + int gidy = get_global_id(1); + + img_sums_offset /= ELEM_SIZE; + img_sums_step /= ELEM_SIZE; + img_sqsums_step /= sizeof(float); + img_sqsums_offset /= sizeof(float); + res_step /= sizeof(*res); + res_offset /= sizeof(*res); + + + int res_idx = mad24(gidy, res_step, res_offset + gidx); + + float sum_[2]; + float sqsum_[2]; + + if(gidx < res_cols && gidy < res_rows) + { + __global ELEM_TYPE* sum = (__global ELEM_TYPE*)(img_sums); + __global float * sqsum = (__global float*)(img_sqsums); + + sum_[0] = (float)((sum[SUMS_PTR(t_cols, t_rows)] - sum[SUMS_PTR(t_cols, 0)])-(sum[SUMS_PTR(0, t_rows)] - sum[SUMS_PTR(0, 0)])); + sum_[1] = (float)((sum[SUMS_PTR(t_cols, t_rows)+1] - sum[SUMS_PTR(t_cols, 0)+1])-(sum[SUMS_PTR(0, t_rows)+1] - sum[SUMS_PTR(0, 0)+1])); + + sqsum_[0] = (float)((sqsum[SQSUMS(t_cols, t_rows)] - sqsum[SQSUMS(t_cols, 0)])-(sqsum[SQSUMS(0, t_rows)] - sqsum[SQSUMS(0, 0)])); + sqsum_[1] = (float)((sqsum[SQSUMS(t_cols, t_rows)+1] - sqsum[SQSUMS(t_cols, 0)+1])-(sqsum[SQSUMS(0, t_rows)+1] - sqsum[SQSUMS(0, 0)+1])); + + float num = sum_[0]*tpl_sum_0 + sum_[1]*tpl_sum_1; + + float denum = sqrt( tpl_sqsum * (sqsum_[0] - weight * sum_[0]* sum_[0] + + sqsum_[1] - weight * sum_[1]* sum_[1])); + + __global float * result = (__global float *)(res)+res_idx; + *result = normAcc((*result) - num, denum); + } +} + +__kernel void matchTemplate_CCOEFF_NORMED_C4 (__global const uchar * img_sums, int img_sums_step, int img_sums_offset, + __global const uchar * img_sqsums, int img_sqsums_step, int img_sqsums_offset, + __global float * res, int res_step, int res_offset, int res_rows, int res_cols, + int t_rows, int t_cols, float weight, + float tpl_sum_0,float tpl_sum_1,float tpl_sum_2,float tpl_sum_3, + float tpl_sqsum) +{ + int gidx = get_global_id(0); + int gidy = get_global_id(1); + + img_sums_offset /= ELEM_SIZE; + img_sums_step /= ELEM_SIZE; + img_sqsums_step /= sizeof(float); + img_sqsums_offset /= sizeof(float); + res_step /= sizeof(*res); + res_offset /= sizeof(*res); + + + int res_idx = mad24(gidy, res_step, res_offset + gidx); + + float sum_[4]; + float sqsum_[4]; + + if(gidx < res_cols && gidy < res_rows) + { + __global ELEM_TYPE* sum = (__global ELEM_TYPE*)(img_sums); + __global float * sqsum = (__global float*)(img_sqsums); + + sum_[0] = (float)((sum[SUMS_PTR(t_cols, t_rows)] - sum[SUMS_PTR(t_cols, 0)])-(sum[SUMS_PTR(0, t_rows)] - sum[SUMS_PTR(0, 0)])); + sum_[1] = (float)((sum[SUMS_PTR(t_cols, t_rows)+1] - sum[SUMS_PTR(t_cols, 0)+1])-(sum[SUMS_PTR(0, t_rows)+1] - sum[SUMS_PTR(0, 0)+1])); + sum_[2] = (float)((sum[SUMS_PTR(t_cols, t_rows)+2] - sum[SUMS_PTR(t_cols, 0)+2])-(sum[SUMS_PTR(0, t_rows)+2] - sum[SUMS_PTR(0, 0)+2])); + sum_[3] = (float)((sum[SUMS_PTR(t_cols, t_rows)+3] - sum[SUMS_PTR(t_cols, 0)+3])-(sum[SUMS_PTR(0, t_rows)+3] - sum[SUMS_PTR(0, 0)+3])); + + sqsum_[0] = (float)((sqsum[SQSUMS(t_cols, t_rows)] - sqsum[SQSUMS(t_cols, 0)])-(sqsum[SQSUMS(0, t_rows)] - sqsum[SQSUMS(0, 0)])); + sqsum_[1] = (float)((sqsum[SQSUMS(t_cols, t_rows)+1] - sqsum[SQSUMS(t_cols, 0)+1])-(sqsum[SQSUMS(0, t_rows)+1] - sqsum[SQSUMS(0, 0)+1])); + sqsum_[2] = (float)((sqsum[SQSUMS(t_cols, t_rows)+2] - sqsum[SQSUMS(t_cols, 0)+2])-(sqsum[SQSUMS(0, t_rows)+2] - sqsum[SQSUMS(0, 0)+2])); + sqsum_[3] = (float)((sqsum[SQSUMS(t_cols, t_rows)+3] - sqsum[SQSUMS(t_cols, 0)+3])-(sqsum[SQSUMS(0, t_rows)+3] - sqsum[SQSUMS(0, 0)+3])); + + float num = sum_[0]*tpl_sum_0 + sum_[1]*tpl_sum_1 + sum_[2]*tpl_sum_2 + sum_[3]*tpl_sum_3; + + float denum = sqrt( tpl_sqsum * ( + sqsum_[0] - weight * sum_[0]* sum_[0] + + sqsum_[1] - weight * sum_[1]* sum_[1] + + sqsum_[2] - weight * sum_[2]* sum_[2] + + sqsum_[3] - weight * sum_[3]* sum_[3] )); + + __global float * result = (__global float *)(res)+res_idx; + *result = normAcc((*result) - num, denum); + } +} + +//////////////////////////////////////////// extractFirstChannel///////////////////////////// +__kernel void extractFirstChannel( const __global float4* img, int img_step, int img_offset, + __global float* res, int res_step, int res_offset, int rows, int cols) +{ + img_step /= sizeof(float4); + img_offset /= sizeof(float4); + res_step /= sizeof(float); + res_offset /= sizeof(float); + + int gidx = get_global_id(0); + int gidy = get_global_id(1); + + if(gidx < cols && gidy < rows) + { + __global const float4 * image = (__global const float4 *)(img) + mad24(gidy, img_step, img_offset + gidx); + __global float * result = (__global float *)(res)+ mad24(gidy, res_step, res_offset + gidx); + *result = image[0].x; + } +} \ No newline at end of file diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index bfe7ce600..3e31b9c76 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -40,6 +40,365 @@ //M*/ #include "precomp.hpp" +#include "opencl_kernels.hpp" + +//////////////////////////////////////////////////matchTemplate////////////////////////////////////////////////////////// +namespace cv +{ + struct MatchTemplateBuf + { + Size user_block_size; + UMat imagef, templf; + UMat image_sums; + UMat image_sqsums; + }; + + static bool matchTemplate_CCORR(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf); + static bool matchTemplate_CCORR_NORMED(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf); + + static bool matchTemplate_SQDIFF(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf); + static bool matchTemplate_SQDIFF_NORMED (const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf); + + static bool matchTemplate_CCOEFF(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf); + static bool matchTemplate_CCOEFF_NORMED(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf); + + static bool matchTemplateNaive_CCORR (const UMat &image, const UMat &templ, UMat &result, int cn); + static bool matchTemplateNaive_SQDIFF(const UMat &image, const UMat &templ, UMat &result, int cn); + + static bool useNaive(int method, int depth, Size size) + { +#ifdef HAVE_CLAMDFFT + if (method == TM_SQDIFF && depth == CV_32F) + return true; + else if(method == TM_CCORR || (method == TM_SQDIFF && depth == CV_8U)) + return size.height < 18 && size.width < 18; + else + return false; +#else +#define UNUSED(x) (void)(x); + UNUSED(method) UNUSED(depth) UNUSED(size) +#undef UNUSED + return true; +#endif + } + +///////////////////////////////////////////////////CCORR////////////////////////////////////////////////////////////// + + static bool extractFirstChannel_32F(const UMat &image, UMat &result) + { + const char * kernelName = "extractFirstChannel"; + int type = image.type(); + int depth = CV_MAT_DEPTH(type); + int cn = CV_MAT_CN(type); + + ocl::Kernel k (kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); + if (k.empty()) + return false; + + size_t globalsize[2] = {result.cols, result.rows}; + size_t localsize[2] = {16, 16}; + + return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,localsize,true); + } + + static bool matchTemplate_CCORR(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf) + { + if (useNaive(TM_CCORR, image.depth(), templ.size()) ) + return matchTemplateNaive_CCORR(image, templ, result, image.channels()); + else + return false; + } + + static bool matchTemplateNaive_CCORR (const UMat &image, const UMat &templ, UMat &result, int cn) + { + int type = image.type(); + int depth = CV_MAT_DEPTH(type); + + CV_Assert(result.channels() == 1); + + const char * kernelName = "matchTemplate_Naive_CCORR"; + + ocl::Kernel k (kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); + if (k.empty()) + return false; + + size_t globalsize[2] = {result.cols, result.rows}; + size_t localsize[2] = {16, 16}; + + return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,localsize,true); + } + + static bool matchTemplate_CCORR_NORMED(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf) + { + if (!matchTemplate_CCORR(image, templ, result, buf)) + return false; + + int type = image.type(); + int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + + const char * kernelName = "matchTemplate_CCORR_NORMED"; + + ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); + if (k.empty()) + return false; + + UMat temp; + integral(image.reshape(1), buf.image_sums, temp); + + if(temp.depth() == CV_64F) + temp.convertTo(buf.image_sqsums, CV_32F); + else + buf.image_sqsums = temp; + + UMat templ_resh; + templ.reshape(1).convertTo(templ_resh, CV_32F); + + multiply(templ_resh, templ_resh, temp); + unsigned long long templ_sqsum = (unsigned long long)sum(temp)[0]; + + size_t globalsize[2] = {result.cols, result.rows}; + size_t localsize[2] = {16, 16}; + + return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,localsize,true); + } + +//////////////////////////////////////SQDIFF////////////////////////////////////////////////////////////// + + static bool matchTemplate_SQDIFF(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf) + { + if (useNaive(TM_SQDIFF, image.depth(), templ.size())) + { + return matchTemplateNaive_SQDIFF(image, templ, result, image.channels());; + } + else + return false; + } + + static bool matchTemplateNaive_SQDIFF(const UMat &image, const UMat &templ, UMat &result, int cn) + { + int type = image.type(); + int depth = CV_MAT_DEPTH(type); + + CV_Assert(result.channels() == 1); + + const char * kernelName = "matchTemplate_Naive_SQDIFF"; + + ocl::Kernel k (kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); + if (k.empty()) + return false; + + size_t globalsize[2] = {result.cols, result.rows}; + size_t localsize[2] = {16, 16}; + + return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,localsize,true); + } + + static bool matchTemplate_SQDIFF_NORMED (const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf) + { + if (!matchTemplate_CCORR(image, templ, result, buf)) + return false; + + int type = image.type(); + int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + + const char * kernelName = "matchTemplate_SQDIFF_NORMED"; + + ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); + if (k.empty()) + return false; + + UMat temp; + integral(image.reshape(1), buf.image_sums, temp); + + if(temp.depth() == CV_64F) + temp.convertTo(buf.image_sqsums, CV_32F); + else + buf.image_sqsums = temp; + + UMat templ_resh; + templ.reshape(1).convertTo(templ_resh, CV_32F); + + multiply(templ_resh, templ_resh, temp); + unsigned long long templ_sqsum = (unsigned long long)sum(temp)[0]; + + size_t globalsize[2] = {result.cols, result.rows}; + size_t localsize[2] = {16, 16}; + + return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,localsize,true); + } + +/////////////////////////////////////CCOEFF///////////////////////////////////////////////////////////////// + + static bool matchTemplate_CCOEFF(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf) + { + if (!matchTemplate_CCORR(image, templ, result, buf)) + return false; + + integral(image, buf.image_sums); + + int type = buf.image_sums.type(); + int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + + const char * kernelName; + + if (cn==1) + kernelName = "matchTemplate_Prepared_CCOEFF_C1"; + else if (cn==2) + kernelName = "matchTemplate_Prepared_CCOEFF_C2"; + else + kernelName = "matchTemplate_Prepared_CCOEFF_C4"; + + ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); + if (k.empty()) + return false; + + size_t globalsize[2] = {result.cols, result.rows}; + size_t localsize[2] = {16, 16}; + + if (cn==1) + { + float templ_sum = (float)sum(templ)[0]/ templ.size().area(); + return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sum).run(2,globalsize,localsize,true); + } + else + { + Vec4f templ_sum = Vec4f::all(0); + templ_sum = sum(templ)/ templ.size().area(); + if (cn==2) + return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, + templ_sum[0],templ_sum[1]).run(2,globalsize,localsize,true); + + return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, + templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3]).run(2,globalsize,localsize,true); + } + } + + static bool matchTemplate_CCOEFF_NORMED(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf) + { + image.convertTo(buf.imagef, CV_32F); + templ.convertTo(buf.templf, CV_32F); + + if(!matchTemplate_CCORR(buf.imagef, buf.templf, result, buf)) + return false; + + const char * kernelName; + + UMat temp; + integral(image, buf.image_sums, temp); + + int type = buf.image_sums.type(); + int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + + if (cn== 1) + kernelName = "matchTemplate_CCOEFF_NORMED_C1"; + else if (cn==2) + kernelName = "matchTemplate_CCOEFF_NORMED_C2"; + else + kernelName = "matchTemplate_CCOEFF_NORMED_C4"; + + ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, + format("-D type=%s -D elem_type=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn)); + if (k.empty()) + return false; + + if(temp.depth() == CV_64F) + temp.convertTo(buf.image_sqsums, CV_32F); + else + buf.image_sqsums = temp; + + size_t globalsize[2] = {result.cols, result.rows}; + size_t localsize[2] = {16, 16}; + + float scale = 1.f / templ.size().area(); + + if (cn==1) + { + float templ_sum = (float)sum(templ)[0]; + + multiply(buf.templf, buf.templf, temp); + float templ_sqsum = (float)sum(temp)[0]; + + templ_sqsum -= scale * templ_sum * templ_sum; + templ_sum *= scale; + + if (templ_sqsum < DBL_EPSILON) + { + result = Scalar::all(1); + return true; + } + + return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sums),ocl::KernelArg::ReadOnlyNoSize(buf.image_sqsums), + ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, templ_sum, templ_sqsum) + .run(2,globalsize,localsize,true); + } + else + { + Vec4f templ_sum = Vec4f::all(0); + Vec4f templ_sqsum = Vec4f::all(0); + + templ_sum = sum(templ); + + multiply(buf.templf, buf.templf, temp); + templ_sqsum = sum(temp); + + float templ_sqsum_sum = 0; + for(int i = 0; i < cn; i ++) + { + templ_sqsum_sum += templ_sqsum[i] - scale * templ_sum[i] * templ_sum[i]; + } + + templ_sum *= scale; + + if (templ_sqsum_sum < DBL_EPSILON) + { + result = Scalar::all(1); + return true; + } + + if (cn==2) + return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sums), ocl::KernelArg::ReadOnlyNoSize(buf.image_sqsums), + ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, + templ_sum[0],templ_sum[1], templ_sqsum_sum) + .run(2,globalsize,localsize,true); + + return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sums), ocl::KernelArg::ReadOnlyNoSize(buf.image_sqsums), + ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, + templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3], templ_sqsum_sum) + .run(2,globalsize,localsize,true); + } + + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + + static bool ocl_matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method) + { + int type = _img.type(); + int cn = CV_MAT_CN(type); + + CV_Assert( cn == _templ.channels() && cn!=3 && cn<=4); + + typedef bool (*Caller)(const UMat &, const UMat &, UMat &, MatchTemplateBuf &); + + const Caller callers[] = + { + matchTemplate_SQDIFF, matchTemplate_SQDIFF_NORMED, matchTemplate_CCORR, + matchTemplate_CCORR_NORMED, matchTemplate_CCOEFF, matchTemplate_CCOEFF_NORMED + }; + + Caller caller; + if (!(caller = callers[method])) + return false; + + MatchTemplateBuf buf; + + UMat image = _img.getUMat(); + UMat templ = _templ.getUMat(), result; + _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); + result = _result.getUMat(); + return caller(image, templ, result, buf); + } +} namespace cv { @@ -226,15 +585,24 @@ void crossCorr( const Mat& img, const Mat& _templ, Mat& corr, } } } - } -/*****************************************************************************************/ +//////////////////////////////////////////////////////////////////////////////////////////////////////// void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method ) { CV_Assert( CV_TM_SQDIFF <= method && method <= CV_TM_CCOEFF_NORMED ); + CV_Assert( (_img.depth() == CV_8U || _img.depth() == CV_32F) && _img.type() == _templ.type() ); + + CV_Assert(_img.size().height >= _templ.size().height && _img.size().width >= _templ.size().width); + + CV_Assert(_img.dims() <= 2); + + bool use_opencl = ocl::useOpenCL() && _result.isUMat(); + if ( use_opencl && ocl_matchTemplate(_img,_templ,_result,method)) + return; + int numType = method == CV_TM_CCORR || method == CV_TM_CCORR_NORMED ? 0 : method == CV_TM_CCOEFF || method == CV_TM_CCOEFF_NORMED ? 1 : 2; bool isNormed = method == CV_TM_CCORR_NORMED || @@ -245,11 +613,6 @@ void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, if( img.rows < templ.rows || img.cols < templ.cols ) std::swap(img, templ); - CV_Assert( (img.depth() == CV_8U || img.depth() == CV_32F) && - img.type() == templ.type() ); - - CV_Assert( img.rows >= templ.rows && img.cols >= templ.cols); - Size corrSize(img.cols - templ.cols + 1, img.rows - templ.rows + 1); _result.create(corrSize, CV_32F); Mat result = _result.getMat(); diff --git a/modules/imgproc/test/ocl/test_match_template.cpp b/modules/imgproc/test/ocl/test_match_template.cpp new file mode 100644 index 000000000..2163ac36c --- /dev/null +++ b/modules/imgproc/test/ocl/test_match_template.cpp @@ -0,0 +1,130 @@ +/*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. +// +// +// 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 "test_precomp.hpp" +#include "opencv2/ts/ocl_test.hpp" +#include "iostream" +#include "fstream" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +/////////////////////////////////////////////matchTemplate////////////////////////////////////////////////////////// + +PARAM_TEST_CASE(MatchTemplate, MatDepth, Channels, int, bool) +{ + int type; + int depth; + int method; + bool use_roi; + + TEST_DECLARE_INPUT_PARAMETER(image) + TEST_DECLARE_INPUT_PARAMETER(templ) + TEST_DECLARE_OUTPUT_PARAMETER(result) + + virtual void SetUp() + { + type = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1)); + depth = GET_PARAM(0); + method = GET_PARAM(2); + use_roi = GET_PARAM(3); + } + + virtual void generateTestData() + { + Size image_roiSize = randomSize(2, 20); + Size templ_roiSize = Size (randomInt(1,image_roiSize.width), randomInt(1,image_roiSize.height)); + Size result_roiSize = Size(image_roiSize.width - templ_roiSize.width + 1, + image_roiSize.height - templ_roiSize.height + 1); + + const double upValue = 256; + const double max_val = 100; + + Border imageBorder = randomBorder(0, use_roi ? max_val : 0); + randomSubMat(image, image_roi, image_roiSize, imageBorder, type, -upValue, upValue); + + Border templBorder = randomBorder(0, use_roi ? max_val : 0); + randomSubMat(templ, templ_roi, templ_roiSize, templBorder, type, -upValue, upValue); + + Border resultBorder = randomBorder(0, use_roi ? max_val : 0); + randomSubMat(result, result_roi, result_roiSize, resultBorder, CV_32F, -upValue, upValue); + + UMAT_UPLOAD_INPUT_PARAMETER(image) + UMAT_UPLOAD_INPUT_PARAMETER(templ) + UMAT_UPLOAD_OUTPUT_PARAMETER(result) + } + + void Near(double threshold = 0.0) + { + EXPECT_MAT_NEAR(result, uresult, threshold); + EXPECT_MAT_NEAR(result_roi, uresult_roi, threshold); + } +}; + +OCL_TEST_P(MatchTemplate, Mat) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::matchTemplate(image_roi,templ_roi,result_roi, method)); + OCL_ON(cv::matchTemplate(uimage_roi,utempl_roi,uresult_roi, method)); + + if (method == 0) + Near(10.0f); + else + Near(method % 2 == 1 ? 0.001f : 1.0f); + } +} + +OCL_INSTANTIATE_TEST_CASE_P(ImageProc, MatchTemplate, Combine( + Values(CV_8U, CV_32F), + Values(1, 2, 4), + Values(0,1,2,3,4,5), + Bool()) + ); +} } // namespace cvtest::ocl + +#endif \ No newline at end of file From ba5d480f80bee48e238a7ff42b6097cbd0bc4ccf Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Tue, 14 Jan 2014 16:31:04 +0400 Subject: [PATCH 220/295] Fixed warnings --- modules/imgproc/src/opencl/match_template.cl | 20 --- modules/imgproc/src/templmatch.cpp | 123 ++++++++----------- 2 files changed, 48 insertions(+), 95 deletions(-) diff --git a/modules/imgproc/src/opencl/match_template.cl b/modules/imgproc/src/opencl/match_template.cl index b24ec2c48..26a9cbc1e 100644 --- a/modules/imgproc/src/opencl/match_template.cl +++ b/modules/imgproc/src/opencl/match_template.cl @@ -404,24 +404,4 @@ __kernel void matchTemplate_CCOEFF_NORMED_C4 (__global const uchar * img_sums, i __global float * result = (__global float *)(res)+res_idx; *result = normAcc((*result) - num, denum); } -} - -//////////////////////////////////////////// extractFirstChannel///////////////////////////// -__kernel void extractFirstChannel( const __global float4* img, int img_step, int img_offset, - __global float* res, int res_step, int res_offset, int rows, int cols) -{ - img_step /= sizeof(float4); - img_offset /= sizeof(float4); - res_step /= sizeof(float); - res_offset /= sizeof(float); - - int gidx = get_global_id(0); - int gidy = get_global_id(1); - - if(gidx < cols && gidy < rows) - { - __global const float4 * image = (__global const float4 *)(img) + mad24(gidy, img_step, img_offset + gidx); - __global float * result = (__global float *)(res)+ mad24(gidy, res_step, res_offset + gidx); - *result = image[0].x; - } } \ No newline at end of file diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index 3e31b9c76..ea6bddc8d 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -45,22 +45,14 @@ //////////////////////////////////////////////////matchTemplate////////////////////////////////////////////////////////// namespace cv { - struct MatchTemplateBuf - { - Size user_block_size; - UMat imagef, templf; - UMat image_sums; - UMat image_sqsums; - }; + static bool matchTemplate_CCORR(const UMat &image, const UMat &templ, UMat &result); + static bool matchTemplate_CCORR_NORMED(const UMat &image, const UMat &templ, UMat &result); - static bool matchTemplate_CCORR(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf); - static bool matchTemplate_CCORR_NORMED(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf); + static bool matchTemplate_SQDIFF(const UMat &image, const UMat &templ, UMat &result); + static bool matchTemplate_SQDIFF_NORMED (const UMat &image, const UMat &templ, UMat &result); - static bool matchTemplate_SQDIFF(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf); - static bool matchTemplate_SQDIFF_NORMED (const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf); - - static bool matchTemplate_CCOEFF(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf); - static bool matchTemplate_CCOEFF_NORMED(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf); + static bool matchTemplate_CCOEFF(const UMat &image, const UMat &templ, UMat &result); + static bool matchTemplate_CCOEFF_NORMED(const UMat &image, const UMat &templ, UMat &result); static bool matchTemplateNaive_CCORR (const UMat &image, const UMat &templ, UMat &result, int cn); static bool matchTemplateNaive_SQDIFF(const UMat &image, const UMat &templ, UMat &result, int cn); @@ -84,24 +76,7 @@ namespace cv ///////////////////////////////////////////////////CCORR////////////////////////////////////////////////////////////// - static bool extractFirstChannel_32F(const UMat &image, UMat &result) - { - const char * kernelName = "extractFirstChannel"; - int type = image.type(); - int depth = CV_MAT_DEPTH(type); - int cn = CV_MAT_CN(type); - - ocl::Kernel k (kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); - if (k.empty()) - return false; - - size_t globalsize[2] = {result.cols, result.rows}; - size_t localsize[2] = {16, 16}; - - return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,localsize,true); - } - - static bool matchTemplate_CCORR(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf) + static bool matchTemplate_CCORR(const UMat &image, const UMat &templ, UMat &result) { if (useNaive(TM_CCORR, image.depth(), templ.size()) ) return matchTemplateNaive_CCORR(image, templ, result, image.channels()); @@ -128,9 +103,9 @@ namespace cv return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,localsize,true); } - static bool matchTemplate_CCORR_NORMED(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf) + static bool matchTemplate_CCORR_NORMED(const UMat &image, const UMat &templ, UMat &result) { - if (!matchTemplate_CCORR(image, templ, result, buf)) + if (!matchTemplate_CCORR(image, templ, result)) return false; int type = image.type(); @@ -142,13 +117,13 @@ namespace cv if (k.empty()) return false; - UMat temp; - integral(image.reshape(1), buf.image_sums, temp); + UMat temp, image_sums, image_sqsums; + integral(image.reshape(1), image_sums, temp); if(temp.depth() == CV_64F) - temp.convertTo(buf.image_sqsums, CV_32F); + temp.convertTo(image_sqsums, CV_32F); else - buf.image_sqsums = temp; + image_sqsums = temp; UMat templ_resh; templ.reshape(1).convertTo(templ_resh, CV_32F); @@ -159,12 +134,12 @@ namespace cv size_t globalsize[2] = {result.cols, result.rows}; size_t localsize[2] = {16, 16}; - return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,localsize,true); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,localsize,true); } //////////////////////////////////////SQDIFF////////////////////////////////////////////////////////////// - static bool matchTemplate_SQDIFF(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf) + static bool matchTemplate_SQDIFF(const UMat &image, const UMat &templ, UMat &result) { if (useNaive(TM_SQDIFF, image.depth(), templ.size())) { @@ -193,9 +168,9 @@ namespace cv return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,localsize,true); } - static bool matchTemplate_SQDIFF_NORMED (const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf) + static bool matchTemplate_SQDIFF_NORMED (const UMat &image, const UMat &templ, UMat &result) { - if (!matchTemplate_CCORR(image, templ, result, buf)) + if (!matchTemplate_CCORR(image, templ, result)) return false; int type = image.type(); @@ -207,13 +182,13 @@ namespace cv if (k.empty()) return false; - UMat temp; - integral(image.reshape(1), buf.image_sums, temp); + UMat temp, image_sums, image_sqsums; + integral(image.reshape(1), image_sums, temp); if(temp.depth() == CV_64F) - temp.convertTo(buf.image_sqsums, CV_32F); + temp.convertTo(image_sqsums, CV_32F); else - buf.image_sqsums = temp; + image_sqsums = temp; UMat templ_resh; templ.reshape(1).convertTo(templ_resh, CV_32F); @@ -224,19 +199,20 @@ namespace cv size_t globalsize[2] = {result.cols, result.rows}; size_t localsize[2] = {16, 16}; - return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,localsize,true); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,localsize,true); } /////////////////////////////////////CCOEFF///////////////////////////////////////////////////////////////// - static bool matchTemplate_CCOEFF(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf) + static bool matchTemplate_CCOEFF(const UMat &image, const UMat &templ, UMat &result) { - if (!matchTemplate_CCORR(image, templ, result, buf)) + if (!matchTemplate_CCORR(image, templ, result)) return false; - integral(image, buf.image_sums); + UMat image_sums; + integral(image, image_sums); - int type = buf.image_sums.type(); + int type = image_sums.type(); int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); const char * kernelName; @@ -258,35 +234,36 @@ namespace cv if (cn==1) { float templ_sum = (float)sum(templ)[0]/ templ.size().area(); - return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sum).run(2,globalsize,localsize,true); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sum).run(2,globalsize,localsize,true); } else { Vec4f templ_sum = Vec4f::all(0); templ_sum = sum(templ)/ templ.size().area(); if (cn==2) - return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sum[0],templ_sum[1]).run(2,globalsize,localsize,true); - return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3]).run(2,globalsize,localsize,true); } } - static bool matchTemplate_CCOEFF_NORMED(const UMat &image, const UMat &templ, UMat &result, MatchTemplateBuf &buf) + static bool matchTemplate_CCOEFF_NORMED(const UMat &image, const UMat &templ, UMat &result) { - image.convertTo(buf.imagef, CV_32F); - templ.convertTo(buf.templf, CV_32F); + UMat imagef, templf; + image.convertTo(imagef, CV_32F); + templ.convertTo(templf, CV_32F); - if(!matchTemplate_CCORR(buf.imagef, buf.templf, result, buf)) + if(!matchTemplate_CCORR(imagef, templf, result)) return false; const char * kernelName; - UMat temp; - integral(image, buf.image_sums, temp); + UMat temp, image_sums, image_sqsums; + integral(image,image_sums, temp); - int type = buf.image_sums.type(); + int type = image_sums.type(); int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); if (cn== 1) @@ -302,9 +279,9 @@ namespace cv return false; if(temp.depth() == CV_64F) - temp.convertTo(buf.image_sqsums, CV_32F); + temp.convertTo(image_sqsums, CV_32F); else - buf.image_sqsums = temp; + image_sqsums = temp; size_t globalsize[2] = {result.cols, result.rows}; size_t localsize[2] = {16, 16}; @@ -315,7 +292,7 @@ namespace cv { float templ_sum = (float)sum(templ)[0]; - multiply(buf.templf, buf.templf, temp); + multiply(templf, templf, temp); float templ_sqsum = (float)sum(temp)[0]; templ_sqsum -= scale * templ_sum * templ_sum; @@ -327,7 +304,7 @@ namespace cv return true; } - return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sums),ocl::KernelArg::ReadOnlyNoSize(buf.image_sqsums), + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums),ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, templ_sum, templ_sqsum) .run(2,globalsize,localsize,true); } @@ -338,7 +315,7 @@ namespace cv templ_sum = sum(templ); - multiply(buf.templf, buf.templf, temp); + multiply(templf, templf, temp); templ_sqsum = sum(temp); float templ_sqsum_sum = 0; @@ -356,12 +333,12 @@ namespace cv } if (cn==2) - return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sums), ocl::KernelArg::ReadOnlyNoSize(buf.image_sqsums), + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, templ_sum[0],templ_sum[1], templ_sqsum_sum) .run(2,globalsize,localsize,true); - return k.args(ocl::KernelArg::ReadOnlyNoSize(buf.image_sums), ocl::KernelArg::ReadOnlyNoSize(buf.image_sqsums), + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3], templ_sqsum_sum) .run(2,globalsize,localsize,true); @@ -378,7 +355,7 @@ namespace cv CV_Assert( cn == _templ.channels() && cn!=3 && cn<=4); - typedef bool (*Caller)(const UMat &, const UMat &, UMat &, MatchTemplateBuf &); + typedef bool (*Caller)(const UMat &, const UMat &, UMat &); const Caller callers[] = { @@ -386,17 +363,13 @@ namespace cv matchTemplate_CCORR_NORMED, matchTemplate_CCOEFF, matchTemplate_CCOEFF_NORMED }; - Caller caller; - if (!(caller = callers[method])) - return false; - - MatchTemplateBuf buf; + Caller caller = callers[method]; UMat image = _img.getUMat(); UMat templ = _templ.getUMat(), result; _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); result = _result.getUMat(); - return caller(image, templ, result, buf); + return caller(image, templ, result); } } From 9de70c9a00e60f0ae333e23de939a2fb4c7300e9 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Tue, 14 Jan 2014 17:34:05 +0400 Subject: [PATCH 221/295] Fixed trailing whitespace --- modules/imgproc/src/opencl/match_template.cl | 4 ++-- modules/imgproc/src/templmatch.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/imgproc/src/opencl/match_template.cl b/modules/imgproc/src/opencl/match_template.cl index 26a9cbc1e..89a8d618f 100644 --- a/modules/imgproc/src/opencl/match_template.cl +++ b/modules/imgproc/src/opencl/match_template.cl @@ -93,7 +93,7 @@ __kernel void matchTemplate_Naive_CCORR (__global const uchar * img,int img_step for (int c = 0; c < CN; c++) sum += (float)(img_ptr[j*CN+c] * tpl_ptr[j*CN+c]); - + } __global float * result = (__global float *)(res)+res_idx; *result = sum; @@ -300,7 +300,7 @@ __kernel void matchTemplate_CCOEFF_NORMED_C1 (__global const uchar * img_sums, i __global ELEM_TYPE* sum = (__global ELEM_TYPE*)(img_sums); __global float * sqsum = (__global float*)(img_sqsums); - float image_sum_ = (float)((sum[SUMS_PTR(t_cols, t_rows)] - sum[SUMS_PTR(t_cols, 0)]) - + float image_sum_ = (float)((sum[SUMS_PTR(t_cols, t_rows)] - sum[SUMS_PTR(t_cols, 0)]) - (sum[SUMS_PTR(0, t_rows)] - sum[SUMS_PTR(0, 0)])); float image_sqsum_ = (float)((sqsum[SQSUMS_PTR(t_cols, t_rows)] - sqsum[SQSUMS_PTR(t_cols, 0)]) - diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index ea6bddc8d..1abb8fb2f 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -273,7 +273,7 @@ namespace cv else kernelName = "matchTemplate_CCOEFF_NORMED_C4"; - ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, + ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn)); if (k.empty()) return false; From da4d33ec2699575311474ccb42d4fa456d1fae56 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Wed, 15 Jan 2014 10:24:14 +0400 Subject: [PATCH 222/295] Fixed test_match_template --- modules/imgproc/test/ocl/test_match_template.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/imgproc/test/ocl/test_match_template.cpp b/modules/imgproc/test/ocl/test_match_template.cpp index 2163ac36c..48a8027b2 100644 --- a/modules/imgproc/test/ocl/test_match_template.cpp +++ b/modules/imgproc/test/ocl/test_match_template.cpp @@ -75,20 +75,19 @@ PARAM_TEST_CASE(MatchTemplate, MatDepth, Channels, int, bool) virtual void generateTestData() { Size image_roiSize = randomSize(2, 20); - Size templ_roiSize = Size (randomInt(1,image_roiSize.width), randomInt(1,image_roiSize.height)); + Size templ_roiSize = Size(randomInt(1,image_roiSize.width), randomInt(1,image_roiSize.height)); Size result_roiSize = Size(image_roiSize.width - templ_roiSize.width + 1, image_roiSize.height - templ_roiSize.height + 1); const double upValue = 256; - const double max_val = 100; - Border imageBorder = randomBorder(0, use_roi ? max_val : 0); + Border imageBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); randomSubMat(image, image_roi, image_roiSize, imageBorder, type, -upValue, upValue); - Border templBorder = randomBorder(0, use_roi ? max_val : 0); + Border templBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); randomSubMat(templ, templ_roi, templ_roiSize, templBorder, type, -upValue, upValue); - Border resultBorder = randomBorder(0, use_roi ? max_val : 0); + Border resultBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); randomSubMat(result, result_roi, result_roiSize, resultBorder, CV_32F, -upValue, upValue); UMAT_UPLOAD_INPUT_PARAMETER(image) From 47b572f99f4f818ac4cc3ac8c7ac50228aa64a0d Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Thu, 16 Jan 2014 14:26:48 +0400 Subject: [PATCH 223/295] fixed --- modules/imgproc/src/templmatch.cpp | 134 ++++++++++-------- .../imgproc/test/ocl/test_match_template.cpp | 2 +- 2 files changed, 78 insertions(+), 58 deletions(-) diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index 1abb8fb2f..ae10cd929 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -45,17 +45,17 @@ //////////////////////////////////////////////////matchTemplate////////////////////////////////////////////////////////// namespace cv { - static bool matchTemplate_CCORR(const UMat &image, const UMat &templ, UMat &result); - static bool matchTemplate_CCORR_NORMED(const UMat &image, const UMat &templ, UMat &result); + static bool matchTemplate_CCORR(InputArray _image, InputArray _templ, OutputArray _result); + static bool matchTemplate_CCORR_NORMED(InputArray _image, InputArray _templ, OutputArray _result); - static bool matchTemplate_SQDIFF(const UMat &image, const UMat &templ, UMat &result); - static bool matchTemplate_SQDIFF_NORMED (const UMat &image, const UMat &templ, UMat &result); + static bool matchTemplate_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result); + static bool matchTemplate_SQDIFF_NORMED (InputArray _image, InputArray _templ, OutputArray _result); - static bool matchTemplate_CCOEFF(const UMat &image, const UMat &templ, UMat &result); - static bool matchTemplate_CCOEFF_NORMED(const UMat &image, const UMat &templ, UMat &result); + static bool matchTemplate_CCOEFF(InputArray _image, InputArray _templ, OutputArray _result); + static bool matchTemplate_CCOEFF_NORMED(InputArray _image, InputArray _templ, OutputArray _result); - static bool matchTemplateNaive_CCORR (const UMat &image, const UMat &templ, UMat &result, int cn); - static bool matchTemplateNaive_SQDIFF(const UMat &image, const UMat &templ, UMat &result, int cn); + static bool matchTemplateNaive_CCORR (InputArray _image, InputArray _templ, OutputArray _result, int cn); + static bool matchTemplateNaive_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result, int cn); static bool useNaive(int method, int depth, Size size) { @@ -76,39 +76,41 @@ namespace cv ///////////////////////////////////////////////////CCORR////////////////////////////////////////////////////////////// - static bool matchTemplate_CCORR(const UMat &image, const UMat &templ, UMat &result) + static bool matchTemplate_CCORR(InputArray _image, InputArray _templ, OutputArray _result) { - if (useNaive(TM_CCORR, image.depth(), templ.size()) ) - return matchTemplateNaive_CCORR(image, templ, result, image.channels()); + if (useNaive(TM_CCORR, _image.depth(), _templ.size()) ) + return matchTemplateNaive_CCORR(_image, _templ, _result, _image.channels()); else return false; } - static bool matchTemplateNaive_CCORR (const UMat &image, const UMat &templ, UMat &result, int cn) + static bool matchTemplateNaive_CCORR (InputArray _image, InputArray _templ, OutputArray _result, int cn) { - int type = image.type(); + int type = _image.type(); int depth = CV_MAT_DEPTH(type); - CV_Assert(result.channels() == 1); - const char * kernelName = "matchTemplate_Naive_CCORR"; ocl::Kernel k (kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); if (k.empty()) return false; + UMat image = _image.getUMat(); + UMat templ = _templ.getUMat(), result; + _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); + result = _result.getUMat(); + size_t globalsize[2] = {result.cols, result.rows}; size_t localsize[2] = {16, 16}; - return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,localsize,true); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,localsize,false); } - static bool matchTemplate_CCORR_NORMED(const UMat &image, const UMat &templ, UMat &result) + static bool matchTemplate_CCORR_NORMED(InputArray _image, InputArray _templ, OutputArray _result) { - if (!matchTemplate_CCORR(image, templ, result)) - return false; + matchTemplate(_image, _templ, _result, CV_TM_CCORR); - int type = image.type(); + int type = _image.type(); int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); const char * kernelName = "matchTemplate_CCORR_NORMED"; @@ -117,6 +119,11 @@ namespace cv if (k.empty()) return false; + UMat image = _image.getUMat(); + UMat templ = _templ.getUMat(), result; + _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); + result = _result.getUMat(); + UMat temp, image_sums, image_sqsums; integral(image.reshape(1), image_sums, temp); @@ -134,46 +141,48 @@ namespace cv size_t globalsize[2] = {result.cols, result.rows}; size_t localsize[2] = {16, 16}; - return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,localsize,true); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,localsize,false); } //////////////////////////////////////SQDIFF////////////////////////////////////////////////////////////// - static bool matchTemplate_SQDIFF(const UMat &image, const UMat &templ, UMat &result) + static bool matchTemplate_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result) { - if (useNaive(TM_SQDIFF, image.depth(), templ.size())) + if (useNaive(TM_SQDIFF, _image.depth(), _templ.size())) { - return matchTemplateNaive_SQDIFF(image, templ, result, image.channels());; + return matchTemplateNaive_SQDIFF(_image, _templ, _result, _image.channels());; } else return false; } - static bool matchTemplateNaive_SQDIFF(const UMat &image, const UMat &templ, UMat &result, int cn) + static bool matchTemplateNaive_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result, int cn) { - int type = image.type(); + int type = _image.type(); int depth = CV_MAT_DEPTH(type); - CV_Assert(result.channels() == 1); - const char * kernelName = "matchTemplate_Naive_SQDIFF"; ocl::Kernel k (kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); if (k.empty()) return false; + UMat image = _image.getUMat(); + UMat templ = _templ.getUMat(), result; + _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); + result = _result.getUMat(); + size_t globalsize[2] = {result.cols, result.rows}; size_t localsize[2] = {16, 16}; - return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,localsize,true); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,localsize,false); } - static bool matchTemplate_SQDIFF_NORMED (const UMat &image, const UMat &templ, UMat &result) + static bool matchTemplate_SQDIFF_NORMED (InputArray _image, InputArray _templ, OutputArray _result) { - if (!matchTemplate_CCORR(image, templ, result)) - return false; + matchTemplate(_image, _templ, _result, CV_TM_CCORR); - int type = image.type(); + int type = _image.type(); int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); const char * kernelName = "matchTemplate_SQDIFF_NORMED"; @@ -182,6 +191,11 @@ namespace cv if (k.empty()) return false; + UMat image = _image.getUMat(); + UMat templ = _templ.getUMat(), result; + _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); + result = _result.getUMat(); + UMat temp, image_sums, image_sqsums; integral(image.reshape(1), image_sums, temp); @@ -199,18 +213,17 @@ namespace cv size_t globalsize[2] = {result.cols, result.rows}; size_t localsize[2] = {16, 16}; - return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,localsize,true); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,localsize,false); } /////////////////////////////////////CCOEFF///////////////////////////////////////////////////////////////// - static bool matchTemplate_CCOEFF(const UMat &image, const UMat &templ, UMat &result) + static bool matchTemplate_CCOEFF(InputArray _image, InputArray _templ, OutputArray _result) { - if (!matchTemplate_CCORR(image, templ, result)) - return false; + matchTemplate(_image, _templ, _result, CV_TM_CCORR); UMat image_sums; - integral(image, image_sums); + integral(_image, image_sums); int type = image_sums.type(); int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); @@ -228,13 +241,18 @@ namespace cv if (k.empty()) return false; + UMat templ = _templ.getUMat(), result; + int image_rows = _image.size().height, image_cols = _image.size().width; + _result.create(image_rows - templ.rows + 1, image_cols - templ.cols + 1, CV_32F); + result = _result.getUMat(); + size_t globalsize[2] = {result.cols, result.rows}; size_t localsize[2] = {16, 16}; if (cn==1) { - float templ_sum = (float)sum(templ)[0]/ templ.size().area(); - return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sum).run(2,globalsize,localsize,true); + float templ_sum = (float)sum(_templ)[0]/ _templ.size().area(); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sum).run(2,globalsize,localsize,false); } else { @@ -242,26 +260,26 @@ namespace cv templ_sum = sum(templ)/ templ.size().area(); if (cn==2) return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, - templ_sum[0],templ_sum[1]).run(2,globalsize,localsize,true); + templ_sum[0],templ_sum[1]).run(2,globalsize,localsize,false); return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, - templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3]).run(2,globalsize,localsize,true); + templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3]).run(2,globalsize,localsize,false); } } - static bool matchTemplate_CCOEFF_NORMED(const UMat &image, const UMat &templ, UMat &result) + static bool matchTemplate_CCOEFF_NORMED(InputArray _image, InputArray _templ, OutputArray _result) { UMat imagef, templf; - image.convertTo(imagef, CV_32F); - templ.convertTo(templf, CV_32F); - if(!matchTemplate_CCORR(imagef, templf, result)) - return false; + _image.getUMat().convertTo(imagef, CV_32F); + _templ.getUMat().convertTo(templf, CV_32F); + + matchTemplate(imagef, templf, _result, CV_TM_CCORR); const char * kernelName; UMat temp, image_sums, image_sqsums; - integral(image,image_sums, temp); + integral(_image,image_sums, temp); int type = image_sums.type(); int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); @@ -278,6 +296,12 @@ namespace cv if (k.empty()) return false; + UMat image = _image.getUMat(); + UMat templ = _templ.getUMat(), result; + int image_rows = _image.size().height, image_cols = _image.size().width; + _result.create(image_rows - templ.rows + 1, image_cols - templ.cols + 1, CV_32F); + result = _result.getUMat(); + if(temp.depth() == CV_64F) temp.convertTo(image_sqsums, CV_32F); else @@ -306,7 +330,7 @@ namespace cv return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums),ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, templ_sum, templ_sqsum) - .run(2,globalsize,localsize,true); + .run(2,globalsize,localsize,false); } else { @@ -336,12 +360,12 @@ namespace cv return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, templ_sum[0],templ_sum[1], templ_sqsum_sum) - .run(2,globalsize,localsize,true); + .run(2,globalsize,localsize,false); return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3], templ_sqsum_sum) - .run(2,globalsize,localsize,true); + .run(2,globalsize,localsize,false); } } @@ -355,7 +379,7 @@ namespace cv CV_Assert( cn == _templ.channels() && cn!=3 && cn<=4); - typedef bool (*Caller)(const UMat &, const UMat &, UMat &); + typedef bool (*Caller)(InputArray _img, InputArray _templ, OutputArray _result); const Caller callers[] = { @@ -365,11 +389,7 @@ namespace cv Caller caller = callers[method]; - UMat image = _img.getUMat(); - UMat templ = _templ.getUMat(), result; - _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); - result = _result.getUMat(); - return caller(image, templ, result); + return caller(_img, _templ, _result); } } diff --git a/modules/imgproc/test/ocl/test_match_template.cpp b/modules/imgproc/test/ocl/test_match_template.cpp index 48a8027b2..2a0402342 100644 --- a/modules/imgproc/test/ocl/test_match_template.cpp +++ b/modules/imgproc/test/ocl/test_match_template.cpp @@ -74,7 +74,7 @@ PARAM_TEST_CASE(MatchTemplate, MatDepth, Channels, int, bool) virtual void generateTestData() { - Size image_roiSize = randomSize(2, 20); + Size image_roiSize = randomSize(2, 100); Size templ_roiSize = Size(randomInt(1,image_roiSize.width), randomInt(1,image_roiSize.height)); Size result_roiSize = Size(image_roiSize.width - templ_roiSize.width + 1, image_roiSize.height - templ_roiSize.height + 1); From 4da1ba56b3c705bd9217ee16d810d754368ff5de Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Fri, 17 Jan 2014 15:01:22 +0400 Subject: [PATCH 224/295] fixed --- modules/imgproc/src/opencl/match_template.cl | 126 +++++++++---------- modules/imgproc/src/templmatch.cpp | 77 +++++------- 2 files changed, 87 insertions(+), 116 deletions(-) diff --git a/modules/imgproc/src/opencl/match_template.cl b/modules/imgproc/src/opencl/match_template.cl index 89a8d618f..451ec0cb2 100644 --- a/modules/imgproc/src/opencl/match_template.cl +++ b/modules/imgproc/src/opencl/match_template.cl @@ -29,15 +29,13 @@ // 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. -#define DATA_TYPE type #define DATA_SIZE ((int)sizeof(type)) #define ELEM_TYPE elem_type #define ELEM_SIZE ((int)sizeof(elem_type)) #define CN cn -#define SQSUMS_PTR(ox, oy) mad24(gidy + oy, img_sqsums_step, (gidx + img_sqsums_offset + ox) * CN) -#define SQSUMS(ox, oy) mad24(gidy + oy, img_sqsums_step, (gidx*CN + img_sqsums_offset + ox*CN)) -#define SUMS_PTR(ox, oy) mad24(gidy + oy, img_sums_step, (gidx*CN + img_sums_offset + ox*CN)) +#define SQSUMS_PTR(ox, oy) mad24(gidy + oy, img_sqsums_step, gidx*CN + img_sqsums_offset + ox*CN) +#define SUMS_PTR(ox, oy) mad24(gidy + oy, img_sums_step, gidx*CN + img_sums_offset + ox*CN) inline float normAcc(float num, float denum) { @@ -76,10 +74,7 @@ __kernel void matchTemplate_Naive_CCORR (__global const uchar * img,int img_step int i,j; float sum = 0; - res_step /= sizeof(float); - res_offset /= sizeof(float); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); + int res_idx = mad24(gidy, res_step, res_offset + gidx * (int)sizeof(float)); if(gidx < res_cols && gidy < res_rows) { @@ -90,12 +85,13 @@ __kernel void matchTemplate_Naive_CCORR (__global const uchar * img,int img_step for(j = 0; j < tpl_cols; j ++) +#pragma unroll for (int c = 0; c < CN; c++) sum += (float)(img_ptr[j*CN+c] * tpl_ptr[j*CN+c]); } - __global float * result = (__global float *)(res)+res_idx; + __global float * result = (__global float *)(res+res_idx); *result = sum; } } @@ -109,10 +105,8 @@ __kernel void matchTemplate_CCORR_NORMED ( __global const uchar * img_sqsums, in img_sqsums_step /= sizeof(float); img_sqsums_offset /= sizeof(float); - res_step /= sizeof(float); - res_offset /= sizeof(float); - int res_idx = mad24(gidy, res_step, res_offset + gidx); + int res_idx = mad24(gidy, res_step, res_offset + gidx * (int)sizeof(float)); if(gidx < res_cols && gidy < res_rows) { @@ -121,7 +115,7 @@ __kernel void matchTemplate_CCORR_NORMED ( __global const uchar * img_sqsums, in (sqsum[SQSUMS_PTR(tpl_cols, tpl_rows)] - sqsum[SQSUMS_PTR(tpl_cols, 0)]) - (sqsum[SQSUMS_PTR(0, tpl_rows)] - sqsum[SQSUMS_PTR(0, 0)])); - __global float * result = (__global float *)(res)+res_idx; + __global float * result = (__global float *)(res+res_idx); *result = normAcc(*result, sqrt(image_sqsum_ * tpl_sqsum)); } } @@ -138,10 +132,7 @@ __kernel void matchTemplate_Naive_SQDIFF(__global const uchar * img,int img_step float delta; float sum = 0; - res_step /= sizeof(float); - res_offset /= sizeof(float); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); + int res_idx = mad24(gidy, res_step, res_offset + gidx * (int)sizeof(float)); if(gidx < res_cols && gidy < res_rows) { @@ -152,13 +143,14 @@ __kernel void matchTemplate_Naive_SQDIFF(__global const uchar * img,int img_step for(j = 0; j < tpl_cols; j ++) +#pragma unroll for (int c = 0; c < CN; c++) { delta = (float)(img_ptr[j*CN+c] - tpl_ptr[j*CN+c]); sum += delta*delta; } } - __global float * result = (__global float *)(res)+res_idx; + __global float * result = (__global float *)(res+res_idx); *result = sum; } } @@ -172,10 +164,8 @@ __kernel void matchTemplate_SQDIFF_NORMED ( __global const uchar * img_sqsums, i img_sqsums_step /= sizeof(float); img_sqsums_offset /= sizeof(float); - res_step /= sizeof(float); - res_offset /= sizeof(float); - int res_idx = mad24(gidy, res_step, res_offset + gidx); + int res_idx = mad24(gidy, res_step, res_offset + gidx * (int)sizeof(float)); if(gidx < res_cols && gidy < res_rows) { @@ -184,7 +174,7 @@ __kernel void matchTemplate_SQDIFF_NORMED ( __global const uchar * img_sqsums, i (sqsum[SQSUMS_PTR(tpl_cols, tpl_rows)] - sqsum[SQSUMS_PTR(tpl_cols, 0)]) - (sqsum[SQSUMS_PTR(0, tpl_rows)] - sqsum[SQSUMS_PTR(0, 0)])); - __global float * result = (__global float *)(res)+res_idx; + __global float * result = (__global float *)(res+res_idx); *result = normAcc_SQDIFF(image_sqsum_ - 2.f * result[0] + tpl_sqsum, sqrt(image_sqsum_ * tpl_sqsum)); } @@ -201,10 +191,8 @@ __kernel void matchTemplate_Prepared_CCOEFF_C1 (__global const uchar * img_sums, img_sums_step /= ELEM_SIZE; img_sums_offset /= ELEM_SIZE; - res_step /= sizeof(float); - res_offset /= sizeof(float); - int res_idx = mad24(gidy, res_step, res_offset + gidx); + int res_idx = mad24(gidy, res_step, res_offset + gidx * (int)sizeof(float)); float image_sum_ = 0; if(gidx < res_cols && gidy < res_rows) @@ -214,7 +202,7 @@ __kernel void matchTemplate_Prepared_CCOEFF_C1 (__global const uchar * img_sums, image_sum_ += (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)] - sum[SUMS_PTR(tpl_cols, 0)])- (sum[SUMS_PTR(0, tpl_rows)] - sum[SUMS_PTR(0, 0)])) * tpl_sum; - __global float * result = (__global float *)(res)+res_idx; + __global float * result = (__global float *)(res+res_idx); *result -= image_sum_; } } @@ -228,10 +216,8 @@ __kernel void matchTemplate_Prepared_CCOEFF_C2 (__global const uchar * img_sums, img_sums_step /= ELEM_SIZE; img_sums_offset /= ELEM_SIZE; - res_step /= sizeof(float); - res_offset /= sizeof(float); - int res_idx = mad24(gidy, res_step, res_offset + gidx); + int res_idx = mad24(gidy, res_step, res_offset + gidx * (int)sizeof(float)); float image_sum_ = 0; if(gidx < res_cols && gidy < res_rows) @@ -241,37 +227,40 @@ __kernel void matchTemplate_Prepared_CCOEFF_C2 (__global const uchar * img_sums, image_sum_ += tpl_sum_0 * (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)] - sum[SUMS_PTR(tpl_cols, 0)]) -(sum[SUMS_PTR(0, tpl_rows)] - sum[SUMS_PTR(0, 0)])); image_sum_ += tpl_sum_1 * (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)+1] - sum[SUMS_PTR(tpl_cols, 0)+1])-(sum[SUMS_PTR(0, tpl_rows)+1] - sum[SUMS_PTR(0, 0)+1])); - __global float * result = (__global float *)(res)+res_idx; + __global float * result = (__global float *)(res+res_idx); *result -= image_sum_; } } __kernel void matchTemplate_Prepared_CCOEFF_C4 (__global const uchar * img_sums, int img_sums_step, int img_sums_offset, - __global uchar * res, int res_step, int res_offset, int res_rows, int res_cols, - int tpl_rows, int tpl_cols, float tpl_sum_0,float tpl_sum_1,float tpl_sum_2,float tpl_sum_3) + __global uchar * res, int res_step, int res_offset, int res_rows, int res_cols, + int tpl_rows, int tpl_cols, float tpl_sum_0,float tpl_sum_1,float tpl_sum_2,float tpl_sum_3) { int gidx = get_global_id(0); int gidy = get_global_id(1); img_sums_step /= ELEM_SIZE; img_sums_offset /= ELEM_SIZE; - res_step /= sizeof(float); - res_offset /= sizeof(float); - int res_idx = mad24(gidy, res_step, res_offset + gidx); + int res_idx = mad24(gidy, res_step, res_offset + gidx * (int)sizeof(float)); float image_sum_ = 0; if(gidx < res_cols && gidy < res_rows) { __global ELEM_TYPE* sum = (__global ELEM_TYPE*)(img_sums); - image_sum_ += tpl_sum_0 * (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)] - sum[SUMS_PTR(tpl_cols, 0)]) -(sum[SUMS_PTR(0, tpl_rows)] - sum[SUMS_PTR(0, 0)])); - image_sum_ += tpl_sum_1 * (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)+1] - sum[SUMS_PTR(tpl_cols, 0)+1])-(sum[SUMS_PTR(0, tpl_rows)+1] - sum[SUMS_PTR(0, 0)+1])); - image_sum_ += tpl_sum_2 * (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)+2] - sum[SUMS_PTR(tpl_cols, 0)+2])-(sum[SUMS_PTR(0, tpl_rows)+2] - sum[SUMS_PTR(0, 0)+2])); - image_sum_ += tpl_sum_3 * (float)((sum[SUMS_PTR(tpl_cols, tpl_rows)+3] - sum[SUMS_PTR(tpl_cols, 0)+3])-(sum[SUMS_PTR(0, tpl_rows)+3] - sum[SUMS_PTR(0, 0)+3])); + int c_r = SUMS_PTR(tpl_cols, tpl_rows); + int c_o = SUMS_PTR(tpl_cols, 0); + int o_r = SUMS_PTR(0,tpl_rows); + int oo = SUMS_PTR(0, 0); - __global float * result = (__global float *)(res)+res_idx; + image_sum_ += tpl_sum_0 * (float)((sum[c_r] - sum[c_o]) -(sum[o_r] - sum[oo])); + image_sum_ += tpl_sum_1 * (float)((sum[c_r+1] - sum[c_o+1])-(sum[o_r+1] - sum[oo+1])); + image_sum_ += tpl_sum_2 * (float)((sum[c_r+2] - sum[c_o+2])-(sum[o_r+2] - sum[oo+2])); + image_sum_ += tpl_sum_3 * (float)((sum[c_r+3] - sum[c_o+3])-(sum[o_r+3] - sum[oo+3])); + + __global float * result = (__global float *)(res+res_idx); *result -= image_sum_; } @@ -279,7 +268,7 @@ __kernel void matchTemplate_Prepared_CCOEFF_C4 (__global const uchar * img_sums, __kernel void matchTemplate_CCOEFF_NORMED_C1 (__global const uchar * img_sums, int img_sums_step, int img_sums_offset, __global const uchar * img_sqsums, int img_sqsums_step, int img_sqsums_offset, - __global float * res, int res_step, int res_offset, int res_rows, int res_cols, + __global uchar * res, int res_step, int res_offset, int res_rows, int res_cols, int t_rows, int t_cols, float weight, float tpl_sum, float tpl_sqsum) { int gidx = get_global_id(0); @@ -289,11 +278,8 @@ __kernel void matchTemplate_CCOEFF_NORMED_C1 (__global const uchar * img_sums, i img_sums_step /= ELEM_SIZE; img_sqsums_step /= sizeof(float); img_sqsums_offset /= sizeof(float); - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); + int res_idx = mad24(gidy, res_step, res_offset + gidx * (int)sizeof(float)); if(gidx < res_cols && gidy < res_rows) { @@ -306,7 +292,7 @@ __kernel void matchTemplate_CCOEFF_NORMED_C1 (__global const uchar * img_sums, i float image_sqsum_ = (float)((sqsum[SQSUMS_PTR(t_cols, t_rows)] - sqsum[SQSUMS_PTR(t_cols, 0)]) - (sqsum[SQSUMS_PTR(0, t_rows)] - sqsum[SQSUMS_PTR(0, 0)])); - __global float * result = (__global float *)(res)+res_idx; + __global float * result = (__global float *)(res+res_idx); *result = normAcc((*result) - image_sum_ * tpl_sum, sqrt(tpl_sqsum * (image_sqsum_ - weight * image_sum_ * image_sum_))); @@ -315,7 +301,7 @@ __kernel void matchTemplate_CCOEFF_NORMED_C1 (__global const uchar * img_sums, i __kernel void matchTemplate_CCOEFF_NORMED_C2 (__global const uchar * img_sums, int img_sums_step, int img_sums_offset, __global const uchar * img_sqsums, int img_sqsums_step, int img_sqsums_offset, - __global float * res, int res_step, int res_offset, int res_rows, int res_cols, + __global uchar * res, int res_step, int res_offset, int res_rows, int res_cols, int t_rows, int t_cols, float weight, float tpl_sum_0, float tpl_sum_1, float tpl_sqsum) { int gidx = get_global_id(0); @@ -325,11 +311,8 @@ __kernel void matchTemplate_CCOEFF_NORMED_C2 (__global const uchar * img_sums, i img_sums_step /= ELEM_SIZE; img_sqsums_step /= sizeof(float); img_sqsums_offset /= sizeof(float); - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); + int res_idx = mad24(gidy, res_step, res_offset + gidx * (int)sizeof(float)); float sum_[2]; float sqsum_[2]; @@ -342,22 +325,22 @@ __kernel void matchTemplate_CCOEFF_NORMED_C2 (__global const uchar * img_sums, i sum_[0] = (float)((sum[SUMS_PTR(t_cols, t_rows)] - sum[SUMS_PTR(t_cols, 0)])-(sum[SUMS_PTR(0, t_rows)] - sum[SUMS_PTR(0, 0)])); sum_[1] = (float)((sum[SUMS_PTR(t_cols, t_rows)+1] - sum[SUMS_PTR(t_cols, 0)+1])-(sum[SUMS_PTR(0, t_rows)+1] - sum[SUMS_PTR(0, 0)+1])); - sqsum_[0] = (float)((sqsum[SQSUMS(t_cols, t_rows)] - sqsum[SQSUMS(t_cols, 0)])-(sqsum[SQSUMS(0, t_rows)] - sqsum[SQSUMS(0, 0)])); - sqsum_[1] = (float)((sqsum[SQSUMS(t_cols, t_rows)+1] - sqsum[SQSUMS(t_cols, 0)+1])-(sqsum[SQSUMS(0, t_rows)+1] - sqsum[SQSUMS(0, 0)+1])); + sqsum_[0] = (float)((sqsum[SQSUMS_PTR(t_cols, t_rows)] - sqsum[SQSUMS_PTR(t_cols, 0)])-(sqsum[SQSUMS_PTR(0, t_rows)] - sqsum[SQSUMS_PTR(0, 0)])); + sqsum_[1] = (float)((sqsum[SQSUMS_PTR(t_cols, t_rows)+1] - sqsum[SQSUMS_PTR(t_cols, 0)+1])-(sqsum[SQSUMS_PTR(0, t_rows)+1] - sqsum[SQSUMS_PTR(0, 0)+1])); float num = sum_[0]*tpl_sum_0 + sum_[1]*tpl_sum_1; float denum = sqrt( tpl_sqsum * (sqsum_[0] - weight * sum_[0]* sum_[0] + sqsum_[1] - weight * sum_[1]* sum_[1])); - __global float * result = (__global float *)(res)+res_idx; + __global float * result = (__global float *)(res+res_idx); *result = normAcc((*result) - num, denum); } } __kernel void matchTemplate_CCOEFF_NORMED_C4 (__global const uchar * img_sums, int img_sums_step, int img_sums_offset, __global const uchar * img_sqsums, int img_sqsums_step, int img_sqsums_offset, - __global float * res, int res_step, int res_offset, int res_rows, int res_cols, + __global uchar * res, int res_step, int res_offset, int res_rows, int res_cols, int t_rows, int t_cols, float weight, float tpl_sum_0,float tpl_sum_1,float tpl_sum_2,float tpl_sum_3, float tpl_sqsum) @@ -369,11 +352,8 @@ __kernel void matchTemplate_CCOEFF_NORMED_C4 (__global const uchar * img_sums, i img_sums_step /= ELEM_SIZE; img_sqsums_step /= sizeof(float); img_sqsums_offset /= sizeof(float); - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); + int res_idx = mad24(gidy, res_step, res_offset + gidx * (int)sizeof(float)); float sum_[4]; float sqsum_[4]; @@ -383,15 +363,25 @@ __kernel void matchTemplate_CCOEFF_NORMED_C4 (__global const uchar * img_sums, i __global ELEM_TYPE* sum = (__global ELEM_TYPE*)(img_sums); __global float * sqsum = (__global float*)(img_sqsums); - sum_[0] = (float)((sum[SUMS_PTR(t_cols, t_rows)] - sum[SUMS_PTR(t_cols, 0)])-(sum[SUMS_PTR(0, t_rows)] - sum[SUMS_PTR(0, 0)])); - sum_[1] = (float)((sum[SUMS_PTR(t_cols, t_rows)+1] - sum[SUMS_PTR(t_cols, 0)+1])-(sum[SUMS_PTR(0, t_rows)+1] - sum[SUMS_PTR(0, 0)+1])); - sum_[2] = (float)((sum[SUMS_PTR(t_cols, t_rows)+2] - sum[SUMS_PTR(t_cols, 0)+2])-(sum[SUMS_PTR(0, t_rows)+2] - sum[SUMS_PTR(0, 0)+2])); - sum_[3] = (float)((sum[SUMS_PTR(t_cols, t_rows)+3] - sum[SUMS_PTR(t_cols, 0)+3])-(sum[SUMS_PTR(0, t_rows)+3] - sum[SUMS_PTR(0, 0)+3])); + int c_r = SUMS_PTR(t_cols, t_rows); + int c_o = SUMS_PTR(t_cols, 0); + int o_r = SUMS_PTR(0, t_rows); + int o_o = SUMS_PTR(0, 0); - sqsum_[0] = (float)((sqsum[SQSUMS(t_cols, t_rows)] - sqsum[SQSUMS(t_cols, 0)])-(sqsum[SQSUMS(0, t_rows)] - sqsum[SQSUMS(0, 0)])); - sqsum_[1] = (float)((sqsum[SQSUMS(t_cols, t_rows)+1] - sqsum[SQSUMS(t_cols, 0)+1])-(sqsum[SQSUMS(0, t_rows)+1] - sqsum[SQSUMS(0, 0)+1])); - sqsum_[2] = (float)((sqsum[SQSUMS(t_cols, t_rows)+2] - sqsum[SQSUMS(t_cols, 0)+2])-(sqsum[SQSUMS(0, t_rows)+2] - sqsum[SQSUMS(0, 0)+2])); - sqsum_[3] = (float)((sqsum[SQSUMS(t_cols, t_rows)+3] - sqsum[SQSUMS(t_cols, 0)+3])-(sqsum[SQSUMS(0, t_rows)+3] - sqsum[SQSUMS(0, 0)+3])); + sum_[0] = (float)((sum[c_r] - sum[c_o]) -(sum[o_r] - sum[o_o ])); + sum_[1] = (float)((sum[c_r+1] - sum[c_o+1])-(sum[o_r+1] - sum[o_o +1])); + sum_[2] = (float)((sum[c_r+2] - sum[c_o+2])-(sum[o_r+2] - sum[o_o +2])); + sum_[3] = (float)((sum[c_r+3] - sum[c_o+3])-(sum[o_r+3] - sum[o_o +3])); + + c_r = SQSUMS_PTR(t_cols, t_rows); + c_o = SQSUMS_PTR(t_cols, 0); + o_r = SQSUMS_PTR(0, t_rows); + o_o = SQSUMS_PTR(0, 0); + + sqsum_[0] = (float)((sqsum[c_r] - sqsum[c_o]) -(sqsum[o_r] - sqsum[o_o])); + sqsum_[1] = (float)((sqsum[c_r+1] - sqsum[c_o+1])-(sqsum[o_r+1] - sqsum[o_o+1])); + sqsum_[2] = (float)((sqsum[c_r+2] - sqsum[c_o+2])-(sqsum[o_r+2] - sqsum[o_o+2])); + sqsum_[3] = (float)((sqsum[c_r+3] - sqsum[c_o+3])-(sqsum[o_r+3] - sqsum[o_o+3])); float num = sum_[0]*tpl_sum_0 + sum_[1]*tpl_sum_1 + sum_[2]*tpl_sum_2 + sum_[3]*tpl_sum_3; @@ -401,7 +391,7 @@ __kernel void matchTemplate_CCOEFF_NORMED_C4 (__global const uchar * img_sums, i sqsum_[2] - weight * sum_[2]* sum_[2] + sqsum_[3] - weight * sum_[3]* sum_[3] )); - __global float * result = (__global float *)(res)+res_idx; + __global float * result = (__global float *)(res+res_idx); *result = normAcc((*result) - num, denum); } } \ No newline at end of file diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index ae10cd929..bb3423bb2 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -101,9 +101,8 @@ namespace cv result = _result.getUMat(); size_t globalsize[2] = {result.cols, result.rows}; - size_t localsize[2] = {16, 16}; - return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,localsize,false); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,NULL,false); } static bool matchTemplate_CCORR_NORMED(InputArray _image, InputArray _templ, OutputArray _result) @@ -124,24 +123,18 @@ namespace cv _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); result = _result.getUMat(); - UMat temp, image_sums, image_sqsums; - integral(image.reshape(1), image_sums, temp); + UMat image_sums, image_sqsums; + integral(image.reshape(1), image_sums, image_sqsums, CV_32F, CV_32F); - if(temp.depth() == CV_64F) - temp.convertTo(image_sqsums, CV_32F); - else - image_sqsums = temp; - - UMat templ_resh; + UMat templ_resh, temp; templ.reshape(1).convertTo(templ_resh, CV_32F); multiply(templ_resh, templ_resh, temp); unsigned long long templ_sqsum = (unsigned long long)sum(temp)[0]; size_t globalsize[2] = {result.cols, result.rows}; - size_t localsize[2] = {16, 16}; - return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,localsize,false); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,NULL,false); } //////////////////////////////////////SQDIFF////////////////////////////////////////////////////////////// @@ -173,9 +166,8 @@ namespace cv result = _result.getUMat(); size_t globalsize[2] = {result.cols, result.rows}; - size_t localsize[2] = {16, 16}; - return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,localsize,false); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,NULL,false); } static bool matchTemplate_SQDIFF_NORMED (InputArray _image, InputArray _templ, OutputArray _result) @@ -196,24 +188,18 @@ namespace cv _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); result = _result.getUMat(); - UMat temp, image_sums, image_sqsums; - integral(image.reshape(1), image_sums, temp); + UMat image_sums, image_sqsums; + integral(image.reshape(1), image_sums, image_sqsums, CV_32F, CV_32F); - if(temp.depth() == CV_64F) - temp.convertTo(image_sqsums, CV_32F); - else - image_sqsums = temp; - - UMat templ_resh; + UMat temp, templ_resh; templ.reshape(1).convertTo(templ_resh, CV_32F); multiply(templ_resh, templ_resh, temp); unsigned long long templ_sqsum = (unsigned long long)sum(temp)[0]; size_t globalsize[2] = {result.cols, result.rows}; - size_t localsize[2] = {16, 16}; - return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,localsize,false); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,NULL,false); } /////////////////////////////////////CCOEFF///////////////////////////////////////////////////////////////// @@ -242,17 +228,16 @@ namespace cv return false; UMat templ = _templ.getUMat(), result; - int image_rows = _image.size().height, image_cols = _image.size().width; - _result.create(image_rows - templ.rows + 1, image_cols - templ.cols + 1, CV_32F); + Size size = _image.size(); + _result.create(size.height - templ.rows + 1, size.width - templ.cols + 1, CV_32F); result = _result.getUMat(); size_t globalsize[2] = {result.cols, result.rows}; - size_t localsize[2] = {16, 16}; if (cn==1) { float templ_sum = (float)sum(_templ)[0]/ _templ.size().area(); - return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sum).run(2,globalsize,localsize,false); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sum).run(2,globalsize,NULL,false); } else { @@ -260,10 +245,10 @@ namespace cv templ_sum = sum(templ)/ templ.size().area(); if (cn==2) return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, - templ_sum[0],templ_sum[1]).run(2,globalsize,localsize,false); + templ_sum[0],templ_sum[1]).run(2,globalsize,NULL,false); return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, - templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3]).run(2,globalsize,localsize,false); + templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3]).run(2,globalsize,NULL,false); } } @@ -279,7 +264,7 @@ namespace cv const char * kernelName; UMat temp, image_sums, image_sqsums; - integral(_image,image_sums, temp); + integral(_image,image_sums, image_sqsums, CV_32F, CV_32F); int type = image_sums.type(); int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); @@ -302,13 +287,7 @@ namespace cv _result.create(image_rows - templ.rows + 1, image_cols - templ.cols + 1, CV_32F); result = _result.getUMat(); - if(temp.depth() == CV_64F) - temp.convertTo(image_sqsums, CV_32F); - else - image_sqsums = temp; - size_t globalsize[2] = {result.cols, result.rows}; - size_t localsize[2] = {16, 16}; float scale = 1.f / templ.size().area(); @@ -330,7 +309,7 @@ namespace cv return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums),ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, templ_sum, templ_sqsum) - .run(2,globalsize,localsize,false); + .run(2,globalsize,NULL,false); } else { @@ -360,12 +339,12 @@ namespace cv return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, templ_sum[0],templ_sum[1], templ_sqsum_sum) - .run(2,globalsize,localsize,false); + .run(2,globalsize,NULL,false); return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3], templ_sqsum_sum) - .run(2,globalsize,localsize,false); + .run(2,globalsize,NULL,false); } } @@ -374,10 +353,10 @@ namespace cv static bool ocl_matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method) { - int type = _img.type(); - int cn = CV_MAT_CN(type); + int cn = CV_MAT_CN(_img.type()); - CV_Assert( cn == _templ.channels() && cn!=3 && cn<=4); + if (cn == 3 || cn > 4) + return false; typedef bool (*Caller)(InputArray _img, InputArray _templ, OutputArray _result); @@ -588,13 +567,15 @@ void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, CV_Assert( (_img.depth() == CV_8U || _img.depth() == CV_32F) && _img.type() == _templ.type() ); - CV_Assert(_img.size().height >= _templ.size().height && _img.size().width >= _templ.size().width); - CV_Assert(_img.dims() <= 2); + + bool swapNotNeed = (_img.size().height >= _templ.size().height && _img.size().width >= _templ.size().width); + if (!swapNotNeed) + CV_Assert(_img.size().height <= _templ.size().height && _img.size().width <= _templ.size().width); bool use_opencl = ocl::useOpenCL() && _result.isUMat(); - if ( use_opencl && ocl_matchTemplate(_img,_templ,_result,method)) - return; + if ( use_opencl && (swapNotNeed ? ocl_matchTemplate(_img,_templ,_result,method) : ocl_matchTemplate(_templ,_img,_result,method))) + return; int numType = method == CV_TM_CCORR || method == CV_TM_CCORR_NORMED ? 0 : method == CV_TM_CCOEFF || method == CV_TM_CCOEFF_NORMED ? 1 : 2; @@ -603,7 +584,7 @@ void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, method == CV_TM_CCOEFF_NORMED; Mat img = _img.getMat(), templ = _templ.getMat(); - if( img.rows < templ.rows || img.cols < templ.cols ) + if(!swapNotNeed ) std::swap(img, templ); Size corrSize(img.cols - templ.cols + 1, img.rows - templ.rows + 1); From 7e2bdb590f781de8c2fb6c2109641e81fae4146b Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Fri, 17 Jan 2014 16:26:11 +0400 Subject: [PATCH 225/295] fixed --- modules/imgproc/src/templmatch.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index bb3423bb2..aaaa83345 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -571,7 +571,9 @@ void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, bool swapNotNeed = (_img.size().height >= _templ.size().height && _img.size().width >= _templ.size().width); if (!swapNotNeed) + { CV_Assert(_img.size().height <= _templ.size().height && _img.size().width <= _templ.size().width); + } bool use_opencl = ocl::useOpenCL() && _result.isUMat(); if ( use_opencl && (swapNotNeed ? ocl_matchTemplate(_img,_templ,_result,method) : ocl_matchTemplate(_templ,_img,_result,method))) From 2c0765b4d13260a53103b2693a13d997efd15784 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Fri, 17 Jan 2014 18:37:57 +0400 Subject: [PATCH 226/295] fixed trailing whitespace --- modules/imgproc/src/templmatch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index aaaa83345..9953c6851 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -568,7 +568,7 @@ void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, CV_Assert( (_img.depth() == CV_8U || _img.depth() == CV_32F) && _img.type() == _templ.type() ); CV_Assert(_img.dims() <= 2); - + bool swapNotNeed = (_img.size().height >= _templ.size().height && _img.size().width >= _templ.size().width); if (!swapNotNeed) { From b4652e2cb32a3824ec70cd0c5f7ca6df09c99685 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Mon, 20 Jan 2014 15:48:16 +0400 Subject: [PATCH 227/295] Added perf test for ocl_matchTemplate --- .../perf/opencl/perf_matchTemplate.cpp | 54 +++++++++++++++++++ .../imgproc/test/ocl/test_match_template.cpp | 3 +- 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 modules/imgproc/perf/opencl/perf_matchTemplate.cpp diff --git a/modules/imgproc/perf/opencl/perf_matchTemplate.cpp b/modules/imgproc/perf/opencl/perf_matchTemplate.cpp new file mode 100644 index 000000000..b790f36cc --- /dev/null +++ b/modules/imgproc/perf/opencl/perf_matchTemplate.cpp @@ -0,0 +1,54 @@ +#include "perf_precomp.hpp" +#include "opencv2/ts/ocl_perf.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { + +namespace ocl { + + CV_ENUM(MethodType, TM_SQDIFF, TM_SQDIFF_NORMED, TM_CCORR, TM_CCORR_NORMED, TM_CCOEFF, TM_CCOEFF_NORMED) + + typedef std::tr1::tuple ImgSize_TmplSize_Method_t; + typedef TestBaseWithParam ImgSize_TmplSize_Method; + + OCL_PERF_TEST_P(ImgSize_TmplSize_Method, matchTemplate, + ::testing::Combine( + testing::Values(szSmall128, cv::Size(320, 240), + cv::Size(640, 480), cv::Size(800, 600), + cv::Size(1024, 768), cv::Size(1280, 1024)), + testing::Values(cv::Size(12, 12), cv::Size(28, 9), + cv::Size(8, 30), cv::Size(16, 16)), + MethodType::all() + ) + ) + { + Size imgSz = get<0>(GetParam()); + Size tmplSz = get<1>(GetParam()); + int method = get<2>(GetParam()); + + Mat img(imgSz, CV_8UC1); + Mat tmpl(tmplSz, CV_8UC1); + Mat result(imgSz - tmplSz + Size(1,1), CV_32F); + + declare + .in(img, WARMUP_RNG) + .in(tmpl, WARMUP_RNG) + .out(result) + .time(30); + + OCL_TEST_CYCLE() matchTemplate(img, tmpl, result, method); + + bool isNormed = + method == TM_CCORR_NORMED || + method == TM_SQDIFF_NORMED || + method == TM_CCOEFF_NORMED; + double eps = isNormed ? 1e-6 + : 255 * 255 * tmpl.total() * 1e-6; + + SANITY_CHECK(result, eps); + } +} +} + +#endif // HAVE_OPENCL \ No newline at end of file diff --git a/modules/imgproc/test/ocl/test_match_template.cpp b/modules/imgproc/test/ocl/test_match_template.cpp index 2a0402342..7656a1446 100644 --- a/modules/imgproc/test/ocl/test_match_template.cpp +++ b/modules/imgproc/test/ocl/test_match_template.cpp @@ -97,8 +97,7 @@ PARAM_TEST_CASE(MatchTemplate, MatDepth, Channels, int, bool) void Near(double threshold = 0.0) { - EXPECT_MAT_NEAR(result, uresult, threshold); - EXPECT_MAT_NEAR(result_roi, uresult_roi, threshold); + OCL_EXPECT_MATS_NEAR(result,threshold); } }; From 8c5e19c27058e9ec9fb0b3272d6a4175222d10a8 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Tue, 21 Jan 2014 16:57:01 +0400 Subject: [PATCH 228/295] fixed pref test --- modules/imgproc/perf/opencl/perf_matchTemplate.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/imgproc/perf/opencl/perf_matchTemplate.cpp b/modules/imgproc/perf/opencl/perf_matchTemplate.cpp index b790f36cc..b5ffecc0e 100644 --- a/modules/imgproc/perf/opencl/perf_matchTemplate.cpp +++ b/modules/imgproc/perf/opencl/perf_matchTemplate.cpp @@ -27,9 +27,9 @@ namespace ocl { Size tmplSz = get<1>(GetParam()); int method = get<2>(GetParam()); - Mat img(imgSz, CV_8UC1); - Mat tmpl(tmplSz, CV_8UC1); - Mat result(imgSz - tmplSz + Size(1,1), CV_32F); + UMat img(imgSz, CV_8UC1); + UMat tmpl(tmplSz, CV_8UC1); + UMat result(imgSz - tmplSz + Size(1,1), CV_32F); declare .in(img, WARMUP_RNG) From 7bd8f9294d9d28895456b13f31d116f13c7651b7 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Wed, 22 Jan 2014 13:34:40 +0400 Subject: [PATCH 229/295] fixed --- modules/imgproc/perf/opencl/perf_matchTemplate.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/imgproc/perf/opencl/perf_matchTemplate.cpp b/modules/imgproc/perf/opencl/perf_matchTemplate.cpp index b5ffecc0e..b28645cd9 100644 --- a/modules/imgproc/perf/opencl/perf_matchTemplate.cpp +++ b/modules/imgproc/perf/opencl/perf_matchTemplate.cpp @@ -12,7 +12,7 @@ namespace ocl { typedef std::tr1::tuple ImgSize_TmplSize_Method_t; typedef TestBaseWithParam ImgSize_TmplSize_Method; - OCL_PERF_TEST_P(ImgSize_TmplSize_Method, matchTemplate, + OCL_PERF_TEST_P(ImgSize_TmplSize_Method, MatchTemplate, ::testing::Combine( testing::Values(szSmall128, cv::Size(320, 240), cv::Size(640, 480), cv::Size(800, 600), @@ -43,10 +43,13 @@ namespace ocl { method == TM_CCORR_NORMED || method == TM_SQDIFF_NORMED || method == TM_CCOEFF_NORMED; - double eps = isNormed ? 1e-6 - : 255 * 255 * tmpl.total() * 1e-6; + double eps = isNormed ? 1e-3 + : 255 * 255 * tmpl.total() * 1e-3; - SANITY_CHECK(result, eps); + if (isNormed) + SANITY_CHECK(result,eps,ERROR_RELATIVE); + else + SANITY_CHECK(result, eps); } } } From 4d86804f1120e655031a372d14f754ab756f45b5 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Thu, 23 Jan 2014 15:31:32 +0400 Subject: [PATCH 230/295] Fixed merge conflicts --- modules/imgproc/test/ocl/test_match_template.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/test/ocl/test_match_template.cpp b/modules/imgproc/test/ocl/test_match_template.cpp index 7656a1446..782509cc9 100644 --- a/modules/imgproc/test/ocl/test_match_template.cpp +++ b/modules/imgproc/test/ocl/test_match_template.cpp @@ -75,7 +75,7 @@ PARAM_TEST_CASE(MatchTemplate, MatDepth, Channels, int, bool) virtual void generateTestData() { Size image_roiSize = randomSize(2, 100); - Size templ_roiSize = Size(randomInt(1,image_roiSize.width), randomInt(1,image_roiSize.height)); + Size templ_roiSize = Size(randomInt(1, image_roiSize.width), randomInt(1, image_roiSize.height)); Size result_roiSize = Size(image_roiSize.width - templ_roiSize.width + 1, image_roiSize.height - templ_roiSize.height + 1); From dca56841459dadfa01ac74eb1ac01cd7e05d8522 Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Wed, 22 Jan 2014 21:47:50 +0400 Subject: [PATCH 231/295] removing duplicated legacy license, the actual instance is in 'opencv/LICENSE' --- doc/license.txt | 37 ------------------- .../android_binary_package/O4A_SDK.rst | 2 +- 2 files changed, 1 insertion(+), 38 deletions(-) delete mode 100644 doc/license.txt diff --git a/doc/license.txt b/doc/license.txt deleted file mode 100644 index 8824228d0..000000000 --- a/doc/license.txt +++ /dev/null @@ -1,37 +0,0 @@ -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) 2000-2008, Intel Corporation, all rights reserved. -Copyright (C) 2008-2011, Willow Garage Inc., 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: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions 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. diff --git a/doc/tutorials/introduction/android_binary_package/O4A_SDK.rst b/doc/tutorials/introduction/android_binary_package/O4A_SDK.rst index 9a683ea49..ef9337aae 100644 --- a/doc/tutorials/introduction/android_binary_package/O4A_SDK.rst +++ b/doc/tutorials/introduction/android_binary_package/O4A_SDK.rst @@ -66,7 +66,7 @@ The structure of package contents looks as follows: | |_ armeabi-v7a | |_ x86 | - |_ license.txt + |_ LICENSE |_ README.android * :file:`sdk` folder contains OpenCV API and libraries for Android: From 0a4a1d7526ba893e818365875cd5aa916fc9f92b Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Fri, 24 Jan 2014 10:07:21 +0400 Subject: [PATCH 232/295] temporary disabling hanging test --- modules/ocl/perf/perf_haar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ocl/perf/perf_haar.cpp b/modules/ocl/perf/perf_haar.cpp index 86890a891..3aedd8886 100644 --- a/modules/ocl/perf/perf_haar.cpp +++ b/modules/ocl/perf/perf_haar.cpp @@ -97,8 +97,8 @@ PERF_TEST_P( OCL_Cascade_Image_MinSize, CascadeClassifier, testing::Combine( testing::Values( string("cv/cascadeandhog/cascades/haarcascade_frontalface_alt.xml") ), testing::Values( string("cv/shared/lena.png"), - string("cv/cascadeandhog/images/bttf301.png"), - string("cv/cascadeandhog/images/class57.png") ), + string("cv/cascadeandhog/images/bttf301.png")/*, + string("cv/cascadeandhog/images/class57.png")*/ ), testing::Values(30, 64, 90) ) ) { const string cascasePath = get<0>(GetParam()); From 07a88d48e9bdb63bf5b3ddf677296bfcd16248e4 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Fri, 24 Jan 2014 11:41:23 +0400 Subject: [PATCH 233/295] fixed --- modules/imgproc/perf/opencl/perf_matchTemplate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/perf/opencl/perf_matchTemplate.cpp b/modules/imgproc/perf/opencl/perf_matchTemplate.cpp index b28645cd9..948774743 100644 --- a/modules/imgproc/perf/opencl/perf_matchTemplate.cpp +++ b/modules/imgproc/perf/opencl/perf_matchTemplate.cpp @@ -43,8 +43,8 @@ namespace ocl { method == TM_CCORR_NORMED || method == TM_SQDIFF_NORMED || method == TM_CCOEFF_NORMED; - double eps = isNormed ? 1e-3 - : 255 * 255 * tmpl.total() * 1e-3; + double eps = isNormed ? 3e-2 + : 255 * 255 * tmpl.total() * 1e-4; if (isNormed) SANITY_CHECK(result,eps,ERROR_RELATIVE); From 086792ec06ff78a45fdd5e1b2fa7f72fe3b7c9a2 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Thu, 23 Jan 2014 20:57:30 +0400 Subject: [PATCH 234/295] Improvements in package build. --- cmake/OpenCVPackaging.cmake | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/cmake/OpenCVPackaging.cmake b/cmake/OpenCVPackaging.cmake index 4a81c255b..3b8d4db54 100644 --- a/cmake/OpenCVPackaging.cmake +++ b/cmake/OpenCVPackaging.cmake @@ -2,24 +2,29 @@ if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") set(CPACK_set_DESTDIR "on") if(NOT OPENCV_CUSTOM_PACKAGE_INFO) - set(CPACK_PACKAGE_DESCRIPTION "Open Computer Vision Library") - set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "OpenCV") + set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Open Computer Vision Library") + set(CPACK_PACKAGE_DESCRIPTION +"OpenCV (Open Source Computer Vision Library) is an open source computer vision +and machine learning software library. OpenCV was built to provide a common +infrastructure for computer vision applications and to accelerate the use of +machine perception in the commercial products. Being a BSD-licensed product, +OpenCV makes it easy for businesses to utilize and modify the code.") set(CPACK_PACKAGE_VENDOR "OpenCV Foundation") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") set(CPACK_PACKAGE_CONTACT "admin@opencv.org") + set(CPACK_PACKAGE_VERSION_MAJOR "${OPENCV_VERSION_MAJOR}") + set(CPACK_PACKAGE_VERSION_MINOR "${OPENCV_VERSION_MINOR}") + set(CPACK_PACKAGE_VERSION_PATCH "${OPENCV_VERSION_PATCH}") + set(CPACK_PACKAGE_VERSION "${OPENCV_VCSVERSION}") endif(NOT OPENCV_CUSTOM_PACKAGE_INFO) -set(CPACK_PACKAGE_VERSION_MAJOR "${OPENCV_VERSION_MAJOR}") -set(CPACK_PACKAGE_VERSION_MINOR "${OPENCV_VERSION_MINOR}") -set(CPACK_PACKAGE_VERSION_PATCH "${OPENCV_VERSION_PATCH}") - #arch if(X86) set(CPACK_DEBIAN_ARCHITECTURE "i386") set(CPACK_RPM_PACKAGE_ARCHITECTURE "i686") elseif(X86_64) set(CPACK_DEBIAN_ARCHITECTURE "amd64") - set(CPACK_RPM_PACKAGE_ARCHITECTURE "amd64") + set(CPACK_RPM_PACKAGE_ARCHITECTURE "x86_64") elseif(ARM) set(CPACK_DEBIAN_ARCHITECTURE "armhf") set(CPACK_RPM_PACKAGE_ARCHITECTURE "armhf") @@ -41,11 +46,16 @@ set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${OPENCV_VCSVERSION}-$ #rpm options set(CPACK_RPM_COMPONENT_INSTALL TRUE) -set(CPACK_RPM_PACKAGE_LICENSE ${CPACK_RESOURCE_FILE_LICENSE}) +set(CPACK_RPM_PACKAGE_SUMMARY ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}) +set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION}) +set(CPACK_RPM_PACKAGE_URL "http://opencv.org") +set(CPACK_RPM_PACKAGE_LICENSE "BSD") #deb options set(CPACK_DEB_COMPONENT_INSTALL TRUE) -set(CPACK_DEBIAN_PACKAGE_PRIORITY "extra") +set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") +set(CPACK_DEBIAN_PACKAGE_SECTION "libs") +set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://opencv.org") #depencencies set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS TRUE) @@ -55,6 +65,13 @@ set(CPACK_COMPONENT_docs_DEPENDS libs) set(CPACK_COMPONENT_java_DEPENDS libs) set(CPACK_COMPONENT_python_DEPENDS libs) +if(HAVE_CUDA) + string(REPLACE "." "-" cuda_version_suffix ${CUDA_VERSION}) + set(CPACK_DEB_libs_PACKAGE_DEPENDS "cuda-core-libs-${cuda_version_suffix}, cuda-extra-libs-${cuda_version_suffix}") + set(CPACK_COMPONENT_dev_DEPENDS libs) + set(CPACK_DEB_dev_PACKAGE_DEPENDS "cuda-headers-${cuda_version_suffix}") +endif() + if(NOT OPENCV_CUSTOM_PACKAGE_INFO) set(CPACK_COMPONENT_libs_DISPLAY_NAME "lib${CMAKE_PROJECT_NAME}") set(CPACK_COMPONENT_libs_DESCRIPTION "Open Computer Vision Library") From 450ea3131feb1f608cd4344cc8d0f9f0f70b6e86 Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Mon, 20 Jan 2014 10:25:05 +0400 Subject: [PATCH 235/295] samples --- samples/tapi/CMakeLists.txt | 2 +- samples/tapi/bgfg_segm.cpp | 122 ++++++++++ samples/tapi/clahe.cpp | 107 ++++++++ samples/tapi/hog.cpp | 364 ++++++++++++++++++++++++++++ samples/tapi/morphology.cpp | 104 ++++++++ samples/tapi/pyrlk_optical_flow.cpp | 230 ++++++++++++++++++ samples/tapi/squares.cpp | 203 ++++++++++++++++ samples/tapi/surf_matcher.cpp | 212 ++++++++++++++++ samples/tapi/tvl1_optical_flow.cpp | 231 ++++++++++++++++++ 9 files changed, 1574 insertions(+), 1 deletion(-) create mode 100644 samples/tapi/bgfg_segm.cpp create mode 100644 samples/tapi/clahe.cpp create mode 100644 samples/tapi/hog.cpp create mode 100644 samples/tapi/morphology.cpp create mode 100644 samples/tapi/pyrlk_optical_flow.cpp create mode 100644 samples/tapi/squares.cpp create mode 100644 samples/tapi/surf_matcher.cpp create mode 100644 samples/tapi/tvl1_optical_flow.cpp diff --git a/samples/tapi/CMakeLists.txt b/samples/tapi/CMakeLists.txt index 4cfb5805b..f3aa17461 100644 --- a/samples/tapi/CMakeLists.txt +++ b/samples/tapi/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(OPENCV_TAPI_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_video opencv_highgui) +SET(OPENCV_TAPI_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_video opencv_highgui opencv_objdetect opencv_features2d opencv_calib3d opencv_nonfree opencv_flann) ocv_check_dependencies(${OPENCV_TAPI_SAMPLES_REQUIRED_DEPS}) diff --git a/samples/tapi/bgfg_segm.cpp b/samples/tapi/bgfg_segm.cpp new file mode 100644 index 000000000..d8e4617bd --- /dev/null +++ b/samples/tapi/bgfg_segm.cpp @@ -0,0 +1,122 @@ +#include +#include + +#include "opencv2/core.hpp" +#include "opencv2/core/ocl.hpp" +#include "opencv2/core/utility.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/video.hpp" + +using namespace std; +using namespace cv; + +#define M_MOG 1 +#define M_MOG2 2 + +int main(int argc, const char** argv) +{ + cv::CommandLineParser cmd(argc, argv, + "{ c camera | false | use camera }" + "{ f file | 768x576.avi | input video file }" + "{ t type | mog | method's type (mog, mog2) }" + "{ h help | false | print help message }" + "{ m cpu_mode | false | press 'm' to switch OpenCL<->CPU}"); + + if (cmd.has("help")) + { + cout << "Usage : bgfg_segm [options]" << endl; + cout << "Available options:" << endl; + cmd.printMessage(); + return EXIT_SUCCESS; + } + + bool useCamera = cmd.has("camera"); + string file = cmd.get("file"); + string method = cmd.get("type"); + + if (method != "mog" && method != "mog2") + { + cerr << "Incorrect method" << endl; + return EXIT_FAILURE; + } + + int m = method == "mog" ? M_MOG : M_MOG2; + + VideoCapture cap; + if (useCamera) + cap.open(0); + else + cap.open(file); + + if (!cap.isOpened()) + { + cout << "can not open camera or video file" << endl; + return EXIT_FAILURE; + } + + UMat frame, fgmask, fgimg; + cap >> frame; + fgimg.create(frame.size(), frame.type()); + + Ptr mog = createBackgroundSubtractorMOG(); + cv::Ptr mog2 = createBackgroundSubtractorMOG2(); + + switch (m) + { + case M_MOG: + mog->apply(frame, fgmask, 0.01f); + break; + + case M_MOG2: + mog2->apply(frame, fgmask); + break; + } + bool running=true; + for (;;) + { + if(!running) + break; + cap >> frame; + if (frame.empty()) + break; + + int64 start = cv::getTickCount(); + + //update the model + switch (m) + { + case M_MOG: + mog->apply(frame, fgmask, 0.01f); + break; + + case M_MOG2: + mog2->apply(frame, fgmask); + break; + } + + double fps = cv::getTickFrequency() / (cv::getTickCount() - start); + std::cout << "FPS : " << fps << std::endl; + std::cout << fgimg.size() << std::endl; + fgimg.setTo(Scalar::all(0)); + frame.copyTo(fgimg, fgmask); + + imshow("image", frame); + imshow("foreground mask", fgmask); + imshow("foreground image", fgimg); + + char key = (char)waitKey(30); + + switch (key) + { + case 27: + running = false; + break; + case 'm': + case 'M': + ocl::setUseOpenCL(!cv::ocl::useOpenCL()); + cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL" : "CPU") << " mode\n"; + break; + } + } + return EXIT_SUCCESS; +} diff --git a/samples/tapi/clahe.cpp b/samples/tapi/clahe.cpp new file mode 100644 index 000000000..94ca191aa --- /dev/null +++ b/samples/tapi/clahe.cpp @@ -0,0 +1,107 @@ +#include +#include "opencv2/core/core.hpp" +#include "opencv2/core/ocl.hpp" +#include "opencv2/core/utility.hpp" +#include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/highgui/highgui.hpp" + +using namespace cv; +using namespace std; + +Ptr pFilter; +int tilesize; +int cliplimit; + +static void TSize_Callback(int pos) +{ + if(pos==0) + pFilter->setTilesGridSize(Size(1,1)); + else + pFilter->setTilesGridSize(Size(tilesize,tilesize)); +} + +static void Clip_Callback(int) +{ + pFilter->setClipLimit(cliplimit); +} + +int main(int argc, char** argv) +{ + const char* keys = + "{ i input | | specify input image }" + "{ c camera | 0 | specify camera id }" + "{ o output | clahe_output.jpg | specify output save path}" + "{ h help | false | print help message }"; + + cv::CommandLineParser cmd(argc, argv, keys); + if (cmd.has("help")) + { + cout << "Usage : clahe [options]" << endl; + cout << "Available options:" << endl; + cmd.printMessage(); + return EXIT_SUCCESS; + } + + string infile = cmd.get("i"), outfile = cmd.get("o"); + int camid = cmd.get("c"); + VideoCapture capture; + + namedWindow("CLAHE"); + createTrackbar("Tile Size", "CLAHE", &tilesize, 32, (TrackbarCallback)TSize_Callback); + createTrackbar("Clip Limit", "CLAHE", &cliplimit, 20, (TrackbarCallback)Clip_Callback); + + UMat frame, outframe; + + int cur_clip; + Size cur_tilesize; + pFilter = createCLAHE(); + + cur_clip = (int)pFilter->getClipLimit(); + cur_tilesize = pFilter->getTilesGridSize(); + setTrackbarPos("Tile Size", "CLAHE", cur_tilesize.width); + setTrackbarPos("Clip Limit", "CLAHE", cur_clip); + + if(infile != "") + { + imread(infile).copyTo(frame); + if(frame.empty()) + { + cout << "error read image: " << infile << endl; + return EXIT_FAILURE; + } + } + else + capture.open(camid); + + cout << "\nControls:\n" + << "\to - save output image\n" + << "\tm - switch OpenCL <-> CPU mode" + << "\tESC - exit\n"; + + for (;;) + { + if(capture.isOpened()) + capture.read(frame); + else + imread(infile).copyTo(frame); + if(frame.empty()) + continue; + + cvtColor(frame, frame, COLOR_BGR2GRAY); + pFilter->apply(frame, outframe); + + imshow("CLAHE", outframe); + + char key = (char)waitKey(3); + if(key == 'o') + imwrite(outfile, outframe); + else if(key == 27) + break; + else if(key == 'm') + { + ocl::setUseOpenCL(!cv::ocl::useOpenCL()); + cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL" : "CPU") << " mode\n"; + } + } + return EXIT_SUCCESS; +} diff --git a/samples/tapi/hog.cpp b/samples/tapi/hog.cpp new file mode 100644 index 000000000..d8c0ee9ac --- /dev/null +++ b/samples/tapi/hog.cpp @@ -0,0 +1,364 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace cv; + +class App +{ +public: + App(CommandLineParser& cmd); + void run(); + void handleKey(char key); + void hogWorkBegin(); + void hogWorkEnd(); + string hogWorkFps() const; + void workBegin(); + void workEnd(); + string workFps() const; + string message() const; + + +// This function test if gpu_rst matches cpu_rst. +// If the two vectors are not equal, it will return the difference in vector size +// Else if will return +// (total diff of each cpu and gpu rects covered pixels)/(total cpu rects covered pixels) + double checkRectSimilarity(Size sz, + std::vector& cpu_rst, + std::vector& gpu_rst); +private: + App operator=(App&); + + //Args args; + bool running; + bool make_gray; + double scale; + double resize_scale; + int win_width; + int win_stride_width, win_stride_height; + int gr_threshold; + int nlevels; + double hit_threshold; + bool gamma_corr; + + int64 hog_work_begin; + double hog_work_fps; + int64 work_begin; + double work_fps; + + string img_source; + string vdo_source; + string output; + int camera_id; + bool write_once; +}; + +int main(int argc, char** argv) +{ + const char* keys = + "{ h help | false | print help message }" + "{ i input | | specify input image}" + "{ c camera | -1 | enable camera capturing }" + "{ v video | 768x576.avi | use video as input }" + "{ g gray | false | convert image to gray one or not}" + "{ s scale | 1.0 | resize the image before detect}" + "{ o output | | specify output path when input is images}"; + CommandLineParser cmd(argc, argv, keys); + if (cmd.has("help")) + { + cout << "Usage : hog [options]" << endl; + cout << "Available options:" << endl; + cmd.printMessage(); + return EXIT_SUCCESS; + } + + App app(cmd); + try + { + app.run(); + } + catch (const Exception& e) + { + return cout << "error: " << e.what() << endl, 1; + } + catch (const exception& e) + { + return cout << "error: " << e.what() << endl, 1; + } + catch(...) + { + return cout << "unknown exception" << endl, 1; + } + return EXIT_SUCCESS; +} + +App::App(CommandLineParser& cmd) +{ + cout << "\nControls:\n" + << "\tESC - exit\n" + << "\tm - change mode GPU <-> CPU\n" + << "\tg - convert image to gray or not\n" + << "\to - save output image once, or switch on/off video save\n" + << "\t1/q - increase/decrease HOG scale\n" + << "\t2/w - increase/decrease levels count\n" + << "\t3/e - increase/decrease HOG group threshold\n" + << "\t4/r - increase/decrease hit threshold\n" + << endl; + + make_gray = cmd.has("gray"); + resize_scale = cmd.get("s"); + vdo_source = cmd.get("v"); + img_source = cmd.get("i"); + output = cmd.get("o"); + camera_id = cmd.get("c"); + + win_width = 48; + win_stride_width = 8; + win_stride_height = 8; + gr_threshold = 8; + nlevels = 13; + hit_threshold = 1.4; + scale = 1.05; + gamma_corr = true; + write_once = false; + + cout << "Group threshold: " << gr_threshold << endl; + cout << "Levels number: " << nlevels << endl; + cout << "Win width: " << win_width << endl; + cout << "Win stride: (" << win_stride_width << ", " << win_stride_height << ")\n"; + cout << "Hit threshold: " << hit_threshold << endl; + cout << "Gamma correction: " << gamma_corr << endl; + cout << endl; +} + +void App::run() +{ + running = true; + VideoWriter video_writer; + + Size win_size(win_width, win_width * 2); + Size win_stride(win_stride_width, win_stride_height); + + // Create HOG descriptors and detectors here + + HOGDescriptor hog(win_size, Size(16, 16), Size(8, 8), Size(8, 8), 9, 1, -1, + HOGDescriptor::L2Hys, 0.2, gamma_corr, cv::HOGDescriptor::DEFAULT_NLEVELS); + hog.setSVMDetector( HOGDescriptor::getDaimlerPeopleDetector() ); + + while (running) + { + VideoCapture vc; + UMat frame; + + if (vdo_source!="") + { + vc.open(vdo_source.c_str()); + if (!vc.isOpened()) + throw runtime_error(string("can't open video file: " + vdo_source)); + vc >> frame; + } + else if (camera_id != -1) + { + vc.open(camera_id); + if (!vc.isOpened()) + { + stringstream msg; + msg << "can't open camera: " << camera_id; + throw runtime_error(msg.str()); + } + vc >> frame; + } + else + { + imread(img_source).copyTo(frame); + if (frame.empty()) + throw runtime_error(string("can't open image file: " + img_source)); + } + + UMat img_aux, img; + Mat img_to_show; + + // Iterate over all frames + while (running && !frame.empty()) + { + workBegin(); + + // Change format of the image + if (make_gray) cvtColor(frame, img_aux, COLOR_BGR2GRAY ); + else frame.copyTo(img_aux); + + // Resize image + if (abs(scale-1.0)>0.001) + { + Size sz((int)((double)img_aux.cols/resize_scale), (int)((double)img_aux.rows/resize_scale)); + resize(img_aux, img, sz); + } + else img = img_aux; + img.copyTo(img_to_show); + hog.nlevels = nlevels; + vector found; + + // Perform HOG classification + hogWorkBegin(); + + hog.detectMultiScale(img.getMat(ACCESS_READ), found, hit_threshold, win_stride, + Size(0, 0), scale, gr_threshold); + hogWorkEnd(); + + + // Draw positive classified windows + for (size_t i = 0; i < found.size(); i++) + { + Rect r = found[i]; + rectangle(img_to_show, r.tl(), r.br(), Scalar(0, 255, 0), 3); + } + + putText(img_to_show, "Mode: CPU", Point(5, 25), FONT_HERSHEY_SIMPLEX, 1., Scalar(255, 100, 0), 2); + putText(img_to_show, "FPS (HOG only): " + hogWorkFps(), Point(5, 65), FONT_HERSHEY_SIMPLEX, 1., Scalar(255, 100, 0), 2); + putText(img_to_show, "FPS (total): " + workFps(), Point(5, 105), FONT_HERSHEY_SIMPLEX, 1., Scalar(255, 100, 0), 2); + imshow("opencv_hog", img_to_show); + if (vdo_source!="" || camera_id!=-1) vc >> frame; + + workEnd(); + + if (output!="" && write_once) + { + if (img_source!="") // wirte image + { + write_once = false; + imwrite(output, img_to_show); + } + else //write video + { + if (!video_writer.isOpened()) + { + video_writer.open(output, VideoWriter::fourcc('x','v','i','d'), 24, + img_to_show.size(), true); + if (!video_writer.isOpened()) + throw std::runtime_error("can't create video writer"); + } + + if (make_gray) cvtColor(img_to_show, img, COLOR_GRAY2BGR); + else cvtColor(img_to_show, img, COLOR_BGRA2BGR); + + video_writer << img.getMat(ACCESS_READ); + } + } + + handleKey((char)waitKey(3)); + } + } +} + +void App::handleKey(char key) +{ + switch (key) + { + case 27: + running = false; + break; + case 'm': + case 'M': + ocl::setUseOpenCL(!cv::ocl::useOpenCL()); + cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL" : "CPU") << " mode\n"; + break; + case 'g': + case 'G': + make_gray = !make_gray; + cout << "Convert image to gray: " << (make_gray ? "YES" : "NO") << endl; + break; + case '1': + scale *= 1.05; + cout << "Scale: " << scale << endl; + break; + case 'q': + case 'Q': + scale /= 1.05; + cout << "Scale: " << scale << endl; + break; + case '2': + nlevels++; + cout << "Levels number: " << nlevels << endl; + break; + case 'w': + case 'W': + nlevels = max(nlevels - 1, 1); + cout << "Levels number: " << nlevels << endl; + break; + case '3': + gr_threshold++; + cout << "Group threshold: " << gr_threshold << endl; + break; + case 'e': + case 'E': + gr_threshold = max(0, gr_threshold - 1); + cout << "Group threshold: " << gr_threshold << endl; + break; + case '4': + hit_threshold+=0.25; + cout << "Hit threshold: " << hit_threshold << endl; + break; + case 'r': + case 'R': + hit_threshold = max(0.0, hit_threshold - 0.25); + cout << "Hit threshold: " << hit_threshold << endl; + break; + case 'c': + case 'C': + gamma_corr = !gamma_corr; + cout << "Gamma correction: " << gamma_corr << endl; + break; + case 'o': + case 'O': + write_once = !write_once; + break; + } +} + + +inline void App::hogWorkBegin() +{ + hog_work_begin = getTickCount(); +} + +inline void App::hogWorkEnd() +{ + int64 delta = getTickCount() - hog_work_begin; + double freq = getTickFrequency(); + hog_work_fps = freq / delta; +} + +inline string App::hogWorkFps() const +{ + stringstream ss; + ss << hog_work_fps; + return ss.str(); +} + +inline void App::workBegin() +{ + work_begin = getTickCount(); +} + +inline void App::workEnd() +{ + int64 delta = getTickCount() - work_begin; + double freq = getTickFrequency(); + work_fps = freq / delta; +} + +inline string App::workFps() const +{ + stringstream ss; + ss << work_fps; + return ss.str(); +} diff --git a/samples/tapi/morphology.cpp b/samples/tapi/morphology.cpp new file mode 100644 index 000000000..5179c9738 --- /dev/null +++ b/samples/tapi/morphology.cpp @@ -0,0 +1,104 @@ +#include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/highgui/highgui.hpp" +#include +#include +#include "opencv2/core/ocl.hpp" + +using namespace cv; + +static void help() +{ + +printf("\nShow off image morphology: erosion, dialation, open and close\n" + "Call:\n morphology2 [image]\n" + "This program also shows use of rect, elipse and cross kernels\n\n"); +printf( "Hot keys: \n" + "\tESC - quit the program\n" + "\tr - use rectangle structuring element\n" + "\te - use elliptic structuring element\n" + "\tc - use cross-shaped structuring element\n" + "\tSPACE - loop through all the options\n" + "\tm - switch openCL mode support\n"); +} + +UMat src, dst; + +int element_shape = MORPH_RECT; + +//the address of variable which receives trackbar position update +int max_iters = 10; +int open_close_pos = 0; +int erode_dilate_pos = 0; + +// callback function for open/close trackbar +static void OpenClose(int, void*) +{ + int n = open_close_pos - max_iters; + int an = n > 0 ? n : -n; + Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an) ); + if( n < 0 ) + morphologyEx(src, dst, MORPH_OPEN, element); + else + morphologyEx(src, dst, MORPH_CLOSE, element); + imshow("Open/Close",dst); +} + +// callback function for erode/dilate trackbar +static void ErodeDilate(int, void*) +{ + int n = erode_dilate_pos - max_iters; + int an = n > 0 ? n : -n; + Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an) ); + if( n < 0 ) + erode(src, dst, element); + else + dilate(src, dst, element); + imshow("Erode/Dilate",dst); +} + + +int main( int argc, char** argv ) +{ + char* filename = argc == 2 ? argv[1] : (char*)"baboon.jpg"; + + imread(filename,1).copyTo(src); + if( src.u == 0 ) + return -1; + + help(); + + //create windows for output images + namedWindow("Open/Close",1); + namedWindow("Erode/Dilate",1); + + open_close_pos = erode_dilate_pos = max_iters; + createTrackbar("iterations", "Open/Close",&open_close_pos,max_iters*2+1,OpenClose); + createTrackbar("iterations", "Erode/Dilate",&erode_dilate_pos,max_iters*2+1,ErodeDilate); + + for(;;) + { + int c; + + OpenClose(open_close_pos, 0); + ErodeDilate(erode_dilate_pos, 0); + c = waitKey(0); + + if( (char)c == 27 ) + break; + if( (char)c == 'e' ) + element_shape = MORPH_ELLIPSE; + else if( (char)c == 'r' ) + element_shape = MORPH_RECT; + else if( (char)c == 'c' ) + element_shape = MORPH_CROSS; + else if( (char)c == ' ' ) + element_shape = (element_shape + 1) % 3; + else if( (char)c == 'm' ) + { + cv::ocl::setUseOpenCL(!cv::ocl::useOpenCL()); + printf("OpenCL is %s\n", ocl::useOpenCL() ? "enabled" : "disabled"); + } + } + + return 0; +} diff --git a/samples/tapi/pyrlk_optical_flow.cpp b/samples/tapi/pyrlk_optical_flow.cpp new file mode 100644 index 000000000..d4b77294b --- /dev/null +++ b/samples/tapi/pyrlk_optical_flow.cpp @@ -0,0 +1,230 @@ +#include +#include +#include + +#include "opencv2/core/utility.hpp" +#include "opencv2/highgui/highgui.hpp" +#include "opencv2/core/ocl.hpp" +#include "opencv2/video/video.hpp" + +using namespace std; +using namespace cv; + +typedef unsigned char uchar; +#define LOOP_NUM 10 +int64 work_begin = 0; +int64 work_end = 0; + +static void workBegin() +{ + work_begin = getTickCount(); +} +static void workEnd() +{ + work_end += (getTickCount() - work_begin); +} +static double getTime() +{ + return work_end * 1000. / getTickFrequency(); +} + +static void drawArrows(UMat& _frame, const vector& prevPts, const vector& nextPts, const vector& status, + Scalar line_color = Scalar(0, 0, 255)) +{ + Mat frame = _frame.getMat(ACCESS_WRITE); + for (size_t i = 0; i < prevPts.size(); ++i) + { + if (status[i]) + { + int line_thickness = 1; + + Point p = prevPts[i]; + Point q = nextPts[i]; + + double angle = atan2((double) p.y - q.y, (double) p.x - q.x); + + double hypotenuse = sqrt( (double)(p.y - q.y)*(p.y - q.y) + (double)(p.x - q.x)*(p.x - q.x) ); + + if (hypotenuse < 1.0) + continue; + + // Here we lengthen the arrow by a factor of three. + q.x = (int) (p.x - 3 * hypotenuse * cos(angle)); + q.y = (int) (p.y - 3 * hypotenuse * sin(angle)); + + // Now we draw the main line of the arrow. + line(frame, p, q, line_color, line_thickness); + + // Now draw the tips of the arrow. I do some scaling so that the + // tips look proportional to the main line of the arrow. + + p.x = (int) (q.x + 9 * cos(angle + CV_PI / 4)); + p.y = (int) (q.y + 9 * sin(angle + CV_PI / 4)); + line(frame, p, q, line_color, line_thickness); + + p.x = (int) (q.x + 9 * cos(angle - CV_PI / 4)); + p.y = (int) (q.y + 9 * sin(angle - CV_PI / 4)); + line(frame, p, q, line_color, line_thickness); + } + } +} + + +int main(int argc, const char* argv[]) +{ + const char* keys = + "{ h help | false | print help message }" + "{ l left | | specify left image }" + "{ r right | | specify right image }" + "{ c camera | 0 | enable camera capturing }" + "{ v video | | use video as input }" + "{ o output | pyrlk_output.jpg| specify output save path when input is images }" + "{ points | 1000 | specify points count [GoodFeatureToTrack] }" + "{ min_dist | 0 | specify minimal distance between points [GoodFeatureToTrack] }" + "{ m cpu_mode | false | run without OpenCL }"; + + CommandLineParser cmd(argc, argv, keys); + + if (cmd.has("help")) + { + cout << "Usage: pyrlk_optical_flow [options]" << endl; + cout << "Available options:" << endl; + cmd.printMessage(); + return EXIT_SUCCESS; + } + + bool defaultPicturesFail = true; + string fname0 = cmd.get("left"); + string fname1 = cmd.get("right"); + string vdofile = cmd.get("video"); + string outfile = cmd.get("output"); + int points = cmd.get("points"); + double minDist = cmd.get("min_dist"); + int inputName = cmd.get("c"); + + UMat frame0; + imread(fname0, cv::IMREAD_GRAYSCALE).copyTo(frame0); + UMat frame1; + imread(fname1, cv::IMREAD_GRAYSCALE).copyTo(frame1); + + vector pts(points); + vector nextPts(points); + vector status(points); + vector err; + + cout << "Points count : " << points << endl << endl; + + if (frame0.empty() || frame1.empty()) + { + VideoCapture capture; + UMat frame, frameCopy; + UMat frame0Gray, frame1Gray; + UMat ptr0, ptr1; + + if(vdofile.empty()) + capture.open( inputName ); + else + capture.open(vdofile.c_str()); + + int c = inputName ; + if(!capture.isOpened()) + { + if(vdofile.empty()) + cout << "Capture from CAM " << c << " didn't work" << endl; + else + cout << "Capture from file " << vdofile << " failed" < 0) workBegin(); + + goodFeaturesToTrack(frame0, pts, points, 0.01, minDist); + calcOpticalFlowPyrLK(frame0, frame1, pts, nextPts, status, err); + + if (i > 0 && i <= LOOP_NUM) + workEnd(); + + if (i == LOOP_NUM) + { + cout << "average time (noCamera) : "; + + cout << getTime() / LOOP_NUM << " ms" << endl; + + drawArrows(frame0, pts, nextPts, status, Scalar(255, 0, 0)); + imshow("PyrLK [Sparse]", frame0); + imwrite(outfile, frame0); + } + } + } + + waitKey(); + + return EXIT_SUCCESS; +} diff --git a/samples/tapi/squares.cpp b/samples/tapi/squares.cpp new file mode 100644 index 000000000..9135ffa93 --- /dev/null +++ b/samples/tapi/squares.cpp @@ -0,0 +1,203 @@ +// The "Square Detector" program. +// It loads several images sequentially and tries to find squares in +// each image + +#include "opencv2/core.hpp" +#include "opencv2/core/ocl.hpp" +#include "opencv2/core/utility.hpp" +#include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/highgui/highgui.hpp" +#include +#include + +using namespace cv; +using namespace std; + +int thresh = 50, N = 11; +const char* wndname = "Square Detection Demo"; + +// helper function: +// finds a cosine of angle between vectors +// from pt0->pt1 and from pt0->pt2 +static double angle( Point pt1, Point pt2, Point pt0 ) +{ + double dx1 = pt1.x - pt0.x; + double dy1 = pt1.y - pt0.y; + double dx2 = pt2.x - pt0.x; + double dy2 = pt2.y - pt0.y; + return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); +} + + +// returns sequence of squares detected on the image. +// the sequence is stored in the specified memory storage +static void findSquares( const UMat& image, vector >& squares ) +{ + squares.clear(); + UMat pyr, timg, gray0(image.size(), CV_8U), gray; + + // down-scale and upscale the image to filter out the noise + pyrDown(image, pyr, Size(image.cols/2, image.rows/2)); + pyrUp(pyr, timg, image.size()); + vector > contours; + + // find squares in every color plane of the image + for( int c = 0; c < 3; c++ ) + { + int ch[] = {c, 0}; + mixChannels(timg, gray0, ch, 1); + + // try several threshold levels + for( int l = 0; l < N; l++ ) + { + // hack: use Canny instead of zero threshold level. + // Canny helps to catch squares with gradient shading + if( l == 0 ) + { + // apply Canny. Take the upper threshold from slider + // and set the lower to 0 (which forces edges merging) + Canny(gray0, gray, 0, thresh, 5); + // dilate canny output to remove potential + // holes between edge segments + dilate(gray, gray, UMat(), Point(-1,-1)); + } + else + { + // apply threshold if l!=0: + // tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0 + cv::threshold(gray0, gray, (l+1)*255/N, 255, THRESH_BINARY); + } + + // find contours and store them all as a list + findContours(gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE); + + vector approx; + + // test each contour + for( size_t i = 0; i < contours.size(); i++ ) + { + // approximate contour with accuracy proportional + // to the contour perimeter + + approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true); + + // square contours should have 4 vertices after approximation + // relatively large area (to filter out noisy contours) + // and be convex. + // Note: absolute value of an area is used because + // area may be positive or negative - in accordance with the + // contour orientation + if( approx.size() == 4 && + fabs(contourArea(Mat(approx))) > 1000 && + isContourConvex(Mat(approx)) ) + { + double maxCosine = 0; + + for( int j = 2; j < 5; j++ ) + { + // find the maximum cosine of the angle between joint edges + double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1])); + maxCosine = MAX(maxCosine, cosine); + } + + // if cosines of all angles are small + // (all angles are ~90 degree) then write quandrange + // vertices to resultant sequence + if( maxCosine < 0.3 ) + squares.push_back(approx); + } + } + } + } +} + +// the function draws all the squares in the image +static void drawSquares( UMat& _image, const vector >& squares ) +{ + Mat image = _image.getMat(ACCESS_WRITE); + for( size_t i = 0; i < squares.size(); i++ ) + { + const Point* p = &squares[i][0]; + int n = (int)squares[i].size(); + polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, LINE_AA); + } +} + + +// draw both pure-C++ and ocl square results onto a single image +static UMat drawSquaresBoth( const UMat& image, + const vector >& sqs) +{ + UMat imgToShow(Size(image.cols, image.rows), image.type()); + image.copyTo(imgToShow); + + drawSquares(imgToShow, sqs); + + return imgToShow; +} + + +int main(int argc, char** argv) +{ + const char* keys = + "{ i input | | specify input image }" + "{ o output | squares_output.jpg | specify output save path}" + "{ h help | false | print help message }" + "{ m cpu_mode | false | run without OpenCL }"; + + CommandLineParser cmd(argc, argv, keys); + + if(cmd.has("help")) + { + cout << "Usage : squares [options]" << endl; + cout << "Available options:" << endl; + cmd.printMessage(); + return EXIT_SUCCESS; + } + if (cmd.has("cpu_mode")) + { + ocl::setUseOpenCL(false); + std::cout << "OpenCL was disabled" << std::endl; + } + + string inputName = cmd.get("i"); + string outfile = cmd.get("o"); + + int iterations = 10; + namedWindow( wndname, WINDOW_AUTOSIZE ); + vector > squares; + + UMat image; + imread(inputName, 1).copyTo(image); + if( image.empty() ) + { + cout << "Couldn't load " << inputName << endl; + return EXIT_FAILURE; + } + + int j = iterations; + int64 t_cpp = 0; + //warm-ups + cout << "warming up ..." << endl; + findSquares(image, squares); + + do + { + int64 t_start = cv::getTickCount(); + findSquares(image, squares); + t_cpp += cv::getTickCount() - t_start; + + t_start = cv::getTickCount(); + + cout << "run loop: " << j << endl; + } + while(--j); + cout << "average time: " << 1000.0f * (double)t_cpp / getTickFrequency() / iterations << "ms" << endl; + + UMat result = drawSquaresBoth(image, squares); + imshow(wndname, result); + imwrite(outfile, result); + waitKey(0); + + return EXIT_SUCCESS; +} diff --git a/samples/tapi/surf_matcher.cpp b/samples/tapi/surf_matcher.cpp new file mode 100644 index 000000000..eeac5da63 --- /dev/null +++ b/samples/tapi/surf_matcher.cpp @@ -0,0 +1,212 @@ +#include +#include +#include "opencv2/core/core.hpp" +#include "opencv2/core/utility.hpp" +#include "opencv2/core/ocl.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/features2d.hpp" +#include "opencv2/calib3d.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/nonfree.hpp" + +using namespace cv; + +const int LOOP_NUM = 10; +const int GOOD_PTS_MAX = 50; +const float GOOD_PORTION = 0.15f; + +int64 work_begin = 0; +int64 work_end = 0; + +static void workBegin() +{ + work_begin = getTickCount(); +} + +static void workEnd() +{ + work_end = getTickCount() - work_begin; +} + +static double getTime() +{ + return work_end /((double)getTickFrequency() * 1000.); +} + +template +struct SURFDetector +{ + KPDetector surf; + SURFDetector(double hessian = 800.0) + :surf(hessian) + { + } + template + void operator()(const T& in, const T& mask, std::vector& pts, T& descriptors, bool useProvided = false) + { + surf(in, mask, pts, descriptors, useProvided); + } +}; + +template +struct SURFMatcher +{ + KPMatcher matcher; + template + void match(const T& in1, const T& in2, std::vector& matches) + { + matcher.match(in1, in2, matches); + } +}; + +static Mat drawGoodMatches( + const Mat& img1, + const Mat& img2, + const std::vector& keypoints1, + const std::vector& keypoints2, + std::vector& matches, + std::vector& scene_corners_ + ) +{ + //-- Sort matches and preserve top 10% matches + std::sort(matches.begin(), matches.end()); + std::vector< DMatch > good_matches; + double minDist = matches.front().distance; + double maxDist = matches.back().distance; + + const int ptsPairs = std::min(GOOD_PTS_MAX, (int)(matches.size() * GOOD_PORTION)); + for( int i = 0; i < ptsPairs; i++ ) + { + good_matches.push_back( matches[i] ); + } + std::cout << "\nMax distance: " << maxDist << std::endl; + std::cout << "Min distance: " << minDist << std::endl; + + std::cout << "Calculating homography using " << ptsPairs << " point pairs." << std::endl; + + // drawing the results + Mat img_matches; + + drawMatches( img1, keypoints1, img2, keypoints2, + good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), + std::vector(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); + + //-- Localize the object + std::vector obj; + std::vector scene; + + for( size_t i = 0; i < good_matches.size(); i++ ) + { + //-- Get the keypoints from the good matches + obj.push_back( keypoints1[ good_matches[i].queryIdx ].pt ); + scene.push_back( keypoints2[ good_matches[i].trainIdx ].pt ); + } + //-- Get the corners from the image_1 ( the object to be "detected" ) + std::vector obj_corners(4); + obj_corners[0] = Point(0,0); + obj_corners[1] = Point( img1.cols, 0 ); + obj_corners[2] = Point( img1.cols, img1.rows ); + obj_corners[3] = Point( 0, img1.rows ); + std::vector scene_corners(4); + + Mat H = findHomography( obj, scene, RANSAC ); + perspectiveTransform( obj_corners, scene_corners, H); + + scene_corners_ = scene_corners; + + //-- Draw lines between the corners (the mapped object in the scene - image_2 ) + line( img_matches, + scene_corners[0] + Point2f( (float)img1.cols, 0), scene_corners[1] + Point2f( (float)img1.cols, 0), + Scalar( 0, 255, 0), 2, LINE_AA ); + line( img_matches, + scene_corners[1] + Point2f( (float)img1.cols, 0), scene_corners[2] + Point2f( (float)img1.cols, 0), + Scalar( 0, 255, 0), 2, LINE_AA ); + line( img_matches, + scene_corners[2] + Point2f( (float)img1.cols, 0), scene_corners[3] + Point2f( (float)img1.cols, 0), + Scalar( 0, 255, 0), 2, LINE_AA ); + line( img_matches, + scene_corners[3] + Point2f( (float)img1.cols, 0), scene_corners[0] + Point2f( (float)img1.cols, 0), + Scalar( 0, 255, 0), 2, LINE_AA ); + return img_matches; +} + +//////////////////////////////////////////////////// +// This program demonstrates the usage of SURF_OCL. +// use cpu findHomography interface to calculate the transformation matrix +int main(int argc, char* argv[]) +{ + const char* keys = + "{ h help | false | print help message }" + "{ l left | | specify left image }" + "{ r right | | specify right image }" + "{ o output | SURF_output.jpg | specify output save path }" + "{ m cpu_mode | false | run without OpenCL }"; + + CommandLineParser cmd(argc, argv, keys); + if (cmd.has("help")) + { + std::cout << "Usage: surf_matcher [options]" << std::endl; + std::cout << "Available options:" << std::endl; + cmd.printMessage(); + return EXIT_SUCCESS; + } + if (cmd.has("cpu_mode")) + { + ocl::setUseOpenCL(false); + std::cout << "OpenCL was disabled" << std::endl; + } + + UMat img1, img2; + + std::string outpath = cmd.get("o"); + + imread(cmd.get("l"), IMREAD_GRAYSCALE).copyTo(img1); + CV_Assert(!img1.empty()); + + imread(cmd.get("r"), IMREAD_GRAYSCALE).copyTo(img2); + CV_Assert(!img2.empty()); + + double surf_time = 0.; + + //declare input/output + std::vector keypoints1, keypoints2; + std::vector matches; + + UMat _descriptors1, _descriptors2; + Mat descriptors1 = _descriptors1.getMat(ACCESS_RW), + descriptors2 = _descriptors2.getMat(ACCESS_RW); + + //instantiate detectors/matchers + SURFDetector surf; + + SURFMatcher matcher; + + //-- start of timing section + + for (int i = 0; i <= LOOP_NUM; i++) + { + if(i == 1) workBegin(); + surf(img1.getMat(ACCESS_READ), Mat(), keypoints1, descriptors1); + surf(img2.getMat(ACCESS_READ), Mat(), keypoints2, descriptors2); + matcher.match(descriptors1, descriptors2, matches); + } + workEnd(); + std::cout << "FOUND " << keypoints1.size() << " keypoints on first image" << std::endl; + std::cout << "FOUND " << keypoints2.size() << " keypoints on second image" << std::endl; + + surf_time = getTime(); + std::cout << "SURF run time: " << surf_time / LOOP_NUM << " ms" << std::endl<<"\n"; + + + std::vector corner; + Mat img_matches = drawGoodMatches(img1.getMat(ACCESS_READ), img2.getMat(ACCESS_READ), keypoints1, keypoints2, matches, corner); + + //-- Show detected matches + + namedWindow("surf matches", 0); + imshow("surf matches", img_matches); + imwrite(outpath, img_matches); + + waitKey(0); + return EXIT_SUCCESS; +} diff --git a/samples/tapi/tvl1_optical_flow.cpp b/samples/tapi/tvl1_optical_flow.cpp new file mode 100644 index 000000000..436ba715c --- /dev/null +++ b/samples/tapi/tvl1_optical_flow.cpp @@ -0,0 +1,231 @@ +#include +#include +#include + +#include "opencv2/core/ocl.hpp" +#include "opencv2/core/utility.hpp" +#include "opencv2/highgui/highgui.hpp" +#include "opencv2/video/video.hpp" + +using namespace std; +using namespace cv; + +typedef unsigned char uchar; +#define LOOP_NUM 10 +int64 work_begin = 0; +int64 work_end = 0; + +static void workBegin() +{ + work_begin = getTickCount(); +} +static void workEnd() +{ + work_end += (getTickCount() - work_begin); +} +static double getTime() +{ + return work_end * 1000. / getTickFrequency(); +} + +template inline T clamp (T x, T a, T b) +{ + return ((x) > (a) ? ((x) < (b) ? (x) : (b)) : (a)); +} + +template inline T mapValue(T x, T a, T b, T c, T d) +{ + x = clamp(x, a, b); + return c + (d - c) * (x - a) / (b - a); +} + +static void getFlowField(const Mat& u, const Mat& v, Mat& flowField) +{ + float maxDisplacement = 1.0f; + + for (int i = 0; i < u.rows; ++i) + { + const float* ptr_u = u.ptr(i); + const float* ptr_v = v.ptr(i); + + for (int j = 0; j < u.cols; ++j) + { + float d = max(fabsf(ptr_u[j]), fabsf(ptr_v[j])); + + if (d > maxDisplacement) + maxDisplacement = d; + } + } + + flowField.create(u.size(), CV_8UC4); + + for (int i = 0; i < flowField.rows; ++i) + { + const float* ptr_u = u.ptr(i); + const float* ptr_v = v.ptr(i); + + + Vec4b* row = flowField.ptr(i); + + for (int j = 0; j < flowField.cols; ++j) + { + row[j][0] = 0; + row[j][1] = static_cast (mapValue (-ptr_v[j], -maxDisplacement, maxDisplacement, 0.0f, 255.0f)); + row[j][2] = static_cast (mapValue ( ptr_u[j], -maxDisplacement, maxDisplacement, 0.0f, 255.0f)); + row[j][3] = 255; + } + } +} + + +int main(int argc, const char* argv[]) +{ + const char* keys = + "{ h help | false | print help message }" + "{ l left | | specify left image }" + "{ r right | | specify right image }" + "{ o output | tvl1_output.jpg | specify output save path }" + "{ c camera | 0 | enable camera capturing }" + "{ m cpu_mode | false | run without OpenCL }" + "{ v video | | use video as input }"; + + CommandLineParser cmd(argc, argv, keys); + + if (cmd.has("help")) + { + cout << "Usage: pyrlk_optical_flow [options]" << endl; + cout << "Available options:" << endl; + cmd.printMessage(); + return EXIT_SUCCESS; + } + + string fname0 = cmd.get("l"); + string fname1 = cmd.get("r"); + string vdofile = cmd.get("v"); + string outpath = cmd.get("o"); + bool useCPU = cmd.get("s"); + bool useCamera = cmd.get("c"); + int inputName = cmd.get("c"); + + UMat frame0, frame1; + imread(fname0, cv::IMREAD_GRAYSCALE).copyTo(frame0); + imread(fname1, cv::IMREAD_GRAYSCALE).copyTo(frame1); + cv::Ptr alg = cv::createOptFlow_DualTVL1(); + + UMat flow; + Mat show_flow; + vector flow_vec; + if (frame0.empty() || frame1.empty()) + useCamera = true; + + if (useCamera) + { + VideoCapture capture; + UMat frame, frameCopy; + UMat frame0Gray, frame1Gray; + UMat ptr0, ptr1; + + if(vdofile.empty()) + capture.open( inputName ); + else + capture.open(vdofile.c_str()); + + if(!capture.isOpened()) + { + if(vdofile.empty()) + cout << "Capture from CAM " << inputName << " didn't work" << endl; + else + cout << "Capture from file " << vdofile << " failed" <calc(ptr0, ptr1, flow); + split(flow, flow_vec); + + if (i%2 == 1) + frame1.copyTo(frameCopy); + else + frame0.copyTo(frameCopy); + getFlowField(flow_vec[0].getMat(ACCESS_READ), flow_vec[1].getMat(ACCESS_READ), show_flow); + imshow("tvl1 optical flow field", show_flow); + } + + char key = (char)waitKey(10); + if (key == 27) + break; + else if (key == 'm' || key == 'M') + { + ocl::setUseOpenCL(!cv::ocl::useOpenCL()); + cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL" : "CPU") << " mode\n"; + } + } + + capture.release(); + } + else + { +nocamera: + if (cmd.has("cpu_mode")) + { + ocl::setUseOpenCL(false); + std::cout << "OpenCL was disabled" << std::endl; + } + for(int i = 0; i <= LOOP_NUM; i ++) + { + cout << "loop" << i << endl; + + if (i > 0) workBegin(); + + alg->calc(frame0, frame1, flow); + split(flow, flow_vec); + + if (i > 0 && i <= LOOP_NUM) + workEnd(); + + if (i == LOOP_NUM) + { + if (useCPU) + cout << "average CPU time (noCamera) : "; + else + cout << "average GPU time (noCamera) : "; + cout << getTime() / LOOP_NUM << " ms" << endl; + + getFlowField(flow_vec[0].getMat(ACCESS_READ), flow_vec[1].getMat(ACCESS_READ), show_flow); + imshow("PyrLK [Sparse]", show_flow); + imwrite(outpath, show_flow); + } + } + } + + waitKey(); + + return EXIT_SUCCESS; +} From 07778e17606ce34ecbf30eb397bde01111697021 Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Fri, 24 Jan 2014 13:37:19 +0400 Subject: [PATCH 236/295] fixes --- samples/tapi/bgfg_segm.cpp | 14 ++--- samples/tapi/clahe.cpp | 2 +- samples/tapi/hog.cpp | 2 +- samples/tapi/morphology.cpp | 104 ---------------------------------- samples/tapi/squares.cpp | 3 +- samples/tapi/surf_matcher.cpp | 32 +++++++---- 6 files changed, 33 insertions(+), 124 deletions(-) delete mode 100644 samples/tapi/morphology.cpp diff --git a/samples/tapi/bgfg_segm.cpp b/samples/tapi/bgfg_segm.cpp index d8e4617bd..2fa12bba9 100644 --- a/samples/tapi/bgfg_segm.cpp +++ b/samples/tapi/bgfg_segm.cpp @@ -15,7 +15,7 @@ using namespace cv; int main(int argc, const char** argv) { - cv::CommandLineParser cmd(argc, argv, + CommandLineParser cmd(argc, argv, "{ c camera | false | use camera }" "{ f file | 768x576.avi | input video file }" "{ t type | mog | method's type (mog, mog2) }" @@ -58,8 +58,8 @@ int main(int argc, const char** argv) cap >> frame; fgimg.create(frame.size(), frame.type()); - Ptr mog = createBackgroundSubtractorMOG(); - cv::Ptr mog2 = createBackgroundSubtractorMOG2(); + Ptr mog = createBackgroundSubtractorMOG(); + Ptr mog2 = createBackgroundSubtractorMOG2(); switch (m) { @@ -80,7 +80,7 @@ int main(int argc, const char** argv) if (frame.empty()) break; - int64 start = cv::getTickCount(); + int64 start = getTickCount(); //update the model switch (m) @@ -94,7 +94,7 @@ int main(int argc, const char** argv) break; } - double fps = cv::getTickFrequency() / (cv::getTickCount() - start); + double fps = getTickFrequency() / (getTickCount() - start); std::cout << "FPS : " << fps << std::endl; std::cout << fgimg.size() << std::endl; fgimg.setTo(Scalar::all(0)); @@ -113,8 +113,8 @@ int main(int argc, const char** argv) break; case 'm': case 'M': - ocl::setUseOpenCL(!cv::ocl::useOpenCL()); - cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL" : "CPU") << " mode\n"; + ocl::setUseOpenCL(!ocl::useOpenCL()); + cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL enabled" : "CPU") << " mode\n"; break; } } diff --git a/samples/tapi/clahe.cpp b/samples/tapi/clahe.cpp index 94ca191aa..a28f2ab05 100644 --- a/samples/tapi/clahe.cpp +++ b/samples/tapi/clahe.cpp @@ -100,7 +100,7 @@ int main(int argc, char** argv) else if(key == 'm') { ocl::setUseOpenCL(!cv::ocl::useOpenCL()); - cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL" : "CPU") << " mode\n"; + cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL enabled" : "CPU") << " mode\n"; } } return EXIT_SUCCESS; diff --git a/samples/tapi/hog.cpp b/samples/tapi/hog.cpp index d8c0ee9ac..ee537b310 100644 --- a/samples/tapi/hog.cpp +++ b/samples/tapi/hog.cpp @@ -269,7 +269,7 @@ void App::handleKey(char key) case 'm': case 'M': ocl::setUseOpenCL(!cv::ocl::useOpenCL()); - cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL" : "CPU") << " mode\n"; + cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL enabled" : "CPU") << " mode\n"; break; case 'g': case 'G': diff --git a/samples/tapi/morphology.cpp b/samples/tapi/morphology.cpp deleted file mode 100644 index 5179c9738..000000000 --- a/samples/tapi/morphology.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include "opencv2/imgproc/imgproc.hpp" -#include "opencv2/highgui/highgui.hpp" -#include -#include -#include "opencv2/core/ocl.hpp" - -using namespace cv; - -static void help() -{ - -printf("\nShow off image morphology: erosion, dialation, open and close\n" - "Call:\n morphology2 [image]\n" - "This program also shows use of rect, elipse and cross kernels\n\n"); -printf( "Hot keys: \n" - "\tESC - quit the program\n" - "\tr - use rectangle structuring element\n" - "\te - use elliptic structuring element\n" - "\tc - use cross-shaped structuring element\n" - "\tSPACE - loop through all the options\n" - "\tm - switch openCL mode support\n"); -} - -UMat src, dst; - -int element_shape = MORPH_RECT; - -//the address of variable which receives trackbar position update -int max_iters = 10; -int open_close_pos = 0; -int erode_dilate_pos = 0; - -// callback function for open/close trackbar -static void OpenClose(int, void*) -{ - int n = open_close_pos - max_iters; - int an = n > 0 ? n : -n; - Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an) ); - if( n < 0 ) - morphologyEx(src, dst, MORPH_OPEN, element); - else - morphologyEx(src, dst, MORPH_CLOSE, element); - imshow("Open/Close",dst); -} - -// callback function for erode/dilate trackbar -static void ErodeDilate(int, void*) -{ - int n = erode_dilate_pos - max_iters; - int an = n > 0 ? n : -n; - Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an) ); - if( n < 0 ) - erode(src, dst, element); - else - dilate(src, dst, element); - imshow("Erode/Dilate",dst); -} - - -int main( int argc, char** argv ) -{ - char* filename = argc == 2 ? argv[1] : (char*)"baboon.jpg"; - - imread(filename,1).copyTo(src); - if( src.u == 0 ) - return -1; - - help(); - - //create windows for output images - namedWindow("Open/Close",1); - namedWindow("Erode/Dilate",1); - - open_close_pos = erode_dilate_pos = max_iters; - createTrackbar("iterations", "Open/Close",&open_close_pos,max_iters*2+1,OpenClose); - createTrackbar("iterations", "Erode/Dilate",&erode_dilate_pos,max_iters*2+1,ErodeDilate); - - for(;;) - { - int c; - - OpenClose(open_close_pos, 0); - ErodeDilate(erode_dilate_pos, 0); - c = waitKey(0); - - if( (char)c == 27 ) - break; - if( (char)c == 'e' ) - element_shape = MORPH_ELLIPSE; - else if( (char)c == 'r' ) - element_shape = MORPH_RECT; - else if( (char)c == 'c' ) - element_shape = MORPH_CROSS; - else if( (char)c == ' ' ) - element_shape = (element_shape + 1) % 3; - else if( (char)c == 'm' ) - { - cv::ocl::setUseOpenCL(!cv::ocl::useOpenCL()); - printf("OpenCL is %s\n", ocl::useOpenCL() ? "enabled" : "disabled"); - } - } - - return 0; -} diff --git a/samples/tapi/squares.cpp b/samples/tapi/squares.cpp index 9135ffa93..402702e49 100644 --- a/samples/tapi/squares.cpp +++ b/samples/tapi/squares.cpp @@ -140,7 +140,7 @@ static UMat drawSquaresBoth( const UMat& image, int main(int argc, char** argv) { const char* keys = - "{ i input | | specify input image }" + "{ i input | pic1.png | specify input image }" "{ o output | squares_output.jpg | specify output save path}" "{ h help | false | print help message }" "{ m cpu_mode | false | run without OpenCL }"; @@ -172,6 +172,7 @@ int main(int argc, char** argv) if( image.empty() ) { cout << "Couldn't load " << inputName << endl; + cmd.printMessage(); return EXIT_FAILURE; } diff --git a/samples/tapi/surf_matcher.cpp b/samples/tapi/surf_matcher.cpp index eeac5da63..9066bfd3f 100644 --- a/samples/tapi/surf_matcher.cpp +++ b/samples/tapi/surf_matcher.cpp @@ -30,7 +30,7 @@ static void workEnd() static double getTime() { - return work_end /((double)getTickFrequency() * 1000.); + return work_end /((double)getTickFrequency() )* 1000.; } template @@ -136,11 +136,11 @@ static Mat drawGoodMatches( int main(int argc, char* argv[]) { const char* keys = - "{ h help | false | print help message }" - "{ l left | | specify left image }" - "{ r right | | specify right image }" - "{ o output | SURF_output.jpg | specify output save path }" - "{ m cpu_mode | false | run without OpenCL }"; + "{ h help | false | print help message }" + "{ l left | box.png | specify left image }" + "{ r right | box_in_scene.png | specify right image }" + "{ o output | SURF_output.jpg | specify output save path }" + "{ m cpu_mode | false | run without OpenCL }"; CommandLineParser cmd(argc, argv, keys); if (cmd.has("help")) @@ -160,11 +160,23 @@ int main(int argc, char* argv[]) std::string outpath = cmd.get("o"); - imread(cmd.get("l"), IMREAD_GRAYSCALE).copyTo(img1); - CV_Assert(!img1.empty()); + std::string leftName = cmd.get("l"); + imread(leftName, IMREAD_GRAYSCALE).copyTo(img1); + if(img1.empty()) + { + std::cout << "Couldn't load " << leftName << std::endl; + cmd.printMessage(); + return EXIT_FAILURE; + } - imread(cmd.get("r"), IMREAD_GRAYSCALE).copyTo(img2); - CV_Assert(!img2.empty()); + std::string rightName = cmd.get("r"); + imread(rightName, IMREAD_GRAYSCALE).copyTo(img2); + if(img2.empty()) + { + std::cout << "Couldn't load " << rightName << std::endl; + cmd.printMessage(); + return EXIT_FAILURE; + } double surf_time = 0.; From ae827a638c4b4f25f8e314aa3585340b179f63f8 Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Fri, 24 Jan 2014 14:01:31 +0400 Subject: [PATCH 237/295] fixes --- modules/core/include/opencv2/core/ocl.hpp | 12 ++++++------ modules/core/src/ocl.cpp | 22 +++++++++++----------- modules/ts/src/ocl_test.cpp | 8 ++++---- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/modules/core/include/opencv2/core/ocl.hpp b/modules/core/include/opencv2/core/ocl.hpp index 5d339a488..12c7b8b06 100644 --- a/modules/core/include/opencv2/core/ocl.hpp +++ b/modules/core/include/opencv2/core/ocl.hpp @@ -59,7 +59,7 @@ class CV_EXPORTS Kernel; class CV_EXPORTS Program; class CV_EXPORTS ProgramSource2; class CV_EXPORTS Queue; -class CV_EXPORTS PlatformInform; +class CV_EXPORTS PlatformInfo2; class CV_EXPORTS Device { @@ -551,12 +551,12 @@ protected: Impl* p; }; -class CV_EXPORTS PlatformInform +class CV_EXPORTS PlatformInfo2 { public: - PlatformInform(); - explicit PlatformInform(void* id); - ~PlatformInform(); + PlatformInfo2(); + explicit PlatformInfo2(void* id); + ~PlatformInfo2(); String name() const; String vendor() const; @@ -572,7 +572,7 @@ protected: CV_EXPORTS const char* convertTypeStr(int sdepth, int ddepth, int cn, char* buf); CV_EXPORTS const char* typeToStr(int t); CV_EXPORTS const char* memopTypeToStr(int t); -CV_EXPORTS void getPlatfomsInfo(std::vector& platform_info); +CV_EXPORTS void getPlatfomsInfo(std::vector& platform_info); }} diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index c4859544d..73980629a 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3640,7 +3640,7 @@ static void getDevices(std::vector& devices,cl_platform_id& platfo devices.resize(numDevices); } -struct PlatformInform::Impl +struct PlatformInfo2::Impl { Impl(void* id) { @@ -3661,45 +3661,45 @@ struct PlatformInform::Impl cl_platform_id handle; }; -PlatformInform::PlatformInform() +PlatformInfo2::PlatformInfo2() { p = 0; } -PlatformInform::PlatformInform(void* platform_id) +PlatformInfo2::PlatformInfo2(void* platform_id) { p = new Impl(platform_id); } -PlatformInform::~PlatformInform() +PlatformInfo2::~PlatformInfo2() { if(p) p->release(); } -int PlatformInform::deviceNumber() const +int PlatformInfo2::deviceNumber() const { return p ? (int)p->devices.size() : 0; } -void PlatformInform::getDevice(Device& device, int d) const +void PlatformInfo2::getDevice(Device& device, int d) const { CV_Assert(d < (int)p->devices.size() ); if(p) device.set(p->devices[d]); } -String PlatformInform::name() const +String PlatformInfo2::name() const { return p ? p->getStrProp(CL_PLATFORM_NAME) : String(); } -String PlatformInform::vendor() const +String PlatformInfo2::vendor() const { return p ? p->getStrProp(CL_PLATFORM_VENDOR) : String(); } -String PlatformInform::version() const +String PlatformInfo2::version() const { return p ? p->getStrProp(CL_PLATFORM_VERSION) : String(); } @@ -3718,13 +3718,13 @@ static void getPlatforms(std::vector& platforms) platforms.resize(numPlatforms); } -void getPlatfomsInfo(std::vector& platformsInfo) +void getPlatfomsInfo(std::vector& platformsInfo) { std::vector platforms; getPlatforms(platforms); for (size_t i = 0; i < platforms.size(); i++) { - platformsInfo.push_back( PlatformInform((void*)&platforms[i]) ); + platformsInfo.push_back( PlatformInfo2((void*)&platforms[i]) ); } } diff --git a/modules/ts/src/ocl_test.cpp b/modules/ts/src/ocl_test.cpp index 7c9ca9c5c..32cc5287e 100644 --- a/modules/ts/src/ocl_test.cpp +++ b/modules/ts/src/ocl_test.cpp @@ -98,21 +98,21 @@ void dumpOpenCLDevice() using namespace cv::ocl; try { - std::vector platforms; + std::vector platforms; cv::ocl::getPlatfomsInfo(platforms); if (platforms.size() > 0) { DUMP_MESSAGE_STDOUT("OpenCL Platforms: "); for (size_t i = 0; i < platforms.size(); i++) { - const PlatformInform* platform = &platforms[i]; + const PlatformInfo2* platform = &platforms[i]; DUMP_MESSAGE_STDOUT(" " << platform->name().c_str()); Device current_device; for (int j = 0; j < platform->deviceNumber(); j++) { platform->getDevice(current_device, j); const char* deviceTypeStr = current_device.type() == Device::TYPE_CPU - ? ("CPU") : (current_device.type() == Device::TYPE_GPU ? "GPU" : "unknown"); + ? ("CPU") : (current_device.type() == Device::TYPE_GPU ? current_device.hostUnifiedMemory() ? "iGPU" : "dGPU" : "unknown"); DUMP_MESSAGE_STDOUT( " " << deviceTypeStr << ": " << current_device.name().c_str() << " (" << current_device.version().c_str() << ")"); DUMP_PROPERTY_XML( cv::format("cv_ocl_platform_%d_device_%d", (int)i, (int)j ), cv::format("(Platform=%sType=%sName=%sVersion=%s", @@ -136,7 +136,7 @@ void dumpOpenCLDevice() #endif const char* deviceTypeStr = device.type() == Device::TYPE_CPU - ? "CPU" : (device.type() == Device::TYPE_GPU ? "GPU" : "unknown"); + ? ("CPU") : (device.type() == Device::TYPE_GPU ? device.hostUnifiedMemory() ? "iGPU" : "dGPU" : "unknown"); DUMP_MESSAGE_STDOUT(" Type = "<< deviceTypeStr); DUMP_PROPERTY_XML("cv_ocl_current_deviceType", deviceTypeStr); From c7a6537b8335a310a3e4e7ffdca0506229e31f00 Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Fri, 24 Jan 2014 16:35:51 +0400 Subject: [PATCH 238/295] add brackets --- modules/ts/src/ocl_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ts/src/ocl_test.cpp b/modules/ts/src/ocl_test.cpp index 32cc5287e..0ad3df693 100644 --- a/modules/ts/src/ocl_test.cpp +++ b/modules/ts/src/ocl_test.cpp @@ -115,7 +115,7 @@ void dumpOpenCLDevice() ? ("CPU") : (current_device.type() == Device::TYPE_GPU ? current_device.hostUnifiedMemory() ? "iGPU" : "dGPU" : "unknown"); DUMP_MESSAGE_STDOUT( " " << deviceTypeStr << ": " << current_device.name().c_str() << " (" << current_device.version().c_str() << ")"); DUMP_PROPERTY_XML( cv::format("cv_ocl_platform_%d_device_%d", (int)i, (int)j ), - cv::format("(Platform=%sType=%sName=%sVersion=%s", + cv::format("(Platform=%s)(Type=%s)(Name=%s)(Version=%s)", platform->name().c_str(), deviceTypeStr, current_device.name().c_str(), current_device.version().c_str()) ); } } From cc514ac7a98409250f39bbc565e73da598bf5ecc Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 22 Jan 2014 15:51:28 +0400 Subject: [PATCH 239/295] added new macros useful for tracking whether OpenCL impl run or not --- cmake/cl2cpp.cmake | 1 + .../include/opencv2/core/opencl/ocl_defs.hpp | 34 +++++++++++ modules/core/src/mathfuncs.cpp | 61 +++++++++++-------- 3 files changed, 69 insertions(+), 27 deletions(-) create mode 100644 modules/core/include/opencv2/core/opencl/ocl_defs.hpp diff --git a/cmake/cl2cpp.cmake b/cmake/cl2cpp.cmake index 24d3eb2dc..84be36a98 100644 --- a/cmake/cl2cpp.cmake +++ b/cmake/cl2cpp.cmake @@ -29,6 +29,7 @@ ${nested_namespace_start} set(STR_HPP "// This file is auto-generated. Do not edit! #include \"opencv2/core/ocl_genbase.hpp\" +#include \"opencv2/core/opencl/ocl_defs.hpp\" namespace cv { diff --git a/modules/core/include/opencv2/core/opencl/ocl_defs.hpp b/modules/core/include/opencv2/core/opencl/ocl_defs.hpp new file mode 100644 index 000000000..5e7c4f39d --- /dev/null +++ b/modules/core/include/opencv2/core/opencl/ocl_defs.hpp @@ -0,0 +1,34 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +// Copyright (C) 2014, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. + +#ifdef HAVE_OPENCL + +#ifdef CV_OPENCL_RUN_VERBOSE +#define CV_OCL_RUN(condition, func) \ + { \ + if (cv::ocl::useOpenCL() && (condition) && func) \ + { \ + printf("%s: OpenCL implementation is running\n", CV_Func); \ + fflush(stdout); \ + return; \ + } \ + else \ + { \ + printf("%s: Plain implementation is running\n", CV_Func); \ + fflush(stdout); \ + } \ + } +#else +#define CV_OCL_RUN(condition, func) \ + if (cv::ocl::useOpenCL() && (condition) && func) \ + return; +#endif + +#else +#define CV_OCL_RUN(condition, func) +#endif + diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index 9d0231df3..b2a080a73 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -54,6 +54,7 @@ static const float atan2_p3 = -0.3258083974640975f*(float)(180/CV_PI); static const float atan2_p5 = 0.1555786518463281f*(float)(180/CV_PI); static const float atan2_p7 = -0.04432655554792128f*(float)(180/CV_PI); +#ifdef HAVE_OPENCL enum { OCL_OP_LOG=0, OCL_OP_EXP=1, OCL_OP_MAG=2, OCL_OP_PHASE_DEGREES=3, OCL_OP_PHASE_RADIANS=4 }; @@ -98,6 +99,8 @@ static bool ocl_math_op(InputArray _src1, InputArray _src2, OutputArray _dst, in return k.run(2, globalsize, 0, false); } +#endif + float fastAtan2( float y, float x ) { float ax = std::abs(x), ay = std::abs(y); @@ -401,11 +404,8 @@ void magnitude( InputArray src1, InputArray src2, OutputArray dst ) int type = src1.type(), depth = src1.depth(), cn = src1.channels(); CV_Assert( src1.size() == src2.size() && type == src2.type() && (depth == CV_32F || depth == CV_64F)); - bool use_opencl = dst.isUMat() && ocl::useOpenCL() - && src1.dims() <= 2 && src2.dims() <= 2; - - if(use_opencl && ocl_math_op(src1, src2, dst, OCL_OP_MAG) ) - return; + CV_OCL_RUN(dst.isUMat() && src1.dims() <= 2 && src2.dims() <= 2, + ocl_math_op(src1, src2, dst, OCL_OP_MAG)) Mat X = src1.getMat(), Y = src2.getMat(); dst.create(X.dims, X.size, X.type()); @@ -439,11 +439,8 @@ void phase( InputArray src1, InputArray src2, OutputArray dst, bool angleInDegre int type = src1.type(), depth = src1.depth(), cn = src1.channels(); CV_Assert( src1.size() == src2.size() && type == src2.type() && (depth == CV_32F || depth == CV_64F)); - bool use_opencl = dst.isUMat() && ocl::useOpenCL() - && src1.dims() <= 2 && src2.dims() <= 2; - - if(use_opencl && ocl_math_op(src1, src2, dst, angleInDegrees ? OCL_OP_PHASE_DEGREES : OCL_OP_PHASE_RADIANS) ) - return; + CV_OCL_RUN(dst.isUMat() && src1.dims() <= 2 && src2.dims() <= 2, + ocl_math_op(src1, src2, dst, angleInDegrees ? OCL_OP_PHASE_DEGREES : OCL_OP_PHASE_RADIANS)) Mat X = src1.getMat(), Y = src2.getMat(); dst.create( X.dims, X.size, type ); @@ -497,6 +494,8 @@ void phase( InputArray src1, InputArray src2, OutputArray dst, bool angleInDegre } } +#ifdef HAVE_OPENCL + static bool ocl_cartToPolar( InputArray _src1, InputArray _src2, OutputArray _dst1, OutputArray _dst2, bool angleInDegrees ) { @@ -533,12 +532,13 @@ static bool ocl_cartToPolar( InputArray _src1, InputArray _src2, return k.run(2, globalsize, NULL, false); } +#endif + void cartToPolar( InputArray src1, InputArray src2, OutputArray dst1, OutputArray dst2, bool angleInDegrees ) { - if (ocl::useOpenCL() && dst1.isUMat() && dst2.isUMat() && + CV_OCL_RUN(dst1.isUMat() && dst2.isUMat(), ocl_cartToPolar(src1, src2, dst1, dst2, angleInDegrees)) - return; Mat X = src1.getMat(), Y = src2.getMat(); int type = X.type(), depth = X.depth(), cn = X.channels(); @@ -683,6 +683,8 @@ static void SinCos_32f( const float *angle, float *sinval, float* cosval, } +#ifdef HAVE_OPENCL + static bool ocl_polarToCart( InputArray _mag, InputArray _angle, OutputArray _dst1, OutputArray _dst2, bool angleInDegrees ) { @@ -715,15 +717,16 @@ static bool ocl_polarToCart( InputArray _mag, InputArray _angle, return k.run(2, globalsize, NULL, false); } +#endif + void polarToCart( InputArray src1, InputArray src2, OutputArray dst1, OutputArray dst2, bool angleInDegrees ) { int type = src2.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); CV_Assert((depth == CV_32F || depth == CV_64F) && (src1.empty() || src1.type() == type)); - if (ocl::useOpenCL() && !src1.empty() && src2.dims() <= 2 && dst1.isUMat() && dst2.isUMat() && - ocl_polarToCart(src1, src2, dst1, dst2, angleInDegrees)) - return; + CV_OCL_RUN(!src1.empty() && src2.dims() <= 2 && dst1.isUMat() && dst2.isUMat(), + ocl_polarToCart(src1, src2, dst1, dst2, angleInDegrees)) Mat Mag = src1.getMat(), Angle = src2.getMat(); CV_Assert( Mag.empty() || Angle.size == Mag.size); @@ -1289,10 +1292,8 @@ void exp( InputArray _src, OutputArray _dst ) int type = _src.type(), depth = _src.depth(), cn = _src.channels(); CV_Assert( depth == CV_32F || depth == CV_64F ); - bool use_opencl = _dst.isUMat() && ocl::useOpenCL() && _src.dims() <= 2; - - if(use_opencl && ocl_math_op(_src, noArray(), _dst, OCL_OP_EXP) ) - return; + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2, + ocl_math_op(_src, noArray(), _dst, OCL_OP_EXP)) Mat src = _src.getMat(); _dst.create( src.dims, src.size, type ); @@ -1938,10 +1939,8 @@ void log( InputArray _src, OutputArray _dst ) int type = _src.type(), depth = _src.depth(), cn = _src.channels(); CV_Assert( depth == CV_32F || depth == CV_64F ); - bool use_opencl = _dst.isUMat() && ocl::useOpenCL() && _src.dims() <= 2; - - if(use_opencl && ocl_math_op(_src, noArray(), _dst, OCL_OP_LOG) ) - return; + CV_OCL_RUN( _dst.isUMat() && _src.dims() <= 2, + ocl_math_op(_src, noArray(), _dst, OCL_OP_LOG)) Mat src = _src.getMat(); _dst.create( src.dims, src.size, type ); @@ -2032,6 +2031,8 @@ static IPowFunc ipowTab[] = (IPowFunc)iPow32s, (IPowFunc)iPow32f, (IPowFunc)iPow64f, 0 }; +#ifdef HAVE_OPENCL + static bool ocl_pow(InputArray _src, double power, OutputArray _dst) { int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); @@ -2071,10 +2072,12 @@ static bool ocl_pow(InputArray _src, double power, OutputArray _dst) return k.run(2, globalsize, NULL, false); } +#endif + void pow( InputArray _src, double power, OutputArray _dst ) { - if (ocl::useOpenCL() && _dst.isUMat() && ocl_pow(_src, power, _dst)) - return; + CV_OCL_RUN(_dst.isUMat(), + ocl_pow(_src, power, _dst)) Mat src = _src.getMat(); int type = src.type(), depth = src.depth(), cn = src.channels(); @@ -2369,6 +2372,8 @@ bool checkRange(InputArray _src, bool quiet, Point* pt, double minVal, double ma return badPt.x < 0; } +#ifdef HAVE_OPENCL + static bool ocl_patchNaNs( InputOutputArray _a, float value ) { ocl::Kernel k("KF", ocl::core::arithm_oclsrc, @@ -2386,12 +2391,14 @@ static bool ocl_patchNaNs( InputOutputArray _a, float value ) return k.run(2, globalsize, NULL, false); } +#endif + void patchNaNs( InputOutputArray _a, double _val ) { CV_Assert( _a.depth() == CV_32F ); - if (ocl::useOpenCL() && _a.isUMat() && _a.dims() <= 2 && ocl_patchNaNs(_a, (float)_val)) - return; + CV_OCL_RUN(_a.isUMat() && _a.dims() <= 2, + ocl_patchNaNs(_a, (float)_val)) Mat a = _a.getMat(); const Mat* arrays[] = {&a, 0}; From c57e427fba279bb08fa37b02f65cfa3d85e3032d Mon Sep 17 00:00:00 2001 From: vbystricky Date: Thu, 16 Jan 2014 11:57:57 +0400 Subject: [PATCH 240/295] Move OpticalFlowPyrLK from ocl module to video module --- modules/core/include/opencv2/core/ocl.hpp | 16 + modules/core/src/ocl.cpp | 154 +++++ modules/video/src/lkpyramid.cpp | 230 ++++++++ modules/video/src/opencl/pyrlk.cl | 583 +++++++++++++++++++ modules/video/test/ocl/test_optflowpyrlk.cpp | 140 +++++ 5 files changed, 1123 insertions(+) create mode 100644 modules/video/src/opencl/pyrlk.cl create mode 100644 modules/video/test/ocl/test_optflowpyrlk.cpp diff --git a/modules/core/include/opencv2/core/ocl.hpp b/modules/core/include/opencv2/core/ocl.hpp index 12c7b8b06..850a2e60e 100644 --- a/modules/core/include/opencv2/core/ocl.hpp +++ b/modules/core/include/opencv2/core/ocl.hpp @@ -60,6 +60,7 @@ class CV_EXPORTS Program; class CV_EXPORTS ProgramSource2; class CV_EXPORTS Queue; class CV_EXPORTS PlatformInfo2; +class CV_EXPORTS Image2D; class CV_EXPORTS Device { @@ -89,6 +90,7 @@ public: String vendor() const; String OpenCL_C_Version() const; String OpenCLVersion() const; + String deviceVersion() const; String driverVersion() const; void* ptr() const; @@ -325,6 +327,7 @@ public: const String& buildopts, String* errmsg=0); int set(int i, const void* value, size_t sz); + int set(int i, const Image2D& image2D); int set(int i, const UMat& m); int set(int i, const KernelArg& arg); template int set(int i, const _Tp& value) @@ -574,6 +577,19 @@ CV_EXPORTS const char* typeToStr(int t); CV_EXPORTS const char* memopTypeToStr(int t); CV_EXPORTS void getPlatfomsInfo(std::vector& platform_info); +class CV_EXPORTS Image2D +{ +public: + Image2D(); + Image2D(const UMat &src); + ~Image2D(); + + void* ptr() const; +protected: + struct Impl; + Impl* p; +}; + }} #endif diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 73980629a..f103cd99d 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -1705,6 +1705,9 @@ String Device::OpenCL_C_Version() const String Device::OpenCLVersion() const { return p ? p->getStrProp(CL_DEVICE_EXTENSIONS) : String(); } +String Device::deviceVersion() const +{ return p ? p->getStrProp(CL_DEVICE_VERSION) : String(); } + String Device::driverVersion() const { return p ? p->getStrProp(CL_DRIVER_VERSION) : String(); } @@ -2689,6 +2692,12 @@ int Kernel::set(int i, const void* value, size_t sz) return i+1; } +int Kernel::set(int i, const Image2D& image2D) +{ + cl_mem h = (cl_mem)image2D.ptr(); + return set(i, &h, sizeof(h)); +} + int Kernel::set(int i, const UMat& m) { return set(i, KernelArg(KernelArg::READ_WRITE, (UMat*)&m, 0, 0)); @@ -3785,4 +3794,149 @@ const char* convertTypeStr(int sdepth, int ddepth, int cn, char* buf) return buf; } +/////////////////////////////////////////////////////////////////////////////////////////////// +// deviceVersion has format +// OpenCL +// by specification +// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetDeviceInfo.html +// http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clGetDeviceInfo.html +static void parseDeviceVersion(const String &deviceVersion, int &major, int &minor) +{ + major = minor = 0; + if (10 >= deviceVersion.length()) + return; + const char *pstr = deviceVersion.c_str(); + if (0 != strncmp(pstr, "OpenCL ", 7)) + return; + size_t ppos = deviceVersion.find('.', 7); + if (String::npos == ppos) + return; + String temp = deviceVersion.substr(7, ppos - 7); + major = atoi(temp.c_str()); + temp = deviceVersion.substr(ppos + 1); + minor = atoi(temp.c_str()); +} + +struct Image2D::Impl +{ + Impl(const UMat &src) + { + init(src); + } + ~Impl() + { + if (handle) + clReleaseMemObject(handle); + } + void init(const UMat &src) + { + cl_image_format format; + int err; + int depth = src.depth(); + int channels = src.channels(); + + switch(depth) + { + case CV_8U: + format.image_channel_data_type = CL_UNSIGNED_INT8; + break; + case CV_32S: + format.image_channel_data_type = CL_UNSIGNED_INT32; + break; + case CV_32F: + format.image_channel_data_type = CL_FLOAT; + break; + default: + CV_Error(-1, "Image forma is not supported"); + break; + } + switch(channels) + { + case 1: + format.image_channel_order = CL_R; + break; + case 3: + format.image_channel_order = CL_RGB; + break; + case 4: + format.image_channel_order = CL_RGBA; + break; + default: + CV_Error(-1, "Image format is not supported"); + break; + } +#ifdef CL_VERSION_1_2 + //this enables backwards portability to + //run on OpenCL 1.1 platform if library binaries are compiled with OpenCL 1.2 support + int minor, major; + parseDeviceVersion(Device::getDefault().deviceVersion(), major, minor); + if ((1 < major) || ((1 == major) && (2 <= minor))) + { + cl_image_desc desc; + desc.image_type = CL_MEM_OBJECT_IMAGE2D; + desc.image_width = src.cols; + desc.image_height = src.rows; + desc.image_depth = 0; + desc.image_array_size = 1; + desc.image_row_pitch = 0; + desc.image_slice_pitch = 0; + desc.buffer = NULL; + desc.num_mip_levels = 0; + desc.num_samples = 0; + handle = clCreateImage((cl_context)Context2::getDefault().ptr(), CL_MEM_READ_WRITE, &format, &desc, NULL, &err); + } + else +#endif + { + handle = clCreateImage2D((cl_context)Context2::getDefault().ptr(), CL_MEM_READ_WRITE, &format, src.cols, src.rows, 0, NULL, &err); + } + size_t origin[] = { 0, 0, 0 }; + size_t region[] = { src.cols, src.rows, 1 }; + + cl_mem devData; + if (!src.isContinuous()) + { + devData = clCreateBuffer((cl_context)Context2::getDefault().ptr(), CL_MEM_READ_ONLY, src.cols * src.rows * src.elemSize(), NULL, NULL); + const size_t roi[3] = {src.cols * src.elemSize(), src.rows, 1}; + clEnqueueCopyBufferRect((cl_command_queue)Queue::getDefault().ptr(), (cl_mem)src.handle(ACCESS_READ), devData, origin, origin, + roi, src.step, 0, src.cols * src.elemSize(), 0, 0, NULL, NULL); + clFlush((cl_command_queue)Queue::getDefault().ptr()); + } + else + { + devData = (cl_mem)src.handle(ACCESS_READ); + } + + clEnqueueCopyBufferToImage((cl_command_queue)Queue::getDefault().ptr(), devData, handle, 0, origin, region, 0, NULL, 0); + if (!src.isContinuous()) + { + clFlush((cl_command_queue)Queue::getDefault().ptr()); + clReleaseMemObject(devData); + } + } + + IMPLEMENT_REFCOUNTABLE(); + + cl_mem handle; +}; + +Image2D::Image2D() +{ + p = NULL; +} +Image2D::Image2D(const UMat &src) +{ + p = new Impl(src); +} +Image2D::~Image2D() +{ + if (p) + p->release(); +} + +void* Image2D::ptr() const +{ + return p ? p->handle : 0; +} + }} diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 155737ba7..2cab3237c 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -43,6 +43,7 @@ #include #include #include "lkpyramid.hpp" +#include "opencl_kernels.hpp" #define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n)) @@ -590,6 +591,231 @@ int cv::buildOpticalFlowPyramid(InputArray _img, OutputArrayOfArrays pyramid, Si return maxLevel; } +namespace cv +{ + class PyrLKOpticalFlow + { + struct dim3 + { + unsigned int x, y, z; + }; + public: + PyrLKOpticalFlow() + { + winSize = Size(21, 21); + maxLevel = 3; + iters = 30; + derivLambda = 0.5; + useInitialFlow = false; + //minEigThreshold = 1e-4f; + //getMinEigenVals = false; + } + + bool sparse(const UMat &prevImg, const UMat &nextImg, const UMat &prevPts, UMat &nextPts, UMat &status, UMat &err) + { + if (prevPts.empty()) + { + nextPts.release(); + status.release(); + return false; + } + + derivLambda = std::min(std::max(derivLambda, 0.0), 1.0); + if (derivLambda < 0) + return false; + if (maxLevel < 0 || winSize.width <= 2 || winSize.height <= 2) + return false; + iters = std::min(std::max(iters, 0), 100); + if (prevPts.rows != 1 || prevPts.type() != CV_32FC2) + return false; + + dim3 patch; + calcPatchSize(patch); + if (patch.x <= 0 || patch.x >= 6 || patch.y <= 0 || patch.y >= 6) + return false; + if (!initWaveSize()) + return false; + if (useInitialFlow) + { + if (nextPts.size() != prevPts.size() || nextPts.type() != CV_32FC2) + return false; + } + else + ensureSizeIsEnough(1, prevPts.cols, prevPts.type(), nextPts); + + UMat temp1 = (useInitialFlow ? nextPts : prevPts).reshape(1); + UMat temp2 = nextPts.reshape(1); + multiply(1.0f / (1 << maxLevel) /2.0f, temp1, temp2); + + ensureSizeIsEnough(1, prevPts.cols, CV_8UC1, status); + status.setTo(Scalar::all(1)); + + ensureSizeIsEnough(1, prevPts.cols, CV_32FC1, err); + + // build the image pyramids. + std::vector prevPyr; prevPyr.resize(maxLevel + 1); + std::vector nextPyr; nextPyr.resize(maxLevel + 1); + + prevImg.convertTo(prevPyr[0], CV_32F); + nextImg.convertTo(nextPyr[0], CV_32F); + + for (int level = 1; level <= maxLevel; ++level) + { + pyrDown(prevPyr[level - 1], prevPyr[level]); + pyrDown(nextPyr[level - 1], nextPyr[level]); + } + + // dI/dx ~ Ix, dI/dy ~ Iy + for (int level = maxLevel; level >= 0; level--) + { + lkSparse_run(prevPyr[level], nextPyr[level], + prevPts, nextPts, status, err, prevPts.cols, + level, patch); + } + return true; + } + + Size winSize; + int maxLevel; + int iters; + double derivLambda; + bool useInitialFlow; + //float minEigThreshold; + //bool getMinEigenVals; + + private: + void calcPatchSize(dim3 &patch) + { + dim3 block; + //winSize.width *= cn; + + if (winSize.width > 32 && winSize.width > 2 * winSize.height) + { + block.x = 32; + block.y = 8; + } + else + { + block.x = 16; + block.y = 16; + } + + patch.x = (winSize.width + block.x - 1) / block.x; + patch.y = (winSize.height + block.y - 1) / block.y; + + block.z = patch.z = 1; + } + private: + int waveSize; + bool initWaveSize() + { + waveSize = 1; + if (isDeviceCPU()) + return true; + + ocl::Kernel kernel; + if (!kernel.create("lkSparse", cv::ocl::video::pyrlk_oclsrc, "")) + return false; + waveSize = (int)kernel.preferedWorkGroupSizeMultiple(); + return true; + } + bool lkSparse_run(UMat &I, UMat &J, const UMat &prevPts, UMat &nextPts, UMat &status, UMat& err, + int ptcount, int level, dim3 patch) + { + size_t localThreads[3] = { 8, 8}; + size_t globalThreads[3] = { 8 * ptcount, 8}; + char calcErr = (0 == level) ? 1 : 0; + + cv::String build_options; + if (isDeviceCPU()) + build_options = " -D CPU"; + else + build_options = cv::format("-D WAVE_SIZE=%d", waveSize); + + ocl::Kernel kernel; + if (!kernel.create("lkSparse", cv::ocl::video::pyrlk_oclsrc, build_options)) + return false; + + ocl::Image2D imageI(I); + ocl::Image2D imageJ(J); + int idxArg = 0; + idxArg = kernel.set(idxArg, imageI); //image2d_t I + idxArg = kernel.set(idxArg, imageJ); //image2d_t J + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(prevPts)); // __global const float2* prevPts + idxArg = kernel.set(idxArg, (int)prevPts.step); // int prevPtsStep + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadWrite(nextPts)); // __global const float2* nextPts + idxArg = kernel.set(idxArg, (int)nextPts.step); // int nextPtsStep + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadWrite(status)); // __global uchar* status + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadWrite(err)); // __global float* err + idxArg = kernel.set(idxArg, (int)level); // const int level + idxArg = kernel.set(idxArg, (int)I.rows); // const int rows + idxArg = kernel.set(idxArg, (int)I.cols); // const int cols + idxArg = kernel.set(idxArg, (int)patch.x); // int PATCH_X + idxArg = kernel.set(idxArg, (int)patch.y); // int PATCH_Y + idxArg = kernel.set(idxArg, (int)winSize.width); // int c_winSize_x + idxArg = kernel.set(idxArg, (int)winSize.height); // int c_winSize_y + idxArg = kernel.set(idxArg, (int)iters); // int c_iters + idxArg = kernel.set(idxArg, (char)calcErr); //char calcErr + + return kernel.run(2, globalThreads, localThreads, true); + } + private: + inline static bool isDeviceCPU() + { + return (cv::ocl::Device::TYPE_CPU == cv::ocl::Device::getDefault().type()); + } + inline static void ensureSizeIsEnough(int rows, int cols, int type, UMat &m) + { + if (m.type() == type && m.rows >= rows && m.cols >= cols) + m = m(Rect(0, 0, cols, rows)); + else + m.create(rows, cols, type); + } + }; + + + bool ocl_calcOpticalFlowPyrLK(InputArray _prevImg, InputArray _nextImg, + InputArray _prevPts, InputOutputArray _nextPts, + OutputArray _status, OutputArray _err, + Size winSize, int maxLevel, + TermCriteria criteria, + int flags/*, double minEigThreshold*/ ) + { + if (0 != (OPTFLOW_LK_GET_MIN_EIGENVALS & flags)) + return false; + if (!cv::ocl::Device::getDefault().imageSupport()) + return false; + if (_nextImg.size() != _prevImg.size()) + return false; + int typePrev = _prevImg.type(); + int typeNext = _nextImg.type(); + if ((1 != CV_MAT_CN(typePrev)) || (1 != CV_MAT_CN(typeNext))) + return false; + if ((0 != CV_MAT_DEPTH(typePrev)) || (0 != CV_MAT_DEPTH(typeNext))) + return false; + + PyrLKOpticalFlow opticalFlow; + opticalFlow.winSize = winSize; + opticalFlow.maxLevel = maxLevel; + opticalFlow.iters = criteria.maxCount; + opticalFlow.derivLambda = criteria.epsilon; + opticalFlow.useInitialFlow = (0 != (flags & OPTFLOW_USE_INITIAL_FLOW)); + + UMat umatErr; + if (_err.needed()) + { + _err.create(_prevPts.size(), CV_8UC1); + umatErr = _err.getUMat(); + } + + _nextPts.create(_prevPts.size(), _prevPts.type()); + _status.create(_prevPts.size(), CV_8UC1); + UMat umatNextPts = _nextPts.getUMat(); + UMat umatStatus = _status.getUMat(); + return opticalFlow.sparse(_prevImg.getUMat(), _nextImg.getUMat(), _prevPts.getUMat(), umatNextPts, umatStatus, umatErr); + } +}; + void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg, InputArray _prevPts, InputOutputArray _nextPts, OutputArray _status, OutputArray _err, @@ -597,6 +823,10 @@ void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg, TermCriteria criteria, int flags, double minEigThreshold ) { + bool use_opencl = ocl::useOpenCL() && (_prevImg.isUMat() || _nextImg.isUMat()); + if ( use_opencl && ocl_calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err, winSize, maxLevel, criteria, flags/*, minEigThreshold*/)) + return; + Mat prevPtsMat = _prevPts.getMat(); const int derivDepth = DataType::depth; diff --git a/modules/video/src/opencl/pyrlk.cl b/modules/video/src/opencl/pyrlk.cl new file mode 100644 index 000000000..c01855490 --- /dev/null +++ b/modules/video/src/opencl/pyrlk.cl @@ -0,0 +1,583 @@ +/*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 +// Dachuan Zhao, dachuan@multicorewareinc.com +// Yao Wang, bitwangyaoyao@gmail.com +// Xiaopeng Fu, fuxiaopeng2222@163.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*/ + +#define BUFFER 64 +#define BUFFER2 BUFFER>>1 +#ifndef WAVE_SIZE +#define WAVE_SIZE 1 +#endif +#ifdef CPU + +inline void reduce3(float val1, float val2, float val3, __local float* smem1, __local float* smem2, __local float* smem3, int tid) +{ + smem1[tid] = val1; + smem2[tid] = val2; + smem3[tid] = val3; + barrier(CLK_LOCAL_MEM_FENCE); + + for(int i = BUFFER2; i > 0; i >>= 1) + { + if(tid < i) + { + smem1[tid] += smem1[tid + i]; + smem2[tid] += smem2[tid + i]; + smem3[tid] += smem3[tid + i]; + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} + +inline void reduce2(float val1, float val2, volatile __local float* smem1, volatile __local float* smem2, int tid) +{ + smem1[tid] = val1; + smem2[tid] = val2; + barrier(CLK_LOCAL_MEM_FENCE); + + for(int i = BUFFER2; i > 0; i >>= 1) + { + if(tid < i) + { + smem1[tid] += smem1[tid + i]; + smem2[tid] += smem2[tid + i]; + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} + +inline void reduce1(float val1, volatile __local float* smem1, int tid) +{ + smem1[tid] = val1; + barrier(CLK_LOCAL_MEM_FENCE); + + for(int i = BUFFER2; i > 0; i >>= 1) + { + if(tid < i) + { + smem1[tid] += smem1[tid + i]; + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} +#else +inline void reduce3(float val1, float val2, float val3, + __local volatile float* smem1, __local volatile float* smem2, __local volatile float* smem3, int tid) +{ + smem1[tid] = val1; + smem2[tid] = val2; + smem3[tid] = val3; + barrier(CLK_LOCAL_MEM_FENCE); + + if (tid < 32) + { + smem1[tid] += smem1[tid + 32]; + smem2[tid] += smem2[tid + 32]; + smem3[tid] += smem3[tid + 32]; +#if WAVE_SIZE < 32 + } + barrier(CLK_LOCAL_MEM_FENCE); + if (tid < 16) + { +#endif + smem1[tid] += smem1[tid + 16]; + smem2[tid] += smem2[tid + 16]; + smem3[tid] += smem3[tid + 16]; +#if WAVE_SIZE <16 + } + barrier(CLK_LOCAL_MEM_FENCE); + if (tid < 8) + { +#endif + smem1[tid] += smem1[tid + 8]; + smem2[tid] += smem2[tid + 8]; + smem3[tid] += smem3[tid + 8]; + + smem1[tid] += smem1[tid + 4]; + smem2[tid] += smem2[tid + 4]; + smem3[tid] += smem3[tid + 4]; + + smem1[tid] += smem1[tid + 2]; + smem2[tid] += smem2[tid + 2]; + smem3[tid] += smem3[tid + 2]; + + smem1[tid] += smem1[tid + 1]; + smem2[tid] += smem2[tid + 1]; + smem3[tid] += smem3[tid + 1]; + } + barrier(CLK_LOCAL_MEM_FENCE); +} + +inline void reduce2(float val1, float val2, __local volatile float* smem1, __local volatile float* smem2, int tid) +{ + smem1[tid] = val1; + smem2[tid] = val2; + barrier(CLK_LOCAL_MEM_FENCE); + + if (tid < 32) + { + smem1[tid] += smem1[tid + 32]; + smem2[tid] += smem2[tid + 32]; +#if WAVE_SIZE < 32 + } + barrier(CLK_LOCAL_MEM_FENCE); + if (tid < 16) + { +#endif + smem1[tid] += smem1[tid + 16]; + smem2[tid] += smem2[tid + 16]; +#if WAVE_SIZE <16 + } + barrier(CLK_LOCAL_MEM_FENCE); + if (tid < 8) + { +#endif + smem1[tid] += smem1[tid + 8]; + smem2[tid] += smem2[tid + 8]; + + smem1[tid] += smem1[tid + 4]; + smem2[tid] += smem2[tid + 4]; + + smem1[tid] += smem1[tid + 2]; + smem2[tid] += smem2[tid + 2]; + + smem1[tid] += smem1[tid + 1]; + smem2[tid] += smem2[tid + 1]; + } + barrier(CLK_LOCAL_MEM_FENCE); +} + +inline void reduce1(float val1, __local volatile float* smem1, int tid) +{ + smem1[tid] = val1; + barrier(CLK_LOCAL_MEM_FENCE); + + if (tid < 32) + { + smem1[tid] += smem1[tid + 32]; +#if WAVE_SIZE < 32 + } + barrier(CLK_LOCAL_MEM_FENCE); + if (tid < 16) + { +#endif + smem1[tid] += smem1[tid + 16]; +#if WAVE_SIZE <16 + } + barrier(CLK_LOCAL_MEM_FENCE); + if (tid < 8) + { +#endif + smem1[tid] += smem1[tid + 8]; + smem1[tid] += smem1[tid + 4]; + smem1[tid] += smem1[tid + 2]; + smem1[tid] += smem1[tid + 1]; + } + barrier(CLK_LOCAL_MEM_FENCE); +} +#endif + +#define SCALE (1.0f / (1 << 20)) +#define THRESHOLD 0.01f + +// Image read mode +__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR; + +inline void SetPatch(image2d_t I, float x, float y, + float* Pch, float* Dx, float* Dy, + float* A11, float* A12, float* A22) +{ + *Pch = read_imagef(I, sampler, (float2)(x, y)).x; + + float dIdx = 3.0f * read_imagef(I, sampler, (float2)(x + 1, y - 1)).x + 10.0f * read_imagef(I, sampler, (float2)(x + 1, y)).x + 3.0f * read_imagef(I, sampler, (float2)(x + 1, y + 1)).x - + (3.0f * read_imagef(I, sampler, (float2)(x - 1, y - 1)).x + 10.0f * read_imagef(I, sampler, (float2)(x - 1, y)).x + 3.0f * read_imagef(I, sampler, (float2)(x - 1, y + 1)).x); + + float dIdy = 3.0f * read_imagef(I, sampler, (float2)(x - 1, y + 1)).x + 10.0f * read_imagef(I, sampler, (float2)(x, y + 1)).x + 3.0f * read_imagef(I, sampler, (float2)(x + 1, y + 1)).x - + (3.0f * read_imagef(I, sampler, (float2)(x - 1, y - 1)).x + 10.0f * read_imagef(I, sampler, (float2)(x, y - 1)).x + 3.0f * read_imagef(I, sampler, (float2)(x + 1, y - 1)).x); + + + *Dx = dIdx; + *Dy = dIdy; + + *A11 += dIdx * dIdx; + *A12 += dIdx * dIdy; + *A22 += dIdy * dIdy; +} + +inline void GetPatch(image2d_t J, float x, float y, + float* Pch, float* Dx, float* Dy, + float* b1, float* b2) +{ + float J_val = read_imagef(J, sampler, (float2)(x, y)).x; + float diff = (J_val - *Pch) * 32.0f; + *b1 += diff**Dx; + *b2 += diff**Dy; +} + +inline void GetError(image2d_t J, const float x, const float y, const float* Pch, float* errval) +{ + float diff = read_imagef(J, sampler, (float2)(x,y)).x-*Pch; + *errval += fabs(diff); +} + +inline void SetPatch4(image2d_t I, const float x, const float y, + float4* Pch, float4* Dx, float4* Dy, + float* A11, float* A12, float* A22) +{ + *Pch = read_imagef(I, sampler, (float2)(x, y)); + + float4 dIdx = 3.0f * read_imagef(I, sampler, (float2)(x + 1, y - 1)) + 10.0f * read_imagef(I, sampler, (float2)(x + 1, y)) + 3.0f * read_imagef(I, sampler, (float2)(x + 1, y + 1)) - + (3.0f * read_imagef(I, sampler, (float2)(x - 1, y - 1)) + 10.0f * read_imagef(I, sampler, (float2)(x - 1, y)) + 3.0f * read_imagef(I, sampler, (float2)(x - 1, y + 1))); + + float4 dIdy = 3.0f * read_imagef(I, sampler, (float2)(x - 1, y + 1)) + 10.0f * read_imagef(I, sampler, (float2)(x, y + 1)) + 3.0f * read_imagef(I, sampler, (float2)(x + 1, y + 1)) - + (3.0f * read_imagef(I, sampler, (float2)(x - 1, y - 1)) + 10.0f * read_imagef(I, sampler, (float2)(x, y - 1)) + 3.0f * read_imagef(I, sampler, (float2)(x + 1, y - 1))); + + + *Dx = dIdx; + *Dy = dIdy; + float4 sqIdx = dIdx * dIdx; + *A11 += sqIdx.x + sqIdx.y + sqIdx.z; + sqIdx = dIdx * dIdy; + *A12 += sqIdx.x + sqIdx.y + sqIdx.z; + sqIdx = dIdy * dIdy; + *A22 += sqIdx.x + sqIdx.y + sqIdx.z; +} + +inline void GetPatch4(image2d_t J, const float x, const float y, + const float4* Pch, const float4* Dx, const float4* Dy, + float* b1, float* b2) +{ + float4 J_val = read_imagef(J, sampler, (float2)(x, y)); + float4 diff = (J_val - *Pch) * 32.0f; + float4 xdiff = diff* *Dx; + *b1 += xdiff.x + xdiff.y + xdiff.z; + xdiff = diff* *Dy; + *b2 += xdiff.x + xdiff.y + xdiff.z; +} + +inline void GetError4(image2d_t J, const float x, const float y, const float4* Pch, float* errval) +{ + float4 diff = read_imagef(J, sampler, (float2)(x,y))-*Pch; + *errval += fabs(diff.x) + fabs(diff.y) + fabs(diff.z); +} + +#define GRIDSIZE 3 +__kernel void lkSparse(image2d_t I, image2d_t J, + __global const float2* prevPts, int prevPtsStep, __global float2* nextPts, int nextPtsStep, __global uchar* status, __global float* err, + const int level, const int rows, const int cols, int PATCH_X, int PATCH_Y, int c_winSize_x, int c_winSize_y, int c_iters, char calcErr) +{ + __local float smem1[BUFFER]; + __local float smem2[BUFFER]; + __local float smem3[BUFFER]; + + unsigned int xid=get_local_id(0); + unsigned int yid=get_local_id(1); + unsigned int gid=get_group_id(0); + unsigned int xsize=get_local_size(0); + unsigned int ysize=get_local_size(1); + int xBase, yBase, k; + + float2 c_halfWin = (float2)((c_winSize_x - 1)>>1, (c_winSize_y - 1)>>1); + + const int tid = mad24(yid, xsize, xid); + + float2 prevPt = prevPts[gid] / (float2)(1 << level); + + if (prevPt.x < 0 || prevPt.x >= cols || prevPt.y < 0 || prevPt.y >= rows) + { + if (tid == 0 && level == 0) + { + status[gid] = 0; + } + + return; + } + prevPt -= c_halfWin; + + // extract the patch from the first image, compute covariation matrix of derivatives + + float A11 = 0; + float A12 = 0; + float A22 = 0; + + float I_patch[GRIDSIZE][GRIDSIZE]; + float dIdx_patch[GRIDSIZE][GRIDSIZE]; + float dIdy_patch[GRIDSIZE][GRIDSIZE]; + + yBase=yid; + { + xBase=xid; + SetPatch(I, prevPt.x + xBase + 0.5f, prevPt.y + yBase + 0.5f, + &I_patch[0][0], &dIdx_patch[0][0], &dIdy_patch[0][0], + &A11, &A12, &A22); + + + xBase+=xsize; + SetPatch(I, prevPt.x + xBase + 0.5f, prevPt.y + yBase + 0.5f, + &I_patch[0][1], &dIdx_patch[0][1], &dIdy_patch[0][1], + &A11, &A12, &A22); + + xBase+=xsize; + if(xBase= cols || prevPt.y < -c_halfWin.y || prevPt.y >= rows) + { + if (tid == 0 && level == 0) + status[gid] = 0; + return; + } + + float b1 = 0; + float b2 = 0; + + yBase=yid; + { + xBase=xid; + GetPatch(J, prevPt.x + xBase + 0.5f, prevPt.y + yBase + 0.5f, + &I_patch[0][0], &dIdx_patch[0][0], &dIdy_patch[0][0], + &b1, &b2); + + + xBase+=xsize; + GetPatch(J, prevPt.x + xBase + 0.5f, prevPt.y + yBase + 0.5f, + &I_patch[0][1], &dIdx_patch[0][1], &dIdy_patch[0][1], + &b1, &b2); + + xBase+=xsize; + if(xBase pts; + cv::goodFeaturesToTrack(frame0, pts, 1000, 0.01, 0.0); + + std::vector nextPtsCPU; + std::vector statusCPU; + std::vector errCPU; + OCL_OFF(cv::calcOpticalFlowPyrLK(frame0, frame1, pts, nextPtsCPU, statusCPU, errCPU, winSize, maxLevel, criteria, flags, minEigThreshold)); + + UMat umatNextPts, umatStatus, umatErr; + OCL_ON(cv::calcOpticalFlowPyrLK(umatFrame0, umatFrame1, pts, umatNextPts, umatStatus, umatErr, winSize, maxLevel, criteria, flags, minEigThreshold)); + std::vector nextPts(umatNextPts.cols); umatNextPts.copyTo(nextPts); + std::vector status; umatStatus.copyTo(status); + std::vector err; umatErr.copyTo(err); + + ASSERT_EQ(nextPtsCPU.size(), nextPts.size()); + ASSERT_EQ(statusCPU.size(), status.size()); + + size_t mistmatch = 0; + for (size_t i = 0; i < nextPts.size(); ++i) + { + if (status[i] != statusCPU[i]) + { + ++mistmatch; + continue; + } + + if (status[i]) + { + cv::Point2i a = nextPts[i]; + cv::Point2i b = nextPtsCPU[i]; + + bool eq = std::abs(a.x - b.x) < 1 && std::abs(a.y - b.y) < 1; + float errdiff = 0.0f; + + if (!eq || errdiff > 1e-1) + ++mistmatch; + } + } + + double bad_ratio = static_cast(mistmatch) / (nextPts.size()); + + ASSERT_LE(bad_ratio, 0.02f); +} + +OCL_INSTANTIATE_TEST_CASE_P(Video, PyrLKOpticalFlow, + Combine( + Values(21, 25), + Values(3, 5) + ) + ); + +} } // namespace cvtest::ocl + + +#endif // HAVE_OPENCL \ No newline at end of file From 4152135e63731cadd1eba17d0c53d1ad44169a7a Mon Sep 17 00:00:00 2001 From: vbystricky Date: Thu, 16 Jan 2014 13:35:10 +0400 Subject: [PATCH 241/295] Fix error with some opencl functions on the build WITH_OPENCL=OFF --- modules/core/src/ocl.cpp | 24 ++++++++++++++++++++++-- modules/video/src/lkpyramid.cpp | 2 +- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index f103cd99d..7b29e7774 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -821,6 +821,7 @@ OCL_FUNC_P(cl_mem, clCreateSubBuffer, const void * buffer_create_info, cl_int * errcode_ret), (buffer, flags, buffer_create_type, buffer_create_info, errcode_ret)) +*/ OCL_FUNC_P(cl_mem, clCreateImage, (cl_context context, @@ -831,6 +832,18 @@ OCL_FUNC_P(cl_mem, clCreateImage, cl_int * errcode_ret), (context, flags, image_format, image_desc, host_ptr, errcode_ret)) +OCL_FUNC_P(cl_mem, clCreateImage2D, + (cl_context context, + cl_mem_flags flags, + const cl_image_format * image_format, + size_t image_width, + size_t image_height, + size_t image_row_pitch, + void * host_ptr, + cl_int *errcode_ret), + (context, flags, image_format, image_width, image_height, image_row_pitch, host_ptr, errcode_ret)) + +/* OCL_FUNC(cl_int, clGetSupportedImageFormats, (cl_context context, cl_mem_flags flags, @@ -945,21 +958,26 @@ OCL_FUNC(cl_int, clEnqueueCopyImageToBuffer, cl_event * event), (command_queue, src_image, dst_buffer, src_origin, region, dst_offset, num_events_in_wait_list, event_wait_list, event)) +*/ OCL_FUNC(cl_int, clEnqueueCopyBufferToImage, (cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_image, size_t src_offset, - const size_t * dst_origin[3], - const size_t * region[3], + const size_t dst_origin[3], + const size_t region[3], cl_uint num_events_in_wait_list, const cl_event * event_wait_list, cl_event * event), (command_queue, src_buffer, dst_image, src_offset, dst_origin, region, num_events_in_wait_list, event_wait_list, event)) + OCL_FUNC(cl_int, clFlush, + (cl_command_queue command_queue), + (command_queue)) +/* OCL_FUNC_P(void*, clEnqueueMapImage, (cl_command_queue command_queue, cl_mem image, @@ -976,7 +994,9 @@ OCL_FUNC_P(void*, clEnqueueMapImage, (command_queue, image, blocking_map, map_flags, origin, region, image_row_pitch, image_slice_pitch, num_events_in_wait_list, event_wait_list, event, errcode_ret)) +*/ +/* OCL_FUNC(cl_int, clRetainProgram, (cl_program program), (program)) OCL_FUNC(cl_int, clGetKernelInfo, diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 2cab3237c..3eeac4de8 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -774,7 +774,7 @@ namespace cv }; - bool ocl_calcOpticalFlowPyrLK(InputArray _prevImg, InputArray _nextImg, + static bool ocl_calcOpticalFlowPyrLK(InputArray _prevImg, InputArray _nextImg, InputArray _prevPts, InputOutputArray _nextPts, OutputArray _status, OutputArray _err, Size winSize, int maxLevel, From 33fc46cdec5260989c57e08e8896de35583e1798 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Thu, 16 Jan 2014 15:44:35 +0400 Subject: [PATCH 242/295] Validate parameters for using OpenCL version, before upload UMat --- modules/core/src/ocl.cpp | 2 + modules/video/src/lkpyramid.cpp | 64 +++++++++----------- modules/video/test/ocl/test_optflowpyrlk.cpp | 16 ++--- 3 files changed, 40 insertions(+), 42 deletions(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 7b29e7774..7201fca71 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3841,6 +3841,8 @@ struct Image2D::Impl { Impl(const UMat &src) { + handle = 0; + refcount = 1; init(src); } ~Impl() diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 3eeac4de8..8359cca08 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -611,47 +611,34 @@ namespace cv //getMinEigenVals = false; } - bool sparse(const UMat &prevImg, const UMat &nextImg, const UMat &prevPts, UMat &nextPts, UMat &status, UMat &err) + bool checkParam() { - if (prevPts.empty()) - { - nextPts.release(); - status.release(); - return false; - } + iters = std::min(std::max(iters, 0), 100); derivLambda = std::min(std::max(derivLambda, 0.0), 1.0); if (derivLambda < 0) return false; if (maxLevel < 0 || winSize.width <= 2 || winSize.height <= 2) return false; - iters = std::min(std::max(iters, 0), 100); - if (prevPts.rows != 1 || prevPts.type() != CV_32FC2) - return false; - - dim3 patch; calcPatchSize(patch); if (patch.x <= 0 || patch.x >= 6 || patch.y <= 0 || patch.y >= 6) return false; if (!initWaveSize()) return false; - if (useInitialFlow) - { - if (nextPts.size() != prevPts.size() || nextPts.type() != CV_32FC2) - return false; - } - else - ensureSizeIsEnough(1, prevPts.cols, prevPts.type(), nextPts); + return true; + } + + bool sparse(const UMat &prevImg, const UMat &nextImg, const UMat &prevPts, UMat &nextPts, UMat &status, UMat &err) + { + if (!checkParam()) + return false; UMat temp1 = (useInitialFlow ? nextPts : prevPts).reshape(1); UMat temp2 = nextPts.reshape(1); multiply(1.0f / (1 << maxLevel) /2.0f, temp1, temp2); - ensureSizeIsEnough(1, prevPts.cols, CV_8UC1, status); status.setTo(Scalar::all(1)); - ensureSizeIsEnough(1, prevPts.cols, CV_32FC1, err); - // build the image pyramids. std::vector prevPyr; prevPyr.resize(maxLevel + 1); std::vector nextPyr; nextPyr.resize(maxLevel + 1); @@ -668,9 +655,10 @@ namespace cv // dI/dx ~ Ix, dI/dy ~ Iy for (int level = maxLevel; level >= 0; level--) { - lkSparse_run(prevPyr[level], nextPyr[level], - prevPts, nextPts, status, err, prevPts.cols, - level, patch); + if (!lkSparse_run(prevPyr[level], nextPyr[level], prevPts, + nextPts, status, err, + prevPts.cols, level, patch)) + return false; } return true; } @@ -707,6 +695,7 @@ namespace cv } private: int waveSize; + dim3 patch; bool initWaveSize() { waveSize = 1; @@ -764,13 +753,6 @@ namespace cv { return (cv::ocl::Device::TYPE_CPU == cv::ocl::Device::getDefault().type()); } - inline static void ensureSizeIsEnough(int rows, int cols, int type, UMat &m) - { - if (m.type() == type && m.rows >= rows && m.cols >= cols) - m = m(Rect(0, 0, cols, rows)); - else - m.create(rows, cols, type); - } }; @@ -794,19 +776,33 @@ namespace cv if ((0 != CV_MAT_DEPTH(typePrev)) || (0 != CV_MAT_DEPTH(typeNext))) return false; + if (_prevPts.empty() || _prevPts.size().height != 1 || _prevPts.type() != CV_32FC2) + return false; + bool useInitialFlow = (0 != (flags & OPTFLOW_USE_INITIAL_FLOW)); + if (useInitialFlow) + { + if (_nextPts.size() != _prevPts.size() || _nextPts.type() != CV_32FC2) + return false; + } + PyrLKOpticalFlow opticalFlow; opticalFlow.winSize = winSize; opticalFlow.maxLevel = maxLevel; opticalFlow.iters = criteria.maxCount; opticalFlow.derivLambda = criteria.epsilon; - opticalFlow.useInitialFlow = (0 != (flags & OPTFLOW_USE_INITIAL_FLOW)); + opticalFlow.useInitialFlow = useInitialFlow; + + if (!opticalFlow.checkParam()) + return false; UMat umatErr; if (_err.needed()) { - _err.create(_prevPts.size(), CV_8UC1); + _err.create(_prevPts.size(), CV_32FC1); umatErr = _err.getUMat(); } + else + umatErr.create(_prevPts.size(), CV_32FC1); _nextPts.create(_prevPts.size(), _prevPts.type()); _status.create(_prevPts.size(), CV_8UC1); diff --git a/modules/video/test/ocl/test_optflowpyrlk.cpp b/modules/video/test/ocl/test_optflowpyrlk.cpp index f3ef6363d..1957aedcb 100644 --- a/modules/video/test/ocl/test_optflowpyrlk.cpp +++ b/modules/video/test/ocl/test_optflowpyrlk.cpp @@ -86,10 +86,10 @@ OCL_TEST_P(PyrLKOpticalFlow, Mat) std::vector pts; cv::goodFeaturesToTrack(frame0, pts, 1000, 0.01, 0.0); - std::vector nextPtsCPU; - std::vector statusCPU; - std::vector errCPU; - OCL_OFF(cv::calcOpticalFlowPyrLK(frame0, frame1, pts, nextPtsCPU, statusCPU, errCPU, winSize, maxLevel, criteria, flags, minEigThreshold)); + std::vector cpuNextPts; + std::vector cpuStatusCPU; + std::vector cpuErr; + OCL_OFF(cv::calcOpticalFlowPyrLK(frame0, frame1, pts, cpuNextPts, cpuStatusCPU, cpuErr, winSize, maxLevel, criteria, flags, minEigThreshold)); UMat umatNextPts, umatStatus, umatErr; OCL_ON(cv::calcOpticalFlowPyrLK(umatFrame0, umatFrame1, pts, umatNextPts, umatStatus, umatErr, winSize, maxLevel, criteria, flags, minEigThreshold)); @@ -97,13 +97,13 @@ OCL_TEST_P(PyrLKOpticalFlow, Mat) std::vector status; umatStatus.copyTo(status); std::vector err; umatErr.copyTo(err); - ASSERT_EQ(nextPtsCPU.size(), nextPts.size()); - ASSERT_EQ(statusCPU.size(), status.size()); + ASSERT_EQ(cpuNextPts.size(), nextPts.size()); + ASSERT_EQ(cpuStatusCPU.size(), status.size()); size_t mistmatch = 0; for (size_t i = 0; i < nextPts.size(); ++i) { - if (status[i] != statusCPU[i]) + if (status[i] != cpuStatusCPU[i]) { ++mistmatch; continue; @@ -112,7 +112,7 @@ OCL_TEST_P(PyrLKOpticalFlow, Mat) if (status[i]) { cv::Point2i a = nextPts[i]; - cv::Point2i b = nextPtsCPU[i]; + cv::Point2i b = cpuNextPts[i]; bool eq = std::abs(a.x - b.x) < 1 && std::abs(a.y - b.y) < 1; float errdiff = 0.0f; From 3ba663665168b231dcbc3bd522841a5f7de54485 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Thu, 16 Jan 2014 16:24:10 +0400 Subject: [PATCH 243/295] Fix builds errors --- modules/video/src/lkpyramid.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 8359cca08..04880c154 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -620,7 +620,7 @@ namespace cv return false; if (maxLevel < 0 || winSize.width <= 2 || winSize.height <= 2) return false; - calcPatchSize(patch); + calcPatchSize(); if (patch.x <= 0 || patch.x >= 6 || patch.y <= 0 || patch.y >= 6) return false; if (!initWaveSize()) @@ -672,7 +672,21 @@ namespace cv //bool getMinEigenVals; private: - void calcPatchSize(dim3 &patch) + int waveSize; + bool initWaveSize() + { + waveSize = 1; + if (isDeviceCPU()) + return true; + + ocl::Kernel kernel; + if (!kernel.create("lkSparse", cv::ocl::video::pyrlk_oclsrc, "")) + return false; + waveSize = (int)kernel.preferedWorkGroupSizeMultiple(); + return true; + } + dim3 patch; + void calcPatchSize() { dim3 block; //winSize.width *= cn; @@ -693,21 +707,7 @@ namespace cv block.z = patch.z = 1; } - private: - int waveSize; - dim3 patch; - bool initWaveSize() - { - waveSize = 1; - if (isDeviceCPU()) - return true; - ocl::Kernel kernel; - if (!kernel.create("lkSparse", cv::ocl::video::pyrlk_oclsrc, "")) - return false; - waveSize = (int)kernel.preferedWorkGroupSizeMultiple(); - return true; - } bool lkSparse_run(UMat &I, UMat &J, const UMat &prevPts, UMat &nextPts, UMat &status, UMat& err, int ptcount, int level, dim3 patch) { From ece635bf3c6ca324807fa47922bbf4f854941128 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Thu, 16 Jan 2014 16:24:10 +0400 Subject: [PATCH 244/295] Fix builds errors --- modules/video/src/lkpyramid.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 04880c154..354bdfe0f 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -657,7 +657,7 @@ namespace cv { if (!lkSparse_run(prevPyr[level], nextPyr[level], prevPts, nextPts, status, err, - prevPts.cols, level, patch)) + prevPts.cols, level)) return false; } return true; @@ -709,7 +709,7 @@ namespace cv } bool lkSparse_run(UMat &I, UMat &J, const UMat &prevPts, UMat &nextPts, UMat &status, UMat& err, - int ptcount, int level, dim3 patch) + int ptcount, int level) { size_t localThreads[3] = { 8, 8}; size_t globalThreads[3] = { 8 * ptcount, 8}; From 3a798a27e50346f04dbdc831f592adb05ec15ed9 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Mon, 20 Jan 2014 12:39:04 +0400 Subject: [PATCH 245/295] Add perfomance test --- .../video/perf/opencl/perf_optflow_pyrlk.cpp | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 modules/video/perf/opencl/perf_optflow_pyrlk.cpp diff --git a/modules/video/perf/opencl/perf_optflow_pyrlk.cpp b/modules/video/perf/opencl/perf_optflow_pyrlk.cpp new file mode 100644 index 000000000..dc288dce1 --- /dev/null +++ b/modules/video/perf/opencl/perf_optflow_pyrlk.cpp @@ -0,0 +1,110 @@ +/*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/ts/ocl_perf.hpp" + +using std::tr1::make_tuple; + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +///////////// FarnebackOpticalFlow //////////////////////// +CV_ENUM(farneFlagType, 0, OPTFLOW_FARNEBACK_GAUSSIAN) + +typedef tuple< int > PyrLKOpticalFlowParams; +typedef TestBaseWithParam PyrLKOpticalFlowFixture; + +OCL_PERF_TEST_P(PyrLKOpticalFlowFixture, PyrLKOpticalFlow, + ::testing::Values(1000, 2000, 4000) + //::testing::Combine( + // ::testing::Values( + // make_tuple(5, 1.1), + // make_tuple(7, 1.5) + // ), + // farneFlagType::all(), + // ::testing::Bool() + // ) + ) +{ + Mat frame0 = imread(getDataPath("gpu/opticalflow/rubberwhale1.png"), cv::IMREAD_GRAYSCALE); + ASSERT_FALSE(frame0.empty()) << "can't load rubberwhale1.png"; + + Mat frame1 = imread(getDataPath("gpu/opticalflow/rubberwhale2.png"), cv::IMREAD_GRAYSCALE); + ASSERT_FALSE(frame1.empty()) << "can't load rubberwhale2.png"; + + UMat uFrame0; frame0.copyTo(uFrame0); + UMat uFrame1; frame1.copyTo(uFrame1); + + const Size winSize = Size(21, 21); + const int maxLevel = 3; + const TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.5); + const int flags = 0; + const float minEigThreshold = 1e-4f; + const double eps = 0.5; + + const PyrLKOpticalFlowParams params = GetParam(); + const int pointsCount = get<0>(params); + + vector pts, nextPts; + vector status; + vector err; + goodFeaturesToTrack(frame0, pts, pointsCount, 0.01, 0.0); + Mat ptsMat(1, static_cast(pts.size()), CV_32FC2, (void *)&pts[0]); + + declare.in(uFrame0, uFrame1, WARMUP_READ); + UMat uNextPts, uStatus, uErr; + OCL_TEST_CYCLE() + cv::calcOpticalFlowPyrLK(uFrame0, uFrame1, pts, uNextPts, uStatus, uErr, winSize, maxLevel, criteria, flags, minEigThreshold); + + SANITY_CHECK(uNextPts, eps); +} + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL \ No newline at end of file From e96ba8140ce489e1fd85e134ad374a3dd5ce4482 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Mon, 20 Jan 2014 14:50:47 +0400 Subject: [PATCH 246/295] Grow up epsilon for sanity checks --- modules/video/perf/opencl/perf_optflow_pyrlk.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/video/perf/opencl/perf_optflow_pyrlk.cpp b/modules/video/perf/opencl/perf_optflow_pyrlk.cpp index dc288dce1..6a3f62cf7 100644 --- a/modules/video/perf/opencl/perf_optflow_pyrlk.cpp +++ b/modules/video/perf/opencl/perf_optflow_pyrlk.cpp @@ -83,10 +83,10 @@ OCL_PERF_TEST_P(PyrLKOpticalFlowFixture, PyrLKOpticalFlow, const Size winSize = Size(21, 21); const int maxLevel = 3; - const TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.5); + const TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01); const int flags = 0; const float minEigThreshold = 1e-4f; - const double eps = 0.5; + const double eps = 1.0; const PyrLKOpticalFlowParams params = GetParam(); const int pointsCount = get<0>(params); From a7e5a488a8f6cd2254cac326a7d9d0d62a8e821e Mon Sep 17 00:00:00 2001 From: vbystricky Date: Mon, 20 Jan 2014 16:21:08 +0400 Subject: [PATCH 247/295] Change method of setting arguments to kernel to safe one --- modules/video/src/lkpyramid.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 354bdfe0f..d568709e9 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -708,6 +708,16 @@ namespace cv block.z = patch.z = 1; } + #define SAFE_KERNEL_SET_ARG(idx, arg) \ + {\ + int idxNew = kernel.set(idx, arg);\ + if (-1 == idxNew)\ + {\ + printf("lkSparse_run can't setup argument index = %d to kernel\n");\ + return false;\ + }\ + idx = idxNew;\ + } bool lkSparse_run(UMat &I, UMat &J, const UMat &prevPts, UMat &nextPts, UMat &status, UMat& err, int ptcount, int level) { @@ -728,6 +738,7 @@ namespace cv ocl::Image2D imageI(I); ocl::Image2D imageJ(J); int idxArg = 0; +#if 0 idxArg = kernel.set(idxArg, imageI); //image2d_t I idxArg = kernel.set(idxArg, imageJ); //image2d_t J idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(prevPts)); // __global const float2* prevPts @@ -745,6 +756,25 @@ namespace cv idxArg = kernel.set(idxArg, (int)winSize.height); // int c_winSize_y idxArg = kernel.set(idxArg, (int)iters); // int c_iters idxArg = kernel.set(idxArg, (char)calcErr); //char calcErr +#else + SAFE_KERNEL_SET_ARG(idxArg, imageI); //image2d_t I + SAFE_KERNEL_SET_ARG(idxArg, imageJ); //image2d_t J + SAFE_KERNEL_SET_ARG(idxArg, ocl::KernelArg::PtrReadOnly(prevPts)); // __global const float2* prevPts + SAFE_KERNEL_SET_ARG(idxArg, (int)prevPts.step); // int prevPtsStep + SAFE_KERNEL_SET_ARG(idxArg, ocl::KernelArg::PtrReadWrite(nextPts)); // __global const float2* nextPts + SAFE_KERNEL_SET_ARG(idxArg, (int)nextPts.step); // int nextPtsStep + SAFE_KERNEL_SET_ARG(idxArg, ocl::KernelArg::PtrReadWrite(status)); // __global uchar* status + SAFE_KERNEL_SET_ARG(idxArg, ocl::KernelArg::PtrReadWrite(err)); // __global float* err + SAFE_KERNEL_SET_ARG(idxArg, (int)level); // const int level + SAFE_KERNEL_SET_ARG(idxArg, (int)I.rows); // const int rows + SAFE_KERNEL_SET_ARG(idxArg, (int)I.cols); // const int cols + SAFE_KERNEL_SET_ARG(idxArg, (int)patch.x); // int PATCH_X + SAFE_KERNEL_SET_ARG(idxArg, (int)patch.y); // int PATCH_Y + SAFE_KERNEL_SET_ARG(idxArg, (int)winSize.width); // int c_winSize_x + SAFE_KERNEL_SET_ARG(idxArg, (int)winSize.height); // int c_winSize_y + SAFE_KERNEL_SET_ARG(idxArg, (int)iters); // int c_iters + SAFE_KERNEL_SET_ARG(idxArg, (char)calcErr); //char calcErr +#endif return kernel.run(2, globalThreads, localThreads, true); } From 094bc923182272a50a378f914c0f7dd7e26192bd Mon Sep 17 00:00:00 2001 From: vbystricky Date: Mon, 20 Jan 2014 17:22:39 +0400 Subject: [PATCH 248/295] Fix build error --- modules/video/src/lkpyramid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index d568709e9..139eda670 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -713,7 +713,7 @@ namespace cv int idxNew = kernel.set(idx, arg);\ if (-1 == idxNew)\ {\ - printf("lkSparse_run can't setup argument index = %d to kernel\n");\ + printf("lkSparse_run can't setup argument index = %d to kernel\n", idx);\ return false;\ }\ idx = idxNew;\ From 27fb7e180207879d52a561ab251fc4118f4c12c2 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Thu, 23 Jan 2014 12:17:25 +0400 Subject: [PATCH 249/295] Change type of result vector of ocl version from row to column --- modules/video/src/lkpyramid.cpp | 22 ++++++++++++++------ modules/video/test/ocl/test_optflowpyrlk.cpp | 17 ++++++++------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 139eda670..2ba20d315 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -806,13 +806,24 @@ namespace cv if ((0 != CV_MAT_DEPTH(typePrev)) || (0 != CV_MAT_DEPTH(typeNext))) return false; - if (_prevPts.empty() || _prevPts.size().height != 1 || _prevPts.type() != CV_32FC2) + if (_prevPts.empty() || _prevPts.type() != CV_32FC2 || (!_prevPts.isContinuous())) return false; + if ((1 != _prevPts.size().height) && (1 != _prevPts.size().width)) + return false; + size_t npoints = _prevPts.total(); bool useInitialFlow = (0 != (flags & OPTFLOW_USE_INITIAL_FLOW)); if (useInitialFlow) { - if (_nextPts.size() != _prevPts.size() || _nextPts.type() != CV_32FC2) + if (_nextPts.empty() || _nextPts.type() != CV_32FC2 || (!_prevPts.isContinuous())) return false; + if ((1 != _nextPts.size().height) && (1 != _nextPts.size().width)) + return false; + if (_nextPts.total() != npoints) + return false; + } + else + { + _nextPts.create(_prevPts.size(), _prevPts.type()); } PyrLKOpticalFlow opticalFlow; @@ -828,14 +839,13 @@ namespace cv UMat umatErr; if (_err.needed()) { - _err.create(_prevPts.size(), CV_32FC1); + _err.create((int)npoints, 1, CV_32FC1); umatErr = _err.getUMat(); } else - umatErr.create(_prevPts.size(), CV_32FC1); + umatErr.create((int)npoints, 1, CV_32FC1); - _nextPts.create(_prevPts.size(), _prevPts.type()); - _status.create(_prevPts.size(), CV_8UC1); + _status.create((int)npoints, 1, CV_8UC1); UMat umatNextPts = _nextPts.getUMat(); UMat umatStatus = _status.getUMat(); return opticalFlow.sparse(_prevImg.getUMat(), _nextImg.getUMat(), _prevPts.getUMat(), umatNextPts, umatStatus, umatErr); diff --git a/modules/video/test/ocl/test_optflowpyrlk.cpp b/modules/video/test/ocl/test_optflowpyrlk.cpp index 1957aedcb..94195eabe 100644 --- a/modules/video/test/ocl/test_optflowpyrlk.cpp +++ b/modules/video/test/ocl/test_optflowpyrlk.cpp @@ -75,16 +75,19 @@ PARAM_TEST_CASE(PyrLKOpticalFlow, int, int) OCL_TEST_P(PyrLKOpticalFlow, Mat) { - cv::Mat frame0 = readImage("optflow/rubberwhale1.png", cv::IMREAD_GRAYSCALE); + static const int npoints = 1000; + static const float eps = 0.03f; + + cv::Mat frame0 = readImage("optflow/RubberWhale1.png", cv::IMREAD_GRAYSCALE); ASSERT_FALSE(frame0.empty()); UMat umatFrame0; frame0.copyTo(umatFrame0); - cv::Mat frame1 = readImage("optflow/rubberwhale1.png", cv::IMREAD_GRAYSCALE); + cv::Mat frame1 = readImage("optflow/RubberWhale2.png", cv::IMREAD_GRAYSCALE); ASSERT_FALSE(frame1.empty()); UMat umatFrame1; frame1.copyTo(umatFrame1); std::vector pts; - cv::goodFeaturesToTrack(frame0, pts, 1000, 0.01, 0.0); + cv::goodFeaturesToTrack(frame0, pts, npoints, 0.01, 0.0); std::vector cpuNextPts; std::vector cpuStatusCPU; @@ -93,9 +96,9 @@ OCL_TEST_P(PyrLKOpticalFlow, Mat) UMat umatNextPts, umatStatus, umatErr; OCL_ON(cv::calcOpticalFlowPyrLK(umatFrame0, umatFrame1, pts, umatNextPts, umatStatus, umatErr, winSize, maxLevel, criteria, flags, minEigThreshold)); - std::vector nextPts(umatNextPts.cols); umatNextPts.copyTo(nextPts); - std::vector status; umatStatus.copyTo(status); - std::vector err; umatErr.copyTo(err); + std::vector nextPts; umatNextPts.reshape(2, 1).copyTo(nextPts); + std::vector status; umatStatus.reshape(1, 1).copyTo(status); + std::vector err; umatErr.reshape(1, 1).copyTo(err); ASSERT_EQ(cpuNextPts.size(), nextPts.size()); ASSERT_EQ(cpuStatusCPU.size(), status.size()); @@ -124,7 +127,7 @@ OCL_TEST_P(PyrLKOpticalFlow, Mat) double bad_ratio = static_cast(mistmatch) / (nextPts.size()); - ASSERT_LE(bad_ratio, 0.02f); + ASSERT_LE(bad_ratio, eps); } OCL_INSTANTIATE_TEST_CASE_P(Video, PyrLKOpticalFlow, From bb09d44e0aa4cf109d39f566f9695f7b438a8a53 Mon Sep 17 00:00:00 2001 From: vbystricky Date: Thu, 23 Jan 2014 17:35:44 +0400 Subject: [PATCH 250/295] Unused code removed --- modules/video/perf/opencl/perf_optflow_pyrlk.cpp | 8 -------- modules/video/src/lkpyramid.cpp | 5 ----- 2 files changed, 13 deletions(-) diff --git a/modules/video/perf/opencl/perf_optflow_pyrlk.cpp b/modules/video/perf/opencl/perf_optflow_pyrlk.cpp index 6a3f62cf7..b2492e114 100644 --- a/modules/video/perf/opencl/perf_optflow_pyrlk.cpp +++ b/modules/video/perf/opencl/perf_optflow_pyrlk.cpp @@ -62,14 +62,6 @@ typedef TestBaseWithParam PyrLKOpticalFlowFixture; OCL_PERF_TEST_P(PyrLKOpticalFlowFixture, PyrLKOpticalFlow, ::testing::Values(1000, 2000, 4000) - //::testing::Combine( - // ::testing::Values( - // make_tuple(5, 1.1), - // make_tuple(7, 1.5) - // ), - // farneFlagType::all(), - // ::testing::Bool() - // ) ) { Mat frame0 = imread(getDataPath("gpu/opticalflow/rubberwhale1.png"), cv::IMREAD_GRAYSCALE); diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 2ba20d315..382914b2d 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -607,8 +607,6 @@ namespace cv iters = 30; derivLambda = 0.5; useInitialFlow = false; - //minEigThreshold = 1e-4f; - //getMinEigenVals = false; } bool checkParam() @@ -668,8 +666,6 @@ namespace cv int iters; double derivLambda; bool useInitialFlow; - //float minEigThreshold; - //bool getMinEigenVals; private: int waveSize; @@ -689,7 +685,6 @@ namespace cv void calcPatchSize() { dim3 block; - //winSize.width *= cn; if (winSize.width > 32 && winSize.width > 2 * winSize.height) { From 7f785e0a110b74f4a3315a56dd33515dfe8b839e Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 24 Jan 2014 21:03:31 +0400 Subject: [PATCH 251/295] refactored core using new macro --- .../include/opencv2/core/opencl/ocl_defs.hpp | 1 - modules/core/src/arithm.cpp | 54 ++++++++++------ modules/core/src/convert.cpp | 61 ++++++++++++------- modules/core/src/copy.cpp | 27 ++++---- modules/core/src/dxt.cpp | 13 ++-- modules/core/src/matmul.cpp | 11 ++-- modules/core/src/matrix.cpp | 25 +++++--- modules/core/src/stat.cpp | 47 ++++++++++---- 8 files changed, 155 insertions(+), 84 deletions(-) diff --git a/modules/core/include/opencv2/core/opencl/ocl_defs.hpp b/modules/core/include/opencv2/core/opencl/ocl_defs.hpp index 5e7c4f39d..6a4fd992c 100644 --- a/modules/core/include/opencv2/core/opencl/ocl_defs.hpp +++ b/modules/core/include/opencv2/core/opencl/ocl_defs.hpp @@ -31,4 +31,3 @@ #else #define CV_OCL_RUN(condition, func) #endif - diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index d176e3263..dbf05a3f8 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -918,6 +918,8 @@ enum { OCL_OP_ADD=0, OCL_OP_SUB=1, OCL_OP_RSUB=2, OCL_OP_ABSDIFF=3, OCL_OP_MUL=4 OCL_OP_AND=9, OCL_OP_OR=10, OCL_OP_XOR=11, OCL_OP_NOT=12, OCL_OP_MIN=13, OCL_OP_MAX=14, OCL_OP_RDIV_SCALE=15 }; +#ifdef HAVE_OPENCL + static const char* oclop2str[] = { "OP_ADD", "OP_SUB", "OP_RSUB", "OP_ABSDIFF", "OP_MUL", "OP_MUL_SCALE", "OP_DIV_SCALE", "OP_RECIP_SCALE", "OP_ADDW", "OP_AND", "OP_OR", "OP_XOR", "OP_NOT", "OP_MIN", "OP_MAX", "OP_RDIV_SCALE", 0 }; @@ -989,6 +991,7 @@ static bool ocl_binary_op(InputArray _src1, InputArray _src2, OutputArray _dst, return k.run(2, globalsize, 0, false); } +#endif static void binary_op( InputArray _src1, InputArray _src2, OutputArray _dst, InputArray _mask, const BinaryFunc* tab, @@ -1001,16 +1004,19 @@ static void binary_op( InputArray _src1, InputArray _src2, OutputArray _dst, int dims1 = psrc1->dims(), dims2 = psrc2->dims(); Size sz1 = dims1 <= 2 ? psrc1->size() : Size(); Size sz2 = dims2 <= 2 ? psrc2->size() : Size(); +#ifdef HAVE_OPENCL bool use_opencl = (kind1 == _InputArray::UMAT || kind2 == _InputArray::UMAT) && - ocl::useOpenCL() && dims1 <= 2 && dims2 <= 2; + dims1 <= 2 && dims2 <= 2; +#endif bool haveMask = !_mask.empty(), haveScalar = false; BinaryFunc func; if( dims1 <= 2 && dims2 <= 2 && kind1 == kind2 && sz1 == sz2 && type1 == type2 && !haveMask ) { _dst.create(sz1, type1); - if( use_opencl && ocl_binary_op(*psrc1, *psrc2, _dst, _mask, bitwise, oclop, false) ) - return; + CV_OCL_RUN(use_opencl, + ocl_binary_op(*psrc1, *psrc2, _dst, _mask, bitwise, oclop, false)) + if( bitwise ) { func = *tab; @@ -1077,8 +1083,9 @@ static void binary_op( InputArray _src1, InputArray _src2, OutputArray _dst, if( haveMask && reallocate ) _dst.setTo(0.); - if( use_opencl && ocl_binary_op(*psrc1, *psrc2, _dst, _mask, bitwise, oclop, haveScalar )) - return; + CV_OCL_RUN(use_opencl, + ocl_binary_op(*psrc1, *psrc2, _dst, _mask, bitwise, oclop, haveScalar)) + Mat src1 = psrc1->getMat(), src2 = psrc2->getMat(); Mat dst = _dst.getMat(), mask = _mask.getMat(); @@ -1089,9 +1096,7 @@ static void binary_op( InputArray _src1, InputArray _src2, OutputArray _dst, cn = (int)esz; } else - { func = tab[depth1]; - } if( !haveScalar ) { @@ -1278,6 +1283,7 @@ static int actualScalarDepth(const double* data, int len) CV_32S; } +#ifdef HAVE_OPENCL static bool ocl_arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, InputArray _mask, int wtype, @@ -1395,6 +1401,7 @@ static bool ocl_arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, return k.run(2, globalsize, NULL, false); } +#endif static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, InputArray _mask, int dtype, BinaryFunc* tab, bool muldiv=false, @@ -1409,7 +1416,9 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, int wtype, dims1 = psrc1->dims(), dims2 = psrc2->dims(); Size sz1 = dims1 <= 2 ? psrc1->size() : Size(); Size sz2 = dims2 <= 2 ? psrc2->size() : Size(); - bool use_opencl = _dst.isUMat() && ocl::useOpenCL() && dims1 <= 2 && dims2 <= 2; +#ifdef HAVE_OPENCL + bool use_opencl = _dst.isUMat() && dims1 <= 2 && dims2 <= 2; +#endif bool src1Scalar = checkScalar(*psrc1, type2, kind1, kind2); bool src2Scalar = checkScalar(*psrc2, type1, kind2, kind1); @@ -1419,11 +1428,10 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, ((src1Scalar && src2Scalar) || (!src1Scalar && !src2Scalar)) ) { _dst.createSameSize(*psrc1, type1); - if( use_opencl && + CV_OCL_RUN(use_opencl, ocl_arithm_op(*psrc1, *psrc2, _dst, _mask, (!usrdata ? type1 : std::max(depth1, CV_32F)), usrdata, oclop, false)) - return; Mat src1 = psrc1->getMat(), src2 = psrc2->getMat(), dst = _dst.getMat(); Size sz = getContinuousSize(src1, src2, dst, src1.channels()); @@ -1520,10 +1528,9 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, if( reallocate ) _dst.setTo(0.); - if( use_opencl && - ocl_arithm_op(*psrc1, *psrc2, _dst, _mask, wtype, - usrdata, oclop, haveScalar)) - return; + CV_OCL_RUN(use_opencl, + ocl_arithm_op(*psrc1, *psrc2, _dst, _mask, wtype, + usrdata, oclop, haveScalar)) BinaryFunc cvtsrc1 = type1 == wtype ? 0 : getConvertFunc(type1, wtype); BinaryFunc cvtsrc2 = type2 == type1 ? cvtsrc1 : type2 == wtype ? 0 : getConvertFunc(type2, wtype); @@ -2600,6 +2607,8 @@ static double getMaxVal(int depth) return tab[depth]; } +#ifdef HAVE_OPENCL + static bool ocl_compare(InputArray _src1, InputArray _src2, OutputArray _dst, int op) { if ( !((_src1.isMat() || _src1.isUMat()) && (_src2.isMat() || _src2.isUMat())) ) @@ -2636,6 +2645,8 @@ static bool ocl_compare(InputArray _src1, InputArray _src2, OutputArray _dst, in return k.run(2, globalsize, NULL, false); } +#endif + } void cv::compare(InputArray _src1, InputArray _src2, OutputArray _dst, int op) @@ -2643,9 +2654,8 @@ void cv::compare(InputArray _src1, InputArray _src2, OutputArray _dst, int op) CV_Assert( op == CMP_LT || op == CMP_LE || op == CMP_EQ || op == CMP_NE || op == CMP_GE || op == CMP_GT ); - if (ocl::useOpenCL() && _src1.dims() <= 2 && _src2.dims() <= 2 && _dst.isUMat() && - ocl_compare(_src1, _src2, _dst, op)) - return; + CV_OCL_RUN(_src1.dims() <= 2 && _src2.dims() <= 2 && _dst.isUMat(), + ocl_compare(_src1, _src2, _dst, op)) int kind1 = _src1.kind(), kind2 = _src2.kind(); Mat src1 = _src1.getMat(), src2 = _src2.getMat(); @@ -2877,6 +2887,8 @@ static InRangeFunc getInRangeFunc(int depth) return inRangeTab[depth]; } +#ifdef HAVE_OPENCL + static bool ocl_inRange( InputArray _src, InputArray _lowerb, InputArray _upperb, OutputArray _dst ) { @@ -2983,14 +2995,16 @@ static bool ocl_inRange( InputArray _src, InputArray _lowerb, return ker.run(2, globalsize, NULL, false); } +#endif + } void cv::inRange(InputArray _src, InputArray _lowerb, InputArray _upperb, OutputArray _dst) { - if (ocl::useOpenCL() && _src.dims() <= 2 && _lowerb.dims() <= 2 && - _upperb.dims() <= 2 && _dst.isUMat() && ocl_inRange(_src, _lowerb, _upperb, _dst)) - return; + CV_OCL_RUN(_src.dims() <= 2 && _lowerb.dims() <= 2 && + _upperb.dims() <= 2 && _dst.isUMat(), + ocl_inRange(_src, _lowerb, _upperb, _dst)) int skind = _src.kind(), lkind = _lowerb.kind(), ukind = _upperb.kind(); Mat src = _src.getMat(), lb = _lowerb.getMat(), ub = _upperb.getMat(); diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 4558d09d9..25ab93dfa 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -264,6 +264,8 @@ void cv::split(const Mat& src, Mat* mv) } } +#ifdef HAVE_OPENCL + namespace cv { static bool ocl_split( InputArray _m, OutputArrayOfArrays _mv ) @@ -302,11 +304,12 @@ static bool ocl_split( InputArray _m, OutputArrayOfArrays _mv ) } +#endif + void cv::split(InputArray _m, OutputArrayOfArrays _mv) { - if (ocl::useOpenCL() && _m.dims() <= 2 && _mv.isUMatVector() && - ocl_split(_m, _mv)) - return; + CV_OCL_RUN(_m.dims() <= 2 && _mv.isUMatVector(), + ocl_split(_m, _mv)) Mat m = _m.getMat(); if( m.empty() ) @@ -395,6 +398,8 @@ void cv::merge(const Mat* mv, size_t n, OutputArray _dst) } } +#ifdef HAVE_OPENCL + namespace cv { static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst ) @@ -442,10 +447,12 @@ static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst ) } +#endif + void cv::merge(InputArrayOfArrays _mv, OutputArray _dst) { - if (ocl::useOpenCL() && _mv.isUMatVector() && _dst.isUMat() && ocl_merge(_mv, _dst)) - return; + CV_OCL_RUN(_mv.isUMatVector() && _dst.isUMat(), + ocl_merge(_mv, _dst)) std::vector mv; _mv.getMatVector(mv); @@ -612,6 +619,8 @@ void cv::mixChannels( const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, cons } } +#ifdef HAVE_OPENCL + namespace cv { static void getUMatIndex(const std::vector & um, int cn, int & idx, int & cnidx) @@ -701,15 +710,16 @@ static bool ocl_mixChannels(InputArrayOfArrays _src, InputOutputArrayOfArrays _d } +#endif + void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, const int* fromTo, size_t npairs) { if (npairs == 0 || fromTo == NULL) return; - if (ocl::useOpenCL() && src.isUMatVector() && dst.isUMatVector() && - ocl_mixChannels(src, dst, fromTo, npairs)) - return; + CV_OCL_RUN(src.isUMatVector() && dst.isUMatVector(), + ocl_mixChannels(src, dst, fromTo, npairs)) bool src_is_mat = src.kind() != _InputArray::STD_VECTOR_MAT && src.kind() != _InputArray::STD_VECTOR_VECTOR && @@ -737,9 +747,8 @@ void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, if (fromTo.empty()) return; - if (ocl::useOpenCL() && src.isUMatVector() && dst.isUMatVector() && - ocl_mixChannels(src, dst, &fromTo[0], fromTo.size()>>1)) - return; + CV_OCL_RUN(src.isUMatVector() && dst.isUMatVector(), + ocl_mixChannels(src, dst, &fromTo[0], fromTo.size()>>1)) bool src_is_mat = src.kind() != _InputArray::STD_VECTOR_MAT && src.kind() != _InputArray::STD_VECTOR_VECTOR && @@ -1284,6 +1293,8 @@ static BinaryFunc getConvertScaleFunc(int sdepth, int ddepth) return cvtScaleTab[CV_MAT_DEPTH(ddepth)][CV_MAT_DEPTH(sdepth)]; } +#ifdef HAVE_OPENCL + static bool ocl_convertScaleAbs( InputArray _src, OutputArray _dst, double alpha, double beta ) { int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); @@ -1319,13 +1330,14 @@ static bool ocl_convertScaleAbs( InputArray _src, OutputArray _dst, double alpha return k.run(2, globalsize, NULL, false); } +#endif + } void cv::convertScaleAbs( InputArray _src, OutputArray _dst, double alpha, double beta ) { - if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() && - ocl_convertScaleAbs(_src, _dst, alpha, beta)) - return; + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_convertScaleAbs(_src, _dst, alpha, beta)) Mat src = _src.getMat(); int cn = src.channels(); @@ -1462,9 +1474,7 @@ static LUTFunc lutTab[] = (LUTFunc)LUT8u_32s, (LUTFunc)LUT8u_32f, (LUTFunc)LUT8u_64f, 0 }; -} - -namespace cv { +#ifdef HAVE_OPENCL static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst) { @@ -1489,7 +1499,9 @@ static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst) return k.run(2, globalSize, NULL, false); } -} // cv +#endif + +} void cv::LUT( InputArray _src, InputArray _lut, OutputArray _dst ) { @@ -1500,8 +1512,8 @@ void cv::LUT( InputArray _src, InputArray _lut, OutputArray _dst ) _lut.total() == 256 && _lut.isContinuous() && (depth == CV_8U || depth == CV_8S) ); - if (ocl::useOpenCL() && _dst.isUMat() && ocl_LUT(_src, _lut, _dst)) - return; + CV_OCL_RUN(_dst.isUMat(), + ocl_LUT(_src, _lut, _dst)) Mat src = _src.getMat(), lut = _lut.getMat(); _dst.create(src.dims, src.size, CV_MAKETYPE(_lut.depth(), cn)); @@ -1521,6 +1533,8 @@ void cv::LUT( InputArray _src, InputArray _lut, OutputArray _dst ) namespace cv { +#ifdef HAVE_OPENCL + static bool ocl_normalize( InputArray _src, OutputArray _dst, InputArray _mask, int rtype, double scale, double shift ) { @@ -1538,6 +1552,8 @@ static bool ocl_normalize( InputArray _src, OutputArray _dst, InputArray _mask, return true; } +#endif + } void cv::normalize( InputArray _src, OutputArray _dst, double a, double b, @@ -1566,9 +1582,8 @@ void cv::normalize( InputArray _src, OutputArray _dst, double a, double b, rtype = _dst.fixedType() ? _dst.depth() : depth; _dst.createSameSize(_src, CV_MAKETYPE(rtype, cn)); - if (ocl::useOpenCL() && _dst.isUMat() && - ocl_normalize(_src, _dst, _mask, rtype, scale, shift)) - return; + CV_OCL_RUN(_dst.isUMat(), + ocl_normalize(_src, _dst, _mask, rtype, scale, shift)) Mat src = _src.getMat(), dst = _dst.getMat(); if( _mask.empty() ) diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index 3a712c4a9..a227aa486 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -475,6 +475,8 @@ flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, } } +#ifdef HAVE_OPENCL + enum { FLIP_COLS = 1 << 0, FLIP_ROWS = 1 << 1, FLIP_BOTH = FLIP_ROWS | FLIP_COLS }; static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode ) @@ -519,13 +521,13 @@ static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode ) return k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), rows, cols).run(2, globalsize, NULL, false); } +#endif + void flip( InputArray _src, OutputArray _dst, int flip_mode ) { CV_Assert( _src.dims() <= 2 ); - bool use_opencl = ocl::useOpenCL() && _dst.isUMat(); - if ( use_opencl && ocl_flip(_src,_dst, flip_mode)) - return; + CV_OCL_RUN( _dst.isUMat(), ocl_flip(_src,_dst, flip_mode)) Mat src = _src.getMat(); _dst.create( src.size(), src.type() ); @@ -541,6 +543,7 @@ void flip( InputArray _src, OutputArray _dst, int flip_mode ) flipHoriz( dst.data, dst.step, dst.data, dst.step, dst.size(), esz ); } +#ifdef HAVE_OPENCL static bool ocl_repeat(InputArray _src, int ny, int nx, OutputArray _dst) { @@ -556,6 +559,8 @@ static bool ocl_repeat(InputArray _src, int ny, int nx, OutputArray _dst) return true; } +#endif + void repeat(InputArray _src, int ny, int nx, OutputArray _dst) { CV_Assert( _src.dims() <= 2 ); @@ -564,11 +569,8 @@ void repeat(InputArray _src, int ny, int nx, OutputArray _dst) Size ssize = _src.size(); _dst.create(ssize.height*ny, ssize.width*nx, _src.type()); - if (ocl::useOpenCL() && _src.isUMat()) - { - CV_Assert(ocl_repeat(_src, ny, nx, _dst)); - return; - } + CV_OCL_RUN(_dst.isUMat(), + ocl_repeat(_src, ny, nx, _dst)) Mat src = _src.getMat(), dst = _dst.getMat(); Size dsize = dst.size(); @@ -768,6 +770,8 @@ void copyMakeConstBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi, } +#ifdef HAVE_OPENCL + namespace cv { static bool ocl_copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom, @@ -824,14 +828,15 @@ static bool ocl_copyMakeBorder( InputArray _src, OutputArray _dst, int top, int } +#endif + void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom, int left, int right, int borderType, const Scalar& value ) { CV_Assert( top >= 0 && bottom >= 0 && left >= 0 && right >= 0 ); - if (ocl::useOpenCL() && _dst.isUMat() && _src.dims() <= 2 && - ocl_copyMakeBorder(_src, _dst, top, bottom, left, right, borderType, value)) - return; + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2, + ocl_copyMakeBorder(_src, _dst, top, bottom, left, right, borderType, value)) Mat src = _src.getMat(); diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index c1f8a54da..e57343038 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -1726,9 +1726,9 @@ static bool ocl_dft(InputArray _src, OutputArray _dst, int flags) void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) { #ifdef HAVE_CLAMDFFT - if (ocl::useOpenCL() && ocl::haveAmdFft() && ocl::Device::getDefault().type() != ocl::Device::TYPE_CPU && - _dst.isUMat() && _src0.dims() <= 2 && nonzero_rows == 0 && ocl_dft(_src0, _dst, flags)) - return; + CV_OCL_RUN(ocl::haveAmdFft() && ocl::Device::getDefault().type() != ocl::Device::TYPE_CPU && + _dst.isUMat() && _src0.dims() <= 2 && nonzero_rows == 0, + ocl_dft(_src0, _dst, flags)) #endif static DFTFunc dft_tbl[6] = @@ -2135,6 +2135,8 @@ void cv::idft( InputArray src, OutputArray dst, int flags, int nonzero_rows ) dft( src, dst, flags | DFT_INVERSE, nonzero_rows ); } +#ifdef HAVE_OPENCL + namespace cv { static bool ocl_mulSpectrums( InputArray _srcA, InputArray _srcB, @@ -2168,12 +2170,13 @@ static bool ocl_mulSpectrums( InputArray _srcA, InputArray _srcB, } +#endif + void cv::mulSpectrums( InputArray _srcA, InputArray _srcB, OutputArray _dst, int flags, bool conjB ) { - if (ocl::useOpenCL() && _dst.isUMat() && + CV_OCL_RUN(_dst.isUMat() && _srcA.dims() <= 2 && _srcB.dims() <= 2, ocl_mulSpectrums(_srcA, _srcB, _dst, flags, conjB)) - return; Mat srcA = _srcA.getMat(), srcB = _srcB.getMat(); int depth = srcA.depth(), cn = srcA.channels(), type = srcA.type(); diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index 3081676f5..c6dde6509 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -785,10 +785,8 @@ void cv::gemm( InputArray matA, InputArray matB, double alpha, InputArray matC, double beta, OutputArray _matD, int flags ) { #ifdef HAVE_CLAMDBLAS - if (ocl::haveAmdBlas() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2 && - ocl::useOpenCL() && _matD.isUMat() && + CV_OCL_RUN(ocl::haveAmdBlas() && matA.dims() <= 2 && matB.dims() <= 2 && matC.dims() <= 2 && _matD.isUMat(), ocl_gemm(matA, matB, alpha, matC, beta, _matD, flags)) - return; #endif const int block_lin_size = 128; @@ -2155,6 +2153,8 @@ static void scaleAdd_64f(const double* src1, const double* src2, double* dst, typedef void (*ScaleAddFunc)(const uchar* src1, const uchar* src2, uchar* dst, int len, const void* alpha); +#ifdef HAVE_OPENCL + static bool ocl_scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray _dst, int type ) { int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), wdepth = std::max(depth, CV_32F); @@ -2190,6 +2190,8 @@ static bool ocl_scaleAdd( InputArray _src1, double alpha, InputArray _src2, Outp return k.run(2, globalsize, NULL, false); } +#endif + } void cv::scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray _dst ) @@ -2197,9 +2199,8 @@ void cv::scaleAdd( InputArray _src1, double alpha, InputArray _src2, OutputArray int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); CV_Assert( type == _src2.type() ); - if (ocl::useOpenCL() && _src1.dims() <= 2 && _src2.dims() <= 2 && _dst.isUMat() && + CV_OCL_RUN(_src1.dims() <= 2 && _src2.dims() <= 2 && _dst.isUMat(), ocl_scaleAdd(_src1, alpha, _src2, _dst, type)) - return; if( depth < CV_32F ) { diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 2d97319e4..b9e55ca7d 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -2522,6 +2522,8 @@ void cv::vconcat(InputArray _src, OutputArray dst) //////////////////////////////////////// set identity //////////////////////////////////////////// +#ifdef HAVE_OPENCL + namespace cv { static bool ocl_setIdentity( InputOutputArray _m, const Scalar& s ) @@ -2544,12 +2546,14 @@ static bool ocl_setIdentity( InputOutputArray _m, const Scalar& s ) } +#endif + void cv::setIdentity( InputOutputArray _m, const Scalar& s ) { CV_Assert( _m.dims() <= 2 ); - if (ocl::useOpenCL() && _m.isUMat() && ocl_setIdentity(_m, s)) - return; + CV_OCL_RUN(_m.isUMat(), + ocl_setIdentity(_m, s)) Mat m = _m.getMat(); int i, j, rows = m.rows, cols = m.cols, type = m.type(); @@ -2728,6 +2732,8 @@ static TransposeInplaceFunc transposeInplaceTab[] = 0, 0, 0, 0, 0, 0, 0, transposeI_32sC6, 0, 0, 0, 0, 0, 0, 0, transposeI_32sC8 }; +#ifdef HAVE_OPENCL + static inline int divUp(int a, int b) { return (a + b - 1) / b; @@ -2769,6 +2775,8 @@ static bool ocl_transpose( InputArray _src, OutputArray _dst ) return k.run(2, globalsize, localsize, false); } +#endif + } void cv::transpose( InputArray _src, OutputArray _dst ) @@ -2776,8 +2784,8 @@ void cv::transpose( InputArray _src, OutputArray _dst ) int type = _src.type(), esz = CV_ELEM_SIZE(type); CV_Assert( _src.dims() <= 2 && esz <= 32 ); - if (ocl::useOpenCL() && _dst.isUMat() && ocl_transpose(_src, _dst)) - return; + CV_OCL_RUN(_dst.isUMat(), + ocl_transpose(_src, _dst)) Mat src = _src.getMat(); if( src.empty() ) @@ -3007,6 +3015,8 @@ typedef void (*ReduceFunc)( const Mat& src, Mat& dst ); #define reduceMinC32f reduceC_ > #define reduceMinC64f reduceC_ > +#ifdef HAVE_OPENCL + namespace cv { static bool ocl_reduce(InputArray _src, OutputArray _dst, @@ -3060,6 +3070,8 @@ static bool ocl_reduce(InputArray _src, OutputArray _dst, } +#endif + void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype) { CV_Assert( _src.dims() <= 2 ); @@ -3074,9 +3086,8 @@ void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype) CV_Assert( op == CV_REDUCE_SUM || op == CV_REDUCE_MAX || op == CV_REDUCE_MIN || op == CV_REDUCE_AVG ); - if (ocl::useOpenCL() && _dst.isUMat() && - ocl_reduce(_src, _dst, dim, op, op0, stype, dtype)) - return; + CV_OCL_RUN(_dst.isUMat(), + ocl_reduce(_src, _dst, dim, op, op0, stype, dtype)) Mat src = _src.getMat(); _dst.create(dim == 0 ? 1 : src.rows, dim == 0 ? src.cols : 1, dtype); diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 4170a7d7a..4484bd5aa 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -464,6 +464,8 @@ template Scalar ocl_part_sum(Mat m) return s; } +#ifdef HAVE_OPENCL + enum { OCL_OP_SUM = 0, OCL_OP_SUM_ABS = 1, OCL_OP_SUM_SQR = 2 }; static bool ocl_sum( InputArray _src, Scalar & res, int sum_op, InputArray _mask = noArray() ) @@ -523,13 +525,17 @@ static bool ocl_sum( InputArray _src, Scalar & res, int sum_op, InputArray _mask return false; } +#endif + } cv::Scalar cv::sum( InputArray _src ) { +#ifdef HAVE_OPENCL Scalar _res; if (ocl::useOpenCL() && _src.isUMat() && ocl_sum(_src, _res, OCL_OP_SUM)) return _res; +#endif Mat src = _src.getMat(); int k, cn = src.channels(), depth = src.depth(); @@ -621,6 +627,8 @@ cv::Scalar cv::sum( InputArray _src ) return s; } +#ifdef HAVE_OPENCL + namespace cv { static bool ocl_countNonZero( InputArray _src, int & res ) @@ -658,13 +666,17 @@ static bool ocl_countNonZero( InputArray _src, int & res ) } +#endif + int cv::countNonZero( InputArray _src ) { CV_Assert( _src.channels() == 1 ); +#ifdef HAVE_OPENCL int res = -1; if (ocl::useOpenCL() && _src.isUMat() && ocl_countNonZero(_src, res)) return res; +#endif Mat src = _src.getMat(); CountNonZeroFunc func = getCountNonZeroTab(src.depth()); @@ -815,6 +827,8 @@ cv::Scalar cv::mean( InputArray _src, InputArray _mask ) return s*(nz0 ? 1./nz0 : 0); } +#ifdef HAVE_OPENCL + namespace cv { static bool ocl_meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray _mask ) @@ -861,10 +875,12 @@ static bool ocl_meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv } +#endif + void cv::meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray _mask ) { - if (ocl::useOpenCL() && _src.isUMat() && ocl_meanStdDev(_src, _mean, _sdv, _mask)) - return; + CV_OCL_RUN(_src.isUMat() && _src.dims() <= 2, + ocl_meanStdDev(_src, _mean, _sdv, _mask)) Mat src = _src.getMat(), mask = _mask.getMat(); CV_Assert( mask.empty() || mask.type() == CV_8U ); @@ -1171,10 +1187,7 @@ static void ofs2idx(const Mat& a, size_t ofs, int* idx) } } -} - -namespace cv -{ +#ifdef HAVE_OPENCL template void getMinMaxRes(const Mat &minv, const Mat &maxv, const Mat &minl, const Mat &maxl, double* minVal, @@ -1288,6 +1301,9 @@ static bool ocl_minMaxIdx( InputArray _src, double* minVal, double* maxVal, int* return true; } + +#endif + } void cv::minMaxIdx(InputArray _src, double* minVal, @@ -1297,9 +1313,8 @@ void cv::minMaxIdx(InputArray _src, double* minVal, CV_Assert( (_src.channels() == 1 && (_mask.empty() || _mask.type() == CV_8U)) || (_src.channels() >= 1 && _mask.empty() && !minIdx && !maxIdx) ); - if( ocl::useOpenCL() && _src.isUMat() && _src.dims() <= 2 && ( _mask.empty() || _src.size() == _mask.size() ) - && ocl_minMaxIdx(_src, minVal, maxVal, minIdx, maxIdx, _mask) ) - return; + CV_OCL_RUN(_src.isUMat() && _src.dims() <= 2 && (_mask.empty() || _src.size() == _mask.size()), + ocl_minMaxIdx(_src, minVal, maxVal, minIdx, maxIdx, _mask)) Mat src = _src.getMat(), mask = _mask.getMat(); int depth = src.depth(), cn = src.channels(); @@ -1892,9 +1907,7 @@ static NormDiffFunc getNormDiffFunc(int normType, int depth) return normDiffTab[normType][depth]; } -} - -namespace cv { +#ifdef HAVE_OPENCL static bool ocl_norm( InputArray _src, int normType, InputArray _mask, double & result ) { @@ -1959,6 +1972,8 @@ static bool ocl_norm( InputArray _src, int normType, InputArray _mask, double & return true; } +#endif + } double cv::norm( InputArray _src, int normType, InputArray _mask ) @@ -1968,9 +1983,11 @@ double cv::norm( InputArray _src, int normType, InputArray _mask ) normType == NORM_L2 || normType == NORM_L2SQR || ((normType == NORM_HAMMING || normType == NORM_HAMMING2) && _src.type() == CV_8U) ); +#ifdef HAVE_OPENCL double _result = 0; if (ocl::useOpenCL() && _src.isUMat() && _src.dims() <= 2 && ocl_norm(_src, normType, _mask, _result)) return _result; +#endif Mat src = _src.getMat(), mask = _mask.getMat(); int depth = src.depth(), cn = src.channels(); @@ -2252,6 +2269,8 @@ double cv::norm( InputArray _src, int normType, InputArray _mask ) return result.d; } +#ifdef HAVE_OPENCL + namespace cv { static bool ocl_norm( InputArray _src1, InputArray _src2, int normType, double & result ) @@ -2293,14 +2312,18 @@ static bool ocl_norm( InputArray _src1, InputArray _src2, int normType, double & } +#endif + double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask ) { CV_Assert( _src1.sameSize(_src2) && _src1.type() == _src2.type() ); +#ifdef HAVE_OPENCL double _result = 0; if (ocl::useOpenCL() && _mask.empty() && _src1.isUMat() && _src2.isUMat() && _src1.dims() <= 2 && _src2.dims() <= 2 && ocl_norm(_src1, _src2, normType, _result)) return _result; +#endif if( normType & CV_RELATIVE ) { From e559256719ea994c86dd59d8691bb748357f548e Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 24 Jan 2014 19:39:05 +0400 Subject: [PATCH 252/295] added cv::GFTTDetector --- .../features2d/include/opencv2/features2d.hpp | 66 ++++++++---------- modules/features2d/src/blobdetector.cpp | 33 +-------- modules/features2d/src/brisk.cpp | 6 +- modules/features2d/src/detectors.cpp | 69 +++++++++++++++---- modules/features2d/src/dynamic.cpp | 10 +-- modules/features2d/src/fast.cpp | 7 +- modules/features2d/src/matchers.cpp | 28 +++++--- modules/features2d/src/mser.cpp | 3 +- modules/features2d/src/orb.cpp | 4 +- modules/features2d/src/stardetector.cpp | 4 +- .../include/opencv2/nonfree/features2d.hpp | 4 +- modules/nonfree/src/sift.cpp | 4 +- modules/nonfree/src/surf.cpp | 4 +- 13 files changed, 128 insertions(+), 114 deletions(-) diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index f43d85f41..8f2d05691 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -108,7 +108,7 @@ public: * mask Mask specifying where to look for keypoints (optional). Must be a char * matrix with non-zero values in the region of interest. */ - CV_WRAP void detect( const Mat& image, CV_OUT std::vector& keypoints, const Mat& mask=Mat() ) const; + CV_WRAP void detect( InputArray image, CV_OUT std::vector& keypoints, InputArray mask=noArray() ) const; /* * Detect keypoints in an image set. @@ -116,7 +116,7 @@ public: * keypoints Collection of keypoints detected in an input images. keypoints[i] is a set of keypoints detected in an images[i]. * masks Masks for image set. masks[i] is a mask for images[i]. */ - void detect( const std::vector& images, std::vector >& keypoints, const std::vector& masks=std::vector() ) const; + void detect( InputArrayOfArrays images, std::vector >& keypoints, InputArrayOfArrays masks=noArray() ) const; // Return true if detector object is empty CV_WRAP virtual bool empty() const; @@ -125,14 +125,14 @@ public: CV_WRAP static Ptr create( const String& detectorType ); protected: - virtual void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const = 0; + virtual void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const = 0; /* * Remove keypoints that are not in the mask. * Helper function, useful when wrapping a library call for keypoint detection that * does not support a mask argument. */ - static void removeInvalidPoints( const Mat& mask, std::vector& keypoints ); + static void removeInvalidPoints( const Mat & mask, std::vector& keypoints ); }; @@ -253,7 +253,7 @@ public: protected: void computeImpl( const Mat& image, std::vector& keypoints, Mat& descriptors ) const; - void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; void computeKeypointsNoOrientation(InputArray image, InputArray mask, std::vector& keypoints) const; void computeDescriptorsAndOrOrientation(InputArray image, InputArray mask, std::vector& keypoints, @@ -338,7 +338,7 @@ public: protected: void computeImpl( const Mat& image, std::vector& keypoints, Mat& descriptors ) const; - void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; CV_PROP_RW int nfeatures; CV_PROP_RW double scaleFactor; @@ -470,7 +470,7 @@ public: AlgorithmInfo* info() const; protected: - void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; int delta; int minArea; @@ -506,7 +506,7 @@ public: AlgorithmInfo* info() const; protected: - void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; int maxSize; int responseThreshold; @@ -535,7 +535,7 @@ public: AlgorithmInfo* info() const; protected: - virtual void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + virtual void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; int threshold; bool nonmaxSuppression; @@ -551,7 +551,7 @@ public: AlgorithmInfo* info() const; protected: - virtual void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + virtual void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; int nfeatures; double qualityLevel; @@ -608,7 +608,7 @@ protected: double confidence; }; - virtual void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + virtual void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; virtual void findBlobs(const Mat &image, const Mat &binaryImage, std::vector

¢ers) const; Params params; @@ -627,7 +627,7 @@ public: AlgorithmInfo* info() const; protected: - virtual void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + virtual void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; double initFeatureScale; int featureScaleLevels; @@ -664,7 +664,7 @@ public: AlgorithmInfo* info() const; protected: - virtual void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + virtual void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; Ptr detector; int maxTotalKeypoints; @@ -686,7 +686,7 @@ public: virtual bool empty() const; protected: - virtual void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + virtual void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; Ptr detector; int maxLevel; @@ -747,7 +747,7 @@ public: virtual bool empty() const; protected: - virtual void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + virtual void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; private: DynamicAdaptedFeatureDetector& operator=(const DynamicAdaptedFeatureDetector&); @@ -776,7 +776,7 @@ public: virtual Ptr clone() const; protected: - virtual void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + virtual void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; int thresh_; bool nonmax_; @@ -799,7 +799,7 @@ public: virtual Ptr clone() const; protected: - virtual void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + virtual void detectImpl(InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; double thresh_, init_thresh_, min_thresh_, max_thresh_; }; @@ -816,7 +816,7 @@ public: virtual Ptr clone() const; protected: - virtual void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const; + virtual void detectImpl( InputArray image, std::vector& keypoints, InputArray mask=noArray() ) const; double thresh_, init_thresh_, min_thresh_, max_thresh_; }; @@ -1035,29 +1035,29 @@ public: */ // Find one best match for each query descriptor (if mask is empty). CV_WRAP void match( InputArray queryDescriptors, InputArray trainDescriptors, - CV_OUT std::vector& matches, InputArray mask=Mat() ) const; + CV_OUT std::vector& matches, InputArray mask=noArray() ) const; // Find k best matches for each query descriptor (in increasing order of distances). // compactResult is used when mask is not empty. If compactResult is false matches // vector will have the same size as queryDescriptors rows. If compactResult is true // matches vector will not contain matches for fully masked out query descriptors. CV_WRAP void knnMatch( InputArray queryDescriptors, InputArray trainDescriptors, CV_OUT std::vector >& matches, int k, - InputArray mask=Mat(), bool compactResult=false ) const; + InputArray mask=noArray(), bool compactResult=false ) const; // Find best matches for each query descriptor which have distance less than // maxDistance (in increasing order of distances). void radiusMatch( InputArray queryDescriptors, InputArray trainDescriptors, std::vector >& matches, float maxDistance, - InputArray mask=Mat(), bool compactResult=false ) const; + InputArray mask=noArray(), bool compactResult=false ) const; /* * Group of methods to match descriptors from one image to image set. * See description of similar methods for matching image pair above. */ CV_WRAP void match( InputArray queryDescriptors, CV_OUT std::vector& matches, - const std::vector& masks=std::vector() ); + const std::vector& masks=std::vector() ); CV_WRAP void knnMatch( InputArray queryDescriptors, CV_OUT std::vector >& matches, int k, - const std::vector& masks=std::vector(), bool compactResult=false ); + const std::vector& masks=std::vector(), bool compactResult=false ); void radiusMatch( InputArray queryDescriptors, std::vector >& matches, float maxDistance, - const std::vector& masks=std::vector(), bool compactResult=false ); + const std::vector& masks=std::vector(), bool compactResult=false ); // Reads matcher object from a file node virtual void read( const FileNode& ); @@ -1102,9 +1102,9 @@ protected: // that the class object has been trained already. Public match methods call these methods // after calling train(). virtual void knnMatchImpl( InputArray queryDescriptors, std::vector >& matches, int k, - InputArrayOfArrays masks=std::vector(), bool compactResult=false ) = 0; + InputArrayOfArrays masks=noArray(), bool compactResult=false ) = 0; virtual void radiusMatchImpl( InputArray queryDescriptors, std::vector >& matches, float maxDistance, - InputArrayOfArrays masks=std::vector(), bool compactResult=false ) = 0; + InputArrayOfArrays masks=noArray(), bool compactResult=false ) = 0; static bool isPossibleMatch( const Mat& mask, int queryIdx, int trainIdx ); static bool isMaskedOut( const std::vector& masks, int queryIdx ); @@ -1139,15 +1139,9 @@ public: AlgorithmInfo* info() const; protected: virtual void knnMatchImpl( InputArray queryDescriptors, std::vector >& matches, int k, - InputArrayOfArrays masks=std::vector(), bool compactResult=false ); + InputArrayOfArrays masks=noArray(), bool compactResult=false ); virtual void radiusMatchImpl( InputArray queryDescriptors, std::vector >& matches, float maxDistance, - InputArrayOfArrays masks=std::vector(), bool compactResult=false ); - - bool ocl_knnMatch(InputArray query, InputArray train, std::vector< std::vector > &matches, - int k, int dstType, bool compactResult=false); - bool ocl_radiusMatch(InputArray query, InputArray train, std::vector< std::vector > &matches, - float maxDistance, int dstType, bool compactResult=false); - bool ocl_match(InputArray query, InputArray train, std::vector< std::vector > &matches, int dstType); + InputArrayOfArrays masks=noArray(), bool compactResult=false ); int normType; bool crossCheck; @@ -1183,9 +1177,9 @@ protected: std::vector >& matches ); virtual void knnMatchImpl( InputArray queryDescriptors, std::vector >& matches, int k, - InputArrayOfArrays masks=std::vector(), bool compactResult=false ); + InputArrayOfArrays masks=noArray(), bool compactResult=false ); virtual void radiusMatchImpl( InputArray queryDescriptors, std::vector >& matches, float maxDistance, - InputArrayOfArrays masks=std::vector(), bool compactResult=false ); + InputArrayOfArrays masks=noArray(), bool compactResult=false ); Ptr indexParams; Ptr searchParams; diff --git a/modules/features2d/src/blobdetector.cpp b/modules/features2d/src/blobdetector.cpp index 92d50ee53..fb7e30fef 100644 --- a/modules/features2d/src/blobdetector.cpp +++ b/modules/features2d/src/blobdetector.cpp @@ -276,7 +276,7 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm #endif } -void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector& keypoints, const cv::Mat&) const +void SimpleBlobDetector::detectImpl(InputArray image, std::vector& keypoints, InputArray) const { //TODO: support mask keypoints.clear(); @@ -284,7 +284,7 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector > centers; for (double thresh = params.minThreshold; thresh < params.maxThreshold; thresh += params.thresholdStep) @@ -292,20 +292,11 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector curCenters; findBlobs(grayscaleImage, binarizedImage, curCenters); std::vector < std::vector
> newCenters; for (size_t i = 0; i < curCenters.size(); i++) { -#ifdef DEBUG_BLOB_DETECTOR - // circle(keypointsImage, curCenters[i].location, curCenters[i].radius, Scalar(0,0,255),-1); -#endif - bool isNew = true; for (size_t j = 0; j < centers.size(); j++) { @@ -327,17 +318,9 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector (1, curCenters[i])); - //centers.push_back(std::vector
(1, curCenters[i])); - } } std::copy(newCenters.begin(), newCenters.end(), std::back_inserter(centers)); - -#ifdef DEBUG_BLOB_DETECTOR - // imshow("binarized", keypointsImage ); - //waitKey(); -#endif } for (size_t i = 0; i < centers.size(); i++) @@ -355,16 +338,4 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector& keypoints, const Mat& mask) const +BRISK::detectImpl( InputArray image, std::vector& keypoints, InputArray mask) const { - (*this)(image, mask, keypoints); + (*this)(image.getMat(), mask.getMat(), keypoints); } void @@ -2229,7 +2229,7 @@ BriskLayer::halfsample(const cv::Mat& srcimg, cv::Mat& dstimg) CV_Assert(srcimg.cols / 2 == dstimg.cols); CV_Assert(srcimg.rows / 2 == dstimg.rows); - // handle non-SSE case + // handle non-SSE case resize(srcimg, dstimg, dstimg.size(), 0, 0, INTER_AREA); } diff --git a/modules/features2d/src/detectors.cpp b/modules/features2d/src/detectors.cpp index 63a882dd3..d3c1f3f20 100644 --- a/modules/features2d/src/detectors.cpp +++ b/modules/features2d/src/detectors.cpp @@ -51,7 +51,7 @@ namespace cv FeatureDetector::~FeatureDetector() {} -void FeatureDetector::detect( const Mat& image, std::vector& keypoints, const Mat& mask ) const +void FeatureDetector::detect( InputArray image, std::vector& keypoints, InputArray mask ) const { keypoints.clear(); @@ -63,11 +63,29 @@ void FeatureDetector::detect( const Mat& image, std::vector& keypoints detectImpl( image, keypoints, mask ); } -void FeatureDetector::detect(const std::vector& imageCollection, std::vector >& pointCollection, const std::vector& masks ) const +void FeatureDetector::detect(InputArrayOfArrays _imageCollection, std::vector >& pointCollection, + InputArrayOfArrays _masks ) const { + if (_imageCollection.isUMatVector()) + { + std::vector uimageCollection, umasks; + _imageCollection.getUMatVector(uimageCollection); + _masks.getUMatVector(umasks); + + pointCollection.resize( uimageCollection.size() ); + for( size_t i = 0; i < uimageCollection.size(); i++ ) + detect( uimageCollection[i], pointCollection[i], umasks.empty() ? noArray() : umasks[i] ); + + return; + } + + std::vector imageCollection, masks; + _imageCollection.getMatVector(imageCollection); + _masks.getMatVector(masks); + pointCollection.resize( imageCollection.size() ); for( size_t i = 0; i < imageCollection.size(); i++ ) - detect( imageCollection[i], pointCollection[i], masks.empty() ? Mat() : masks[i] ); + detect( imageCollection[i], pointCollection[i], masks.empty() ? noArray() : masks[i] ); } /*void FeatureDetector::read( const FileNode& ) @@ -125,21 +143,37 @@ GFTTDetector::GFTTDetector( int _nfeatures, double _qualityLevel, { } -void GFTTDetector::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask) const +void GFTTDetector::detectImpl( InputArray _image, std::vector& keypoints, InputArray _mask) const { - Mat grayImage = image; - if( image.type() != CV_8U ) cvtColor( image, grayImage, COLOR_BGR2GRAY ); - std::vector corners; - goodFeaturesToTrack( grayImage, corners, nfeatures, qualityLevel, minDistance, mask, - blockSize, useHarrisDetector, k ); + + if (_image.isUMat()) + { + UMat ugrayImage; + if( _image.type() != CV_8U ) + cvtColor( _image, ugrayImage, COLOR_BGR2GRAY ); + else + ugrayImage = _image.getUMat(); + + goodFeaturesToTrack( ugrayImage, corners, nfeatures, qualityLevel, minDistance, _mask, + blockSize, useHarrisDetector, k ); + } + else + { + Mat image = _image.getMat(), grayImage = image; + if( image.type() != CV_8U ) + cvtColor( image, grayImage, COLOR_BGR2GRAY ); + + goodFeaturesToTrack( grayImage, corners, nfeatures, qualityLevel, minDistance, _mask, + blockSize, useHarrisDetector, k ); + } + keypoints.resize(corners.size()); std::vector::const_iterator corner_it = corners.begin(); std::vector::iterator keypoint_it = keypoints.begin(); for( ; corner_it != corners.end(); ++corner_it, ++keypoint_it ) - { *keypoint_it = KeyPoint( *corner_it, (float)blockSize ); - } + } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -157,8 +191,10 @@ DenseFeatureDetector::DenseFeatureDetector( float _initFeatureScale, int _featur {} -void DenseFeatureDetector::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask ) const +void DenseFeatureDetector::detectImpl( InputArray _image, std::vector& keypoints, InputArray _mask ) const { + Mat image = _image.getMat(), mask = _mask.getMat(); + float curScale = static_cast(initFeatureScale); int curStep = initXyStep; int curBound = initImgBound; @@ -271,9 +307,9 @@ public: }; } // namepace -void GridAdaptedFeatureDetector::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask ) const +void GridAdaptedFeatureDetector::detectImpl( InputArray _image, std::vector& keypoints, InputArray _mask ) const { - if (image.empty() || maxTotalKeypoints < gridRows * gridCols) + if (_image.empty() || maxTotalKeypoints < gridRows * gridCols) { keypoints.clear(); return; @@ -281,6 +317,8 @@ void GridAdaptedFeatureDetector::detectImpl( const Mat& image, std::vectorempty(); } -void PyramidAdaptedFeatureDetector::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask ) const +void PyramidAdaptedFeatureDetector::detectImpl( InputArray _image, std::vector& keypoints, InputArray _mask ) const { + Mat image = _image.getMat(), mask = _mask.getMat(); Mat src = image; Mat src_mask = mask; diff --git a/modules/features2d/src/dynamic.cpp b/modules/features2d/src/dynamic.cpp index 6bd6ab4de..560005fba 100644 --- a/modules/features2d/src/dynamic.cpp +++ b/modules/features2d/src/dynamic.cpp @@ -54,8 +54,10 @@ bool DynamicAdaptedFeatureDetector::empty() const return !adjuster_ || adjuster_->empty(); } -void DynamicAdaptedFeatureDetector::detectImpl(const Mat& image, std::vector& keypoints, const Mat& mask) const +void DynamicAdaptedFeatureDetector::detectImpl(InputArray _image, std::vector& keypoints, InputArray _mask) const { + Mat image = _image.getMat(), mask = _mask.getMat(); + //for oscillation testing bool down = false; bool up = false; @@ -98,7 +100,7 @@ FastAdjuster::FastAdjuster( int init_thresh, bool nonmax, int min_thresh, int ma min_thresh_(min_thresh), max_thresh_(max_thresh) {} -void FastAdjuster::detectImpl(const Mat& image, std::vector& keypoints, const Mat& mask) const +void FastAdjuster::detectImpl(InputArray image, std::vector& keypoints, InputArray mask) const { FastFeatureDetector(thresh_, nonmax_).detect(image, keypoints, mask); } @@ -133,7 +135,7 @@ StarAdjuster::StarAdjuster(double initial_thresh, double min_thresh, double max_ min_thresh_(min_thresh), max_thresh_(max_thresh) {} -void StarAdjuster::detectImpl(const Mat& image, std::vector& keypoints, const Mat& mask) const +void StarAdjuster::detectImpl(InputArray image, std::vector& keypoints, InputArray mask) const { StarFeatureDetector detector_tmp(16, cvRound(thresh_), 10, 8, 3); detector_tmp.detect(image, keypoints, mask); @@ -167,7 +169,7 @@ SurfAdjuster::SurfAdjuster( double initial_thresh, double min_thresh, double max min_thresh_(min_thresh), max_thresh_(max_thresh) {} -void SurfAdjuster::detectImpl(const Mat& image, std::vector& keypoints, const cv::Mat& mask) const +void SurfAdjuster::detectImpl(InputArray image, std::vector& keypoints, InputArray mask) const { Ptr surf = FeatureDetector::create("SURF"); surf->set("hessianThreshold", thresh_); diff --git a/modules/features2d/src/fast.cpp b/modules/features2d/src/fast.cpp index 9e2181c14..b3335a067 100644 --- a/modules/features2d/src/fast.cpp +++ b/modules/features2d/src/fast.cpp @@ -283,10 +283,11 @@ FastFeatureDetector::FastFeatureDetector( int _threshold, bool _nonmaxSuppressio : threshold(_threshold), nonmaxSuppression(_nonmaxSuppression), type((short)_type) {} -void FastFeatureDetector::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask ) const +void FastFeatureDetector::detectImpl( InputArray _image, std::vector& keypoints, InputArray _mask ) const { - Mat grayImage = image; - if( image.type() != CV_8U ) cvtColor( image, grayImage, COLOR_BGR2GRAY ); + Mat image = _image.getMat(), mask = _mask.getMat(), grayImage = image; + if( image.type() != CV_8U ) + cvtColor( image, grayImage, COLOR_BGR2GRAY ); FAST( grayImage, keypoints, threshold, nonmaxSuppression, type ); KeyPointsFilter::runByPixelsMask( keypoints, mask ); } diff --git a/modules/features2d/src/matchers.cpp b/modules/features2d/src/matchers.cpp index b2001d97e..f8b98d4d6 100644 --- a/modules/features2d/src/matchers.cpp +++ b/modules/features2d/src/matchers.cpp @@ -891,21 +891,25 @@ Ptr BFMatcher::clone( bool emptyTrainData ) const return matcher; } -bool BFMatcher::ocl_match(InputArray query, InputArray _train, std::vector< std::vector > &matches, int dstType) +static bool ocl_match(InputArray query, InputArray _train, std::vector< std::vector > &matches, int dstType) { UMat trainIdx, distance; - if(!ocl_matchSingle(query, _train, trainIdx, distance, dstType)) return false; - if(!ocl_matchDownload(trainIdx, distance, matches)) return false; + if (!ocl_matchSingle(query, _train, trainIdx, distance, dstType)) + return false; + if (!ocl_matchDownload(trainIdx, distance, matches)) + return false; return true; } -bool BFMatcher::ocl_knnMatch(InputArray query, InputArray _train, std::vector< std::vector > &matches, int k, int dstType, bool compactResult) +static bool ocl_knnMatch(InputArray query, InputArray _train, std::vector< std::vector > &matches, int k, int dstType, bool compactResult) { UMat trainIdx, distance; if (k != 2) return false; - if (!ocl_knnMatchSingle(query, _train, trainIdx, distance, dstType)) return false; - if( !ocl_knnMatchDownload(trainIdx, distance, matches, compactResult) ) return false; + if (!ocl_knnMatchSingle(query, _train, trainIdx, distance, dstType)) + return false; + if (!ocl_knnMatchDownload(trainIdx, distance, matches, compactResult) ) + return false; return true; } @@ -1033,12 +1037,14 @@ void BFMatcher::knnMatchImpl( InputArray _queryDescriptors, std::vector > &matches, +static bool ocl_radiusMatch(InputArray query, InputArray _train, std::vector< std::vector > &matches, float maxDistance, int dstType, bool compactResult) { UMat trainIdx, distance, nMatches; - if(!ocl_radiusMatchSingle(query, _train, trainIdx, distance, nMatches, maxDistance, dstType)) return false; - if(!ocl_radiusMatchDownload(trainIdx, distance, nMatches, matches, compactResult)) return false; + if (!ocl_radiusMatchSingle(query, _train, trainIdx, distance, nMatches, maxDistance, dstType)) + return false; + if (!ocl_radiusMatchDownload(trainIdx, distance, nMatches, matches, compactResult)) + return false; return true; } @@ -1076,14 +1082,14 @@ void BFMatcher::radiusMatchImpl( InputArray _queryDescriptors, std::vector >& dstco } -void MserFeatureDetector::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask ) const +void MserFeatureDetector::detectImpl( InputArray _image, std::vector& keypoints, InputArray _mask ) const { + Mat image = _image.getMat(), mask = _mask.getMat(); std::vector > msers; (*this)(image, msers, mask); diff --git a/modules/features2d/src/orb.cpp b/modules/features2d/src/orb.cpp index be06c6984..da5dd5671 100644 --- a/modules/features2d/src/orb.cpp +++ b/modules/features2d/src/orb.cpp @@ -943,9 +943,9 @@ void ORB::operator()( InputArray _image, InputArray _mask, std::vector } } -void ORB::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask) const +void ORB::detectImpl( InputArray image, std::vector& keypoints, InputArray mask) const { - (*this)(image, mask, keypoints, noArray(), false); + (*this)(image.getMat(), mask.getMat(), keypoints, noArray(), false); } void ORB::computeImpl( const Mat& image, std::vector& keypoints, Mat& descriptors) const diff --git a/modules/features2d/src/stardetector.cpp b/modules/features2d/src/stardetector.cpp index 02b999b62..1e00ee604 100644 --- a/modules/features2d/src/stardetector.cpp +++ b/modules/features2d/src/stardetector.cpp @@ -426,9 +426,9 @@ StarDetector::StarDetector(int _maxSize, int _responseThreshold, {} -void StarDetector::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask ) const +void StarDetector::detectImpl( InputArray _image, std::vector& keypoints, InputArray _mask ) const { - Mat grayImage = image; + Mat image = _image.getMat(), mask = _mask.getMat(), grayImage = image; if( image.type() != CV_8U ) cvtColor( image, grayImage, COLOR_BGR2GRAY ); (*this)(grayImage, keypoints); diff --git a/modules/nonfree/include/opencv2/nonfree/features2d.hpp b/modules/nonfree/include/opencv2/nonfree/features2d.hpp index 88a173115..353d1bf79 100644 --- a/modules/nonfree/include/opencv2/nonfree/features2d.hpp +++ b/modules/nonfree/include/opencv2/nonfree/features2d.hpp @@ -87,7 +87,7 @@ public: std::vector& keypoints ) const; protected: - void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask = Mat() ) const; + void detectImpl( InputArray image, std::vector& keypoints, InputArray mask = noArray() ) const; void computeImpl( const Mat& image, std::vector& keypoints, Mat& descriptors ) const; CV_PROP_RW int nfeatures; @@ -143,7 +143,7 @@ public: protected: - void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask = Mat() ) const; + void detectImpl( InputArray image, std::vector& keypoints, InputArray mask = noArray() ) const; void computeImpl( const Mat& image, std::vector& keypoints, Mat& descriptors ) const; }; diff --git a/modules/nonfree/src/sift.cpp b/modules/nonfree/src/sift.cpp index 4a36c2d9f..903221472 100644 --- a/modules/nonfree/src/sift.cpp +++ b/modules/nonfree/src/sift.cpp @@ -818,9 +818,9 @@ void SIFT::operator()(InputArray _image, InputArray _mask, } } -void SIFT::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask) const +void SIFT::detectImpl( InputArray image, std::vector& keypoints, InputArray mask) const { - (*this)(image, mask, keypoints, noArray()); + (*this)(image.getMat(), mask.getMat(), keypoints, noArray()); } void SIFT::computeImpl( const Mat& image, std::vector& keypoints, Mat& descriptors) const diff --git a/modules/nonfree/src/surf.cpp b/modules/nonfree/src/surf.cpp index be8d14d4c..db846bb46 100644 --- a/modules/nonfree/src/surf.cpp +++ b/modules/nonfree/src/surf.cpp @@ -979,9 +979,9 @@ void SURF::operator()(InputArray _img, InputArray _mask, } -void SURF::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask) const +void SURF::detectImpl( InputArray image, std::vector& keypoints, InputArray mask) const { - (*this)(image, mask, keypoints, noArray(), false); + (*this)(image.getMat(), mask.getMat(), keypoints, noArray(), false); } void SURF::computeImpl( const Mat& image, std::vector& keypoints, Mat& descriptors) const From 7184925105d94a0977b0e4949a774d03648dfb90 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 25 Jan 2014 11:50:28 +0400 Subject: [PATCH 253/295] fix --- modules/stitching/perf/opencl/perf_warpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/stitching/perf/opencl/perf_warpers.cpp b/modules/stitching/perf/opencl/perf_warpers.cpp index 4cb014126..8563bc820 100644 --- a/modules/stitching/perf/opencl/perf_warpers.cpp +++ b/modules/stitching/perf/opencl/perf_warpers.cpp @@ -39,7 +39,7 @@ // //M*/ -#include "test_precomp.hpp" +#include "perf_precomp.hpp" #include "opencv2/stitching/warpers.hpp" #include "opencv2/ts/ocl_perf.hpp" From 9968197ebf16ed55671e8f32e8295fdf9affebdb Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 25 Jan 2014 14:44:28 +0400 Subject: [PATCH 254/295] doc fix --- .../doc/common_interfaces_of_descriptor_matchers.rst | 10 +++++----- .../doc/common_interfaces_of_feature_detectors.rst | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst b/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst index ea9e13fa5..9350f6f5c 100644 --- a/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst +++ b/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst @@ -41,7 +41,7 @@ with an image set. :: * Group of methods to match descriptors from an image pair. */ void match( InputArray queryDescriptors, InputArray trainDescriptors, - vector& matches, InputArray mask=Mat() ) const; + vector& matches, InputArray mask=noArray() ) const; void knnMatch( InputArray queryDescriptors, InputArray trainDescriptors, vector >& matches, int k, InputArray mask=Mat(), bool compactResult=false ) const; @@ -52,7 +52,7 @@ with an image set. :: * Group of methods to match descriptors from one image to an image set. */ void match( InputArray queryDescriptors, vector& matches, - const vector& masks=vector() ); + const vector& masks=noArray() ); void knnMatch( InputArray queryDescriptors, vector >& matches, int k, const vector& masks=vector(), bool compactResult=false ); @@ -131,7 +131,7 @@ DescriptorMatcher::match ---------------------------- Finds the best match for each descriptor from a query set. -.. ocv:function:: void DescriptorMatcher::match( InputArray queryDescriptors, InputArray trainDescriptors, vector& matches, InputArray mask=Mat() ) const +.. ocv:function:: void DescriptorMatcher::match( InputArray queryDescriptors, InputArray trainDescriptors, vector& matches, InputArray mask=noArray() ) const .. ocv:function:: void DescriptorMatcher::match(InputArray queryDescriptors, vector& matches, const vector& masks=vector() ) @@ -153,7 +153,7 @@ DescriptorMatcher::knnMatch ------------------------------- Finds the k best matches for each descriptor from a query set. -.. ocv:function:: void DescriptorMatcher::knnMatch(InputArray queryDescriptors, InputArray trainDescriptors, vector >& matches, int k, InputArray mask=Mat(), bool compactResult=false ) const +.. ocv:function:: void DescriptorMatcher::knnMatch(InputArray queryDescriptors, InputArray trainDescriptors, vector >& matches, int k, InputArray mask=noArray(), bool compactResult=false ) const .. ocv:function:: void DescriptorMatcher::knnMatch( InputArray queryDescriptors, vector >& matches, int k, const vector& masks=vector(), bool compactResult=false ) @@ -179,7 +179,7 @@ DescriptorMatcher::radiusMatch ---------------------------------- For each query descriptor, finds the training descriptors not farther than the specified distance. -.. ocv:function:: void DescriptorMatcher::radiusMatch( InputArray queryDescriptors, InputArray trainDescriptors, vector >& matches, float maxDistance, InputArray mask=Mat(), bool compactResult=false ) const +.. ocv:function:: void DescriptorMatcher::radiusMatch( InputArray queryDescriptors, InputArray trainDescriptors, vector >& matches, float maxDistance, InputArray mask=noArray(), bool compactResult=false ) const .. ocv:function:: void DescriptorMatcher::radiusMatch( InputArray queryDescriptors, vector >& matches, float maxDistance, const vector& masks=vector(), bool compactResult=false ) diff --git a/modules/features2d/doc/common_interfaces_of_feature_detectors.rst b/modules/features2d/doc/common_interfaces_of_feature_detectors.rst index 434585d1e..62a99073b 100644 --- a/modules/features2d/doc/common_interfaces_of_feature_detectors.rst +++ b/modules/features2d/doc/common_interfaces_of_feature_detectors.rst @@ -23,12 +23,12 @@ Abstract base class for 2D image feature detectors. :: public: virtual ~FeatureDetector(); - void detect( const Mat& image, vector& keypoints, - const Mat& mask=Mat() ) const; + void detect( InputArray image, vector& keypoints, + InputArray mask=noArray() ) const; - void detect( const vector& images, + void detect( InputArrayOfArrays images, vector >& keypoints, - const vector& masks=vector() ) const; + InputArrayOfArrays masks=noArray() ) const; virtual void read(const FileNode&); virtual void write(FileStorage&) const; @@ -43,9 +43,9 @@ FeatureDetector::detect --------------------------- Detects keypoints in an image (first variant) or image set (second variant). -.. ocv:function:: void FeatureDetector::detect( const Mat& image, vector& keypoints, const Mat& mask=Mat() ) const +.. ocv:function:: void FeatureDetector::detect( InputArray image, vector& keypoints, InputArray mask=noArray() ) const -.. ocv:function:: void FeatureDetector::detect( const vector& images, vector >& keypoints, const vector& masks=vector() ) const +.. ocv:function:: void FeatureDetector::detect( InputArrayOfArrays images, vector >& keypoints, InputArrayOfArrays masks=noArray() ) const .. ocv:pyfunction:: cv2.FeatureDetector_create.detect(image[, mask]) -> keypoints From fa5492343ac8bb40eeb25e72fecb481949d9ab7d Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 25 Jan 2014 00:27:33 +0400 Subject: [PATCH 255/295] added STD_VECTOR_UMAT support to _OutputArray::create --- modules/core/src/matrix.cpp | 59 +++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 338fe6844..2a8a0667c 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -2318,6 +2318,65 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i, return; } + if( k == STD_VECTOR_UMAT ) + { + std::vector& v = *(std::vector*)obj; + + if( i < 0 ) + { + CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) ); + size_t len = sizes[0]*sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0, len0 = v.size(); + + CV_Assert(!fixedSize() || len == len0); + v.resize(len); + if( fixedType() ) + { + int _type = CV_MAT_TYPE(flags); + for( size_t j = len0; j < len; j++ ) + { + if( v[j].type() == _type ) + continue; + CV_Assert( v[j].empty() ); + v[j].flags = (v[j].flags & ~CV_MAT_TYPE_MASK) | _type; + } + } + return; + } + + CV_Assert( i < (int)v.size() ); + UMat& m = v[i]; + + if( allowTransposed ) + { + if( !m.isContinuous() ) + { + CV_Assert(!fixedType() && !fixedSize()); + m.release(); + } + + if( d == 2 && m.dims == 2 && m.u && + m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] ) + return; + } + + if(fixedType()) + { + if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 ) + mtype = m.type(); + else + CV_Assert(!fixedType() || (CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0)); + } + if(fixedSize()) + { + CV_Assert(m.dims == d); + for(int j = 0; j < d; ++j) + CV_Assert(m.size[j] == sizes[j]); + } + + m.create(d, sizes, mtype); + return; + } + CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); } From 2dd294cc84b3e07c82894cb06c5b40b4245006b6 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 25 Jan 2014 00:43:32 +0400 Subject: [PATCH 256/295] fixed cv::split; enabled test --- modules/core/src/convert.cpp | 35 +++++++++++++++++-------- modules/core/test/ocl/test_channels.cpp | 2 +- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 25ab93dfa..37741c399 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -289,10 +289,12 @@ static bool ocl_split( InputArray _m, OutputArrayOfArrays _mv ) return false; Size size = _m.size(); - std::vector & dst = *(std::vector *)_mv.getObj(); - dst.resize(cn); + _mv.create(cn, 1, depth); for (int i = 0; i < cn; ++i) - dst[i].create(size, depth); + _mv.create(size, depth, i); + + std::vector dst; + _mv.getUMatVector(dst); int argidx = k.set(0, ocl::KernelArg::ReadOnly(_m.getUMat())); for (int i = 0; i < cn; ++i) @@ -317,10 +319,19 @@ void cv::split(InputArray _m, OutputArrayOfArrays _mv) _mv.release(); return; } + CV_Assert( !_mv.fixedType() || _mv.empty() || _mv.type() == m.depth() ); - _mv.create(m.channels(), 1, m.depth()); - Mat* dst = &_mv.getMatRef(0); - split(m, dst); + + Size size = m.size(); + int depth = m.depth(), cn = m.channels(); + _mv.create(cn, 1, depth); + for (int i = 0; i < cn; ++i) + _mv.create(size, depth, i); + + std::vector dst; + _mv.getMatVector(dst); + + split(m, &dst[0]); } void cv::merge(const Mat* mv, size_t n, OutputArray _dst) @@ -404,7 +415,8 @@ namespace cv { static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst ) { - const std::vector & src = *(const std::vector *)(_mv.getObj()); + std::vector src; + _mv.getUMatVector(src); CV_Assert(!src.empty()); int type = src[0].type(), depth = CV_MAT_DEPTH(type); @@ -651,8 +663,9 @@ static void getUMatIndex(const std::vector & um, int cn, int & idx, int & static bool ocl_mixChannels(InputArrayOfArrays _src, InputOutputArrayOfArrays _dst, const int* fromTo, size_t npairs) { - const std::vector & src = *(const std::vector *)_src.getObj(); - std::vector & dst = *(std::vector *)_dst.getObj(); + std::vector src, dst; + _src.getUMatVector(src); + _dst.getUMatVector(dst); size_t nsrc = src.size(), ndst = dst.size(); CV_Assert(nsrc > 0 && ndst > 0); @@ -718,7 +731,7 @@ void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, if (npairs == 0 || fromTo == NULL) return; - CV_OCL_RUN(src.isUMatVector() && dst.isUMatVector(), + CV_OCL_RUN(dst.isUMatVector(), ocl_mixChannels(src, dst, fromTo, npairs)) bool src_is_mat = src.kind() != _InputArray::STD_VECTOR_MAT && @@ -747,7 +760,7 @@ void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, if (fromTo.empty()) return; - CV_OCL_RUN(src.isUMatVector() && dst.isUMatVector(), + CV_OCL_RUN(dst.isUMatVector(), ocl_mixChannels(src, dst, &fromTo[0], fromTo.size()>>1)) bool src_is_mat = src.kind() != _InputArray::STD_VECTOR_MAT && diff --git a/modules/core/test/ocl/test_channels.cpp b/modules/core/test/ocl/test_channels.cpp index 09d709e91..f0dc10250 100644 --- a/modules/core/test/ocl/test_channels.cpp +++ b/modules/core/test/ocl/test_channels.cpp @@ -197,7 +197,7 @@ PARAM_TEST_CASE(Split, MatType, Channels, bool) } }; -OCL_TEST_P(Split, DISABLED_Accuracy) +OCL_TEST_P(Split, Accuracy) { for (int j = 0; j < test_loop_times; j++) { From f767077a419c6ff7cf3b931cccb98b451378e004 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 25 Jan 2014 01:58:55 +0400 Subject: [PATCH 257/295] fixed condition --- modules/core/src/matrix.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 2a8a0667c..c74e854f1 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -1193,7 +1193,6 @@ Mat _InputArray::getMat(int i) const return Mat(); } - UMat _InputArray::getUMat(int i) const { int k = kind(); @@ -1226,7 +1225,6 @@ UMat _InputArray::getUMat(int i) const return getMat(i).getUMat(accessFlags); } - void _InputArray::getMatVector(std::vector& mv) const { int k = kind(); @@ -1504,7 +1502,6 @@ Size _InputArray::size(int i) const } } - int _InputArray::sizend(int* arrsz, int i) const { int j, d=0, k = kind(); @@ -1563,7 +1560,6 @@ int _InputArray::sizend(int* arrsz, int i) const return d; } - bool _InputArray::sameSize(const _InputArray& arr) const { int k1 = kind(), k2 = arr.kind(); @@ -2305,7 +2301,7 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i, if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 ) mtype = m.type(); else - CV_Assert(!fixedType() || (CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0)); + CV_Assert(CV_MAT_TYPE(mtype) == m.type()); } if(fixedSize()) { @@ -2364,7 +2360,7 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i, if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 ) mtype = m.type(); else - CV_Assert(!fixedType() || (CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0)); + CV_Assert(CV_MAT_TYPE(mtype) == m.type()); } if(fixedSize()) { From 321782b9b7f20864793fb7383075f8feb7817258 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 27 Jan 2014 12:32:26 +0400 Subject: [PATCH 258/295] added macro with ability of returning values --- .../include/opencv2/core/opencl/ocl_defs.hpp | 12 ++++++---- modules/core/src/stat.cpp | 24 +++++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/modules/core/include/opencv2/core/opencl/ocl_defs.hpp b/modules/core/include/opencv2/core/opencl/ocl_defs.hpp index 6a4fd992c..7a8aed4b8 100644 --- a/modules/core/include/opencv2/core/opencl/ocl_defs.hpp +++ b/modules/core/include/opencv2/core/opencl/ocl_defs.hpp @@ -8,13 +8,13 @@ #ifdef HAVE_OPENCL #ifdef CV_OPENCL_RUN_VERBOSE -#define CV_OCL_RUN(condition, func) \ +#define CV_OCL_RUN_(condition, func, ...) \ { \ if (cv::ocl::useOpenCL() && (condition) && func) \ { \ printf("%s: OpenCL implementation is running\n", CV_Func); \ fflush(stdout); \ - return; \ + return __VA_ARGS__; \ } \ else \ { \ @@ -23,11 +23,13 @@ } \ } #else -#define CV_OCL_RUN(condition, func) \ +#define CV_OCL_RUN_(condition, func, ...) \ if (cv::ocl::useOpenCL() && (condition) && func) \ - return; + return __VA_ARGS__; #endif #else -#define CV_OCL_RUN(condition, func) +#define CV_OCL_RUN_(condition, func, retval) #endif + +#define CV_OCL_RUN(condition, func) CV_OCL_RUN_(condition, func) diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 4484bd5aa..63970c544 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -475,7 +475,7 @@ static bool ocl_sum( InputArray _src, Scalar & res, int sum_op, InputArray _mask int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; - if ( (!doubleSupport && depth == CV_64F) || cn > 4 || cn == 3 || _src.dims() > 2 ) + if ( (!doubleSupport && depth == CV_64F) || cn > 4 || cn == 3 ) return false; int dbsize = ocl::Device::getDefault().maxComputeUnits(); @@ -533,8 +533,9 @@ cv::Scalar cv::sum( InputArray _src ) { #ifdef HAVE_OPENCL Scalar _res; - if (ocl::useOpenCL() && _src.isUMat() && ocl_sum(_src, _res, OCL_OP_SUM)) - return _res; + CV_OCL_RUN_( _src.isUMat() && _src.dims() <= 2, + ocl_sum(_src, _res, OCL_OP_SUM), + _res) #endif Mat src = _src.getMat(); @@ -674,8 +675,9 @@ int cv::countNonZero( InputArray _src ) #ifdef HAVE_OPENCL int res = -1; - if (ocl::useOpenCL() && _src.isUMat() && ocl_countNonZero(_src, res)) - return res; + CV_OCL_RUN_(_src.isUMat() && _src.dims() <= 2, + ocl_countNonZero(_src, res), + res) #endif Mat src = _src.getMat(); @@ -1985,8 +1987,9 @@ double cv::norm( InputArray _src, int normType, InputArray _mask ) #ifdef HAVE_OPENCL double _result = 0; - if (ocl::useOpenCL() && _src.isUMat() && _src.dims() <= 2 && ocl_norm(_src, normType, _mask, _result)) - return _result; + CV_OCL_RUN_(_src.isUMat() && _src.dims() <= 2, + ocl_norm(_src, normType, _mask, _result), + _result) #endif Mat src = _src.getMat(), mask = _mask.getMat(); @@ -2320,9 +2323,10 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m #ifdef HAVE_OPENCL double _result = 0; - if (ocl::useOpenCL() && _mask.empty() && _src1.isUMat() && _src2.isUMat() && - _src1.dims() <= 2 && _src2.dims() <= 2 && ocl_norm(_src1, _src2, normType, _result)) - return _result; + CV_OCL_RUN_(_mask.empty() && _src1.isUMat() && _src2.isUMat() && + _src1.dims() <= 2 && _src2.dims() <= 2, + ocl_norm(_src1, _src2, normType, _result), + _result) #endif if( normType & CV_RELATIVE ) From c8f2050cc2801b968924629df330423bf0e8957f Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 27 Jan 2014 12:34:30 +0400 Subject: [PATCH 259/295] warn fix --- modules/ocl/test/test_brief.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ocl/test/test_brief.cpp b/modules/ocl/test/test_brief.cpp index 369e6b53b..8ca2c90c7 100644 --- a/modules/ocl/test/test_brief.cpp +++ b/modules/ocl/test/test_brief.cpp @@ -80,7 +80,7 @@ OCL_TEST_P( BRIEF, Accuracy ) brief.compute( img, keypoints, descriptorsGold ); Mat kpMat( 2, int( keypoints.size() ), CV_32FC1 ); - for ( size_t i = 0; i < keypoints.size( ); ++i ) + for ( int i = 0, size = (int)keypoints.size( ); i < size; ++i ) { kpMat.col( i ).row( 0 ) = int( keypoints[i].pt.x ); kpMat.col( i ).row( 1 ) = int( keypoints[i].pt.y ); @@ -112,4 +112,4 @@ OCL_TEST_P( BRIEF, Accuracy ) } INSTANTIATE_TEST_CASE_P( OCL_Features2D, BRIEF, testing::Values( 16, 32, 64 ) ); -#endif \ No newline at end of file +#endif From 1ff9a8ef52308692da7038f4fe6ab842d8c066a1 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 27 Jan 2014 13:38:47 +0400 Subject: [PATCH 260/295] core/ocl: added warning about incompatible configuration --- .../core/src/opencl/runtime/opencl_clamdblas.cpp | 5 +++++ modules/core/src/opencl/runtime/opencl_clamdfft.cpp | 5 +++++ modules/core/src/opencl/runtime/opencl_core.cpp | 13 +++++++++---- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/modules/core/src/opencl/runtime/opencl_clamdblas.cpp b/modules/core/src/opencl/runtime/opencl_clamdblas.cpp index 1f06446ae..fceda79ac 100644 --- a/modules/core/src/opencl/runtime/opencl_clamdblas.cpp +++ b/modules/core/src/opencl/runtime/opencl_clamdblas.cpp @@ -87,6 +87,11 @@ #endif #ifndef CV_CL_GET_PROC_ADDRESS +#ifdef __GNUC__ +#warning("OPENCV: OpenCL BLAS dynamic library loader: check configuration") +#else +#pragma message("WARNING: OPENCV: OpenCL BLAS dynamic library loader: check configuration") +#endif #define CV_CL_GET_PROC_ADDRESS(name) NULL #endif diff --git a/modules/core/src/opencl/runtime/opencl_clamdfft.cpp b/modules/core/src/opencl/runtime/opencl_clamdfft.cpp index a3a6eff0c..2d8b964d4 100644 --- a/modules/core/src/opencl/runtime/opencl_clamdfft.cpp +++ b/modules/core/src/opencl/runtime/opencl_clamdfft.cpp @@ -87,6 +87,11 @@ #endif #ifndef CV_CL_GET_PROC_ADDRESS +#ifdef __GNUC__ +#warning("OPENCV: OpenCL FFT dynamic library loader: check configuration") +#else +#pragma message("WARNING: OPENCV: OpenCL FFT dynamic library loader: check configuration") +#endif #define CV_CL_GET_PROC_ADDRESS(name) NULL #endif diff --git a/modules/core/src/opencl/runtime/opencl_core.cpp b/modules/core/src/opencl/runtime/opencl_core.cpp index fb82c0d93..df91f9284 100644 --- a/modules/core/src/opencl/runtime/opencl_core.cpp +++ b/modules/core/src/opencl/runtime/opencl_core.cpp @@ -47,7 +47,7 @@ #include "opencv2/core/opencl/runtime/opencl_core.hpp" -static const char* funcToCheckOpenCL1_1 = "clEnqueueReadBufferRect"; +#define OPENCL_FUNC_TO_CHECK_1_1 "clEnqueueReadBufferRect" #define ERROR_MSG_CANT_LOAD "Failed to load OpenCL runtime\n" #define ERROR_MSG_INVALID_VERSION "Failed to load OpenCL runtime (expected version 1.1+)\n" @@ -72,7 +72,7 @@ static void* AppleCLGetProcAddress(const char* name) { fprintf(stderr, ERROR_MSG_CANT_LOAD); } - else if (dlsym(handle, funcToCheckOpenCL1_1) == NULL) + else if (dlsym(handle, OPENCL_FUNC_TO_CHECK_1_1) == NULL) { fprintf(stderr, ERROR_MSG_INVALID_VERSION); handle = NULL; @@ -110,7 +110,7 @@ static void* WinGetProcAddress(const char* name) { fprintf(stderr, ERROR_MSG_CANT_LOAD); } - else if (GetProcAddress(handle, funcToCheckOpenCL1_1) == NULL) + else if (GetProcAddress(handle, OPENCL_FUNC_TO_CHECK_1_1) == NULL) { fprintf(stderr, ERROR_MSG_INVALID_VERSION); handle = NULL; @@ -147,7 +147,7 @@ static void* GetProcAddress(const char* name) { fprintf(stderr, ERROR_MSG_CANT_LOAD); } - else if (dlsym(handle, funcToCheckOpenCL1_1) == NULL) + else if (dlsym(handle, OPENCL_FUNC_TO_CHECK_1_1) == NULL) { fprintf(stderr, ERROR_MSG_INVALID_VERSION); handle = NULL; @@ -162,6 +162,11 @@ static void* GetProcAddress(const char* name) #endif #ifndef CV_CL_GET_PROC_ADDRESS +#ifdef __GNUC__ +#warning("OPENCV: OpenCL dynamic library loader: check configuration") +#else +#pragma message("WARNING: OPENCV: OpenCL dynamic library loader: check configuration") +#endif #define CV_CL_GET_PROC_ADDRESS(name) NULL #endif From 6a511755b2a6a9b267b377b460ba6885ce41cce9 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Mon, 27 Jan 2014 17:39:33 +0400 Subject: [PATCH 261/295] Fixed build for samples/cpp/train_HOG.cpp. get_hogdescriptor_visu is passed img->clone(), which is not usable as a non-const reference (and it doesn't modify the argument, anyway). --- samples/cpp/train_HOG.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/cpp/train_HOG.cpp b/samples/cpp/train_HOG.cpp index 3f21206a1..e3ee190fc 100644 --- a/samples/cpp/train_HOG.cpp +++ b/samples/cpp/train_HOG.cpp @@ -14,7 +14,7 @@ void get_svm_detector(const SVM& svm, vector< float > & hog_detector ); void convert_to_ml(const std::vector< cv::Mat > & train_samples, cv::Mat& trainData ); void load_images( const string & prefix, const string & filename, vector< Mat > & img_lst ); void sample_neg( const vector< Mat > & full_neg_lst, vector< Mat > & neg_lst, const Size & size ); -Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, const Size & size ); +Mat get_hogdescriptor_visu(const Mat& color_origImg, vector& descriptorValues, const Size & size ); void compute_hog( const vector< Mat > & img_lst, vector< Mat > & gradient_lst, const Size & size ); void train_svm( const vector< Mat > & gradient_lst, const vector< int > & labels ); void draw_locations( Mat & img, const vector< Rect > & locations, const Scalar & color ); @@ -155,7 +155,7 @@ void sample_neg( const vector< Mat > & full_neg_lst, vector< Mat > & neg_lst, co } // From http://www.juergenwiki.de/work/wiki/doku.php?id=public:hog_descriptor_computation_and_visualization -Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, const Size & size ) +Mat get_hogdescriptor_visu(const Mat& color_origImg, vector& descriptorValues, const Size & size ) { const int DIMX = size.width; const int DIMY = size.height; From 48a084c236c261668cf9cbd2b583a9b6d4bf3583 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 27 Jan 2014 18:34:19 +0400 Subject: [PATCH 262/295] OpenCL version of cv::buildPyramid --- modules/core/include/opencv2/core/mat.hpp | 1 + modules/core/src/matrix.cpp | 17 ++++++++++++ modules/imgproc/perf/opencl/perf_pyramid.cpp | 29 ++++++++++++++++++++ modules/imgproc/src/pyramids.cpp | 10 +++++++ 4 files changed, 57 insertions(+) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 6c09efdf8..dcbac6b43 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -207,6 +207,7 @@ public: virtual bool fixedType() const; virtual bool needed() const; virtual Mat& getMatRef(int i=-1) const; + virtual UMat& getUMatRef(int i=-1) const; virtual cuda::GpuMat& getGpuMatRef() const; virtual ogl::Buffer& getOGlBufferRef() const; virtual cuda::CudaMem& getCudaMemRef() const; diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index c74e854f1..0f15ac1d6 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -2484,6 +2484,23 @@ Mat& _OutputArray::getMatRef(int i) const } } +UMat& _OutputArray::getUMatRef(int i) const +{ + int k = kind(); + if( i < 0 ) + { + CV_Assert( k == UMAT ); + return *(UMat*)obj; + } + else + { + CV_Assert( k == STD_VECTOR_UMAT ); + std::vector& v = *(std::vector*)obj; + CV_Assert( i < (int)v.size() ); + return v[i]; + } +} + cuda::GpuMat& _OutputArray::getGpuMatRef() const { int k = kind(); diff --git a/modules/imgproc/perf/opencl/perf_pyramid.cpp b/modules/imgproc/perf/opencl/perf_pyramid.cpp index 4beba2280..55bb0679b 100644 --- a/modules/imgproc/perf/opencl/perf_pyramid.cpp +++ b/modules/imgproc/perf/opencl/perf_pyramid.cpp @@ -100,6 +100,35 @@ OCL_PERF_TEST_P(PyrUpFixture, PyrUp, SANITY_CHECK(dst, eps); } +///////////// buildPyramid //////////////////////// + +typedef Size_MatType BuildPyramidFixture; + +OCL_PERF_TEST_P(BuildPyramidFixture, BuildPyramid, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + const Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params), maxLevel = 5; + const double eps = CV_MAT_DEPTH(type) <= CV_32S ? 1 : 1e-5; + + checkDeviceMaxMemoryAllocSize(srcSize, type); + + std::vector dst(maxLevel); + UMat src(srcSize, type); + declare.in(src, WARMUP_RNG); + + OCL_TEST_CYCLE() cv::buildPyramid(src, dst, maxLevel); + + UMat dst0 = dst[0], dst1 = dst[1], dst2 = dst[2], dst3 = dst[3], dst4 = dst[4]; + + SANITY_CHECK(dst0, eps); + SANITY_CHECK(dst1, eps); + SANITY_CHECK(dst2, eps); + SANITY_CHECK(dst3, eps); + SANITY_CHECK(dst4, eps); +} + } } // namespace cvtest::ocl #endif // HAVE_OPENCL diff --git a/modules/imgproc/src/pyramids.cpp b/modules/imgproc/src/pyramids.cpp index 6802e9eeb..24d7ef950 100644 --- a/modules/imgproc/src/pyramids.cpp +++ b/modules/imgproc/src/pyramids.cpp @@ -556,6 +556,16 @@ void cv::pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int borderT void cv::buildPyramid( InputArray _src, OutputArrayOfArrays _dst, int maxlevel, int borderType ) { + if (_src.dims() <= 2 && _dst.isUMatVector()) + { + UMat src = _src.getUMat(); + _dst.create( maxlevel + 1, 1, 0 ); + _dst.getUMatRef(0) = src; + for( int i = 1; i <= maxlevel; i++ ) + pyrDown( _dst.getUMatRef(i-1), _dst.getUMatRef(i), Size(), borderType ); + return; + } + Mat src = _src.getMat(); _dst.create( maxlevel + 1, 1, 0 ); _dst.getMatRef(0) = src; From 78c2b3ca2a30d66ddc0320248cf79b89c2dfb028 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 27 Jan 2014 13:25:21 +0400 Subject: [PATCH 263/295] refactored imgproc --- .../include/opencv2/core/opencl/ocl_defs.hpp | 2 +- modules/imgproc/src/blend.cpp | 8 +- modules/imgproc/src/canny.cpp | 9 +- modules/imgproc/src/clahe.cpp | 19 +- modules/imgproc/src/color.cpp | 8 +- modules/imgproc/src/corner.cpp | 19 +- modules/imgproc/src/featureselect.cpp | 9 +- modules/imgproc/src/filter.cpp | 18 +- modules/imgproc/src/histogram.cpp | 24 +- modules/imgproc/src/imgwarp.cpp | 33 +- modules/imgproc/src/moments.cpp | 6 + modules/imgproc/src/morph.cpp | 21 +- modules/imgproc/src/pyramids.cpp | 14 +- modules/imgproc/src/smooth.cpp | 81 +-- modules/imgproc/src/sumpixels.cpp | 14 +- modules/imgproc/src/templmatch.cpp | 617 +++++++++--------- modules/imgproc/src/thresh.cpp | 9 +- 17 files changed, 479 insertions(+), 432 deletions(-) diff --git a/modules/core/include/opencv2/core/opencl/ocl_defs.hpp b/modules/core/include/opencv2/core/opencl/ocl_defs.hpp index 7a8aed4b8..1c5ca58c1 100644 --- a/modules/core/include/opencv2/core/opencl/ocl_defs.hpp +++ b/modules/core/include/opencv2/core/opencl/ocl_defs.hpp @@ -29,7 +29,7 @@ #endif #else -#define CV_OCL_RUN_(condition, func, retval) +#define CV_OCL_RUN_(condition, func, ...) #endif #define CV_OCL_RUN(condition, func) CV_OCL_RUN_(condition, func) diff --git a/modules/imgproc/src/blend.cpp b/modules/imgproc/src/blend.cpp index 91b261dfa..4fbdff9c3 100644 --- a/modules/imgproc/src/blend.cpp +++ b/modules/imgproc/src/blend.cpp @@ -91,6 +91,8 @@ private: Mat * dst; }; +#ifdef HAVE_OPENCL + static bool ocl_blendLinear( InputArray _src1, InputArray _src2, InputArray _weights1, InputArray _weights2, OutputArray _dst ) { int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); @@ -113,6 +115,8 @@ static bool ocl_blendLinear( InputArray _src1, InputArray _src2, InputArray _wei return k.run(2, globalsize, NULL, false); } +#endif + } void cv::blendLinear( InputArray _src1, InputArray _src2, InputArray _weights1, InputArray _weights2, OutputArray _dst ) @@ -126,8 +130,8 @@ void cv::blendLinear( InputArray _src1, InputArray _src2, InputArray _weights1, _dst.create(size, type); - if (ocl::useOpenCL() && _dst.isUMat() && ocl_blendLinear(_src1, _src2, _weights1, _weights2, _dst)) - return; + CV_OCL_RUN(_dst.isUMat(), + ocl_blendLinear(_src1, _src2, _weights1, _weights2, _dst)) Mat src1 = _src1.getMat(), src2 = _src2.getMat(), weights1 = _weights1.getMat(), weights2 = _weights2.getMat(), dst = _dst.getMat(); diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index b52ca46de..990074d49 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -88,6 +88,8 @@ static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high) } #endif +#ifdef HAVE_OPENCL + static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float high_thresh, int aperture_size, bool L2gradient, int cn, const Size & size) { @@ -230,6 +232,8 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float return getEdgesKernel.run(2, globalsize, NULL, false); } +#endif + } void cv::Canny( InputArray _src, OutputArray _dst, @@ -255,9 +259,8 @@ void cv::Canny( InputArray _src, OutputArray _dst, if (low_thresh > high_thresh) std::swap(low_thresh, high_thresh); - if (ocl::useOpenCL() && _dst.isUMat() && cn == 1 && - ocl_Canny(_src, _dst, (float)low_thresh, (float)high_thresh, aperture_size, L2gradient, cn, size)) - return; + CV_OCL_RUN(_dst.isUMat() && cn == 1, + ocl_Canny(_src, _dst, (float)low_thresh, (float)high_thresh, aperture_size, L2gradient, cn, size)) Mat src = _src.getMat(), dst = _dst.getMat(); diff --git a/modules/imgproc/src/clahe.cpp b/modules/imgproc/src/clahe.cpp index 82474788d..138bf83b5 100644 --- a/modules/imgproc/src/clahe.cpp +++ b/modules/imgproc/src/clahe.cpp @@ -45,6 +45,8 @@ // ---------------------------------------------------------------------- // CLAHE +#ifdef HAVE_OPENCL + namespace clahe { static bool calcLut(cv::InputArray _src, cv::OutputArray _dst, @@ -124,6 +126,8 @@ namespace clahe } } +#endif + namespace { class CLAHE_CalcLut_Body : public cv::ParallelLoopBody @@ -321,9 +325,12 @@ namespace int tilesY_; cv::Mat srcExt_; - cv::UMat usrcExt_; cv::Mat lut_; + +#ifdef HAVE_OPENCL + cv::UMat usrcExt_; cv::UMat ulut_; +#endif }; CLAHE_Impl::CLAHE_Impl(double clipLimit, int tilesX, int tilesY) : @@ -340,7 +347,9 @@ namespace { CV_Assert( _src.type() == CV_8UC1 ); +#ifdef HAVE_OPENCL bool useOpenCL = cv::ocl::useOpenCL() && _src.isUMat() && _src.dims()<=2; +#endif const int histSize = 256; @@ -354,6 +363,7 @@ namespace } else { +#ifdef HAVE_OPENCL if(useOpenCL) { cv::copyMakeBorder(_src, usrcExt_, 0, tilesY_ - (_src.size().height % tilesY_), 0, tilesX_ - (_src.size().width % tilesX_), cv::BORDER_REFLECT_101); @@ -361,6 +371,7 @@ namespace _srcForLut = usrcExt_; } else +#endif { cv::copyMakeBorder(_src, srcExt_, 0, tilesY_ - (_src.size().height % tilesY_), 0, tilesX_ - (_src.size().width % tilesX_), cv::BORDER_REFLECT_101); tileSize = cv::Size(srcExt_.size().width / tilesX_, srcExt_.size().height / tilesY_); @@ -378,9 +389,11 @@ namespace clipLimit = std::max(clipLimit, 1); } - if(useOpenCL && clahe::calcLut(_srcForLut, ulut_, tilesX_, tilesY_, tileSize, clipLimit, lutScale) ) +#ifdef HAVE_OPENCL + if (useOpenCL && clahe::calcLut(_srcForLut, ulut_, tilesX_, tilesY_, tileSize, clipLimit, lutScale) ) if( clahe::transform(_src, _dst, ulut_, tilesX_, tilesY_, tileSize) ) return; +#endif cv::Mat src = _src.getMat(); _dst.create( src.size(), src.type() ); @@ -420,8 +433,10 @@ namespace { srcExt_.release(); lut_.release(); +#ifdef HAVE_OPENCL usrcExt_.release(); ulut_.release(); +#endif } } diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index e698690ab..8d06c46c5 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -2688,6 +2688,7 @@ struct mRGBA2RGBA } }; +#ifdef HAVE_OPENCL static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) { @@ -3041,6 +3042,8 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) return ok; } +#endif + }//namespace cv ////////////////////////////////////////////////////////////////////////////////////////// @@ -3049,12 +3052,11 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) { - bool use_opencl = ocl::useOpenCL() && _dst.kind() == _InputArray::UMAT; int stype = _src.type(); int scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype), bidx; - if( use_opencl && ocl_cvtColor(_src, _dst, code, dcn) ) - return; + CV_OCL_RUN( _src.dims() <= 2 && _dst.isUMat(), + ocl_cvtColor(_src, _dst, code, dcn) ) Mat src = _src.getMat(), dst; Size sz = src.size(); diff --git a/modules/imgproc/src/corner.cpp b/modules/imgproc/src/corner.cpp index fe7648191..172a531a3 100644 --- a/modules/imgproc/src/corner.cpp +++ b/modules/imgproc/src/corner.cpp @@ -302,6 +302,8 @@ cornerEigenValsVecs( const Mat& src, Mat& eigenv, int block_size, calcEigenValsVecs( cov, eigenv ); } +#ifdef HAVE_OPENCL + static bool ocl_cornerMinEigenValVecs(InputArray _src, OutputArray _dst, int block_size, int aperture_size, double k, int borderType, int op_type) { @@ -393,13 +395,14 @@ static bool ocl_preCornerDetect( InputArray _src, OutputArray _dst, int ksize, i return k.run(2, globalsize, NULL, false); } +#endif + } void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType ) { - if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() && - ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, 0.0, borderType, MINEIGENVAL)) - return; + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, 0.0, borderType, MINEIGENVAL)) Mat src = _src.getMat(); _dst.create( src.size(), CV_32FC1 ); @@ -410,9 +413,8 @@ void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, in void cv::cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksize, double k, int borderType ) { - if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() && - ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, k, borderType, HARRIS)) - return; + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, k, borderType, HARRIS)) Mat src = _src.getMat(); _dst.create( src.size(), CV_32FC1 ); @@ -439,9 +441,8 @@ void cv::preCornerDetect( InputArray _src, OutputArray _dst, int ksize, int bord int type = _src.type(); CV_Assert( type == CV_8UC1 || type == CV_32FC1 ); - if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() && - ocl_preCornerDetect(_src, _dst, ksize, borderType, CV_MAT_DEPTH(type))) - return; + CV_OCL_RUN( _src.dims() <= 2 && _dst.isUMat(), + ocl_preCornerDetect(_src, _dst, ksize, borderType, CV_MAT_DEPTH(type))) Mat Dx, Dy, D2x, D2y, Dxy, src = _src.getMat(); _dst.create( src.size(), CV_32FC1 ); diff --git a/modules/imgproc/src/featureselect.cpp b/modules/imgproc/src/featureselect.cpp index c8b65b1ef..ff923a3e9 100644 --- a/modules/imgproc/src/featureselect.cpp +++ b/modules/imgproc/src/featureselect.cpp @@ -66,6 +66,8 @@ struct Corner { return val > c.val; } }; +#ifdef HAVE_OPENCL + static bool ocl_goodFeaturesToTrack( InputArray _image, OutputArray _corners, int maxCorners, double qualityLevel, double minDistance, InputArray _mask, int blockSize, @@ -211,6 +213,8 @@ static bool ocl_goodFeaturesToTrack( InputArray _image, OutputArray _corners, return true; } +#endif + } void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, @@ -221,10 +225,9 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, CV_Assert( qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0 ); CV_Assert( _mask.empty() || (_mask.type() == CV_8UC1 && _mask.sameSize(_image)) ); - if (ocl::useOpenCL() && _image.dims() <= 2 && _image.isUMat() && - ocl_goodFeaturesToTrack(_image, _corners, maxCorners, qualityLevel, minDistance, + CV_OCL_RUN(_image.dims() <= 2 && _image.isUMat(), + ocl_goodFeaturesToTrack(_image, _corners, maxCorners, qualityLevel, minDistance, _mask, blockSize, useHarrisDetector, harrisK)) - return; Mat image = _image.getMat(), eig, tmp; if( useHarrisDetector ) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index a94d99a3b..8c11c62db 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -3115,10 +3115,7 @@ template struct Filter2D : public BaseFi VecOp vecOp; }; -} - -namespace cv -{ +#ifdef HAVE_OPENCL #define DIVUP(total, grain) (((total) + (grain) - 1) / (grain)) #define ROUNDUP(sz, n) ((sz) + (n) - 1 - (((sz) + (n) - 1) % (n))) @@ -3551,6 +3548,9 @@ static bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, UMat dst = _dst.getUMat(); return ocl_sepColFilter2D(buf, dst, kernelY, anchor.y, true); } + +#endif + } cv::Ptr cv::getLinearFilter(int srcType, int dstType, @@ -3668,9 +3668,8 @@ void cv::filter2D( InputArray _src, OutputArray _dst, int ddepth, InputArray _kernel, Point anchor, double delta, int borderType ) { - bool use_opencl = ocl::useOpenCL() && _dst.isUMat(); - if( use_opencl && ocl_filter2D(_src, _dst, ddepth, _kernel, anchor, delta, borderType)) - return; + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2, + ocl_filter2D(_src, _dst, ddepth, _kernel, anchor, delta, borderType)) Mat src = _src.getMat(), kernel = _kernel.getMat(); @@ -3718,9 +3717,8 @@ void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, InputArray _kernelX, InputArray _kernelY, Point anchor, double delta, int borderType ) { - bool use_opencl = ocl::useOpenCL() && _dst.isUMat(); - if (use_opencl && ocl_sepFilter2D(_src, _dst, ddepth, _kernelX, _kernelY, anchor, delta, borderType)) - return; + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2, + ocl_sepFilter2D(_src, _dst, ddepth, _kernelX, _kernelY, anchor, delta, borderType)) Mat src = _src.getMat(), kernelX = _kernelX.getMat(), kernelY = _kernelY.getMat(); diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 71127b638..0533bbba2 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -1929,6 +1929,7 @@ void cv::calcBackProject( const Mat* images, int nimages, const int* channels, CV_Error(CV_StsUnsupportedFormat, ""); } +#ifdef HAVE_OPENCL namespace cv { @@ -1962,7 +1963,9 @@ static bool ocl_calcBackProject( InputArrayOfArrays _images, std::vector ch const std::vector& ranges, float scale, size_t histdims ) { - const std::vector & images = *(const std::vector *)_images.getObj(); + std::vector images; + _images.getUMatVector(images); + size_t nimages = images.size(), totalcn = images[0].channels(); CV_Assert(nimages > 0); @@ -2066,19 +2069,22 @@ static bool ocl_calcBackProject( InputArrayOfArrays _images, std::vector ch } +#endif + void cv::calcBackProject( InputArrayOfArrays images, const std::vector& channels, InputArray hist, OutputArray dst, const std::vector& ranges, double scale ) { Size histSize = hist.size(); +#ifdef HAVE_OPENCL bool _1D = histSize.height == 1 || histSize.width == 1; size_t histdims = _1D ? 1 : hist.dims(); +#endif - if (ocl::useOpenCL() && images.isUMatVector() && dst.isUMat() && hist.type() == CV_32FC1 && - histdims <= 2 && ranges.size() == histdims * 2 && histdims == channels.size() && - ocl_calcBackProject(images, channels, hist, dst, ranges, (float)scale, histdims)) - return; + CV_OCL_RUN(dst.isUMat() && hist.type() == CV_32FC1 && + histdims <= 2 && ranges.size() == histdims * 2 && histdims == channels.size(), + ocl_calcBackProject(images, channels, hist, dst, ranges, (float)scale, histdims)) Mat H0 = hist.getMat(), H; int hcn = H0.channels(); @@ -3280,6 +3286,8 @@ CV_IMPL void cvEqualizeHist( const CvArr* srcarr, CvArr* dstarr ) cv::equalizeHist(cv::cvarrToMat(srcarr), cv::cvarrToMat(dstarr)); } +#ifdef HAVE_OPENCL + namespace cv { enum @@ -3340,6 +3348,8 @@ static bool ocl_equalizeHist(InputArray _src, OutputArray _dst) } +#endif + void cv::equalizeHist( InputArray _src, OutputArray _dst ) { CV_Assert( _src.type() == CV_8UC1 ); @@ -3347,8 +3357,8 @@ void cv::equalizeHist( InputArray _src, OutputArray _dst ) if (_src.empty()) return; - if (ocl::useOpenCL() && _dst.isUMat() && ocl_equalizeHist(_src, _dst)) - return; + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_equalizeHist(_src, _dst)) Mat src = _src.getMat(); _dst.create( src.size(), src.type() ); diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index e9fd60d5d..af961ee5b 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -1900,6 +1900,8 @@ private: }; #endif +#ifdef HAVE_OPENCL + static void ocl_computeResizeAreaTabs(int ssize, int dsize, double scale, int * const map_tab, float * const alpha_tab, int * const ofs_tab) { @@ -2069,6 +2071,8 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize, return k.run(2, globalsize, 0, false); } +#endif + } ////////////////////////////////////////////////////////////////////////////////////////// @@ -2196,9 +2200,8 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize, inv_scale_y = (double)dsize.height/ssize.height; } - if( ocl::useOpenCL() && _dst.kind() == _InputArray::UMAT && - ocl_resize(_src, _dst, dsize, inv_scale_x, inv_scale_y, interpolation)) - return; + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_resize(_src, _dst, dsize, inv_scale_x, inv_scale_y, interpolation)) Mat src = _src.getMat(); _dst.create(dsize, src.type()); @@ -3390,6 +3393,8 @@ private: const void *ctab; }; +#ifdef HAVE_OPENCL + static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, InputArray _map2, int interpolation, int borderType, const Scalar& borderValue) { @@ -3462,6 +3467,8 @@ static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, Input return k.run(2, globalThreads, NULL, false); } +#endif + } void cv::remap( InputArray _src, OutputArray _dst, @@ -3504,8 +3511,8 @@ void cv::remap( InputArray _src, OutputArray _dst, CV_Assert( _map1.size().area() > 0 ); CV_Assert( _map2.empty() || (_map2.size() == _map1.size())); - if (ocl::useOpenCL() && _dst.isUMat() && ocl_remap(_src, _dst, _map1, _map2, interpolation, borderType, borderValue)) - return; + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_remap(_src, _dst, _map1, _map2, interpolation, borderType, borderValue)) Mat src = _src.getMat(), map1 = _map1.getMat(), map2 = _map2.getMat(); _dst.create( map1.size(), src.type() ); @@ -3870,6 +3877,8 @@ private: }; #endif +#ifdef HAVE_OPENCL + enum { OCL_OP_PERSPECTIVE = 1, OCL_OP_AFFINE = 0 }; static bool ocl_warpTransform(InputArray _src, OutputArray _dst, InputArray _M0, @@ -3953,6 +3962,8 @@ static bool ocl_warpTransform(InputArray _src, OutputArray _dst, InputArray _M0, return k.run(2, globalThreads, NULL, false); } +#endif + } @@ -3960,10 +3971,9 @@ void cv::warpAffine( InputArray _src, OutputArray _dst, InputArray _M0, Size dsize, int flags, int borderType, const Scalar& borderValue ) { - if (ocl::useOpenCL() && _dst.isUMat() && - ocl_warpTransform(_src, _dst, _M0, dsize, flags, borderType, - borderValue, OCL_OP_AFFINE)) - return; + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_warpTransform(_src, _dst, _M0, dsize, flags, borderType, + borderValue, OCL_OP_AFFINE)) Mat src = _src.getMat(), M0 = _M0.getMat(); _dst.create( dsize.area() == 0 ? src.size() : dsize, src.type() ); @@ -4206,10 +4216,9 @@ void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0, { CV_Assert( _src.total() > 0 ); - if (ocl::useOpenCL() && _dst.isUMat() && - ocl_warpTransform(_src, _dst, _M0, dsize, flags, borderType, borderValue, + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_warpTransform(_src, _dst, _M0, dsize, flags, borderType, borderValue, OCL_OP_PERSPECTIVE)) - return; Mat src = _src.getMat(), M0 = _M0.getMat(); _dst.create( dsize.area() == 0 ? src.size() : dsize, src.type() ); diff --git a/modules/imgproc/src/moments.cpp b/modules/imgproc/src/moments.cpp index f1954cfe3..98c542b20 100644 --- a/modules/imgproc/src/moments.cpp +++ b/modules/imgproc/src/moments.cpp @@ -363,6 +363,8 @@ Moments::Moments( double _m00, double _m10, double _m01, double _m20, double _m1 nu30 = mu30*s3; nu21 = mu21*s3; nu12 = mu12*s3; nu03 = mu03*s3; } +#ifdef HAVE_OPENCL + static bool ocl_moments( InputArray _src, Moments& m) { const int TILE_SIZE = 32; @@ -427,6 +429,8 @@ static bool ocl_moments( InputArray _src, Moments& m) return true; } +#endif + } @@ -444,10 +448,12 @@ cv::Moments cv::moments( InputArray _src, bool binary ) if( size.width <= 0 || size.height <= 0 ) return m; +#ifdef HAVE_OPENCL if( ocl::useOpenCL() && type == CV_8UC1 && !binary && _src.isUMat() && ocl_moments(_src, m) ) ; else +#endif { Mat mat = _src.getMat(); if( mat.checkVector(2) >= 0 && (depth == CV_32F || depth == CV_32S)) diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 7ade970d9..4cf0d0103 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1284,7 +1284,7 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst, } #endif -static const char* op2str[] = {"ERODE", "DILATE"}; +#ifdef HAVE_OPENCL static bool ocl_morphology_op(InputArray _src, OutputArray _dst, InputArray _kernel, Size &ksize, const Point anchor, int iterations, int op) { @@ -1315,6 +1315,7 @@ static bool ocl_morphology_op(InputArray _src, OutputArray _dst, InputArray _ker return false; char compile_option[128]; + static const char* op2str[] = {"ERODE", "DILATE"}; sprintf(compile_option, "-D RADIUSX=%d -D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D %s %s %s -D GENTYPE=%s -D DEPTH_%d", anchor.x, anchor.y, (int)localThreads[0], (int)localThreads[1], op2str[op], doubleSupport?"-D DOUBLE_SUPPORT" :"", rectKernel?"-D RECTKERNEL":"", ocl::typeToStr(_src.type()), _src.depth() ); @@ -1396,19 +1397,17 @@ static bool ocl_morphology_op(InputArray _src, OutputArray _dst, InputArray _ker return true; } +#endif + static void morphOp( int op, InputArray _src, OutputArray _dst, InputArray _kernel, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { +#ifdef HAVE_OPENCL int src_type = _src.type(), dst_type = _dst.type(), src_cn = CV_MAT_CN(src_type), src_depth = CV_MAT_DEPTH(src_type); - - bool useOpenCL = cv::ocl::useOpenCL() && _dst.isUMat() && _src.size() == _dst.size() && src_type == dst_type && - _src.dims() <= 2 && (src_cn == 1 || src_cn == 4) && anchor.x == -1 && anchor.y == -1 && - (src_depth == CV_8U || src_depth == CV_32F || src_depth == CV_64F ) && - borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue() && - (op == MORPH_ERODE || op == MORPH_DILATE); +#endif Mat kernel = _kernel.getMat(); Size ksize = kernel.data ? kernel.size() : Size(3,3); @@ -1443,8 +1442,12 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, iterations = 1; } - if (useOpenCL && ocl_morphology_op(_src, _dst, kernel, ksize, anchor, iterations, op) ) - return; + CV_OCL_RUN(_dst.isUMat() && _src.size() == _dst.size() && src_type == dst_type && + _src.dims() <= 2 && (src_cn == 1 || src_cn == 4) && anchor.x == -1 && anchor.y == -1 && + (src_depth == CV_8U || src_depth == CV_32F || src_depth == CV_64F ) && + borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue() && + (op == MORPH_ERODE || op == MORPH_DILATE), + ocl_morphology_op(_src, _dst, kernel, ksize, anchor, iterations, op) ) Mat src = _src.getMat(); diff --git a/modules/imgproc/src/pyramids.cpp b/modules/imgproc/src/pyramids.cpp index 6802e9eeb..a50e10680 100644 --- a/modules/imgproc/src/pyramids.cpp +++ b/modules/imgproc/src/pyramids.cpp @@ -401,6 +401,8 @@ pyrUp_( const Mat& _src, Mat& _dst, int) typedef void (*PyrFunc)(const Mat&, Mat&, int); +#ifdef HAVE_OPENCL + static bool ocl_pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType) { int type = _src.type(), depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type); @@ -484,13 +486,14 @@ static bool ocl_pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int return k.run(2, globalThreads, localThreads, false); } +#endif + } void cv::pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType ) { - if (ocl::useOpenCL() && _dst.isUMat() && - ocl_pyrDown(_src, _dst, _dsz, borderType)) - return; + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_pyrDown(_src, _dst, _dsz, borderType)) Mat src = _src.getMat(); Size dsz = _dsz.area() == 0 ? Size((src.cols + 1)/2, (src.rows + 1)/2) : _dsz; @@ -522,9 +525,8 @@ void cv::pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borde void cv::pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType ) { - if (ocl::useOpenCL() && _dst.isUMat() && - ocl_pyrUp(_src, _dst, _dsz, borderType)) - return; + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_pyrUp(_src, _dst, _dsz, borderType)) Mat src = _src.getMat(); Size dsz = _dsz.area() == 0 ? Size(src.cols*2, src.rows*2) : _dsz; diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index bc621be3b..e5c0cde28 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1920,39 +1920,41 @@ medianBlur_SortNet( const Mat& _src, Mat& _dst, int m ) } } +#ifdef HAVE_OPENCL + +static bool ocl_medianFilter ( InputArray _src, OutputArray _dst, int m) +{ + int type = _src.type(); + int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + + if (!((depth == CV_8U || depth == CV_16U || depth == CV_16S || depth == CV_32F) && (cn != 3 && cn <= 4))) + return false; + + const char * kernelName; + + if (m == 3) + kernelName = "medianFilter3"; + else if (m == 5) + kernelName = "medianFilter5"; + else + return false; + + ocl::Kernel k(kernelName,ocl::imgproc::medianFilter_oclsrc,format("-D type=%s",ocl::typeToStr(type))); + if (k.empty()) + return false; + + UMat src = _src.getUMat(); + _dst.create(_src.size(),type); + UMat dst = _dst.getUMat(); + + size_t globalsize[2] = {(src.cols + 18) / 16 * 16, (src.rows + 15) / 16 * 16}; + size_t localsize[2] = {16, 16}; + + return k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst)).run(2,globalsize,localsize,false); } -namespace cv -{ - static bool ocl_medianFilter ( InputArray _src, OutputArray _dst, int m) - { - int type = _src.type(); - int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); +#endif - if (!((depth == CV_8U || depth == CV_16U || depth == CV_16S || depth == CV_32F) && (cn != 3 && cn <= 4))) - return false; - - const char * kernelName; - - if (m==3) - kernelName = "medianFilter3"; - else if (m==5) - kernelName = "medianFilter5"; - else - return false; - - ocl::Kernel k(kernelName,ocl::imgproc::medianFilter_oclsrc,format("-D type=%s",ocl::typeToStr(type))); - if (k.empty()) - return false; - - _dst.create(_src.size(),type); - UMat src = _src.getUMat(), dst = _dst.getUMat(); - - size_t globalsize[2] = {(src.cols + 18) / 16 * 16, (src.rows + 15) / 16 * 16}; - size_t localsize[2] = {16, 16}; - - return k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst)).run(2,globalsize,localsize,false); - } } void cv::medianBlur( InputArray _src0, OutputArray _dst, int ksize ) @@ -1961,16 +1963,12 @@ void cv::medianBlur( InputArray _src0, OutputArray _dst, int ksize ) if( ksize <= 1 ) { - Mat src0 = _src0.getMat(); - _dst.create( src0.size(), src0.type() ); - Mat dst = _dst.getMat(); - src0.copyTo(dst); + _src0.copyTo(_dst); return; } - bool use_opencl = ocl::useOpenCL() && _dst.isUMat(); - if ( use_opencl && ocl_medianFilter(_src0,_dst, ksize)) - return; + CV_OCL_RUN(_src0.dims() <= 2 && _dst.isUMat(), + ocl_medianFilter(_src0,_dst, ksize)) Mat src0 = _src0.getMat(); _dst.create( src0.size(), src0.type() ); @@ -2226,6 +2224,8 @@ private: }; #endif +#ifdef HAVE_OPENCL + static bool ocl_bilateralFilter_8u(InputArray _src, OutputArray _dst, int d, double sigma_color, double sigma_space, int borderType) @@ -2301,6 +2301,8 @@ static bool ocl_bilateralFilter_8u(InputArray _src, OutputArray _dst, int d, return k.run(2, globalsize, NULL, false); } +#endif + static void bilateralFilter_8u( const Mat& src, Mat& dst, int d, double sigma_color, double sigma_space, @@ -2651,9 +2653,8 @@ void cv::bilateralFilter( InputArray _src, OutputArray _dst, int d, { _dst.create( _src.size(), _src.type() ); - if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() && - ocl_bilateralFilter_8u(_src, _dst, d, sigmaColor, sigmaSpace, borderType)) - return; + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_bilateralFilter_8u(_src, _dst, d, sigmaColor, sigmaSpace, borderType)) Mat src = _src.getMat(), dst = _dst.getMat(); diff --git a/modules/imgproc/src/sumpixels.cpp b/modules/imgproc/src/sumpixels.cpp index c6ce0f296..4e18f119f 100644 --- a/modules/imgproc/src/sumpixels.cpp +++ b/modules/imgproc/src/sumpixels.cpp @@ -231,6 +231,8 @@ typedef void (*IntegralFunc)(const uchar* src, size_t srcstep, uchar* sum, size_ uchar* sqsum, size_t sqsumstep, uchar* tilted, size_t tstep, Size size, int cn ); +#ifdef HAVE_OPENCL + enum { vlen = 4 }; static bool ocl_integral( InputArray _src, OutputArray _sum, int sdepth ) @@ -324,6 +326,8 @@ static bool ocl_integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, return k2.run(1, >2, <2, false); } +#endif + } @@ -336,19 +340,17 @@ void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, Output sqdepth = CV_64F; sdepth = CV_MAT_DEPTH(sdepth), sqdepth = CV_MAT_DEPTH(sqdepth); +#ifdef HAVE_OPENCL if (ocl::useOpenCL() && _sum.isUMat() && !_tilted.needed()) { if (!_sqsum.needed()) { - if (ocl_integral(_src, _sum, sdepth)) - return; + CV_OCL_RUN(ocl::useOpenCL(), ocl_integral(_src, _sum, sdepth)) } else if (_sqsum.isUMat()) - { - if (ocl_integral(_src, _sum, _sqsum, sdepth, sqdepth)) - return; - } + CV_OCL_RUN(ocl::useOpenCL(), ocl_integral(_src, _sum, _sqsum, sdepth, sqdepth)) } +#endif Size ssize = _src.size(), isize(ssize.width + 1, ssize.height + 1); _sum.create( isize, CV_MAKETYPE(sdepth, cn) ); diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index 9953c6851..0242068ee 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -42,338 +42,326 @@ #include "precomp.hpp" #include "opencl_kernels.hpp" -//////////////////////////////////////////////////matchTemplate////////////////////////////////////////////////////////// +////////////////////////////////////////////////// matchTemplate ////////////////////////////////////////////////////////// + namespace cv { - static bool matchTemplate_CCORR(InputArray _image, InputArray _templ, OutputArray _result); - static bool matchTemplate_CCORR_NORMED(InputArray _image, InputArray _templ, OutputArray _result); - static bool matchTemplate_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result); - static bool matchTemplate_SQDIFF_NORMED (InputArray _image, InputArray _templ, OutputArray _result); +#ifdef HAVE_OPENCL - static bool matchTemplate_CCOEFF(InputArray _image, InputArray _templ, OutputArray _result); - static bool matchTemplate_CCOEFF_NORMED(InputArray _image, InputArray _templ, OutputArray _result); - - static bool matchTemplateNaive_CCORR (InputArray _image, InputArray _templ, OutputArray _result, int cn); - static bool matchTemplateNaive_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result, int cn); - - static bool useNaive(int method, int depth, Size size) - { +static bool useNaive(int method, int depth, Size size) +{ #ifdef HAVE_CLAMDFFT - if (method == TM_SQDIFF && depth == CV_32F) - return true; - else if(method == TM_CCORR || (method == TM_SQDIFF && depth == CV_8U)) - return size.height < 18 && size.width < 18; - else - return false; + if (method == TM_SQDIFF && depth == CV_32F) + return true; + else if(method == TM_CCORR || (method == TM_SQDIFF && depth == CV_8U)) + return size.height < 18 && size.width < 18; + else + return false; #else #define UNUSED(x) (void)(x); - UNUSED(method) UNUSED(depth) UNUSED(size) + UNUSED(method) UNUSED(depth) UNUSED(size) #undef UNUSED - return true; + return true; #endif - } +} -///////////////////////////////////////////////////CCORR////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////// CCORR ////////////////////////////////////////////////////////////// - static bool matchTemplate_CCORR(InputArray _image, InputArray _templ, OutputArray _result) - { - if (useNaive(TM_CCORR, _image.depth(), _templ.size()) ) - return matchTemplateNaive_CCORR(_image, _templ, _result, _image.channels()); - else - return false; - } +static bool matchTemplateNaive_CCORR (InputArray _image, InputArray _templ, OutputArray _result, int cn) +{ + int type = _image.type(); + int depth = CV_MAT_DEPTH(type); - static bool matchTemplateNaive_CCORR (InputArray _image, InputArray _templ, OutputArray _result, int cn) + const char * kernelName = "matchTemplate_Naive_CCORR"; + + ocl::Kernel k (kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); + if (k.empty()) + return false; + + UMat image = _image.getUMat(); + UMat templ = _templ.getUMat(), result; + _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); + result = _result.getUMat(); + + size_t globalsize[2] = {result.cols, result.rows}; + + return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,NULL,false); +} + +static bool matchTemplate_CCORR_NORMED(InputArray _image, InputArray _templ, OutputArray _result) +{ + matchTemplate(_image, _templ, _result, CV_TM_CCORR); + + int type = _image.type(); + int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + + const char * kernelName = "matchTemplate_CCORR_NORMED"; + + ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); + if (k.empty()) + return false; + + UMat image = _image.getUMat(); + UMat templ = _templ.getUMat(), result; + _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); + result = _result.getUMat(); + + UMat image_sums, image_sqsums; + integral(image.reshape(1), image_sums, image_sqsums, CV_32F, CV_32F); + + UMat templ_resh, temp; + templ.reshape(1).convertTo(templ_resh, CV_32F); + + multiply(templ_resh, templ_resh, temp); + unsigned long long templ_sqsum = (unsigned long long)sum(temp)[0]; + + size_t globalsize[2] = {result.cols, result.rows}; + + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,NULL,false); +} + +static bool matchTemplate_CCORR(InputArray _image, InputArray _templ, OutputArray _result) +{ + if (useNaive(TM_CCORR, _image.depth(), _templ.size()) ) + return matchTemplateNaive_CCORR(_image, _templ, _result, _image.channels()); + else + return false; +} + +////////////////////////////////////// SQDIFF ////////////////////////////////////////////////////////////// + +static bool matchTemplateNaive_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result, int cn) +{ + int type = _image.type(); + int depth = CV_MAT_DEPTH(type); + + const char * kernelName = "matchTemplate_Naive_SQDIFF"; + + ocl::Kernel k (kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); + if (k.empty()) + return false; + + UMat image = _image.getUMat(); + UMat templ = _templ.getUMat(), result; + _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); + result = _result.getUMat(); + + size_t globalsize[2] = {result.cols, result.rows}; + + return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,NULL,false); +} + +static bool matchTemplate_SQDIFF_NORMED (InputArray _image, InputArray _templ, OutputArray _result) +{ + matchTemplate(_image, _templ, _result, CV_TM_CCORR); + + int type = _image.type(); + int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + + const char * kernelName = "matchTemplate_SQDIFF_NORMED"; + + ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); + if (k.empty()) + return false; + + UMat image = _image.getUMat(); + UMat templ = _templ.getUMat(), result; + _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); + result = _result.getUMat(); + + UMat image_sums, image_sqsums; + integral(image.reshape(1), image_sums, image_sqsums, CV_32F, CV_32F); + + UMat temp, templ_resh; + templ.reshape(1).convertTo(templ_resh, CV_32F); + + multiply(templ_resh, templ_resh, temp); + unsigned long long templ_sqsum = (unsigned long long)sum(temp)[0]; + + size_t globalsize[2] = {result.cols, result.rows}; + + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,NULL,false); +} + +static bool matchTemplate_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result) +{ + if (useNaive(TM_SQDIFF, _image.depth(), _templ.size())) + return matchTemplateNaive_SQDIFF(_image, _templ, _result, _image.channels()); + else + return false; +} + +///////////////////////////////////// CCOEFF ///////////////////////////////////////////////////////////////// + +static bool matchTemplate_CCOEFF(InputArray _image, InputArray _templ, OutputArray _result) +{ + matchTemplate(_image, _templ, _result, CV_TM_CCORR); + + UMat image_sums; + integral(_image, image_sums); + + int type = image_sums.type(); + int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + + const char * kernelName; + + if (cn==1) + kernelName = "matchTemplate_Prepared_CCOEFF_C1"; + else if (cn==2) + kernelName = "matchTemplate_Prepared_CCOEFF_C2"; + else + kernelName = "matchTemplate_Prepared_CCOEFF_C4"; + + ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); + if (k.empty()) + return false; + + UMat templ = _templ.getUMat(), result; + Size size = _image.size(); + _result.create(size.height - templ.rows + 1, size.width - templ.cols + 1, CV_32F); + result = _result.getUMat(); + + size_t globalsize[2] = {result.cols, result.rows}; + + if (cn==1) { - int type = _image.type(); - int depth = CV_MAT_DEPTH(type); - - const char * kernelName = "matchTemplate_Naive_CCORR"; - - ocl::Kernel k (kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); - if (k.empty()) - return false; - - UMat image = _image.getUMat(); - UMat templ = _templ.getUMat(), result; - _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); - result = _result.getUMat(); - - size_t globalsize[2] = {result.cols, result.rows}; - - return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,NULL,false); + float templ_sum = (float)sum(_templ)[0]/ _templ.size().area(); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sum).run(2,globalsize,NULL,false); } - - static bool matchTemplate_CCORR_NORMED(InputArray _image, InputArray _templ, OutputArray _result) + else { - matchTemplate(_image, _templ, _result, CV_TM_CCORR); - - int type = _image.type(); - int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); - - const char * kernelName = "matchTemplate_CCORR_NORMED"; - - ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); - if (k.empty()) - return false; - - UMat image = _image.getUMat(); - UMat templ = _templ.getUMat(), result; - _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); - result = _result.getUMat(); - - UMat image_sums, image_sqsums; - integral(image.reshape(1), image_sums, image_sqsums, CV_32F, CV_32F); - - UMat templ_resh, temp; - templ.reshape(1).convertTo(templ_resh, CV_32F); - - multiply(templ_resh, templ_resh, temp); - unsigned long long templ_sqsum = (unsigned long long)sum(temp)[0]; - - size_t globalsize[2] = {result.cols, result.rows}; - - return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,NULL,false); - } - -//////////////////////////////////////SQDIFF////////////////////////////////////////////////////////////// - - static bool matchTemplate_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result) - { - if (useNaive(TM_SQDIFF, _image.depth(), _templ.size())) - { - return matchTemplateNaive_SQDIFF(_image, _templ, _result, _image.channels());; - } - else - return false; - } - - static bool matchTemplateNaive_SQDIFF(InputArray _image, InputArray _templ, OutputArray _result, int cn) - { - int type = _image.type(); - int depth = CV_MAT_DEPTH(type); - - const char * kernelName = "matchTemplate_Naive_SQDIFF"; - - ocl::Kernel k (kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); - if (k.empty()) - return false; - - UMat image = _image.getUMat(); - UMat templ = _templ.getUMat(), result; - _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); - result = _result.getUMat(); - - size_t globalsize[2] = {result.cols, result.rows}; - - return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)).run(2,globalsize,NULL,false); - } - - static bool matchTemplate_SQDIFF_NORMED (InputArray _image, InputArray _templ, OutputArray _result) - { - matchTemplate(_image, _templ, _result, CV_TM_CCORR); - - int type = _image.type(); - int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); - - const char * kernelName = "matchTemplate_SQDIFF_NORMED"; - - ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); - if (k.empty()) - return false; - - UMat image = _image.getUMat(); - UMat templ = _templ.getUMat(), result; - _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); - result = _result.getUMat(); - - UMat image_sums, image_sqsums; - integral(image.reshape(1), image_sums, image_sqsums, CV_32F, CV_32F); - - UMat temp, templ_resh; - templ.reshape(1).convertTo(templ_resh, CV_32F); - - multiply(templ_resh, templ_resh, temp); - unsigned long long templ_sqsum = (unsigned long long)sum(temp)[0]; - - size_t globalsize[2] = {result.cols, result.rows}; - - return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sqsum).run(2,globalsize,NULL,false); - } - -/////////////////////////////////////CCOEFF///////////////////////////////////////////////////////////////// - - static bool matchTemplate_CCOEFF(InputArray _image, InputArray _templ, OutputArray _result) - { - matchTemplate(_image, _templ, _result, CV_TM_CCORR); - - UMat image_sums; - integral(_image, image_sums); - - int type = image_sums.type(); - int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); - - const char * kernelName; - - if (cn==1) - kernelName = "matchTemplate_Prepared_CCOEFF_C1"; - else if (cn==2) - kernelName = "matchTemplate_Prepared_CCOEFF_C2"; - else - kernelName = "matchTemplate_Prepared_CCOEFF_C4"; - - ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, format("-D type=%s -D elem_type=%s -D cn=%d",ocl::typeToStr(type), ocl::typeToStr(depth), cn)); - if (k.empty()) - return false; - - UMat templ = _templ.getUMat(), result; - Size size = _image.size(); - _result.create(size.height - templ.rows + 1, size.width - templ.cols + 1, CV_32F); - result = _result.getUMat(); - - size_t globalsize[2] = {result.cols, result.rows}; - - if (cn==1) - { - float templ_sum = (float)sum(_templ)[0]/ _templ.size().area(); - return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, templ_sum).run(2,globalsize,NULL,false); - } - else - { - Vec4f templ_sum = Vec4f::all(0); - templ_sum = sum(templ)/ templ.size().area(); - if (cn==2) - return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, - templ_sum[0],templ_sum[1]).run(2,globalsize,NULL,false); - + Vec4f templ_sum = Vec4f::all(0); + templ_sum = sum(templ)/ templ.size().area(); + if (cn==2) return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, - templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3]).run(2,globalsize,NULL,false); - } - } + templ_sum[0],templ_sum[1]).run(2,globalsize,NULL,false); - static bool matchTemplate_CCOEFF_NORMED(InputArray _image, InputArray _templ, OutputArray _result) - { - UMat imagef, templf; - - _image.getUMat().convertTo(imagef, CV_32F); - _templ.getUMat().convertTo(templf, CV_32F); - - matchTemplate(imagef, templf, _result, CV_TM_CCORR); - - const char * kernelName; - - UMat temp, image_sums, image_sqsums; - integral(_image,image_sums, image_sqsums, CV_32F, CV_32F); - - int type = image_sums.type(); - int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); - - if (cn== 1) - kernelName = "matchTemplate_CCOEFF_NORMED_C1"; - else if (cn==2) - kernelName = "matchTemplate_CCOEFF_NORMED_C2"; - else - kernelName = "matchTemplate_CCOEFF_NORMED_C4"; - - ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, - format("-D type=%s -D elem_type=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn)); - if (k.empty()) - return false; - - UMat image = _image.getUMat(); - UMat templ = _templ.getUMat(), result; - int image_rows = _image.size().height, image_cols = _image.size().width; - _result.create(image_rows - templ.rows + 1, image_cols - templ.cols + 1, CV_32F); - result = _result.getUMat(); - - size_t globalsize[2] = {result.cols, result.rows}; - - float scale = 1.f / templ.size().area(); - - if (cn==1) - { - float templ_sum = (float)sum(templ)[0]; - - multiply(templf, templf, temp); - float templ_sqsum = (float)sum(temp)[0]; - - templ_sqsum -= scale * templ_sum * templ_sum; - templ_sum *= scale; - - if (templ_sqsum < DBL_EPSILON) - { - result = Scalar::all(1); - return true; - } - - return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums),ocl::KernelArg::ReadOnlyNoSize(image_sqsums), - ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, templ_sum, templ_sqsum) - .run(2,globalsize,NULL,false); - } - else - { - Vec4f templ_sum = Vec4f::all(0); - Vec4f templ_sqsum = Vec4f::all(0); - - templ_sum = sum(templ); - - multiply(templf, templf, temp); - templ_sqsum = sum(temp); - - float templ_sqsum_sum = 0; - for(int i = 0; i < cn; i ++) - { - templ_sqsum_sum += templ_sqsum[i] - scale * templ_sum[i] * templ_sum[i]; - } - - templ_sum *= scale; - - if (templ_sqsum_sum < DBL_EPSILON) - { - result = Scalar::all(1); - return true; - } - - if (cn==2) - return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums), - ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, - templ_sum[0],templ_sum[1], templ_sqsum_sum) - .run(2,globalsize,NULL,false); - - return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums), - ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, - templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3], templ_sqsum_sum) - .run(2,globalsize,NULL,false); - } - - } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////// - - static bool ocl_matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method) - { - int cn = CV_MAT_CN(_img.type()); - - if (cn == 3 || cn > 4) - return false; - - typedef bool (*Caller)(InputArray _img, InputArray _templ, OutputArray _result); - - const Caller callers[] = - { - matchTemplate_SQDIFF, matchTemplate_SQDIFF_NORMED, matchTemplate_CCORR, - matchTemplate_CCORR_NORMED, matchTemplate_CCOEFF, matchTemplate_CCOEFF_NORMED - }; - - Caller caller = callers[method]; - - return caller(_img, _templ, _result); + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, + templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3]).run(2,globalsize,NULL,false); } } -namespace cv +static bool matchTemplate_CCOEFF_NORMED(InputArray _image, InputArray _templ, OutputArray _result) { + UMat imagef, templf; + + _image.getUMat().convertTo(imagef, CV_32F); + _templ.getUMat().convertTo(templf, CV_32F); + + matchTemplate(imagef, templf, _result, CV_TM_CCORR); + + const char * kernelName; + + UMat temp, image_sums, image_sqsums; + integral(_image,image_sums, image_sqsums, CV_32F, CV_32F); + + int type = image_sums.type(); + int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + + if (cn== 1) + kernelName = "matchTemplate_CCOEFF_NORMED_C1"; + else if (cn==2) + kernelName = "matchTemplate_CCOEFF_NORMED_C2"; + else + kernelName = "matchTemplate_CCOEFF_NORMED_C4"; + + ocl::Kernel k(kernelName, ocl::imgproc::match_template_oclsrc, + format("-D type=%s -D elem_type=%s -D cn=%d", ocl::typeToStr(type), ocl::typeToStr(depth), cn)); + if (k.empty()) + return false; + + UMat image = _image.getUMat(); + UMat templ = _templ.getUMat(), result; + int image_rows = _image.size().height, image_cols = _image.size().width; + _result.create(image_rows - templ.rows + 1, image_cols - templ.cols + 1, CV_32F); + result = _result.getUMat(); + + size_t globalsize[2] = {result.cols, result.rows}; + + float scale = 1.f / templ.size().area(); + + if (cn==1) + { + float templ_sum = (float)sum(templ)[0]; + + multiply(templf, templf, temp); + float templ_sqsum = (float)sum(temp)[0]; + + templ_sqsum -= scale * templ_sum * templ_sum; + templ_sum *= scale; + + if (templ_sqsum < DBL_EPSILON) + { + result = Scalar::all(1); + return true; + } + + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums),ocl::KernelArg::ReadOnlyNoSize(image_sqsums), + ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, templ_sum, templ_sqsum) + .run(2,globalsize,NULL,false); + } + else + { + Vec4f templ_sum = Vec4f::all(0); + Vec4f templ_sqsum = Vec4f::all(0); + + templ_sum = sum(templ); + + multiply(templf, templf, temp); + templ_sqsum = sum(temp); + + float templ_sqsum_sum = 0; + for(int i = 0; i < cn; i ++) + { + templ_sqsum_sum += templ_sqsum[i] - scale * templ_sum[i] * templ_sum[i]; + } + + templ_sum *= scale; + + if (templ_sqsum_sum < DBL_EPSILON) + { + result = Scalar::all(1); + return true; + } + + if (cn==2) + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums), + ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, + templ_sum[0],templ_sum[1], templ_sqsum_sum) + .run(2,globalsize,NULL,false); + + return k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadOnlyNoSize(image_sqsums), + ocl::KernelArg::WriteOnly(result), templ.rows, templ.cols, scale, + templ_sum[0],templ_sum[1],templ_sum[2],templ_sum[3], templ_sqsum_sum) + .run(2,globalsize,NULL,false); + } + +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static bool ocl_matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method) +{ + int cn = CV_MAT_CN(_img.type()); + + if (cn == 3 || cn > 4) + return false; + + typedef bool (*Caller)(InputArray _img, InputArray _templ, OutputArray _result); + + const Caller callers[] = + { + matchTemplate_SQDIFF, matchTemplate_SQDIFF_NORMED, matchTemplate_CCORR, + matchTemplate_CCORR_NORMED, matchTemplate_CCOEFF, matchTemplate_CCOEFF_NORMED + }; + + Caller caller = callers[method]; + + return caller(_img, _templ, _result); +} + +#endif void crossCorr( const Mat& img, const Mat& _templ, Mat& corr, Size corrsize, int ctype, @@ -564,9 +552,7 @@ void crossCorr( const Mat& img, const Mat& _templ, Mat& corr, void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method ) { CV_Assert( CV_TM_SQDIFF <= method && method <= CV_TM_CCOEFF_NORMED ); - CV_Assert( (_img.depth() == CV_8U || _img.depth() == CV_32F) && _img.type() == _templ.type() ); - CV_Assert(_img.dims() <= 2); bool swapNotNeed = (_img.size().height >= _templ.size().height && _img.size().width >= _templ.size().width); @@ -575,9 +561,8 @@ void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, CV_Assert(_img.size().height <= _templ.size().height && _img.size().width <= _templ.size().width); } - bool use_opencl = ocl::useOpenCL() && _result.isUMat(); - if ( use_opencl && (swapNotNeed ? ocl_matchTemplate(_img,_templ,_result,method) : ocl_matchTemplate(_templ,_img,_result,method))) - return; + CV_OCL_RUN(_img.dims() <= 2 && _result.isUMat(), + (swapNotNeed ? ocl_matchTemplate(_img,_templ,_result,method) : ocl_matchTemplate(_templ,_img,_result,method))) int numType = method == CV_TM_CCORR || method == CV_TM_CCORR_NORMED ? 0 : method == CV_TM_CCOEFF || method == CV_TM_CCOEFF_NORMED ? 1 : 2; diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index ce853a783..fc0f6f9e9 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -706,6 +706,8 @@ private: int thresholdType; }; +#ifdef HAVE_OPENCL + static bool ocl_threshold( InputArray _src, OutputArray _dst, double & thresh, double maxval, int thresh_type ) { int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), ktype = CV_MAKE_TYPE(depth, 1); @@ -739,13 +741,14 @@ static bool ocl_threshold( InputArray _src, OutputArray _dst, double & thresh, d return k.run(2, globalsize, NULL, false); } +#endif + } double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double maxval, int type ) { - if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() && - ocl_threshold(_src, _dst, thresh, maxval, type)) - return thresh; + CV_OCL_RUN_(_src.dims() <= 2 && _dst.isUMat(), + ocl_threshold(_src, _dst, thresh, maxval, type), thresh) Mat src = _src.getMat(); bool use_otsu = (type & THRESH_OTSU) != 0; From 3985980b2fca749c7e329a4ef6d7aed3e377a106 Mon Sep 17 00:00:00 2001 From: Cosmin Boaca Date: Tue, 28 Jan 2014 11:54:39 +0200 Subject: [PATCH 264/295] Added returnDFVal parameter to parallel CvSVM::predict function --- modules/ml/doc/support_vector_machines.rst | 2 +- modules/ml/include/opencv2/ml.hpp | 2 +- modules/ml/src/svm.cpp | 10 ++++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/ml/doc/support_vector_machines.rst b/modules/ml/doc/support_vector_machines.rst index 14ee12bb4..9793bd6e3 100644 --- a/modules/ml/doc/support_vector_machines.rst +++ b/modules/ml/doc/support_vector_machines.rst @@ -242,7 +242,7 @@ Predicts the response for input sample(s). .. ocv:function:: float CvSVM::predict( const CvMat* sample, bool returnDFVal=false ) const -.. ocv:function:: float CvSVM::predict( const CvMat* samples, CvMat* results ) const +.. ocv:function:: float CvSVM::predict( const CvMat* samples, CvMat* results, bool returnDFVal=false ) const .. ocv:pyfunction:: cv2.SVM.predict(sample[, returnDFVal]) -> retval diff --git a/modules/ml/include/opencv2/ml.hpp b/modules/ml/include/opencv2/ml.hpp index 42b90d22d..7bc1d6fcf 100644 --- a/modules/ml/include/opencv2/ml.hpp +++ b/modules/ml/include/opencv2/ml.hpp @@ -490,7 +490,7 @@ public: bool balanced=false ); virtual float predict( const CvMat* sample, bool returnDFVal=false ) const; - virtual float predict( const CvMat* samples, CV_OUT CvMat* results ) const; + virtual float predict( const CvMat* samples, CV_OUT CvMat* results, bool returnDFVal=false ) const; CV_WRAP CvSVM( const cv::Mat& trainData, const cv::Mat& responses, const cv::Mat& varIdx=cv::Mat(), const cv::Mat& sampleIdx=cv::Mat(), diff --git a/modules/ml/src/svm.cpp b/modules/ml/src/svm.cpp index f2d3c33ab..341a817c9 100644 --- a/modules/ml/src/svm.cpp +++ b/modules/ml/src/svm.cpp @@ -2194,18 +2194,20 @@ float CvSVM::predict( const CvMat* sample, bool returnDFVal ) const } struct predict_body_svm : ParallelLoopBody { - predict_body_svm(const CvSVM* _pointer, float* _result, const CvMat* _samples, CvMat* _results) + predict_body_svm(const CvSVM* _pointer, float* _result, const CvMat* _samples, CvMat* _results, bool _returnDFVal) { pointer = _pointer; result = _result; samples = _samples; results = _results; + returnDFVal = _returnDFVal; } const CvSVM* pointer; float* result; const CvMat* samples; CvMat* results; + bool returnDFVal; void operator()( const cv::Range& range ) const { @@ -2213,7 +2215,7 @@ struct predict_body_svm : ParallelLoopBody { { CvMat sample; cvGetRow( samples, &sample, i ); - int r = (int)pointer->predict(&sample); + int r = (int)pointer->predict(&sample, returnDFVal); if (results) results->data.fl[i] = (float)r; if (i == 0) @@ -2222,11 +2224,11 @@ struct predict_body_svm : ParallelLoopBody { } }; -float CvSVM::predict(const CvMat* samples, CV_OUT CvMat* results) const +float CvSVM::predict(const CvMat* samples, CV_OUT CvMat* results, bool returnDFVal) const { float result = 0; cv::parallel_for_(cv::Range(0, samples->rows), - predict_body_svm(this, &result, samples, results) + predict_body_svm(this, &result, samples, results, returnDFVal) ); return result; } From 1391ca1da5c8a50a73c6472439961dffc9e34dde Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Mon, 27 Jan 2014 17:32:51 +0400 Subject: [PATCH 265/295] Added ocl_Mog2 --- modules/video/perf/opencl/perf_bgfg_mog2.cpp | 89 ++++++ modules/video/src/bgfg_gaussmix2.cpp | 168 +++++++++++- modules/video/src/opencl/bgfg_mog2.cl | 272 +++++++++++++++++++ modules/video/test/ocl/test_bgfg_mog2.cpp | 125 +++++++++ 4 files changed, 641 insertions(+), 13 deletions(-) create mode 100644 modules/video/perf/opencl/perf_bgfg_mog2.cpp create mode 100644 modules/video/src/opencl/bgfg_mog2.cl create mode 100644 modules/video/test/ocl/test_bgfg_mog2.cpp diff --git a/modules/video/perf/opencl/perf_bgfg_mog2.cpp b/modules/video/perf/opencl/perf_bgfg_mog2.cpp new file mode 100644 index 000000000..b74643710 --- /dev/null +++ b/modules/video/perf/opencl/perf_bgfg_mog2.cpp @@ -0,0 +1,89 @@ +#include "perf_precomp.hpp" +#include "opencv2/ts/ocl_perf.hpp" + +#ifdef HAVE_OPENCL + +#if defined(HAVE_XINE) || \ +defined(HAVE_GSTREAMER) || \ +defined(HAVE_QUICKTIME) || \ +defined(HAVE_AVFOUNDATION) || \ +defined(HAVE_FFMPEG) || \ +defined(WIN32) + +# define BUILD_WITH_VIDEO_INPUT_SUPPORT 1 +#else +# define BUILD_WITH_VIDEO_INPUT_SUPPORT 0 +#endif + +#if BUILD_WITH_VIDEO_INPUT_SUPPORT + +namespace cvtest { +namespace ocl { + +//////////////////////////// Mog2////////////////////////// + +typedef tuple VideoMOG2ParamType; +typedef TestBaseWithParam MOG2_GetBackgroundImage; + +static void cvtFrameFmt(vector& input, vector& output) +{ + for(int i = 0; i< (int)(input.size()); i++) + { + cvtColor(input[i], output[i], COLOR_RGB2GRAY); + } +} + +static void prepareData(VideoCapture& cap, int cn, vector& frame_buffer) +{ + cv::Mat frame; + std::vector frame_buffer_init; + int nFrame = (int)frame_buffer.size(); + for(int i = 0; i < nFrame; i++) + { + cap >> frame; + ASSERT_FALSE(frame.empty()); + frame_buffer_init.push_back(frame); + } + + if(cn == 1) + cvtFrameFmt(frame_buffer_init, frame_buffer); + else + frame_buffer = frame_buffer_init; +} + +OCL_PERF_TEST_P(MOG2_GetBackgroundImage, Mog2, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), Values(1,3))) +{ + VideoMOG2ParamType params = GetParam(); + + const string inputFile = getDataPath(get<0>(params)); + + const int cn = get<1>(params); + int nFrame = 5; + + vector frame_buffer(nFrame); + + cv::VideoCapture cap(inputFile); + ASSERT_TRUE(cap.isOpened()); + prepareData(cap, cn, frame_buffer); + + UMat u_foreground, u_background; + + OCL_TEST_CYCLE() + { + Ptr mog2 = createBackgroundSubtractorMOG2(); + mog2->setDetectShadows(false); + u_foreground.release(); + u_background.release(); + for (int i = 0; i < nFrame; i++) + { + mog2->apply(frame_buffer[i], u_foreground); + } + mog2->getBackgroundImage(u_background); + } + SANITY_CHECK(u_background); +} + +}}// namespace cvtest::ocl + + #endif +#endif \ No newline at end of file diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index 485e34d26..cfdce37ac 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -83,6 +83,7 @@ ///////////*/ #include "precomp.hpp" +#include "opencl_kernels.hpp" namespace cv { @@ -141,6 +142,8 @@ public: fCT = defaultfCT2; nShadowDetection = defaultnShadowDetection2; fTau = defaultfTau; + + opencl_ON = true; } //! the full constructor that takes the length of the history, // the number of gaussian mixtures, the background ratio parameter and the noise strength @@ -165,6 +168,8 @@ public: nShadowDetection = defaultnShadowDetection2; fTau = defaultfTau; name_ = "BackgroundSubtractor.MOG2"; + + opencl_ON = true; } //! the destructor ~BackgroundSubtractorMOG2Impl() {} @@ -184,14 +189,44 @@ public: int nchannels = CV_MAT_CN(frameType); CV_Assert( nchannels <= CV_CN_MAX ); - // for each gaussian mixture of each pixel bg model we store ... - // the mixture weight (w), - // the mean (nchannels values) and - // the covariance - bgmodel.create( 1, frameSize.height*frameSize.width*nmixtures*(2 + nchannels), CV_32F ); - //make the array for keeping track of the used modes per pixel - all zeros at start - bgmodelUsedModes.create(frameSize,CV_8U); - bgmodelUsedModes = Scalar::all(0); + if (ocl::useOpenCL() && opencl_ON) + { + kernel_apply.create("mog2_kernel", ocl::video::bgfg_mog2_oclsrc, format("-D CN=%d -D NMIXTURES=%d", nchannels, nmixtures)); + kernel_getBg.create("getBackgroundImage2_kernel", ocl::video::bgfg_mog2_oclsrc, format( "-D CN=%d -D NMIXTURES=%d", nchannels, nmixtures)); + + if (kernel_apply.empty() || kernel_getBg.empty()) + opencl_ON = false; + } + else opencl_ON = false; + + if (opencl_ON) + { + u_weight.create(frameSize.height * nmixtures, frameSize.width, CV_32FC1); + u_weight.setTo(Scalar::all(0)); + + u_variance.create(frameSize.height * nmixtures, frameSize.width, CV_32FC1); + u_variance.setTo(Scalar::all(0)); + + if (nchannels==3) + nchannels=4; + u_mean.create(frameSize.height * nmixtures, frameSize.width, CV_32FC(nchannels)); //4 channels + u_mean.setTo(Scalar::all(0)); + + //make the array for keeping track of the used modes per pixel - all zeros at start + u_bgmodelUsedModes.create(frameSize, CV_32FC1); + u_bgmodelUsedModes.setTo(cv::Scalar::all(0)); + } + else + { + // for each gaussian mixture of each pixel bg model we store ... + // the mixture weight (w), + // the mean (nchannels values) and + // the covariance + bgmodel.create( 1, frameSize.height*frameSize.width*nmixtures*(2 + nchannels), CV_32F ); + //make the array for keeping track of the used modes per pixel - all zeros at start + bgmodelUsedModes.create(frameSize,CV_8U); + bgmodelUsedModes = Scalar::all(0); + } } virtual AlgorithmInfo* info() const { return 0; } @@ -271,6 +306,19 @@ protected: int frameType; Mat bgmodel; Mat bgmodelUsedModes;//keep track of number of modes per pixel + + //for OCL + + mutable bool opencl_ON; + + UMat u_weight; + UMat u_variance; + UMat u_mean; + UMat u_bgmodelUsedModes; + + mutable ocl::Kernel kernel_apply; + mutable ocl::Kernel kernel_getBg; + int nframes; int history; int nmixtures; @@ -321,6 +369,9 @@ protected: //See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003. String name_; + + bool ocl_getBackgroundImage(OutputArray backgroundImage) const; + bool ocl_apply(InputArray _image, OutputArray _fgmask, bool needToInitialize, double learningRate=-1); }; struct GaussBGStatModel2Params @@ -685,14 +736,78 @@ public: uchar shadowVal; }; +bool BackgroundSubtractorMOG2Impl::ocl_apply(InputArray _image, OutputArray _fgmask, bool needToInitialize, double learningRate) +{ + ++nframes; + learningRate = learningRate >= 0 && nframes > 1 ? learningRate : 1./std::min( 2*nframes, history ); + CV_Assert(learningRate >= 0); + + UMat fgmask(_image.size(), CV_32SC1); + + fgmask.setTo(cv::Scalar::all(1)); + + const float alpha1 = 1.0f - learningRate; + + int detectShadows_flag = 0; + if(bShadowDetection) + detectShadows_flag = 1; + + UMat frame = _image.getUMat(); + + float varMax = MAX(fVarMin, fVarMax); + float varMin = MIN(fVarMin, fVarMax); + + int idxArg = 0; + idxArg = kernel_apply.set(idxArg, ocl::KernelArg::ReadOnly(frame)); + idxArg = kernel_apply.set(idxArg, ocl::KernelArg::ReadWriteNoSize(u_bgmodelUsedModes)); + idxArg = kernel_apply.set(idxArg, ocl::KernelArg::ReadWriteNoSize(u_weight)); + idxArg = kernel_apply.set(idxArg, ocl::KernelArg::ReadWriteNoSize(u_mean)); + idxArg = kernel_apply.set(idxArg, ocl::KernelArg::ReadWriteNoSize(u_variance)); + idxArg = kernel_apply.set(idxArg, ocl::KernelArg::WriteOnlyNoSize(fgmask)); + + idxArg = kernel_apply.set(idxArg, (float)learningRate); //alphaT + idxArg = kernel_apply.set(idxArg, (float)alpha1); + idxArg = kernel_apply.set(idxArg, (float)(-learningRate*fCT)); //prune + idxArg = kernel_apply.set(idxArg, detectShadows_flag); + + idxArg = kernel_apply.set(idxArg, (float)varThreshold); //c_Tb + idxArg = kernel_apply.set(idxArg, backgroundRatio); //c_TB + idxArg = kernel_apply.set(idxArg, varThresholdGen); //c_Tg + idxArg = kernel_apply.set(idxArg, varMin); + idxArg = kernel_apply.set(idxArg, varMax); + idxArg = kernel_apply.set(idxArg, fVarInit); + idxArg = kernel_apply.set(idxArg, fTau); + idxArg = kernel_apply.set(idxArg, nShadowDetection); + + size_t globalsize[] = {frame.cols, frame.rows, 1}; + + if (!(kernel_apply.run(2, globalsize, NULL, true))) + return false; + + _fgmask.create(_image.size(),CV_8U); + UMat temp = _fgmask.getUMat(); + fgmask.convertTo(temp, CV_8U); + + return true; +} + void BackgroundSubtractorMOG2Impl::apply(InputArray _image, OutputArray _fgmask, double learningRate) { - Mat image = _image.getMat(); - bool needToInitialize = nframes == 0 || learningRate >= 1 || image.size() != frameSize || image.type() != frameType; + bool needToInitialize = nframes == 0 || learningRate >= 1 || _image.size() != frameSize || _image.type() != frameType; if( needToInitialize ) - initialize(image.size(), image.type()); + initialize(_image.size(), _image.type()); + if (opencl_ON) + { + if (ocl_apply(_image,_fgmask, needToInitialize, learningRate)) + return; + else + initialize(_image.size(), _image.type()); + } + opencl_ON = false; + + Mat image = _image.getMat(); _fgmask.create( image.size(), CV_8U ); Mat fgmask = _fgmask.getMat(); @@ -712,8 +827,36 @@ void BackgroundSubtractorMOG2Impl::apply(InputArray _image, OutputArray _fgmask, image.total()/(double)(1 << 16)); } +bool BackgroundSubtractorMOG2Impl::ocl_getBackgroundImage(OutputArray _backgroundImage) const +{ + CV_Assert(frameType == CV_8UC1 || frameType == CV_8UC3); + + _backgroundImage.create(frameSize, frameType); + UMat dst = _backgroundImage.getUMat(); + + int idxArg = 0; + idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::ReadOnly(u_bgmodelUsedModes)); + idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::ReadOnlyNoSize(u_weight)); + idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::ReadOnlyNoSize(u_mean)); + idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::WriteOnlyNoSize(dst)); + idxArg = kernel_getBg.set(idxArg, backgroundRatio); + + size_t globalsize[2] = {u_bgmodelUsedModes.cols, u_bgmodelUsedModes.rows}; + + return kernel_getBg.run(2, globalsize, NULL, false); +} + void BackgroundSubtractorMOG2Impl::getBackgroundImage(OutputArray backgroundImage) const { + if (opencl_ON) + { + if (ocl_getBackgroundImage(backgroundImage)); + return; + + opencl_ON = false; + return; + } + int nchannels = CV_MAT_CN(frameType); CV_Assert( nchannels == 3 ); Mat meanBackground(frameSize, CV_8UC3, Scalar::all(0)); @@ -765,7 +908,6 @@ void BackgroundSubtractorMOG2Impl::getBackgroundImage(OutputArray backgroundImag } } - Ptr createBackgroundSubtractorMOG2(int _history, double _varThreshold, bool _bShadowDetection) { @@ -774,4 +916,4 @@ Ptr createBackgroundSubtractorMOG2(int _history, doubl } -/* End of file. */ +/* End of file. */ \ No newline at end of file diff --git a/modules/video/src/opencl/bgfg_mog2.cl b/modules/video/src/opencl/bgfg_mog2.cl new file mode 100644 index 000000000..6ae278bbb --- /dev/null +++ b/modules/video/src/opencl/bgfg_mog2.cl @@ -0,0 +1,272 @@ +#if CN==1 + +#define T_MEAN float +#define F_ZERO (0.0f) +#define cnMode 1 + +#define frameToMean(a, b) (b) = *(a); +#define meanToFrame(a, b) *b = convert_uchar_sat(a); + +inline float sqr(float val) +{ + return val * val; +} + +inline float sum(float val) +{ + return val; +} + +#else + +#define T_MEAN float4 +#define F_ZERO (0.0f, 0.0f, 0.0f, 0.0f) +#define cnMode 4 + +#define meanToFrame(a, b)\ + b[0] = convert_uchar_sat(a.x); \ + b[1] = convert_uchar_sat(a.y); \ + b[2] = convert_uchar_sat(a.z); + +#define frameToMean(a, b)\ + b.x = a[0]; \ + b.y = a[1]; \ + b.z = a[2]; \ + b.w = 0.0f; + +inline float sqr(const float4 val) +{ + return val.x * val.x + val.y * val.y + val.z * val.z; +} + +inline float sum(const float4 val) +{ + return (val.x + val.y + val.z); +} + +inline void swap4(__global float4* ptr, int x, int y, int k, int rows, int ptr_step) +{ + float4 val = ptr[(k * rows + y) * ptr_step + x]; + ptr[(k * rows + y) * ptr_step + x] = ptr[((k + 1) * rows + y) * ptr_step + x]; + ptr[((k + 1) * rows + y) * ptr_step + x] = val; +} + +#endif + +inline void swap(__global float* ptr, int x, int y, int k, int rows, int ptr_step) +{ + float val = ptr[(k * rows + y) * ptr_step + x]; + ptr[(k * rows + y) * ptr_step + x] = ptr[((k + 1) * rows + y) * ptr_step + x]; + ptr[((k + 1) * rows + y) * ptr_step + x] = val; +} + +__kernel void mog2_kernel(__global const uchar* frame, int frame_step, int frame_offset, int frame_row, int frame_col, //uchar || uchar3 + __global uchar* modesUsed, int modesUsed_step, int modesUsed_offset, //int + __global uchar* weight, int weight_step, int weight_offset, //float + __global uchar* mean, int mean_step, int mean_offset, //T_MEAN=float || float4 + __global uchar* variance, int var_step, int var_offset, //float + __global uchar* fgmask, int fgmask_step, int fgmask_offset, //int + float alphaT, float alpha1, float prune, + int detectShadows_flag, + float c_Tb, float c_TB, float c_Tg, float c_varMin, //constants + float c_varMax, float c_varInit, float c_tau, uchar c_shadowVal) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + weight_step/= sizeof(float); + var_step /= sizeof(float); + mean_step /= (sizeof(float)*cnMode); + + if( x < frame_col && y < frame_row) + { + __global const uchar* _frame = (frame + mad24( y, frame_step, x*CN + frame_offset)); + T_MEAN pix; + frameToMean(_frame, pix); + + bool background = false; // true - the pixel classified as background + + bool fitsPDF = false; //if it remains zero a new GMM mode will be added + + __global int* _modesUsed = (__global int*)(modesUsed + mad24( y, modesUsed_step, x*(int)(sizeof(int)))); + int nmodes = _modesUsed[0]; + int nNewModes = nmodes; //current number of modes in GMM + + float totalWeight = 0.0f; + + __global float* _weight = (__global float*)(weight); + __global float* _variance = (__global float*)(variance); + __global T_MEAN* _mean = (__global T_MEAN*)(mean); + + for (int mode = 0; mode < nmodes; ++mode) + { + + float c_weight = alpha1 * _weight[(mode * frame_row + y) * weight_step + x] + prune; + + if (!fitsPDF) + { + float c_var = _variance[(mode * frame_row + y) * var_step + x]; + + T_MEAN c_mean = _mean[(mode * frame_row + y) * mean_step + x]; + + T_MEAN diff = c_mean - pix; + float dist2 = sqr(diff); + + if (totalWeight < c_TB && dist2 < c_Tb * c_var) + background = true; + + if (dist2 < c_Tg * c_var) + { + fitsPDF = true; + c_weight += alphaT; + float k = alphaT / c_weight; + + _mean[(mode * frame_row + y) * mean_step + x] = c_mean - k * diff; + + float varnew = c_var + k * (dist2 - c_var); + varnew = fmax(varnew, c_varMin); + varnew = fmin(varnew, c_varMax); + + _variance[(mode * frame_row + y) * var_step + x] = varnew; + for (int i = mode; i > 0; --i) + { + if (c_weight < _weight[((i - 1) * frame_row + y) * weight_step + x]) + break; + swap(_weight, x, y, i - 1, frame_row, weight_step); + swap(_variance, x, y, i - 1, frame_row, var_step); + #if (CN==1) + swap(_mean, x, y, i - 1, frame_row, mean_step); + #else + swap4(_mean, x, y, i - 1, frame_row, mean_step); + #endif + } + } + } // !fitsPDF + + if (c_weight < -prune) + { + c_weight = 0.0f; + nmodes--; + } + + _weight[(mode * frame_row + y) * weight_step + x] = c_weight; //update weight by the calculated value + totalWeight += c_weight; + } + + totalWeight = 1.f / totalWeight; + for (int mode = 0; mode < nmodes; ++mode) + _weight[(mode * frame_row + y) * weight_step + x] *= totalWeight; + + nmodes = nNewModes; + + if (!fitsPDF) + { + int mode = nmodes == (NMIXTURES) ? (NMIXTURES) - 1 : nmodes++; + + if (nmodes == 1) + _weight[(mode * frame_row + y) * weight_step + x] = 1.f; + else + { + _weight[(mode * frame_row + y) * weight_step + x] = alphaT; + + for (int i = 0; i < nmodes - 1; ++i) + _weight[(i * frame_row + y) * weight_step + x] *= alpha1; + } + + _mean[(mode * frame_row + y) * mean_step + x] = pix; + _variance[(mode * frame_row + y) * var_step + x] = c_varInit; + + for (int i = nmodes - 1; i > 0; --i) + { + if (alphaT < _weight[((i - 1) * frame_row + y) * weight_step + x]) + break; + + swap(_weight, x, y, i - 1, frame_row, weight_step); + swap(_variance, x, y, i - 1, frame_row, var_step); + #if (CN==1) + swap(_mean, x, y, i - 1, frame_row, mean_step); + #else + swap4(_mean, x, y, i - 1, frame_row, mean_step); + #endif + } + } + + _modesUsed[0] = nmodes; + bool isShadow = false; + if (detectShadows_flag && !background) + { + float tWeight = 0.0f; + + for (int mode = 0; mode < nmodes; ++mode) + { + T_MEAN c_mean = _mean[(mode * frame_row + y) * mean_step + x]; + + T_MEAN pix_mean = pix * c_mean; + + float numerator = sum(pix_mean); + float denominator = sqr(c_mean); + + if (denominator == 0) + break; + + if (numerator <= denominator && numerator >= c_tau * denominator) + { + float a = numerator / denominator; + + T_MEAN dD = a * c_mean - pix; + + if (sqr(dD) < c_Tb * _variance[(mode * frame_row + y) * var_step + x] * a * a) + { + isShadow = true; + break; + } + } + + tWeight += _weight[(mode * frame_row + y) * weight_step + x]; + if (tWeight > c_TB) + break; + } + } + __global int* _fgmask = (__global int*)(fgmask + mad24(y, fgmask_step, x*(int)(sizeof(int)) + fgmask_offset)); + *_fgmask = background ? 0 : isShadow ? c_shadowVal : 255; + } +} + +__kernel void getBackgroundImage2_kernel(__global const uchar* modesUsed, int modesUsed_step, int modesUsed_offset, int modesUsed_row, int modesUsed_col, + __global const uchar* weight, int weight_step, int weight_offset, + __global const uchar* mean, int mean_step, int mean_offset, + __global uchar* dst, int dst_step, int dst_offset, + float c_TB) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if(x < modesUsed_col && y < modesUsed_row) + { + __global int* _modesUsed = (__global int*)(modesUsed + mad24( y, modesUsed_step, x*(int)(sizeof(int)))); + int nmodes = _modesUsed[0]; + + T_MEAN meanVal = (T_MEAN)F_ZERO; + + float totalWeight = 0.0f; + + for (int mode = 0; mode < nmodes; ++mode) + { + __global const float* _weight = (__global const float*)(weight + mad24(mode * modesUsed_row + y, weight_step, x*(int)(sizeof(float)))); + float c_weight = _weight[0]; + + __global const T_MEAN* _mean = (__global const T_MEAN*)(mean + mad24(mode * modesUsed_row + y, mean_step, x*(int)(sizeof(float))*cnMode)); + T_MEAN c_mean = _mean[0]; + meanVal = meanVal + c_weight * c_mean; + + totalWeight += c_weight; + + if(totalWeight > c_TB) + break; + } + + meanVal = meanVal * (1.f / totalWeight); + __global uchar* _dst = dst + y * dst_step + x*CN + dst_offset; + meanToFrame(meanVal, _dst); + } +} \ No newline at end of file diff --git a/modules/video/test/ocl/test_bgfg_mog2.cpp b/modules/video/test/ocl/test_bgfg_mog2.cpp new file mode 100644 index 000000000..a0d811b12 --- /dev/null +++ b/modules/video/test/ocl/test_bgfg_mog2.cpp @@ -0,0 +1,125 @@ +#include "test_precomp.hpp" +#include "opencv2/ts/ocl_test.hpp" + +#ifdef HAVE_OPENCL + +#if defined(HAVE_XINE) || \ +defined(HAVE_GSTREAMER) || \ +defined(HAVE_QUICKTIME) || \ +defined(HAVE_AVFOUNDATION) || \ +defined(HAVE_FFMPEG) || \ +defined(WIN32) + +# define BUILD_WITH_VIDEO_INPUT_SUPPORT 1 +#else +# define BUILD_WITH_VIDEO_INPUT_SUPPORT 0 +#endif + +#if BUILD_WITH_VIDEO_INPUT_SUPPORT + +namespace cvtest { +namespace ocl { + +////////////////////////// MOG2/////////////////////////////////// + +namespace +{ + IMPLEMENT_PARAM_CLASS(UseGray, bool) + IMPLEMENT_PARAM_CLASS(DetectShadow, bool) +} + +PARAM_TEST_CASE(Mog2, UseGray, DetectShadow, bool) +{ + bool useGray; + bool detectShadow; + bool useRoi; + virtual void SetUp() + { + useGray = GET_PARAM(0); + detectShadow = GET_PARAM(1); + useRoi = GET_PARAM(2); + } +}; + +OCL_TEST_P(Mog2, Update) +{ + string inputFile = string(TS::ptr()->get_data_path()) + "video/768x576.avi"; + VideoCapture cap(inputFile); + ASSERT_TRUE(cap.isOpened()); + + Ptr mog2_cpu = createBackgroundSubtractorMOG2(); + Ptr mog2_ocl = createBackgroundSubtractorMOG2(); + + mog2_cpu->setDetectShadows(detectShadow); + mog2_ocl->setDetectShadows(detectShadow); + + Mat frame, foreground; + UMat u_foreground; + + for (int i = 0; i < 10; ++i) + { + cap >> frame; + ASSERT_FALSE(frame.empty()); + + if (useGray) + { + Mat temp; + cvtColor(frame, temp, COLOR_BGR2GRAY); + swap(temp, frame); + } + + OCL_OFF(mog2_cpu->apply(frame, foreground)); + OCL_ON (mog2_ocl->apply(frame, u_foreground)); + + if (detectShadow) + EXPECT_MAT_SIMILAR(foreground, u_foreground, 15e-3) + else + EXPECT_MAT_NEAR(foreground, u_foreground, 0); + } +} + +OCL_TEST_P(Mog2, getBackgroundImage) +{ + if (useGray) + return; + + string inputFile = string(TS::ptr()->get_data_path()) + "video/768x576.avi"; + VideoCapture cap(inputFile); + ASSERT_TRUE(cap.isOpened()); + + Ptr mog2_cpu = createBackgroundSubtractorMOG2(); + Ptr mog2_ocl = createBackgroundSubtractorMOG2(); + + mog2_cpu->setDetectShadows(detectShadow); + mog2_ocl->setDetectShadows(detectShadow); + + Mat frame, foreground; + UMat u_foreground; + + for (int i = 0; i < 10; ++i) + { + cap >> frame; + ASSERT_FALSE(frame.empty()); + + OCL_OFF(mog2_cpu->apply(frame, foreground)); + OCL_ON (mog2_ocl->apply(frame, u_foreground)); + } + + Mat background; + OCL_OFF(mog2_cpu->getBackgroundImage(background)); + + UMat u_background; + OCL_ON (mog2_ocl->getBackgroundImage(u_background)); + + EXPECT_MAT_NEAR(background, u_background, 1.0); +} + +OCL_INSTANTIATE_TEST_CASE_P(OCL_Video, Mog2, Combine( + Values(UseGray(true), UseGray(false)), + Values(DetectShadow(true), DetectShadow(false)), + Bool()) + ); +}}// namespace cvtest::ocl + + #endif +#endif From 0edd0aaf69cb06eaaff1f05b3fddcff58f0c4238 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Tue, 28 Jan 2014 16:22:42 +0400 Subject: [PATCH 266/295] fixed --- modules/video/src/bgfg_gaussmix2.cpp | 2 +- modules/video/src/opencl/bgfg_mog2.cl | 2 +- modules/video/test/ocl/test_bgfg_mog2.cpp | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index cfdce37ac..2534645b1 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -852,7 +852,7 @@ void BackgroundSubtractorMOG2Impl::getBackgroundImage(OutputArray backgroundImag { if (ocl_getBackgroundImage(backgroundImage)); return; - + opencl_ON = false; return; } diff --git a/modules/video/src/opencl/bgfg_mog2.cl b/modules/video/src/opencl/bgfg_mog2.cl index 6ae278bbb..f895b5be7 100644 --- a/modules/video/src/opencl/bgfg_mog2.cl +++ b/modules/video/src/opencl/bgfg_mog2.cl @@ -67,7 +67,7 @@ __kernel void mog2_kernel(__global const uchar* frame, int frame_step, int frame __global uchar* variance, int var_step, int var_offset, //float __global uchar* fgmask, int fgmask_step, int fgmask_offset, //int float alphaT, float alpha1, float prune, - int detectShadows_flag, + int detectShadows_flag, float c_Tb, float c_TB, float c_Tg, float c_varMin, //constants float c_varMax, float c_varInit, float c_tau, uchar c_shadowVal) { diff --git a/modules/video/test/ocl/test_bgfg_mog2.cpp b/modules/video/test/ocl/test_bgfg_mog2.cpp index a0d811b12..e9a73cb9b 100644 --- a/modules/video/test/ocl/test_bgfg_mog2.cpp +++ b/modules/video/test/ocl/test_bgfg_mog2.cpp @@ -28,7 +28,7 @@ namespace IMPLEMENT_PARAM_CLASS(DetectShadow, bool) } -PARAM_TEST_CASE(Mog2, UseGray, DetectShadow, bool) +PARAM_TEST_CASE(Mog2, UseGray, DetectShadow) { bool useGray; bool detectShadow; @@ -37,7 +37,6 @@ PARAM_TEST_CASE(Mog2, UseGray, DetectShadow, bool) { useGray = GET_PARAM(0); detectShadow = GET_PARAM(1); - useRoi = GET_PARAM(2); } }; @@ -116,8 +115,7 @@ OCL_TEST_P(Mog2, getBackgroundImage) OCL_INSTANTIATE_TEST_CASE_P(OCL_Video, Mog2, Combine( Values(UseGray(true), UseGray(false)), - Values(DetectShadow(true), DetectShadow(false)), - Bool()) + Values(DetectShadow(true), DetectShadow(false))) ); }}// namespace cvtest::ocl From 5474935a8180f51eee32de7a4174c280b015fff4 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 28 Jan 2014 20:22:56 +0400 Subject: [PATCH 267/295] fixes for defects from code coverity --- modules/core/src/ocl.cpp | 3 ++- modules/imgproc/src/filter.cpp | 2 +- modules/java/generator/gen_java.py | 4 ++-- modules/java/generator/src/cpp/Mat.cpp | 2 +- modules/java/generator/src/cpp/utils.cpp | 4 ++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 7201fca71..1a2714d05 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3673,6 +3673,7 @@ struct PlatformInfo2::Impl { Impl(void* id) { + refcount = 1; handle = *(cl_platform_id*)id; getDevices(devices, handle); } @@ -3713,7 +3714,7 @@ int PlatformInfo2::deviceNumber() const void PlatformInfo2::getDevice(Device& device, int d) const { - CV_Assert(d < (int)p->devices.size() ); + CV_Assert(p && d < (int)p->devices.size() ); if(p) device.set(p->devices[d]); } diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 8c11c62db..d644f2348 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -3508,7 +3508,7 @@ static bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, int type = _src.type(); if ( !( (CV_8UC1 == type || CV_8UC4 == type || CV_32FC1 == type || CV_32FC4 == type) && - (ddepth == CV_32F || ddepth == CV_8U) ) ) + (ddepth == CV_32F || ddepth == CV_8U || ddepth < 0) ) ) return false; int cn = CV_MAT_CN(type); diff --git a/modules/java/generator/gen_java.py b/modules/java/generator/gen_java.py index 23ed3a9a1..cce270828 100755 --- a/modules/java/generator/gen_java.py +++ b/modules/java/generator/gen_java.py @@ -398,7 +398,7 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1minMaxLocManual return result; - } catch(cv::Exception e) { + } catch(const cv::Exception& e) { LOGD("Core::n_1minMaxLoc() catched cv::Exception: %s", e.what()); jclass je = env->FindClass("org/opencv/core/CvException"); if(!je) je = env->FindClass("java/lang/Exception"); @@ -471,7 +471,7 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1getTextSize return result; - } catch(cv::Exception e) { + } catch(const cv::Exception& e) { LOGD("Core::n_1getTextSize() catched cv::Exception: %s", e.what()); jclass je = env->FindClass("org/opencv/core/CvException"); if(!je) je = env->FindClass("java/lang/Exception"); diff --git a/modules/java/generator/src/cpp/Mat.cpp b/modules/java/generator/src/cpp/Mat.cpp index b3b0f66e7..185cb2de9 100644 --- a/modules/java/generator/src/cpp/Mat.cpp +++ b/modules/java/generator/src/cpp/Mat.cpp @@ -467,7 +467,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_n_1dims LOGD("%s", method_name); Mat* me = (Mat*) self; //TODO: check for NULL return me->dims; - } catch(cv::Exception e) { + } catch(const cv::Exception& e) { throwJavaException(env, &e, method_name); } catch (...) { throwJavaException(env, 0, method_name); diff --git a/modules/java/generator/src/cpp/utils.cpp b/modules/java/generator/src/cpp/utils.cpp index 40811e8f9..2d409c863 100644 --- a/modules/java/generator/src/cpp/utils.cpp +++ b/modules/java/generator/src/cpp/utils.cpp @@ -48,7 +48,7 @@ JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat2 } AndroidBitmap_unlockPixels(env, bitmap); return; - } catch(cv::Exception e) { + } catch(const cv::Exception& e) { AndroidBitmap_unlockPixels(env, bitmap); LOGE("nBitmapToMat catched cv::Exception: %s", e.what()); jclass je = env->FindClass("org/opencv/core/CvException"); @@ -130,7 +130,7 @@ JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap2 } AndroidBitmap_unlockPixels(env, bitmap); return; - } catch(cv::Exception e) { + } catch(const cv::Exception& e) { AndroidBitmap_unlockPixels(env, bitmap); LOGE("nMatToBitmap catched cv::Exception: %s", e.what()); jclass je = env->FindClass("org/opencv/core/CvException"); From 41bc5808c0cc59992ddf3f1b88dc45774d86d74c Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 28 Jan 2014 23:10:43 +0400 Subject: [PATCH 268/295] optimized createHanningWindow --- modules/imgproc/perf/perf_phasecorr.cpp | 22 ++++++++++++++++++++++ modules/imgproc/src/phasecorr.cpp | 24 ++++++++++++------------ 2 files changed, 34 insertions(+), 12 deletions(-) create mode 100644 modules/imgproc/perf/perf_phasecorr.cpp diff --git a/modules/imgproc/perf/perf_phasecorr.cpp b/modules/imgproc/perf/perf_phasecorr.cpp new file mode 100644 index 000000000..ee9d94e31 --- /dev/null +++ b/modules/imgproc/perf/perf_phasecorr.cpp @@ -0,0 +1,22 @@ +#include "perf_precomp.hpp" + +using namespace std; +using namespace cv; +using namespace perf; +using namespace testing; +using std::tr1::make_tuple; +using std::tr1::get; + +typedef TestBaseWithParam CreateHanningWindowFixture; + +PERF_TEST_P( CreateHanningWindowFixture, CreateHanningWindow, Values(szVGA, sz1080p)) +{ + const Size size = GetParam(); + Mat dst(size, CV_32FC1); + + declare.in(dst, WARMUP_RNG).out(dst); + + TEST_CYCLE() cv::createHanningWindow(dst, size, CV_32FC1); + + SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); +} diff --git a/modules/imgproc/src/phasecorr.cpp b/modules/imgproc/src/phasecorr.cpp index d21a4938f..f513e84e2 100644 --- a/modules/imgproc/src/phasecorr.cpp +++ b/modules/imgproc/src/phasecorr.cpp @@ -576,20 +576,23 @@ void cv::createHanningWindow(OutputArray _dst, cv::Size winSize, int type) _dst.create(winSize, type); Mat dst = _dst.getMat(); - int rows = dst.rows; - int cols = dst.cols; + int rows = dst.rows, cols = dst.cols; + + AutoBuffer _wc(cols); + double * const wc = (double *)_wc; + + double coeff0 = 2.0 * CV_PI / (double)(cols - 1), coeff1 = 2.0f * CV_PI / (double)(rows - 1); + for(int j = 0; j < cols; j++) + wc[j] = 0.5 * (1.0 - cos(coeff0 * j)); if(dst.depth() == CV_32F) { for(int i = 0; i < rows; i++) { float* dstData = dst.ptr(i); - double wr = 0.5 * (1.0f - cos(2.0f * CV_PI * (double)i / (double)(rows - 1))); + double wr = 0.5 * (1.0 - cos(coeff1 * i)); for(int j = 0; j < cols; j++) - { - double wc = 0.5 * (1.0f - cos(2.0f * CV_PI * (double)j / (double)(cols - 1))); - dstData[j] = (float)(wr * wc); - } + dstData[j] = (float)(wr * wc[j]); } } else @@ -597,12 +600,9 @@ void cv::createHanningWindow(OutputArray _dst, cv::Size winSize, int type) for(int i = 0; i < rows; i++) { double* dstData = dst.ptr(i); - double wr = 0.5 * (1.0 - cos(2.0 * CV_PI * (double)i / (double)(rows - 1))); + double wr = 0.5 * (1.0 - cos(coeff1 * i)); for(int j = 0; j < cols; j++) - { - double wc = 0.5 * (1.0 - cos(2.0 * CV_PI * (double)j / (double)(cols - 1))); - dstData[j] = wr * wc; - } + dstData[j] = wr * wc[j]; } } From 17c6b4d306486bfc4dfe3d6dce951d9d30ff8e66 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Wed, 29 Jan 2014 11:05:05 +0400 Subject: [PATCH 269/295] fixed warnings --- modules/video/src/bgfg_gaussmix2.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index 2534645b1..947f72031 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -371,7 +371,7 @@ protected: String name_; bool ocl_getBackgroundImage(OutputArray backgroundImage) const; - bool ocl_apply(InputArray _image, OutputArray _fgmask, bool needToInitialize, double learningRate=-1); + bool ocl_apply(InputArray _image, OutputArray _fgmask, double learningRate=-1); }; struct GaussBGStatModel2Params @@ -736,7 +736,7 @@ public: uchar shadowVal; }; -bool BackgroundSubtractorMOG2Impl::ocl_apply(InputArray _image, OutputArray _fgmask, bool needToInitialize, double learningRate) +bool BackgroundSubtractorMOG2Impl::ocl_apply(InputArray _image, OutputArray _fgmask, double learningRate) { ++nframes; learningRate = learningRate >= 0 && nframes > 1 ? learningRate : 1./std::min( 2*nframes, history ); @@ -746,7 +746,7 @@ bool BackgroundSubtractorMOG2Impl::ocl_apply(InputArray _image, OutputArray _fgm fgmask.setTo(cv::Scalar::all(1)); - const float alpha1 = 1.0f - learningRate; + const double alpha1 = 1.0f - learningRate; int detectShadows_flag = 0; if(bShadowDetection) @@ -800,7 +800,7 @@ void BackgroundSubtractorMOG2Impl::apply(InputArray _image, OutputArray _fgmask, if (opencl_ON) { - if (ocl_apply(_image,_fgmask, needToInitialize, learningRate)) + if (ocl_apply(_image, _fgmask, learningRate)) return; else initialize(_image.size(), _image.type()); @@ -850,7 +850,7 @@ void BackgroundSubtractorMOG2Impl::getBackgroundImage(OutputArray backgroundImag { if (opencl_ON) { - if (ocl_getBackgroundImage(backgroundImage)); + if (ocl_getBackgroundImage(backgroundImage)) return; opencl_ON = false; From 7c96d98a24b08e2a1739ba34d612816b0d53e7b7 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 29 Jan 2014 00:10:06 +0400 Subject: [PATCH 270/295] implemented OpenCL version of cv::accumulate**** --- .../include/opencv2/core/opencl/ocl_defs.hpp | 9 + modules/imgproc/src/accum.cpp | 128 ++++++++-- modules/imgproc/src/opencl/accumulate.cl | 65 +++++ modules/imgproc/test/ocl/test_accumulate.cpp | 240 ++++++++++++++++++ modules/imgproc/test/ocl/test_blend.cpp | 5 +- 5 files changed, 421 insertions(+), 26 deletions(-) create mode 100644 modules/imgproc/src/opencl/accumulate.cl create mode 100644 modules/imgproc/test/ocl/test_accumulate.cpp diff --git a/modules/core/include/opencv2/core/opencl/ocl_defs.hpp b/modules/core/include/opencv2/core/opencl/ocl_defs.hpp index 1c5ca58c1..55abd7cd8 100644 --- a/modules/core/include/opencv2/core/opencl/ocl_defs.hpp +++ b/modules/core/include/opencv2/core/opencl/ocl_defs.hpp @@ -22,6 +22,15 @@ fflush(stdout); \ } \ } +#elif defined CV_OPENCL_RUN_ASSERT +#define CV_OCL_RUN_(condition, func, ...) \ + { \ + if (cv::ocl::useOpenCL() && (condition)) \ + { \ + CV_Assert(func); \ + return; \ + } \ + } #else #define CV_OCL_RUN_(condition, func, ...) \ if (cv::ocl::useOpenCL() && (condition) && func) \ diff --git a/modules/imgproc/src/accum.cpp b/modules/imgproc/src/accum.cpp index 0ed2b3fed..4d13ce244 100644 --- a/modules/imgproc/src/accum.cpp +++ b/modules/imgproc/src/accum.cpp @@ -41,6 +41,7 @@ //M*/ #include "precomp.hpp" +#include "opencl_kernels.hpp" namespace cv { @@ -352,15 +353,83 @@ inline int getAccTabIdx(int sdepth, int ddepth) sdepth == CV_64F && ddepth == CV_64F ? 6 : -1; } +#ifdef HAVE_OPENCL + +enum +{ + ACCUMULATE = 0, + ACCUMULATE_SQUARE = 1, + ACCUMULATE_PRODUCT = 2, + ACCUMULATE_WEIGHTED = 3 +}; + +static bool ocl_accumulate( InputArray _src, InputArray _src2, InputOutputArray _dst, double alpha, + InputArray _mask, int op_type ) +{ + CV_Assert(op_type == ACCUMULATE || op_type == ACCUMULATE_SQUARE || + op_type == ACCUMULATE_PRODUCT || op_type == ACCUMULATE_WEIGHTED); + + int stype = _src.type(), cn = CV_MAT_CN(stype); + int sdepth = CV_MAT_DEPTH(stype), ddepth = _dst.depth(); + + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0, + haveMask = !_mask.empty(); + + if (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F)) + return false; + + const char * const opMap[4] = { "ACCUMULATE", "ACCUMULATE_SQUARE", "ACCUMULATE_PRODUCT", + "ACCUMULATE_WEIGHTED" }; + + ocl::Kernel k("accumulate", ocl::imgproc::accumulate_oclsrc, + format("-D %s%s -D srcT=%s -D cn=%d -D dstT=%s%s", + opMap[op_type], haveMask ? " -D HAVE_MASK" : "", + ocl::typeToStr(sdepth), cn, ocl::typeToStr(ddepth), + doubleSupport ? " -D DOUBLE_SUPPORT" : "")); + if (k.empty()) + return false; + + UMat src = _src.getUMat(), src2 = _src2.getUMat(), dst = _dst.getUMat(), mask = _mask.getUMat(); + + ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src), + src2arg = ocl::KernelArg::ReadOnlyNoSize(src2), + dstarg = ocl::KernelArg::ReadWrite(dst), + maskarg = ocl::KernelArg::ReadOnlyNoSize(mask); + + int argidx = k.set(0, srcarg); + if (op_type == ACCUMULATE_PRODUCT) + argidx = k.set(argidx, src2arg); + argidx = k.set(argidx, dstarg); + if (op_type == ACCUMULATE_WEIGHTED) + { + if (ddepth == CV_32F) + argidx = k.set(argidx, (float)alpha); + else + argidx = k.set(argidx, alpha); + } + if (haveMask) + argidx = k.set(argidx, maskarg); + + size_t globalsize[2] = { src.cols, src.rows }; + return k.run(2, globalsize, NULL, false); +} + +#endif + } void cv::accumulate( InputArray _src, InputOutputArray _dst, InputArray _mask ) { - Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat(); - int sdepth = src.depth(), ddepth = dst.depth(), cn = src.channels(); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); + int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype); - CV_Assert( dst.size == src.size && dst.channels() == cn ); - CV_Assert( mask.empty() || (mask.size == src.size && mask.type() == CV_8U) ); + CV_Assert( _src.sameSize(_dst) && dcn == scn ); + CV_Assert( _mask.empty() || (_src.sameSize(_mask) && _mask.type() == CV_8U) ); + + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_accumulate(_src, noArray(), _dst, 0.0, _mask, ACCUMULATE)) + + Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat(); int fidx = getAccTabIdx(sdepth, ddepth); AccFunc func = fidx >= 0 ? accTab[fidx] : 0; @@ -372,17 +441,21 @@ void cv::accumulate( InputArray _src, InputOutputArray _dst, InputArray _mask ) int len = (int)it.size; for( size_t i = 0; i < it.nplanes; i++, ++it ) - func(ptrs[0], ptrs[1], ptrs[2], len, cn); + func(ptrs[0], ptrs[1], ptrs[2], len, scn); } - void cv::accumulateSquare( InputArray _src, InputOutputArray _dst, InputArray _mask ) { - Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat(); - int sdepth = src.depth(), ddepth = dst.depth(), cn = src.channels(); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); + int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype); - CV_Assert( dst.size == src.size && dst.channels() == cn ); - CV_Assert( mask.empty() || (mask.size == src.size && mask.type() == CV_8U) ); + CV_Assert( _src.sameSize(_dst) && dcn == scn ); + CV_Assert( _mask.empty() || (_src.sameSize(_mask) && _mask.type() == CV_8U) ); + + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_accumulate(_src, noArray(), _dst, 0.0, _mask, ACCUMULATE_SQUARE)) + + Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat(); int fidx = getAccTabIdx(sdepth, ddepth); AccFunc func = fidx >= 0 ? accSqrTab[fidx] : 0; @@ -394,18 +467,23 @@ void cv::accumulateSquare( InputArray _src, InputOutputArray _dst, InputArray _m int len = (int)it.size; for( size_t i = 0; i < it.nplanes; i++, ++it ) - func(ptrs[0], ptrs[1], ptrs[2], len, cn); + func(ptrs[0], ptrs[1], ptrs[2], len, scn); } void cv::accumulateProduct( InputArray _src1, InputArray _src2, InputOutputArray _dst, InputArray _mask ) { - Mat src1 = _src1.getMat(), src2 = _src2.getMat(), dst = _dst.getMat(), mask = _mask.getMat(); - int sdepth = src1.depth(), ddepth = dst.depth(), cn = src1.channels(); + int stype = _src1.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); + int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype); - CV_Assert( src2.size && src1.size && src2.type() == src1.type() ); - CV_Assert( dst.size == src1.size && dst.channels() == cn ); - CV_Assert( mask.empty() || (mask.size == src1.size && mask.type() == CV_8U) ); + CV_Assert( _src1.sameSize(_src2) && stype == _src2.type() ); + CV_Assert( _src1.sameSize(_dst) && dcn == scn ); + CV_Assert( _mask.empty() || (_src1.sameSize(_mask) && _mask.type() == CV_8U) ); + + CV_OCL_RUN(_src1.dims() <= 2 && _dst.isUMat(), + ocl_accumulate(_src1, _src2, _dst, 0.0, _mask, ACCUMULATE_PRODUCT)) + + Mat src1 = _src1.getMat(), src2 = _src2.getMat(), dst = _dst.getMat(), mask = _mask.getMat(); int fidx = getAccTabIdx(sdepth, ddepth); AccProdFunc func = fidx >= 0 ? accProdTab[fidx] : 0; @@ -417,18 +495,22 @@ void cv::accumulateProduct( InputArray _src1, InputArray _src2, int len = (int)it.size; for( size_t i = 0; i < it.nplanes; i++, ++it ) - func(ptrs[0], ptrs[1], ptrs[2], ptrs[3], len, cn); + func(ptrs[0], ptrs[1], ptrs[2], ptrs[3], len, scn); } - void cv::accumulateWeighted( InputArray _src, InputOutputArray _dst, double alpha, InputArray _mask ) { - Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat(); - int sdepth = src.depth(), ddepth = dst.depth(), cn = src.channels(); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype); + int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype); - CV_Assert( dst.size == src.size && dst.channels() == cn ); - CV_Assert( mask.empty() || (mask.size == src.size && mask.type() == CV_8U) ); + CV_Assert( _src.sameSize(_dst) && dcn == scn ); + CV_Assert( _mask.empty() || (_src.sameSize(_mask) && _mask.type() == CV_8U) ); + + CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), + ocl_accumulate(_src, noArray(), _dst, alpha, _mask, ACCUMULATE_WEIGHTED)) + + Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat(); int fidx = getAccTabIdx(sdepth, ddepth); AccWFunc func = fidx >= 0 ? accWTab[fidx] : 0; @@ -440,7 +522,7 @@ void cv::accumulateWeighted( InputArray _src, InputOutputArray _dst, int len = (int)it.size; for( size_t i = 0; i < it.nplanes; i++, ++it ) - func(ptrs[0], ptrs[1], ptrs[2], len, cn, alpha); + func(ptrs[0], ptrs[1], ptrs[2], len, scn, alpha); } diff --git a/modules/imgproc/src/opencl/accumulate.cl b/modules/imgproc/src/opencl/accumulate.cl new file mode 100644 index 000000000..a60d4d6d9 --- /dev/null +++ b/modules/imgproc/src/opencl/accumulate.cl @@ -0,0 +1,65 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +// Copyright (C) 2014, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. + +#ifdef DOUBLE_SUPPORT +#ifdef cl_amd_fp64 +#pragma OPENCL EXTENSION cl_amd_fp64:enable +#elif defined (cl_khr_fp64) +#pragma OPENCL EXTENSION cl_khr_fp64:enable +#endif +#endif + +__kernel void accumulate(__global const uchar * srcptr, int src_step, int src_offset, +#ifdef ACCUMULATE_PRODUCT + __global const uchar * src2ptr, int src2_step, int src2_offset, +#endif + __global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols +#ifdef ACCUMULATE_WEIGHTED + , dstT alpha +#endif +#ifdef HAVE_MASK + , __global const uchar * mask, int mask_step, int mask_offset +#endif + ) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if (x < dst_cols && y < dst_rows) + { + int src_index = mad24(y, src_step, src_offset + x * cn * (int)sizeof(srcT)); +#ifdef HAVE_MASK + int mask_index = mad24(y, mask_step, mask_offset + x); + mask += mask_index; +#endif + int dst_index = mad24(y, dst_step, dst_offset + x * cn * (int)sizeof(dstT)); + + __global const srcT * src = (__global const srcT *)(srcptr + src_index); +#ifdef ACCUMULATE_PRODUCT + int src2_index = mad24(y, src2_step, src2_offset + x * cn * (int)sizeof(srcT)); + __global const srcT * src2 = (__global const srcT *)(src2ptr + src2_index); +#endif + __global dstT * dst = (__global dstT *)(dstptr + dst_index); + + #pragma unroll + for (int c = 0; c < cn; ++c) +#ifdef HAVE_MASK + if (mask[0]) +#endif +#ifdef ACCUMULATE + dst[c] += src[c]; +#elif defined ACCUMULATE_SQUARE + dst[c] += src[c] * src[c]; +#elif defined ACCUMULATE_PRODUCT + dst[c] += src[c] * src2[c]; +#elif defined ACCUMULATE_WEIGHTED + dst[c] = (1 - alpha) * dst[c] + src[c] * alpha; +#else +#error "Unknown accumulation type" +#endif + } +} diff --git a/modules/imgproc/test/ocl/test_accumulate.cpp b/modules/imgproc/test/ocl/test_accumulate.cpp new file mode 100644 index 000000000..586c34b26 --- /dev/null +++ b/modules/imgproc/test/ocl/test_accumulate.cpp @@ -0,0 +1,240 @@ +/*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 +// Nathan, liujun@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 "test_precomp.hpp" +#include "cvconfig.h" +#include "opencv2/ts/ocl_test.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +PARAM_TEST_CASE(AccumulateBase, std::pair, Channels, bool) +{ + int sdepth, ddepth, channels; + bool useRoi; + double alpha; + + TEST_DECLARE_INPUT_PARAMETER(src) + TEST_DECLARE_INPUT_PARAMETER(mask) + TEST_DECLARE_INPUT_PARAMETER(src2) + TEST_DECLARE_OUTPUT_PARAMETER(dst) + + virtual void SetUp() + { + const std::pair depths = GET_PARAM(0); + sdepth = depths.first, ddepth = depths.second; + channels = GET_PARAM(1); + useRoi = GET_PARAM(2); + } + + void random_roi() + { + const int stype = CV_MAKE_TYPE(sdepth, channels), + dtype = CV_MAKE_TYPE(ddepth, channels); + + Size roiSize = randomSize(1, 10); + Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, stype, -MAX_VALUE, MAX_VALUE); + + Border maskBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(mask, mask_roi, roiSize, maskBorder, CV_8UC1, -MAX_VALUE, MAX_VALUE); + threshold(mask, mask, 80, 255, THRESH_BINARY); + + Border src2Border = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(src2, src2_roi, roiSize, src2Border, stype, -MAX_VALUE, MAX_VALUE); + + Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(dst, dst_roi, roiSize, dstBorder, dtype, -MAX_VALUE, MAX_VALUE); + + UMAT_UPLOAD_INPUT_PARAMETER(src) + UMAT_UPLOAD_INPUT_PARAMETER(mask) + UMAT_UPLOAD_INPUT_PARAMETER(src2) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst) + + alpha = randomDouble(-5, 5); + } +}; + +/////////////////////////////////// Accumulate /////////////////////////////////// + +typedef AccumulateBase Accumulate; + +OCL_TEST_P(Accumulate, Mat) +{ + for (int i = 0; i < test_loop_times; ++i) + { + random_roi(); + + OCL_OFF(cv::accumulate(src_roi, dst_roi)); + OCL_ON(cv::accumulate(usrc_roi, udst_roi)); + + OCL_EXPECT_MATS_NEAR(dst, 1e-6); + } +} + +OCL_TEST_P(Accumulate, Mask) +{ + for (int i = 0; i < test_loop_times; ++i) + { + random_roi(); + + OCL_OFF(cv::accumulate(src_roi, dst_roi, mask_roi)); + OCL_ON(cv::accumulate(usrc_roi, udst_roi, umask_roi)); + + OCL_EXPECT_MATS_NEAR(dst, 1e-6); + } +} + +/////////////////////////////////// AccumulateSquare /////////////////////////////////// + +typedef AccumulateBase AccumulateSquare; + +OCL_TEST_P(AccumulateSquare, Mat) +{ + for (int i = 0; i < test_loop_times; ++i) + { + random_roi(); + + OCL_OFF(cv::accumulateSquare(src_roi, dst_roi)); + OCL_ON(cv::accumulateSquare(usrc_roi, udst_roi)); + + OCL_EXPECT_MATS_NEAR(dst, 1e-2); + } +} + +OCL_TEST_P(AccumulateSquare, Mask) +{ + for (int i = 0; i < test_loop_times; ++i) + { + random_roi(); + + OCL_OFF(cv::accumulateSquare(src_roi, dst_roi, mask_roi)); + OCL_ON(cv::accumulateSquare(usrc_roi, udst_roi, umask_roi)); + + OCL_EXPECT_MATS_NEAR(dst, 1e-2); + } +} + +/////////////////////////////////// AccumulateProduct /////////////////////////////////// + +typedef AccumulateBase AccumulateProduct; + +OCL_TEST_P(AccumulateProduct, Mat) +{ + for (int i = 0; i < test_loop_times; ++i) + { + random_roi(); + + OCL_OFF(cv::accumulateProduct(src_roi, src2_roi, dst_roi)); + OCL_ON(cv::accumulateProduct(usrc_roi, usrc2_roi, udst_roi)); + + OCL_EXPECT_MATS_NEAR(dst, 1e-2); + } +} + +OCL_TEST_P(AccumulateProduct, Mask) +{ + for (int i = 0; i < test_loop_times; ++i) + { + random_roi(); + + OCL_OFF(cv::accumulateProduct(src_roi, src2_roi, dst_roi, mask_roi)); + OCL_ON(cv::accumulateProduct(usrc_roi, usrc2_roi, udst_roi, umask_roi)); + + OCL_EXPECT_MATS_NEAR(dst, 1e-2); + } +} + +/////////////////////////////////// AccumulateWeighted /////////////////////////////////// + +typedef AccumulateBase AccumulateWeighted; + +OCL_TEST_P(AccumulateWeighted, Mat) +{ + for (int i = 0; i < test_loop_times; ++i) + { + random_roi(); + + OCL_OFF(cv::accumulateWeighted(src_roi, dst_roi, alpha)); + OCL_ON(cv::accumulateWeighted(usrc_roi, udst_roi, alpha)); + + OCL_EXPECT_MATS_NEAR(dst, 1e-2); + } +} + +OCL_TEST_P(AccumulateWeighted, Mask) +{ + for (int i = 0; i < test_loop_times; ++i) + { + random_roi(); + + OCL_OFF(cv::accumulateWeighted(src_roi, dst_roi, alpha)); + OCL_ON(cv::accumulateWeighted(usrc_roi, udst_roi, alpha)); + + OCL_EXPECT_MATS_NEAR(dst, 1e-2); + } +} + +/////////////////////////////////// Instantiation /////////////////////////////////// + +#define OCL_DEPTH_ALL_COMBINATIONS \ + testing::Values(std::make_pair(CV_8U, CV_32F), \ + std::make_pair(CV_16U, CV_32F), \ + std::make_pair(CV_32F, CV_32F), \ + std::make_pair(CV_8U, CV_64F), \ + std::make_pair(CV_16U, CV_64F), \ + std::make_pair(CV_32F, CV_64F), \ + std::make_pair(CV_64F, CV_64F)) + +OCL_INSTANTIATE_TEST_CASE_P(ImgProc, Accumulate, Combine(OCL_DEPTH_ALL_COMBINATIONS, OCL_ALL_CHANNELS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(ImgProc, AccumulateSquare, Combine(OCL_DEPTH_ALL_COMBINATIONS, OCL_ALL_CHANNELS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(ImgProc, AccumulateProduct, Combine(OCL_DEPTH_ALL_COMBINATIONS, OCL_ALL_CHANNELS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(ImgProc, AccumulateWeighted, Combine(OCL_DEPTH_ALL_COMBINATIONS, OCL_ALL_CHANNELS, Bool())); + +} } // namespace cvtest::ocl + +#endif diff --git a/modules/imgproc/test/ocl/test_blend.cpp b/modules/imgproc/test/ocl/test_blend.cpp index 4cfe486d2..17c0b1312 100644 --- a/modules/imgproc/test/ocl/test_blend.cpp +++ b/modules/imgproc/test/ocl/test_blend.cpp @@ -75,7 +75,7 @@ PARAM_TEST_CASE(BlendLinear, MatDepth, Channels, bool) const int type = CV_MAKE_TYPE(depth, channels); const double upValue = 256; - Size roiSize = randomSize(1, 20); + Size roiSize = randomSize(1, MAX_VALUE); Border src1Border = randomBorder(0, useRoi ? MAX_VALUE : 0); randomSubMat(src1, src1_roi, roiSize, src1Border, type, -upValue, upValue); @@ -104,8 +104,7 @@ PARAM_TEST_CASE(BlendLinear, MatDepth, Channels, bool) void Near(double eps = 0.0) { - EXPECT_MAT_NEAR(dst, udst, eps); - EXPECT_MAT_NEAR(dst_roi, udst_roi, eps); + OCL_EXPECT_MATS_NEAR(dst, eps) } }; From 96b6f338e14eb7dcf4ef5a06b203ca9b3fe32ec9 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Wed, 29 Jan 2014 14:10:36 +0400 Subject: [PATCH 271/295] fixed --- modules/video/perf/opencl/perf_bgfg_mog2.cpp | 33 +++++++++++- modules/video/src/bgfg_gaussmix2.cpp | 54 ++++++++++---------- 2 files changed, 60 insertions(+), 27 deletions(-) diff --git a/modules/video/perf/opencl/perf_bgfg_mog2.cpp b/modules/video/perf/opencl/perf_bgfg_mog2.cpp index b74643710..50814bf81 100644 --- a/modules/video/perf/opencl/perf_bgfg_mog2.cpp +++ b/modules/video/perf/opencl/perf_bgfg_mog2.cpp @@ -23,6 +23,7 @@ namespace ocl { //////////////////////////// Mog2////////////////////////// typedef tuple VideoMOG2ParamType; +typedef TestBaseWithParam MOG2_Apply; typedef TestBaseWithParam MOG2_GetBackgroundImage; static void cvtFrameFmt(vector& input, vector& output) @@ -51,7 +52,37 @@ static void prepareData(VideoCapture& cap, int cn, vector& frame_buffer) frame_buffer = frame_buffer_init; } -OCL_PERF_TEST_P(MOG2_GetBackgroundImage, Mog2, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), Values(1,3))) +OCL_PERF_TEST_P(MOG2_Apply, Mog2, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), Values(1,3))) +{ + VideoMOG2ParamType params = GetParam(); + + const string inputFile = getDataPath(get<0>(params)); + + const int cn = get<1>(params); + int nFrame = 5; + + vector frame_buffer(nFrame); + + cv::VideoCapture cap(inputFile); + ASSERT_TRUE(cap.isOpened()); + prepareData(cap, cn, frame_buffer); + + UMat u_foreground; + + OCL_TEST_CYCLE() + { + Ptr mog2 = createBackgroundSubtractorMOG2(); + mog2->setDetectShadows(false); + u_foreground.release(); + for (int i = 0; i < nFrame; i++) + { + mog2->apply(frame_buffer[i], u_foreground); + } + } + SANITY_CHECK(u_foreground); +} + +OCL_PERF_TEST_P(MOG2_GetBackgroundImage, Mog2, Combine(Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), Values(3))) { VideoMOG2ParamType params = GetParam(); diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index 947f72031..8650de9e4 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -736,6 +736,8 @@ public: uchar shadowVal; }; +#ifdef HAVE_OPENCL + bool BackgroundSubtractorMOG2Impl::ocl_apply(InputArray _image, OutputArray _fgmask, double learningRate) { ++nframes; @@ -791,6 +793,27 @@ bool BackgroundSubtractorMOG2Impl::ocl_apply(InputArray _image, OutputArray _fgm return true; } +bool BackgroundSubtractorMOG2Impl::ocl_getBackgroundImage(OutputArray _backgroundImage) const +{ + CV_Assert(frameType == CV_8UC1 || frameType == CV_8UC3); + + _backgroundImage.create(frameSize, frameType); + UMat dst = _backgroundImage.getUMat(); + + int idxArg = 0; + idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::ReadOnly(u_bgmodelUsedModes)); + idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::ReadOnlyNoSize(u_weight)); + idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::ReadOnlyNoSize(u_mean)); + idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::WriteOnlyNoSize(dst)); + idxArg = kernel_getBg.set(idxArg, backgroundRatio); + + size_t globalsize[2] = {u_bgmodelUsedModes.cols, u_bgmodelUsedModes.rows}; + + return kernel_getBg.run(2, globalsize, NULL, false); +} + +#endif + void BackgroundSubtractorMOG2Impl::apply(InputArray _image, OutputArray _fgmask, double learningRate) { bool needToInitialize = nframes == 0 || learningRate >= 1 || _image.size() != frameSize || _image.type() != frameType; @@ -800,12 +823,11 @@ void BackgroundSubtractorMOG2Impl::apply(InputArray _image, OutputArray _fgmask, if (opencl_ON) { - if (ocl_apply(_image, _fgmask, learningRate)) - return; - else - initialize(_image.size(), _image.type()); + CV_OCL_RUN(opencl_ON, ocl_apply(_image, _fgmask, learningRate)) + + opencl_ON = false; + initialize(_image.size(), _image.type()); } - opencl_ON = false; Mat image = _image.getMat(); _fgmask.create( image.size(), CV_8U ); @@ -827,31 +849,11 @@ void BackgroundSubtractorMOG2Impl::apply(InputArray _image, OutputArray _fgmask, image.total()/(double)(1 << 16)); } -bool BackgroundSubtractorMOG2Impl::ocl_getBackgroundImage(OutputArray _backgroundImage) const -{ - CV_Assert(frameType == CV_8UC1 || frameType == CV_8UC3); - - _backgroundImage.create(frameSize, frameType); - UMat dst = _backgroundImage.getUMat(); - - int idxArg = 0; - idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::ReadOnly(u_bgmodelUsedModes)); - idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::ReadOnlyNoSize(u_weight)); - idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::ReadOnlyNoSize(u_mean)); - idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::WriteOnlyNoSize(dst)); - idxArg = kernel_getBg.set(idxArg, backgroundRatio); - - size_t globalsize[2] = {u_bgmodelUsedModes.cols, u_bgmodelUsedModes.rows}; - - return kernel_getBg.run(2, globalsize, NULL, false); -} - void BackgroundSubtractorMOG2Impl::getBackgroundImage(OutputArray backgroundImage) const { if (opencl_ON) { - if (ocl_getBackgroundImage(backgroundImage)) - return; + CV_OCL_RUN(opencl_ON, ocl_getBackgroundImage(backgroundImage)) opencl_ON = false; return; From 97092e31bc326f8fb8ac8a7f72a104a19e6cecd7 Mon Sep 17 00:00:00 2001 From: Cosmin Boaca Date: Wed, 29 Jan 2014 13:57:51 +0200 Subject: [PATCH 272/295] Added result_probabilities parameter to CvNormalBayesClassifier::predict method. Issue #3401 --- modules/ml/doc/normal_bayes_classifier.rst | 6 +-- modules/ml/include/opencv2/ml.hpp | 4 +- modules/ml/src/nbayes.cpp | 50 ++++++++++++++++++---- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/modules/ml/doc/normal_bayes_classifier.rst b/modules/ml/doc/normal_bayes_classifier.rst index a247598fa..dbd6ae229 100644 --- a/modules/ml/doc/normal_bayes_classifier.rst +++ b/modules/ml/doc/normal_bayes_classifier.rst @@ -52,12 +52,12 @@ CvNormalBayesClassifier::predict -------------------------------- Predicts the response for sample(s). -.. ocv:function:: float CvNormalBayesClassifier::predict( const Mat& samples, Mat* results=0 ) const +.. ocv:function:: float CvNormalBayesClassifier::predict( const Mat& samples, Mat* results=0, Mat* results_prob=0 ) const -.. ocv:function:: float CvNormalBayesClassifier::predict( const CvMat* samples, CvMat* results=0 ) const +.. ocv:function:: float CvNormalBayesClassifier::predict( const CvMat* samples, CvMat* results=0, CvMat* results_prob=0 ) const .. ocv:pyfunction:: cv2.NormalBayesClassifier.predict(samples) -> retval, results -The method estimates the most probable classes for input vectors. Input vectors (one or more) are stored as rows of the matrix ``samples``. In case of multiple input vectors, there should be one output vector ``results``. The predicted class for a single input vector is returned by the method. +The method estimates the most probable classes for input vectors. Input vectors (one or more) are stored as rows of the matrix ``samples``. In case of multiple input vectors, there should be one output vector ``results``. The predicted class for a single input vector is returned by the method. The vector ``results_prob`` contains the output probabilities coresponding to each element of ``result``. The function is parallelized with the TBB library. diff --git a/modules/ml/include/opencv2/ml.hpp b/modules/ml/include/opencv2/ml.hpp index 42b90d22d..52ddc8cfd 100644 --- a/modules/ml/include/opencv2/ml.hpp +++ b/modules/ml/include/opencv2/ml.hpp @@ -201,7 +201,7 @@ public: virtual bool train( const CvMat* trainData, const CvMat* responses, const CvMat* varIdx = 0, const CvMat* sampleIdx=0, bool update=false ); - virtual float predict( const CvMat* samples, CV_OUT CvMat* results=0 ) const; + virtual float predict( const CvMat* samples, CV_OUT CvMat* results=0, CV_OUT CvMat* results_prob=0 ) const; CV_WRAP virtual void clear(); CV_WRAP CvNormalBayesClassifier( const cv::Mat& trainData, const cv::Mat& responses, @@ -209,7 +209,7 @@ public: CV_WRAP virtual bool train( const cv::Mat& trainData, const cv::Mat& responses, const cv::Mat& varIdx = cv::Mat(), const cv::Mat& sampleIdx=cv::Mat(), bool update=false ); - CV_WRAP virtual float predict( const cv::Mat& samples, CV_OUT cv::Mat* results=0 ) const; + CV_WRAP virtual float predict( const cv::Mat& samples, CV_OUT cv::Mat* results=0, CV_OUT cv::Mat* results_prob=0 ) const; virtual void write( CvFileStorage* storage, const char* name ) const; virtual void read( CvFileStorage* storage, CvFileNode* node ); diff --git a/modules/ml/src/nbayes.cpp b/modules/ml/src/nbayes.cpp index 5ad1b134d..1d2f74668 100644 --- a/modules/ml/src/nbayes.cpp +++ b/modules/ml/src/nbayes.cpp @@ -282,7 +282,7 @@ bool CvNormalBayesClassifier::train( const CvMat* _train_data, const CvMat* _res struct predict_body : cv::ParallelLoopBody { predict_body(CvMat* _c, CvMat** _cov_rotate_mats, CvMat** _inv_eigen_values, CvMat** _avg, const CvMat* _samples, const int* _vidx, CvMat* _cls_labels, - CvMat* _results, float* _value, int _var_count1 + CvMat* _results, float* _value, int _var_count1, CvMat* _results_prob ) { c = _c; @@ -295,6 +295,7 @@ struct predict_body : cv::ParallelLoopBody { results = _results; value = _value; var_count1 = _var_count1; + results_prob = _results_prob; } CvMat* c; @@ -305,6 +306,7 @@ struct predict_body : cv::ParallelLoopBody { const int* vidx; CvMat* cls_labels; + CvMat* results_prob; CvMat* results; float* value; int var_count1; @@ -313,15 +315,21 @@ struct predict_body : cv::ParallelLoopBody { { int cls = -1; - int rtype = 0, rstep = 0; + int rtype = 0, rstep = 0, rptype = 0, rpstep = 0; int nclasses = cls_labels->cols; int _var_count = avg[0]->cols; + double probability = 0; if (results) { rtype = CV_MAT_TYPE(results->type); rstep = CV_IS_MAT_CONT(results->type) ? 1 : results->step/CV_ELEM_SIZE(rtype); } + if (results_prob) + { + rptype = CV_MAT_TYPE(results_prob->type); + rpstep = CV_IS_MAT_CONT(results_prob->type) ? 1 : results_prob->step/CV_ELEM_SIZE(rptype); + } // allocate memory and initializing headers for calculating cv::AutoBuffer buffer(nclasses + var_count1); CvMat diff = cvMat( 1, var_count1, CV_64FC1, &buffer[0] ); @@ -333,7 +341,6 @@ struct predict_body : cv::ParallelLoopBody { for(int i = 0; i < nclasses; i++ ) { - double cur = c->data.db[i]; CvMat* u = cov_rotate_mats[i]; CvMat* w = inv_eigen_values[i]; @@ -358,6 +365,7 @@ struct predict_body : cv::ParallelLoopBody { opt = cur; } /* probability = exp( -0.5 * cur ) */ + probability = exp( -0.5 * cur ); } ival = cls_labels->data.i[cls]; @@ -368,6 +376,13 @@ struct predict_body : cv::ParallelLoopBody { else results->data.fl[k*rstep] = (float)ival; } + if ( results_prob ) + { + if ( rptype == CV_32FC1 ) + results_prob->data.fl[k*rpstep] = (float)probability; + else + results_prob->data.db[k*rpstep] = probability; + } if( k == 0 ) *value = (float)ival; } @@ -375,7 +390,7 @@ struct predict_body : cv::ParallelLoopBody { }; -float CvNormalBayesClassifier::predict( const CvMat* samples, CvMat* results ) const +float CvNormalBayesClassifier::predict( const CvMat* samples, CvMat* results, CvMat* results_prob ) const { float value = 0; @@ -397,11 +412,21 @@ float CvNormalBayesClassifier::predict( const CvMat* samples, CvMat* results ) c "with the number of elements = number of rows in the input matrix" ); } + if( results_prob ) + { + if( !CV_IS_MAT(results_prob) || (CV_MAT_TYPE(results_prob->type) != CV_32FC1 && + CV_MAT_TYPE(results_prob->type) != CV_64FC1) || + (results_prob->cols != 1 && results_prob->rows != 1) || + results_prob->cols + results_prob->rows - 1 != samples->rows ) + CV_Error( CV_StsBadArg, "The output array must be double or float vector " + "with the number of elements = number of rows in the input matrix" ); + } + const int* vidx = var_idx ? var_idx->data.i : 0; cv::parallel_for_(cv::Range(0, samples->rows), predict_body(c, cov_rotate_mats, inv_eigen_values, avg, samples, - vidx, cls_labels, results, &value, var_count)); + vidx, cls_labels, results, &value, var_count, results_prob)); return value; } @@ -608,9 +633,9 @@ bool CvNormalBayesClassifier::train( const Mat& _train_data, const Mat& _respons sidx.data.ptr ? &sidx : 0, update); } -float CvNormalBayesClassifier::predict( const Mat& _samples, Mat* _results ) const +float CvNormalBayesClassifier::predict( const Mat& _samples, Mat* _results, Mat* _results_prob ) const { - CvMat samples = _samples, results, *presults = 0; + CvMat samples = _samples, results, *presults = 0, results_prob, *presults_prob = 0; if( _results ) { @@ -621,7 +646,16 @@ float CvNormalBayesClassifier::predict( const Mat& _samples, Mat* _results ) con presults = &(results = *_results); } - return predict(&samples, presults); + if( _results_prob ) + { + if( !(_results_prob->data && _results_prob->type() == CV_64F && + (_results_prob->cols == 1 || _results_prob->rows == 1) && + _results_prob->cols + _results_prob->rows - 1 == _samples.rows) ) + _results_prob->create(_samples.rows, 1, CV_64F); + presults_prob = &(results_prob = *_results_prob); + } + + return predict(&samples, presults, presults_prob); } /* End of file. */ From f91f55927e2fcee80d407b4501aa1f705e39e8da Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 29 Jan 2014 17:37:52 +0400 Subject: [PATCH 273/295] fix memory management problem --- modules/core/include/opencv2/core/ocl.hpp | 3 +++ modules/core/src/ocl.cpp | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/modules/core/include/opencv2/core/ocl.hpp b/modules/core/include/opencv2/core/ocl.hpp index 850a2e60e..3b790af98 100644 --- a/modules/core/include/opencv2/core/ocl.hpp +++ b/modules/core/include/opencv2/core/ocl.hpp @@ -561,6 +561,9 @@ public: explicit PlatformInfo2(void* id); ~PlatformInfo2(); + PlatformInfo2(const PlatformInfo2& i); + PlatformInfo2& operator =(const PlatformInfo2& i); + String name() const; String vendor() const; String version() const; diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 1a2714d05..d1e13a8a3 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3707,6 +3707,26 @@ PlatformInfo2::~PlatformInfo2() p->release(); } +PlatformInfo2::PlatformInfo2(const PlatformInfo2& i) +{ + if (i.p) + i.p->addref(); + this->p = i.p; +} + +PlatformInfo2& PlatformInfo2::operator =(const PlatformInfo2& i) +{ + if (i.p != this->p) + { + if (i.p) + i.p->addref(); + if (this->p) + this->p->release(); + this->p = i.p; + } + return *this; +} + int PlatformInfo2::deviceNumber() const { return p ? (int)p->devices.size() : 0; From 6fa49f6e806c452a7fdc032591a3a9eab0550d52 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 29 Jan 2014 18:58:27 +0400 Subject: [PATCH 274/295] fix unintialized fields --- modules/video/src/lkpyramid.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 382914b2d..598e69c88 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -598,6 +598,7 @@ namespace cv struct dim3 { unsigned int x, y, z; + dim3() : x(0), y(0), z(0) { } }; public: PyrLKOpticalFlow() @@ -607,6 +608,8 @@ namespace cv iters = 30; derivLambda = 0.5; useInitialFlow = false; + + waveSize = 0; } bool checkParam() From 384a28622d766c4ce302051152b40d7a1655ba85 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 29 Jan 2014 20:19:15 +0400 Subject: [PATCH 275/295] added cv::calcHist to T-API (only for CV_8UC1 with 256 bins) --- modules/core/src/matrix.cpp | 38 +++++++++ modules/imgproc/src/histogram.cpp | 93 +++++++++++++-------- modules/imgproc/test/ocl/test_histogram.cpp | 56 +++++++++++-- 3 files changed, 146 insertions(+), 41 deletions(-) diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 0f15ac1d6..af2ca7d74 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -1650,6 +1650,16 @@ int _InputArray::dims(int i) const return vv[i].dims; } + if( k == STD_VECTOR_UMAT ) + { + const std::vector& vv = *(const std::vector*)obj; + if( i < 0 ) + return 1; + CV_Assert( i < (int)vv.size() ); + + return vv[i].dims; + } + if( k == OPENGL_BUFFER ) { CV_Assert( i < 0 ); @@ -1701,6 +1711,16 @@ size_t _InputArray::total(int i) const return vv[i].total(); } + if( k == STD_VECTOR_UMAT ) + { + const std::vector& vv = *(const std::vector*)obj; + if( i < 0 ) + return vv.size(); + + CV_Assert( i < (int)vv.size() ); + return vv[i].total(); + } + return size(i).area(); } @@ -1723,6 +1743,18 @@ int _InputArray::type(int i) const if( k == NONE ) return -1; + if( k == STD_VECTOR_UMAT ) + { + const std::vector& vv = *(const std::vector*)obj; + if( vv.empty() ) + { + CV_Assert((flags & FIXED_TYPE) != 0); + return CV_MAT_TYPE(flags); + } + CV_Assert( i < (int)vv.size() ); + return vv[i >= 0 ? i : 0].type(); + } + if( k == STD_VECTOR_MAT ) { const std::vector& vv = *(const std::vector*)obj; @@ -1793,6 +1825,12 @@ bool _InputArray::empty() const return vv.empty(); } + if( k == STD_VECTOR_UMAT ) + { + const std::vector& vv = *(const std::vector*)obj; + return vv.empty(); + } + if( k == OPENGL_BUFFER ) return ((const ogl::Buffer*)obj)->empty(); diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 0533bbba2..1a91119b9 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -1399,6 +1399,57 @@ static void calcHist( const Mat* images, int nimages, const int* channels, } } +enum +{ + BINS = 256 +}; + +static bool ocl_calcHist1(InputArrayOfArrays _src, OutputArray _hist, int ddepth = CV_32S) +{ + int compunits = ocl::Device::getDefault().maxComputeUnits(); + size_t wgs = ocl::Device::getDefault().maxWorkGroupSize(); + + ocl::Kernel k1("calculate_histogram", ocl::imgproc::histogram_oclsrc, + format("-D BINS=%d -D HISTS_COUNT=%d -D WGS=%d", BINS, compunits, wgs)); + if (k1.empty()) + return false; + + _hist.create(1, BINS, ddepth); + UMat src = _src.getUMat(), ghist(1, BINS * compunits, CV_32SC1), + hist = ddepth == CV_32S ? _hist.getUMat() : UMat(BINS, 1, CV_32SC1); + + k1.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::PtrWriteOnly(ghist), + (int)src.total()); + + size_t globalsize = compunits * wgs; + if (!k1.run(1, &globalsize, &wgs, false)) + return false; + + ocl::Kernel k2("merge_histogram", ocl::imgproc::histogram_oclsrc, + format("-D BINS=%d -D HISTS_COUNT=%d -D WGS=%d", BINS, compunits, (int)wgs)); + if (k2.empty()) + return false; + + k2.args(ocl::KernelArg::PtrReadOnly(ghist), ocl::KernelArg::PtrWriteOnly(hist)); + if (!k2.run(1, &wgs, &wgs, false)) + return false; + + if (hist.depth() != ddepth) + hist.convertTo(_hist, ddepth); + else + _hist.getUMatRef() = hist; + + return true; +} + +static bool ocl_calcHist(InputArrayOfArrays images, OutputArray hist) +{ + std::vector v; + images.getUMatVector(v); + + return ocl_calcHist1(v[0], hist, CV_32F); +} + } void cv::calcHist( const Mat* images, int nimages, const int* channels, @@ -1417,6 +1468,12 @@ void cv::calcHist( InputArrayOfArrays images, const std::vector& channels, const std::vector& ranges, bool accumulate ) { + CV_OCL_RUN(images.total() == 1 && channels.size() == 1 && images.channels(0) == 1 && + channels[0] == 0 && images.isUMatVector() && mask.empty() && !accumulate && + histSize.size() == 1 && histSize[0] == BINS && ranges.size() == 2 && + ranges[0] == 0 && ranges[1] == 256, + ocl_calcHist(images, hist)) + int i, dims = (int)histSize.size(), rsz = (int)ranges.size(), csz = (int)channels.size(); int nimages = (int)images.total(); @@ -3290,47 +3347,13 @@ CV_IMPL void cvEqualizeHist( const CvArr* srcarr, CvArr* dstarr ) namespace cv { -enum -{ - BINS = 256 -}; - -static bool ocl_calcHist(InputArray _src, OutputArray _hist) -{ - int compunits = ocl::Device::getDefault().maxComputeUnits(); - size_t wgs = ocl::Device::getDefault().maxWorkGroupSize(); - - ocl::Kernel k1("calculate_histogram", ocl::imgproc::histogram_oclsrc, - format("-D BINS=%d -D HISTS_COUNT=%d -D WGS=%d", BINS, compunits, wgs)); - if (k1.empty()) - return false; - - _hist.create(1, BINS, CV_32SC1); - UMat src = _src.getUMat(), hist = _hist.getUMat(), ghist(1, BINS * compunits, CV_32SC1); - - k1.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::PtrWriteOnly(ghist), - (int)src.total()); - - size_t globalsize = compunits * wgs; - if (!k1.run(1, &globalsize, &wgs, false)) - return false; - - ocl::Kernel k2("merge_histogram", ocl::imgproc::histogram_oclsrc, - format("-D BINS=%d -D HISTS_COUNT=%d -D WGS=%d", BINS, compunits, (int)wgs)); - if (k2.empty()) - return false; - - k2.args(ocl::KernelArg::PtrReadOnly(ghist), ocl::KernelArg::PtrWriteOnly(hist)); - return k2.run(1, &wgs, &wgs, false); -} - static bool ocl_equalizeHist(InputArray _src, OutputArray _dst) { size_t wgs = std::min(ocl::Device::getDefault().maxWorkGroupSize(), BINS); // calculation of histogram UMat hist; - if (!ocl_calcHist(_src, hist)) + if (!ocl_calcHist1(_src, hist)) return false; UMat lut(1, 256, CV_8UC1); diff --git a/modules/imgproc/test/ocl/test_histogram.cpp b/modules/imgproc/test/ocl/test_histogram.cpp index d6cf6efa1..b0837eeaa 100644 --- a/modules/imgproc/test/ocl/test_histogram.cpp +++ b/modules/imgproc/test/ocl/test_histogram.cpp @@ -144,11 +144,6 @@ PARAM_TEST_CASE(CalcBackProject, MatDepth, int, bool) scale = randomDouble(0.1, 1); } - - void Near() - { - OCL_EXPECT_MATS_NEAR(dst, 0.0) - } }; //////////////////////////////// CalcBackProject ////////////////////////////////////////////// @@ -162,13 +157,62 @@ OCL_TEST_P(CalcBackProject, Mat) OCL_OFF(cv::calcBackProject(images_roi, channels, hist_roi, dst_roi, ranges, scale)); OCL_ON(cv::calcBackProject(uimages_roi, channels, uhist_roi, udst_roi, ranges, scale)); - Near(); + OCL_EXPECT_MATS_NEAR(dst, 0.0) + } +} + +//////////////////////////////// CalcHist ////////////////////////////////////////////// + +PARAM_TEST_CASE(CalcHist, bool) +{ + bool useRoi; + + TEST_DECLARE_INPUT_PARAMETER(src) + TEST_DECLARE_OUTPUT_PARAMETER(hist) + + virtual void SetUp() + { + useRoi = GET_PARAM(0); + } + + virtual void random_roi() + { + Size roiSize = randomSize(1, MAX_VALUE); + + Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, CV_8UC1, 0, 256); + + Border histBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(hist, hist_roi, Size(1, 256), histBorder, CV_32SC1, 0, MAX_VALUE); + + UMAT_UPLOAD_INPUT_PARAMETER(src) + UMAT_UPLOAD_OUTPUT_PARAMETER(hist) + } +}; + +OCL_TEST_P(CalcHist, Mat) +{ + const std::vector channels(1, 0); + std::vector ranges(2); + std::vector histSize(1, 256); + ranges[0] = 0; + ranges[1] = 256; + + for (int j = 0; j < test_loop_times; j++) + { + random_roi(); + + OCL_OFF(cv::calcHist(std::vector(1, src_roi), channels, noArray(), hist_roi, histSize, ranges, false)); + OCL_ON(cv::calcHist(std::vector(1, usrc_roi), channels, noArray(), uhist_roi, histSize, ranges, false)); + + OCL_EXPECT_MATS_NEAR(hist, 0.0) } } ///////////////////////////////////////////////////////////////////////////////////// OCL_INSTANTIATE_TEST_CASE_P(Imgproc, CalcBackProject, Combine(Values((MatDepth)CV_8U), Values(1, 2), Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Imgproc, CalcHist, Values(true, false)); } } // namespace cvtest::ocl From faa6074f3d19a7fb59b5eda937dcd45c0e0c5fce Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 29 Jan 2014 20:34:37 +0400 Subject: [PATCH 276/295] added performance test --- modules/imgproc/perf/opencl/perf_imgproc.cpp | 40 ++++++++++++++++++++ modules/imgproc/src/histogram.cpp | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/modules/imgproc/perf/opencl/perf_imgproc.cpp b/modules/imgproc/perf/opencl/perf_imgproc.cpp index 8d4b5c2cd..7e5a817da 100644 --- a/modules/imgproc/perf/opencl/perf_imgproc.cpp +++ b/modules/imgproc/perf/opencl/perf_imgproc.cpp @@ -61,6 +61,8 @@ OCL_PERF_TEST_P(EqualizeHistFixture, EqualizeHist, OCL_TEST_SIZES) const Size srcSize = GetParam(); const double eps = 1; + checkDeviceMaxMemoryAllocSize(srcSize, CV_8UC1); + UMat src(srcSize, CV_8UC1), dst(srcSize, CV_8UC1); declare.in(src, WARMUP_RNG).out(dst); @@ -69,6 +71,30 @@ OCL_PERF_TEST_P(EqualizeHistFixture, EqualizeHist, OCL_TEST_SIZES) SANITY_CHECK(dst, eps); } +///////////// calcHist //////////////////////// + +typedef TestBaseWithParam CalcHistFixture; + +OCL_PERF_TEST_P(CalcHistFixture, CalcHist, OCL_TEST_SIZES) +{ + const Size srcSize = GetParam(); + + const std::vector channels(1, 0); + std::vector ranges(2); + std::vector histSize(1, 256); + ranges[0] = 0; + ranges[1] = 256; + + checkDeviceMaxMemoryAllocSize(srcSize, CV_8UC1); + + UMat src(srcSize, CV_8UC1), hist(256, 1, CV_32FC1); + declare.in(src, WARMUP_RNG).out(hist); + + OCL_TEST_CYCLE() cv::calcHist(std::vector(1, src), channels, noArray(), hist, histSize, ranges, false); + + SANITY_CHECK(hist); +} + /////////// CopyMakeBorder ////////////////////// CV_ENUM(Border, BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT, BORDER_WRAP, BORDER_REFLECT_101) @@ -83,6 +109,8 @@ OCL_PERF_TEST_P(CopyMakeBorderFixture, CopyMakeBorder, const Size srcSize = get<0>(params); const int type = get<1>(params), borderType = get<2>(params); + checkDeviceMaxMemoryAllocSize(srcSize, type); + UMat src(srcSize, type), dst; const Size dstSize = srcSize + Size(12, 12); dst.create(dstSize, type); @@ -105,6 +133,8 @@ OCL_PERF_TEST_P(CornerMinEigenValFixture, CornerMinEigenVal, const int type = get<1>(params), borderType = BORDER_REFLECT; const int blockSize = 7, apertureSize = 1 + 2 * 3; + checkDeviceMaxMemoryAllocSize(srcSize, type); + UMat src(srcSize, type), dst(srcSize, CV_32FC1); declare.in(src, WARMUP_RNG).out(dst); @@ -124,6 +154,8 @@ OCL_PERF_TEST_P(CornerHarrisFixture, CornerHarris, const Size srcSize = get<0>(params); const int type = get<1>(params), borderType = BORDER_REFLECT; + checkDeviceMaxMemoryAllocSize(srcSize, type); + UMat src(srcSize, type), dst(srcSize, CV_32FC1); declare.in(src, WARMUP_RNG).out(dst); @@ -143,6 +175,8 @@ OCL_PERF_TEST_P(PreCornerDetectFixture, PreCornerDetect, const Size srcSize = get<0>(params); const int type = get<1>(params), borderType = BORDER_REFLECT; + checkDeviceMaxMemoryAllocSize(srcSize, type); + UMat src(srcSize, type), dst(srcSize, CV_32FC1); declare.in(src, WARMUP_RNG).out(dst); @@ -162,6 +196,8 @@ OCL_PERF_TEST_P(IntegralFixture, Integral1, ::testing::Combine(OCL_TEST_SIZES, O const Size srcSize = get<0>(params); const int ddepth = get<1>(params); + checkDeviceMaxMemoryAllocSize(srcSize, ddepth); + UMat src(srcSize, CV_8UC1), dst(srcSize + Size(1, 1), ddepth); declare.in(src, WARMUP_RNG).out(dst); @@ -186,6 +222,8 @@ OCL_PERF_TEST_P(ThreshFixture, Threshold, const int threshType = get<2>(params); const double maxValue = 220.0, threshold = 50; + checkDeviceMaxMemoryAllocSize(srcSize, srcType); + UMat src(srcSize, srcType), dst(srcSize, srcType); declare.in(src, WARMUP_RNG).out(dst); @@ -202,6 +240,8 @@ OCL_PERF_TEST_P(CLAHEFixture, CLAHE, OCL_TEST_SIZES) { const Size srcSize = GetParam(); + checkDeviceMaxMemoryAllocSize(srcSize, CV_8UC1); + UMat src(srcSize, CV_8UC1), dst(srcSize, CV_8UC1); const double clipLimit = 40.0; declare.in(src, WARMUP_RNG).out(dst); diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 1a91119b9..e5b5cc76b 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -1414,7 +1414,7 @@ static bool ocl_calcHist1(InputArrayOfArrays _src, OutputArray _hist, int ddepth if (k1.empty()) return false; - _hist.create(1, BINS, ddepth); + _hist.create(BINS, 1, ddepth); UMat src = _src.getUMat(), ghist(1, BINS * compunits, CV_32SC1), hist = ddepth == CV_32S ? _hist.getUMat() : UMat(BINS, 1, CV_32SC1); From 6fa41c5a6438e1391c6005ef0aa8154ce40a94a0 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 30 Jan 2014 00:12:59 +0400 Subject: [PATCH 277/295] some experiments --- modules/imgproc/src/filter.cpp | 62 ++++++++++++++++++++-- modules/imgproc/src/opencl/filterSepCol.cl | 4 +- modules/imgproc/src/opencl/filterSepRow.cl | 14 +++-- 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 8c11c62db..6b767329d 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -3313,6 +3313,56 @@ static bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth, return kernel.run(2, globalsize, localsize, true); } +template +static std::string kerToStr(const Mat & k) +{ + int width = k.cols - 1, depth = k.depth(); + const T * const data = reinterpret_cast(k.data); + + std::ostringstream stream; + stream.precision(10); + + if (depth <= CV_8S) + { + for (int i = 0; i < width; ++i) + stream << (int)data[i] << ","; + stream << (int)data[width]; + } + else if (depth == CV_32F) + { + for (int i = 0; i < width; ++i) + stream << data[i] << "f,"; + stream << data[width] << "f"; + } + else + { + for (int i = 0; i < width; ++i) + stream << data[i] << ","; + } + + return stream.str(); +} + +static String kernelToStr(InputArray _kernel, int ddepth = -1) +{ + Mat kernel = _kernel.getMat().reshape(1, 1); + + int depth = kernel.depth(); + if (ddepth < 0) + ddepth = depth; + + if (ddepth != depth) + kernel.convertTo(kernel, ddepth); + + typedef std::string (*func_t)(const Mat &); + static const func_t funcs[] = { kerToStr, kerToStr, kerToStr,kerToStr, + kerToStr, kerToStr, kerToStr, 0 }; + const func_t func = funcs[depth]; + CV_Assert(func != 0); + + return cv::format(" -D COEFF=%s", func(kernel).c_str()); +} + static bool ocl_sepRowFilter2D( UMat &src, UMat &buf, Mat &kernelX, int anchor, int borderType, bool sync) { int type = src.type(); @@ -3378,6 +3428,7 @@ static bool ocl_sepRowFilter2D( UMat &src, UMat &buf, Mat &kernelX, int anchor, btype, extra_extrapolation ? "EXTRA_EXTRAPOLATION" : "NO_EXTRA_EXTRAPOLATION", isIsolatedBorder ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED"); + build_options += kernelToStr(kernelX, CV_32F); Size srcWholeSize; Point srcOffset; src.locateROI(srcWholeSize, srcOffset); @@ -3390,7 +3441,8 @@ static bool ocl_sepRowFilter2D( UMat &src, UMat &buf, Mat &kernelX, int anchor, strKernel << "_D" << sdepth; ocl::Kernel kernelRow; - if (!kernelRow.create(strKernel.str().c_str(), cv::ocl::imgproc::filterSepRow_oclsrc, build_options)) + if (!kernelRow.create(strKernel.str().c_str(), cv::ocl::imgproc::filterSepRow_oclsrc, + build_options)) return false; int idxArg = 0; @@ -3409,7 +3461,7 @@ static bool ocl_sepRowFilter2D( UMat &src, UMat &buf, Mat &kernelX, int anchor, idxArg = kernelRow.set(idxArg, buf.cols); idxArg = kernelRow.set(idxArg, buf.rows); idxArg = kernelRow.set(idxArg, radiusY); - idxArg = kernelRow.set(idxArg, ocl::KernelArg::PtrReadOnly(kernelX.getUMat(ACCESS_READ))); +// idxArg = kernelRow.set(idxArg, ocl::KernelArg::PtrReadOnly(kernelX.getUMat(ACCESS_READ))); return kernelRow.run(2, globalsize, localsize, sync); } @@ -3479,6 +3531,8 @@ static bool ocl_sepColFilter2D(UMat &buf, UMat &dst, Mat &kernelY, int anchor, b } } + build_options += kernelToStr(kernelY, CV_32F); + ocl::Kernel kernelCol; if (!kernelCol.create("col_filter", cv::ocl::imgproc::filterSepCol_oclsrc, build_options)) return false; @@ -3494,7 +3548,7 @@ static bool ocl_sepColFilter2D(UMat &buf, UMat &dst, Mat &kernelY, int anchor, b idxArg = kernelCol.set(idxArg, (int)(dst.step / dst.elemSize())); idxArg = kernelCol.set(idxArg, dst.cols); idxArg = kernelCol.set(idxArg, dst.rows); - idxArg = kernelCol.set(idxArg, ocl::KernelArg::PtrReadOnly(kernelY.getUMat(ACCESS_READ))); +// idxArg = kernelCol.set(idxArg, ocl::KernelArg::PtrReadOnly(kernelY.getUMat(ACCESS_READ))); return kernelCol.run(2, globalsize, localsize, sync); } @@ -3508,7 +3562,7 @@ static bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, int type = _src.type(); if ( !( (CV_8UC1 == type || CV_8UC4 == type || CV_32FC1 == type || CV_32FC4 == type) && - (ddepth == CV_32F || ddepth == CV_8U) ) ) + (ddepth == CV_32F || ddepth == CV_8U || ddepth < 0) ) ) return false; int cn = CV_MAT_CN(type); diff --git a/modules/imgproc/src/opencl/filterSepCol.cl b/modules/imgproc/src/opencl/filterSepCol.cl index e99fa6ee0..721eb9009 100644 --- a/modules/imgproc/src/opencl/filterSepCol.cl +++ b/modules/imgproc/src/opencl/filterSepCol.cl @@ -60,6 +60,7 @@ Niko The info above maybe obsolete. ***********************************************************************************/ +__constant float mat_kernel[] = { COEFF }; __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void col_filter (__global const GENTYPE_SRC * restrict src, @@ -70,8 +71,7 @@ __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void col_filter const int dst_offset_in_pixel, const int dst_step_in_pixel, const int dst_cols, - const int dst_rows, - __constant float * mat_kernel) + const int dst_rows) { int x = get_global_id(0); int y = get_global_id(1); diff --git a/modules/imgproc/src/opencl/filterSepRow.cl b/modules/imgproc/src/opencl/filterSepRow.cl index dfbf30099..efb082e3e 100644 --- a/modules/imgproc/src/opencl/filterSepRow.cl +++ b/modules/imgproc/src/opencl/filterSepRow.cl @@ -144,6 +144,8 @@ Niko The info above maybe obsolete. ***********************************************************************************/ +__constant float mat_kernel[] = { COEFF }; + __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_C1_D0 (__global uchar * restrict src, int src_step_in_pixel, @@ -153,8 +155,7 @@ __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_ __global float * dst, int dst_step_in_pixel, int dst_cols, int dst_rows, - int radiusy, - __constant float * mat_kernel) + int radiusy) { int x = get_global_id(0)<<2; int y = get_global_id(1); @@ -297,8 +298,7 @@ __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_ __global float4 * dst, int dst_step_in_pixel, int dst_cols, int dst_rows, - int radiusy, - __constant float * mat_kernel) + int radiusy) { int x = get_global_id(0); int y = get_global_id(1); @@ -391,8 +391,7 @@ __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_ __global float * dst, int dst_step_in_pixel, int dst_cols, int dst_rows, - int radiusy, - __constant float * mat_kernel) + int radiusy) { int x = get_global_id(0); int y = get_global_id(1); @@ -484,8 +483,7 @@ __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_ __global float4 * dst, int dst_step_in_pixel, int dst_cols, int dst_rows, - int radiusy, - __constant float * mat_kernel) + int radiusy) { int x = get_global_id(0); int y = get_global_id(1); From 6d64907f18a3bbfc91404f22ae1964ba1a9244ae Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 30 Jan 2014 00:19:18 +0400 Subject: [PATCH 278/295] async --- modules/core/src/ocl.cpp | 2 +- modules/imgproc/src/filter.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 7201fca71..66dbcbbab 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3299,7 +3299,7 @@ public: CV_Assert(u->handle != 0 && u->urefcount == 0); if(u->tempUMat()) { - UMatDataAutoLock lock(u); +// UMatDataAutoLock lock(u); if( u->hostCopyObsolete() && u->refcount > 0 ) { cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr(); diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 6b767329d..9a4a085d7 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -3595,12 +3595,12 @@ static bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, Size srcSize = src.size(); Size bufSize(srcSize.width, srcSize.height + kernelY.cols - 1); UMat buf; buf.create(bufSize, CV_MAKETYPE(CV_32F, cn)); - if (!ocl_sepRowFilter2D(src, buf, kernelX, anchor.x, borderType, true)) + if (!ocl_sepRowFilter2D(src, buf, kernelX, anchor.x, borderType, false)) return false; _dst.create(srcSize, CV_MAKETYPE(ddepth, cn)); UMat dst = _dst.getUMat(); - return ocl_sepColFilter2D(buf, dst, kernelY, anchor.y, true); + return ocl_sepColFilter2D(buf, dst, kernelY, anchor.y, false); } #endif From 0d19cbcc7a80a18d4fa50fb74568d7a41c89c47f Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 29 Jan 2014 16:33:44 +0400 Subject: [PATCH 279/295] added performance test --- .../imgproc/perf/opencl/perf_accumulate.cpp | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 modules/imgproc/perf/opencl/perf_accumulate.cpp diff --git a/modules/imgproc/perf/opencl/perf_accumulate.cpp b/modules/imgproc/perf/opencl/perf_accumulate.cpp new file mode 100644 index 000000000..5b7ac4c75 --- /dev/null +++ b/modules/imgproc/perf/opencl/perf_accumulate.cpp @@ -0,0 +1,140 @@ +/*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 +// Nathan, liujun@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/ts/ocl_perf.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +/////////////////////////////////// Accumulate /////////////////////////////////// + +typedef Size_MatType AccumulateFixture; + +OCL_PERF_TEST_P(AccumulateFixture, Accumulate, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int srcType = get<1>(params), cn = CV_MAT_CN(srcType), dstType = CV_32FC(cn); + + checkDeviceMaxMemoryAllocSize(srcSize, dstType); + + UMat src(srcSize, srcType), dst(srcSize, dstType); + declare.in(src, dst, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::accumulate(src, dst); + + SANITY_CHECK_NOTHING(); +} + +/////////////////////////////////// AccumulateSquare /////////////////////////////////// + +typedef Size_MatType AccumulateSquareFixture; + +OCL_PERF_TEST_P(AccumulateSquareFixture, AccumulateSquare, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int srcType = get<1>(params), cn = CV_MAT_CN(srcType), dstType = CV_32FC(cn); + + checkDeviceMaxMemoryAllocSize(srcSize, dstType); + + UMat src(srcSize, srcType), dst(srcSize, dstType); + declare.in(src, dst, WARMUP_RNG); + + OCL_TEST_CYCLE() cv::accumulateSquare(src, dst); + + SANITY_CHECK_NOTHING(); +} + +/////////////////////////////////// AccumulateProduct /////////////////////////////////// + +typedef Size_MatType AccumulateProductFixture; + +OCL_PERF_TEST_P(AccumulateProductFixture, AccumulateProduct, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int srcType = get<1>(params), cn = CV_MAT_CN(srcType), dstType = CV_32FC(cn); + + checkDeviceMaxMemoryAllocSize(srcSize, dstType); + + UMat src1(srcSize, srcType), src2(srcSize, srcType), dst(srcSize, dstType); + declare.in(src1, src2, dst, WARMUP_RNG); + + OCL_TEST_CYCLE() cv::accumulateProduct(src1, src2, dst); + + SANITY_CHECK_NOTHING(); +} + +/////////////////////////////////// AccumulateWeighted /////////////////////////////////// + +typedef Size_MatType AccumulateWeightedFixture; + +OCL_PERF_TEST_P(AccumulateWeightedFixture, AccumulateWeighted, + ::testing::Combine(OCL_TEST_SIZES, OCL_TEST_TYPES)) +{ + Size_MatType_t params = GetParam(); + const Size srcSize = get<0>(params); + const int srcType = get<1>(params), cn = CV_MAT_CN(srcType), dstType = CV_32FC(cn); + + checkDeviceMaxMemoryAllocSize(srcSize, dstType); + + UMat src(srcSize, srcType), dst(srcSize, dstType); + declare.in(src, dst, WARMUP_RNG); + + OCL_TEST_CYCLE() cv::accumulateWeighted(src, dst, 2.0); + + SANITY_CHECK_NOTHING(); +} + +} } // namespace cvtest::ocl + +#endif From 1862dbc5ab95762ecfdf914e01ba784e2674d0f1 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 30 Jan 2014 05:48:15 +0400 Subject: [PATCH 280/295] fixed fp problem --- modules/imgproc/src/filter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 9a4a085d7..c3a096619 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -3330,6 +3330,7 @@ static std::string kerToStr(const Mat & k) } else if (depth == CV_32F) { + stream.setf(std::ios_base::showpoint); for (int i = 0; i < width; ++i) stream << data[i] << "f,"; stream << data[width] << "f"; From 231bc17de79b773b001dc6dbf08e7ee533872c0b Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 29 Jan 2014 23:00:33 +0400 Subject: [PATCH 281/295] added conditional compilation --- modules/imgproc/src/histogram.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index e5b5cc76b..6fc23d2ce 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -1399,12 +1399,14 @@ static void calcHist( const Mat* images, int nimages, const int* channels, } } +#ifdef HAVE_OPENCL + enum { BINS = 256 }; -static bool ocl_calcHist1(InputArrayOfArrays _src, OutputArray _hist, int ddepth = CV_32S) +static bool ocl_calcHist1(InputArray _src, OutputArray _hist, int ddepth = CV_32S) { int compunits = ocl::Device::getDefault().maxComputeUnits(); size_t wgs = ocl::Device::getDefault().maxWorkGroupSize(); @@ -1450,6 +1452,8 @@ static bool ocl_calcHist(InputArrayOfArrays images, OutputArray hist) return ocl_calcHist1(v[0], hist, CV_32F); } +#endif + } void cv::calcHist( const Mat* images, int nimages, const int* channels, From 372cdac07cbd305d9d9ac94c8dcc518b98d87c61 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 30 Jan 2014 15:23:11 +0400 Subject: [PATCH 282/295] moved kernelToStr to ocl.hpp --- modules/core/include/opencv2/core/ocl.hpp | 1 + modules/core/src/ocl.cpp | 51 ++++++++++++++++++++ modules/imgproc/src/filter.cpp | 57 +---------------------- 3 files changed, 54 insertions(+), 55 deletions(-) diff --git a/modules/core/include/opencv2/core/ocl.hpp b/modules/core/include/opencv2/core/ocl.hpp index 850a2e60e..4d63e3f00 100644 --- a/modules/core/include/opencv2/core/ocl.hpp +++ b/modules/core/include/opencv2/core/ocl.hpp @@ -575,6 +575,7 @@ protected: CV_EXPORTS const char* convertTypeStr(int sdepth, int ddepth, int cn, char* buf); CV_EXPORTS const char* typeToStr(int t); CV_EXPORTS const char* memopTypeToStr(int t); +CV_EXPORTS String kernelToStr(InputArray _kernel, int ddepth = -1); CV_EXPORTS void getPlatfomsInfo(std::vector& platform_info); class CV_EXPORTS Image2D diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 66dbcbbab..03abc061b 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3814,6 +3814,57 @@ const char* convertTypeStr(int sdepth, int ddepth, int cn, char* buf) return buf; } +template +static std::string kerToStr(const Mat & k) +{ + int width = k.cols - 1, depth = k.depth(); + const T * const data = reinterpret_cast(k.data); + + std::ostringstream stream; + stream.precision(10); + + if (depth <= CV_8S) + { + for (int i = 0; i < width; ++i) + stream << (int)data[i] << ", "; + stream << (int)data[width]; + } + else if (depth == CV_32F) + { + stream.setf(std::ios_base::showpoint); + for (int i = 0; i < width; ++i) + stream << data[i] << "f, "; + stream << data[width] << "f"; + } + else + { + for (int i = 0; i < width; ++i) + stream << data[i] << ", "; + } + + return stream.str(); +} + +String kernelToStr(InputArray _kernel, int ddepth) +{ + Mat kernel = _kernel.getMat().reshape(1, 1); + + int depth = kernel.depth(); + if (ddepth < 0) + ddepth = depth; + + if (ddepth != depth) + kernel.convertTo(kernel, ddepth); + + typedef std::string (*func_t)(const Mat &); + static const func_t funcs[] = { kerToStr, kerToStr, kerToStr,kerToStr, + kerToStr, kerToStr, kerToStr, 0 }; + const func_t func = funcs[depth]; + CV_Assert(func != 0); + + return cv::format(" -D COEFF=%s", func(kernel).c_str()); +} + /////////////////////////////////////////////////////////////////////////////////////////////// // deviceVersion has format // OpenCL diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index c3a096619..09519e74d 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -3313,57 +3313,6 @@ static bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth, return kernel.run(2, globalsize, localsize, true); } -template -static std::string kerToStr(const Mat & k) -{ - int width = k.cols - 1, depth = k.depth(); - const T * const data = reinterpret_cast(k.data); - - std::ostringstream stream; - stream.precision(10); - - if (depth <= CV_8S) - { - for (int i = 0; i < width; ++i) - stream << (int)data[i] << ","; - stream << (int)data[width]; - } - else if (depth == CV_32F) - { - stream.setf(std::ios_base::showpoint); - for (int i = 0; i < width; ++i) - stream << data[i] << "f,"; - stream << data[width] << "f"; - } - else - { - for (int i = 0; i < width; ++i) - stream << data[i] << ","; - } - - return stream.str(); -} - -static String kernelToStr(InputArray _kernel, int ddepth = -1) -{ - Mat kernel = _kernel.getMat().reshape(1, 1); - - int depth = kernel.depth(); - if (ddepth < 0) - ddepth = depth; - - if (ddepth != depth) - kernel.convertTo(kernel, ddepth); - - typedef std::string (*func_t)(const Mat &); - static const func_t funcs[] = { kerToStr, kerToStr, kerToStr,kerToStr, - kerToStr, kerToStr, kerToStr, 0 }; - const func_t func = funcs[depth]; - CV_Assert(func != 0); - - return cv::format(" -D COEFF=%s", func(kernel).c_str()); -} - static bool ocl_sepRowFilter2D( UMat &src, UMat &buf, Mat &kernelX, int anchor, int borderType, bool sync) { int type = src.type(); @@ -3429,7 +3378,7 @@ static bool ocl_sepRowFilter2D( UMat &src, UMat &buf, Mat &kernelX, int anchor, btype, extra_extrapolation ? "EXTRA_EXTRAPOLATION" : "NO_EXTRA_EXTRAPOLATION", isIsolatedBorder ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED"); - build_options += kernelToStr(kernelX, CV_32F); + build_options += ocl::kernelToStr(kernelX, CV_32F); Size srcWholeSize; Point srcOffset; src.locateROI(srcWholeSize, srcOffset); @@ -3462,7 +3411,6 @@ static bool ocl_sepRowFilter2D( UMat &src, UMat &buf, Mat &kernelX, int anchor, idxArg = kernelRow.set(idxArg, buf.cols); idxArg = kernelRow.set(idxArg, buf.rows); idxArg = kernelRow.set(idxArg, radiusY); -// idxArg = kernelRow.set(idxArg, ocl::KernelArg::PtrReadOnly(kernelX.getUMat(ACCESS_READ))); return kernelRow.run(2, globalsize, localsize, sync); } @@ -3532,7 +3480,7 @@ static bool ocl_sepColFilter2D(UMat &buf, UMat &dst, Mat &kernelY, int anchor, b } } - build_options += kernelToStr(kernelY, CV_32F); + build_options += ocl::kernelToStr(kernelY, CV_32F); ocl::Kernel kernelCol; if (!kernelCol.create("col_filter", cv::ocl::imgproc::filterSepCol_oclsrc, build_options)) @@ -3549,7 +3497,6 @@ static bool ocl_sepColFilter2D(UMat &buf, UMat &dst, Mat &kernelY, int anchor, b idxArg = kernelCol.set(idxArg, (int)(dst.step / dst.elemSize())); idxArg = kernelCol.set(idxArg, dst.cols); idxArg = kernelCol.set(idxArg, dst.rows); -// idxArg = kernelCol.set(idxArg, ocl::KernelArg::PtrReadOnly(kernelY.getUMat(ACCESS_READ))); return kernelCol.run(2, globalsize, localsize, sync); } From 2cd22a3ca32dfe52fde0926c5be6b3445e806354 Mon Sep 17 00:00:00 2001 From: Cosmin Boaca Date: Thu, 30 Jan 2014 13:37:53 +0200 Subject: [PATCH 283/295] Fixed broken alignment --- modules/ml/src/nbayes.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/ml/src/nbayes.cpp b/modules/ml/src/nbayes.cpp index 1d2f74668..b37f4a4c5 100644 --- a/modules/ml/src/nbayes.cpp +++ b/modules/ml/src/nbayes.cpp @@ -404,22 +404,22 @@ float CvNormalBayesClassifier::predict( const CvMat* samples, CvMat* results, Cv if( results ) { - if( !CV_IS_MAT(results) || (CV_MAT_TYPE(results->type) != CV_32FC1 && - CV_MAT_TYPE(results->type) != CV_32SC1) || - (results->cols != 1 && results->rows != 1) || - results->cols + results->rows - 1 != samples->rows ) + if( !CV_IS_MAT(results) || (CV_MAT_TYPE(results->type) != CV_32FC1 && + CV_MAT_TYPE(results->type) != CV_32SC1) || + (results->cols != 1 && results->rows != 1) || + results->cols + results->rows - 1 != samples->rows ) CV_Error( CV_StsBadArg, "The output array must be integer or floating-point vector " - "with the number of elements = number of rows in the input matrix" ); + "with the number of elements = number of rows in the input matrix" ); } if( results_prob ) { - if( !CV_IS_MAT(results_prob) || (CV_MAT_TYPE(results_prob->type) != CV_32FC1 && - CV_MAT_TYPE(results_prob->type) != CV_64FC1) || - (results_prob->cols != 1 && results_prob->rows != 1) || - results_prob->cols + results_prob->rows - 1 != samples->rows ) + if( !CV_IS_MAT(results_prob) || (CV_MAT_TYPE(results_prob->type) != CV_32FC1 && + CV_MAT_TYPE(results_prob->type) != CV_64FC1) || + (results_prob->cols != 1 && results_prob->rows != 1) || + results_prob->cols + results_prob->rows - 1 != samples->rows ) CV_Error( CV_StsBadArg, "The output array must be double or float vector " - "with the number of elements = number of rows in the input matrix" ); + "with the number of elements = number of rows in the input matrix" ); } const int* vidx = var_idx ? var_idx->data.i : 0; From 1ab1594d00be987d18bc6a62151a93428a7b919b Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 30 Jan 2014 17:23:56 +0400 Subject: [PATCH 284/295] workaround --- modules/core/src/ocl.cpp | 11 ++++++----- modules/imgproc/src/opencl/filterSepCol.cl | 1 + modules/imgproc/src/opencl/filterSepRow.cl | 1 + 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 03abc061b..7334670f5 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3826,20 +3826,21 @@ static std::string kerToStr(const Mat & k) if (depth <= CV_8S) { for (int i = 0; i < width; ++i) - stream << (int)data[i] << ", "; - stream << (int)data[width]; + stream << "DIG(" << (int)data[i] << ")"; + stream << "DIG(" << (int)data[width] << ")"; } else if (depth == CV_32F) { stream.setf(std::ios_base::showpoint); for (int i = 0; i < width; ++i) - stream << data[i] << "f, "; - stream << data[width] << "f"; + stream << "DIG(" << data[i] << "f)"; + stream << "DIG(" << data[width] << "f)"; } else { for (int i = 0; i < width; ++i) - stream << data[i] << ", "; + stream << "DIG(" << data[i] << ")"; + stream << "DIG(" << data[width] << ")"; } return stream.str(); diff --git a/modules/imgproc/src/opencl/filterSepCol.cl b/modules/imgproc/src/opencl/filterSepCol.cl index 721eb9009..2657ae931 100644 --- a/modules/imgproc/src/opencl/filterSepCol.cl +++ b/modules/imgproc/src/opencl/filterSepCol.cl @@ -60,6 +60,7 @@ Niko The info above maybe obsolete. ***********************************************************************************/ +#define DIG(a) a, __constant float mat_kernel[] = { COEFF }; __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void col_filter diff --git a/modules/imgproc/src/opencl/filterSepRow.cl b/modules/imgproc/src/opencl/filterSepRow.cl index efb082e3e..d0623f590 100644 --- a/modules/imgproc/src/opencl/filterSepRow.cl +++ b/modules/imgproc/src/opencl/filterSepRow.cl @@ -144,6 +144,7 @@ Niko The info above maybe obsolete. ***********************************************************************************/ +#define DIG(a) a, __constant float mat_kernel[] = { COEFF }; __kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_C1_D0 From 8782eb8657985786898820216e4f6030a402f1ba Mon Sep 17 00:00:00 2001 From: Cosmin Boaca Date: Thu, 30 Jan 2014 16:41:38 +0200 Subject: [PATCH 285/295] Fixed alignment --- modules/ml/src/nbayes.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/ml/src/nbayes.cpp b/modules/ml/src/nbayes.cpp index b37f4a4c5..589d172aa 100644 --- a/modules/ml/src/nbayes.cpp +++ b/modules/ml/src/nbayes.cpp @@ -404,20 +404,20 @@ float CvNormalBayesClassifier::predict( const CvMat* samples, CvMat* results, Cv if( results ) { - if( !CV_IS_MAT(results) || (CV_MAT_TYPE(results->type) != CV_32FC1 && - CV_MAT_TYPE(results->type) != CV_32SC1) || - (results->cols != 1 && results->rows != 1) || - results->cols + results->rows - 1 != samples->rows ) + if( !CV_IS_MAT(results) || (CV_MAT_TYPE(results->type) != CV_32FC1 && + CV_MAT_TYPE(results->type) != CV_32SC1) || + (results->cols != 1 && results->rows != 1) || + results->cols + results->rows - 1 != samples->rows ) CV_Error( CV_StsBadArg, "The output array must be integer or floating-point vector " "with the number of elements = number of rows in the input matrix" ); } if( results_prob ) { - if( !CV_IS_MAT(results_prob) || (CV_MAT_TYPE(results_prob->type) != CV_32FC1 && + if( !CV_IS_MAT(results_prob) || (CV_MAT_TYPE(results_prob->type) != CV_32FC1 && CV_MAT_TYPE(results_prob->type) != CV_64FC1) || - (results_prob->cols != 1 && results_prob->rows != 1) || - results_prob->cols + results_prob->rows - 1 != samples->rows ) + (results_prob->cols != 1 && results_prob->rows != 1) || + results_prob->cols + results_prob->rows - 1 != samples->rows ) CV_Error( CV_StsBadArg, "The output array must be double or float vector " "with the number of elements = number of rows in the input matrix" ); } From f756171f7be444920485b3e21eaea839e5954db2 Mon Sep 17 00:00:00 2001 From: Cosmin Boaca Date: Thu, 30 Jan 2014 16:43:56 +0200 Subject: [PATCH 286/295] Fixed alignment --- modules/ml/src/nbayes.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ml/src/nbayes.cpp b/modules/ml/src/nbayes.cpp index 589d172aa..938f3fbd8 100644 --- a/modules/ml/src/nbayes.cpp +++ b/modules/ml/src/nbayes.cpp @@ -407,7 +407,7 @@ float CvNormalBayesClassifier::predict( const CvMat* samples, CvMat* results, Cv if( !CV_IS_MAT(results) || (CV_MAT_TYPE(results->type) != CV_32FC1 && CV_MAT_TYPE(results->type) != CV_32SC1) || (results->cols != 1 && results->rows != 1) || - results->cols + results->rows - 1 != samples->rows ) + results->cols + results->rows - 1 != samples->rows ) CV_Error( CV_StsBadArg, "The output array must be integer or floating-point vector " "with the number of elements = number of rows in the input matrix" ); } @@ -415,9 +415,9 @@ float CvNormalBayesClassifier::predict( const CvMat* samples, CvMat* results, Cv if( results_prob ) { if( !CV_IS_MAT(results_prob) || (CV_MAT_TYPE(results_prob->type) != CV_32FC1 && - CV_MAT_TYPE(results_prob->type) != CV_64FC1) || + CV_MAT_TYPE(results_prob->type) != CV_64FC1) || (results_prob->cols != 1 && results_prob->rows != 1) || - results_prob->cols + results_prob->rows - 1 != samples->rows ) + results_prob->cols + results_prob->rows - 1 != samples->rows ) CV_Error( CV_StsBadArg, "The output array must be double or float vector " "with the number of elements = number of rows in the input matrix" ); } From b7f2b671a27098929f0622b211ec450f1b3a3f7e Mon Sep 17 00:00:00 2001 From: Ivy Lee Date: Thu, 30 Jan 2014 21:53:05 +0000 Subject: [PATCH 287/295] Fixed Bug #3514 Incorrect Chi-Square distance used in LBPH FaceRecognizer --- modules/contrib/src/facerec.cpp | 2 +- modules/imgproc/include/opencv2/imgproc.hpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/contrib/src/facerec.cpp b/modules/contrib/src/facerec.cpp index 669fd735a..c6f154af2 100644 --- a/modules/contrib/src/facerec.cpp +++ b/modules/contrib/src/facerec.cpp @@ -833,7 +833,7 @@ void LBPH::predict(InputArray _src, int &minClass, double &minDist) const { minDist = DBL_MAX; minClass = -1; for(size_t sampleIdx = 0; sampleIdx < _histograms.size(); sampleIdx++) { - double dist = compareHist(_histograms[sampleIdx], query, HISTCMP_CHISQR); + double dist = compareHist(_histograms[sampleIdx], query, HISTCMP_CHISQR_ALT); if((dist < minDist) && (dist < _threshold)) { minDist = dist; minClass = _labels.at((int) sampleIdx); diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 2b94e0de2..84de283c0 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -203,7 +203,8 @@ enum { HISTCMP_CORREL = 0, HISTCMP_CHISQR = 1, HISTCMP_INTERSECT = 2, HISTCMP_BHATTACHARYYA = 3, - HISTCMP_HELLINGER = HISTCMP_BHATTACHARYYA + HISTCMP_HELLINGER = HISTCMP_BHATTACHARYYA, + HISTCMP_CHISQR_ALT = 4 }; //! the color conversion code From 68f5dd41706eb11cd0d8a002bc13dc2a805bbc83 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 30 Jan 2014 19:37:01 +0400 Subject: [PATCH 288/295] simplified cv::boxFilter OpenCL impl --- modules/imgproc/src/opencl/boxFilter.cl | 276 ++++---------------- modules/imgproc/src/smooth.cpp | 173 +++++------- modules/imgproc/test/ocl/test_boxfilter.cpp | 24 +- 3 files changed, 132 insertions(+), 341 deletions(-) diff --git a/modules/imgproc/src/opencl/boxFilter.cl b/modules/imgproc/src/opencl/boxFilter.cl index b65934ad4..16a15cfe2 100644 --- a/modules/imgproc/src/opencl/boxFilter.cl +++ b/modules/imgproc/src/opencl/boxFilter.cl @@ -39,45 +39,15 @@ // //M*/ -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////Macro for border type//////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////// -#ifdef BORDER_REPLICATE -//BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh -#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? (l_edge) : (i)) -#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? (r_edge)-1 : (addr)) -#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? (t_edge) :(i)) -#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? (b_edge)-1 :(addr)) +#ifdef DOUBLE_SUPPORT +#ifdef cl_amd_fp64 +#pragma OPENCL EXTENSION cl_amd_fp64:enable +#elif defined (cl_khr_fp64) +#pragma OPENCL EXTENSION cl_khr_fp64:enable +#endif #endif -#ifdef BORDER_REFLECT -//BORDER_REFLECT: fedcba|abcdefgh|hgfedcb -#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? -(i)-1 : (i)) -#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? -(i)-1+((r_edge)<<1) : (addr)) -#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? -(i)-1 : (i)) -#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? -(i)-1+((b_edge)<<1) : (addr)) -#endif - -#ifdef BORDER_REFLECT_101 -//BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba -#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? -(i) : (i)) -#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? -(i)-2+((r_edge)<<1) : (addr)) -#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? -(i) : (i)) -#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? -(i)-2+((b_edge)<<1) : (addr)) -#endif - -//blur function does not support BORDER_WRAP -#ifdef BORDER_WRAP -//BORDER_WRAP: cdefgh|abcdefgh|abcdefg -#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? (i)+(r_edge) : (i)) -#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? (i)-(r_edge) : (addr)) -#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? (i)+(b_edge) : (i)) -#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? (i)-(b_edge) : (addr)) -#endif - -#ifdef EXTRA_EXTRAPOLATION // border > src image size #ifdef BORDER_CONSTANT -// None #elif defined BORDER_REPLICATE #define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \ { \ @@ -131,248 +101,110 @@ #else #error No extrapolation method #endif -#else -#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \ - { \ - int _row = y - minY, _col = x - minX; \ - _row = ADDR_H(_row, 0, maxY - minY); \ - _row = ADDR_B(_row, maxY - minY, _row); \ - y = _row + minY; \ - \ - _col = ADDR_L(_col, 0, maxX - minX); \ - _col = ADDR_R(_col, maxX - minX, _col); \ - x = _col + minX; \ - } -#endif -#if USE_DOUBLE -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#define FPTYPE double -#define CONVERT_TO_FPTYPE CAT(convert_double, VEC_SIZE) -#else -#define FPTYPE float -#define CONVERT_TO_FPTYPE CAT(convert_float, VEC_SIZE) -#endif - -#if DATA_DEPTH == 0 -#define BASE_TYPE uchar -#elif DATA_DEPTH == 1 -#define BASE_TYPE char -#elif DATA_DEPTH == 2 -#define BASE_TYPE ushort -#elif DATA_DEPTH == 3 -#define BASE_TYPE short -#elif DATA_DEPTH == 4 -#define BASE_TYPE int -#elif DATA_DEPTH == 5 -#define BASE_TYPE float -#elif DATA_DEPTH == 6 -#define BASE_TYPE double -#else -#error data_depth -#endif - -#define __CAT(x, y) x##y -#define CAT(x, y) __CAT(x, y) - -#define uchar1 uchar -#define char1 char -#define ushort1 ushort -#define short1 short -#define int1 int -#define float1 float -#define double1 double - -#define convert_uchar1_sat_rte convert_uchar_sat_rte -#define convert_char1_sat_rte convert_char_sat_rte -#define convert_ushort1_sat_rte convert_ushort_sat_rte -#define convert_short1_sat_rte convert_short_sat_rte -#define convert_int1_sat_rte convert_int_sat_rte -#define convert_float1 -#define convert_double1 - -#if DATA_DEPTH == 5 || DATA_DEPTH == 6 -#define CONVERT_TO_TYPE CAT(CAT(convert_, BASE_TYPE), VEC_SIZE) -#else -#define CONVERT_TO_TYPE CAT(CAT(CAT(convert_, BASE_TYPE), VEC_SIZE), _sat_rte) -#endif - -#define VEC_SIZE DATA_CHAN - -#define VEC_TYPE CAT(BASE_TYPE, VEC_SIZE) -#define TYPE VEC_TYPE - -#define SCALAR_TYPE CAT(FPTYPE, VEC_SIZE) - -#define INTERMEDIATE_TYPE CAT(FPTYPE, VEC_SIZE) - -#define TYPE_SIZE (VEC_SIZE*sizeof(BASE_TYPE)) +#define noconvert struct RectCoords { int x1, y1, x2, y2; }; -//#define DEBUG -#ifdef DEBUG -#define DEBUG_ONLY(x) x -#define ASSERT(condition) do { if (!(condition)) { printf("BUG in boxFilter kernel (global=%d,%d): " #condition "\n", get_global_id(0), get_global_id(1)); } } while (0) -#else -#define DEBUG_ONLY(x) -#define ASSERT(condition) -#endif - - -inline INTERMEDIATE_TYPE readSrcPixel(int2 pos, __global const uchar* srcptr, int srcstep, const struct RectCoords srcCoords -#ifdef BORDER_CONSTANT - , SCALAR_TYPE borderValue -#endif - ) +inline WT readSrcPixel(int2 pos, __global const uchar * srcptr, int src_step, const struct RectCoords srcCoords) { #ifdef BORDER_ISOLATED - if(pos.x >= srcCoords.x1 && pos.y >= srcCoords.y1 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) + if (pos.x >= srcCoords.x1 && pos.y >= srcCoords.y1 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) #else - if(pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) + if (pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) #endif { - __global TYPE* ptr = (__global TYPE*)(srcptr + pos.y * srcstep + pos.x * sizeof(TYPE)); - return CONVERT_TO_FPTYPE(*ptr); + int src_index = mad24(pos.y, src_step, pos.x * (int)sizeof(ST)); + return convertToWT(*(__global const ST *)(srcptr + src_index)); } else { #ifdef BORDER_CONSTANT - return borderValue; + return (WT)(0); #else - int selected_col = pos.x; - int selected_row = pos.y; + int selected_col = pos.x, selected_row = pos.y; EXTRAPOLATE(selected_col, selected_row, #ifdef BORDER_ISOLATED - srcCoords.x1, srcCoords.y1, + srcCoords.x1, srcCoords.y1, #else - 0, 0, + 0, 0, #endif - srcCoords.x2, srcCoords.y2 - ); + srcCoords.x2, srcCoords.y2); - // debug border mapping - //printf("pos=%d,%d --> %d, %d\n", pos.x, pos.y, selected_col, selected_row); - - pos = (int2)(selected_col, selected_row); - if(pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) - { - __global TYPE* ptr = (__global TYPE*)(srcptr + pos.y * srcstep + pos.x * sizeof(TYPE)); - return CONVERT_TO_FPTYPE(*ptr); - } - else - { - // for debug only - DEBUG_ONLY(printf("BUG in boxFilter kernel\n")); - return (FPTYPE)(0.0f); - } + int src_index = mad24(selected_row, src_step, selected_col * (int)sizeof(ST)); + return convertToWT(*(__global const ST *)(srcptr + src_index)); #endif } } -// INPUT PARAMETER: BLOCK_SIZE_Y (via defines) - -__kernel -__attribute__((reqd_work_group_size(LOCAL_SIZE, 1, 1))) -void boxFilter(__global const uchar* srcptr, int srcstep, int srcOffsetX, int srcOffsetY, int srcEndX, int srcEndY, - __global uchar* dstptr, int dststep, int dstoffset, - int rows, int cols, -#ifdef BORDER_CONSTANT - SCALAR_TYPE borderValue, +__kernel void boxFilter(__global const uchar * srcptr, int src_step, int srcOffsetX, int srcOffsetY, int srcEndX, int srcEndY, + __global uchar * dstptr, int dst_step, int dst_offset, int rows, int cols +#ifdef NORMALIZE + , float alpha #endif - FPTYPE alpha - ) + ) { - const struct RectCoords srcCoords = {srcOffsetX, srcOffsetY, srcEndX, srcEndY}; // for non-isolated border: offsetX, offsetY, wholeX, wholeY + const struct RectCoords srcCoords = { srcOffsetX, srcOffsetY, srcEndX, srcEndY }; // for non-isolated border: offsetX, offsetY, wholeX, wholeY - const int x = get_local_id(0) + (LOCAL_SIZE - (KERNEL_SIZE_X - 1)) * get_group_id(0) - ANCHOR_X; - const int y = get_global_id(1) * BLOCK_SIZE_Y; - - const int local_id = get_local_id(0); - - INTERMEDIATE_TYPE data[KERNEL_SIZE_Y]; - __local INTERMEDIATE_TYPE sumOfCols[LOCAL_SIZE]; + int x = get_local_id(0) + (LOCAL_SIZE_X - (KERNEL_SIZE_X - 1)) * get_group_id(0) - ANCHOR_X; + int y = get_global_id(1) * BLOCK_SIZE_Y; + int local_id = get_local_id(0); + WT data[KERNEL_SIZE_Y]; + __local WT sumOfCols[LOCAL_SIZE_X]; int2 srcPos = (int2)(srcCoords.x1 + x, srcCoords.y1 + y - ANCHOR_Y); - for(int sy = 0; sy < KERNEL_SIZE_Y; sy++, srcPos.y++) - { - data[sy] = readSrcPixel(srcPos, srcptr, srcstep, srcCoords -#ifdef BORDER_CONSTANT - , borderValue -#endif - ); - } - INTERMEDIATE_TYPE tmp_sum = 0; - for(int sy = 0; sy < KERNEL_SIZE_Y; sy++) - { - tmp_sum += (data[sy]); - } + #pragma unroll + for (int sy = 0; sy < KERNEL_SIZE_Y; sy++, srcPos.y++) + data[sy] = readSrcPixel(srcPos, srcptr, src_step, srcCoords); + + WT tmp_sum = (WT)(0); + #pragma unroll + for (int sy = 0; sy < KERNEL_SIZE_Y; sy++) + tmp_sum += data[sy]; sumOfCols[local_id] = tmp_sum; barrier(CLK_LOCAL_MEM_FENCE); - int2 pos = (int2)(x, y); - __global TYPE* dstPtr = (__global TYPE*)(dstptr + pos.y * dststep + dstoffset + pos.x * TYPE_SIZE/*sizeof(TYPE)*/); // Pointer can be out of bounds! + int dst_index = mad24(y, dst_step, x * (int)sizeof(DT) + dst_offset); + __global DT * dst = (__global DT *)(dstptr + dst_index); int sy_index = 0; // current index in data[] array - int stepsY = min(rows - pos.y, BLOCK_SIZE_Y); - ASSERT(stepsY > 0); - for (; ;) + for (int i = 0, stepY = min(rows - y, BLOCK_SIZE_Y); i < stepY; ++i) { - ASSERT(pos.y < rows); - - if(local_id >= ANCHOR_X && local_id < LOCAL_SIZE - (KERNEL_SIZE_X - 1 - ANCHOR_X) && - pos.x >= 0 && pos.x < cols) + if (local_id >= ANCHOR_X && local_id < LOCAL_SIZE_X - (KERNEL_SIZE_X - 1 - ANCHOR_X) && + x >= 0 && x < cols) { - ASSERT(pos.y >= 0 && pos.y < rows); + WT total_sum = (WT)(0); - INTERMEDIATE_TYPE total_sum = 0; -#pragma unroll + #pragma unroll for (int sx = 0; sx < KERNEL_SIZE_X; sx++) - { total_sum += sumOfCols[local_id + sx - ANCHOR_X]; - } - *dstPtr = CONVERT_TO_TYPE(((INTERMEDIATE_TYPE)alpha) * total_sum); - } -#if BLOCK_SIZE_Y == 1 - break; +#ifdef NORMALIZE + dst[0] = convertToDT((WT)(alpha) * total_sum); #else - if (--stepsY == 0) - break; - + dst[0] = convertToDT(total_sum); +#endif + } barrier(CLK_LOCAL_MEM_FENCE); - tmp_sum = sumOfCols[local_id]; // TODO FIX IT: workaround for BUG in OpenCL compiler - // only works with scalars: ASSERT(fabs(tmp_sum - sumOfCols[local_id]) < (INTERMEDIATE_TYPE)1e-6); + tmp_sum = sumOfCols[local_id]; tmp_sum -= data[sy_index]; - data[sy_index] = readSrcPixel(srcPos, srcptr, srcstep, srcCoords -#ifdef BORDER_CONSTANT - , borderValue -#endif - ); + data[sy_index] = readSrcPixel(srcPos, srcptr, src_step, srcCoords); srcPos.y++; tmp_sum += data[sy_index]; sumOfCols[local_id] = tmp_sum; - sy_index = (sy_index + 1 < KERNEL_SIZE_Y) ? sy_index + 1 : 0; - + sy_index = sy_index + 1 < KERNEL_SIZE_Y ? sy_index + 1 : 0; barrier(CLK_LOCAL_MEM_FENCE); - // next line - DEBUG_ONLY(pos.y++); - dstPtr = (__global TYPE*)((__global char*)dstPtr + dststep); // Pointer can be out of bounds! -#endif // BLOCK_SIZE_Y == 1 + dst = (__global DT *)((__global uchar *)dst + dst_step); } } diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index e5c0cde28..9eb959901 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -611,155 +611,114 @@ template<> struct ColumnSum : public BaseColumnFilter std::vector sum; }; +#ifdef HAVE_OPENCL + #define DIVUP(total, grain) ((total + grain - 1) / (grain)) static bool ocl_boxFilter( InputArray _src, OutputArray _dst, int ddepth, - Size ksize, Point anchor, int borderType ) + Size ksize, Point anchor, int borderType, bool normalize ) { - int type = _src.type(); - int cn = CV_MAT_CN(type); - if ((1 != cn) && (2 != cn) && (4 != cn)) - return false;//TODO + int type = _src.type(), sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), esz = CV_ELEM_SIZE(type); + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; - int sdepth = CV_MAT_DEPTH(type); - if( ddepth < 0 ) + if (ddepth < 0) ddepth = sdepth; - else if (ddepth != sdepth) + + if (!(cn == 1 || cn == 2 || cn == 4) || (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F)) || + _src.offset() % esz != 0 || _src.step() % esz != 0) return false; - if( anchor.x < 0 ) + + if (anchor.x < 0) anchor.x = ksize.width / 2; - if( anchor.y < 0 ) + if (anchor.y < 0) anchor.y = ksize.height / 2; - ocl::Kernel kernel; - - //Normalize the result by default + int computeUnits = ocl::Device::getDefault().maxComputeUnits(); float alpha = 1.0f / (ksize.height * ksize.width); - bool isIsolatedBorder = (borderType & BORDER_ISOLATED) != 0; - bool useDouble = (CV_64F == sdepth); - const cv::ocl::Device &device = cv::ocl::Device::getDefault(); - int doubleFPConfig = device.doubleFPConfig(); - if (useDouble && (0 == doubleFPConfig)) - return false;// may be we have to check is (0 != (CL_FP_SOFT_FLOAT & doubleFPConfig)) ? + Size size = _src.size(), wholeSize; + bool isolated = (borderType & BORDER_ISOLATED) != 0; + borderType &= ~BORDER_ISOLATED; + int wdepth = std::max(CV_32F, std::max(ddepth, sdepth)); - const char* btype = NULL; - switch (borderType & ~BORDER_ISOLATED) + const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", 0, "BORDER_REFLECT_101" }; + size_t globalsize[2] = { size.width, size.height }; + size_t localsize[2] = { 0, 1 }; + + UMat src = _src.getUMat(); + if (!isolated) { - case BORDER_CONSTANT: - btype = "BORDER_CONSTANT"; - break; - case BORDER_REPLICATE: - btype = "BORDER_REPLICATE"; - break; - case BORDER_REFLECT: - btype = "BORDER_REFLECT"; - break; - case BORDER_WRAP: - //CV_Error(CV_StsUnsupportedFormat, "BORDER_WRAP is not supported!"); - return false; - case BORDER_REFLECT101: - btype = "BORDER_REFLECT_101"; - break; - } - - cv::Size sz = _src.size(); - - size_t globalsize[2] = {sz.width, sz.height}; - size_t localsize[2] = {0, 1}; - - UMat src; Size wholeSize; - if (!isIsolatedBorder) - { - src = _src.getUMat(); Point ofs; src.locateROI(wholeSize, ofs); } - size_t maxWorkItemSizes[32]; device.maxWorkItemSizes(maxWorkItemSizes); - size_t tryWorkItems = maxWorkItemSizes[0]; - for (;;) + int h = isolated ? size.height : wholeSize.height; + int w = isolated ? size.width : wholeSize.width; + + size_t maxWorkItemSizes[32]; + ocl::Device::getDefault().maxWorkItemSizes(maxWorkItemSizes); + int tryWorkItems = (int)maxWorkItemSizes[0]; + + ocl::Kernel kernel; + for ( ; ; ) { - size_t BLOCK_SIZE = tryWorkItems; - while (BLOCK_SIZE > 32 && BLOCK_SIZE >= (size_t)ksize.width * 2 && BLOCK_SIZE > (size_t)sz.width * 2) - BLOCK_SIZE /= 2; - size_t BLOCK_SIZE_Y = 8; // TODO Check heuristic value on devices - while (BLOCK_SIZE_Y < BLOCK_SIZE / 8 && BLOCK_SIZE_Y * device.maxComputeUnits() * 32 < (size_t)sz.height) + int BLOCK_SIZE_X = tryWorkItems, BLOCK_SIZE_Y = 8; + + while (BLOCK_SIZE_X > 32 && BLOCK_SIZE_X >= ksize.width * 2 && BLOCK_SIZE_X > size.width * 2) + BLOCK_SIZE_X /= 2; + while (BLOCK_SIZE_Y < BLOCK_SIZE_X / 8 && BLOCK_SIZE_Y * computeUnits * 32 < size.height) BLOCK_SIZE_Y *= 2; - if ((size_t)ksize.width > BLOCK_SIZE) + if (ksize.width > BLOCK_SIZE_X || w < ksize.width || h < ksize.height) return false; - int requiredTop = anchor.y; - int requiredLeft = (int)BLOCK_SIZE; // not this: anchor.x; - int requiredBottom = ksize.height - 1 - anchor.y; - int requiredRight = (int)BLOCK_SIZE; // not this: ksize.width - 1 - anchor.x; - int h = isIsolatedBorder ? sz.height : wholeSize.height; - int w = isIsolatedBorder ? sz.width : wholeSize.width; + char cvt[2][50]; + String opts = format("-D LOCAL_SIZE_X=%d -D BLOCK_SIZE_Y=%d -D ST=%s -D DT=%s -D WT=%s -D convertToDT=%s -D convertToWT=%s " + "-D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d -D %s%s%s%s", + BLOCK_SIZE_X, BLOCK_SIZE_Y, ocl::typeToStr(type), ocl::typeToStr(CV_MAKE_TYPE(ddepth, cn)), + ocl::typeToStr(CV_MAKE_TYPE(wdepth, cn)), + ocl::convertTypeStr(wdepth, ddepth, cn, cvt[0]), + ocl::convertTypeStr(sdepth, wdepth, cn, cvt[1]), + anchor.x, anchor.y, ksize.width, ksize.height, borderMap[borderType], + isolated ? " -D BORDER_ISOLATED" : "", doubleSupport ? " -D DOUBLE_SUPPORT" : "", + normalize ? " -D NORMALIZE" : ""); - bool extra_extrapolation = h < requiredTop || h < requiredBottom || w < requiredLeft || w < requiredRight; + localsize[0] = BLOCK_SIZE_X; + globalsize[0] = DIVUP(size.width, BLOCK_SIZE_X - (ksize.width - 1)) * BLOCK_SIZE_X; + globalsize[1] = DIVUP(size.height, BLOCK_SIZE_Y); - if ((w < ksize.width) || (h < ksize.height)) - return false; - - char build_options[1024]; - sprintf(build_options, "-D LOCAL_SIZE=%d -D BLOCK_SIZE_Y=%d -D DATA_DEPTH=%d -D DATA_CHAN=%d -D USE_DOUBLE=%d -D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d -D %s -D %s -D %s", - (int)BLOCK_SIZE, (int)BLOCK_SIZE_Y, - sdepth, cn, useDouble ? 1 : 0, - anchor.x, anchor.y, ksize.width, ksize.height, - btype, - extra_extrapolation ? "EXTRA_EXTRAPOLATION" : "NO_EXTRA_EXTRAPOLATION", - isIsolatedBorder ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED"); - - localsize[0] = BLOCK_SIZE; - globalsize[0] = DIVUP(sz.width, BLOCK_SIZE - (ksize.width - 1)) * BLOCK_SIZE; - globalsize[1] = DIVUP(sz.height, BLOCK_SIZE_Y); - - cv::String errmsg; - kernel.create("boxFilter", cv::ocl::imgproc::boxFilter_oclsrc, build_options); + kernel.create("boxFilter", cv::ocl::imgproc::boxFilter_oclsrc, opts); size_t kernelWorkGroupSize = kernel.workGroupSize(); if (localsize[0] <= kernelWorkGroupSize) break; - - if (BLOCK_SIZE < kernelWorkGroupSize) + if (BLOCK_SIZE_X < (int)kernelWorkGroupSize) return false; - tryWorkItems = kernelWorkGroupSize; + + tryWorkItems = (int)kernelWorkGroupSize; } - _dst.create(sz, CV_MAKETYPE(ddepth, cn)); + _dst.create(size, CV_MAKETYPE(ddepth, cn)); UMat dst = _dst.getUMat(); - if (src.empty()) - src = _src.getUMat(); - int idxArg = 0; - idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(src)); + + int idxArg = kernel.set(0, ocl::KernelArg::PtrReadOnly(src)); idxArg = kernel.set(idxArg, (int)src.step); int srcOffsetX = (int)((src.offset % src.step) / src.elemSize()); int srcOffsetY = (int)(src.offset / src.step); - int srcEndX = (isIsolatedBorder ? (srcOffsetX + sz.width) : wholeSize.width); - int srcEndY = (isIsolatedBorder ? (srcOffsetY + sz.height) : wholeSize.height); + int srcEndX = isolated ? srcOffsetX + size.width : wholeSize.width; + int srcEndY = isolated ? srcOffsetY + size.height : wholeSize.height; idxArg = kernel.set(idxArg, srcOffsetX); idxArg = kernel.set(idxArg, srcOffsetY); idxArg = kernel.set(idxArg, srcEndX); idxArg = kernel.set(idxArg, srcEndY); idxArg = kernel.set(idxArg, ocl::KernelArg::WriteOnly(dst)); - float borderValue[4] = {0, 0, 0, 0}; - double borderValueDouble[4] = {0, 0, 0, 0}; - if ((borderType & ~BORDER_ISOLATED) == BORDER_CONSTANT) - { - int cnocl = (3 == cn) ? 4 : cn; - if (useDouble) - idxArg = kernel.set(idxArg, (void *)&borderValueDouble[0], sizeof(double) * cnocl); - else - idxArg = kernel.set(idxArg, (void *)&borderValue[0], sizeof(float) * cnocl); - } - if (useDouble) - idxArg = kernel.set(idxArg, (double)alpha); - else + if (normalize) idxArg = kernel.set(idxArg, (float)alpha); - return kernel.run(2, globalsize, localsize, true); + return kernel.run(2, globalsize, localsize, false); } +#endif + } @@ -862,9 +821,7 @@ void cv::boxFilter( InputArray _src, OutputArray _dst, int ddepth, Size ksize, Point anchor, bool normalize, int borderType ) { - bool use_opencl = ocl::useOpenCL() && _dst.isUMat() && normalize; - if( use_opencl && ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType) ) - return; + CV_OCL_RUN(_dst.isUMat(), ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType, normalize)) Mat src = _src.getMat(); int sdepth = src.depth(), cn = src.channels(); diff --git a/modules/imgproc/test/ocl/test_boxfilter.cpp b/modules/imgproc/test/ocl/test_boxfilter.cpp index 178aef4c2..96ad46fb5 100644 --- a/modules/imgproc/test/ocl/test_boxfilter.cpp +++ b/modules/imgproc/test/ocl/test_boxfilter.cpp @@ -56,32 +56,34 @@ enum ///////////////////////////////////////////////////////////////////////////////////////////////// // boxFilter -PARAM_TEST_CASE(BoxFilter, MatDepth, Channels, BorderType, bool) +PARAM_TEST_CASE(BoxFilter, MatDepth, Channels, BorderType, bool, bool) { static const int kernelMinSize = 2; static const int kernelMaxSize = 10; - int type; + int depth, cn; Size ksize; Size dsize; Point anchor; int borderType; - bool useRoi; + bool normalize, useRoi; TEST_DECLARE_INPUT_PARAMETER(src) TEST_DECLARE_OUTPUT_PARAMETER(dst) virtual void SetUp() { - type = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1)); + depth = GET_PARAM(0); + cn = GET_PARAM(1); borderType = GET_PARAM(2); // only not isolated border tested, because CPU module doesn't support isolated border case. - useRoi = GET_PARAM(3); + normalize = GET_PARAM(3); + useRoi = GET_PARAM(4); } void random_roi() { + int type = CV_MAKE_TYPE(depth, cn); dsize = randomSize(1, MAX_VALUE); - ksize = randomSize(kernelMinSize, kernelMaxSize); Size roiSize = randomSize(ksize.width, MAX_VALUE, ksize.height, MAX_VALUE); @@ -100,8 +102,7 @@ PARAM_TEST_CASE(BoxFilter, MatDepth, Channels, BorderType, bool) void Near(double threshold = 0.0) { - EXPECT_MAT_NEAR(dst, udst, threshold); - EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold); + OCL_EXPECT_MATS_NEAR(dst, threshold) } }; @@ -111,10 +112,10 @@ OCL_TEST_P(BoxFilter, Mat) { random_roi(); - OCL_OFF(cv::boxFilter(src_roi, dst_roi, -1, ksize, anchor, true, borderType)); - OCL_ON(cv::boxFilter(usrc_roi, udst_roi, -1, ksize, anchor, true, borderType)); + OCL_OFF(cv::boxFilter(src_roi, dst_roi, -1, ksize, anchor, normalize, borderType)); + OCL_ON(cv::boxFilter(usrc_roi, udst_roi, -1, ksize, anchor, normalize, borderType)); - Near(1.0); + Near(depth <= CV_32S ? 1 : 1e-3); } } @@ -127,6 +128,7 @@ OCL_INSTANTIATE_TEST_CASE_P(ImageProc, BoxFilter, (BorderType)BORDER_REPLICATE, (BorderType)BORDER_REFLECT, (BorderType)BORDER_REFLECT_101), + Bool(), Bool() // ROI ) ); From 69630ee9d9506259aab42099ffbae00cceef5694 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Fri, 31 Jan 2014 10:46:29 +0400 Subject: [PATCH 289/295] fixed test --- modules/video/test/ocl/test_bgfg_mog2.cpp | 33 ++++++++++++++++------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/modules/video/test/ocl/test_bgfg_mog2.cpp b/modules/video/test/ocl/test_bgfg_mog2.cpp index e9a73cb9b..bfb1621fe 100644 --- a/modules/video/test/ocl/test_bgfg_mog2.cpp +++ b/modules/video/test/ocl/test_bgfg_mog2.cpp @@ -20,7 +20,7 @@ defined(WIN32) namespace cvtest { namespace ocl { -////////////////////////// MOG2/////////////////////////////////// +//////////////////////////Mog2_Update/////////////////////////////////// namespace { @@ -28,11 +28,10 @@ namespace IMPLEMENT_PARAM_CLASS(DetectShadow, bool) } -PARAM_TEST_CASE(Mog2, UseGray, DetectShadow) +PARAM_TEST_CASE(Mog2_Update, UseGray, DetectShadow) { bool useGray; bool detectShadow; - bool useRoi; virtual void SetUp() { useGray = GET_PARAM(0); @@ -40,7 +39,7 @@ PARAM_TEST_CASE(Mog2, UseGray, DetectShadow) } }; -OCL_TEST_P(Mog2, Update) +OCL_TEST_P(Mog2_Update, Accuracy) { string inputFile = string(TS::ptr()->get_data_path()) + "video/768x576.avi"; VideoCapture cap(inputFile); @@ -77,11 +76,19 @@ OCL_TEST_P(Mog2, Update) } } -OCL_TEST_P(Mog2, getBackgroundImage) -{ - if (useGray) - return; +//////////////////////////Mog2_getBackgroundImage/////////////////////////////////// +PARAM_TEST_CASE(Mog2_getBackgroundImage, DetectShadow) +{ + bool detectShadow; + virtual void SetUp() + { + detectShadow = GET_PARAM(0); + } +}; + +OCL_TEST_P(Mog2_getBackgroundImage, Accuracy) +{ string inputFile = string(TS::ptr()->get_data_path()) + "video/768x576.avi"; VideoCapture cap(inputFile); ASSERT_TRUE(cap.isOpened()); @@ -113,11 +120,17 @@ OCL_TEST_P(Mog2, getBackgroundImage) EXPECT_MAT_NEAR(background, u_background, 1.0); } -OCL_INSTANTIATE_TEST_CASE_P(OCL_Video, Mog2, Combine( +/////////////////////////////////////////////////////////////////////////////////////////// + +OCL_INSTANTIATE_TEST_CASE_P(OCL_Video, Mog2_Update, Combine( Values(UseGray(true), UseGray(false)), Values(DetectShadow(true), DetectShadow(false))) ); + +OCL_INSTANTIATE_TEST_CASE_P(OCL_Video, Mog2_getBackgroundImage, (Values(DetectShadow(true), DetectShadow(false))) + ); + }}// namespace cvtest::ocl #endif -#endif +#endif \ No newline at end of file From 0f168936a08c24f48cef02cab65520f0d1e06cf7 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 31 Jan 2014 13:19:16 +0400 Subject: [PATCH 290/295] OCL module 2 trash --- modules/nonfree/CMakeLists.txt | 2 +- modules/ocl/CMakeLists.txt | 11 - ...mera_calibration_and_3D_reconstruction.rst | 328 --- modules/ocl/doc/data_structures.rst | 189 -- .../doc/feature_detection_and_description.rst | 836 ------ modules/ocl/doc/image_filtering.rst | 719 ------ modules/ocl/doc/image_processing.rst | 347 --- .../doc/images/adaptiveBilateralFilter.jpg | Bin 65410 -> 0 bytes modules/ocl/doc/introduction.rst | 73 - modules/ocl/doc/matrix_reductions.rst | 106 - modules/ocl/doc/ml_machine_learning.rst | 106 - modules/ocl/doc/object_detection.rst | 95 - modules/ocl/doc/ocl.rst | 21 - modules/ocl/doc/operations_on_matrices.rst | 602 ----- .../doc/structures_and_utility_functions.rst | 56 - modules/ocl/doc/video_analysis.rst | 561 ----- modules/ocl/include/opencv2/ocl.hpp | 2230 ----------------- .../include/opencv2/ocl/matrix_operations.hpp | 490 ---- modules/ocl/include/opencv2/ocl/ocl.hpp | 48 - .../opencv2/ocl/private/opencl_dumpinfo.hpp | 154 -- .../opencv2/ocl/private/opencl_utils.hpp | 115 - .../ocl/include/opencv2/ocl/private/util.hpp | 191 -- modules/ocl/perf/main.cpp | 76 - modules/ocl/perf/perf_arithm.cpp | 1127 --------- modules/ocl/perf/perf_bgfg.cpp | 289 --- modules/ocl/perf/perf_blend.cpp | 130 - modules/ocl/perf/perf_brief.cpp | 114 - modules/ocl/perf/perf_brute_force_matcher.cpp | 177 -- modules/ocl/perf/perf_calib3d.cpp | 85 - modules/ocl/perf/perf_canny.cpp | 76 - modules/ocl/perf/perf_color.cpp | 110 - modules/ocl/perf/perf_fast.cpp | 93 - modules/ocl/perf/perf_fft.cpp | 88 - modules/ocl/perf/perf_filters.cpp | 416 --- modules/ocl/perf/perf_gemm.cpp | 88 - modules/ocl/perf/perf_gftt.cpp | 95 - modules/ocl/perf/perf_haar.cpp | 153 -- modules/ocl/perf/perf_hog.cpp | 100 - modules/ocl/perf/perf_hough.cpp | 106 - modules/ocl/perf/perf_imgproc.cpp | 737 ------ modules/ocl/perf/perf_imgwarp.cpp | 364 --- modules/ocl/perf/perf_kalman.cpp | 103 - modules/ocl/perf/perf_match_template.cpp | 121 - modules/ocl/perf/perf_matrix_operation.cpp | 238 -- modules/ocl/perf/perf_ml.cpp | 109 - modules/ocl/perf/perf_moments.cpp | 90 - modules/ocl/perf/perf_norm.cpp | 86 - modules/ocl/perf/perf_opticalflow.cpp | 255 -- modules/ocl/perf/perf_orb.cpp | 103 - modules/ocl/perf/perf_precomp.hpp | 198 -- modules/ocl/perf/perf_pyramid.cpp | 130 - modules/ocl/perf/perf_split_merge.cpp | 146 -- modules/ocl/src/arithm.cpp | 1804 ------------- modules/ocl/src/bgfg_mog.cpp | 639 ----- modules/ocl/src/blend.cpp | 99 - modules/ocl/src/brief.cpp | 91 - modules/ocl/src/brute_force_matcher.cpp | 1213 --------- modules/ocl/src/build_warps.cpp | 285 --- modules/ocl/src/canny.cpp | 387 --- modules/ocl/src/cl_context.cpp | 944 ------- modules/ocl/src/cl_operations.cpp | 549 ---- modules/ocl/src/cl_programcache.cpp | 514 ---- modules/ocl/src/cl_programcache.hpp | 85 - modules/ocl/src/color.cpp | 656 ----- modules/ocl/src/columnsum.cpp | 75 - modules/ocl/src/error.cpp | 174 -- modules/ocl/src/fast.cpp | 229 -- modules/ocl/src/fft.cpp | 382 --- modules/ocl/src/filtering.cpp | 1710 ------------- modules/ocl/src/gemm.cpp | 205 -- modules/ocl/src/gftt.cpp | 300 --- modules/ocl/src/haar.cpp | 1224 --------- modules/ocl/src/hog.cpp | 1962 --------------- modules/ocl/src/hough.cpp | 398 --- modules/ocl/src/imgproc.cpp | 2014 --------------- modules/ocl/src/interpolate_frames.cpp | 235 -- modules/ocl/src/kalman.cpp | 134 - modules/ocl/src/kmeans.cpp | 451 ---- modules/ocl/src/knearest.cpp | 151 -- modules/ocl/src/match_template.cpp | 570 ----- modules/ocl/src/matrix_operations.cpp | 632 ----- modules/ocl/src/mcwutil.cpp | 226 -- modules/ocl/src/moments.cpp | 391 --- modules/ocl/src/mssegmentation.cpp | 402 --- modules/ocl/src/opencl/arithm_LUT.cl | 107 - .../src/opencl/arithm_absdiff_nonsaturate.cl | 107 - modules/ocl/src/opencl/arithm_add.cl | 143 -- modules/ocl/src/opencl/arithm_addWeighted.cl | 75 - modules/ocl/src/opencl/arithm_add_mask.cl | 97 - modules/ocl/src/opencl/arithm_add_scalar.cl | 103 - .../ocl/src/opencl/arithm_add_scalar_mask.cl | 96 - .../ocl/src/opencl/arithm_bitwise_binary.cl | 82 - .../src/opencl/arithm_bitwise_binary_mask.cl | 88 - .../opencl/arithm_bitwise_binary_scalar.cl | 82 - .../arithm_bitwise_binary_scalar_mask.cl | 86 - modules/ocl/src/opencl/arithm_bitwise_not.cl | 253 -- modules/ocl/src/opencl/arithm_cartToPolar.cl | 141 -- modules/ocl/src/opencl/arithm_compare.cl | 74 - modules/ocl/src/opencl/arithm_exp.cl | 111 - modules/ocl/src/opencl/arithm_flip.cl | 125 - modules/ocl/src/opencl/arithm_log.cl | 111 - modules/ocl/src/opencl/arithm_magnitude.cl | 74 - modules/ocl/src/opencl/arithm_minMax.cl | 176 -- modules/ocl/src/opencl/arithm_minMaxLoc.cl | 258 -- .../ocl/src/opencl/arithm_minMaxLoc_mask.cl | 256 -- modules/ocl/src/opencl/arithm_nonzero.cl | 93 - modules/ocl/src/opencl/arithm_phase.cl | 171 -- modules/ocl/src/opencl/arithm_polarToCart.cl | 197 -- modules/ocl/src/opencl/arithm_pow.cl | 73 - modules/ocl/src/opencl/arithm_setidentity.cl | 69 - modules/ocl/src/opencl/arithm_sqrt.cl | 111 - modules/ocl/src/opencl/arithm_sum.cl | 104 - modules/ocl/src/opencl/arithm_transpose.cl | 139 - modules/ocl/src/opencl/bgfg_mog.cl | 540 ---- modules/ocl/src/opencl/blend_linear.cl | 78 - modules/ocl/src/opencl/brief.cl | 173 -- modules/ocl/src/opencl/brute_force_match.cl | 789 ------ modules/ocl/src/opencl/build_warps.cl | 207 -- modules/ocl/src/opencl/convertC3C4.cl | 153 -- modules/ocl/src/opencl/cvt_color.cl | 1599 ------------ modules/ocl/src/opencl/featdetect_fast.cl | 1331 ---------- modules/ocl/src/opencl/filter_sep_col.cl | 118 - modules/ocl/src/opencl/filter_sep_row.cl | 457 ---- .../opencl/filtering_adaptive_bilateral.cl | 429 ---- modules/ocl/src/opencl/filtering_boxFilter.cl | 376 --- modules/ocl/src/opencl/filtering_filter2D.cl | 374 --- modules/ocl/src/opencl/filtering_morph.cl | 228 -- .../opencl/filtering_sep_filter_singlepass.cl | 185 -- modules/ocl/src/opencl/haarobjectdetect.cl | 596 ----- .../src/opencl/haarobjectdetect_scaled2.cl | 323 --- modules/ocl/src/opencl/imgproc_bilateral.cl | 145 -- modules/ocl/src/opencl/imgproc_calcHarris.cl | 214 -- .../ocl/src/opencl/imgproc_calcMinEigenVal.cl | 204 -- modules/ocl/src/opencl/imgproc_canny.cl | 721 ------ modules/ocl/src/opencl/imgproc_clahe.cl | 255 -- modules/ocl/src/opencl/imgproc_columnsum.cl | 70 - modules/ocl/src/opencl/imgproc_convolve.cl | 111 - .../ocl/src/opencl/imgproc_copymakeboder.cl | 134 - modules/ocl/src/opencl/imgproc_gftt.cl | 129 - modules/ocl/src/opencl/imgproc_histogram.cl | 279 --- modules/ocl/src/opencl/imgproc_hough.cl | 280 --- modules/ocl/src/opencl/imgproc_integral.cl | 503 ---- .../ocl/src/opencl/imgproc_integral_sum.cl | 412 --- modules/ocl/src/opencl/imgproc_median.cl | 486 ---- .../opencl/imgproc_mulAndScaleSpectrums.cl | 96 - modules/ocl/src/opencl/imgproc_remap.cl | 408 --- modules/ocl/src/opencl/imgproc_resize.cl | 405 --- modules/ocl/src/opencl/imgproc_sobel3.cl | 347 --- modules/ocl/src/opencl/imgproc_threshold.cl | 136 - modules/ocl/src/opencl/imgproc_warpAffine.cl | 761 ------ .../ocl/src/opencl/imgproc_warpPerspective.cl | 682 ----- modules/ocl/src/opencl/interpolate_frames.cl | 252 -- .../src/opencl/kernel_radix_sort_by_key.cl | 176 -- modules/ocl/src/opencl/kernel_sort_by_key.cl | 244 -- .../src/opencl/kernel_stablesort_by_key.cl | 264 -- modules/ocl/src/opencl/kmeans_kernel.cl | 107 - modules/ocl/src/opencl/knearest.cl | 186 -- modules/ocl/src/opencl/match_template.cl | 853 ------- modules/ocl/src/opencl/meanShift.cl | 241 -- modules/ocl/src/opencl/merge_mat.cl | 1378 ---------- modules/ocl/src/opencl/moments.cl | 432 ---- modules/ocl/src/opencl/objdetect_hog.cl | 726 ------ modules/ocl/src/opencl/operator_convertTo.cl | 64 - modules/ocl/src/opencl/operator_copyToM.cl | 71 - modules/ocl/src/opencl/operator_setTo.cl | 95 - modules/ocl/src/opencl/operator_setToM.cl | 68 - .../ocl/src/opencl/optical_flow_farneback.cl | 450 ---- modules/ocl/src/opencl/orb.cl | 503 ---- modules/ocl/src/opencl/pyr_down.cl | 1010 -------- modules/ocl/src/opencl/pyr_up.cl | 146 -- modules/ocl/src/opencl/pyrlk.cl | 1019 -------- modules/ocl/src/opencl/split_mat.cl | 217 -- modules/ocl/src/opencl/stereobm.cl | 338 --- modules/ocl/src/opencl/stereobp.cl | 393 --- modules/ocl/src/opencl/stereocsbp.cl | 1382 ---------- modules/ocl/src/opencl/svm.cl | 211 -- modules/ocl/src/opencl/tvl1flow.cl | 386 --- modules/ocl/src/optical_flow_farneback.cpp | 542 ---- modules/ocl/src/orb.cpp | 916 ------- modules/ocl/src/precomp.hpp | 98 - modules/ocl/src/pyrdown.cpp | 91 - modules/ocl/src/pyrlk.cpp | 338 --- modules/ocl/src/pyrup.cpp | 104 - modules/ocl/src/safe_call.hpp | 69 - modules/ocl/src/sort_by_key.cpp | 472 ---- modules/ocl/src/split_merge.cpp | 300 --- modules/ocl/src/stereo_csbp.cpp | 698 ------ modules/ocl/src/stereobm.cpp | 222 -- modules/ocl/src/stereobp.cpp | 502 ---- modules/ocl/src/svm.cpp | 1136 --------- modules/ocl/src/tvl1flow.cpp | 477 ---- modules/ocl/test/main.cpp | 80 - modules/ocl/test/test_api.cpp | 213 -- modules/ocl/test/test_arithm.cpp | 1621 ------------ modules/ocl/test/test_bgfg.cpp | 240 -- modules/ocl/test/test_blend.cpp | 176 -- modules/ocl/test/test_brief.cpp | 115 - modules/ocl/test/test_brute_force_matcher.cpp | 220 -- modules/ocl/test/test_calib3d.cpp | 196 -- modules/ocl/test/test_canny.cpp | 89 - modules/ocl/test/test_color.cpp | 316 --- modules/ocl/test/test_fast.cpp | 93 - modules/ocl/test/test_fft.cpp | 244 -- modules/ocl/test/test_filters.cpp | 476 ---- modules/ocl/test/test_gemm.cpp | 84 - modules/ocl/test/test_hough.cpp | 112 - modules/ocl/test/test_imgproc.cpp | 622 ----- modules/ocl/test/test_kalman.cpp | 148 -- modules/ocl/test/test_kmeans.cpp | 235 -- modules/ocl/test/test_match_template.cpp | 137 - modules/ocl/test/test_matrix_operation.cpp | 250 -- modules/ocl/test/test_mean_shift.cpp | 408 --- modules/ocl/test/test_ml.cpp | 309 --- modules/ocl/test/test_moments.cpp | 64 - modules/ocl/test/test_objdetect.cpp | 226 -- modules/ocl/test/test_optflow.cpp | 341 --- modules/ocl/test/test_orb.cpp | 138 - modules/ocl/test/test_precomp.hpp | 79 - modules/ocl/test/test_pyramids.cpp | 117 - modules/ocl/test/test_sort.cpp | 244 -- modules/ocl/test/test_split_merge.cpp | 224 -- modules/ocl/test/test_warp.cpp | 494 ---- modules/ocl/test/utility.cpp | 366 --- modules/ocl/test/utility.hpp | 328 --- samples/CMakeLists.txt | 1 - samples/ocl/CMakeLists.txt | 58 - samples/ocl/adaptive_bilateral_filter.cpp | 65 - samples/ocl/bgfg_segm.cpp | 126 - samples/ocl/clahe.cpp | 112 - samples/ocl/facedetect.cpp | 390 --- samples/ocl/hog.cpp | 448 ---- samples/ocl/pyrlk_optical_flow.cpp | 264 -- samples/ocl/squares.cpp | 341 --- samples/ocl/stereo_match.cpp | 384 --- samples/ocl/surf_matcher.cpp | 329 --- samples/ocl/tvl1_optical_flow.cpp | 237 -- 236 files changed, 1 insertion(+), 79686 deletions(-) delete mode 100644 modules/ocl/CMakeLists.txt delete mode 100644 modules/ocl/doc/camera_calibration_and_3D_reconstruction.rst delete mode 100644 modules/ocl/doc/data_structures.rst delete mode 100644 modules/ocl/doc/feature_detection_and_description.rst delete mode 100644 modules/ocl/doc/image_filtering.rst delete mode 100644 modules/ocl/doc/image_processing.rst delete mode 100644 modules/ocl/doc/images/adaptiveBilateralFilter.jpg delete mode 100644 modules/ocl/doc/introduction.rst delete mode 100644 modules/ocl/doc/matrix_reductions.rst delete mode 100644 modules/ocl/doc/ml_machine_learning.rst delete mode 100644 modules/ocl/doc/object_detection.rst delete mode 100644 modules/ocl/doc/ocl.rst delete mode 100644 modules/ocl/doc/operations_on_matrices.rst delete mode 100644 modules/ocl/doc/structures_and_utility_functions.rst delete mode 100644 modules/ocl/doc/video_analysis.rst delete mode 100644 modules/ocl/include/opencv2/ocl.hpp delete mode 100644 modules/ocl/include/opencv2/ocl/matrix_operations.hpp delete mode 100644 modules/ocl/include/opencv2/ocl/ocl.hpp delete mode 100644 modules/ocl/include/opencv2/ocl/private/opencl_dumpinfo.hpp delete mode 100644 modules/ocl/include/opencv2/ocl/private/opencl_utils.hpp delete mode 100644 modules/ocl/include/opencv2/ocl/private/util.hpp delete mode 100644 modules/ocl/perf/main.cpp delete mode 100644 modules/ocl/perf/perf_arithm.cpp delete mode 100644 modules/ocl/perf/perf_bgfg.cpp delete mode 100644 modules/ocl/perf/perf_blend.cpp delete mode 100644 modules/ocl/perf/perf_brief.cpp delete mode 100644 modules/ocl/perf/perf_brute_force_matcher.cpp delete mode 100644 modules/ocl/perf/perf_calib3d.cpp delete mode 100644 modules/ocl/perf/perf_canny.cpp delete mode 100644 modules/ocl/perf/perf_color.cpp delete mode 100644 modules/ocl/perf/perf_fast.cpp delete mode 100644 modules/ocl/perf/perf_fft.cpp delete mode 100644 modules/ocl/perf/perf_filters.cpp delete mode 100644 modules/ocl/perf/perf_gemm.cpp delete mode 100644 modules/ocl/perf/perf_gftt.cpp delete mode 100644 modules/ocl/perf/perf_haar.cpp delete mode 100644 modules/ocl/perf/perf_hog.cpp delete mode 100644 modules/ocl/perf/perf_hough.cpp delete mode 100644 modules/ocl/perf/perf_imgproc.cpp delete mode 100644 modules/ocl/perf/perf_imgwarp.cpp delete mode 100644 modules/ocl/perf/perf_kalman.cpp delete mode 100644 modules/ocl/perf/perf_match_template.cpp delete mode 100644 modules/ocl/perf/perf_matrix_operation.cpp delete mode 100644 modules/ocl/perf/perf_ml.cpp delete mode 100644 modules/ocl/perf/perf_moments.cpp delete mode 100644 modules/ocl/perf/perf_norm.cpp delete mode 100644 modules/ocl/perf/perf_opticalflow.cpp delete mode 100644 modules/ocl/perf/perf_orb.cpp delete mode 100644 modules/ocl/perf/perf_precomp.hpp delete mode 100644 modules/ocl/perf/perf_pyramid.cpp delete mode 100644 modules/ocl/perf/perf_split_merge.cpp delete mode 100644 modules/ocl/src/arithm.cpp delete mode 100644 modules/ocl/src/bgfg_mog.cpp delete mode 100644 modules/ocl/src/blend.cpp delete mode 100644 modules/ocl/src/brief.cpp delete mode 100644 modules/ocl/src/brute_force_matcher.cpp delete mode 100644 modules/ocl/src/build_warps.cpp delete mode 100644 modules/ocl/src/canny.cpp delete mode 100644 modules/ocl/src/cl_context.cpp delete mode 100644 modules/ocl/src/cl_operations.cpp delete mode 100644 modules/ocl/src/cl_programcache.cpp delete mode 100644 modules/ocl/src/cl_programcache.hpp delete mode 100644 modules/ocl/src/color.cpp delete mode 100644 modules/ocl/src/columnsum.cpp delete mode 100644 modules/ocl/src/error.cpp delete mode 100644 modules/ocl/src/fast.cpp delete mode 100644 modules/ocl/src/fft.cpp delete mode 100644 modules/ocl/src/filtering.cpp delete mode 100644 modules/ocl/src/gemm.cpp delete mode 100644 modules/ocl/src/gftt.cpp delete mode 100644 modules/ocl/src/haar.cpp delete mode 100644 modules/ocl/src/hog.cpp delete mode 100644 modules/ocl/src/hough.cpp delete mode 100644 modules/ocl/src/imgproc.cpp delete mode 100644 modules/ocl/src/interpolate_frames.cpp delete mode 100644 modules/ocl/src/kalman.cpp delete mode 100644 modules/ocl/src/kmeans.cpp delete mode 100644 modules/ocl/src/knearest.cpp delete mode 100644 modules/ocl/src/match_template.cpp delete mode 100644 modules/ocl/src/matrix_operations.cpp delete mode 100644 modules/ocl/src/mcwutil.cpp delete mode 100644 modules/ocl/src/moments.cpp delete mode 100644 modules/ocl/src/mssegmentation.cpp delete mode 100644 modules/ocl/src/opencl/arithm_LUT.cl delete mode 100644 modules/ocl/src/opencl/arithm_absdiff_nonsaturate.cl delete mode 100644 modules/ocl/src/opencl/arithm_add.cl delete mode 100644 modules/ocl/src/opencl/arithm_addWeighted.cl delete mode 100644 modules/ocl/src/opencl/arithm_add_mask.cl delete mode 100644 modules/ocl/src/opencl/arithm_add_scalar.cl delete mode 100644 modules/ocl/src/opencl/arithm_add_scalar_mask.cl delete mode 100644 modules/ocl/src/opencl/arithm_bitwise_binary.cl delete mode 100644 modules/ocl/src/opencl/arithm_bitwise_binary_mask.cl delete mode 100644 modules/ocl/src/opencl/arithm_bitwise_binary_scalar.cl delete mode 100644 modules/ocl/src/opencl/arithm_bitwise_binary_scalar_mask.cl delete mode 100644 modules/ocl/src/opencl/arithm_bitwise_not.cl delete mode 100644 modules/ocl/src/opencl/arithm_cartToPolar.cl delete mode 100644 modules/ocl/src/opencl/arithm_compare.cl delete mode 100644 modules/ocl/src/opencl/arithm_exp.cl delete mode 100644 modules/ocl/src/opencl/arithm_flip.cl delete mode 100644 modules/ocl/src/opencl/arithm_log.cl delete mode 100644 modules/ocl/src/opencl/arithm_magnitude.cl delete mode 100644 modules/ocl/src/opencl/arithm_minMax.cl delete mode 100644 modules/ocl/src/opencl/arithm_minMaxLoc.cl delete mode 100644 modules/ocl/src/opencl/arithm_minMaxLoc_mask.cl delete mode 100644 modules/ocl/src/opencl/arithm_nonzero.cl delete mode 100644 modules/ocl/src/opencl/arithm_phase.cl delete mode 100644 modules/ocl/src/opencl/arithm_polarToCart.cl delete mode 100644 modules/ocl/src/opencl/arithm_pow.cl delete mode 100644 modules/ocl/src/opencl/arithm_setidentity.cl delete mode 100644 modules/ocl/src/opencl/arithm_sqrt.cl delete mode 100644 modules/ocl/src/opencl/arithm_sum.cl delete mode 100644 modules/ocl/src/opencl/arithm_transpose.cl delete mode 100644 modules/ocl/src/opencl/bgfg_mog.cl delete mode 100644 modules/ocl/src/opencl/blend_linear.cl delete mode 100644 modules/ocl/src/opencl/brief.cl delete mode 100644 modules/ocl/src/opencl/brute_force_match.cl delete mode 100644 modules/ocl/src/opencl/build_warps.cl delete mode 100644 modules/ocl/src/opencl/convertC3C4.cl delete mode 100644 modules/ocl/src/opencl/cvt_color.cl delete mode 100644 modules/ocl/src/opencl/featdetect_fast.cl delete mode 100644 modules/ocl/src/opencl/filter_sep_col.cl delete mode 100644 modules/ocl/src/opencl/filter_sep_row.cl delete mode 100644 modules/ocl/src/opencl/filtering_adaptive_bilateral.cl delete mode 100644 modules/ocl/src/opencl/filtering_boxFilter.cl delete mode 100644 modules/ocl/src/opencl/filtering_filter2D.cl delete mode 100644 modules/ocl/src/opencl/filtering_morph.cl delete mode 100644 modules/ocl/src/opencl/filtering_sep_filter_singlepass.cl delete mode 100644 modules/ocl/src/opencl/haarobjectdetect.cl delete mode 100644 modules/ocl/src/opencl/haarobjectdetect_scaled2.cl delete mode 100644 modules/ocl/src/opencl/imgproc_bilateral.cl delete mode 100644 modules/ocl/src/opencl/imgproc_calcHarris.cl delete mode 100644 modules/ocl/src/opencl/imgproc_calcMinEigenVal.cl delete mode 100644 modules/ocl/src/opencl/imgproc_canny.cl delete mode 100644 modules/ocl/src/opencl/imgproc_clahe.cl delete mode 100644 modules/ocl/src/opencl/imgproc_columnsum.cl delete mode 100644 modules/ocl/src/opencl/imgproc_convolve.cl delete mode 100644 modules/ocl/src/opencl/imgproc_copymakeboder.cl delete mode 100644 modules/ocl/src/opencl/imgproc_gftt.cl delete mode 100644 modules/ocl/src/opencl/imgproc_histogram.cl delete mode 100644 modules/ocl/src/opencl/imgproc_hough.cl delete mode 100644 modules/ocl/src/opencl/imgproc_integral.cl delete mode 100644 modules/ocl/src/opencl/imgproc_integral_sum.cl delete mode 100644 modules/ocl/src/opencl/imgproc_median.cl delete mode 100644 modules/ocl/src/opencl/imgproc_mulAndScaleSpectrums.cl delete mode 100644 modules/ocl/src/opencl/imgproc_remap.cl delete mode 100644 modules/ocl/src/opencl/imgproc_resize.cl delete mode 100644 modules/ocl/src/opencl/imgproc_sobel3.cl delete mode 100644 modules/ocl/src/opencl/imgproc_threshold.cl delete mode 100644 modules/ocl/src/opencl/imgproc_warpAffine.cl delete mode 100644 modules/ocl/src/opencl/imgproc_warpPerspective.cl delete mode 100644 modules/ocl/src/opencl/interpolate_frames.cl delete mode 100644 modules/ocl/src/opencl/kernel_radix_sort_by_key.cl delete mode 100644 modules/ocl/src/opencl/kernel_sort_by_key.cl delete mode 100644 modules/ocl/src/opencl/kernel_stablesort_by_key.cl delete mode 100644 modules/ocl/src/opencl/kmeans_kernel.cl delete mode 100644 modules/ocl/src/opencl/knearest.cl delete mode 100644 modules/ocl/src/opencl/match_template.cl delete mode 100644 modules/ocl/src/opencl/meanShift.cl delete mode 100644 modules/ocl/src/opencl/merge_mat.cl delete mode 100644 modules/ocl/src/opencl/moments.cl delete mode 100644 modules/ocl/src/opencl/objdetect_hog.cl delete mode 100644 modules/ocl/src/opencl/operator_convertTo.cl delete mode 100644 modules/ocl/src/opencl/operator_copyToM.cl delete mode 100644 modules/ocl/src/opencl/operator_setTo.cl delete mode 100644 modules/ocl/src/opencl/operator_setToM.cl delete mode 100644 modules/ocl/src/opencl/optical_flow_farneback.cl delete mode 100644 modules/ocl/src/opencl/orb.cl delete mode 100644 modules/ocl/src/opencl/pyr_down.cl delete mode 100644 modules/ocl/src/opencl/pyr_up.cl delete mode 100644 modules/ocl/src/opencl/pyrlk.cl delete mode 100644 modules/ocl/src/opencl/split_mat.cl delete mode 100644 modules/ocl/src/opencl/stereobm.cl delete mode 100644 modules/ocl/src/opencl/stereobp.cl delete mode 100644 modules/ocl/src/opencl/stereocsbp.cl delete mode 100644 modules/ocl/src/opencl/svm.cl delete mode 100644 modules/ocl/src/opencl/tvl1flow.cl delete mode 100644 modules/ocl/src/optical_flow_farneback.cpp delete mode 100644 modules/ocl/src/orb.cpp delete mode 100644 modules/ocl/src/precomp.hpp delete mode 100644 modules/ocl/src/pyrdown.cpp delete mode 100644 modules/ocl/src/pyrlk.cpp delete mode 100644 modules/ocl/src/pyrup.cpp delete mode 100644 modules/ocl/src/safe_call.hpp delete mode 100644 modules/ocl/src/sort_by_key.cpp delete mode 100644 modules/ocl/src/split_merge.cpp delete mode 100644 modules/ocl/src/stereo_csbp.cpp delete mode 100644 modules/ocl/src/stereobm.cpp delete mode 100644 modules/ocl/src/stereobp.cpp delete mode 100644 modules/ocl/src/svm.cpp delete mode 100644 modules/ocl/src/tvl1flow.cpp delete mode 100644 modules/ocl/test/main.cpp delete mode 100644 modules/ocl/test/test_api.cpp delete mode 100644 modules/ocl/test/test_arithm.cpp delete mode 100644 modules/ocl/test/test_bgfg.cpp delete mode 100644 modules/ocl/test/test_blend.cpp delete mode 100644 modules/ocl/test/test_brief.cpp delete mode 100644 modules/ocl/test/test_brute_force_matcher.cpp delete mode 100644 modules/ocl/test/test_calib3d.cpp delete mode 100644 modules/ocl/test/test_canny.cpp delete mode 100644 modules/ocl/test/test_color.cpp delete mode 100644 modules/ocl/test/test_fast.cpp delete mode 100644 modules/ocl/test/test_fft.cpp delete mode 100644 modules/ocl/test/test_filters.cpp delete mode 100644 modules/ocl/test/test_gemm.cpp delete mode 100644 modules/ocl/test/test_hough.cpp delete mode 100644 modules/ocl/test/test_imgproc.cpp delete mode 100644 modules/ocl/test/test_kalman.cpp delete mode 100644 modules/ocl/test/test_kmeans.cpp delete mode 100644 modules/ocl/test/test_match_template.cpp delete mode 100644 modules/ocl/test/test_matrix_operation.cpp delete mode 100644 modules/ocl/test/test_mean_shift.cpp delete mode 100644 modules/ocl/test/test_ml.cpp delete mode 100644 modules/ocl/test/test_moments.cpp delete mode 100644 modules/ocl/test/test_objdetect.cpp delete mode 100644 modules/ocl/test/test_optflow.cpp delete mode 100644 modules/ocl/test/test_orb.cpp delete mode 100644 modules/ocl/test/test_precomp.hpp delete mode 100644 modules/ocl/test/test_pyramids.cpp delete mode 100644 modules/ocl/test/test_sort.cpp delete mode 100644 modules/ocl/test/test_split_merge.cpp delete mode 100644 modules/ocl/test/test_warp.cpp delete mode 100644 modules/ocl/test/utility.cpp delete mode 100644 modules/ocl/test/utility.hpp delete mode 100644 samples/ocl/CMakeLists.txt delete mode 100644 samples/ocl/adaptive_bilateral_filter.cpp delete mode 100644 samples/ocl/bgfg_segm.cpp delete mode 100644 samples/ocl/clahe.cpp delete mode 100644 samples/ocl/facedetect.cpp delete mode 100644 samples/ocl/hog.cpp delete mode 100644 samples/ocl/pyrlk_optical_flow.cpp delete mode 100644 samples/ocl/squares.cpp delete mode 100644 samples/ocl/stereo_match.cpp delete mode 100644 samples/ocl/surf_matcher.cpp delete mode 100644 samples/ocl/tvl1_optical_flow.cpp diff --git a/modules/nonfree/CMakeLists.txt b/modules/nonfree/CMakeLists.txt index eec28e975..86caca9d7 100644 --- a/modules/nonfree/CMakeLists.txt +++ b/modules/nonfree/CMakeLists.txt @@ -4,4 +4,4 @@ endif() set(the_description "Functionality with possible limitations on the use") ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef) -ocv_define_module(nonfree opencv_imgproc opencv_features2d opencv_calib3d OPTIONAL opencv_cudaarithm opencv_ocl) +ocv_define_module(nonfree opencv_imgproc opencv_features2d opencv_calib3d OPTIONAL opencv_cudaarithm) diff --git a/modules/ocl/CMakeLists.txt b/modules/ocl/CMakeLists.txt deleted file mode 100644 index db9d64e1e..000000000 --- a/modules/ocl/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -if(NOT HAVE_OPENCL) - ocv_module_disable(ocl) - return() -endif() - -set(the_description "OpenCL-accelerated Computer Vision") -ocv_define_module(ocl opencv_core opencv_imgproc opencv_features2d opencv_objdetect opencv_video opencv_calib3d opencv_ml "${OPENCL_LIBRARIES}") -if(TARGET opencv_test_ocl) - target_link_libraries(opencv_test_ocl "${OPENCL_LIBRARIES}") -endif() -ocv_warnings_disable(CMAKE_CXX_FLAGS -Wshadow) diff --git a/modules/ocl/doc/camera_calibration_and_3D_reconstruction.rst b/modules/ocl/doc/camera_calibration_and_3D_reconstruction.rst deleted file mode 100644 index 824366927..000000000 --- a/modules/ocl/doc/camera_calibration_and_3D_reconstruction.rst +++ /dev/null @@ -1,328 +0,0 @@ -Camera Calibration and 3D Reconstruction -======================================== - -.. highlight:: cpp - - - -ocl::StereoBM_OCL ---------------------- -.. ocv:class:: ocl::StereoBM_OCL - -Class computing stereo correspondence (disparity map) using the block matching algorithm. :: - - class CV_EXPORTS StereoBM_OCL - { - public: - enum { BASIC_PRESET = 0, PREFILTER_XSOBEL = 1 }; - - enum { DEFAULT_NDISP = 64, DEFAULT_WINSZ = 19 }; - - //! the default constructor - StereoBM_OCL(); - //! the full constructor taking the camera-specific preset, number of disparities and the SAD window size. ndisparities must be multiple of 8. - StereoBM_OCL(int preset, int ndisparities = DEFAULT_NDISP, int winSize = DEFAULT_WINSZ); - - //! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair - //! Output disparity has CV_8U type. - void operator() ( const oclMat &left, const oclMat &right, oclMat &disparity); - - //! Some heuristics that tries to estmate - // if current GPU will be faster then CPU in this algorithm. - // It queries current active device. - static bool checkIfGpuCallReasonable(); - - int preset; - int ndisp; - int winSize; - - // If avergeTexThreshold == 0 => post procesing is disabled - // If avergeTexThreshold != 0 then disparity is set 0 in each point (x,y) where for left image - // SumOfHorizontalGradiensInWindow(x, y, winSize) < (winSize * winSize) * avergeTexThreshold - // i.e. input left image is low textured. - float avergeTexThreshold; - private: - /* hidden */ - }; - - -The class also performs pre- and post-filtering steps: Sobel pre-filtering (if ``PREFILTER_XSOBEL`` flag is set) and low textureness filtering (if ``averageTexThreshols > 0`` ). If ``avergeTexThreshold = 0`` , low textureness filtering is disabled. Otherwise, the disparity is set to 0 in each point ``(x, y)`` , where for the left image - -.. math:: - \sum HorizontalGradiensInWindow(x, y, winSize) < (winSize \cdot winSize) \cdot avergeTexThreshold - -This means that the input left image is low textured. - - -ocl::StereoBM_OCL::StereoBM_OCL ------------------------------------ -Enables :ocv:class:`ocl::StereoBM_OCL` constructors. - -.. ocv:function:: ocl::StereoBM_OCL::StereoBM_OCL() - -.. ocv:function:: ocl::StereoBM_OCL::StereoBM_OCL(int preset, int ndisparities = DEFAULT_NDISP, int winSize = DEFAULT_WINSZ) - - :param preset: Parameter presetting: - - * **BASIC_PRESET** Basic mode without pre-processing. - - * **PREFILTER_XSOBEL** Sobel pre-filtering mode. - - :param ndisparities: Number of disparities. It must be a multiple of 8 and less or equal to 256. - - :param winSize: Block size. - - - -ocl::StereoBM_OCL::operator () ----------------------------------- -Enables the stereo correspondence operator that finds the disparity for the specified rectified stereo pair. - -.. ocv:function:: void ocl::StereoBM_OCL::operator ()(const oclMat& left, const oclMat& right, oclMat& disparity) - - :param left: Left image. Only ``CV_8UC1`` type is supported. - - :param right: Right image with the same size and the same type as the left one. - - :param disparity: Output disparity map. It is a ``CV_8UC1`` image with the same size as the input images. - - -ocl::StereoBM_OCL::checkIfGpuCallReasonable ------------------------------------------------ -Uses a heuristic method to estimate whether the current GPU is faster than the CPU in this algorithm. It queries the currently active device. - -.. ocv:function:: bool ocl::StereoBM_OCL::checkIfGpuCallReasonable() - -ocl::StereoBeliefPropagation --------------------------------- -.. ocv:class:: ocl::StereoBeliefPropagation - -Class computing stereo correspondence using the belief propagation algorithm. :: - - class CV_EXPORTS StereoBeliefPropagation - { - public: - enum { DEFAULT_NDISP = 64 }; - enum { DEFAULT_ITERS = 5 }; - enum { DEFAULT_LEVELS = 5 }; - static void estimateRecommendedParams(int width, int height, int &ndisp, int &iters, int &levels); - explicit StereoBeliefPropagation(int ndisp = DEFAULT_NDISP, - int iters = DEFAULT_ITERS, - int levels = DEFAULT_LEVELS, - int msg_type = CV_16S); - StereoBeliefPropagation(int ndisp, int iters, int levels, - float max_data_term, float data_weight, - float max_disc_term, float disc_single_jump, - int msg_type = CV_32F); - void operator()(const oclMat &left, const oclMat &right, oclMat &disparity); - void operator()(const oclMat &data, oclMat &disparity); - int ndisp; - int iters; - int levels; - float max_data_term; - float data_weight; - float max_disc_term; - float disc_single_jump; - int msg_type; - private: - /* hidden */ - }; - -The class implements algorithm described in [Felzenszwalb2006]_ . It can compute own data cost (using a truncated linear model) or use a user-provided data cost. - -.. note:: - - ``StereoBeliefPropagation`` requires a lot of memory for message storage: - - .. math:: - - width \_ step \cdot height \cdot ndisp \cdot 4 \cdot (1 + 0.25) - - and for data cost storage: - - .. math:: - - width\_step \cdot height \cdot ndisp \cdot (1 + 0.25 + 0.0625 + \dotsm + \frac{1}{4^{levels}}) - - ``width_step`` is the number of bytes in a line including padding. - - - -ocl::StereoBeliefPropagation::StereoBeliefPropagation ---------------------------------------------------------- -Enables the :ocv:class:`ocl::StereoBeliefPropagation` constructors. - -.. ocv:function:: ocl::StereoBeliefPropagation::StereoBeliefPropagation(int ndisp = DEFAULT_NDISP, int iters = DEFAULT_ITERS, int levels = DEFAULT_LEVELS, int msg_type = CV_16S) - -.. ocv:function:: ocl::StereoBeliefPropagation::StereoBeliefPropagation(int ndisp, int iters, int levels, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int msg_type = CV_32F) - - :param ndisp: Number of disparities. - - :param iters: Number of BP iterations on each level. - - :param levels: Number of levels. - - :param max_data_term: Threshold for data cost truncation. - - :param data_weight: Data weight. - - :param max_disc_term: Threshold for discontinuity truncation. - - :param disc_single_jump: Discontinuity single jump. - - :param msg_type: Type for messages. ``CV_16SC1`` and ``CV_32FC1`` types are supported. - -``StereoBeliefPropagation`` uses a truncated linear model for the data cost and discontinuity terms: - -.. math:: - - DataCost = data \_ weight \cdot \min ( \lvert Img_Left(x,y)-Img_Right(x-d,y) \rvert , max \_ data \_ term) - -.. math:: - - DiscTerm = \min (disc \_ single \_ jump \cdot \lvert f_1-f_2 \rvert , max \_ disc \_ term) - -For more details, see [Felzenszwalb2006]_. - -By default, :ocv:class:`ocl::StereoBeliefPropagation` uses floating-point arithmetics and the ``CV_32FC1`` type for messages. But it can also use fixed-point arithmetics and the ``CV_16SC1`` message type for better performance. To avoid an overflow in this case, the parameters must satisfy the following requirement: - -.. math:: - - 10 \cdot 2^{levels-1} \cdot max \_ data \_ term < SHRT \_ MAX - - - -ocl::StereoBeliefPropagation::estimateRecommendedParams ------------------------------------------------------------ -Uses a heuristic method to compute the recommended parameters ( ``ndisp``, ``iters`` and ``levels`` ) for the specified image size ( ``width`` and ``height`` ). - -.. ocv:function:: void ocl::StereoBeliefPropagation::estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels) - - - -ocl::StereoBeliefPropagation::operator () ---------------------------------------------- -Enables the stereo correspondence operator that finds the disparity for the specified rectified stereo pair or data cost. - -.. ocv:function:: void ocl::StereoBeliefPropagation::operator ()(const oclMat& left, const oclMat& right, oclMat& disparity) - -.. ocv:function:: void ocl::StereoBeliefPropagation::operator ()(const oclMat& data, oclMat& disparity) - - :param left: Left image. ``CV_8UC1`` , ``CV_8UC3`` and ``CV_8UC4`` types are supported. - - :param right: Right image with the same size and the same type as the left one. - - :param data: User-specified data cost, a matrix of ``msg_type`` type and ``Size(*ndisp, )`` size. - - :param disparity: Output disparity map. If ``disparity`` is empty, the output type is ``CV_16SC1`` . Otherwise, the type is retained. - -ocl::StereoConstantSpaceBP ------------------------------- -.. ocv:class:: ocl::StereoConstantSpaceBP - -Class computing stereo correspondence using the constant space belief propagation algorithm. :: - - class CV_EXPORTS StereoConstantSpaceBP - { - public: - enum { DEFAULT_NDISP = 128 }; - enum { DEFAULT_ITERS = 8 }; - enum { DEFAULT_LEVELS = 4 }; - enum { DEFAULT_NR_PLANE = 4 }; - static void estimateRecommendedParams(int width, int height, int &ndisp, int &iters, int &levels, int &nr_plane); - explicit StereoConstantSpaceBP( - int ndisp = DEFAULT_NDISP, - int iters = DEFAULT_ITERS, - int levels = DEFAULT_LEVELS, - int nr_plane = DEFAULT_NR_PLANE, - int msg_type = CV_32F); - StereoConstantSpaceBP(int ndisp, int iters, int levels, int nr_plane, - float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, - int min_disp_th = 0, - int msg_type = CV_32F); - void operator()(const oclMat &left, const oclMat &right, oclMat &disparity); - int ndisp; - int iters; - int levels; - int nr_plane; - float max_data_term; - float data_weight; - float max_disc_term; - float disc_single_jump; - int min_disp_th; - int msg_type; - bool use_local_init_data_cost; - private: - /* hidden */ - }; - -The class implements algorithm described in [Yang2010]_. ``StereoConstantSpaceBP`` supports both local minimum and global minimum data cost initialization algorithms. For more details, see the paper mentioned above. By default, a local algorithm is used. To enable a global algorithm, set ``use_local_init_data_cost`` to ``false`` . - - -ocl::StereoConstantSpaceBP::StereoConstantSpaceBP ------------------------------------------------------ -Enables the :ocv:class:`ocl::StereoConstantSpaceBP` constructors. - -.. ocv:function:: ocl::StereoConstantSpaceBP::StereoConstantSpaceBP(int ndisp = DEFAULT_NDISP, int iters = DEFAULT_ITERS, int levels = DEFAULT_LEVELS, int nr_plane = DEFAULT_NR_PLANE, int msg_type = CV_32F) - -.. ocv:function:: ocl::StereoConstantSpaceBP::StereoConstantSpaceBP(int ndisp, int iters, int levels, int nr_plane, float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, int min_disp_th = 0, int msg_type = CV_32F) - - :param ndisp: Number of disparities. - - :param iters: Number of BP iterations on each level. - - :param levels: Number of levels. - - :param nr_plane: Number of disparity levels on the first level. - - :param max_data_term: Truncation of data cost. - - :param data_weight: Data weight. - - :param max_disc_term: Truncation of discontinuity. - - :param disc_single_jump: Discontinuity single jump. - - :param min_disp_th: Minimal disparity threshold. - - :param msg_type: Type for messages. ``CV_16SC1`` and ``CV_32FC1`` types are supported. - -``StereoConstantSpaceBP`` uses a truncated linear model for the data cost and discontinuity terms: - -.. math:: - - DataCost = data \_ weight \cdot \min ( \lvert I_2-I_1 \rvert , max \_ data \_ term) - -.. math:: - - DiscTerm = \min (disc \_ single \_ jump \cdot \lvert f_1-f_2 \rvert , max \_ disc \_ term) - -For more details, see [Yang2010]_. - -By default, ``StereoConstantSpaceBP`` uses floating-point arithmetics and the ``CV_32FC1`` type for messages. But it can also use fixed-point arithmetics and the ``CV_16SC1`` message type for better performance. To avoid an overflow in this case, the parameters must satisfy the following requirement: - -.. math:: - - 10 \cdot 2^{levels-1} \cdot max \_ data \_ term < SHRT \_ MAX - - - -ocl::StereoConstantSpaceBP::estimateRecommendedParams ---------------------------------------------------------- -Uses a heuristic method to compute parameters (ndisp, iters, levelsand nrplane) for the specified image size (widthand height). - -.. ocv:function:: void ocl::StereoConstantSpaceBP::estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels, int& nr_plane) - - - -ocl::StereoConstantSpaceBP::operator () -------------------------------------------- -Enables the stereo correspondence operator that finds the disparity for the specified rectified stereo pair. - -.. ocv:function:: void ocl::StereoConstantSpaceBP::operator ()(const oclMat& left, const oclMat& right, oclMat& disparity) - - :param left: Left image. ``CV_8UC1`` , ``CV_8UC3`` and ``CV_8UC4`` types are supported. - - :param right: Right image with the same size and the same type as the left one. - - :param disparity: Output disparity map. If ``disparity`` is empty, the output type is ``CV_16SC1`` . Otherwise, the output type is ``disparity.type()`` . diff --git a/modules/ocl/doc/data_structures.rst b/modules/ocl/doc/data_structures.rst deleted file mode 100644 index bde3d14af..000000000 --- a/modules/ocl/doc/data_structures.rst +++ /dev/null @@ -1,189 +0,0 @@ -Data Structures -============================= - -.. ocv:class:: ocl::oclMat - -OpenCV C++ 1-D or 2-D dense array class :: - - class CV_EXPORTS oclMat - { - public: - //! default constructor - oclMat(); - //! constructs oclMatrix of the specified size and type (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.) - oclMat(int rows, int cols, int type); - oclMat(Size size, int type); - //! constucts oclMatrix and fills it with the specified value _s. - oclMat(int rows, int cols, int type, const Scalar &s); - oclMat(Size size, int type, const Scalar &s); - //! copy constructor - oclMat(const oclMat &m); - - //! constructor for oclMatrix headers pointing to user-allocated data - oclMat(int rows, int cols, int type, void *data, size_t step = Mat::AUTO_STEP); - oclMat(Size size, int type, void *data, size_t step = Mat::AUTO_STEP); - - //! creates a matrix header for a part of the bigger matrix - oclMat(const oclMat &m, const Range &rowRange, const Range &colRange); - oclMat(const oclMat &m, const Rect &roi); - - //! builds oclMat from Mat. Perfom blocking upload to device. - explicit oclMat (const Mat &m); - - //! destructor - calls release() - ~oclMat(); - - //! assignment operators - oclMat &operator = (const oclMat &m); - //! assignment operator. Perfom blocking upload to device. - oclMat &operator = (const Mat &m); - oclMat &operator = (const oclMatExpr& expr); - - //! pefroms blocking upload data to oclMat. - void upload(const cv::Mat &m); - - - //! downloads data from device to host memory. Blocking calls. - operator Mat() const; - void download(cv::Mat &m) const; - - //! convert to _InputArray - operator _InputArray(); - - //! convert to _OutputArray - operator _OutputArray(); - - //! returns a new oclMatrix header for the specified row - oclMat row(int y) const; - //! returns a new oclMatrix header for the specified column - oclMat col(int x) const; - //! ... for the specified row span - oclMat rowRange(int startrow, int endrow) const; - oclMat rowRange(const Range &r) const; - //! ... for the specified column span - oclMat colRange(int startcol, int endcol) const; - oclMat colRange(const Range &r) const; - - //! returns deep copy of the oclMatrix, i.e. the data is copied - oclMat clone() const; - - //! copies those oclMatrix elements to "m" that are marked with non-zero mask elements. - // It calls m.create(this->size(), this->type()). - // It supports any data type - void copyTo( oclMat &m, const oclMat &mask = oclMat()) const; - - //! converts oclMatrix to another datatype with optional scalng. See cvConvertScale. - void convertTo( oclMat &m, int rtype, double alpha = 1, double beta = 0 ) const; - - void assignTo( oclMat &m, int type = -1 ) const; - - //! sets every oclMatrix element to s - oclMat& operator = (const Scalar &s); - //! sets some of the oclMatrix elements to s, according to the mask - oclMat& setTo(const Scalar &s, const oclMat &mask = oclMat()); - //! creates alternative oclMatrix header for the same data, with different - // number of channels and/or different number of rows. see cvReshape. - oclMat reshape(int cn, int rows = 0) const; - - //! allocates new oclMatrix data unless the oclMatrix already has specified size and type. - // previous data is unreferenced if needed. - void create(int rows, int cols, int type); - void create(Size size, int type); - - //! allocates new oclMatrix with specified device memory type. - void createEx(int rows, int cols, int type, DevMemRW rw_type, DevMemType mem_type); - void createEx(Size size, int type, DevMemRW rw_type, DevMemType mem_type); - - //! decreases reference counter; - // deallocate the data when reference counter reaches 0. - void release(); - - //! swaps with other smart pointer - void swap(oclMat &mat); - - //! locates oclMatrix header within a parent oclMatrix. See below - void locateROI( Size &wholeSize, Point &ofs ) const; - //! moves/resizes the current oclMatrix ROI inside the parent oclMatrix. - oclMat& adjustROI( int dtop, int dbottom, int dleft, int dright ); - //! extracts a rectangular sub-oclMatrix - // (this is a generalized form of row, rowRange etc.) - oclMat operator()( Range rowRange, Range colRange ) const; - oclMat operator()( const Rect &roi ) const; - - oclMat& operator+=( const oclMat& m ); - oclMat& operator-=( const oclMat& m ); - oclMat& operator*=( const oclMat& m ); - oclMat& operator/=( const oclMat& m ); - - //! returns true if the oclMatrix data is continuous - // (i.e. when there are no gaps between successive rows). - // similar to CV_IS_oclMat_CONT(cvoclMat->type) - bool isContinuous() const; - //! returns element size in bytes, - // similar to CV_ELEM_SIZE(cvMat->type) - size_t elemSize() const; - //! returns the size of element channel in bytes. - size_t elemSize1() const; - //! returns element type, similar to CV_MAT_TYPE(cvMat->type) - int type() const; - //! returns element type, i.e. 8UC3 returns 8UC4 because in ocl - //! 3 channels element actually use 4 channel space - int ocltype() const; - //! returns element type, similar to CV_MAT_DEPTH(cvMat->type) - int depth() const; - //! returns element type, similar to CV_MAT_CN(cvMat->type) - int channels() const; - //! returns element type, return 4 for 3 channels element, - //!becuase 3 channels element actually use 4 channel space - int oclchannels() const; - //! returns step/elemSize1() - size_t step1() const; - //! returns oclMatrix size: - // width == number of columns, height == number of rows - Size size() const; - //! returns true if oclMatrix data is NULL - bool empty() const; - - //! matrix transposition - oclMat t() const; - - /*! includes several bit-fields: - - the magic signature - - continuity flag - - depth - - number of channels - */ - int flags; - //! the number of rows and columns - int rows, cols; - //! a distance between successive rows in bytes; includes the gap if any - size_t step; - //! pointer to the data(OCL memory object) - uchar *data; - - //! pointer to the reference counter; - // when oclMatrix points to user-allocated data, the pointer is NULL - int *refcount; - - //! helper fields used in locateROI and adjustROI - //datastart and dataend are not used in current version - uchar *datastart; - uchar *dataend; - - //! OpenCL context associated with the oclMat object. - Context *clCxt; - //add offset for handle ROI, calculated in byte - int offset; - //add wholerows and wholecols for the whole matrix, datastart and dataend are no longer used - int wholerows; - int wholecols; - }; - -Basically speaking, the ``oclMat`` is the mirror of ``Mat`` with the extension of OCL feature, the members have the same meaning and useage of ``Mat`` except following: - -* ``datastart`` and ``dataend`` are replaced with ``wholerows`` and ``wholecols`` - -* Only basic flags are supported in ``oclMat`` (i.e. depth number of channels) - -* All the 3-channel matrix (i.e. RGB image) are represented by 4-channel matrix in ``oclMat``. It means 3-channel image have 4-channel space with the last channel unused. We provide a transparent interface to handle the difference between OpenCV ``Mat`` and ``oclMat``. - For example: If a ``oclMat`` has 3 channels, ``channels()`` returns 3 and ``oclchannels()`` returns 4 diff --git a/modules/ocl/doc/feature_detection_and_description.rst b/modules/ocl/doc/feature_detection_and_description.rst deleted file mode 100644 index 9cfabdf37..000000000 --- a/modules/ocl/doc/feature_detection_and_description.rst +++ /dev/null @@ -1,836 +0,0 @@ -Feature Detection And Description -================================= - -.. highlight:: cpp - -ocl::Canny -------------------- -Finds edges in an image using the [Canny86]_ algorithm. - -.. ocv:function:: void ocl::Canny(const oclMat& image, oclMat& edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false) - -.. ocv:function:: void ocl::Canny(const oclMat& image, CannyBuf& buf, oclMat& edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false) - -.. ocv:function:: void ocl::Canny(const oclMat& dx, const oclMat& dy, oclMat& edges, double low_thresh, double high_thresh, bool L2gradient = false) - -.. ocv:function:: void ocl::Canny(const oclMat& dx, const oclMat& dy, CannyBuf& buf, oclMat& edges, double low_thresh, double high_thresh, bool L2gradient = false) - - :param image: Single-channel 8-bit input image. - - :param dx: First derivative of image in the vertical direction. Support only ``CV_32S`` type. - - :param dy: First derivative of image in the horizontal direction. Support only ``CV_32S`` type. - - :param edges: Output edge map. It has the same size and type as ``image`` . - - :param low_thresh: First threshold for the hysteresis procedure. - - :param high_thresh: Second threshold for the hysteresis procedure. - - :param apperture_size: Aperture size for the :ocv:func:`Sobel` operator. - - :param L2gradient: Flag indicating whether a more accurate :math:`L_2` norm :math:`=\sqrt{(dI/dx)^2 + (dI/dy)^2}` should be used to compute the image gradient magnitude ( ``L2gradient=true`` ), or a faster default :math:`L_1` norm :math:`=|dI/dx|+|dI/dy|` is enough ( ``L2gradient=false`` ). - - :param buf: Optional buffer to avoid extra memory allocations (for many calls with the same sizes). - -.. seealso:: :ocv:func:`Canny` - - -ocl::BruteForceMatcher_OCL_base ------------------------------------ -.. ocv:class:: ocl::BruteForceMatcher_OCL_base - -Brute-force descriptor matcher. For each descriptor in the first set, this matcher finds the closest descriptor in the second set by trying each one. This descriptor matcher supports masking permissible matches between descriptor sets. :: - - class BruteForceMatcher_OCL_base - { - public: - enum DistType {L1Dist = 0, L2Dist, HammingDist}; - - // Add descriptors to train descriptor collection. - void add(const std::vector& descCollection); - - // Get train descriptors collection. - const std::vector& getTrainDescriptors() const; - - // Clear train descriptors collection. - void clear(); - - // Return true if there are no train descriptors in collection. - bool empty() const; - - // Return true if the matcher supports mask in match methods. - bool isMaskSupported() const; - - void matchSingle(const oclMat& query, const oclMat& train, - oclMat& trainIdx, oclMat& distance, - const oclMat& mask = oclMat()); - - static void matchDownload(const oclMat& trainIdx, - const oclMat& distance, std::vector& matches); - static void matchConvert(const Mat& trainIdx, - const Mat& distance, std::vector& matches); - - void match(const oclMat& query, const oclMat& train, - std::vector& matches, const oclMat& mask = oclMat()); - - void makeGpuCollection(oclMat& trainCollection, oclMat& maskCollection, - const vector& masks = std::vector()); - - void matchCollection(const oclMat& query, const oclMat& trainCollection, - oclMat& trainIdx, oclMat& imgIdx, oclMat& distance, - const oclMat& maskCollection); - - static void matchDownload(const oclMat& trainIdx, oclMat& imgIdx, - const oclMat& distance, std::vector& matches); - static void matchConvert(const Mat& trainIdx, const Mat& imgIdx, - const Mat& distance, std::vector& matches); - - void match(const oclMat& query, std::vector& matches, - const std::vector& masks = std::vector()); - - void knnMatchSingle(const oclMat& query, const oclMat& train, - oclMat& trainIdx, oclMat& distance, oclMat& allDist, int k, - const oclMat& mask = oclMat()); - - static void knnMatchDownload(const oclMat& trainIdx, const oclMat& distance, - std::vector< std::vector >& matches, bool compactResult = false); - static void knnMatchConvert(const Mat& trainIdx, const Mat& distance, - std::vector< std::vector >& matches, bool compactResult = false); - - void knnMatch(const oclMat& query, const oclMat& train, - std::vector< std::vector >& matches, int k, - const oclMat& mask = oclMat(), bool compactResult = false); - - void knnMatch2Collection(const oclMat& query, const oclMat& trainCollection, - oclMat& trainIdx, oclMat& imgIdx, oclMat& distance, - const oclMat& maskCollection = oclMat()); - - static void knnMatch2Download(const oclMat& trainIdx, const oclMat& imgIdx, const oclMat& distance, - std::vector< std::vector >& matches, bool compactResult = false); - static void knnMatch2Convert(const Mat& trainIdx, const Mat& imgIdx, const Mat& distance, - std::vector< std::vector >& matches, bool compactResult = false); - - void knnMatch(const oclMat& query, std::vector< std::vector >& matches, int k, - const std::vector& masks = std::vector(), - bool compactResult = false); - - void radiusMatchSingle(const oclMat& query, const oclMat& train, - oclMat& trainIdx, oclMat& distance, oclMat& nMatches, float maxDistance, - const oclMat& mask = oclMat()); - - static void radiusMatchDownload(const oclMat& trainIdx, const oclMat& distance, const oclMat& nMatches, - std::vector< std::vector >& matches, bool compactResult = false); - static void radiusMatchConvert(const Mat& trainIdx, const Mat& distance, const Mat& nMatches, - std::vector< std::vector >& matches, bool compactResult = false); - - void radiusMatch(const oclMat& query, const oclMat& train, - std::vector< std::vector >& matches, float maxDistance, - const oclMat& mask = oclMat(), bool compactResult = false); - - void radiusMatchCollection(const oclMat& query, oclMat& trainIdx, oclMat& imgIdx, oclMat& distance, oclMat& nMatches, float maxDistance, - const std::vector& masks = std::vector()); - - static void radiusMatchDownload(const oclMat& trainIdx, const oclMat& imgIdx, const oclMat& distance, const oclMat& nMatches, - std::vector< std::vector >& matches, bool compactResult = false); - static void radiusMatchConvert(const Mat& trainIdx, const Mat& imgIdx, const Mat& distance, const Mat& nMatches, - std::vector< std::vector >& matches, bool compactResult = false); - - void radiusMatch(const oclMat& query, std::vector< std::vector >& matches, float maxDistance, - const std::vector& masks = std::vector(), bool compactResult = false); - - DistType distType; - - private: - std::vector trainDescCollection; - }; - - -The class ``BruteForceMatcher_OCL_base`` has an interface similar to the class :ocv:class:`DescriptorMatcher`. It has two groups of ``match`` methods: for matching descriptors of one image with another image or with an image set. Also, all functions have an alternative to save results either to the GPU memory or to the CPU memory. ``BruteForceMatcher_OCL_base`` supports only the ``L1``, ``L2``, and ``Hamming`` distance types. - -.. seealso:: :ocv:class:`DescriptorMatcher`, :ocv:class:`BFMatcher` - - - -ocl::BruteForceMatcher_OCL_base::match ------------------------------------------- -Finds the best match for each descriptor from a query set with train descriptors. - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::match(const oclMat& query, const oclMat& train, std::vector& matches, const oclMat& mask = oclMat()) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::matchSingle(const oclMat& query, const oclMat& train, oclMat& trainIdx, oclMat& distance, const oclMat& mask = oclMat()) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::match(const oclMat& query, std::vector& matches, const std::vector& masks = std::vector()) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::matchCollection( const oclMat& query, const oclMat& trainCollection, oclMat& trainIdx, oclMat& imgIdx, oclMat& distance, const oclMat& masks=oclMat() ) - -.. seealso:: :ocv:func:`DescriptorMatcher::match` - - - -ocl::BruteForceMatcher_OCL_base::makeGpuCollection ------------------------------------------------------- -Performs a GPU collection of train descriptors and masks in a suitable format for the :ocv:func:`ocl::BruteForceMatcher_OCL_base::matchCollection` function. - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::makeGpuCollection(oclMat& trainCollection, oclMat& maskCollection, const vector& masks = std::vector()) - - -ocl::BruteForceMatcher_OCL_base::matchDownload --------------------------------------------------- -Downloads matrices obtained via :ocv:func:`ocl::BruteForceMatcher_OCL_base::matchSingle` or :ocv:func:`ocl::BruteForceMatcher_OCL_base::matchCollection` to vector with :ocv:class:`DMatch`. - -.. ocv:function:: static void ocl::BruteForceMatcher_OCL_base::matchDownload( const oclMat& trainIdx, const oclMat& distance, std::vector& matches ) - -.. ocv:function:: static void ocl::BruteForceMatcher_OCL_base::matchDownload( const oclMat& trainIdx, const oclMat& imgIdx, const oclMat& distance, std::vector& matches ) - - -ocl::BruteForceMatcher_OCL_base::matchConvert -------------------------------------------------- -Converts matrices obtained via :ocv:func:`ocl::BruteForceMatcher_OCL_base::matchSingle` or :ocv:func:`ocl::BruteForceMatcher_OCL_base::matchCollection` to vector with :ocv:class:`DMatch`. - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::matchConvert(const Mat& trainIdx, const Mat& distance, std::vector&matches) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::matchConvert(const Mat& trainIdx, const Mat& imgIdx, const Mat& distance, std::vector&matches) - - - -ocl::BruteForceMatcher_OCL_base::knnMatch ---------------------------------------------- -Finds the ``k`` best matches for each descriptor from a query set with train descriptors. - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::knnMatch(const oclMat& query, const oclMat& train, std::vector< std::vector >&matches, int k, const oclMat& mask = oclMat(), bool compactResult = false) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::knnMatchSingle(const oclMat& query, const oclMat& train, oclMat& trainIdx, oclMat& distance, oclMat& allDist, int k, const oclMat& mask = oclMat()) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::knnMatch(const oclMat& query, std::vector< std::vector >&matches, int k, const std::vector&masks = std::vector(), bool compactResult = false ) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::knnMatch2Collection(const oclMat& query, const oclMat& trainCollection, oclMat& trainIdx, oclMat& imgIdx, oclMat& distance, const oclMat& maskCollection = oclMat()) - - :param query: Query set of descriptors. - - :param train: Training set of descriptors. It is not be added to train descriptors collection stored in the class object. - - :param k: Number of the best matches per each query descriptor (or less if it is not possible). - - :param mask: Mask specifying permissible matches between the input query and train matrices of descriptors. - - :param compactResult: If ``compactResult`` is ``true`` , the ``matches`` vector does not contain matches for fully masked-out query descriptors. - - -The function returns detected ``k`` (or less if not possible) matches in the increasing order by distance. - -The third variant of the method stores the results in GPU memory. - -.. seealso:: :ocv:func:`DescriptorMatcher::knnMatch` - - - -ocl::BruteForceMatcher_OCL_base::knnMatchDownload ------------------------------------------------------ -Downloads matrices obtained via :ocv:func:`ocl::BruteForceMatcher_OCL_base::knnMatchSingle` or :ocv:func:`ocl::BruteForceMatcher_OCL_base::knnMatch2Collection` to vector with :ocv:class:`DMatch`. - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::knnMatchDownload(const oclMat& trainIdx, const oclMat& distance, std::vector< std::vector >&matches, bool compactResult = false) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::knnMatch2Download(const oclMat& trainIdx, const oclMat& imgIdx, const oclMat& distance, std::vector< std::vector >& matches, bool compactResult = false) - -If ``compactResult`` is ``true`` , the ``matches`` vector does not contain matches for fully masked-out query descriptors. - - - -ocl::BruteForceMatcher_OCL_base::knnMatchConvert ----------------------------------------------------- -Converts matrices obtained via :ocv:func:`ocl::BruteForceMatcher_OCL_base::knnMatchSingle` or :ocv:func:`ocl::BruteForceMatcher_OCL_base::knnMatch2Collection` to CPU vector with :ocv:class:`DMatch`. - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::knnMatchConvert(const Mat& trainIdx, const Mat& distance, std::vector< std::vector >&matches, bool compactResult = false) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::knnMatch2Convert(const Mat& trainIdx, const Mat& imgIdx, const Mat& distance, std::vector< std::vector >& matches, bool compactResult = false) - -If ``compactResult`` is ``true`` , the ``matches`` vector does not contain matches for fully masked-out query descriptors. - - - -ocl::BruteForceMatcher_OCL_base::radiusMatch ------------------------------------------------- -For each query descriptor, finds the best matches with a distance less than a given threshold. - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::radiusMatch(const oclMat& query, const oclMat& train, std::vector< std::vector >&matches, float maxDistance, const oclMat& mask = oclMat(), bool compactResult = false) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::radiusMatchSingle(const oclMat& query, const oclMat& train, oclMat& trainIdx, oclMat& distance, oclMat& nMatches, float maxDistance, const oclMat& mask = oclMat()) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::radiusMatch(const oclMat& query, std::vector< std::vector >&matches, float maxDistance, const std::vector& masks = std::vector(), bool compactResult = false) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::radiusMatchCollection(const oclMat& query, oclMat& trainIdx, oclMat& imgIdx, oclMat& distance, oclMat& nMatches, float maxDistance, const std::vector& masks = std::vector()) - - :param query: Query set of descriptors. - - :param train: Training set of descriptors. It is not added to train descriptors collection stored in the class object. - - :param maxDistance: Distance threshold. - - :param mask: Mask specifying permissible matches between the input query and train matrices of descriptors. - - :param compactResult: If ``compactResult`` is ``true`` , the ``matches`` vector does not contain matches for fully masked-out query descriptors. - - -The function returns detected matches in the increasing order by distance. - -The methods work only on devices with the compute capability :math:`>=` 1.1. - -The third variant of the method stores the results in GPU memory and does not store the points by the distance. - -.. seealso:: :ocv:func:`DescriptorMatcher::radiusMatch` - - - -ocl::BruteForceMatcher_OCL_base::radiusMatchDownload --------------------------------------------------------- -Downloads matrices obtained via :ocv:func:`ocl::BruteForceMatcher_OCL_base::radiusMatchSingle` or :ocv:func:`ocl::BruteForceMatcher_OCL_base::radiusMatchCollection` to vector with :ocv:class:`DMatch`. - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::radiusMatchDownload(const oclMat& trainIdx, const oclMat& distance, const oclMat& nMatches, std::vector< std::vector >&matches, bool compactResult = false) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::radiusMatchDownload(const oclMat& trainIdx, const oclMat& imgIdx, const oclMat& distance, const oclMat& nMatches, std::vector< std::vector >& matches, bool compactResult = false) - -If ``compactResult`` is ``true`` , the ``matches`` vector does not contain matches for fully masked-out query descriptors. - - - - -ocl::BruteForceMatcher_OCL_base::radiusMatchConvert -------------------------------------------------------- -Converts matrices obtained via :ocv:func:`ocl::BruteForceMatcher_OCL_base::radiusMatchSingle` or :ocv:func:`ocl::BruteForceMatcher_OCL_base::radiusMatchCollection` to vector with :ocv:class:`DMatch`. - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::radiusMatchConvert(const Mat& trainIdx, const Mat& distance, const Mat& nMatches, std::vector< std::vector >&matches, bool compactResult = false) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::radiusMatchConvert(const Mat& trainIdx, const Mat& imgIdx, const Mat& distance, const Mat& nMatches, std::vector< std::vector >& matches, bool compactResult = false) - -If ``compactResult`` is ``true`` , the ``matches`` vector does not contain matches for fully masked-out query descriptors. - - -ocl::FAST_OCL ------------------- -.. ocv:class:: ocl::FAST_OCL - -Class used for corner detection using the FAST algorithm. :: - - class CV_EXPORTS FAST_OCL - { - public: - enum - { - X_ROW = 0, - Y_ROW, - RESPONSE_ROW, - ROWS_COUNT - }; - - // all features have same size - static const int FEATURE_SIZE = 7; - - explicit FAST_OCL(int threshold, bool nonmaxSupression = true, double keypointsRatio = 0.05); - - //! finds the keypoints using FAST detector - //! supports only CV_8UC1 images - void operator ()(const oclMat& image, const oclMat& mask, oclMat& keypoints); - void operator ()(const oclMat& image, const oclMat& mask, std::vector& keypoints); - - //! download keypoints from device to host memory - static void downloadKeypoints(const oclMat& d_keypoints, std::vector& keypoints); - - //! convert keypoints to KeyPoint vector - static void convertKeypoints(const Mat& h_keypoints, std::vector& keypoints); - - //! release temporary buffer's memory - void release(); - - bool nonmaxSupression; - - int threshold; - - //! max keypoints = keypointsRatio * img.size().area() - double keypointsRatio; - - //! find keypoints and compute it's response if nonmaxSupression is true - //! return count of detected keypoints - int calcKeyPointsLocation(const oclMat& image, const oclMat& mask); - - //! get final array of keypoints - //! performs nonmax supression if needed - //! return final count of keypoints - int getKeyPoints(oclMat& keypoints); - - private: - // Hidden - }; - - -The class ``FAST_OCL`` implements FAST corner detection algorithm. - -.. seealso:: :ocv:func:`FAST` - - - -ocl::FAST_OCL::FAST_OCL --------------------------- -Constructor. - -.. ocv:function:: ocl::FAST_OCL::FAST_OCL(int threshold, bool nonmaxSupression = true, double keypointsRatio = 0.05) - - :param threshold: Threshold on difference between intensity of the central pixel and pixels on a circle around this pixel. - - :param nonmaxSupression: If it is true, non-maximum suppression is applied to detected corners (keypoints). - - :param keypointsRatio: Inner buffer size for keypoints store is determined as (keypointsRatio * image_width * image_height). - - - -ocl::FAST_OCL::operator () ----------------------------- -Finds the keypoints using FAST detector. - -.. ocv:function:: void ocl::FAST_OCL::operator ()(const oclMat& image, const oclMat& mask, oclMat& keypoints) -.. ocv:function:: void ocl::FAST_OCL::operator ()(const oclMat& image, const oclMat& mask, std::vector& keypoints) - - :param image: Image where keypoints (corners) are detected. Only 8-bit grayscale images are supported. - - :param mask: Optional input mask that marks the regions where we should detect features. - - :param keypoints: The output vector of keypoints. Can be stored both in host or device memory. For device memory: - - * X_ROW of keypoints will contain the horizontal coordinate of the i'th point - * Y_ROW of keypoints will contain the vertical coordinate of the i'th point - * RESPONSE_ROW will contain response of i'th point (if non-maximum suppression is applied) - - - -ocl::FAST_OCL::downloadKeypoints ----------------------------------- -Download keypoints from device to host memory. - -.. ocv:function:: void ocl::FAST_OCL::downloadKeypoints(const oclMat& d_keypoints, std::vector& keypoints) - - - -ocl::FAST_OCL::convertKeypoints ---------------------------------- -Converts keypoints from OpenCL representation to vector of ``KeyPoint``. - -.. ocv:function:: void ocl::FAST_OCL::convertKeypoints(const Mat& h_keypoints, std::vector& keypoints) - - - -ocl::FAST_OCL::release ------------------------- -Releases inner buffer memory. - -.. ocv:function:: void ocl::FAST_OCL::release() - - - -ocl::FAST_OCL::calcKeyPointsLocation --------------------------------------- -Find keypoints. If ``nonmaxSupression`` is true, responses are computed and eliminates keypoints with the smaller responses from 9-neighborhood regions. - -.. ocv:function:: int ocl::FAST_OCL::calcKeyPointsLocation(const oclMat& image, const oclMat& mask) - - :param image: Image where keypoints (corners) are detected. Only 8-bit grayscale images are supported. - - :param mask: Optional input mask that marks the regions where we should detect features. - -The function returns the amount of detected keypoints. - - - -ocl::FAST_OCL::getKeyPoints ------------------------------ -Gets final array of keypoints. - -.. ocv:function:: int ocl::FAST_OCL::getKeyPoints(oclMat& keypoints) - - :param keypoints: The output vector of keypoints. - -The function performs non-max suppression if needed and returns the final amount of keypoints. - -ocl::BRIEF_OCL ------------------- -.. ocv:class:: ocl::BRIEF_OCL - -Class for computing BRIEF descriptors described in a paper of Calonder M., Lepetit V., -Strecha C., Fua P. *BRIEF: Binary Robust Independent Elementary Features* , -11th European Conference on Computer Vision (ECCV), Heraklion, Crete. LNCS Springer, September 2010. :: - - class CV_EXPORTS BRIEF_OCL - { - public: - static const int PATCH_SIZE = 48; - static const int KERNEL_SIZE = 9; - - explicit BRIEF_OCL(int _bytes = 32); - - //!computes the brief descriptor for a set of given keypoints - //! supports only CV_8UC1 images - void compute(const oclMat& image, const oclMat& keypoints, oclMat& mask, oclMat& descriptors) const; - - static int getBorderSize(); - protected: - ... - }; - -ocl::BRIEF_OCL::BRIEF_OCL --------------------------- -Constructor. - -.. ocv:function:: ocl::BRIEF_OCL::BRIEF_OCL(int _bytes = 32) - - :param bytes: The length of the descriptor in bytes. Supported values are 16, 32 or 64 bytes. - -ocl::BRIEF_OCL::compute ------------------------- -Computes BRIEF descriptors. - -.. ocv:function:: void ocl::BRIEF_OCL::compute(const oclMat& image, const oclMat& keypoints, oclMat& mask, oclMat& descriptors) const - - :param image: Image The input 8-bit grayscale image. - - :param keypoints: The keypoints. - - :param mask: In and output mask. If mask has same cols as keypoints, descriptors are computed for keypoints with non-zero mask element. - On return it indicates for what keypoints a descriptor was computed or not(if a keypoint is near the image border). - - :param descriptors: The computed descriptors. It has size keypoints.cols x bytes. - -ocl::BRIEF_OCL::getBorderSize ------------------------------ -Returns the size of the image border where descriptors cannot be computed - -.. ocv:function:: static int ocl::BRIEF_OCL::getBorderSize() const - -ocl::HOGDescriptor ----------------------- - -.. ocv:struct:: ocl::HOGDescriptor - -The class implements Histogram of Oriented Gradients ([Dalal2005]_) object detector. :: - - struct CV_EXPORTS HOGDescriptor - { - enum { DEFAULT_WIN_SIGMA = -1 }; - enum { DEFAULT_NLEVELS = 64 }; - enum { DESCR_FORMAT_ROW_BY_ROW, DESCR_FORMAT_COL_BY_COL }; - - HOGDescriptor(Size win_size=Size(64, 128), Size block_size=Size(16, 16), - Size block_stride=Size(8, 8), Size cell_size=Size(8, 8), - int nbins=9, double win_sigma=DEFAULT_WIN_SIGMA, - double threshold_L2hys=0.2, bool gamma_correction=true, - int nlevels=DEFAULT_NLEVELS); - - size_t getDescriptorSize() const; - size_t getBlockHistogramSize() const; - - void setSVMDetector(const vector& detector); - - static vector getDefaultPeopleDetector(); - static vector getPeopleDetector48x96(); - static vector getPeopleDetector64x128(); - - void detect(const oclMat& img, vector& found_locations, - double hit_threshold=0, Size win_stride=Size(), - Size padding=Size()); - - void detectMultiScale(const oclMat& img, vector& found_locations, - double hit_threshold=0, Size win_stride=Size(), - Size padding=Size(), double scale0=1.05, - int group_threshold=2); - - void getDescriptors(const oclMat& img, Size win_stride, - oclMat& descriptors, - int descr_format=DESCR_FORMAT_COL_BY_COL); - - Size win_size; - Size block_size; - Size block_stride; - Size cell_size; - int nbins; - double win_sigma; - double threshold_L2hys; - bool gamma_correction; - int nlevels; - - private: - // Hidden - } - - -Interfaces of all methods are kept similar to the ``CPU HOG`` descriptor and detector analogues as much as possible. - -.. note:: - - (Ocl) An example using the HOG descriptor can be found at opencv_source_code/samples/ocl/hog.cpp - -ocl::HOGDescriptor::HOGDescriptor -------------------------------------- -Creates the ``HOG`` descriptor and detector. - -.. ocv:function:: ocl::HOGDescriptor::HOGDescriptor(Size win_size=Size(64, 128), Size block_size=Size(16, 16), Size block_stride=Size(8, 8), Size cell_size=Size(8, 8), int nbins=9, double win_sigma=DEFAULT_WIN_SIGMA, double threshold_L2hys=0.2, bool gamma_correction=true, int nlevels=DEFAULT_NLEVELS) - - :param win_size: Detection window size. Align to block size and block stride. - - :param block_size: Block size in pixels. Align to cell size. Only (16,16) is supported for now. - - :param block_stride: Block stride. It must be a multiple of cell size. - - :param cell_size: Cell size. Only (8, 8) is supported for now. - - :param nbins: Number of bins. Only 9 bins per cell are supported for now. - - :param win_sigma: Gaussian smoothing window parameter. - - :param threshold_L2hys: L2-Hys normalization method shrinkage. - - :param gamma_correction: Flag to specify whether the gamma correction preprocessing is required or not. - - :param nlevels: Maximum number of detection window increases. - - - -ocl::HOGDescriptor::getDescriptorSize ------------------------------------------ -Returns the number of coefficients required for the classification. - -.. ocv:function:: size_t ocl::HOGDescriptor::getDescriptorSize() const - - - -ocl::HOGDescriptor::getBlockHistogramSize ---------------------------------------------- -Returns the block histogram size. - -.. ocv:function:: size_t ocl::HOGDescriptor::getBlockHistogramSize() const - - - -ocl::HOGDescriptor::setSVMDetector --------------------------------------- -Sets coefficients for the linear SVM classifier. - -.. ocv:function:: void ocl::HOGDescriptor::setSVMDetector(const vector& detector) - - - -ocl::HOGDescriptor::getDefaultPeopleDetector ------------------------------------------------- -Returns coefficients of the classifier trained for people detection (for default window size). - -.. ocv:function:: static vector ocl::HOGDescriptor::getDefaultPeopleDetector() - - - -ocl::HOGDescriptor::getPeopleDetector48x96 ----------------------------------------------- -Returns coefficients of the classifier trained for people detection (for 48x96 windows). - -.. ocv:function:: static vector ocl::HOGDescriptor::getPeopleDetector48x96() - - - -ocl::HOGDescriptor::getPeopleDetector64x128 ------------------------------------------------ -Returns coefficients of the classifier trained for people detection (for 64x128 windows). - -.. ocv:function:: static vector ocl::HOGDescriptor::getPeopleDetector64x128() - - - -ocl::HOGDescriptor::detect ------------------------------- -Performs object detection without a multi-scale window. - -.. ocv:function:: void ocl::HOGDescriptor::detect(const oclMat& img, vector& found_locations, double hit_threshold=0, Size win_stride=Size(), Size padding=Size()) - - :param img: Source image. ``CV_8UC1`` and ``CV_8UC4`` types are supported for now. - - :param found_locations: Left-top corner points of detected objects boundaries. - - :param hit_threshold: Threshold for the distance between features and SVM classifying plane. Usually it is 0 and should be specfied in the detector coefficients (as the last free coefficient). But if the free coefficient is omitted (which is allowed), you can specify it manually here. - - :param win_stride: Window stride. It must be a multiple of block stride. - - :param padding: Mock parameter to keep the CPU interface compatibility. It must be (0,0). - - - -ocl::HOGDescriptor::detectMultiScale ----------------------------------------- -Performs object detection with a multi-scale window. - -.. ocv:function:: void ocl::HOGDescriptor::detectMultiScale(const oclMat& img, vector& found_locations, double hit_threshold=0, Size win_stride=Size(), Size padding=Size(), double scale0=1.05, int group_threshold=2) - - :param img: Source image. See :ocv:func:`ocl::HOGDescriptor::detect` for type limitations. - - :param found_locations: Detected objects boundaries. - - :param hit_threshold: Threshold for the distance between features and SVM classifying plane. See :ocv:func:`ocl::HOGDescriptor::detect` for details. - - :param win_stride: Window stride. It must be a multiple of block stride. - - :param padding: Mock parameter to keep the CPU interface compatibility. It must be (0,0). - - :param scale0: Coefficient of the detection window increase. - - :param group_threshold: Coefficient to regulate the similarity threshold. When detected, some objects can be covered by many rectangles. 0 means not to perform grouping. See :ocv:func:`groupRectangles` . - - - -ocl::HOGDescriptor::getDescriptors --------------------------------------- -Returns block descriptors computed for the whole image. - -.. ocv:function:: void ocl::HOGDescriptor::getDescriptors(const oclMat& img, Size win_stride, oclMat& descriptors, int descr_format=DESCR_FORMAT_COL_BY_COL) - - :param img: Source image. See :ocv:func:`ocl::HOGDescriptor::detect` for type limitations. - - :param win_stride: Window stride. It must be a multiple of block stride. - - :param descriptors: 2D array of descriptors. - - :param descr_format: Descriptor storage format: - - * **DESCR_FORMAT_ROW_BY_ROW** - Row-major order. - - * **DESCR_FORMAT_COL_BY_COL** - Column-major order. - -The function is mainly used to learn the classifier. - - - -ocl::ORB_OCL --------------- -.. ocv:class:: ocl::ORB_OCL - -Class for extracting ORB features and descriptors from an image. :: - - class ORB_OCL - { - public: - enum - { - X_ROW = 0, - Y_ROW, - RESPONSE_ROW, - ANGLE_ROW, - OCTAVE_ROW, - SIZE_ROW, - ROWS_COUNT - }; - - enum - { - DEFAULT_FAST_THRESHOLD = 20 - }; - - explicit ORB_OCL(int nFeatures = 500, float scaleFactor = 1.2f, - int nLevels = 8, int edgeThreshold = 31, - int firstLevel = 0, int WTA_K = 2, - int scoreType = 0, int patchSize = 31); - - void operator()(const oclMat& image, const oclMat& mask, - std::vector& keypoints); - void operator()(const oclMat& image, const oclMat& mask, oclMat& keypoints); - - void operator()(const oclMat& image, const oclMat& mask, - std::vector& keypoints, oclMat& descriptors); - void operator()(const oclMat& image, const oclMat& mask, - oclMat& keypoints, oclMat& descriptors); - - void downloadKeyPoints(oclMat& d_keypoints, std::vector& keypoints); - - void convertKeyPoints(Mat& d_keypoints, std::vector& keypoints); - - int descriptorSize() const; - int descriptorType() const; - int defaultNorm() const; - - void setFastParams(int threshold, bool nonmaxSupression = true); - - void release(); - - bool blurForDescriptor; - }; - -The class implements ORB feature detection and description algorithm. - - - -ocl::ORB_OCL::ORB_OCL ------------------------- -Constructor. - -.. ocv:function:: ocl::ORB_OCL::ORB_OCL(int nFeatures = 500, float scaleFactor = 1.2f, int nLevels = 8, int edgeThreshold = 31, int firstLevel = 0, int WTA_K = 2, int scoreType = 0, int patchSize = 31) - - :param nfeatures: The maximum number of features to retain. - - :param scaleFactor: Pyramid decimation ratio, greater than 1. ``scaleFactor==2`` means the classical pyramid, where each next level has 4x less pixels than the previous, but such a big scale factor will degrade feature matching scores dramatically. On the other hand, too close to 1 scale factor will mean that to cover certain scale range you will need more pyramid levels and so the speed will suffer. - - :param nlevels: The number of pyramid levels. The smallest level will have linear size equal to ``input_image_linear_size/pow(scaleFactor, nlevels)``. - - :param edgeThreshold: This is size of the border where the features are not detected. It should roughly match the ``patchSize`` parameter. - - :param firstLevel: It should be 0 in the current implementation. - - :param WTA_K: The number of points that produce each element of the oriented BRIEF descriptor. The default value 2 means the BRIEF where we take a random point pair and compare their brightnesses, so we get 0/1 response. Other possible values are 3 and 4. For example, 3 means that we take 3 random points (of course, those point coordinates are random, but they are generated from the pre-defined seed, so each element of BRIEF descriptor is computed deterministically from the pixel rectangle), find point of maximum brightness and output index of the winner (0, 1 or 2). Such output will occupy 2 bits, and therefore it will need a special variant of Hamming distance, denoted as ``NORM_HAMMING2`` (2 bits per bin). When ``WTA_K=4``, we take 4 random points to compute each bin (that will also occupy 2 bits with possible values 0, 1, 2 or 3). - - :param scoreType: The default HARRIS_SCORE means that Harris algorithm is used to rank features (the score is written to ``KeyPoint::score`` and is used to retain best ``nfeatures`` features); FAST_SCORE is alternative value of the parameter that produces slightly less stable keypoints, but it is a little faster to compute. - - :param patchSize: size of the patch used by the oriented BRIEF descriptor. Of course, on smaller pyramid layers the perceived image area covered by a feature will be larger. - - - -ocl::ORB_OCL::operator() --------------------------- -Detects keypoints and computes descriptors for them. - -.. ocv:function:: void ocl::ORB_OCL::operator()(const oclMat& image, const oclMat& mask, std::vector& keypoints) - -.. ocv:function:: void ocl::ORB_OCL::operator()(const oclMat& image, const oclMat& mask, oclMat& keypoints) - -.. ocv:function:: void ocl::ORB_OCL::operator()(const oclMat& image, const oclMat& mask, std::vector& keypoints, oclMat& descriptors) - -.. ocv:function:: void ocl::ORB_OCL::operator()(const oclMat& image, const oclMat& mask, oclMat& keypoints, oclMat& descriptors) - - :param image: Input 8-bit grayscale image. - - :param mask: Optional input mask that marks the regions where we should detect features. - - :param keypoints: The input/output vector of keypoints. Can be stored both in host and device memory. For device memory: - - * ``X_ROW`` contains the horizontal coordinate of the i'th feature. - * ``Y_ROW`` contains the vertical coordinate of the i'th feature. - * ``RESPONSE_ROW`` contains the response of the i'th feature. - * ``ANGLE_ROW`` contains the orientation of the i'th feature. - * ``RESPONSE_ROW`` contains the octave of the i'th feature. - * ``ANGLE_ROW`` contains the size of the i'th feature. - - :param descriptors: Computed descriptors. if ``blurForDescriptor`` is true, image will be blurred before descriptors calculation. - - - -ocl::ORB_OCL::downloadKeyPoints ---------------------------------- -Download keypoints from device to host memory. - -.. ocv:function:: static void ocl::ORB_OCL::downloadKeyPoints( const oclMat& d_keypoints, std::vector& keypoints ) - - - -ocl::ORB_OCL::convertKeyPoints --------------------------------- -Converts keypoints from OCL representation to vector of ``KeyPoint``. - -.. ocv:function:: static void ocl::ORB_OCL::convertKeyPoints( const Mat& d_keypoints, std::vector& keypoints ) - - - -ocl::ORB_OCL::release ------------------------ -Releases inner buffer memory. - -.. ocv:function:: void ocl::ORB_OCL::release() diff --git a/modules/ocl/doc/image_filtering.rst b/modules/ocl/doc/image_filtering.rst deleted file mode 100644 index 6fbc19a71..000000000 --- a/modules/ocl/doc/image_filtering.rst +++ /dev/null @@ -1,719 +0,0 @@ -Image Filtering -============================= - -.. highlight:: cpp - -ocl::BaseRowFilter_GPU --------------------------- -.. ocv:class:: ocl::BaseRowFilter_GPU - -Base class for linear or non-linear filters that processes rows of 2D arrays. Such filters are used for the "horizontal" filtering passes in separable filters. :: - - class CV_EXPORTS BaseRowFilter_GPU - { - public: - BaseRowFilter_GPU(int ksize_, int anchor_, int bordertype_) : ksize(ksize_), anchor(anchor_), bordertype(bordertype_) {} - virtual ~BaseRowFilter_GPU() {} - virtual void operator()(const oclMat &src, oclMat &dst) = 0; - int ksize, anchor, bordertype; - }; - -.. note:: This class does not allocate memory for a destination image. Usually this class is used inside :ocv:class:`ocl::FilterEngine_GPU`. - -ocl::BaseColumnFilter_GPU ------------------------------ -.. ocv:class:: ocl::BaseColumnFilter_GPU - -Base class for linear or non-linear filters that processes columns of 2D arrays. Such filters are used for the "vertical" filtering passes in separable filters. :: - - class CV_EXPORTS BaseColumnFilter_GPU - { - public: - BaseColumnFilter_GPU(int ksize_, int anchor_, int bordertype_) : ksize(ksize_), anchor(anchor_), bordertype(bordertype_) {} - virtual ~BaseColumnFilter_GPU() {} - virtual void operator()(const oclMat &src, oclMat &dst) = 0; - int ksize, anchor, bordertype; - }; - -.. note:: This class does not allocate memory for a destination image. Usually this class is used inside :ocv:class:`ocl::FilterEngine_GPU`. - -ocl::BaseFilter_GPU ------------------------ -.. ocv:class:: ocl::BaseFilter_GPU - -Base class for non-separable 2D filters. :: - - class CV_EXPORTS BaseFilter_GPU - { - public: - BaseFilter_GPU(const Size &ksize_, const Point &anchor_, const int &borderType_) - : ksize(ksize_), anchor(anchor_), borderType(borderType_) {} - virtual ~BaseFilter_GPU() {} - virtual void operator()(const oclMat &src, oclMat &dst) = 0; - Size ksize; - Point anchor; - int borderType; - }; - -.. note:: This class does not allocate memory for a destination image. Usually this class is used inside :ocv:class:`ocl::FilterEngine_GPU` - -ocl::FilterEngine_GPU ------------------------- -.. ocv:class:: ocl::FilterEngine_GPU - -Base class for the Filter Engine. :: - - class CV_EXPORTS FilterEngine_GPU - { - public: - virtual ~FilterEngine_GPU() {} - - virtual void apply(const oclMat &src, oclMat &dst, Rect roi = Rect(0, 0, -1, -1)) = 0; - }; - -The class can be used to apply an arbitrary filtering operation to an image. It contains all the necessary intermediate buffers. Pointers to the initialized ``FilterEngine_GPU`` instances are returned by various ``create*Filter_GPU`` functions (see below), and they are used inside high-level functions such as :ocv:func:`ocl::filter2D`, :ocv:func:`ocl::erode`, :ocv:func:`ocl::Sobel` , and others. - -By using ``FilterEngine_GPU`` instead of functions you can avoid unnecessary memory allocation for intermediate buffers and get better performance: :: - - while (...) - { - ocl::oclMat src = getImg(); - ocl::oclMat dst; - // Allocate and release buffers at each iterations - ocl::GaussianBlur(src, dst, ksize, sigma1); - } - - // Allocate buffers only once - cv::Ptr filter = - ocl::createGaussianFilter_GPU(CV_8UC4, ksize, sigma1); - while (...) - { - ocl::oclMat src = getImg(); - ocl::oclMat dst; - filter->apply(src, dst, cv::Rect(0, 0, src.cols, src.rows)); - } - // Release buffers only once - filter.release(); - - -``FilterEngine_GPU`` can process a rectangular sub-region of an image. By default, if ``roi == Rect(0,0,-1,-1)`` , ``FilterEngine_GPU`` processes the inner region of an image ( ``Rect(anchor.x, anchor.y, src_size.width - ksize.width, src_size.height - ksize.height)`` ) because some filters do not check whether indices are outside the image for better performance. See below to understand which filters support processing the whole image and which do not and identify image type limitations. - -.. note:: The GPU filters do not support the in-place mode. - -.. seealso:: :ocv:class:`ocl::BaseRowFilter_GPU`, :ocv:class:`ocl::BaseColumnFilter_GPU`, :ocv:class:`ocl::BaseFilter_GPU`, :ocv:func:`ocl::createFilter2D_GPU`, :ocv:func:`ocl::createSeparableFilter_GPU`, :ocv:func:`ocl::createBoxFilter_GPU`, :ocv:func:`ocl::createMorphologyFilter_GPU`, :ocv:func:`ocl::createLinearFilter_GPU`, :ocv:func:`ocl::createSeparableLinearFilter_GPU`, :ocv:func:`ocl::createDerivFilter_GPU`, :ocv:func:`ocl::createGaussianFilter_GPU` - -ocl::createFilter2D_GPU ---------------------------- -Creates a non-separable filter engine with the specified filter. - -.. ocv:function:: Ptr ocl::createFilter2D_GPU( const Ptr filter2D) - - :param filter2D: Non-separable 2D filter. - -Usually this function is used inside such high-level functions as :ocv:func:`ocl::createLinearFilter_GPU`, :ocv:func:`ocl::createBoxFilter_GPU`. - - -ocl::createSeparableFilter_GPU ----------------------------------- -Creates a separable filter engine with the specified filters. - -.. ocv:function:: Ptr ocl::createSeparableFilter_GPU(const Ptr &rowFilter, const Ptr &columnFilter) - - :param rowFilter: "Horizontal" 1D filter. - - :param columnFilter: "Vertical" 1D filter. - -Usually this function is used inside such high-level functions as :ocv:func:`ocl::createSeparableLinearFilter_GPU`. - -ocl::createBoxFilter_GPU ----------------------------- -Creates a normalized 2D box filter. - -.. ocv:function:: Ptr ocl::createBoxFilter_GPU(int srcType, int dstType, const Size &ksize, const Point &anchor = Point(-1, -1), int borderType = BORDER_DEFAULT) - -.. ocv:function:: Ptr ocl::getBoxFilter_GPU(int srcType, int dstType, const Size &ksize, Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT) - - :param srcType: Input image type. - - :param dstType: Output image type. It supports only the same values as the source type. - - :param ksize: Kernel size. - - :param anchor: Anchor point. The default value ``Point(-1, -1)`` means that the anchor is at the kernel center. - - :param borderType: Border type. - -.. seealso:: :ocv:func:`boxFilter` - -ocl::boxFilter ------------------- -Smooths the image using the normalized box filter. - -.. ocv:function:: void ocl::boxFilter(const oclMat &src, oclMat &dst, int ddepth, Size ksize, Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT) - - :param src: Input image. - - :param dst: Output image type. The size and type is the same as ``src`` . - - :param ddepth: Desired depth of the destination image. If it is negative, it is the same as ``src.depth()`` . It supports only the same depth as the source image depth. - - :param ksize: Kernel size. - - :param anchor: Anchor point. The default value ``Point(-1, -1)`` means that the anchor is at the kernel center. - - :param borderType: Border type. - -Smoothes image using box filter. - -ocl::blur -------------- -Acts as a synonym for the normalized box filter. - -.. ocv:function:: void ocl::blur(const oclMat &src, oclMat &dst, Size ksize, Point anchor = Point(-1, -1), int borderType = BORDER_CONSTANT) - - :param src: Input image. - - :param dst: Output image type with the same size and type as ``src`` . - - :param ksize: Kernel size. - - :param anchor: Anchor point. The default value Point(-1, -1) means that the anchor is at the kernel center. - - :param borderType: Border type. - -.. seealso:: :ocv:func:`blur`, :ocv:func:`ocl::boxFilter` - -ocl::createMorphologyFilter_GPU ------------------------------------ -Creates a 2D morphological filter. - -.. ocv:function:: Ptr ocl::createMorphologyFilter_GPU(int op, int type, const Mat &kernel, const Point &anchor = Point(-1, -1), int iterations = 1) - -.. ocv:function:: Ptr ocl::getMorphologyFilter_GPU(int op, int type, const Mat &kernel, const Size &ksize, Point anchor = Point(-1, -1)) - - :param op: Morphology operation id. Only ``MORPH_ERODE`` and ``MORPH_DILATE`` are supported. - - :param type: Input/output image type. Only ``CV_8UC1`` and ``CV_8UC4`` are supported. - - :param kernel: 2D 8-bit structuring element for the morphological operation. - - :param ksize: Size of a horizontal or vertical structuring element used for separable morphological operations. - - :param anchor: Anchor position within the structuring element. Negative values mean that the anchor is at the center. - -.. note:: This filter does not check out-of-border accesses, so only a proper sub-matrix of a bigger matrix has to be passed to it. - -.. seealso:: :ocv:func:`createMorphologyFilter` - -ocl::createLinearFilter_GPU -------------------------------- -Creates a non-separable linear filter. - -.. ocv:function:: Ptr ocl::createLinearFilter_GPU(int srcType, int dstType, const Mat &kernel, const Point &anchor = Point(-1, -1), int borderType = BORDER_DEFAULT) - - :param srcType: Input image type.. - - :param dstType: Output image type. The same type as ``src`` is supported. - - :param kernel: 2D array of filter coefficients. - - :param anchor: Anchor point. The default value Point(-1, -1) means that the anchor is at the kernel center. - - :param borderType: Pixel extrapolation method. For details, see :ocv:func:`borderInterpolate` . - -.. seealso:: :ocv:func:`createLinearFilter` - - -ocl::filter2D ------------------ -Applies the non-separable 2D linear filter to an image. - -.. ocv:function:: void ocl::filter2D(const oclMat &src, oclMat &dst, int ddepth, const Mat &kernel, Point anchor = Point(-1, -1), double delta = 0.0, int borderType = BORDER_DEFAULT) - - :param src: Source image. - - :param dst: Destination image. The size and the number of channels is the same as ``src`` . - - :param ddepth: Desired depth of the destination image. If it is negative, it is the same as ``src.depth()`` . It supports only the same depth as the source image depth. - - :param kernel: 2D array of filter coefficients. - - :param anchor: Anchor of the kernel that indicates the relative position of a filtered point within the kernel. The anchor resides within the kernel. The special default value (-1,-1) means that the anchor is at the kernel center. - - :param delta: optional value added to the filtered pixels before storing them in ``dst``. Value '0' is supported only. - - :param borderType: Pixel extrapolation method. For details, see :ocv:func:`borderInterpolate` . - -ocl::getLinearRowFilter_GPU -------------------------------- -Creates a primitive row filter with the specified kernel. - -.. ocv:function:: Ptr ocl::getLinearRowFilter_GPU(int srcType, int bufType, const Mat &rowKernel, int anchor = -1, int bordertype = BORDER_DEFAULT) - - :param srcType: Source array type. Only ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` source types are supported. - - :param bufType: Intermediate buffer type with as many channels as ``srcType`` . - - :param rowKernel: Filter coefficients. Support kernels with ``size <= 16`` . - - :param anchor: Anchor position within the kernel. Negative values mean that the anchor is positioned at the aperture center. - - :param borderType: Pixel extrapolation method. For details, see :ocv:func:`borderInterpolate`. - -.. seealso:: :ocv:func:`createSeparableLinearFilter` . - - -ocl::getLinearColumnFilter_GPU ----------------------------------- -Creates a primitive column filter with the specified kernel. - -.. ocv:function:: Ptr ocl::getLinearColumnFilter_GPU(int bufType, int dstType, const Mat &columnKernel, int anchor = -1, int bordertype = BORDER_DEFAULT, double delta = 0.0) - - :param bufType: Intermediate buffer type with as many channels as ``dstType`` . - - :param dstType: Destination array type. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` destination types are supported. - - :param columnKernel: Filter coefficients. Support kernels with ``size <= 16`` . - - :param anchor: Anchor position within the kernel. Negative values mean that the anchor is positioned at the aperture center. - - :param bordertype: Pixel extrapolation method. For details, see :ocv:func:`borderInterpolate` . - - :param delta: default value is 0.0. - -.. seealso:: :ocv:func:`ocl::getLinearRowFilter_GPU`, :ocv:func:`createSeparableLinearFilter` - -ocl::createSeparableLinearFilter_GPU ----------------------------------------- -Creates a separable linear filter engine. - -.. ocv:function:: Ptr ocl::createSeparableLinearFilter_GPU(int srcType, int dstType, const Mat &rowKernel, const Mat &columnKernel, const Point &anchor = Point(-1, -1), double delta = 0.0, int bordertype = BORDER_DEFAULT, Size imgSize = Size(-1,-1) ) - - :param srcType: Source array type. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` source types are supported. - - :param dstType: Destination array type. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` destination types are supported. - - :param rowKernel: Horizontal filter coefficients. Support kernels with ``size <= 16`` . - - :param columnKernel: Vertical filter coefficients. Support kernels with ``size <= 16`` . - - :param anchor: Anchor position within the kernel. Negative values mean that anchor is positioned at the aperture center. - - :param delta: default value is 0.0. - - :param bordertype: Pixel extrapolation method. - - :param imgSize: Source image size to choose optimal method for processing. - -.. seealso:: :ocv:func:`ocl::getLinearRowFilter_GPU`, :ocv:func:`ocl::getLinearColumnFilter_GPU`, :ocv:func:`createSeparableLinearFilter` - - -ocl::sepFilter2D --------------------- -Applies a separable 2D linear filter to an image. - -.. ocv:function:: void ocl::sepFilter2D(const oclMat &src, oclMat &dst, int ddepth, const Mat &kernelX, const Mat &kernelY, Point anchor = Point(-1, -1), double delta = 0.0, int bordertype = BORDER_DEFAULT) - - :param src: Source image. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_32SC1`` , ``CV_32FC1`` source types are supported. - - :param dst: Destination image with the same size and number of channels as ``src`` . - - :param ddepth: Destination image depth. ``CV_8U`` , ``CV_16S`` , ``CV_32S`` , and ``CV_32F`` are supported. - - :param kernelX: Horizontal filter coefficients. - - :param kernelY: Vertical filter coefficients. - - :param anchor: Anchor position within the kernel. The default value ``(-1, 1)`` means that the anchor is at the kernel center. - - :param delta: default value is 0.0. - - :param bordertype: Pixel extrapolation method. For details, see :ocv:func:`borderInterpolate`. - -.. seealso:: :ocv:func:`ocl::createSeparableLinearFilter_GPU`, :ocv:func:`sepFilter2D` - -ocl::createDerivFilter_GPU ------------------------------- -Creates a filter engine for the generalized Sobel operator. - -.. ocv:function:: Ptr ocl::createDerivFilter_GPU( int srcType, int dstType, int dx, int dy, int ksize, int borderType = BORDER_DEFAULT, Size imgSize = Size(-1,-1) ) - - :param srcType: Source image type. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` source types are supported. - - :param dstType: Destination image type with as many channels as ``srcType`` , ``CV_8U`` , ``CV_16S`` , ``CV_32S`` , and ``CV_32F`` depths are supported. - - :param dx: Derivative order in respect of x. - - :param dy: Derivative order in respect of y. - - :param ksize: Aperture size. See :ocv:func:`getDerivKernels` for details. - - :param borderType: Pixel extrapolation method. For details, see :ocv:func:`borderInterpolate`. - - :param imgSize: Source image size to choose optimal method for processing. - -.. seealso:: :ocv:func:`ocl::createSeparableLinearFilter_GPU`, :ocv:func:`createDerivFilter` - - -ocl::Sobel ------------------- -Returns void - -.. ocv:function:: void ocl::Sobel(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double delta = 0.0, int bordertype = BORDER_DEFAULT) - - :param src: The source image - - :param dst: The destination image; It will have the same size as src - - :param ddepth: The destination image depth - - :param dx: Order of the derivative x - - :param dy: Order of the derivative y - - :param ksize: Size of the extended Sobel kernel - - :param scale: The optional scale factor for the computed derivative values(by default, no scaling is applied) - - :param delta: The optional delta value, added to the results prior to storing them in dst - - :param bordertype: Pixel extrapolation method. - -The function computes the first x- or y- spatial image derivative using Sobel operator. Surpport 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4 data type. - -ocl::Scharr ------------------- -Returns void - -.. ocv:function:: void ocl::Scharr(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, double scale = 1, double delta = 0.0, int bordertype = BORDER_DEFAULT) - - :param src: The source image - - :param dst: The destination image; It will have the same size as src - - :param ddepth: The destination image depth - - :param dx: Order of the derivative x - - :param dy: Order of the derivative y - - :param scale: The optional scale factor for the computed derivative values(by default, no scaling is applied) - - :param delta: The optional delta value, added to the results prior to storing them in dst - - :param bordertype: Pixel extrapolation method. - -The function computes the first x- or y- spatial image derivative using Scharr operator. Surpport 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4 data type. - -ocl::createGaussianFilter_GPU ---------------------------------- -Creates a Gaussian filter engine. - -.. ocv:function:: Ptr ocl::createGaussianFilter_GPU(int type, Size ksize, double sigma1, double sigma2 = 0, int bordertype = BORDER_DEFAULT, Size imgSize = Size(-1,-1) ) - - :param type: Source and destination image type. ``CV_8UC1`` , ``CV_8UC4`` , ``CV_16SC1`` , ``CV_16SC2`` , ``CV_16SC3`` , ``CV_32SC1`` , ``CV_32FC1`` are supported. - - :param ksize: Aperture size. See :ocv:func:`getGaussianKernel` for details. - - :param sigma1: Gaussian sigma in the horizontal direction. See :ocv:func:`getGaussianKernel` for details. - - :param sigma2: Gaussian sigma in the vertical direction. If 0, then :math:`\texttt{sigma2}\leftarrow\texttt{sigma1}` . - - :param bordertype: Pixel extrapolation method. For details, see :ocv:func:`borderInterpolate`. - - :param imgSize: Source image size to choose optimal method for processing. - -.. seealso:: :ocv:func:`ocl::createSeparableLinearFilter_GPU`, :ocv:func:`createGaussianFilter` - -ocl::GaussianBlur ---------------------- -Returns void - -.. ocv:function:: void ocl::GaussianBlur(const oclMat &src, oclMat &dst, Size ksize, double sigma1, double sigma2 = 0, int bordertype = BORDER_DEFAULT) - - :param src: The source image - - :param dst: The destination image; It will have the same size and the same type as src - - :param ksize: The Gaussian kernel size; ksize.width and ksize.height can differ, but they both must be positive and odd. Or, they can be zero's, then they are computed from sigma - - :param sigma1sigma2: The Gaussian kernel standard deviations in X and Y direction. If sigmaY is zero, it is set to be equal to sigmaX. If they are both zeros, they are computed from ksize.width and ksize.height. To fully control the result regardless of possible future modification of all this semantics, it is recommended to specify all of ksize, sigmaX and sigmaY - - :param bordertype: Pixel extrapolation method. - -The function convolves the source image with the specified Gaussian kernel. In-place filtering is supported. Surpport 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4 data type. - -ocl::Laplacian ------------------- -Returns void - -.. ocv:function:: void ocl::Laplacian(const oclMat &src, oclMat &dst, int ddepth, int ksize = 1, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT) - - :param src: The source image - - :param dst: The destination image; It will have the same size and the same type as src - - :param ddepth: The desired depth of the destination image - - :param ksize: The aperture size used to compute the second-derivative filters. It must be positive and odd - - :param scale: The optional scale factor for the computed Laplacian values (by default, no scaling is applied - - :param delta: Optional delta value that is added to the results prior to storing them in ``dst`` . Supported value is 0 only. - - :param bordertype: Pixel extrapolation method. - -The function calculates the Laplacian of the source image by adding up the second x and y derivatives calculated using the Sobel operator. - -ocl::ConvolveBuf ----------------- -.. ocv:struct:: ocl::ConvolveBuf - -Class providing a memory buffer for :ocv:func:`ocl::convolve` function, plus it allows to adjust some specific parameters. :: - - struct CV_EXPORTS ConvolveBuf - { - Size result_size; - Size block_size; - Size user_block_size; - Size dft_size; - int spect_len; - - oclMat image_spect, templ_spect, result_spect; - oclMat image_block, templ_block, result_data; - - void create(Size image_size, Size templ_size); - static Size estimateBlockSize(Size result_size, Size templ_size); - }; - -You can use field `user_block_size` to set specific block size for :ocv:func:`ocl::convolve` function. If you leave its default value `Size(0,0)` then automatic estimation of block size will be used (which is optimized for speed). By varying `user_block_size` you can reduce memory requirements at the cost of speed. - -ocl::ConvolveBuf::create ------------------------- -.. ocv:function:: ocl::ConvolveBuf::create(Size image_size, Size templ_size) - -Constructs a buffer for :ocv:func:`ocl::convolve` function with respective arguments. - -ocl::convolve ------------------- -Returns void - -.. ocv:function:: void ocl::convolve(const oclMat &image, const oclMat &temp1, oclMat &result, bool ccorr=false) - -.. ocv:function:: void ocl::convolve(const oclMat &image, const oclMat &temp1, oclMat &result, bool ccorr, ConvolveBuf& buf) - - :param image: The source image. Only ``CV_32FC1`` images are supported for now. - - :param temp1: Convolution kernel, a single-channel floating point matrix. The size is not greater than the ``image`` size. The type is the same as ``image``. - - :param result: The destination image - - :param ccorr: Flags to evaluate cross-correlation instead of convolution. - - :param buf: Optional buffer to avoid extra memory allocations and to adjust some specific parameters. See :ocv:struct:`ocl::ConvolveBuf`. - -Convolves an image with the kernel. Supports only CV_32FC1 data types and do not support ROI. - -ocl::bilateralFilter ------------------------- -Returns void - -.. ocv:function:: void ocl::bilateralFilter(const oclMat &src, oclMat &dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT) - - :param src: The source image - - :param dst: The destination image; will have the same size and the same type as src - - :param d: The diameter of each pixel neighborhood, that is used during filtering. If it is non-positive, it's computed from sigmaSpace - - :param sigmaColor: Filter sigma in the color space. Larger value of the parameter means that farther colors within the pixel neighborhood (see sigmaSpace) will be mixed together, resulting in larger areas of semi-equal color - - :param sigmaSpave: Filter sigma in the coordinate space. Larger value of the parameter means that farther pixels will influence each other (as long as their colors are close enough; see sigmaColor). Then d>0, it specifies the neighborhood size regardless of sigmaSpace, otherwise d is proportional to sigmaSpace. - - :param borderType: Pixel extrapolation method. - -Applies bilateral filter to the image. Supports 8UC1 8UC4 data types. - -ocl::adaptiveBilateralFilter --------------------------------- -Returns void - -.. ocv:function:: void ocl::adaptiveBilateralFilter(const oclMat& src, oclMat& dst, Size ksize, double sigmaSpace, double maxSigmaColor = 20.0, Point anchor = Point(-1, -1), int borderType=BORDER_DEFAULT) - - :param src: The source image - - :param dst: The destination image; will have the same size and the same type as src - - :param ksize: The kernel size. This is the neighborhood where the local variance will be calculated, and where pixels will contribute (in a weighted manner). - - :param sigmaSpace: Filter sigma in the coordinate space. Larger value of the parameter means that farther pixels will influence each other (as long as their colors are close enough; see sigmaColor). Then d>0, it specifies the neighborhood size regardless of sigmaSpace, otherwise d is proportional to sigmaSpace. - - :param maxSigmaColor: Maximum allowed sigma color (will clamp the value calculated in the ksize neighborhood. Larger value of the parameter means that more dissimilar pixels will influence each other (as long as their colors are close enough; see sigmaColor). Then d>0, it specifies the neighborhood size regardless of sigmaSpace, otherwise d is proportional to sigmaSpace. - - :param borderType: Pixel extrapolation method. - -A main part of our strategy will be to load each raw pixel once, and reuse it to calculate all pixels in the output (filtered) image that need this pixel value. The math of the filter is that of the usual bilateral filter, except that the sigma color is calculated in the neighborhood, and clamped by the optional input value. - -Local memory organization - - -.. image:: images/adaptiveBilateralFilter.jpg - :height: 250pt - :width: 350pt - :alt: Introduction Icon - -.. note:: We partition the image to non-overlapping blocks of size (Ux, Uy). Each such block will correspond to the pixel locations where we will calculate the filter result in one workgroup. Considering neighbourhoods of sizes (kx, ky), where kx = 2 dx + 1, and ky = 2 dy + 1 (in image ML, dx = dy = 1, and kx = ky = 3), it is clear that we need to load data of size Wx = Ux + 2 dx, Wy = Uy + 2 dy. Furthermore, if (Sx, Sy) is the top left pixel coordinates for a particular block, and (Sx + Ux - 1, Sy + Uy -1) is to botom right coordinate of the block, we need to load data starting at top left coordinate (PSx, PSy) = (Sx - dx, Sy - dy), and ending at bottom right coordinate (Sx + Ux - 1 + dx, Sy + Uy - 1 + dy). The workgroup layout is (Wx,1). However, to take advantage of the natural hardware properties (preferred wavefront sizes), we restrict Wx to be a multiple of that preferred wavefront size (for current AMD hardware this is typically 64). Each thread in the workgroup will load Wy elements (under the constraint that Wx*Wy*pixel width <= max local memory). - -Applies bilateral filter to the image. Supports 8UC1 8UC3 data types. - -ocl::copyMakeBorder ------------------------ -Returns void - -.. ocv:function:: void ocl::copyMakeBorder(const oclMat &src, oclMat &dst, int top, int bottom, int left, int right, int boardtype, const Scalar &value = Scalar()) - - :param src: The source image - - :param dst: The destination image; will have the same type as src and the size size(src.cols+left+right, src.rows+top+bottom) - - :param topbottomleftright: Specify how much pixels in each direction from the source image rectangle one needs to extrapolate, e.g. top=1, bottom=1, left=1, right=1mean that 1 pixel-wide border needs to be built - - :param bordertype: Pixel extrapolation method. - - :param value: The border value if borderType==BORDER CONSTANT - -Forms a border around the image. Supports 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4 data types. - -ocl::dilate ------------------- -Returns void - -.. ocv:function:: void ocl::dilate( const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue()) - - :param src: The source image - - :param dst: The destination image; It will have the same size and the same type as src - - :param kernel: The structuring element used for dilation. If element=Mat(), a 3times 3 rectangular structuring element is used - - :param anchor: Position of the anchor within the element. The default value (-1, -1) means that the anchor is at the element center, only default value is supported - - :param iterations: The number of times dilation is applied - - :param bordertype: Pixel extrapolation method. - - :param value: The border value if borderType==BORDER CONSTANT - -The function dilates the source image using the specified structuring element that determines the shape of a pixel neighborhood over which the maximum is taken. Supports 8UC1 8UC4 data types. - -ocl::erode ------------------- -Returns void - -.. ocv:function:: void ocl::erode( const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue()) - - :param src: The source image - - :param dst: The destination image; It will have the same size and the same type as src - - :param kernel: The structuring element used for dilation. If element=Mat(), a 3times 3 rectangular structuring element is used - - :param anchor: Position of the anchor within the element. The default value (-1, -1) means that the anchor is at the element center, only default value is supported - - :param iterations: The number of times dilation is applied - - :param bordertype: Pixel extrapolation method. - - :param value: The border value if borderType==BORDER CONSTANT - -The function erodes the source image using the specified structuring element that determines the shape of a pixel neighborhood over which the minimum is taken. Supports 8UC1 8UC4 data types. - -ocl::morphologyEx ---------------------- -Returns void - -.. ocv:function:: void ocl::morphologyEx( const oclMat &src, oclMat &dst, int op, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue()) - - :param src: The source image - - :param dst: The destination image; It will have the same size and the same type as src - - :param op: Type of morphological operation, one of the following: ERODE DILTATE OPEN CLOSE GRADIENT TOPHAT BLACKHAT - - :param kernel: The structuring element used for dilation. If element=Mat(), a 3times 3 rectangular structuring element is used - - :param anchor: Position of the anchor within the element. The default value (-1, -1) means that the anchor is at the element center, only default value is supported - - :param iterations: The number of times dilation is applied - - :param bordertype: Pixel extrapolation method. - - :param value: The border value if borderType==BORDER CONSTANT - -A wrapper for erode and dilate. Supports 8UC1 8UC4 data types. - -ocl::pyrDown -------------------- -Smoothes an image and downsamples it. - -.. ocv:function:: void ocl::pyrDown(const oclMat& src, oclMat& dst) - - :param src: Source image. - - :param dst: Destination image. Will have ``Size((src.cols+1)/2, (src.rows+1)/2)`` size and the same type as ``src`` . - -.. seealso:: :ocv:func:`pyrDown` - - -ocl::pyrUp -------------------- -Upsamples an image and then smoothes it. - -.. ocv:function:: void ocl::pyrUp(const oclMat& src, oclMat& dst) - - :param src: Source image. - - :param dst: Destination image. Will have ``Size(src.cols*2, src.rows*2)`` size and the same type as ``src`` . - -.. seealso:: :ocv:func:`pyrUp` - -ocl::columnSum ------------------- -Computes a vertical (column) sum. - -.. ocv:function:: void ocl::columnSum(const oclMat& src, oclMat& sum) - - :param src: Source image. Only ``CV_32FC1`` images are supported for now. - - :param sum: Destination image of the ``CV_32FC1`` type. - - -ocl::blendLinear --------------------- -Performs linear blending of two images. - -.. ocv:function:: void ocl::blendLinear(const oclMat& img1, const oclMat& img2, const oclMat& weights1, const oclMat& weights2, oclMat& result) - - :param img1: First image. Supports only ``CV_8U`` and ``CV_32F`` depth. - - :param img2: Second image. Must have the same size and the same type as ``img1`` . - - :param weights1: Weights for first image. Must have tha same size as ``img1`` . Supports only ``CV_32F`` type. - - :param weights2: Weights for second image. Must have tha same size as ``img2`` . Supports only ``CV_32F`` type. - - :param result: Destination image. - -ocl::medianFilter --------------------- -Blurs an image using the median filter. - -.. ocv:function:: void ocl::medianFilter(const oclMat &src, oclMat &dst, int m) - - :param src: input ```1-``` or ```4```-channel image; the image depth should be ```CV_8U```, ```CV_32F```. - - :param dst: destination array of the same size and type as ```src```. - - :param m: aperture linear size; it must be odd and greater than ```1```. Currently only ```3```, ```5``` are supported. - -The function smoothes an image using the median filter with the \texttt{m} \times \texttt{m} aperture. Each channel of a multi-channel image is processed independently. In-place operation is supported. diff --git a/modules/ocl/doc/image_processing.rst b/modules/ocl/doc/image_processing.rst deleted file mode 100644 index 959c97f9e..000000000 --- a/modules/ocl/doc/image_processing.rst +++ /dev/null @@ -1,347 +0,0 @@ -Image Processing -============================= - -.. highlight:: cpp - -ocl::meanShiftFiltering ---------------------------- -Performs mean-shift filtering for each point of the source image. - -.. ocv:function:: void ocl::meanShiftFiltering(const oclMat &src, oclMat &dst, int sp, int sr, TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1)) - - :param src: Source image. Only ``CV_8UC4`` images are supported for now. - - :param dst: Destination image containing the color of mapped points. It has the same size and type as ``src`` . - - :param sp: Spatial window radius. - - :param sr: Color window radius. - - :param criteria: Termination criteria. See :ocv:class:`TermCriteria`. - -It maps each point of the source image into another point. As a result, you have a new color and new position of each point. - - -ocl::meanShiftProc ----------------------- -Performs a mean-shift procedure and stores information about processed points (their colors and positions) in two images. - -.. ocv:function:: void ocl::meanShiftProc(const oclMat &src, oclMat &dstr, oclMat &dstsp, int sp, int sr, TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1)) - - :param src: Source image. Only ``CV_8UC4`` images are supported for now. - - :param dstr: Destination image containing the color of mapped points. The size and type is the same as ``src`` . - - :param dstsp: Destination image containing the position of mapped points. The size is the same as ``src`` size. The type is ``CV_16SC2`` . - - :param sp: Spatial window radius. - - :param sr: Color window radius. - - :param criteria: Termination criteria. See :ocv:class:`TermCriteria`. - -.. seealso:: :ocv:func:`ocl::meanShiftFiltering` - - -ocl::meanShiftSegmentation ------------------------------- -Performs a mean-shift segmentation of the source image and eliminates small segments. - -.. ocv:function:: void ocl::meanShiftSegmentation(const oclMat &src, Mat &dst, int sp, int sr, int minsize, TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1)) - - :param src: Source image. Only ``CV_8UC4`` images are supported for now. - - :param dst: Segmented image with the same size and type as ``src`` . - - :param sp: Spatial window radius. - - :param sr: Color window radius. - - :param minsize: Minimum segment size. Smaller segments are merged. - - :param criteria: Termination criteria. See :ocv:class:`TermCriteria`. - -ocl::integral ------------------ -Computes an integral image. - -.. ocv:function:: void ocl::integral(const oclMat &src, oclMat &sum, oclMat &sqsum, int sdepth=-1) - -.. ocv:function:: void ocl::integral(const oclMat &src, oclMat &sum, int sdepth=-1) - - :param src: Source image. Only ``CV_8UC1`` images are supported for now. - - :param sum: Integral image containing 32-bit unsigned integer or 32-bit floating-point . - - :param sqsum: Sqsum values is ``CV_32FC1`` or ``CV_64FC1`` type. - -.. seealso:: :ocv:func:`integral` - -ocl::cornerHarris ---------------------- -Returns void - -.. ocv:function:: void ocl::cornerHarris(const oclMat &src, oclMat &dst, int blockSize, int ksize, double k, int bordertype = cv::BORDER_DEFAULT) - - :param src: Source image. Only CV_8UC1 and CV_32FC1 images are supported now. - - :param dst: Destination image containing cornerness values. It has the same size as src and CV_32FC1 type. - - :param blockSize: Neighborhood size - - :param ksize: Aperture parameter for the Sobel operator - - :param k: Harris detector free parameter - - :param bordertype: Pixel extrapolation method. Only BORDER_REFLECT101, BORDER_REFLECT, BORDER_CONSTANT and BORDER_REPLICATE are supported now. - -Calculate Harris corner. - -ocl::cornerMinEigenVal --------------------------- -Returns void - -.. ocv:function:: void ocl::cornerMinEigenVal(const oclMat &src, oclMat &dst, int blockSize, int ksize, int bordertype = cv::BORDER_DEFAULT) - - :param src: Source image. Only CV_8UC1 and CV_32FC1 images are supported now. - - :param dst: Destination image containing cornerness values. It has the same size as src and CV_32FC1 type. - - :param blockSize: Neighborhood size - - :param ksize: Aperture parameter for the Sobel operator - - :param bordertype: Pixel extrapolation method. Only BORDER_REFLECT101, BORDER_REFLECT, BORDER_CONSTANT and BORDER_REPLICATE are supported now. - -Calculate MinEigenVal. - -ocl::calcHist ------------------- -Returns void - -.. ocv:function:: void ocl::calcHist(const oclMat &mat_src, oclMat &mat_hist) - - :param src: Source arrays. They all should have the same depth, CV 8U, and the same size. Each of them can have an arbitrary number of channels. - - :param dst: The output histogram, a dense or sparse dims-dimensional - -Calculates histogram of one or more arrays. Supports only 8UC1 data type. - -ocl::equalizeHist ---------------------- -Equalizes the histogram of a grayscale image. - -.. ocv:function:: void ocl::equalizeHist(const oclMat &mat_src, oclMat &mat_dst) - - :param mat_src: Source image. - - :param mat_dst: Destination image. - -.. seealso:: :ocv:func:`equalizeHist` - - -ocl::remap ------------------- -Returns void - -.. ocv:function:: void ocl::remap(const oclMat &src, oclMat &dst, oclMat &map1, oclMat &map2, int interpolation, int bordertype, const Scalar &value = Scalar()) - - :param src: Source image. - - :param dst: Destination image containing cornerness values. It has the same size as src and CV_32FC1 type. - - :param map1: The first map of either (x,y) points or just x values having the type CV_16SC2 , CV_32FC1 , or CV_32FC2 . See covertMaps() for details on converting a floating point representation to fixed-point for speed. - - :param map2: The second map of y values having the type CV_32FC1 , or none (empty map if map1 is (x,y) points), respectively. - - :param interpolation: The interpolation method - - :param bordertype: Pixel extrapolation method. - - :param value: The border value if borderType==BORDER CONSTANT - -The function remap transforms the source image using the specified map: dst (x ,y) = src (map1(x , y) , map2(x , y)) where values of pixels with non-integer coordinates are computed using one of available interpolation methods. map1 and map2 can be encoded as separate floating-point maps in map1 and map2 respectively, or interleaved floating-point maps of (x,y) in map1. - -ocl::resize ------------------- -Returns void - -.. ocv:function:: void ocl::resize(const oclMat &src, oclMat &dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR) - - :param src: Source image. - - :param dst: Destination image. - - :param dsize: he destination image size. If it is zero, then it is computed as: dsize = Size(round(fx*src.cols), round(fy*src.rows)). Either dsize or both fx or fy must be non-zero. - - :param fx: The scale factor along the horizontal axis. When 0, it is computed as (double)dsize.width/src.cols - - :param fy: The scale factor along the vertical axis. When 0, it is computed as (double)dsize.height/src.rows - - :param interpolation: The interpolation method: INTER NEAREST or INTER LINEAR - -Resizes an image. Supports CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1 , CV_32FC3 and CV_32FC4 data types. - -ocl::warpAffine -------------------- -Returns void - -.. ocv:function:: void ocl::warpAffine(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags = INTER_LINEAR) - - :param src: Source image. - - :param dst: Destination image. - - :param M: 2times 3 transformation matrix - - :param dsize: Size of the destination image - - :param flags: A combination of interpolation methods, see cv::resize, and the optional flag WARP INVERSE MAP that means that M is the inverse transformation (dst to $src) - -The function warpAffine transforms the source image using the specified matrix. Supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC types. - -ocl::warpPerspective ------------------------- -Returns void - -.. ocv:function:: void ocl::warpPerspective(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags = INTER_LINEAR) - - :param src: Source image. - - :param dst: Destination image. - - :param M: 2times 3 transformation matrix - - :param dsize: Size of the destination image - - :param flags: A combination of interpolation methods, see cv::resize, and the optional flag WARP INVERSE MAP that means that M is the inverse transformation (dst to $src) - -Applies a perspective transformation to an image. Supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC types. - -ocl::cvtColor ------------------- -Returns void - -.. ocv:function:: void ocl::cvtColor(const oclMat &src, oclMat &dst, int code, int dcn = 0) - - :param src: Source image. - - :param dst: Destination image. - - :param code:The color space conversion code - - :param dcn: The number of channels in the destination image; if the parameter is 0, the number of the channels will be derived automatically from src and the code - -Converts image from one color space to another.For now, only RGB2GRAY is supportted. Supports.CV_8UC1,CV_8UC4,CV_32SC1,CV_32SC4,CV_32FC1,CV_32FC4 - -ocl::threshold ------------------- -Returns Threshold value - -.. ocv:function:: double ocl::threshold(const oclMat &src, oclMat &dst, double thresh, double maxVal, int type = THRESH_TRUNC) - - :param src: The source array - - :param dst: Destination array; will have the same size and the same type as src - - :param thresh: Threshold value - - :param maxVal: Maximum value to use with THRESH BINARY and THRESH BINARY INV thresholding types - - :param type: Thresholding type - -The function applies fixed-level thresholding to a single-channel array. The function is typically used to get a bi-level (binary) image out of a grayscale image or for removing a noise, i.e. filtering out pixels with too small or too large values. There are several types of thresholding that the function supports that are determined by thresholdType. - -ocl::buildWarpPlaneMaps ------------------------ -Builds plane warping maps. - -.. ocv:function:: void ocl::buildWarpPlaneMaps( Size src_size, Rect dst_roi, const Mat& K, const Mat& R, const Mat& T, float scale, oclMat& map_x, oclMat& map_y ) - - - -ocl::buildWarpCylindricalMaps ------------------------------ -Builds cylindrical warping maps. - -.. ocv:function:: void ocl::buildWarpCylindricalMaps( Size src_size, Rect dst_roi, const Mat& K, const Mat& R, float scale, oclMat& map_x, oclMat& map_y ) - - - - -ocl::buildWarpSphericalMaps ---------------------------- -Builds spherical warping maps. - -.. ocv:function:: void ocl::buildWarpSphericalMaps( Size src_size, Rect dst_roi, const Mat& K, const Mat& R, float scale, oclMat& map_x, oclMat& map_y ) - - -ocl::buildWarpPerspectiveMaps ------------------------------ -Builds transformation maps for perspective transformation. - -.. ocv:function:: void ocl::buildWarpAffineMaps(const Mat& M, bool inverse, Size dsize, oclMat& xmap, oclMat& ymap) - - :param M: *3x3* transformation matrix. - - :param inverse: Flag specifying that ``M`` is an inverse transformation ( ``dst=>src`` ). - - :param dsize: Size of the destination image. - - :param xmap: X values with ``CV_32FC1`` type. - - :param ymap: Y values with ``CV_32FC1`` type. - -.. seealso:: :ocv:func:`ocl::warpPerspective` , :ocv:func:`ocl::remap` - - -ocl::buildWarpAffineMaps ----------------------------- -Builds transformation maps for affine transformation. - -.. ocv:function:: void ocl::buildWarpAffineMaps(const Mat& M, bool inverse, Size dsize, oclMat& xmap, oclMat& ymap) - - :param M: *2x3* transformation matrix. - - :param inverse: Flag specifying that ``M`` is an inverse transformation ( ``dst=>src`` ). - - :param dsize: Size of the destination image. - - :param xmap: X values with ``CV_32FC1`` type. - - :param ymap: Y values with ``CV_32FC1`` type. - -.. seealso:: :ocv:func:`ocl::warpAffine` , :ocv:func:`ocl::remap` - -ocl::HoughCircles ------------------ -Finds circles in a grayscale image using the Hough transform. - -.. ocv:function:: void ocl::HoughCircles(const oclMat& src, oclMat& circles, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096) - -.. ocv:function:: void ocl::HoughCircles(const oclMat& src, oclMat& circles, HoughCirclesBuf& buf, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096) - - :param src: 8-bit, single-channel grayscale input image. - - :param circles: Output vector of found circles. Each vector is encoded as a 3-element floating-point vector :math:`(x, y, radius)` . - - :param method: Detection method to use. Currently, the only implemented method is ``CV_HOUGH_GRADIENT`` , which is basically *21HT* , described in [Yuen90]_. - - :param dp: Inverse ratio of the accumulator resolution to the image resolution. For example, if ``dp=1`` , the accumulator has the same resolution as the input image. If ``dp=2`` , the accumulator has half as big width and height. - - :param minDist: Minimum distance between the centers of the detected circles. If the parameter is too small, multiple neighbor circles may be falsely detected in addition to a true one. If it is too large, some circles may be missed. - - :param cannyThreshold: The higher threshold of the two passed to the :ocv:func:`ocl::Canny` edge detector (the lower one is twice smaller). - - :param votesThreshold: The accumulator threshold for the circle centers at the detection stage. The smaller it is, the more false circles may be detected. - - :param minRadius: Minimum circle radius. - - :param maxRadius: Maximum circle radius. - - :param maxCircles: Maximum number of output circles. - - :param buf: Optional buffer to avoid extra memory allocations (for many calls with the same sizes). - -.. note:: Currently only non-ROI oclMat is supported for src. -.. seealso:: :ocv:func:`HoughCircles` diff --git a/modules/ocl/doc/images/adaptiveBilateralFilter.jpg b/modules/ocl/doc/images/adaptiveBilateralFilter.jpg deleted file mode 100644 index 6508f693c38542868f5b2b08c7cadc8ec2bc915e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65410 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 z 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 diff --git a/modules/ocl/doc/introduction.rst b/modules/ocl/doc/introduction.rst deleted file mode 100644 index 2c050cb27..000000000 --- a/modules/ocl/doc/introduction.rst +++ /dev/null @@ -1,73 +0,0 @@ -OpenCL Module Introduction -========================== - -.. highlight:: cpp - -General Information -------------------- - -The OpenCV OCL module contains a set of classes and functions that implement and accelerate OpenCV functionality on OpenCL compatible devices. OpenCL is a Khronos standard, implemented by a variety of devices (CPUs, GPUs, FPGAs, ARM), abstracting the exact hardware details, while enabling vendors to provide native implementation for maximal acceleration on their hardware. The standard enjoys wide industry support, and the end user of the module will enjoy the data parallelism benefits that the specific platform/hardware may be capable of, in a platform/hardware independent manner. - -While in the future we hope to validate (and enable) the OCL module in all OpenCL capable devices, we currently develop and test on GPU devices only. This includes both discrete GPUs (NVidia, AMD), as well as integrated chips (AMD APU and Intel HD devices). Performance of any particular algorithm will depend on the particular platform characteristics and capabilities. However, currently, accuracy and mathematical correctness has been verified to be identical to that of the pure CPU implementation on all tested GPU devices and platforms (both Windows and Linux). - - -The OpenCV OCL module includes utility functions, low-level vision primitives, and high-level algorithms. The utility functions and low-level primitives provide a powerful infrastructure for developing fast vision algorithms taking advantage of OCL, whereas the high-level functionality (samples) includes some state-of-the-art algorithms (including LK Optical flow, and Face detection) ready to be used by the application developers. The module is also accompanied by an extensive performance and accuracy test suite. - -The OpenCV OCL module is designed for ease of use and does not require any knowledge of OpenCL. At a minimum level, it can be viewed as a set of accelerators, that can take advantage of the high compute throughput that GPU/APU devices can provide. However, it can also be viewed as a starting point to really integrate the built-in functionality with your own custom OpenCL kernels, with or without modifying the source of OpenCV-OCL. Of course, knowledge of OpenCL will certainly help, however we hope that OpenCV-OCL module, and the kernels it contains in source code, can be very useful as a means of actually learning openCL. Such a knowledge would be necessary to further fine-tune any of the existing OpenCL kernels, or for extending the framework with new kernels. As of OpenCV 2.4.4, we introduce interoperability with OpenCL, enabling easy use of custom OpenCL kernels within the OpenCV framework. - -To correctly run the OCL module, you need to have the OpenCL runtime provided by the device vendor, typically the device driver. - -To enable OCL support, configure OpenCV using CMake with ``WITH_OPENCL=ON``. When the flag is set and if OpenCL SDK is installed, the full-featured OpenCV OCL module is built. Otherwise, the module may be not built. If you have AMD'S FFT and BLAS library, you can select it with ``WITH_OPENCLAMDFFT=ON``, ``WITH_OPENCLAMDBLAS=ON``. - -The ocl module can be found under the "modules" directory. In "modules/ocl/src" you can find the source code for the cpp class that wrap around the direct kernel invocation. The kernels themselves can be found in "modules/ocl/src/opencl". Samples can be found under "samples/ocl". Accuracy tests can be found in "modules/ocl/test", and performance tests under "module/ocl/perf". - - - -Right now, the user can select OpenCL device by specifying the environment variable ``OPENCV_OPENCL_DEVICE``. Variable format: - -.. code-block:: cpp - - :: - -**Note:** Device ID range is: 0..9 (only one digit, 10 - it is a part of name) - -Samples: - -.. code-block:: cpp - - '' = ':' = '::' = ':GPU|CPU:' - 'AMD:GPU|CPU:' - 'AMD::Tahiti' - ':GPU:1' - ':CPU:2' - -Also the user can use ``cv::ocl::setDevice`` function (with ``cv::ocl::getOpenCLPlatforms`` and ``cv::ocl::getOpenCLDevices``). This function initializes OpenCL runtime and setup the passed device as computing device. - -In the current version, all the thread share the same context and device so the multi-devices are not supported. We will add this feature soon. If a function support 4-channel operator, it should support 3-channel operator as well, because All the 3-channel matrix(i.e. RGB image) are represented by 4-channel matrix in ``oclMat``. It means 3-channel image have 4-channel space with the last channel unused. We provide a transparent interface to handle the difference between OpenCV Mat and ``oclMat``. - -Developer Notes -------------------- - -In a heterogeneous device environment, there may be cost associated with data transfer. This would be the case, for example, when data needs to be moved from host memory (accessible to the CPU), to device memory (accessible to a discrete GPU). in the case of integrated graphics chips, there may be performance issues, relating to memory coherency between access from the GPU "part" of the integrated device, or the CPU "part." For best performance, in either case, it is recommended that you do not introduce data transfers between CPU and the discrete GPU, except in the beginning and the end of the algorithmic pipeline. - -Some tidbits: - -1. OpenCL version should be larger than 1.1 with FULL PROFILE. - -2. Currently there's only one OpenCL context and command queue. We hope to implement multi device and multi queue support in the future. - -3. Many kernels use 256 as its workgroup size if possible, so the max work group size of the device must larger than 256. All GPU devices we are aware of indeed support 256 workitems in a workgroup, however non GPU devices may not. This will be improved in the future. - -4. If the device does not support double arithmetic, then functions' implementation generates an error. - -5. The ``oclMat`` uses buffer object, not image object. - -6. All the 3-channel matrices (i.e. RGB image) are represented by 4-channel matrices in ``oclMat``, with the last channel unused. We provide a transparent interface to handle the difference between OpenCV Mat and ``oclMat``. - -7. All the matrix in ``oclMat`` is aligned in column (now the alignment factor for ``step`` is 32+ byte). It means, m.cols * m.elemSize() <= m.step. - -8. Data transfer between Mat and ``oclMat``: If the CPU matrix is aligned in column, we will use faster API to transfer between Mat and ``oclMat``, otherwise, we will use clEnqueueRead/WriteBufferRect to transfer data to guarantee the alignment. 3-channel matrix is an exception, it's directly transferred to a temp buffer and then padded to 4-channel matrix(also aligned) when uploading and do the reverse operation when downloading. - -9. Data transfer between Mat and ``oclMat``: ROI is a feature of OpenCV, which allow users process a sub rectangle of a matrix. When a CPU matrix which has ROI will be transfered to GPU, the whole matrix will be transfered and set ROI as CPU's. In a word, we always transfer the whole matrix despite whether it has ROI or not. - -10. All the kernel file should locate in "modules/ocl/src/opencl/" with the extension ".cl". All the kernel files are transformed to pure characters at compilation time in opencl_kernels.cpp, and the file name without extension is the name of the program sources. diff --git a/modules/ocl/doc/matrix_reductions.rst b/modules/ocl/doc/matrix_reductions.rst deleted file mode 100644 index 41161d8aa..000000000 --- a/modules/ocl/doc/matrix_reductions.rst +++ /dev/null @@ -1,106 +0,0 @@ -Matrix Reductions -============================= - -.. highlight:: cpp - -ocl::absSum ---------------- -Returns the sum of absolute values for matrix elements. - -.. ocv:function:: Scalar ocl::absSum(const oclMat &m) - - :param m: The Source image of all depth. - -Counts the abs sum of matrix elements for each channel. Supports all data types. - -ocl::countNonZero ---------------------- -Returns the number of non-zero elements in src - -.. ocv:function:: int ocl::countNonZero(const oclMat &src) - - :param src: Single-channel array - -Counts non-zero array elements. Supports all data types. - -ocl::min ------------------- - -.. ocv:function:: void ocl::min(const oclMat &src1, const oclMat &src2, oclMat &dst) - - :param src1: the first input array. - - :param src2: the second input array, must be the same size and same type as ``src1``. - - :param dst: the destination array, it will have the same size and same type as ``src1``. - -Computes element-wise minima of two arrays. Supports all data types. - -ocl::max ------------------- - -.. ocv:function:: void ocl::max(const oclMat &src1, const oclMat &src2, oclMat &dst) - - :param src1: the first input array. - - :param src2: the second input array, must be the same size and same type as ``src1``. - - :param dst: the destination array, it will have the same size and same type as ``src1``. - -Computes element-wise maxima of two arrays. Supports all data types. - -ocl::minMax ------------------- -Returns void - -.. ocv:function:: void ocl::minMax(const oclMat &src, double *minVal, double *maxVal = 0, const oclMat &mask = oclMat()) - - :param src: Single-channel array - - :param minVal: Pointer to returned minimum value, should not be NULL - - :param maxVal: Pointer to returned maximum value, should not be NULL - - :param mask: The optional mask used to select a sub-array - -Finds global minimum and maximum in a whole array or sub-array. Supports all data types. - -ocl::minMaxLoc ------------------- -Returns void - -.. ocv:function:: void ocl::minMaxLoc(const oclMat &src, double *minVal, double *maxVal = 0, Point *minLoc = 0, Point *maxLoc = 0,const oclMat &mask = oclMat()) - - :param src: Single-channel array - - :param minVal: Pointer to returned minimum value, should not be NULL - - :param maxVal: Pointer to returned maximum value, should not be NULL - - :param minLoc: Pointer to returned minimum location (in 2D case), should not be NULL - - :param maxLoc: Pointer to returned maximum location (in 2D case) should not be NULL - - :param mask: The optional mask used to select a sub-array - -The functions minMaxLoc find minimum and maximum element values and their positions. The extremums are searched across the whole array, or, if mask is not an empty array, in the specified array region. The functions do not work with multi-channel arrays. - -ocl::sqrSum ------------------- -Returns the squared sum of matrix elements for each channel - -.. ocv:function:: Scalar ocl::sqrSum(const oclMat &m) - - :param m: The Source image of all depth. - -Counts the squared sum of matrix elements for each channel. Supports all data types. - -ocl::sum ------------------- -Returns the sum of matrix elements for each channel - -.. ocv:function:: Scalar ocl::sum(const oclMat &m) - - :param m: The Source image of all depth. - -Counts the sum of matrix elements for each channel. diff --git a/modules/ocl/doc/ml_machine_learning.rst b/modules/ocl/doc/ml_machine_learning.rst deleted file mode 100644 index ad0e30397..000000000 --- a/modules/ocl/doc/ml_machine_learning.rst +++ /dev/null @@ -1,106 +0,0 @@ -ml.Machine Learning -============================= - -.. highlight:: cpp - -ocl::KNearestNeighbour --------------------------- -.. ocv:class:: ocl::KNearestNeighbour : public ocl::CvKNearest - -The class implements K-Nearest Neighbors model as described in the beginning of this section. - -ocl::KNearestNeighbour --------------------------- -Computes the weighted sum of two arrays. :: - - class CV_EXPORTS KNearestNeighbour: public CvKNearest - { - public: - KNearestNeighbour(); - ~KNearestNeighbour(); - - bool train(const Mat& trainData, Mat& labels, Mat& sampleIdx = Mat().setTo(Scalar::all(0)), - bool isRegression = false, int max_k = 32, bool updateBase = false); - - void clear(); - - void find_nearest(const oclMat& samples, int k, oclMat& lables); - - private: - /* hidden */ - }; - -ocl::KNearestNeighbour::train ---------------------------------- -Trains the model. - -.. ocv:function:: bool ocl::KNearestNeighbour::train(const Mat& trainData, Mat& labels, Mat& sampleIdx = Mat().setTo(Scalar::all(0)), bool isRegression = false, int max_k = 32, bool updateBase = false) - - :param isRegression: Type of the problem: ``true`` for regression and ``false`` for classification. - - :param maxK: Number of maximum neighbors that may be passed to the method :ocv:func:`CvKNearest::find_nearest`. - - :param updateBase: Specifies whether the model is trained from scratch (``update_base=false``), or it is updated using the new training data (``update_base=true``). In the latter case, the parameter ``maxK`` must not be larger than the original value. - -The method trains the K-Nearest model. It follows the conventions of the generic :ocv:func:`CvStatModel::train` approach with the following limitations: - -* Only ``CV_ROW_SAMPLE`` data layout is supported. -* Input variables are all ordered. -* Output variables can be either categorical ( ``is_regression=false`` ) or ordered ( ``is_regression=true`` ). -* Variable subsets (``var_idx``) and missing measurements are not supported. - -ocl::KNearestNeighbour::find_nearest ----------------------------------------- -Finds the neighbors and predicts responses for input vectors. - -.. ocv:function:: void ocl::KNearestNeighbour::find_nearest(const oclMat& samples, int k, oclMat& lables ) - - :param samples: Input samples stored by rows. It is a single-precision floating-point matrix of :math:`number\_of\_samples \times number\_of\_features` size. - - :param k: Number of used nearest neighbors. It must satisfy constraint: :math:`k \le` :ocv:func:`CvKNearest::get_max_k`. - - :param labels: Vector with results of prediction (regression or classification) for each input sample. It is a single-precision floating-point vector with ``number_of_samples`` elements. - -ocl::kmeans ---------------- -Finds centers of clusters and groups input samples around the clusters. - -.. ocv:function:: double ocl::kmeans(const oclMat &src, int K, oclMat &bestLabels, TermCriteria criteria, int attemps, int flags, oclMat ¢ers) - - :param src: Floating-point matrix of input samples, one row per sample. - - :param K: Number of clusters to split the set by. - - :param bestLabels: Input/output integer array that stores the cluster indices for every sample. - - :param criteria: The algorithm termination criteria, that is, the maximum number of iterations and/or the desired accuracy. The accuracy is specified as ``criteria.epsilon``. As soon as each of the cluster centers moves by less than ``criteria.epsilon`` on some iteration, the algorithm stops. - - :param attempts: Flag to specify the number of times the algorithm is executed using different initial labellings. The algorithm returns the labels that yield the best compactness (see the last function parameter). - - :param flags: Flag that can take the following values: - - * **KMEANS_RANDOM_CENTERS** Select random initial centers in each attempt. - - * **KMEANS_PP_CENTERS** Use ``kmeans++`` center initialization by Arthur and Vassilvitskii [Arthur2007]. - - * **KMEANS_USE_INITIAL_LABELS** During the first (and possibly the only) attempt, use the user-supplied labels instead of computing them from the initial centers. For the second and further attempts, use the random or semi-random centers. Use one of ``KMEANS_*_CENTERS`` flag to specify the exact method. - - :param centers: Output matrix of the cluster centers, one row per each cluster center. - -ocl::distanceToCenters ----------------------- -For each samples in ``source``, find its closest neighour in ``centers``. - -.. ocv:function:: void ocl::distanceToCenters(const oclMat &src, const oclMat ¢ers, Mat &dists, Mat &labels, int distType = NORM_L2SQR) - - :param src: Floating-point matrix of input samples. One row per sample. - - :param centers: Floating-point matrix of center candidates. One row per center. - - :param distType: Distance metric to calculate distances. Supports ``NORM_L1`` and ``NORM_L2SQR``. - - :param dists: The output distances calculated from each sample to the best matched center. - - :param labels: The output index of best matched center for each row of sample. - -The method is a utility function which maybe used for multiple clustering algorithms such as K-means. diff --git a/modules/ocl/doc/object_detection.rst b/modules/ocl/doc/object_detection.rst deleted file mode 100644 index 0539e7738..000000000 --- a/modules/ocl/doc/object_detection.rst +++ /dev/null @@ -1,95 +0,0 @@ -Object Detection -============================= - -.. highlight:: cpp - -ocl::OclCascadeClassifier ------------------------------ -.. ocv:class:: ocl::OclCascadeClassifier : public CascadeClassifier - -Cascade classifier class used for object detection. Supports HAAR cascade classifier in the form of cross link :: - - class CV_EXPORTS OclCascadeClassifier : public CascadeClassifier - { - public: - void detectMultiScale(oclMat &image, CV_OUT std::vector& faces, - double scaleFactor = 1.1, int minNeighbors = 3, int flags = 0, - Size minSize = Size(), Size maxSize = Size()); - }; - -.. note:: - - (Ocl) A face detection example using cascade classifiers can be found at opencv_source_code/samples/ocl/facedetect.cpp - -ocl::OclCascadeClassifier::detectMultiScale ------------------------------------------------------- -Detects objects of different sizes in the input image. - -.. ocv:function:: void ocl::OclCascadeClassifier::detectMultiScale(oclMat &image, std::vector& faces, double scaleFactor = 1.1, int minNeighbors = 3, int flags = 0, Size minSize = Size(), Size maxSize = Size()) - - :param faces: Vector of rectangles where each rectangle contains the detected object. - - :param image: Matrix of type CV_8U containing an image where objects should be detected. - - :param scaleFactor: Parameter specifying how much the image size is reduced at each image scale. - - :param minNeighbors: Parameter specifying how many neighbors each candidate rectangle should have to retain it. - - :param flags: Parameter with the same meaning for an old cascade as in the function ``cvHaarDetectObjects``. It is not used for a new cascade. - - :param minSize: Minimum possible object size. Objects smaller than that are ignored. - - :param maxSize: Maximum possible object size. Objects larger than that are ignored. - -The function provides a very similar interface with that in CascadeClassifier class, except using oclMat as input image. - -ocl::MatchTemplateBuf -------------------------- -.. ocv:struct:: ocl::MatchTemplateBuf - -Class providing memory buffers for :ocv:func:`ocl::matchTemplate` function, plus it allows to adjust some specific parameters. :: - - struct CV_EXPORTS MatchTemplateBuf - { - Size user_block_size; - oclMat imagef, templf; - std::vector images; - std::vector image_sums; - std::vector image_sqsums; - }; - -You can use field `user_block_size` to set specific block size for :ocv:func:`ocl::matchTemplate` function. If you leave its default value `Size(0,0)` then automatic estimation of block size will be used (which is optimized for speed). By varying `user_block_size` you can reduce memory requirements at the cost of speed. - -ocl::matchTemplate ----------------------- -Computes a proximity map for a raster template and an image where the template is searched for. - -.. ocv:function:: void ocl::matchTemplate(const oclMat& image, const oclMat& templ, oclMat& result, int method) - -.. ocv:function:: void ocl::matchTemplate(const oclMat& image, const oclMat& templ, oclMat& result, int method, MatchTemplateBuf &buf) - - :param image: Source image. ``CV_32F`` and ``CV_8U`` depth images (1..4 channels) are supported for now. - - :param templ: Template image with the size and type the same as ``image`` . - - :param result: Map containing comparison results ( ``CV_32FC1`` ). If ``image`` is *W x H* and ``templ`` is *w x h*, then ``result`` must be *W-w+1 x H-h+1*. - - :param method: Specifies the way to compare the template with the image. - - :param buf: Optional buffer to avoid extra memory allocations and to adjust some specific parameters. See :ocv:struct:`ocl::MatchTemplateBuf`. - - The following methods are supported for the ``CV_8U`` depth images for now: - - * ``CV_TM_SQDIFF`` - * ``CV_TM_SQDIFF_NORMED`` - * ``CV_TM_CCORR`` - * ``CV_TM_CCORR_NORMED`` - * ``CV_TM_CCOEFF`` - * ``CV_TM_CCOEFF_NORMED`` - - The following methods are supported for the ``CV_32F`` images for now: - - * ``CV_TM_SQDIFF`` - * ``CV_TM_CCORR`` - -.. seealso:: :ocv:func:`matchTemplate` diff --git a/modules/ocl/doc/ocl.rst b/modules/ocl/doc/ocl.rst deleted file mode 100644 index 76c1f882b..000000000 --- a/modules/ocl/doc/ocl.rst +++ /dev/null @@ -1,21 +0,0 @@ -*************************************** -ocl. OpenCL-accelerated Computer Vision -*************************************** - -.. toctree:: - :maxdepth: 1 - - introduction - structures_and_utility_functions - data_structures - operations_on_matrices - matrix_reductions - image_filtering - image_processing - ml_machine_learning - object_detection - feature_detection_and_description - video_analysis - camera_calibration_and_3D_reconstruction -.. camera_calibration_and_3d_reconstruction -.. video diff --git a/modules/ocl/doc/operations_on_matrices.rst b/modules/ocl/doc/operations_on_matrices.rst deleted file mode 100644 index 1763d33d1..000000000 --- a/modules/ocl/doc/operations_on_matrices.rst +++ /dev/null @@ -1,602 +0,0 @@ -Operations on Matrics -============================= - -.. highlight:: cpp - -ocl::abs ------------------- -Returns void - -.. ocv:function:: void ocl::abs(const oclMat& src, oclMat& dst) - - :param src: input array. - - :param dst: destination array, it will have the same size and same type as ``src``. - -Computes per-element absolute values of the input array. Supports all data types. - -ocl::absdiff ------------------- -Returns void - -.. ocv:function:: void ocl::absdiff(const oclMat& src1, const oclMat& src2, oclMat& dst) - -.. ocv:function:: void ocl::absdiff(const oclMat& src1, const Scalar& s, oclMat& dst) - - :param src1: the first input array. - - :param src2: the second input array, must be the same size and same type as ``src1``. - - :param s: scalar, the second input parameter. - - :param dst: the destination array, it will have the same size and same type as ``src1``. - -Computes per-element absolute difference between two arrays or between array and a scalar. Supports all data types. - -ocl::add ------------------- -Returns void - -.. ocv:function:: void ocl::add(const oclMat & src1, const oclMat & src2, oclMat & dst, const oclMat & mask = oclMat()) - -.. ocv:function:: void ocl::add(const oclMat & src1, const Scalar & s, oclMat & dst, const oclMat & mask = oclMat()) - - :param src1: the first input array. - - :param src2: the second input array, must be the same size and same type as ``src1``. - - :param s: scalar, the second input parameter - - :param dst: the destination array, it will have the same size and same type as ``src1``. - - :param mask: the optional operation mask, 8-bit single channel array; specifies elements of the destination array to be changed. - -Computes per-element additon between two arrays or between array and a scalar. Supports all data types. - -ocl::addWeighted --------------------- -Computes the weighted sum of two arrays. - -.. ocv:function:: void ocl::addWeighted(const oclMat& src1, double alpha, const oclMat& src2, double beta, double gama, oclMat& dst) - - :param src1: First source array. - - :param alpha: Weight for the first array elements. - - :param src2: Second source array of the same size and channel number as ``src1`` . - - :param beta: Weight for the second array elements. - - :param dst: Destination array that has the same size and number of channels as the input arrays. - - :param gamma: Scalar added to each sum. - -The function ``addWeighted`` calculates the weighted sum of two arrays as follows: - -.. math:: - - \texttt{c} (I)= \texttt{saturate} ( \texttt{a} (I)* \texttt{alpha} + \texttt{b} (I)* \texttt{beta} + \texttt{gamma} ) - -where ``I`` is a multi-dimensional index of array elements. In case of multi-channel arrays, each channel is processed independently. - -.. seealso:: :ocv:func:`addWeighted` - -ocl::bitwise_and ------------------- -Returns void - -.. ocv:function:: void ocl::bitwise_and(const oclMat& src1, const oclMat& src2, oclMat& dst, const oclMat& mask = oclMat()) - -.. ocv:function:: void ocl::bitwise_and(const oclMat& src1, const Scalar& s, oclMat& dst, const oclMat& mask = oclMat()) - - :param src1: the first input array. - - :param src2: the second input array, must be the same size and same type as ``src1``. - - :param s: scalar, the second input parameter. - - :param dst: the destination array, it will have the same size and same type as ``src1``. - - :param mask: the optional operation mask, 8-bit single channel array; specifies elements of the destination array to be changed. - -Computes per-element bitwise_and between two arrays or between array and a scalar. Supports all data types. - -ocl::bitwise_not ------------------- -Returns void - -.. ocv:function:: void ocl::bitwise_not(const oclMat &src, oclMat &dst) - - :param src: the input array. - - :param dst: the destination array, it will have the same size and same type as ``src``. - -The functions bitwise not compute per-element bit-wise inversion of the source array. Supports all data types. - -ocl::bitwise_or ------------------- -Returns void - -.. ocv:function:: void ocl::bitwise_or(const oclMat& src1, const oclMat& src2, oclMat& dst, const oclMat& mask = oclMat()) - -.. ocv:function:: void ocl::bitwise_or(const oclMat& src1, const Scalar& s, oclMat& dst, const oclMat& mask = oclMat()) - - :param src1: the first input array. - - :param src2: the second input array, must be the same size and same type as ``src1``. - - :param s: scalar, the second input parameter. - - :param dst: the destination array, it will have the same size and same type as ``src1``. - - :param mask: the optional operation mask, 8-bit single channel array; specifies elements of the destination array to be changed. - -Computes per-element bitwise_or between two arrays or between array and a scalar. Supports all data types. - -ocl::bitwise_xor ------------------- -Returns void - -.. ocv:function:: void ocl::bitwise_xor(const oclMat& src1, const oclMat& src2, oclMat& dst, const oclMat& mask = oclMat()) - -.. ocv:function:: void ocl::bitwise_xor(const oclMat& src1, const Scalar& s, oclMat& dst, const oclMat& mask = oclMat()) - - :param src1: the first input array. - - :param src2: the second input array, must be the same size and same type as ``src1``. - - :param sc: scalar, the second input parameter. - - :param dst: the destination array, it will have the same size and same type as ``src1``. - - :param mask: the optional operation mask, 8-bit single channel array; specifies elements of the destination array to be changed. - -Computes per-element bitwise_xor between two arrays or between array and a scalar. Supports all data types. - -ocl::cartToPolar ------------------- -Returns void - -.. ocv:function:: void ocl::cartToPolar(const oclMat &x, const oclMat &y, oclMat &magnitude, oclMat &angle, bool angleInDegrees = false) - - :param x: the array of x-coordinates; must be single-precision or double-precision floating-point array. - - :param y: the array of y-coordinates; it must have the same size and same type as ``x``. - - :param magnitude: the destination array of magnitudes of the same size and same type as ``x``. - - :param angle: the destination array of angles of the same size and same type as ``x``. The angles are measured in radians (0 to 2pi) or in degrees (0 to 360 degrees). - - :param angleInDegrees: the flag indicating whether the angles are measured in radians, which is default mode, or in degrees. - -Calculates the magnitude and angle of 2D vectors. Supports only ``CV_32F`` and ``CV_64F`` data types. - -ocl::compare ------------------- -Returns void - -.. ocv:function:: void ocl::compare(const oclMat &src1, const oclMat &src2, oclMat &dst, int cmpop) - - :param src1: the first source array. - - :param src2: the second source array; must have the same size and same type as ``src1``. - - :param dst: the destination array; will have the same size as ``src1`` and type ``CV_8UC1``. - - :param cmpop: the flag specifying the relation between the elements to be checked. - -Performs per-element comparison of two arrays or an array and scalar value. Supports all data types. - -ocl::dft ------------- -Performs a forward or inverse discrete Fourier transform (1D or 2D) of the floating point matrix. - -.. ocv:function:: void ocl::dft(const oclMat& src, oclMat& dst, Size dft_size = Size(), int flags = 0) - - :param src: source matrix (real or complex). - - :param dst: destination matrix (real or complex). - - :param dft_size: size of original input, which is used for transformation from complex to real. - - :param flags: optional flags: - - * **DFT_ROWS** transforms each individual row of the source matrix. - - * **DFT_COMPLEX_OUTPUT** performs a forward transformation of 1D or 2D real array. The result, though being a complex array, has complex-conjugate symmetry (*CCS*, see the function description below for details). Such an array can be packed into a real array of the same size as input, which is the fastest option and which is what the function does by default. However, you may wish to get a full complex array (for simpler spectrum analysis, and so on). Pass the flag to enable the function to produce a full-size complex output array. - - * **DFT_INVERSE** inverts DFT. Use for complex-complex cases (real-complex and complex-real cases are always forward and inverse, respectively). - - * **DFT_REAL_OUTPUT** specifies the output as real. The source matrix is the result of real-complex transform, so the destination matrix must be real. - -Use to handle real matrices (``CV_32FC1``) and complex matrices in the interleaved format (``CV_32FC2``). - -The ``dft_size`` must be powers of ``2``, ``3`` and ``5``. Real to complex dft output is not the same with cpu version. Real to complex and complex to real does not support ``DFT_ROWS``. - -.. seealso:: :ocv:func:`dft` - -ocl::divide ------------------- -Returns void - -.. ocv:function:: void ocl::divide(const oclMat& src1, const oclMat& src2, oclMat& dst, double scale = 1) - -.. ocv:function:: void ocl::divide(double scale, const oclMat& src1, oclMat& dst) - - :param src1: the first input array. - - :param src2: the second input array, must be the same size and same type as ``src1``. - - :param dst: the destination array, it will have the same size and same type as ``src1``. - - :param scale: scalar factor. - -Computes per-element divide between two arrays or between array and a scalar. Supports all data types. - -ocl::exp ------------------- -Returns void - -.. ocv:function:: void ocl::exp(const oclMat &src, oclMat &dst) - - :param src: the first source array. - - :param dst: the dst array; must have the same size and same type as ``src``. - -The function exp calculates the exponent of every element of the input array. Supports only ``CV_32FC1`` and ``CV_64F`` data types. - -ocl::flip ------------------- -Returns void - -.. ocv:function:: void ocl::flip(const oclMat& src, oclMat& dst, int flipCode) - - :param src: source image. - - :param dst: destination image. - - :param flipCode: specifies how to flip the array: 0 means flipping around the x-axis, positive (e.g., 1) means flipping around y-axis, and negative (e.g., -1) means flipping around both axes. - -The function flip flips the array in one of three different ways (row and column indices are 0-based). Supports all data types. - -ocl::gemm ------------------- -Performs generalized matrix multiplication. - -.. ocv:function:: void ocl::gemm(const oclMat& src1, const oclMat& src2, double alpha, const oclMat& src3, double beta, oclMat& dst, int flags = 0) - - :param src1: first multiplied input matrix that should be ``CV_32FC1`` type. - - :param src2: second multiplied input matrix of the same type as ``src1``. - - :param alpha: weight of the matrix product. - - :param src3: third optional delta matrix added to the matrix product. It should have the same type as ``src1`` and ``src2``. - - :param beta: weight of ``src3``. - - :param dst: destination matrix. It has the proper size and the same type as input matrices. - - :param flags: operation flags: - - * **GEMM_1_T** transpose ``src1``. - * **GEMM_2_T** transpose ``src2``. - -.. seealso:: :ocv:func:`gemm` - -ocl::log ------------------- -Returns void - -.. ocv:function:: void ocl::log(const oclMat &src, oclMat &dst) - - :param src: the first source array. - - :param dst: the dst array; must have the same size and same type as ``src``. - -The function log calculates the log of every element of the input array. Supports only ``CV_32FC1`` and ``CV_64F`` data types. - -ocl::LUT ------------------- -Returns void - -.. ocv:function:: void ocl::LUT(const oclMat &src, const oclMat &lut, oclMat &dst) - - :param src: source array of 8-bit elements. - - :param lut: look-up table of 256 elements. In the case of multi-channel source array, the table should either have a single channel (in this case the same table is used for all channels) or the same number of channels as in the source array. - - :param dst: destination array; will have the same size and the same number of channels as ``src``, and the same depth as ``lut``. - -Performs a look-up table transform of an array. - -ocl::magnitude ------------------- -Returns void - -.. ocv:function:: void ocl::magnitude(const oclMat &x, const oclMat &y, oclMat &magnitude) - - :param x: the floating-point array of x-coordinates of the vectors. - - :param y: the floating-point array of y-coordinates of the vectors; must have the same size as ``x``. - - :param magnitude: the destination array; will have the same size and same type as ``x``. - -The function magnitude calculates magnitude of 2D vectors formed from the corresponding elements of ``x`` and ``y`` arrays. Supports only ``CV_32F`` and ``CV_64F`` data types. - -ocl::meanStdDev ------------------- -Returns void - -.. ocv:function:: void ocl::meanStdDev(const oclMat &mtx, Scalar &mean, Scalar &stddev) - - :param mtx: source image. - - :param mean: the output parameter: computed mean value. - - :param stddev: the output parameter: computed standard deviation. - -The functions meanStdDev compute the mean and the standard deviation M of array elements, independently for each channel, and return it via the output parameters. Supports all data types. - -ocl::merge ------------------- -Returns void - -.. ocv:function:: void ocl::merge(const vector &src, oclMat &dst) - - :param src: The source array or vector of the single-channel matrices to be merged. All the matrices in src must have the same size and the same type. - - :param dst: The destination array; will have the same size and the same depth as src, the number of channels will match the number of source matrices. - -Composes a multi-channel array from several single-channel arrays. Supports all data types. - -ocl::multiply ------------------- -Returns void - -.. ocv:function:: void ocl::multiply(const oclMat& src1, const oclMat& src2, oclMat& dst, double scale = 1) - - :param src1: the first input array. - - :param src2: the second input array, must be the same size and same type as ``src1``. - - :param dst: the destination array, it will have the same size and same type as ``src1``. - - :param scale: optional scale factor. - -Computes per-element multiply between two arrays or between array and a scalar. Supports all data types. - -ocl::norm ------------------- -Returns the calculated norm - -.. ocv:function:: double ocl::norm(const oclMat &src1, int normType = NORM_L2) - -.. ocv:function:: double ocl::norm(const oclMat &src1, const oclMat &src2, int normType = NORM_L2) - - :param src1: the first source array. - - :param src2: the second source array of the same size and the same type as ``src1``. - - :param normType: type of the norm. - -The functions ``norm`` calculate an absolute norm of ``src1`` (when there is no ``src2`` ): - -.. math:: - - norm = \forkthree{\|\texttt{src1}\|_{L_{\infty}} = \max _I | \texttt{src1} (I)|}{if $\texttt{normType} = \texttt{NORM\_INF}$ } - { \| \texttt{src1} \| _{L_1} = \sum _I | \texttt{src1} (I)|}{if $\texttt{normType} = \texttt{NORM\_L1}$ } - { \| \texttt{src1} \| _{L_2} = \sqrt{\sum_I \texttt{src1}(I)^2} }{if $\texttt{normType} = \texttt{NORM\_L2}$ } - -or an absolute or relative difference norm if ``src2`` is there: - -.. math:: - - norm = \forkthree{\|\texttt{src1}-\texttt{src2}\|_{L_{\infty}} = \max _I | \texttt{src1} (I) - \texttt{src2} (I)|}{if $\texttt{normType} = \texttt{NORM\_INF}$ } - { \| \texttt{src1} - \texttt{src2} \| _{L_1} = \sum _I | \texttt{src1} (I) - \texttt{src2} (I)|}{if $\texttt{normType} = \texttt{NORM\_L1}$ } - { \| \texttt{src1} - \texttt{src2} \| _{L_2} = \sqrt{\sum_I (\texttt{src1}(I) - \texttt{src2}(I))^2} }{if $\texttt{normType} = \texttt{NORM\_L2}$ } - -or - -.. math:: - - norm = \forkthree{\frac{\|\texttt{src1}-\texttt{src2}\|_{L_{\infty}} }{\|\texttt{src2}\|_{L_{\infty}} }}{if $\texttt{normType} = \texttt{NORM\_RELATIVE\_INF}$ } - { \frac{\|\texttt{src1}-\texttt{src2}\|_{L_1} }{\|\texttt{src2}\|_{L_1}} }{if $\texttt{normType} = \texttt{NORM\_RELATIVE\_L1}$ } - { \frac{\|\texttt{src1}-\texttt{src2}\|_{L_2} }{\|\texttt{src2}\|_{L_2}} }{if $\texttt{normType} = \texttt{NORM\_RELATIVE\_L2}$ } - -The functions ``norm`` return the calculated norm. - -A multi-channel input arrays are treated as a single-channel, that is, the results for all channels are combined. - -ocl::oclMat::convertTo --------------------------- -Returns void - -.. ocv:function:: void ocl::oclMat::convertTo(oclMat &m, int rtype, double alpha = 1, double beta = 0) const - - :param m: the destination matrix. If it does not have a proper size or type before the operation, it will be reallocated. - - :param rtype: the desired destination matrix type, or rather, the depth (since the number of channels will be the same with the source one). If rtype is negative, the destination matrix will have the same type as the source. - - :param alpha: optional scale factor. - - :param beta: optional delta added to the scaled values. - -The method converts source pixel values to the target datatype. Saturate cast is applied in the end to avoid possible overflows. Supports all data types. - -ocl::oclMat::copyTo ------------------------ -Returns void - -.. ocv:function:: void ocl::oclMat::copyTo(oclMat &m, const oclMat &mask = oclMat()) const - - :param m: The destination matrix. If it does not have a proper size or type before the operation, it will be reallocated. - - :param mask: The operation mask. Its non-zero elements indicate, which matrix elements need to be copied. - -Copies the matrix to another one. Supports all data types. - -ocl::oclMat::setTo ----------------------- -Returns oclMat - -.. ocv:function:: oclMat& ocl::oclMat::setTo(const Scalar &s, const oclMat &mask = oclMat()) - - :param s: Assigned scalar, which is converted to the actual array type. - - :param mask: The operation mask of the same size as ``*this`` and type ``CV_8UC1``. - -Sets all or some of the array elements to the specified value. This is the advanced variant of Mat::operator=(const Scalar s) operator. Supports all data types. - -ocl::phase ------------------- -Returns void - -.. ocv:function:: void ocl::phase(const oclMat &x, const oclMat &y, oclMat &angle, bool angleInDegrees = false) - - :param x: the source floating-point array of x-coordinates of 2D vectors - - :param y: the source array of y-coordinates of 2D vectors; must have the same size and the same type as ``x``. - - :param angle: the destination array of vector angles; it will have the same size and same type as ``x``. - - :param angleInDegrees: when it is true, the function will compute angle in degrees, otherwise they will be measured in radians. - -The function phase computes the rotation angle of each 2D vector that is formed from the corresponding elements of ``x`` and ``y``. Supports only ``CV_32FC1`` and ``CV_64FC1`` data type. - -ocl::polarToCart ------------------- -Returns void - -.. ocv:function:: void ocl::polarToCart(const oclMat &magnitude, const oclMat &angle, oclMat &x, oclMat &y, bool angleInDegrees = false) - - :param magnitude: the source floating-point array of magnitudes of 2D vectors. It can be an empty matrix (=Mat()) - in this case the function assumes that all the magnitudes are = 1. If it's not empty, it must have the same size and same type as ``angle``. - - :param angle: the source floating-point array of angles of the 2D vectors. - - :param x: the destination array of x-coordinates of 2D vectors; will have the same size and the same type as ``angle``. - - :param y: the destination array of y-coordinates of 2D vectors; will have the same size and the same type as ``angle``. - - :param angleInDegrees: the flag indicating whether the angles are measured in radians, which is default mode, or in degrees. - -The function polarToCart computes the cartesian coordinates of each 2D vector represented by the corresponding elements of magnitude and angle. Supports only ``CV_32F`` and ``CV_64F`` data types. - -ocl::pow ------------------- -Returns void - -.. ocv:function:: void ocl::pow(const oclMat &x, double p, oclMat &y) - - :param x: the source array. - - :param p: the exponent of power; the source floating-point array of angles of the 2D vectors. - - :param y: the destination array, should be the same type as the source. - -The function pow raises every element of the input array to ``p``. Supports only ``CV_32FC1`` and ``CV_64FC1`` data types. - -ocl::setIdentity ------------------- -Returns void - -.. ocv:function:: void ocl::setIdentity(oclMat& src, const Scalar & val = Scalar(1)) - - :param src: matrix to initialize (not necessarily square). - - :param val: value to assign to diagonal elements. - -The function initializes a scaled identity matrix. - -ocl::sortByKey ------------------- -Returns void - -.. ocv:function:: void ocl::sortByKey(oclMat& keys, oclMat& values, int method, bool isGreaterThan = false) - - :param keys: the keys to be used as sorting indices. - - :param values: the array of values. - - :param isGreaterThan: determine sorting order. - - :param method: supported sorting methods: - - * **SORT_BITONIC** bitonic sort, only support power-of-2 buffer size. - * **SORT_SELECTION** selection sort, currently cannot sort duplicate keys. - * **SORT_MERGE** merge sort. - * **SORT_RADIX** radix sort, only support signed int/float keys(``CV_32S``/``CV_32F``). - -Returns the sorted result of all the elements in values based on equivalent keys. - -The element unit in the values to be sorted is determined from the data type, i.e., a ``CV_32FC2`` input ``{a1a2, b1b2}`` will be considered as two elements, regardless its matrix dimension. - -Both keys and values will be sorted inplace. - -Keys needs to be a **single** channel ``oclMat``. - -Example:: - - input - - keys = {2, 3, 1} (CV_8UC1) - values = {10,5, 4,3, 6,2} (CV_8UC2) - sortByKey(keys, values, SORT_SELECTION, false); - output - - keys = {1, 2, 3} (CV_8UC1) - values = {6,2, 10,5, 4,3} (CV_8UC2) - -ocl::split ------------------- -Returns void - -.. ocv:function:: void ocl::split(const oclMat &src, vector &dst) - - :param src: The source multi-channel array - - :param dst: The destination array or vector of arrays; The number of arrays must match src.channels(). The arrays themselves will be reallocated if needed. - -The functions split split multi-channel array into separate single-channel arrays. Supports all data types. - -ocl::sqrt ------------------- -Returns void - -.. ocv:function:: void ocl::sqrt(const oclMat &src, oclMat &dst) - - :param src: the first source array. - - :param dst: the dst array; must have the same size and same type as ``src``. - -The function ``sqrt`` calculates the square root of each input array element. Supports only ``CV_32FC1`` and ``CV_64F`` data types. - -ocl::subtract ------------------- -Returns void - -.. ocv:function:: void ocl::subtract(const oclMat& src1, const oclMat& src2, oclMat& dst, const oclMat& mask = oclMat()) - -.. ocv:function:: void ocl::subtract(const oclMat& src1, const Scalar& s, oclMat& dst, const oclMat& mask = oclMat()) - - :param src1: the first input array. - - :param src2: the second input array, must be the same size and same type as ``src1``. - - :param s: scalar, the second input parameter. - - :param dst: the destination array, it will have the same size and same type as ``src1``. - - :param mask: the optional operation mask, 8-bit single channel array; specifies elements of the destination array to be changed. - -Computes per-element subtract between two arrays or between array and a scalar. Supports all data types. - -ocl::transpose ------------------- -Returns void - -.. ocv:function:: void ocl::transpose(const oclMat &src, oclMat &dst) - - :param src: the source array. - - :param dst: the destination array of the same type as ``src``. - -Transposes a matrix (in case when ``src`` == ``dst`` and matrix is square the operation are performed inplace). diff --git a/modules/ocl/doc/structures_and_utility_functions.rst b/modules/ocl/doc/structures_and_utility_functions.rst deleted file mode 100644 index 1d1265c81..000000000 --- a/modules/ocl/doc/structures_and_utility_functions.rst +++ /dev/null @@ -1,56 +0,0 @@ -Data Structures and Utility Functions -======================================== - -.. highlight:: cpp - -ocl::getOpenCLPlatforms ------------------------ -Returns the list of OpenCL platforms - -.. ocv:function:: int ocl::getOpenCLPlatforms( PlatformsInfo& platforms ) - - :param platforms: Output variable - -ocl::getOpenCLDevices ---------------------- -Returns the list of devices - -.. ocv:function:: int ocl::getOpenCLDevices( DevicesInfo& devices, int deviceType = CVCL_DEVICE_TYPE_GPU, const PlatformInfo* platform = NULL ) - - :param devices: Output variable - - :param deviceType: Bitmask of ``CVCL_DEVICE_TYPE_GPU``, ``CVCL_DEVICE_TYPE_CPU`` or ``CVCL_DEVICE_TYPE_DEFAULT``. - - :param platform: Specifies preferrable platform - -ocl::setDevice --------------- -Initialize OpenCL computation context - -.. ocv:function:: void ocl::setDevice( const DeviceInfo* info ) - - :param info: device info - -ocl::initializeContext --------------------------------- -Alternative way to initialize OpenCL computation context. - -.. ocv:function:: void ocl::initializeContext(void* pClPlatform, void* pClContext, void* pClDevice) - - :param pClPlatform: selected ``platform_id`` (via pointer, parameter type is ``cl_platform_id*``) - - :param pClContext: selected ``cl_context`` (via pointer, parameter type is ``cl_context*``) - - :param pClDevice: selected ``cl_device_id`` (via pointer, parameter type is ``cl_device_id*``) - -This function can be used for context initialization with D3D/OpenGL interoperability. - -ocl::setBinaryPath ------------------- -Returns void - -.. ocv:function:: void ocl::setBinaryPath(const char *path) - - :param path: the path of OpenCL kernel binaries - -If you call this function and set a valid path, the OCL module will save the compiled kernel to the address in the first time and reload the binary since that. It can save compilation time at the runtime. diff --git a/modules/ocl/doc/video_analysis.rst b/modules/ocl/doc/video_analysis.rst deleted file mode 100644 index 83ba2008e..000000000 --- a/modules/ocl/doc/video_analysis.rst +++ /dev/null @@ -1,561 +0,0 @@ -Video Analysis -============================= - -.. highlight:: cpp - -ocl::GoodFeaturesToTrackDetector_OCL ----------------------------------------- -.. ocv:class:: ocl::GoodFeaturesToTrackDetector_OCL - -Class used for strong corners detection on an image. :: - - class GoodFeaturesToTrackDetector_OCL - { - public: - explicit GoodFeaturesToTrackDetector_OCL(int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 0.0, - int blockSize = 3, bool useHarrisDetector = false, double harrisK = 0.04); - - //! return 1 rows matrix with CV_32FC2 type - void operator ()(const oclMat& image, oclMat& corners, const oclMat& mask = oclMat()); - //! download points of type Point2f to a vector. the vector's content will be erased - void downloadPoints(const oclMat &points, std::vector &points_v); - - int maxCorners; - double qualityLevel; - double minDistance; - - int blockSize; - bool useHarrisDetector; - double harrisK; - void releaseMemory() - { - Dx_.release(); - Dy_.release(); - eig_.release(); - minMaxbuf_.release(); - tmpCorners_.release(); - } - }; - -The class finds the most prominent corners in the image. - -.. seealso:: :ocv:func:`goodFeaturesToTrack()` - -ocl::GoodFeaturesToTrackDetector_OCL::GoodFeaturesToTrackDetector_OCL -------------------------------------------------------------------------- -Constructor. - -.. ocv:function:: ocl::GoodFeaturesToTrackDetector_OCL::GoodFeaturesToTrackDetector_OCL(int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 0.0, int blockSize = 3, bool useHarrisDetector = false, double harrisK = 0.04) - - :param maxCorners: Maximum number of corners to return. If there are more corners than are found, the strongest of them is returned. - - :param qualityLevel: Parameter characterizing the minimal accepted quality of image corners. The parameter value is multiplied by the best corner quality measure, which is the minimal eigenvalue (see :ocv:func:`ocl::cornerMinEigenVal` ) or the Harris function response (see :ocv:func:`ocl::cornerHarris` ). The corners with the quality measure less than the product are rejected. For example, if the best corner has the quality measure = 1500, and the ``qualityLevel=0.01`` , then all the corners with the quality measure less than 15 are rejected. - - :param minDistance: Minimum possible Euclidean distance between the returned corners. - - :param blockSize: Size of an average block for computing a derivative covariation matrix over each pixel neighborhood. See :ocv:func:`cornerEigenValsAndVecs` . - - :param useHarrisDetector: Parameter indicating whether to use a Harris detector (see :ocv:func:`ocl::cornerHarris`) or :ocv:func:`ocl::cornerMinEigenVal`. - - :param harrisK: Free parameter of the Harris detector. - -ocl::GoodFeaturesToTrackDetector_OCL::operator () -------------------------------------------------------- -Finds the most prominent corners in the image. - -.. ocv:function:: void ocl::GoodFeaturesToTrackDetector_OCL::operator ()(const oclMat& image, oclMat& corners, const oclMat& mask = oclMat()) - - :param image: Input 8-bit, single-channel image. - - :param corners: Output vector of detected corners (it will be one row matrix with CV_32FC2 type). - - :param mask: Optional region of interest. If the image is not empty (it needs to have the type ``CV_8UC1`` and the same size as ``image`` ), it specifies the region in which the corners are detected. - -.. seealso:: :ocv:func:`goodFeaturesToTrack` - -ocl::GoodFeaturesToTrackDetector_OCL::releaseMemory --------------------------------------------------------- -Releases inner buffers memory. - -.. ocv:function:: void ocl::GoodFeaturesToTrackDetector_OCL::releaseMemory() - -ocl::FarnebackOpticalFlow -------------------------------- -.. ocv:class:: ocl::FarnebackOpticalFlow - -Class computing a dense optical flow using the Gunnar Farneback's algorithm. :: - - class CV_EXPORTS FarnebackOpticalFlow - { - public: - FarnebackOpticalFlow(); - - int numLevels; - double pyrScale; - bool fastPyramids; - int winSize; - int numIters; - int polyN; - double polySigma; - int flags; - - void operator ()(const oclMat &frame0, const oclMat &frame1, oclMat &flowx, oclMat &flowy); - - void releaseMemory(); - - private: - /* hidden */ - }; - -ocl::FarnebackOpticalFlow::operator () ------------------------------------------- -Computes a dense optical flow using the Gunnar Farneback's algorithm. - -.. ocv:function:: void ocl::FarnebackOpticalFlow::operator ()(const oclMat &frame0, const oclMat &frame1, oclMat &flowx, oclMat &flowy) - - :param frame0: First 8-bit gray-scale input image - :param frame1: Second 8-bit gray-scale input image - :param flowx: Flow horizontal component - :param flowy: Flow vertical component - -.. seealso:: :ocv:func:`calcOpticalFlowFarneback` - -ocl::FarnebackOpticalFlow::releaseMemory --------------------------------------------- -Releases unused auxiliary memory buffers. - -.. ocv:function:: void ocl::FarnebackOpticalFlow::releaseMemory() - - -ocl::PyrLKOpticalFlow -------------------------- -.. ocv:class:: ocl::PyrLKOpticalFlow - -Class used for calculating an optical flow. :: - - class PyrLKOpticalFlow - { - public: - PyrLKOpticalFlow(); - - void sparse(const oclMat& prevImg, const oclMat& nextImg, const oclMat& prevPts, oclMat& nextPts, - oclMat& status, oclMat* err = 0); - - void dense(const oclMat& prevImg, const oclMat& nextImg, oclMat& u, oclMat& v, oclMat* err = 0); - - Size winSize; - int maxLevel; - int iters; - double derivLambda; - bool useInitialFlow; - float minEigThreshold; - bool getMinEigenVals; - - void releaseMemory(); - - private: - /* hidden */ - }; - -The class can calculate an optical flow for a sparse feature set or dense optical flow using the iterative Lucas-Kanade method with pyramids. - -.. seealso:: :ocv:func:`calcOpticalFlowPyrLK` - -ocl::PyrLKOpticalFlow::sparse ---------------------------------- -Calculate an optical flow for a sparse feature set. - -.. ocv:function:: void ocl::PyrLKOpticalFlow::sparse(const oclMat& prevImg, const oclMat& nextImg, const oclMat& prevPts, oclMat& nextPts, oclMat& status, oclMat* err = 0) - - :param prevImg: First 8-bit input image (supports both grayscale and color images). - - :param nextImg: Second input image of the same size and the same type as ``prevImg`` . - - :param prevPts: Vector of 2D points for which the flow needs to be found. It must be one row matrix with CV_32FC2 type. - - :param nextPts: Output vector of 2D points (with single-precision floating-point coordinates) containing the calculated new positions of input features in the second image. When ``useInitialFlow`` is true, the vector must have the same size as in the input. - - :param status: Output status vector (CV_8UC1 type). Each element of the vector is set to 1 if the flow for the corresponding features has been found. Otherwise, it is set to 0. - - :param err: Output vector (CV_32FC1 type) that contains the difference between patches around the original and moved points or min eigen value if ``getMinEigenVals`` is checked. It can be NULL, if not needed. - -.. seealso:: :ocv:func:`calcOpticalFlowPyrLK` - - -ocl::PyrLKOpticalFlow::dense ---------------------------------- -Calculate dense optical flow. - -.. ocv:function:: void ocl::PyrLKOpticalFlow::dense(const oclMat& prevImg, const oclMat& nextImg, oclMat& u, oclMat& v, oclMat* err = 0) - - :param prevImg: First 8-bit grayscale input image. - - :param nextImg: Second input image of the same size and the same type as ``prevImg`` . - - :param u: Horizontal component of the optical flow of the same size as input images, 32-bit floating-point, single-channel - - :param v: Vertical component of the optical flow of the same size as input images, 32-bit floating-point, single-channel - - :param err: Output vector (CV_32FC1 type) that contains the difference between patches around the original and moved points or min eigen value if ``getMinEigenVals`` is checked. It can be NULL, if not needed. - - -ocl::PyrLKOpticalFlow::releaseMemory ----------------------------------------- -Releases inner buffers memory. - -.. ocv:function:: void ocl::PyrLKOpticalFlow::releaseMemory() - -ocl::interpolateFrames --------------------------- -Interpolates frames (images) using provided optical flow (displacement field). - -.. ocv:function:: void ocl::interpolateFrames(const oclMat& frame0, const oclMat& frame1, const oclMat& fu, const oclMat& fv, const oclMat& bu, const oclMat& bv, float pos, oclMat& newFrame, oclMat& buf) - - :param frame0: First frame (32-bit floating point images, single channel). - - :param frame1: Second frame. Must have the same type and size as ``frame0`` . - - :param fu: Forward horizontal displacement. - - :param fv: Forward vertical displacement. - - :param bu: Backward horizontal displacement. - - :param bv: Backward vertical displacement. - - :param pos: New frame position. - - :param newFrame: Output image. - - :param buf: Temporary buffer, will have width x 6*height size, CV_32FC1 type and contain 6 oclMat: occlusion masks for first frame, occlusion masks for second, interpolated forward horizontal flow, interpolated forward vertical flow, interpolated backward horizontal flow, interpolated backward vertical flow. - -ocl::KalmanFilter --------------------- -.. ocv:class:: ocl::KalmanFilter - -Kalman filter class. :: - - class CV_EXPORTS KalmanFilter - { - public: - KalmanFilter(); - //! the full constructor taking the dimensionality of the state, of the measurement and of the control vector - KalmanFilter(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F); - //! re-initializes Kalman filter. The previous content is destroyed. - void init(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F); - - const oclMat& predict(const oclMat& control=oclMat()); - const oclMat& correct(const oclMat& measurement); - - oclMat statePre; //!< predicted state (x'(k)): x(k)=A*x(k-1)+B*u(k) - oclMat statePost; //!< corrected state (x(k)): x(k)=x'(k)+K(k)*(z(k)-H*x'(k)) - oclMat transitionMatrix; //!< state transition matrix (A) - oclMat controlMatrix; //!< control matrix (B) (not used if there is no control) - oclMat measurementMatrix; //!< measurement matrix (H) - oclMat processNoiseCov; //!< process noise covariance matrix (Q) - oclMat measurementNoiseCov;//!< measurement noise covariance matrix (R) - oclMat errorCovPre; //!< priori error estimate covariance matrix (P'(k)): P'(k)=A*P(k-1)*At + Q)*/ - oclMat gain; //!< Kalman gain matrix (K(k)): K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R) - oclMat errorCovPost; //!< posteriori error estimate covariance matrix (P(k)): P(k)=(I-K(k)*H)*P'(k) - private: - /* hidden */ - }; - -ocl::KalmanFilter::KalmanFilter ----------------------------------- -The constructors. - -.. ocv:function:: ocl::KalmanFilter::KalmanFilter() - -.. ocv:function:: ocl::KalmanFilter::KalmanFilter(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F) - - The full constructor. - - :param dynamParams: Dimensionality of the state. - - :param measureParams: Dimensionality of the measurement. - - :param controlParams: Dimensionality of the control vector. - - :param type: Type of the created matrices that should be ``CV_32F`` or ``CV_64F``. - - -ocl::KalmanFilter::init ---------------------------- -Re-initializes Kalman filter. The previous content is destroyed. - -.. ocv:function:: void ocl::KalmanFilter::init(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F) - - :param dynamParams: Dimensionalityensionality of the state. - - :param measureParams: Dimensionality of the measurement. - - :param controlParams: Dimensionality of the control vector. - - :param type: Type of the created matrices that should be ``CV_32F`` or ``CV_64F``. - - -ocl::KalmanFilter::predict ------------------------------- -Computes a predicted state. - -.. ocv:function:: const oclMat& ocl::KalmanFilter::predict(const oclMat& control=oclMat()) - - :param control: The optional input control - - -ocl::KalmanFilter::correct ------------------------------ -Updates the predicted state from the measurement. - -.. ocv:function:: const oclMat& ocl::KalmanFilter::correct(const oclMat& measurement) - - :param measurement: The measured system parameters - - -ocl::BackgroundSubtractor ----------------------------- -.. ocv:class:: ocl::BackgroundSubtractor - -Base class for background/foreground segmentation. :: - - class CV_EXPORTS BackgroundSubtractor - { - public: - //! the virtual destructor - virtual ~BackgroundSubtractor(); - //! the update operator that takes the next video frame and returns the current foreground mask as 8-bit binary image. - virtual void operator()(const oclMat& image, oclMat& fgmask, float learningRate); - - //! computes a background image - virtual void getBackgroundImage(oclMat& backgroundImage) const = 0; - }; - - -The class is only used to define the common interface for the whole family of background/foreground segmentation algorithms. - - -ocl::BackgroundSubtractor::operator() ------------------------------------------ -Computes a foreground mask. - -.. ocv:function:: void ocl::BackgroundSubtractor::operator()(const oclMat& image, oclMat& fgmask, float learningRate) - - :param image: Next video frame. - - :param fgmask: The output foreground mask as an 8-bit binary image. - - -ocl::BackgroundSubtractor::getBackgroundImage -------------------------------------------------- -Computes a background image. - -.. ocv:function:: void ocl::BackgroundSubtractor::getBackgroundImage(oclMat& backgroundImage) const - - :param backgroundImage: The output background image. - -.. note:: Sometimes the background image can be very blurry, as it contain the average background statistics. - -ocl::MOG ------------- -.. ocv:class:: ocl::MOG : public ocl::BackgroundSubtractor - -Gaussian Mixture-based Backbround/Foreground Segmentation Algorithm. :: - - class CV_EXPORTS MOG: public cv::ocl::BackgroundSubtractor - { - public: - //! the default constructor - MOG(int nmixtures = -1); - - //! re-initiaization method - void initialize(Size frameSize, int frameType); - - //! the update operator - void operator()(const oclMat& frame, oclMat& fgmask, float learningRate = 0.f); - - //! computes a background image which are the mean of all background gaussians - void getBackgroundImage(oclMat& backgroundImage) const; - - //! releases all inner buffers - void release(); - - int history; - float varThreshold; - float backgroundRatio; - float noiseSigma; - - private: - /* hidden */ - }; - -The class discriminates between foreground and background pixels by building and maintaining a model of the background. Any pixel which does not fit this model is then deemed to be foreground. The class implements algorithm described in [MOG2001]_. - -.. seealso:: :ocv:class:`BackgroundSubtractorMOG` - - -ocl::MOG::MOG ---------------------- -The constructor. - -.. ocv:function:: ocl::MOG::MOG(int nmixtures = -1) - - :param nmixtures: Number of Gaussian mixtures. - -Default constructor sets all parameters to default values. - - -ocl::MOG::operator() ------------------------- -Updates the background model and returns the foreground mask. - -.. ocv:function:: void ocl::MOG::operator()(const oclMat& frame, oclMat& fgmask, float learningRate = 0.f) - - :param frame: Next video frame. - - :param fgmask: The output foreground mask as an 8-bit binary image. - - -ocl::MOG::getBackgroundImage --------------------------------- -Computes a background image. - -.. ocv:function:: void ocl::MOG::getBackgroundImage(oclMat& backgroundImage) const - - :param backgroundImage: The output background image. - - -ocl::MOG::release ---------------------- -Releases all inner buffer's memory. - -.. ocv:function:: void ocl::MOG::release() - - -ocl::MOG2 -------------- -.. ocv:class:: ocl::MOG2 : public ocl::BackgroundSubtractor - - Gaussian Mixture-based Background/Foreground Segmentation Algorithm. - - The class discriminates between foreground and background pixels by building and maintaining a model of the background. Any pixel which does not fit this model is then deemed to be foreground. The class implements algorithm described in [MOG2004]_. :: - - class CV_EXPORTS MOG2: public cv::ocl::BackgroundSubtractor - { - public: - //! the default constructor - MOG2(int nmixtures = -1); - - //! re-initiaization method - void initialize(Size frameSize, int frameType); - - //! the update operator - void operator()(const oclMat& frame, oclMat& fgmask, float learningRate = -1.0f); - - //! computes a background image which are the mean of all background gaussians - void getBackgroundImage(oclMat& backgroundImage) const; - - //! releases all inner buffers - void release(); - - int history; - - float varThreshold; - - float backgroundRatio; - - float varThresholdGen; - - float fVarInit; - float fVarMin; - float fVarMax; - - float fCT; - - bool bShadowDetection; - unsigned char nShadowDetection; - float fTau; - - private: - /* hidden */ - }; - - .. ocv:member:: float backgroundRatio - - Threshold defining whether the component is significant enough to be included into the background model. ``cf=0.1 => TB=0.9`` is default. For ``alpha=0.001``, it means that the mode should exist for approximately 105 frames before it is considered foreground. - - .. ocv:member:: float varThreshold - - Threshold for the squared Mahalanobis distance that helps decide when a sample is close to the existing components (corresponds to ``Tg``). If it is not close to any component, a new component is generated. ``3 sigma => Tg=3*3=9`` is default. A smaller ``Tg`` value generates more components. A higher ``Tg`` value may result in a small number of components but they can grow too large. - - .. ocv:member:: float fVarInit - - Initial variance for the newly generated components. It affects the speed of adaptation. The parameter value is based on your estimate of the typical standard deviation from the images. OpenCV uses 15 as a reasonable value. - - .. ocv:member:: float fVarMin - - Parameter used to further control the variance. - - .. ocv:member:: float fVarMax - - Parameter used to further control the variance. - - .. ocv:member:: float fCT - - Complexity reduction parameter. This parameter defines the number of samples needed to accept to prove the component exists. ``CT=0.05`` is a default value for all the samples. By setting ``CT=0`` you get an algorithm very similar to the standard Stauffer&Grimson algorithm. - - .. ocv:member:: uchar nShadowDetection - - The value for marking shadow pixels in the output foreground mask. Default value is 127. - - .. ocv:member:: float fTau - - Shadow threshold. The shadow is detected if the pixel is a darker version of the background. ``Tau`` is a threshold defining how much darker the shadow can be. ``Tau= 0.5`` means that if a pixel is more than twice darker then it is not shadow. See [ShadowDetect2003]_. - - .. ocv:member:: bool bShadowDetection - - Parameter defining whether shadow detection should be enabled. - - -.. seealso:: :ocv:class:`BackgroundSubtractorMOG2` - - -ocl::MOG2::MOG2 ------------------------ -The constructor. - -.. ocv:function:: ocl::MOG2::MOG2(int nmixtures = -1) - - :param nmixtures: Number of Gaussian mixtures. - -Default constructor sets all parameters to default values. - - -ocl::MOG2::operator() -------------------------- -Updates the background model and returns the foreground mask. - -.. ocv:function:: void ocl::MOG2::operator()( const oclMat& frame, oclMat& fgmask, float learningRate=-1.0f) - - :param frame: Next video frame. - - :param fgmask: The output foreground mask as an 8-bit binary image. - - -ocl::MOG2::getBackgroundImage ---------------------------------- -Computes a background image. - -.. ocv:function:: void ocl::MOG2::getBackgroundImage(oclMat& backgroundImage) const - - :param backgroundImage: The output background image. - - -ocl::MOG2::release ----------------------- -Releases all inner buffer's memory. - -.. ocv:function:: void ocl::MOG2::release() - - -.. [ShadowDetect2003] Prati, Mikic, Trivedi and Cucchiarra. *Detecting Moving Shadows...*. IEEE PAMI, 2003 diff --git a/modules/ocl/include/opencv2/ocl.hpp b/modules/ocl/include/opencv2/ocl.hpp deleted file mode 100644 index 190b0a394..000000000 --- a/modules/ocl/include/opencv2/ocl.hpp +++ /dev/null @@ -1,2230 +0,0 @@ -// This file is part of OpenCV project. -// It is subject to the license terms in the LICENSE file found in the top-level directory -// of this distribution and at http://opencv.org/license.html. - -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. - -#ifndef __OPENCV_OCL_HPP__ -#define __OPENCV_OCL_HPP__ - -#include -#include - -#include "opencv2/core.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/objdetect.hpp" -#include "opencv2/ml.hpp" - -namespace cv -{ - namespace ocl - { - enum DeviceType - { - CVCL_DEVICE_TYPE_DEFAULT = (1 << 0), - CVCL_DEVICE_TYPE_CPU = (1 << 1), - CVCL_DEVICE_TYPE_GPU = (1 << 2), - CVCL_DEVICE_TYPE_ACCELERATOR = (1 << 3), - //CVCL_DEVICE_TYPE_CUSTOM = (1 << 4) - CVCL_DEVICE_TYPE_ALL = 0xFFFFFFFF - }; - - enum DevMemRW - { - DEVICE_MEM_R_W = 0, - DEVICE_MEM_R_ONLY, - DEVICE_MEM_W_ONLY - }; - - enum DevMemType - { - DEVICE_MEM_DEFAULT = 0, - DEVICE_MEM_AHP, //alloc host pointer - DEVICE_MEM_UHP, //use host pointer - DEVICE_MEM_CHP, //copy host pointer - DEVICE_MEM_PM //persistent memory - }; - - // these classes contain OpenCL runtime information - - struct PlatformInfo; - - struct DeviceInfo - { - public: - int _id; // reserved, don't use it - - DeviceType deviceType; - std::string deviceProfile; - std::string deviceVersion; - std::string deviceName; - std::string deviceVendor; - int deviceVendorId; - std::string deviceDriverVersion; - std::string deviceExtensions; - - size_t maxWorkGroupSize; - std::vector maxWorkItemSizes; - int maxComputeUnits; - size_t localMemorySize; - size_t maxMemAllocSize; - - int deviceVersionMajor; - int deviceVersionMinor; - - bool haveDoubleSupport; - bool isUnifiedMemory; // 1 means integrated GPU, otherwise this value is 0 - bool isIntelDevice; - - std::string compilationExtraOptions; - - const PlatformInfo* platform; - - DeviceInfo(); - ~DeviceInfo(); - }; - - struct PlatformInfo - { - int _id; // reserved, don't use it - - std::string platformProfile; - std::string platformVersion; - std::string platformName; - std::string platformVendor; - std::string platformExtensons; - - int platformVersionMajor; - int platformVersionMinor; - - std::vector devices; - - PlatformInfo(); - ~PlatformInfo(); - }; - - //////////////////////////////// Initialization & Info //////////////////////// - typedef std::vector PlatformsInfo; - - CV_EXPORTS int getOpenCLPlatforms(PlatformsInfo& platforms); - - typedef std::vector DevicesInfo; - - CV_EXPORTS int getOpenCLDevices(DevicesInfo& devices, int deviceType = CVCL_DEVICE_TYPE_GPU, - const PlatformInfo* platform = NULL); - - // set device you want to use - CV_EXPORTS void setDevice(const DeviceInfo* info); - - // Initialize from OpenCL handles directly. - // Argument types is (pointers): cl_platform_id*, cl_context*, cl_device_id* - CV_EXPORTS void initializeContext(void* pClPlatform, void* pClContext, void* pClDevice); - - enum FEATURE_TYPE - { - FEATURE_CL_DOUBLE = 1, - FEATURE_CL_UNIFIED_MEM, - FEATURE_CL_VER_1_2, - FEATURE_CL_INTEL_DEVICE - }; - - // Represents OpenCL context, interface - class CV_EXPORTS Context - { - protected: - Context() { } - ~Context() { } - public: - static Context *getContext(); - - bool supportsFeature(FEATURE_TYPE featureType) const; - const DeviceInfo& getDeviceInfo() const; - - const void* getOpenCLContextPtr() const; - const void* getOpenCLCommandQueuePtr() const; - const void* getOpenCLDeviceIDPtr() const; - }; - - inline const void *getClContextPtr() - { - return Context::getContext()->getOpenCLContextPtr(); - } - - inline const void *getClCommandQueuePtr() - { - return Context::getContext()->getOpenCLCommandQueuePtr(); - } - - CV_EXPORTS bool supportsFeature(FEATURE_TYPE featureType); - - CV_EXPORTS void finish(); - - enum BINARY_CACHE_MODE - { - CACHE_NONE = 0, // do not cache OpenCL binary - CACHE_DEBUG = 0x1 << 0, // cache OpenCL binary when built in debug mode - CACHE_RELEASE = 0x1 << 1, // default behavior, only cache when built in release mode - CACHE_ALL = CACHE_DEBUG | CACHE_RELEASE // cache opencl binary - }; - //! Enable or disable OpenCL program binary caching onto local disk - // After a program (*.cl files in opencl/ folder) is built at runtime, we allow the - // compiled OpenCL program to be cached to the path automatically as "path/*.clb" - // binary file, which will be reused when the OpenCV executable is started again. - // - // This feature is enabled by default. - CV_EXPORTS void setBinaryDiskCache(int mode = CACHE_RELEASE, cv::String path = "./"); - - //! set where binary cache to be saved to - CV_EXPORTS void setBinaryPath(const char *path); - - struct ProgramSource - { - const char* name; - const char* programStr; - const char* programHash; - - // Cache in memory by name (should be unique). Caching on disk disabled. - inline ProgramSource(const char* _name, const char* _programStr) - : name(_name), programStr(_programStr), programHash(NULL) - { - } - - // Cache in memory by name (should be unique). Caching on disk uses programHash mark. - inline ProgramSource(const char* _name, const char* _programStr, const char* _programHash) - : name(_name), programStr(_programStr), programHash(_programHash) - { - } - }; - - //! Calls OpenCL kernel. Pass globalThreads = NULL, and cleanUp = true, to finally clean-up without executing. - //! Deprecated, will be replaced - CV_EXPORTS void openCLExecuteKernelInterop(Context *clCxt, - const cv::ocl::ProgramSource& source, String kernelName, - size_t globalThreads[3], size_t localThreads[3], - std::vector< std::pair > &args, - int channels, int depth, const char *build_options); - - class CV_EXPORTS oclMatExpr; - //////////////////////////////// oclMat //////////////////////////////// - class CV_EXPORTS oclMat - { - public: - //! default constructor - oclMat(); - //! constructs oclMatrix of the specified size and type (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.) - oclMat(int rows, int cols, int type); - oclMat(Size size, int type); - //! constucts oclMatrix and fills it with the specified value _s. - oclMat(int rows, int cols, int type, const Scalar &s); - oclMat(Size size, int type, const Scalar &s); - //! copy constructor - oclMat(const oclMat &m); - - //! constructor for oclMatrix headers pointing to user-allocated data - oclMat(int rows, int cols, int type, void *data, size_t step = Mat::AUTO_STEP); - oclMat(Size size, int type, void *data, size_t step = Mat::AUTO_STEP); - - //! creates a matrix header for a part of the bigger matrix - oclMat(const oclMat &m, const Range &rowRange, const Range &colRange); - oclMat(const oclMat &m, const Rect &roi); - - //! builds oclMat from Mat. Perfom blocking upload to device. - explicit oclMat (const Mat &m); - - //! destructor - calls release() - ~oclMat(); - - //! assignment operators - oclMat &operator = (const oclMat &m); - //! assignment operator. Perfom blocking upload to device. - oclMat &operator = (const Mat &m); - oclMat &operator = (const oclMatExpr& expr); - - //! pefroms blocking upload data to oclMat. - void upload(const cv::Mat &m); - - - //! downloads data from device to host memory. Blocking calls. - operator Mat() const; - void download(cv::Mat &m) const; - - //! convert to _InputArray - operator _InputArray(); - - //! convert to _OutputArray - operator _OutputArray(); - - //! returns a new oclMatrix header for the specified row - oclMat row(int y) const; - //! returns a new oclMatrix header for the specified column - oclMat col(int x) const; - //! ... for the specified row span - oclMat rowRange(int startrow, int endrow) const; - oclMat rowRange(const Range &r) const; - //! ... for the specified column span - oclMat colRange(int startcol, int endcol) const; - oclMat colRange(const Range &r) const; - - //! returns deep copy of the oclMatrix, i.e. the data is copied - oclMat clone() const; - - //! copies those oclMatrix elements to "m" that are marked with non-zero mask elements. - // It calls m.create(this->size(), this->type()). - // It supports any data type - void copyTo( oclMat &m, const oclMat &mask = oclMat()) const; - - //! converts oclMatrix to another datatype with optional scalng. See cvConvertScale. - void convertTo( oclMat &m, int rtype, double alpha = 1, double beta = 0 ) const; - - void assignTo( oclMat &m, int type = -1 ) const; - - //! sets every oclMatrix element to s - oclMat& operator = (const Scalar &s); - //! sets some of the oclMatrix elements to s, according to the mask - oclMat& setTo(const Scalar &s, const oclMat &mask = oclMat()); - //! creates alternative oclMatrix header for the same data, with different - // number of channels and/or different number of rows. see cvReshape. - oclMat reshape(int cn, int rows = 0) const; - - //! allocates new oclMatrix data unless the oclMatrix already has specified size and type. - // previous data is unreferenced if needed. - void create(int rows, int cols, int type); - void create(Size size, int type); - - //! allocates new oclMatrix with specified device memory type. - void createEx(int rows, int cols, int type, - DevMemRW rw_type, DevMemType mem_type); - void createEx(Size size, int type, DevMemRW rw_type, - DevMemType mem_type); - - //! decreases reference counter; - // deallocate the data when reference counter reaches 0. - void release(); - - //! swaps with other smart pointer - void swap(oclMat &mat); - - //! locates oclMatrix header within a parent oclMatrix. See below - void locateROI( Size &wholeSize, Point &ofs ) const; - //! moves/resizes the current oclMatrix ROI inside the parent oclMatrix. - oclMat& adjustROI( int dtop, int dbottom, int dleft, int dright ); - //! extracts a rectangular sub-oclMatrix - // (this is a generalized form of row, rowRange etc.) - oclMat operator()( Range rowRange, Range colRange ) const; - oclMat operator()( const Rect &roi ) const; - - oclMat& operator+=( const oclMat& m ); - oclMat& operator-=( const oclMat& m ); - oclMat& operator*=( const oclMat& m ); - oclMat& operator/=( const oclMat& m ); - - //! returns true if the oclMatrix data is continuous - // (i.e. when there are no gaps between successive rows). - // similar to CV_IS_oclMat_CONT(cvoclMat->type) - bool isContinuous() const; - //! returns element size in bytes, - // similar to CV_ELEM_SIZE(cvMat->type) - size_t elemSize() const; - //! returns the size of element channel in bytes. - size_t elemSize1() const; - //! returns element type, similar to CV_MAT_TYPE(cvMat->type) - int type() const; - //! returns element type, i.e. 8UC3 returns 8UC4 because in ocl - //! 3 channels element actually use 4 channel space - int ocltype() const; - //! returns element type, similar to CV_MAT_DEPTH(cvMat->type) - int depth() const; - //! returns element type, similar to CV_MAT_CN(cvMat->type) - int channels() const; - //! returns element type, return 4 for 3 channels element, - //!becuase 3 channels element actually use 4 channel space - int oclchannels() const; - //! returns step/elemSize1() - size_t step1() const; - //! returns oclMatrix size: - // width == number of columns, height == number of rows - Size size() const; - //! returns true if oclMatrix data is NULL - bool empty() const; - - //! matrix transposition - oclMat t() const; - - /*! includes several bit-fields: - - the magic signature - - continuity flag - - depth - - number of channels - */ - int flags; - //! the number of rows and columns - int rows, cols; - //! a distance between successive rows in bytes; includes the gap if any - size_t step; - //! pointer to the data(OCL memory object) - uchar *data; - - //! pointer to the reference counter; - // when oclMatrix points to user-allocated data, the pointer is NULL - int *refcount; - - //! helper fields used in locateROI and adjustROI - //datastart and dataend are not used in current version - uchar *datastart; - uchar *dataend; - - //! OpenCL context associated with the oclMat object. - Context *clCxt; // TODO clCtx - //add offset for handle ROI, calculated in byte - int offset; - //add wholerows and wholecols for the whole matrix, datastart and dataend are no longer used - int wholerows; - int wholecols; - }; - - // convert InputArray/OutputArray to oclMat references - CV_EXPORTS oclMat& getOclMatRef(InputArray src); - CV_EXPORTS oclMat& getOclMatRef(OutputArray src); - - ///////////////////// mat split and merge ///////////////////////////////// - //! Compose a multi-channel array from several single-channel arrays - // Support all types - CV_EXPORTS void merge(const oclMat *src, size_t n, oclMat &dst); - CV_EXPORTS void merge(const std::vector &src, oclMat &dst); - - //! Divides multi-channel array into several single-channel arrays - // Support all types - CV_EXPORTS void split(const oclMat &src, oclMat *dst); - CV_EXPORTS void split(const oclMat &src, std::vector &dst); - - ////////////////////////////// Arithmetics /////////////////////////////////// - - //! adds one matrix to another with scale (dst = src1 * alpha + src2 * beta + gama) - // supports all data types - CV_EXPORTS void addWeighted(const oclMat &src1, double alpha, const oclMat &src2, double beta, double gama, oclMat &dst); - - //! adds one matrix to another (dst = src1 + src2) - // supports all data types - CV_EXPORTS void add(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask = oclMat()); - //! adds scalar to a matrix (dst = src1 + s) - // supports all data types - CV_EXPORTS void add(const oclMat &src1, const Scalar &s, oclMat &dst, const oclMat &mask = oclMat()); - - //! subtracts one matrix from another (dst = src1 - src2) - // supports all data types - CV_EXPORTS void subtract(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask = oclMat()); - //! subtracts scalar from a matrix (dst = src1 - s) - // supports all data types - CV_EXPORTS void subtract(const oclMat &src1, const Scalar &s, oclMat &dst, const oclMat &mask = oclMat()); - - //! computes element-wise product of the two arrays (dst = src1 * scale * src2) - // supports all data types - CV_EXPORTS void multiply(const oclMat &src1, const oclMat &src2, oclMat &dst, double scale = 1); - //! multiplies matrix to a number (dst = scalar * src) - // supports all data types - CV_EXPORTS void multiply(double scalar, const oclMat &src, oclMat &dst); - - //! computes element-wise quotient of the two arrays (dst = src1 * scale / src2) - // supports all data types - CV_EXPORTS void divide(const oclMat &src1, const oclMat &src2, oclMat &dst, double scale = 1); - //! computes element-wise quotient of the two arrays (dst = scale / src) - // supports all data types - CV_EXPORTS void divide(double scale, const oclMat &src1, oclMat &dst); - - //! computes element-wise minimum of the two arrays (dst = min(src1, src2)) - // supports all data types - CV_EXPORTS void min(const oclMat &src1, const oclMat &src2, oclMat &dst); - - //! computes element-wise maximum of the two arrays (dst = max(src1, src2)) - // supports all data types - CV_EXPORTS void max(const oclMat &src1, const oclMat &src2, oclMat &dst); - - //! compares elements of two arrays (dst = src1 src2) - // supports all data types - CV_EXPORTS void compare(const oclMat &src1, const oclMat &src2, oclMat &dst, int cmpop); - - //! transposes the matrix - // supports all data types - CV_EXPORTS void transpose(const oclMat &src, oclMat &dst); - - //! computes element-wise absolute values of an array (dst = abs(src)) - // supports all data types - CV_EXPORTS void abs(const oclMat &src, oclMat &dst); - - //! computes element-wise absolute difference of two arrays (dst = abs(src1 - src2)) - // supports all data types - CV_EXPORTS void absdiff(const oclMat &src1, const oclMat &src2, oclMat &dst); - //! computes element-wise absolute difference of array and scalar (dst = abs(src1 - s)) - // supports all data types - CV_EXPORTS void absdiff(const oclMat &src1, const Scalar &s, oclMat &dst); - - //! computes mean value and standard deviation of all or selected array elements - // supports all data types - CV_EXPORTS void meanStdDev(const oclMat &mtx, Scalar &mean, Scalar &stddev); - - //! computes norm of array - // supports NORM_INF, NORM_L1, NORM_L2 - // supports all data types - CV_EXPORTS double norm(const oclMat &src1, int normType = NORM_L2); - - //! computes norm of the difference between two arrays - // supports NORM_INF, NORM_L1, NORM_L2 - // supports all data types - CV_EXPORTS double norm(const oclMat &src1, const oclMat &src2, int normType = NORM_L2); - - //! reverses the order of the rows, columns or both in a matrix - // supports all types - CV_EXPORTS void flip(const oclMat &src, oclMat &dst, int flipCode); - - //! computes sum of array elements - // support all types - CV_EXPORTS Scalar sum(const oclMat &m); - CV_EXPORTS Scalar absSum(const oclMat &m); - CV_EXPORTS Scalar sqrSum(const oclMat &m); - - //! finds global minimum and maximum array elements and returns their values - // support all C1 types - CV_EXPORTS void minMax(const oclMat &src, double *minVal, double *maxVal = 0, const oclMat &mask = oclMat()); - - //! finds global minimum and maximum array elements and returns their values with locations - // support all C1 types - CV_EXPORTS void minMaxLoc(const oclMat &src, double *minVal, double *maxVal = 0, Point *minLoc = 0, Point *maxLoc = 0, - const oclMat &mask = oclMat()); - - //! counts non-zero array elements - // support all types - CV_EXPORTS int countNonZero(const oclMat &src); - - //! transforms 8-bit unsigned integers using lookup table: dst(i)=lut(src(i)) - // destination array will have the depth type as lut and the same channels number as source - //It supports 8UC1 8UC4 only - CV_EXPORTS void LUT(const oclMat &src, const oclMat &lut, oclMat &dst); - - //! only 8UC1 and 256 bins is supported now - CV_EXPORTS void calcHist(const oclMat &mat_src, oclMat &mat_hist); - //! only 8UC1 and 256 bins is supported now - CV_EXPORTS void equalizeHist(const oclMat &mat_src, oclMat &mat_dst); - - //! only 8UC1 is supported now - CV_EXPORTS Ptr createCLAHE(double clipLimit = 40.0, Size tileGridSize = Size(8, 8)); - - //! bilateralFilter - // supports 8UC1 8UC4 - CV_EXPORTS void bilateralFilter(const oclMat& src, oclMat& dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT); - - //! Applies an adaptive bilateral filter to the input image - // Unlike the usual bilateral filter that uses fixed value for sigmaColor, - // the adaptive version calculates the local variance in he ksize neighborhood - // and use this as sigmaColor, for the value filtering. However, the local standard deviation is - // clamped to the maxSigmaColor. - // supports 8UC1, 8UC3 - CV_EXPORTS void adaptiveBilateralFilter(const oclMat& src, oclMat& dst, Size ksize, double sigmaSpace, double maxSigmaColor=20.0, Point anchor = Point(-1, -1), int borderType=BORDER_DEFAULT); - - //! computes exponent of each matrix element (dst = e**src) - // supports only CV_32FC1, CV_64FC1 type - CV_EXPORTS void exp(const oclMat &src, oclMat &dst); - - //! computes natural logarithm of absolute value of each matrix element: dst = log(abs(src)) - // supports only CV_32FC1, CV_64FC1 type - CV_EXPORTS void log(const oclMat &src, oclMat &dst); - - //! computes square root of each matrix element - // supports only CV_32FC1, CV_64FC1 type - CV_EXPORTS void sqrt(const oclMat &src, oclMat &dst); - - //! computes magnitude of each (x(i), y(i)) vector - // supports only CV_32F, CV_64F type - CV_EXPORTS void magnitude(const oclMat &x, const oclMat &y, oclMat &magnitude); - - //! computes angle (angle(i)) of each (x(i), y(i)) vector - // supports only CV_32F, CV_64F type - CV_EXPORTS void phase(const oclMat &x, const oclMat &y, oclMat &angle, bool angleInDegrees = false); - - //! the function raises every element of tne input array to p - // support only CV_32F, CV_64F type - CV_EXPORTS void pow(const oclMat &x, double p, oclMat &y); - - //! converts Cartesian coordinates to polar - // supports only CV_32F CV_64F type - CV_EXPORTS void cartToPolar(const oclMat &x, const oclMat &y, oclMat &magnitude, oclMat &angle, bool angleInDegrees = false); - - //! converts polar coordinates to Cartesian - // supports only CV_32F CV_64F type - CV_EXPORTS void polarToCart(const oclMat &magnitude, const oclMat &angle, oclMat &x, oclMat &y, bool angleInDegrees = false); - - //! perfroms per-elements bit-wise inversion - // supports all types - CV_EXPORTS void bitwise_not(const oclMat &src, oclMat &dst); - - //! calculates per-element bit-wise disjunction of two arrays - // supports all types - CV_EXPORTS void bitwise_or(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask = oclMat()); - CV_EXPORTS void bitwise_or(const oclMat &src1, const Scalar &s, oclMat &dst, const oclMat &mask = oclMat()); - - //! calculates per-element bit-wise conjunction of two arrays - // supports all types - CV_EXPORTS void bitwise_and(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask = oclMat()); - CV_EXPORTS void bitwise_and(const oclMat &src1, const Scalar &s, oclMat &dst, const oclMat &mask = oclMat()); - - //! calculates per-element bit-wise "exclusive or" operation - // supports all types - CV_EXPORTS void bitwise_xor(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask = oclMat()); - CV_EXPORTS void bitwise_xor(const oclMat &src1, const Scalar &s, oclMat &dst, const oclMat &mask = oclMat()); - - //! Logical operators - CV_EXPORTS oclMat operator ~ (const oclMat &); - CV_EXPORTS oclMat operator | (const oclMat &, const oclMat &); - CV_EXPORTS oclMat operator & (const oclMat &, const oclMat &); - CV_EXPORTS oclMat operator ^ (const oclMat &, const oclMat &); - - - //! Mathematics operators - CV_EXPORTS oclMatExpr operator + (const oclMat &src1, const oclMat &src2); - CV_EXPORTS oclMatExpr operator - (const oclMat &src1, const oclMat &src2); - CV_EXPORTS oclMatExpr operator * (const oclMat &src1, const oclMat &src2); - CV_EXPORTS oclMatExpr operator / (const oclMat &src1, const oclMat &src2); - - struct CV_EXPORTS ConvolveBuf - { - Size result_size; - Size block_size; - Size user_block_size; - Size dft_size; - - oclMat image_spect, templ_spect, result_spect; - oclMat image_block, templ_block, result_data; - - void create(Size image_size, Size templ_size); - static Size estimateBlockSize(Size result_size, Size templ_size); - }; - - //! computes convolution of two images, may use discrete Fourier transform - // support only CV_32FC1 type - CV_EXPORTS void convolve(const oclMat &image, const oclMat &temp1, oclMat &result, bool ccorr = false); - CV_EXPORTS void convolve(const oclMat &image, const oclMat &temp1, oclMat &result, bool ccorr, ConvolveBuf& buf); - - //! Performs a per-element multiplication of two Fourier spectrums. - //! Only full (not packed) CV_32FC2 complex spectrums in the interleaved format are supported for now. - //! support only CV_32FC2 type - CV_EXPORTS void mulSpectrums(const oclMat &a, const oclMat &b, oclMat &c, int flags, float scale, bool conjB = false); - - CV_EXPORTS void cvtColor(const oclMat &src, oclMat &dst, int code, int dcn = 0); - - //! initializes a scaled identity matrix - CV_EXPORTS void setIdentity(oclMat& src, const Scalar & val = Scalar(1)); - - //! fills the output array with repeated copies of the input array - CV_EXPORTS void repeat(const oclMat & src, int ny, int nx, oclMat & dst); - - //////////////////////////////// Filter Engine //////////////////////////////// - - /*! - The Base Class for 1D or Row-wise Filters - - This is the base class for linear or non-linear filters that process 1D data. - In particular, such filters are used for the "horizontal" filtering parts in separable filters. - */ - class CV_EXPORTS BaseRowFilter_GPU - { - public: - BaseRowFilter_GPU(int ksize_, int anchor_, int bordertype_) : ksize(ksize_), anchor(anchor_), bordertype(bordertype_) {} - virtual ~BaseRowFilter_GPU() {} - virtual void operator()(const oclMat &src, oclMat &dst) = 0; - int ksize, anchor, bordertype; - }; - - /*! - The Base Class for Column-wise Filters - - This is the base class for linear or non-linear filters that process columns of 2D arrays. - Such filters are used for the "vertical" filtering parts in separable filters. - */ - class CV_EXPORTS BaseColumnFilter_GPU - { - public: - BaseColumnFilter_GPU(int ksize_, int anchor_, int bordertype_) : ksize(ksize_), anchor(anchor_), bordertype(bordertype_) {} - virtual ~BaseColumnFilter_GPU() {} - virtual void operator()(const oclMat &src, oclMat &dst) = 0; - int ksize, anchor, bordertype; - }; - - /*! - The Base Class for Non-Separable 2D Filters. - - This is the base class for linear or non-linear 2D filters. - */ - class CV_EXPORTS BaseFilter_GPU - { - public: - BaseFilter_GPU(const Size &ksize_, const Point &anchor_, const int &borderType_) - : ksize(ksize_), anchor(anchor_), borderType(borderType_) {} - virtual ~BaseFilter_GPU() {} - virtual void operator()(const oclMat &src, oclMat &dst) = 0; - Size ksize; - Point anchor; - int borderType; - }; - - /*! - The Base Class for Filter Engine. - - The class can be used to apply an arbitrary filtering operation to an image. - It contains all the necessary intermediate buffers. - */ - class CV_EXPORTS FilterEngine_GPU - { - public: - virtual ~FilterEngine_GPU() {} - - virtual void apply(const oclMat &src, oclMat &dst, Rect roi = Rect(0, 0, -1, -1)) = 0; - }; - - //! returns the non-separable filter engine with the specified filter - CV_EXPORTS Ptr createFilter2D_GPU(const Ptr filter2D); - - //! returns the primitive row filter with the specified kernel - CV_EXPORTS Ptr getLinearRowFilter_GPU(int srcType, int bufType, const Mat &rowKernel, - int anchor = -1, int bordertype = BORDER_DEFAULT); - - //! returns the primitive column filter with the specified kernel - CV_EXPORTS Ptr getLinearColumnFilter_GPU(int bufType, int dstType, const Mat &columnKernel, - int anchor = -1, int bordertype = BORDER_DEFAULT, double delta = 0.0); - - //! returns the separable linear filter engine - CV_EXPORTS Ptr createSeparableLinearFilter_GPU(int srcType, int dstType, const Mat &rowKernel, - const Mat &columnKernel, const Point &anchor = Point(-1, -1), double delta = 0.0, int bordertype = BORDER_DEFAULT, Size imgSize = Size(-1,-1)); - - //! returns the separable filter engine with the specified filters - CV_EXPORTS Ptr createSeparableFilter_GPU(const Ptr &rowFilter, - const Ptr &columnFilter); - - //! returns the Gaussian filter engine - CV_EXPORTS Ptr createGaussianFilter_GPU(int type, Size ksize, double sigma1, double sigma2 = 0, int bordertype = BORDER_DEFAULT, Size imgSize = Size(-1,-1)); - - //! returns filter engine for the generalized Sobel operator - CV_EXPORTS Ptr createDerivFilter_GPU( int srcType, int dstType, int dx, int dy, int ksize, int borderType = BORDER_DEFAULT, Size imgSize = Size(-1,-1) ); - - //! applies Laplacian operator to the image - // supports only ksize = 1 and ksize = 3 - CV_EXPORTS void Laplacian(const oclMat &src, oclMat &dst, int ddepth, int ksize = 1, double scale = 1, - double delta=0, int borderType=BORDER_DEFAULT); - - //! returns 2D box filter - // dst type must be the same as source type - CV_EXPORTS Ptr getBoxFilter_GPU(int srcType, int dstType, - const Size &ksize, Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT); - - //! returns box filter engine - CV_EXPORTS Ptr createBoxFilter_GPU(int srcType, int dstType, const Size &ksize, - const Point &anchor = Point(-1, -1), int borderType = BORDER_DEFAULT); - - //! returns 2D filter with the specified kernel - // supports: dst type must be the same as source type - CV_EXPORTS Ptr getLinearFilter_GPU(int srcType, int dstType, const Mat &kernel, const Size &ksize, - const Point &anchor = Point(-1, -1), int borderType = BORDER_DEFAULT); - - //! returns the non-separable linear filter engine - // supports: dst type must be the same as source type - CV_EXPORTS Ptr createLinearFilter_GPU(int srcType, int dstType, const Mat &kernel, - const Point &anchor = Point(-1, -1), int borderType = BORDER_DEFAULT); - - //! smooths the image using the normalized box filter - CV_EXPORTS void boxFilter(const oclMat &src, oclMat &dst, int ddepth, Size ksize, - Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT); - - //! returns 2D morphological filter - //! only MORPH_ERODE and MORPH_DILATE are supported - // supports CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 types - // kernel must have CV_8UC1 type, one rows and cols == ksize.width * ksize.height - CV_EXPORTS Ptr getMorphologyFilter_GPU(int op, int type, const Mat &kernel, const Size &ksize, - Point anchor = Point(-1, -1)); - - //! returns morphological filter engine. Only MORPH_ERODE and MORPH_DILATE are supported. - CV_EXPORTS Ptr createMorphologyFilter_GPU(int op, int type, const Mat &kernel, - const Point &anchor = Point(-1, -1), int iterations = 1); - - //! a synonym for normalized box filter - static inline void blur(const oclMat &src, oclMat &dst, Size ksize, Point anchor = Point(-1, -1), - int borderType = BORDER_CONSTANT) - { - boxFilter(src, dst, -1, ksize, anchor, borderType); - } - - //! applies non-separable 2D linear filter to the image - CV_EXPORTS void filter2D(const oclMat &src, oclMat &dst, int ddepth, const Mat &kernel, - Point anchor = Point(-1, -1), double delta = 0.0, int borderType = BORDER_DEFAULT); - - //! applies separable 2D linear filter to the image - CV_EXPORTS void sepFilter2D(const oclMat &src, oclMat &dst, int ddepth, const Mat &kernelX, const Mat &kernelY, - Point anchor = Point(-1, -1), double delta = 0.0, int bordertype = BORDER_DEFAULT); - - //! applies generalized Sobel operator to the image - // dst.type must equalize src.type - // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 - // supports border type: BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT,BORDER_REFLECT_101 - CV_EXPORTS void Sobel(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double delta = 0.0, int bordertype = BORDER_DEFAULT); - - //! applies the vertical or horizontal Scharr operator to the image - // dst.type must equalize src.type - // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 - // supports border type: BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT,BORDER_REFLECT_101 - CV_EXPORTS void Scharr(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, double scale = 1, double delta = 0.0, int bordertype = BORDER_DEFAULT); - - //! smooths the image using Gaussian filter. - // dst.type must equalize src.type - // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 - // supports border type: BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT,BORDER_REFLECT_101 - CV_EXPORTS void GaussianBlur(const oclMat &src, oclMat &dst, Size ksize, double sigma1, double sigma2 = 0, int bordertype = BORDER_DEFAULT); - - //! erodes the image (applies the local minimum operator) - // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 - CV_EXPORTS void erode( const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1, - - int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue()); - - - //! dilates the image (applies the local maximum operator) - // supports data type: CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 - CV_EXPORTS void dilate( const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1, - - int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue()); - - - //! applies an advanced morphological operation to the image - CV_EXPORTS void morphologyEx( const oclMat &src, oclMat &dst, int op, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1, - - int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue()); - - - ////////////////////////////// Image processing ////////////////////////////// - //! Does mean shift filtering on GPU. - CV_EXPORTS void meanShiftFiltering(const oclMat &src, oclMat &dst, int sp, int sr, - TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1)); - - //! Does mean shift procedure on GPU. - CV_EXPORTS void meanShiftProc(const oclMat &src, oclMat &dstr, oclMat &dstsp, int sp, int sr, - TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1)); - - //! Does mean shift segmentation with elimiation of small regions. - CV_EXPORTS void meanShiftSegmentation(const oclMat &src, Mat &dst, int sp, int sr, int minsize, - TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1)); - - //! applies fixed threshold to the image. - // supports CV_8UC1 and CV_32FC1 data type - // supports threshold type: THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV - CV_EXPORTS double threshold(const oclMat &src, oclMat &dst, double thresh, double maxVal, int type = THRESH_TRUNC); - - //! resizes the image - // Supports INTER_NEAREST, INTER_LINEAR - // supports CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 types - CV_EXPORTS void resize(const oclMat &src, oclMat &dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR); - - //! Applies a generic geometrical transformation to an image. - - // Supports INTER_NEAREST, INTER_LINEAR. - // Map1 supports CV_16SC2, CV_32FC2 types. - // Src supports CV_8UC1, CV_8UC2, CV_8UC4. - CV_EXPORTS void remap(const oclMat &src, oclMat &dst, oclMat &map1, oclMat &map2, int interpolation, int bordertype, const Scalar &value = Scalar()); - - //! copies 2D array to a larger destination array and pads borders with user-specifiable constant - // supports CV_8UC1, CV_8UC4, CV_32SC1 types - CV_EXPORTS void copyMakeBorder(const oclMat &src, oclMat &dst, int top, int bottom, int left, int right, int boardtype, const Scalar &value = Scalar()); - - //! Smoothes image using median filter - // The source 1- or 4-channel image. m should be 3 or 5, the image depth should be CV_8U or CV_32F. - CV_EXPORTS void medianFilter(const oclMat &src, oclMat &dst, int m); - - //! warps the image using affine transformation - // Supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC - // supports CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 types - CV_EXPORTS void warpAffine(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags = INTER_LINEAR); - - //! warps the image using perspective transformation - // Supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC - // supports CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 types - CV_EXPORTS void warpPerspective(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags = INTER_LINEAR); - - //! computes the integral image and integral for the squared image - // sum will support CV_32S, CV_32F, sqsum - support CV32F, CV_64F - // supports only CV_8UC1 source type - CV_EXPORTS void integral(const oclMat &src, oclMat &sum, oclMat &sqsum, int sdepth=-1 ); - CV_EXPORTS void integral(const oclMat &src, oclMat &sum, int sdepth=-1 ); - CV_EXPORTS void cornerHarris(const oclMat &src, oclMat &dst, int blockSize, int ksize, double k, int bordertype = cv::BORDER_DEFAULT); - CV_EXPORTS void cornerHarris_dxdy(const oclMat &src, oclMat &dst, oclMat &Dx, oclMat &Dy, - int blockSize, int ksize, double k, int bordertype = cv::BORDER_DEFAULT); - CV_EXPORTS void cornerMinEigenVal(const oclMat &src, oclMat &dst, int blockSize, int ksize, int bordertype = cv::BORDER_DEFAULT); - CV_EXPORTS void cornerMinEigenVal_dxdy(const oclMat &src, oclMat &dst, oclMat &Dx, oclMat &Dy, - int blockSize, int ksize, int bordertype = cv::BORDER_DEFAULT); - - - /////////////////////////////////// ML /////////////////////////////////////////// - - //! Compute closest centers for each lines in source and lable it after center's index - // supports CV_32FC1/CV_32FC2/CV_32FC4 data type - // supports NORM_L1 and NORM_L2 distType - // if indices is provided, only the indexed rows will be calculated and their results are in the same - // order of indices - CV_EXPORTS void distanceToCenters(const oclMat &src, const oclMat ¢ers, Mat &dists, Mat &labels, int distType = NORM_L2SQR); - - //!Does k-means procedure on GPU - // supports CV_32FC1/CV_32FC2/CV_32FC4 data type - CV_EXPORTS double kmeans(const oclMat &src, int K, oclMat &bestLabels, - TermCriteria criteria, int attemps, int flags, oclMat ¢ers); - - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////////////CascadeClassifier////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - class CV_EXPORTS OclCascadeClassifier : public cv::CascadeClassifier - { - public: - void detectMultiScale(oclMat &image, CV_OUT std::vector& faces, - double scaleFactor = 1.1, int minNeighbors = 3, int flags = 0, - Size minSize = Size(), Size maxSize = Size()); - }; - - /////////////////////////////// Pyramid ///////////////////////////////////// - CV_EXPORTS void pyrDown(const oclMat &src, oclMat &dst); - - //! upsamples the source image and then smoothes it - CV_EXPORTS void pyrUp(const oclMat &src, oclMat &dst); - - //! performs linear blending of two images - //! to avoid accuracy errors sum of weigths shouldn't be very close to zero - // supports only CV_8UC1 source type - CV_EXPORTS void blendLinear(const oclMat &img1, const oclMat &img2, const oclMat &weights1, const oclMat &weights2, oclMat &result); - - //! computes vertical sum, supports only CV_32FC1 images - CV_EXPORTS void columnSum(const oclMat &src, oclMat &sum); - - ///////////////////////////////////////// match_template ///////////////////////////////////////////////////////////// - struct CV_EXPORTS MatchTemplateBuf - { - Size user_block_size; - oclMat imagef, templf; - std::vector images; - std::vector image_sums; - std::vector image_sqsums; - }; - - //! computes the proximity map for the raster template and the image where the template is searched for - // Supports TM_SQDIFF, TM_SQDIFF_NORMED, TM_CCORR, TM_CCORR_NORMED, TM_CCOEFF, TM_CCOEFF_NORMED for type 8UC1 and 8UC4 - // Supports TM_SQDIFF, TM_CCORR for type 32FC1 and 32FC4 - CV_EXPORTS void matchTemplate(const oclMat &image, const oclMat &templ, oclMat &result, int method); - - //! computes the proximity map for the raster template and the image where the template is searched for - // Supports TM_SQDIFF, TM_SQDIFF_NORMED, TM_CCORR, TM_CCORR_NORMED, TM_CCOEFF, TM_CCOEFF_NORMED for type 8UC1 and 8UC4 - // Supports TM_SQDIFF, TM_CCORR for type 32FC1 and 32FC4 - CV_EXPORTS void matchTemplate(const oclMat &image, const oclMat &templ, oclMat &result, int method, MatchTemplateBuf &buf); - - - - ///////////////////////////////////////////// Canny ///////////////////////////////////////////// - struct CV_EXPORTS CannyBuf; - - //! compute edges of the input image using Canny operator - // Support CV_8UC1 only - CV_EXPORTS void Canny(const oclMat &image, oclMat &edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false); - CV_EXPORTS void Canny(const oclMat &image, CannyBuf &buf, oclMat &edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false); - CV_EXPORTS void Canny(const oclMat &dx, const oclMat &dy, oclMat &edges, double low_thresh, double high_thresh, bool L2gradient = false); - CV_EXPORTS void Canny(const oclMat &dx, const oclMat &dy, CannyBuf &buf, oclMat &edges, double low_thresh, double high_thresh, bool L2gradient = false); - - struct CV_EXPORTS CannyBuf - { - CannyBuf() : counter(1, 1, CV_32S) { } - ~CannyBuf() - { - release(); - } - explicit CannyBuf(const Size &image_size, int apperture_size = 3) : counter(1, 1, CV_32S) - { - create(image_size, apperture_size); - } - CannyBuf(const oclMat &dx_, const oclMat &dy_); - void create(const Size &image_size, int apperture_size = 3); - void release(); - - oclMat dx, dy; - oclMat dx_buf, dy_buf; - oclMat magBuf, mapBuf; - oclMat trackBuf1, trackBuf2; - oclMat counter; - Ptr filterDX, filterDY; - }; - - ///////////////////////////////////////// Hough Transform ///////////////////////////////////////// - //! HoughCircles - struct HoughCirclesBuf - { - oclMat edges; - oclMat accum; - oclMat srcPoints; - oclMat centers; - CannyBuf cannyBuf; - }; - - CV_EXPORTS void HoughCircles(const oclMat& src, oclMat& circles, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096); - CV_EXPORTS void HoughCircles(const oclMat& src, oclMat& circles, HoughCirclesBuf& buf, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096); - CV_EXPORTS void HoughCirclesDownload(const oclMat& d_circles, OutputArray h_circles); - - - ///////////////////////////////////////// clAmdFft related ///////////////////////////////////////// - //! Performs a forward or inverse discrete Fourier transform (1D or 2D) of floating point matrix. - //! Param dft_size is the size of DFT transform. - //! - //! For complex-to-real transform it is assumed that the source matrix is packed in CLFFT's format. - // support src type of CV32FC1, CV32FC2 - // support flags: DFT_INVERSE, DFT_REAL_OUTPUT, DFT_COMPLEX_OUTPUT, DFT_ROWS - // dft_size is the size of original input, which is used for transformation from complex to real. - // dft_size must be powers of 2, 3 and 5 - // real to complex dft requires at least v1.8 clAmdFft - // real to complex dft output is not the same with cpu version - // real to complex and complex to real does not support DFT_ROWS - CV_EXPORTS void dft(const oclMat &src, oclMat &dst, Size dft_size = Size(), int flags = 0); - - //! implements generalized matrix product algorithm GEMM from BLAS - // The functionality requires clAmdBlas library - // only support type CV_32FC1 - // flag GEMM_3_T is not supported - CV_EXPORTS void gemm(const oclMat &src1, const oclMat &src2, double alpha, - const oclMat &src3, double beta, oclMat &dst, int flags = 0); - - //////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector ////////////// - - struct CV_EXPORTS HOGDescriptor - - { - - enum { DEFAULT_WIN_SIGMA = -1 }; - - enum { DEFAULT_NLEVELS = 64 }; - - enum { DESCR_FORMAT_ROW_BY_ROW, DESCR_FORMAT_COL_BY_COL }; - - - - HOGDescriptor(Size win_size = Size(64, 128), Size block_size = Size(16, 16), - - Size block_stride = Size(8, 8), Size cell_size = Size(8, 8), - - int nbins = 9, double win_sigma = DEFAULT_WIN_SIGMA, - - double threshold_L2hys = 0.2, bool gamma_correction = true, - - int nlevels = DEFAULT_NLEVELS); - - - - size_t getDescriptorSize() const; - - size_t getBlockHistogramSize() const; - - - - void setSVMDetector(const std::vector &detector); - - - - static std::vector getDefaultPeopleDetector(); - - static std::vector getPeopleDetector48x96(); - - static std::vector getPeopleDetector64x128(); - - - - void detect(const oclMat &img, std::vector &found_locations, - - double hit_threshold = 0, Size win_stride = Size(), - - Size padding = Size()); - - - - void detectMultiScale(const oclMat &img, std::vector &found_locations, - - double hit_threshold = 0, Size win_stride = Size(), - - Size padding = Size(), double scale0 = 1.05, - - int group_threshold = 2); - - - - void getDescriptors(const oclMat &img, Size win_stride, - - oclMat &descriptors, - - int descr_format = DESCR_FORMAT_COL_BY_COL); - - - - Size win_size; - - Size block_size; - - Size block_stride; - - Size cell_size; - - int nbins; - - double win_sigma; - - double threshold_L2hys; - - bool gamma_correction; - - int nlevels; - - - - protected: - - // initialize buffers; only need to do once in case of multiscale detection - - void init_buffer(const oclMat &img, Size win_stride); - - - - void computeBlockHistograms(const oclMat &img); - - void computeGradient(const oclMat &img, oclMat &grad, oclMat &qangle); - - - - double getWinSigma() const; - - bool checkDetectorSize() const; - - - - static int numPartsWithin(int size, int part_size, int stride); - - static Size numPartsWithin(Size size, Size part_size, Size stride); - - - - // Coefficients of the separating plane - - float free_coef; - - oclMat detector; - - - - // Results of the last classification step - - oclMat labels; - - Mat labels_host; - - - - // Results of the last histogram evaluation step - - oclMat block_hists; - - - - // Gradients conputation results - - oclMat grad, qangle; - - - - // scaled image - - oclMat image_scale; - - - - // effect size of input image (might be different from original size after scaling) - - Size effect_size; - - }; - - - ////////////////////////feature2d_ocl///////////////// - /****************************************************************************************\ - * Distance * - \****************************************************************************************/ - template - struct CV_EXPORTS Accumulator - { - typedef T Type; - }; - template<> struct Accumulator - { - typedef float Type; - }; - template<> struct Accumulator - { - typedef float Type; - }; - template<> struct Accumulator - { - typedef float Type; - }; - template<> struct Accumulator - { - typedef float Type; - }; - - /* - * Manhattan distance (city block distance) functor - */ - template - struct CV_EXPORTS L1 - { - enum { normType = NORM_L1 }; - typedef T ValueType; - typedef typename Accumulator::Type ResultType; - - ResultType operator()( const T *a, const T *b, int size ) const - { - return normL1(a, b, size); - } - }; - - /* - * Euclidean distance functor - */ - template - struct CV_EXPORTS L2 - { - enum { normType = NORM_L2 }; - typedef T ValueType; - typedef typename Accumulator::Type ResultType; - - ResultType operator()( const T *a, const T *b, int size ) const - { - return (ResultType)std::sqrt((double)normL2Sqr(a, b, size)); - } - }; - - /* - * Hamming distance functor - counts the bit differences between two strings - useful for the Brief descriptor - * bit count of A exclusive XOR'ed with B - */ - struct CV_EXPORTS Hamming - { - enum { normType = NORM_HAMMING }; - typedef unsigned char ValueType; - typedef int ResultType; - - /** this will count the bits in a ^ b - */ - ResultType operator()( const unsigned char *a, const unsigned char *b, int size ) const - { - return normHamming(a, b, size); - } - }; - - ////////////////////////////////// BruteForceMatcher ////////////////////////////////// - - class CV_EXPORTS BruteForceMatcher_OCL_base - { - public: - enum DistType {L1Dist = 0, L2Dist, HammingDist}; - explicit BruteForceMatcher_OCL_base(DistType distType = L2Dist); - - // Add descriptors to train descriptor collection - void add(const std::vector &descCollection); - - // Get train descriptors collection - const std::vector &getTrainDescriptors() const; - - // Clear train descriptors collection - void clear(); - - // Return true if there are not train descriptors in collection - bool empty() const; - - // Return true if the matcher supports mask in match methods - bool isMaskSupported() const; - - // Find one best match for each query descriptor - void matchSingle(const oclMat &query, const oclMat &train, - oclMat &trainIdx, oclMat &distance, - const oclMat &mask = oclMat()); - - // Download trainIdx and distance and convert it to CPU vector with DMatch - static void matchDownload(const oclMat &trainIdx, const oclMat &distance, std::vector &matches); - // Convert trainIdx and distance to vector with DMatch - static void matchConvert(const Mat &trainIdx, const Mat &distance, std::vector &matches); - - // Find one best match for each query descriptor - void match(const oclMat &query, const oclMat &train, std::vector &matches, const oclMat &mask = oclMat()); - - // Make gpu collection of trains and masks in suitable format for matchCollection function - void makeGpuCollection(oclMat &trainCollection, oclMat &maskCollection, const std::vector &masks = std::vector()); - - // Find one best match from train collection for each query descriptor - void matchCollection(const oclMat &query, const oclMat &trainCollection, - oclMat &trainIdx, oclMat &imgIdx, oclMat &distance, - const oclMat &masks = oclMat()); - - // Download trainIdx, imgIdx and distance and convert it to vector with DMatch - static void matchDownload(const oclMat &trainIdx, const oclMat &imgIdx, const oclMat &distance, std::vector &matches); - // Convert trainIdx, imgIdx and distance to vector with DMatch - static void matchConvert(const Mat &trainIdx, const Mat &imgIdx, const Mat &distance, std::vector &matches); - - // Find one best match from train collection for each query descriptor. - void match(const oclMat &query, std::vector &matches, const std::vector &masks = std::vector()); - - // Find k best matches for each query descriptor (in increasing order of distances) - void knnMatchSingle(const oclMat &query, const oclMat &train, - oclMat &trainIdx, oclMat &distance, oclMat &allDist, int k, - const oclMat &mask = oclMat()); - - // Download trainIdx and distance and convert it to vector with DMatch - // compactResult is used when mask is not empty. If compactResult is false matches - // vector will have the same size as queryDescriptors rows. If compactResult is true - // matches vector will not contain matches for fully masked out query descriptors. - static void knnMatchDownload(const oclMat &trainIdx, const oclMat &distance, - std::vector< std::vector > &matches, bool compactResult = false); - // Convert trainIdx and distance to vector with DMatch - static void knnMatchConvert(const Mat &trainIdx, const Mat &distance, - std::vector< std::vector > &matches, bool compactResult = false); - - // Find k best matches for each query descriptor (in increasing order of distances). - // compactResult is used when mask is not empty. If compactResult is false matches - // vector will have the same size as queryDescriptors rows. If compactResult is true - // matches vector will not contain matches for fully masked out query descriptors. - void knnMatch(const oclMat &query, const oclMat &train, - std::vector< std::vector > &matches, int k, const oclMat &mask = oclMat(), - bool compactResult = false); - - // Find k best matches from train collection for each query descriptor (in increasing order of distances) - void knnMatch2Collection(const oclMat &query, const oclMat &trainCollection, - oclMat &trainIdx, oclMat &imgIdx, oclMat &distance, - const oclMat &maskCollection = oclMat()); - - // Download trainIdx and distance and convert it to vector with DMatch - // compactResult is used when mask is not empty. If compactResult is false matches - // vector will have the same size as queryDescriptors rows. If compactResult is true - // matches vector will not contain matches for fully masked out query descriptors. - static void knnMatch2Download(const oclMat &trainIdx, const oclMat &imgIdx, const oclMat &distance, - std::vector< std::vector > &matches, bool compactResult = false); - // Convert trainIdx and distance to vector with DMatch - static void knnMatch2Convert(const Mat &trainIdx, const Mat &imgIdx, const Mat &distance, - std::vector< std::vector > &matches, bool compactResult = false); - - // Find k best matches for each query descriptor (in increasing order of distances). - // compactResult is used when mask is not empty. If compactResult is false matches - // vector will have the same size as queryDescriptors rows. If compactResult is true - // matches vector will not contain matches for fully masked out query descriptors. - void knnMatch(const oclMat &query, std::vector< std::vector > &matches, int k, - const std::vector &masks = std::vector(), bool compactResult = false); - - // Find best matches for each query descriptor which have distance less than maxDistance. - // nMatches.at(0, queryIdx) will contain matches count for queryIdx. - // carefully nMatches can be greater than trainIdx.cols - it means that matcher didn't find all matches, - // because it didn't have enough memory. - // If trainIdx is empty, then trainIdx and distance will be created with size nQuery x max((nTrain / 100), 10), - // otherwize user can pass own allocated trainIdx and distance with size nQuery x nMaxMatches - // Matches doesn't sorted. - void radiusMatchSingle(const oclMat &query, const oclMat &train, - oclMat &trainIdx, oclMat &distance, oclMat &nMatches, float maxDistance, - const oclMat &mask = oclMat()); - - // Download trainIdx, nMatches and distance and convert it to vector with DMatch. - // matches will be sorted in increasing order of distances. - // compactResult is used when mask is not empty. If compactResult is false matches - // vector will have the same size as queryDescriptors rows. If compactResult is true - // matches vector will not contain matches for fully masked out query descriptors. - static void radiusMatchDownload(const oclMat &trainIdx, const oclMat &distance, const oclMat &nMatches, - std::vector< std::vector > &matches, bool compactResult = false); - // Convert trainIdx, nMatches and distance to vector with DMatch. - static void radiusMatchConvert(const Mat &trainIdx, const Mat &distance, const Mat &nMatches, - std::vector< std::vector > &matches, bool compactResult = false); - - // Find best matches for each query descriptor which have distance less than maxDistance - // in increasing order of distances). - void radiusMatch(const oclMat &query, const oclMat &train, - std::vector< std::vector > &matches, float maxDistance, - const oclMat &mask = oclMat(), bool compactResult = false); - - // Find best matches for each query descriptor which have distance less than maxDistance. - // If trainIdx is empty, then trainIdx and distance will be created with size nQuery x max((nQuery / 100), 10), - // otherwize user can pass own allocated trainIdx and distance with size nQuery x nMaxMatches - // Matches doesn't sorted. - void radiusMatchCollection(const oclMat &query, oclMat &trainIdx, oclMat &imgIdx, oclMat &distance, oclMat &nMatches, float maxDistance, - const std::vector &masks = std::vector()); - - // Download trainIdx, imgIdx, nMatches and distance and convert it to vector with DMatch. - // matches will be sorted in increasing order of distances. - // compactResult is used when mask is not empty. If compactResult is false matches - // vector will have the same size as queryDescriptors rows. If compactResult is true - // matches vector will not contain matches for fully masked out query descriptors. - static void radiusMatchDownload(const oclMat &trainIdx, const oclMat &imgIdx, const oclMat &distance, const oclMat &nMatches, - std::vector< std::vector > &matches, bool compactResult = false); - // Convert trainIdx, nMatches and distance to vector with DMatch. - static void radiusMatchConvert(const Mat &trainIdx, const Mat &imgIdx, const Mat &distance, const Mat &nMatches, - std::vector< std::vector > &matches, bool compactResult = false); - - // Find best matches from train collection for each query descriptor which have distance less than - // maxDistance (in increasing order of distances). - void radiusMatch(const oclMat &query, std::vector< std::vector > &matches, float maxDistance, - const std::vector &masks = std::vector(), bool compactResult = false); - - DistType distType; - - private: - std::vector trainDescCollection; - }; - - template - class CV_EXPORTS BruteForceMatcher_OCL; - - template - class CV_EXPORTS BruteForceMatcher_OCL< L1 > : public BruteForceMatcher_OCL_base - { - public: - explicit BruteForceMatcher_OCL() : BruteForceMatcher_OCL_base(L1Dist) {} - explicit BruteForceMatcher_OCL(L1 /*d*/) : BruteForceMatcher_OCL_base(L1Dist) {} - }; - template - class CV_EXPORTS BruteForceMatcher_OCL< L2 > : public BruteForceMatcher_OCL_base - { - public: - explicit BruteForceMatcher_OCL() : BruteForceMatcher_OCL_base(L2Dist) {} - explicit BruteForceMatcher_OCL(L2 /*d*/) : BruteForceMatcher_OCL_base(L2Dist) {} - }; - template <> class CV_EXPORTS BruteForceMatcher_OCL< Hamming > : public BruteForceMatcher_OCL_base - { - public: - explicit BruteForceMatcher_OCL() : BruteForceMatcher_OCL_base(HammingDist) {} - explicit BruteForceMatcher_OCL(Hamming /*d*/) : BruteForceMatcher_OCL_base(HammingDist) {} - }; - - class CV_EXPORTS BFMatcher_OCL : public BruteForceMatcher_OCL_base - { - public: - explicit BFMatcher_OCL(int norm = NORM_L2) : BruteForceMatcher_OCL_base(norm == NORM_L1 ? L1Dist : norm == NORM_L2 ? L2Dist : HammingDist) {} - }; - - class CV_EXPORTS GoodFeaturesToTrackDetector_OCL - { - public: - explicit GoodFeaturesToTrackDetector_OCL(int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 0.0, - int blockSize = 3, bool useHarrisDetector = false, double harrisK = 0.04); - - //! return 1 rows matrix with CV_32FC2 type - void operator ()(const oclMat& image, oclMat& corners, const oclMat& mask = oclMat()); - //! download points of type Point2f to a vector. the vector's content will be erased - void downloadPoints(const oclMat &points, std::vector &points_v); - - int maxCorners; - double qualityLevel; - double minDistance; - - int blockSize; - bool useHarrisDetector; - double harrisK; - void releaseMemory() - { - Dx_.release(); - Dy_.release(); - eig_.release(); - minMaxbuf_.release(); - tmpCorners_.release(); - } - private: - oclMat Dx_; - oclMat Dy_; - oclMat eig_; - oclMat eig_minmax_; - oclMat minMaxbuf_; - oclMat tmpCorners_; - oclMat counter_; - }; - - inline GoodFeaturesToTrackDetector_OCL::GoodFeaturesToTrackDetector_OCL(int maxCorners_, double qualityLevel_, double minDistance_, - int blockSize_, bool useHarrisDetector_, double harrisK_) - { - maxCorners = maxCorners_; - qualityLevel = qualityLevel_; - minDistance = minDistance_; - blockSize = blockSize_; - useHarrisDetector = useHarrisDetector_; - harrisK = harrisK_; - } - - ////////////////////////////////// FAST Feature Detector ////////////////////////////////// - class CV_EXPORTS FAST_OCL - { - public: - enum - { - X_ROW = 0, - Y_ROW, - RESPONSE_ROW, - ROWS_COUNT - }; - - // all features have same size - static const int FEATURE_SIZE = 7; - - explicit FAST_OCL(int threshold, bool nonmaxSupression = true, double keypointsRatio = 0.05); - - //! finds the keypoints using FAST detector - //! supports only CV_8UC1 images - void operator ()(const oclMat& image, const oclMat& mask, oclMat& keypoints); - void operator ()(const oclMat& image, const oclMat& mask, std::vector& keypoints); - - //! download keypoints from device to host memory - static void downloadKeypoints(const oclMat& d_keypoints, std::vector& keypoints); - - //! convert keypoints to KeyPoint vector - static void convertKeypoints(const Mat& h_keypoints, std::vector& keypoints); - - //! release temporary buffer's memory - void release(); - - bool nonmaxSupression; - - int threshold; - - //! max keypoints = keypointsRatio * img.size().area() - double keypointsRatio; - - //! find keypoints and compute it's response if nonmaxSupression is true - //! return count of detected keypoints - int calcKeyPointsLocation(const oclMat& image, const oclMat& mask); - - //! get final array of keypoints - //! performs nonmax supression if needed - //! return final count of keypoints - int getKeyPoints(oclMat& keypoints); - - private: - oclMat kpLoc_; - int count_; - - oclMat score_; - - oclMat d_keypoints_; - - int calcKeypointsOCL(const oclMat& img, const oclMat& mask, int maxKeypoints); - int nonmaxSupressionOCL(oclMat& keypoints); - }; - - ////////////////////////////////// BRIEF Feature Descriptor ////////////////////////////////// - - class CV_EXPORTS BRIEF_OCL - { - public: - static const int PATCH_SIZE = 48; - static const int KERNEL_SIZE = 9; - - explicit BRIEF_OCL(int _bytes = 32); - - //!computes the brief descriptor for a set of given keypoints - //! supports only CV_8UC1 images - void compute(const oclMat& image, const oclMat& keypoints, oclMat& mask, oclMat& descriptors) const; - - static int getBorderSize(); - protected: - - int bytes; - }; - - ////////////////////////////////// ORB Descriptor Extractor ////////////////////////////////// - class CV_EXPORTS ORB_OCL - { - public: - enum - { - X_ROW = 0, - Y_ROW, - RESPONSE_ROW, - ANGLE_ROW, - OCTAVE_ROW, - SIZE_ROW, - ROWS_COUNT - }; - - enum - { - DEFAULT_FAST_THRESHOLD = 20 - }; - - //! Constructor - explicit ORB_OCL(int nFeatures = 500, float scaleFactor = 1.2f, int nLevels = 8, int edgeThreshold = 31, - int firstLevel = 0, int WTA_K = 2, int scoreType = 0, int patchSize = 31); - - //! Compute the ORB features on an image - //! image - the image to compute the features (supports only CV_8UC1 images) - //! mask - the mask to apply - //! keypoints - the resulting keypoints - void operator ()(const oclMat& image, const oclMat& mask, std::vector& keypoints); - void operator ()(const oclMat& image, const oclMat& mask, oclMat& keypoints); - - //! Compute the ORB features and descriptors on an image - //! image - the image to compute the features (supports only CV_8UC1 images) - //! mask - the mask to apply - //! keypoints - the resulting keypoints - //! descriptors - descriptors array - void operator ()(const oclMat& image, const oclMat& mask, std::vector& keypoints, oclMat& descriptors); - void operator ()(const oclMat& image, const oclMat& mask, oclMat& keypoints, oclMat& descriptors); - - //! download keypoints from device to host memory - static void downloadKeyPoints(const oclMat& d_keypoints, std::vector& keypoints); - //! convert keypoints to KeyPoint vector - static void convertKeyPoints(const Mat& d_keypoints, std::vector& keypoints); - - //! returns the descriptor size in bytes - inline int descriptorSize() const { return kBytes; } - inline int descriptorType() const { return CV_8U; } - inline int defaultNorm() const { return NORM_HAMMING; } - - inline void setFastParams(int threshold, bool nonmaxSupression = true) - { - fastDetector_.threshold = threshold; - fastDetector_.nonmaxSupression = nonmaxSupression; - } - - //! release temporary buffer's memory - void release(); - - //! if true, image will be blurred before descriptors calculation - bool blurForDescriptor; - - private: - enum { kBytes = 32 }; - - void buildScalePyramids(const oclMat& image, const oclMat& mask); - - void computeKeyPointsPyramid(); - - void computeDescriptors(oclMat& descriptors); - - void mergeKeyPoints(oclMat& keypoints); - - int nFeatures_; - float scaleFactor_; - int nLevels_; - int edgeThreshold_; - int firstLevel_; - int WTA_K_; - int scoreType_; - int patchSize_; - - // The number of desired features per scale - std::vector n_features_per_level_; - - // Points to compute BRIEF descriptors from - oclMat pattern_; - - std::vector imagePyr_; - std::vector maskPyr_; - - oclMat buf_; - - std::vector keyPointsPyr_; - std::vector keyPointsCount_; - - FAST_OCL fastDetector_; - - Ptr blurFilter; - - oclMat d_keypoints_; - - oclMat uMax_; - }; - - /////////////////////////////// PyrLKOpticalFlow ///////////////////////////////////// - - class CV_EXPORTS PyrLKOpticalFlow - { - public: - PyrLKOpticalFlow() - { - winSize = Size(21, 21); - maxLevel = 3; - iters = 30; - derivLambda = 0.5; - useInitialFlow = false; - minEigThreshold = 1e-4f; - getMinEigenVals = false; - isDeviceArch11_ = false; - } - - void sparse(const oclMat &prevImg, const oclMat &nextImg, const oclMat &prevPts, oclMat &nextPts, - oclMat &status, oclMat *err = 0); - - void dense(const oclMat &prevImg, const oclMat &nextImg, oclMat &u, oclMat &v, oclMat *err = 0); - - Size winSize; - int maxLevel; - int iters; - double derivLambda; - bool useInitialFlow; - float minEigThreshold; - bool getMinEigenVals; - - void releaseMemory() - { - dx_calcBuf_.release(); - dy_calcBuf_.release(); - - prevPyr_.clear(); - nextPyr_.clear(); - - dx_buf_.release(); - dy_buf_.release(); - } - - private: - void calcSharrDeriv(const oclMat &src, oclMat &dx, oclMat &dy); - - void buildImagePyramid(const oclMat &img0, std::vector &pyr, bool withBorder); - - oclMat dx_calcBuf_; - oclMat dy_calcBuf_; - - std::vector prevPyr_; - std::vector nextPyr_; - - oclMat dx_buf_; - oclMat dy_buf_; - - oclMat uPyr_[2]; - oclMat vPyr_[2]; - - bool isDeviceArch11_; - }; - - class CV_EXPORTS FarnebackOpticalFlow - { - public: - FarnebackOpticalFlow(); - - int numLevels; - double pyrScale; - bool fastPyramids; - int winSize; - int numIters; - int polyN; - double polySigma; - int flags; - - void operator ()(const oclMat &frame0, const oclMat &frame1, oclMat &flowx, oclMat &flowy); - - void releaseMemory(); - - private: - void prepareGaussian( - int n, double sigma, float *g, float *xg, float *xxg, - double &ig11, double &ig03, double &ig33, double &ig55); - - void setPolynomialExpansionConsts(int n, double sigma); - - void updateFlow_boxFilter( - const oclMat& R0, const oclMat& R1, oclMat& flowx, oclMat &flowy, - oclMat& M, oclMat &bufM, int blockSize, bool updateMatrices); - - void updateFlow_gaussianBlur( - const oclMat& R0, const oclMat& R1, oclMat& flowx, oclMat& flowy, - oclMat& M, oclMat &bufM, int blockSize, bool updateMatrices); - - oclMat frames_[2]; - oclMat pyrLevel_[2], M_, bufM_, R_[2], blurredFrame_[2]; - std::vector pyramid0_, pyramid1_; - }; - - //////////////// build warping maps //////////////////// - //! builds plane warping maps - CV_EXPORTS void buildWarpPlaneMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat &R, const Mat &T, float scale, oclMat &map_x, oclMat &map_y); - //! builds cylindrical warping maps - CV_EXPORTS void buildWarpCylindricalMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat &R, float scale, oclMat &map_x, oclMat &map_y); - //! builds spherical warping maps - CV_EXPORTS void buildWarpSphericalMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat &R, float scale, oclMat &map_x, oclMat &map_y); - //! builds Affine warping maps - CV_EXPORTS void buildWarpAffineMaps(const Mat &M, bool inverse, Size dsize, oclMat &xmap, oclMat &ymap); - - //! builds Perspective warping maps - CV_EXPORTS void buildWarpPerspectiveMaps(const Mat &M, bool inverse, Size dsize, oclMat &xmap, oclMat &ymap); - - ///////////////////////////////////// interpolate frames ////////////////////////////////////////////// - //! Interpolate frames (images) using provided optical flow (displacement field). - //! frame0 - frame 0 (32-bit floating point images, single channel) - //! frame1 - frame 1 (the same type and size) - //! fu - forward horizontal displacement - //! fv - forward vertical displacement - //! bu - backward horizontal displacement - //! bv - backward vertical displacement - //! pos - new frame position - //! newFrame - new frame - //! buf - temporary buffer, will have width x 6*height size, CV_32FC1 type and contain 6 oclMat; - //! occlusion masks 0, occlusion masks 1, - //! interpolated forward flow 0, interpolated forward flow 1, - //! interpolated backward flow 0, interpolated backward flow 1 - //! - CV_EXPORTS void interpolateFrames(const oclMat &frame0, const oclMat &frame1, - const oclMat &fu, const oclMat &fv, - const oclMat &bu, const oclMat &bv, - float pos, oclMat &newFrame, oclMat &buf); - - //! computes moments of the rasterized shape or a vector of points - //! _array should be a vector a points standing for the contour - CV_EXPORTS Moments ocl_moments(InputArray contour); - //! src should be a general image uploaded to the GPU. - //! the supported oclMat type are CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1 and CV_64FC1 - //! to use type of CV_64FC1, the GPU should support CV_64FC1 - CV_EXPORTS Moments ocl_moments(oclMat& src, bool binary); - - class CV_EXPORTS StereoBM_OCL - { - public: - enum { BASIC_PRESET = 0, PREFILTER_XSOBEL = 1 }; - - enum { DEFAULT_NDISP = 64, DEFAULT_WINSZ = 19 }; - - //! the default constructor - StereoBM_OCL(); - //! the full constructor taking the camera-specific preset, number of disparities and the SAD window size. ndisparities must be multiple of 8. - StereoBM_OCL(int preset, int ndisparities = DEFAULT_NDISP, int winSize = DEFAULT_WINSZ); - - //! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair - //! Output disparity has CV_8U type. - void operator() ( const oclMat &left, const oclMat &right, oclMat &disparity); - - //! Some heuristics that tries to estmate - // if current GPU will be faster then CPU in this algorithm. - // It queries current active device. - static bool checkIfGpuCallReasonable(); - - int preset; - int ndisp; - int winSize; - - // If avergeTexThreshold == 0 => post procesing is disabled - // If avergeTexThreshold != 0 then disparity is set 0 in each point (x,y) where for left image - // SumOfHorizontalGradiensInWindow(x, y, winSize) < (winSize * winSize) * avergeTexThreshold - // i.e. input left image is low textured. - float avergeTexThreshold; - private: - oclMat minSSD, leBuf, riBuf; - }; - - class CV_EXPORTS StereoBeliefPropagation - { - public: - enum { DEFAULT_NDISP = 64 }; - enum { DEFAULT_ITERS = 5 }; - enum { DEFAULT_LEVELS = 5 }; - static void estimateRecommendedParams(int width, int height, int &ndisp, int &iters, int &levels); - explicit StereoBeliefPropagation(int ndisp = DEFAULT_NDISP, - int iters = DEFAULT_ITERS, - int levels = DEFAULT_LEVELS, - int msg_type = CV_16S); - StereoBeliefPropagation(int ndisp, int iters, int levels, - float max_data_term, float data_weight, - float max_disc_term, float disc_single_jump, - int msg_type = CV_32F); - void operator()(const oclMat &left, const oclMat &right, oclMat &disparity); - void operator()(const oclMat &data, oclMat &disparity); - int ndisp; - int iters; - int levels; - float max_data_term; - float data_weight; - float max_disc_term; - float disc_single_jump; - int msg_type; - private: - oclMat u, d, l, r, u2, d2, l2, r2; - std::vector datas; - oclMat out; - }; - - class CV_EXPORTS StereoConstantSpaceBP - { - public: - enum { DEFAULT_NDISP = 128 }; - enum { DEFAULT_ITERS = 8 }; - enum { DEFAULT_LEVELS = 4 }; - enum { DEFAULT_NR_PLANE = 4 }; - static void estimateRecommendedParams(int width, int height, int &ndisp, int &iters, int &levels, int &nr_plane); - explicit StereoConstantSpaceBP( - int ndisp = DEFAULT_NDISP, - int iters = DEFAULT_ITERS, - int levels = DEFAULT_LEVELS, - int nr_plane = DEFAULT_NR_PLANE, - int msg_type = CV_32F); - StereoConstantSpaceBP(int ndisp, int iters, int levels, int nr_plane, - float max_data_term, float data_weight, float max_disc_term, float disc_single_jump, - int min_disp_th = 0, - int msg_type = CV_32F); - void operator()(const oclMat &left, const oclMat &right, oclMat &disparity); - int ndisp; - int iters; - int levels; - int nr_plane; - float max_data_term; - float data_weight; - float max_disc_term; - float disc_single_jump; - int min_disp_th; - int msg_type; - bool use_local_init_data_cost; - private: - oclMat u[2], d[2], l[2], r[2]; - oclMat disp_selected_pyr[2]; - oclMat data_cost; - oclMat data_cost_selected; - oclMat temp; - oclMat out; - }; - - // Implementation of the Zach, Pock and Bischof Dual TV-L1 Optical Flow method - // - // see reference: - // [1] C. Zach, T. Pock and H. Bischof, "A Duality Based Approach for Realtime TV-L1 Optical Flow". - // [2] Javier Sanchez, Enric Meinhardt-Llopis and Gabriele Facciolo. "TV-L1 Optical Flow Estimation". - class CV_EXPORTS OpticalFlowDual_TVL1_OCL - { - public: - OpticalFlowDual_TVL1_OCL(); - - void operator ()(const oclMat& I0, const oclMat& I1, oclMat& flowx, oclMat& flowy); - - void collectGarbage(); - - /** - * Time step of the numerical scheme. - */ - double tau; - - /** - * Weight parameter for the data term, attachment parameter. - * This is the most relevant parameter, which determines the smoothness of the output. - * The smaller this parameter is, the smoother the solutions we obtain. - * It depends on the range of motions of the images, so its value should be adapted to each image sequence. - */ - double lambda; - - /** - * Weight parameter for (u - v)^2, tightness parameter. - * It serves as a link between the attachment and the regularization terms. - * In theory, it should have a small value in order to maintain both parts in correspondence. - * The method is stable for a large range of values of this parameter. - */ - double theta; - - /** - * Number of scales used to create the pyramid of images. - */ - int nscales; - - /** - * Number of warpings per scale. - * Represents the number of times that I1(x+u0) and grad( I1(x+u0) ) are computed per scale. - * This is a parameter that assures the stability of the method. - * It also affects the running time, so it is a compromise between speed and accuracy. - */ - int warps; - - /** - * Stopping criterion threshold used in the numerical scheme, which is a trade-off between precision and running time. - * A small value will yield more accurate solutions at the expense of a slower convergence. - */ - double epsilon; - - /** - * Stopping criterion iterations number used in the numerical scheme. - */ - int iterations; - - bool useInitialFlow; - - private: - void procOneScale(const oclMat& I0, const oclMat& I1, oclMat& u1, oclMat& u2); - - std::vector I0s; - std::vector I1s; - std::vector u1s; - std::vector u2s; - - oclMat I1x_buf; - oclMat I1y_buf; - - oclMat I1w_buf; - oclMat I1wx_buf; - oclMat I1wy_buf; - - oclMat grad_buf; - oclMat rho_c_buf; - - oclMat p11_buf; - oclMat p12_buf; - oclMat p21_buf; - oclMat p22_buf; - - oclMat diff_buf; - oclMat norm_buf; - }; - // current supported sorting methods - enum - { - SORT_BITONIC, // only support power-of-2 buffer size - SORT_SELECTION, // cannot sort duplicate keys - SORT_MERGE, - SORT_RADIX // only support signed int/float keys(CV_32S/CV_32F) - }; - //! Returns the sorted result of all the elements in input based on equivalent keys. - // - // The element unit in the values to be sorted is determined from the data type, - // i.e., a CV_32FC2 input {a1a2, b1b2} will be considered as two elements, regardless its - // matrix dimension. - // both keys and values will be sorted inplace - // Key needs to be single channel oclMat. - // - // Example: - // input - - // keys = {2, 3, 1} (CV_8UC1) - // values = {10,5, 4,3, 6,2} (CV_8UC2) - // sortByKey(keys, values, SORT_SELECTION, false); - // output - - // keys = {1, 2, 3} (CV_8UC1) - // values = {6,2, 10,5, 4,3} (CV_8UC2) - CV_EXPORTS void sortByKey(oclMat& keys, oclMat& values, int method, bool isGreaterThan = false); - /*!Base class for MOG and MOG2!*/ - class CV_EXPORTS BackgroundSubtractor - { - public: - //! the virtual destructor - virtual ~BackgroundSubtractor(); - //! the update operator that takes the next video frame and returns the current foreground mask as 8-bit binary image. - virtual void operator()(const oclMat& image, oclMat& fgmask, float learningRate); - - //! computes a background image - virtual void getBackgroundImage(oclMat& backgroundImage) const = 0; - }; - /*! - Gaussian Mixture-based Backbround/Foreground Segmentation Algorithm - - The class implements the following algorithm: - "An improved adaptive background mixture model for real-time tracking with shadow detection" - P. KadewTraKuPong and R. Bowden, - Proc. 2nd European Workshp on Advanced Video-Based Surveillance Systems, 2001." - http://personal.ee.surrey.ac.uk/Personal/R.Bowden/publications/avbs01/avbs01.pdf - */ - class CV_EXPORTS MOG: public cv::ocl::BackgroundSubtractor - { - public: - //! the default constructor - MOG(int nmixtures = -1); - - //! re-initiaization method - void initialize(Size frameSize, int frameType); - - //! the update operator - void operator()(const oclMat& frame, oclMat& fgmask, float learningRate = 0.f); - - //! computes a background image which are the mean of all background gaussians - void getBackgroundImage(oclMat& backgroundImage) const; - - //! releases all inner buffers - void release(); - - int history; - float varThreshold; - float backgroundRatio; - float noiseSigma; - - private: - int nmixtures_; - - Size frameSize_; - int frameType_; - int nframes_; - - oclMat weight_; - oclMat sortKey_; - oclMat mean_; - oclMat var_; - }; - - /*! - The class implements the following algorithm: - "Improved adaptive Gausian mixture model for background subtraction" - Z.Zivkovic - International Conference Pattern Recognition, UK, August, 2004. - http://www.zoranz.net/Publications/zivkovic2004ICPR.pdf - */ - class CV_EXPORTS MOG2: public cv::ocl::BackgroundSubtractor - { - public: - //! the default constructor - MOG2(int nmixtures = -1); - - //! re-initiaization method - void initialize(Size frameSize, int frameType); - - //! the update operator - void operator()(const oclMat& frame, oclMat& fgmask, float learningRate = -1.0f); - - //! computes a background image which are the mean of all background gaussians - void getBackgroundImage(oclMat& backgroundImage) const; - - //! releases all inner buffers - void release(); - - // parameters - // you should call initialize after parameters changes - - int history; - - //! here it is the maximum allowed number of mixture components. - //! Actual number is determined dynamically per pixel - float varThreshold; - // threshold on the squared Mahalanobis distance to decide if it is well described - // by the background model or not. Related to Cthr from the paper. - // This does not influence the update of the background. A typical value could be 4 sigma - // and that is varThreshold=4*4=16; Corresponds to Tb in the paper. - - ///////////////////////// - // less important parameters - things you might change but be carefull - //////////////////////// - - float backgroundRatio; - // corresponds to fTB=1-cf from the paper - // TB - threshold when the component becomes significant enough to be included into - // the background model. It is the TB=1-cf from the paper. So I use cf=0.1 => TB=0. - // For alpha=0.001 it means that the mode should exist for approximately 105 frames before - // it is considered foreground - // float noiseSigma; - float varThresholdGen; - - //correspondts to Tg - threshold on the squared Mahalan. dist. to decide - //when a sample is close to the existing components. If it is not close - //to any a new component will be generated. I use 3 sigma => Tg=3*3=9. - //Smaller Tg leads to more generated components and higher Tg might make - //lead to small number of components but they can grow too large - float fVarInit; - float fVarMin; - float fVarMax; - - //initial variance for the newly generated components. - //It will will influence the speed of adaptation. A good guess should be made. - //A simple way is to estimate the typical standard deviation from the images. - //I used here 10 as a reasonable value - // min and max can be used to further control the variance - float fCT; //CT - complexity reduction prior - //this is related to the number of samples needed to accept that a component - //actually exists. We use CT=0.05 of all the samples. By setting CT=0 you get - //the standard Stauffer&Grimson algorithm (maybe not exact but very similar) - - //shadow detection parameters - bool bShadowDetection; //default 1 - do shadow detection - unsigned char nShadowDetection; //do shadow detection - insert this value as the detection result - 127 default value - float fTau; - // Tau - shadow threshold. The shadow is detected if the pixel is darker - //version of the background. Tau is a threshold on how much darker the shadow can be. - //Tau= 0.5 means that if pixel is more than 2 times darker then it is not shadow - //See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003. - - private: - int nmixtures_; - - Size frameSize_; - int frameType_; - int nframes_; - - oclMat weight_; - oclMat variance_; - oclMat mean_; - - oclMat bgmodelUsedModes_; //keep track of number of modes per pixel - }; - - /*!***************Kalman Filter*************!*/ - class CV_EXPORTS KalmanFilter - { - public: - KalmanFilter(); - //! the full constructor taking the dimensionality of the state, of the measurement and of the control vector - KalmanFilter(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F); - //! re-initializes Kalman filter. The previous content is destroyed. - void init(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F); - - const oclMat& predict(const oclMat& control=oclMat()); - const oclMat& correct(const oclMat& measurement); - - oclMat statePre; //!< predicted state (x'(k)): x(k)=A*x(k-1)+B*u(k) - oclMat statePost; //!< corrected state (x(k)): x(k)=x'(k)+K(k)*(z(k)-H*x'(k)) - oclMat transitionMatrix; //!< state transition matrix (A) - oclMat controlMatrix; //!< control matrix (B) (not used if there is no control) - oclMat measurementMatrix; //!< measurement matrix (H) - oclMat processNoiseCov; //!< process noise covariance matrix (Q) - oclMat measurementNoiseCov;//!< measurement noise covariance matrix (R) - oclMat errorCovPre; //!< priori error estimate covariance matrix (P'(k)): P'(k)=A*P(k-1)*At + Q)*/ - oclMat gain; //!< Kalman gain matrix (K(k)): K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R) - oclMat errorCovPost; //!< posteriori error estimate covariance matrix (P(k)): P(k)=(I-K(k)*H)*P'(k) - private: - oclMat temp1; - oclMat temp2; - oclMat temp3; - oclMat temp4; - oclMat temp5; - }; - - /*!***************K Nearest Neighbour*************!*/ - class CV_EXPORTS KNearestNeighbour: public CvKNearest - { - public: - KNearestNeighbour(); - ~KNearestNeighbour(); - - bool train(const Mat& trainData, Mat& labels, Mat& sampleIdx = Mat().setTo(Scalar::all(0)), - bool isRegression = false, int max_k = 32, bool updateBase = false); - - void clear(); - - void find_nearest(const oclMat& samples, int k, oclMat& lables); - - private: - oclMat samples_ocl; - }; - - /*!*************** SVM *************!*/ - class CV_EXPORTS CvSVM_OCL : public CvSVM - { - public: - CvSVM_OCL(); - - CvSVM_OCL(const cv::Mat& trainData, const cv::Mat& responses, - const cv::Mat& varIdx=cv::Mat(), const cv::Mat& sampleIdx=cv::Mat(), - CvSVMParams params=CvSVMParams()); - CV_WRAP float predict( const int row_index, Mat& src, bool returnDFVal=false ) const; - CV_WRAP void predict( cv::InputArray samples, cv::OutputArray results ) const; - CV_WRAP float predict( const cv::Mat& sample, bool returnDFVal=false ) const; - float predict( const CvMat* samples, CV_OUT CvMat* results ) const; - - protected: - float predict( const int row_index, int row_len, Mat& src, bool returnDFVal=false ) const; - void create_kernel(); - void create_solver(); - }; - - /*!*************** END *************!*/ - } -} -#if defined _MSC_VER && _MSC_VER >= 1200 -# pragma warning( push) -# pragma warning( disable: 4267) -#endif -#include "opencv2/ocl/matrix_operations.hpp" -#if defined _MSC_VER && _MSC_VER >= 1200 -# pragma warning( pop) -#endif - -#endif /* __OPENCV_OCL_HPP__ */ diff --git a/modules/ocl/include/opencv2/ocl/matrix_operations.hpp b/modules/ocl/include/opencv2/ocl/matrix_operations.hpp deleted file mode 100644 index 410adbd8b..000000000 --- a/modules/ocl/include/opencv2/ocl/matrix_operations.hpp +++ /dev/null @@ -1,490 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., 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_OCL_MATRIX_OPERATIONS_HPP__ -#define __OPENCV_OCL_MATRIX_OPERATIONS_HPP__ - -#include "opencv2/ocl.hpp" - -namespace cv -{ - - namespace ocl - { - - enum - { - MAT_ADD = 1, - MAT_SUB, - MAT_MUL, - MAT_DIV, - MAT_NOT, - MAT_AND, - MAT_OR, - MAT_XOR - }; - - class CV_EXPORTS oclMatExpr - { - public: - oclMatExpr() : a(oclMat()), b(oclMat()), op(0) {} - oclMatExpr(const oclMat& _a, const oclMat& _b, int _op) - : a(_a), b(_b), op(_op) {} - operator oclMat() const; - void assign(oclMat& m) const; - - protected: - oclMat a, b; - int op; - }; - //////////////////////////////////////////////////////////////////////// - //////////////////////////////// oclMat //////////////////////////////// - //////////////////////////////////////////////////////////////////////// - - inline oclMat::oclMat() : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), offset(0), wholerows(0), wholecols(0) {} - - inline oclMat::oclMat(int _rows, int _cols, int _type) : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), offset(0), wholerows(0), wholecols(0) - { - if( _rows > 0 && _cols > 0 ) - create( _rows, _cols, _type ); - } - - inline oclMat::oclMat(Size _size, int _type) : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), offset(0), wholerows(0), wholecols(0) - { - if( _size.height > 0 && _size.width > 0 ) - create( _size.height, _size.width, _type ); - } - - inline oclMat::oclMat(int _rows, int _cols, int _type, const Scalar &_s) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), offset(0), wholerows(0), wholecols(0) - { - if(_rows > 0 && _cols > 0) - { - create(_rows, _cols, _type); - *this = _s; - } - } - - inline oclMat::oclMat(Size _size, int _type, const Scalar &_s) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), offset(0), wholerows(0), wholecols(0) - { - if( _size.height > 0 && _size.width > 0 ) - { - create( _size.height, _size.width, _type ); - *this = _s; - } - } - - inline oclMat::oclMat(const oclMat &m) - : flags(m.flags), rows(m.rows), cols(m.cols), step(m.step), data(m.data), - refcount(m.refcount), datastart(m.datastart), dataend(m.dataend), clCxt(m.clCxt), offset(m.offset), wholerows(m.wholerows), wholecols(m.wholecols) - { - if( refcount ) - CV_XADD(refcount, 1); - } - - inline oclMat::oclMat(int _rows, int _cols, int _type, void *_data, size_t _step) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), - datastart(0), dataend(0), offset(0), wholerows(0), wholecols(0) - { - cv::Mat m(_rows, _cols, _type, _data, _step); - upload(m); - //size_t minstep = cols * elemSize(); - //if( step == Mat::AUTO_STEP ) - //{ - // step = minstep; - // flags |= Mat::CONTINUOUS_FLAG; - //} - //else - //{ - // if( rows == 1 ) step = minstep; - // CV_DbgAssert( step >= minstep ); - // flags |= step == minstep ? Mat::CONTINUOUS_FLAG : 0; - //} - //dataend += step * (rows - 1) + minstep; - } - - inline oclMat::oclMat(Size _size, int _type, void *_data, size_t _step) - : flags(0), rows(0), cols(0), - step(0), data(0), refcount(0), - datastart(0), dataend(0), offset(0), wholerows(0), wholecols(0) - { - cv::Mat m(_size, _type, _data, _step); - upload(m); - //size_t minstep = cols * elemSize(); - //if( step == Mat::AUTO_STEP ) - //{ - // step = minstep; - // flags |= Mat::CONTINUOUS_FLAG; - //} - //else - //{ - // if( rows == 1 ) step = minstep; - // CV_DbgAssert( step >= minstep ); - // flags |= step == minstep ? Mat::CONTINUOUS_FLAG : 0; - //} - //dataend += step * (rows - 1) + minstep; - } - - - inline oclMat::oclMat(const oclMat &m, const Range &rRange, const Range &cRange) - { - flags = m.flags; - step = m.step; - refcount = m.refcount; - data = m.data; - datastart = m.datastart; - dataend = m.dataend; - clCxt = m.clCxt; - wholerows = m.wholerows; - wholecols = m.wholecols; - offset = m.offset; - if( rRange == Range::all() ) - rows = m.rows; - else - { - CV_Assert( 0 <= rRange.start && rRange.start <= rRange.end && rRange.end <= m.rows ); - rows = rRange.size(); - offset += step * rRange.start; - } - - if( cRange == Range::all() ) - cols = m.cols; - else - { - CV_Assert( 0 <= cRange.start && cRange.start <= cRange.end && cRange.end <= m.cols ); - cols = cRange.size(); - offset += cRange.start * elemSize(); - flags &= cols < m.cols ? ~Mat::CONTINUOUS_FLAG : -1; - } - - if( rows == 1 ) - flags |= Mat::CONTINUOUS_FLAG; - - if( refcount ) - CV_XADD(refcount, 1); - if( rows <= 0 || cols <= 0 ) - rows = cols = 0; - } - - inline oclMat::oclMat(const oclMat &m, const Rect &roi) - : flags(m.flags), rows(roi.height), cols(roi.width), - step(m.step), data(m.data), refcount(m.refcount), - datastart(m.datastart), dataend(m.dataend), clCxt(m.clCxt), offset(m.offset), wholerows(m.wholerows), wholecols(m.wholecols) - { - flags &= roi.width < m.cols ? ~Mat::CONTINUOUS_FLAG : -1; - offset += roi.y * step + roi.x * elemSize(); - CV_Assert( 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.wholecols && - 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.wholerows ); - if( refcount ) - CV_XADD(refcount, 1); - if( rows <= 0 || cols <= 0 ) - rows = cols = 0; - } - - inline oclMat::oclMat(const Mat &m) - : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) , offset(0), wholerows(0), wholecols(0) - { - //clCxt = Context::getContext(); - upload(m); - } - - inline oclMat::~oclMat() - { - release(); - } - - inline oclMat &oclMat::operator = (const oclMat &m) - { - if( this != &m ) - { - if( m.refcount ) - CV_XADD(m.refcount, 1); - release(); - clCxt = m.clCxt; - flags = m.flags; - rows = m.rows; - cols = m.cols; - step = m.step; - data = m.data; - datastart = m.datastart; - dataend = m.dataend; - offset = m.offset; - wholerows = m.wholerows; - wholecols = m.wholecols; - refcount = m.refcount; - } - return *this; - } - - inline oclMat &oclMat::operator = (const Mat &m) - { - //clCxt = Context::getContext(); - upload(m); - return *this; - } - - inline oclMat& oclMat::operator = (const oclMatExpr& expr) - { - expr.assign(*this); - return *this; - } - - /* Fixme! To be supported in OpenCL later. */ -#if 0 - template inline oclMat::operator DevMem2D_() const - { - return DevMem2D_(rows, cols, (T *)data, step); - } - template inline oclMat::operator PtrStep_() const - { - return PtrStep_(static_cast< DevMem2D_ >(*this)); - } -#endif - - //CPP: void oclMat::upload(const Mat& m); - - inline oclMat::operator Mat() const - { - Mat m; - download(m); - return m; - } - - //CPP void oclMat::download(cv::Mat& m) const; - - inline oclMat oclMat::row(int y) const - { - return oclMat(*this, Range(y, y + 1), Range::all()); - } - inline oclMat oclMat::col(int x) const - { - return oclMat(*this, Range::all(), Range(x, x + 1)); - } - inline oclMat oclMat::rowRange(int startrow, int endrow) const - { - return oclMat(*this, Range(startrow, endrow), Range::all()); - } - inline oclMat oclMat::rowRange(const Range &r) const - { - return oclMat(*this, r, Range::all()); - } - inline oclMat oclMat::colRange(int startcol, int endcol) const - { - return oclMat(*this, Range::all(), Range(startcol, endcol)); - } - inline oclMat oclMat::colRange(const Range &r) const - { - return oclMat(*this, Range::all(), r); - } - - inline oclMat oclMat::clone() const - { - oclMat m; - copyTo(m); - return m; - } - - //CPP void oclMat::copyTo( oclMat& m ) const; - //CPP void oclMat::copyTo( oclMat& m, const oclMat& mask ) const; - //CPP void oclMat::convertTo( oclMat& m, int rtype, double alpha=1, double beta=0 ) const; - - inline void oclMat::assignTo( oclMat &m, int mtype ) const - { - if( mtype < 0 ) - m = *this; - else - convertTo(m, mtype); - } - - //CPP oclMat& oclMat::operator = (const Scalar& s); - //CPP oclMat& oclMat::setTo(const Scalar& s, const oclMat& mask=oclMat()); - //CPP oclMat oclMat::reshape(int _cn, int _rows=0) const; - inline void oclMat::create(Size _size, int _type) - { - create(_size.height, _size.width, _type); - } - //CPP void oclMat::create(int _rows, int _cols, int _type); - //CPP void oclMat::release(); - - inline void oclMat::swap(oclMat &b) - { - std::swap( flags, b.flags ); - std::swap( rows, b.rows ); - std::swap( cols, b.cols ); - std::swap( step, b.step ); - std::swap( data, b.data ); - std::swap( datastart, b.datastart ); - std::swap( dataend, b.dataend ); - std::swap( refcount, b.refcount ); - std::swap( offset, b.offset ); - std::swap( clCxt, b.clCxt ); - std::swap( wholerows, b.wholerows ); - std::swap( wholecols, b.wholecols ); - } - - inline void oclMat::locateROI( Size &wholeSize, Point &ofs ) const - { - size_t esz = elemSize();//, minstep; - //ptrdiff_t delta1 = offset;//, delta2 = dataend - datastart; - CV_DbgAssert( step > 0 ); - if( offset == 0 ) - ofs.x = ofs.y = 0; - else - { - ofs.y = (int)(offset / step); - ofs.x = (int)((offset - step * ofs.y) / esz); - //CV_DbgAssert( data == datastart + ofs.y*step + ofs.x*esz ); - } - //minstep = (ofs.x + cols)*esz; - //wholeSize.height = (int)((delta2 - minstep)/step + 1); - //wholeSize.height = std::max(wholeSize.height, ofs.y + rows); - //wholeSize.width = (int)((delta2 - step*(wholeSize.height-1))/esz); - //wholeSize.width = std::max(wholeSize.width, ofs.x + cols); - wholeSize.height = wholerows; - wholeSize.width = wholecols; - } - - inline oclMat &oclMat::adjustROI( int dtop, int dbottom, int dleft, int dright ) - { - Size wholeSize; - Point ofs; - size_t esz = elemSize(); - locateROI( wholeSize, ofs ); - int row1 = std::max(ofs.y - dtop, 0), row2 = std::min(ofs.y + rows + dbottom, wholeSize.height); - int col1 = std::max(ofs.x - dleft, 0), col2 = std::min(ofs.x + cols + dright, wholeSize.width); - offset += (row1 - ofs.y) * step + (col1 - ofs.x) * esz; - rows = row2 - row1; - cols = col2 - col1; - if( esz * cols == step || rows == 1 ) - flags |= Mat::CONTINUOUS_FLAG; - else - flags &= ~Mat::CONTINUOUS_FLAG; - return *this; - } - - inline oclMat oclMat::operator()( Range rRange, Range cRange ) const - { - return oclMat(*this, rRange, cRange); - } - inline oclMat oclMat::operator()( const Rect &roi ) const - { - return oclMat(*this, roi); - } - - inline bool oclMat::isContinuous() const - { - return (flags & Mat::CONTINUOUS_FLAG) != 0; - } - inline size_t oclMat::elemSize() const - { - return CV_ELEM_SIZE((CV_MAKE_TYPE(type(), oclchannels()))); - } - inline size_t oclMat::elemSize1() const - { - return CV_ELEM_SIZE1(flags); - } - inline int oclMat::type() const - { - return CV_MAT_TYPE(flags); - } - inline int oclMat::ocltype() const - { - return CV_MAKE_TYPE(depth(), oclchannels()); - } - inline int oclMat::depth() const - { - return CV_MAT_DEPTH(flags); - } - inline int oclMat::channels() const - { - return CV_MAT_CN(flags); - } - inline int oclMat::oclchannels() const - { - return (CV_MAT_CN(flags)) == 3 ? 4 : (CV_MAT_CN(flags)); - } - inline size_t oclMat::step1() const - { - return step / elemSize1(); - } - inline Size oclMat::size() const - { - return Size(cols, rows); - } - inline bool oclMat::empty() const - { - return data == 0; - } - - inline oclMat oclMat::t() const - { - oclMat tmp; - transpose(*this, tmp); - return tmp; - } - - static inline void swap( oclMat &a, oclMat &b ) - { - a.swap(b); - } - - inline void ensureSizeIsEnough(int rows, int cols, int type, oclMat &m) - { - if (m.type() == type && m.rows >= rows && m.cols >= cols) - m = m(Rect(0, 0, cols, rows)); - else - m.create(rows, cols, type); - } - - inline void ensureSizeIsEnough(Size size, int type, oclMat &m) - { - ensureSizeIsEnough(size.height, size.width, type, m); - } - - - } /* end of namespace ocl */ - -} /* end of namespace cv */ - -#endif /* __OPENCV_OCL_MATRIX_OPERATIONS_HPP__ */ diff --git a/modules/ocl/include/opencv2/ocl/ocl.hpp b/modules/ocl/include/opencv2/ocl/ocl.hpp deleted file mode 100644 index 3dd46545a..000000000 --- a/modules/ocl/include/opencv2/ocl/ocl.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/*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) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. -// 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*/ - -#ifdef __OPENCV_BUILD -#error this is a compatibility header which should not be used inside the OpenCV library -#endif - -#include "opencv2/ocl.hpp" diff --git a/modules/ocl/include/opencv2/ocl/private/opencl_dumpinfo.hpp b/modules/ocl/include/opencv2/ocl/private/opencl_dumpinfo.hpp deleted file mode 100644 index ee0f703ee..000000000 --- a/modules/ocl/include/opencv2/ocl/private/opencl_dumpinfo.hpp +++ /dev/null @@ -1,154 +0,0 @@ -/*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-2013, Advanced Micro Devices, Inc., 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 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(DUMP_MESSAGE_STDOUT) && !defined(DUMP_PROPERTY_XML) -#error Invalid usage -#endif - -#if !defined(DUMP_PROPERTY_XML) -#define DUMP_PROPERTY_XML(...) -#endif - -#if !defined(DUMP_MESSAGE_STDOUT) -#define DUMP_MESSAGE_STDOUT(...) -#endif - -#include - -static std::string bytesToStringRepr(size_t value) -{ - size_t b = value % 1024; - value /= 1024; - - size_t kb = value % 1024; - value /= 1024; - - size_t mb = value % 1024; - value /= 1024; - - size_t gb = value; - - std::ostringstream stream; - - if (gb > 0) - stream << gb << " GB "; - if (mb > 0) - stream << mb << " MB "; - if (kb > 0) - stream << kb << " kB "; - if (b > 0) - stream << b << " B"; - - return stream.str(); -} - -static void dumpOpenCLDevice() -{ - using namespace cv::ocl; - try - { - cv::ocl::PlatformsInfo platforms; - cv::ocl::getOpenCLPlatforms(platforms); - DUMP_MESSAGE_STDOUT("OpenCL Platforms: "); - const char* deviceTypeStr; - for(unsigned int i=0; i < platforms.size(); i++) - { - DUMP_MESSAGE_STDOUT(" " << platforms.at(i)->platformName); - const cv::ocl::DevicesInfo& devices = platforms.at(i)->devices; - for(unsigned int j=0; j < devices.size(); j++) - { - const cv::ocl::DeviceInfo& current_device = *devices.at(j); - deviceTypeStr = current_device.deviceType == CVCL_DEVICE_TYPE_CPU - ? ("CPU") : (current_device.deviceType == CVCL_DEVICE_TYPE_GPU ? "GPU" : "unknown"); - DUMP_MESSAGE_STDOUT( " " << deviceTypeStr << " : " << current_device.deviceName << " : " << current_device.deviceVersion ); - DUMP_PROPERTY_XML("cv_ocl_platform_"<< i<<"_device_"<getDeviceInfo(); - - DUMP_MESSAGE_STDOUT(" Platform = "<< deviceInfo.platform->platformName); - DUMP_PROPERTY_XML("cv_ocl_current_platformName", deviceInfo.platform->platformName); - - deviceTypeStr = deviceInfo.deviceType == CVCL_DEVICE_TYPE_CPU - ? "CPU" : (deviceInfo.deviceType == CVCL_DEVICE_TYPE_GPU ? "GPU" : "unknown"); - DUMP_MESSAGE_STDOUT(" Type = "<< deviceTypeStr); - DUMP_PROPERTY_XML("cv_ocl_current_deviceType", deviceTypeStr); - - DUMP_MESSAGE_STDOUT(" Name = "<< deviceInfo.deviceName); - DUMP_PROPERTY_XML("cv_ocl_current_deviceName", deviceInfo.deviceName); - - DUMP_MESSAGE_STDOUT(" Version = " << deviceInfo.deviceVersion); - DUMP_PROPERTY_XML("cv_ocl_current_deviceVersion", deviceInfo.deviceVersion); - - DUMP_MESSAGE_STDOUT(" Compute units = "<< deviceInfo.maxComputeUnits); - DUMP_PROPERTY_XML("cv_ocl_current_maxComputeUnits", deviceInfo.maxComputeUnits); - - DUMP_MESSAGE_STDOUT(" Max work group size = "<< deviceInfo.maxWorkGroupSize); - DUMP_PROPERTY_XML("cv_ocl_current_maxWorkGroupSize", deviceInfo.maxWorkGroupSize); - - std::string localMemorySizeStr = bytesToStringRepr(deviceInfo.localMemorySize); - DUMP_MESSAGE_STDOUT(" Local memory size = "<< localMemorySizeStr.c_str()); - DUMP_PROPERTY_XML("cv_ocl_current_localMemorySize", deviceInfo.localMemorySize); - - std::string maxMemAllocSizeStr = bytesToStringRepr(deviceInfo.maxMemAllocSize); - DUMP_MESSAGE_STDOUT(" Max memory allocation size = "<< maxMemAllocSizeStr.c_str()); - DUMP_PROPERTY_XML("cv_ocl_current_maxMemAllocSize", deviceInfo.maxMemAllocSize); - - const char* doubleSupportStr = deviceInfo.haveDoubleSupport ? "Yes" : "No"; - DUMP_MESSAGE_STDOUT(" Double support = "<< doubleSupportStr); - DUMP_PROPERTY_XML("cv_ocl_current_haveDoubleSupport", deviceInfo.haveDoubleSupport); - - const char* isUnifiedMemoryStr = deviceInfo.isUnifiedMemory ? "Yes" : "No"; - DUMP_MESSAGE_STDOUT(" Unified memory = "<< isUnifiedMemoryStr); - DUMP_PROPERTY_XML("cv_ocl_current_isUnifiedMemory", deviceInfo.isUnifiedMemory); - } - catch (...) - { - DUMP_MESSAGE_STDOUT("OpenCL device not available"); - DUMP_PROPERTY_XML("cv_ocl", "not available"); - } -} - -#undef DUMP_MESSAGE_STDOUT -#undef DUMP_PROPERTY_XML diff --git a/modules/ocl/include/opencv2/ocl/private/opencl_utils.hpp b/modules/ocl/include/opencv2/ocl/private/opencl_utils.hpp deleted file mode 100644 index 6d74eb1f8..000000000 --- a/modules/ocl/include/opencv2/ocl/private/opencl_utils.hpp +++ /dev/null @@ -1,115 +0,0 @@ -/*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-2013, Advanced Micro Devices, Inc., 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 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_OCL_PRIVATE_OPENCL_UTILS_HPP__ -#define __OPENCV_OCL_PRIVATE_OPENCL_UTILS_HPP__ - -#include "opencv2/core/opencl/runtime/opencl_core.hpp" -#include -#include - -namespace cl_utils { - -inline cl_int getPlatforms(std::vector& platforms) -{ - cl_uint n = 0; - - cl_int err = ::clGetPlatformIDs(0, NULL, &n); - if (err != CL_SUCCESS) - return err; - - platforms.clear(); platforms.resize(n); - err = ::clGetPlatformIDs(n, &platforms[0], NULL); - if (err != CL_SUCCESS) - return err; - - return CL_SUCCESS; -} - -inline cl_int getDevices(cl_platform_id platform, cl_device_type type, std::vector& devices) -{ - cl_uint n = 0; - - cl_int err = ::clGetDeviceIDs(platform, type, 0, NULL, &n); - if (err != CL_SUCCESS) - return err; - - devices.clear(); devices.resize(n); - err = ::clGetDeviceIDs(platform, type, n, &devices[0], NULL); - if (err != CL_SUCCESS) - return err; - - return CL_SUCCESS; -} - - - - -template -inline cl_int getScalarInfo(Functor f, ObjectType obj, cl_uint name, T& param) -{ - return f(obj, name, sizeof(T), ¶m, NULL); -} - -template -inline cl_int getStringInfo(Functor f, ObjectType obj, cl_uint name, std::string& param) -{ - ::size_t required; - cl_int err = f(obj, name, 0, NULL, &required); - if (err != CL_SUCCESS) - return err; - - param.clear(); - if (required > 0) - { - std::vector buf(required + 1, char(0)); - err = f(obj, name, required, &buf[0], NULL); - if (err != CL_SUCCESS) - return err; - param = &buf[0]; - } - - return CL_SUCCESS; -} - -} // namespace cl_utils - -#endif // __OPENCV_OCL_PRIVATE_OPENCL_UTILS_HPP__ diff --git a/modules/ocl/include/opencv2/ocl/private/util.hpp b/modules/ocl/include/opencv2/ocl/private/util.hpp deleted file mode 100644 index b1ceacd7a..000000000 --- a/modules/ocl/include/opencv2/ocl/private/util.hpp +++ /dev/null @@ -1,191 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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*/ - -#ifndef __OPENCV_OCL_PRIVATE_UTIL__ -#define __OPENCV_OCL_PRIVATE_UTIL__ - -#include "opencv2/core/opencl/runtime/opencl_core.hpp" -#include "opencv2/core/ocl_genbase.hpp" - -#include "opencv2/ocl.hpp" - -namespace cv -{ -namespace ocl -{ - -inline cl_device_id getClDeviceID(const Context *ctx) -{ - return *(cl_device_id*)(ctx->getOpenCLDeviceIDPtr()); -} - -inline cl_context getClContext(const Context *ctx) -{ - return *(cl_context*)(ctx->getOpenCLContextPtr()); -} - -inline cl_command_queue getClCommandQueue(const Context *ctx) -{ - return *(cl_command_queue*)(ctx->getOpenCLCommandQueuePtr()); -} - -CV_EXPORTS cv::Mutex& getInitializationMutex(); - -enum openCLMemcpyKind -{ - clMemcpyHostToDevice = 0, - clMemcpyDeviceToHost, - clMemcpyDeviceToDevice -}; -///////////////////////////OpenCL call wrappers//////////////////////////// -CV_EXPORTS void openCLMallocPitch(Context *clCxt, void **dev_ptr, size_t *pitch, - size_t widthInBytes, size_t height); -CV_EXPORTS void openCLMallocPitchEx(Context *clCxt, void **dev_ptr, size_t *pitch, - size_t widthInBytes, size_t height, DevMemRW rw_type, DevMemType mem_type); -CV_EXPORTS void openCLMemcpy2D(Context *clCxt, void *dst, size_t dpitch, - const void *src, size_t spitch, - size_t width, size_t height, openCLMemcpyKind kind, int channels = -1); -CV_EXPORTS void openCLCopyBuffer2D(Context *clCxt, void *dst, size_t dpitch, int dst_offset, - const void *src, size_t spitch, - size_t width, size_t height, int src_offset); -CV_EXPORTS void openCLFree(void *devPtr); -CV_EXPORTS cl_mem openCLCreateBuffer(Context *clCxt, size_t flag, size_t size); -CV_EXPORTS void openCLReadBuffer(Context *clCxt, cl_mem dst_buffer, void *host_buffer, size_t size); -CV_EXPORTS cl_kernel openCLGetKernelFromSource(const Context *clCxt, - const cv::ocl::ProgramEntry* source, String kernelName); -CV_EXPORTS cl_kernel openCLGetKernelFromSource(const Context *clCxt, - const cv::ocl::ProgramEntry* source, String kernelName, const char *build_options); -CV_EXPORTS cl_kernel openCLGetKernelFromSource(Context *ctx, const cv::ocl::ProgramEntry* source, - String kernelName, int channels, int depth, const char *build_options); -CV_EXPORTS void openCLVerifyKernel(const Context *clCxt, cl_kernel kernel, size_t *localThreads); -CV_EXPORTS void openCLExecuteKernel(Context *ctx, cl_kernel kernel, size_t globalThreads[3], - size_t localThreads[3], std::vector< std::pair > &args); -CV_EXPORTS void openCLExecuteKernel(Context *clCxt , const cv::ocl::ProgramEntry* source, String kernelName, std::vector< std::pair > &args, - int globalcols , int globalrows, size_t blockSize = 16, int kernel_expand_depth = -1, int kernel_expand_channel = -1); -CV_EXPORTS void openCLExecuteKernel_(Context *clCxt, const cv::ocl::ProgramEntry* source, String kernelName, - size_t globalThreads[3], size_t localThreads[3], - std::vector< std::pair > &args, int channels, int depth, const char *build_options); -CV_EXPORTS void openCLExecuteKernel(Context *clCxt, const cv::ocl::ProgramEntry* source, String kernelName, size_t globalThreads[3], - size_t localThreads[3], std::vector< std::pair > &args, int channels, int depth); -CV_EXPORTS void openCLExecuteKernel(Context *clCxt, const cv::ocl::ProgramEntry* source, String kernelName, size_t globalThreads[3], - size_t localThreads[3], std::vector< std::pair > &args, int channels, - int depth, const char *build_options); - -CV_EXPORTS cl_mem load_constant(cl_context context, cl_command_queue command_queue, const void *value, - const size_t size); - -CV_EXPORTS cl_mem openCLMalloc(cl_context clCxt, size_t size, cl_mem_flags flags, void *host_ptr); - -enum FLUSH_MODE -{ - CLFINISH = 0, - CLFLUSH, - DISABLE -}; - -CV_EXPORTS void openCLExecuteKernel2(Context *clCxt, const cv::ocl::ProgramEntry* source, String kernelName, size_t globalThreads[3], - size_t localThreads[3], std::vector< std::pair > &args, int channels, int depth, FLUSH_MODE finish_mode = DISABLE); -CV_EXPORTS void openCLExecuteKernel2(Context *clCxt, const cv::ocl::ProgramEntry* source, String kernelName, size_t globalThreads[3], - size_t localThreads[3], std::vector< std::pair > &args, int channels, - int depth, const char *build_options, FLUSH_MODE finish_mode = DISABLE); - -// bind oclMat to OpenCL image textures -// note: -// 1. there is no memory management. User need to explicitly release the resource -// 2. for faster clamping, there is no buffer padding for the constructed texture -CV_EXPORTS cl_mem bindTexture(const oclMat &mat); -CV_EXPORTS void releaseTexture(cl_mem& texture); - -//Represents an image texture object -class CV_EXPORTS TextureCL -{ -public: - TextureCL(cl_mem tex, int r, int c, int t) - : tex_(tex), rows(r), cols(c), type(t) {} - ~TextureCL() - { - openCLFree(tex_); - } - operator cl_mem() - { - return tex_; - } - cl_mem const tex_; - const int rows; - const int cols; - const int type; -private: - //disable assignment - void operator=(const TextureCL&); -}; -// bind oclMat to OpenCL image textures and retunrs an TextureCL object -// note: -// for faster clamping, there is no buffer padding for the constructed texture -CV_EXPORTS Ptr bindTexturePtr(const oclMat &mat); - -CV_EXPORTS bool isCpuDevice(); - -CV_EXPORTS size_t queryWaveFrontSize(cl_kernel kernel); - - -inline size_t divUp(size_t total, size_t grain) -{ - return (total + grain - 1) / grain; -} - -inline size_t roundUp(size_t sz, size_t n) -{ - // we don't assume that n is a power of 2 (see alignSize) - // equal to divUp(sz, n) * n - size_t t = sz + n - 1; - size_t rem = t % n; - size_t result = t - rem; - return result; -} - -}//namespace ocl -}//namespace cv - -#endif //__OPENCV_OCL_PRIVATE_UTIL__ diff --git a/modules/ocl/perf/main.cpp b/modules/ocl/perf/main.cpp deleted file mode 100644 index b537ec1af..000000000 --- a/modules/ocl/perf/main.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/*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. -// -// 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" - -#define DUMP_PROPERTY_XML(propertyName, propertyValue) \ - do { \ - std::stringstream ssName, ssValue;\ - ssName << propertyName;\ - ssValue << propertyValue; \ - ::testing::Test::RecordProperty(ssName.str(), ssValue.str()); \ - } while (false) - -#define DUMP_MESSAGE_STDOUT(msg) \ - do { \ - std::cout << msg << std::endl; \ - } while (false) - - -#include "opencv2/ocl/private/opencl_dumpinfo.hpp" - -static const char * impls[] = -{ - IMPL_OCL, - IMPL_PLAIN, -#ifdef HAVE_OPENCV_GPU - IMPL_GPU -#endif -}; - - -int main(int argc, char ** argv) -{ - ::perf::TestBase::setModulePerformanceStrategy(::perf::PERF_STRATEGY_SIMPLE); - - CV_PERF_TEST_MAIN_INTERNALS(ocl, impls, ::dumpOpenCLDevice()) -} diff --git a/modules/ocl/perf/perf_arithm.cpp b/modules/ocl/perf/perf_arithm.cpp deleted file mode 100644 index 592c65285..000000000 --- a/modules/ocl/perf/perf_arithm.cpp +++ /dev/null @@ -1,1127 +0,0 @@ -/*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" - -using namespace perf; -using std::tr1::get; -using std::tr1::tuple; - -///////////// Lut //////////////////////// - -typedef Size_MatType LUTFixture; - -PERF_TEST_P(LUTFixture, LUT, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC3))) -{ - // getting params - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - // creating src data - Mat src(srcSize, type), lut(1, 256, CV_8UC1); - int dstType = CV_MAKETYPE(lut.depth(), src.channels()); - Mat dst(srcSize, dstType); - - randu(lut, 0, 2); - declare.in(src, WARMUP_RNG).in(lut).out(dst); - - // select implementation - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclLut(lut), oclDst(srcSize, dstType); - - OCL_TEST_CYCLE() cv::ocl::LUT(oclSrc, oclLut, oclDst); - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::LUT(src, lut, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Exp //////////////////////// - -typedef TestBaseWithParam ExpFixture; - -PERF_TEST_P(ExpFixture, Exp, OCL_TYPICAL_MAT_SIZES) -{ - // getting params - const Size srcSize = GetParam(); - const double eps = 1e-6; - - // creating src data - Mat src(srcSize, CV_32FC1), dst(srcSize, CV_32FC1); - declare.in(src).out(dst); - randu(src, 5, 16); - - // select implementation - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, src.type()); - - OCL_TEST_CYCLE() cv::ocl::exp(oclSrc, oclDst); - - oclDst.download(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::exp(src, dst); - } - else - OCL_PERF_ELSE - - SANITY_CHECK(dst, eps, ERROR_RELATIVE); -} - -///////////// LOG //////////////////////// - -typedef TestBaseWithParam LogFixture; - -PERF_TEST_P(LogFixture, Log, OCL_TYPICAL_MAT_SIZES) -{ - // getting params - const Size srcSize = GetParam(); - const double eps = 1e-6; - - // creating src data - Mat src(srcSize, CV_32F), dst(srcSize, src.type()); - randu(src, 1, 10); - declare.in(src).out(dst); - - if (srcSize == OCL_SIZE_4000) - declare.time(3.6); - - // select implementation - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, src.type()); - - OCL_TEST_CYCLE() cv::ocl::log(oclSrc, oclDst); - - oclDst.download(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::log(src, dst); - } - else - OCL_PERF_ELSE - - SANITY_CHECK(dst, eps, ERROR_RELATIVE); -} - -///////////// SQRT /////////////////////// - -typedef TestBaseWithParam SqrtFixture; - -PERF_TEST_P(SqrtFixture, Sqrt, OCL_TYPICAL_MAT_SIZES) -{ - // getting params - const Size srcSize = GetParam(); - const double eps = 1e-6; - - // creating src data - Mat src(srcSize, CV_32F), dst(srcSize, src.type()); - randu(src, 0, 10); - declare.in(src).out(dst); - - // select implementation - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, src.type()); - - OCL_TEST_CYCLE() cv::ocl::sqrt(oclSrc, oclDst); - - oclDst.download(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::sqrt(src, dst); - } - else - OCL_PERF_ELSE - - SANITY_CHECK(dst, eps, ERROR_RELATIVE); -} - -///////////// Add //////////////////////// - -typedef Size_MatType AddFixture; - -PERF_TEST_P(AddFixture, Add, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) -{ - // getting params - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - // creating src data - Mat src1(srcSize, type), src2(srcSize, type), dst(srcSize, type); - randu(src1, 0, 1); - randu(src2, 0, 1); - declare.in(src1, src2).out(dst); - - // select implementation - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::add(oclSrc1, oclSrc2, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::add(src1, src2, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Mul //////////////////////// - -typedef Size_MatType MulFixture; - -PERF_TEST_P(MulFixture, Mul, ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - // getting params - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - // creating src data - Mat src1(srcSize, type), src2(srcSize, type), dst(srcSize, type); - randu(src1, 0, 256); - randu(src2, 0, 256); - declare.in(src1, src2).out(dst); - - // select implementation - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::multiply(oclSrc1, oclSrc2, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::multiply(src1, src2, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Div //////////////////////// - -typedef Size_MatType DivFixture; - -PERF_TEST_P(DivFixture, Div, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - // getting params - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - // creating src data - Mat src1(srcSize, type), src2(srcSize, type), dst(srcSize, type); - declare.in(src1, src2).out(dst); - randu(src1, 0, 256); - randu(src2, 0, 256); - - if ((srcSize == OCL_SIZE_4000 && type == CV_8UC1) || - (srcSize == OCL_SIZE_2000 && type == CV_8UC4)) - declare.time(4.2); - else if (srcSize == OCL_SIZE_4000 && type == CV_8UC4) - declare.time(16.6); - - // select implementation - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::divide(oclSrc1, oclSrc2, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::divide(src1, src2, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Absdiff //////////////////////// - -typedef Size_MatType AbsDiffFixture; - -PERF_TEST_P(AbsDiffFixture, Absdiff, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src1(srcSize, type), src2(srcSize, type), dst(srcSize, type); - declare.in(src1, src2).in(dst); - randu(src1, 0, 256); - randu(src2, 0, 256); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::absdiff(oclSrc1, oclSrc2, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::absdiff(src1, src2, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// CartToPolar //////////////////////// - -typedef TestBaseWithParam CartToPolarFixture; - -PERF_TEST_P(CartToPolarFixture, CartToPolar, OCL_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - const double eps = 8e-3; - - Mat src1(srcSize, CV_32FC1), src2(srcSize, CV_32FC1), - dst1(srcSize, CV_32FC1), dst2(srcSize, CV_32FC1); - declare.in(src1, src2).out(dst1, dst2); - randu(src1, 0, 256); - randu(src2, 0, 256); - - if (srcSize == OCL_SIZE_4000) - declare.time(3.6); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), - oclDst1(srcSize, src1.type()), oclDst2(srcSize, src1.type()); - - OCL_TEST_CYCLE() cv::ocl::cartToPolar(oclSrc1, oclSrc2, oclDst1, oclDst2); - - oclDst1.download(dst1); - oclDst2.download(dst2); - - SANITY_CHECK(dst1, eps); - SANITY_CHECK(dst2, eps); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::cartToPolar(src1, src2, dst1, dst2); - - SANITY_CHECK(dst1, eps); - SANITY_CHECK(dst2, eps); - } - else - OCL_PERF_ELSE -} - -///////////// PolarToCart //////////////////////// - -typedef TestBaseWithParam PolarToCartFixture; - -PERF_TEST_P(PolarToCartFixture, PolarToCart, OCL_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - - Mat src1(srcSize, CV_32FC1), src2(srcSize, CV_32FC1), - dst1(srcSize, CV_32FC1), dst2(srcSize, CV_32FC1); - declare.in(src1, src2).out(dst1, dst2); - randu(src1, 0, 256); - randu(src2, 0, 256); - - if (srcSize == OCL_SIZE_4000) - declare.time(5.4); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), - oclDst1(srcSize, src1.type()), oclDst2(srcSize, src1.type()); - - OCL_TEST_CYCLE() cv::ocl::polarToCart(oclSrc1, oclSrc2, oclDst1, oclDst2); - - oclDst1.download(dst1); - oclDst2.download(dst2); - - SANITY_CHECK(dst1, 5e-5); - SANITY_CHECK(dst2, 5e-5); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::polarToCart(src1, src2, dst1, dst2); - - SANITY_CHECK(dst1, 5e-5); - SANITY_CHECK(dst2, 5e-5); - } - else - OCL_PERF_ELSE -} - -///////////// Magnitude //////////////////////// - -typedef TestBaseWithParam MagnitudeFixture; - -PERF_TEST_P(MagnitudeFixture, Magnitude, OCL_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - - Mat src1(srcSize, CV_32FC1), src2(srcSize, CV_32FC1), - dst(srcSize, CV_32FC1); - randu(src1, 0, 1); - randu(src2, 0, 1); - declare.in(src1, src2).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), - oclDst(srcSize, src1.type()); - - OCL_TEST_CYCLE() cv::ocl::magnitude(oclSrc1, oclSrc2, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst, 1e-6); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::magnitude(src1, src2, dst); - - SANITY_CHECK(dst, 1e-6); - } - else - OCL_PERF_ELSE -} - -///////////// Transpose //////////////////////// - -typedef Size_MatType TransposeFixture; - -PERF_TEST_P(TransposeFixture, Transpose, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::transpose(oclSrc, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::transpose(src, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Flip //////////////////////// - -typedef Size_MatType FlipFixture; - -PERF_TEST_P(FlipFixture, Flip, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::flip(oclSrc, oclDst, 0); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::flip(src, dst, 0); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// minMax //////////////////////// - -typedef Size_MatType minMaxFixture; - -PERF_TEST_P(minMaxFixture, minMax, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src(srcSize, type); - declare.in(src, WARMUP_RNG); - - double min_val = std::numeric_limits::max(), - max_val = std::numeric_limits::min(); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src); - - OCL_TEST_CYCLE() cv::ocl::minMax(oclSrc, &min_val, &max_val); - - ASSERT_GE(max_val, min_val); - SANITY_CHECK(min_val); - SANITY_CHECK(max_val); - } - else if (RUN_PLAIN_IMPL) - { - Point min_loc, max_loc; - - TEST_CYCLE() cv::minMaxLoc(src, &min_val, &max_val, &min_loc, &max_loc); - - ASSERT_GE(max_val, min_val); - SANITY_CHECK(min_val); - SANITY_CHECK(max_val); - } - else - OCL_PERF_ELSE -} - -///////////// minMaxLoc //////////////////////// - -typedef Size_MatType minMaxLocFixture; - -PERF_TEST_P(minMaxLocFixture, minMaxLoc, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src(srcSize, type); - randu(src, 0, 1); - declare.in(src); - - double min_val = 0.0, max_val = 0.0; - Point min_loc, max_loc; - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src); - - OCL_TEST_CYCLE() cv::ocl::minMaxLoc(oclSrc, &min_val, &max_val, &min_loc, &max_loc); - - ASSERT_GE(max_val, min_val); - SANITY_CHECK(min_val); - SANITY_CHECK(max_val); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::minMaxLoc(src, &min_val, &max_val, &min_loc, &max_loc); - - ASSERT_GE(max_val, min_val); - SANITY_CHECK(min_val); - SANITY_CHECK(max_val); - } - else - OCL_PERF_ELSE -} - -///////////// Sum //////////////////////// - -typedef Size_MatType SumFixture; - -PERF_TEST_P(SumFixture, Sum, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32SC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src(srcSize, type); - Scalar result; - randu(src, 0, 60); - declare.in(src); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src); - - OCL_TEST_CYCLE() result = cv::ocl::sum(oclSrc); - - SANITY_CHECK(result); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() result = cv::sum(src); - - SANITY_CHECK(result); - } - else - OCL_PERF_ELSE -} - -///////////// countNonZero //////////////////////// - -typedef Size_MatType countNonZeroFixture; - -PERF_TEST_P(countNonZeroFixture, countNonZero, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src(srcSize, type); - int result = 0; - randu(src, 0, 256); - declare.in(src); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src); - - OCL_TEST_CYCLE() result = cv::ocl::countNonZero(oclSrc); - - SANITY_CHECK(result); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() result = cv::countNonZero(src); - - SANITY_CHECK(result); - } - else - OCL_PERF_ELSE -} - -///////////// Phase //////////////////////// - -typedef TestBaseWithParam PhaseFixture; - -PERF_TEST_P(PhaseFixture, Phase, OCL_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - - Mat src1(srcSize, CV_32FC1), src2(srcSize, CV_32FC1), - dst(srcSize, CV_32FC1); - declare.in(src1, src2).out(dst); - randu(src1, 0, 256); - randu(src2, 0, 256); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), - oclDst(srcSize, src1.type()); - - OCL_TEST_CYCLE() cv::ocl::phase(oclSrc1, oclSrc2, oclDst, 1); - - oclDst.download(dst); - - SANITY_CHECK(dst, 1e-2); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::phase(src1, src2, dst, 1); - - SANITY_CHECK(dst, 1e-2); - } - else - OCL_PERF_ELSE -} - -///////////// bitwise_and//////////////////////// - -typedef Size_MatType BitwiseAndFixture; - -PERF_TEST_P(BitwiseAndFixture, bitwise_and, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32SC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src1(srcSize, type), src2(srcSize, type), dst(srcSize, type); - declare.in(src1, src2).out(dst); - randu(src1, 0, 256); - randu(src2, 0, 256); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), oclDst(srcSize, src1.type()); - - OCL_TEST_CYCLE() cv::ocl::bitwise_and(oclSrc1, oclSrc2, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::bitwise_and(src1, src2, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// bitwise_xor //////////////////////// - -typedef Size_MatType BitwiseXorFixture; - -PERF_TEST_P(BitwiseXorFixture, bitwise_xor, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32SC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src1(srcSize, type), src2(srcSize, type), dst(srcSize, type); - declare.in(src1, src2).out(dst); - randu(src1, 0, 256); - randu(src2, 0, 256); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), oclDst(srcSize, src1.type()); - - OCL_TEST_CYCLE() cv::ocl::bitwise_xor(oclSrc1, oclSrc2, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::bitwise_xor(src1, src2, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// bitwise_or //////////////////////// - -typedef Size_MatType BitwiseOrFixture; - -PERF_TEST_P(BitwiseOrFixture, bitwise_or, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32SC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src1(srcSize, type), src2(srcSize, type), dst(srcSize, type); - declare.in(src1, src2).out(dst); - randu(src1, 0, 256); - randu(src2, 0, 256); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), oclDst(srcSize, src1.type()); - - OCL_TEST_CYCLE() cv::ocl::bitwise_or(oclSrc1, oclSrc2, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::bitwise_or(src1, src2, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// bitwise_not//////////////////////// - -typedef Size_MatType BitwiseNotFixture; - -PERF_TEST_P(BitwiseAndFixture, bitwise_not, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32SC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::bitwise_not(oclSrc, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::bitwise_not(src, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// compare//////////////////////// - -typedef Size_MatType CompareFixture; - -PERF_TEST_P(CompareFixture, compare, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src1(srcSize, type), src2(srcSize, type), dst(srcSize, CV_8UC1); - declare.in(src1, src2, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), oclDst(srcSize, CV_8UC1); - - OCL_TEST_CYCLE() cv::ocl::compare(oclSrc1, oclSrc2, oclDst, CMP_EQ); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::compare(src1, src2, dst, CMP_EQ); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// pow //////////////////////// - -typedef TestBaseWithParam PowFixture; - -PERF_TEST_P(PowFixture, pow, OCL_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - const double eps = 1e-6; - - Mat src(srcSize, CV_32F), dst(srcSize, CV_32F); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, src.type()); - - OCL_TEST_CYCLE() cv::ocl::pow(oclSrc, -2.0, oclDst); - - oclDst.download(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::pow(src, -2.0, dst); - } - else - OCL_PERF_ELSE - - SANITY_CHECK(dst, eps, ERROR_RELATIVE); -} - -///////////// AddWeighted//////////////////////// - -typedef Size_MatType AddWeightedFixture; - -PERF_TEST_P(AddWeightedFixture, AddWeighted, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src1(srcSize, type), src2(srcSize, type), dst(srcSize, type); - declare.in(src1, src2, WARMUP_RNG).out(dst); - double alpha = 2.0, beta = 1.0, gama = 3.0; - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::addWeighted(oclSrc1, alpha, oclSrc2, beta, gama, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::addWeighted(src1, alpha, src2, beta, gama, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Min //////////////////////// - -typedef Size_MatType MinFixture; - -PERF_TEST_P(MinFixture, Min, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src1(srcSize, type), src2(srcSize, type), dst(srcSize, type); - declare.in(src1, src2, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::min(oclSrc1, oclSrc2, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() dst = cv::min(src1, src2); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Max //////////////////////// - -typedef Size_MatType MaxFixture; - -PERF_TEST_P(MaxFixture, Max, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src1(srcSize, type), src2(srcSize, type), dst(srcSize, type); - declare.in(src1, src2, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::max(oclSrc1, oclSrc2, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() dst = cv::max(src1, src2); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Max //////////////////////// - -typedef Size_MatType AbsFixture; - -PERF_TEST_P(AbsFixture, Abs, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::abs(oclSrc, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() dst = cv::abs(src); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Repeat //////////////////////// - -typedef Size_MatType RepeatFixture; - -PERF_TEST_P(RepeatFixture, Repeat, - ::testing::Combine(::testing::Values(OCL_SIZE_1000, OCL_SIZE_2000), - OCL_PERF_ENUM(CV_8UC1, CV_8UC4, CV_32FC1, CV_32FC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - const int nx = 3, ny = 2; - const Size dstSize(srcSize.width * nx, srcSize.height * ny); - - checkDeviceMaxMemoryAllocSize(srcSize, type); - checkDeviceMaxMemoryAllocSize(dstSize, type); - - Mat src(srcSize, type), dst(dstSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(dstSize, type); - - OCL_TEST_CYCLE() cv::ocl::repeat(oclSrc, ny, nx, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::repeat(src, ny, nx, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} diff --git a/modules/ocl/perf/perf_bgfg.cpp b/modules/ocl/perf/perf_bgfg.cpp deleted file mode 100644 index 95099640f..000000000 --- a/modules/ocl/perf/perf_bgfg.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/*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" - -using namespace perf; -using namespace std; -using namespace cv::ocl; -using namespace cv; -using std::tr1::tuple; -using std::tr1::get; - -#if defined(HAVE_XINE) || \ - defined(HAVE_GSTREAMER) || \ - defined(HAVE_QUICKTIME) || \ - defined(HAVE_AVFOUNDATION) || \ - defined(HAVE_FFMPEG) || \ - defined(WIN32) - -# define BUILD_WITH_VIDEO_INPUT_SUPPORT 1 -#else -# define BUILD_WITH_VIDEO_INPUT_SUPPORT 0 -#endif - -#if BUILD_WITH_VIDEO_INPUT_SUPPORT - -static void cvtFrameFmt(vector& input, vector& output) -{ - for(int i = 0; i< (int)(input.size()); i++) - { - cvtColor(input[i], output[i], COLOR_RGB2GRAY); - } -} - -//prepare data for CPU -static void prepareData(VideoCapture& cap, int cn, vector& frame_buffer) -{ - cv::Mat frame; - std::vector frame_buffer_init; - int nFrame = (int)frame_buffer.size(); - for(int i = 0; i < nFrame; i++) - { - cap >> frame; - ASSERT_FALSE(frame.empty()); - frame_buffer_init.push_back(frame); - } - - if(cn == 1) - cvtFrameFmt(frame_buffer_init, frame_buffer); - else - frame_buffer = frame_buffer_init; -} - -//copy CPU data to GPU -static void prepareData(vector& frame_buffer, vector& frame_buffer_ocl) -{ - for(int i = 0; i < (int)frame_buffer.size(); i++) - frame_buffer_ocl.push_back(cv::ocl::oclMat(frame_buffer[i])); -} - -///////////// MOG //////////////////////// - -typedef tuple VideoMOGParamType; -typedef TestBaseWithParam VideoMOGFixture; - -PERF_TEST_P(VideoMOGFixture, MOG, - ::testing::Combine(::testing::Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), - ::testing::Values(1, 3), - ::testing::Values(0.0, 0.01))) -{ - VideoMOGParamType params = GetParam(); - - const string inputFile = perf::TestBase::getDataPath(get<0>(params)); - const int cn = get<1>(params); - const float learningRate = static_cast(get<2>(params)); - - const int nFrame = 5; - - Mat foreground_cpu; - std::vector frame_buffer(nFrame); - std::vector frame_buffer_ocl; - - cv::VideoCapture cap(inputFile); - ASSERT_TRUE(cap.isOpened()); - - prepareData(cap, cn, frame_buffer); - - cv::Mat foreground; - cv::ocl::oclMat foreground_d; - if(RUN_PLAIN_IMPL) - { - TEST_CYCLE() - { - cv::Ptr mog = createBackgroundSubtractorMOG(); - foreground.release(); - for (int i = 0; i < nFrame; i++) - { - mog->apply(frame_buffer[i], foreground, learningRate); - } - } - SANITY_CHECK(foreground); - } - else if(RUN_OCL_IMPL) - { - prepareData(frame_buffer, frame_buffer_ocl); - CV_Assert((int)(frame_buffer_ocl.size()) == nFrame); - OCL_TEST_CYCLE() - { - cv::ocl::MOG d_mog; - foreground_d.release(); - for (int i = 0; i < nFrame; ++i) - { - d_mog(frame_buffer_ocl[i], foreground_d, learningRate); - } - } - foreground_d.download(foreground); - SANITY_CHECK(foreground); - } - else - OCL_PERF_ELSE -} - -///////////// MOG2 //////////////////////// - -typedef tuple VideoMOG2ParamType; -typedef TestBaseWithParam VideoMOG2Fixture; - -PERF_TEST_P(VideoMOG2Fixture, DISABLED_MOG2, // TODO Disabled: random hungs on buildslave - ::testing::Combine(::testing::Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), - ::testing::Values(1, 3))) -{ - VideoMOG2ParamType params = GetParam(); - - const string inputFile = perf::TestBase::getDataPath(get<0>(params)); - const int cn = get<1>(params); - int nFrame = 5; - - std::vector frame_buffer(nFrame); - std::vector frame_buffer_ocl; - - cv::VideoCapture cap(inputFile); - ASSERT_TRUE(cap.isOpened()); - prepareData(cap, cn, frame_buffer); - cv::Mat foreground; - cv::ocl::oclMat foreground_d; - - if(RUN_PLAIN_IMPL) - { - TEST_CYCLE() - { - cv::Ptr mog2 = createBackgroundSubtractorMOG2(); - mog2->setDetectShadows(false); - foreground.release(); - - for (int i = 0; i < nFrame; i++) - { - mog2->apply(frame_buffer[i], foreground); - } - } - SANITY_CHECK(foreground); - } - else if(RUN_OCL_IMPL) - { - prepareData(frame_buffer, frame_buffer_ocl); - CV_Assert((int)(frame_buffer_ocl.size()) == nFrame); - OCL_TEST_CYCLE() - { - cv::ocl::MOG2 d_mog2; - foreground_d.release(); - for (int i = 0; i < nFrame; i++) - { - d_mog2(frame_buffer_ocl[i], foreground_d); - } - } - foreground_d.download(foreground); - SANITY_CHECK(foreground); - } - else - OCL_PERF_ELSE -} - -///////////// MOG2_GetBackgroundImage ////////////////// - -typedef TestBaseWithParam Video_MOG2GetBackgroundImage; - -PERF_TEST_P(Video_MOG2GetBackgroundImage, MOG2, - ::testing::Combine(::testing::Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi"), - ::testing::Values(3))) -{ - VideoMOG2ParamType params = GetParam(); - - const string inputFile = perf::TestBase::getDataPath(get<0>(params)); - const int cn = get<1>(params); - int nFrame = 5; - - std::vector frame_buffer(nFrame); - std::vector frame_buffer_ocl; - - cv::VideoCapture cap(inputFile); - ASSERT_TRUE(cap.isOpened()); - - prepareData(cap, cn, frame_buffer); - - cv::Mat foreground; - cv::Mat background; - cv::ocl::oclMat foreground_d; - cv::ocl::oclMat background_d; - - if(RUN_PLAIN_IMPL) - { - TEST_CYCLE() - { - cv::Ptr mog2 = createBackgroundSubtractorMOG2(); - mog2->setDetectShadows(false); - foreground.release(); - background.release(); - for (int i = 0; i < nFrame; i++) - { - mog2->apply(frame_buffer[i], foreground); - } - mog2->getBackgroundImage(background); - } - SANITY_CHECK(background); - } - else if(RUN_OCL_IMPL) - { - prepareData(frame_buffer, frame_buffer_ocl); - CV_Assert((int)(frame_buffer_ocl.size()) == nFrame); - OCL_TEST_CYCLE() - { - cv::ocl::MOG2 d_mog2; - foreground_d.release(); - background_d.release(); - for (int i = 0; i < nFrame; i++) - { - d_mog2(frame_buffer_ocl[i], foreground_d); - } - d_mog2.getBackgroundImage(background_d); - } - background_d.download(background); - SANITY_CHECK(background); - } - else - OCL_PERF_ELSE -} - -#endif diff --git a/modules/ocl/perf/perf_blend.cpp b/modules/ocl/perf/perf_blend.cpp deleted file mode 100644 index 6f611bbc3..000000000 --- a/modules/ocl/perf/perf_blend.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/*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" - -using namespace perf; -using namespace cv; -using std::tr1::get; - -///////////// blend //////////////////////// - -template -static void blendLinearGold(const Mat &img1, const Mat &img2, - const Mat &weights1, const Mat &weights2, - Mat &result_gold) -{ - CV_Assert(img1.size() == img2.size() && img1.type() == img2.type()); - CV_Assert(weights1.size() == weights2.size() && weights1.size() == img1.size() && - weights1.type() == CV_32FC1 && weights2.type() == CV_32FC1); - - result_gold.create(img1.size(), img1.type()); - - int cn = img1.channels(); - int step1 = img1.cols * img1.channels(); - - for (int y = 0; y < img1.rows; ++y) - { - const float * const weights1_row = weights1.ptr(y); - const float * const weights2_row = weights2.ptr(y); - const T * const img1_row = img1.ptr(y); - const T * const img2_row = img2.ptr(y); - T * const result_gold_row = result_gold.ptr(y); - - for (int x = 0; x < step1; ++x) - { - int x1 = x / cn; - float w1 = weights1_row[x1], w2 = weights2_row[x1]; - result_gold_row[x] = saturate_cast(((float)img1_row[x] * w1 - + (float)img2_row[x] * w2) / (w1 + w2 + 1e-5f)); - } - } -} - -typedef void (*blendFunction)(const Mat &img1, const Mat &img2, - const Mat &weights1, const Mat &weights2, - Mat &result_gold); - -typedef Size_MatType blendLinearFixture; - -PERF_TEST_P(blendLinearFixture, blendLinear, ::testing::Combine( - OCL_TYPICAL_MAT_SIZES, testing::Values(CV_8UC1, CV_8UC3, CV_32FC1))) -{ - Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int srcType = get<1>(params); - const double eps = CV_MAT_DEPTH(srcType) <= CV_32S ? 1.0 : 0.2; - - Mat src1(srcSize, srcType), src2(srcSize, srcType), dst(srcSize, srcType); - Mat weights1(srcSize, CV_32FC1), weights2(srcSize, CV_32FC1); - - declare.in(src1, src2, WARMUP_RNG).out(dst); - randu(weights1, 0.0f, 1.0f); - randu(weights2, 0.0f, 1.0f); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), oclDst; - ocl::oclMat oclWeights1(weights1), oclWeights2(weights2); - - OCL_TEST_CYCLE() ocl::blendLinear(oclSrc1, oclSrc2, oclWeights1, oclWeights2, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst, eps); - } - else if (RUN_PLAIN_IMPL) - { - blendFunction funcs[] = { (blendFunction)blendLinearGold, (blendFunction)blendLinearGold }; - int funcIdx = CV_MAT_DEPTH(srcType) == CV_8UC1 ? 0 : 1; - - TEST_CYCLE() (funcs[funcIdx])(src1, src2, weights1, weights2, dst); - - SANITY_CHECK(dst, eps); - } - else - OCL_PERF_ELSE -} diff --git a/modules/ocl/perf/perf_brief.cpp b/modules/ocl/perf/perf_brief.cpp deleted file mode 100644 index de1f4f9d2..000000000 --- a/modules/ocl/perf/perf_brief.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/*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. -// -// Authors: -// * Matthias Bady, aegirxx ==> gmail.com -// -//M*/ - -#include "perf_precomp.hpp" - -using namespace std; -using namespace cv; -using namespace ocl; -using namespace perf; - -///////////// BRIEF //////////////////////// -typedef TestBaseWithParam > OCL_BRIEF; - -PERF_TEST_P( OCL_BRIEF, extract, testing::Combine( - testing::Values( string( "gpu/opticalflow/rubberwhale1.png" ), - string( "gpu/stereobm/aloe-L.png" ) - ), testing::Values( 16, 32, 64 ), testing::Values( 250, 500, 1000, 2500, 3000 ) ) ) -{ - const std::string filename = std::tr1::get<0>(GetParam( )); - const int bytes = std::tr1::get<1>(GetParam( )); - const size_t numKp = std::tr1::get<2>(GetParam( )); - - Mat img = imread( getDataPath( filename ), IMREAD_GRAYSCALE ); - ASSERT_TRUE( !img.empty( ) ) << "no input image"; - - int threshold = 15; - std::vector keypoints; - while (threshold > 0 && keypoints.size( ) < numKp) - { - FastFeatureDetector fast( threshold ); - fast.detect( img, keypoints, Mat( ) ); - threshold -= 5; - KeyPointsFilter::runByImageBorder( keypoints, img.size( ), BRIEF_OCL::getBorderSize( ) ); - } - ASSERT_TRUE( keypoints.size( ) >= numKp ) << "not enough keypoints"; - keypoints.resize( numKp ); - - if ( RUN_OCL_IMPL ) - { - Mat kpMat( 2, int( keypoints.size() ), CV_32FC1 ); - for ( size_t i = 0; i < keypoints.size( ); ++i ) - { - kpMat.col( int( i ) ).row( 0 ) = keypoints[i].pt.x; - kpMat.col( int( i ) ).row( 1 ) = keypoints[i].pt.y; - } - BRIEF_OCL brief( bytes ); - oclMat imgCL( img ), keypointsCL(kpMat), mask; - while (next( )) - { - startTimer( ); - oclMat descriptorsCL; - brief.compute( imgCL, keypointsCL, mask, descriptorsCL ); - cv::ocl::finish( ); - stopTimer( ); - } - SANITY_CHECK_NOTHING( ) - } - else if ( RUN_PLAIN_IMPL ) - { - BriefDescriptorExtractor brief( bytes ); - - while (next( )) - { - startTimer( ); - Mat descriptors; - brief.compute( img, keypoints, descriptors ); - stopTimer( ); - } - SANITY_CHECK_NOTHING( ) - } - else - OCL_PERF_ELSE; -} \ No newline at end of file diff --git a/modules/ocl/perf/perf_brute_force_matcher.cpp b/modules/ocl/perf/perf_brute_force_matcher.cpp deleted file mode 100644 index d124428e9..000000000 --- a/modules/ocl/perf/perf_brute_force_matcher.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/*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" - -using namespace perf; - -#define OCL_BFMATCHER_TYPICAL_MAT_SIZES ::testing::Values(cv::Size(128, 500), cv::Size(128, 1000), cv::Size(128, 2000)) - -//////////////////// BruteForceMatch ///////////////// - -typedef TestBaseWithParam BruteForceMatcherFixture; - -PERF_TEST_P(BruteForceMatcherFixture, match, - OCL_BFMATCHER_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - - vector matches; - Mat query(srcSize, CV_32F), train(srcSize, CV_32F); - declare.in(query, train).time(srcSize.height == 2000 ? 9 : 4 ); - randu(query, 0.0f, 1.0f); - randu(train, 0.0f, 1.0f); - - if (RUN_PLAIN_IMPL) - { - BFMatcher matcher(NORM_L2); - TEST_CYCLE() matcher.match(query, train, matches); - - SANITY_CHECK_MATCHES(matches); - } - else if (RUN_OCL_IMPL) - { - ocl::BruteForceMatcher_OCL_base oclMatcher(ocl::BruteForceMatcher_OCL_base::L2Dist); - ocl::oclMat oclQuery(query), oclTrain(train); - ocl::oclMat oclTrainIdx, oclDistance; - - OCL_TEST_CYCLE() - oclMatcher.matchSingle(oclQuery, oclTrain, oclTrainIdx, oclDistance); - - oclMatcher.matchDownload(oclTrainIdx, oclDistance, matches); - - SANITY_CHECK_MATCHES(matches, 1e-5); - } - else - OCL_PERF_ELSE -} - -PERF_TEST_P(BruteForceMatcherFixture, knnMatch, - OCL_BFMATCHER_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - - vector > matches(2); - Mat query(srcSize, CV_32F), train(srcSize, CV_32F); - randu(query, 0.0f, 1.0f); - randu(train, 0.0f, 1.0f); - - declare.in(query, train); - if (srcSize.height == 2000) - declare.time(9); - - if (RUN_PLAIN_IMPL) - { - BFMatcher matcher(NORM_L2); - TEST_CYCLE() matcher.knnMatch(query, train, matches, 2); - - std::vector & matches0 = matches[0], & matches1 = matches[1]; - SANITY_CHECK_MATCHES(matches0); - SANITY_CHECK_MATCHES(matches1); - } - else if (RUN_OCL_IMPL) - { - ocl::BruteForceMatcher_OCL_base oclMatcher(ocl::BruteForceMatcher_OCL_base::L2Dist); - ocl::oclMat oclQuery(query), oclTrain(train); - ocl::oclMat oclTrainIdx, oclDistance, oclAllDist; - - OCL_TEST_CYCLE() - oclMatcher.knnMatchSingle(oclQuery, oclTrain, oclTrainIdx, oclDistance, oclAllDist, 2); - - oclMatcher.knnMatchDownload(oclTrainIdx, oclDistance, matches); - - std::vector & matches0 = matches[0], & matches1 = matches[1]; - SANITY_CHECK_MATCHES(matches0, 1e-5); - SANITY_CHECK_MATCHES(matches1, 1e-5); - } - else - OCL_PERF_ELSE -} - -PERF_TEST_P(BruteForceMatcherFixture, radiusMatch, - OCL_BFMATCHER_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - - const float max_distance = 2.0f; - vector > matches(2); - Mat query(srcSize, CV_32F), train(srcSize, CV_32F); - declare.in(query, train); - - randu(query, 0.0f, 1.0f); - randu(train, 0.0f, 1.0f); - - if (srcSize.height == 2000) - declare.time(9.15); - - if (RUN_PLAIN_IMPL) - { - cv::BFMatcher matcher(NORM_L2); - TEST_CYCLE() matcher.radiusMatch(query, train, matches, max_distance); - - std::vector & matches0 = matches[0], & matches1 = matches[1]; - SANITY_CHECK_MATCHES(matches0); - SANITY_CHECK_MATCHES(matches1); - } - else if (RUN_OCL_IMPL) - { - ocl::oclMat oclQuery(query), oclTrain(train); - ocl::BruteForceMatcher_OCL_base oclMatcher(ocl::BruteForceMatcher_OCL_base::L2Dist); - ocl::oclMat oclTrainIdx, oclDistance, oclNMatches; - - OCL_TEST_CYCLE() - oclMatcher.radiusMatchSingle(oclQuery, oclTrain, oclTrainIdx, oclDistance, oclNMatches, max_distance); - - oclMatcher.radiusMatchDownload(oclTrainIdx, oclDistance, oclNMatches, matches); - - std::vector & matches0 = matches[0], & matches1 = matches[1]; - SANITY_CHECK_MATCHES(matches0); - SANITY_CHECK_MATCHES(matches1); - } - else - OCL_PERF_ELSE -} - -#undef OCL_BFMATCHER_TYPICAL_MAT_SIZES diff --git a/modules/ocl/perf/perf_calib3d.cpp b/modules/ocl/perf/perf_calib3d.cpp deleted file mode 100644 index 12fee549b..000000000 --- a/modules/ocl/perf/perf_calib3d.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/*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" - -///////////// StereoMatchBM //////////////////////// - -PERF_TEST(StereoMatchBMFixture, StereoMatchBM) -{ - Mat left_image = imread(getDataPath("gpu/stereobm/aloe-L.png"), cv::IMREAD_GRAYSCALE); - Mat right_image = imread(getDataPath("gpu/stereobm/aloe-R.png"), cv::IMREAD_GRAYSCALE); - - ASSERT_TRUE(!left_image.empty()) << "no input image"; - ASSERT_TRUE(!right_image.empty()) << "no input image"; - ASSERT_TRUE(right_image.size() == left_image.size()); - ASSERT_TRUE(right_image.size() == left_image.size()); - - const int n_disp = 128, winSize = 19; - Mat disp(left_image.size(), CV_16SC1); - - declare.in(left_image, right_image).out(disp); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclLeft(left_image), oclRight(right_image), - oclDisp(left_image.size(), CV_16SC1); - ocl::StereoBM_OCL oclBM(0, n_disp, winSize); - - OCL_TEST_CYCLE() oclBM(oclLeft, oclRight, oclDisp); - } - else if (RUN_PLAIN_IMPL) - { - Ptr bm = createStereoBM(n_disp, winSize); - - TEST_CYCLE() bm->compute(left_image, right_image, disp); - } - else - OCL_PERF_ELSE - - int value = 0; - SANITY_CHECK(value); -} diff --git a/modules/ocl/perf/perf_canny.cpp b/modules/ocl/perf/perf_canny.cpp deleted file mode 100644 index 33723daa3..000000000 --- a/modules/ocl/perf/perf_canny.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/*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" - -using namespace perf; - -///////////// Canny //////////////////////// - -PERF_TEST(CannyFixture, Canny) -{ - Mat img = imread(getDataPath("gpu/stereobm/aloe-L.png"), cv::IMREAD_GRAYSCALE), - edges(img.size(), CV_8UC1); - ASSERT_TRUE(!img.empty()) << "can't open aloe-L.png"; - - declare.in(img).out(edges); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclImg(img), oclEdges(img.size(), CV_8UC1); - - OCL_TEST_CYCLE() ocl::Canny(oclImg, oclEdges, 50.0, 100.0); - oclEdges.download(edges); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() Canny(img, edges, 50.0, 100.0); - } - else - OCL_PERF_ELSE - - int value = 0; - SANITY_CHECK(value); -} diff --git a/modules/ocl/perf/perf_color.cpp b/modules/ocl/perf/perf_color.cpp deleted file mode 100644 index 1145f1f2e..000000000 --- a/modules/ocl/perf/perf_color.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/*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" - -using namespace perf; -using std::tr1::tuple; -using std::tr1::get; -using std::tr1::make_tuple; - -///////////// cvtColor//////////////////////// - -CV_ENUM(ConversionTypes, COLOR_RGB2GRAY, COLOR_RGB2BGR, COLOR_RGB2YUV, COLOR_YUV2RGB, COLOR_RGB2YCrCb, - COLOR_YCrCb2RGB, COLOR_RGB2XYZ, COLOR_XYZ2RGB, COLOR_RGB2HSV, COLOR_HSV2RGB, COLOR_RGB2HLS, - COLOR_HLS2RGB, COLOR_BGR5652BGR, COLOR_BGR2BGR565, COLOR_RGBA2mRGBA, COLOR_mRGBA2RGBA, COLOR_YUV2RGB_NV12) - -typedef tuple > cvtColorParams; -typedef TestBaseWithParam cvtColorFixture; - -PERF_TEST_P(cvtColorFixture, cvtColor, testing::Combine( - testing::Values(Size(1000, 1002), Size(2000, 2004), Size(4000, 4008)), - testing::Values( - make_tuple(ConversionTypes(COLOR_RGB2GRAY), 3, 1), - make_tuple(ConversionTypes(COLOR_RGB2BGR), 3, 3), - make_tuple(ConversionTypes(COLOR_RGB2YUV), 3, 3), - make_tuple(ConversionTypes(COLOR_YUV2RGB), 3, 3), - make_tuple(ConversionTypes(COLOR_RGB2YCrCb), 3, 3), - make_tuple(ConversionTypes(COLOR_YCrCb2RGB), 3, 3), - make_tuple(ConversionTypes(COLOR_RGB2XYZ), 3, 3), - make_tuple(ConversionTypes(COLOR_XYZ2RGB), 3, 3), - make_tuple(ConversionTypes(COLOR_RGB2HSV), 3, 3), - make_tuple(ConversionTypes(COLOR_HSV2RGB), 3, 3), - make_tuple(ConversionTypes(COLOR_RGB2HLS), 3, 3), - make_tuple(ConversionTypes(COLOR_HLS2RGB), 3, 3), - make_tuple(ConversionTypes(COLOR_BGR5652BGR), 2, 3), - make_tuple(ConversionTypes(COLOR_BGR2BGR565), 3, 2), - make_tuple(ConversionTypes(COLOR_RGBA2mRGBA), 4, 4), - make_tuple(ConversionTypes(COLOR_mRGBA2RGBA), 4, 4), - make_tuple(ConversionTypes(COLOR_YUV2RGB_NV12), 1, 3) - ))) -{ - cvtColorParams params = GetParam(); - const Size srcSize = get<0>(params); - const tuple conversionParams = get<1>(params); - const int code = get<0>(conversionParams), scn = get<1>(conversionParams), - dcn = get<2>(conversionParams); - - Mat src(srcSize, CV_8UC(scn)), dst(srcSize, CV_8UC(scn)); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(src.size(), dst.type()); - - OCL_TEST_CYCLE() ocl::cvtColor(oclSrc, oclDst, code, dcn); - oclDst.download(dst); - - SANITY_CHECK(dst, 1); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::cvtColor(src, dst, code, dcn); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} diff --git a/modules/ocl/perf/perf_fast.cpp b/modules/ocl/perf/perf_fast.cpp deleted file mode 100644 index e5ac84894..000000000 --- a/modules/ocl/perf/perf_fast.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/*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. -// -// Authors: -// * Peter Andreas Entschev, peter@entschev.com -// -//M*/ - -#include "perf_precomp.hpp" - -using namespace perf; - -///////////// FAST //////////////////////// - -typedef std::tr1::tuple Image_Threshold_NonmaxSupression_t; -typedef perf::TestBaseWithParam Image_Threshold_NonmaxSupression; - -PERF_TEST_P(Image_Threshold_NonmaxSupression, FAST, - testing::Combine(testing::Values("gpu/perf/aloe.png"), - testing::Values(20), - testing::Bool())) -{ - const Image_Threshold_NonmaxSupression_t params = GetParam(); - const std::string imgFile = std::tr1::get<0>(params); - const int threshold = std::tr1::get<1>(params); - const bool nonmaxSupression = std::tr1::get<2>(params); - - const cv::Mat img = imread(getDataPath(imgFile), cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(img.empty()); - - if (RUN_OCL_IMPL) - { - cv::ocl::FAST_OCL fast(threshold, nonmaxSupression, 0.5); - - cv::ocl::oclMat d_img(img); - cv::ocl::oclMat d_keypoints; - - OCL_TEST_CYCLE() fast(d_img, cv::ocl::oclMat(), d_keypoints); - - std::vector ocl_keypoints; - fast.downloadKeypoints(d_keypoints, ocl_keypoints); - - sortKeyPoints(ocl_keypoints); - - SANITY_CHECK_KEYPOINTS(ocl_keypoints); - } - else if (RUN_PLAIN_IMPL) - { - std::vector cpu_keypoints; - - TEST_CYCLE() cv::FAST(img, cpu_keypoints, threshold, nonmaxSupression); - - SANITY_CHECK_KEYPOINTS(cpu_keypoints); - } - else - OCL_PERF_ELSE; -} diff --git a/modules/ocl/perf/perf_fft.cpp b/modules/ocl/perf/perf_fft.cpp deleted file mode 100644 index 49da65936..000000000 --- a/modules/ocl/perf/perf_fft.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/*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" - -using namespace perf; - -///////////// dft //////////////////////// - -typedef TestBaseWithParam dftFixture; - -#ifdef HAVE_CLAMDFFT - -PERF_TEST_P(dftFixture, dft, OCL_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - - Mat src(srcSize, CV_32FC2), dst; - randu(src, 0.0f, 1.0f); - declare.in(src); - - if (srcSize == OCL_SIZE_4000) - declare.time(7.4); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst; - - OCL_TEST_CYCLE() cv::ocl::dft(oclSrc, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst, 1.5); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::dft(src, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -#endif diff --git a/modules/ocl/perf/perf_filters.cpp b/modules/ocl/perf/perf_filters.cpp deleted file mode 100644 index 7e5389df6..000000000 --- a/modules/ocl/perf/perf_filters.cpp +++ /dev/null @@ -1,416 +0,0 @@ -/*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" - -using namespace perf; -using std::tr1::get; -using std::tr1::tuple; - -///////////// Blur//////////////////////// - -typedef Size_MatType BlurFixture; - -PERF_TEST_P(BlurFixture, Blur, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params), ksize(3, 3); - const int type = get<1>(params), bordertype = BORDER_CONSTANT; - - checkDeviceMaxMemoryAllocSize(srcSize, type); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (srcSize == OCL_SIZE_4000 && type == CV_8UC4) - declare.time(5); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::blur(oclSrc, oclDst, ksize, Point(-1, -1), bordertype); - - oclDst.download(dst); - - SANITY_CHECK(dst, 1 + DBL_EPSILON); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::blur(src, dst, ksize, Point(-1, -1), bordertype); - - SANITY_CHECK(dst, 1 + DBL_EPSILON); - } - else - OCL_PERF_ELSE -} - -///////////// Laplacian//////////////////////// - -typedef Size_MatType LaplacianFixture; - -PERF_TEST_P(LaplacianFixture, Laplacian, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params), ksize = 3; - - checkDeviceMaxMemoryAllocSize(srcSize, type); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (srcSize == OCL_SIZE_4000 && type == CV_8UC4) - declare.time(6); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::Laplacian(oclSrc, oclDst, -1, ksize, 1); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::Laplacian(src, dst, -1, ksize, 1); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Erode //////////////////// - -typedef Size_MatType ErodeFixture; - -PERF_TEST_P(ErodeFixture, Erode, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4, CV_32FC1, CV_32FC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params), ksize = 3; - const Mat ker = getStructuringElement(MORPH_RECT, Size(ksize, ksize)); - - checkDeviceMaxMemoryAllocSize(srcSize, type); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst).in(ker); - - if (srcSize == OCL_SIZE_4000 && type == CV_8UC4) - declare.time(5); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type), oclKer(ker); - - OCL_TEST_CYCLE() cv::ocl::erode(oclSrc, oclDst, oclKer); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::erode(src, dst, ker); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Sobel //////////////////////// - -typedef Size_MatType SobelFixture; - -PERF_TEST_P(SobelFixture, Sobel, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params), dx = 1, dy = 1; - - checkDeviceMaxMemoryAllocSize(srcSize, type, sizeof(float) * 2); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if ((srcSize == OCL_SIZE_2000 && type == CV_8UC4) || - (srcSize == OCL_SIZE_4000 && type == CV_8UC1)) - declare.time(5.5); - else if (srcSize == OCL_SIZE_4000 && type == CV_8UC4) - declare.time(20); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::Sobel(oclSrc, oclDst, -1, dx, dy); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::Sobel(src, dst, -1, dx, dy); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Scharr //////////////////////// - -typedef Size_MatType ScharrFixture; - -PERF_TEST_P(ScharrFixture, Scharr, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params), dx = 1, dy = 0; - - checkDeviceMaxMemoryAllocSize(srcSize, type, sizeof(float) * 2); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if ((srcSize == OCL_SIZE_2000 && type == CV_8UC4) || - (srcSize == OCL_SIZE_4000 && type == CV_8UC1)) - declare.time(5.5); - else if (srcSize == OCL_SIZE_4000 && type == CV_8UC4) - declare.time(21); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::Scharr(oclSrc, oclDst, -1, dx, dy); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::Scharr(src, dst, -1, dx, dy); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// GaussianBlur //////////////////////// - -typedef Size_MatType GaussianBlurFixture; - -PERF_TEST_P(GaussianBlurFixture, GaussianBlur, - ::testing::Combine(::testing::Values(OCL_SIZE_1000, OCL_SIZE_2000), - OCL_PERF_ENUM(CV_8UC1, CV_8UC4, CV_32FC1, CV_32FC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params), ksize = 7; - - checkDeviceMaxMemoryAllocSize(srcSize, type); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - const double eps = src.depth() == CV_8U ? 1 + DBL_EPSILON : 3e-4; - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::GaussianBlur(oclSrc, oclDst, Size(ksize, ksize), 0); - - oclDst.download(dst); - - SANITY_CHECK(dst, eps); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::GaussianBlur(src, dst, Size(ksize, ksize), 0); - - SANITY_CHECK(dst, eps); - } - else - OCL_PERF_ELSE -} - -///////////// filter2D//////////////////////// - -typedef Size_MatType filter2DFixture; - -PERF_TEST_P(filter2DFixture, filter2D, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params), ksize = 3; - - checkDeviceMaxMemoryAllocSize(srcSize, type); - - Mat src(srcSize, type), dst(srcSize, type), kernel(ksize, ksize, CV_32SC1); - declare.in(src, WARMUP_RNG).in(kernel).out(dst); - randu(kernel, -3.0, 3.0); - - if (srcSize == OCL_SIZE_4000 && type == CV_8UC4) - declare.time(8); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type), oclKernel(kernel); - - OCL_TEST_CYCLE() cv::ocl::filter2D(oclSrc, oclDst, -1, oclKernel); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::filter2D(src, dst, -1, kernel); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Bilateral//////////////////////// - -typedef Size_MatType BilateralFixture; - -PERF_TEST_P(BilateralFixture, Bilateral, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC3))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params), d = 7; - const double sigmacolor = 50.0, sigmaspace = 50.0; - - checkDeviceMaxMemoryAllocSize(srcSize, type); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (srcSize == OCL_SIZE_4000) - declare.time(type == CV_8UC3 ? 8 : 4.5); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::bilateralFilter(oclSrc, oclDst, d, sigmacolor, sigmaspace); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::bilateralFilter(src, dst, d, sigmacolor, sigmaspace); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// adaptiveBilateral//////////////////////// - -typedef Size_MatType adaptiveBilateralFixture; - -PERF_TEST_P(adaptiveBilateralFixture, adaptiveBilateral, - ::testing::Combine(::testing::Values(OCL_SIZE_1000), OCL_PERF_ENUM(CV_8UC1, CV_8UC3))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - const double sigmaspace = 10.0; - Size ksize(9, 9); - - checkDeviceMaxMemoryAllocSize(srcSize, type); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::adaptiveBilateralFilter(oclSrc, oclDst, ksize, sigmaspace); - - oclDst.download(dst); - - SANITY_CHECK(dst, 1.0); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::adaptiveBilateralFilter(src, dst, ksize, sigmaspace); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} diff --git a/modules/ocl/perf/perf_gemm.cpp b/modules/ocl/perf/perf_gemm.cpp deleted file mode 100644 index 4dcd5d4d6..000000000 --- a/modules/ocl/perf/perf_gemm.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/*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" - -using namespace perf; - -///////////// gemm //////////////////////// - -typedef TestBaseWithParam gemmFixture; - -#ifdef HAVE_CLAMDBLAS - -PERF_TEST_P(gemmFixture, gemm, ::testing::Values(OCL_SIZE_1000, OCL_SIZE_2000)) -{ - const Size srcSize = GetParam(); - - Mat src1(srcSize, CV_32FC1), src2(srcSize, CV_32FC1), - src3(srcSize, CV_32FC1), dst(srcSize, CV_32FC1); - declare.in(src1, src2, src3).out(dst).time(srcSize == OCL_SIZE_2000 ? 65 : 8); - randu(src1, -10.0f, 10.0f); - randu(src2, -10.0f, 10.0f); - randu(src3, -10.0f, 10.0f); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2), - oclSrc3(src3), oclDst(srcSize, CV_32FC1); - - OCL_TEST_CYCLE() cv::ocl::gemm(oclSrc1, oclSrc2, 1.0, oclSrc3, 1.0, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst, 0.01); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::gemm(src1, src2, 1.0, src3, 1.0, dst); - - SANITY_CHECK(dst, 0.01); - } - else - OCL_PERF_ELSE -} - -#endif diff --git a/modules/ocl/perf/perf_gftt.cpp b/modules/ocl/perf/perf_gftt.cpp deleted file mode 100644 index af24c3489..000000000 --- a/modules/ocl/perf/perf_gftt.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@outlook.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" - -using namespace perf; -using std::tr1::tuple; -using std::tr1::get; - -///////////// GoodFeaturesToTrack //////////////////////// - -typedef tuple GoodFeaturesToTrackParams; -typedef TestBaseWithParam GoodFeaturesToTrackFixture; - -PERF_TEST_P(GoodFeaturesToTrackFixture, GoodFeaturesToTrack, - ::testing::Combine(::testing::Values(string("gpu/opticalflow/rubberwhale1.png"), - string("gpu/stereobm/aloe-L.png")), - ::testing::Range(0.0, 4.0, 3.0))) -{ - - const GoodFeaturesToTrackParams param = GetParam(); - const string fileName = getDataPath(get<0>(param)); - const int maxCorners = 2000; - const double qualityLevel = 0.01, minDistance = get<1>(param); - - Mat frame = imread(fileName, IMREAD_GRAYSCALE); - ASSERT_TRUE(!frame.empty()) << "no input image"; - - vector pts_gold; - declare.in(frame); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclFrame(frame), pts_oclmat; - ocl::GoodFeaturesToTrackDetector_OCL detector(maxCorners, qualityLevel, minDistance); - - OCL_TEST_CYCLE() detector(oclFrame, pts_oclmat); - - detector.downloadPoints(pts_oclmat, pts_gold); - - SANITY_CHECK(pts_gold); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::goodFeaturesToTrack(frame, pts_gold, - maxCorners, qualityLevel, minDistance); - - SANITY_CHECK(pts_gold); - } - else - OCL_PERF_ELSE -} diff --git a/modules/ocl/perf/perf_haar.cpp b/modules/ocl/perf/perf_haar.cpp deleted file mode 100644 index dd888ac95..000000000 --- a/modules/ocl/perf/perf_haar.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/*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/objdetect/objdetect_c.h" - -using namespace perf; - -///////////// Haar //////////////////////// -PERF_TEST(HaarFixture, Haar) -{ - vector faces; - - Mat img = imread(getDataPath("gpu/haarcascade/basketball1.png"), IMREAD_GRAYSCALE); - ASSERT_TRUE(!img.empty()) << "can't open basketball1.png"; - declare.in(img); - - if (RUN_PLAIN_IMPL) - { - CascadeClassifier faceCascade; - ASSERT_TRUE(faceCascade.load(getDataPath("gpu/haarcascade/haarcascade_frontalface_alt.xml"))) - << "can't load haarcascade_frontalface_alt.xml"; - - TEST_CYCLE() faceCascade.detectMultiScale(img, faces, - 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30)); - - SANITY_CHECK(faces, 4 + 1e-4); - } - else if (RUN_OCL_IMPL) - { - ocl::OclCascadeClassifier faceCascade; - ocl::oclMat oclImg(img); - - ASSERT_TRUE(faceCascade.load(getDataPath("gpu/haarcascade/haarcascade_frontalface_alt.xml"))) - << "can't load haarcascade_frontalface_alt.xml"; - - OCL_TEST_CYCLE() faceCascade.detectMultiScale(oclImg, faces, - 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30)); - - SANITY_CHECK(faces, 4 + 1e-4); - } - else - OCL_PERF_ELSE -} - -using namespace std; -using namespace cv; -using namespace perf; -using std::tr1::make_tuple; -using std::tr1::get; - -typedef std::tr1::tuple OCL_Cascade_Image_MinSize_t; -typedef perf::TestBaseWithParam OCL_Cascade_Image_MinSize; - -PERF_TEST_P( OCL_Cascade_Image_MinSize, CascadeClassifier, - testing::Combine( - testing::Values( string("cv/cascadeandhog/cascades/haarcascade_frontalface_alt.xml") ), - testing::Values( string("cv/shared/lena.png"), - string("cv/cascadeandhog/images/bttf301.png")/*, - string("cv/cascadeandhog/images/class57.png")*/ ), - testing::Values(30, 64, 90) ) ) -{ - const string cascasePath = get<0>(GetParam()); - const string imagePath = get<1>(GetParam()); - const int min_size = get<2>(GetParam()); - Size minSize(min_size, min_size); - vector faces; - - Mat img = imread(getDataPath(imagePath), IMREAD_GRAYSCALE); - ASSERT_TRUE(!img.empty()) << "Can't load source image: " << getDataPath(imagePath); - equalizeHist(img, img); - declare.in(img); - - if (RUN_PLAIN_IMPL) - { - CascadeClassifier cc; - ASSERT_TRUE(cc.load(getDataPath(cascasePath))) << "Can't load cascade file: " << getDataPath(cascasePath); - - while (next()) - { - faces.clear(); - - startTimer(); - cc.detectMultiScale(img, faces, 1.1, 3, 0, minSize); - stopTimer(); - } - } - else if (RUN_OCL_IMPL) - { - ocl::oclMat uimg(img); - ocl::OclCascadeClassifier cc; - ASSERT_TRUE(cc.load(getDataPath(cascasePath))) << "Can't load cascade file: " << getDataPath(cascasePath); - - while (next()) - { - faces.clear(); - ocl::finish(); - - startTimer(); - cc.detectMultiScale(uimg, faces, 1.1, 3, 0, minSize); - stopTimer(); - } - } - else - OCL_PERF_ELSE - - //sort(faces.begin(), faces.end(), comparators::RectLess()); - SANITY_CHECK_NOTHING();//(faces, min_size/5); - // using SANITY_CHECK_NOTHING() since OCL and PLAIN version may find different faces number -} diff --git a/modules/ocl/perf/perf_hog.cpp b/modules/ocl/perf/perf_hog.cpp deleted file mode 100644 index 2a6731117..000000000 --- a/modules/ocl/perf/perf_hog.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/*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" - -using namespace perf; - -///////////// HOG//////////////////////// - -struct RectLess : - public std::binary_function -{ - bool operator()(const cv::Rect& a, - const cv::Rect& b) const - { - if (a.x != b.x) - return a.x < b.x; - else if (a.y != b.y) - return a.y < b.y; - else if (a.width != b.width) - return a.width < b.width; - else - return a.height < b.height; - } -}; - -PERF_TEST(HOGFixture, HOG) -{ - Mat src = imread(getDataPath("gpu/hog/road.png"), cv::IMREAD_GRAYSCALE); - ASSERT_TRUE(!src.empty()) << "can't open input image road.png"; - - vector found_locations; - declare.in(src).time(5); - - if (RUN_PLAIN_IMPL) - { - HOGDescriptor hog; - hog.setSVMDetector(hog.getDefaultPeopleDetector()); - - TEST_CYCLE() hog.detectMultiScale(src, found_locations); - - std::sort(found_locations.begin(), found_locations.end(), RectLess()); - SANITY_CHECK(found_locations, 1 + DBL_EPSILON); - } - else if (RUN_OCL_IMPL) - { - ocl::HOGDescriptor ocl_hog; - ocl_hog.setSVMDetector(ocl_hog.getDefaultPeopleDetector()); - ocl::oclMat oclSrc(src); - - OCL_TEST_CYCLE() ocl_hog.detectMultiScale(oclSrc, found_locations); - - std::sort(found_locations.begin(), found_locations.end(), RectLess()); - SANITY_CHECK(found_locations, 1 + DBL_EPSILON); - } - else - OCL_PERF_ELSE -} diff --git a/modules/ocl/perf/perf_hough.cpp b/modules/ocl/perf/perf_hough.cpp deleted file mode 100644 index e90356acb..000000000 --- a/modules/ocl/perf/perf_hough.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/*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. -// -// 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" - -#ifdef HAVE_OPENCL - -using namespace cv; -using namespace perf; - -////////////////////////////////////////////////////////////////////// -// HoughCircles - -typedef std::tr1::tuple Size_Dp_MinDist_t; -typedef perf::TestBaseWithParam Size_Dp_MinDist; - -PERF_TEST_P(Size_Dp_MinDist, OCL_HoughCircles, - testing::Combine( - testing::Values(perf::sz720p, perf::szSXGA, perf::sz1080p), - testing::Values(1.0f, 2.0f, 4.0f), - testing::Values(1.0f, 10.0f))) -{ - const Size_Dp_MinDist_t params = GetParam(); - const cv::Size size = std::tr1::get<0>(params); - const float dp = std::tr1::get<1>(params); - const float minDist = std::tr1::get<2>(params); - - const int minRadius = 10; - const int maxRadius = 30; - const int cannyThreshold = 100; - const int votesThreshold = 15; - - cv::RNG rng(123456789); - - cv::Mat src(size, CV_8UC1, cv::Scalar::all(0)), circles; - - const int numCircles = rng.uniform(50, 100); - for (int i = 0; i < numCircles; ++i) - { - cv::Point center(rng.uniform(0, src.cols), rng.uniform(0, src.rows)); - const int radius = rng.uniform(minRadius, maxRadius + 1); - - cv::circle(src, center, radius, cv::Scalar::all(255), -1); - } - - declare.time(10.0).iterations(25); - - if (RUN_OCL_IMPL) - { - cv::ocl::oclMat ocl_src(src), ocl_circles; - - OCL_TEST_CYCLE() cv::ocl::HoughCircles(ocl_src, ocl_circles, HOUGH_GRADIENT, dp, minDist, - cannyThreshold, votesThreshold, minRadius, maxRadius); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::HoughCircles(src, circles, HOUGH_GRADIENT, dp, minDist, cannyThreshold, - votesThreshold, minRadius, maxRadius); - } - else - OCL_PERF_ELSE - - int value = 0; - SANITY_CHECK(value); -} - -#endif // HAVE_OPENCL diff --git a/modules/ocl/perf/perf_imgproc.cpp b/modules/ocl/perf/perf_imgproc.cpp deleted file mode 100644 index 51b354f41..000000000 --- a/modules/ocl/perf/perf_imgproc.cpp +++ /dev/null @@ -1,737 +0,0 @@ -/*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" - -using namespace perf; -using std::tr1::tuple; -using std::tr1::get; - -///////////// equalizeHist //////////////////////// - -typedef TestBaseWithParam equalizeHistFixture; - -PERF_TEST_P(equalizeHistFixture, equalizeHist, OCL_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - const double eps = 1 + DBL_EPSILON; - - Mat src(srcSize, CV_8UC1), dst(srcSize, CV_8UC1); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, src.type()); - - OCL_TEST_CYCLE() cv::ocl::equalizeHist(oclSrc, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst, eps); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::equalizeHist(src, dst); - - SANITY_CHECK(dst, eps); - } - else - OCL_PERF_ELSE -} - -/////////// CopyMakeBorder ////////////////////// - -CV_ENUM(Border, BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT, - BORDER_WRAP, BORDER_REFLECT_101) - -typedef tuple CopyMakeBorderParamType; -typedef TestBaseWithParam CopyMakeBorderFixture; - -PERF_TEST_P(CopyMakeBorderFixture, CopyMakeBorder, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4), - Border::all())) -{ - const CopyMakeBorderParamType params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params), borderType = get<2>(params); - - Mat src(srcSize, type), dst; - const Size dstSize = srcSize + Size(12, 12); - dst.create(dstSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(dstSize, type); - - OCL_TEST_CYCLE() cv::ocl::copyMakeBorder(oclSrc, oclDst, 7, 5, 5, 7, borderType, cv::Scalar(1.0)); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::copyMakeBorder(src, dst, 7, 5, 5, 7, borderType, cv::Scalar(1.0)); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// cornerMinEigenVal //////////////////////// - -typedef Size_MatType cornerMinEigenValFixture; - -PERF_TEST_P(cornerMinEigenValFixture, cornerMinEigenVal, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params), borderType = BORDER_REFLECT; - const int blockSize = 7, apertureSize = 1 + 2 * 3; - - Mat src(srcSize, type), dst(srcSize, CV_32FC1); - declare.in(src, WARMUP_RNG).out(dst) - .time(srcSize == OCL_SIZE_4000 ? 20 : srcSize == OCL_SIZE_2000 ? 5 : 3); - - const int depth = CV_MAT_DEPTH(type); - const ERROR_TYPE errorType = depth == CV_8U ? ERROR_ABSOLUTE : ERROR_RELATIVE; - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, CV_32FC1); - - OCL_TEST_CYCLE() cv::ocl::cornerMinEigenVal(oclSrc, oclDst, blockSize, apertureSize, borderType); - - oclDst.download(dst); - - SANITY_CHECK(dst, 1e-6, errorType); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::cornerMinEigenVal(src, dst, blockSize, apertureSize, borderType); - - SANITY_CHECK(dst, 1e-6, errorType); - } - else - OCL_PERF_ELSE -} - -///////////// cornerHarris //////////////////////// - -typedef Size_MatType cornerHarrisFixture; - -PERF_TEST_P(cornerHarrisFixture, cornerHarris, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params), borderType = BORDER_REFLECT; - - Mat src(srcSize, type), dst(srcSize, CV_32FC1); - randu(src, 0, 1); - declare.in(src).out(dst) - .time(srcSize == OCL_SIZE_4000 ? 20 : srcSize == OCL_SIZE_2000 ? 5 : 3); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, CV_32FC1); - - OCL_TEST_CYCLE() cv::ocl::cornerHarris(oclSrc, oclDst, 5, 7, 0.1, borderType); - - oclDst.download(dst); - - SANITY_CHECK(dst, 3e-5); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::cornerHarris(src, dst, 5, 7, 0.1, borderType); - - SANITY_CHECK(dst, 3e-5); - } - else - OCL_PERF_ELSE -} - -///////////// integral //////////////////////// - -typedef TestBaseWithParam integralFixture; - -PERF_TEST_P(integralFixture, integral, OCL_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - - Mat src(srcSize, CV_8UC1), dst; - declare.in(src, WARMUP_RNG); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst; - - OCL_TEST_CYCLE() cv::ocl::integral(oclSrc, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::integral(src, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// threshold//////////////////////// - -CV_ENUM(ThreshType, THRESH_BINARY, THRESH_TOZERO_INV) - -typedef tuple ThreshParams; -typedef TestBaseWithParam ThreshFixture; - -PERF_TEST_P(ThreshFixture, threshold, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4, CV_16SC1, CV_16SC4, CV_32FC1), - ThreshType::all())) -{ - const ThreshParams params = GetParam(); - const Size srcSize = get<0>(params); - const int srcType = get<1>(params); - const int threshType = get<2>(params); - const double maxValue = 220.0, threshold = 50; - - Mat src(srcSize, srcType), dst(srcSize, srcType); - randu(src, 0, 100); - declare.in(src).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, CV_8U); - - OCL_TEST_CYCLE() cv::ocl::threshold(oclSrc, oclDst, threshold, maxValue, threshType); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::threshold(src, dst, threshold, maxValue, threshType); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// meanShiftFiltering//////////////////////// - -typedef struct _COOR -{ - short x; - short y; -} COOR; - -static COOR do_meanShift(int x0, int y0, uchar *sptr, uchar *dptr, int sstep, cv::Size size, int sp, int sr, int maxIter, float eps, int *tab) -{ - - int isr2 = sr * sr; - int c0, c1, c2, c3; - int iter; - uchar *ptr = NULL; - uchar *pstart = NULL; - int revx = 0, revy = 0; - c0 = sptr[0]; - c1 = sptr[1]; - c2 = sptr[2]; - c3 = sptr[3]; - // iterate meanshift procedure - for(iter = 0; iter < maxIter; iter++ ) - { - int count = 0; - int s0 = 0, s1 = 0, s2 = 0, sx = 0, sy = 0; - - //mean shift: process pixels in window (p-sigmaSp)x(p+sigmaSp) - int minx = x0 - sp; - int miny = y0 - sp; - int maxx = x0 + sp; - int maxy = y0 + sp; - - //deal with the image boundary - if(minx < 0) minx = 0; - if(miny < 0) miny = 0; - if(maxx >= size.width) maxx = size.width - 1; - if(maxy >= size.height) maxy = size.height - 1; - if(iter == 0) - { - pstart = sptr; - } - else - { - pstart = pstart + revy * sstep + (revx << 2); //point to the new position - } - ptr = pstart; - ptr = ptr + (miny - y0) * sstep + ((minx - x0) << 2); //point to the start in the row - - for( int y = miny; y <= maxy; y++, ptr += sstep - ((maxx - minx + 1) << 2)) - { - int rowCount = 0; - int x = minx; -#if CV_ENABLE_UNROLLED - for( ; x + 4 <= maxx; x += 4, ptr += 16) - { - int t0, t1, t2; - t0 = ptr[0], t1 = ptr[1], t2 = ptr[2]; - if(tab[t0 - c0 + 255] + tab[t1 - c1 + 255] + tab[t2 - c2 + 255] <= isr2) - { - s0 += t0; - s1 += t1; - s2 += t2; - sx += x; - rowCount++; - } - t0 = ptr[4], t1 = ptr[5], t2 = ptr[6]; - if(tab[t0 - c0 + 255] + tab[t1 - c1 + 255] + tab[t2 - c2 + 255] <= isr2) - { - s0 += t0; - s1 += t1; - s2 += t2; - sx += x + 1; - rowCount++; - } - t0 = ptr[8], t1 = ptr[9], t2 = ptr[10]; - if(tab[t0 - c0 + 255] + tab[t1 - c1 + 255] + tab[t2 - c2 + 255] <= isr2) - { - s0 += t0; - s1 += t1; - s2 += t2; - sx += x + 2; - rowCount++; - } - t0 = ptr[12], t1 = ptr[13], t2 = ptr[14]; - if(tab[t0 - c0 + 255] + tab[t1 - c1 + 255] + tab[t2 - c2 + 255] <= isr2) - { - s0 += t0; - s1 += t1; - s2 += t2; - sx += x + 3; - rowCount++; - } - } -#endif - for(; x <= maxx; x++, ptr += 4) - { - int t0 = ptr[0], t1 = ptr[1], t2 = ptr[2]; - if(tab[t0 - c0 + 255] + tab[t1 - c1 + 255] + tab[t2 - c2 + 255] <= isr2) - { - s0 += t0; - s1 += t1; - s2 += t2; - sx += x; - rowCount++; - } - } - if(rowCount == 0) - continue; - count += rowCount; - sy += y * rowCount; - } - - if( count == 0 ) - break; - - int x1 = sx / count; - int y1 = sy / count; - s0 = s0 / count; - s1 = s1 / count; - s2 = s2 / count; - - bool stopFlag = (x0 == x1 && y0 == y1) || (abs(x1 - x0) + abs(y1 - y0) + - tab[s0 - c0 + 255] + tab[s1 - c1 + 255] + tab[s2 - c2 + 255] <= eps); - - //revise the pointer corresponding to the new (y0,x0) - revx = x1 - x0; - revy = y1 - y0; - - x0 = x1; - y0 = y1; - c0 = s0; - c1 = s1; - c2 = s2; - - if( stopFlag ) - break; - } //for iter - - dptr[0] = (uchar)c0; - dptr[1] = (uchar)c1; - dptr[2] = (uchar)c2; - dptr[3] = (uchar)c3; - - COOR coor; - coor.x = static_cast(x0); - coor.y = static_cast(y0); - return coor; -} - -static void meanShiftFiltering_(const Mat &src_roi, Mat &dst_roi, int sp, int sr, cv::TermCriteria crit) -{ - if( src_roi.empty() ) - CV_Error( Error::StsBadArg, "The input image is empty" ); - - if( src_roi.depth() != CV_8U || src_roi.channels() != 4 ) - CV_Error( Error::StsUnsupportedFormat, "Only 8-bit, 4-channel images are supported" ); - - dst_roi.create(src_roi.size(), src_roi.type()); - - CV_Assert( (src_roi.cols == dst_roi.cols) && (src_roi.rows == dst_roi.rows) ); - CV_Assert( !(dst_roi.step & 0x3) ); - - if( !(crit.type & cv::TermCriteria::MAX_ITER) ) - crit.maxCount = 5; - int maxIter = std::min(std::max(crit.maxCount, 1), 100); - float eps; - if( !(crit.type & cv::TermCriteria::EPS) ) - eps = 1.f; - eps = (float)std::max(crit.epsilon, 0.0); - - int tab[512]; - for(int i = 0; i < 512; i++) - tab[i] = (i - 255) * (i - 255); - uchar *sptr = src_roi.data; - uchar *dptr = dst_roi.data; - int sstep = (int)src_roi.step; - int dstep = (int)dst_roi.step; - cv::Size size = src_roi.size(); - - for(int i = 0; i < size.height; i++, sptr += sstep - (size.width << 2), - dptr += dstep - (size.width << 2)) - { - for(int j = 0; j < size.width; j++, sptr += 4, dptr += 4) - { - do_meanShift(j, i, sptr, dptr, sstep, size, sp, sr, maxIter, eps, tab); - } - } -} - -typedef TestBaseWithParam meanShiftFilteringFixture; - -PERF_TEST_P(meanShiftFilteringFixture, meanShiftFiltering, - OCL_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - const int sp = 5, sr = 6; - cv::TermCriteria crit(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 5, 1); - - Mat src(srcSize, CV_8UC4), dst(srcSize, CV_8UC4); - declare.in(src, WARMUP_RNG).out(dst) - .time(srcSize == OCL_SIZE_4000 ? - 56 : srcSize == OCL_SIZE_2000 ? 15 : 3.8); - - if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() meanShiftFiltering_(src, dst, sp, sr, crit); - - SANITY_CHECK(dst); - } - else if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, CV_8UC4); - - OCL_TEST_CYCLE() ocl::meanShiftFiltering(oclSrc, oclDst, sp, sr, crit); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -static void meanShiftProc_(const Mat &src_roi, Mat &dst_roi, Mat &dstCoor_roi, int sp, int sr, cv::TermCriteria crit) -{ - if (src_roi.empty()) - { - CV_Error(Error::StsBadArg, "The input image is empty"); - } - if (src_roi.depth() != CV_8U || src_roi.channels() != 4) - { - CV_Error(Error::StsUnsupportedFormat, "Only 8-bit, 4-channel images are supported"); - } - - dst_roi.create(src_roi.size(), src_roi.type()); - dstCoor_roi.create(src_roi.size(), CV_16SC2); - - CV_Assert((src_roi.cols == dst_roi.cols) && (src_roi.rows == dst_roi.rows) && - (src_roi.cols == dstCoor_roi.cols) && (src_roi.rows == dstCoor_roi.rows)); - CV_Assert(!(dstCoor_roi.step & 0x3)); - - if (!(crit.type & cv::TermCriteria::MAX_ITER)) - { - crit.maxCount = 5; - } - - int maxIter = std::min(std::max(crit.maxCount, 1), 100); - float eps; - - if (!(crit.type & cv::TermCriteria::EPS)) - { - eps = 1.f; - } - - eps = (float)std::max(crit.epsilon, 0.0); - - int tab[512]; - - for (int i = 0; i < 512; i++) - { - tab[i] = (i - 255) * (i - 255); - } - - uchar *sptr = src_roi.data; - uchar *dptr = dst_roi.data; - short *dCoorptr = (short *)dstCoor_roi.data; - int sstep = (int)src_roi.step; - int dstep = (int)dst_roi.step; - int dCoorstep = (int)dstCoor_roi.step >> 1; - cv::Size size = src_roi.size(); - - for (int i = 0; i < size.height; i++, sptr += sstep - (size.width << 2), - dptr += dstep - (size.width << 2), dCoorptr += dCoorstep - (size.width << 1)) - { - for (int j = 0; j < size.width; j++, sptr += 4, dptr += 4, dCoorptr += 2) - { - *((COOR *)dCoorptr) = do_meanShift(j, i, sptr, dptr, sstep, size, sp, sr, maxIter, eps, tab); - } - } - -} - -typedef TestBaseWithParam meanShiftProcFixture; - -PERF_TEST_P(meanShiftProcFixture, meanShiftProc, - OCL_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - TermCriteria crit(TermCriteria::COUNT + TermCriteria::EPS, 5, 1); - - Mat src(srcSize, CV_8UC4), dst1(srcSize, CV_8UC4), - dst2(srcSize, CV_16SC2); - declare.in(src, WARMUP_RNG).out(dst1, dst2) - .time(srcSize == OCL_SIZE_4000 ? - 56 : srcSize == OCL_SIZE_2000 ? 15 : 3.8);; - - if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() meanShiftProc_(src, dst1, dst2, 5, 6, crit); - - SANITY_CHECK(dst1); - SANITY_CHECK(dst2); - } - else if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst1(srcSize, CV_8UC4), - oclDst2(srcSize, CV_16SC2); - - OCL_TEST_CYCLE() ocl::meanShiftProc(oclSrc, oclDst1, oclDst2, 5, 6, crit); - - oclDst1.download(dst1); - oclDst2.download(dst2); - - SANITY_CHECK(dst1); - SANITY_CHECK(dst2); - } - else - OCL_PERF_ELSE -} - -///////////// CLAHE //////////////////////// - -typedef TestBaseWithParam CLAHEFixture; - -PERF_TEST_P(CLAHEFixture, CLAHE, OCL_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - const string impl = getSelectedImpl(); - - Mat src(srcSize, CV_8UC1), dst; - const double clipLimit = 40.0; - declare.in(src, WARMUP_RNG); - - if (srcSize == OCL_SIZE_4000) - declare.time(11); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst; - cv::Ptr oclClahe = cv::ocl::createCLAHE(clipLimit); - - OCL_TEST_CYCLE() oclClahe->apply(oclSrc, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - cv::Ptr clahe = cv::createCLAHE(clipLimit); - TEST_CYCLE() clahe->apply(src, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// columnSum//////////////////////// - -typedef TestBaseWithParam columnSumFixture; - -static void columnSumPerfTest(const Mat & src, Mat & dst) -{ - for (int j = 0; j < src.cols; j++) - dst.at(0, j) = src.at(0, j); - - for (int i = 1; i < src.rows; ++i) - for (int j = 0; j < src.cols; ++j) - dst.at(i, j) = dst.at(i - 1 , j) + src.at(i , j); -} - -PERF_TEST_P(columnSumFixture, columnSum, OCL_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(); - - Mat src(srcSize, CV_32FC1), dst(srcSize, CV_32FC1); - declare.in(src, WARMUP_RNG).out(dst); - - if (srcSize == OCL_SIZE_4000) - declare.time(5); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, CV_32FC1); - - OCL_TEST_CYCLE() cv::ocl::columnSum(oclSrc, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() columnSumPerfTest(src, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -//////////////////////////////distanceToCenters//////////////////////////////////////////////// - -CV_ENUM(DistType, NORM_L1, NORM_L2SQR) - -typedef tuple distanceToCentersParameters; -typedef TestBaseWithParam distanceToCentersFixture; - -static void distanceToCentersPerfTest(Mat& src, Mat& centers, Mat& dists, Mat& labels, int distType) -{ - Mat batch_dists; - cv::batchDistance(src, centers, batch_dists, CV_32FC1, noArray(), distType); - - std::vector dists_v; - std::vector labels_v; - - for (int i = 0; i < batch_dists.rows; i++) - { - Mat r = batch_dists.row(i); - double mVal; - Point mLoc; - - minMaxLoc(r, &mVal, NULL, &mLoc, NULL); - dists_v.push_back(static_cast(mVal)); - labels_v.push_back(mLoc.x); - } - - Mat(dists_v).copyTo(dists); - Mat(labels_v).copyTo(labels); -} - -PERF_TEST_P(distanceToCentersFixture, distanceToCenters, ::testing::Combine(::testing::Values(cv::Size(256,256), cv::Size(512,512)), DistType::all()) ) -{ - Size size = get<0>(GetParam()); - int distType = get<1>(GetParam()); - - Mat src(size, CV_32FC1), centers(size, CV_32FC1); - Mat dists(src.rows, 1, CV_32FC1), labels(src.rows, 1, CV_32SC1); - - declare.in(src, centers, WARMUP_RNG).out(dists, labels); - - if (RUN_OCL_IMPL) - { - ocl::oclMat ocl_src(src), ocl_centers(centers); - - OCL_TEST_CYCLE() ocl::distanceToCenters(ocl_src, ocl_centers, dists, labels, distType); - - SANITY_CHECK(dists, 1e-6, ERROR_RELATIVE); - SANITY_CHECK(labels); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() distanceToCentersPerfTest(src, centers, dists, labels, distType); - - SANITY_CHECK(dists, 1e-6, ERROR_RELATIVE); - SANITY_CHECK(labels); - } - else - OCL_PERF_ELSE -} diff --git a/modules/ocl/perf/perf_imgwarp.cpp b/modules/ocl/perf/perf_imgwarp.cpp deleted file mode 100644 index e768d6621..000000000 --- a/modules/ocl/perf/perf_imgwarp.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/*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" - -using namespace perf; -using std::tr1::tuple; -using std::tr1::get; - -///////////// WarpAffine //////////////////////// - -typedef Size_MatType WarpAffineFixture; - -PERF_TEST_P(WarpAffineFixture, WarpAffine, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - static const double coeffs[2][3] = - { - { cos(CV_PI / 6), -sin(CV_PI / 6), 100.0 }, - { sin(CV_PI / 6), cos(CV_PI / 6), -100.0 } - }; - Mat M(2, 3, CV_64F, (void *)coeffs); - const int interpolation = INTER_NEAREST; - - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::warpAffine(oclSrc, oclDst, M, srcSize, interpolation); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::warpAffine(src, dst, M, srcSize, interpolation); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// WarpPerspective //////////////////////// - -typedef Size_MatType WarpPerspectiveFixture; - -PERF_TEST_P(WarpPerspectiveFixture, WarpPerspective, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - static const double coeffs[3][3] = - { - {cos(CV_PI / 6), -sin(CV_PI / 6), 100.0}, - {sin(CV_PI / 6), cos(CV_PI / 6), -100.0}, - {0.0, 0.0, 1.0} - }; - Mat M(3, 3, CV_64F, (void *)coeffs); - const int interpolation = INTER_LINEAR; - - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst) - .time(srcSize == OCL_SIZE_4000 ? 18 : srcSize == OCL_SIZE_2000 ? 5 : 2); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() cv::ocl::warpPerspective(oclSrc, oclDst, M, srcSize, interpolation); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::warpPerspective(src, dst, M, srcSize, interpolation); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// resize //////////////////////// - -CV_ENUM(resizeInterType, INTER_NEAREST, INTER_LINEAR) - -typedef tuple resizeParams; -typedef TestBaseWithParam resizeFixture; - -PERF_TEST_P(resizeFixture, resize, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4), - resizeInterType::all(), - ::testing::Values(0.5, 2.0))) -{ - const resizeParams params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params), interType = get<2>(params); - double scale = get<3>(params); - const Size dstSize(cvRound(srcSize.width * scale), cvRound(srcSize.height * scale)); - - checkDeviceMaxMemoryAllocSize(srcSize, type); - checkDeviceMaxMemoryAllocSize(dstSize, type); - - Mat src(srcSize, type), dst; - dst.create(dstSize, type); - declare.in(src, WARMUP_RNG).out(dst); - if (interType == INTER_LINEAR && type == CV_8UC4 && OCL_SIZE_4000 == srcSize) - declare.time(11); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(dstSize, type); - - OCL_TEST_CYCLE() cv::ocl::resize(oclSrc, oclDst, Size(), scale, scale, interType); - - oclDst.download(dst); - - SANITY_CHECK(dst, 1 + DBL_EPSILON); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::resize(src, dst, Size(), scale, scale, interType); - - SANITY_CHECK(dst, 1 + DBL_EPSILON); - } - else - OCL_PERF_ELSE -} - -typedef tuple resizeAreaParams; -typedef TestBaseWithParam resizeAreaFixture; - -PERF_TEST_P(resizeAreaFixture, resize, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4, CV_32FC1, CV_32FC4), - ::testing::Values(0.3, 0.5, 0.6))) -{ - const resizeAreaParams params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - double scale = get<2>(params); - const Size dstSize(cvRound(srcSize.width * scale), cvRound(srcSize.height * scale)); - - checkDeviceMaxMemoryAllocSize(srcSize, type); - - Mat src(srcSize, type), dst; - dst.create(dstSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(dstSize, type); - - OCL_TEST_CYCLE() cv::ocl::resize(oclSrc, oclDst, Size(), scale, scale, cv::INTER_AREA); - - oclDst.download(dst); - - SANITY_CHECK(dst, 1 + DBL_EPSILON); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::resize(src, dst, Size(), scale, scale, cv::INTER_AREA); - - SANITY_CHECK(dst, 1 + DBL_EPSILON); - } - else - OCL_PERF_ELSE -} - -///////////// remap//////////////////////// - -CV_ENUM(RemapInterType, INTER_NEAREST, INTER_LINEAR) - -typedef tuple remapParams; -typedef TestBaseWithParam remapFixture; - -PERF_TEST_P(remapFixture, remap, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4), - RemapInterType::all())) -{ - const remapParams params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params), interpolation = get<2>(params); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (srcSize == OCL_SIZE_4000 && interpolation == INTER_LINEAR) - declare.time(9); - - Mat xmap, ymap; - xmap.create(srcSize, CV_32FC1); - ymap.create(srcSize, CV_32FC1); - - for (int i = 0; i < srcSize.height; ++i) - { - float * const xmap_row = xmap.ptr(i); - float * const ymap_row = ymap.ptr(i); - - for (int j = 0; j < srcSize.width; ++j) - { - xmap_row[j] = (j - srcSize.width * 0.5f) * 0.75f + srcSize.width * 0.5f; - ymap_row[j] = (i - srcSize.height * 0.5f) * 0.75f + srcSize.height * 0.5f; - } - } - - const int borderMode = BORDER_CONSTANT; - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - ocl::oclMat oclXMap(xmap), oclYMap(ymap); - - OCL_TEST_CYCLE() cv::ocl::remap(oclSrc, oclDst, oclXMap, oclYMap, interpolation, borderMode); - - oclDst.download(dst); - - SANITY_CHECK(dst, 1 + DBL_EPSILON); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::remap(src, dst, xmap, ymap, interpolation, borderMode); - - SANITY_CHECK(dst, 1 + DBL_EPSILON); - } - else - OCL_PERF_ELSE -} - - -///////////// buildWarpPerspectiveMaps //////////////////////// - -static void buildWarpPerspectiveMaps(const Mat &M, bool inverse, Size dsize, Mat &xmap, Mat &ymap) -{ - CV_Assert(M.rows == 3 && M.cols == 3); - CV_Assert(dsize.area() > 0); - - xmap.create(dsize, CV_32FC1); - ymap.create(dsize, CV_32FC1); - - float coeffs[3 * 3]; - Mat coeffsMat(3, 3, CV_32F, (void *)coeffs); - - if (inverse) - M.convertTo(coeffsMat, coeffsMat.type()); - else - { - cv::Mat iM; - invert(M, iM); - iM.convertTo(coeffsMat, coeffsMat.type()); - } - - for (int y = 0; y < dsize.height; ++y) - { - float * const xmap_ptr = xmap.ptr(y); - float * const ymap_ptr = ymap.ptr(y); - - for (int x = 0; x < dsize.width; ++x) - { - float coeff = 1.0f / (x * coeffs[6] + y * coeffs[7] + coeffs[8]); - xmap_ptr[x] = (x * coeffs[0] + y * coeffs[1] + coeffs[2]) * coeff; - ymap_ptr[x] = (x * coeffs[3] + y * coeffs[4] + coeffs[5]) * coeff; - } - } -} - -typedef TestBaseWithParam buildWarpPerspectiveMapsFixture; - -PERF_TEST_P(buildWarpPerspectiveMapsFixture, Inverse, OCL_TYPICAL_MAT_SIZES) -{ - static const double coeffs[3][3] = - { - {cos(CV_PI / 6), -sin(CV_PI / 6), 100.0}, - {sin(CV_PI / 6), cos(CV_PI / 6), -100.0}, - {0.0, 0.0, 1.0} - }; - Mat M(3, 3, CV_64F, (void *)coeffs); - const Size dsize = GetParam(); - const double eps = 5e-4; - - Mat xmap(dsize, CV_32FC1), ymap(dsize, CV_32FC1); - declare.in(M).out(xmap, ymap); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclXMap(dsize, CV_32FC1), oclYMap(dsize, CV_32FC1); - - OCL_TEST_CYCLE() cv::ocl::buildWarpPerspectiveMaps(M, true, dsize, oclXMap, oclYMap); - - oclXMap.download(xmap); - oclYMap.download(ymap); - - SANITY_CHECK(xmap, eps); - SANITY_CHECK(ymap, eps); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() buildWarpPerspectiveMaps(M, true, dsize, xmap, ymap); - - SANITY_CHECK(xmap, eps); - SANITY_CHECK(ymap, eps); - } - else - OCL_PERF_ELSE -} diff --git a/modules/ocl/perf/perf_kalman.cpp b/modules/ocl/perf/perf_kalman.cpp deleted file mode 100644 index 946444ad9..000000000 --- a/modules/ocl/perf/perf_kalman.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/*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" - -#ifdef HAVE_CLAMDBLAS - -using namespace perf; -using namespace std; -using namespace cv::ocl; -using namespace cv; -using std::tr1::tuple; -using std::tr1::get; - -///////////// Kalman Filter //////////////////////// - -typedef tuple KalmanFilterType; -typedef TestBaseWithParam KalmanFilterFixture; - -PERF_TEST_P(KalmanFilterFixture, KalmanFilter, - ::testing::Values(1000, 1500)) -{ - KalmanFilterType params = GetParam(); - const int dim = get<0>(params); - - cv::Mat sample(dim, 1, CV_32FC1), dresult; - randu(sample, -1, 1); - - cv::Mat statePre_; - - if (RUN_PLAIN_IMPL) - { - cv::KalmanFilter kalman; - TEST_CYCLE() - { - kalman.init(dim, dim); - kalman.correct(sample); - kalman.predict(); - } - statePre_ = kalman.statePre; - } - else if(RUN_OCL_IMPL) - { - cv::ocl::oclMat dsample(sample); - cv::ocl::KalmanFilter kalman_ocl; - OCL_TEST_CYCLE() - { - kalman_ocl.init(dim, dim); - kalman_ocl.correct(dsample); - kalman_ocl.predict(); - } - kalman_ocl.statePre.download(statePre_); - } - else - OCL_PERF_ELSE - - SANITY_CHECK(statePre_); -} - -#endif // HAVE_CLAMDBLAS diff --git a/modules/ocl/perf/perf_match_template.cpp b/modules/ocl/perf/perf_match_template.cpp deleted file mode 100644 index 9c9829cd9..000000000 --- a/modules/ocl/perf/perf_match_template.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/*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" - -using namespace perf; -using std::tr1::tuple; -using std::tr1::get; - -/////////// matchTemplate //////////////////////// - -typedef Size_MatType CV_TM_CCORRFixture; - -PERF_TEST_P(CV_TM_CCORRFixture, matchTemplate, - ::testing::Combine(::testing::Values(OCL_SIZE_1000, OCL_SIZE_2000), - OCL_PERF_ENUM(CV_32FC1, CV_32FC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params), templSize(5, 5); - const int type = get<1>(params); - - Mat src(srcSize, type), templ(templSize, type); - const Size dstSize(src.cols - templ.cols + 1, src.rows - templ.rows + 1); - Mat dst(dstSize, CV_32F); - randu(src, 0.0f, 1.0f); - randu(templ, 0.0f, 1.0f); - declare.time(srcSize == OCL_SIZE_2000 ? 20 : 6).in(src, templ).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclTempl(templ), oclDst(dstSize, CV_32F); - - OCL_TEST_CYCLE() cv::ocl::matchTemplate(oclSrc, oclTempl, oclDst, TM_CCORR); - - oclDst.download(dst); - - SANITY_CHECK(dst, 1e-4); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::matchTemplate(src, templ, dst, TM_CCORR); - - SANITY_CHECK(dst, 1e-4); - } - else - OCL_PERF_ELSE -} - -typedef TestBaseWithParam CV_TM_CCORR_NORMEDFixture; - -PERF_TEST_P(CV_TM_CCORR_NORMEDFixture, matchTemplate, OCL_TYPICAL_MAT_SIZES) -{ - const Size srcSize = GetParam(), templSize(5, 5); - - Mat src(srcSize, CV_8UC1), templ(templSize, CV_8UC1), dst; - const Size dstSize(src.cols - templ.cols + 1, src.rows - templ.rows + 1); - dst.create(dstSize, CV_8UC1); - declare.in(src, templ, WARMUP_RNG).out(dst) - .time(srcSize == OCL_SIZE_2000 ? 10 : srcSize == OCL_SIZE_4000 ? 23 : 2); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclTempl(templ), oclDst(dstSize, CV_8UC1); - - OCL_TEST_CYCLE() cv::ocl::matchTemplate(oclSrc, oclTempl, oclDst, TM_CCORR_NORMED); - - oclDst.download(dst); - - SANITY_CHECK(dst, 3e-2); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::matchTemplate(src, templ, dst, TM_CCORR_NORMED); - - SANITY_CHECK(dst, 3e-2); - } - else - OCL_PERF_ELSE -} diff --git a/modules/ocl/perf/perf_matrix_operation.cpp b/modules/ocl/perf/perf_matrix_operation.cpp deleted file mode 100644 index 5ca322e22..000000000 --- a/modules/ocl/perf/perf_matrix_operation.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/*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" - -using namespace perf; -using std::tr1::tuple; -using std::tr1::get; - -///////////// ConvertTo//////////////////////// - -typedef Size_MatType ConvertToFixture; - -PERF_TEST_P(ConvertToFixture, ConvertTo, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src(srcSize, type), dst; - const int dstType = CV_MAKE_TYPE(CV_32F, src.channels()); - - checkDeviceMaxMemoryAllocSize(srcSize, type); - checkDeviceMaxMemoryAllocSize(srcSize, dstType); - - dst.create(srcSize, dstType); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, dstType); - - OCL_TEST_CYCLE() oclSrc.convertTo(oclDst, dstType); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() src.convertTo(dst, dstType); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// copyTo//////////////////////// - -typedef Size_MatType copyToFixture; - -PERF_TEST_P(copyToFixture, copyTo, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - - Mat src(srcSize, type), dst(srcSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(srcSize, type); - - OCL_TEST_CYCLE() oclSrc.copyTo(oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() src.copyTo(dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// setTo//////////////////////// - -typedef Size_MatType setToFixture; - -PERF_TEST_P(setToFixture, setTo, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - const Scalar val(1, 2, 3, 4); - - Mat src(srcSize, type); - declare.in(src); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(srcSize, type); - - OCL_TEST_CYCLE() oclSrc.setTo(val); - oclSrc.download(src); - - SANITY_CHECK(src); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() src.setTo(val); - - SANITY_CHECK(src); - } - else - OCL_PERF_ELSE -} - -#if 0 - -/////////////////// upload /////////////////////////// - -typedef tuple uploadParams; -typedef TestBaseWithParam uploadFixture; - -PERF_TEST_P(uploadFixture, upload, - testing::Combine( - OCL_TYPICAL_MAT_SIZES, - testing::Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F), - testing::Range(1, 5))) -{ - const uploadParams params = GetParam(); - const Size srcSize = get<0>(params); - const int depth = get<1>(params), cn = get<2>(params); - const int type = CV_MAKE_TYPE(depth, cn); - - Mat src(srcSize, type), dst; - declare.in(src, WARMUP_RNG); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclDst; - - for(; startTimer(), next(); ocl::finish(), stopTimer(), oclDst.release()) - oclDst.upload(src); - } - else if (RUN_PLAIN_IMPL) - { - for(; startTimer(), next(); ocl::finish(), stopTimer(), dst.release()) - dst = src.clone(); - } - else - OCL_PERF_ELSE - - SANITY_CHECK_NOTHING(); -} - -/////////////////// download /////////////////////////// - -typedef TestBaseWithParam downloadFixture; - -PERF_TEST_P(downloadFixture, download, - testing::Combine( - OCL_TYPICAL_MAT_SIZES, - testing::Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F), - testing::Range(1, 5))) -{ - const uploadParams params = GetParam(); - const Size srcSize = get<0>(params); - const int depth = get<1>(params), cn = get<2>(params); - const int type = CV_MAKE_TYPE(depth, cn); - - Mat src(srcSize, type), dst; - declare.in(src, WARMUP_RNG); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src); - - for(; startTimer(), next(); ocl::finish(), stopTimer(), dst.release()) - oclSrc.download(dst); - } - else if (RUN_PLAIN_IMPL) - { - for(; startTimer(), next(); ocl::finish(), stopTimer(), dst.release()) - dst = src.clone(); - } - else - OCL_PERF_ELSE - - SANITY_CHECK_NOTHING(); -} - -#endif diff --git a/modules/ocl/perf/perf_ml.cpp b/modules/ocl/perf/perf_ml.cpp deleted file mode 100644 index db45eceb8..000000000 --- a/modules/ocl/perf/perf_ml.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/*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 -// Jin Ma, jin@multicorewareinc.com -// Xiaopeng Fu, fuxiaopeng2222@163.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" -using namespace perf; -using namespace std; -using namespace cv::ocl; -using namespace cv; -using std::tr1::tuple; -using std::tr1::get; -////////////////////////////////// K-NEAREST NEIGHBOR //////////////////////////////////// -static void genData(Mat& trainData, Size size, Mat& trainLabel = Mat().setTo(Scalar::all(0)), int nClasses = 0) -{ - trainData.create(size, CV_32FC1); - randu(trainData, 1.0, 100.0); - - if(nClasses != 0) - { - trainLabel.create(size.height, 1, CV_8UC1); - randu(trainLabel, 0, nClasses - 1); - trainLabel.convertTo(trainLabel, CV_32FC1); - } -} - -typedef tuple KNNParamType; -typedef TestBaseWithParam KNNFixture; - -PERF_TEST_P(KNNFixture, KNN, - testing::Values(1000, 2000, 4000)) -{ - KNNParamType params = GetParam(); - const int rows = get<0>(params); - int columns = 100; - int k = rows/250; - - Mat trainData, trainLabels; - Size size(columns, rows); - genData(trainData, size, trainLabels, 3); - - Mat testData; - genData(testData, size); - Mat best_label; - - if(RUN_PLAIN_IMPL) - { - TEST_CYCLE() - { - CvKNearest knn_cpu; - knn_cpu.train(trainData, trainLabels); - knn_cpu.find_nearest(testData, k, &best_label); - } - }else if(RUN_OCL_IMPL) - { - cv::ocl::oclMat best_label_ocl; - cv::ocl::oclMat testdata; - testdata.upload(testData); - - OCL_TEST_CYCLE() - { - cv::ocl::KNearestNeighbour knn_ocl; - knn_ocl.train(trainData, trainLabels); - knn_ocl.find_nearest(testdata, k, best_label_ocl); - } - best_label_ocl.download(best_label); - }else - OCL_PERF_ELSE - SANITY_CHECK(best_label); -} \ No newline at end of file diff --git a/modules/ocl/perf/perf_moments.cpp b/modules/ocl/perf/perf_moments.cpp deleted file mode 100644 index 631031ecb..000000000 --- a/modules/ocl/perf/perf_moments.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/*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" - -using namespace perf; -using std::tr1::tuple; -using std::tr1::get; -using namespace cv; -using namespace cv::ocl; -using namespace cvtest; -using namespace testing; -using namespace std; - - -///////////// Moments //////////////////////// -//*! performance of image -typedef tuple MomentsParamType; -typedef TestBaseWithParam MomentsFixture; - -PERF_TEST_P(MomentsFixture, Moments, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_16SC1, CV_16UC1, CV_32FC1), ::testing::Bool())) -{ - const MomentsParamType params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - const bool binaryImage = get<2>(params); - - Mat src(srcSize, type), dst(7, 1, CV_64F); - randu(src, 0, 255); - - cv::Moments mom; - if (RUN_OCL_IMPL) - { - oclMat src_d(src); - OCL_TEST_CYCLE() mom = cv::ocl::ocl_moments(src_d, binaryImage); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() mom = cv::moments(src, binaryImage); - } - else - OCL_PERF_ELSE - cv::HuMoments(mom, dst); - SANITY_CHECK(dst, 2e-1); -} diff --git a/modules/ocl/perf/perf_norm.cpp b/modules/ocl/perf/perf_norm.cpp deleted file mode 100644 index ff49eb4ed..000000000 --- a/modules/ocl/perf/perf_norm.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/*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" - -using namespace perf; -using std::tr1::tuple; -using std::tr1::get; - -///////////// norm//////////////////////// - -typedef tuple normParams; -typedef TestBaseWithParam normFixture; - -PERF_TEST_P(normFixture, norm, testing::Combine( - OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_32FC1))) -{ - const normParams params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - double value = 0.0; - const double eps = CV_MAT_DEPTH(type) == CV_8U ? DBL_EPSILON : 1e-3; - - Mat src1(srcSize, type), src2(srcSize, type); - declare.in(src1, src2, WARMUP_RNG); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc1(src1), oclSrc2(src2); - - OCL_TEST_CYCLE() value = cv::ocl::norm(oclSrc1, oclSrc2, NORM_INF); - - SANITY_CHECK(value, eps); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() value = cv::norm(src1, src2, NORM_INF); - - SANITY_CHECK(value); - } - else - OCL_PERF_ELSE -} diff --git a/modules/ocl/perf/perf_opticalflow.cpp b/modules/ocl/perf/perf_opticalflow.cpp deleted file mode 100644 index bc1761b49..000000000 --- a/modules/ocl/perf/perf_opticalflow.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/*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" - -///////////// PyrLKOpticalFlow //////////////////////// - -using namespace perf; -using std::tr1::get; -using std::tr1::tuple; -using std::tr1::make_tuple; - -CV_ENUM(LoadMode, IMREAD_GRAYSCALE, IMREAD_COLOR) - -typedef tuple > PyrLKOpticalFlowParamType; -typedef TestBaseWithParam PyrLKOpticalFlowFixture; - -PERF_TEST_P(PyrLKOpticalFlowFixture, - PyrLKOpticalFlow, - ::testing::Combine( - ::testing::Values(1000, 2000, 4000), - ::testing::Values( - make_tuple - ( - string("gpu/opticalflow/rubberwhale1.png"), - string("gpu/opticalflow/rubberwhale2.png"), - LoadMode(IMREAD_COLOR) - ), - make_tuple - ( - string("gpu/stereobm/aloe-L.png"), - string("gpu/stereobm/aloe-R.png"), - LoadMode(IMREAD_GRAYSCALE) - ) - ) - ) - ) -{ - PyrLKOpticalFlowParamType params = GetParam(); - tuple fileParam = get<1>(params); - const int pointsCount = get<0>(params); - const int openMode = static_cast(get<2>(fileParam)); - const string fileName0 = get<0>(fileParam), fileName1 = get<1>(fileParam); - Mat frame0 = imread(getDataPath(fileName0), openMode); - Mat frame1 = imread(getDataPath(fileName1), openMode); - - declare.in(frame0, frame1); - - ASSERT_FALSE(frame0.empty()) << "can't load " << fileName0; - ASSERT_FALSE(frame1.empty()) << "can't load " << fileName1; - - Mat grayFrame; - if (openMode == IMREAD_COLOR) - cvtColor(frame0, grayFrame, COLOR_BGR2GRAY); - else - grayFrame = frame0; - - vector pts, nextPts; - vector status; - vector err; - goodFeaturesToTrack(grayFrame, pts, pointsCount, 0.01, 0.0); - Mat ptsMat(1, static_cast(pts.size()), CV_32FC2, (void *)&pts[0]); - - if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() - cv::calcOpticalFlowPyrLK(frame0, frame1, pts, nextPts, status, err); - } - else if (RUN_OCL_IMPL) - { - ocl::PyrLKOpticalFlow oclPyrLK; - ocl::oclMat oclFrame0(frame0), oclFrame1(frame1); - ocl::oclMat oclPts(ptsMat); - ocl::oclMat oclNextPts, oclStatus, oclErr; - - OCL_TEST_CYCLE() - oclPyrLK.sparse(oclFrame0, oclFrame1, oclPts, oclNextPts, oclStatus, &oclErr); - } - else - OCL_PERF_ELSE - - int value = 0; - SANITY_CHECK(value); -} - -PERF_TEST(tvl1flowFixture, tvl1flow) -{ - Mat frame0 = imread(getDataPath("gpu/opticalflow/rubberwhale1.png"), cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame0.empty()) << "can't load rubberwhale1.png"; - - Mat frame1 = imread(getDataPath("gpu/opticalflow/rubberwhale2.png"), cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame1.empty()) << "can't load rubberwhale2.png"; - - const Size srcSize = frame0.size(); - const double eps = 1.2; - Mat flow(srcSize, CV_32FC2), flow1(srcSize, CV_32FC1), flow2(srcSize, CV_32FC1); - declare.in(frame0, frame1).out(flow1, flow2).time(159); - - if (RUN_PLAIN_IMPL) - { - Ptr alg = createOptFlow_DualTVL1(); - - TEST_CYCLE() alg->calc(frame0, frame1, flow); - - alg->collectGarbage(); - Mat flows[2] = { flow1, flow2 }; - split(flow, flows); - - SANITY_CHECK(flow1, eps); - SANITY_CHECK(flow2, eps); - } - else if (RUN_OCL_IMPL) - { - ocl::OpticalFlowDual_TVL1_OCL oclAlg; - ocl::oclMat oclFrame0(frame0), oclFrame1(frame1), oclFlow1(srcSize, CV_32FC1), - oclFlow2(srcSize, CV_32FC1); - - OCL_TEST_CYCLE() oclAlg(oclFrame0, oclFrame1, oclFlow1, oclFlow2); - - oclAlg.collectGarbage(); - - oclFlow1.download(flow1); - oclFlow2.download(flow2); - - SANITY_CHECK(flow1, eps); - SANITY_CHECK(flow2, eps); - } - else - OCL_PERF_ELSE -} - -///////////// FarnebackOpticalFlow //////////////////////// - -CV_ENUM(farneFlagType, 0, OPTFLOW_FARNEBACK_GAUSSIAN) - -typedef tuple, farneFlagType, bool> FarnebackOpticalFlowParams; -typedef TestBaseWithParam FarnebackOpticalFlowFixture; - -PERF_TEST_P(FarnebackOpticalFlowFixture, FarnebackOpticalFlow, - ::testing::Combine( - ::testing::Values(make_tuple(5, 1.1), - make_tuple(7, 1.5)), - farneFlagType::all(), - ::testing::Bool())) -{ - Mat frame0 = imread(getDataPath("gpu/opticalflow/rubberwhale1.png"), cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame0.empty()) << "can't load rubberwhale1.png"; - - Mat frame1 = imread(getDataPath("gpu/opticalflow/rubberwhale2.png"), cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame1.empty()) << "can't load rubberwhale2.png"; - - const Size srcSize = frame0.size(); - - const FarnebackOpticalFlowParams params = GetParam(); - const tuple polyParams = get<0>(params); - const int polyN = get<0>(polyParams), flags = get<1>(params); - const double polySigma = get<1>(polyParams), pyrScale = 0.5; - const bool useInitFlow = get<2>(params); - const double eps = 1.5; - - Mat flowx(srcSize, CV_32FC1), flowy(srcSize, CV_32FC1), flow(srcSize, CV_32FC2); - declare.in(frame0, frame1).out(flowx, flowy); - - ocl::FarnebackOpticalFlow farn; - farn.pyrScale = pyrScale; - farn.polyN = polyN; - farn.polySigma = polySigma; - farn.flags = flags; - - if (RUN_PLAIN_IMPL) - { - if (useInitFlow) - { - calcOpticalFlowFarneback( - frame0, frame1, flow, farn.pyrScale, farn.numLevels, farn.winSize, - farn.numIters, farn.polyN, farn.polySigma, farn.flags); - farn.flags |= OPTFLOW_USE_INITIAL_FLOW; - } - - TEST_CYCLE() - calcOpticalFlowFarneback( - frame0, frame1, flow, farn.pyrScale, farn.numLevels, farn.winSize, - farn.numIters, farn.polyN, farn.polySigma, farn.flags); - - Mat flowxy[2] = { flowx, flowy }; - split(flow, flowxy); - - SANITY_CHECK(flowx, eps); - SANITY_CHECK(flowy, eps); - } - else if (RUN_OCL_IMPL) - { - ocl::oclMat oclFrame0(frame0), oclFrame1(frame1), - oclFlowx(srcSize, CV_32FC1), oclFlowy(srcSize, CV_32FC1); - - if (useInitFlow) - { - farn(oclFrame0, oclFrame1, oclFlowx, oclFlowy); - farn.flags |= OPTFLOW_USE_INITIAL_FLOW; - } - - OCL_TEST_CYCLE() - farn(oclFrame0, oclFrame1, oclFlowx, oclFlowy); - - oclFlowx.download(flowx); - oclFlowy.download(flowy); - - SANITY_CHECK(flowx, eps); - SANITY_CHECK(flowy, eps); - } - else - OCL_PERF_ELSE -} diff --git a/modules/ocl/perf/perf_orb.cpp b/modules/ocl/perf/perf_orb.cpp deleted file mode 100644 index 628a56090..000000000 --- a/modules/ocl/perf/perf_orb.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/*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. -// -// Authors: -// * Peter Andreas Entschev, peter@entschev.com -// -//M*/ - -#include "perf_precomp.hpp" - -using namespace perf; - -/////////////////// ORB /////////////////// - -typedef std::tr1::tuple Image_NFeatures_t; -typedef perf::TestBaseWithParam Image_NFeatures; - -PERF_TEST_P(Image_NFeatures, ORB, - testing::Combine(testing::Values("gpu/perf/aloe.png"), - testing::Values(4000))) -{ - declare.time(300.0); - - const Image_NFeatures_t params = GetParam(); - const std::string imgFile = std::tr1::get<0>(params); - const int nFeatures = std::tr1::get<1>(params); - - const cv::Mat img = imread(getDataPath(imgFile), cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(img.empty()); - - if (RUN_OCL_IMPL) - { - cv::ocl::ORB_OCL d_orb(nFeatures); - - const cv::ocl::oclMat d_img(img); - cv::ocl::oclMat d_keypoints, d_descriptors; - - TEST_CYCLE() d_orb(d_img, cv::ocl::oclMat(), d_keypoints, d_descriptors); - - std::vector ocl_keypoints; - d_orb.downloadKeyPoints(d_keypoints, ocl_keypoints); - - cv::Mat ocl_descriptors(d_descriptors); - - ocl_keypoints.resize(10); - ocl_descriptors = ocl_descriptors.rowRange(0, 10); - - sortKeyPoints(ocl_keypoints, ocl_descriptors); - - SANITY_CHECK_KEYPOINTS(ocl_keypoints, 1e-4); - SANITY_CHECK(ocl_descriptors); - } - else if (RUN_PLAIN_IMPL) - { - cv::ORB orb(nFeatures); - - std::vector cpu_keypoints; - cv::Mat cpu_descriptors; - - TEST_CYCLE() orb(img, cv::noArray(), cpu_keypoints, cpu_descriptors); - - SANITY_CHECK_KEYPOINTS(cpu_keypoints); - SANITY_CHECK(cpu_descriptors); - } - else - OCL_PERF_ELSE; -} diff --git a/modules/ocl/perf/perf_precomp.hpp b/modules/ocl/perf/perf_precomp.hpp deleted file mode 100644 index 366329c1a..000000000 --- a/modules/ocl/perf/perf_precomp.hpp +++ /dev/null @@ -1,198 +0,0 @@ -/*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. - -// 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*/ - -#ifdef __GNUC__ -# pragma GCC diagnostic ignored "-Wmissing-declarations" -# if defined __clang__ || defined __APPLE__ -# pragma GCC diagnostic ignored "-Wmissing-prototypes" -# pragma GCC diagnostic ignored "-Wextra" -# endif -#endif - -#ifndef __OPENCV_PERF_PRECOMP_HPP__ -#define __OPENCV_PERF_PRECOMP_HPP__ - -#ifdef __GNUC__ -# pragma GCC diagnostic ignored "-Wmissing-declarations" -# if defined __clang__ || defined __APPLE__ -# pragma GCC diagnostic ignored "-Wmissing-prototypes" -# pragma GCC diagnostic ignored "-Wextra" -# endif -#endif - -#define CV_BUILD_OCL_MODULE - -#include -#include -#include -#include -#include -#include -#include - -#include "cvconfig.h" -#include "opencv2/core.hpp" -#include "opencv2/core/utility.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" -#include "opencv2/calib3d.hpp" -#include "opencv2/video.hpp" -#include "opencv2/objdetect.hpp" -#include "opencv2/features2d.hpp" -#include "opencv2/ocl.hpp" -#include "opencv2/ts.hpp" - -using namespace std; -using namespace cv; - -#define OCL_SIZE_1000 Size(1000, 1000) -#define OCL_SIZE_2000 Size(2000, 2000) -#define OCL_SIZE_4000 Size(4000, 4000) - -#define OCL_TYPICAL_MAT_SIZES ::testing::Values(OCL_SIZE_1000, OCL_SIZE_2000, OCL_SIZE_4000) - -#define OCL_PERF_ENUM(type, ...) ::testing::Values(type, ## __VA_ARGS__ ) - -#define IMPL_OCL "ocl" -#define IMPL_GPU "gpu" -#define IMPL_PLAIN "plain" - -#define RUN_OCL_IMPL (IMPL_OCL == getSelectedImpl()) -#define RUN_PLAIN_IMPL (IMPL_PLAIN == getSelectedImpl()) - -#ifdef HAVE_OPENCV_GPU -# define RUN_GPU_IMPL (IMPL_GPU == getSelectedImpl()) -#endif - -#ifdef HAVE_OPENCV_GPU -#define OCL_PERF_ELSE \ - if (RUN_GPU_IMPL) \ - CV_TEST_FAIL_NO_IMPL(); \ - else \ - CV_TEST_FAIL_NO_IMPL(); -#else -#define OCL_PERF_ELSE \ - CV_TEST_FAIL_NO_IMPL(); -#endif - -#define OCL_TEST_CYCLE_N(n) for(declare.iterations(n); startTimer(), next(); cv::ocl::finish(), stopTimer()) -#define OCL_TEST_CYCLE() for(; startTimer(), next(); cv::ocl::finish(), stopTimer()) -#define OCL_TEST_CYCLE_MULTIRUN(runsNum) for(declare.runs(runsNum); startTimer(), next(); stopTimer()) for(int r = 0; r < runsNum; cv::ocl::finish(), ++r) - -// TODO: Move to the ts module -namespace cvtest { -namespace ocl { -inline void checkDeviceMaxMemoryAllocSize(const Size& size, int type, int factor = 1) -{ - assert(factor > 0); - if (!(IMPL_OCL == perf::TestBase::getSelectedImpl())) - return; // OpenCL devices are not used - int cn = CV_MAT_CN(type); - int cn_ocl = cn == 3 ? 4 : cn; - int type_ocl = CV_MAKE_TYPE(CV_MAT_DEPTH(type), cn_ocl); - size_t memSize = size.area() * CV_ELEM_SIZE(type_ocl); - const cv::ocl::DeviceInfo& devInfo = cv::ocl::Context::getContext()->getDeviceInfo(); - if (memSize * factor >= devInfo.maxMemAllocSize) - { - throw perf::TestBase::PerfSkipTestException(); - } -} - -struct KeypointIdxCompare -{ - std::vector* keypoints; - - explicit KeypointIdxCompare(std::vector* _keypoints) : keypoints(_keypoints) {} - - bool operator ()(size_t i1, size_t i2) const - { - cv::KeyPoint kp1 = (*keypoints)[i1]; - cv::KeyPoint kp2 = (*keypoints)[i2]; - if (kp1.pt.x != kp2.pt.x) - return kp1.pt.x < kp2.pt.x; - if (kp1.pt.y != kp2.pt.y) - return kp1.pt.y < kp2.pt.y; - if (kp1.response != kp2.response) - return kp1.response < kp2.response; - return kp1.octave < kp2.octave; - } -}; - -inline void sortKeyPoints(std::vector& keypoints, cv::InputOutputArray _descriptors = cv::noArray()) -{ - std::vector indexies(keypoints.size()); - for (size_t i = 0; i < indexies.size(); ++i) - indexies[i] = i; - - std::sort(indexies.begin(), indexies.end(), KeypointIdxCompare(&keypoints)); - - std::vector new_keypoints; - cv::Mat new_descriptors; - - new_keypoints.resize(keypoints.size()); - - cv::Mat descriptors; - if (_descriptors.needed()) - { - descriptors = _descriptors.getMat(); - new_descriptors.create(descriptors.size(), descriptors.type()); - } - - for (size_t i = 0; i < indexies.size(); ++i) - { - size_t new_idx = indexies[i]; - new_keypoints[i] = keypoints[new_idx]; - if (!new_descriptors.empty()) - descriptors.row((int) new_idx).copyTo(new_descriptors.row((int) i)); - } - - keypoints.swap(new_keypoints); - if (_descriptors.needed()) - new_descriptors.copyTo(_descriptors); -} - -} // namespace cvtest::ocl -} // namespace cvtest - -using namespace cvtest::ocl; - -#endif diff --git a/modules/ocl/perf/perf_pyramid.cpp b/modules/ocl/perf/perf_pyramid.cpp deleted file mode 100644 index 820dd6062..000000000 --- a/modules/ocl/perf/perf_pyramid.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/*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" - -using namespace perf; -using std::tr1::tuple; -using std::tr1::get; - -///////////// pyrDown ////////////////////// - -typedef Size_MatType pyrDownFixture; - -PERF_TEST_P(pyrDownFixture, pyrDown, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - Size dstSize((srcSize.height + 1) >> 1, (srcSize.width + 1) >> 1); - - checkDeviceMaxMemoryAllocSize(srcSize, type); - checkDeviceMaxMemoryAllocSize(dstSize, type); - - Mat src(srcSize, type), dst; - dst.create(dstSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(dstSize, type); - - OCL_TEST_CYCLE() ocl::pyrDown(oclSrc, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() pyrDown(src, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// pyrUp //////////////////////// - -typedef Size_MatType pyrUpFixture; - -PERF_TEST_P(pyrUpFixture, pyrUp, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8UC1, CV_8UC4))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int type = get<1>(params); - Size dstSize(srcSize.height << 1, srcSize.width << 1); - - checkDeviceMaxMemoryAllocSize(srcSize, type); - checkDeviceMaxMemoryAllocSize(dstSize, type); - - Mat src(srcSize, type), dst; - dst.create(dstSize, type); - declare.in(src, WARMUP_RNG).out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src), oclDst(dstSize, type); - - OCL_TEST_CYCLE() ocl::pyrDown(oclSrc, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() pyrDown(src, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} diff --git a/modules/ocl/perf/perf_split_merge.cpp b/modules/ocl/perf/perf_split_merge.cpp deleted file mode 100644 index ecfc49e33..000000000 --- a/modules/ocl/perf/perf_split_merge.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/*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" - -using namespace perf; -using std::tr1::tuple; -using std::tr1::get; - -///////////// Merge//////////////////////// - -typedef Size_MatType MergeFixture; - -PERF_TEST_P(MergeFixture, Merge, - ::testing::Combine(::testing::Values(OCL_SIZE_1000, OCL_SIZE_2000), - OCL_PERF_ENUM(CV_8U, CV_32F))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int depth = get<1>(params), channels = 3; - const int dstType = CV_MAKE_TYPE(depth, channels); - - checkDeviceMaxMemoryAllocSize(srcSize, dstType); - - Mat dst(srcSize, dstType); - vector src(channels); - for (vector::iterator i = src.begin(), end = src.end(); i != end; ++i) - { - i->create(srcSize, CV_MAKE_TYPE(depth, 1)); - declare.in(*i, WARMUP_RNG); - } - declare.out(dst); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclDst(srcSize, dstType); - vector oclSrc(src.size()); - for (vector::size_type i = 0, end = src.size(); i < end; ++i) - oclSrc[i] = src[i]; - - OCL_TEST_CYCLE() cv::ocl::merge(oclSrc, oclDst); - - oclDst.download(dst); - - SANITY_CHECK(dst); - } - else if (RUN_PLAIN_IMPL) - { - TEST_CYCLE() cv::merge(src, dst); - - SANITY_CHECK(dst); - } - else - OCL_PERF_ELSE -} - -///////////// Split//////////////////////// - -typedef Size_MatType SplitFixture; - -PERF_TEST_P(SplitFixture, Split, - ::testing::Combine(OCL_TYPICAL_MAT_SIZES, - OCL_PERF_ENUM(CV_8U, CV_32F))) -{ - const Size_MatType_t params = GetParam(); - const Size srcSize = get<0>(params); - const int depth = get<1>(params), channels = 3; - const int type = CV_MAKE_TYPE(depth, channels); - - checkDeviceMaxMemoryAllocSize(srcSize, type); - - Mat src(srcSize, type); - declare.in(src, WARMUP_RNG); - - if (RUN_OCL_IMPL) - { - ocl::oclMat oclSrc(src); - vector oclDst(channels, ocl::oclMat(srcSize, CV_MAKE_TYPE(depth, 1))); - - OCL_TEST_CYCLE() cv::ocl::split(oclSrc, oclDst); - - ASSERT_EQ(3, channels); - Mat dst0, dst1, dst2; - oclDst[0].download(dst0); - oclDst[1].download(dst1); - oclDst[2].download(dst2); - SANITY_CHECK(dst0); - SANITY_CHECK(dst1); - SANITY_CHECK(dst2); - } - else if (RUN_PLAIN_IMPL) - { - vector dst(channels, Mat(srcSize, CV_MAKE_TYPE(depth, 1))); - TEST_CYCLE() cv::split(src, dst); - - ASSERT_EQ(3, channels); - Mat & dst0 = dst[0], & dst1 = dst[1], & dst2 = dst[2]; - SANITY_CHECK(dst0); - SANITY_CHECK(dst1); - SANITY_CHECK(dst2); - } - else - OCL_PERF_ELSE -} diff --git a/modules/ocl/src/arithm.cpp b/modules/ocl/src/arithm.cpp deleted file mode 100644 index d008e8b40..000000000 --- a/modules/ocl/src/arithm.cpp +++ /dev/null @@ -1,1804 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Jia Haipeng, jiahaipeng95@gmail.com -// Shengen Yan, yanshengen@gmail.com -// Jiang Liyuan, jlyuan001.good@163.com -// Rock Li, Rock.Li@amd.com -// Zailong Wu, bullet@yeah.net -// Peng Xiao, pengxiao@outlook.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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -static std::vector scalarToVector(const cv::Scalar & sc, int depth, int ocn, int cn) -{ - CV_Assert(ocn == cn || (ocn == 4 && cn == 3)); - - static const int sizeMap[] = { sizeof(uchar), sizeof(char), sizeof(ushort), - sizeof(short), sizeof(int), sizeof(float), sizeof(double) }; - - int elemSize1 = sizeMap[depth]; - int bufSize = elemSize1 * ocn; - std::vector _buf(bufSize); - uchar * buf = &_buf[0]; - scalarToRawData(sc, buf, CV_MAKE_TYPE(depth, cn)); - memset(buf + elemSize1 * cn, 0, (ocn - cn) * elemSize1); - - return _buf; -} - -////////////////////////////////////////////////////////////////////////////// -/////////////// add subtract multiply divide min max ///////////////////////// -////////////////////////////////////////////////////////////////////////////// - -enum { ADD = 0, SUB, MUL, DIV, ABS, ABS_DIFF, MIN, MAX }; - -static void arithmetic_run_generic(const oclMat &src1, const oclMat &src2, const Scalar & scalar, const oclMat & mask, - oclMat &dst, int op_type, bool use_scalar = false) -{ - Context *clCxt = src1.clCxt; - bool hasDouble = clCxt->supportsFeature(FEATURE_CL_DOUBLE); - if (!hasDouble && (src1.depth() == CV_64F || src2.depth() == CV_64F || dst.depth() == CV_64F)) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_Assert(src2.empty() || (!src2.empty() && src1.type() == src2.type() && src1.size() == src2.size())); - CV_Assert(mask.empty() || (!mask.empty() && mask.type() == CV_8UC1 && mask.size() == src1.size())); - CV_Assert(op_type >= ADD && op_type <= MAX); - - dst.create(src1.size(), src1.type()); - - int oclChannels = src1.oclchannels(), depth = src1.depth(); - int src1step1 = src1.step / src1.elemSize(), src1offset1 = src1.offset / src1.elemSize(); - int src2step1 = src2.step / src2.elemSize(), src2offset1 = src2.offset / src2.elemSize(); - int maskstep1 = mask.step, maskoffset1 = mask.offset / mask.elemSize(); - int dststep1 = dst.step / dst.elemSize(), dstoffset1 = dst.offset / dst.elemSize(); - std::vector m; - -#ifdef ANDROID - size_t localThreads[3] = { 16, 10, 1 }; -#else - size_t localThreads[3] = { 16, 16, 1 }; -#endif - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - - std::string kernelName = "arithm_binary_op"; - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char * const WTypeMap[] = { "short", "short", "int", "int", "int", "float", "double" }; - const char * const funcMap[] = { "FUNC_ADD", "FUNC_SUB", "FUNC_MUL", "FUNC_DIV", "FUNC_ABS", "FUNC_ABS_DIFF", "FUNC_MIN", "FUNC_MAX" }; - const char * const channelMap[] = { "", "", "2", "4", "4" }; - bool haveScalar = use_scalar || src2.empty(); - - int WDepth = depth; - if (haveScalar) - WDepth = hasDouble && WDepth == CV_64F ? CV_64F : CV_32F; - if (op_type == DIV) - WDepth = hasDouble ? CV_64F : CV_32F; - else if (op_type == MUL) - WDepth = hasDouble && (depth == CV_32S || depth == CV_64F) ? CV_64F : CV_32F; - - std::string buildOptions = format("-D T=%s%s -D WT=%s%s -D convertToT=convert_%s%s%s -D %s " - "-D convertToWT=convert_%s%s", - typeMap[depth], channelMap[oclChannels], - WTypeMap[WDepth], channelMap[oclChannels], - typeMap[depth], channelMap[oclChannels], (depth >= CV_32F ? "" : (depth == CV_32S ? "_rte" : "_sat_rte")), - funcMap[op_type], WTypeMap[WDepth], channelMap[oclChannels]); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src1.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1step1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1offset1 )); - - if (!src2.empty()) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src2.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2step1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2offset1 )); - - kernelName += "_mat"; - - if (haveScalar) - buildOptions += " -D HAVE_SCALAR"; - } - - if (haveScalar) - { - const int WDepthMap[] = { CV_16S, CV_16S, CV_32S, CV_32S, CV_32S, CV_32F, CV_64F }; - m = scalarToVector(scalar, WDepthMap[WDepth], oclChannels, src1.channels()); - - args.push_back( std::make_pair( m.size(), (void *)&m[0])); - - kernelName += "_scalar"; - } - - if (!mask.empty()) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&maskstep1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&maskoffset1 )); - - kernelName += "_mask"; - } - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dststep1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstoffset1 )); - - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.rows )); - - openCLExecuteKernel(clCxt, mask.empty() ? - (!src2.empty() ? &arithm_add : &arithm_add_scalar) : - (!src2.empty() ? &arithm_add_mask : &arithm_add_scalar_mask), - kernelName, globalThreads, localThreads, - args, -1, -1, buildOptions.c_str()); -} - -void cv::ocl::add(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask) -{ - arithmetic_run_generic(src1, src2, Scalar(), mask, dst, ADD); -} - -void cv::ocl::add(const oclMat &src1, const Scalar &src2, oclMat &dst, const oclMat &mask) -{ - arithmetic_run_generic(src1, oclMat(), src2, mask, dst, ADD); -} - -void cv::ocl::subtract(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask) -{ - arithmetic_run_generic(src1, src2, Scalar(), mask, dst, SUB); -} - -void cv::ocl::subtract(const oclMat &src1, const Scalar &src2, oclMat &dst, const oclMat &mask) -{ - arithmetic_run_generic(src1, oclMat(), src2, mask, dst, SUB); -} - -void cv::ocl::multiply(const oclMat &src1, const oclMat &src2, oclMat &dst, double scalar) -{ - const bool use_scalar = !(std::abs(scalar - 1.0) < std::numeric_limits::epsilon()); - arithmetic_run_generic(src1, src2, Scalar::all(scalar), oclMat(), dst, MUL, use_scalar); -} - -void cv::ocl::multiply(double scalar, const oclMat &src, oclMat &dst) -{ - arithmetic_run_generic(src, oclMat(), Scalar::all(scalar), oclMat(), dst, MUL); -} - -void cv::ocl::divide(const oclMat &src1, const oclMat &src2, oclMat &dst, double scalar) -{ - const bool use_scalar = !(std::abs(scalar - 1.0) < std::numeric_limits::epsilon()); - arithmetic_run_generic(src1, src2, Scalar::all(scalar), oclMat(), dst, DIV, use_scalar); -} - -void cv::ocl::divide(double scalar, const oclMat &src, oclMat &dst) -{ - arithmetic_run_generic(src, oclMat(), Scalar::all(scalar), oclMat(), dst, DIV); -} - -void cv::ocl::min(const oclMat &src1, const oclMat &src2, oclMat &dst) -{ - arithmetic_run_generic(src1, src2, Scalar::all(0), oclMat(), dst, MIN); -} - -void cv::ocl::max(const oclMat &src1, const oclMat &src2, oclMat &dst) -{ - arithmetic_run_generic(src1, src2, Scalar::all(0), oclMat(), dst, MAX); -} - -////////////////////////////////////////////////////////////////////////////// -/////////////////////////////Abs, Absdiff //////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -void cv::ocl::abs(const oclMat &src, oclMat &dst) -{ - // explicitly uses use_scalar (even if zero) so that the correct kernel is used - arithmetic_run_generic(src, oclMat(), Scalar(), oclMat(), dst, ABS, true); -} - -void cv::ocl::absdiff(const oclMat &src1, const oclMat &src2, oclMat &dst) -{ - arithmetic_run_generic(src1, src2, Scalar(), oclMat(), dst, ABS_DIFF); -} - -void cv::ocl::absdiff(const oclMat &src1, const Scalar &src2, oclMat &dst) -{ - arithmetic_run_generic(src1, oclMat(), src2, oclMat(), dst, ABS_DIFF); -} - -////////////////////////////////////////////////////////////////////////////// -///////////////////////////////// compare /////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -static void compare_run(const oclMat &src1, const oclMat &src2, oclMat &dst, int cmpOp, - String kernelName, const cv::ocl::ProgramEntry* source) -{ - dst.create(src1.size(), CV_8UC1); - - int depth = src1.depth(); - size_t localThreads[3] = { 64, 4, 1 }; - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - - int src1step1 = src1.step1(), src1offset1 = src1.offset / src1.elemSize1(); - int src2step1 = src2.step1(), src2offset1 = src2.offset / src2.elemSize1(); - int dststep1 = dst.step1(), dstoffset1 = dst.offset / dst.elemSize1(); - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char * operationMap[] = { "==", ">", ">=", "<", "<=", "!=" }; - std::string buildOptions = format("-D T=%s -D Operation=%s", typeMap[depth], operationMap[cmpOp]); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src1.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1step1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1offset1 )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src2.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2step1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2offset1 )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dststep1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstoffset1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.rows )); - - openCLExecuteKernel(src1.clCxt, source, kernelName, globalThreads, localThreads, - args, -1, -1, buildOptions.c_str()); -} - -void cv::ocl::compare(const oclMat &src1, const oclMat &src2, oclMat &dst , int cmpOp) -{ - if (!src1.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src1.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_Assert(src1.type() == src2.type() && src1.channels() == 1); - CV_Assert(cmpOp >= CMP_EQ && cmpOp <= CMP_NE); - - compare_run(src1, src2, dst, cmpOp, "arithm_compare", &arithm_compare); -} - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////// sum ////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -enum { SUM = 0, ABS_SUM, SQR_SUM }; - -static void arithmetic_sum_buffer_run(const oclMat &src, cl_mem &dst, int groupnum, int type, int ddepth) -{ - int ochannels = src.oclchannels(); - int all_cols = src.step / src.elemSize(); - int pre_cols = (src.offset % src.step) / src.elemSize(); - int sec_cols = all_cols - (src.offset % src.step + src.cols * src.elemSize() - 1) / src.elemSize() - 1; - int invalid_cols = pre_cols + sec_cols; - int cols = all_cols - invalid_cols , elemnum = cols * src.rows;; - int offset = src.offset / src.elemSize(); - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char * const funcMap[] = { "FUNC_SUM", "FUNC_ABS_SUM", "FUNC_SQR_SUM" }; - const char * const channelMap[] = { " ", " ", "2", "4", "4" }; - String buildOptions = format("-D srcT=%s%s -D dstT=%s%s -D convertToDstT=convert_%s%s -D %s", - typeMap[src.depth()], channelMap[ochannels], - typeMap[ddepth], channelMap[ochannels], - typeMap[ddepth], channelMap[ochannels], - funcMap[type]); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&invalid_cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&offset)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&elemnum)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&groupnum)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst )); - size_t globalThreads[3] = { groupnum * 256, 1, 1 }; - -#ifdef ANDROID - openCLExecuteKernel(src.clCxt, &arithm_sum, "arithm_op_sum", globalThreads, NULL, - args, -1, -1, buildOptions.c_str()); -#else - size_t localThreads[3] = { 256, 1, 1 }; - openCLExecuteKernel(src.clCxt, &arithm_sum, "arithm_op_sum", globalThreads, localThreads, - args, -1, -1, buildOptions.c_str()); -#endif -} - -template -Scalar arithmetic_sum(const oclMat &src, int type, int ddepth) -{ - CV_Assert(src.step % src.elemSize() == 0); - - size_t groupnum = src.clCxt->getDeviceInfo().maxComputeUnits; - CV_Assert(groupnum != 0); - - int dbsize = groupnum * src.oclchannels(); - Context *clCxt = src.clCxt; - - AutoBuffer _buf(dbsize); - T *p = (T*)_buf; - memset(p, 0, dbsize * sizeof(T)); - - cl_mem dstBuffer = openCLCreateBuffer(clCxt, CL_MEM_WRITE_ONLY, dbsize * sizeof(T)); - arithmetic_sum_buffer_run(src, dstBuffer, groupnum, type, ddepth); - openCLReadBuffer(clCxt, dstBuffer, (void *)p, dbsize * sizeof(T)); - openCLFree(dstBuffer); - - Scalar s = Scalar::all(0.0); - for (int i = 0; i < dbsize;) - for (int j = 0; j < src.oclchannels(); j++, i++) - s.val[j] += p[i]; - - return s; -} - -typedef Scalar (*sumFunc)(const oclMat &src, int type, int ddepth); - -Scalar cv::ocl::sum(const oclMat &src) -{ - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return Scalar::all(0); - } - static sumFunc functab[3] = - { - arithmetic_sum, - arithmetic_sum, - arithmetic_sum - }; - - int ddepth = std::max(src.depth(), CV_32S); - sumFunc func = functab[ddepth - CV_32S]; - return func(src, SUM, ddepth); -} - -Scalar cv::ocl::absSum(const oclMat &src) -{ - int sdepth = src.depth(); - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && sdepth == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return cv::Scalar::all(0); - } - - if (sdepth == CV_8U || sdepth == CV_16U) - return sum(src); - - static sumFunc functab[3] = - { - arithmetic_sum, - arithmetic_sum, - arithmetic_sum - }; - - int ddepth = std::max(sdepth, CV_32S); - sumFunc func = functab[ddepth - CV_32S]; - return func(src, ABS_SUM, ddepth); -} - -Scalar cv::ocl::sqrSum(const oclMat &src) -{ - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return cv::Scalar::all(0); - } - static sumFunc functab[3] = - { - arithmetic_sum, - arithmetic_sum, - arithmetic_sum - }; - - int ddepth = std::max(src.depth(), CV_32S); - sumFunc func = functab[ddepth - CV_32S]; - return func(src, SQR_SUM, ddepth); -} - -////////////////////////////////////////////////////////////////////////////// -//////////////////////////////// meanStdDev ////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -void cv::ocl::meanStdDev(const oclMat &src, Scalar &mean, Scalar &stddev) -{ - if (src.depth() == CV_64F && !src.clCxt->supportsFeature(FEATURE_CL_DOUBLE)) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - double total = 1.0 / src.size().area(); - - mean = sum(src); - stddev = sqrSum(src); - - for (int i = 0; i < 4; ++i) - { - mean[i] *= total; - stddev[i] = std::sqrt(std::max(stddev[i] * total - mean.val[i] * mean.val[i] , 0.)); - } -} - -////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// minMax ///////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -template -static void arithmetic_minMax_run(const oclMat &src, const oclMat & mask, cl_mem &dst, int groupnum, String kernelName) -{ - int all_cols = src.step / src.elemSize(); - int pre_cols = (src.offset % src.step) / src.elemSize(); - int sec_cols = all_cols - (src.offset % src.step + src.cols * src.elemSize() - 1) / src.elemSize() - 1; - int invalid_cols = pre_cols + sec_cols; - int cols = all_cols - invalid_cols , elemnum = cols * src.rows; - int offset = src.offset / src.elemSize(); - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char * const channelMap[] = { " ", " ", "2", "4", "4" }; - - std::ostringstream stream; - stream << "-D T=" << typeMap[src.depth()] << channelMap[src.channels()]; - if (std::numeric_limits::is_integer) - { - stream << " -D MAX_VAL=" << (WT)std::numeric_limits::max(); - stream << " -D MIN_VAL=" << (WT)std::numeric_limits::min(); - } - else - stream << " -D DEPTH_" << src.depth(); - std::string buildOptions = stream.str(); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&invalid_cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&offset)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&elemnum)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&groupnum)); - - int minvalid_cols = 0, moffset = 0; - if (!mask.empty()) - { - int mall_cols = mask.step / mask.elemSize(); - int mpre_cols = (mask.offset % mask.step) / mask.elemSize(); - int msec_cols = mall_cols - (mask.offset % mask.step + mask.cols * mask.elemSize() - 1) / mask.elemSize() - 1; - minvalid_cols = mpre_cols + msec_cols; - moffset = mask.offset / mask.elemSize(); - - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&minvalid_cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&moffset )); - - kernelName += "_mask"; - } - - size_t globalThreads[3] = {groupnum * 256, 1, 1}; - size_t localThreads[3] = {256, 1, 1}; - - // kernel use fixed grid size, replace lt on NULL is imposible without kernel changes - openCLExecuteKernel(src.clCxt, &arithm_minMax, kernelName, globalThreads, localThreads, - args, -1, -1, buildOptions.c_str()); -} - -template -void arithmetic_minMax(const oclMat &src, double *minVal, double *maxVal, const oclMat &mask) -{ - size_t groupnum = src.clCxt->getDeviceInfo().maxComputeUnits; - CV_Assert(groupnum != 0); - - int dbsize = groupnum * 2 * src.elemSize(); - oclMat buf; - ensureSizeIsEnough(1, dbsize, CV_8UC1, buf); - - cl_mem buf_data = reinterpret_cast(buf.data); - arithmetic_minMax_run(src, mask, buf_data, groupnum, "arithm_op_minMax"); - - Mat matbuf = Mat(buf); - T *p = matbuf.ptr(); - if (minVal != NULL) - { - *minVal = std::numeric_limits::max(); - for (int i = 0, end = src.oclchannels() * (int)groupnum; i < end; i++) - *minVal = *minVal < p[i] ? *minVal : p[i]; - } - if (maxVal != NULL) - { - *maxVal = -std::numeric_limits::max(); - for (int i = src.oclchannels() * (int)groupnum, end = i << 1; i < end; i++) - *maxVal = *maxVal > p[i] ? *maxVal : p[i]; - } -} - -typedef void (*minMaxFunc)(const oclMat &src, double *minVal, double *maxVal, const oclMat &mask); - -void cv::ocl::minMax(const oclMat &src, double *minVal, double *maxVal, const oclMat &mask) -{ - CV_Assert(src.channels() == 1); - CV_Assert(src.size() == mask.size() || mask.empty()); - CV_Assert(src.step % src.elemSize() == 0); - - if (minVal == NULL && maxVal == NULL) - return; - - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - static minMaxFunc functab[] = - { - arithmetic_minMax, - arithmetic_minMax, - arithmetic_minMax, - arithmetic_minMax, - arithmetic_minMax, - arithmetic_minMax, - arithmetic_minMax, - 0 - }; - - minMaxFunc func = functab[src.depth()]; - CV_Assert(func != 0); - - func(src, minVal, maxVal, mask); -} - -////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////// norm ///////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -double cv::ocl::norm(const oclMat &src1, int normType) -{ - CV_Assert((normType & NORM_RELATIVE) == 0); - return norm(src1, oclMat(), normType); -} - -static void arithm_absdiff_nonsaturate_run(const oclMat & src1, const oclMat & src2, oclMat & diff, int ntype) -{ - Context *clCxt = src1.clCxt; - if (!clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src1.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - CV_Assert(src1.step % src1.elemSize() == 0 && (src2.empty() || src2.step % src2.elemSize() == 0)); - - if (src2.empty() && (src1.depth() == CV_8U || src1.depth() == CV_16U)) - { - src1.convertTo(diff, CV_32S); - return; - } - - int ddepth = std::max(src1.depth(), CV_32S); - if (ntype == NORM_L2) - ddepth = std::max(CV_32F, ddepth); - - diff.create(src1.size(), CV_MAKE_TYPE(ddepth, src1.channels())); - CV_Assert(diff.step % diff.elemSize() == 0); - - int oclChannels = src1.oclchannels(), sdepth = src1.depth(); - int src1step1 = src1.step / src1.elemSize(), src1offset1 = src1.offset / src1.elemSize(); - int src2step1 = src2.step / src2.elemSize(), src2offset1 = src2.offset / src2.elemSize(); - int diffstep1 = diff.step / diff.elemSize(), diffoffset1 = diff.offset / diff.elemSize(); - - String kernelName = "arithm_absdiff_nonsaturate"; -#ifdef ANDROID - size_t localThreads[3] = { 16, 10, 1 }; -#else - size_t localThreads[3] = { 16, 16, 1 }; -#endif - size_t globalThreads[3] = { diff.cols, diff.rows, 1 }; - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char * const channelMap[] = { "", "", "2", "4", "4" }; - - std::string buildOptions = format("-D srcT=%s%s -D dstT=%s%s -D convertToDstT=convert_%s%s", - typeMap[sdepth], channelMap[oclChannels], - typeMap[ddepth], channelMap[oclChannels], - typeMap[ddepth], channelMap[oclChannels]); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src1.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1step1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1offset1 )); - - if (!src2.empty()) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src2.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2step1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2offset1 )); - - kernelName += "_binary"; - buildOptions += " -D BINARY"; - } - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&diff.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&diffstep1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&diffoffset1 )); - - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.rows )); - - openCLExecuteKernel(clCxt, &arithm_absdiff_nonsaturate, - kernelName, globalThreads, localThreads, - args, -1, -1, buildOptions.c_str()); -} - -double cv::ocl::norm(const oclMat &src1, const oclMat &src2, int normType) -{ - if (!src1.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src1.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return -1; - } - CV_Assert(src2.empty() || (src1.type() == src2.type() && src1.size() == src2.size())); - - bool isRelative = (normType & NORM_RELATIVE) != 0; - normType &= NORM_TYPE_MASK; - CV_Assert(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2); - - Scalar s; - int cn = src1.channels(); - double r = 0; - oclMat diff; - - arithm_absdiff_nonsaturate_run(src1, src2, diff, normType); - - switch (normType) - { - case NORM_INF: - diff = diff.reshape(1); - minMax(diff, NULL, &r); - break; - case NORM_L1: - s = sum(diff); - for (int i = 0; i < cn; ++i) - r += s[i]; - break; - case NORM_L2: - s = sqrSum(diff); - for (int i = 0; i < cn; ++i) - r += s[i]; - r = std::sqrt(r); - break; - } - if (isRelative) - r = r / (norm(src2, normType) + DBL_EPSILON); - - return r; -} - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////// flip ////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -enum { FLIP_COLS = 1 << 0, FLIP_ROWS = 1 << 1, FLIP_BOTH = FLIP_ROWS | FLIP_COLS }; - -static void arithmetic_flip_run(const oclMat &src, oclMat &dst, String kernelName, int flipType) -{ - int cols = dst.cols, rows = dst.rows; - if ((cols == 1 && flipType == FLIP_COLS) || - (rows == 1 && flipType == FLIP_ROWS) || - (rows == 1 && cols == 1 && flipType == FLIP_BOTH)) - { - src.copyTo(dst); - return; - } - - cols = flipType == FLIP_COLS ? divUp(cols, 2) : cols; - rows = flipType & FLIP_ROWS ? divUp(rows, 2) : rows; - - const char * const channelMap[] = { "", "", "2", "4", "4" }; - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - std::string buildOptions = format("-D T=%s%s", typeMap[dst.depth()], channelMap[dst.oclchannels()]); - - size_t localThreads[3] = { 64, 4, 1 }; - size_t globalThreads[3] = { cols, rows, 1 }; - - int elemSize = src.elemSize(); - int src_step = src.step / elemSize, src_offset = src.offset / elemSize; - int dst_step = dst.step / elemSize, dst_offset = dst.offset / elemSize; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_offset )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols )); - - openCLExecuteKernel(src.clCxt, &arithm_flip, kernelName, globalThreads, localThreads, args, - -1, -1, buildOptions.c_str()); -} - -void cv::ocl::flip(const oclMat &src, oclMat &dst, int flipCode) -{ - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - dst.create(src.size(), src.type()); - - if (flipCode == 0) - arithmetic_flip_run(src, dst, "arithm_flip_rows", FLIP_ROWS); - else if (flipCode > 0) - arithmetic_flip_run(src, dst, "arithm_flip_cols", FLIP_COLS); - else - arithmetic_flip_run(src, dst, "arithm_flip_rows_cols", FLIP_BOTH); -} - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////// LUT ////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -static void arithmetic_lut_run(const oclMat &src, const oclMat &lut, oclMat &dst, String kernelName) -{ - int sdepth = src.depth(); - int src_step1 = src.step1(), dst_step1 = dst.step1(); - int src_offset1 = src.offset / src.elemSize1(), dst_offset1 = dst.offset / dst.elemSize1(); - int lut_offset1 = lut.offset / lut.elemSize1() + (sdepth == CV_8U ? 0 : 128) * lut.channels(); - int cols1 = src.cols * src.oclchannels(); - - size_t localSize[] = { 16, 16, 1 }; - size_t globalSize[] = { lut.channels() == 1 ? cols1 : src.cols, src.rows, 1 }; - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - std::string buildOptions = format("-D srcT=%s -D dstT=%s", typeMap[sdepth], typeMap[dst.depth()]); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&lut.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols1)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_offset1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&lut_offset1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_offset1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_step1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_step1 )); - - openCLExecuteKernel(src.clCxt, &arithm_LUT, kernelName, globalSize, localSize, - args, lut.oclchannels(), -1, buildOptions.c_str()); -} - -void cv::ocl::LUT(const oclMat &src, const oclMat &lut, oclMat &dst) -{ - if (!lut.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && lut.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - int cn = src.channels(), depth = src.depth(); - - CV_Assert(depth == CV_8U || depth == CV_8S); - CV_Assert(lut.channels() == 1 || lut.channels() == src.channels()); - CV_Assert(lut.rows == 1 && lut.cols == 256); - - dst.create(src.size(), CV_MAKETYPE(lut.depth(), cn)); - arithmetic_lut_run(src, lut, dst, "LUT"); -} - -////////////////////////////////////////////////////////////////////////////// -//////////////////////////////// exp log ///////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -static void arithmetic_exp_log_sqrt_run(const oclMat &src, oclMat &dst, String kernelName, const cv::ocl::ProgramEntry* source) -{ - Context *clCxt = src.clCxt; - if (!clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_Assert( src.depth() == CV_32F || src.depth() == CV_64F); - dst.create(src.size(), src.type()); - - int ddepth = dst.depth(); - int cols1 = src.cols * src.oclchannels(); - int srcoffset1 = src.offset / src.elemSize1(), dstoffset1 = dst.offset / dst.elemSize1(); - int srcstep1 = src.step1(), dststep1 = dst.step1(); - -#ifdef ANDROID - size_t localThreads[3] = { 64, 2, 1 }; -#else - size_t localThreads[3] = { 64, 4, 1 }; -#endif - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - - std::string buildOptions = format("-D srcT=%s", - ddepth == CV_32F ? "float" : "double"); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcoffset1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstoffset1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcstep1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dststep1 )); - - openCLExecuteKernel(clCxt, source, kernelName, globalThreads, localThreads, - args, src.oclchannels(), -1, buildOptions.c_str()); -} - -void cv::ocl::exp(const oclMat &src, oclMat &dst) -{ - arithmetic_exp_log_sqrt_run(src, dst, "arithm_exp", &arithm_exp); -} - -void cv::ocl::log(const oclMat &src, oclMat &dst) -{ - arithmetic_exp_log_sqrt_run(src, dst, "arithm_log", &arithm_log); -} - -void cv::ocl::sqrt(const oclMat &src, oclMat &dst) -{ - arithmetic_exp_log_sqrt_run(src, dst, "arithm_sqrt", &arithm_sqrt); -} - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////// magnitude phase /////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -static void arithmetic_magnitude_phase_run(const oclMat &src1, const oclMat &src2, oclMat &dst, String kernelName) -{ - int depth = dst.depth(); - -#ifdef ANDROID - size_t localThreads[3] = { 64, 2, 1 }; -#else - size_t localThreads[3] = { 64, 4, 1 }; -#endif - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - - int src1_step = src1.step / src1.elemSize(), src1_offset = src1.offset / src1.elemSize(); - int src2_step = src2.step / src2.elemSize(), src2_offset = src2.offset / src2.elemSize(); - int dst_step = dst.step / dst.elemSize(), dst_offset = dst.offset / dst.elemSize(); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src1.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1_offset )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src2.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2_offset )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.cols )); - - const char * const channelMap[] = { "", "", "2", "4", "4" }; - std::string buildOptions = format("-D T=%s%s", depth == CV_32F ? "float" : "double", channelMap[dst.channels()]); - - openCLExecuteKernel(src1.clCxt, &arithm_magnitude, kernelName, globalThreads, localThreads, args, -1, -1, buildOptions.c_str()); -} - -void cv::ocl::magnitude(const oclMat &src1, const oclMat &src2, oclMat &dst) -{ - if (!src1.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src1.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_Assert(src1.type() == src2.type() && src1.size() == src2.size() && - (src1.depth() == CV_32F || src1.depth() == CV_64F)); - - dst.create(src1.size(), src1.type()); - arithmetic_magnitude_phase_run(src1, src2, dst, "arithm_magnitude"); -} - -static void arithmetic_phase_run(const oclMat &src1, const oclMat &src2, oclMat &dst, String kernelName, const cv::ocl::ProgramEntry* source) -{ - int depth = dst.depth(), cols1 = src1.cols * src1.oclchannels(); - int src1step1 = src1.step / src1.elemSize1(), src1offset1 = src1.offset / src1.elemSize1(); - int src2step1 = src2.step / src2.elemSize1(), src2offset1 = src2.offset / src2.elemSize1(); - int dststep1 = dst.step / dst.elemSize1(), dstoffset1 = dst.offset / dst.elemSize1(); - -#ifdef ANDROID - size_t localThreads[3] = { 64, 2, 1 }; -#else - size_t localThreads[3] = { 64, 4, 1 }; -#endif - size_t globalThreads[3] = { cols1, dst.rows, 1 }; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src1.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1step1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1offset1 )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src2.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2step1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2offset1 )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dststep1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstoffset1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.rows )); - - openCLExecuteKernel(src1.clCxt, source, kernelName, globalThreads, localThreads, args, -1, depth); -} - -void cv::ocl::phase(const oclMat &x, const oclMat &y, oclMat &Angle, bool angleInDegrees) -{ - if (!x.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && x.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_Assert(x.type() == y.type() && x.size() == y.size() && (x.depth() == CV_32F || x.depth() == CV_64F)); - CV_Assert(x.step % x.elemSize() == 0 && y.step % y.elemSize() == 0); - - Angle.create(x.size(), x.type()); - arithmetic_phase_run(x, y, Angle, angleInDegrees ? "arithm_phase_indegrees" : "arithm_phase_inradians", &arithm_phase); -} - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////// cartToPolar /////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -static void arithmetic_cartToPolar_run(const oclMat &src1, const oclMat &src2, oclMat &dst_mag, oclMat &dst_cart, - String kernelName, bool angleInDegrees) -{ - int channels = src1.oclchannels(); - int depth = src1.depth(); - - int cols = src1.cols * channels; - -#ifdef ANDROID - size_t localThreads[3] = { 64, 2, 1 }; -#else - size_t localThreads[3] = { 64, 4, 1 }; -#endif - size_t globalThreads[3] = { cols, src1.rows, 1 }; - - int src1_step = src1.step / src1.elemSize1(), src1_offset = src1.offset / src1.elemSize1(); - int src2_step = src2.step / src2.elemSize1(), src2_offset = src2.offset / src2.elemSize1(); - int dst_mag_step = dst_mag.step / dst_mag.elemSize1(), dst_mag_offset = dst_mag.offset / dst_mag.elemSize1(); - int dst_cart_step = dst_cart.step / dst_cart.elemSize1(), dst_cart_offset = dst_cart.offset / dst_cart.elemSize1(); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src1.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1_offset )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src2.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2_offset )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst_mag.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_mag_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_mag_offset )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst_cart.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_cart_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_cart_offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols )); - - openCLExecuteKernel(src1.clCxt, &arithm_cartToPolar, kernelName, globalThreads, localThreads, args, - -1, depth, angleInDegrees ? "-D DEGREE" : "-D RADIAN"); -} - -void cv::ocl::cartToPolar(const oclMat &x, const oclMat &y, oclMat &mag, oclMat &angle, bool angleInDegrees) -{ - if (!x.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && x.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_Assert(x.type() == y.type() && x.size() == y.size() && (x.depth() == CV_32F || x.depth() == CV_64F)); - - mag.create(x.size(), x.type()); - angle.create(x.size(), x.type()); - - arithmetic_cartToPolar_run(x, y, mag, angle, "arithm_cartToPolar", angleInDegrees); -} - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////// polarToCart /////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -static void arithmetic_ptc_run(const oclMat &src1, const oclMat &src2, oclMat &dst1, oclMat &dst2, bool angleInDegrees, - String kernelName) -{ - int channels = src2.oclchannels(), depth = src2.depth(); - int cols = src2.cols * channels, rows = src2.rows; - -#ifdef ANDROID - size_t localThreads[3] = { 64, 2, 1 }; -#else - size_t localThreads[3] = { 64, 4, 1 }; -#endif - size_t globalThreads[3] = { cols, rows, 1 }; - - int src1_step = src1.step / src1.elemSize1(), src1_offset = src1.offset / src1.elemSize1(); - int src2_step = src2.step / src2.elemSize1(), src2_offset = src2.offset / src2.elemSize1(); - int dst1_step = dst1.step / dst1.elemSize1(), dst1_offset = dst1.offset / dst1.elemSize1(); - int dst2_step = dst2.step / dst2.elemSize1(), dst2_offset = dst2.offset / dst2.elemSize1(); - - std::vector > args; - if (src1.data) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src1.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1_offset )); - } - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src2.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2_offset )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst1.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst1_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst1_offset )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst2.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst2_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst2_offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols )); - - openCLExecuteKernel(src1.clCxt, &arithm_polarToCart, kernelName, globalThreads, localThreads, - args, -1, depth, angleInDegrees ? "-D DEGREE" : "-D RADIAN"); -} - -void cv::ocl::polarToCart(const oclMat &magnitude, const oclMat &angle, oclMat &x, oclMat &y, bool angleInDegrees) -{ - if (!magnitude.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && magnitude.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_Assert(angle.depth() == CV_32F || angle.depth() == CV_64F); - CV_Assert(magnitude.size() == angle.size() && magnitude.type() == angle.type()); - - x.create(angle.size(), angle.type()); - y.create(angle.size(), angle.type()); - - if ( magnitude.data ) - arithmetic_ptc_run(magnitude, angle, x, y, angleInDegrees, "arithm_polarToCart_mag"); - else - arithmetic_ptc_run(magnitude, angle, x, y, angleInDegrees, "arithm_polarToCart"); -} - -////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////// minMaxLoc //////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -static void arithmetic_minMaxLoc_run(const oclMat &src, cl_mem &dst, int vlen , int groupnum) -{ - std::vector > args; - int all_cols = src.step / (vlen * src.elemSize1()); - int pre_cols = (src.offset % src.step) / (vlen * src.elemSize1()); - int sec_cols = all_cols - (src.offset % src.step + src.cols * src.elemSize1() - 1) / (vlen * src.elemSize1()) - 1; - int invalid_cols = pre_cols + sec_cols; - int cols = all_cols - invalid_cols , elemnum = cols * src.rows;; - int offset = src.offset / (vlen * src.elemSize1()); - int repeat_s = src.offset / src.elemSize1() - offset * vlen; - int repeat_e = (offset + cols) * vlen - src.offset / src.elemSize1() - src.cols; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&invalid_cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&offset)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&elemnum)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&groupnum)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst )); - char build_options[50]; - sprintf(build_options, "-D DEPTH_%d -D REPEAT_S%d -D REPEAT_E%d", src.depth(), repeat_s, repeat_e); - size_t gt[3] = {groupnum * 256, 1, 1}, lt[3] = {256, 1, 1}; - - // kernel use fixed grid size, replace lt on NULL is imposible without kernel changes - openCLExecuteKernel(src.clCxt, &arithm_minMaxLoc, "arithm_op_minMaxLoc", gt, lt, args, -1, -1, build_options); -} - -static void arithmetic_minMaxLoc_mask_run(const oclMat &src, const oclMat &mask, cl_mem &dst, int vlen, int groupnum) -{ - std::vector > args; - size_t gt[3] = {groupnum * 256, 1, 1}, lt[3] = {256, 1, 1}; - char build_options[50]; - if (src.oclchannels() == 1) - { - int cols = (src.cols - 1) / vlen + 1; - int invalid_cols = src.step / (vlen * src.elemSize1()) - cols; - int offset = src.offset / src.elemSize1(); - int repeat_me = vlen - (mask.cols % vlen == 0 ? vlen : mask.cols % vlen); - int minvalid_cols = mask.step / (vlen * mask.elemSize1()) - cols; - int moffset = mask.offset / mask.elemSize1(); - int elemnum = cols * src.rows; - sprintf(build_options, "-D DEPTH_%d -D REPEAT_E%d", src.depth(), repeat_me); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&invalid_cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&offset)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&elemnum)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&groupnum)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&minvalid_cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&moffset )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst )); - - // kernel use fixed grid size, replace lt on NULL is imposible without kernel changes - openCLExecuteKernel(src.clCxt, &arithm_minMaxLoc_mask, "arithm_op_minMaxLoc_mask", gt, lt, args, -1, -1, build_options); - } -} - -template -void arithmetic_minMaxLoc(const oclMat &src, double *minVal, double *maxVal, - Point *minLoc, Point *maxLoc, const oclMat &mask) -{ - CV_Assert(src.oclchannels() == 1); - size_t groupnum = src.clCxt->getDeviceInfo().maxComputeUnits; - CV_Assert(groupnum != 0); - int minloc = -1 , maxloc = -1; - int vlen = 4, dbsize = groupnum * vlen * 4 * sizeof(T) ; - Context *clCxt = src.clCxt; - cl_mem dstBuffer = openCLCreateBuffer(clCxt, CL_MEM_WRITE_ONLY, dbsize); - *minVal = std::numeric_limits::max() , *maxVal = -std::numeric_limits::max(); - - if (mask.empty()) - arithmetic_minMaxLoc_run(src, dstBuffer, vlen, groupnum); - else - arithmetic_minMaxLoc_mask_run(src, mask, dstBuffer, vlen, groupnum); - - AutoBuffer _buf(groupnum * vlen * 4); - T *p = (T*)_buf; - memset(p, 0, dbsize); - - openCLReadBuffer(clCxt, dstBuffer, (void *)p, dbsize); - for (int i = 0; i < vlen * (int)groupnum; i++) - { - *minVal = (*minVal < p[i] || p[i + 2 * vlen * groupnum] == -1) ? *minVal : p[i]; - minloc = (*minVal < p[i] || p[i + 2 * vlen * groupnum] == -1) ? minloc : cvRound(p[i + 2 * vlen * groupnum]); - } - for (int i = vlen * (int)groupnum; i < 2 * vlen * (int)groupnum; i++) - { - *maxVal = (*maxVal > p[i] || p[i + 2 * vlen * groupnum] == -1) ? *maxVal : p[i]; - maxloc = (*maxVal > p[i] || p[i + 2 * vlen * groupnum] == -1) ? maxloc : cvRound(p[i + 2 * vlen * groupnum]); - } - - int pre_rows = src.offset / src.step; - int pre_cols = (src.offset % src.step) / src.elemSize1(); - int wholecols = src.step / src.elemSize1(); - if ( minLoc ) - { - if ( minloc >= 0 ) - { - minLoc->y = minloc / wholecols - pre_rows; - minLoc->x = minloc % wholecols - pre_cols; - } - else - minLoc->x = minLoc->y = -1; - } - if ( maxLoc ) - { - if ( maxloc >= 0 ) - { - maxLoc->y = maxloc / wholecols - pre_rows; - maxLoc->x = maxloc % wholecols - pre_cols; - } - else - maxLoc->x = maxLoc->y = -1; - } - - openCLSafeCall(clReleaseMemObject(dstBuffer)); -} - -typedef void (*minMaxLocFunc)(const oclMat &src, double *minVal, double *maxVal, - Point *minLoc, Point *maxLoc, const oclMat &mask); - -void cv::ocl::minMaxLoc(const oclMat &src, double *minVal, double *maxVal, - Point *minLoc, Point *maxLoc, const oclMat &mask) -{ - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - static minMaxLocFunc functab[2] = - { - arithmetic_minMaxLoc, - arithmetic_minMaxLoc - }; - - minMaxLocFunc func; - func = functab[(int)src.clCxt->supportsFeature(FEATURE_CL_DOUBLE)]; - func(src, minVal, maxVal, minLoc, maxLoc, mask); -} - -////////////////////////////////////////////////////////////////////////////// -///////////////////////////// countNonZero /////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -static void arithmetic_countNonZero_run(const oclMat &src, cl_mem &dst, int groupnum, String kernelName) -{ - int ochannels = src.oclchannels(); - int all_cols = src.step / src.elemSize(); - int pre_cols = (src.offset % src.step) / src.elemSize(); - int sec_cols = all_cols - (src.offset % src.step + src.cols * src.elemSize() - 1) / src.elemSize() - 1; - int invalid_cols = pre_cols + sec_cols; - int cols = all_cols - invalid_cols , elemnum = cols * src.rows;; - int offset = src.offset / src.elemSize(); - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char * const channelMap[] = { " ", " ", "2", "4", "4" }; - String buildOptions = format("-D srcT=%s%s -D dstT=int%s", typeMap[src.depth()], channelMap[ochannels], - channelMap[ochannels]); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&invalid_cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&offset)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&elemnum)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&groupnum)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst )); - - size_t globalThreads[3] = { groupnum * 256, 1, 1 }; - -#ifdef ANDROID - openCLExecuteKernel(src.clCxt, &arithm_nonzero, kernelName, globalThreads, NULL, - args, -1, -1, buildOptions.c_str()); -#else - size_t localThreads[3] = { 256, 1, 1 }; - openCLExecuteKernel(src.clCxt, &arithm_nonzero, kernelName, globalThreads, localThreads, - args, -1, -1, buildOptions.c_str()); -#endif -} - -int cv::ocl::countNonZero(const oclMat &src) -{ - CV_Assert(src.step % src.elemSize() == 0); - CV_Assert(src.channels() == 1); - - Context *clCxt = src.clCxt; - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "selected device doesn't support double"); - return -1; - } - - size_t groupnum = src.clCxt->getDeviceInfo().maxComputeUnits; - CV_Assert(groupnum != 0); - int dbsize = groupnum; - - String kernelName = "arithm_op_nonzero"; - - AutoBuffer _buf(dbsize); - int *p = (int*)_buf, nonzero = 0; - memset(p, 0, dbsize * sizeof(int)); - - cl_mem dstBuffer = openCLCreateBuffer(clCxt, CL_MEM_WRITE_ONLY, dbsize * sizeof(int)); - arithmetic_countNonZero_run(src, dstBuffer, groupnum, kernelName); - openCLReadBuffer(clCxt, dstBuffer, (void *)p, dbsize * sizeof(int)); - - for (int i = 0; i < dbsize; i++) - nonzero += p[i]; - - openCLSafeCall(clReleaseMemObject(dstBuffer)); - - return nonzero; -} - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////bitwise_op//////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -static void bitwise_unary_run(const oclMat &src1, oclMat &dst, String kernelName, const cv::ocl::ProgramEntry* source) -{ - dst.create(src1.size(), src1.type()); - - int channels = dst.oclchannels(); - int depth = dst.depth(); - - int vector_lengths[4][7] = {{4, 4, 4, 4, 1, 1, 1}, - {4, 4, 4, 4, 1, 1, 1}, - {4, 4, 4, 4, 1, 1, 1}, - {4, 4, 4, 4, 1, 1, 1} - }; - - size_t vector_length = vector_lengths[channels - 1][depth]; - int offset_cols = (dst.offset / dst.elemSize1()) & (vector_length - 1); - int cols = divUp(dst.cols * channels + offset_cols, vector_length); - -#ifdef ANDROID - size_t localThreads[3] = { 64, 2, 1 }; -#else - size_t localThreads[3] = { 64, 4, 1 }; -#endif - size_t globalThreads[3] = { cols, dst.rows, 1 }; - - int dst_step1 = dst.cols * dst.elemSize(); - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src1.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.offset )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_step1 )); - - openCLExecuteKernel(src1.clCxt, source, kernelName, globalThreads, localThreads, args, -1, depth); -} - -enum { AND = 0, OR, XOR }; - -static void bitwise_binary_run(const oclMat &src1, const oclMat &src2, const Scalar& src3, const oclMat &mask, - oclMat &dst, int operationType) -{ - CV_Assert(operationType >= AND && operationType <= XOR); - CV_Assert(src2.empty() || (!src2.empty() && src1.type() == src2.type() && src1.size() == src2.size())); - CV_Assert(mask.empty() || (!mask.empty() && mask.type() == CV_8UC1 && mask.size() == src1.size())); - - dst.create(src1.size(), src1.type()); - oclMat m; - - const char operationMap[] = { '&', '|', '^' }; - std::string kernelName("arithm_bitwise_binary"); - - int vlen = std::min(8, src1.elemSize1() * src1.oclchannels()); - std::string vlenstr = vlen > 1 ? format("%d", vlen) : ""; - std::string buildOptions = format("-D Operation=%c -D vloadn=vload%s -D vstoren=vstore%s -D elemSize=%d -D vlen=%d" - " -D ucharv=uchar%s", - operationMap[operationType], vlenstr.c_str(), vlenstr.c_str(), - (int)src1.elemSize(), vlen, vlenstr.c_str()); - -#ifdef ANDROID - size_t localThreads[3] = { 16, 10, 1 }; -#else - size_t localThreads[3] = { 16, 16, 1 }; -#endif - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src1.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.offset )); - - if (src2.empty()) - { - m.create(1, 1, dst.type()); - m.setTo(src3); - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&m.data )); - - kernelName += "_scalar"; - } - else - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src2.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2.offset )); - } - - if (!mask.empty()) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mask.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mask.offset )); - - kernelName += "_mask"; - } - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.offset )); - - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.rows )); - - openCLExecuteKernel(src1.clCxt, mask.empty() ? (!src2.empty() ? &arithm_bitwise_binary : &arithm_bitwise_binary_scalar) : - (!src2.empty() ? &arithm_bitwise_binary_mask : &arithm_bitwise_binary_scalar_mask), - kernelName, globalThreads, localThreads, - args, -1, -1, buildOptions.c_str()); -} - -void cv::ocl::bitwise_not(const oclMat &src, oclMat &dst) -{ - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - dst.create(src.size(), src.type()); - bitwise_unary_run(src, dst, "arithm_bitwise_not", &arithm_bitwise_not); -} - -void cv::ocl::bitwise_or(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask) -{ - bitwise_binary_run(src1, src2, Scalar(), mask, dst, OR); -} - -void cv::ocl::bitwise_or(const oclMat &src1, const Scalar &src2, oclMat &dst, const oclMat &mask) -{ - bitwise_binary_run(src1, oclMat(), src2, mask, dst, OR); -} - -void cv::ocl::bitwise_and(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask) -{ - bitwise_binary_run(src1, src2, Scalar(), mask, dst, AND); -} - -void cv::ocl::bitwise_and(const oclMat &src1, const Scalar &src2, oclMat &dst, const oclMat &mask) -{ - bitwise_binary_run(src1, oclMat(), src2, mask, dst, AND); -} - -void cv::ocl::bitwise_xor(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask) -{ - bitwise_binary_run(src1, src2, Scalar(), mask, dst, XOR); -} - -void cv::ocl::bitwise_xor(const oclMat &src1, const Scalar &src2, oclMat &dst, const oclMat &mask) -{ - bitwise_binary_run(src1, oclMat(), src2, mask, dst, XOR); -} - -oclMat cv::ocl::operator ~ (const oclMat &src) -{ - return oclMatExpr(src, oclMat(), MAT_NOT); -} - -oclMat cv::ocl::operator | (const oclMat &src1, const oclMat &src2) -{ - return oclMatExpr(src1, src2, MAT_OR); -} - -oclMat cv::ocl::operator & (const oclMat &src1, const oclMat &src2) -{ - return oclMatExpr(src1, src2, MAT_AND); -} - -oclMat cv::ocl::operator ^ (const oclMat &src1, const oclMat &src2) -{ - return oclMatExpr(src1, src2, MAT_XOR); -} - -cv::ocl::oclMatExpr cv::ocl::operator + (const oclMat &src1, const oclMat &src2) -{ - return oclMatExpr(src1, src2, cv::ocl::MAT_ADD); -} - -cv::ocl::oclMatExpr cv::ocl::operator - (const oclMat &src1, const oclMat &src2) -{ - return oclMatExpr(src1, src2, cv::ocl::MAT_SUB); -} - -cv::ocl::oclMatExpr cv::ocl::operator * (const oclMat &src1, const oclMat &src2) -{ - return oclMatExpr(src1, src2, cv::ocl::MAT_MUL); -} - -cv::ocl::oclMatExpr cv::ocl::operator / (const oclMat &src1, const oclMat &src2) -{ - return oclMatExpr(src1, src2, cv::ocl::MAT_DIV); -} - -void oclMatExpr::assign(oclMat& m) const -{ - switch (op) - { - case MAT_ADD: - add(a, b, m); - break; - case MAT_SUB: - subtract(a, b, m); - break; - case MAT_MUL: - multiply(a, b, m); - break; - case MAT_DIV: - divide(a, b, m); - break; - case MAT_NOT: - bitwise_not(a, m); - break; - case MAT_AND: - bitwise_and(a, b, m); - break; - case MAT_OR: - bitwise_or(a, b, m); - break; - case MAT_XOR: - bitwise_xor(a, b, m); - break; - } -} - -oclMatExpr::operator oclMat() const -{ - oclMat m; - assign(m); - return m; -} - -////////////////////////////////////////////////////////////////////////////// -/////////////////////////////// transpose //////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -#define TILE_DIM (32) -#define BLOCK_ROWS (256 / TILE_DIM) - -static void transpose_run(const oclMat &src, oclMat &dst, String kernelName, bool inplace = false) -{ - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char channelsString[] = { ' ', ' ', '2', '4', '4' }; - std::string buildOptions = format("-D T=%s%c", typeMap[src.depth()], - channelsString[src.channels()]); - - size_t localThreads[3] = { TILE_DIM, BLOCK_ROWS, 1 }; - size_t globalThreads[3] = { src.cols, inplace ? src.rows : divUp(src.rows, TILE_DIM) * BLOCK_ROWS, 1 }; - - int srcstep1 = src.step / src.elemSize(), dststep1 = dst.step / dst.elemSize(); - int srcoffset1 = src.offset / src.elemSize(), dstoffset1 = dst.offset / dst.elemSize(); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcstep1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dststep1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcoffset1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstoffset1 )); - - openCLExecuteKernel(src.clCxt, &arithm_transpose, kernelName, globalThreads, localThreads, - args, -1, -1, buildOptions.c_str()); -} - -void cv::ocl::transpose(const oclMat &src, oclMat &dst) -{ - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - if ( src.data == dst.data && src.cols == src.rows && dst.offset == src.offset - && dst.size() == src.size()) - transpose_run( src, dst, "transpose_inplace", true); - else - { - dst.create(src.cols, src.rows, src.type()); - transpose_run( src, dst, "transpose"); - } -} - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////// addWeighted /////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -void cv::ocl::addWeighted(const oclMat &src1, double alpha, const oclMat &src2, double beta, double gama, oclMat &dst) -{ - Context *clCxt = src1.clCxt; - bool hasDouble = clCxt->supportsFeature(FEATURE_CL_DOUBLE); - if (!hasDouble && src1.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); - dst.create(src1.size(), src1.type()); - - int channels = dst.oclchannels(); - int depth = dst.depth(); - - int cols1 = src1.cols * channels; - int src1step1 = src1.step1(), src1offset1 = src1.offset / src1.elemSize1(); - int src2step1 = src2.step1(), src2offset1 = src2.offset / src1.elemSize1(); - int dststep1 = dst.step1(), dstoffset1 = dst.offset / dst.elemSize1(); - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - std::string buildOptions = format("-D T=%s -D WT=%s -D convertToT=convert_%s%s", - typeMap[depth], hasDouble ? "double" : "float", typeMap[depth], - depth >= CV_32F ? "" : "_sat_rte"); - - size_t globalThreads[3] = { cols1, dst.rows, 1}; - - float alpha_f = static_cast(alpha), - beta_f = static_cast(beta), - gama_f = static_cast(gama); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src1.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1step1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1offset1)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src2.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2step1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2offset1)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dststep1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstoffset1)); - - if (!hasDouble) - { - args.push_back( std::make_pair( sizeof(cl_float), (void *)&alpha_f )); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&beta_f )); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&gama_f )); - } - else - { - args.push_back( std::make_pair( sizeof(cl_double), (void *)&alpha )); - args.push_back( std::make_pair( sizeof(cl_double), (void *)&beta )); - args.push_back( std::make_pair( sizeof(cl_double), (void *)&gama )); - } - - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1.rows )); - -#ifdef ANDROID - openCLExecuteKernel(clCxt, &arithm_addWeighted, "addWeighted", globalThreads, NULL, - args, -1, -1, buildOptions.c_str()); -#else - size_t localThreads[3] = { 256, 1, 1}; - openCLExecuteKernel(clCxt, &arithm_addWeighted, "addWeighted", globalThreads, localThreads, - args, -1, -1, buildOptions.c_str()); -#endif -} - -////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////// Pow ////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -static void arithmetic_pow_run(const oclMat &src, double p, oclMat &dst, String kernelName, const cv::ocl::ProgramEntry* source) -{ - int channels = dst.oclchannels(); - int depth = dst.depth(); - - size_t localThreads[3] = { 64, 4, 1 }; - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - - const char * const typeStr = depth == CV_32F ? "float" : "double"; - const char * const channelMap[] = { "", "", "2", "4", "4" }; - std::string buildOptions = format("-D VT=%s%s -D T=%s", typeStr, channelMap[channels], typeStr); - - int src_step = src.step / src.elemSize(), src_offset = src.offset / src.elemSize(); - int dst_step = dst.step / dst.elemSize(), dst_offset = dst.offset / dst.elemSize(); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_offset )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.cols )); - - float pf = static_cast(p); - if(src.depth() == CV_32F) - args.push_back( std::make_pair( sizeof(cl_float), (void *)&pf )); - else - args.push_back( std::make_pair( sizeof(cl_double), (void *)&p )); - - openCLExecuteKernel(src.clCxt, source, kernelName, globalThreads, localThreads, args, -1, -1, buildOptions.c_str()); -} - -void cv::ocl::pow(const oclMat &x, double p, oclMat &y) -{ - if (!x.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && x.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_Assert(x.depth() == CV_32F || x.depth() == CV_64F); - y.create(x.size(), x.type()); - - arithmetic_pow_run(x, p, y, "arithm_pow", &arithm_pow); -} - -////////////////////////////////////////////////////////////////////////////// -/////////////////////////////// setIdentity ////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -void cv::ocl::setIdentity(oclMat& src, const Scalar & scalar) -{ - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_Assert(src.step % src.elemSize() == 0); - - int src_step1 = src.step / src.elemSize(), src_offset1 = src.offset / src.elemSize(); - size_t local_threads[] = { 16, 16, 1 }; - size_t global_threads[] = { src.cols, src.rows, 1 }; - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char * const channelMap[] = { "", "", "2", "4", "4" }; - String buildOptions = format("-D T=%s%s", typeMap[src.depth()], channelMap[src.oclchannels()]); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_step1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_offset1 )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows)); - - oclMat sc(1, 1, src.type(), scalar); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&sc.data )); - - openCLExecuteKernel(src.clCxt, &arithm_setidentity, "setIdentity", global_threads, local_threads, - args, -1, -1, buildOptions.c_str()); -} - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////// Repeat //////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -void cv::ocl::repeat(const oclMat & src, int ny, int nx, oclMat & dst) -{ - CV_Assert(nx > 0 && ny > 0); - dst.create(src.rows * ny, src.cols * nx, src.type()); - - for (int y = 0; y < ny; ++y) - for (int x = 0; x < nx; ++x) - { - Rect roi(x * src.cols, y * src.rows, src.cols, src.rows); - oclMat hdr = dst(roi); - src.copyTo(hdr); - } -} diff --git a/modules/ocl/src/bgfg_mog.cpp b/modules/ocl/src/bgfg_mog.cpp deleted file mode 100644 index c6883661b..000000000 --- a/modules/ocl/src/bgfg_mog.cpp +++ /dev/null @@ -1,639 +0,0 @@ -/*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-2013, Multicoreware, Inc., all rights reserved. -// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// 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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -namespace cv -{ - namespace ocl - { - typedef struct _contant_struct - { - cl_float c_Tb; - cl_float c_TB; - cl_float c_Tg; - cl_float c_varInit; - cl_float c_varMin; - cl_float c_varMax; - cl_float c_tau; - cl_uchar c_shadowVal; - }contant_struct; - - cl_mem cl_constants = NULL; - float c_TB; - } -} - -#if defined _MSC_VER -#define snprintf sprintf_s -#endif - -namespace cv { namespace ocl { namespace device -{ - namespace mog - { - void mog_ocl(const oclMat& frame, int cn, oclMat& fgmask, oclMat& weight, oclMat& sortKey, oclMat& mean, oclMat& var, - int nmixtures, float varThreshold, float learningRate, float backgroundRatio, float noiseSigma); - - void getBackgroundImage_ocl(int cn, const oclMat& weight, const oclMat& mean, oclMat& dst, int nmixtures, float backgroundRatio); - - void loadConstants(float Tb, float TB, float Tg, float varInit, float varMin, float varMax, float tau, - unsigned char shadowVal); - - void mog2_ocl(const oclMat& frame, int cn, oclMat& fgmask, oclMat& modesUsed, oclMat& weight, oclMat& variance, oclMat& mean, - float alphaT, float prune, bool detectShadows, int nmixtures); - - void getBackgroundImage2_ocl(int cn, const oclMat& modesUsed, const oclMat& weight, const oclMat& mean, oclMat& dst, int nmixtures); - } -}}} - -namespace mog -{ - const int defaultNMixtures = 5; - const int defaultHistory = 200; - const float defaultBackgroundRatio = 0.7f; - const float defaultVarThreshold = 2.5f * 2.5f; - const float defaultNoiseSigma = 30.0f * 0.5f; - const float defaultInitialWeight = 0.05f; -} -void cv::ocl::BackgroundSubtractor::operator()(const oclMat&, oclMat&, float) -{ - -} -cv::ocl::BackgroundSubtractor::~BackgroundSubtractor() -{ - -} - -cv::ocl::MOG::MOG(int nmixtures) : -frameSize_(0, 0), frameType_(0), nframes_(0) -{ - nmixtures_ = std::min(nmixtures > 0 ? nmixtures : mog::defaultNMixtures, 8); - history = mog::defaultHistory; - varThreshold = mog::defaultVarThreshold; - backgroundRatio = mog::defaultBackgroundRatio; - noiseSigma = mog::defaultNoiseSigma; -} - -void cv::ocl::MOG::initialize(cv::Size frameSize, int frameType) -{ - CV_Assert(frameType == CV_8UC1 || frameType == CV_8UC3 || frameType == CV_8UC4); - - frameSize_ = frameSize; - frameType_ = frameType; - - int ch = CV_MAT_CN(frameType); - int work_ch = ch; - - // for each gaussian mixture of each pixel bg model we store - // the mixture sort key (w/sum_of_variances), the mixture weight (w), - // the mean (nchannels values) and - // the diagonal covariance matrix (another nchannels values) - - weight_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1); - sortKey_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1); - mean_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC(work_ch)); - var_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC(work_ch)); - - weight_.setTo(cv::Scalar::all(0)); - sortKey_.setTo(cv::Scalar::all(0)); - mean_.setTo(cv::Scalar::all(0)); - var_.setTo(cv::Scalar::all(0)); - - nframes_ = 0; -} - -void cv::ocl::MOG::operator()(const cv::ocl::oclMat& frame, cv::ocl::oclMat& fgmask, float learningRate) -{ - using namespace cv::ocl::device::mog; - - CV_Assert(frame.depth() == CV_8U); - - int ch = frame.oclchannels(); - int work_ch = ch; - - if (nframes_ == 0 || learningRate >= 1.0 || frame.size() != frameSize_ || work_ch != mean_.oclchannels()) - initialize(frame.size(), frame.type()); - - fgmask.create(frameSize_, CV_8UC1); - - ++nframes_; - learningRate = learningRate >= 0.0f && nframes_ > 1 ? learningRate : 1.0f / std::min(nframes_, history); - CV_Assert(learningRate >= 0.0f); - - mog_ocl(frame, ch, fgmask, weight_, sortKey_, mean_, var_, nmixtures_, - varThreshold, learningRate, backgroundRatio, noiseSigma); -} - -void cv::ocl::MOG::getBackgroundImage(oclMat& backgroundImage) const -{ - using namespace cv::ocl::device::mog; - - backgroundImage.create(frameSize_, frameType_); - - cv::ocl::device::mog::getBackgroundImage_ocl(backgroundImage.oclchannels(), weight_, mean_, backgroundImage, nmixtures_, backgroundRatio); -} - -void cv::ocl::MOG::release() -{ - frameSize_ = Size(0, 0); - frameType_ = 0; - nframes_ = 0; - - weight_.release(); - sortKey_.release(); - mean_.release(); - var_.release(); - clReleaseMemObject(cl_constants); -} - -static void mog_withoutLearning(const oclMat& frame, int cn, oclMat& fgmask, oclMat& weight, oclMat& mean, oclMat& var, - int nmixtures, float varThreshold, float backgroundRatio) -{ - Context* clCxt = Context::getContext(); - - size_t local_thread[] = {32, 8, 1}; - size_t global_thread[] = {frame.cols, frame.rows, 1}; - - int frame_step = (int)(frame.step/frame.elemSize()); - int fgmask_step = (int)(fgmask.step/fgmask.elemSize()); - int weight_step = (int)(weight.step/weight.elemSize()); - int mean_step = (int)(mean.step/mean.elemSize()); - int var_step = (int)(var.step/var.elemSize()); - - int fgmask_offset_y = (int)(fgmask.offset/fgmask.step); - int fgmask_offset_x = (int)(fgmask.offset%fgmask.step); - fgmask_offset_x = fgmask_offset_x/(int)fgmask.elemSize(); - - int frame_offset_y = (int)(frame.offset/frame.step); - int frame_offset_x = (int)(frame.offset%frame.step); - frame_offset_x = frame_offset_x/(int)frame.elemSize(); - - char build_option[50]; - if(cn == 1) - { - snprintf(build_option, 50, "-D CN1 -D NMIXTURES=%d", nmixtures); - }else - { - snprintf(build_option, 50, "-D NMIXTURES=%d", nmixtures); - } - - String kernel_name = "mog_withoutLearning_kernel"; - std::vector > args; - - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&frame.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&fgmask.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&weight.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&mean.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&var.data)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame.cols)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&fgmask_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&weight_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&mean_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&var_step)); - - args.push_back(std::make_pair(sizeof(cl_float), (void*)&varThreshold)); - args.push_back(std::make_pair(sizeof(cl_float), (void*)&backgroundRatio)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&fgmask_offset_x)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&fgmask_offset_y)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame_offset_x)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame_offset_y)); - - openCLExecuteKernel(clCxt, &bgfg_mog, kernel_name, global_thread, local_thread, args, -1, -1, build_option); -} - - -static void mog_withLearning(const oclMat& frame, int cn, oclMat& fgmask_raw, oclMat& weight, oclMat& sortKey, oclMat& mean, oclMat& var, - int nmixtures, float varThreshold, float backgroundRatio, float learningRate, float minVar) -{ - Context* clCxt = Context::getContext(); - - size_t local_thread[] = {32, 8, 1}; - size_t global_thread[] = {frame.cols, frame.rows, 1}; - - oclMat fgmask(fgmask_raw.size(), CV_32SC1); - - int frame_step = (int)(frame.step/frame.elemSize()); - int fgmask_step = (int)(fgmask.step/fgmask.elemSize()); - int weight_step = (int)(weight.step/weight.elemSize()); - int sortKey_step = (int)(sortKey.step/sortKey.elemSize()); - int mean_step = (int)(mean.step/mean.elemSize()); - int var_step = (int)(var.step/var.elemSize()); - - int fgmask_offset_y = (int)(fgmask.offset/fgmask.step); - int fgmask_offset_x = (int)(fgmask.offset%fgmask.step); - fgmask_offset_x = fgmask_offset_x/(int)fgmask.elemSize(); - - int frame_offset_y = (int)(frame.offset/frame.step); - int frame_offset_x = (int)(frame.offset%frame.step); - frame_offset_x = frame_offset_x/(int)frame.elemSize(); - - char build_option[50]; - if(cn == 1) - { - snprintf(build_option, 50, "-D CN1 -D NMIXTURES=%d", nmixtures); - }else - { - snprintf(build_option, 50, "-D NMIXTURES=%d", nmixtures); - } - - String kernel_name = "mog_withLearning_kernel"; - std::vector > args; - - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&frame.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&fgmask.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&weight.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&sortKey.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&mean.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&var.data)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame.cols)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&fgmask_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&weight_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&sortKey_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&mean_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&var_step)); - - args.push_back(std::make_pair(sizeof(cl_float), (void*)&varThreshold)); - args.push_back(std::make_pair(sizeof(cl_float), (void*)&backgroundRatio)); - args.push_back(std::make_pair(sizeof(cl_float), (void*)&learningRate)); - args.push_back(std::make_pair(sizeof(cl_float), (void*)&minVar)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&fgmask_offset_x)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&fgmask_offset_y)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame_offset_x)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame_offset_y)); - - openCLExecuteKernel(clCxt, &bgfg_mog, kernel_name, global_thread, local_thread, args, -1, -1, build_option); - fgmask.convertTo(fgmask, CV_8U); - fgmask.copyTo(fgmask_raw); -} - -void cv::ocl::device::mog::mog_ocl(const oclMat& frame, int cn, oclMat& fgmask, oclMat& weight, oclMat& sortKey, oclMat& mean, oclMat& var, - int nmixtures, float varThreshold, float learningRate, float backgroundRatio, float noiseSigma) -{ - const float minVar = noiseSigma * noiseSigma; - - if(learningRate > 0.0f) - mog_withLearning(frame, cn, fgmask, weight, sortKey, mean, var, nmixtures, - varThreshold, backgroundRatio, learningRate, minVar); - else - mog_withoutLearning(frame, cn, fgmask, weight, mean, var, nmixtures, varThreshold, backgroundRatio); -} - -void cv::ocl::device::mog::getBackgroundImage_ocl(int cn, const oclMat& weight, const oclMat& mean, oclMat& dst, int nmixtures, float backgroundRatio) -{ - Context* clCxt = Context::getContext(); - - size_t local_thread[] = {32, 8, 1}; - size_t global_thread[] = {dst.cols, dst.rows, 1}; - - int weight_step = (int)(weight.step/weight.elemSize()); - int mean_step = (int)(mean.step/mean.elemSize()); - int dst_step = (int)(dst.step/dst.elemSize()); - - char build_option[50]; - if(cn == 1) - { - snprintf(build_option, 50, "-D CN1 -D NMIXTURES=%d", nmixtures); - }else - { - snprintf(build_option, 50, "-D NMIXTURES=%d", nmixtures); - } - - String kernel_name = "getBackgroundImage_kernel"; - std::vector > args; - - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&weight.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&mean.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&dst.data)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&dst.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&dst.cols)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&weight_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&mean_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&dst_step)); - - args.push_back(std::make_pair(sizeof(cl_float), (void*)&backgroundRatio)); - - openCLExecuteKernel(clCxt, &bgfg_mog, kernel_name, global_thread, local_thread, args, -1, -1, build_option); -} - -void cv::ocl::device::mog::loadConstants(float Tb, float TB, float Tg, float varInit, float varMin, float varMax, float tau, unsigned char shadowVal) -{ - varMin = cv::min(varMin, varMax); - varMax = cv::max(varMin, varMax); - - c_TB = TB; - - _contant_struct *constants = new _contant_struct; - constants->c_Tb = Tb; - constants->c_TB = TB; - constants->c_Tg = Tg; - constants->c_varInit = varInit; - constants->c_varMin = varMin; - constants->c_varMax = varMax; - constants->c_tau = tau; - constants->c_shadowVal = shadowVal; - - cl_constants = load_constant(*((cl_context*)getClContextPtr()), *((cl_command_queue*)getClCommandQueuePtr()), - (void *)constants, sizeof(_contant_struct)); -} - -void cv::ocl::device::mog::mog2_ocl(const oclMat& frame, int cn, oclMat& fgmaskRaw, oclMat& modesUsed, oclMat& weight, oclMat& variance, - oclMat& mean, float alphaT, float prune, bool detectShadows, int nmixtures) -{ - oclMat fgmask(fgmaskRaw.size(), CV_32SC1); - - Context* clCxt = Context::getContext(); - - const float alpha1 = 1.0f - alphaT; - - cl_int detectShadows_flag = 0; - if(detectShadows) - detectShadows_flag = 1; - - size_t local_thread[] = {32, 8, 1}; - size_t global_thread[] = {frame.cols, frame.rows, 1}; - - int frame_step = (int)(frame.step/frame.elemSize()); - int fgmask_step = (int)(fgmask.step/fgmask.elemSize()); - int weight_step = (int)(weight.step/weight.elemSize()); - int modesUsed_step = (int)(modesUsed.step/modesUsed.elemSize()); - int mean_step = (int)(mean.step/mean.elemSize()); - int var_step = (int)(variance.step/variance.elemSize()); - - int fgmask_offset_y = (int)(fgmask.offset/fgmask.step); - int fgmask_offset_x = (int)(fgmask.offset%fgmask.step); - fgmask_offset_x = fgmask_offset_x/(int)fgmask.elemSize(); - - int frame_offset_y = (int)(frame.offset/frame.step); - int frame_offset_x = (int)(frame.offset%frame.step); - frame_offset_x = frame_offset_x/(int)frame.elemSize(); - - String kernel_name = "mog2_kernel"; - std::vector > args; - - char build_option[50]; - if(cn == 1) - { - snprintf(build_option, 50, "-D CN1 -D NMIXTURES=%d", nmixtures); - }else - { - snprintf(build_option, 50, "-D NMIXTURES=%d", nmixtures); - } - - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&frame.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&fgmask.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&weight.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&mean.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&modesUsed.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&variance.data)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame.cols)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&fgmask_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&weight_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&mean_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&modesUsed_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&var_step)); - - args.push_back(std::make_pair(sizeof(cl_float), (void*)&alphaT)); - args.push_back(std::make_pair(sizeof(cl_float), (void*)&alpha1)); - args.push_back(std::make_pair(sizeof(cl_float), (void*)&prune)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&detectShadows_flag)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&fgmask_offset_x)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&fgmask_offset_y)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame_offset_x)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&frame_offset_y)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&cl_constants)); - - openCLExecuteKernel(clCxt, &bgfg_mog, kernel_name, global_thread, local_thread, args, -1, -1, build_option); - - fgmask.convertTo(fgmask, CV_8U); - fgmask.copyTo(fgmaskRaw); -} - -void cv::ocl::device::mog::getBackgroundImage2_ocl(int cn, const oclMat& modesUsed, const oclMat& weight, const oclMat& mean, oclMat& dst, int nmixtures) -{ - Context* clCxt = Context::getContext(); - - size_t local_thread[] = {32, 8, 1}; - size_t global_thread[] = {modesUsed.cols, modesUsed.rows, 1}; - - int weight_step = (int)(weight.step/weight.elemSize()); - int modesUsed_step = (int)(modesUsed.step/modesUsed.elemSize()); - int mean_step = (int)(mean.step/mean.elemSize()); - int dst_step = (int)(dst.step/dst.elemSize()); - - int dst_y = (int)(dst.offset/dst.step); - int dst_x = (int)(dst.offset%dst.step); - dst_x = dst_x/(int)dst.elemSize(); - - String kernel_name = "getBackgroundImage2_kernel"; - std::vector > args; - - char build_option[50]; - if(cn == 1) - { - snprintf(build_option, 50, "-D CN1 -D NMIXTURES=%d", nmixtures); - }else - { - snprintf(build_option, 50, "-D NMIXTURES=%d", nmixtures); - } - - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&modesUsed.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&weight.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&mean.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&dst.data)); - args.push_back(std::make_pair(sizeof(cl_float), (void*)&c_TB)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&modesUsed.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&modesUsed.cols)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&modesUsed_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&weight_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&mean_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&dst_step)); - - args.push_back(std::make_pair(sizeof(cl_int), (void*)&dst_x)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&dst_y)); - - openCLExecuteKernel(clCxt, &bgfg_mog, kernel_name, global_thread, local_thread, args, -1, -1, build_option); -} - -///////////////////////////////////////////////////////////////// -// MOG2 - -namespace mog2 -{ - // default parameters of gaussian background detection algorithm - const int defaultHistory = 500; // Learning rate; alpha = 1/defaultHistory2 - const float defaultVarThreshold = 4.0f * 4.0f; - const int defaultNMixtures = 5; // maximal number of Gaussians in mixture - const float defaultBackgroundRatio = 0.9f; // threshold sum of weights for background test - const float defaultVarThresholdGen = 3.0f * 3.0f; - const float defaultVarInit = 15.0f; // initial variance for new components - const float defaultVarMax = 5.0f * defaultVarInit; - const float defaultVarMin = 4.0f; - - // additional parameters - const float defaultfCT = 0.05f; // complexity reduction prior constant 0 - no reduction of number of components - const unsigned char defaultnShadowDetection = 127; // value to use in the segmentation mask for shadows, set 0 not to do shadow detection - const float defaultfTau = 0.5f; // Tau - shadow threshold, see the paper for explanation -} - -cv::ocl::MOG2::MOG2(int nmixtures) : frameSize_(0, 0), frameType_(0), nframes_(0) -{ - nmixtures_ = nmixtures > 0 ? nmixtures : mog2::defaultNMixtures; - - history = mog2::defaultHistory; - varThreshold = mog2::defaultVarThreshold; - bShadowDetection = true; - - backgroundRatio = mog2::defaultBackgroundRatio; - fVarInit = mog2::defaultVarInit; - fVarMax = mog2::defaultVarMax; - fVarMin = mog2::defaultVarMin; - - varThresholdGen = mog2::defaultVarThresholdGen; - fCT = mog2::defaultfCT; - nShadowDetection = mog2::defaultnShadowDetection; - fTau = mog2::defaultfTau; -} - -void cv::ocl::MOG2::initialize(cv::Size frameSize, int frameType) -{ - using namespace cv::ocl::device::mog; - CV_Assert(frameType == CV_8UC1 || frameType == CV_8UC3 || frameType == CV_8UC4); - - frameSize_ = frameSize; - frameType_ = frameType; - nframes_ = 0; - - int ch = CV_MAT_CN(frameType); - int work_ch = ch; - - // for each gaussian mixture of each pixel bg model we store ... - // the mixture weight (w), - // the mean (nchannels values) and - // the covariance - weight_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1); - weight_.setTo(Scalar::all(0)); - - variance_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1); - variance_.setTo(Scalar::all(0)); - - mean_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC(work_ch)); //4 channels - mean_.setTo(Scalar::all(0)); - - //make the array for keeping track of the used modes per pixel - all zeros at start - bgmodelUsedModes_.create(frameSize_, CV_32FC1); - bgmodelUsedModes_.setTo(cv::Scalar::all(0)); - - loadConstants(varThreshold, backgroundRatio, varThresholdGen, fVarInit, fVarMin, fVarMax, fTau, nShadowDetection); -} - -void cv::ocl::MOG2::operator()(const oclMat& frame, oclMat& fgmask, float learningRate) -{ - using namespace cv::ocl::device::mog; - - int ch = frame.oclchannels(); - int work_ch = ch; - - if (nframes_ == 0 || learningRate >= 1.0f || frame.size() != frameSize_ || work_ch != mean_.oclchannels()) - initialize(frame.size(), frame.type()); - - fgmask.create(frameSize_, CV_8UC1); - fgmask.setTo(cv::Scalar::all(0)); - - ++nframes_; - learningRate = learningRate >= 0.0f && nframes_ > 1 ? learningRate : 1.0f / std::min(2 * nframes_, history); - CV_Assert(learningRate >= 0.0f); - - mog2_ocl(frame, frame.oclchannels(), fgmask, bgmodelUsedModes_, weight_, variance_, mean_, learningRate, -learningRate * fCT, bShadowDetection, nmixtures_); -} - -void cv::ocl::MOG2::getBackgroundImage(oclMat& backgroundImage) const -{ - using namespace cv::ocl::device::mog; - - backgroundImage.create(frameSize_, frameType_); - - cv::ocl::device::mog::getBackgroundImage2_ocl(backgroundImage.oclchannels(), bgmodelUsedModes_, weight_, mean_, backgroundImage, nmixtures_); -} - -void cv::ocl::MOG2::release() -{ - frameSize_ = Size(0, 0); - frameType_ = 0; - nframes_ = 0; - - weight_.release(); - variance_.release(); - mean_.release(); - - bgmodelUsedModes_.release(); -} diff --git a/modules/ocl/src/blend.cpp b/modules/ocl/src/blend.cpp deleted file mode 100644 index 39f09c47b..000000000 --- a/modules/ocl/src/blend.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/*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 -// Nathan, liujun@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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -void cv::ocl::blendLinear(const oclMat &src1, const oclMat &src2, const oclMat &weights1, const oclMat &weights2, - oclMat &dst) -{ - CV_Assert(src1.depth() <= CV_32F); - CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); - CV_Assert(weights1.size() == weights2.size() && weights1.size() == src1.size() && - weights1.type() == CV_32FC1 && weights2.type() == CV_32FC1); - - dst.create(src1.size(), src1.type()); - - size_t globalSize[] = { dst.cols, dst.rows, 1}; - size_t localSize[] = { 16, 16, 1 }; - - int depth = dst.depth(), ocn = dst.oclchannels(); - int src1_step = src1.step / src1.elemSize(), src1_offset = src1.offset / src1.elemSize(); - int src2_step = src2.step / src2.elemSize(), src2_offset = src2.offset / src2.elemSize(); - int weight1_step = weights1.step / weights1.elemSize(), weight1_offset = weights1.offset / weights1.elemSize(); - int weight2_step = weights2.step / weights2.elemSize(), weight2_offset = weights2.offset / weights2.elemSize(); - int dst_step = dst.step / dst.elemSize(), dst_offset = dst.offset / dst.elemSize(); - - const char * const channelMap[] = { "", "", "2", "4", "4" }; - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - std::string buildOptions = format("-D T=%s%s -D convertToT=convert_%s%s%s -D FT=float%s -D convertToFT=convert_float%s", - typeMap[depth], channelMap[ocn], typeMap[depth], channelMap[ocn], - depth >= CV_32S ? "" : "_sat_rte", channelMap[ocn], channelMap[ocn]); - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src1.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1_offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src1_step )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src2.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2_offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src2_step )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&weights1.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&weight1_offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&weight1_step )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&weights2.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&weight2_offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&weight2_step )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.cols )); - - openCLExecuteKernel(src1.clCxt, &blend_linear, "blendLinear", globalSize, localSize, args, - -1, -1, buildOptions.c_str()); -} diff --git a/modules/ocl/src/brief.cpp b/modules/ocl/src/brief.cpp deleted file mode 100644 index d176a5e1a..000000000 --- a/modules/ocl/src/brief.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/*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) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009-2010, Willow Garage Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Matthias Bady aegirxx ==> gmail.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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -BRIEF_OCL::BRIEF_OCL( int _bytes ) : bytes( _bytes ) -{ -} - -void BRIEF_OCL::compute( const oclMat& image, const oclMat& keypoints, oclMat& mask, oclMat& descriptors ) const -{ - CV_Assert( image.type( ) == CV_8UC1 ); - if ( keypoints.size( ).area( ) == 0 ) return; - descriptors = oclMat( Mat( keypoints.cols, bytes, CV_8UC1 ) ); - if( mask.cols != keypoints.cols ) - { - mask = oclMat( Mat::ones( 1, keypoints.cols, CV_8UC1 ) ); - } - oclMat sum; - integral( image, sum, CV_32S ); - cl_mem sumTexture = bindTexture( sum ); - std::stringstream build_opt; - build_opt - << " -D BYTES=" << bytes - << " -D KERNEL_SIZE=" << KERNEL_SIZE - << " -D BORDER=" << getBorderSize(); - const String kernelname = "extractBriefDescriptors"; - size_t localThreads[3] = {bytes, 1, 1}; - size_t globalThreads[3] = {keypoints.cols * bytes, 1, 1}; - Context* ctx = Context::getContext( ); - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof (cl_mem), (void *) &sumTexture ) ); - args.push_back( std::make_pair( sizeof (cl_mem), (void *) &keypoints.data ) ); - args.push_back( std::make_pair( sizeof (cl_int), (void *) &keypoints.step ) ); - args.push_back( std::make_pair( sizeof (cl_mem), (void *) &descriptors.data ) ); - args.push_back( std::make_pair( sizeof (cl_int), (void *) &descriptors.step ) ); - args.push_back( std::make_pair( sizeof (cl_mem), (void *) &mask.data ) ); - openCLExecuteKernel( ctx, &brief, kernelname, globalThreads, localThreads, args, -1, -1, build_opt.str( ).c_str( ) ); - openCLFree( sumTexture ); -} - -int BRIEF_OCL::getBorderSize( ) -{ - return PATCH_SIZE / 2 + KERNEL_SIZE / 2; -} diff --git a/modules/ocl/src/brute_force_matcher.cpp b/modules/ocl/src/brute_force_matcher.cpp deleted file mode 100644 index ca16f4346..000000000 --- a/modules/ocl/src/brute_force_matcher.cpp +++ /dev/null @@ -1,1213 +0,0 @@ -/*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 -// Nathan, liujun@multicorewareinc.com -// Peng Xiao, pengxiao@outlook.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 "precomp.hpp" -#include -#include -#include -#include -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -static const int OPT_SIZE = 100; - -static const char * T_ARR [] = { - "uchar", - "char", - "ushort", - "short", - "int", - "float -D T_FLOAT", - "double"}; - -template < int BLOCK_SIZE, int MAX_DESC_LEN/*, typename Mask*/ > -void matchUnrolledCached(const oclMat &query, const oclMat &train, const oclMat &/*mask*/, - const oclMat &trainIdx, const oclMat &distance, int distType) -{ - cv::ocl::Context *ctx = query.clCxt; - size_t globalSize[] = {(query.rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; - size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; - const size_t smemSize = (BLOCK_SIZE * (MAX_DESC_LEN >= 2 * BLOCK_SIZE ? MAX_DESC_LEN : 2 * BLOCK_SIZE) + BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); - int block_size = BLOCK_SIZE; - int m_size = MAX_DESC_LEN; - std::vector< std::pair > args; - - char opt [OPT_SIZE] = ""; - sprintf(opt, - "-D T=%s -D DIST_TYPE=%d -D BLOCK_SIZE=%d -D MAX_DESC_LEN=%d", - T_ARR[query.depth()], distType, block_size, m_size); - - if(globalSize[0] != 0) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&query.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&train.data )); - //args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&trainIdx.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&distance.data )); - args.push_back( std::make_pair( smemSize, (void *)NULL)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.step )); - - String kernelName = "BruteForceMatch_UnrollMatch"; - - openCLExecuteKernel(ctx, &brute_force_match, kernelName, globalSize, localSize, args, -1, -1, opt); - } -} - -template < int BLOCK_SIZE, int MAX_DESC_LEN/*, typename Mask*/ > -void matchUnrolledCached(const oclMat /*query*/, const oclMat * /*trains*/, int /*n*/, const oclMat /*mask*/, - const oclMat &/*bestTrainIdx*/, const oclMat & /*bestImgIdx*/, const oclMat & /*bestDistance*/, int /*distType*/) -{ -} - -template < int BLOCK_SIZE/*, typename Mask*/ > -void match(const oclMat &query, const oclMat &train, const oclMat &/*mask*/, - const oclMat &trainIdx, const oclMat &distance, int distType) -{ - cv::ocl::Context *ctx = query.clCxt; - size_t globalSize[] = {(query.rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; - size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; - const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); - int block_size = BLOCK_SIZE; - std::vector< std::pair > args; - - char opt [OPT_SIZE] = ""; - sprintf(opt, - "-D T=%s -D DIST_TYPE=%d -D BLOCK_SIZE=%d", - T_ARR[query.depth()], distType, block_size); - if(globalSize[0] != 0) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&query.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&train.data )); - //args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&trainIdx.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&distance.data )); - args.push_back( std::make_pair( smemSize, (void *)NULL)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.step )); - - String kernelName = "BruteForceMatch_Match"; - - openCLExecuteKernel(ctx, &brute_force_match, kernelName, globalSize, localSize, args, -1, -1, opt); - } -} - -template < int BLOCK_SIZE/*, typename Mask*/ > -void match(const oclMat /*query*/, const oclMat * /*trains*/, int /*n*/, const oclMat /*mask*/, - const oclMat &/*bestTrainIdx*/, const oclMat & /*bestImgIdx*/, const oclMat & /*bestDistance*/, int /*distType*/) -{ -} - -//radius_matchUnrolledCached -template < int BLOCK_SIZE, int MAX_DESC_LEN/*, typename Mask*/ > -void matchUnrolledCached(const oclMat &query, const oclMat &train, float maxDistance, const oclMat &/*mask*/, - const oclMat &trainIdx, const oclMat &distance, const oclMat &nMatches, int distType) -{ - cv::ocl::Context *ctx = query.clCxt; - size_t globalSize[] = {(train.rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, (query.rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, 1}; - size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; - const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); - int block_size = BLOCK_SIZE; - int m_size = MAX_DESC_LEN; - std::vector< std::pair > args; - - char opt [OPT_SIZE] = ""; - sprintf(opt, - "-D T=%s -D DIST_TYPE=%d -D BLOCK_SIZE=%d -D MAX_DESC_LEN=%d", - T_ARR[query.depth()], distType, block_size, m_size); - - if(globalSize[0] != 0) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&query.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&train.data )); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&maxDistance )); - //args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&trainIdx.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&distance.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&nMatches.data )); - args.push_back( std::make_pair( smemSize, (void *)NULL)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&trainIdx.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&trainIdx.step )); - - String kernelName = "BruteForceMatch_RadiusUnrollMatch"; - - openCLExecuteKernel(ctx, &brute_force_match, kernelName, globalSize, localSize, args, -1, -1, opt); - } -} - -//radius_match -template < int BLOCK_SIZE/*, typename Mask*/ > -void radius_match(const oclMat &query, const oclMat &train, float maxDistance, const oclMat &/*mask*/, - const oclMat &trainIdx, const oclMat &distance, const oclMat &nMatches, int distType) -{ - cv::ocl::Context *ctx = query.clCxt; - size_t globalSize[] = {(train.rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, (query.rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, 1}; - size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; - const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); - int block_size = BLOCK_SIZE; - std::vector< std::pair > args; - - char opt [OPT_SIZE] = ""; - sprintf(opt, - "-D T=%s -D DIST_TYPE=%d -D BLOCK_SIZE=%d", - T_ARR[query.depth()], distType, block_size); - - if(globalSize[0] != 0) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&query.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&train.data )); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&maxDistance )); - //args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&trainIdx.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&distance.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&nMatches.data )); - args.push_back( std::make_pair( smemSize, (void *)NULL)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&trainIdx.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&trainIdx.step )); - - String kernelName = "BruteForceMatch_RadiusMatch"; - - openCLExecuteKernel(ctx, &brute_force_match, kernelName, globalSize, localSize, args, -1, -1, opt); - } -} - -static void matchDispatcher(const oclMat &query, const oclMat &train, const oclMat &mask, - const oclMat &trainIdx, const oclMat &distance, int distType) -{ - const oclMat zeroMask; - const oclMat &tempMask = mask.data ? mask : zeroMask; - bool is_cpu = isCpuDevice(); - if (query.cols <= 64) - { - matchUnrolledCached<16, 64>(query, train, tempMask, trainIdx, distance, distType); - } - else if (query.cols <= 128 && !is_cpu) - { - matchUnrolledCached<16, 128>(query, train, tempMask, trainIdx, distance, distType); - } - else - { - match<16>(query, train, tempMask, trainIdx, distance, distType); - } -} - -static void matchDispatcher(const oclMat &query, const oclMat *trains, int n, const oclMat &mask, - const oclMat &trainIdx, const oclMat &imgIdx, const oclMat &distance, int distType) -{ - const oclMat zeroMask; - const oclMat &tempMask = mask.data ? mask : zeroMask; - bool is_cpu = isCpuDevice(); - if (query.cols <= 64) - { - matchUnrolledCached<16, 64>(query, trains, n, tempMask, trainIdx, imgIdx, distance, distType); - } - else if (query.cols <= 128 && !is_cpu) - { - matchUnrolledCached<16, 128>(query, trains, n, tempMask, trainIdx, imgIdx, distance, distType); - } - else - { - match<16>(query, trains, n, tempMask, trainIdx, imgIdx, distance, distType); - } -} - -//radius matchDispatcher -static void matchDispatcher(const oclMat &query, const oclMat &train, float maxDistance, const oclMat &mask, - const oclMat &trainIdx, const oclMat &distance, const oclMat &nMatches, int distType) -{ - const oclMat zeroMask; - const oclMat &tempMask = mask.data ? mask : zeroMask; - bool is_cpu = isCpuDevice(); - if (query.cols <= 64) - { - matchUnrolledCached<16, 64>(query, train, maxDistance, tempMask, trainIdx, distance, nMatches, distType); - } - else if (query.cols <= 128 && !is_cpu) - { - matchUnrolledCached<16, 128>(query, train, maxDistance, tempMask, trainIdx, distance, nMatches, distType); - } - else - { - radius_match<16>(query, train, maxDistance, tempMask, trainIdx, distance, nMatches, distType); - } -} - -//knn match Dispatcher -template < int BLOCK_SIZE, int MAX_DESC_LEN/*, typename Mask*/ > -void knn_matchUnrolledCached(const oclMat &query, const oclMat &train, const oclMat &/*mask*/, - const oclMat &trainIdx, const oclMat &distance, int distType) -{ - cv::ocl::Context *ctx = query.clCxt; - size_t globalSize[] = {(query.rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; - size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; - const size_t smemSize = (BLOCK_SIZE * (MAX_DESC_LEN >= BLOCK_SIZE ? MAX_DESC_LEN : BLOCK_SIZE) + BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); - int block_size = BLOCK_SIZE; - int m_size = MAX_DESC_LEN; - std::vector< std::pair > args; - - char opt [OPT_SIZE] = ""; - sprintf(opt, - "-D T=%s -D DIST_TYPE=%d -D BLOCK_SIZE=%d -D MAX_DESC_LEN=%d", - T_ARR[query.depth()], distType, block_size, m_size); - - if(globalSize[0] != 0) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&query.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&train.data )); - //args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&trainIdx.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&distance.data )); - args.push_back( std::make_pair( smemSize, (void *)NULL)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.step )); - - String kernelName = "BruteForceMatch_knnUnrollMatch"; - - openCLExecuteKernel(ctx, &brute_force_match, kernelName, globalSize, localSize, args, -1, -1, opt); - } -} - -template < int BLOCK_SIZE/*, typename Mask*/ > -void knn_match(const oclMat &query, const oclMat &train, const oclMat &/*mask*/, - const oclMat &trainIdx, const oclMat &distance, int distType) -{ - cv::ocl::Context *ctx = query.clCxt; - size_t globalSize[] = {(query.rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; - size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; - const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); - int block_size = BLOCK_SIZE; - std::vector< std::pair > args; - - char opt [OPT_SIZE] = ""; - sprintf(opt, - "-D T=%s -D DIST_TYPE=%d -D BLOCK_SIZE=%d", - T_ARR[query.depth()], distType, block_size); - - if(globalSize[0] != 0) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&query.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&train.data )); - //args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&trainIdx.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&distance.data )); - args.push_back( std::make_pair( smemSize, (void *)NULL)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.step )); - - String kernelName = "BruteForceMatch_knnMatch"; - - openCLExecuteKernel(ctx, &brute_force_match, kernelName, globalSize, localSize, args, -1, -1, opt); - } -} - -template < int BLOCK_SIZE, int MAX_DESC_LEN/*, typename Mask*/ > -void calcDistanceUnrolled(const oclMat &query, const oclMat &train, const oclMat &/*mask*/, const oclMat &allDist, int distType) -{ - cv::ocl::Context *ctx = query.clCxt; - size_t globalSize[] = {(query.rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; - size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; - const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); - int block_size = BLOCK_SIZE; - int m_size = MAX_DESC_LEN; - std::vector< std::pair > args; - - char opt [OPT_SIZE] = ""; - sprintf(opt, - "-D T=%s -D DIST_TYPE=%d -D BLOCK_SIZE=%d -D MAX_DESC_LEN=%d", - T_ARR[query.depth()], distType, block_size, m_size); - - if(globalSize[0] != 0) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&query.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&train.data )); - //args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&allDist.data )); - args.push_back( std::make_pair( smemSize, (void *)NULL)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&block_size )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&m_size )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.step )); - - String kernelName = "BruteForceMatch_calcDistanceUnrolled"; - - openCLExecuteKernel(ctx, &brute_force_match, kernelName, globalSize, localSize, args, -1, -1, opt); - } -} - -template < int BLOCK_SIZE/*, typename Mask*/ > -void calcDistance(const oclMat &query, const oclMat &train, const oclMat &/*mask*/, const oclMat &allDist, int distType) -{ - cv::ocl::Context *ctx = query.clCxt; - size_t globalSize[] = {(query.rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, BLOCK_SIZE, 1}; - size_t localSize[] = {BLOCK_SIZE, BLOCK_SIZE, 1}; - const size_t smemSize = (2 * BLOCK_SIZE * BLOCK_SIZE) * sizeof(int); - int block_size = BLOCK_SIZE; - std::vector< std::pair > args; - - char opt [OPT_SIZE] = ""; - sprintf(opt, - "-D T=%s -D DIST_TYPE=%d -D BLOCK_SIZE=%d", - T_ARR[query.depth()], distType, block_size); - - if(globalSize[0] != 0) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&query.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&train.data )); - //args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&allDist.data )); - args.push_back( std::make_pair( smemSize, (void *)NULL)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&block_size )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.step )); - - String kernelName = "BruteForceMatch_calcDistance"; - - openCLExecuteKernel(ctx, &brute_force_match, kernelName, globalSize, localSize, args, -1, -1, opt); - } -} - -/////////////////////////////////////////////////////////////////////////////// -// Calc Distance dispatcher -static void calcDistanceDispatcher(const oclMat &query, const oclMat &train, const oclMat &mask, - const oclMat &allDist, int distType) -{ - if (query.cols <= 64) - { - calcDistanceUnrolled<16, 64>(query, train, mask, allDist, distType); - } - else if (query.cols <= 128) - { - calcDistanceUnrolled<16, 128>(query, train, mask, allDist, distType); - } - else - { - calcDistance<16>(query, train, mask, allDist, distType); - } -} - -static void match2Dispatcher(const oclMat &query, const oclMat &train, const oclMat &mask, - const oclMat &trainIdx, const oclMat &distance, int distType) -{ - bool is_cpu = isCpuDevice(); - if (query.cols <= 64) - { - knn_matchUnrolledCached<16, 64>(query, train, mask, trainIdx, distance, distType); - } - else if (query.cols <= 128 && !is_cpu) - { - knn_matchUnrolledCached<16, 128>(query, train, mask, trainIdx, distance, distType); - } - else - { - knn_match<16>(query, train, mask, trainIdx, distance, distType); - } -} - -template -void findKnnMatch(int k, const oclMat &trainIdx, const oclMat &distance, const oclMat &allDist, int /*distType*/) -{ - cv::ocl::Context *ctx = trainIdx.clCxt; - size_t globalSize[] = {trainIdx.rows * BLOCK_SIZE, 1, 1}; - size_t localSize[] = {BLOCK_SIZE, 1, 1}; - int block_size = BLOCK_SIZE; - String kernelName = "BruteForceMatch_findBestMatch"; - - for (int i = 0; i < k; ++i) - { - std::vector< std::pair > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&allDist.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&trainIdx.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&distance.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&i)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&block_size )); - //args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.rows )); - //args.push_back( std::make_pair( sizeof(cl_int), (void *)&train.cols )); - //args.push_back( std::make_pair( sizeof(cl_int), (void *)&query.step )); - - openCLExecuteKernel(ctx, &brute_force_match, kernelName, globalSize, localSize, args, -1, -1); - } -} - -static void findKnnMatchDispatcher(int k, const oclMat &trainIdx, const oclMat &distance, const oclMat &allDist, int distType) -{ - findKnnMatch<256>(k, trainIdx, distance, allDist, distType); -} - -static void kmatchDispatcher(const oclMat &query, const oclMat &train, int k, const oclMat &mask, - const oclMat &trainIdx, const oclMat &distance, const oclMat &allDist, int distType) -{ - const oclMat zeroMask; - const oclMat &tempMask = mask.data ? mask : zeroMask; - if (k == 2) - { - match2Dispatcher(query, train, tempMask, trainIdx, distance, distType); - } - else - { - calcDistanceDispatcher(query, train, tempMask, allDist, distType); - findKnnMatchDispatcher(k, trainIdx, distance, allDist, distType); - } -} - -cv::ocl::BruteForceMatcher_OCL_base::BruteForceMatcher_OCL_base(DistType distType_) : distType(distType_) -{ -} - -void cv::ocl::BruteForceMatcher_OCL_base::add(const std::vector &descCollection) -{ - trainDescCollection.insert(trainDescCollection.end(), descCollection.begin(), descCollection.end()); -} - -const std::vector &cv::ocl::BruteForceMatcher_OCL_base::getTrainDescriptors() const -{ - return trainDescCollection; -} - -void cv::ocl::BruteForceMatcher_OCL_base::clear() -{ - trainDescCollection.clear(); -} - -bool cv::ocl::BruteForceMatcher_OCL_base::empty() const -{ - return trainDescCollection.empty(); -} - -bool cv::ocl::BruteForceMatcher_OCL_base::isMaskSupported() const -{ - return true; -} - -void cv::ocl::BruteForceMatcher_OCL_base::matchSingle(const oclMat &query, const oclMat &train, - oclMat &trainIdx, oclMat &distance, const oclMat &mask) -{ - if (query.empty() || train.empty()) - return; - - CV_Assert(query.channels() == 1 && query.depth() < CV_64F); - CV_Assert(train.cols == query.cols && train.type() == query.type()); - - ensureSizeIsEnough(1, query.rows, CV_32S, trainIdx); - ensureSizeIsEnough(1, query.rows, CV_32F, distance); - - matchDispatcher(query, train, mask, trainIdx, distance, distType); - - return; -} - -void cv::ocl::BruteForceMatcher_OCL_base::matchDownload(const oclMat &trainIdx, const oclMat &distance, std::vector &matches) -{ - if (trainIdx.empty() || distance.empty()) - return; - - Mat trainIdxCPU(trainIdx); - Mat distanceCPU(distance); - - matchConvert(trainIdxCPU, distanceCPU, matches); -} - -void cv::ocl::BruteForceMatcher_OCL_base::matchConvert(const Mat &trainIdx, const Mat &distance, std::vector &matches) -{ - if (trainIdx.empty() || distance.empty()) - return; - - CV_Assert(trainIdx.type() == CV_32SC1); - CV_Assert(distance.type() == CV_32FC1 && distance.cols == trainIdx.cols); - - const int nQuery = trainIdx.cols; - - matches.clear(); - matches.reserve(nQuery); - - const int *trainIdx_ptr = trainIdx.ptr(); - const float *distance_ptr = distance.ptr(); - for (int queryIdx = 0; queryIdx < nQuery; ++queryIdx, ++trainIdx_ptr, ++distance_ptr) - { - int trainIdx = *trainIdx_ptr; - - if (trainIdx == -1) - continue; - - float distance = *distance_ptr; - - DMatch m(queryIdx, trainIdx, 0, distance); - - matches.push_back(m); - } -} - -void cv::ocl::BruteForceMatcher_OCL_base::match(const oclMat &query, const oclMat &train, std::vector &matches, const oclMat &mask) -{ - CV_Assert(mask.empty()); // mask is not supported at the moment - oclMat trainIdx, distance; - matchSingle(query, train, trainIdx, distance, mask); - matchDownload(trainIdx, distance, matches); -} - -void cv::ocl::BruteForceMatcher_OCL_base::makeGpuCollection(oclMat &trainCollection, oclMat &maskCollection, const std::vector &masks) -{ - - if (empty()) - return; - - if (masks.empty()) - { - Mat trainCollectionCPU(1, static_cast(trainDescCollection.size()), CV_8UC(sizeof(oclMat))); - - oclMat *trainCollectionCPU_ptr = trainCollectionCPU.ptr(); - - for (size_t i = 0, size = trainDescCollection.size(); i < size; ++i, ++trainCollectionCPU_ptr) - *trainCollectionCPU_ptr = trainDescCollection[i]; - - trainCollection.upload(trainCollectionCPU); - maskCollection.release(); - } - else - { - CV_Assert(masks.size() == trainDescCollection.size()); - - Mat trainCollectionCPU(1, static_cast(trainDescCollection.size()), CV_8UC(sizeof(oclMat))); - Mat maskCollectionCPU(1, static_cast(trainDescCollection.size()), CV_8UC(sizeof(oclMat))); - - oclMat *trainCollectionCPU_ptr = trainCollectionCPU.ptr(); - oclMat *maskCollectionCPU_ptr = maskCollectionCPU.ptr(); - - for (size_t i = 0, size = trainDescCollection.size(); i < size; ++i, ++trainCollectionCPU_ptr, ++maskCollectionCPU_ptr) - { - const oclMat &train = trainDescCollection[i]; - const oclMat &mask = masks[i]; - - CV_Assert(mask.empty() || (mask.type() == CV_8UC1 && mask.cols == train.rows)); - - *trainCollectionCPU_ptr = train; - *maskCollectionCPU_ptr = mask; - } - - trainCollection.upload(trainCollectionCPU); - maskCollection.upload(maskCollectionCPU); - } -} - -void cv::ocl::BruteForceMatcher_OCL_base::matchCollection(const oclMat &query, const oclMat &trainCollection, oclMat &trainIdx, - oclMat &imgIdx, oclMat &distance, const oclMat &masks) -{ - if (query.empty() || trainCollection.empty()) - return; - - CV_Assert(query.channels() == 1 && query.depth() < CV_64F); - - const int nQuery = query.rows; - - ensureSizeIsEnough(1, nQuery, CV_32S, trainIdx); - ensureSizeIsEnough(1, nQuery, CV_32S, imgIdx); - ensureSizeIsEnough(1, nQuery, CV_32F, distance); - - matchDispatcher(query, &trainCollection, trainCollection.cols, masks, trainIdx, imgIdx, distance, distType); - - return; -} - -void cv::ocl::BruteForceMatcher_OCL_base::matchDownload(const oclMat &trainIdx, const oclMat &imgIdx, const oclMat &distance, std::vector &matches) -{ - if (trainIdx.empty() || imgIdx.empty() || distance.empty()) - return; - - Mat trainIdxCPU(trainIdx); - Mat imgIdxCPU(imgIdx); - Mat distanceCPU(distance); - - matchConvert(trainIdxCPU, imgIdxCPU, distanceCPU, matches); -} - -void cv::ocl::BruteForceMatcher_OCL_base::matchConvert(const Mat &trainIdx, const Mat &imgIdx, const Mat &distance, std::vector &matches) -{ - if (trainIdx.empty() || imgIdx.empty() || distance.empty()) - return; - - CV_Assert(trainIdx.type() == CV_32SC1); - CV_Assert(imgIdx.type() == CV_32SC1 && imgIdx.cols == trainIdx.cols); - CV_Assert(distance.type() == CV_32FC1 && distance.cols == trainIdx.cols); - - const int nQuery = trainIdx.cols; - - matches.clear(); - matches.reserve(nQuery); - - const int *trainIdx_ptr = trainIdx.ptr(); - const int *imgIdx_ptr = imgIdx.ptr(); - const float *distance_ptr = distance.ptr(); - for (int queryIdx = 0; queryIdx < nQuery; ++queryIdx, ++trainIdx_ptr, ++imgIdx_ptr, ++distance_ptr) - { - int trainIdx = *trainIdx_ptr; - - if (trainIdx == -1) - continue; - - int imgIdx = *imgIdx_ptr; - - float distance = *distance_ptr; - - DMatch m(queryIdx, trainIdx, imgIdx, distance); - - matches.push_back(m); - } -} - -void cv::ocl::BruteForceMatcher_OCL_base::match(const oclMat &query, std::vector &matches, const std::vector &masks) -{ - oclMat trainCollection; - oclMat maskCollection; - - makeGpuCollection(trainCollection, maskCollection, masks); - - oclMat trainIdx, imgIdx, distance; - - matchCollection(query, trainCollection, trainIdx, imgIdx, distance, maskCollection); - matchDownload(trainIdx, imgIdx, distance, matches); -} - -// knn match -void cv::ocl::BruteForceMatcher_OCL_base::knnMatchSingle(const oclMat &query, const oclMat &train, oclMat &trainIdx, - oclMat &distance, oclMat &allDist, int k, const oclMat &mask) -{ - if (query.empty() || train.empty()) - return; - - CV_Assert(query.channels() == 1 && query.depth() < CV_64F); - CV_Assert(train.type() == query.type() && train.cols == query.cols); - - const int nQuery = query.rows; - const int nTrain = train.rows; - - if (k == 2) - { - ensureSizeIsEnough(1, nQuery, CV_32SC2, trainIdx); - ensureSizeIsEnough(1, nQuery, CV_32FC2, distance); - } - else - { - ensureSizeIsEnough(nQuery, k, CV_32S, trainIdx); - ensureSizeIsEnough(nQuery, k, CV_32F, distance); - ensureSizeIsEnough(nQuery, nTrain, CV_32FC1, allDist); - } - - trainIdx.setTo(Scalar::all(-1)); - - kmatchDispatcher(query, train, k, mask, trainIdx, distance, allDist, distType); - - return; -} - -void cv::ocl::BruteForceMatcher_OCL_base::knnMatchDownload(const oclMat &trainIdx, const oclMat &distance, std::vector< std::vector > &matches, bool compactResult) -{ - if (trainIdx.empty() || distance.empty()) - return; - - Mat trainIdxCPU(trainIdx); - Mat distanceCPU(distance); - - knnMatchConvert(trainIdxCPU, distanceCPU, matches, compactResult); -} - -void cv::ocl::BruteForceMatcher_OCL_base::knnMatchConvert(const Mat &trainIdx, const Mat &distance, std::vector< std::vector > &matches, bool compactResult) -{ - if (trainIdx.empty() || distance.empty()) - return; - - CV_Assert(trainIdx.type() == CV_32SC2 || trainIdx.type() == CV_32SC1); - CV_Assert(distance.type() == CV_32FC2 || distance.type() == CV_32FC1); - CV_Assert(distance.size() == trainIdx.size()); - CV_Assert(trainIdx.isContinuous() && distance.isContinuous()); - - const int nQuery = trainIdx.type() == CV_32SC2 ? trainIdx.cols : trainIdx.rows; - const int k = trainIdx.type() == CV_32SC2 ? 2 : trainIdx.cols; - - matches.clear(); - matches.reserve(nQuery); - - const int *trainIdx_ptr = trainIdx.ptr(); - const float *distance_ptr = distance.ptr(); - - for (int queryIdx = 0; queryIdx < nQuery; ++queryIdx) - { - matches.push_back(std::vector()); - std::vector &curMatches = matches.back(); - curMatches.reserve(k); - - for (int i = 0; i < k; ++i, ++trainIdx_ptr, ++distance_ptr) - { - int trainIdx = *trainIdx_ptr; - - if (trainIdx != -1) - { - float distance = *distance_ptr; - - DMatch m(queryIdx, trainIdx, 0, distance); - - curMatches.push_back(m); - } - } - - if (compactResult && curMatches.empty()) - matches.pop_back(); - } -} - -void cv::ocl::BruteForceMatcher_OCL_base::knnMatch(const oclMat &query, const oclMat &train, std::vector< std::vector > &matches - , int k, const oclMat &mask, bool compactResult) -{ - oclMat trainIdx, distance, allDist; - knnMatchSingle(query, train, trainIdx, distance, allDist, k, mask); - knnMatchDownload(trainIdx, distance, matches, compactResult); -} - -void cv::ocl::BruteForceMatcher_OCL_base::knnMatch2Collection(const oclMat &query, const oclMat &trainCollection, - oclMat &trainIdx, oclMat &imgIdx, oclMat &distance, const oclMat &/*maskCollection*/) -{ - if (query.empty() || trainCollection.empty()) - return; - - // typedef void (*caller_t)(const oclMat & query, const oclMat & trains, const oclMat & masks, - // const oclMat & trainIdx, const oclMat & imgIdx, const oclMat & distance); - - CV_Assert(query.channels() == 1 && query.depth() < CV_64F); - - const int nQuery = query.rows; - - ensureSizeIsEnough(1, nQuery, CV_32SC2, trainIdx); - ensureSizeIsEnough(1, nQuery, CV_32SC2, imgIdx); - ensureSizeIsEnough(1, nQuery, CV_32FC2, distance); - - trainIdx.setTo(Scalar::all(-1)); - - //caller_t func = callers[distType][query.depth()]; - //CV_Assert(func != 0); - - //func(query, trainCollection, maskCollection, trainIdx, imgIdx, distance, cc, StreamAccessor::getStream(stream)); -} - -void cv::ocl::BruteForceMatcher_OCL_base::knnMatch2Download(const oclMat &trainIdx, const oclMat &imgIdx, - const oclMat &distance, std::vector< std::vector > &matches, bool compactResult) -{ - if (trainIdx.empty() || imgIdx.empty() || distance.empty()) - return; - - Mat trainIdxCPU(trainIdx); - Mat imgIdxCPU(imgIdx); - Mat distanceCPU(distance); - - knnMatch2Convert(trainIdxCPU, imgIdxCPU, distanceCPU, matches, compactResult); -} - -void cv::ocl::BruteForceMatcher_OCL_base::knnMatch2Convert(const Mat &trainIdx, const Mat &imgIdx, const Mat &distance, - std::vector< std::vector > &matches, bool compactResult) -{ - if (trainIdx.empty() || imgIdx.empty() || distance.empty()) - return; - - CV_Assert(trainIdx.type() == CV_32SC2); - CV_Assert(imgIdx.type() == CV_32SC2 && imgIdx.cols == trainIdx.cols); - CV_Assert(distance.type() == CV_32FC2 && distance.cols == trainIdx.cols); - - const int nQuery = trainIdx.cols; - - matches.clear(); - matches.reserve(nQuery); - - const int *trainIdx_ptr = trainIdx.ptr(); - const int *imgIdx_ptr = imgIdx.ptr(); - const float *distance_ptr = distance.ptr(); - - for (int queryIdx = 0; queryIdx < nQuery; ++queryIdx) - { - matches.push_back(std::vector()); - std::vector &curMatches = matches.back(); - curMatches.reserve(2); - - for (int i = 0; i < 2; ++i, ++trainIdx_ptr, ++imgIdx_ptr, ++distance_ptr) - { - int trainIdx = *trainIdx_ptr; - - if (trainIdx != -1) - { - int imgIdx = *imgIdx_ptr; - - float distance = *distance_ptr; - - DMatch m(queryIdx, trainIdx, imgIdx, distance); - - curMatches.push_back(m); - } - } - - if (compactResult && curMatches.empty()) - matches.pop_back(); - } -} - -namespace -{ - struct ImgIdxSetter - { - explicit inline ImgIdxSetter(int imgIdx_) : imgIdx(imgIdx_) {} - inline void operator()(DMatch &m) const - { - m.imgIdx = imgIdx; - } - int imgIdx; - }; -} - -void cv::ocl::BruteForceMatcher_OCL_base::knnMatch(const oclMat &query, std::vector< std::vector > &matches, int k, - const std::vector &masks, bool compactResult) -{ - if (k == 2) - { - oclMat trainCollection; - oclMat maskCollection; - - makeGpuCollection(trainCollection, maskCollection, masks); - - oclMat trainIdx, imgIdx, distance; - - knnMatch2Collection(query, trainCollection, trainIdx, imgIdx, distance, maskCollection); - knnMatch2Download(trainIdx, imgIdx, distance, matches); - } - else - { - if (query.empty() || empty()) - return; - - std::vector< std::vector > curMatches; - std::vector temp; - temp.reserve(2 * k); - - matches.resize(query.rows); - for_each(matches.begin(), matches.end(), bind2nd(mem_fun_ref(&std::vector::reserve), k)); - - for (size_t imgIdx = 0, size = trainDescCollection.size(); imgIdx < size; ++imgIdx) - { - knnMatch(query, trainDescCollection[imgIdx], curMatches, k, masks.empty() ? oclMat() : masks[imgIdx]); - - for (int queryIdx = 0; queryIdx < query.rows; ++queryIdx) - { - std::vector &localMatch = curMatches[queryIdx]; - std::vector &globalMatch = matches[queryIdx]; - - std::for_each(localMatch.begin(), localMatch.end(), ImgIdxSetter(static_cast(imgIdx))); - - temp.clear(); - std::merge(globalMatch.begin(), globalMatch.end(), localMatch.begin(), localMatch.end(), back_inserter(temp)); - - globalMatch.clear(); - const size_t count = std::min((size_t)k, temp.size()); - std::copy(temp.begin(), temp.begin() + count, back_inserter(globalMatch)); - } - } - - if (compactResult) - { - std::vector< std::vector >::iterator new_end = remove_if(matches.begin(), matches.end(), mem_fun_ref(&std::vector::empty)); - matches.erase(new_end, matches.end()); - } - } -} - -// radiusMatchSingle -void cv::ocl::BruteForceMatcher_OCL_base::radiusMatchSingle(const oclMat &query, const oclMat &train, - oclMat &trainIdx, oclMat &distance, oclMat &nMatches, float maxDistance, const oclMat &mask) -{ - if (query.empty() || train.empty()) - return; - - const int nQuery = query.rows; - const int nTrain = train.rows; - - CV_Assert(query.channels() == 1 && query.depth() < CV_64F); - CV_Assert(train.type() == query.type() && train.cols == query.cols); - CV_Assert(trainIdx.empty() || (trainIdx.rows == query.rows && trainIdx.size() == distance.size())); - - ensureSizeIsEnough(1, nQuery, CV_32SC1, nMatches); - if (trainIdx.empty()) - { - ensureSizeIsEnough(nQuery, std::max((nTrain / 100), 10), CV_32SC1, trainIdx); - ensureSizeIsEnough(nQuery, std::max((nTrain / 100), 10), CV_32FC1, distance); - } - - nMatches.setTo(Scalar::all(0)); - - matchDispatcher(query, train, maxDistance, mask, trainIdx, distance, nMatches, distType); - - return; -} - -void cv::ocl::BruteForceMatcher_OCL_base::radiusMatchDownload(const oclMat &trainIdx, const oclMat &distance, const oclMat &nMatches, - std::vector< std::vector > &matches, bool compactResult) -{ - if (trainIdx.empty() || distance.empty() || nMatches.empty()) - return; - - Mat trainIdxCPU(trainIdx); - Mat distanceCPU(distance); - Mat nMatchesCPU(nMatches); - - radiusMatchConvert(trainIdxCPU, distanceCPU, nMatchesCPU, matches, compactResult); -} - -void cv::ocl::BruteForceMatcher_OCL_base::radiusMatchConvert(const Mat &trainIdx, const Mat &distance, const Mat &nMatches, - std::vector< std::vector > &matches, bool compactResult) -{ - if (trainIdx.empty() || distance.empty() || nMatches.empty()) - return; - - CV_Assert(trainIdx.type() == CV_32SC1); - CV_Assert(distance.type() == CV_32FC1 && distance.size() == trainIdx.size()); - CV_Assert(nMatches.type() == CV_32SC1 && nMatches.cols == trainIdx.rows); - - const int nQuery = trainIdx.rows; - - matches.clear(); - matches.reserve(nQuery); - - const int *nMatches_ptr = nMatches.ptr(); - - for (int queryIdx = 0; queryIdx < nQuery; ++queryIdx) - { - const int *trainIdx_ptr = trainIdx.ptr(queryIdx); - const float *distance_ptr = distance.ptr(queryIdx); - - const int nMatches = std::min(nMatches_ptr[queryIdx], trainIdx.cols); - - if (nMatches == 0) - { - if (!compactResult) - matches.push_back(std::vector()); - continue; - } - - matches.push_back(std::vector(nMatches)); - std::vector &curMatches = matches.back(); - - for (int i = 0; i < nMatches; ++i, ++trainIdx_ptr, ++distance_ptr) - { - int trainIdx = *trainIdx_ptr; - - float distance = *distance_ptr; - - DMatch m(queryIdx, trainIdx, 0, distance); - - curMatches[i] = m; - } - - std::sort(curMatches.begin(), curMatches.end()); - } -} - -void cv::ocl::BruteForceMatcher_OCL_base::radiusMatch(const oclMat &query, const oclMat &train, std::vector< std::vector > &matches, - float maxDistance, const oclMat &mask, bool compactResult) -{ - oclMat trainIdx, distance, nMatches; - radiusMatchSingle(query, train, trainIdx, distance, nMatches, maxDistance, mask); - radiusMatchDownload(trainIdx, distance, nMatches, matches, compactResult); -} - -void cv::ocl::BruteForceMatcher_OCL_base::radiusMatchCollection(const oclMat &query, oclMat &trainIdx, oclMat &imgIdx, oclMat &distance, - oclMat &nMatches, float /*maxDistance*/, const std::vector &masks) -{ - if (query.empty() || empty()) - return; - -#if 0 - typedef void (*caller_t)(const oclMat & query, const oclMat * trains, int n, float maxDistance, const oclMat * masks, - const oclMat & trainIdx, const oclMat & imgIdx, const oclMat & distance, const oclMat & nMatches); - static const caller_t callers[3][6] = - { - { - ocl_matchL1_gpu, 0/*matchL1_gpu*/, - ocl_matchL1_gpu, matchL1_gpu, - ocl_matchL1_gpu, matchL1_gpu - }, - { - 0/*matchL2_gpu*/, 0/*matchL2_gpu*/, - 0/*matchL2_gpu*/, 0/*matchL2_gpu*/, - 0/*matchL2_gpu*/, ocl_matchL2_gpu - }, - { - ocl_matchHamming_gpu, 0/*matchHamming_gpu*/, - ocl_matchHamming_gpu, 0/*matchHamming_gpu*/, - ocl_matchHamming_gpu, 0/*matchHamming_gpu*/ - } - }; -#endif - const int nQuery = query.rows; - - CV_Assert(query.channels() == 1 && query.depth() < CV_64F); - CV_Assert(trainIdx.empty() || (trainIdx.rows == nQuery && trainIdx.size() == distance.size() && trainIdx.size() == imgIdx.size())); - - nMatches.create(1, nQuery, CV_32SC1); - if (trainIdx.empty()) - { - trainIdx.create(nQuery, std::max((nQuery / 100), 10), CV_32SC1); - imgIdx.create(nQuery, std::max((nQuery / 100), 10), CV_32SC1); - distance.create(nQuery, std::max((nQuery / 100), 10), CV_32FC1); - } - - nMatches.setTo(Scalar::all(0)); - - //caller_t func = callers[distType][query.depth()]; - //CV_Assert(func != 0); - - std::vector trains_(trainDescCollection.begin(), trainDescCollection.end()); - std::vector masks_(masks.begin(), masks.end()); - - /* func(query, &trains_[0], static_cast(trains_.size()), maxDistance, masks_.size() == 0 ? 0 : &masks_[0], - trainIdx, imgIdx, distance, nMatches));*/ -} - -void cv::ocl::BruteForceMatcher_OCL_base::radiusMatchDownload(const oclMat &trainIdx, const oclMat &imgIdx, const oclMat &distance, - const oclMat &nMatches, std::vector< std::vector > &matches, bool compactResult) -{ - if (trainIdx.empty() || imgIdx.empty() || distance.empty() || nMatches.empty()) - return; - - Mat trainIdxCPU(trainIdx); - Mat imgIdxCPU(imgIdx); - Mat distanceCPU(distance); - Mat nMatchesCPU(nMatches); - - radiusMatchConvert(trainIdxCPU, imgIdxCPU, distanceCPU, nMatchesCPU, matches, compactResult); -} - -void cv::ocl::BruteForceMatcher_OCL_base::radiusMatchConvert(const Mat &trainIdx, const Mat &imgIdx, const Mat &distance, const Mat &nMatches, - std::vector< std::vector > &matches, bool compactResult) -{ - if (trainIdx.empty() || imgIdx.empty() || distance.empty() || nMatches.empty()) - return; - - CV_Assert(trainIdx.type() == CV_32SC1); - CV_Assert(imgIdx.type() == CV_32SC1 && imgIdx.size() == trainIdx.size()); - CV_Assert(distance.type() == CV_32FC1 && distance.size() == trainIdx.size()); - CV_Assert(nMatches.type() == CV_32SC1 && nMatches.cols == trainIdx.rows); - - const int nQuery = trainIdx.rows; - - matches.clear(); - matches.reserve(nQuery); - - const int *nMatches_ptr = nMatches.ptr(); - - for (int queryIdx = 0; queryIdx < nQuery; ++queryIdx) - { - const int *trainIdx_ptr = trainIdx.ptr(queryIdx); - const int *imgIdx_ptr = imgIdx.ptr(queryIdx); - const float *distance_ptr = distance.ptr(queryIdx); - - const int nMatches = std::min(nMatches_ptr[queryIdx], trainIdx.cols); - - if (nMatches == 0) - { - if (!compactResult) - matches.push_back(std::vector()); - continue; - } - - matches.push_back(std::vector()); - std::vector &curMatches = matches.back(); - curMatches.reserve(nMatches); - - for (int i = 0; i < nMatches; ++i, ++trainIdx_ptr, ++imgIdx_ptr, ++distance_ptr) - { - int trainIdx = *trainIdx_ptr; - int imgIdx = *imgIdx_ptr; - float distance = *distance_ptr; - - DMatch m(queryIdx, trainIdx, imgIdx, distance); - - curMatches.push_back(m); - } - - std::sort(curMatches.begin(), curMatches.end()); - } -} - -void cv::ocl::BruteForceMatcher_OCL_base::radiusMatch(const oclMat &query, std::vector< std::vector > &matches, float maxDistance, - const std::vector &masks, bool compactResult) -{ - oclMat trainIdx, imgIdx, distance, nMatches; - radiusMatchCollection(query, trainIdx, imgIdx, distance, nMatches, maxDistance, masks); - radiusMatchDownload(trainIdx, imgIdx, distance, nMatches, matches, compactResult); -} diff --git a/modules/ocl/src/build_warps.cpp b/modules/ocl/src/build_warps.cpp deleted file mode 100644 index 011672847..000000000 --- a/modules/ocl/src/build_warps.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -////////////////////////////////////////////////////////////////////////////// -// buildWarpPlaneMaps - -void cv::ocl::buildWarpPlaneMaps(Size /*src_size*/, Rect dst_roi, const Mat &K, const Mat &R, const Mat &T, - float scale, oclMat &xmap, oclMat &ymap) -{ - CV_Assert(K.size() == Size(3, 3) && K.type() == CV_32F); - CV_Assert(R.size() == Size(3, 3) && R.type() == CV_32F); - CV_Assert((T.size() == Size(3, 1) || T.size() == Size(1, 3)) && T.type() == CV_32F && T.isContinuous()); - - Mat K_Rinv = K * R.t(); - CV_Assert(K_Rinv.isContinuous()); - - Mat KRT_mat(1, 12, CV_32FC1); // 9 + 3 - KRT_mat(Range::all(), Range(0, 8)) = K_Rinv.reshape(1, 1); - KRT_mat(Range::all(), Range(9, 11)) = T; - - oclMat KRT_oclMat(KRT_mat); - // transfer K_Rinv and T into a single cl_mem - xmap.create(dst_roi.size(), CV_32F); - ymap.create(dst_roi.size(), CV_32F); - - int tl_u = dst_roi.tl().x; - int tl_v = dst_roi.tl().y; - - int xmap_step = xmap.step / xmap.elemSize(), xmap_offset = xmap.offset / xmap.elemSize(); - int ymap_step = ymap.step / ymap.elemSize(), ymap_offset = ymap.offset / ymap.elemSize(); - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&xmap.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&ymap.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&KRT_mat.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&tl_u)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&tl_v)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&ymap_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap_offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&ymap_offset)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&scale)); - - size_t globalThreads[3] = { xmap.cols, xmap.rows, 1 }; -#ifdef ANDROID - size_t localThreads[3] = {32, 4, 1}; -#else - size_t localThreads[3] = {32, 8, 1}; -#endif - openCLExecuteKernel(Context::getContext(), &build_warps, "buildWarpPlaneMaps", globalThreads, localThreads, args, -1, -1); -} - -////////////////////////////////////////////////////////////////////////////// -// buildWarpCylyndricalMaps - -void cv::ocl::buildWarpCylindricalMaps(Size /*src_size*/, Rect dst_roi, const Mat &K, const Mat &R, float scale, - oclMat &xmap, oclMat &ymap) -{ - CV_Assert(K.size() == Size(3, 3) && K.type() == CV_32F); - CV_Assert(R.size() == Size(3, 3) && R.type() == CV_32F); - - Mat K_Rinv = K * R.t(); - CV_Assert(K_Rinv.isContinuous()); - - oclMat KR_oclMat(K_Rinv.reshape(1, 1)); - - xmap.create(dst_roi.size(), CV_32F); - ymap.create(dst_roi.size(), CV_32F); - - int tl_u = dst_roi.tl().x; - int tl_v = dst_roi.tl().y; - - int xmap_step = xmap.step / xmap.elemSize(), xmap_offset = xmap.offset / xmap.elemSize(); - int ymap_step = ymap.step / ymap.elemSize(), ymap_offset = ymap.offset / ymap.elemSize(); - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&xmap.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&ymap.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&KR_oclMat.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&tl_u)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&tl_v)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&ymap_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap_offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&ymap_offset)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&scale)); - - size_t globalThreads[3] = { xmap.cols, xmap.rows, 1 }; -#ifdef ANDROID - size_t localThreads[3] = {32, 1, 1}; -#else - size_t localThreads[3] = {32, 8, 1}; -#endif - openCLExecuteKernel(Context::getContext(), &build_warps, "buildWarpCylindricalMaps", globalThreads, localThreads, args, -1, -1); -} - -////////////////////////////////////////////////////////////////////////////// -// buildWarpSphericalMaps - -void cv::ocl::buildWarpSphericalMaps(Size /*src_size*/, Rect dst_roi, const Mat &K, const Mat &R, float scale, - oclMat &xmap, oclMat &ymap) -{ - CV_Assert(K.size() == Size(3, 3) && K.type() == CV_32F); - CV_Assert(R.size() == Size(3, 3) && R.type() == CV_32F); - - Mat K_Rinv = K * R.t(); - CV_Assert(K_Rinv.isContinuous()); - - oclMat KR_oclMat(K_Rinv.reshape(1, 1)); - // transfer K_Rinv, R_Kinv into a single cl_mem - xmap.create(dst_roi.size(), CV_32F); - ymap.create(dst_roi.size(), CV_32F); - - int tl_u = dst_roi.tl().x; - int tl_v = dst_roi.tl().y; - - int xmap_step = xmap.step / xmap.elemSize(), xmap_offset = xmap.offset / xmap.elemSize(); - int ymap_step = ymap.step / ymap.elemSize(), ymap_offset = ymap.offset / ymap.elemSize(); - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&xmap.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&ymap.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&KR_oclMat.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&tl_u)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&tl_v)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&ymap_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap_offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&ymap_offset)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&scale)); - - size_t globalThreads[3] = { xmap.cols, xmap.rows, 1 }; -#ifdef ANDROID - size_t localThreads[3] = {32, 4, 1}; -#else - size_t localThreads[3] = {32, 8, 1}; -#endif - openCLExecuteKernel(Context::getContext(), &build_warps, "buildWarpSphericalMaps", globalThreads, localThreads, args, -1, -1); -} - -////////////////////////////////////////////////////////////////////////////// -// buildWarpAffineMaps - -void cv::ocl::buildWarpAffineMaps(const Mat &M, bool inverse, Size dsize, oclMat &xmap, oclMat &ymap) -{ - CV_Assert(M.rows == 2 && M.cols == 3); - CV_Assert(dsize.area()); - - xmap.create(dsize, CV_32FC1); - ymap.create(dsize, CV_32FC1); - - float coeffs[2 * 3]; - Mat coeffsMat(2, 3, CV_32F, (void *)coeffs); - - if (inverse) - M.convertTo(coeffsMat, coeffsMat.type()); - else - { - cv::Mat iM; - invertAffineTransform(M, iM); - iM.convertTo(coeffsMat, coeffsMat.type()); - } - - int xmap_step = xmap.step / xmap.elemSize(), xmap_offset = xmap.offset / xmap.elemSize(); - int ymap_step = ymap.step / ymap.elemSize(), ymap_offset = ymap.offset / ymap.elemSize(); - - oclMat coeffsOclMat(coeffsMat.reshape(1, 1)); - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&xmap.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&ymap.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&coeffsOclMat.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&ymap_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap_offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&ymap_offset)); - - size_t globalThreads[3] = { xmap.cols, xmap.rows, 1 }; -#ifdef ANDROID - size_t localThreads[3] = {32, 4, 1}; -#else - size_t localThreads[3] = {32, 8, 1}; -#endif - openCLExecuteKernel(Context::getContext(), &build_warps, "buildWarpAffineMaps", globalThreads, localThreads, args, -1, -1); -} - -////////////////////////////////////////////////////////////////////////////// -// buildWarpPerspectiveMaps - -void cv::ocl::buildWarpPerspectiveMaps(const Mat &M, bool inverse, Size dsize, oclMat &xmap, oclMat &ymap) -{ - CV_Assert(M.rows == 3 && M.cols == 3); - CV_Assert(dsize.area() > 0); - - xmap.create(dsize, CV_32FC1); - ymap.create(dsize, CV_32FC1); - - float coeffs[3 * 3]; - Mat coeffsMat(3, 3, CV_32F, (void *)coeffs); - - if (inverse) - M.convertTo(coeffsMat, coeffsMat.type()); - else - { - cv::Mat iM; - invert(M, iM); - iM.convertTo(coeffsMat, coeffsMat.type()); - } - - oclMat coeffsOclMat(coeffsMat.reshape(1, 1)); - - int xmap_step = xmap.step / xmap.elemSize(), xmap_offset = xmap.offset / xmap.elemSize(); - int ymap_step = ymap.step / ymap.elemSize(), ymap_offset = ymap.offset / ymap.elemSize(); - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&xmap.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&ymap.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&coeffsOclMat.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&ymap_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&xmap_offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&ymap_offset)); - - size_t globalThreads[3] = { xmap.cols, xmap.rows, 1 }; - - openCLExecuteKernel(Context::getContext(), &build_warps, "buildWarpPerspectiveMaps", globalThreads, NULL, args, -1, -1); -} diff --git a/modules/ocl/src/canny.cpp b/modules/ocl/src/canny.cpp deleted file mode 100644 index 8c68d8bac..000000000 --- a/modules/ocl/src/canny.cpp +++ /dev/null @@ -1,387 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -cv::ocl::CannyBuf::CannyBuf(const oclMat &dx_, const oclMat &dy_) : dx(dx_), dy(dy_), counter(1, 1, CV_32SC1) -{ - CV_Assert(dx_.type() == CV_32SC1 && dy_.type() == CV_32SC1 && dx_.size() == dy_.size()); - - create(dx_.size(), -1); -} - -void cv::ocl::CannyBuf::create(const Size &image_size, int apperture_size) -{ - ensureSizeIsEnough(image_size, CV_32SC1, dx); - ensureSizeIsEnough(image_size, CV_32SC1, dy); - - if(apperture_size == 3) - { - ensureSizeIsEnough(image_size, CV_32SC1, dx_buf); - ensureSizeIsEnough(image_size, CV_32SC1, dy_buf); - } - else if(apperture_size > 0) - { - Mat kx, ky; - if (!filterDX) - { - filterDX = createDerivFilter_GPU(CV_8U, CV_32S, 1, 0, apperture_size, BORDER_REPLICATE); - } - if (!filterDY) - { - filterDY = createDerivFilter_GPU(CV_8U, CV_32S, 0, 1, apperture_size, BORDER_REPLICATE); - } - } - ensureSizeIsEnough(image_size.height + 2, image_size.width + 2, CV_32FC1, magBuf); - ensureSizeIsEnough(image_size.height + 2, image_size.width + 2, CV_32FC1, mapBuf); - - ensureSizeIsEnough(1, image_size.area(), CV_16UC2, trackBuf1); - ensureSizeIsEnough(1, image_size.area(), CV_16UC2, trackBuf2); -} - -void cv::ocl::CannyBuf::release() -{ - dx.release(); - dy.release(); - dx_buf.release(); - dy_buf.release(); - magBuf.release(); - mapBuf.release(); - trackBuf1.release(); - trackBuf2.release(); -} - -namespace cv -{ - namespace ocl - { - namespace canny - { - void calcSobelRowPass_gpu(const oclMat &src, oclMat &dx_buf, oclMat &dy_buf, int rows, int cols); - - void calcMagnitude_gpu(const oclMat &dx_buf, const oclMat &dy_buf, oclMat &dx, oclMat &dy, oclMat &mag, int rows, int cols, bool L2Grad); - void calcMagnitude_gpu(const oclMat &dx, const oclMat &dy, oclMat &mag, int rows, int cols, bool L2Grad); - - void calcMap_gpu(oclMat &dx, oclMat &dy, oclMat &mag, oclMat &map, int rows, int cols, float low_thresh, float high_thresh); - - void edgesHysteresisLocal_gpu(oclMat &map, oclMat &st1, oclMat& counter, int rows, int cols); - - void edgesHysteresisGlobal_gpu(oclMat &map, oclMat &st1, oclMat &st2, oclMat& counter, int rows, int cols); - - void getEdges_gpu(oclMat &map, oclMat &dst, int rows, int cols); - } - } -}// cv::ocl - -namespace -{ - void CannyCaller(CannyBuf &buf, oclMat &dst, float low_thresh, float high_thresh) - { - using namespace ::cv::ocl::canny; - calcMap_gpu(buf.dx, buf.dy, buf.magBuf, buf.mapBuf, dst.rows, dst.cols, low_thresh, high_thresh); - - edgesHysteresisLocal_gpu(buf.mapBuf, buf.trackBuf1, buf.counter, dst.rows, dst.cols); - - edgesHysteresisGlobal_gpu(buf.mapBuf, buf.trackBuf1, buf.trackBuf2, buf.counter, dst.rows, dst.cols); - - getEdges_gpu(buf.mapBuf, dst, dst.rows, dst.cols); - } -} - -void cv::ocl::Canny(const oclMat &src, oclMat &dst, double low_thresh, double high_thresh, int apperture_size, bool L2gradient) -{ - CannyBuf buf(src.size(), apperture_size); - Canny(src, buf, dst, low_thresh, high_thresh, apperture_size, L2gradient); -} - -void cv::ocl::Canny(const oclMat &src, CannyBuf &buf, oclMat &dst, double low_thresh, double high_thresh, int apperture_size, bool L2gradient) -{ - using namespace ::cv::ocl::canny; - - CV_Assert(src.type() == CV_8UC1); - - if( low_thresh > high_thresh ) - std::swap( low_thresh, high_thresh ); - - dst.create(src.size(), CV_8U); - dst.setTo(Scalar::all(0)); - - buf.create(src.size(), apperture_size); - buf.magBuf.setTo(Scalar::all(0)); - - if (apperture_size == 3) - { - calcSobelRowPass_gpu(src, buf.dx_buf, buf.dy_buf, src.rows, src.cols); - - calcMagnitude_gpu(buf.dx_buf, buf.dy_buf, buf.dx, buf.dy, buf.magBuf, src.rows, src.cols, L2gradient); - } - else - { - buf.filterDX->apply(src, buf.dx); - buf.filterDY->apply(src, buf.dy); - - calcMagnitude_gpu(buf.dx, buf.dy, buf.magBuf, src.rows, src.cols, L2gradient); - } - CannyCaller(buf, dst, static_cast(low_thresh), static_cast(high_thresh)); -} -void cv::ocl::Canny(const oclMat &dx, const oclMat &dy, oclMat &dst, double low_thresh, double high_thresh, bool L2gradient) -{ - CannyBuf buf(dx, dy); - Canny(dx, dy, buf, dst, low_thresh, high_thresh, L2gradient); -} - -void cv::ocl::Canny(const oclMat &dx, const oclMat &dy, CannyBuf &buf, oclMat &dst, double low_thresh, double high_thresh, bool L2gradient) -{ - using namespace ::cv::ocl::canny; - - CV_Assert(dx.type() == CV_32SC1 && dy.type() == CV_32SC1 && dx.size() == dy.size()); - - if( low_thresh > high_thresh ) - std::swap( low_thresh, high_thresh); - - dst.create(dx.size(), CV_8U); - dst.setTo(Scalar::all(0)); - - buf.dx = dx; - buf.dy = dy; - buf.create(dx.size(), -1); - buf.magBuf.setTo(Scalar::all(0)); - calcMagnitude_gpu(buf.dx, buf.dy, buf.magBuf, dx.rows, dx.cols, L2gradient); - - CannyCaller(buf, dst, static_cast(low_thresh), static_cast(high_thresh)); -} - -void canny::calcSobelRowPass_gpu(const oclMat &src, oclMat &dx_buf, oclMat &dy_buf, int rows, int cols) -{ - Context *clCxt = src.clCxt; - String kernelName = "calcSobelRowPass"; - std::vector< std::pair > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dx_buf.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dy_buf.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dx_buf.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dx_buf.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dy_buf.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dy_buf.offset)); - - size_t globalThreads[3] = {cols, rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - openCLExecuteKernel(clCxt, &imgproc_canny, kernelName, globalThreads, localThreads, args, -1, -1); -} - -void canny::calcMagnitude_gpu(const oclMat &dx_buf, const oclMat &dy_buf, oclMat &dx, oclMat &dy, oclMat &mag, int rows, int cols, bool L2Grad) -{ - Context *clCxt = dx_buf.clCxt; - String kernelName = "calcMagnitude_buf"; - std::vector< std::pair > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dx_buf.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dy_buf.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dx.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dy.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mag.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dx_buf.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dx_buf.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dy_buf.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dy_buf.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dx.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dx.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dy.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dy.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mag.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mag.offset)); - - size_t globalThreads[3] = {cols, rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - - const char * build_options = L2Grad ? "-D L2GRAD":""; - openCLExecuteKernel(clCxt, &imgproc_canny, kernelName, globalThreads, localThreads, args, -1, -1, build_options); -} -void canny::calcMagnitude_gpu(const oclMat &dx, const oclMat &dy, oclMat &mag, int rows, int cols, bool L2Grad) -{ - Context *clCxt = dx.clCxt; - String kernelName = "calcMagnitude"; - std::vector< std::pair > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dx.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dy.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mag.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dx.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dx.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dy.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dy.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mag.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mag.offset)); - - size_t globalThreads[3] = {cols, rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - - const char * build_options = L2Grad ? "-D L2GRAD":""; - openCLExecuteKernel(clCxt, &imgproc_canny, kernelName, globalThreads, localThreads, args, -1, -1, build_options); -} - -void canny::calcMap_gpu(oclMat &dx, oclMat &dy, oclMat &mag, oclMat &map, int rows, int cols, float low_thresh, float high_thresh) -{ - Context *clCxt = dx.clCxt; - - std::vector< std::pair > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dx.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dy.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mag.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&map.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&low_thresh)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&high_thresh)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dx.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dx.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dy.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dy.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mag.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mag.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&map.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&map.offset)); - - - size_t globalThreads[3] = {cols, rows, 1}; - String kernelName = "calcMap"; - size_t localThreads[3] = {16, 16, 1}; - - openCLExecuteKernel(clCxt, &imgproc_canny, kernelName, globalThreads, localThreads, args, -1, -1); -} - -void canny::edgesHysteresisLocal_gpu(oclMat &map, oclMat &st1, oclMat& counter, int rows, int cols) -{ - Context *clCxt = map.clCxt; - std::vector< std::pair > args; - - Mat counterMat(counter.rows, counter.cols, counter.type()); - counterMat.at(0, 0) = 0; - counter.upload(counterMat); - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&map.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&st1.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&counter.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols)); - cl_int stepBytes = map.step; - args.push_back( std::make_pair( sizeof(cl_int), (void *)&stepBytes)); - cl_int offsetBytes = map.offset; - args.push_back( std::make_pair( sizeof(cl_int), (void *)&offsetBytes)); - - size_t globalThreads[3] = {cols, rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - - openCLExecuteKernel(clCxt, &imgproc_canny, "edgesHysteresisLocal", globalThreads, localThreads, args, -1, -1); -} - -void canny::edgesHysteresisGlobal_gpu(oclMat &map, oclMat &st1, oclMat &st2, oclMat& counter, int rows, int cols) -{ - Context *clCxt = map.clCxt; - std::vector< std::pair > args; - size_t localThreads[3] = {128, 1, 1}; - - while(1 > 0) - { - Mat counterMat; counter.download(counterMat); - int count = counterMat.at(0, 0); - CV_Assert(count >= 0); - if (count == 0) - break; - - counterMat.at(0, 0) = 0; - counter.upload(counterMat); - - args.clear(); - size_t globalThreads[3] = {std::min((unsigned)count, 65535u) * 128, divUp(count, 65535), 1}; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&map.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&st1.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&st2.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&counter.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&count)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&map.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&map.offset)); - - openCLExecuteKernel(clCxt, &imgproc_canny, "edgesHysteresisGlobal", globalThreads, localThreads, args, -1, -1); - std::swap(st1, st2); - } -} - -void canny::getEdges_gpu(oclMat &map, oclMat &dst, int rows, int cols) -{ - Context *clCxt = map.clCxt; - String kernelName = "getEdges"; - std::vector< std::pair > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&map.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&map.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&map.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.offset)); - - size_t globalThreads[3] = {cols, rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - - openCLExecuteKernel(clCxt, &imgproc_canny, kernelName, globalThreads, localThreads, args, -1, -1); -} diff --git a/modules/ocl/src/cl_context.cpp b/modules/ocl/src/cl_context.cpp deleted file mode 100644 index d6d081fe1..000000000 --- a/modules/ocl/src/cl_context.cpp +++ /dev/null @@ -1,944 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Guoping Long, longguoping@gmail.com -// Niko Li, newlife20080214@gmail.com -// Yao Wang, bitwangyaoyao@gmail.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 "precomp.hpp" -#include -#include -#include -#include -#include "cl_programcache.hpp" - -#include "opencv2/ocl/private/opencl_utils.hpp" - -namespace cv { -namespace ocl { - -using namespace cl_utils; - -#if defined(WIN32) -static bool __termination = false; -#endif - -struct __Module -{ - __Module(); - ~__Module(); - cv::Mutex initializationMutex; - cv::Mutex currentContextMutex; -}; -static __Module __module; - -cv::Mutex& getInitializationMutex() -{ - return __module.initializationMutex; -} - -static cv::Mutex& getCurrentContextMutex() -{ - return __module.currentContextMutex; -} - -static bool parseOpenCLVersion(const std::string& versionStr, int& major, int& minor) -{ - size_t p0 = versionStr.find(' '); - while (true) - { - if (p0 == std::string::npos) - break; - if (p0 + 1 >= versionStr.length()) - break; - char c = versionStr[p0 + 1]; - if (isdigit(c)) - break; - p0 = versionStr.find(' ', p0 + 1); - } - size_t p1 = versionStr.find('.', p0); - size_t p2 = versionStr.find(' ', p1); - if (p0 == std::string::npos || p1 == std::string::npos || p2 == std::string::npos) - { - major = 0; - minor = 0; - return false; - } - std::string majorStr = versionStr.substr(p0 + 1, p1 - p0 - 1); - std::string minorStr = versionStr.substr(p1 + 1, p2 - p1 - 1); - major = atoi(majorStr.c_str()); - minor = atoi(minorStr.c_str()); - return true; -} - -struct PlatformInfoImpl : public PlatformInfo -{ - cl_platform_id platform_id; - - std::vector deviceIDs; - - PlatformInfoImpl() - : platform_id(NULL) - { - } - - void init(int id, cl_platform_id platform) - { - CV_Assert(platform_id == NULL); - - this->_id = id; - platform_id = platform; - - openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_PROFILE, this->platformProfile)); - openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_VERSION, this->platformVersion)); - openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_NAME, this->platformName)); - openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_VENDOR, this->platformVendor)); - openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_EXTENSIONS, this->platformExtensons)); - - parseOpenCLVersion(this->platformVersion, - this->platformVersionMajor, this->platformVersionMinor); - } - -}; - -struct DeviceInfoImpl: public DeviceInfo -{ - cl_platform_id platform_id; - cl_device_id device_id; - - DeviceInfoImpl() - : platform_id(NULL), device_id(NULL) - { - } - - void init(int id, PlatformInfoImpl& platformInfoImpl, cl_device_id device) - { - CV_Assert(device_id == NULL); - - this->_id = id; - platform_id = platformInfoImpl.platform_id; - device_id = device; - - this->platform = &platformInfoImpl; - - cl_device_type type = cl_device_type(-1); - openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_TYPE, type)); - this->deviceType = DeviceType(type); - - openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_PROFILE, this->deviceProfile)); - openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_VERSION, this->deviceVersion)); - openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_NAME, this->deviceName)); - openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_VENDOR, this->deviceVendor)); - cl_uint vendorID = 0; - openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_VENDOR_ID, vendorID)); - this->deviceVendorId = vendorID; - openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DRIVER_VERSION, this->deviceDriverVersion)); - openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, this->deviceExtensions)); - - parseOpenCLVersion(this->deviceVersion, - this->deviceVersionMajor, this->deviceVersionMinor); - - size_t maxWorkGroupSize = 0; - openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_WORK_GROUP_SIZE, maxWorkGroupSize)); - this->maxWorkGroupSize = maxWorkGroupSize; - - cl_uint maxDimensions = 0; - openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, maxDimensions)); - std::vector maxWorkItemSizes(maxDimensions); - openCLSafeCall(clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t) * maxDimensions, - (void *)&maxWorkItemSizes[0], 0)); - this->maxWorkItemSizes = maxWorkItemSizes; - - cl_uint maxComputeUnits = 0; - openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_COMPUTE_UNITS, maxComputeUnits)); - this->maxComputeUnits = maxComputeUnits; - - cl_ulong localMemorySize = 0; - openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_LOCAL_MEM_SIZE, localMemorySize)); - this->localMemorySize = (size_t)localMemorySize; - - cl_ulong maxMemAllocSize = 0; - openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, maxMemAllocSize)); - this->maxMemAllocSize = (size_t)maxMemAllocSize; - - cl_bool unifiedMemory = false; - openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_HOST_UNIFIED_MEMORY, unifiedMemory)); - this->isUnifiedMemory = unifiedMemory != 0; - - //initialize extra options for compilation. Currently only fp64 is included. - //Assume 4KB is enough to store all possible extensions. - openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, this->deviceExtensions)); - - size_t fp64_khr = this->deviceExtensions.find("cl_khr_fp64"); - if(fp64_khr != std::string::npos) - { - this->compilationExtraOptions += "-D DOUBLE_SUPPORT"; - this->haveDoubleSupport = true; - } - else - { - this->haveDoubleSupport = false; - } - - size_t intel_platform = platformInfoImpl.platformVendor.find("Intel"); - if(intel_platform != std::string::npos) - { - this->compilationExtraOptions += " -D INTEL_DEVICE"; - this->isIntelDevice = true; - } - else - { - this->isIntelDevice = false; - } - - if (id < 0) - { -#ifdef CL_VERSION_1_2 - if (this->deviceVersionMajor > 1 || (this->deviceVersionMajor == 1 && this->deviceVersionMinor >= 2)) - { - ::clRetainDevice(device); - } -#endif - } - } -}; - -static std::vector global_platforms; -static std::vector global_devices; - -static void split(const std::string &s, char delim, std::vector &elems) { - std::stringstream ss(s); - std::string item; - while (std::getline(ss, item, delim)) { - elems.push_back(item); - } -} - -static std::vector split(const std::string &s, char delim) { - std::vector elems; - split(s, delim, elems); - return elems; -} - -// Layout: :: -// Sample: AMD:GPU: -// Sample: AMD:GPU:Tahiti -// Sample: :GPU|CPU: = '' = ':' = '::' -static bool parseOpenCLDeviceConfiguration(const std::string& configurationStr, - std::string& platform, std::vector& deviceTypes, std::string& deviceNameOrID) -{ - std::string deviceTypesStr; - size_t p0 = configurationStr.find(':'); - if (p0 != std::string::npos) - { - size_t p1 = configurationStr.find(':', p0 + 1); - if (p1 != std::string::npos) - { - size_t p2 = configurationStr.find(':', p1 + 1); - if (p2 != std::string::npos) - { - std::cerr << "ERROR: Invalid configuration string for OpenCL device" << std::endl; - return false; - } - else - { - // assume platform + device types + device name/id - platform = configurationStr.substr(0, p0); - deviceTypesStr = configurationStr.substr(p0 + 1, p1 - (p0 + 1)); - deviceNameOrID = configurationStr.substr(p1 + 1, configurationStr.length() - (p1 + 1)); - } - } - else - { - // assume platform + device types - platform = configurationStr.substr(0, p0); - deviceTypesStr = configurationStr.substr(p0 + 1, configurationStr.length() - (p0 + 1)); - } - } - else - { - // assume only platform - platform = configurationStr; - } - deviceTypes = split(deviceTypesStr, '|'); - return true; -} - -static bool selectOpenCLDevice() -{ - std::string platform; - std::vector deviceTypes; - std::string deviceName; - const char* configuration = getenv("OPENCV_OPENCL_DEVICE"); - if (configuration) - { - if (!parseOpenCLDeviceConfiguration(std::string(configuration), platform, deviceTypes, deviceName)) - return false; - } - - bool isID = false; - int deviceID = -1; - if (deviceName.length() == 1) - // We limit ID range to 0..9, because we want to write: - // - '2500' to mean i5-2500 - // - '8350' to mean AMD FX-8350 - // - '650' to mean GeForce 650 - // To extend ID range change condition to '> 0' - { - isID = true; - for (size_t i = 0; i < deviceName.length(); i++) - { - if (!isdigit(deviceName[i])) - { - isID = false; - break; - } - } - if (isID) - { - deviceID = atoi(deviceName.c_str()); - CV_Assert(deviceID >= 0); - } - } - - const PlatformInfo* platformInfo = NULL; - if (platform.length() > 0) - { - PlatformsInfo platforms; - getOpenCLPlatforms(platforms); - for (size_t i = 0; i < platforms.size(); i++) - { - if (platforms[i]->platformName.find(platform) != std::string::npos) - { - platformInfo = platforms[i]; - break; - } - } - if (platformInfo == NULL) - { - std::cerr << "ERROR: Can't find OpenCL platform by name: " << platform << std::endl; - goto not_found; - } - } - - if (deviceTypes.size() == 0) - { - if (!isID) - { - deviceTypes.push_back("GPU"); - deviceTypes.push_back("CPU"); - } - else - { - deviceTypes.push_back("ALL"); - } - } - for (size_t t = 0; t < deviceTypes.size(); t++) - { - int deviceType = 0; - if (deviceTypes[t] == "GPU") - { - deviceType = CVCL_DEVICE_TYPE_GPU; - } - else if (deviceTypes[t] == "CPU") - { - deviceType = CVCL_DEVICE_TYPE_CPU; - } - else if (deviceTypes[t] == "ACCELERATOR") - { - deviceType = CVCL_DEVICE_TYPE_ACCELERATOR; - } - else if (deviceTypes[t] == "ALL") - { - deviceType = CVCL_DEVICE_TYPE_ALL; - } - else - { - std::cerr << "ERROR: Unsupported device type for OpenCL device (GPU, CPU, ACCELERATOR): " << deviceTypes[t] << std::endl; - goto not_found; - } - - DevicesInfo devices; - getOpenCLDevices(devices, deviceType, platformInfo); - - for (size_t i = (isID ? deviceID : 0); - (isID ? (i == (size_t)deviceID) : true) && (i < devices.size()); - i++) - { - if (isID || devices[i]->deviceName.find(deviceName) != std::string::npos) - { - // check for OpenCL 1.1 - if (devices[i]->deviceVersionMajor < 1 || - (devices[i]->deviceVersionMajor == 1 && devices[i]->deviceVersionMinor < 1)) - { - std::cerr << "Skip unsupported version of OpenCL device: " << devices[i]->deviceName - << "(" << devices[i]->platform->platformName << ")" << std::endl; - continue; // unsupported version of device, skip it - } - try - { - setDevice(devices[i]); - } - catch (...) - { - std::cerr << "ERROR: Can't select OpenCL device: " << devices[i]->deviceName - << "(" << devices[i]->platform->platformName << ")" << std::endl; - goto not_found; - } - return true; - } - } - } -not_found: - std::cerr << "ERROR: Required OpenCL device not found, check configuration: " << (configuration == NULL ? "" : configuration) << std::endl - << " Platform: " << (platform.length() == 0 ? "any" : platform) << std::endl - << " Device types: "; - for (size_t t = 0; t < deviceTypes.size(); t++) - { - std::cerr << deviceTypes[t] << " "; - } - std::cerr << std::endl << " Device name: " << (deviceName.length() == 0 ? "any" : deviceName) << std::endl; - return false; -} - -static bool __initialized = false; -static int initializeOpenCLDevices() -{ - assert(!__initialized); - __initialized = true; - - assert(global_devices.size() == 0); - - std::vector platforms; - try - { - openCLSafeCall(getPlatforms(platforms)); - } - catch (cv::Exception&) - { - return 0; // OpenCL not found - } - - global_platforms.resize(platforms.size()); - - for (size_t i = 0; i < platforms.size(); ++i) - { - PlatformInfoImpl& platformInfo = global_platforms[i]; - - cl_platform_id platform = platforms[i]; - platformInfo.init(i, platform); - - std::vector devices; - cl_int status = getDevices(platform, CL_DEVICE_TYPE_ALL, devices); - if(status != CL_DEVICE_NOT_FOUND) - openCLVerifyCall(status); - - if(devices.size() > 0) - { - int baseIndx = global_devices.size(); - global_devices.resize(baseIndx + devices.size()); - platformInfo.deviceIDs.resize(devices.size()); - platformInfo.devices.resize(devices.size()); - - for(size_t j = 0; j < devices.size(); ++j) - { - cl_device_id device = devices[j]; - - DeviceInfoImpl& deviceInfo = global_devices[baseIndx + j]; - platformInfo.deviceIDs[j] = baseIndx + j; - deviceInfo.init(baseIndx + j, platformInfo, device); - } - } - } - - for (size_t i = 0; i < platforms.size(); ++i) - { - PlatformInfoImpl& platformInfo = global_platforms[i]; - for(size_t j = 0; j < platformInfo.deviceIDs.size(); ++j) - { - DeviceInfoImpl& deviceInfo = global_devices[platformInfo.deviceIDs[j]]; - platformInfo.devices[j] = &deviceInfo; - } - } - - return global_devices.size(); -} - - -DeviceInfo::DeviceInfo() - : _id(-1), deviceType(DeviceType(0)), - deviceVendorId(-1), - maxWorkGroupSize(0), maxComputeUnits(0), localMemorySize(0), maxMemAllocSize(0), - deviceVersionMajor(0), deviceVersionMinor(0), - haveDoubleSupport(false), isUnifiedMemory(false),isIntelDevice(false), - platform(NULL) -{ - // nothing -} - -DeviceInfo::~DeviceInfo() { } - -PlatformInfo::PlatformInfo() - : _id(-1), - platformVersionMajor(0), platformVersionMinor(0) -{ - // nothing -} - -PlatformInfo::~PlatformInfo() { } - -class ContextImpl; - -struct CommandQueue -{ - ContextImpl* context_; - cl_command_queue clQueue_; - - CommandQueue() : context_(NULL), clQueue_(NULL) { } - ~CommandQueue() { release(); } - - void create(ContextImpl* context_); - void release() - { -#ifdef WIN32 - // if process is on termination stage (ExitProcess was called and other threads were terminated) - // then disable command queue release because it may cause program hang - if (!__termination) -#endif - { - if(clQueue_) - { - openCLSafeCall(clReleaseCommandQueue(clQueue_)); // some cleanup problems are here - } - - } - clQueue_ = NULL; - context_ = NULL; - } -}; - -cv::TLSData commandQueueTLSData; - -//////////////////////////////// OpenCL context //////////////////////// -//This is a global singleton class used to represent a OpenCL context. -class ContextImpl : public Context -{ -public: - cl_device_id clDeviceID; - cl_context clContext; - const DeviceInfoImpl& deviceInfoImpl; - -protected: - ContextImpl(const DeviceInfoImpl& _deviceInfoImpl, cl_context context) - : clDeviceID(_deviceInfoImpl.device_id), clContext(context), deviceInfoImpl(_deviceInfoImpl) - { -#ifdef CL_VERSION_1_2 - if (supportsFeature(FEATURE_CL_VER_1_2)) - { - openCLSafeCall(clRetainDevice(clDeviceID)); - } -#endif - openCLSafeCall(clRetainContext(clContext)); - - ContextImpl* old = NULL; - { - cv::AutoLock lock(getCurrentContextMutex()); - old = currentContext; - currentContext = this; - } - if (old != NULL) - { - delete old; - } - } - ~ContextImpl() - { - CV_Assert(this != currentContext); - -#ifdef CL_VERSION_1_2 - if (supportsFeature(FEATURE_CL_VER_1_2)) - { - openCLSafeCall(clReleaseDevice(clDeviceID)); - } -#endif - if (deviceInfoImpl._id < 0) // not in the global registry, so we should cleanup it - { -#ifdef CL_VERSION_1_2 - if (supportsFeature(FEATURE_CL_VER_1_2)) - { - openCLSafeCall(clReleaseDevice(deviceInfoImpl.device_id)); - } -#endif - PlatformInfoImpl* platformImpl = (PlatformInfoImpl*)(deviceInfoImpl.platform); - delete platformImpl; - delete const_cast(&deviceInfoImpl); - } - clDeviceID = NULL; - -#ifdef WIN32 - // if process is on termination stage (ExitProcess was called and other threads were terminated) - // then disable command queue release because it may cause program hang - if (!__termination) -#endif - { - if(clContext) - { - openCLSafeCall(clReleaseContext(clContext)); - } - } - clContext = NULL; - } -public: - static void setContext(const DeviceInfo* deviceInfo); - static void initializeContext(void* pClPlatform, void* pClContext, void* pClDevice); - - bool supportsFeature(FEATURE_TYPE featureType) const; - - static void cleanupContext(void); - - static ContextImpl* getContext(); -private: - ContextImpl(const ContextImpl&); // disabled - ContextImpl& operator=(const ContextImpl&); // disabled - - static ContextImpl* currentContext; -}; - -ContextImpl* ContextImpl::currentContext = NULL; - -static bool __deviceSelected = false; - -Context* Context::getContext() -{ - return ContextImpl::getContext(); -} - -ContextImpl* ContextImpl::getContext() -{ - if (currentContext == NULL) - { - static bool defaultInitiaization = false; - if (!defaultInitiaization) - { - cv::AutoLock lock(getInitializationMutex()); - try - { - if (!__initialized) - { - if (initializeOpenCLDevices() == 0) - { - CV_Error(Error::OpenCLInitError, "OpenCL not available"); - } - } - if (!__deviceSelected) - { - if (!selectOpenCLDevice()) - { - CV_Error(Error::OpenCLInitError, "Can't select OpenCL device"); - } - } - defaultInitiaization = true; - } - catch (...) - { - defaultInitiaization = true; - throw; - } - } - CV_Assert(currentContext != NULL); - } - return currentContext; -} - -bool Context::supportsFeature(FEATURE_TYPE featureType) const -{ - return ((ContextImpl*)this)->supportsFeature(featureType); -} - -const DeviceInfo& Context::getDeviceInfo() const -{ - return ((ContextImpl*)this)->deviceInfoImpl; -} - -const void* Context::getOpenCLContextPtr() const -{ - return &(((ContextImpl*)this)->clContext); -} - -const void* Context::getOpenCLCommandQueuePtr() const -{ - ContextImpl* pThis = (ContextImpl*)this; - CommandQueue* commandQueue = commandQueueTLSData.get(); - if (commandQueue->context_ != pThis) - { - commandQueue->create(pThis); - } - return &commandQueue->clQueue_; -} - -const void* Context::getOpenCLDeviceIDPtr() const -{ - return &(((ContextImpl*)this)->clDeviceID); -} - - -bool ContextImpl::supportsFeature(FEATURE_TYPE featureType) const -{ - switch (featureType) - { - case FEATURE_CL_INTEL_DEVICE: - return deviceInfoImpl.isIntelDevice; - case FEATURE_CL_DOUBLE: - return deviceInfoImpl.haveDoubleSupport; - case FEATURE_CL_UNIFIED_MEM: - return deviceInfoImpl.isUnifiedMemory; - case FEATURE_CL_VER_1_2: - return deviceInfoImpl.deviceVersionMajor > 1 || (deviceInfoImpl.deviceVersionMajor == 1 && deviceInfoImpl.deviceVersionMinor >= 2); - } - CV_Error(CV_StsBadArg, "Invalid feature type"); - return false; -} - -void fft_teardown(); -void clBlasTeardown(); - -void ContextImpl::cleanupContext(void) -{ - fft_teardown(); - clBlasTeardown(); - - cv::AutoLock lock(getCurrentContextMutex()); - if (currentContext) - { - ContextImpl* ctx = currentContext; - currentContext = NULL; - delete ctx; - } -} - -void ContextImpl::setContext(const DeviceInfo* deviceInfo) -{ - CV_Assert(deviceInfo->_id >= 0); // we can't specify custom devices - CV_Assert(deviceInfo->_id < (int)global_devices.size()); - - { - cv::AutoLock lock(getCurrentContextMutex()); - if (currentContext) - { - if (currentContext->deviceInfoImpl._id == deviceInfo->_id) - return; - } - } - - DeviceInfoImpl& infoImpl = global_devices[deviceInfo->_id]; - CV_Assert(deviceInfo == &infoImpl); - - cl_int status = 0; - cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(infoImpl.platform_id), 0 }; - cl_context clContext = clCreateContext(cps, 1, &infoImpl.device_id, NULL, NULL, &status); - openCLVerifyCall(status); - - ContextImpl* ctx = new ContextImpl(infoImpl, clContext); - clReleaseContext(clContext); - (void)ctx; -} - -void ContextImpl::initializeContext(void* pClPlatform, void* pClContext, void* pClDevice) -{ - CV_Assert(pClPlatform != NULL); - CV_Assert(pClContext != NULL); - CV_Assert(pClDevice != NULL); - cl_platform_id platform = *(cl_platform_id*)pClPlatform; - cl_context context = *(cl_context*)pClContext; - cl_device_id device = *(cl_device_id*)pClDevice; - - PlatformInfoImpl* platformInfoImpl = new PlatformInfoImpl(); - platformInfoImpl->init(-1, platform); - DeviceInfoImpl* deviceInfoImpl = new DeviceInfoImpl(); - deviceInfoImpl->init(-1, *platformInfoImpl, device); - - ContextImpl* ctx = new ContextImpl(*deviceInfoImpl, context); - (void)ctx; -} - -void CommandQueue::create(ContextImpl* context) -{ - release(); - cl_int status = 0; - // TODO add CL_QUEUE_PROFILING_ENABLE - cl_command_queue clCmdQueue = clCreateCommandQueue(context->clContext, context->clDeviceID, 0, &status); - openCLVerifyCall(status); - context_ = context; - clQueue_ = clCmdQueue; -} - -int getOpenCLPlatforms(PlatformsInfo& platforms) -{ - if (!__initialized) - initializeOpenCLDevices(); - - platforms.clear(); - - for (size_t id = 0; id < global_platforms.size(); ++id) - { - PlatformInfoImpl& impl = global_platforms[id]; - platforms.push_back(&impl); - } - - return platforms.size(); -} - -int getOpenCLDevices(std::vector &devices, int deviceType, const PlatformInfo* platform) -{ - if (!__initialized) - initializeOpenCLDevices(); - - devices.clear(); - - switch(deviceType) - { - case CVCL_DEVICE_TYPE_DEFAULT: - case CVCL_DEVICE_TYPE_CPU: - case CVCL_DEVICE_TYPE_GPU: - case CVCL_DEVICE_TYPE_ACCELERATOR: - case CVCL_DEVICE_TYPE_ALL: - break; - default: - return 0; - } - - if (platform == NULL) - { - for (size_t id = 0; id < global_devices.size(); ++id) - { - DeviceInfoImpl& deviceInfo = global_devices[id]; - if (((int)deviceInfo.deviceType & deviceType) != 0) - { - devices.push_back(&deviceInfo); - } - } - } - else - { - for (size_t id = 0; id < platform->devices.size(); ++id) - { - const DeviceInfo* deviceInfo = platform->devices[id]; - if (((int)deviceInfo->deviceType & deviceType) == deviceType) - { - devices.push_back(deviceInfo); - } - } - } - - return (int)devices.size(); -} - -void setDevice(const DeviceInfo* info) -{ - try - { - ContextImpl::setContext(info); - __deviceSelected = true; - } - catch (...) - { - __deviceSelected = true; - throw; - } -} - -void initializeContext(void* pClPlatform, void* pClContext, void* pClDevice) -{ - try - { - ContextImpl::initializeContext(pClPlatform, pClContext, pClDevice); - __deviceSelected = true; - } - catch (...) - { - __deviceSelected = true; - throw; - } -} - -bool supportsFeature(FEATURE_TYPE featureType) -{ - return Context::getContext()->supportsFeature(featureType); -} - -__Module::__Module() -{ - /* moved to Context::getContext(): initializeOpenCLDevices(); */ -} - -__Module::~__Module() -{ -#if defined(WIN32) && defined(CVAPI_EXPORTS) - // nothing, see DllMain -#else - ContextImpl::cleanupContext(); -#endif -} - -} // namespace ocl -} // namespace cv - - -#if defined(WIN32) && defined(CVAPI_EXPORTS) - -extern "C" -BOOL WINAPI DllMain(HINSTANCE /*hInst*/, DWORD fdwReason, LPVOID lpReserved); - -extern "C" -BOOL WINAPI DllMain(HINSTANCE /*hInst*/, DWORD fdwReason, LPVOID lpReserved) -{ - if (fdwReason == DLL_PROCESS_DETACH) - { - if (lpReserved != NULL) // called after ExitProcess() call - cv::ocl::__termination = true; - cv::ocl::ContextImpl::cleanupContext(); - } - return TRUE; -} - -#endif diff --git a/modules/ocl/src/cl_operations.cpp b/modules/ocl/src/cl_operations.cpp deleted file mode 100644 index aa44c4874..000000000 --- a/modules/ocl/src/cl_operations.cpp +++ /dev/null @@ -1,549 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Guoping Long, longguoping@gmail.com -// Niko Li, newlife20080214@gmail.com -// Yao Wang, bitwangyaoyao@gmail.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 "precomp.hpp" -#include -#include -#include "cl_programcache.hpp" - -//#define PRINT_KERNEL_RUN_TIME -#define RUN_TIMES 100 -#ifndef CL_MEM_USE_PERSISTENT_MEM_AMD -#define CL_MEM_USE_PERSISTENT_MEM_AMD 0 -#endif -//#define AMD_DOUBLE_DIFFER - -namespace cv { -namespace ocl { - -DevMemType gDeviceMemType = DEVICE_MEM_DEFAULT; -DevMemRW gDeviceMemRW = DEVICE_MEM_R_W; -int gDevMemTypeValueMap[5] = {0, - CL_MEM_ALLOC_HOST_PTR, - CL_MEM_USE_HOST_PTR, - CL_MEM_COPY_HOST_PTR, - CL_MEM_USE_PERSISTENT_MEM_AMD}; -int gDevMemRWValueMap[3] = {CL_MEM_READ_WRITE, CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY}; - -void finish() -{ - clFinish(getClCommandQueue(Context::getContext())); -} - -bool isCpuDevice() -{ - const DeviceInfo& info = Context::getContext()->getDeviceInfo(); - return (info.deviceType == CVCL_DEVICE_TYPE_CPU); -} - -size_t queryWaveFrontSize(cl_kernel kernel) -{ - const DeviceInfo& info = Context::getContext()->getDeviceInfo(); - if (info.deviceType == CVCL_DEVICE_TYPE_CPU) - return 1; - size_t wavefront = 0; - CV_Assert(kernel != NULL); - openCLSafeCall(clGetKernelWorkGroupInfo(kernel, getClDeviceID(Context::getContext()), - CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, sizeof(size_t), &wavefront, NULL)); - return wavefront; -} - - -void openCLReadBuffer(Context *ctx, cl_mem dst_buffer, void *host_buffer, size_t size) -{ - cl_int status; - status = clEnqueueReadBuffer(getClCommandQueue(ctx), dst_buffer, CL_TRUE, 0, - size, host_buffer, 0, NULL, NULL); - openCLVerifyCall(status); -} - -cl_mem openCLCreateBuffer(Context *ctx, size_t flag , size_t size) -{ - cl_int status; - cl_mem buffer = clCreateBuffer(getClContext(ctx), (cl_mem_flags)flag, size, NULL, &status); - openCLVerifyCall(status); - return buffer; -} - -#define MEMORY_CORRUPTION_GUARD -#ifdef MEMORY_CORRUPTION_GUARD -//#define CHECK_MEMORY_CORRUPTION -#define CHECK_MEMORY_CORRUPTION_PRINT_ERROR -#define CHECK_MEMORY_CORRUPTION_RAISE_ERROR -static const int __memory_corruption_guard_bytes = 64*1024; -#ifdef CHECK_MEMORY_CORRUPTION -static const int __memory_corruption_check_pattern = 0x14326547; // change pattern for sizeof(int)==8 -#endif -struct CheckBuffers -{ - cl_mem mainBuffer; - size_t size; - size_t widthInBytes, height; - CheckBuffers() - : mainBuffer(NULL), size(0), widthInBytes(0), height(0) - { - // nothing - } - CheckBuffers(cl_mem _mainBuffer, size_t _size, size_t _widthInBytes, size_t _height) - : mainBuffer(_mainBuffer), size(_size), widthInBytes(_widthInBytes), height(_height) - { - // nothing - } -}; -static std::map __check_buffers; -#endif - -void openCLMallocPitch(Context *ctx, void **dev_ptr, size_t *pitch, - size_t widthInBytes, size_t height) -{ - openCLMallocPitchEx(ctx, dev_ptr, pitch, widthInBytes, height, gDeviceMemRW, gDeviceMemType); -} - -void openCLMallocPitchEx(Context *ctx, void **dev_ptr, size_t *pitch, - size_t widthInBytes, size_t height, DevMemRW rw_type, DevMemType mem_type) -{ - cl_int status; - size_t size = widthInBytes * height; - bool useSubBuffers = -#ifndef MEMORY_CORRUPTION_GUARD - false; -#else - true; -#endif - const DeviceInfo& devInfo = ctx->getDeviceInfo(); - if (useSubBuffers && devInfo.isIntelDevice) - { - useSubBuffers = false; // TODO FIXIT We observe memory leaks then we working with sub-buffers - // on the CPU device of Intel OpenCL SDK (Linux). We will investigate this later. - } - if (!useSubBuffers) - { - *dev_ptr = clCreateBuffer(getClContext(ctx), gDevMemRWValueMap[rw_type]|gDevMemTypeValueMap[mem_type], - size, 0, &status); - openCLVerifyCall(status); - } -#ifdef MEMORY_CORRUPTION_GUARD - else - { - size_t allocSize = size + __memory_corruption_guard_bytes * 2; - cl_mem mainBuffer = clCreateBuffer(getClContext(ctx), gDevMemRWValueMap[rw_type]|gDevMemTypeValueMap[mem_type], - allocSize, 0, &status); - openCLVerifyCall(status); - cl_buffer_region r = {__memory_corruption_guard_bytes, size}; - *dev_ptr = clCreateSubBuffer(mainBuffer, - gDevMemRWValueMap[rw_type]|gDevMemTypeValueMap[mem_type], - CL_BUFFER_CREATE_TYPE_REGION, &r, - &status); - openCLVerifyCall(status); -#ifdef CHECK_MEMORY_CORRUPTION - std::vector tmp(__memory_corruption_guard_bytes / sizeof(int), - __memory_corruption_check_pattern); - CV_Assert(tmp.size() * sizeof(int) == __memory_corruption_guard_bytes); - openCLVerifyCall(clEnqueueWriteBuffer(getClCommandQueue(ctx), - mainBuffer, CL_FALSE, 0, __memory_corruption_guard_bytes, &tmp[0], - 0, NULL, NULL)); - openCLVerifyCall(clEnqueueWriteBuffer(getClCommandQueue(ctx), - mainBuffer, CL_FALSE, __memory_corruption_guard_bytes + size, __memory_corruption_guard_bytes, &tmp[0], - 0, NULL, NULL)); - clFinish(getClCommandQueue(ctx)); -#endif - CheckBuffers data(mainBuffer, size, widthInBytes, height); - cv::AutoLock lock(getInitializationMutex()); - __check_buffers.insert(std::pair((cl_mem)*dev_ptr, data)); - } -#endif - *pitch = widthInBytes; -} - -void openCLMemcpy2D(Context *ctx, void *dst, size_t dpitch, - const void *src, size_t spitch, - size_t width, size_t height, openCLMemcpyKind kind, int channels) -{ - size_t buffer_origin[3] = {0, 0, 0}; - size_t host_origin[3] = {0, 0, 0}; - size_t region[3] = {width, height, 1}; - if(kind == clMemcpyHostToDevice) - { - if(dpitch == width || channels == 3 || height == 1) - { - openCLSafeCall(clEnqueueWriteBuffer(getClCommandQueue(ctx), (cl_mem)dst, CL_TRUE, - 0, width * height, src, 0, NULL, NULL)); - } - else - { - openCLSafeCall(clEnqueueWriteBufferRect(getClCommandQueue(ctx), (cl_mem)dst, CL_TRUE, - buffer_origin, host_origin, region, dpitch, 0, spitch, 0, src, 0, 0, 0)); - } - } - else if(kind == clMemcpyDeviceToHost) - { - if(spitch == width || channels == 3 || height == 1) - { - openCLSafeCall(clEnqueueReadBuffer(getClCommandQueue(ctx), (cl_mem)src, CL_TRUE, - 0, width * height, dst, 0, NULL, NULL)); - } - else - { - openCLSafeCall(clEnqueueReadBufferRect(getClCommandQueue(ctx), (cl_mem)src, CL_TRUE, - buffer_origin, host_origin, region, spitch, 0, dpitch, 0, dst, 0, 0, 0)); - } - } -} - -void openCLCopyBuffer2D(Context *ctx, void *dst, size_t dpitch, int dst_offset, - const void *src, size_t spitch, - size_t width, size_t height, int src_offset) -{ - size_t src_origin[3] = {src_offset % spitch, src_offset / spitch, 0}; - size_t dst_origin[3] = {dst_offset % dpitch, dst_offset / dpitch, 0}; - size_t region[3] = {width, height, 1}; - - openCLSafeCall(clEnqueueCopyBufferRect(getClCommandQueue(ctx), (cl_mem)src, (cl_mem)dst, src_origin, dst_origin, - region, spitch, 0, dpitch, 0, 0, 0, 0)); -} - -void openCLFree(void *devPtr) -{ - openCLSafeCall(clReleaseMemObject((cl_mem)devPtr)); -#ifdef MEMORY_CORRUPTION_GUARD -#ifdef CHECK_MEMORY_CORRUPTION - bool failBefore = false, failAfter = false; -#endif - CheckBuffers data; - { - cv::AutoLock lock(getInitializationMutex()); - std::map::iterator i = __check_buffers.find((cl_mem)devPtr); - if (i != __check_buffers.end()) - { - data = i->second; - __check_buffers.erase(i); - } - } - if (data.mainBuffer != NULL) - { -#ifdef CHECK_MEMORY_CORRUPTION - Context* ctx = Context::getContext(); - std::vector checkBefore(__memory_corruption_guard_bytes); - std::vector checkAfter(__memory_corruption_guard_bytes); - openCLVerifyCall(clEnqueueReadBuffer(getClCommandQueue(ctx), - data.mainBuffer, CL_FALSE, 0, __memory_corruption_guard_bytes, &checkBefore[0], - 0, NULL, NULL)); - openCLVerifyCall(clEnqueueReadBuffer(getClCommandQueue(ctx), - data.mainBuffer, CL_FALSE, __memory_corruption_guard_bytes + data.size, __memory_corruption_guard_bytes, &checkAfter[0], - 0, NULL, NULL)); - clFinish(getClCommandQueue(ctx)); - - std::vector tmp(__memory_corruption_guard_bytes / sizeof(int), - __memory_corruption_check_pattern); - - if (memcmp(&checkBefore[0], &tmp[0], __memory_corruption_guard_bytes) != 0) - { - failBefore = true; - } - if (memcmp(&checkAfter[0], &tmp[0], __memory_corruption_guard_bytes) != 0) - { - failAfter = true; - } -#else - // TODO FIXIT Attach clReleaseMemObject call to event completion callback - // TODO 2013/12/04 Disable workaround - // Context* ctx = Context::getContext(); - // clFinish(getClCommandQueue(ctx)); -#endif - openCLSafeCall(clReleaseMemObject(data.mainBuffer)); - } -#if defined(CHECK_MEMORY_CORRUPTION) - if (failBefore) - { -#ifdef CHECK_MEMORY_CORRUPTION_PRINT_ERROR - std::cerr << "ERROR: Memory corruption detected: before buffer: " << cv::format("widthInBytes=%d height=%d", (int)data.widthInBytes, (int)data.height) << std::endl; -#endif -#ifdef CHECK_MEMORY_CORRUPTION_RAISE_ERROR - CV_Error(CV_StsInternal, "Memory corruption detected: before buffer"); -#endif - } - if (failAfter) - { -#ifdef CHECK_MEMORY_CORRUPTION_PRINT_ERROR - std::cerr << "ERROR: Memory corruption detected: after buffer: " << cv::format("widthInBytes=%d height=%d", (int)data.widthInBytes, (int)data.height) << std::endl; -#endif -#ifdef CHECK_MEMORY_CORRUPTION_RAISE_ERROR - CV_Error(CV_StsInternal, "Memory corruption detected: after buffer"); -#endif - } -#endif // CHECK_MEMORY_CORRUPTION -#endif // MEMORY_CORRUPTION_GUARD -} - -cl_kernel openCLGetKernelFromSource(const Context *ctx, const cv::ocl::ProgramEntry* source, String kernelName) -{ - return openCLGetKernelFromSource(ctx, source, kernelName, NULL); -} - -cl_kernel openCLGetKernelFromSource(const Context *ctx, const cv::ocl::ProgramEntry* source, String kernelName, - const char *build_options) -{ - cl_kernel kernel; - cl_int status = 0; - CV_Assert(ProgramCache::getProgramCache() != NULL); - cl_program program = ProgramCache::getProgramCache()->getProgram(ctx, source, build_options); - CV_Assert(program != NULL); - kernel = clCreateKernel(program, kernelName.c_str(), &status); - openCLVerifyCall(status); - openCLVerifyCall(clReleaseProgram(program)); - return kernel; -} - -void openCLVerifyKernel(const Context *ctx, cl_kernel kernel, size_t *localThreads) -{ - size_t kernelWorkGroupSize; - openCLSafeCall(clGetKernelWorkGroupInfo(kernel, getClDeviceID(ctx), - CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &kernelWorkGroupSize, 0)); - CV_Assert( localThreads[0] <= ctx->getDeviceInfo().maxWorkItemSizes[0] ); - CV_Assert( localThreads[1] <= ctx->getDeviceInfo().maxWorkItemSizes[1] ); - CV_Assert( localThreads[2] <= ctx->getDeviceInfo().maxWorkItemSizes[2] ); - CV_Assert( localThreads[0] * localThreads[1] * localThreads[2] <= kernelWorkGroupSize ); - CV_Assert( localThreads[0] * localThreads[1] * localThreads[2] <= ctx->getDeviceInfo().maxWorkGroupSize ); -} - -#ifdef PRINT_KERNEL_RUN_TIME -static double total_execute_time = 0; -static double total_kernel_time = 0; -#endif - -static std::string removeDuplicatedWhiteSpaces(const char * buildOptions) -{ - if (buildOptions == NULL) - return ""; - - size_t length = strlen(buildOptions), didx = 0, sidx = 0; - while (sidx < length && buildOptions[sidx] == 0) - ++sidx; - - std::string opt; - opt.resize(length); - - for ( ; sidx < length; ++sidx) - if (buildOptions[sidx] != ' ') - opt[didx++] = buildOptions[sidx]; - else if ( !(didx > 0 && opt[didx - 1] == ' ') ) - opt[didx++] = buildOptions[sidx]; - - return opt; -} - -cl_kernel openCLGetKernelFromSource(Context *ctx, const cv::ocl::ProgramEntry* source, String kernelName, int channels, - int depth, const char *build_options) -{ - //construct kernel name - //The rule is functionName_Cn_Dn, C represent Channels, D Represent DataType Depth, n represent an integer number - //for example split_C2_D3, represent the split kernel with channels = 2 and dataType Depth = 3(Data type is short) - std::stringstream idxStr; - if(channels != -1) - idxStr << "_C" << channels; - if(depth != -1) - idxStr << "_D" << depth; - kernelName += idxStr.str(); - - std::string fixedOptions = removeDuplicatedWhiteSpaces(build_options); - cl_kernel kernel = openCLGetKernelFromSource(ctx, source, kernelName, fixedOptions.c_str()); - return kernel; -} - -void openCLExecuteKernel(Context *ctx, cl_kernel kernel, size_t globalThreads[3], - size_t localThreads[3], std::vector< std::pair > &args) -{ - if ( localThreads != NULL) - { - globalThreads[0] = roundUp(globalThreads[0], localThreads[0]); - globalThreads[1] = roundUp(globalThreads[1], localThreads[1]); - globalThreads[2] = roundUp(globalThreads[2], localThreads[2]); - - cv::ocl::openCLVerifyKernel(ctx, kernel, localThreads); - } - for(size_t i = 0; i < args.size(); i ++) - openCLSafeCall(clSetKernelArg(kernel, i, args[i].first, args[i].second)); - -#ifndef PRINT_KERNEL_RUN_TIME - openCLSafeCall(clEnqueueNDRangeKernel(getClCommandQueue(ctx), kernel, 3, NULL, globalThreads, - localThreads, 0, NULL, NULL)); -#else - cl_event event = NULL; - openCLSafeCall(clEnqueueNDRangeKernel(getClCommandQueue(ctx), kernel, 3, NULL, globalThreads, - localThreads, 0, NULL, &event)); - - cl_ulong start_time, end_time, queue_time; - double execute_time = 0; - double total_time = 0; - - openCLSafeCall(clWaitForEvents(1, &event)); - openCLSafeCall(clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START, - sizeof(cl_ulong), &start_time, 0)); - - openCLSafeCall(clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END, - sizeof(cl_ulong), &end_time, 0)); - - openCLSafeCall(clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_QUEUED, - sizeof(cl_ulong), &queue_time, 0)); - - execute_time = (double)(end_time - start_time) / (1000 * 1000); - total_time = (double)(end_time - queue_time) / (1000 * 1000); - - total_execute_time += execute_time; - total_kernel_time += total_time; - clReleaseEvent(event); -#endif - - clFlush(getClCommandQueue(ctx)); - openCLSafeCall(clReleaseKernel(kernel)); -} - -void openCLExecuteKernel_(Context *ctx, const cv::ocl::ProgramEntry* source, String kernelName, size_t globalThreads[3], - size_t localThreads[3], std::vector< std::pair > &args, int channels, - int depth, const char *build_options) -{ - cl_kernel kernel = openCLGetKernelFromSource(ctx, source, kernelName, channels, depth, build_options); - - openCLExecuteKernel(ctx, kernel, globalThreads, localThreads, args); -} - -void openCLExecuteKernel(Context *ctx, const cv::ocl::ProgramEntry* source, String kernelName, - size_t globalThreads[3], size_t localThreads[3], - std::vector< std::pair > &args, int channels, int depth) -{ - openCLExecuteKernel(ctx, source, kernelName, globalThreads, localThreads, args, - channels, depth, NULL); -} -void openCLExecuteKernel(Context *ctx, const cv::ocl::ProgramEntry* source, String kernelName, - size_t globalThreads[3], size_t localThreads[3], - std::vector< std::pair > &args, int channels, int depth, const char *build_options) - -{ -#ifndef PRINT_KERNEL_RUN_TIME - openCLExecuteKernel_(ctx, source, kernelName, globalThreads, localThreads, args, channels, depth, - build_options); -#else - String data_type[] = { "uchar", "char", "ushort", "short", "int", "float", "double"}; - std::cout << std::endl; - std::cout << "Function Name: " << kernelName; - if(depth >= 0) - std::cout << " |data type: " << data_type[depth]; - std::cout << " |channels: " << channels; - std::cout << " |Time Unit: " << "ms" << std::endl; - - total_execute_time = 0; - total_kernel_time = 0; - std::cout << "-------------------------------------" << std::endl; - - std::cout << std::setiosflags(std::ios::left) << std::setw(15) << "execute time"; - std::cout << std::setiosflags(std::ios::left) << std::setw(15) << "launch time"; - std::cout << std::setiosflags(std::ios::left) << std::setw(15) << "kernel time" << std::endl; - int i = 0; - for(i = 0; i < RUN_TIMES; i++) - openCLExecuteKernel_(ctx, source, kernelName, globalThreads, localThreads, args, channels, depth, - build_options); - - std::cout << "average kernel execute time: " << total_execute_time / RUN_TIMES << std::endl; // "ms" << std::endl; - std::cout << "average kernel total time: " << total_kernel_time / RUN_TIMES << std::endl; // "ms" << std::endl; -#endif -} - -void openCLExecuteKernelInterop(Context *ctx, const cv::ocl::ProgramSource& source, String kernelName, - size_t globalThreads[3], size_t localThreads[3], - std::vector< std::pair > &args, int channels, int depth, const char *build_options) - -{ - //construct kernel name - //The rule is functionName_Cn_Dn, C represent Channels, D Represent DataType Depth, n represent an integer number - //for example split_C2_D2, represent the split kernel with channels = 2 and dataType Depth = 2 (Data type is char) - std::stringstream idxStr; - if(channels != -1) - idxStr << "_C" << channels; - if(depth != -1) - idxStr << "_D" << depth; - kernelName += idxStr.str(); - - std::string name = std::string("custom_") + source.name; - ProgramEntry program = { name.c_str(), source.programStr, source.programHash }; - cl_kernel kernel = openCLGetKernelFromSource(ctx, &program, kernelName, build_options); - - CV_Assert(globalThreads != NULL); - if ( localThreads != NULL) - { - globalThreads[0] = roundUp(globalThreads[0], localThreads[0]); - globalThreads[1] = roundUp(globalThreads[1], localThreads[1]); - globalThreads[2] = roundUp(globalThreads[2], localThreads[2]); - - cv::ocl::openCLVerifyKernel(ctx, kernel, localThreads); - } - for(size_t i = 0; i < args.size(); i ++) - openCLSafeCall(clSetKernelArg(kernel, i, args[i].first, args[i].second)); - - openCLSafeCall(clEnqueueNDRangeKernel(getClCommandQueue(ctx), kernel, 3, NULL, globalThreads, - localThreads, 0, NULL, NULL)); - - clFinish(getClCommandQueue(ctx)); - openCLSafeCall(clReleaseKernel(kernel)); -} - -cl_mem load_constant(cl_context context, cl_command_queue command_queue, const void *value, - const size_t size) -{ - int status; - cl_mem con_struct; - - con_struct = clCreateBuffer(context, CL_MEM_READ_ONLY, size, NULL, &status); - openCLSafeCall(status); - - openCLSafeCall(clEnqueueWriteBuffer(command_queue, con_struct, 1, 0, size, - value, 0, 0, 0)); - - return con_struct; -} - -}//namespace ocl -}//namespace cv diff --git a/modules/ocl/src/cl_programcache.cpp b/modules/ocl/src/cl_programcache.cpp deleted file mode 100644 index 56f0213c5..000000000 --- a/modules/ocl/src/cl_programcache.cpp +++ /dev/null @@ -1,514 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Guoping Long, longguoping@gmail.com -// Niko Li, newlife20080214@gmail.com -// Yao Wang, bitwangyaoyao@gmail.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 "precomp.hpp" -#include -#include -#include "cl_programcache.hpp" - -namespace cv { namespace ocl { - -/* - * The binary caching system to eliminate redundant program source compilation. - * Strictly, this is not a cache because we do not implement evictions right now. - * We shall add such features to trade-off memory consumption and performance when necessary. - */ - -cv::Mutex ProgramCache::mutexFiles; -cv::Mutex ProgramCache::mutexCache; - -ProgramCache* _programCache = NULL; -ProgramCache* ProgramCache::getProgramCache() -{ - if (NULL == _programCache) - { - cv::AutoLock lock(getInitializationMutex()); - if (NULL == _programCache) - _programCache = new ProgramCache(); - } - return _programCache; -} - -ProgramCache::ProgramCache() -{ - codeCache.clear(); - cacheSize = 0; -} - -ProgramCache::~ProgramCache() -{ - releaseProgram(); - if (this == _programCache) - { - cv::AutoLock lock(getInitializationMutex()); - if (this == _programCache) - _programCache = NULL; - } -} - -cl_program ProgramCache::progLookup(const String& srcsign) -{ - std::map::iterator iter; - iter = codeCache.find(srcsign); - if(iter != codeCache.end()) - return iter->second; - else - return NULL; -} - -void ProgramCache::addProgram(const String& srcsign, cl_program program) -{ - if (!progLookup(srcsign)) - { - clRetainProgram(program); - codeCache.insert(std::map::value_type(srcsign, program)); - } -} - -void ProgramCache::releaseProgram() -{ - std::map::iterator iter; - for(iter = codeCache.begin(); iter != codeCache.end(); iter++) - { - openCLSafeCall(clReleaseProgram(iter->second)); - } - codeCache.clear(); - cacheSize = 0; -} - -static bool enable_disk_cache = true; -static String binpath = ""; - -void setBinaryDiskCache(int mode, String path) -{ - enable_disk_cache = false; - binpath = ""; - - if(mode == CACHE_NONE) - { - return; - } - enable_disk_cache = -#if defined(_DEBUG) || defined(DEBUG) - (mode & CACHE_DEBUG) == CACHE_DEBUG; -#else - (mode & CACHE_RELEASE) == CACHE_RELEASE; -#endif - if(enable_disk_cache && !path.empty()) - { - binpath = path; - } -} - -void setBinaryPath(const char *path) -{ - binpath = path; -} - -static const int MAX_ENTRIES = 64; - -struct ProgramFileCache -{ - struct CV_DECL_ALIGNED(1) ProgramFileHeader - { - int hashLength; - //char hash[]; - }; - - struct CV_DECL_ALIGNED(1) ProgramFileTable - { - int numberOfEntries; - //int firstEntryOffset[]; - }; - - struct CV_DECL_ALIGNED(1) ProgramFileConfigurationEntry - { - int nextEntry; - int dataSize; - int optionsLength; - //char options[]; - // char data[]; - }; - - String fileName_; - const char* hash_; - std::fstream f; - - ProgramFileCache(const String& fileName, const char* hash) - : fileName_(fileName), hash_(hash) - { - if (hash_ != NULL) - { - f.open(fileName_.c_str(), std::ios::in|std::ios::out|std::ios::binary); - if(f.is_open()) - { - int hashLength = 0; - f.read((char*)&hashLength, sizeof(int)); - std::vector fhash(hashLength + 1); - f.read(&fhash[0], hashLength); - if (f.eof() || strncmp(hash_, &fhash[0], hashLength) != 0) - { - f.close(); - remove(fileName_.c_str()); - return; - } - } - } - } - - int getHash(const String& options) - { - int hash = 0; - for (size_t i = 0; i < options.length(); i++) - { - hash = (hash << 2) ^ (hash >> 17) ^ options[i]; - } - return (hash + (hash >> 16)) & (MAX_ENTRIES - 1); - } - - bool readConfigurationFromFile(const String& options, std::vector& buf) - { - if (hash_ == NULL) - return false; - - if (!f.is_open()) - return false; - - f.seekg(0, std::fstream::end); - size_t fileSize = (size_t)f.tellg(); - if (fileSize == 0) - { - std::cerr << "Invalid file (empty): " << fileName_ << std::endl; - f.close(); - remove(fileName_.c_str()); - return false; - } - f.seekg(0, std::fstream::beg); - - int hashLength = 0; - f.read((char*)&hashLength, sizeof(int)); - CV_Assert(hashLength > 0); - f.seekg(sizeof(hashLength) + hashLength, std::fstream::beg); - - int numberOfEntries = 0; - f.read((char*)&numberOfEntries, sizeof(int)); - CV_Assert(numberOfEntries > 0); - if (numberOfEntries != MAX_ENTRIES) - { - std::cerr << "Invalid file: " << fileName_ << std::endl; - f.close(); - remove(fileName_.c_str()); - return false; - } - - std::vector firstEntryOffset(numberOfEntries); - f.read((char*)&firstEntryOffset[0], sizeof(int)*numberOfEntries); - - int entryNum = getHash(options); - - int entryOffset = firstEntryOffset[entryNum]; - ProgramFileConfigurationEntry entry; - while (entryOffset > 0) - { - f.seekg(entryOffset, std::fstream::beg); - assert(sizeof(entry) == sizeof(int)*3); - f.read((char*)&entry, sizeof(entry)); - std::vector foptions(entry.optionsLength); - if ((int)options.length() == entry.optionsLength) - { - if (entry.optionsLength > 0) - f.read(&foptions[0], entry.optionsLength); - if (memcmp(&foptions[0], options.c_str(), entry.optionsLength) == 0) - { - buf.resize(entry.dataSize); - f.read(&buf[0], entry.dataSize); - f.seekg(0, std::fstream::beg); - return true; - } - } - if (entry.nextEntry <= 0) - break; - entryOffset = entry.nextEntry; - } - return false; - } - - bool writeConfigurationToFile(const String& options, std::vector& buf) - { - if (hash_ == NULL) - return true; // don't save programs without hash - - if (!f.is_open()) - { - f.open(fileName_.c_str(), std::ios::in|std::ios::out|std::ios::binary); - if (!f.is_open()) - { - f.open(fileName_.c_str(), std::ios::out|std::ios::binary); - if (!f.is_open()) - return false; - } - } - - f.seekg(0, std::fstream::end); - size_t fileSize = (size_t)f.tellg(); - if (fileSize == 0) - { - f.seekp(0, std::fstream::beg); - int hashLength = strlen(hash_); - f.write((char*)&hashLength, sizeof(int)); - f.write(hash_, hashLength); - - int numberOfEntries = MAX_ENTRIES; - f.write((char*)&numberOfEntries, sizeof(int)); - std::vector firstEntryOffset(MAX_ENTRIES, 0); - f.write((char*)&firstEntryOffset[0], sizeof(int)*numberOfEntries); - f.close(); - f.open(fileName_.c_str(), std::ios::in|std::ios::out|std::ios::binary); - CV_Assert(f.is_open()); - f.seekg(0, std::fstream::end); - fileSize = (size_t)f.tellg(); - } - f.seekg(0, std::fstream::beg); - - int hashLength = 0; - f.read((char*)&hashLength, sizeof(int)); - CV_Assert(hashLength > 0); - f.seekg(sizeof(hashLength) + hashLength, std::fstream::beg); - - int numberOfEntries = 0; - f.read((char*)&numberOfEntries, sizeof(int)); - CV_Assert(numberOfEntries > 0); - if (numberOfEntries != MAX_ENTRIES) - { - std::cerr << "Invalid file: " << fileName_ << std::endl; - f.close(); - remove(fileName_.c_str()); - return false; - } - - size_t tableEntriesOffset = (size_t)f.tellg(); - std::vector firstEntryOffset(numberOfEntries); - f.read((char*)&firstEntryOffset[0], sizeof(int)*numberOfEntries); - - int entryNum = getHash(options); - - int entryOffset = firstEntryOffset[entryNum]; - ProgramFileConfigurationEntry entry; - while (entryOffset > 0) - { - f.seekg(entryOffset, std::fstream::beg); - assert(sizeof(entry) == sizeof(int)*3); - f.read((char*)&entry, sizeof(entry)); - std::vector foptions(entry.optionsLength); - if ((int)options.length() == entry.optionsLength) - { - if (entry.optionsLength > 0) - f.read(&foptions[0], entry.optionsLength); - CV_Assert(memcmp(&foptions, options.c_str(), entry.optionsLength) != 0); - } - if (entry.nextEntry <= 0) - break; - entryOffset = entry.nextEntry; - } - if (entryOffset > 0) - { - f.seekp(entryOffset, std::fstream::beg); - entry.nextEntry = fileSize; - f.write((char*)&entry, sizeof(entry)); - } - else - { - firstEntryOffset[entryNum] = fileSize; - f.seekp(tableEntriesOffset, std::fstream::beg); - f.write((char*)&firstEntryOffset[0], sizeof(int)*numberOfEntries); - } - f.seekp(fileSize, std::fstream::beg); - entry.nextEntry = 0; - entry.dataSize = buf.size(); - entry.optionsLength = options.length(); - f.write((char*)&entry, sizeof(entry)); - f.write(options.c_str(), entry.optionsLength); - f.write(&buf[0], entry.dataSize); - return true; - } - - cl_program getOrBuildProgram(const Context* ctx, const cv::ocl::ProgramEntry* source, const String& options) - { - cl_int status = 0; - cl_program program = NULL; - std::vector binary; - if (!enable_disk_cache || !readConfigurationFromFile(options, binary)) - { - program = clCreateProgramWithSource(getClContext(ctx), 1, (const char**)&source->programStr, NULL, &status); - openCLVerifyCall(status); - cl_device_id device = getClDeviceID(ctx); - status = clBuildProgram(program, 1, &device, options.c_str(), NULL, NULL); - if(status == CL_SUCCESS) - { - if (enable_disk_cache) - { - size_t binarySize; - openCLSafeCall(clGetProgramInfo(program, - CL_PROGRAM_BINARY_SIZES, - sizeof(size_t), - &binarySize, NULL)); - - std::vector binary(binarySize); - - char* ptr = &binary[0]; - openCLSafeCall(clGetProgramInfo(program, - CL_PROGRAM_BINARIES, - sizeof(char*), - &ptr, - NULL)); - - if (!writeConfigurationToFile(options, binary)) - { - std::cerr << "Can't write data to file: " << fileName_ << std::endl; - } - } - } - } - else - { - cl_device_id device = getClDeviceID(ctx); - size_t size = binary.size(); - const char* ptr = &binary[0]; - program = clCreateProgramWithBinary(getClContext(ctx), - 1, &device, - (const size_t *)&size, (const unsigned char **)&ptr, - NULL, &status); - openCLVerifyCall(status); - status = clBuildProgram(program, 1, &device, options.c_str(), NULL, NULL); - } - - if(status != CL_SUCCESS) - { - if (status == CL_BUILD_PROGRAM_FAILURE || status == CL_INVALID_BUILD_OPTIONS) - { - size_t buildLogSize = 0; - openCLSafeCall(clGetProgramBuildInfo(program, getClDeviceID(ctx), - CL_PROGRAM_BUILD_LOG, 0, NULL, &buildLogSize)); - std::vector buildLog; buildLog.resize(buildLogSize); - memset(&buildLog[0], 0, buildLogSize); - openCLSafeCall(clGetProgramBuildInfo(program, getClDeviceID(ctx), - CL_PROGRAM_BUILD_LOG, buildLogSize, &buildLog[0], NULL)); - std::cout << std::endl << "BUILD LOG: " - << (source->name ? source->name : "dynamic program") << ": " - << options << "\n"; - std::cout << &buildLog[0] << std::endl; - } - openCLVerifyCall(status); - } - return program; - } -}; - -cl_program ProgramCache::getProgram(const Context *ctx, const cv::ocl::ProgramEntry* source, - const char *build_options) -{ - std::stringstream src_sign; - - if (source->name) - { - src_sign << source->name; - src_sign << getClContext(ctx); - if (NULL != build_options) - { - src_sign << "_" << build_options; - } - - { - cv::AutoLock lockCache(mutexCache); - cl_program program = ProgramCache::getProgramCache()->progLookup(src_sign.str()); - if (!!program) - { - clRetainProgram(program); - return program; - } - } - } - - cv::AutoLock lockCache(mutexFiles); - - // second check - if (source->name) - { - cv::AutoLock lockCache(mutexCache); - cl_program program = ProgramCache::getProgramCache()->progLookup(src_sign.str()); - if (!!program) - { - clRetainProgram(program); - return program; - } - } - - String all_build_options; - if (!ctx->getDeviceInfo().compilationExtraOptions.empty()) - all_build_options += ctx->getDeviceInfo().compilationExtraOptions; - if (build_options != NULL) - { - all_build_options += " "; - all_build_options += build_options; - } - const DeviceInfo& devInfo = ctx->getDeviceInfo(); - String filename = binpath + (source->name ? source->name : "NULL") + "_" + devInfo.platform->platformName + "_" + devInfo.deviceName + ".clb"; - - ProgramFileCache programFileCache(filename, source->programHash); - cl_program program = programFileCache.getOrBuildProgram(ctx, source, all_build_options); - - //Cache the binary for future use if build_options is null - if (source->name) - { - cv::AutoLock lockCache(mutexCache); - this->addProgram(src_sign.str(), program); - } - return program; -} - -} // namespace ocl -} // namespace cv diff --git a/modules/ocl/src/cl_programcache.hpp b/modules/ocl/src/cl_programcache.hpp deleted file mode 100644 index ebf3e7676..000000000 --- a/modules/ocl/src/cl_programcache.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// -// 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 "precomp.hpp" - -namespace cv { -namespace ocl { - -class ProgramCache -{ -protected: - ProgramCache(); - ~ProgramCache(); -public: - static ProgramCache *getProgramCache(); - - cl_program getProgram(const Context *ctx, const cv::ocl::ProgramEntry* source, - const char *build_options); - - void releaseProgram(); -protected: - //lookup the binary given the file name - // (with acquired mutexCache) - cl_program progLookup(const String& srcsign); - - //add program to the cache - // (with acquired mutexCache) - void addProgram(const String& srcsign, cl_program program); - - std::map codeCache; - unsigned int cacheSize; - - //The presumed watermark for the cache volume (256MB). Is it enough? - //We may need more delicate algorithms when necessary later. - //Right now, let's just leave it along. - static const unsigned MAX_PROG_CACHE_SIZE = 1024; - - // acquire both mutexes in this order: 1) mutexFiles 2) mutexCache - static cv::Mutex mutexFiles; - static cv::Mutex mutexCache; -}; - -}//namespace ocl -}//namespace cv diff --git a/modules/ocl/src/color.cpp b/modules/ocl/src/color.cpp deleted file mode 100644 index 408ba4cce..000000000 --- a/modules/ocl/src/color.cpp +++ /dev/null @@ -1,656 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Wang Weiyan, wangweiyanster@gmail.com -// Peng Xiao, pengxiao@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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -static void fromRGB_caller(const oclMat &src, oclMat &dst, int bidx, const std::string & kernelName, - const std::string & additionalOptions = std::string(), - const oclMat & data1 = oclMat(), const oclMat & data2 = oclMat()) -{ - int src_offset = src.offset / src.elemSize1(), src_step = src.step1(); - int dst_offset = dst.offset / dst.elemSize1(), dst_step = dst.step1(); - int pixels_per_work_item = 1; - - if (Context::getContext()->supportsFeature(FEATURE_CL_INTEL_DEVICE)) - { - if ((src.cols % 4 == 0) && (src.depth() == CV_8U)) - pixels_per_work_item = 4; - else if (src.cols % 2 == 0) - pixels_per_work_item = 2; - else - pixels_per_work_item = 1; - } - - String build_options = format("-D DEPTH_%d -D scn=%d -D bidx=%d -D pixels_per_work_item=%d", src.depth(), src.oclchannels(), bidx, pixels_per_work_item); - if (!additionalOptions.empty()) - build_options = build_options + additionalOptions; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_offset )); - - if (!data1.empty()) - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&data1.data )); - if (!data2.empty()) - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&data2.data )); - - size_t gt[3] = { dst.cols/pixels_per_work_item, dst.rows, 1 }; -#ifdef ANDROID - size_t lt[3] = { 16, 10, 1 }; -#else - size_t lt[3] = { 16, 16, 1 }; -#endif - openCLExecuteKernel(src.clCxt, &cvt_color, kernelName.c_str(), gt, lt, args, -1, -1, build_options.c_str()); -} - -static void toHSV_caller(const oclMat &src, oclMat &dst, int bidx, const std::string & kernelName, - const std::string & additionalOptions = std::string(), - const oclMat & data1 = oclMat(), const oclMat & data2 = oclMat()) -{ - int src_offset = src.offset / src.elemSize1(), src_step = src.step1(); - int dst_offset = dst.offset / dst.elemSize1(), dst_step = dst.step1(); - - std::string build_options = format("-D DEPTH_%d -D scn=%d -D bidx=%d", src.depth(), src.oclchannels(), bidx); - if (!additionalOptions.empty()) - build_options += additionalOptions; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_offset )); - - if (!data1.empty()) - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&data1.data )); - if (!data2.empty()) - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&data2.data )); - - size_t gt[3] = { dst.cols, dst.rows, 1 }; -#ifdef ANDROID - size_t lt[3] = { 16, 10, 1 }; -#else - size_t lt[3] = { 16, 16, 1 }; -#endif - openCLExecuteKernel(src.clCxt, &cvt_color, kernelName.c_str(), gt, lt, args, -1, -1, build_options.c_str()); -} - -static void fromGray_caller(const oclMat &src, oclMat &dst, int bidx, const std::string & kernelName, - const std::string & additionalOptions = std::string(), const oclMat & data = oclMat()) -{ - std::string build_options = format("-D DEPTH_%d -D dcn=%d -D bidx=%d", src.depth(), dst.channels(), bidx); - if (!additionalOptions.empty()) - build_options += additionalOptions; - - int src_offset = src.offset / src.elemSize1(), src_step = src.step1(); - int dst_offset = dst.offset / dst.elemSize1(), dst_step = dst.step1(); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_offset )); - - if (!data.empty()) - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&data.data )); - - size_t gt[3] = { dst.cols, dst.rows, 1 }; -#ifdef ANDROID - size_t lt[3] = { 16, 10, 1 }; -#else - size_t lt[3] = { 16, 16, 1 }; -#endif - openCLExecuteKernel(src.clCxt, &cvt_color, kernelName.c_str(), gt, lt, args, -1, -1, build_options.c_str()); -} - -static void toRGB_caller(const oclMat &src, oclMat &dst, int bidx, const std::string & kernelName, - const std::string & additionalOptions = std::string(), const oclMat & data = oclMat()) -{ - int src_offset = src.offset / src.elemSize1(), src_step = src.step1(); - int dst_offset = dst.offset / dst.elemSize1(), dst_step = dst.step1(); - int pixels_per_work_item = 1; - - if (Context::getContext()->supportsFeature(FEATURE_CL_INTEL_DEVICE)) - { - if ((src.cols % 4 == 0) && (src.depth() == CV_8U)) - pixels_per_work_item = 4; - else if (src.cols % 2 == 0) - pixels_per_work_item = 2; - else - pixels_per_work_item = 1; - } - - std::string build_options = format("-D DEPTH_%d -D dcn=%d -D bidx=%d -D pixels_per_work_item=%d", src.depth(), dst.channels(), bidx, pixels_per_work_item); - if (!additionalOptions.empty()) - build_options += additionalOptions; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_offset )); - - if (!data.empty()) - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&data.data )); - - size_t gt[3] = { dst.cols/pixels_per_work_item, dst.rows, 1 }; -#ifdef ANDROID - size_t lt[3] = { 16, 10, 1 }; -#else - size_t lt[3] = { 16, 16, 1 }; -#endif - openCLExecuteKernel(src.clCxt, &cvt_color, kernelName.c_str(), gt, lt, args, -1, -1, build_options.c_str()); -} - -static void toRGB_NV12_caller(const oclMat &src, oclMat &dst, int bidx, const std::string & kernelName, - const std::string & additionalOptions = std::string(), const oclMat & data = oclMat()) -{ - String build_options = format("-D DEPTH_%d -D dcn=%d -D bidx=%d", src.depth(), dst.channels(), bidx); - if (!additionalOptions.empty()) - build_options = build_options + additionalOptions; - - int src_offset = src.offset / src.elemSize1(), src_step = src.step1(); - int dst_offset = dst.offset / dst.elemSize1(), dst_step = dst.step1(); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_offset )); - - if (!data.empty()) - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&data.data )); - - size_t gt[3] = {src.cols, src.rows, 1}; -#ifdef ANDROID - size_t lt[3] = {16, 10, 1}; -#else - size_t lt[3] = {16, 16, 1}; -#endif - openCLExecuteKernel(src.clCxt, &cvt_color, kernelName.c_str(), gt, lt, args, -1, -1, build_options.c_str()); -} - -static void fromHSV_caller(const oclMat &src, oclMat &dst, int bidx, const std::string & kernelName, - const std::string & additionalOptions = std::string(), const oclMat & data = oclMat()) -{ - std::string build_options = format("-D DEPTH_%d -D dcn=%d -D bidx=%d", src.depth(), dst.channels(), bidx); - if (!additionalOptions.empty()) - build_options += additionalOptions; - - int src_offset = src.offset / src.elemSize1(), src_step = src.step1(); - int dst_offset = dst.offset / dst.elemSize1(), dst_step = dst.step1(); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_offset )); - - if (!data.empty()) - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&data.data )); - - size_t gt[3] = { dst.cols, dst.rows, 1 }; -#ifdef ANDROID - size_t lt[3] = { 16, 10, 1 }; -#else - size_t lt[3] = { 16, 16, 1 }; -#endif - openCLExecuteKernel(src.clCxt, &cvt_color, kernelName.c_str(), gt, lt, args, -1, -1, build_options.c_str()); -} - -static void RGB_caller(const oclMat &src, oclMat &dst, bool reverse) -{ - int src_offset = src.offset / src.elemSize1(), src_step = src.step1(); - int dst_offset = dst.offset / dst.elemSize1(), dst_step = dst.step1(); - - String build_options = format("-D DEPTH_%d -D dcn=%d -D scn=%d -D %s", - src.depth(), dst.channels(), src.channels(), reverse ? "REVERSE" : "ORDER"); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_offset )); - - size_t gt[3] = { dst.cols, dst.rows, 1 }; -#ifdef ANDROID - size_t lt[3] = { 16, 10, 1 }; -#else - size_t lt[3] = { 16, 16, 1 }; -#endif - openCLExecuteKernel(src.clCxt, &cvt_color, "RGB", gt, lt, args, -1, -1, build_options.c_str()); -} - -static void fromRGB5x5_caller(const oclMat &src, oclMat &dst, int bidx, int greenbits, const std::string & kernelName) -{ - String build_options = format("-D DEPTH_%d -D greenbits=%d -D dcn=%d -D bidx=%d", - src.depth(), greenbits, dst.channels(), bidx); - int src_offset = src.offset >> 1, src_step = src.step >> 1; - int dst_offset = dst.offset / dst.elemSize1(), dst_step = dst.step / dst.elemSize1(); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_offset )); - - size_t gt[3] = { dst.cols, dst.rows, 1 }; -#ifdef ANDROID - size_t lt[3] = { 16, 10, 1 }; -#else - size_t lt[3] = { 16, 16, 1 }; -#endif - openCLExecuteKernel(src.clCxt, &cvt_color, kernelName.c_str(), gt, lt, args, -1, -1, build_options.c_str()); -} - -static void toRGB5x5_caller(const oclMat &src, oclMat &dst, int bidx, int greenbits, const std::string & kernelName) -{ - String build_options = format("-D DEPTH_%d -D greenbits=%d -D scn=%d -D bidx=%d", - src.depth(), greenbits, src.channels(), bidx); - int src_offset = (int)src.offset, src_step = (int)src.step; - int dst_offset = dst.offset >> 1, dst_step = dst.step >> 1; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_offset )); - - size_t gt[3] = { dst.cols, dst.rows, 1 }; -#ifdef ANDROID - size_t lt[3] = { 16, 10, 1 }; -#else - size_t lt[3] = { 16, 16, 1 }; -#endif - openCLExecuteKernel(src.clCxt, &cvt_color, kernelName.c_str(), gt, lt, args, -1, -1, build_options.c_str()); -} - -static void cvtColor_caller(const oclMat &src, oclMat &dst, int code, int dcn) -{ - Size sz = src.size(); - int scn = src.channels(), depth = src.depth(), bidx; - - CV_Assert(depth == CV_8U || depth == CV_16U || depth == CV_32F); - - switch (code) - { - case COLOR_BGR2BGRA: case COLOR_RGB2BGRA: case COLOR_BGRA2BGR: - case COLOR_RGBA2BGR: case COLOR_RGB2BGR: case COLOR_BGRA2RGBA: - { - CV_Assert(scn == 3 || scn == 4); - dcn = code == COLOR_BGR2BGRA || code == COLOR_RGB2BGRA || code == COLOR_BGRA2RGBA ? 4 : 3; - bool reverse = !(code == COLOR_BGR2BGRA || code == COLOR_BGRA2BGR); - dst.create(sz, CV_MAKE_TYPE(depth, dcn)); - RGB_caller(src, dst, reverse); - break; - } - case COLOR_BGR2BGR565: case COLOR_BGR2BGR555: case COLOR_RGB2BGR565: case COLOR_RGB2BGR555: - case COLOR_BGRA2BGR565: case COLOR_BGRA2BGR555: case COLOR_RGBA2BGR565: case COLOR_RGBA2BGR555: - { - CV_Assert((scn == 3 || scn == 4) && depth == CV_8U ); - bidx = code == COLOR_BGR2BGR565 || code == COLOR_BGR2BGR555 || - code == COLOR_BGRA2BGR565 || code == COLOR_BGRA2BGR555 ? 0 : 2; - int greenbits = code == COLOR_BGR2BGR565 || code == COLOR_RGB2BGR565 || - code == COLOR_BGRA2BGR565 || code == COLOR_RGBA2BGR565 ? 6 : 5; - dst.create(sz, CV_8UC2); - toRGB5x5_caller(src, dst, bidx, greenbits, "RGB2RGB5x5"); - break; - } - case COLOR_BGR5652BGR: case COLOR_BGR5552BGR: case COLOR_BGR5652RGB: case COLOR_BGR5552RGB: - case COLOR_BGR5652BGRA: case COLOR_BGR5552BGRA: case COLOR_BGR5652RGBA: case COLOR_BGR5552RGBA: - { - dcn = code == COLOR_BGR5652BGRA || code == COLOR_BGR5552BGRA || code == COLOR_BGR5652RGBA || code == COLOR_BGR5552RGBA ? 4 : 3; - CV_Assert((dcn == 3 || dcn == 4) && scn == 2 && depth == CV_8U); - bidx = code == COLOR_BGR5652BGR || code == COLOR_BGR5552BGR || - code == COLOR_BGR5652BGRA || code == COLOR_BGR5552BGRA ? 0 : 2; - int greenbits = code == COLOR_BGR5652BGR || code == COLOR_BGR5652RGB || - code == COLOR_BGR5652BGRA || code == COLOR_BGR5652RGBA ? 6 : 5; - dst.create(sz, CV_MAKETYPE(depth, dcn)); - fromRGB5x5_caller(src, dst, bidx, greenbits, "RGB5x52RGB"); - break; - } - case COLOR_BGR5652GRAY: case COLOR_BGR5552GRAY: - { - CV_Assert(scn == 2 && depth == CV_8U); - dst.create(sz, CV_8UC1); - int greenbits = code == COLOR_BGR5652GRAY ? 6 : 5; - fromRGB5x5_caller(src, dst, -1, greenbits, "BGR5x52Gray"); - break; - } - case COLOR_GRAY2BGR565: case COLOR_GRAY2BGR555: - { - CV_Assert(scn == 1 && depth == CV_8U); - dst.create(sz, CV_8UC2); - int greenbits = code == COLOR_GRAY2BGR565 ? 6 : 5; - toRGB5x5_caller(src, dst, -1, greenbits, "Gray2BGR5x5"); - break; - } - case COLOR_RGB2GRAY: case COLOR_BGR2GRAY: case COLOR_RGBA2GRAY: case COLOR_BGRA2GRAY: - { - CV_Assert(scn == 3 || scn == 4); - bidx = code == COLOR_BGR2GRAY || code == COLOR_BGRA2GRAY ? 0 : 2; - dst.create(sz, CV_MAKETYPE(depth, 1)); - fromRGB_caller(src, dst, bidx, "RGB2Gray"); - break; - } - case COLOR_GRAY2BGR: case COLOR_GRAY2BGRA: - { - CV_Assert(scn == 1); - dcn = code == COLOR_GRAY2BGRA ? 4 : 3; - dst.create(sz, CV_MAKETYPE(depth, dcn)); - fromGray_caller(src, dst, 0, "Gray2RGB"); - break; - } - case COLOR_BGR2YUV: case COLOR_RGB2YUV: - { - CV_Assert(scn == 3 || scn == 4); - bidx = code == COLOR_BGR2YUV ? 0 : 2; - dst.create(sz, CV_MAKETYPE(depth, 3)); - fromRGB_caller(src, dst, bidx, "RGB2YUV"); - break; - } - case COLOR_YUV2BGR: case COLOR_YUV2RGB: - { - if( dcn <= 0 ) - dcn = 3; - CV_Assert(scn == 3 && (dcn == 3 || dcn == 4)); - bidx = code == COLOR_YUV2BGR ? 0 : 2; - dst.create(sz, CV_MAKETYPE(depth, dcn)); - toRGB_caller(src, dst, bidx, "YUV2RGB"); - break; - } - case COLOR_YUV2RGB_NV12: case COLOR_YUV2BGR_NV12: - case COLOR_YUV2RGBA_NV12: case COLOR_YUV2BGRA_NV12: - { - CV_Assert(scn == 1); - CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U ); - dcn = code == COLOR_YUV2BGRA_NV12 || code == COLOR_YUV2RGBA_NV12 ? 4 : 3; - bidx = code == COLOR_YUV2BGRA_NV12 || code == COLOR_YUV2BGR_NV12 ? 0 : 2; - - Size dstSz(sz.width, sz.height * 2 / 3); - dst.create(dstSz, CV_MAKETYPE(depth, dcn)); - toRGB_NV12_caller(src, dst, bidx, "YUV2RGBA_NV12"); - break; - } - case COLOR_BGR2YCrCb: case COLOR_RGB2YCrCb: - { - CV_Assert(scn == 3 || scn == 4); - bidx = code == COLOR_BGR2YCrCb ? 0 : 2; - dst.create(sz, CV_MAKETYPE(depth, 3)); - fromRGB_caller(src, dst, bidx, "RGB2YCrCb"); - break; - } - case COLOR_YCrCb2BGR: case COLOR_YCrCb2RGB: - { - if( dcn <= 0 ) - dcn = 3; - CV_Assert(scn == 3 && (dcn == 3 || dcn == 4)); - bidx = code == COLOR_YCrCb2BGR ? 0 : 2; - dst.create(sz, CV_MAKETYPE(depth, dcn)); - toRGB_caller(src, dst, bidx, "YCrCb2RGB"); - break; - } - case COLOR_BGR2XYZ: case COLOR_RGB2XYZ: - { - CV_Assert(scn == 3 || scn == 4); - bidx = code == COLOR_BGR2XYZ ? 0 : 2; - dst.create(sz, CV_MAKE_TYPE(depth, 3)); - - Mat c; - if (depth == CV_32F) - { - float coeffs[] = - { - 0.412453f, 0.357580f, 0.180423f, - 0.212671f, 0.715160f, 0.072169f, - 0.019334f, 0.119193f, 0.950227f - }; - if (bidx == 0) - { - std::swap(coeffs[0], coeffs[2]); - std::swap(coeffs[3], coeffs[5]); - std::swap(coeffs[6], coeffs[8]); - } - Mat(1, 9, CV_32FC1, &coeffs[0]).copyTo(c); - } - else - { - int coeffs[] = - { - 1689, 1465, 739, - 871, 2929, 296, - 79, 488, 3892 - }; - if (bidx == 0) - { - std::swap(coeffs[0], coeffs[2]); - std::swap(coeffs[3], coeffs[5]); - std::swap(coeffs[6], coeffs[8]); - } - Mat(1, 9, CV_32SC1, &coeffs[0]).copyTo(c); - } - oclMat oclCoeffs(c); - - fromRGB_caller(src, dst, bidx, "RGB2XYZ", "", oclCoeffs); - break; - } - case COLOR_XYZ2BGR: case COLOR_XYZ2RGB: - { - if (dcn <= 0) - dcn = 3; - CV_Assert(scn == 3 && (dcn == 3 || dcn == 4)); - bidx = code == COLOR_XYZ2BGR ? 0 : 2; - dst.create(sz, CV_MAKE_TYPE(depth, dcn)); - - Mat c; - if (depth == CV_32F) - { - float coeffs[] = - { - 3.240479f, -1.53715f, -0.498535f, - -0.969256f, 1.875991f, 0.041556f, - 0.055648f, -0.204043f, 1.057311f - }; - if (bidx == 0) - { - std::swap(coeffs[0], coeffs[6]); - std::swap(coeffs[1], coeffs[7]); - std::swap(coeffs[2], coeffs[8]); - } - Mat(1, 9, CV_32FC1, &coeffs[0]).copyTo(c); - } - else - { - int coeffs[] = - { - 13273, -6296, -2042, - -3970, 7684, 170, - 228, -836, 4331 - }; - if (bidx == 0) - { - std::swap(coeffs[0], coeffs[6]); - std::swap(coeffs[1], coeffs[7]); - std::swap(coeffs[2], coeffs[8]); - } - Mat(1, 9, CV_32SC1, &coeffs[0]).copyTo(c); - } - oclMat oclCoeffs(c); - - toRGB_caller(src, dst, bidx, "XYZ2RGB", "", oclCoeffs); - break; - } - case COLOR_BGR2HSV: case COLOR_RGB2HSV: case COLOR_BGR2HSV_FULL: case COLOR_RGB2HSV_FULL: - case COLOR_BGR2HLS: case COLOR_RGB2HLS: case COLOR_BGR2HLS_FULL: case COLOR_RGB2HLS_FULL: - { - CV_Assert((scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F)); - bidx = code == COLOR_BGR2HSV || code == COLOR_BGR2HLS || - code == COLOR_BGR2HSV_FULL || code == COLOR_BGR2HLS_FULL ? 0 : 2; - int hrange = depth == CV_32F ? 360 : code == COLOR_BGR2HSV || code == COLOR_RGB2HSV || - code == COLOR_BGR2HLS || code == COLOR_RGB2HLS ? 180 : 256; - bool is_hsv = code == COLOR_BGR2HSV || code == COLOR_RGB2HSV || code == COLOR_BGR2HSV_FULL || code == COLOR_RGB2HSV_FULL; - dst.create(sz, CV_MAKETYPE(depth, 3)); - std::string kernelName = std::string("RGB2") + (is_hsv ? "HSV" : "HLS"); - - if (is_hsv && depth == CV_8U) - { - static oclMat sdiv_data; - static oclMat hdiv_data180; - static oclMat hdiv_data256; - static int sdiv_table[256]; - static int hdiv_table180[256]; - static int hdiv_table256[256]; - static volatile bool initialized180 = false, initialized256 = false; - volatile bool & initialized = hrange == 180 ? initialized180 : initialized256; - - if (!initialized) - { - int * const hdiv_table = hrange == 180 ? hdiv_table180 : hdiv_table256, hsv_shift = 12; - oclMat & hdiv_data = hrange == 180 ? hdiv_data180 : hdiv_data256; - - sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0; - - int v = 255 << hsv_shift; - if (!initialized180 && !initialized256) - { - for(int i = 1; i < 256; i++ ) - sdiv_table[i] = saturate_cast(v/(1.*i)); - sdiv_data.upload(Mat(1, 256, CV_32SC1, sdiv_table)); - } - - v = hrange << hsv_shift; - for (int i = 1; i < 256; i++ ) - hdiv_table[i] = saturate_cast(v/(6.*i)); - - hdiv_data.upload(Mat(1, 256, CV_32SC1, hdiv_table)); - initialized = true; - } - - toHSV_caller(src, dst, bidx, kernelName, format(" -D hrange=%d", hrange), sdiv_data, hrange == 256 ? hdiv_data256 : hdiv_data180); - return; - } - - toHSV_caller(src, dst, bidx, kernelName, format(" -D hscale=%f", hrange*(1.f/360.f))); - break; - } - case COLOR_HSV2BGR: case COLOR_HSV2RGB: case COLOR_HSV2BGR_FULL: case COLOR_HSV2RGB_FULL: - case COLOR_HLS2BGR: case COLOR_HLS2RGB: case COLOR_HLS2BGR_FULL: case COLOR_HLS2RGB_FULL: - { - if (dcn <= 0) - dcn = 3; - CV_Assert(scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F)); - bidx = code == COLOR_HSV2BGR || code == COLOR_HLS2BGR || - code == COLOR_HSV2BGR_FULL || code == COLOR_HLS2BGR_FULL ? 0 : 2; - int hrange = depth == CV_32F ? 360 : code == COLOR_HSV2BGR || code == COLOR_HSV2RGB || - code == COLOR_HLS2BGR || code == COLOR_HLS2RGB ? 180 : 255; - bool is_hsv = code == COLOR_HSV2BGR || code == COLOR_HSV2RGB || - code == COLOR_HSV2BGR_FULL || code == COLOR_HSV2RGB_FULL; - - dst.create(sz, CV_MAKETYPE(depth, dcn)); - - std::string kernelName = std::string(is_hsv ? "HSV" : "HLS") + "2RGB"; - fromHSV_caller(src, dst, bidx, kernelName, format(" -D hrange=%d -D hscale=%f", hrange, 6.f/hrange)); - break; - } - case COLOR_RGBA2mRGBA: case COLOR_mRGBA2RGBA: - { - CV_Assert(scn == 4 && depth == CV_8U); - dst.create(sz, CV_MAKETYPE(depth, 4)); - std::string kernelName = code == COLOR_RGBA2mRGBA ? "RGBA2mRGBA" : "mRGBA2RGBA"; - - fromRGB_caller(src, dst, 0, kernelName); - break; - } - default: - CV_Error(Error::StsBadFlag, "Unknown/unsupported color conversion code" ); - } -} - -void cv::ocl::cvtColor(const oclMat &src, oclMat &dst, int code, int dcn) -{ - cvtColor_caller(src, dst, code, dcn); -} diff --git a/modules/ocl/src/columnsum.cpp b/modules/ocl/src/columnsum.cpp deleted file mode 100644 index ccbd960bc..000000000 --- a/modules/ocl/src/columnsum.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/*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 -// Chunpeng Zhang, chunpeng@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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -void cv::ocl::columnSum(const oclMat &src, oclMat &dst) -{ - CV_Assert(src.type() == CV_32FC1); - dst.create(src.size(), src.type()); - - int src_step = src.step / src.elemSize(), src_offset = src.offset / src.elemSize(); - int dst_step = dst.step / dst.elemSize(), dst_offset = dst.offset / dst.elemSize(); - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_offset)); - - size_t globalThreads[3] = {dst.cols, 1, 1}; - size_t localThreads[3] = {256, 1, 1}; - - openCLExecuteKernel(src.clCxt, &imgproc_columnsum, "columnSum", globalThreads, localThreads, args, src.oclchannels(), src.depth()); - -} diff --git a/modules/ocl/src/error.cpp b/modules/ocl/src/error.cpp deleted file mode 100644 index a1e2d807d..000000000 --- a/modules/ocl/src/error.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// -// 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 "precomp.hpp" - -using namespace cv; -using namespace cv::ocl; - -namespace cv -{ - namespace ocl - { - - const char *getOpenCLErrorString( int err ) - { - switch(err) - { - case CL_DEVICE_NOT_FOUND: - return "CL_DEVICE_NOT_FOUND"; - case CL_DEVICE_NOT_AVAILABLE: - return "CL_DEVICE_NOT_AVAILABLE"; - case CL_COMPILER_NOT_AVAILABLE: - return "CL_COMPILER_NOT_AVAILABLE"; - case CL_MEM_OBJECT_ALLOCATION_FAILURE: - return "CL_MEM_OBJECT_ALLOCATION_FAILURE"; - case CL_OUT_OF_RESOURCES: - return "CL_OUT_OF_RESOURCES"; - case CL_OUT_OF_HOST_MEMORY: - return "CL_OUT_OF_HOST_MEMORY"; - case CL_PROFILING_INFO_NOT_AVAILABLE: - return "CL_PROFILING_INFO_NOT_AVAILABLE"; - case CL_MEM_COPY_OVERLAP: - return "CL_MEM_COPY_OVERLAP"; - case CL_IMAGE_FORMAT_MISMATCH: - return "CL_IMAGE_FORMAT_MISMATCH"; - case CL_IMAGE_FORMAT_NOT_SUPPORTED: - return "CL_IMAGE_FORMAT_NOT_SUPPORTED"; - case CL_BUILD_PROGRAM_FAILURE: - return "CL_BUILD_PROGRAM_FAILURE"; - case CL_MAP_FAILURE: - return "CL_MAP_FAILURE"; - case CL_MISALIGNED_SUB_BUFFER_OFFSET: - return "CL_MISALIGNED_SUB_BUFFER_OFFSET"; - case CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST: - return "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST"; - case CL_INVALID_VALUE: - return "CL_INVALID_VALUE"; - case CL_INVALID_DEVICE_TYPE: - return "CL_INVALID_DEVICE_TYPE"; - case CL_INVALID_PLATFORM: - return "CL_INVALID_PLATFORM"; - case CL_INVALID_DEVICE: - return "CL_INVALID_DEVICE"; - case CL_INVALID_CONTEXT: - return "CL_INVALID_CONTEXT"; - case CL_INVALID_QUEUE_PROPERTIES: - return "CL_INVALID_QUEUE_PROPERTIES"; - case CL_INVALID_COMMAND_QUEUE: - return "CL_INVALID_COMMAND_QUEUE"; - case CL_INVALID_HOST_PTR: - return "CL_INVALID_HOST_PTR"; - case CL_INVALID_MEM_OBJECT: - return "CL_INVALID_MEM_OBJECT"; - case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR: - return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR"; - case CL_INVALID_IMAGE_SIZE: - return "CL_INVALID_IMAGE_SIZE"; - case CL_INVALID_SAMPLER: - return "CL_INVALID_SAMPLER"; - case CL_INVALID_BINARY: - return "CL_INVALID_BINARY"; - case CL_INVALID_BUILD_OPTIONS: - return "CL_INVALID_BUILD_OPTIONS"; - case CL_INVALID_PROGRAM: - return "CL_INVALID_PROGRAM"; - case CL_INVALID_PROGRAM_EXECUTABLE: - return "CL_INVALID_PROGRAM_EXECUTABLE"; - case CL_INVALID_KERNEL_NAME: - return "CL_INVALID_KERNEL_NAME"; - case CL_INVALID_KERNEL_DEFINITION: - return "CL_INVALID_KERNEL_DEFINITION"; - case CL_INVALID_KERNEL: - return "CL_INVALID_KERNEL"; - case CL_INVALID_ARG_INDEX: - return "CL_INVALID_ARG_INDEX"; - case CL_INVALID_ARG_VALUE: - return "CL_INVALID_ARG_VALUE"; - case CL_INVALID_ARG_SIZE: - return "CL_INVALID_ARG_SIZE"; - case CL_INVALID_KERNEL_ARGS: - return "CL_INVALID_KERNEL_ARGS"; - case CL_INVALID_WORK_DIMENSION: - return "CL_INVALID_WORK_DIMENSION"; - case CL_INVALID_WORK_GROUP_SIZE: - return "CL_INVALID_WORK_GROUP_SIZE"; - case CL_INVALID_WORK_ITEM_SIZE: - return "CL_INVALID_WORK_ITEM_SIZE"; - case CL_INVALID_GLOBAL_OFFSET: - return "CL_INVALID_GLOBAL_OFFSET"; - case CL_INVALID_EVENT_WAIT_LIST: - return "CL_INVALID_EVENT_WAIT_LIST"; - case CL_INVALID_EVENT: - return "CL_INVALID_EVENT"; - case CL_INVALID_OPERATION: - return "CL_INVALID_OPERATION"; - case CL_INVALID_GL_OBJECT: - return "CL_INVALID_GL_OBJECT"; - case CL_INVALID_BUFFER_SIZE: - return "CL_INVALID_BUFFER_SIZE"; - case CL_INVALID_MIP_LEVEL: - return "CL_INVALID_MIP_LEVEL"; - case CL_INVALID_GLOBAL_WORK_SIZE: - return "CL_INVALID_GLOBAL_WORK_SIZE"; - //case CL_INVALID_PROPERTY: - // return "CL_INVALID_PROPERTY"; - //case CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR: - // return "CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR"; - //case CL_PLATFORM_NOT_FOUND_KHR: - // return "CL_PLATFORM_NOT_FOUND_KHR"; - // //case CL_INVALID_PROPERTY_EXT: - // // return "CL_INVALID_PROPERTY_EXT"; - //case CL_DEVICE_PARTITION_FAILED_EXT: - // return "CL_DEVICE_PARTITION_FAILED_EXT"; - //case CL_INVALID_PARTITION_COUNT_EXT: - // return "CL_INVALID_PARTITION_COUNT_EXT"; - //default: - // return "unknown error code"; - } - static char buf[256]; - sprintf(buf, "%d", err); - return buf; - } - } -} diff --git a/modules/ocl/src/fast.cpp b/modules/ocl/src/fast.cpp deleted file mode 100644 index b32ea287b..000000000 --- a/modules/ocl/src/fast.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/*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. -// -// Authors: -// * Peter Andreas Entschev, peter@entschev.com -// -//M*/ - -#include "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -cv::ocl::FAST_OCL::FAST_OCL(int _threshold, bool _nonmaxSupression, double _keypointsRatio) : - nonmaxSupression(_nonmaxSupression), threshold(_threshold), keypointsRatio(_keypointsRatio), count_(0) -{ -} - -void cv::ocl::FAST_OCL::operator ()(const oclMat& image, const oclMat& mask, std::vector& keypoints) -{ - if (image.empty()) - return; - - (*this)(image, mask, d_keypoints_); - downloadKeypoints(d_keypoints_, keypoints); -} - -void cv::ocl::FAST_OCL::downloadKeypoints(const oclMat& d_keypoints, std::vector& keypoints) -{ - if (d_keypoints.empty()) - return; - - Mat h_keypoints(d_keypoints); - convertKeypoints(h_keypoints, keypoints); -} - -void cv::ocl::FAST_OCL::convertKeypoints(const Mat& h_keypoints, std::vector& keypoints) -{ - if (h_keypoints.empty()) - return; - - CV_Assert(h_keypoints.rows == ROWS_COUNT && h_keypoints.elemSize() == 4); - - int npoints = h_keypoints.cols; - - keypoints.resize(npoints); - - const float* loc_x = h_keypoints.ptr(X_ROW); - const float* loc_y = h_keypoints.ptr(Y_ROW); - const float* response_row = h_keypoints.ptr(RESPONSE_ROW); - - for (int i = 0; i < npoints; ++i) - { - KeyPoint kp(loc_x[i], loc_y[i], static_cast(FEATURE_SIZE), -1, response_row[i]); - keypoints[i] = kp; - } -} - -void cv::ocl::FAST_OCL::operator ()(const oclMat& img, const oclMat& mask, oclMat& keypoints) -{ - calcKeyPointsLocation(img, mask); - keypoints.cols = getKeyPoints(keypoints); -} - -int cv::ocl::FAST_OCL::calcKeyPointsLocation(const oclMat& img, const oclMat& mask) -{ - CV_Assert(img.type() == CV_8UC1); - CV_Assert(mask.empty() || (mask.type() == CV_8UC1 && mask.size() == img.size())); - - int maxKeypoints = static_cast(keypointsRatio * img.size().area()); - - ensureSizeIsEnough(ROWS_COUNT, maxKeypoints, CV_32SC1, kpLoc_); - kpLoc_.setTo(Scalar::all(0)); - - if (nonmaxSupression) - { - ensureSizeIsEnough(img.size(), CV_32SC1, score_); - score_.setTo(Scalar::all(0)); - } - - count_ = calcKeypointsOCL(img, mask, maxKeypoints); - count_ = std::min(count_, maxKeypoints); - - return count_; -} - -int cv::ocl::FAST_OCL::calcKeypointsOCL(const oclMat& img, const oclMat& mask, int maxKeypoints) -{ - size_t localThreads[3] = {16, 16, 1}; - size_t globalThreads[3] = {divUp(img.cols - 6, localThreads[0]) * localThreads[0], - divUp(img.rows - 6, localThreads[1]) * localThreads[1], - 1}; - - Context *clCxt = Context::getContext(); - String kernelName = (mask.empty()) ? "calcKeypoints" : "calcKeypointsWithMask"; - std::vector< std::pair > args; - - int counter = 0; - int err = CL_SUCCESS; - cl_mem counterCL = clCreateBuffer(*(cl_context*)clCxt->getOpenCLContextPtr(), - CL_MEM_COPY_HOST_PTR, sizeof(int), - &counter, &err); - - int kpLocStep = kpLoc_.step / kpLoc_.elemSize(); - int scoreStep = score_.step / score_.elemSize(); - int nms = (nonmaxSupression) ? 1 : 0; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&img.data)); - if (!mask.empty()) args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mask.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&kpLoc_.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&score_.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&counterCL)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&nms)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&maxKeypoints)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&threshold)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&img.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&img.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&img.cols)); - if (!mask.empty()) args.push_back( std::make_pair( sizeof(cl_int), (void *)&mask.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&kpLocStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&scoreStep)); - - openCLExecuteKernel(clCxt, &featdetect_fast, kernelName, globalThreads, localThreads, args, -1, -1); - - openCLSafeCall(clEnqueueReadBuffer(*(cl_command_queue*)clCxt->getOpenCLCommandQueuePtr(), - counterCL, CL_TRUE, 0, sizeof(int), &counter, 0, NULL, NULL)); - openCLSafeCall(clReleaseMemObject(counterCL)); - - return counter; -} - -int cv::ocl::FAST_OCL::nonmaxSupressionOCL(oclMat& keypoints) -{ - size_t localThreads[3] = {256, 1, 1}; - size_t globalThreads[3] = {count_, 1, 1}; - - Context *clCxt = Context::getContext(); - String kernelName = "nonmaxSupression"; - std::vector< std::pair > args; - - int counter = 0; - int err = CL_SUCCESS; - cl_mem counterCL = clCreateBuffer(*(cl_context*)clCxt->getOpenCLContextPtr(), - CL_MEM_COPY_HOST_PTR, sizeof(int), - &counter, &err); - - int kpLocStep = kpLoc_.step / kpLoc_.elemSize(); - int sStep = score_.step / score_.elemSize(); - int kStep = keypoints.step / keypoints.elemSize(); - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&kpLoc_.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&score_.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&keypoints.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&counterCL)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&count_)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&kpLocStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&sStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&kStep)); - - openCLExecuteKernel(clCxt, &featdetect_fast, kernelName, globalThreads, localThreads, args, -1, -1); - - openCLSafeCall(clEnqueueReadBuffer(*(cl_command_queue*)clCxt->getOpenCLCommandQueuePtr(), - counterCL, CL_TRUE, 0, sizeof(int), &counter, 0, NULL, NULL)); - openCLSafeCall(clReleaseMemObject(counterCL)); - - return counter; -} - -int cv::ocl::FAST_OCL::getKeyPoints(oclMat& keypoints) -{ - if (count_ == 0) - return 0; - - if (nonmaxSupression) - { - ensureSizeIsEnough(ROWS_COUNT, count_, CV_32FC1, keypoints); - return nonmaxSupressionOCL(keypoints); - } - - kpLoc_.convertTo(keypoints, CV_32FC1); - Mat k = keypoints; - - return count_; -} - -void cv::ocl::FAST_OCL::release() -{ - kpLoc_.release(); - score_.release(); - - d_keypoints_.release(); -} diff --git a/modules/ocl/src/fft.cpp b/modules/ocl/src/fft.cpp deleted file mode 100644 index 2cfffef5f..000000000 --- a/modules/ocl/src/fft.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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 "precomp.hpp" - -using namespace cv; -using namespace cv::ocl; - -#if !defined HAVE_CLAMDFFT - -void cv::ocl::dft(const oclMat&, oclMat&, Size, int) -{ - CV_Error(Error::OpenCLNoAMDBlasFft, "OpenCL DFT is not implemented"); -} - -namespace cv { namespace ocl { - void fft_teardown(); -} } - -void cv::ocl::fft_teardown() { } - -#else - -#include "opencv2/core/opencl/runtime/opencl_clamdfft.hpp" - -namespace cv -{ - namespace ocl - { - void fft_setup(); - void fft_teardown(); - - enum FftType - { - C2R = 1, // complex to complex - R2C = 2, // real to opencl HERMITIAN_INTERLEAVED - C2C = 3 // opencl HERMITIAN_INTERLEAVED to real - }; - - struct FftPlan - { - protected: - clAmdFftPlanHandle plHandle; - FftPlan& operator=(const FftPlan&); - public: - FftPlan(Size _dft_size, int _src_step, int _dst_step, int _depth, int _flags, FftType _type); - ~FftPlan(); - inline clAmdFftPlanHandle getPlanHandle() { return plHandle; } - - const Size dft_size; - const int src_step, dst_step; - const int depth; - const int flags; - const FftType type; - }; - - class PlanCache - { - protected: - PlanCache(); - ~PlanCache(); - static PlanCache* planCache; - - bool started; - std::vector planStore; - clAmdFftSetupData *setupData; - public: - friend void fft_setup(); - friend void fft_teardown(); - - static PlanCache* getPlanCache() - { - if (NULL == planCache) - planCache = new PlanCache(); - return planCache; - } - - // return a baked plan-> - // if there is one matched plan, return it - // if not, bake a new one, put it into the planStore and return it. - static FftPlan* getPlan(Size _dft_size, int _src_step, int _dst_step, int _depth, int _flags, FftType _type); - - // remove a single plan from the store - // return true if the plan is successfully removed - // else - static bool removePlan(clAmdFftPlanHandle ); - }; - } -} - -PlanCache* PlanCache::planCache = NULL; - -void cv::ocl::fft_setup() -{ - PlanCache& pCache = *PlanCache::getPlanCache(); - if(pCache.started) - { - return; - } - if (pCache.setupData == NULL) - pCache.setupData = new clAmdFftSetupData; - - openCLSafeCall(clAmdFftInitSetupData( pCache.setupData )); - pCache.started = true; -} - -void cv::ocl::fft_teardown() -{ - PlanCache& pCache = *PlanCache::getPlanCache(); - - if(!pCache.started) - return; - - for(size_t i = 0; i < pCache.planStore.size(); i ++) - delete pCache.planStore[i]; - pCache.planStore.clear(); - - try - { - openCLSafeCall( clAmdFftTeardown( ) ); - } - catch (const std::bad_alloc &) - { } - - delete pCache.setupData; pCache.setupData = NULL; - pCache.started = false; -} - -// bake a new plan -cv::ocl::FftPlan::FftPlan(Size _dft_size, int _src_step, int _dst_step, int _depth, int _flags, FftType _type) - : plHandle(0), dft_size(_dft_size), src_step(_src_step), dst_step(_dst_step), depth(_depth), flags(_flags), type(_type) -{ - fft_setup(); - - bool is_1d_input = (_dft_size.height == 1); - int is_row_dft = flags & DFT_ROWS; - int is_scaled_dft = flags & DFT_SCALE; - int is_inverse = flags & DFT_INVERSE; - - //clAmdFftResultLocation place; - clAmdFftLayout inLayout; - clAmdFftLayout outLayout; - clAmdFftDim dim = is_1d_input || is_row_dft ? CLFFT_1D : CLFFT_2D; - - size_t batchSize = is_row_dft ? dft_size.height : 1; - size_t clLengthsIn[ 3 ] = {1, 1, 1}; - size_t clStridesIn[ 3 ] = {1, 1, 1}; - //size_t clLengthsOut[ 3 ] = {1, 1, 1}; - size_t clStridesOut[ 3 ] = {1, 1, 1}; - clLengthsIn[0] = dft_size.width; - clLengthsIn[1] = is_row_dft ? 1 : dft_size.height; - clStridesIn[0] = 1; - clStridesOut[0] = 1; - - switch(_type) - { - case C2C: - inLayout = CLFFT_COMPLEX_INTERLEAVED; - outLayout = CLFFT_COMPLEX_INTERLEAVED; - clStridesIn[1] = src_step / (2*CV_ELEM_SIZE(_depth)); - clStridesOut[1] = dst_step / (2*CV_ELEM_SIZE(_depth)); - break; - case R2C: - inLayout = CLFFT_REAL; - outLayout = CLFFT_HERMITIAN_INTERLEAVED; - clStridesIn[1] = src_step / CV_ELEM_SIZE(_depth); - clStridesOut[1] = dst_step / (2*CV_ELEM_SIZE(_depth)); - break; - case C2R: - inLayout = CLFFT_HERMITIAN_INTERLEAVED; - outLayout = CLFFT_REAL; - clStridesIn[1] = src_step / (2*CV_ELEM_SIZE(_depth)); - clStridesOut[1] = dst_step / CV_ELEM_SIZE(_depth); - break; - default: - //std::runtime_error("does not support this convertion!"); - std::cout << "Does not support this convertion!" << std::endl; - throw std::exception(); - break; - } - - clStridesIn[2] = is_row_dft ? clStridesIn[1] : dft_size.width * clStridesIn[1]; - clStridesOut[2] = is_row_dft ? clStridesOut[1] : dft_size.width * clStridesOut[1]; - - openCLSafeCall( clAmdFftCreateDefaultPlan( &plHandle, *(cl_context*)getClContextPtr(), dim, clLengthsIn ) ); - - openCLSafeCall( clAmdFftSetPlanPrecision( plHandle, depth == CV_64F ? CLFFT_DOUBLE : CLFFT_SINGLE ) ); - openCLSafeCall( clAmdFftSetResultLocation( plHandle, CLFFT_OUTOFPLACE ) ); - openCLSafeCall( clAmdFftSetLayout( plHandle, inLayout, outLayout ) ); - openCLSafeCall( clAmdFftSetPlanBatchSize( plHandle, batchSize ) ); - - openCLSafeCall( clAmdFftSetPlanInStride ( plHandle, dim, clStridesIn ) ); - openCLSafeCall( clAmdFftSetPlanOutStride ( plHandle, dim, clStridesOut ) ); - openCLSafeCall( clAmdFftSetPlanDistance ( plHandle, clStridesIn[ dim ], clStridesOut[ dim ]) ); - - float scale_ = is_scaled_dft ? 1.f / _dft_size.area() : 1.f; - openCLSafeCall( clAmdFftSetPlanScale ( plHandle, is_inverse ? CLFFT_BACKWARD : CLFFT_FORWARD, scale_ ) ); - - //ready to bake - openCLSafeCall( clAmdFftBakePlan( plHandle, 1, (cl_command_queue*)getClCommandQueuePtr(), NULL, NULL ) ); -} - -cv::ocl::FftPlan::~FftPlan() -{ - openCLSafeCall( clAmdFftDestroyPlan( &plHandle ) ); -} - -cv::ocl::PlanCache::PlanCache() - : started(false), - planStore(std::vector()), - setupData(NULL) -{ -} - -cv::ocl::PlanCache::~PlanCache() -{ - fft_teardown(); -} - -FftPlan* cv::ocl::PlanCache::getPlan(Size _dft_size, int _src_step, int _dst_step, int _depth, int _flags, FftType _type) -{ - PlanCache& pCache = *PlanCache::getPlanCache(); - std::vector& pStore = pCache.planStore; - // go through search - for(size_t i = 0; i < pStore.size(); i ++) - { - FftPlan *plan = pStore[i]; - if( - plan->dft_size.width == _dft_size.width && - plan->dft_size.height == _dft_size.height && - plan->flags == _flags && - plan->src_step == _src_step && - plan->dst_step == _dst_step && - plan->depth == _depth && - plan->type == _type - ) - { - return plan; - } - } - // no baked plan is found - FftPlan *newPlan = new FftPlan(_dft_size, _src_step, _dst_step, _depth, _flags, _type); - pStore.push_back(newPlan); - return newPlan; -} - -bool cv::ocl::PlanCache::removePlan(clAmdFftPlanHandle plHandle) -{ - PlanCache& pCache = *PlanCache::getPlanCache(); - std::vector& pStore = pCache.planStore; - for(size_t i = 0; i < pStore.size(); i ++) - { - if(pStore[i]->getPlanHandle() == plHandle) - { - pStore.erase(pStore.begin() + i); - delete pStore[i]; - return true; - } - } - return false; -} - -void cv::ocl::dft(const oclMat &src, oclMat &dst, Size dft_size, int flags) -{ - CV_Assert(cv::ocl::haveAmdFft()); - - if(dft_size == Size(0, 0)) - { - dft_size = src.size(); - } - // check if the given dft size is of optimal dft size - CV_Assert(dft_size.area() == getOptimalDFTSize(dft_size.area())); - - // the two flags are not compatible - CV_Assert( !((flags & DFT_SCALE) && (flags & DFT_ROWS)) ); - - //bool is_1d_input = (src.rows == 1); - //int is_row_dft = flags & DFT_ROWS; - //int is_scaled_dft = flags & DFT_SCALE; - int is_inverse = flags & DFT_INVERSE; - bool is_complex_input = src.channels() == 2; - bool is_complex_output = !(flags & DFT_REAL_OUTPUT); - - int depth = src.depth(); - - // We don't support real-to-real transform - CV_Assert(is_complex_input || is_complex_output); - FftType type = (FftType)(is_complex_input << 0 | is_complex_output << 1); - - switch(type) - { - case C2C: - dst.create(src.rows, src.cols, CV_MAKE_TYPE(depth, 2)); - printf("C2C\n"); - break; - case R2C: - dst.create(src.rows, src.cols / 2 + 1, CV_MAKE_TYPE(depth, 2)); - printf("R2C\n"); - break; - case C2R: - CV_Assert(dft_size.width / 2 + 1 == src.cols && dft_size.height == src.rows); - dst.create(src.rows, dft_size.width, CV_MAKE_TYPE(depth, 1)); - printf("C2R\n"); - break; - default: - //std::runtime_error("does not support this convertion!"); - std::cout << "Does not support this convertion!" << std::endl; - throw std::exception(); - break; - } - clAmdFftPlanHandle plHandle = PlanCache::getPlan(dft_size, src.step, dst.step, depth, flags, type)->getPlanHandle(); - - //get the buffersize - size_t buffersize = 0; - openCLSafeCall( clAmdFftGetTmpBufSize(plHandle, &buffersize ) ); - - //allocate the intermediate buffer - // TODO, bind this with the current FftPlan - cl_mem clMedBuffer = NULL; - if (buffersize) - { - cl_int medstatus; - clMedBuffer = clCreateBuffer ( *(cl_context*)(src.clCxt->getOpenCLContextPtr()), CL_MEM_READ_WRITE, buffersize, 0, &medstatus); - openCLSafeCall( medstatus ); - } - cl_command_queue clq = *(cl_command_queue*)(src.clCxt->getOpenCLCommandQueuePtr()); - openCLSafeCall( clAmdFftEnqueueTransform( plHandle, - is_inverse ? CLFFT_BACKWARD : CLFFT_FORWARD, - 1, - &clq, - 0, NULL, NULL, - (cl_mem *)&src.data, (cl_mem *)&dst.data, clMedBuffer ) ); - openCLSafeCall( clFinish(clq) ); - if(clMedBuffer) - { - openCLFree(clMedBuffer); - } - fft_teardown(); -} - -#endif diff --git a/modules/ocl/src/filtering.cpp b/modules/ocl/src/filtering.cpp deleted file mode 100644 index b6e1fff4e..000000000 --- a/modules/ocl/src/filtering.cpp +++ /dev/null @@ -1,1710 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Jia Haipeng, jiahaipeng95@gmail.com -// Zero Lin, Zero.Lin@amd.com -// Zhang Ying, zhangying913@gmail.com -// Yao Wang, bitwangyaoyao@gmail.com -// Harris Gasparakis, harris.gasparakis@amd.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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -namespace -{ -inline void normalizeAnchor(int &anchor, int ksize) -{ - if (anchor < 0) - anchor = ksize >> 1; - - CV_Assert(0 <= anchor && anchor < ksize); -} - -inline void normalizeAnchor(Point &anchor, const Size &ksize) -{ - normalizeAnchor(anchor.x, ksize.width); - normalizeAnchor(anchor.y, ksize.height); -} - -inline void normalizeROI(Rect &roi, const Size &ksize, const Point &/*anchor*/, const Size &src_size) -{ - if (roi == Rect(0, 0, -1, -1)) - roi = Rect(0, 0, src_size.width, src_size.height); - - CV_Assert(ksize.height > 0 && ksize.width > 0 && ((ksize.height & 1) == 1) && ((ksize.width & 1) == 1)); - CV_Assert(roi.x >= 0 && roi.y >= 0 && roi.width <= src_size.width && roi.height <= src_size.height); -} -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Filter2D -namespace -{ -class Filter2DEngine_GPU : public FilterEngine_GPU -{ -public: - Filter2DEngine_GPU(const Ptr &filter2D_) : filter2D(filter2D_) {} - - virtual void apply(const oclMat &src, oclMat &dst, Rect roi = Rect(0, 0, -1, -1)) - { - Size src_size = src.size(); - - // Delete those two clause below which exist before, However, the result is also correct - // dst.create(src_size, src.type()); - // dst = Scalar(0.0); - - normalizeROI(roi, filter2D->ksize, filter2D->anchor, src_size); - - oclMat srcROI = src(roi); - oclMat dstROI = dst(roi); - - (*filter2D)(srcROI, dstROI); - } - - Ptr filter2D; -}; -} - -Ptr cv::ocl::createFilter2D_GPU(const Ptr filter2D) -{ - return makePtr(filter2D); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Box Filter -namespace -{ -typedef void (*FilterBox_t)(const oclMat & , oclMat & , Size &, const Point, const int); - -class GPUBoxFilter : public BaseFilter_GPU -{ -public: - GPUBoxFilter(const Size &ksize_, const Point &anchor_, const int borderType_, FilterBox_t func_) : - BaseFilter_GPU(ksize_, anchor_, borderType_), func(func_) {} - - virtual void operator()(const oclMat &src, oclMat &dst) - { - func(src, dst, ksize, anchor, borderType); - } - - FilterBox_t func; - -}; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Morphology Filter - -namespace -{ -typedef void (*GPUMorfFilter_t)(const oclMat & , oclMat & , oclMat & , Size &, const Point, bool rectKernel); - -class MorphFilter_GPU : public BaseFilter_GPU -{ -public: - MorphFilter_GPU(const Size &ksize_, const Point &anchor_, const Mat &kernel_, GPUMorfFilter_t func_) : - BaseFilter_GPU(ksize_, anchor_, BORDER_CONSTANT), kernel(kernel_), func(func_), rectKernel(false) {} - - virtual void operator()(const oclMat &src, oclMat &dst) - { - func(src, dst, kernel, ksize, anchor, rectKernel) ; - } - - oclMat kernel; - GPUMorfFilter_t func; - bool rectKernel; -}; -} - -/* -**We should be able to support any data types here. -**Extend this if necessary later. -**Note that the kernel need to be further refined. -*/ -static void GPUErode(const oclMat &src, oclMat &dst, oclMat &mat_kernel, - Size &ksize, const Point anchor, bool rectKernel) -{ - //Normalize the result by default - //float alpha = ksize.height * ksize.width; - CV_Assert(src.clCxt == dst.clCxt); - CV_Assert((src.cols == dst.cols) && - (src.rows == dst.rows)); - CV_Assert((src.oclchannels() == dst.oclchannels())); - - int srcStep = src.step / src.elemSize(); - int dstStep = dst.step / dst.elemSize(); - int srcOffset = src.offset / src.elemSize(); - int dstOffset = dst.offset / dst.elemSize(); - - int srcOffset_x = srcOffset % srcStep; - int srcOffset_y = srcOffset / srcStep; - Context *clCxt = src.clCxt; - String kernelName; -#ifdef ANDROID - size_t localThreads[3] = {16, 8, 1}; -#else - size_t localThreads[3] = {16, 16, 1}; -#endif - size_t globalThreads[3] = {(src.cols + localThreads[0] - 1) / localThreads[0] *localThreads[0], (src.rows + localThreads[1] - 1) / localThreads[1] *localThreads[1], 1}; - - if (src.type() == CV_8UC1) - { - kernelName = "morph_C1_D0"; - globalThreads[0] = ((src.cols + 3) / 4 + localThreads[0] - 1) / localThreads[0] * localThreads[0]; - CV_Assert(localThreads[0]*localThreads[1] * 8 >= (localThreads[0] * 4 + ksize.width - 1) * (localThreads[1] + ksize.height - 1)); - } - else - { - kernelName = "morph"; - CV_Assert(localThreads[0]*localThreads[1] * 2 >= (localThreads[0] + ksize.width - 1) * (localThreads[1] + ksize.height - 1)); - } - - char s[64]; - - switch (src.type()) - { - case CV_8UC1: - sprintf(s, "-D VAL=255"); - break; - case CV_8UC3: - case CV_8UC4: - sprintf(s, "-D VAL=255 -D GENTYPE=uchar4"); - break; - case CV_32FC1: - sprintf(s, "-D VAL=FLT_MAX -D GENTYPE=float"); - break; - case CV_32FC3: - case CV_32FC4: - sprintf(s, "-D VAL=FLT_MAX -D GENTYPE=float4"); - break; - default: - CV_Error(Error::StsUnsupportedFormat, "unsupported type"); - } - - char compile_option[128]; - sprintf(compile_option, "-D RADIUSX=%d -D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D ERODE %s %s", - anchor.x, anchor.y, (int)localThreads[0], (int)localThreads[1], - rectKernel?"-D RECTKERNEL":"", - s); - - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&src.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&dst.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&srcOffset_x)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&srcOffset_y)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&srcStep)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dstStep)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&mat_kernel.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.wholecols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.wholerows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dstOffset)); - - openCLExecuteKernel(clCxt, &filtering_morph, kernelName, globalThreads, localThreads, args, -1, -1, compile_option); -} - - -//! data type supported: CV_8UC1, CV_8UC4, CV_32FC1, CV_32FC4 -static void GPUDilate(const oclMat &src, oclMat &dst, oclMat &mat_kernel, - Size &ksize, const Point anchor, bool rectKernel) -{ - //Normalize the result by default - //float alpha = ksize.height * ksize.width; - CV_Assert(src.clCxt == dst.clCxt); - CV_Assert((src.cols == dst.cols) && - (src.rows == dst.rows)); - CV_Assert((src.oclchannels() == dst.oclchannels())); - - int srcStep = src.step1() / src.oclchannels(); - int dstStep = dst.step1() / dst.oclchannels(); - int srcOffset = src.offset / src.elemSize(); - int dstOffset = dst.offset / dst.elemSize(); - - int srcOffset_x = srcOffset % srcStep; - int srcOffset_y = srcOffset / srcStep; - Context *clCxt = src.clCxt; - String kernelName; -#ifdef ANDROID - size_t localThreads[3] = {16, 10, 1}; -#else - size_t localThreads[3] = {16, 16, 1}; -#endif - size_t globalThreads[3] = {(src.cols + localThreads[0] - 1) / localThreads[0] *localThreads[0], - (src.rows + localThreads[1] - 1) / localThreads[1] *localThreads[1], 1}; - - if (src.type() == CV_8UC1) - { - kernelName = "morph_C1_D0"; - globalThreads[0] = ((src.cols + 3) / 4 + localThreads[0] - 1) / localThreads[0] * localThreads[0]; - CV_Assert(localThreads[0]*localThreads[1] * 8 >= (localThreads[0] * 4 + ksize.width - 1) * (localThreads[1] + ksize.height - 1)); - } - else - { - kernelName = "morph"; - CV_Assert(localThreads[0]*localThreads[1] * 2 >= (localThreads[0] + ksize.width - 1) * (localThreads[1] + ksize.height - 1)); - } - - char s[64]; - - switch (src.type()) - { - case CV_8UC1: - sprintf(s, "-D VAL=0"); - break; - case CV_8UC3: - case CV_8UC4: - sprintf(s, "-D VAL=0 -D GENTYPE=uchar4"); - break; - case CV_32FC1: - sprintf(s, "-D VAL=-FLT_MAX -D GENTYPE=float"); - break; - case CV_32FC3: - case CV_32FC4: - sprintf(s, "-D VAL=-FLT_MAX -D GENTYPE=float4"); - break; - default: - CV_Error(Error::StsUnsupportedFormat, "unsupported type"); - } - - char compile_option[128]; - sprintf(compile_option, "-D RADIUSX=%d -D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D DILATE %s %s", - anchor.x, anchor.y, (int)localThreads[0], (int)localThreads[1], - s, rectKernel?"-D RECTKERNEL":""); - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&src.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&dst.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&srcOffset_x)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&srcOffset_y)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&srcStep)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dstStep)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&mat_kernel.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.wholecols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.wholerows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dstOffset)); - openCLExecuteKernel(clCxt, &filtering_morph, kernelName, globalThreads, localThreads, args, -1, -1, compile_option); -} - -Ptr cv::ocl::getMorphologyFilter_GPU(int op, int type, const Mat &_kernel, const Size &ksize, Point anchor) -{ - CV_Assert(op == MORPH_ERODE || op == MORPH_DILATE); - CV_Assert(type == CV_8UC1 || type == CV_8UC3 || type == CV_8UC4 || type == CV_32FC1 || type == CV_32FC3 || type == CV_32FC4); - - normalizeAnchor(anchor, ksize); - Mat kernel8U; - _kernel.convertTo(kernel8U, CV_8U); - Mat kernel = kernel8U.reshape(1, 1); - - bool noZero = true; - for(int i = 0; i < kernel.rows * kernel.cols; ++i) - if(kernel.at(i) != 1) - noZero = false; - - MorphFilter_GPU* mfgpu = new MorphFilter_GPU(ksize, anchor, kernel, op == MORPH_ERODE ? GPUErode : GPUDilate); - if(noZero) - mfgpu->rectKernel = true; - - return Ptr(mfgpu); -} - -namespace -{ -class MorphologyFilterEngine_GPU : public Filter2DEngine_GPU -{ -public: - MorphologyFilterEngine_GPU(const Ptr &filter2D_, int iters_) : - Filter2DEngine_GPU(filter2D_), iters(iters_) {} - - virtual void apply(const oclMat &src, oclMat &dst) - { - Filter2DEngine_GPU::apply(src, dst); - - for (int i = 1; i < iters; ++i) - { - Size wholesize; - Point ofs; - dst.locateROI(wholesize, ofs); - int rows = dst.rows, cols = dst.cols; - dst.adjustROI(ofs.y, -ofs.y - rows + dst.wholerows, ofs.x, -ofs.x - cols + dst.wholecols); - dst.copyTo(morfBuf); - dst.adjustROI(-ofs.y, ofs.y + rows - dst.wholerows, -ofs.x, ofs.x + cols - dst.wholecols); - morfBuf.adjustROI(-ofs.y, ofs.y + rows - dst.wholerows, -ofs.x, ofs.x + cols - dst.wholecols); - Filter2DEngine_GPU::apply(morfBuf, dst); - } - } - - int iters; - oclMat morfBuf; -}; -} - -Ptr cv::ocl::createMorphologyFilter_GPU(int op, int type, const Mat &kernel, const Point &anchor, int iterations) -{ - CV_Assert(iterations > 0); - - Size ksize = kernel.size(); - - Ptr filter2D = getMorphologyFilter_GPU(op, type, kernel, ksize, anchor); - - return makePtr(filter2D, iterations); -} - -namespace -{ -void morphOp(int op, const oclMat &src, oclMat &dst, const Mat &_kernel, Point anchor, int iterations, int borderType, const Scalar &borderValue) -{ - if ((borderType != cv::BORDER_CONSTANT) || (borderValue != morphologyDefaultBorderValue())) - { - CV_Error(Error::StsBadArg, "unsupported border type"); - } - - Mat kernel; - Size ksize = _kernel.data ? _kernel.size() : Size(3, 3); - - normalizeAnchor(anchor, ksize); - - if (iterations == 0 || _kernel.rows *_kernel.cols == 1) - { - src.copyTo(dst); - return; - } - - dst.create(src.size(), src.type()); - - if (!_kernel.data) - { - kernel = getStructuringElement(MORPH_RECT, Size(1 + iterations * 2, 1 + iterations * 2)); - anchor = Point(iterations, iterations); - iterations = 1; - } - else if (iterations > 1 && countNonZero(_kernel) == _kernel.rows * _kernel.cols) - { - anchor = Point(anchor.x * iterations, anchor.y * iterations); - kernel = getStructuringElement(MORPH_RECT, Size(ksize.width + (iterations - 1) * (ksize.width - 1), - ksize.height + (iterations - 1) * (ksize.height - 1)), anchor); - iterations = 1; - } - else - kernel = _kernel; - - Ptr f = createMorphologyFilter_GPU(op, src.type(), kernel, anchor, iterations) - .staticCast(); - - f->apply(src, dst); -} -} - -void cv::ocl::erode(const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor, int iterations, - int borderType, const Scalar &borderValue) -{ - bool allZero = true; - - for (int i = 0; i < kernel.rows * kernel.cols; ++i) - if (kernel.data[i] != 0) - allZero = false; - - if (allZero) - kernel.data[0] = 1; - - morphOp(MORPH_ERODE, src, dst, kernel, anchor, iterations, borderType, borderValue); -} - -void cv::ocl::dilate(const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor, int iterations, - int borderType, const Scalar &borderValue) -{ - morphOp(MORPH_DILATE, src, dst, kernel, anchor, iterations, borderType, borderValue); -} - -void cv::ocl::morphologyEx(const oclMat &src, oclMat &dst, int op, const Mat &kernel, Point anchor, int iterations, - int borderType, const Scalar &borderValue) -{ - oclMat temp; - - switch (op) - { - case MORPH_ERODE: - erode(src, dst, kernel, anchor, iterations, borderType, borderValue); - break; - case MORPH_DILATE: - dilate(src, dst, kernel, anchor, iterations, borderType, borderValue); - break; - case MORPH_OPEN: - erode(src, temp, kernel, anchor, iterations, borderType, borderValue); - dilate(temp, dst, kernel, anchor, iterations, borderType, borderValue); - break; - case MORPH_CLOSE: - dilate(src, temp, kernel, anchor, iterations, borderType, borderValue); - erode(temp, dst, kernel, anchor, iterations, borderType, borderValue); - break; - case MORPH_GRADIENT: - erode(src, temp, kernel, anchor, iterations, borderType, borderValue); - dilate(src, dst, kernel, anchor, iterations, borderType, borderValue); - subtract(dst, temp, dst); - break; - case MORPH_TOPHAT: - erode(src, dst, kernel, anchor, iterations, borderType, borderValue); - dilate(dst, temp, kernel, anchor, iterations, borderType, borderValue); - subtract(src, temp, dst); - break; - case MORPH_BLACKHAT: - dilate(src, dst, kernel, anchor, iterations, borderType, borderValue); - erode(dst, temp, kernel, anchor, iterations, borderType, borderValue); - subtract(temp, src, dst); - break; - default: - CV_Error(Error::StsBadArg, "unknown morphological operation"); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Linear Filter - -namespace -{ -typedef void (*GPUFilter2D_t)(const oclMat & , oclMat & , const Mat & , const Size &, const Point&, const int); - -class LinearFilter_GPU : public BaseFilter_GPU -{ -public: - LinearFilter_GPU(const Size &ksize_, const Point &anchor_, const Mat &kernel_, GPUFilter2D_t func_, - int borderType_) : - BaseFilter_GPU(ksize_, anchor_, borderType_), kernel(kernel_), func(func_) {} - - virtual void operator()(const oclMat &src, oclMat &dst) - { - func(src, dst, kernel, ksize, anchor, borderType) ; - } - - Mat kernel; - GPUFilter2D_t func; -}; -} - -// prepare kernel: transpose and make double rows (+align). Returns size of aligned row -// Samples: -// a b c -// Input: d e f -// g h i -// Output, last two zeros is the alignment: -// a d g a d g 0 0 -// b e h b e h 0 0 -// c f i c f i 0 0 -template -static int _prepareKernelFilter2D(std::vector& data, const Mat &kernel) -{ - Mat _kernel; kernel.convertTo(_kernel, DataDepth::value); - int size_y_aligned = roundUp(kernel.rows * 2, 4); - data.clear(); data.resize(size_y_aligned * kernel.cols, 0); - for (int x = 0; x < kernel.cols; x++) - { - for (int y = 0; y < kernel.rows; y++) - { - data[x * size_y_aligned + y] = _kernel.at(y, x); - data[x * size_y_aligned + y + kernel.rows] = _kernel.at(y, x); - } - } - return size_y_aligned; -} - -static void GPUFilter2D(const oclMat &src, oclMat &dst, const Mat &kernel, - const Size &ksize, const Point& anchor, const int borderType) -{ - CV_Assert(src.clCxt == dst.clCxt); - CV_Assert((src.cols == dst.cols) && - (src.rows == dst.rows)); - CV_Assert(src.oclchannels() == dst.oclchannels()); - - CV_Assert(kernel.cols == ksize.width && kernel.rows == ksize.height); - CV_Assert(kernel.channels() == 1); - - CV_Assert(anchor.x >= 0 && anchor.x < kernel.cols); - CV_Assert(anchor.y >= 0 && anchor.y < kernel.rows); - - bool useDouble = src.depth() == CV_64F; - - std::vector kernelDataFloat; - std::vector kernelDataDouble; - int kernel_size_y2_aligned = useDouble ? - _prepareKernelFilter2D(kernelDataDouble, kernel) - : _prepareKernelFilter2D(kernelDataFloat, kernel); - oclMat oclKernelParameter; - if (useDouble) - { - oclKernelParameter.createEx(1, kernelDataDouble.size(), CV_64FC1, DEVICE_MEM_R_ONLY, DEVICE_MEM_DEFAULT); - openCLMemcpy2D(src.clCxt, oclKernelParameter.data, kernelDataDouble.size()*sizeof(double), - &kernelDataDouble[0], kernelDataDouble.size()*sizeof(double), - kernelDataDouble.size()*sizeof(double), 1, clMemcpyHostToDevice); - } - else - { - oclKernelParameter.createEx(1, kernelDataFloat.size(), CV_32FC1, DEVICE_MEM_R_ONLY, DEVICE_MEM_DEFAULT); - openCLMemcpy2D(src.clCxt, oclKernelParameter.data, kernelDataFloat.size()*sizeof(float), - &kernelDataFloat[0], kernelDataFloat.size()*sizeof(float), - kernelDataFloat.size()*sizeof(float), 1, clMemcpyHostToDevice); - } - - size_t tryWorkItems = src.clCxt->getDeviceInfo().maxWorkItemSizes[0]; - do { - size_t BLOCK_SIZE = tryWorkItems; - while (BLOCK_SIZE > 32 && BLOCK_SIZE >= (size_t)ksize.width * 2 && BLOCK_SIZE > (size_t)src.cols * 2) - BLOCK_SIZE /= 2; -#if 1 // TODO Mode with several blocks requires a much more VGPRs, so this optimization is not actual for the current devices - size_t BLOCK_SIZE_Y = 1; -#else - size_t BLOCK_SIZE_Y = 8; // TODO Check heuristic value on devices - while (BLOCK_SIZE_Y < BLOCK_SIZE / 8 && BLOCK_SIZE_Y * src.clCxt->getDeviceInfo().maxComputeUnits * 32 < (size_t)src.rows) - BLOCK_SIZE_Y *= 2; -#endif - - CV_Assert((size_t)ksize.width <= BLOCK_SIZE); - - bool isIsolatedBorder = (borderType & BORDER_ISOLATED) != 0; - - std::vector > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data)); - cl_uint stepBytes = src.step; - args.push_back( std::make_pair( sizeof(cl_uint), (void *)&stepBytes)); - int offsetXBytes = src.offset % src.step; - int offsetX = offsetXBytes / src.elemSize(); - CV_Assert((int)(offsetX * src.elemSize()) == offsetXBytes); - int offsetY = src.offset / src.step; - int endX = (offsetX + src.cols); - int endY = (offsetY + src.rows); - cl_int rect[4] = {offsetX, offsetY, endX, endY}; - if (!isIsolatedBorder) - { - rect[2] = src.wholecols; - rect[3] = src.wholerows; - } - args.push_back( std::make_pair( sizeof(cl_int)*4, (void *)&rect[0])); - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data)); - cl_uint _stepBytes = dst.step; - args.push_back( std::make_pair( sizeof(cl_uint), (void *)&_stepBytes)); - int _offsetXBytes = dst.offset % dst.step; - int _offsetX = _offsetXBytes / dst.elemSize(); - CV_Assert((int)(_offsetX * dst.elemSize()) == _offsetXBytes); - int _offsetY = dst.offset / dst.step; - int _endX = (_offsetX + dst.cols); - int _endY = (_offsetY + dst.rows); - cl_int _rect[4] = {_offsetX, _offsetY, _endX, _endY}; - args.push_back( std::make_pair( sizeof(cl_int)*4, (void *)&_rect[0])); - - float borderValue[4] = {0, 0, 0, 0}; // DON'T move into 'if' body - double borderValueDouble[4] = {0, 0, 0, 0}; // DON'T move into 'if' body - if ((borderType & ~BORDER_ISOLATED) == BORDER_CONSTANT) - { - if (useDouble) - args.push_back( std::make_pair( sizeof(double) * src.oclchannels(), (void *)&borderValue[0])); - else - args.push_back( std::make_pair( sizeof(float) * src.oclchannels(), (void *)&borderValueDouble[0])); - } - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&oclKernelParameter.data)); - - const char* btype = NULL; - - switch (borderType & ~BORDER_ISOLATED) - { - case BORDER_CONSTANT: - btype = "BORDER_CONSTANT"; - break; - case BORDER_REPLICATE: - btype = "BORDER_REPLICATE"; - break; - case BORDER_REFLECT: - btype = "BORDER_REFLECT"; - break; - case BORDER_WRAP: - CV_Error(CV_StsUnsupportedFormat, "BORDER_WRAP is not supported!"); - return; - case BORDER_REFLECT101: - btype = "BORDER_REFLECT_101"; - break; - } - - int requiredTop = anchor.y; - int requiredLeft = BLOCK_SIZE; // not this: anchor.x; - int requiredBottom = ksize.height - 1 - anchor.y; - int requiredRight = BLOCK_SIZE; // not this: ksize.width - 1 - anchor.x; - int h = isIsolatedBorder ? src.rows : src.wholerows; - int w = isIsolatedBorder ? src.cols : src.wholecols; - bool extra_extrapolation = h < requiredTop || h < requiredBottom || w < requiredLeft || w < requiredRight; - - char build_options[1024]; - sprintf(build_options, "-D LOCAL_SIZE=%d -D BLOCK_SIZE_Y=%d -D DATA_DEPTH=%d -D DATA_CHAN=%d -D USE_DOUBLE=%d " - "-D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d -D KERNEL_SIZE_Y2_ALIGNED=%d " - "-D %s -D %s -D %s", - (int)BLOCK_SIZE, (int)BLOCK_SIZE_Y, - src.depth(), src.oclchannels(), useDouble ? 1 : 0, - anchor.x, anchor.y, ksize.width, ksize.height, kernel_size_y2_aligned, - btype, - extra_extrapolation ? "EXTRA_EXTRAPOLATION" : "NO_EXTRA_EXTRAPOLATION", - isIsolatedBorder ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED"); - - size_t lt[3] = {BLOCK_SIZE, 1, 1}; - size_t gt[3] = {divUp(dst.cols, BLOCK_SIZE - (ksize.width - 1)) * BLOCK_SIZE, divUp(dst.rows, BLOCK_SIZE_Y), 1}; - - cl_kernel kernel = openCLGetKernelFromSource(src.clCxt, &filtering_filter2D, "filter2D", -1, -1, build_options); - - size_t kernelWorkGroupSize; - openCLSafeCall(clGetKernelWorkGroupInfo(kernel, getClDeviceID(src.clCxt), - CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &kernelWorkGroupSize, 0)); - if (lt[0] > kernelWorkGroupSize) - { - clReleaseKernel(kernel); - CV_Assert(BLOCK_SIZE > kernelWorkGroupSize); - tryWorkItems = kernelWorkGroupSize; - continue; - } - - openCLExecuteKernel(src.clCxt, kernel, gt, lt, args); // kernel will be released here - } while (false); -} - -Ptr cv::ocl::getLinearFilter_GPU(int /*srcType*/, int /*dstType*/, const Mat &kernel, const Size &ksize, - const Point &anchor, int borderType) -{ - Point norm_archor = anchor; - normalizeAnchor(norm_archor, ksize); - - return Ptr(new LinearFilter_GPU(ksize, norm_archor, kernel, GPUFilter2D, - borderType)); -} - -Ptr cv::ocl::createLinearFilter_GPU(int srcType, int dstType, const Mat &kernel, const Point &anchor, - int borderType) -{ - Size ksize = kernel.size(); // TODO remove duplicated parameter - Ptr linearFilter = getLinearFilter_GPU(srcType, dstType, kernel, ksize, anchor, borderType); - - return createFilter2D_GPU(linearFilter); -} - -void cv::ocl::filter2D(const oclMat &src, oclMat &dst, int ddepth, const Mat &kernel, Point anchor, double delta, int borderType) -{ - CV_Assert(delta == 0); - - if (ddepth < 0) - ddepth = src.depth(); - - dst.create(src.size(), CV_MAKETYPE(ddepth, src.channels())); - - Ptr f = createLinearFilter_GPU(src.type(), dst.type(), kernel, anchor, borderType); - f->apply(src, dst); -} - -const int optimizedSepFilterLocalSize = 16; -static void sepFilter2D_SinglePass(const oclMat &src, oclMat &dst, - const Mat &row_kernel, const Mat &col_kernel, int bordertype = BORDER_DEFAULT) -{ - size_t lt2[3] = {optimizedSepFilterLocalSize, optimizedSepFilterLocalSize, 1}; - size_t gt2[3] = {lt2[0]*(1 + (src.cols-1) / lt2[0]), lt2[1]*(1 + (src.rows-1) / lt2[1]), 1}; - - unsigned int src_pitch = src.step; - unsigned int dst_pitch = dst.step; - - int src_offset_x = (src.offset % src.step) / src.elemSize(); - int src_offset_y = src.offset / src.step; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_uint) , (void *)&src_pitch )); - - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_offset_x )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_offset_y )); - - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.offset )); - args.push_back( std::make_pair( sizeof(cl_uint) , (void *)&dst_pitch )); - - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.wholecols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.wholerows )); - - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows )); - - String option = cv::format("-D BLK_X=%d -D BLK_Y=%d -D RADIUSX=%d -D RADIUSY=%d",(int)lt2[0], (int)lt2[1], - row_kernel.rows / 2, col_kernel.rows / 2 ); - - option += " -D KERNEL_MATRIX_X="; - for(int i=0; i( &row_kernel.at(i) ) ); - option += "0x0"; - - option += " -D KERNEL_MATRIX_Y="; - for(int i=0; i( &col_kernel.at(i) ) ); - option += "0x0"; - - switch(src.type()) - { - case CV_8UC1: - option += " -D SRCTYPE=uchar -D CONVERT_SRCTYPE=convert_float -D WORKTYPE=float"; - break; - case CV_32FC1: - option += " -D SRCTYPE=float -D CONVERT_SRCTYPE= -D WORKTYPE=float"; - break; - case CV_8UC2: - option += " -D SRCTYPE=uchar2 -D CONVERT_SRCTYPE=convert_float2 -D WORKTYPE=float2"; - break; - case CV_32FC2: - option += " -D SRCTYPE=float2 -D CONVERT_SRCTYPE= -D WORKTYPE=float2"; - break; - case CV_8UC3: - option += " -D SRCTYPE=uchar3 -D CONVERT_SRCTYPE=convert_float3 -D WORKTYPE=float3"; - break; - case CV_32FC3: - option += " -D SRCTYPE=float3 -D CONVERT_SRCTYPE= -D WORKTYPE=float3"; - break; - case CV_8UC4: - option += " -D SRCTYPE=uchar4 -D CONVERT_SRCTYPE=convert_float4 -D WORKTYPE=float4"; - break; - case CV_32FC4: - option += " -D SRCTYPE=float4 -D CONVERT_SRCTYPE= -D WORKTYPE=float4"; - break; - default: - CV_Error(CV_StsUnsupportedFormat, "Image type is not supported!"); - break; - } - switch(dst.type()) - { - case CV_8UC1: - option += " -D DSTTYPE=uchar -D CONVERT_DSTTYPE=convert_uchar_sat"; - break; - case CV_8UC2: - option += " -D DSTTYPE=uchar2 -D CONVERT_DSTTYPE=convert_uchar2_sat"; - break; - case CV_8UC3: - option += " -D DSTTYPE=uchar3 -D CONVERT_DSTTYPE=convert_uchar3_sat"; - break; - case CV_8UC4: - option += " -D DSTTYPE=uchar4 -D CONVERT_DSTTYPE=convert_uchar4_sat"; - break; - case CV_32FC1: - option += " -D DSTTYPE=float -D CONVERT_DSTTYPE="; - break; - case CV_32FC2: - option += " -D DSTTYPE=float2 -D CONVERT_DSTTYPE="; - break; - case CV_32FC3: - option += " -D DSTTYPE=float3 -D CONVERT_DSTTYPE="; - break; - case CV_32FC4: - option += " -D DSTTYPE=float4 -D CONVERT_DSTTYPE="; - break; - default: - CV_Error(CV_StsUnsupportedFormat, "Image type is not supported!"); - break; - } - switch(bordertype) - { - case cv::BORDER_CONSTANT: - option += " -D BORDER_CONSTANT"; - break; - case cv::BORDER_REPLICATE: - option += " -D BORDER_REPLICATE"; - break; - case cv::BORDER_REFLECT: - option += " -D BORDER_REFLECT"; - break; - case cv::BORDER_REFLECT101: - option += " -D BORDER_REFLECT_101"; - break; - case cv::BORDER_WRAP: - option += " -D BORDER_WRAP"; - break; - default: - CV_Error(CV_StsBadFlag, "BORDER type is not supported!"); - break; - } - - openCLExecuteKernel(src.clCxt, &filtering_sep_filter_singlepass, "sep_filter_singlepass", gt2, lt2, args, - -1, -1, option.c_str() ); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// SeparableFilter - -namespace -{ -class SeparableFilterEngine_GPU : public FilterEngine_GPU -{ -public: - SeparableFilterEngine_GPU(const Ptr &rowFilter_, - const Ptr &columnFilter_) : - rowFilter(rowFilter_), columnFilter(columnFilter_) - { - ksize = Size(rowFilter->ksize, columnFilter->ksize); - anchor = Point(rowFilter->anchor, columnFilter->anchor); - } - - virtual void apply(const oclMat &src, oclMat &dst, Rect roi = Rect(0, 0, -1, -1)) - { - Size src_size = src.size(); - - int cn = src.oclchannels(); - dstBuf.create(src_size.height + ksize.height - 1, src_size.width, CV_MAKETYPE(CV_32F, cn)); - - normalizeROI(roi, ksize, anchor, src_size); - - srcROI = src(roi); - dstROI = dst(roi); - - (*rowFilter)(srcROI, dstBuf); - (*columnFilter)(dstBuf, dstROI); - } - - Ptr rowFilter; - Ptr columnFilter; - Size ksize; - Point anchor; - oclMat dstBuf; - oclMat srcROI; - oclMat dstROI; - oclMat dstBufROI; -}; -} - -Ptr cv::ocl::createSeparableFilter_GPU(const Ptr &rowFilter, - const Ptr &columnFilter) -{ - return makePtr(rowFilter, columnFilter); -} - -namespace -{ -class SingleStepSeparableFilterEngine_GPU : public FilterEngine_GPU -{ -public: - SingleStepSeparableFilterEngine_GPU( const Mat &rowKernel_, const Mat &columnKernel_, const int btype ) - { - bordertype = btype; - rowKernel = rowKernel_; - columnKernel = columnKernel_; - } - - virtual void apply(const oclMat &src, oclMat &dst, Rect roi = Rect(0, 0, -1, -1)) - { - normalizeROI(roi, Size(rowKernel.rows, columnKernel.rows), Point(-1,-1), src.size()); - - oclMat srcROI = src(roi); - oclMat dstROI = dst(roi); - - sepFilter2D_SinglePass(src, dst, rowKernel, columnKernel, bordertype); - } - - Mat rowKernel; - Mat columnKernel; - int bordertype; -}; -} - - -static void GPUFilterBox(const oclMat &src, oclMat &dst, - Size &ksize, const Point anchor, const int borderType) -{ - //Normalize the result by default - float alpha = 1.0f / (ksize.height * ksize.width); - - CV_Assert(src.clCxt == dst.clCxt); - CV_Assert((src.cols == dst.cols) && - (src.rows == dst.rows)); - CV_Assert(src.oclchannels() == dst.oclchannels()); - - size_t tryWorkItems = src.clCxt->getDeviceInfo().maxWorkItemSizes[0]; - do { - size_t BLOCK_SIZE = tryWorkItems; - while (BLOCK_SIZE > 32 && BLOCK_SIZE >= (size_t)ksize.width * 2 && BLOCK_SIZE > (size_t)src.cols * 2) - BLOCK_SIZE /= 2; - size_t BLOCK_SIZE_Y = 8; // TODO Check heuristic value on devices - while (BLOCK_SIZE_Y < BLOCK_SIZE / 8 && BLOCK_SIZE_Y * src.clCxt->getDeviceInfo().maxComputeUnits * 32 < (size_t)src.rows) - BLOCK_SIZE_Y *= 2; - - CV_Assert((size_t)ksize.width <= BLOCK_SIZE); - - bool isIsolatedBorder = (borderType & BORDER_ISOLATED) != 0; - - std::vector > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data)); - cl_uint stepBytes = src.step; - args.push_back( std::make_pair( sizeof(cl_uint), (void *)&stepBytes)); - int offsetXBytes = src.offset % src.step; - int offsetX = offsetXBytes / src.elemSize(); - CV_Assert((int)(offsetX * src.elemSize()) == offsetXBytes); - int offsetY = src.offset / src.step; - int endX = (offsetX + src.cols); - int endY = (offsetY + src.rows); - cl_int rect[4] = {offsetX, offsetY, endX, endY}; - if (!isIsolatedBorder) - { - rect[2] = src.wholecols; - rect[3] = src.wholerows; - } - args.push_back( std::make_pair( sizeof(cl_int)*4, (void *)&rect[0])); - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data)); - cl_uint _stepBytes = dst.step; - args.push_back( std::make_pair( sizeof(cl_uint), (void *)&_stepBytes)); - int _offsetXBytes = dst.offset % dst.step; - int _offsetX = _offsetXBytes / dst.elemSize(); - CV_Assert((int)(_offsetX * dst.elemSize()) == _offsetXBytes); - int _offsetY = dst.offset / dst.step; - int _endX = (_offsetX + dst.cols); - int _endY = (_offsetY + dst.rows); - cl_int _rect[4] = {_offsetX, _offsetY, _endX, _endY}; - args.push_back( std::make_pair( sizeof(cl_int)*4, (void *)&_rect[0])); - - bool useDouble = src.depth() == CV_64F; - - float borderValue[4] = {0, 0, 0, 0}; // DON'T move into 'if' body - double borderValueDouble[4] = {0, 0, 0, 0}; // DON'T move into 'if' body - if ((borderType & ~BORDER_ISOLATED) == BORDER_CONSTANT) - { - if (useDouble) - args.push_back( std::make_pair( sizeof(double) * src.oclchannels(), (void *)&borderValue[0])); - else - args.push_back( std::make_pair( sizeof(float) * src.oclchannels(), (void *)&borderValueDouble[0])); - } - - double alphaDouble = alpha; // DON'T move into 'if' body - if (useDouble) - args.push_back( std::make_pair( sizeof(double), (void *)&alphaDouble)); - else - args.push_back( std::make_pair( sizeof(float), (void *)&alpha)); - - const char* btype = NULL; - - switch (borderType & ~BORDER_ISOLATED) - { - case BORDER_CONSTANT: - btype = "BORDER_CONSTANT"; - break; - case BORDER_REPLICATE: - btype = "BORDER_REPLICATE"; - break; - case BORDER_REFLECT: - btype = "BORDER_REFLECT"; - break; - case BORDER_WRAP: - CV_Error(CV_StsUnsupportedFormat, "BORDER_WRAP is not supported!"); - return; - case BORDER_REFLECT101: - btype = "BORDER_REFLECT_101"; - break; - } - - int requiredTop = anchor.y; - int requiredLeft = BLOCK_SIZE; // not this: anchor.x; - int requiredBottom = ksize.height - 1 - anchor.y; - int requiredRight = BLOCK_SIZE; // not this: ksize.width - 1 - anchor.x; - int h = isIsolatedBorder ? src.rows : src.wholerows; - int w = isIsolatedBorder ? src.cols : src.wholecols; - bool extra_extrapolation = h < requiredTop || h < requiredBottom || w < requiredLeft || w < requiredRight; - - CV_Assert(w >= ksize.width && h >= ksize.height); // TODO Other cases are not tested well - - char build_options[1024]; - sprintf(build_options, "-D LOCAL_SIZE=%d -D BLOCK_SIZE_Y=%d -D DATA_DEPTH=%d -D DATA_CHAN=%d -D USE_DOUBLE=%d -D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d -D %s -D %s -D %s", - (int)BLOCK_SIZE, (int)BLOCK_SIZE_Y, - src.depth(), src.oclchannels(), useDouble ? 1 : 0, - anchor.x, anchor.y, ksize.width, ksize.height, - btype, - extra_extrapolation ? "EXTRA_EXTRAPOLATION" : "NO_EXTRA_EXTRAPOLATION", - isIsolatedBorder ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED"); - - size_t lt[3] = {BLOCK_SIZE, 1, 1}; - size_t gt[3] = {divUp(dst.cols, BLOCK_SIZE - (ksize.width - 1)) * BLOCK_SIZE, divUp(dst.rows, BLOCK_SIZE_Y), 1}; - - cl_kernel kernel = openCLGetKernelFromSource(src.clCxt, &filtering_boxFilter, "boxFilter", -1, -1, build_options); - - size_t kernelWorkGroupSize; - openCLSafeCall(clGetKernelWorkGroupInfo(kernel, getClDeviceID(src.clCxt), - CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &kernelWorkGroupSize, 0)); - if (lt[0] > kernelWorkGroupSize) - { - clReleaseKernel(kernel); - CV_Assert(BLOCK_SIZE > kernelWorkGroupSize); - tryWorkItems = kernelWorkGroupSize; - continue; - } - - openCLExecuteKernel(src.clCxt, kernel, gt, lt, args); // kernel will be released here - } while (false); -} - -Ptr cv::ocl::getBoxFilter_GPU(int /*srcType*/, int /*dstType*/, - const Size &ksize, Point anchor, int borderType) -{ - normalizeAnchor(anchor, ksize); - - return Ptr(new GPUBoxFilter(ksize, anchor, - borderType, GPUFilterBox)); -} - -Ptr cv::ocl::createBoxFilter_GPU(int srcType, int dstType, - const Size &ksize, const Point &anchor, int borderType) -{ - Ptr boxFilter = getBoxFilter_GPU(srcType, dstType, ksize, anchor, borderType); - return createFilter2D_GPU(boxFilter); -} - -void cv::ocl::boxFilter(const oclMat &src, oclMat &dst, int ddepth, Size ksize, - Point anchor, int borderType) -{ - int sdepth = src.depth(), cn = src.channels(); - - if (ddepth < 0) - { - ddepth = sdepth; - } - - dst.create(src.size(), CV_MAKETYPE(ddepth, cn)); - - Ptr f = createBoxFilter_GPU(src.type(), - dst.type(), ksize, anchor, borderType); - f->apply(src, dst); -} - -namespace -{ -typedef void (*gpuFilter1D_t)(const oclMat &src, const oclMat &dst, oclMat kernel, int ksize, int anchor, int bordertype); - -class GpuLinearRowFilter : public BaseRowFilter_GPU -{ -public: - GpuLinearRowFilter(int ksize_, int anchor_, const oclMat &kernel_, gpuFilter1D_t func_, int bordertype_) : - BaseRowFilter_GPU(ksize_, anchor_, bordertype_), kernel(kernel_), func(func_) {} - - virtual void operator()(const oclMat &src, oclMat &dst) - { - func(src, dst, kernel, ksize, anchor, bordertype); - } - - oclMat kernel; - gpuFilter1D_t func; -}; -} - -template struct index_and_sizeof; -template <> struct index_and_sizeof -{ - enum { index = 1 }; -}; -template <> struct index_and_sizeof -{ - enum { index = 2 }; -}; -template <> struct index_and_sizeof -{ - enum { index = 3 }; -}; -template <> struct index_and_sizeof -{ - enum { index = 4 }; -}; -template <> struct index_and_sizeof -{ - enum { index = 5 }; -}; -template <> struct index_and_sizeof -{ - enum { index = 6 }; -}; - -template -void linearRowFilter_gpu(const oclMat &src, const oclMat &dst, oclMat mat_kernel, int ksize, int anchor, int bordertype) -{ - CV_Assert(bordertype <= BORDER_REFLECT_101); - CV_Assert(ksize == (anchor << 1) + 1); - int channels = src.oclchannels(); - -#ifdef ANDROID - size_t localThreads[3] = { 16, 10, 1 }; -#else - size_t localThreads[3] = { 16, 16, 1 }; -#endif - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - - const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101" }; - std::string buildOptions = format("-D RADIUSX=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D %s", - anchor, (int)localThreads[0], (int)localThreads[1], channels, borderMap[bordertype]); - - if (src.depth() == CV_8U) - { - switch (channels) - { - case 1: - globalThreads[0] = (dst.cols + 3) >> 2; - break; - case 2: - globalThreads[0] = (dst.cols + 1) >> 1; - break; - case 4: - globalThreads[0] = dst.cols; - break; - } - } - - int src_pix_per_row = src.step / src.elemSize(); - int src_offset_x = (src.offset % src.step) / src.elemSize(); - int src_offset_y = src.offset / src.step; - int dst_pix_per_row = dst.step / dst.elemSize(); - int ridusy = (dst.rows - src.rows) >> 1; - - std::vector > args; - args.push_back(std::make_pair(sizeof(cl_mem), &src.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &dst.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.wholecols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.wholerows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src_pix_per_row)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src_offset_x)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src_offset_y)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst_pix_per_row)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&ridusy)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&mat_kernel.data)); - - openCLExecuteKernel(src.clCxt, &filter_sep_row, "row_filter", globalThreads, localThreads, - args, channels, src.depth(), buildOptions.c_str()); -} - -Ptr cv::ocl::getLinearRowFilter_GPU(int srcType, int /*bufType*/, const Mat &rowKernel, int anchor, int bordertype) -{ - static const gpuFilter1D_t gpuFilter1D_callers[6] = - { - linearRowFilter_gpu, - linearRowFilter_gpu, - linearRowFilter_gpu, - linearRowFilter_gpu, - linearRowFilter_gpu, - linearRowFilter_gpu - }; - - Mat temp = rowKernel.reshape(1, 1); - oclMat mat_kernel(temp); - - - int ksize = temp.cols; - - //CV_Assert(ksize < 16); - - normalizeAnchor(anchor, ksize); - - return makePtr(ksize, anchor, mat_kernel, - gpuFilter1D_callers[CV_MAT_DEPTH(srcType)], bordertype); -} - -namespace -{ -class GpuLinearColumnFilter : public BaseColumnFilter_GPU -{ -public: - GpuLinearColumnFilter(int ksize_, int anchor_, const oclMat &kernel_, gpuFilter1D_t func_, int bordertype_) : - BaseColumnFilter_GPU(ksize_, anchor_, bordertype_), kernel(kernel_), func(func_) {} - - virtual void operator()(const oclMat &src, oclMat &dst) - { - func(src, dst, kernel, ksize, anchor, bordertype); - } - - oclMat kernel; - gpuFilter1D_t func; -}; -} - -template -void linearColumnFilter_gpu(const oclMat &src, const oclMat &dst, oclMat mat_kernel, int ksize, int anchor, int bordertype) -{ - Context *clCxt = src.clCxt; - int channels = src.oclchannels(); - -#ifdef ANDROID - size_t localThreads[3] = {16, 10, 1}; -#else - size_t localThreads[3] = {16, 16, 1}; -#endif - String kernelName = "col_filter"; - - char btype[30]; - - switch (bordertype) - { - case 0: - sprintf(btype, "BORDER_CONSTANT"); - break; - case 1: - sprintf(btype, "BORDER_REPLICATE"); - break; - case 2: - sprintf(btype, "BORDER_REFLECT"); - break; - case 3: - sprintf(btype, "BORDER_WRAP"); - break; - case 4: - sprintf(btype, "BORDER_REFLECT_101"); - break; - } - - char compile_option[256]; - - - size_t globalThreads[3]; - globalThreads[1] = (dst.rows + localThreads[1] - 1) / localThreads[1] * localThreads[1]; - globalThreads[2] = (1 + localThreads[2] - 1) / localThreads[2] * localThreads[2]; - - if (dst.depth() == CV_8U) - { - switch (channels) - { - case 1: - globalThreads[0] = (dst.cols + localThreads[0] - 1) / localThreads[0] * localThreads[0]; - sprintf(compile_option, "-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D %s -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s", - anchor, (int)localThreads[0], (int)localThreads[1], channels, btype, "float", "uchar", "convert_uchar_sat"); - break; - case 2: - globalThreads[0] = ((dst.cols + 1) / 2 + localThreads[0] - 1) / localThreads[0] * localThreads[0]; - sprintf(compile_option, "-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D %s -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s", - anchor, (int)localThreads[0], (int)localThreads[1], channels, btype, "float2", "uchar2", "convert_uchar2_sat"); - break; - case 3: - case 4: - globalThreads[0] = (dst.cols + localThreads[0] - 1) / localThreads[0] * localThreads[0]; - sprintf(compile_option, "-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D %s -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s", - anchor, (int)localThreads[0], (int)localThreads[1], channels, btype, "float4", "uchar4", "convert_uchar4_sat"); - break; - } - } - else - { - globalThreads[0] = (dst.cols + localThreads[0] - 1) / localThreads[0] * localThreads[0]; - - switch (dst.type()) - { - case CV_32SC1: - sprintf(compile_option, "-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D %s -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s", - anchor, (int)localThreads[0], (int)localThreads[1], channels, btype, "float", "int", "convert_int_sat"); - break; - case CV_32SC3: - case CV_32SC4: - sprintf(compile_option, "-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D %s -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s", - anchor, (int)localThreads[0], (int)localThreads[1], channels, btype, "float4", "int4", "convert_int4_sat"); - break; - case CV_32FC1: - sprintf(compile_option, "-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D %s -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s", - anchor, (int)localThreads[0], (int)localThreads[1], channels, btype, "float", "float", ""); - break; - case CV_32FC3: - case CV_32FC4: - sprintf(compile_option, "-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D %s -D GENTYPE_SRC=%s -D GENTYPE_DST=%s -D convert_to_DST=%s", - anchor, (int)localThreads[0], (int)localThreads[1], channels, btype, "float4", "float4", ""); - break; - } - } - - //sanity checks - CV_Assert(clCxt == dst.clCxt); - CV_Assert(src.cols == dst.cols); - CV_Assert(src.oclchannels() == dst.oclchannels()); - CV_Assert(ksize == (anchor << 1) + 1); - int src_pix_per_row, dst_pix_per_row; - int dst_offset_in_pixel; - src_pix_per_row = src.step / src.elemSize(); - dst_pix_per_row = dst.step / dst.elemSize(); - dst_offset_in_pixel = dst.offset / dst.elemSize(); - - std::vector > args; - args.push_back(std::make_pair(sizeof(cl_mem), &src.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &dst.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.wholecols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.wholerows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src_pix_per_row)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst_pix_per_row)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst_offset_in_pixel)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&mat_kernel.data)); - - openCLExecuteKernel(clCxt, &filter_sep_col, kernelName, globalThreads, localThreads, args, -1, -1, compile_option); -} - -Ptr cv::ocl::getLinearColumnFilter_GPU(int /*bufType*/, int dstType, const Mat &columnKernel, int anchor, int bordertype, double /*delta*/) -{ - static const gpuFilter1D_t gpuFilter1D_callers[6] = - { - linearColumnFilter_gpu, - linearColumnFilter_gpu, - linearColumnFilter_gpu, - linearColumnFilter_gpu, - linearColumnFilter_gpu, - linearColumnFilter_gpu - }; - - Mat temp = columnKernel.reshape(1, 1); - oclMat mat_kernel(temp); - - int ksize = temp.cols; - normalizeAnchor(anchor, ksize); - - return makePtr(ksize, anchor, mat_kernel, - gpuFilter1D_callers[CV_MAT_DEPTH(dstType)], bordertype); -} - -Ptr cv::ocl::createSeparableLinearFilter_GPU(int srcType, int dstType, - const Mat &rowKernel, const Mat &columnKernel, const Point &anchor, double delta, int bordertype, Size imgSize ) -{ - int sdepth = CV_MAT_DEPTH(srcType), ddepth = CV_MAT_DEPTH(dstType); - int cn = CV_MAT_CN(srcType); - int bdepth = std::max(std::max(sdepth, ddepth), CV_32F); - int bufType = CV_MAKETYPE(bdepth, cn); - Context* clCxt = Context::getContext(); - - //if image size is non-degenerate and large enough - //and if filter support is reasonable to satisfy larger local memory requirements, - //then we can use single pass routine to avoid extra runtime calls overhead - if( clCxt && clCxt->supportsFeature(FEATURE_CL_INTEL_DEVICE) && - rowKernel.rows <= 21 && columnKernel.rows <= 21 && - (rowKernel.rows & 1) == 1 && (columnKernel.rows & 1) == 1 && - imgSize.width > optimizedSepFilterLocalSize + (rowKernel.rows>>1) && - imgSize.height > optimizedSepFilterLocalSize + (columnKernel.rows>>1) ) - { - return Ptr(new SingleStepSeparableFilterEngine_GPU(rowKernel, columnKernel, bordertype)); - } - else - { - Ptr rowFilter = getLinearRowFilter_GPU(srcType, bufType, rowKernel, anchor.x, bordertype); - Ptr columnFilter = getLinearColumnFilter_GPU(bufType, dstType, columnKernel, anchor.y, bordertype, delta); - - return createSeparableFilter_GPU(rowFilter, columnFilter); - } -} - -void cv::ocl::sepFilter2D(const oclMat &src, oclMat &dst, int ddepth, const Mat &kernelX, const Mat &kernelY, Point anchor, double delta, int bordertype) -{ - if ((dst.cols != dst.wholecols) || (dst.rows != dst.wholerows)) //has roi - { - if ((bordertype & cv::BORDER_ISOLATED) != 0) - { - bordertype &= ~cv::BORDER_ISOLATED; - - if ((bordertype != cv::BORDER_CONSTANT) && - (bordertype != cv::BORDER_REPLICATE)) - { - CV_Error(Error::StsBadArg, "unsupported border type"); - } - } - } - - if (ddepth < 0) - ddepth = src.depth(); - - dst.create(src.size(), CV_MAKETYPE(ddepth, src.channels())); - - Ptr f = createSeparableLinearFilter_GPU(src.type(), dst.type(), kernelX, kernelY, anchor, delta, bordertype, src.size()); - f->apply(src, dst); -} - -Ptr cv::ocl::createDerivFilter_GPU(int srcType, int dstType, int dx, int dy, int ksize, int borderType, Size imgSize ) -{ - Mat kx, ky; - getDerivKernels(kx, ky, dx, dy, ksize, false, CV_32F); - return createSeparableLinearFilter_GPU(srcType, dstType, - kx, ky, Point(-1, -1), 0, borderType, imgSize); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Deriv Filter -void cv::ocl::Sobel(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType) -{ - Mat kx, ky; - getDerivKernels(kx, ky, dx, dy, ksize, false, CV_32F); - - if (scale != 1) - { - // usually the smoothing part is the slowest to compute, - // so try to scale it instead of the faster differenciating part - if (dx == 0) - kx *= scale; - else - ky *= scale; - } - - sepFilter2D(src, dst, ddepth, kx, ky, Point(-1, -1), delta, borderType); -} - -void cv::ocl::Scharr(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, double scale, double delta , int bordertype) -{ - Mat kx, ky; - getDerivKernels(kx, ky, dx, dy, -1, false, CV_32F); - - if (scale != 1) - { - // usually the smoothing part is the slowest to compute, - // so try to scale it instead of the faster differenciating part - if (dx == 0) - kx *= scale; - else - ky *= scale; - } - - sepFilter2D(src, dst, ddepth, kx, ky, Point(-1, -1), delta, bordertype); -} - -void cv::ocl::Laplacian(const oclMat &src, oclMat &dst, int ddepth, int ksize, double scale, - double delta, int borderType) -{ - CV_Assert(delta == 0); - - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.type() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_Assert(ksize == 1 || ksize == 3); - - double K[2][9] = - { - {0, 1, 0, 1, -4, 1, 0, 1, 0}, - {2, 0, 2, 0, -8, 0, 2, 0, 2} - }; - Mat kernel(3, 3, CV_64F, (void *)K[ksize == 3 ? 1 : 0]); - - if (scale != 1) - kernel *= scale; - - filter2D(src, dst, ddepth, kernel, Point(-1, -1), 0, borderType); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Gaussian Filter - -Ptr cv::ocl::createGaussianFilter_GPU(int type, Size ksize, double sigma1, double sigma2, int bordertype, Size imgSize) -{ - int depth = CV_MAT_DEPTH(type); - - if (sigma2 <= 0) - sigma2 = sigma1; - - // automatic detection of kernel size from sigma - if (ksize.width <= 0 && sigma1 > 0) - ksize.width = cvRound(sigma1 * (depth == CV_8U ? 3 : 4) * 2 + 1) | 1; - - if (ksize.height <= 0 && sigma2 > 0) - ksize.height = cvRound(sigma2 * (depth == CV_8U ? 3 : 4) * 2 + 1) | 1; - - CV_Assert(ksize.width > 0 && ksize.width % 2 == 1 && ksize.height > 0 && ksize.height % 2 == 1); - - sigma1 = std::max(sigma1, 0.0); - sigma2 = std::max(sigma2, 0.0); - - Mat kx = getGaussianKernel(ksize.width, sigma1, std::max(depth, CV_32F)); - Mat ky; - - if (ksize.height == ksize.width && std::abs(sigma1 - sigma2) < DBL_EPSILON) - ky = kx; - else - ky = getGaussianKernel(ksize.height, sigma2, std::max(depth, CV_32F)); - - return createSeparableLinearFilter_GPU(type, type, kx, ky, Point(-1, -1), 0.0, bordertype, imgSize); -} - -void cv::ocl::GaussianBlur(const oclMat &src, oclMat &dst, Size ksize, double sigma1, double sigma2, int bordertype) -{ - if (bordertype != BORDER_CONSTANT) - { - if (src.rows == 1) - ksize.height = 1; - - if (src.cols == 1) - ksize.width = 1; - } - - if (ksize.width == 1 && ksize.height == 1) - { - src.copyTo(dst); - return; - } - - if ((dst.cols != dst.wholecols) || (dst.rows != dst.wholerows)) //has roi - { - if ((bordertype & cv::BORDER_ISOLATED) != 0) - { - bordertype &= ~cv::BORDER_ISOLATED; - - if ((bordertype != cv::BORDER_CONSTANT) && - (bordertype != cv::BORDER_REPLICATE)) - { - CV_Error(Error::StsBadArg, "unsupported border type"); - } - } - } - - dst.create(src.size(), src.type()); - - Ptr f = createGaussianFilter_GPU(src.type(), ksize, sigma1, sigma2, bordertype, src.size()); - f->apply(src, dst); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Adaptive Bilateral Filter - -void cv::ocl::adaptiveBilateralFilter(const oclMat& src, oclMat& dst, Size ksize, double sigmaSpace, double maxSigmaColor, Point anchor, int borderType) -{ - CV_Assert((ksize.width & 1) && (ksize.height & 1)); // ksize must be odd - CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3); // source must be 8bit RGB image - if( sigmaSpace <= 0 ) - sigmaSpace = 1; - Mat lut(Size(ksize.width, ksize.height), CV_32FC1); - double sigma2 = sigmaSpace * sigmaSpace; - int idx = 0; - int w = ksize.width / 2; - int h = ksize.height / 2; - - int ABF_GAUSSIAN_ocl = 1; - - if(ABF_GAUSSIAN_ocl) - { - for(int y=-h; y<=h; y++) - for(int x=-w; x<=w; x++) - { - lut.at(idx++) = expf( (float)(-0.5 * (x * x + y * y)/sigma2)); - } - } - else - { - for(int y=-h; y<=h; y++) - for(int x=-w; x<=w; x++) - { - lut.at(idx++) = (float) (sigma2 / (sigma2 + x * x + y * y)); - } - } - - oclMat dlut(lut); - int depth = src.depth(); - int cn = src.oclchannels(); - - normalizeAnchor(anchor, ksize); - const static String kernelName = "adaptiveBilateralFilter"; - - dst.create(src.size(), src.type()); - - char btype[30]; - switch(borderType) - { - case BORDER_CONSTANT: - sprintf(btype, "BORDER_CONSTANT"); - break; - case BORDER_REPLICATE: - sprintf(btype, "BORDER_REPLICATE"); - break; - case BORDER_REFLECT: - sprintf(btype, "BORDER_REFLECT"); - break; - case BORDER_WRAP: - sprintf(btype, "BORDER_WRAP"); - break; - case BORDER_REFLECT101: - sprintf(btype, "BORDER_REFLECT_101"); - break; - default: - CV_Error(Error::StsBadArg, "This border type is not supported"); - break; - } - - //the following constants may be adjusted for performance concerns - const static size_t blockSizeX = 64, blockSizeY = 1, EXTRA = ksize.height - 1; - - //Normalize the result by default - const float alpha = ksize.height * ksize.width; - - const size_t gSize = blockSizeX - ksize.width / 2 * 2; - const size_t globalSizeX = (src.cols) % gSize == 0 ? - src.cols / gSize * blockSizeX : - (src.cols / gSize + 1) * blockSizeX; - const size_t rows_per_thread = 1 + EXTRA; - const size_t globalSizeY = ((src.rows + rows_per_thread - 1) / rows_per_thread) % blockSizeY == 0 ? - ((src.rows + rows_per_thread - 1) / rows_per_thread) : - (((src.rows + rows_per_thread - 1) / rows_per_thread) / blockSizeY + 1) * blockSizeY; - - size_t globalThreads[3] = { globalSizeX, globalSizeY, 1}; - size_t localThreads[3] = { blockSizeX, blockSizeY, 1}; - - char build_options[250]; - - //LDATATYPESIZE is sizeof local data store. This is to exemplify effect of LDS on kernel performance - sprintf(build_options, - "-D VAR_PER_CHANNEL=1 -D CALCVAR=1 -D FIXED_WEIGHT=0 -D EXTRA=%d -D MAX_VAR_VAL=%f -D ABF_GAUSSIAN=%d" - " -D THREADS=%d -D anX=%d -D anY=%d -D ksX=%d -D ksY=%d -D %s", - static_cast(EXTRA), static_cast(maxSigmaColor*maxSigmaColor), static_cast(ABF_GAUSSIAN_ocl), - static_cast(blockSizeX), anchor.x, anchor.y, ksize.width, ksize.height, btype); - - std::vector > args; - args.push_back(std::make_pair(sizeof(cl_mem), &src.data)); - args.push_back(std::make_pair(sizeof(cl_mem), &dst.data)); - args.push_back(std::make_pair(sizeof(cl_float), (void *)&alpha)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.offset)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.wholerows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.wholecols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.offset)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.step)); - args.push_back(std::make_pair(sizeof(cl_mem), &dlut.data)); - int lut_step = dlut.step1(); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&lut_step)); - - openCLExecuteKernel(Context::getContext(), &filtering_adaptive_bilateral, kernelName, - globalThreads, localThreads, args, cn, depth, build_options); -} diff --git a/modules/ocl/src/gemm.cpp b/modules/ocl/src/gemm.cpp deleted file mode 100644 index 50a2fdcce..000000000 --- a/modules/ocl/src/gemm.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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 "precomp.hpp" - -namespace cv { namespace ocl { - -// used for clAmdBlas library to avoid redundant setup/teardown -void clBlasSetup(); -void clBlasTeardown(); - -}} /* namespace cv { namespace ocl */ - - -#if !defined HAVE_CLAMDBLAS -void cv::ocl::gemm(const oclMat&, const oclMat&, double, - const oclMat&, double, oclMat&, int) -{ - CV_Error(Error::OpenCLNoAMDBlasFft, "OpenCL BLAS is not implemented"); -} - -void cv::ocl::clBlasSetup() -{ - CV_Error(Error::OpenCLNoAMDBlasFft, "OpenCL BLAS is not implemented"); -} - -void cv::ocl::clBlasTeardown() -{ - //intentionally do nothing -} - -#else -#include "opencv2/core/opencl/runtime/opencl_clamdblas.hpp" -using namespace cv; - -static bool clBlasInitialized = false; - -void cv::ocl::clBlasSetup() -{ - if(!clBlasInitialized) - { - AutoLock lock(getInitializationMutex()); - if(!clBlasInitialized) - { - openCLSafeCall(clAmdBlasSetup()); - clBlasInitialized = true; - } - } -} - -void cv::ocl::clBlasTeardown() -{ - AutoLock lock(getInitializationMutex()); - if(clBlasInitialized) - { - clAmdBlasTeardown(); - clBlasInitialized = false; - } -} - -void cv::ocl::gemm(const oclMat &src1, const oclMat &src2, double alpha, - const oclMat &src3, double beta, oclMat &dst, int flags) -{ - CV_Assert(src1.cols == src2.rows && - (src3.empty() || (src1.rows == src3.rows && src2.cols == src3.cols))); - CV_Assert(!(cv::GEMM_3_T & flags)); // cv::GEMM_3_T is not supported - if(!src3.empty()) - { - src3.copyTo(dst); - } - else - { - dst.create(src1.rows, src2.cols, src1.type()); - dst.setTo(Scalar::all(0)); - } - - clBlasSetup(); - - const clAmdBlasTranspose transA = (cv::GEMM_1_T & flags) ? clAmdBlasTrans : clAmdBlasNoTrans; - const clAmdBlasTranspose transB = (cv::GEMM_2_T & flags) ? clAmdBlasTrans : clAmdBlasNoTrans; - const clAmdBlasOrder order = clAmdBlasRowMajor; - - const int M = src1.rows; - const int N = src2.cols; - const int K = src1.cols; - int lda = src1.step; - int ldb = src2.step; - int ldc = dst.step; - int offa = src1.offset; - int offb = src2.offset; - int offc = dst.offset; - - cl_command_queue clq = *(cl_command_queue*)src1.clCxt->getOpenCLCommandQueuePtr(); - switch(src1.type()) - { - case CV_32FC1: - lda /= sizeof(float); - ldb /= sizeof(float); - ldc /= sizeof(float); - offa /= sizeof(float); - offb /= sizeof(float); - offc /= sizeof(float); - - openCLSafeCall - ( - clAmdBlasSgemmEx(order, transA, transB, M, N, K, - alpha, (const cl_mem)src1.data, offa, lda, (const cl_mem)src2.data, offb, ldb, - beta, (cl_mem)dst.data, offc, ldc, 1, &clq, 0, NULL, NULL) - ); - break; - case CV_64FC1: - lda /= sizeof(double); - ldb /= sizeof(double); - ldc /= sizeof(double); - offa /= sizeof(double); - offb /= sizeof(double); - offc /= sizeof(double); - openCLSafeCall - ( - clAmdBlasDgemmEx(order, transA, transB, M, N, K, - alpha, (const cl_mem)src1.data, offa, lda, (const cl_mem)src2.data, offb, ldb, - beta, (cl_mem)dst.data, offc, ldc, 1, &clq, 0, NULL, NULL) - ); - break; - case CV_32FC2: - { - lda /= (2*sizeof(float)); - ldb /= (2*sizeof(float)); - ldc /= (2*sizeof(float)); - offa /= (2*sizeof(float)); - offb /= (2*sizeof(float)); - offc /= (2*sizeof(float)); - cl_float2 alpha_2 = {{alpha, 0}}; - cl_float2 beta_2 = {{beta, 0}}; - openCLSafeCall - ( - clAmdBlasCgemmEx(order, transA, transB, M, N, K, - alpha_2, (const cl_mem)src1.data, offa, lda, (const cl_mem)src2.data, offb, ldb, - beta_2, (cl_mem)dst.data, offc, ldc, 1, &clq, 0, NULL, NULL) - ); - } - break; - case CV_64FC2: - { - lda /= (2*sizeof(double)); - ldb /= (2*sizeof(double)); - ldc /= (2*sizeof(double)); - offa /= (2*sizeof(double)); - offb /= (2*sizeof(double)); - offc /= (2*sizeof(double)); - cl_double2 alpha_2 = {{alpha, 0}}; - cl_double2 beta_2 = {{beta, 0}}; - openCLSafeCall - ( - clAmdBlasZgemmEx(order, transA, transB, M, N, K, - alpha_2, (const cl_mem)src1.data, offa, lda, (const cl_mem)src2.data, offb, ldb, - beta_2, (cl_mem)dst.data, offc, ldc, 1, &clq, 0, NULL, NULL) - ); - } - break; - } -} -#endif diff --git a/modules/ocl/src/gftt.cpp b/modules/ocl/src/gftt.cpp deleted file mode 100644 index 252313677..000000000 --- a/modules/ocl/src/gftt.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@outlook.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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -// compact structure for corners -struct DefCorner -{ - float eig; //eigenvalue of corner - short x; //x coordinate of corner point - short y; //y coordinate of corner point -}; - -// compare procedure for corner -//it is used for sort on the host side -struct DefCornerCompare : - public std::binary_function -{ - bool operator()(const DefCorner a, const DefCorner b) const - { - return a.eig > b.eig; - } -}; - -// find corners on matrix and put it into array -static void findCorners_caller( - const oclMat& eig_mat, //input matrix worth eigenvalues - oclMat& eigMinMax, //input with min and max values of eigenvalues - const float qualityLevel, - const oclMat& mask, - oclMat& corners, //output array with detected corners - oclMat& counter) //output value with number of detected corners, have to be 0 before call -{ - String opt; - std::vector k; - Context * cxt = Context::getContext(); - - std::vector< std::pair > args; - - const int mask_strip = mask.step / mask.elemSize1(); - - args.push_back(std::make_pair( sizeof(cl_mem), (void*)&(eig_mat.data))); - - int src_pitch = (int)eig_mat.step; - args.push_back(std::make_pair( sizeof(cl_int), (void*)&src_pitch )); - args.push_back(std::make_pair( sizeof(cl_mem), (void*)&mask.data )); - args.push_back(std::make_pair( sizeof(cl_mem), (void*)&corners.data )); - args.push_back(std::make_pair( sizeof(cl_int), (void*)&mask_strip)); - args.push_back(std::make_pair( sizeof(cl_mem), (void*)&eigMinMax.data )); - args.push_back(std::make_pair( sizeof(cl_float), (void*)&qualityLevel )); - args.push_back(std::make_pair( sizeof(cl_int), (void*)&eig_mat.rows )); - args.push_back(std::make_pair( sizeof(cl_int), (void*)&eig_mat.cols )); - args.push_back(std::make_pair( sizeof(cl_int), (void*)&corners.cols )); - args.push_back(std::make_pair( sizeof(cl_mem), (void*)&counter.data )); - - size_t globalThreads[3] = {eig_mat.cols, eig_mat.rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - if(!mask.empty()) - opt += " -D WITH_MASK=1"; - - openCLExecuteKernel(cxt, &imgproc_gftt, "findCorners", globalThreads, localThreads, args, -1, -1, opt.c_str()); -} - - -static void minMaxEig_caller(const oclMat &src, oclMat &dst, oclMat & tozero) -{ - size_t groupnum = src.clCxt->getDeviceInfo().maxComputeUnits; - CV_Assert(groupnum != 0); - - int dbsize = groupnum * 2 * src.elemSize(); - - ensureSizeIsEnough(1, dbsize, CV_8UC1, dst); - - cl_mem dst_data = reinterpret_cast(dst.data); - - int all_cols = src.step / src.elemSize(); - int pre_cols = (src.offset % src.step) / src.elemSize(); - int sec_cols = all_cols - (src.offset % src.step + src.cols * src.elemSize() - 1) / src.elemSize() - 1; - int invalid_cols = pre_cols + sec_cols; - int cols = all_cols - invalid_cols , elemnum = cols * src.rows; - int offset = src.offset / src.elemSize(); - - { - // first parallel pass - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst_data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&invalid_cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&offset)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&elemnum)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&groupnum)); - size_t globalThreads[3] = {groupnum * 256, 1, 1}; - size_t localThreads[3] = {256, 1, 1}; - openCLExecuteKernel(src.clCxt, &arithm_minMax, "arithm_op_minMax", globalThreads, localThreads, - args, -1, -1, "-D T=float -D DEPTH_5"); - } - - { - // run final "serial" kernel to find accumulate results from threads and reset corner counter - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst_data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&groupnum )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&tozero.data )); - size_t globalThreads[3] = {1, 1, 1}; - size_t localThreads[3] = {1, 1, 1}; - openCLExecuteKernel(src.clCxt, &imgproc_gftt, "arithm_op_minMax_final", globalThreads, localThreads, - args, -1, -1); - } -} - -void cv::ocl::GoodFeaturesToTrackDetector_OCL::operator ()(const oclMat& image, oclMat& corners, const oclMat& mask) -{ - CV_Assert(qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0); - CV_Assert(mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size())); - - ensureSizeIsEnough(image.size(), CV_32F, eig_); - - if (useHarrisDetector) - cornerHarris_dxdy(image, eig_, Dx_, Dy_, blockSize, 3, harrisK); - else - cornerMinEigenVal_dxdy(image, eig_, Dx_, Dy_, blockSize, 3); - - ensureSizeIsEnough(1,1, CV_32SC1, counter_); - - // find max eigenvalue and reset detected counters - minMaxEig_caller(eig_, eig_minmax_, counter_); - - // allocate buffer for kernels - int corner_array_size = std::max(1024, static_cast(image.size().area() * 0.05)); - ensureSizeIsEnough(1, corner_array_size , CV_32FC2, tmpCorners_); - - int total = tmpCorners_.cols; // by default the number of corner is full array - std::vector tmp(tmpCorners_.cols); // input buffer with corner for HOST part of algorithm - - // find points with high eigenvalue and put it into the output array - findCorners_caller(eig_, eig_minmax_, static_cast(qualityLevel), mask, tmpCorners_, counter_); - - // send non-blocking request to read real non-zero number of corners to sort it on the HOST side - openCLVerifyCall(clEnqueueReadBuffer(getClCommandQueue(counter_.clCxt), (cl_mem)counter_.data, CL_FALSE, 0, sizeof(int), &total, 0, NULL, NULL)); - - if (total == 0) - { - // check for trivial case - corners.release(); - return; - } - - // blocking read whole corners array (sorted or not sorted) - openCLReadBuffer(tmpCorners_.clCxt, (cl_mem)tmpCorners_.data, &tmp[0], tmpCorners_.cols * sizeof(DefCorner)); - - // sort detected corners on cpu side. - tmp.resize(total); - std::sort(tmp.begin(), tmp.end(), DefCornerCompare()); - - // estimate maximal size of final output array - int total_max = maxCorners > 0 ? std::min(maxCorners, total) : total; - int D2 = (int)ceil(minDistance * minDistance); - - // allocate output buffer - std::vector tmp2; - tmp2.reserve(total_max); - - - if (minDistance < 1) - { - // we have not distance restriction. then just copy with conversion maximal allowed points into output array - for (int i = 0; i < total_max; ++i) - tmp2.push_back(Point2f(tmp[i].x, tmp[i].y)); - } - else - { - // we have distance restriction. then start coping to output array from the first element and check distance for each next one - const int cell_size = cvRound(minDistance); - const int grid_width = (image.cols + cell_size - 1) / cell_size; - const int grid_height = (image.rows + cell_size - 1) / cell_size; - - std::vector< std::vector > grid(grid_width * grid_height); - - for (int i = 0; i < total ; ++i) - { - DefCorner p = tmp[i]; - bool good = true; - - int x_cell = static_cast(p.x / cell_size); - int y_cell = static_cast(p.y / cell_size); - - int x1 = x_cell - 1; - int y1 = y_cell - 1; - int x2 = x_cell + 1; - int y2 = y_cell + 1; - - // boundary check - x1 = std::max(0, x1); - y1 = std::max(0, y1); - x2 = std::min(grid_width - 1, x2); - y2 = std::min(grid_height - 1, y2); - - for (int yy = y1; yy <= y2; yy++) - { - for (int xx = x1; xx <= x2; xx++) - { - std::vector& m = grid[yy * grid_width + xx]; - if (m.empty()) - continue; - for(size_t j = 0; j < m.size(); j++) - { - int dx = p.x - m[j].x; - int dy = p.y - m[j].y; - - if (dx * dx + dy * dy < D2) - { - good = false; - goto break_out_; - } - } - } - } - - break_out_: - - if(good) - { - grid[y_cell * grid_width + x_cell].push_back(Point2i(p.x, p.y)); - tmp2.push_back(Point2f(p.x, p.y)); - - if (maxCorners > 0 && tmp2.size() == static_cast(maxCorners)) - break; - } - } - - } - - int final_size = static_cast(tmp2.size()); - if (final_size > 0) - corners.upload(Mat(1, final_size, CV_32FC2, &tmp2[0])); - else - corners.release(); -} - -void cv::ocl::GoodFeaturesToTrackDetector_OCL::downloadPoints(const oclMat &points, std::vector &points_v) -{ - CV_DbgAssert(points.type() == CV_32FC2); - points_v.resize(points.cols); - openCLSafeCall(clEnqueueReadBuffer( - *(cl_command_queue*)getClCommandQueuePtr(), - reinterpret_cast(points.data), - CL_TRUE, - 0, - points.cols * sizeof(Point2f), - &points_v[0], - 0, - NULL, - NULL)); -} diff --git a/modules/ocl/src/haar.cpp b/modules/ocl/src/haar.cpp deleted file mode 100644 index d38b3bad9..000000000 --- a/modules/ocl/src/haar.cpp +++ /dev/null @@ -1,1224 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Wang Weiyan, wangweiyanster@gmail.com -// Jia Haipeng, jiahaipeng95@gmail.com -// Wu Xinglong, wxl370@126.com -// Wang Yao, bitwangyaoyao@gmail.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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -/* these settings affect the quality of detection: change with care */ -#define CV_ADJUST_FEATURES 1 -#define CV_ADJUST_WEIGHTS 0 -#define CV_HAAR_FEATURE_MAX 3 -typedef int sumtype; -typedef double sqsumtype; - -typedef struct CvHidHaarFeature -{ - struct - { - sumtype *p0, *p1, *p2, *p3; - float weight; - } - rect[CV_HAAR_FEATURE_MAX]; -} -CvHidHaarFeature; - - -typedef struct CvHidHaarTreeNode -{ - CvHidHaarFeature feature; - float threshold; - int left; - int right; -} -CvHidHaarTreeNode; - - -typedef struct CvHidHaarClassifier -{ - int count; - //CvHaarFeature* orig_feature; - CvHidHaarTreeNode *node; - float *alpha; -} -CvHidHaarClassifier; - - -typedef struct CvHidHaarStageClassifier -{ - int count; - float threshold; - CvHidHaarClassifier *classifier; - int two_rects; - - struct CvHidHaarStageClassifier *next; - struct CvHidHaarStageClassifier *child; - struct CvHidHaarStageClassifier *parent; -} -CvHidHaarStageClassifier; - - -struct CvHidHaarClassifierCascade -{ - int count; - int is_stump_based; - int has_tilted_features; - int is_tree; - double inv_window_area; - CvMat sum, sqsum, tilted; - CvHidHaarStageClassifier *stage_classifier; - sqsumtype *pq0, *pq1, *pq2, *pq3; - sumtype *p0, *p1, *p2, *p3; - - void **ipp_stages; -}; -typedef struct -{ - int width_height; - int grpnumperline_totalgrp; - int imgoff; - float factor; -} detect_piramid_info; -#ifdef _MSC_VER -#define _ALIGNED_ON(_ALIGNMENT) __declspec(align(_ALIGNMENT)) - -typedef _ALIGNED_ON(128) struct GpuHidHaarTreeNode -{ - _ALIGNED_ON(64) int p[CV_HAAR_FEATURE_MAX][4]; - float weight[CV_HAAR_FEATURE_MAX] ; - float threshold ; - _ALIGNED_ON(16) float alpha[3] ; - _ALIGNED_ON(4) int left ; - _ALIGNED_ON(4) int right ; -} -GpuHidHaarTreeNode; - - -typedef _ALIGNED_ON(32) struct GpuHidHaarClassifier -{ - _ALIGNED_ON(4) int count; - _ALIGNED_ON(8) GpuHidHaarTreeNode *node ; - _ALIGNED_ON(8) float *alpha ; -} -GpuHidHaarClassifier; - - -typedef _ALIGNED_ON(64) struct GpuHidHaarStageClassifier -{ - _ALIGNED_ON(4) int count ; - _ALIGNED_ON(4) float threshold ; - _ALIGNED_ON(4) int two_rects ; - _ALIGNED_ON(8) GpuHidHaarClassifier *classifier ; - _ALIGNED_ON(8) struct GpuHidHaarStageClassifier *next; - _ALIGNED_ON(8) struct GpuHidHaarStageClassifier *child ; - _ALIGNED_ON(8) struct GpuHidHaarStageClassifier *parent ; -} -GpuHidHaarStageClassifier; - - -typedef _ALIGNED_ON(64) struct GpuHidHaarClassifierCascade -{ - _ALIGNED_ON(4) int count ; - _ALIGNED_ON(4) int is_stump_based ; - _ALIGNED_ON(4) int has_tilted_features ; - _ALIGNED_ON(4) int is_tree ; - _ALIGNED_ON(4) int pq0 ; - _ALIGNED_ON(4) int pq1 ; - _ALIGNED_ON(4) int pq2 ; - _ALIGNED_ON(4) int pq3 ; - _ALIGNED_ON(4) int p0 ; - _ALIGNED_ON(4) int p1 ; - _ALIGNED_ON(4) int p2 ; - _ALIGNED_ON(4) int p3 ; - _ALIGNED_ON(4) float inv_window_area ; -} GpuHidHaarClassifierCascade; -#else -#define _ALIGNED_ON(_ALIGNMENT) __attribute__((aligned(_ALIGNMENT) )) - -typedef struct _ALIGNED_ON(128) GpuHidHaarTreeNode -{ - int p[CV_HAAR_FEATURE_MAX][4] _ALIGNED_ON(64); - float weight[CV_HAAR_FEATURE_MAX];// _ALIGNED_ON(16); - float threshold;// _ALIGNED_ON(4); - float alpha[3] _ALIGNED_ON(16); - int left _ALIGNED_ON(4); - int right _ALIGNED_ON(4); -} -GpuHidHaarTreeNode; - -typedef struct _ALIGNED_ON(32) GpuHidHaarClassifier -{ - int count _ALIGNED_ON(4); - GpuHidHaarTreeNode *node _ALIGNED_ON(8); - float *alpha _ALIGNED_ON(8); -} -GpuHidHaarClassifier; - - -typedef struct _ALIGNED_ON(64) GpuHidHaarStageClassifier -{ - int count _ALIGNED_ON(4); - float threshold _ALIGNED_ON(4); - int two_rects _ALIGNED_ON(4); - GpuHidHaarClassifier *classifier _ALIGNED_ON(8); - struct GpuHidHaarStageClassifier *next _ALIGNED_ON(8); - struct GpuHidHaarStageClassifier *child _ALIGNED_ON(8); - struct GpuHidHaarStageClassifier *parent _ALIGNED_ON(8); -} -GpuHidHaarStageClassifier; - - -typedef struct _ALIGNED_ON(64) GpuHidHaarClassifierCascade -{ - int count _ALIGNED_ON(4); - int is_stump_based _ALIGNED_ON(4); - int has_tilted_features _ALIGNED_ON(4); - int is_tree _ALIGNED_ON(4); - int pq0 _ALIGNED_ON(4); - int pq1 _ALIGNED_ON(4); - int pq2 _ALIGNED_ON(4); - int pq3 _ALIGNED_ON(4); - int p0 _ALIGNED_ON(4); - int p1 _ALIGNED_ON(4); - int p2 _ALIGNED_ON(4); - int p3 _ALIGNED_ON(4); - float inv_window_area _ALIGNED_ON(4); -} GpuHidHaarClassifierCascade; -#endif - -const int icv_object_win_border = 1; -const float icv_stage_threshold_bias = 0.0001f; -double globaltime = 0; - -/* create more efficient internal representation of haar classifier cascade */ -static GpuHidHaarClassifierCascade * gpuCreateHidHaarClassifierCascade( CvHaarClassifierCascade *cascade, int *size, int *totalclassifier) -{ - GpuHidHaarClassifierCascade *out = 0; - - int i, j, k, l; - int datasize; - int total_classifiers = 0; - int total_nodes = 0; - char errorstr[256]; - - GpuHidHaarStageClassifier *stage_classifier_ptr; - GpuHidHaarClassifier *haar_classifier_ptr; - GpuHidHaarTreeNode *haar_node_ptr; - - CvSize orig_window_size; - int has_tilted_features = 0; - - if( !CV_IS_HAAR_CLASSIFIER(cascade) ) - CV_Error( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" ); - - if( cascade->hid_cascade ) - CV_Error( CV_StsError, "hid_cascade has been already created" ); - - if( !cascade->stage_classifier ) - CV_Error( CV_StsNullPtr, "" ); - - if( cascade->count <= 0 ) - CV_Error( CV_StsOutOfRange, "Negative number of cascade stages" ); - - orig_window_size = cascade->orig_window_size; - - /* check input structure correctness and calculate total memory size needed for - internal representation of the classifier cascade */ - for( i = 0; i < cascade->count; i++ ) - { - CvHaarStageClassifier *stage_classifier = cascade->stage_classifier + i; - - if( !stage_classifier->classifier || - stage_classifier->count <= 0 ) - { - sprintf( errorstr, "header of the stage classifier #%d is invalid " - "(has null pointers or non-positive classfier count)", i ); - CV_Error( CV_StsError, errorstr ); - } - - total_classifiers += stage_classifier->count; - - for( j = 0; j < stage_classifier->count; j++ ) - { - CvHaarClassifier *classifier = stage_classifier->classifier + j; - - total_nodes += classifier->count; - for( l = 0; l < classifier->count; l++ ) - { - for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ ) - { - if( classifier->haar_feature[l].rect[k].r.width ) - { - CvRect r = classifier->haar_feature[l].rect[k].r; - int tilted = classifier->haar_feature[l].tilted; - has_tilted_features |= tilted != 0; - if( r.width < 0 || r.height < 0 || r.y < 0 || - r.x + r.width > orig_window_size.width - || - (!tilted && - (r.x < 0 || r.y + r.height > orig_window_size.height)) - || - (tilted && (r.x - r.height < 0 || - r.y + r.width + r.height > orig_window_size.height))) - { - sprintf( errorstr, "rectangle #%d of the classifier #%d of " - "the stage classifier #%d is not inside " - "the reference (original) cascade window", k, j, i ); - CV_Error( CV_StsNullPtr, errorstr ); - } - } - } - } - } - } - - // this is an upper boundary for the whole hidden cascade size - datasize = sizeof(GpuHidHaarClassifierCascade) + - sizeof(GpuHidHaarStageClassifier) * cascade->count + - sizeof(GpuHidHaarClassifier) * total_classifiers + - sizeof(GpuHidHaarTreeNode) * total_nodes; - - *totalclassifier = total_classifiers; - *size = datasize; - out = (GpuHidHaarClassifierCascade *)cvAlloc( datasize ); - memset( out, 0, sizeof(*out) ); - - /* init header */ - out->count = cascade->count; - stage_classifier_ptr = (GpuHidHaarStageClassifier *)(out + 1); - haar_classifier_ptr = (GpuHidHaarClassifier *)(stage_classifier_ptr + cascade->count); - haar_node_ptr = (GpuHidHaarTreeNode *)(haar_classifier_ptr + total_classifiers); - - out->is_stump_based = 1; - out->has_tilted_features = has_tilted_features; - out->is_tree = 0; - - /* initialize internal representation */ - for( i = 0; i < cascade->count; i++ ) - { - CvHaarStageClassifier *stage_classifier = cascade->stage_classifier + i; - GpuHidHaarStageClassifier *hid_stage_classifier = stage_classifier_ptr + i; - - hid_stage_classifier->count = stage_classifier->count; - hid_stage_classifier->threshold = stage_classifier->threshold - icv_stage_threshold_bias; - hid_stage_classifier->classifier = haar_classifier_ptr; - hid_stage_classifier->two_rects = 1; - haar_classifier_ptr += stage_classifier->count; - - for( j = 0; j < stage_classifier->count; j++ ) - { - CvHaarClassifier *classifier = stage_classifier->classifier + j; - GpuHidHaarClassifier *hid_classifier = hid_stage_classifier->classifier + j; - int node_count = classifier->count; - - float *alpha_ptr = &haar_node_ptr->alpha[0]; - - hid_classifier->count = node_count; - hid_classifier->node = haar_node_ptr; - hid_classifier->alpha = alpha_ptr; - - for( l = 0; l < node_count; l++ ) - { - GpuHidHaarTreeNode *node = hid_classifier->node + l; - CvHaarFeature *feature = classifier->haar_feature + l; - - memset( node, -1, sizeof(*node) ); - node->threshold = classifier->threshold[l]; - node->left = classifier->left[l]; - node->right = classifier->right[l]; - - if( fabs(feature->rect[2].weight) < DBL_EPSILON || - feature->rect[2].r.width == 0 || - feature->rect[2].r.height == 0 ) - { - node->p[2][0] = 0; - node->p[2][1] = 0; - node->p[2][2] = 0; - node->p[2][3] = 0; - node->weight[2] = 0; - } - else - hid_stage_classifier->two_rects = 0; - - memcpy( node->alpha, classifier->alpha, (node_count + 1)*sizeof(alpha_ptr[0])); - haar_node_ptr = haar_node_ptr + 1; - } - out->is_stump_based &= node_count == 1; - } - } - - cascade->hid_cascade = (CvHidHaarClassifierCascade *)out; - assert( (char *)haar_node_ptr - (char *)out <= datasize ); - - return out; -} - - -#define sum_elem_ptr(sum,row,col) \ - ((sumtype*)CV_MAT_ELEM_PTR_FAST((sum),(row),(col),sizeof(sumtype))) - -#define sqsum_elem_ptr(sqsum,row,col) \ - ((sqsumtype*)CV_MAT_ELEM_PTR_FAST((sqsum),(row),(col),sizeof(sqsumtype))) - -#define calc_sum(rect,offset) \ - ((rect).p0[offset] - (rect).p1[offset] - (rect).p2[offset] + (rect).p3[offset]) - - -static void gpuSetImagesForHaarClassifierCascade( CvHaarClassifierCascade *_cascade, - double scale, - int step) -{ - GpuHidHaarClassifierCascade *cascade; - int coi0 = 0, coi1 = 0; - int i; - int datasize; - int total; - CvRect equRect; - double weight_scale; - GpuHidHaarStageClassifier *stage_classifier; - - if( !CV_IS_HAAR_CLASSIFIER(_cascade) ) - CV_Error( !_cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" ); - - if( scale <= 0 ) - CV_Error( CV_StsOutOfRange, "Scale must be positive" ); - - if( coi0 || coi1 ) - CV_Error( CV_BadCOI, "COI is not supported" ); - - if( !_cascade->hid_cascade ) - gpuCreateHidHaarClassifierCascade(_cascade, &datasize, &total); - - cascade = (GpuHidHaarClassifierCascade *) _cascade->hid_cascade; - stage_classifier = (GpuHidHaarStageClassifier *) (cascade + 1); - - _cascade->scale = scale; - _cascade->real_window_size.width = cvRound( _cascade->orig_window_size.width * scale ); - _cascade->real_window_size.height = cvRound( _cascade->orig_window_size.height * scale ); - - equRect.x = equRect.y = cvRound(scale); - equRect.width = cvRound((_cascade->orig_window_size.width - 2) * scale); - equRect.height = cvRound((_cascade->orig_window_size.height - 2) * scale); - weight_scale = 1. / (equRect.width * equRect.height); - cascade->inv_window_area = weight_scale; - - cascade->pq0 = equRect.x; - cascade->pq1 = equRect.y; - cascade->pq2 = equRect.x + equRect.width; - cascade->pq3 = equRect.y + equRect.height; - - cascade->p0 = equRect.x; - cascade->p1 = equRect.y; - cascade->p2 = equRect.x + equRect.width; - cascade->p3 = equRect.y + equRect.height; - - - /* init pointers in haar features according to real window size and - given image pointers */ - for( i = 0; i < _cascade->count; i++ ) - { - int j, k, l; - for( j = 0; j < stage_classifier[i].count; j++ ) - { - for( l = 0; l < stage_classifier[i].classifier[j].count; l++ ) - { - CvHaarFeature *feature = - &_cascade->stage_classifier[i].classifier[j].haar_feature[l]; - GpuHidHaarTreeNode *hidnode = &stage_classifier[i].classifier[j].node[l]; - double sum0 = 0, area0 = 0; - CvRect r[3]; - - int base_w = -1, base_h = -1; - int new_base_w = 0, new_base_h = 0; - int kx, ky; - int flagx = 0, flagy = 0; - int x0 = 0, y0 = 0; - int nr; - - /* align blocks */ - for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ ) - { - if(!hidnode->p[k][0]) - break; - r[k] = feature->rect[k].r; - base_w = (int)CV_IMIN( (unsigned)base_w, (unsigned)(r[k].width - 1) ); - base_w = (int)CV_IMIN( (unsigned)base_w, (unsigned)(r[k].x - r[0].x - 1) ); - base_h = (int)CV_IMIN( (unsigned)base_h, (unsigned)(r[k].height - 1) ); - base_h = (int)CV_IMIN( (unsigned)base_h, (unsigned)(r[k].y - r[0].y - 1) ); - } - - nr = k; - base_w += 1; - base_h += 1; - if(base_w == 0) - base_w = 1; - kx = r[0].width / base_w; - if(base_h == 0) - base_h = 1; - ky = r[0].height / base_h; - - if( kx <= 0 ) - { - flagx = 1; - new_base_w = cvRound( r[0].width * scale ) / kx; - x0 = cvRound( r[0].x * scale ); - } - - if( ky <= 0 ) - { - flagy = 1; - new_base_h = cvRound( r[0].height * scale ) / ky; - y0 = cvRound( r[0].y * scale ); - } - - for( k = 0; k < nr; k++ ) - { - CvRect tr; - double correction_ratio; - - if( flagx ) - { - tr.x = (r[k].x - r[0].x) * new_base_w / base_w + x0; - tr.width = r[k].width * new_base_w / base_w; - } - else - { - tr.x = cvRound( r[k].x * scale ); - tr.width = cvRound( r[k].width * scale ); - } - - if( flagy ) - { - tr.y = (r[k].y - r[0].y) * new_base_h / base_h + y0; - tr.height = r[k].height * new_base_h / base_h; - } - else - { - tr.y = cvRound( r[k].y * scale ); - tr.height = cvRound( r[k].height * scale ); - } - -#if CV_ADJUST_WEIGHTS - { - // RAINER START - const float orig_feature_size = (float)(feature->rect[k].r.width) * feature->rect[k].r.height; - const float orig_norm_size = (float)(_cascade->orig_window_size.width) * (_cascade->orig_window_size.height); - const float feature_size = float(tr.width * tr.height); - //const float normSize = float(equRect.width*equRect.height); - float target_ratio = orig_feature_size / orig_norm_size; - //float isRatio = featureSize / normSize; - //correctionRatio = targetRatio / isRatio / normSize; - correction_ratio = target_ratio / feature_size; - // RAINER END - } -#else - correction_ratio = weight_scale * (!feature->tilted ? 1 : 0.5); -#endif - - if( !feature->tilted ) - { - hidnode->p[k][0] = tr.x; - hidnode->p[k][1] = tr.y; - hidnode->p[k][2] = tr.x + tr.width; - hidnode->p[k][3] = tr.y + tr.height; - } - else - { - hidnode->p[k][2] = (tr.y + tr.width) * step + tr.x + tr.width; - hidnode->p[k][3] = (tr.y + tr.width + tr.height) * step + tr.x + tr.width - tr.height; - hidnode->p[k][0] = tr.y * step + tr.x; - hidnode->p[k][1] = (tr.y + tr.height) * step + tr.x - tr.height; - } - hidnode->weight[k] = (float)(feature->rect[k].weight * correction_ratio); - if( k == 0 ) - area0 = tr.width * tr.height; - else - sum0 += hidnode->weight[k] * tr.width * tr.height; - } - hidnode->weight[0] = (float)(-sum0 / area0); - } /* l */ - } /* j */ - } -} - -static void gpuSetHaarClassifierCascade( CvHaarClassifierCascade *_cascade) -{ - GpuHidHaarClassifierCascade *cascade; - int i; - int datasize; - int total; - CvRect equRect; - double weight_scale; - GpuHidHaarStageClassifier *stage_classifier; - - if( !CV_IS_HAAR_CLASSIFIER(_cascade) ) - CV_Error( !_cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" ); - - if( !_cascade->hid_cascade ) - gpuCreateHidHaarClassifierCascade(_cascade, &datasize, &total); - - cascade = (GpuHidHaarClassifierCascade *) _cascade->hid_cascade; - stage_classifier = (GpuHidHaarStageClassifier *) cascade + 1; - - _cascade->scale = 1.0; - _cascade->real_window_size.width = _cascade->orig_window_size.width ; - _cascade->real_window_size.height = _cascade->orig_window_size.height; - - equRect.x = equRect.y = 1; - equRect.width = _cascade->orig_window_size.width - 2; - equRect.height = _cascade->orig_window_size.height - 2; - weight_scale = 1; - cascade->inv_window_area = weight_scale; - - cascade->p0 = equRect.x; - cascade->p1 = equRect.y; - cascade->p2 = equRect.height; - cascade->p3 = equRect.width ; - for( i = 0; i < _cascade->count; i++ ) - { - int j, l; - for( j = 0; j < stage_classifier[i].count; j++ ) - { - for( l = 0; l < stage_classifier[i].classifier[j].count; l++ ) - { - const CvHaarFeature *feature = - &_cascade->stage_classifier[i].classifier[j].haar_feature[l]; - GpuHidHaarTreeNode *hidnode = &stage_classifier[i].classifier[j].node[l]; - - for( int k = 0; k < CV_HAAR_FEATURE_MAX; k++ ) - { - const CvRect tr = feature->rect[k].r; - if (tr.width == 0) - break; - double correction_ratio = weight_scale * (!feature->tilted ? 1 : 0.5); - hidnode->p[k][0] = tr.x; - hidnode->p[k][1] = tr.y; - hidnode->p[k][2] = tr.width; - hidnode->p[k][3] = tr.height; - hidnode->weight[k] = (float)(feature->rect[k].weight * correction_ratio); - } - } /* l */ - } /* j */ - } -} -void OclCascadeClassifier::detectMultiScale(oclMat &gimg, CV_OUT std::vector& faces, - double scaleFactor, int minNeighbors, int flags, - Size minSize, Size maxSize) -//CvSeq *cv::ocl::OclCascadeClassifier::oclHaarDetectObjects( oclMat &gimg, CvMemStorage *storage, double scaleFactor, -// int minNeighbors, int flags, CvSize minSize, CvSize maxSize) -{ - CvHaarClassifierCascade *cascade = (CvHaarClassifierCascade*)getOldCascade(); - - const double GROUP_EPS = 0.2; - - cv::ConcurrentRectVector allCandidates; - std::vector rectList; - std::vector rweights; - double factor; - int datasize=0; - int totalclassifier=0; - - GpuHidHaarClassifierCascade *gcascade; - GpuHidHaarStageClassifier *stage; - GpuHidHaarClassifier *classifier; - GpuHidHaarTreeNode *node; - - int *candidate; - cl_int status; - - bool findBiggestObject = (flags & CV_HAAR_FIND_BIGGEST_OBJECT) != 0; - - if( maxSize.height == 0 || maxSize.width == 0 ) - { - maxSize.height = gimg.rows; - maxSize.width = gimg.cols; - } - - if( !CV_IS_HAAR_CLASSIFIER(cascade) ) - CV_Error( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier cascade" ); - - //if( !storage ) - // CV_Error( CV_StsNullPtr, "Null storage pointer" ); - - if( CV_MAT_DEPTH(gimg.type()) != CV_8U ) - CV_Error( CV_StsUnsupportedFormat, "Only 8-bit images are supported" ); - - if( scaleFactor <= 1 ) - CV_Error( CV_StsOutOfRange, "scale factor must be > 1" ); - - if( findBiggestObject ) - flags &= ~CV_HAAR_SCALE_IMAGE; - - if( !cascade->hid_cascade ) - gpuCreateHidHaarClassifierCascade(cascade, &datasize, &totalclassifier); - - //result_seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvAvgComp), storage ); - - if( CV_MAT_CN(gimg.type()) > 1 ) - { - oclMat gtemp; - cvtColor( gimg, gtemp, COLOR_BGR2GRAY ); - gimg = gtemp; - } - - if( findBiggestObject ) - flags &= ~(CV_HAAR_SCALE_IMAGE | CV_HAAR_DO_CANNY_PRUNING); - - if( gimg.cols < minSize.width || gimg.rows < minSize.height ) - CV_Error(CV_StsError, "Image too small"); - - cl_command_queue qu = getClCommandQueue(Context::getContext()); - if( (flags & CV_HAAR_SCALE_IMAGE) ) - { - CvSize winSize0 = cascade->orig_window_size; - int totalheight = 0; - int indexy = 0; - CvSize sz; - std::vector sizev; - std::vector scalev; - for(factor = 1.f;; factor *= scaleFactor) - { - CvSize winSize( cvRound(winSize0.width * factor), cvRound(winSize0.height * factor) ); - sz.width = cvRound( gimg.cols / factor ) + 1; - sz.height = cvRound( gimg.rows / factor ) + 1; - CvSize sz1( sz.width - winSize0.width - 1, sz.height - winSize0.height - 1 ); - - if( sz1.width <= 0 || sz1.height <= 0 ) - break; - if( winSize.width > maxSize.width || winSize.height > maxSize.height ) - break; - if( winSize.width < minSize.width || winSize.height < minSize.height ) - continue; - - totalheight += sz.height; - sizev.push_back(sz); - scalev.push_back(factor); - } - - oclMat gimg1(gimg.rows, gimg.cols, CV_8UC1); - oclMat gsum(totalheight + 4, gimg.cols + 1, CV_32SC1); - oclMat gsqsum(totalheight + 4, gimg.cols + 1, CV_32FC1); - - int sdepth = 0; - if(Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - sdepth = CV_64FC1; - else - sdepth = CV_32FC1; - sdepth = CV_MAT_DEPTH(sdepth); - int type = CV_MAKE_TYPE(sdepth, 1); - oclMat gsqsum_t(totalheight + 4, gimg.cols + 1, type); - - cl_mem stagebuffer; - cl_mem nodebuffer; - cl_mem candidatebuffer; - cl_mem scaleinfobuffer; - cv::Rect roi, roi2; - cv::Mat imgroi, imgroisq; - cv::ocl::oclMat resizeroi, gimgroi, gimgroisq; - - int grp_per_CU = 12; - - size_t blocksize = 8; - size_t localThreads[3] = { blocksize, blocksize , 1 }; - size_t globalThreads[3] = { grp_per_CU *(gsum.clCxt->getDeviceInfo().maxComputeUnits) *localThreads[0], - localThreads[1], 1 - }; - int outputsz = 256 * globalThreads[0] / localThreads[0]; - int loopcount = sizev.size(); - detect_piramid_info *scaleinfo = (detect_piramid_info *)malloc(sizeof(detect_piramid_info) * loopcount); - - for( int i = 0; i < loopcount; i++ ) - { - sz = sizev[i]; - factor = scalev[i]; - roi = Rect(0, indexy, sz.width, sz.height); - roi2 = Rect(0, 0, sz.width - 1, sz.height - 1); - resizeroi = gimg1(roi2); - gimgroi = gsum(roi); - gimgroisq = gsqsum_t(roi); - int width = gimgroi.cols - 1 - cascade->orig_window_size.width; - int height = gimgroi.rows - 1 - cascade->orig_window_size.height; - scaleinfo[i].width_height = (width << 16) | height; - - - int grpnumperline = (width + localThreads[0] - 1) / localThreads[0]; - int totalgrp = ((height + localThreads[1] - 1) / localThreads[1]) * grpnumperline; - - scaleinfo[i].grpnumperline_totalgrp = (grpnumperline << 16) | totalgrp; - scaleinfo[i].imgoff = gimgroi.offset >> 2; - scaleinfo[i].factor = factor; - cv::ocl::resize(gimg, resizeroi, Size(sz.width - 1, sz.height - 1), 0, 0, INTER_LINEAR); - cv::ocl::integral(resizeroi, gimgroi, gimgroisq); - - indexy += sz.height; - } - if(gsqsum_t.depth() == CV_64F) - gsqsum_t.convertTo(gsqsum, CV_32FC1); - else - gsqsum = gsqsum_t; - - gcascade = (GpuHidHaarClassifierCascade *)cascade->hid_cascade; - stage = (GpuHidHaarStageClassifier *)(gcascade + 1); - classifier = (GpuHidHaarClassifier *)(stage + gcascade->count); - node = (GpuHidHaarTreeNode *)(classifier->node); - - int nodenum = (datasize - sizeof(GpuHidHaarClassifierCascade) - - sizeof(GpuHidHaarStageClassifier) * gcascade->count - sizeof(GpuHidHaarClassifier) * totalclassifier) / sizeof(GpuHidHaarTreeNode); - - candidate = (int *)malloc(4 * sizeof(int) * outputsz); - - gpuSetImagesForHaarClassifierCascade( cascade, 1., gsum.step / 4 ); - - stagebuffer = openCLCreateBuffer(gsum.clCxt, CL_MEM_READ_ONLY, sizeof(GpuHidHaarStageClassifier) * gcascade->count); - openCLSafeCall(clEnqueueWriteBuffer(qu, stagebuffer, 1, 0, sizeof(GpuHidHaarStageClassifier)*gcascade->count, stage, 0, NULL, NULL)); - - nodebuffer = openCLCreateBuffer(gsum.clCxt, CL_MEM_READ_ONLY, nodenum * sizeof(GpuHidHaarTreeNode)); - - openCLSafeCall(clEnqueueWriteBuffer(qu, nodebuffer, 1, 0, nodenum * sizeof(GpuHidHaarTreeNode), - node, 0, NULL, NULL)); - candidatebuffer = openCLCreateBuffer(gsum.clCxt, CL_MEM_WRITE_ONLY, 4 * sizeof(int) * outputsz); - - scaleinfobuffer = openCLCreateBuffer(gsum.clCxt, CL_MEM_READ_ONLY, sizeof(detect_piramid_info) * loopcount); - openCLSafeCall(clEnqueueWriteBuffer(qu, scaleinfobuffer, 1, 0, sizeof(detect_piramid_info)*loopcount, scaleinfo, 0, NULL, NULL)); - - int startstage = 0; - int endstage = gcascade->count; - int startnode = 0; - int pixelstep = gsum.step / 4; - int splitstage = 3; - int splitnode = stage[0].count + stage[1].count + stage[2].count; - cl_int4 p, pq; - p.s[0] = gcascade->p0; - p.s[1] = gcascade->p1; - p.s[2] = gcascade->p2; - p.s[3] = gcascade->p3; - pq.s[0] = gcascade->pq0; - pq.s[1] = gcascade->pq1; - pq.s[2] = gcascade->pq2; - pq.s[3] = gcascade->pq3; - float correction = gcascade->inv_window_area; - - std::vector > args; - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&stagebuffer )); - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&scaleinfobuffer )); - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&nodebuffer )); - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&gsum.data )); - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&gsqsum.data )); - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&candidatebuffer )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&pixelstep )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&loopcount )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&startstage )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&splitstage )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&endstage )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&startnode )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&splitnode )); - args.push_back ( std::make_pair(sizeof(cl_int4) , (void *)&p )); - args.push_back ( std::make_pair(sizeof(cl_int4) , (void *)&pq )); - args.push_back ( std::make_pair(sizeof(cl_float) , (void *)&correction )); - - if(gcascade->is_stump_based && gsum.clCxt->supportsFeature(FEATURE_CL_INTEL_DEVICE)) - { - //setup local group size for "pixel step" = 1 - localThreads[0] = 16; - localThreads[1] = 32; - localThreads[2] = 1; - - //calc maximal number of workgroups - int WGNumX = 1+(sizev[0].width /(localThreads[0])); - int WGNumY = 1+(sizev[0].height/(localThreads[1])); - int WGNumZ = loopcount; - int WGNumTotal = 0; //accurate number of non-empty workgroups - int WGNumSampled = 0; //accurate number of workgroups processed only 1/4 part of all pixels. it is made for large images with scale <= 2 - oclMat oclWGInfo(1,sizeof(cl_int4) * WGNumX*WGNumY*WGNumZ,CV_8U); - { - cl_int4* pWGInfo = (cl_int4*)clEnqueueMapBuffer(getClCommandQueue(oclWGInfo.clCxt),(cl_mem)oclWGInfo.datastart,true,CL_MAP_WRITE, 0, oclWGInfo.step, 0,0,0,&status); - openCLVerifyCall(status); - for(int z=0;z> 16)&0xFFFF; - int Height = (scaleinfo[z].width_height >> 0 )& 0xFFFF; - for(int y=0;y=(Height-cascade->orig_window_size.height)) - continue; // no data to process - for(int x=0;x=(Width-cascade->orig_window_size.width)) - continue; // no data to process - - if(scaleinfo[z].factor<=2) - { - WGNumSampled++; - } - // save no-empty workgroup info into array - pWGInfo[WGNumTotal].s[0] = scaleinfo[z].width_height; - pWGInfo[WGNumTotal].s[1] = (gx << 16) | gy; - pWGInfo[WGNumTotal].s[2] = scaleinfo[z].imgoff; - memcpy(&(pWGInfo[WGNumTotal].s[3]),&(scaleinfo[z].factor),sizeof(float)); - WGNumTotal++; - } - } - } - openCLSafeCall(clEnqueueUnmapMemObject(getClCommandQueue(oclWGInfo.clCxt),(cl_mem)oclWGInfo.datastart,pWGInfo,0,0,0)); - pWGInfo = NULL; - } - -#define NODE_SIZE 12 - // pack node info to have less memory loads on the device side - oclMat oclNodesPK(1,sizeof(cl_int) * NODE_SIZE * nodenum,CV_8U); - { - cl_int status; - cl_int* pNodesPK = (cl_int*)clEnqueueMapBuffer(getClCommandQueue(oclNodesPK.clCxt),(cl_mem)oclNodesPK.datastart,true,CL_MAP_WRITE, 0, oclNodesPK.step, 0,0,0,&status); - openCLVerifyCall(status); - //use known local data stride to precalulate indexes - int DATA_SIZE_X = (localThreads[0]+cascade->orig_window_size.width); - // check that maximal value is less than maximal unsigned short - assert(DATA_SIZE_X*cascade->orig_window_size.height+cascade->orig_window_size.width < (int)USHRT_MAX); - for(int i = 0;islm_index[k][0] = (unsigned short)(p[1]*DATA_SIZE_X+p[0]); - pOut->slm_index[k][1] = (unsigned short)(p[1]*DATA_SIZE_X+p[2]); - pOut->slm_index[k][2] = (unsigned short)(p[3]*DATA_SIZE_X+p[0]); - pOut->slm_index[k][3] = (unsigned short)(p[3]*DATA_SIZE_X+p[2]); - } - //store used float point values for each node - pOut->weight[0] = node[i].weight[0]; - pOut->weight[1] = node[i].weight[1]; - pOut->weight[2] = node[i].weight[2]; - pOut->threshold = node[i].threshold; - pOut->alpha[0] = node[i].alpha[0]; - pOut->alpha[1] = node[i].alpha[1]; - } - openCLSafeCall(clEnqueueUnmapMemObject(getClCommandQueue(oclNodesPK.clCxt),(cl_mem)oclNodesPK.datastart,pNodesPK,0,0,0)); - pNodesPK = NULL; - } - // add 2 additional buffers (WGinfo and packed nodes) as 2 last args - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&oclNodesPK.datastart )); - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&oclWGInfo.datastart )); - - //form build options for kernel - String options = "-D PACKED_CLASSIFIER"; - options += format(" -D NODE_SIZE=%d",NODE_SIZE); - options += format(" -D WND_SIZE_X=%d",cascade->orig_window_size.width); - options += format(" -D WND_SIZE_Y=%d",cascade->orig_window_size.height); - options += format(" -D STUMP_BASED=%d",gcascade->is_stump_based); - options += format(" -D SPLITNODE=%d",splitnode); - options += format(" -D SPLITSTAGE=%d",splitstage); - options += format(" -D OUTPUTSZ=%d",outputsz); - - // init candiate global count by 0 - int pattern = 0; - openCLSafeCall(clEnqueueWriteBuffer(qu, candidatebuffer, 1, 0, 1 * sizeof(pattern),&pattern, 0, NULL, NULL)); - - if(WGNumTotal>WGNumSampled) - {// small images and each pixel is processed - // setup global sizes to have linear array of workgroups with WGNum size - int pixelstep = 1; - size_t LS[3]={localThreads[0]/pixelstep,localThreads[1]/pixelstep,1}; - globalThreads[0] = LS[0]*(WGNumTotal-WGNumSampled); - globalThreads[1] = LS[1]; - globalThreads[2] = 1; - String options1 = options; - options1 += format(" -D PIXEL_STEP=%d",pixelstep); - options1 += format(" -D WGSTART=%d",WGNumSampled); - options1 += format(" -D LSx=%d",LS[0]); - options1 += format(" -D LSy=%d",LS[1]); - // execute face detector - openCLExecuteKernel(gsum.clCxt, &haarobjectdetect, "gpuRunHaarClassifierCascadePacked", globalThreads, LS, args, -1, -1, options1.c_str()); - } - if(WGNumSampled>0) - {// large images each 4th pixel is processed - // setup global sizes to have linear array of workgroups with WGNum size - int pixelstep = 2; - size_t LS[3]={localThreads[0]/pixelstep,localThreads[1]/pixelstep,1}; - globalThreads[0] = LS[0]*WGNumSampled; - globalThreads[1] = LS[1]; - globalThreads[2] = 1; - String options2 = options; - options2 += format(" -D PIXEL_STEP=%d",pixelstep); - options2 += format(" -D WGSTART=%d",0); - options2 += format(" -D LSx=%d",LS[0]); - options2 += format(" -D LSy=%d",LS[1]); - // execute face detector - openCLExecuteKernel(gsum.clCxt, &haarobjectdetect, "gpuRunHaarClassifierCascadePacked", globalThreads, LS, args, -1, -1, options2.c_str()); - } - //read candidate buffer back and put it into host list - openCLReadBuffer( gsum.clCxt, candidatebuffer, candidate, 4 * sizeof(int)*outputsz ); - assert(candidate[0]is_stump_based ? "-D STUMP_BASED=1" : "-D STUMP_BASED=0"; - - openCLExecuteKernel(gsum.clCxt, &haarobjectdetect, "gpuRunHaarClassifierCascade", globalThreads, localThreads, args, -1, -1, build_options); - - openCLReadBuffer( gsum.clCxt, candidatebuffer, candidate, 4 * sizeof(int)*outputsz ); - - for(int i = 0; i < outputsz; i++) - if(candidate[4 * i + 2] != 0) - allCandidates.push_back(Rect(candidate[4 * i], candidate[4 * i + 1], - candidate[4 * i + 2], candidate[4 * i + 3])); - } - - free(scaleinfo); - free(candidate); - openCLSafeCall(clReleaseMemObject(stagebuffer)); - openCLSafeCall(clReleaseMemObject(scaleinfobuffer)); - openCLSafeCall(clReleaseMemObject(nodebuffer)); - openCLSafeCall(clReleaseMemObject(candidatebuffer)); - - } - else - { - CvSize winsize0 = cascade->orig_window_size; - int n_factors = 0; - oclMat gsum; - oclMat gsqsum; - oclMat gsqsum_t; - cv::ocl::integral(gimg, gsum, gsqsum_t); - if(gsqsum_t.depth() == CV_64F) - gsqsum_t.convertTo(gsqsum, CV_32FC1); - else - gsqsum = gsqsum_t; - CvSize sz; - std::vector sizev; - std::vector scalev; - gpuSetHaarClassifierCascade(cascade); - gcascade = (GpuHidHaarClassifierCascade *)cascade->hid_cascade; - stage = (GpuHidHaarStageClassifier *)(gcascade + 1); - classifier = (GpuHidHaarClassifier *)(stage + gcascade->count); - node = (GpuHidHaarTreeNode *)(classifier->node); - cl_mem stagebuffer; - cl_mem nodebuffer; - cl_mem candidatebuffer; - cl_mem scaleinfobuffer; - cl_mem pbuffer; - cl_mem correctionbuffer; - for( n_factors = 0, factor = 1; - cvRound(factor * winsize0.width) < gimg.cols - 10 && - cvRound(factor * winsize0.height) < gimg.rows - 10; - n_factors++, factor *= scaleFactor ) - { - CvSize winSize( cvRound( winsize0.width * factor ), cvRound( winsize0.height * factor ) ); - if( winSize.width < minSize.width || winSize.height < minSize.height ) - { - continue; - } - sizev.push_back(winSize); - scalev.push_back(factor); - } - int loopcount = scalev.size(); - if(loopcount == 0) - { - loopcount = 1; - n_factors = 1; - sizev.push_back(minSize); - scalev.push_back( std::min(cvRound(minSize.width / winsize0.width), cvRound(minSize.height / winsize0.height)) ); - } - detect_piramid_info *scaleinfo = (detect_piramid_info *)malloc(sizeof(detect_piramid_info) * loopcount); - cl_int4 *p = (cl_int4 *)malloc(sizeof(cl_int4) * loopcount); - float *correction = (float *)malloc(sizeof(float) * loopcount); - int grp_per_CU = 12; - size_t blocksize = 8; - size_t localThreads[3] = { blocksize, blocksize , 1 }; - size_t globalThreads[3] = { grp_per_CU *gsum.clCxt->getDeviceInfo().maxComputeUnits *localThreads[0], - localThreads[1], 1 }; - int outputsz = 256 * globalThreads[0] / localThreads[0]; - int nodenum = (datasize - sizeof(GpuHidHaarClassifierCascade) - - sizeof(GpuHidHaarStageClassifier) * gcascade->count - sizeof(GpuHidHaarClassifier) * totalclassifier) / sizeof(GpuHidHaarTreeNode); - nodebuffer = openCLCreateBuffer(gsum.clCxt, CL_MEM_READ_ONLY, - nodenum * sizeof(GpuHidHaarTreeNode)); - openCLSafeCall(clEnqueueWriteBuffer(qu, nodebuffer, 1, 0, - nodenum * sizeof(GpuHidHaarTreeNode), - node, 0, NULL, NULL)); - cl_mem newnodebuffer = openCLCreateBuffer(gsum.clCxt, CL_MEM_READ_WRITE, - loopcount * nodenum * sizeof(GpuHidHaarTreeNode)); - int startstage = 0; - int endstage = gcascade->count; - for(int i = 0; i < loopcount; i++) - { - sz = sizev[i]; - factor = scalev[i]; - double ystep = std::max(2., factor); - int equRect_x = cvRound(factor * gcascade->p0); - int equRect_y = cvRound(factor * gcascade->p1); - int equRect_w = cvRound(factor * gcascade->p3); - int equRect_h = cvRound(factor * gcascade->p2); - p[i].s[0] = equRect_x; - p[i].s[1] = equRect_y; - p[i].s[2] = equRect_x + equRect_w; - p[i].s[3] = equRect_y + equRect_h; - correction[i] = 1. / (equRect_w * equRect_h); - int width = (gsum.cols - 1 - sz.width + ystep - 1) / ystep; - int height = (gsum.rows - 1 - sz.height + ystep - 1) / ystep; - int grpnumperline = (width + localThreads[0] - 1) / localThreads[0]; - int totalgrp = ((height + localThreads[1] - 1) / localThreads[1]) * grpnumperline; - - scaleinfo[i].width_height = (width << 16) | height; - scaleinfo[i].grpnumperline_totalgrp = (grpnumperline << 16) | totalgrp; - scaleinfo[i].imgoff = 0; - scaleinfo[i].factor = factor; - int startnodenum = nodenum * i; - float factor2 = (float)factor; - - std::vector > args1; - args1.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&nodebuffer )); - args1.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&newnodebuffer )); - args1.push_back ( std::make_pair(sizeof(cl_float) , (void *)&factor2 )); - args1.push_back ( std::make_pair(sizeof(cl_float) , (void *)&correction[i] )); - args1.push_back ( std::make_pair(sizeof(cl_int) , (void *)&startnodenum )); - - size_t globalThreads2[3] = {nodenum, 1, 1}; - openCLExecuteKernel(gsum.clCxt, &haarobjectdetect_scaled2, "gpuscaleclassifier", globalThreads2, NULL/*localThreads2*/, args1, -1, -1); - } - - int step = gsum.step / 4; - int startnode = 0; - int splitstage = 3; - stagebuffer = openCLCreateBuffer(gsum.clCxt, CL_MEM_READ_ONLY, sizeof(GpuHidHaarStageClassifier) * gcascade->count); - openCLSafeCall(clEnqueueWriteBuffer(qu, stagebuffer, 1, 0, sizeof(GpuHidHaarStageClassifier)*gcascade->count, stage, 0, NULL, NULL)); - candidatebuffer = openCLCreateBuffer(gsum.clCxt, CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, 4 * sizeof(int) * outputsz); - scaleinfobuffer = openCLCreateBuffer(gsum.clCxt, CL_MEM_READ_ONLY, sizeof(detect_piramid_info) * loopcount); - openCLSafeCall(clEnqueueWriteBuffer(qu, scaleinfobuffer, 1, 0, sizeof(detect_piramid_info)*loopcount, scaleinfo, 0, NULL, NULL)); - pbuffer = openCLCreateBuffer(gsum.clCxt, CL_MEM_READ_ONLY, sizeof(cl_int4) * loopcount); - openCLSafeCall(clEnqueueWriteBuffer(qu, pbuffer, 1, 0, sizeof(cl_int4)*loopcount, p, 0, NULL, NULL)); - correctionbuffer = openCLCreateBuffer(gsum.clCxt, CL_MEM_READ_ONLY, sizeof(cl_float) * loopcount); - openCLSafeCall(clEnqueueWriteBuffer(qu, correctionbuffer, 1, 0, sizeof(cl_float)*loopcount, correction, 0, NULL, NULL)); - - std::vector > args; - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&stagebuffer )); - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&scaleinfobuffer )); - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&newnodebuffer )); - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&gsum.data )); - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&gsqsum.data )); - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&candidatebuffer )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&gsum.rows )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&gsum.cols )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&step )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&loopcount )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&startstage )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&splitstage )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&endstage )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&startnode )); - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&pbuffer )); - args.push_back ( std::make_pair(sizeof(cl_mem) , (void *)&correctionbuffer )); - args.push_back ( std::make_pair(sizeof(cl_int) , (void *)&nodenum )); - const char * build_options = gcascade->is_stump_based ? "-D STUMP_BASED=1" : "-D STUMP_BASED=0"; - openCLExecuteKernel(gsum.clCxt, &haarobjectdetect_scaled2, "gpuRunHaarClassifierCascade_scaled2", globalThreads, localThreads, args, -1, -1, build_options); - - candidate = (int *)clEnqueueMapBuffer(qu, candidatebuffer, 1, CL_MAP_READ, 0, 4 * sizeof(int) * outputsz, 0, 0, 0, &status); - - for(int i = 0; i < outputsz; i++) - { - if(candidate[4 * i + 2] != 0) - allCandidates.push_back(Rect(candidate[4 * i], candidate[4 * i + 1], candidate[4 * i + 2], candidate[4 * i + 3])); - } - - free(scaleinfo); - free(p); - free(correction); - clEnqueueUnmapMemObject(qu, candidatebuffer, candidate, 0, 0, 0); - openCLSafeCall(clReleaseMemObject(stagebuffer)); - openCLSafeCall(clReleaseMemObject(scaleinfobuffer)); - openCLSafeCall(clReleaseMemObject(nodebuffer)); - openCLSafeCall(clReleaseMemObject(newnodebuffer)); - openCLSafeCall(clReleaseMemObject(candidatebuffer)); - openCLSafeCall(clReleaseMemObject(pbuffer)); - openCLSafeCall(clReleaseMemObject(correctionbuffer)); - } - - cvFree(&cascade->hid_cascade); - rectList.resize(allCandidates.size()); - if(!allCandidates.empty()) - std::copy(allCandidates.begin(), allCandidates.end(), rectList.begin()); - - if( minNeighbors != 0 || findBiggestObject ) - groupRectangles(rectList, rweights, std::max(minNeighbors, 1), GROUP_EPS); - else - rweights.resize(rectList.size(), 0); - - faces.clear(); - if( findBiggestObject && rectList.size() ) - { - Rect result_comp(0, 0, 0, 0); - for( size_t i = 0; i < rectList.size(); i++ ) - { - cv::Rect r = rectList[i]; - if( r.area() > result_comp.area() ) - { - result_comp = r; - } - } - faces.push_back(result_comp); - } - else - { - faces = rectList; - } -} diff --git a/modules/ocl/src/hog.cpp b/modules/ocl/src/hog.cpp deleted file mode 100644 index 3bdb382fb..000000000 --- a/modules/ocl/src/hog.cpp +++ /dev/null @@ -1,1962 +0,0 @@ -/*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 -// Wenju He, wenju@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 bpied warranties, including, but not limited to, the bpied -// 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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -#define CELL_WIDTH 8 -#define CELL_HEIGHT 8 -#define CELLS_PER_BLOCK_X 2 -#define CELLS_PER_BLOCK_Y 2 -#define NTHREADS 256 - -static oclMat gauss_w_lut; -static bool hog_device_cpu; - -namespace cv -{ - namespace ocl - { - namespace device - { - namespace hog - { - int cnbins; - int cblock_stride_x; - int cblock_stride_y; - int cnblocks_win_x; - int cnblocks_win_y; - int cblock_hist_size; - int cdescr_size; - int cdescr_width; - int cdescr_height; - - // A shift value and type that allows qangle to be different - // sizes on different hardware - int qangle_step_shift; - int qangle_type; - - void set_up_constants(int nbins, int block_stride_x, int block_stride_y, - int nblocks_win_x, int nblocks_win_y); - - void compute_hists(int nbins, int block_stride_x, int blovck_stride_y, - int height, int width, const cv::ocl::oclMat &grad, - const cv::ocl::oclMat &qangle, - const cv::ocl::oclMat &gauss_w_lut, cv::ocl::oclMat &block_hists); - - void normalize_hists(int nbins, int block_stride_x, int block_stride_y, - int height, int width, cv::ocl::oclMat &block_hists, - float threshold); - - void classify_hists(int win_height, int win_width, int block_stride_y, - int block_stride_x, int win_stride_y, int win_stride_x, - int height, int width, const cv::ocl::oclMat &block_hists, - const cv::ocl::oclMat &coefs, float free_coef, - float threshold, cv::ocl::oclMat &labels); - - void extract_descrs_by_rows(int win_height, int win_width, int block_stride_y, - int block_stride_x, int win_stride_y, int win_stride_x, - int height, int width, const cv::ocl::oclMat &block_hists, - cv::ocl::oclMat &descriptors); - void extract_descrs_by_cols(int win_height, int win_width, int block_stride_y, - int block_stride_x, int win_stride_y, int win_stride_x, - int height, int width, const cv::ocl::oclMat &block_hists, - cv::ocl::oclMat &descriptors); - - void compute_gradients_8UC1(int height, int width, const cv::ocl::oclMat &img, - float angle_scale, cv::ocl::oclMat &grad, - cv::ocl::oclMat &qangle, bool correct_gamma); - void compute_gradients_8UC4(int height, int width, const cv::ocl::oclMat &img, - float angle_scale, cv::ocl::oclMat &grad, - cv::ocl::oclMat &qangle, bool correct_gamma); - } - } - } -} - -using namespace ::cv::ocl::device; - -cv::ocl::HOGDescriptor::HOGDescriptor(Size win_size_, Size block_size_, Size block_stride_, - Size cell_size_, int nbins_, double win_sigma_, - double threshold_L2hys_, bool gamma_correction_, int nlevels_) - : win_size(win_size_), - block_size(block_size_), - block_stride(block_stride_), - cell_size(cell_size_), - nbins(nbins_), - win_sigma(win_sigma_), - threshold_L2hys(threshold_L2hys_), - gamma_correction(gamma_correction_), - nlevels(nlevels_) -{ - CV_Assert((win_size.width - block_size.width ) % block_stride.width == 0 && - (win_size.height - block_size.height) % block_stride.height == 0); - - CV_Assert(block_size.width % cell_size.width == 0 && - block_size.height % cell_size.height == 0); - - CV_Assert(block_stride == cell_size); - - CV_Assert(cell_size == Size(8, 8)); - - Size cells_per_block(block_size.width / cell_size.width, - block_size.height / cell_size.height); - CV_Assert(cells_per_block == Size(2, 2)); - - cv::Size blocks_per_win = numPartsWithin(win_size, block_size, block_stride); - hog::set_up_constants(nbins, block_stride.width, block_stride.height, - blocks_per_win.width, blocks_per_win.height); - - effect_size = Size(0, 0); - - if (isCpuDevice()) - hog_device_cpu = true; - else - hog_device_cpu = false; - -} - -size_t cv::ocl::HOGDescriptor::getDescriptorSize() const -{ - return numPartsWithin(win_size, block_size, block_stride).area() * getBlockHistogramSize(); -} - -size_t cv::ocl::HOGDescriptor::getBlockHistogramSize() const -{ - Size cells_per_block = Size(block_size.width / cell_size.width, - block_size.height / cell_size.height); - return (size_t)(nbins * cells_per_block.area()); -} - -double cv::ocl::HOGDescriptor::getWinSigma() const -{ - return win_sigma >= 0 ? win_sigma : (block_size.width + block_size.height) / 8.0; -} - -bool cv::ocl::HOGDescriptor::checkDetectorSize() const -{ - size_t detector_size = detector.rows * detector.cols; - size_t descriptor_size = getDescriptorSize(); - return detector_size == 0 || detector_size == descriptor_size || - detector_size == descriptor_size + 1; -} - -void cv::ocl::HOGDescriptor::setSVMDetector(const std::vector &_detector) -{ - std::vector detector_reordered(_detector.size()); - - size_t block_hist_size = getBlockHistogramSize(); - cv::Size blocks_per_img = numPartsWithin(win_size, block_size, block_stride); - - for (int i = 0; i < blocks_per_img.height; ++i) - for (int j = 0; j < blocks_per_img.width; ++j) - { - const float *src = &_detector[0] + (j * blocks_per_img.height + i) * block_hist_size; - float *dst = &detector_reordered[0] + (i * blocks_per_img.width + j) * block_hist_size; - for (size_t k = 0; k < block_hist_size; ++k) - dst[k] = src[k]; - } - - this->detector.upload(Mat(detector_reordered).reshape(1, 1)); - - size_t descriptor_size = getDescriptorSize(); - free_coef = _detector.size() > descriptor_size ? _detector[descriptor_size] : 0; - - CV_Assert(checkDetectorSize()); -} - -void cv::ocl::HOGDescriptor::init_buffer(const oclMat &img, Size win_stride) -{ - if (!image_scale.empty()) - return; - - if (effect_size == Size(0, 0)) - effect_size = img.size(); - - grad.create(img.size(), CV_32FC2); - qangle.create(img.size(), hog::qangle_type); - - const size_t block_hist_size = getBlockHistogramSize(); - const Size blocks_per_img = numPartsWithin(img.size(), block_size, block_stride); - block_hists.create(1, - static_cast(block_hist_size * blocks_per_img.area()) + 256, CV_32F); - - Size wins_per_img = numPartsWithin(img.size(), win_size, win_stride); - labels.create(1, wins_per_img.area(), CV_8U); - - float sigma = getWinSigma(); - float scale = 1.f / (2.f * sigma * sigma); - Mat gaussian_lut(1, 512, CV_32FC1); - int idx = 0; - for(int i=-8; i<8; i++) - for(int j=-8; j<8; j++) - gaussian_lut.at(idx++) = std::exp(-(j * j + i * i) * scale); - for(int i=-8; i<8; i++) - for(int j=-8; j<8; j++) - gaussian_lut.at(idx++) = (8.f - fabs(j + 0.5f)) * (8.f - fabs(i + 0.5f)) / 64.f; - - gauss_w_lut.upload(gaussian_lut); -} - -void cv::ocl::HOGDescriptor::computeGradient(const oclMat &img, oclMat &grad, oclMat &qangle) -{ - CV_Assert(img.type() == CV_8UC1 || img.type() == CV_8UC4); - - float angleScale = (float)(nbins / CV_PI); - switch (img.type()) - { - case CV_8UC1: - hog::compute_gradients_8UC1(effect_size.height, effect_size.width, img, - angleScale, grad, qangle, gamma_correction); - break; - case CV_8UC4: - hog::compute_gradients_8UC4(effect_size.height, effect_size.width, img, - angleScale, grad, qangle, gamma_correction); - break; - } -} - - -void cv::ocl::HOGDescriptor::computeBlockHistograms(const oclMat &img) -{ - computeGradient(img, this->grad, this->qangle); - - hog::compute_hists(nbins, block_stride.width, block_stride.height, effect_size.height, - effect_size.width, grad, qangle, gauss_w_lut, block_hists); - - hog::normalize_hists(nbins, block_stride.width, block_stride.height, effect_size.height, - effect_size.width, block_hists, (float)threshold_L2hys); -} - - -void cv::ocl::HOGDescriptor::getDescriptors(const oclMat &img, Size win_stride, - oclMat &descriptors, int descr_format) -{ - CV_Assert(win_stride.width % block_stride.width == 0 && - win_stride.height % block_stride.height == 0); - - init_buffer(img, win_stride); - - computeBlockHistograms(img); - - const size_t block_hist_size = getBlockHistogramSize(); - Size blocks_per_win = numPartsWithin(win_size, block_size, block_stride); - Size wins_per_img = numPartsWithin(effect_size, win_size, win_stride); - - descriptors.create(wins_per_img.area(), - static_cast(blocks_per_win.area() * block_hist_size), CV_32F); - - switch (descr_format) - { - case DESCR_FORMAT_ROW_BY_ROW: - hog::extract_descrs_by_rows(win_size.height, win_size.width, - block_stride.height, block_stride.width, win_stride.height, win_stride.width, - effect_size.height, effect_size.width, block_hists, descriptors); - break; - case DESCR_FORMAT_COL_BY_COL: - hog::extract_descrs_by_cols(win_size.height, win_size.width, - block_stride.height, block_stride.width, win_stride.height, win_stride.width, - effect_size.height, effect_size.width, block_hists, descriptors); - break; - default: - CV_Error(Error::StsBadArg, "Unknown descriptor format"); - } -} - - -void cv::ocl::HOGDescriptor::detect(const oclMat &img, std::vector &hits, - double hit_threshold, Size win_stride, Size padding) -{ - CV_Assert(img.type() == CV_8UC1 || img.type() == CV_8UC4); - CV_Assert(padding == Size(0, 0)); - - hits.clear(); - if (detector.empty()) - return; - - if (win_stride == Size()) - win_stride = block_stride; - else - CV_Assert(win_stride.width % block_stride.width == 0 && - win_stride.height % block_stride.height == 0); - init_buffer(img, win_stride); - - computeBlockHistograms(img); - - hog::classify_hists(win_size.height, win_size.width, block_stride.height, - block_stride.width, win_stride.height, win_stride.width, - effect_size.height, effect_size.width, block_hists, detector, - (float)free_coef, (float)hit_threshold, labels); - - labels.download(labels_host); - unsigned char *vec = labels_host.ptr(); - Size wins_per_img = numPartsWithin(effect_size, win_size, win_stride); - for (int i = 0; i < wins_per_img.area(); i++) - { - int y = i / wins_per_img.width; - int x = i - wins_per_img.width * y; - if (vec[i]) - hits.push_back(Point(x * win_stride.width, y * win_stride.height)); - } -} - - - -void cv::ocl::HOGDescriptor::detectMultiScale(const oclMat &img, std::vector &found_locations, - double hit_threshold, Size win_stride, Size padding, - double scale0, int group_threshold) -{ - CV_Assert(img.type() == CV_8UC1 || img.type() == CV_8UC4); - CV_Assert(scale0 > 1); - - std::vector level_scale; - double scale = 1.; - int levels = 0; - - for (levels = 0; levels < nlevels; levels++) - { - level_scale.push_back(scale); - if (cvRound(img.cols / scale) < win_size.width || - cvRound(img.rows / scale) < win_size.height || scale0 <= 1) - break; - scale *= scale0; - } - levels = std::max(levels, 1); - level_scale.resize(levels); - - std::vector all_candidates; - std::vector locations; - - if (win_stride == Size()) - win_stride = block_stride; - else - CV_Assert(win_stride.width % block_stride.width == 0 && - win_stride.height % block_stride.height == 0); - init_buffer(img, win_stride); - image_scale.create(img.size(), img.type()); - - for (size_t i = 0; i < level_scale.size(); i++) - { - scale = level_scale[i]; - effect_size = Size(cvRound(img.cols / scale), cvRound(img.rows / scale)); - if (effect_size == img.size()) - { - detect(img, locations, hit_threshold, win_stride, padding); - } - else - { - resize(img, image_scale, effect_size); - detect(image_scale, locations, hit_threshold, win_stride, padding); - } - Size scaled_win_size(cvRound(win_size.width * scale), - cvRound(win_size.height * scale)); - for (size_t j = 0; j < locations.size(); j++) - all_candidates.push_back(Rect(Point2d(locations[j]) * scale, scaled_win_size)); - } - - found_locations.assign(all_candidates.begin(), all_candidates.end()); - groupRectangles(found_locations, group_threshold, 0.2); -} - -int cv::ocl::HOGDescriptor::numPartsWithin(int size, int part_size, int stride) -{ - return (size - part_size + stride) / stride; -} - -cv::Size cv::ocl::HOGDescriptor::numPartsWithin(cv::Size size, cv::Size part_size, - cv::Size stride) -{ - return Size(numPartsWithin(size.width, part_size.width, stride.width), - numPartsWithin(size.height, part_size.height, stride.height)); -} - -std::vector cv::ocl::HOGDescriptor::getDefaultPeopleDetector() -{ - return getPeopleDetector64x128(); -} - -std::vector cv::ocl::HOGDescriptor::getPeopleDetector48x96() -{ - static const float detector[] = - { - 0.294350f, -0.098796f, -0.129522f, 0.078753f, 0.387527f, 0.261529f, - 0.145939f, 0.061520f, 0.328699f, 0.227148f, -0.066467f, -0.086723f, - 0.047559f, 0.106714f, 0.037897f, 0.111461f, -0.024406f, 0.304769f, - 0.254676f, -0.069235f, 0.082566f, 0.147260f, 0.326969f, 0.148888f, - 0.055270f, -0.087985f, 0.261720f, 0.143442f, 0.026812f, 0.238212f, - 0.194020f, 0.056341f, -0.025854f, -0.034444f, -0.156631f, 0.205174f, - 0.089008f, -0.139811f, -0.100147f, -0.037830f, -0.029230f, -0.055641f, - 0.033248f, -0.016512f, 0.155244f, 0.247315f, -0.124694f, -0.048414f, - -0.062219f, 0.193683f, 0.004574f, 0.055089f, 0.093565f, 0.167712f, - 0.167581f, 0.018895f, 0.215258f, 0.122609f, 0.090520f, -0.067219f, - -0.049029f, -0.099615f, 0.241804f, -0.094893f, -0.176248f, 0.001727f, - -0.134473f, 0.104442f, 0.050942f, 0.081165f, 0.072156f, 0.121646f, - 0.002656f, -0.297974f, -0.133587f, -0.060121f, -0.092515f, -0.048974f, - -0.084754f, -0.180111f, -0.038590f, 0.086283f, -0.134636f, -0.107249f, - 0.132890f, 0.141556f, 0.249425f, 0.130273f, -0.030031f, 0.073212f, - -0.008155f, 0.019931f, 0.071688f, 0.000300f, -0.019525f, -0.021725f, - -0.040993f, -0.086841f, 0.070124f, 0.240033f, 0.265350f, 0.043208f, - 0.166754f, 0.091453f, 0.060916f, -0.036972f, -0.091043f, 0.079873f, - 0.219781f, 0.158102f, -0.140618f, -0.043016f, 0.124802f, 0.093668f, - 0.103208f, 0.094872f, 0.080541f, 0.137711f, 0.160566f, -0.169231f, - 0.013983f, 0.309508f, -0.004217f, -0.057200f, -0.064489f, 0.014066f, - 0.361009f, 0.251328f, -0.080983f, -0.044183f, 0.061436f, -0.037381f, - -0.078786f, 0.030993f, 0.066314f, 0.037683f, 0.152325f, -0.091683f, - 0.070203f, 0.217856f, 0.036435f, -0.076462f, 0.006254f, -0.094431f, - 0.154829f, -0.023038f, -0.196961f, -0.024594f, 0.178465f, -0.050139f, - -0.045932f, -0.000965f, 0.109112f, 0.046165f, -0.159373f, -0.008713f, - 0.041307f, 0.097129f, -0.057211f, -0.064599f, 0.077165f, 0.176167f, - 0.138322f, 0.065753f, -0.104950f, 0.017933f, 0.136255f, -0.011598f, - 0.047007f, 0.080550f, 0.068619f, 0.084661f, -0.035493f, -0.091314f, - -0.041411f, 0.060971f, -0.101912f, -0.079870f, -0.085977f, -0.022686f, - 0.079788f, -0.098064f, -0.054603f, 0.040383f, 0.300794f, 0.128603f, - 0.094844f, 0.047407f, 0.101825f, 0.061832f, -0.162160f, -0.204553f, - -0.035165f, 0.101450f, -0.016641f, -0.027140f, -0.134392f, -0.008743f, - 0.102331f, 0.114853f, 0.009644f, 0.062823f, 0.237339f, 0.167843f, - 0.053066f, -0.012592f, 0.043158f, 0.002305f, 0.065001f, -0.038929f, - -0.020356f, 0.152343f, 0.043469f, -0.029967f, -0.042948f, 0.032481f, - 0.068488f, -0.110840f, -0.111083f, 0.111980f, -0.002072f, -0.005562f, - 0.082926f, 0.006635f, -0.108153f, 0.024242f, -0.086464f, -0.189884f, - -0.017492f, 0.191456f, -0.007683f, -0.128769f, -0.038017f, -0.132380f, - 0.091926f, 0.079696f, -0.106728f, -0.007656f, 0.172744f, 0.011576f, - 0.009883f, 0.083258f, -0.026516f, 0.145534f, 0.153924f, -0.130290f, - -0.108945f, 0.124490f, -0.003186f, -0.100485f, 0.015024f, -0.060512f, - 0.026288f, -0.086713f, -0.169012f, 0.076517f, 0.215778f, 0.043701f, - -0.131642f, -0.012585f, -0.045181f, -0.118183f, -0.241544f, -0.167293f, - -0.020107f, -0.019917f, -0.101827f, -0.107096f, -0.010503f, 0.044938f, - 0.189680f, 0.217119f, -0.046086f, 0.044508f, 0.199716f, -0.036004f, - -0.148927f, 0.013355f, -0.078279f, 0.030451f, 0.056301f, -0.024609f, - 0.083224f, 0.099533f, -0.039432f, -0.138880f, 0.005482f, -0.024120f, - -0.140468f, -0.066381f, -0.017057f, 0.009260f, -0.058004f, -0.028486f, - -0.061610f, 0.007483f, -0.158309f, -0.150687f, -0.044595f, -0.105121f, - -0.045763f, -0.006618f, -0.024419f, -0.117713f, -0.119366f, -0.175941f, - -0.071542f, 0.119027f, 0.111362f, 0.043080f, 0.034889f, 0.093003f, - 0.007842f, 0.057368f, -0.108834f, -0.079968f, 0.230959f, 0.020205f, - 0.011470f, 0.098877f, 0.101310f, -0.030215f, -0.018018f, -0.059552f, - -0.106157f, 0.021866f, -0.036471f, 0.080051f, 0.041165f, -0.082101f, - 0.117726f, 0.030961f, -0.054763f, -0.084102f, -0.185778f, -0.061305f, - -0.038089f, -0.110728f, -0.264010f, 0.076675f, -0.077111f, -0.137644f, - 0.036232f, 0.277995f, 0.019116f, 0.107738f, 0.144003f, 0.080304f, - 0.215036f, 0.228897f, 0.072713f, 0.077773f, 0.120168f, 0.075324f, - 0.062730f, 0.122478f, -0.049008f, 0.164912f, 0.162450f, 0.041246f, - 0.009891f, -0.097827f, -0.038700f, -0.023027f, -0.120020f, 0.203364f, - 0.248474f, 0.149810f, -0.036276f, -0.082814f, -0.090343f, -0.027143f, - -0.075689f, -0.320310f, -0.000500f, -0.143334f, -0.065077f, -0.186936f, - 0.129372f, 0.116431f, 0.181699f, 0.170436f, 0.418854f, 0.460045f, - 0.333719f, 0.230515f, 0.047822f, -0.044954f, -0.068086f, 0.140179f, - -0.044821f, 0.085550f, 0.092483f, -0.107296f, -0.130670f, -0.206629f, - 0.114601f, -0.317869f, -0.076663f, 0.038680f, 0.212753f, -0.016059f, - -0.126526f, -0.163602f, 0.210154f, 0.099887f, -0.126366f, 0.118453f, - 0.019309f, -0.021611f, -0.096499f, -0.111809f, -0.200489f, 0.142854f, - 0.228840f, -0.353346f, -0.179151f, 0.116834f, 0.252389f, -0.031728f, - -0.188135f, -0.158998f, 0.386523f, 0.122315f, 0.209944f, 0.394023f, - 0.359030f, 0.260717f, 0.170335f, 0.013683f, -0.142596f, -0.026138f, - -0.011878f, -0.150519f, 0.047159f, -0.107062f, -0.147347f, -0.187689f, - -0.186027f, -0.208048f, 0.058468f, -0.073026f, -0.236556f, -0.079788f, - -0.146216f, -0.058563f, -0.101361f, -0.071294f, -0.071093f, 0.116919f, - 0.234304f, 0.306781f, 0.321866f, 0.240000f, 0.073261f, -0.012173f, - 0.026479f, 0.050173f, 0.166127f, 0.228955f, 0.061905f, 0.156460f, - 0.205990f, 0.120672f, 0.037350f, 0.167884f, 0.290099f, 0.420900f, - -0.012601f, 0.189839f, 0.306378f, 0.118383f, -0.095598f, -0.072360f, - -0.132496f, -0.224259f, -0.126021f, 0.022714f, 0.284039f, 0.051369f, - -0.000927f, -0.058735f, -0.083354f, -0.141254f, -0.187578f, -0.202669f, - 0.048902f, 0.246597f, 0.441863f, 0.342519f, 0.066979f, 0.215286f, - 0.188191f, -0.072240f, -0.208142f, -0.030196f, 0.178141f, 0.136985f, - -0.043374f, -0.181098f, 0.091815f, 0.116177f, -0.126690f, -0.386625f, - 0.368165f, 0.269149f, -0.088042f, -0.028823f, 0.092961f, 0.024099f, - 0.046112f, 0.176756f, 0.135849f, 0.124955f, 0.195467f, -0.037218f, - 0.167217f, 0.188938f, 0.053528f, -0.066561f, 0.133721f, -0.070565f, - 0.115898f, 0.152435f, -0.116993f, -0.110592f, -0.179005f, 0.026668f, - 0.080530f, 0.075084f, -0.070401f, 0.012497f, 0.021849f, -0.139764f, - -0.022020f, -0.096301f, -0.064954f, -0.127446f, -0.013806f, -0.108315f, - 0.156285f, 0.149867f, -0.011382f, 0.064532f, 0.029168f, 0.027393f, - 0.069716f, 0.153735f, 0.038459f, 0.230714f, 0.253840f, 0.059522f, - -0.045053f, 0.014083f, 0.071103f, 0.068747f, 0.095887f, 0.005832f, - 0.144887f, 0.026357f, -0.067359f, -0.044151f, -0.123283f, -0.019911f, - 0.005318f, 0.109208f, -0.003201f, -0.021734f, 0.142025f, -0.066907f, - -0.120070f, -0.188639f, 0.012472f, -0.048704f, -0.012366f, -0.184828f, - 0.168591f, 0.267166f, 0.058208f, -0.044101f, 0.033500f, 0.178558f, - 0.104550f, 0.122418f, 0.080177f, 0.173246f, 0.298537f, 0.064173f, - 0.053397f, 0.174341f, 0.230984f, 0.117025f, 0.166242f, 0.227781f, - 0.120623f, 0.176952f, -0.011393f, -0.086483f, -0.008270f, 0.051700f, - -0.153369f, -0.058837f, -0.057639f, -0.060115f, 0.026349f, -0.160745f, - -0.037894f, -0.048575f, 0.041052f, -0.022112f, 0.060365f, 0.051906f, - 0.162657f, 0.138519f, -0.050185f, -0.005938f, 0.071301f, 0.127686f, - 0.062342f, 0.144400f, 0.072600f, 0.198436f, 0.246219f, -0.078185f, - -0.036169f, 0.075934f, 0.047328f, -0.013601f, 0.087205f, 0.019900f, - 0.022606f, -0.015365f, -0.092506f, 0.075275f, -0.116375f, 0.050500f, - 0.045118f, 0.166567f, 0.072073f, 0.060371f, 0.131747f, -0.169863f, - -0.039352f, -0.047486f, -0.039797f, -0.204312f, 0.021710f, 0.129443f, - -0.021173f, 0.173416f, -0.070794f, -0.063986f, 0.069689f, -0.064099f, - -0.123201f, -0.017372f, -0.206870f, 0.065863f, 0.113226f, 0.024707f, - -0.071341f, -0.066964f, -0.098278f, -0.062927f, 0.075840f, 0.014716f, - 0.019378f, 0.132699f, -0.074191f, -0.089557f, -0.078446f, -0.197488f, - -0.173665f, 0.052583f, 0.044361f, 0.113549f, 0.098492f, 0.077379f, - -0.011146f, -0.192593f, -0.164435f, 0.045568f, 0.205699f, 0.049187f, - -0.082281f, 0.134874f, 0.185499f, 0.034968f, -0.119561f, -0.112372f, - -0.115091f, -0.054042f, -0.183816f, -0.078100f, 0.190695f, 0.091617f, - 0.004257f, -0.041135f, -0.061453f, -0.141592f, -0.194809f, -0.120638f, - 0.020168f, 0.109672f, 0.067398f, -0.015238f, -0.239145f, -0.264671f, - -0.185176f, 0.050472f, 0.020793f, 0.035678f, 0.022839f, -0.052055f, - -0.127968f, -0.113049f, -0.228416f, -0.258281f, -0.053437f, 0.076424f, - 0.061450f, 0.237478f, 0.003618f, -0.055865f, -0.108087f, -0.028937f, - 0.045585f, 0.052829f, -0.001471f, 0.022826f, 0.059565f, -0.104430f, - -0.077266f, -0.211882f, -0.212078f, 0.028074f, 0.075846f, 0.016265f, - 0.161879f, 0.134477f, 0.008935f, -0.048041f, 0.074692f, 0.004928f, - -0.025156f, 0.192874f, 0.074410f, 0.308732f, 0.267400f, 0.094208f, - -0.005251f, 0.042041f, -0.032148f, 0.015588f, 0.252869f, 0.175302f, - 0.022892f, 0.081673f, 0.063208f, 0.162626f, 0.194426f, 0.233890f, - 0.262292f, 0.186930f, 0.084079f, -0.286388f, -0.213034f, -0.048867f, - -0.207669f, -0.170050f, 0.011673f, -0.092958f, -0.192786f, -0.273536f, - 0.230904f, 0.266732f, 0.320519f, 0.297155f, 0.548169f, 0.304922f, - 0.132687f, 0.247333f, 0.212488f, -0.271472f, -0.142105f, -0.002627f, - -0.119215f, 0.128383f, 0.100079f, -0.057490f, -0.121902f, -0.228892f, - 0.202292f, -0.399795f, -0.371326f, -0.095836f, -0.063626f, -0.161375f, - -0.311180f, -0.294797f, 0.242122f, 0.011788f, 0.095573f, 0.322523f, - 0.511840f, 0.322880f, 0.313259f, 0.173331f, 0.002542f, -0.029802f, - 0.324766f, -0.326170f, -0.340547f, -0.138288f, -0.002963f, -0.114060f, - -0.377312f, -0.442570f, 0.212446f, -0.007759f, -0.011576f, 0.169711f, - 0.308689f, 0.317348f, 0.539390f, 0.332845f, 0.057331f, -0.068180f, - 0.101994f, 0.266995f, 0.209570f, 0.355730f, 0.091635f, 0.170238f, - 0.125215f, 0.274154f, 0.070223f, 0.025515f, 0.049946f, -0.000550f, - 0.043715f, -0.141843f, 0.020844f, 0.129871f, 0.256588f, 0.105015f, - 0.148339f, 0.170682f, 0.028792f, 0.074037f, 0.160042f, 0.405137f, - 0.246187f, 0.352160f, 0.168951f, 0.222263f, 0.264439f, 0.065945f, - 0.021963f, -0.075084f, 0.093105f, 0.027318f, 0.098864f, 0.057566f, - -0.080282f, 0.185032f, 0.314419f, 0.333727f, 0.125798f, 0.294919f, - 0.386002f, 0.217619f, -0.183517f, -0.278622f, -0.002342f, -0.027821f, - -0.134266f, -0.331843f, -0.008296f, 0.124564f, 0.053712f, -0.369016f, - -0.095036f, 0.209381f, 0.423760f, 0.371760f, 0.106397f, 0.369408f, - 0.485608f, 0.231201f, -0.138685f, -0.349208f, -0.070083f, 0.028991f, - -0.081630f, -0.395992f, -0.146791f, -0.027354f, 0.063396f, -0.272484f, - 0.058299f, 0.338207f, 0.110767f, -0.052642f, -0.233848f, -0.027448f, - 0.030328f, 0.155572f, -0.093826f, 0.019331f, 0.120638f, 0.006292f, - -0.106083f, -0.236290f, -0.140933f, -0.088067f, -0.025138f, -0.208395f, - -0.025502f, 0.144192f, -0.048353f, -0.106144f, -0.305121f, -0.114147f, - 0.090963f, 0.327727f, 0.035606f, -0.093779f, 0.002651f, -0.171081f, - -0.188131f, -0.216571f, -0.209101f, -0.054402f, 0.157147f, -0.057127f, - 0.066584f, 0.008988f, 0.041191f, 0.034456f, -0.078255f, 0.052099f, - -0.022239f, 0.066981f, -0.117520f, -0.072637f, 0.062512f, 0.037570f, - -0.057544f, -0.312359f, 0.034357f, -0.031549f, 0.002566f, -0.207375f, - -0.070654f, -0.018786f, -0.044815f, -0.012814f, -0.076320f, 0.078183f, - 0.023877f, 0.117078f, 0.022292f, -0.205424f, -0.060430f, -0.017296f, - -0.004827f, -0.321036f, -0.092155f, 0.038837f, 0.073190f, -0.067513f, - 0.026521f, 0.171945f, 0.087318f, 0.034495f, -0.034089f, 0.154410f, - -0.061431f, 0.007435f, -0.111094f, -0.095976f, 0.014741f, -0.132324f, - -0.029517f, -0.192160f, 0.098667f, 0.020762f, 0.177050f, -0.064510f, - -0.054437f, -0.058678f, -0.001858f, 0.167602f, 0.015735f, 0.054338f, - 0.016477f, 0.186381f, -0.010667f, 0.054692f, 0.126742f, 0.013140f, - 0.090353f, -0.133608f, -0.018017f, -0.152619f, 0.027600f, -0.138700f, - -0.050274f, 0.045141f, -0.118731f, 0.094797f, -0.167605f, 0.097461f, - -0.009131f, 0.199920f, -0.052976f, 0.158194f, 0.178568f, -0.107600f, - 0.009671f, -0.084072f, -0.040258f, -0.205673f, 0.102891f, 0.223511f, - 0.042699f, 0.118548f, -0.021274f, 0.110997f, -0.155121f, 0.027696f, - -0.149968f, 0.051552f, -0.129219f, 0.173524f, 0.073972f, -0.189045f, - -0.034523f, -0.106655f, -0.011843f, -0.197381f, 0.219413f, 0.183197f, - -0.054920f, 0.144955f, 0.036517f, -0.085412f, -0.229070f, -0.143710f, - -0.049486f, 0.156634f, -0.008673f, -0.064778f, 0.082344f, 0.145673f, - 0.002912f, -0.210121f, -0.116564f, 0.078425f, 0.220908f, -0.067594f, - 0.048610f, 0.084912f, -0.066202f, -0.112515f, -0.217767f, -0.082640f, - -0.017414f, 0.230265f, -0.070735f, 0.066073f, 0.215256f, 0.071157f, - -0.087220f, -0.202235f, -0.011918f, 0.099562f, 0.174716f, -0.063845f, - -0.121055f, 0.014367f, 0.132709f, -0.005060f, -0.244606f, -0.179693f, - -0.134690f, 0.023239f, -0.193116f, -0.076975f, -0.021164f, -0.001938f, - -0.163799f, -0.111437f, -0.210362f, -0.166376f, 0.034754f, 0.010036f, - -0.021917f, 0.068014f, -0.086893f, -0.251746f, -0.267171f, 0.037383f, - 0.003966f, 0.033571f, -0.151506f, 0.025437f, -0.020626f, -0.308454f, - -0.343143f, -0.092263f, -0.026261f, -0.028345f, 0.036036f, 0.035169f, - 0.129470f, 0.122205f, 0.015661f, -0.070612f, -0.094333f, -0.066055f, - -0.041083f, 0.159146f, 0.073184f, 0.110044f, 0.174471f, 0.078069f, - -0.014881f, 0.008116f, 0.013209f, 0.075857f, 0.195605f, 0.062714f, - 0.067955f, 0.056544f, -0.153908f, -0.141749f, -0.072550f, 0.033523f, - -0.024665f, 0.134487f, 0.079076f, 0.133562f, 0.227130f, 0.018054f, - 0.004928f, 0.169162f, 0.065152f, 0.072160f, 0.131631f, 0.096303f, - 0.054288f, 0.106256f, 0.114632f, 0.119038f, 0.515200f, 0.247429f, - 0.199134f, 0.211957f, 0.127558f, -0.294684f, -0.194890f, -0.049988f, - -0.112247f, -0.008122f, -0.006176f, 0.037035f, -0.110881f, -0.249989f, - 0.152434f, 0.234621f, 0.153340f, 0.349283f, 0.683049f, 0.157174f, - 0.124844f, 0.099136f, 0.064407f, -0.248400f, -0.155323f, -0.026498f, - -0.023450f, 0.049051f, -0.114187f, 0.007195f, -0.176825f, -0.376926f, - 0.366159f, -0.179938f, -0.148508f, 0.006043f, 0.170048f, 0.097866f, - -0.102658f, -0.260430f, 0.248868f, 0.037019f, -0.118111f, 0.078176f, - 0.194171f, 0.211328f, 0.368612f, 0.361213f, 0.130013f, 0.094650f, - 0.227396f, -0.178058f, -0.114782f, -0.008093f, 0.231080f, -0.011843f, - -0.097917f, -0.325788f, 0.141879f, 0.119738f, -0.230427f, -0.117419f, - -0.114153f, 0.037903f, 0.116383f, 0.218773f, -0.101884f, 0.059466f, - 0.119255f, 0.010874f, -0.031449f, 0.045996f, 0.119931f, 0.273760f, - 0.311700f, 0.261794f, 0.194809f, 0.339829f, 0.239449f, 0.064140f, - 0.077597f, 0.098996f, 0.143534f, 0.184602f, 0.037507f, 0.225494f, - 0.096142f, -0.147370f, -0.207833f, -0.174742f, -0.086391f, -0.038942f, - 0.159577f, -0.088492f, -0.000989f, 0.108154f, -0.025890f, -0.072713f, - 0.025997f, -0.006803f, -0.086879f, -0.011290f, -0.269200f, -0.103450f, - -0.124910f, -0.116340f, 0.141459f, 0.208800f, 0.042268f, 0.265034f, - 0.516474f, 0.217591f, -0.018843f, -0.313328f, -0.168363f, 0.047129f, - 0.090480f, -0.109852f, -0.018761f, 0.210669f, 0.281269f, -0.043591f, - -0.034147f, -0.237772f, -0.134843f, -0.072481f, -0.103831f, 0.038355f, - 0.308619f, 0.148023f, -0.045867f, -0.123950f, -0.210860f, -0.064973f, - -0.036308f, -0.046731f, -0.022099f, 0.095776f, 0.409423f, 0.060635f, - -0.065196f, 0.051828f, 0.027981f, -0.009609f, -0.137681f, -0.095011f, - -0.019045f, 0.177278f, 0.009759f, -0.092119f, -0.016958f, -0.133860f, - -0.118421f, -0.032039f, -0.006214f, -0.084541f, 0.063971f, -0.073642f, - 0.165676f, 0.110443f, 0.044131f, 0.046568f, 0.053292f, -0.055466f, - 0.015512f, 0.371947f, 0.232102f, -0.016923f, 0.103979f, -0.091758f, - 0.005907f, 0.209100f, 0.157433f, 0.030518f, 0.250366f, 0.062322f, - 0.036720f, 0.094676f, 0.017306f, -0.010328f, -0.079012f, 0.016781f, - -0.112435f, 0.061795f, 0.042543f, -0.126799f, -0.009975f, -0.056760f, - 0.046424f, -0.194712f, -0.139399f, -0.037731f, 0.157989f, -0.016261f, - 0.123345f, 0.230563f, 0.083300f, -0.016392f, 0.059567f, -0.016035f, - -0.064767f, 0.231945f, 0.156629f, 0.034602f, 0.145628f, 0.041315f, - 0.034535f, 0.019967f, -0.089188f, -0.012091f, 0.307857f, 0.211405f, - -0.025091f, -0.148249f, -0.129384f, 0.063536f, -0.068603f, -0.067941f, - -0.035104f, 0.210832f, 0.063810f, 0.062764f, -0.089889f, -0.030554f, - 0.014791f, -0.053362f, -0.037818f, -0.196640f, 0.008388f, -0.082654f, - 0.143056f, 0.064221f, 0.069795f, 0.191040f, 0.097321f, -0.028679f, - 0.075794f, 0.313154f, 0.086240f, 0.207643f, 0.017809f, 0.122867f, - 0.224586f, 0.167403f, -0.023884f, 0.047434f, 0.344091f, 0.187745f, - 0.136177f, 0.141738f, 0.063799f, 0.045233f, -0.077342f, -0.003525f, - -0.165041f, -0.025616f, -0.073745f, 0.164439f, 0.011200f, -0.145896f, - -0.027954f, -0.061987f, -0.039874f, -0.142775f, 0.151042f, -0.038238f, - 0.053152f, 0.078615f, 0.086061f, 0.100593f, 0.128046f, -0.071006f, - -0.116558f, 0.208445f, 0.051086f, 0.076843f, 0.023191f, -0.084781f, - -0.011790f, 0.147807f, -0.048554f, -0.113932f, 0.283322f, 0.190934f, - 0.092789f, 0.033018f, -0.142428f, -0.142480f, -0.099023f, -0.041020f, - -0.042760f, 0.203295f, -0.053475f, 0.042424f, 0.222839f, -0.019167f, - -0.133176f, -0.276216f, -0.031998f, 0.117290f, 0.177827f, -0.059973f, - -0.064744f, -0.117040f, -0.155482f, -0.099531f, 0.164121f, -0.026682f, - -0.093810f, 0.238993f, -0.006506f, 0.007830f, 0.065819f, -0.203643f, - -0.100925f, -0.053652f, -0.130770f, 0.026277f, 0.131796f, 0.032742f, - 0.127186f, 0.116694f, -0.161122f, -0.279773f, -0.252515f, -0.002638f, - 0.042812f, 0.096776f, -0.123280f, 0.064858f, -0.010455f, -0.219760f, - -0.239331f, -0.104363f, -0.058022f, -0.053584f, 0.025611f, 0.005129f, - -0.100418f, -0.045712f, -0.194418f, -0.126366f, -0.030530f, 0.051168f, - 0.215959f, 0.172402f, -0.054700f, -0.185995f, -0.278360f, -0.193693f, - -0.040309f, 0.003735f, -0.007770f, 0.123556f, 0.190179f, -0.077315f, - 0.117403f, 0.212942f, 0.012160f, 0.000113f, 0.027331f, 0.040202f, - 0.033293f, 0.219438f, 0.184174f, 0.259349f, 0.311206f, 0.082547f, - -0.047875f, -0.078417f, 0.010746f, 0.082620f, 0.311931f, 0.307605f, - 0.003863f, 0.021405f, -0.026388f, -0.019572f, 0.020582f, -0.059353f, - 0.025199f, 0.261319f, 0.086316f, 0.143614f, 0.107780f, 0.003900f, - -0.188397f, -0.038563f, -0.106045f, -0.125154f, -0.010509f, 0.054021f, - 0.242130f, 0.279152f, 0.215546f, 0.346995f, 0.440856f, 0.237452f, - 0.234154f, 0.301646f, 0.168929f, -0.208358f, -0.126848f, 0.010260f, - 0.121018f, -0.062975f, -0.052848f, 0.050341f, -0.061103f, -0.266482f, - 0.107186f, 0.140221f, 0.280065f, 0.287889f, 0.373198f, 0.151596f, - 0.013593f, 0.115616f, 0.014616f, -0.281710f, -0.237597f, -0.117305f, - -0.000034f, -0.136739f, -0.196275f, -0.095225f, -0.125310f, -0.250514f, - 0.236804f, -0.071805f, -0.037421f, 0.048230f, 0.321596f, 0.063632f, - 0.024039f, -0.029133f, 0.230983f, 0.160593f, -0.154355f, -0.013086f, - -0.079929f, 0.094692f, 0.160391f, 0.180239f, 0.053895f, 0.100759f, - 0.288631f, 0.038191f, 0.181692f, 0.229682f, 0.440166f, 0.063401f, - 0.006273f, 0.020865f, 0.338695f, 0.256244f, -0.043927f, 0.115617f, - 0.003296f, 0.173965f, 0.021318f, -0.040936f, -0.118932f, 0.182380f, - 0.235922f, -0.053233f, -0.015053f, -0.101057f, 0.095341f, 0.051111f, - 0.161831f, 0.032614f, 0.159496f, 0.072375f, 0.025089f, 0.023748f, - 0.029151f, 0.161284f, -0.117717f, -0.036191f, -0.176822f, -0.162006f, - 0.226542f, -0.078329f, 0.043079f, -0.119172f, 0.054614f, -0.101365f, - -0.064541f, -0.115304f, 0.135170f, 0.298872f, 0.098060f, 0.089428f, - -0.007497f, 0.110391f, -0.028824f, 0.020835f, -0.036804f, 0.125411f, - 0.192105f, -0.048931f, 0.003086f, -0.010681f, 0.074698f, -0.016263f, - 0.096063f, 0.060267f, -0.007277f, 0.139139f, -0.080635f, 0.036628f, - 0.086058f, 0.131979f, 0.085707f, 0.025301f, 0.226094f, 0.194759f, - 0.042193f, -0.157846f, -0.068402f, -0.141450f, -0.112659f, -0.076305f, - -0.069085f, -0.114332f, -0.102005f, 0.132193f, -0.067042f, 0.106643f, - 0.198964f, 0.171616f, 0.167237f, -0.033730f, -0.026755f, 0.083621f, - 0.149459f, -0.002799f, -0.000318f, 0.011753f, 0.065889f, -0.089375f, - -0.049610f, 0.224579f, 0.216548f, -0.034908f, -0.017851f, -0.088144f, - 0.007530f, 0.240268f, 0.073270f, 0.013263f, 0.175323f, 0.012082f, - 0.093993f, 0.015282f, 0.105854f, 0.107990f, 0.077798f, -0.096166f, - -0.079607f, 0.177820f, 0.142392f, 0.033337f, -0.078100f, -0.081616f, - -0.046993f, 0.139459f, 0.020272f, -0.123161f, 0.175269f, 0.105217f, - 0.057328f, 0.080909f, -0.012612f, -0.097081f, 0.082060f, -0.096716f, - -0.063921f, 0.201884f, 0.128166f, -0.035051f, -0.032227f, -0.068139f, - -0.115915f, 0.095080f, -0.086007f, -0.067543f, 0.030776f, 0.032712f, - 0.088937f, 0.054336f, -0.039329f, -0.114022f, 0.171672f, -0.112321f, - -0.217646f, 0.065186f, 0.060223f, 0.192174f, 0.055580f, -0.131107f, - -0.144338f, 0.056730f, -0.034707f, -0.081616f, -0.135298f, -0.000614f, - 0.087189f, 0.014614f, 0.067709f, 0.107689f, 0.225780f, 0.084361f, - -0.008544f, 0.051649f, -0.048369f, -0.037739f, -0.060710f, 0.002654f, - 0.016935f, 0.085563f, -0.015961f, -0.019265f, 0.111788f, 0.062376f, - 0.202019f, 0.047713f, 0.042261f, 0.069716f, 0.242913f, 0.021052f, - -0.072812f, -0.155920f, -0.026436f, 0.035621f, -0.079300f, -0.028787f, - -0.048329f, 0.084718f, -0.060565f, -0.083750f, -0.164075f, -0.040742f, - -0.086219f, 0.015271f, -0.005204f, -0.016038f, 0.045816f, -0.050433f, - -0.077652f, 0.117109f, 0.009611f, -0.009045f, -0.008634f, -0.055373f, - -0.085968f, 0.028527f, -0.054736f, -0.168089f, 0.175839f, 0.071205f, - -0.023603f, 0.037907f, -0.004561f, -0.022634f, 0.123831f, 0.094469f, - -0.072920f, -0.133642f, -0.014032f, -0.142754f, -0.026999f, -0.199409f, - 0.013268f, 0.226989f, 0.048650f, -0.170988f, -0.050141f, 0.007880f, - 0.061880f, 0.019078f, -0.043578f, -0.038139f, 0.134814f, 0.054097f, - -0.081670f, 0.176838f, 0.047920f, -0.038176f, 0.050406f, -0.107181f, - -0.036279f, 0.027060f, 0.081594f, -0.002820f, 0.090507f, -0.033338f, - -0.059571f, 0.013404f, -0.099860f, 0.073371f, 0.342805f, 0.098305f, - -0.150910f, -0.020822f, -0.056960f, 0.046262f, -0.043413f, -0.149405f, - -0.129105f, -0.010899f, -0.014229f, -0.179949f, -0.113044f, -0.049468f, - -0.065513f, 0.090269f, -0.011919f, 0.087846f, 0.095796f, 0.146127f, - 0.101599f, 0.078066f, -0.084348f, -0.100002f, -0.020134f, -0.050169f, - 0.062122f, 0.014640f, 0.019143f, 0.036543f, 0.180924f, -0.013976f, - -0.066768f, -0.001090f, -0.070419f, -0.004839f, -0.001504f, 0.034483f, - -0.044954f, -0.050336f, -0.088638f, -0.174782f, -0.116082f, -0.205507f, - 0.015587f, -0.042839f, -0.096879f, -0.144097f, -0.050268f, -0.196796f, - 0.109639f, 0.271411f, 0.173732f, 0.108070f, 0.156437f, 0.124255f, - 0.097242f, 0.238693f, 0.083941f, 0.109105f, 0.223940f, 0.267188f, - 0.027385f, 0.025819f, 0.125070f, 0.093738f, 0.040353f, 0.038645f, - -0.012730f, 0.144063f, 0.052931f, -0.009138f, 0.084193f, 0.160272f, - -0.041366f, 0.011951f, -0.121446f, -0.106713f, -0.047566f, 0.047984f, - -0.255224f, -0.076116f, 0.098685f, -0.150845f, -0.171513f, -0.156590f, - 0.058331f, 0.187493f, 0.413018f, 0.554265f, 0.372242f, 0.237943f, - 0.124571f, 0.110829f, 0.010322f, -0.174477f, -0.067627f, -0.001979f, - 0.142913f, 0.040597f, 0.019907f, 0.025963f, -0.043585f, -0.120732f, - 0.099937f, 0.091059f, 0.247307f, 0.204226f, -0.042753f, -0.068580f, - -0.119002f, 0.026722f, 0.034853f, -0.060934f, -0.025054f, -0.093026f, - -0.035372f, -0.233209f, -0.049869f, -0.039151f, -0.022279f, -0.065380f, - -9.063785f - }; - return std::vector(detector, detector + sizeof(detector) / sizeof(detector[0])); -} - - - - -std::vector cv::ocl::HOGDescriptor::getPeopleDetector64x128() -{ - static const float detector[] = - { - 0.05359386f, -0.14721455f, -0.05532170f, 0.05077307f, - 0.11547081f, -0.04268804f, 0.04635834f, -0.05468199f, 0.08232084f, - 0.10424068f, -0.02294518f, 0.01108519f, 0.01378693f, 0.11193510f, - 0.01268418f, 0.08528346f, -0.06309239f, 0.13054633f, 0.08100729f, - -0.05209739f, -0.04315529f, 0.09341384f, 0.11035026f, -0.07596218f, - -0.05517511f, -0.04465296f, 0.02947334f, 0.04555536f, - -3.55954492e-003f, 0.07818956f, 0.07730991f, 0.07890715f, 0.06222893f, - 0.09001380f, -0.03574381f, 0.03414327f, 0.05677258f, -0.04773581f, - 0.03746637f, -0.03521175f, 0.06955440f, -0.03849038f, 0.01052293f, - 0.01736112f, 0.10867710f, 0.08748853f, 3.29739624e-003f, 0.10907028f, - 0.07913758f, 0.10393070f, 0.02091867f, 0.11594022f, 0.13182420f, - 0.09879354f, 0.05362710f, -0.06745391f, -7.01260753e-003f, - 5.24702156e-003f, 0.03236255f, 0.01407916f, 0.02207983f, 0.02537322f, - 0.04547948f, 0.07200756f, 0.03129894f, -0.06274468f, 0.02107014f, - 0.06035208f, 0.08636236f, 4.53164103e-003f, 0.02193363f, 0.02309801f, - 0.05568166f, -0.02645093f, 0.04448695f, 0.02837519f, 0.08975694f, - 0.04461516f, 0.08975355f, 0.07514391f, 0.02306982f, 0.10410084f, - 0.06368385f, 0.05943464f, 4.58420580e-003f, 0.05220337f, 0.06675851f, - 0.08358569f, 0.06712101f, 0.06559004f, -0.03930482f, -9.15936660e-003f, - -0.05897915f, 0.02816453f, 0.05032348f, 0.06780671f, 0.03377650f, - -6.09417039e-004f, -0.01795146f, -0.03083684f, -0.01302475f, - -0.02972313f, 7.88706727e-003f, -0.03525961f, -2.50397739e-003f, - 0.05245084f, 0.11791293f, -0.02167498f, 0.05299332f, 0.06640524f, - 0.05190265f, -8.27316567e-003f, 0.03033127f, 0.05842173f, - -4.01050318e-003f, -6.25105947e-003f, 0.05862958f, -0.02465461f, - 0.05546781f, -0.08228195f, -0.07234028f, 0.04640540f, -0.01308254f, - -0.02506191f, 0.03100746f, -0.04665651f, -0.04591486f, 0.02949927f, - 0.06035462f, 0.02244646f, -0.01698639f, 0.01040041f, 0.01131170f, - 0.05419579f, -0.02130277f, -0.04321722f, -0.03665198f, 0.01126490f, - -0.02606488f, -0.02228328f, -0.02255680f, -0.03427236f, - -7.75165204e-003f, -0.06195229f, 8.21638294e-003f, 0.09535975f, - -0.03709979f, -0.06942501f, 0.14579427f, -0.05448192f, -0.02055904f, - 0.05747357f, 0.02781788f, -0.07077577f, -0.05178314f, -0.10429011f, - -0.11235505f, 0.07529039f, -0.07559302f, -0.08786739f, 0.02983843f, - 0.02667585f, 0.01382199f, -0.01797496f, -0.03141199f, -0.02098101f, - 0.09029204f, 0.04955018f, 0.13718739f, 0.11379953f, 1.80019124e-003f, - -0.04577610f, -1.11108483e-003f, -0.09470536f, -0.11596080f, - 0.04489342f, 0.01784211f, 3.06850672e-003f, 0.10781866f, - 3.36498418e-003f, -0.10842580f, -0.07436839f, -0.10535070f, - -0.01866805f, 0.16057891f, -5.07316366e-003f, -0.04295658f, - -5.90488780e-003f, 8.82003549e-003f, -0.01492646f, -0.05029279f, - -0.12875880f, 8.78831954e-004f, -0.01297184f, -0.07592774f, - -0.02668831f, -6.93787413e-004f, 0.02406698f, -0.01773298f, - -0.03855745f, -0.05877856f, 0.03259695f, 0.12826584f, 0.06292590f, - -4.10733931e-003f, 0.10996531f, 0.01332991f, 0.02088735f, 0.04037504f, - -0.05210760f, 0.07760046f, 0.06399347f, -0.05751930f, -0.10053057f, - 0.07505023f, -0.02139782f, 0.01796176f, 2.34400877e-003f, -0.04208319f, - 0.07355055f, 0.05093350f, -0.02996780f, -0.02219072f, 0.03355330f, - 0.04418742f, -0.05580705f, -0.05037573f, -0.04548179f, 0.01379514f, - 0.02150671f, -0.02194211f, -0.13682702f, 0.05464972f, 0.01608082f, - 0.05309116f, 0.04701022f, 1.33690401e-003f, 0.07575664f, 0.09625306f, - 8.92647635e-003f, -0.02819123f, 0.10866830f, -0.03439325f, - -0.07092371f, -0.06004780f, -0.02712298f, -7.07467366e-003f, - -0.01637020f, 0.01336790f, -0.10313606f, 0.04906582f, -0.05732445f, - -0.02731079f, 0.01042235f, -0.08340668f, 0.03686501f, 0.06108340f, - 0.01322748f, -0.07809529f, 0.03774724f, -0.03413248f, -0.06096525f, - -0.04212124f, -0.07982176f, -1.25973229e-003f, -0.03045501f, - -0.01236493f, -0.06312395f, 0.04789570f, -0.04602066f, 0.08576570f, - 0.02521080f, 0.02988098f, 0.10314583f, 0.07060035f, 0.04520544f, - -0.04426654f, 0.13146530f, 0.08386490f, 0.02164590f, -2.12280243e-003f, - -0.03686353f, -0.02074944f, -0.03829959f, -0.01530596f, 0.02689708f, - 0.11867401f, -0.06043470f, -0.02785023f, -0.04775074f, 0.04878745f, - 0.06350956f, 0.03494788f, 0.01467400f, 1.17890188e-003f, 0.04379614f, - 2.03681854e-003f, -0.03958609f, -0.01072688f, 6.43705716e-003f, - 0.02996500f, -0.03418507f, -0.01960307f, -0.01219154f, - -4.37000440e-003f, -0.02549453f, 0.02646318f, -0.01632513f, - 6.46516960e-003f, -0.01929734f, 4.78711911e-003f, 0.04962371f, - 0.03809111f, 0.07265724f, 0.05758125f, -0.03741554f, 0.01648608f, - -8.45285598e-003f, 0.03996826f, -0.08185477f, 0.02638875f, - -0.04026615f, -0.02744674f, -0.04071517f, 1.05096330e-003f, - -0.04741232f, -0.06733172f, 8.70434940e-003f, -0.02192543f, - 1.35350740e-003f, -0.03056974f, -0.02975521f, -0.02887780f, - -0.01210713f, -0.04828526f, -0.09066251f, -0.09969629f, -0.03665164f, - -8.88111943e-004f, -0.06826669f, -0.01866150f, -0.03627640f, - -0.01408288f, 0.01874239f, -0.02075835f, 0.09145175f, -0.03547291f, - 0.05396780f, 0.04198981f, 0.01301925f, -0.03384354f, -0.12201976f, - 0.06830920f, -0.03715654f, 9.55848210e-003f, 5.05685573e-003f, - 0.05659294f, 3.90764466e-003f, 0.02808490f, -0.05518097f, -0.03711621f, - -0.02835565f, -0.04420464f, -0.01031947f, 0.01883466f, - -8.49525444e-003f, -0.09419250f, -0.01269387f, -0.02133371f, - -0.10190815f, -0.07844430f, 2.43644323e-003f, -4.09610150e-003f, - 0.01202551f, -0.06452291f, -0.10593818f, -0.02464746f, -0.02199699f, - -0.07401930f, 0.07285886f, 8.87513801e-004f, 9.97662079e-003f, - 8.46779719e-003f, 0.03730333f, -0.02905126f, 0.03573337f, -0.04393689f, - -0.12014472f, 0.03176554f, -2.76015815e-003f, 0.10824566f, 0.05090732f, - -3.30179278e-003f, -0.05123822f, 5.04784798e-003f, -0.05664124f, - -5.99415926e-003f, -0.05341901f, -0.01221393f, 0.01291318f, - 9.91760660e-003f, -7.56987557e-003f, -0.06193124f, -2.24549137e-003f, - 0.01987562f, -0.02018840f, -0.06975540f, -0.06601523f, -0.03349112f, - -0.08910118f, -0.03371435f, -0.07406893f, -0.02248047f, -0.06159951f, - 2.77751544e-003f, -0.05723337f, -0.04792468f, 0.07518548f, - 2.77279224e-003f, 0.04211938f, 0.03100502f, 0.05278448f, 0.03954679f, - -0.03006846f, -0.03851741f, -0.02792403f, -0.02875333f, 0.01531280f, - 0.02186953f, -0.01989829f, 2.50679464e-003f, -0.10258728f, - -0.04785743f, -0.02887216f, 3.85063468e-003f, 0.01112236f, - 8.29218887e-003f, -0.04822981f, -0.04503597f, -0.03713100f, - -0.06988008f, -0.11002295f, -2.69209221e-003f, 1.85383670e-003f, - -0.05921049f, -0.06105053f, -0.08458050f, -0.04527602f, - 8.90329306e-004f, -0.05875023f, -2.68602883e-003f, -0.01591195f, - 0.03631859f, 0.05493166f, 0.07300330f, 5.53333294e-003f, 0.06400407f, - 0.01847740f, -5.76280477e-003f, -0.03210877f, 4.25160583e-003f, - 0.01166520f, -1.44864211e-003f, 0.02253744f, -0.03367080f, 0.06983195f, - -4.22323542e-003f, -8.89401045e-003f, -0.07943393f, 0.05199728f, - 0.06065201f, 0.04133492f, 1.44032843e-003f, -0.09585235f, -0.03964731f, - 0.04232114f, 0.01750465f, -0.04487902f, -7.59733608e-003f, 0.02011171f, - 0.04673622f, 0.09011173f, -0.07869188f, -0.04682482f, -0.05080139f, - -3.99383716e-003f, -0.05346331f, 0.01085723f, -0.03599333f, - -0.07097908f, 0.03551549f, 0.02680387f, 0.03471529f, 0.01790393f, - 0.05471273f, 9.62048303e-003f, -0.03180215f, 0.05864431f, 0.02330614f, - 0.01633144f, -0.05616681f, -0.10245429f, -0.08302189f, 0.07291322f, - -0.01972590f, -0.02619633f, -0.02485327f, -0.04627592f, - 1.48853404e-003f, 0.05514185f, -0.01270860f, -0.01948900f, 0.06373586f, - 0.05002292f, -0.03009798f, 8.76216311e-003f, -0.02474238f, - -0.05504891f, 1.74034527e-003f, -0.03333667f, 0.01524987f, 0.11663762f, - -1.32344989e-003f, -0.06608453f, 0.05687166f, -6.89525274e-004f, - -0.04402352f, 0.09450210f, -0.04222684f, -0.05360983f, 0.01779531f, - 0.02561388f, -0.11075410f, -8.77790991e-003f, -0.01099504f, - -0.10380266f, 0.03103457f, -0.02105741f, -0.07371717f, 0.05146710f, - 0.10581432f, -0.08617968f, -0.02892107f, 0.01092199f, 0.14551543f, - -2.24320893e-003f, -0.05818033f, -0.07390742f, 0.05701261f, - 0.12937020f, -0.04986651f, 0.10182415f, 0.05028650f, 0.12515625f, - 0.09175041f, 0.06404983f, 0.01523394f, 0.09460562f, 0.06106631f, - -0.14266998f, -0.02926703f, 0.02762171f, 0.02164151f, - -9.58488265e-004f, -0.04231362f, -0.09866509f, 0.04322244f, - 0.05872034f, -0.04838847f, 0.06319253f, 0.02443798f, -0.03606876f, - 9.38737206e-003f, 0.04289991f, -0.01027411f, 0.08156885f, 0.08751175f, - -0.13191354f, 8.16054735e-003f, -0.01452161f, 0.02952677f, 0.03615945f, - -2.09128903e-003f, 0.02246693f, 0.09623287f, 0.09412123f, -0.02924758f, - -0.07815186f, -0.02203079f, -2.02566991e-003f, 0.01094733f, - -0.01442332f, 0.02838561f, 0.11882371f, 7.28798332e-003f, -0.10345965f, - 0.07561217f, -0.02049661f, 4.44177445e-003f, 0.01609347f, -0.04893158f, - -0.08758243f, -7.67420698e-003f, 0.08862378f, 0.06098121f, 0.06565887f, - 7.32981879e-003f, 0.03558407f, -0.03874352f, -0.02490055f, - -0.06771075f, 0.09939223f, -0.01066077f, 0.01382995f, -0.07289080f, - 7.47184316e-003f, 0.10621431f, -0.02878659f, 0.02383525f, -0.03274646f, - 0.02137008f, 0.03837290f, 0.02450992f, -0.04296818f, -0.02895143f, - 0.05327370f, 0.01499020f, 0.04998732f, 0.12938657f, 0.09391870f, - 0.04292390f, -0.03359194f, -0.06809492f, 0.01125796f, 0.17290455f, - -0.03430733f, -0.06255233f, -0.01813114f, 0.11726857f, -0.06127599f, - -0.08677909f, -0.03429872f, 0.04684938f, 0.08161420f, 0.03538774f, - 0.01833884f, 0.11321855f, 0.03261845f, -0.04826299f, 0.01752407f, - -0.01796414f, -0.10464549f, -3.30041884e-003f, 2.29343961e-004f, - 0.01457292f, -0.02132982f, -0.02602923f, -9.87351313e-003f, - 0.04273872f, -0.02103316f, -0.07994065f, 0.02614958f, -0.02111666f, - -0.06964913f, -0.13453490f, -0.06861878f, -6.09341264e-003f, - 0.08251446f, 0.15612499f, 2.46531400e-003f, 8.88424646e-003f, - -0.04152999f, 0.02054853f, 0.05277953f, -0.03087788f, 0.02817579f, - 0.13939077f, 0.07641046f, -0.03627627f, -0.03015098f, -0.04041540f, - -0.01360690f, -0.06227205f, -0.02738223f, 0.13577610f, 0.15235767f, - -0.05392922f, -0.11175954f, 0.02157129f, 0.01146481f, -0.05264937f, - -0.06595174f, -0.02749175f, 0.11812254f, 0.17404149f, -0.06137035f, - -0.11003478f, -0.01351621f, -0.01745916f, -0.08577441f, -0.04469909f, - -0.06106115f, 0.10559758f, 0.20806813f, -0.09174948f, 7.09621934e-004f, - 0.03579374f, 0.07215115f, 0.02221742f, 0.01827742f, -7.90785067e-003f, - 0.01489554f, 0.14519960f, -0.06425831f, 0.02990399f, -1.80181325e-003f, - -0.01401528f, -0.04171134f, -3.70530109e-003f, -0.09090481f, - 0.09520713f, 0.08845516f, -0.02651753f, -0.03016730f, 0.02562448f, - 0.03563816f, -0.03817881f, 0.01433385f, 0.02256983f, 0.02872120f, - 0.01001934f, -0.06332260f, 0.04338406f, 0.07001807f, -0.04705722f, - -0.07318907f, 0.02630457f, 0.03106382f, 0.06648342f, 0.10913180f, - -0.01630815f, 0.02910308f, 0.02895109f, 0.08040254f, 0.06969310f, - 0.06797734f, 6.08639978e-003f, 4.16588830e-003f, 0.08926726f, - -0.03123648f, 0.02700146f, 0.01168734f, -0.01631594f, 4.61015804e-003f, - 8.51359498e-003f, -0.03544224f, 0.03571994f, 4.29766066e-003f, - -0.01970077f, -8.79793242e-003f, 0.09607988f, 0.01544222f, - -0.03923707f, 0.07308586f, 0.06061262f, 1.31683104e-004f, - -7.98222050e-003f, 0.02399261f, -0.06084389f, -0.02743429f, - -0.05475523f, -0.04131311f, 0.03559756f, 0.03055342f, 0.02981433f, - 0.14860515f, 0.01766787f, 0.02945257f, 0.04898238f, 0.01026922f, - 0.02811658f, 0.08267091f, 0.02732154f, -0.01237693f, 0.11760156f, - 0.03802063f, -0.03309754f, 5.24957618e-003f, -0.02460510f, 0.02691451f, - 0.05399988f, -0.10133506f, 0.06385437f, -0.01818005f, 0.02259503f, - 0.03573135f, 0.01042848f, -0.04153402f, -0.04043029f, 0.01643575f, - 0.08326677f, 4.61383024e-004f, -0.05308095f, -0.08536223f, - -1.61011645e-003f, -0.02163720f, -0.01783352f, 0.03859637f, - 0.08498885f, -0.01725216f, 0.08625131f, 0.10995087f, 0.09177644f, - 0.08498347f, 0.07646490f, 0.05580502f, 0.02693516f, 0.09996913f, - 0.09070327f, 0.06667200f, 0.05873008f, -0.02247842f, 0.07772321f, - 0.12408436f, 0.12629253f, -8.41997913e-004f, 0.01477783f, 0.09165990f, - -2.98401713e-003f, -0.06466447f, -0.07057302f, 2.09516948e-004f, - 0.02210209f, -0.02158809f, -0.08602506f, -0.02284836f, - 4.01876355e-003f, 9.56660323e-003f, -0.02073978f, -0.04635138f, - -7.59423291e-003f, -0.01377393f, -0.04559359f, -0.13284740f, - -0.08671406f, -0.03654395f, 0.01142869f, 0.03287891f, -0.04392983f, - 0.06142959f, 0.17710890f, 0.10385257f, 0.01329137f, 0.10067633f, - 0.12450829f, -0.04476709f, 0.09049144f, 0.04589312f, 0.11167907f, - 0.08587538f, 0.04767583f, 1.67188141e-003f, 0.02359802f, -0.03808852f, - 0.03126272f, -0.01919029f, -0.05698918f, -0.02365112f, -0.06519032f, - -0.05599358f, -0.07097308f, -0.03301812f, -0.04719102f, -0.02566297f, - 0.01324074f, -0.09230672f, -0.05518232f, -0.04712864f, -0.03380903f, - -0.06719479f, 0.01183908f, -0.09326738f, 0.01642865f, 0.03789867f, - -6.61567831e-003f, 0.07796386f, 0.07246574f, 0.04706347f, -0.02523437f, - -0.01696830f, -0.08068866f, 0.06030888f, 0.10527060f, -0.06611756f, - 0.02977346f, 0.02621830f, 0.01913855f, -0.08479366f, -0.06322418f, - -0.13570616f, -0.07644490f, 9.31900274e-003f, -0.08095149f, - -0.10197903f, -0.05204025f, 0.01413151f, -0.07800411f, -0.01885122f, - -0.07509381f, -0.10136326f, -0.05212355f, -0.09944065f, - -1.33606605e-003f, -0.06342617f, -0.04178550f, -0.12373723f, - -0.02832736f, -0.06057501f, 0.05830070f, 0.07604282f, -0.06462587f, - 8.02447461e-003f, 0.11580125f, 0.12332212f, 0.01978462f, - -2.72378162e-003f, 0.05850752f, -0.04674481f, 0.05148062f, - -2.62542837e-003f, 0.11253355f, 0.09893716f, 0.09785093f, -0.04659257f, - -0.01102429f, -0.07002308f, 0.03088913f, -0.02565549f, -0.07671449f, - 3.17443861e-003f, -0.10783514f, -0.02314270f, -0.11089555f, - -0.01024768f, 0.03116021f, -0.04964825f, 0.02281825f, 5.50005678e-003f, - -0.08427856f, -0.14685495f, -0.07719755f, -0.13342668f, -0.04525511f, - -0.09914210f, 0.02588859f, 0.03469279f, 0.04664020f, 0.11688190f, - 0.09647275f, 0.10857815f, -0.01448726f, 0.04299758f, -0.06763151f, - 1.33257592e-003f, 0.14331576f, 0.07574340f, 0.09166205f, 0.05674926f, - 0.11325553f, -0.01106494f, 0.02062161f, -0.11484840f, -0.07492137f, - -0.02864293f, -0.01275638f, -0.06946032f, -0.10101652f, -0.04113498f, - -0.02214783f, -0.01273942f, -0.07480393f, -0.10556041f, -0.07622112f, - -0.09988393f, -0.11453961f, -0.12073903f, -0.09412795f, -0.07146588f, - -0.04054537f, -0.06127083f, 0.04221122f, 0.07688113f, 0.04099256f, - 0.12663734f, 0.14683802f, 0.21761774f, 0.12525328f, 0.18431792f, - -1.66402373e-003f, 2.37777247e-003f, 0.01445475f, 0.03509416f, - 0.02654697f, 0.01716739f, 0.05374011f, 0.02944174f, 0.11323927f, - -0.01485456f, -0.01611330f, -1.85554172e-003f, -0.01708549f, - -0.05435753f, -0.05302101f, 0.05260378f, -0.03582945f, - -3.42867890e-004f, 1.36076682e-003f, -0.04436073f, -0.04228432f, - 0.03281291f, -0.05480836f, -0.10197772f, -0.07206279f, -0.10741059f, - -0.02366946f, 0.10278475f, -2.74783419e-003f, -0.03242477f, - 0.02308955f, 0.02835869f, 0.10348799f, 0.19580358f, 0.10252027f, - 0.08039929f, 0.05525554f, -0.13250865f, -0.14395352f, 3.13586881e-003f, - -0.03387071f, 8.94669443e-003f, 0.05406157f, -4.97324532e-003f, - -0.01189114f, 2.82919413e-004f, -0.03901557f, -0.04898705f, - 0.02164520f, -0.01382906f, -0.01850416f, 0.01869347f, -0.02450060f, - 0.02291678f, 0.08196463f, 0.03309153f, -0.10629974f, 0.02473924f, - 0.05344394f, -0.02404823f, -0.03243643f, -5.55244600e-003f, - -0.08009996f, 0.02811539f, 0.04235742f, 0.01859004f, 0.04902123f, - -0.01438252f, -0.01526853f, 0.02044195f, -0.05008660f, 0.04244113f, - 0.07611816f, 0.04950470f, -0.06020549f, -4.26026015e-003f, 0.13133512f, - -0.01438738f, -0.01958807f, -0.04044152f, -0.12425045f, - 2.84353318e-003f, -0.05042776f, -0.09121484f, 7.34345755e-003f, - 0.09388847f, 0.11800314f, 4.72295098e-003f, 4.44378285e-003f, - -0.07984917f, -0.03613737f, 0.04490915f, -0.02246483f, 0.04681071f, - 0.05240871f, 0.02157206f, -0.04603431f, -0.01197929f, -0.02748779f, - 0.13621049f, 0.08812155f, -0.07802048f, 4.86458559e-003f, -0.01598836f, - 0.01024450f, -0.03463517f, -0.02304239f, -0.08692665f, 0.06655128f, - 0.05785803f, -0.12640759f, 0.02307472f, 0.07337402f, 0.07525434f, - 0.04943763f, -0.02241034f, -0.09978238f, 0.14487994f, -0.06570521f, - -0.07855482f, 0.02830222f, -5.29603509e-004f, -0.04669895f, - -0.11822784f, -0.12246452f, -0.15365660f, -0.02969127f, 0.08078201f, - 0.13512598f, 0.11505685f, 0.04740673f, 0.01376022f, -0.05852978f, - -0.01537809f, -0.05541119f, 0.02491065f, -0.02870786f, 0.02760978f, - 0.23836176f, 0.22347429f, 0.10306466f, -0.06919070f, -0.10132039f, - -0.20198342f, -0.05040560f, 0.27163076f, 0.36987007f, 0.34540465f, - 0.29095781f, 0.05649706f, 0.04125737f, 0.07505883f, -0.02737836f, - -8.43431335e-003f, 0.07368195f, 0.01653876f, -0.09402955f, - -0.09574359f, 0.01474337f, -0.07128561f, -0.03460737f, 0.11438941f, - 0.13752601f, -0.06385452f, -0.06310338f, 8.19548313e-003f, 0.11622470f, - 5.05133113e-003f, -0.07602754f, 0.06695660f, 0.25723928f, 0.09037900f, - 0.28826267f, 0.13165380f, -0.05312614f, -0.02137198f, -0.03442232f, - -0.06255679f, 0.03899667f, 0.18391028f, 0.26016650f, 0.03374462f, - 0.01860465f, 0.19077586f, 0.18160543f, 3.43634398e-003f, -0.03036782f, - 0.19683038f, 0.35378191f, 0.24968483f, -0.03222649f, 0.28972381f, - 0.43091634f, 0.30778357f, 0.02335266f, -0.09877399f, -6.85245218e-003f, - 0.08945240f, -0.08150686f, 0.02792493f, 0.24806842f, 0.17338486f, - 0.06231801f, -0.10432383f, -0.16653322f, -0.13197899f, -0.08531576f, - -0.19271527f, -0.13536365f, 0.22240199f, 0.39219588f, 0.26597717f, - -0.01231649f, 0.01016179f, 0.13379875f, 0.12018334f, -0.04852953f, - -0.07915270f, 0.07036012f, 3.87723115e-003f, -0.06126805f, - -0.15015170f, -0.11406515f, -0.08556531f, -0.07429333f, -0.16115491f, - 0.13214062f, 0.25691369f, 0.05697750f, 0.06861912f, -6.02903729e-003f, - -7.94562511e-003f, 0.04799571f, 0.06695165f, -0.01926842f, 0.06206308f, - 0.13450983f, -0.06381495f, -2.98370165e-003f, -0.03482971f, - 7.53991678e-003f, 0.03895611f, 0.11464261f, 0.01669971f, - 8.27818643e-003f, -7.49160210e-003f, -0.11712562f, -0.10650621f, - -0.10353880f, -0.04994106f, -7.65618810e-004f, 0.03023767f, - -0.04759270f, -0.07302686f, -0.05825012f, -0.13156348f, -0.10639747f, - -0.19393684f, -0.09973683f, -0.07918908f, 4.63177625e-004f, - -6.61382044e-004f, 0.15853868f, 0.08561199f, -0.07660093f, - -0.08015265f, -0.06164073f, 0.01882577f, -7.29908410e-004f, - 0.06840892f, 0.03843764f, 0.20274927f, 0.22028814f, -5.26101235e-003f, - 0.01452435f, -0.06331623f, 0.02865064f, 0.05673740f, 0.12171564f, - 0.03837196f, 0.03555467f, -0.02662914f, -0.10280123f, -0.06526285f, - -0.11066351f, -0.08988424f, -0.10103678f, 8.10526591e-003f, - 5.95238712e-003f, 0.02617721f, -0.01705742f, -0.10897956f, - -0.08004991f, -0.11271993f, -0.06185647f, -0.06103712f, 0.01597041f, - -0.05923606f, 0.09410726f, 0.22858568f, 0.03263380f, 0.06772990f, - -0.09003516f, 0.01017870f, 0.01931688f, 0.08628357f, -0.01430009f, - 0.10954945f, 0.16612452f, -0.02434544f, -0.03310068f, -0.04236627f, - 0.01212392f, -6.15046406e-003f, 0.06954194f, 0.03015283f, 0.01787957f, - 0.02781667f, -0.05561153f, -8.96244217e-003f, -0.04971489f, - 0.07510284f, 0.01775282f, 0.05889897f, -0.07981427f, 0.03647643f, - -3.73833324e-003f, -0.08894575f, -0.06429435f, -0.08068276f, - 0.03567704f, -0.07131936f, -7.21910037e-003f, -0.09566668f, - 0.17886090f, 0.14911725f, 0.02070032f, -0.05017120f, -0.04992622f, - 0.01570143f, -0.09906903f, 0.06456193f, 0.15329507f, 0.18820767f, - 0.11689861f, -0.01178513f, -0.02225163f, -0.01905318f, 0.10271224f, - -7.27029052e-003f, 0.11664233f, 0.14796902f, 0.07771893f, 0.02400013f, - -0.05361797f, -0.01972888f, 0.01376177f, 0.06740040f, -0.06525395f, - 0.05726178f, -0.02404981f, -0.14018567f, -0.02074987f, -0.04621970f, - -0.04688627f, -0.01842059f, 0.07722727f, -0.04852883f, 0.01529004f, - -0.19639495f, 0.10817073f, 0.03795860f, -0.09435206f, -0.07984378f, - -0.03383440f, 0.11081333f, 0.02237366f, 0.12703256f, 0.21613893f, - 0.02918790f, 4.66472283e-003f, -0.10274266f, -0.04854131f, - -3.46305710e-003f, 0.08652268f, 0.02251546f, 0.09636052f, 0.17180754f, - -0.09272388f, 4.59174305e-004f, -0.11723048f, -0.12210111f, - -0.15547538f, 0.07218186f, -0.05297846f, 0.03779940f, 0.05150875f, - -0.03802310f, 0.03870645f, -0.15250699f, -0.08696499f, -0.02021560f, - 0.04118926f, -0.15177974f, 0.01577647f, 0.10249301f, 7.50041893e-003f, - 0.01721806f, -0.06828983f, -0.02397596f, -0.06598977f, -0.04317593f, - -0.08064980f, 6.66632550e-003f, 0.03333484f, 0.07093620f, 0.08231064f, - -0.06577903f, -0.06698844f, -0.06984019f, -0.06508023f, -0.14145090f, - -0.02393239f, 0.06485303f, 8.83263443e-003f, 0.09251080f, -0.07557579f, - -0.05067699f, -0.09798748f, -0.06703258f, -0.14056294f, 0.03245994f, - 0.12554143f, 0.01761621f, 0.12980327f, -0.04081950f, -0.11906909f, - -0.14813015f, -0.08376863f, -0.12200681f, 0.04988137f, 0.05424247f, - -3.90952639e-003f, 0.03255733f, -0.12717837f, -0.07461493f, - -0.05703964f, -0.01736189f, -0.08026433f, -0.05433894f, -0.01719359f, - 0.02886275f, 0.01772653f, -0.09163518f, 3.57789593e-003f, -0.10129993f, - -0.02653764f, -0.08131415f, -0.03847986f, -7.62157550e-004f, - 0.06486648f, 0.19675669f, -0.04919156f, -0.07059129f, -0.04857785f, - -0.01042383f, -0.08328653f, 0.03660302f, -0.03696846f, 0.04969259f, - 0.08241162f, -0.12514858f, -0.06122676f, -0.03750202f, - 6.52989605e-003f, -0.10247213f, 0.02568346f, 4.51781414e-003f, - -0.03734229f, -0.01131264f, -0.05412074f, 8.89345480e-004f, - -0.12388977f, -0.05959237f, -0.12418608f, -0.06151643f, -0.07310260f, - 0.02441575f, 0.07023528f, -0.07548289f, -7.57147965e-004f, - -0.09061348f, -0.08112976f, -0.06920306f, 9.54394229e-003f, - -0.01219902f, 1.21273217e-003f, -8.88989680e-003f, -0.08309301f, - -0.04552661f, -0.10739882f, -0.05691034f, -0.13928030f, 0.09027749f, - 0.15123098f, 0.03175976f, 0.17763577f, 3.29913251e-004f, 0.05151888f, - -0.09844074f, -0.09475287f, -0.08571247f, 0.16241577f, 0.19336018f, - 8.57454538e-003f, 0.11474732f, -0.01493934f, 0.03352379f, -0.08966240f, - -0.02322310f, 0.02663568f, 0.05448750f, -0.03536883f, -0.07210463f, - -0.06807277f, -0.03121621f, -0.05932408f, -0.17282860f, -0.15873498f, - -0.04956378f, 0.01603377f, -0.12385946f, 0.13878587f, 0.21468069f, - 0.13510075f, 0.20992437f, 0.08845878f, 0.08104013f, 0.03754176f, - 0.12173114f, 0.11103114f, 0.10643122f, 0.13941477f, 0.11640384f, - 0.14786847f, 0.01218238f, 0.01160753f, 0.03547940f, 0.08794311f, - -0.01695384f, -0.07692261f, -0.08236158f, 6.79194089e-003f, - -0.02458403f, 0.13022894f, 0.10953187f, 0.09857773f, 0.04735930f, - -0.04353498f, -0.15173385f, -0.17904443f, -0.10450364f, -0.13418166f, - -0.06633098f, -0.03170381f, -0.06839000f, -0.11350126f, -0.06983913f, - 0.19083543f, 0.17604128f, 0.07730632f, 0.10022651f, 0.36428109f, - 0.28291923f, 0.12688625f, 0.15942036f, 0.14064661f, -0.11201853f, - -0.13969108f, -0.09088077f, -0.14107047f, 0.05117374f, - -2.63348082e-003f, -0.10794610f, -0.09715455f, -0.05284977f, - 0.01565668f, 0.05031200f, 0.07021113f, -0.02963028f, 0.01766960f, - 0.08333644f, -0.03211382f, 4.90096770e-003f, 0.05186674f, -0.05045737f, - -0.09624767f, -0.02525997f, 0.06916669f, 0.01213916f, 0.05333899f, - -0.03443280f, -0.10055527f, -0.06291115f, 5.42851724e-003f, - -6.30360236e-003f, 0.02270257f, -0.01769792f, 0.03273688f, 0.07746078f, - 7.77099328e-003f, 0.05041346f, 0.01648103f, -0.02321534f, -0.09930186f, - -0.02293853f, 0.02034990f, -0.08324204f, 0.08510064f, -0.03732836f, - -0.06465405f, -0.06086946f, 0.13680504f, -0.11469388f, -0.03896406f, - -0.07142810f, 2.67581246e-003f, -0.03639632f, -0.09849060f, - -0.11014334f, 0.17489147f, 0.17610909f, -0.16091567f, -0.07248894f, - 0.01567141f, 0.23742996f, 0.07552249f, -0.06270349f, -0.07303379f, - 0.25442186f, 0.16903116f, -0.08168741f, -0.05913896f, -0.03954096f, - 6.81776879e-003f, -0.05615319f, -0.07303037f, -0.12176382f, - 0.12385108f, 0.22084464f, -0.05543206f, -0.03310431f, 0.05731593f, - 0.19481890f, 0.04016430f, -0.06480758f, -0.12353460f, 0.18733442f, - -0.09631214f, -0.11192076f, 0.12404587f, 0.15671748f, 0.19256128f, - 0.10895617f, 0.03391477f, -0.13032004f, -0.05626907f, -0.09025607f, - 0.23485197f, 0.27812332f, 0.26725492f, 0.07255980f, 0.16565137f, - 0.22388470f, 0.07441066f, -0.21003133f, -0.08075339f, -0.15031935f, - 0.07023834f, 0.10872041f, 0.18156518f, 0.20037253f, 0.13571967f, - -0.11915682f, -0.11131983f, -0.18878011f, 0.06074620f, 0.20578890f, - 0.12413109f, 0.03930207f, 0.29176015f, 0.29502738f, 0.27856228f, - -0.01803601f, 0.16646385f, 0.19268319f, 0.01900682f, 0.06026287f, - 2.35868432e-003f, 0.01558199f, 0.02707230f, 0.11383014f, 0.12103992f, - 0.03907350f, 0.04637353f, 0.09020995f, 0.11919726f, -3.63007211e-003f, - 0.02220155f, 0.10336831f, 0.17351882f, 0.12259731f, 0.18983354f, - 0.15736865f, 0.01160725f, -0.01690723f, -9.69582412e-004f, 0.07213813f, - 0.01161613f, 0.17864859f, 0.24486147f, 0.18208991f, 0.20177495f, - 0.05972528f, -8.93934630e-003f, -0.02316955f, 0.14436610f, 0.14114498f, - 0.05520950f, 0.06353590f, -0.19124921f, 0.10174713f, 0.29414919f, - 0.26448128f, 0.09344960f, 0.15284036f, 0.19797507f, 0.11369792f, - -0.12722753f, -0.21396367f, -0.02008235f, -0.06566695f, -0.01662150f, - -0.03937003f, 0.04778343f, 0.05017274f, -0.02299062f, -0.20208496f, - -0.06395898f, 0.13721776f, 0.22544557f, 0.14888357f, 0.08687132f, - 0.27088094f, 0.32206613f, 0.09782200f, -0.18523243f, -0.17232181f, - -0.01041531f, 0.04008654f, 0.04199702f, -0.08081299f, -0.03755421f, - -0.04809646f, -0.05222081f, -0.21709201f, -0.06622940f, 0.02945281f, - -0.04600435f, -0.05256077f, -0.08432942f, 0.02848100f, 0.03490564f, - 8.28621630e-003f, -0.11051246f, -0.11210597f, -0.01998289f, - -0.05369405f, -0.08869293f, -0.18799506f, -0.05436598f, -0.05011634f, - -0.05419716f, -0.06151857f, -0.10827805f, 0.04346735f, 0.04016083f, - 0.01520820f, -0.12173316f, -0.04880285f, -0.01101406f, 0.03250847f, - -0.06009551f, -0.03082932f, -0.02295134f, -0.06856834f, -0.08775249f, - -0.23793389f, -0.09174541f, -0.05538322f, -0.04321031f, -0.11874759f, - -0.04221844f, -0.06070468f, 0.01194489f, 0.02608565f, -0.03892140f, - -0.01643151f, -0.02602034f, -0.01305472f, 0.03920100f, -0.06514261f, - 0.01126918f, -6.27710763e-003f, -0.02720047f, -0.11133634f, - 0.03300330f, 0.02398472f, 0.04079665f, -0.10564448f, 0.05966159f, - 0.01195221f, -0.03179441f, -0.01692590f, -0.06177841f, 0.01841576f, - -5.51078189e-003f, -0.06821765f, -0.03191888f, -0.09545476f, - 0.03030550f, -0.04896152f, -0.02914624f, -0.13283344f, -0.04783419f, - 6.07836898e-003f, -0.01449538f, -0.13358212f, -0.09687774f, - -0.02813793f, 0.01213498f, 0.06650011f, -0.02039067f, 0.13356198f, - 0.05986415f, -9.12760664e-003f, -0.18780160f, -0.11992817f, - -0.06342237f, 0.01229534f, 0.07143231f, 0.10713009f, 0.11085765f, - 0.06569190f, -0.02956399f, -0.16288325f, -0.13993549f, -0.01292515f, - 0.03833013f, 0.09130384f, -0.05086257f, 0.05617329f, -0.03896667f, - -0.06282311f, -0.11490010f, -0.14264110f, -0.04530499f, 0.01598189f, - 0.09167797f, 0.08663294f, 0.04885277f, -0.05741219f, -0.07565769f, - -0.17136464f, -0.02619422f, -0.02477579f, 0.02679587f, 0.11621952f, - 0.08788391f, 0.15520640f, 0.04709549f, 0.04504483f, -0.10214074f, - -0.12293372f, -0.04820546f, -0.05484834f, 0.05473754f, 0.07346445f, - 0.05577277f, -0.08209965f, 0.03462975f, -0.20962234f, -0.09324598f, - 3.79481679e-003f, 0.03617633f, 0.16742408f, 0.07058107f, 0.10204960f, - -0.06795346f, 3.22807301e-003f, -0.12589309f, -0.17496960f, - 0.02078314f, -0.07694324f, 0.12184640f, 0.08997164f, 0.04793497f, - -0.11383379f, -0.08046359f, -0.25716835f, -0.08080962f, - 6.80711539e-003f, -0.02930280f, -3.04938294e-003f, -0.11106286f, - -0.04628860f, -0.07821649f, 7.70127494e-003f, -0.10247706f, - 1.21042714e-003f, 0.20573859f, -0.03241005f, 8.42972286e-003f, - 0.01946464f, -0.01197973f, -0.14579976f, 0.04233614f, - -4.14096704e-003f, -0.06866436f, -0.02431862f, -0.13529138f, - 1.25891645e-003f, -0.11425111f, -0.04303651f, -0.01694815f, - 0.05720210f, -0.16040207f, 0.02772896f, 0.05498345f, -0.15010567f, - 0.01450866f, 0.02350303f, -0.04301004f, -0.04951802f, 0.21702233f, - -0.03159155f, -0.01963303f, 0.18232647f, -0.03263875f, - -2.88476888e-003f, 0.01587562f, -1.94303901e-003f, -0.07789494f, - 0.04674156f, -6.25576358e-003f, 0.08925962f, 0.21353747f, 0.01254677f, - -0.06999976f, -0.05931328f, -0.01884327f, -0.04306272f, 0.11794136f, - 0.03842728f, -0.03907030f, 0.05636114f, -0.09766009f, -0.02104000f, - 8.72711372e-003f, -0.02736877f, -0.05112274f, 0.16996814f, 0.02955785f, - 0.02094014f, 0.08414304f, -0.03335762f, -0.03617457f, -0.05808248f, - -0.08872101f, 0.02927705f, 0.27077839f, 0.06075108f, 0.07478261f, - 0.15282831f, -0.03908454f, -0.05101782f, -9.51998029e-003f, - -0.03272416f, -0.08735625f, 0.07633440f, -0.07185312f, 0.13841286f, - 0.07812646f, -0.12901451f, -0.05488589f, -0.05644578f, -0.03290703f, - -0.11184757f, 0.03751570f, -0.05978153f, -0.09155276f, 0.05657315f, - -0.04328186f, -0.03047933f, -0.01413135f, -0.10181040f, -0.01384013f, - 0.20132534f, -0.01536873f, -0.07641169f, 0.05906778f, -0.07833145f, - -0.01523801f, -0.07502609f, -0.09461885f, -0.15013233f, 0.16050665f, - 0.09021381f, 0.08473236f, 0.03386267f, -0.09147339f, -0.09170618f, - -0.08498498f, -0.05119187f, -0.10431040f, 0.01041618f, -0.03064913f, - 0.09340212f, 0.06448522f, -0.03881054f, -0.04985436f, -0.14794017f, - -0.05200112f, -0.02144495f, 0.04000821f, 0.12420804f, -0.01851651f, - -0.04116732f, -0.11951703f, -0.04879033f, -0.08722515f, -0.08454733f, - -0.10549165f, 0.11251976f, 0.10766345f, 0.19201984f, 0.06128913f, - -0.02734615f, -0.08834923f, -0.16999826f, -0.03548348f, - -5.36092324e-003f, 0.08297954f, 0.07226378f, 0.04194529f, 0.04668673f, - 8.73902347e-003f, 0.06980139f, 0.05652480f, 0.05879445f, 0.02477076f, - 0.02451423f, 0.12433673f, 0.05600227f, 0.06886370f, 0.03863076f, - 0.07459056f, 0.02264139f, 0.01495469f, 0.06344220f, 0.06945208f, - 0.02931899f, 0.11719371f, 0.04527427f, 0.03248192f, 2.08271481e-003f, - 0.02044626f, 0.11403449f, 0.04303892f, 0.06444661f, 0.04959024f, - 0.08174094f, 0.09240247f, 0.04894639f, 0.02252937f, -0.01652530f, - 0.07587013f, 0.06064249f, 0.13954395f, 0.02772832f, 0.07093039f, - 0.08501238f, 0.01701301f, 0.09055722f, 0.33421436f, 0.20163782f, - 0.09821030f, 0.07951369f, 0.08695120f, -0.12757730f, -0.13865978f, - -0.06610068f, -0.10985506f, 0.03406816f, -0.01116336f, -0.07281768f, - -0.13525715f, -0.12844718f, 0.08956250f, 0.09171610f, 0.10092317f, - 0.23385370f, 0.34489515f, 0.09901748f, 0.02002922f, 0.12335990f, - 0.07606190f, -0.14899330f, -0.15634622f, -0.06494618f, -0.01760547f, - 0.03404277f, -0.13208845f, -0.12101169f, -0.18294574f, -0.16560709f, - 0.02183887f, -0.02752613f, 0.01813638f, 0.02000757f, 0.01319924f, - 0.08030242f, 0.01220535f, 2.98233377e-003f, -0.01307070f, 0.05970297f, - -0.05345284f, -0.03381982f, -9.87543724e-003f, -0.06869387f, - 0.03956730f, -0.03108176f, -0.05732809f, 0.02172386f, 0.04159765f, - 2.62783933e-003f, 0.04813229f, 0.09358983f, -8.18389002e-003f, - 0.01724574f, -0.02547474f, -0.04967288f, -0.02390376f, 0.06640504f, - -0.06306566f, 0.01137518f, 0.05589378f, -0.08237787f, 0.02455001f, - -0.03059422f, -0.08953978f, 0.06851497f, 0.07190268f, -0.07610799f, - 7.87237938e-003f, -7.85830803e-003f, 0.06006952f, -0.01126728f, - -2.85743061e-003f, -0.04772895f, 0.01884944f, 0.15005857f, - -0.06268821f, -0.01989072f, 0.01138399f, 0.08760451f, 0.03879007f, - -9.66926850e-003f, -0.08012961f, 0.06414555f, -0.01362950f, - -0.09135523f, 0.01755159f, 0.04459474f, 0.09650917f, 0.05219948f, - -2.19440833e-003f, -0.07037939f, -0.01599054f, 0.13103317f, - -0.02492603f, -0.01032540f, -0.02903307f, 0.04489160f, 0.05148086f, - 0.01858173f, -0.02919228f, 0.08299296f, -0.04590359f, -0.15745632f, - -0.09068198f, -0.02972453f, 0.12985018f, 0.22320485f, 0.24261914f, - 0.03642650f, -0.05506422f, 2.67413049e-003f, -0.03834032f, 0.06449424f, - 0.03834866f, 0.03816991f, 0.25039271f, 0.34212017f, 0.32433882f, - 0.18824573f, -0.08599839f, -0.17599408f, -0.15317015f, -0.09913155f, - -0.02856072f, -0.05304699f, -1.06437842e-003f, -0.06641813f, - -0.07509298f, 0.01463361f, -0.07551918f, -0.04510373f, - -8.44620075e-003f, 0.01772176f, 0.04068235f, 0.20295307f, 0.15719447f, - 0.05712103f, 0.26296997f, 0.14657754f, 0.01547317f, -0.05052776f, - -0.03881342f, -0.01437883f, -0.04930177f, 0.11719568f, 0.24098417f, - 0.26468599f, 0.31698579f, 0.10103608f, -0.01096375f, -0.01367013f, - 0.17104232f, 0.20065314f, 2.67622480e-003f, -0.01190034f, 0.18301608f, - 0.09459770f, -0.06357619f, -0.06473801f, 0.01377906f, -0.10032775f, - -0.06388740f, 3.80393048e-003f, 0.06206078f, 0.10349120f, 0.26804337f, - 8.17918684e-003f, -0.02314351f, 9.34422202e-003f, 0.09198381f, - 0.03681326f, -8.77339672e-003f, -0.09662418f, -0.02715708f, - 0.13503517f, 0.08962728f, -6.57071499e-003f, -0.03201199f, 0.28510824f, - 0.32095715f, 0.18512695f, -0.14230858f, -0.14048551f, -0.07181299f, - -0.08575408f, -0.08661680f, -0.17416079f, 7.54326640e-004f, - 0.05601677f, 0.13585392f, -0.04960437f, -0.07708392f, 0.10676333f, - -0.04407546f, -0.07209078f, 0.03663663f, 0.28949317f, 0.41127121f, - 0.27431169f, -0.06900328f, -0.21474190f, -0.15578632f, -0.19555484f, - -0.15209621f, -0.11269179f, 0.07416003f, 0.18991330f, 0.26858172f, - 0.01952259f, 0.01017922f, 0.02159843f, -4.95165400e-003f, -0.04368168f, - -0.12721671f, -0.06673957f, -0.11275250f, 0.04413409f, 0.05578312f, - 0.03896771f, 0.03566417f, -0.05871816f, -0.07388090f, -0.17965563f, - -0.08570268f, -0.15273231f, -0.06022318f, -0.06999847f, - -6.81510568e-003f, 0.06294262f, -6.54901436e-004f, -0.01128654f, - -0.02289657f, 0.04849290f, 0.04140804f, 0.23681939f, 0.14545733f, - 0.01989965f, 0.12032662f, 3.87463090e-003f, -6.02597650e-003f, - -0.05919775f, -0.03067224f, -0.07787777f, 0.10834727f, 0.02153730f, - 0.02765649f, 0.03975543f, -0.12182906f, -0.04900113f, -0.09940100f, - -0.06453611f, -0.13757215f, -0.03721382f, 0.02827376f, -0.04351249f, - 0.01907038f, -0.10284120f, -0.05671160f, -0.10760647f, -0.09624009f, - -0.09565596f, -0.01303654f, 0.03080539f, 0.01416511f, 0.05846142f, - -5.42971538e-003f, 0.06221476f, -0.03320325f, -0.06791797f, - -0.05791342f, 0.12851369f, 0.14990346f, 0.03634374f, 0.14262885f, - 0.04330391f, 0.05032569f, -0.05631914f, 0.01606137f, 0.04387223f, - 0.22344995f, 0.15722635f, -0.04693628f, 0.03006579f, -2.52882647e-003f, - 0.05717621f, -0.07529724f, -0.02848588f, -0.06868757f, - -4.51729307e-003f, 0.06466042f, -0.05935378f, -0.04704857f, - -0.07363959f, 0.04843248f, -0.13421375f, -0.09789340f, -0.10255270f, - 0.03509852f, 0.04751543f, -0.03822323f, 0.09740467f, 0.04762916f, - 0.03940146f, -0.08283259f, 0.09552965f, 0.05038739f, 0.21258622f, - 0.09646992f, 0.03241193f, 0.05167701f, 0.04614570f, 0.04330090f, - -0.02671840f, -0.06259909f, -0.02301898f, 0.18829170f, 0.10522786f, - 0.04313190f, 0.01670948f, -0.08421925f, 0.05911417f, -0.10582602f, - -0.04855484f, -0.08373898f, 0.07775915f, 0.03723533f, -0.12047344f, - 4.86345543e-003f, -0.10520902f, 0.06571782f, -0.07528137f, - -0.03245651f, -0.09869066f, -0.02917477f, -0.18293270f, 0.14810945f, - 9.24033765e-003f, -0.04354914f, 0.02266885f, -0.11872729f, - -0.04016589f, 0.02830229f, 0.22539048f, 0.20565644f, 0.16701797f, - 0.09019924f, 0.01300652f, 0.09760600f, -0.03675831f, -0.01935448f, - -0.06894835f, 0.08077277f, 0.19047537f, 0.11312226f, 0.04106043f, - -0.11187182f, 0.04312806f, -0.18548580f, -0.11287174f, -0.08794551f, - 0.02078281f, -0.15295486f, 0.11806386f, -0.01103218f, -0.15971117f, - 0.02153538f, -0.05232147f, -0.10835317f, -0.13910367f, 0.05920752f, - -0.10122602f, 0.20174250f, 0.09105796f, -0.01881348f, 0.09559010f, - -0.03725745f, -0.09442931f, -0.09763174f, 0.05854454f, 0.08287182f, - 0.12919849f, 0.08594352f, -2.49806582e-003f, 0.02398440f, - 5.67950122e-003f, -0.06296340f, -0.12993270f, 0.03855852f, 0.05186560f, - 0.10839908f, -0.03380463f, -0.12654832f, -0.05399339f, -0.07456800f, - -0.04736232f, -0.10164231f, 0.07496139f, 0.08125214f, 0.07656177f, - -0.04999603f, -0.12823077f, -0.07692395f, -0.11317524f, -0.09118655f, - -0.05695669f, 0.10477209f, 0.07468581f, 0.01630048f, -8.00961629e-003f, - -0.06582128f, -0.04019095f, -0.04682907f, -0.01907842f, -0.10997720f, - 0.04911406f, 0.02931030f, 0.04197735f, -0.05773980f, -0.09670641f, - -0.03594951f, -0.03402121f, -0.07149299f, -0.10566200f, 0.10601286f, - 0.06340689f, -0.01518632f, -5.96402306e-003f, -0.07628012f, - -3.52779147e-003f, -0.02683854f, -0.10265494f, -0.02680815f, - 0.16338381f, 0.03103515f, 0.02296976f, 0.01624348f, -0.10831620f, - -0.02314233f, -0.04789969f, -0.05530700f, -0.06461314f, 0.10494506f, - 0.04642856f, -0.07592955f, -0.06197905f, -0.09042154f, -0.01445521f, - -0.04297818f, -0.11262015f, -0.11430512f, 0.03174541f, -0.03677487f, - -0.02963996f, -0.06610169f, -0.13292049f, -0.07059067f, -0.08444111f, - -0.02640536f, -0.07136250f, 0.04559967f, 0.01459980f, 0.17989251f, - 0.04435328f, -0.12464730f, -0.02871115f, -0.10752209f, -0.03393742f, - -0.03791408f, 0.02548251f, 0.01956050f, 0.19245651f, 0.13963254f, - -0.05904696f, -0.07424626f, -0.10411884f, 1.54176133e-003f, - 0.01797429f, 0.13025844f, 0.04547642f, -0.05710349f, -0.10697161f, - -0.13489437f, -0.06515755f, -0.06406886f, -4.08572936e-003f, - -0.01336483f, 0.04368737f, -0.11259720f, -0.05701635f, -0.06469971f, - -0.08346602f, -0.04166770f, -0.05795543f, -0.08247511f, -0.05742628f, - 0.08452254f, -0.03350224f, 0.13980860f, 0.13252275f, 0.07589617f, - 0.07539988f, 0.12155797f, 0.19087289f, 0.15050751f, 0.21250245f, - 0.14206800f, 0.01298489f, 0.07450245f, 0.06559097f, 0.01700557f, - 0.04512971f, 0.16950700f, 0.10261577f, 0.16389982f, 0.05505059f, - -0.03453077f, 0.08622462f, 0.07935954f, 0.03976260f, 0.02036091f, - 3.95744899e-003f, 0.03267065f, 0.15235919f, 0.01297494f, -0.08109194f, - 0.01407558f, 4.40693414e-003f, -0.15157418f, -0.11390478f, - -0.07487597f, -7.81322457e-003f, -0.02749545f, -0.10181408f, - 0.13755716f, 0.14007211f, 0.13482562f, 0.27517235f, 0.34251109f, - 0.07639657f, 0.07268607f, 0.19823882f, 0.16135791f, -0.04186463f, - -0.12784107f, -0.09846287f, 0.03169041f, 0.10974082f, -0.15051922f, - -0.08916726f, -0.07138767f, -0.04153349f, 6.25418453e-003f, - 0.01266654f, 0.10533249f, 0.12749144f, 0.15148053f, 0.01498513f, - 0.06305949f, -0.01247123f, -0.08778401f, -0.08551880f, -0.11955146f, - -0.08493572f, -0.02901620f, -0.02394859f, -0.13427313f, -0.11053200f, - -0.14413260f, -0.15203285f, 0.03972760f, -3.72127310e-004f, - -0.04200919f, 0.06105104f, 0.01904975f, -0.01106191f, - -7.27445772e-003f, -0.01520341f, 1.10228511e-003f, -0.04949187f, - -0.08013099f, 5.72071038e-003f, 0.08415454f, -0.06523152f, 0.03664081f, - -0.02673042f, -0.12066154f, -0.03702074f, 0.06006580f, 0.01628682f, - -6.17772620e-003f, 0.08192339f, -3.41629819e-003f, 0.02870512f, - 0.05807141f, 0.04959986f, 0.04618251f, -0.04901629f, -0.10579574f, - 0.02274442f, 0.12070961f, 2.23597488e-003f, 0.09831765f, -0.03019848f, - -0.11181970f, -0.04961075f, 0.02498928f, -0.03714991f, -0.01619653f, - 0.02643486f, -7.62964319e-003f, -0.02882290f, -0.06242594f, - -0.08439861f, 0.07220893f, 0.07263952f, 0.01561574f, 0.03091968f, - 0.01708712f, -0.03797151f, -3.18561122e-003f, 0.01624021f, - -0.02828573f, 0.11284444f, -1.32280716e-003f, -0.07784860f, - -0.07209100f, 0.03372242f, 0.12154529f, 0.02278104f, -0.05275500f, - -0.01918484f, 0.12989293f, 0.05424401f, 0.02333086f, 0.04029022f, - 0.12392918f, 0.09495489f, 0.09190340f, 0.07935889f, 8.76816828e-003f, - 0.17148446f, -8.51302687e-003f, -0.08011249f, -0.06796283f, - 0.04884845f, 0.01112272f, -0.07835306f, -1.14811445e-003f, - -0.03440760f, 0.02845243f, 0.07695542f, -0.07069533f, -0.01151784f, - -8.53884313e-003f, -0.01662786f, -0.04163864f, 0.05400505f, - 0.02859163f, 0.02921852f, 0.05003135f, -6.85718050e-003f, -0.01632611f, - 0.07780217f, 0.04042810f, -0.01216440f, 3.60914599e-003f, -0.06322435f, - 0.09516726f, 0.12877031f, -9.69162490e-003f, 0.01031179f, 0.05180895f, - -9.34659224e-003f, -0.01644533f, -0.04849347f, -0.04343236f, - 0.10514783f, 0.08046635f, -0.04615205f, -0.03975486f, -0.01485525f, - 0.13096830f, -0.01517950f, -0.06571898f, -0.04016372f, 0.01849786f, - 0.02439670f, 0.08067258f, 1.74824719e-003f, 0.07053747f, 0.08819518f, - -5.08352555e-003f, -0.06550863f, -0.08266170f, -0.07780605f, - 0.01453450f, -0.08756890f, 0.01096501f, -8.71319138e-003f, 0.10110464f, - 0.02420769f, -0.06708383f, 0.02007811f, 5.93133038e-003f, 0.05398923f, - 0.07538138f, 0.02049227f, 0.02242589f, 0.04011070f, -1.44875818e-003f, - -4.19115182e-003f, 0.06367654f, 0.02506934f, 0.02434536f, 0.05879405f, - -8.22952855e-003f, -0.01242441f, 0.04224926f, -0.01754923f, - 0.05958161f, 0.03818886f, -0.01830363f, -0.04308917f, -0.04422197f, - -0.02432721f, 0.02264866f, 2.03751423e-003f, 0.01197031f, 0.04439203f, - 0.12169247f, 0.03602713f, -0.02599251f, -1.98226492e-003f, 0.02046336f, - -0.02639058f, -1.91242550e-003f, -0.09334669f, -0.03595153f, - -9.88179818e-003f, -0.06848445f, -0.04666303f, -0.09955736f, - -0.04206430f, 0.02609075f, 9.09005292e-003f, -0.07138551f, - -4.22313227e-004f, 0.01766645f, 0.02756404f, 0.01308276f, 0.04052891f, - 0.02387515f, 0.05337298f, 0.02500631f, -0.04970853f, -0.12467445f, - 0.17604403f, 0.12256411f, -0.07512254f, 8.70451052e-003f, -0.05697548f, - -0.03626474f, -8.76623299e-003f, -0.01210897f, -0.09451522f, - 0.07490732f, -0.02008001f, -0.02681278f, -0.06463405f, -0.01517507f, - 7.33757764e-003f, 6.07147906e-003f, -0.09316964f, -0.04575328f, - 0.13261597f, 0.15424870f, -0.01655918f, -0.02772390f, -0.05243644f, - -0.02356456f, -0.02351753f, -0.10211615f, -0.12873036f, 0.14549787f, - 0.12519856f, 4.38762689e-003f, 0.02795992f, 0.05170322f, 0.09223596f, - 0.05890015f, 0.02376701f, -0.02777346f, 0.09506908f, 0.02328936f, - -0.02319928f, -0.03218696f, -0.01527841f, -0.01016694f, -0.02674719f, - 0.05137179f, 0.01980666f, 0.06544447f, -0.01746171f, 0.01026380f, - 0.01561806f, 7.97004555e-004f, 0.07601810f, 0.01907250f, -0.03083035f, - -0.05987392f, 0.09242783f, 0.14555025f, 0.01035827f, 0.03092401f, - -0.09562709f, -0.03802354f, 0.02531144f, 0.03079449f, -0.07100715f, - 0.03330721f, -2.69116857e-003f, 0.03167490f, 0.05744999f, 0.03259895f, - 1.91266940e-003f, 0.03194578f, 0.07389776f, 0.02198060f, 0.07633314f, - 0.03293105f, -0.09103648f, 0.04718142f, 0.06102672f, -0.01003063f, - 5.85481385e-003f, -0.01522574f, 0.02323526f, 0.10584345f, - 4.35879454e-003f, 0.06107873f, 0.05868603f, -0.03115531f, 0.01214679f, - 0.08567052f, 3.93926632e-003f, -0.02521488f, -1.88425183e-003f, - 0.02038053f, -6.26854831e-004f, 0.04897438f, -0.04280585f, - -0.04819689f, -0.04812867f, -0.01451186f, 0.05101469f, - -9.01125465e-003f, -0.03333859f, 0.03917955f, 0.04196448f, 0.04292135f, - 0.02809529f, 0.02999715f, 0.04081348f, 9.10039060e-003f, 0.09703232f, - 0.10379741f, 0.02348725f, -4.72756615e-003f, 0.01027325f, 0.10402658f, - 0.12071823f, 0.09817299f, -0.02612033f, 0.03638414f, 0.05896405f, - 0.04865025f, 0.04793910f, -0.03882321f, -0.02962117f, -0.01222268f, - 0.04071597f, 0.01922777f, -0.02287866f, 0.03328381f, 0.01859092f, - 0.09024994f, 0.03804455f, -0.01424510f, 0.01953739f, 0.02509617f, - -0.03390914f, -0.05663941f, -0.01641979f, 0.05848591f, 0.04639670f, - 0.02092116f, 0.12911791f, 0.19918139f, 0.07739855f, -7.25806039e-003f, - 0.04074838f, 0.03183993f, 1.39251316e-003f, -0.01428625f, 0.01865480f, - 0.08529541f, 0.13547510f, 0.11189661f, 0.03998901f, 0.09575938f, - -0.02631102f, -0.03458253f, -0.04749985f, -0.06070716f, - 4.71884012e-003f, 0.06445789f, -0.02450038f, -0.05483776f, - -0.04657237f, -0.02030717f, -0.03480766f, -0.09397731f, -0.06399718f, - -0.01804585f, 5.62348310e-003f, -6.64811488e-003f, -0.06517869f, - 6.96210237e-003f, -0.01860148f, -0.04245830f, -0.05850367f, - -3.24417115e-003f, 0.07700698f, 0.11290991f, 0.09923030f, -0.02970599f, - 0.05592411f, 0.04813979f, -0.09811195f, -0.09357996f, -0.03276114f, - 0.05218338f, 0.04141375f, 3.92977800e-003f, -0.05047480f, 0.15960084f, - 0.04612800f, -0.03114098f, -0.04650044f, -0.03249795f, -0.02425641f, - -0.04311355f, 0.04307659f, -0.09401883f, -0.04742785f, -0.01254499f, - -0.06598741f, 3.41369561e-003f, -0.05620445f, -7.28127593e-003f, - -0.05998361f, -0.03274450f, -0.07376868f, 3.19015374e-003f, - -0.07733069f, 0.05815864f, -0.02471071f, 0.03850617f, 0.13838784f, - 0.15399861f, 0.01731321f, -0.01477586f, 0.10393341f, 0.05159833f, - -0.01945555f, -0.03427503f, -0.04867341f, 0.09237480f, 0.10732719f, - 0.06071450f, -0.01355071f, 0.01844356f, -0.03480803f, -0.03796671f, - 2.15628621e-004f, -0.05440186f, 0.01889855f, -0.01443413f, - -0.02607902f, -0.02938001f, 0.02720689f, -0.06228397f, -0.02970936f, - -0.03426210f, -0.10280876f, -0.06739304f, -0.05227850f, 0.03360292f, - -0.11278441f, -0.06966180f, -0.13937433f, 9.10932291e-003f, - 2.52020749e-004f, -4.07359656e-003f, 0.12310639f, 0.09343060f, - 0.07302511f, 0.03222093f, 0.07532879f, 0.03792387f, -0.04985180f, - 0.01804602f, 0.02694195f, 0.13481498f, 0.04601225f, 0.04106982f, - 0.08511057f, 0.12314661f, 0.01320830f, 0.05044121f, -5.52943908e-003f, - -0.08992624f, -0.02249301f, -0.08181777f, 0.06165213f, -0.03256603f, - -0.01068920f, -0.01323473f, -0.11970232f, -0.04616347f, -0.12088681f, - -0.06762606f, -0.08676834f, -0.06434575f, 0.01772529f, 0.03469615f, - -0.10926618f, 0.03013873f, 0.14030397f, 0.16130108f, 0.17985588f, - 0.11281928f, 0.10530639f, 0.08905948f, 0.07733764f, 0.06695238f, - 0.02142088f, 0.06438877f, 0.09794453f, 0.05745072f, 0.02788557f, - 0.02632830f, 0.07985807f, 4.24902979e-003f, 8.47890321e-003f, - -0.02679466f, -5.28812688e-003f, -0.02162580f, -0.07490715f, - -0.08251337f, -0.02056576f, -0.01026194f, -1.15492963e-003f, - -5.75720915e-004f, -0.07210591f, -0.07320981f, -0.04883312f, - -0.10897151f, -0.07477258f, -0.08867134f, -0.09222437f, -0.10924666f, - -0.10430276f, 0.07953499f, 0.02767959f, 0.11393359f, 0.18779543f, - 0.03313421f, 0.02143700f, 0.05852016f, -2.12067598e-003f, - -3.76984011e-003f, 0.02774167f, -0.03124610f, 0.01465141f, 0.01616004f, - -0.01391913f, -0.04404102f, -0.05444227f, -0.14684731f, -0.15016587f, - 0.04509468f, 1.29563001e-003f, 0.01398350f, 0.05610404f, -0.04868806f, - -0.04776716f, -8.16873740e-003f, -2.30126386e-003f, -0.02286313f, - 0.11983398f, -0.04703261f, -0.08814441f, -0.07585249f, -0.10799607f, - -0.03232087f, 0.01509786f, -0.04843464f, -0.03967846f, 0.09589416f, - 0.01352560f, -0.01458119f, 0.01050829f, -0.03038946f, 0.01608388f, - 1.11975556e-003f, -0.01250656f, 2.86211423e-003f, 0.04333691f, - -0.14603497f, -0.01946543f, -0.02327525f, -0.01973944f, 0.07944400f, - -0.02224544f, -0.06701808f, 0.03476532f, 0.11505594f, -0.02712801f, - -0.01665113f, 0.06315716f, -0.08205860f, 0.07431999f, 0.04915778f, - -0.04468752f, -0.01490402f, 0.07400476f, -0.11650901f, 0.05102430f, - 0.04559118f, -0.05916039f, 0.08840760f, -0.01587902f, -0.14890194f, - 0.07857784f, 0.04710254f, -0.05381983f, -0.07331945f, -0.03604643f, - 0.15611970f, 0.07649943f, -0.05959348f, -0.02776607f, 0.11098688f, - 0.03758875f, -0.04446875f, 0.04933187f, 0.01345535f, 0.06921103f, - 0.07364785f, 0.05518956f, 0.02899585f, 0.09375840f, 0.10518434f, - -0.04420241f, 0.01915282f, -3.56386811e-003f, 0.14586878f, 0.10286101f, - -0.04360626f, -0.12723237f, 0.09076386f, 0.11119842f, -0.06035013f, - 0.09674817f, 0.08938243f, 0.07065924f, 0.02603180f, 5.84815582e-003f, - -0.05922065f, 0.12360309f, 3.59695964e-003f, 2.99844006e-003f, - 0.03697936f, 0.02043072f, 0.04168725f, 0.01025975f, -0.01359980f, - -0.01600920f, 0.02581056f, 0.02329250f, 2.98100687e-003f, 0.01629762f, - 0.06652115f, 0.05855627f, 0.01237463f, -0.01297135f, 0.01761587f, - 0.05090865f, 0.06549342f, -0.04425945f, 2.43203156e-003f, - 3.07327788e-003f, 0.06678630f, -0.04303836f, 0.01082393f, -0.06476044f, - 0.04077786f, 0.12441979f, 0.08237778f, 0.07424165f, 0.04065890f, - 0.06905543f, 0.09556347f, 0.12724875f, -0.02132082f, 0.08514154f, - -0.04175328f, -0.02666954f, 0.01897836f, 0.03317382f, 9.45465732e-003f, - -0.01238974f, -0.04242500f, -0.01419479f, -0.03545213f, -0.02440874f, - 0.08684119f, 0.04212951f, 0.02462858f, -0.01104825f, -5.01706870e-003f, - 0.02968982f, 0.02597476f, -0.01568939f, 0.04514892f, 0.06974549f, - 0.08670278f, 0.06828108f, 0.10238872f, 0.05405957f, 0.06548470f, - -0.03763957f, 0.01366090f, 0.07069602f, 0.05363748f, 0.04798120f, - 0.11706422f, 0.05466456f, -0.01869259f, 0.06344382f, 0.03106543f, - 0.08432506f, -0.02061096f, 0.03821088f, -6.92190882e-003f, - 6.40467042e-003f, -0.01271779f, 6.89014705e-005f, 0.04541415f, - -0.01899539f, -0.05020239f, 0.03000903f, 0.01090422f, 4.52452758e-003f, - 0.02573632f, -0.02388454f, -0.04200457f, 1.72783900e-003f, - -0.05978370f, -0.02720562f, 0.06573715f, 0.01154317f, 0.01265615f, - 0.07375994f, -9.19828378e-003f, -0.04914120f, 0.02124831f, 0.06455322f, - 0.04372910f, -0.03310043f, 0.03605788f, -6.78055827e-003f, - 9.36202332e-003f, 0.01747596f, -0.06406314f, -0.06812935f, 0.08080816f, - -0.02778088f, 0.02735260f, 0.06393493f, 0.06652229f, 0.05676993f, - 0.08640018f, -7.59188086e-003f, -0.02012847f, -0.04741159f, - -0.01657069f, -0.01624399f, 0.05547778f, -2.33309763e-003f, - 0.01120033f, 0.06141156f, -0.06285004f, -0.08732341f, -0.09313398f, - -0.04267832f, 5.57443965e-003f, 0.04809862f, 0.01773641f, - 5.37361018e-003f, 0.14842421f, -0.06298012f, -0.02935147f, 0.11443478f, - -0.05034208f, 5.65494271e-003f, 0.02076526f, -0.04577984f, - -0.04735741f, 0.02961071f, -0.09307127f, -0.04417921f, -0.04990027f, - -0.03940028f, 0.01306016f, 0.06267900f, 0.03758737f, 0.08460117f, - 0.13858789f, 0.04862388f, -0.06319809f, -0.05655516f, 0.01885816f, - -0.03285607f, 0.03371567f, -0.07040928f, -0.04514049f, 0.01392166f, - 0.08184422f, -0.07230316f, 0.02386871f, 0.02184591f, 0.02605764f, - -0.01033954f, 9.29878280e-003f, 7.67351175e-003f, 0.15189242f, - 0.02069071f, -0.09738296f, -0.08894105f, -0.07768748f, 0.02332268f, - -0.01778995f, -0.03258888f, -0.08180822f, -0.08492987f, 0.02290156f, - -0.11368170f, -0.03554465f, -0.04533844f, -0.02861580f, 0.06782424f, - 0.01113123f, 0.02453644f, 0.12721945f, 0.08084814f, -0.03607795f, - 0.01109122f, 0.04803548f, -0.03489929f, 0.03399536f, -0.05682014f, - 8.59533902e-003f, -4.27904585e-003f, 0.03230887f, -0.01300198f, - -0.01038137f, -0.07930113f, 8.33097473e-003f, 0.02296994f, - -0.01306500f, -0.01881626f, 0.04413369f, 0.05729880f, -0.03761553f, - 0.01942326f, 1.64540811e-003f, -0.03811319f, 0.04190650f, -0.14978096f, - -0.04514487f, 0.01209545f, -5.46460645e-003f, -0.01647195f, - 7.63064111e-003f, -0.07494587f, 0.08415288f, 0.10020141f, -0.01228561f, - 0.06553826f, 0.04554005f, 0.07890417f, 0.03041138f, 0.01752007f, - 0.09208256f, -3.74419295e-004f, 0.10549527f, 0.04686913f, 0.01894833f, - -0.02651412f, -4.34682379e-003f, 5.44942822e-003f, 0.01444484f, - 0.05882156f, -0.03336544f, 0.04603891f, -0.10432546f, 0.01923928f, - 0.01842845f, -0.01712168f, -0.02222766f, 0.04693324f, -0.06202956f, - -0.01422159f, 0.08732220f, -0.07706107f, 0.02661049f, -0.04300238f, - -0.03092422f, -0.03552184f, -0.01886088f, -0.04979934f, 0.03906401f, - 0.04608644f, 0.04966111f, 0.04275464f, -0.04621769f, -0.02653212f, - 8.57011229e-003f, 0.03839684f, 0.05818764f, 0.03880796f, - -2.76100676e-004f, 0.03076511f, -0.03266929f, -0.05374557f, - 0.04986527f, -9.45429131e-003f, 0.03582499f, -2.64564669e-003f, - -1.07461517e-003f, 0.02962313f, -0.01483363f, 0.03060869f, 0.02448327f, - 0.01845641f, 0.03282966f, -0.03534438f, -0.01084059f, -0.01119136f, - -1.85360224e-003f, -5.94652840e-004f, -0.04451817f, 2.98327743e-003f, - 0.06272484f, -0.02152076f, -3.05971340e-003f, -0.05070828f, - 0.01531762f, 0.01282815f, 0.05167150f, 9.46266949e-003f, - -3.34558333e-003f, 0.11442288f, -0.03906701f, -2.67325155e-003f, - 0.03069184f, -0.01134165f, 0.02949462f, 0.02879886f, 0.03855566f, - -0.03450781f, 0.09142872f, -0.02156654f, 0.06075062f, -0.06220816f, - 0.01944680f, 6.68372354e-003f, -0.06656796f, 8.70784000e-003f, - 0.03456013f, 0.02434320f, -0.13236357f, -0.04177035f, -0.02069627f, - 0.01068112f, 0.01505432f, -0.07517391f, -3.83571628e-003f, - -0.06298508f, -0.02881260f, -0.13101046f, -0.07221562f, - -5.79945277e-003f, -8.57300125e-003f, 0.03782469f, 0.02762164f, - 0.04942456f, -0.02936396f, 0.09597211f, 0.01921411f, 0.06101191f, - -0.04787507f, -0.01379578f, -7.40224449e-003f, -0.02220136f, - -0.01313756f, 7.77558051e-003f, 0.12296968f, 0.02939998f, 0.03594062f, - -0.07788624f, -0.01133144f, 3.99316690e-004f, -0.06090347f, - -0.01122066f, -4.68682544e-003f, 0.07633100f, -0.06748922f, - -0.05640298f, -0.05265681f, -0.01139122f, -0.01624347f, -0.04715714f, - -0.01099092f, 0.01048561f, 3.28499987e-003f, -0.05810167f, - -0.07699911f, -0.03330683f, 0.04185145f, 0.03478536f, 0.02275165f, - 0.02304766f, 6.66040834e-003f, 0.10968148f, -5.93013782e-003f, - -0.04858336f, -0.04203213f, -0.09316786f, -6.13074889e-003f, - -0.02544625f, 0.01366201f, 9.18555818e-003f, -0.01846578f, - -0.05622401f, -0.03989377f, -0.07810296f, 6.91275718e-003f, - 0.05957597f, -0.03901334f, 0.01572002f, -0.01193903f, - -6.89400872e-003f, -0.03093356f, -0.04136098f, -0.01562869f, - -0.04604580f, 0.02865234f, -0.08678447f, -0.03232484f, -0.05364593f, - -0.01445016f, -0.07003860f, -0.08669746f, -0.04520775f, 0.04274122f, - 0.03117515f, 0.08175703f, 0.01081109f, 0.06379741f, 0.06199206f, - 0.02865988f, 0.02360346f, 0.06725410f, -0.03248780f, -9.37702879e-003f, - 0.08265898f, -0.02245839f, 0.05125763f, -0.01862395f, 0.01973453f, - -0.01994494f, -0.10770868f, 0.03180375f, 3.23935156e-003f, - -0.02142080f, -0.04256190f, 0.04760900f, 0.04282863f, 0.05635953f, - -0.01870849f, 0.05540622f, -0.03042666f, 0.01455277f, -0.06630179f, - -0.05843807f, -0.03739681f, -0.09739155f, -0.03220233f, -0.05620182f, - -0.10381401f, 0.07400211f, 4.20676917e-003f, 0.03258535f, - 2.14308966e-003f, 0.05121966f, -0.01274337f, 0.02384761f, 0.06335578f, - -0.07905591f, 0.08375625f, -0.07898903f, -0.06508528f, -0.02498444f, - 0.06535810f, 0.03970535f, 0.04895468f, -0.01169566f, -0.03980601f, - 0.05682293f, 0.05925463f, -0.01165808f, -0.07936699f, -0.04208954f, - 0.01333987f, 0.09051196f, 0.10098671f, -0.03974256f, 0.01238771f, - -0.07501741f, -0.03655440f, -0.04301528f, 0.09216860f, - 4.63579083e-004f, 0.02851115f, 0.02142735f, 1.28244064e-004f, - 0.02879687f, -0.08554889f, -0.04838862f, 0.08135369f, -0.05756533f, - 0.01413900f, 0.03451880f, -0.06619488f, -0.03053130f, 0.02961676f, - -0.07384635f, 0.01135692f, 0.05283910f, -0.07778034f, -0.02107482f, - -0.05511716f, -0.13473752f, 0.03030157f, 0.06722020f, -0.06218817f, - -0.05826827f, 0.06254654f, 0.02895772f, -0.01664000f, -0.03620280f, - -0.01612278f, -1.46097376e-003f, 0.14013411f, -8.96181818e-003f, - -0.03250246f, 3.38630192e-003f, 2.64779478e-003f, 0.03359732f, - -0.02411991f, -0.04229729f, 0.10666174f, -6.66579151f - }; - return std::vector(detector, detector + sizeof(detector) / sizeof(detector[0])); -} - -/* Returns the nearest upper power of two, works only for -the typical GPU thread count (pert block) values */ -static int power_2up(unsigned int n) -{ - if (n < 1) return 1; - else if (n < 2) return 2; - else if (n < 4) return 4; - else if (n < 8) return 8; - else if (n < 16) return 16; - else if (n < 32) return 32; - else if (n < 64) return 64; - else if (n < 128) return 128; - else if (n < 256) return 256; - else if (n < 512) return 512; - else if (n < 1024) return 1024; - return -1; // Input is too big -} - -void cv::ocl::device::hog::set_up_constants(int nbins, - int block_stride_x, int block_stride_y, - int nblocks_win_x, int nblocks_win_y) -{ - cnbins = nbins; - cblock_stride_x = block_stride_x; - cblock_stride_y = block_stride_y; - cnblocks_win_x = nblocks_win_x; - cnblocks_win_y = nblocks_win_y; - - int block_hist_size = nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y; - cblock_hist_size = block_hist_size; - - int descr_width = nblocks_win_x * block_hist_size; - cdescr_width = descr_width; - cdescr_height = nblocks_win_y; - - int descr_size = descr_width * nblocks_win_y; - cdescr_size = descr_size; - - qangle_type = CV_8UC2; - qangle_step_shift = 0; - // Some Intel devices have low single-byte access performance, - // so we change the datatype here. - if (Context::getContext()->supportsFeature(FEATURE_CL_INTEL_DEVICE)) - { - qangle_type = CV_32SC2; - qangle_step_shift = 2; - } -} - -void cv::ocl::device::hog::compute_hists(int nbins, - int block_stride_x, int block_stride_y, - int height, int width, - const cv::ocl::oclMat &grad, - const cv::ocl::oclMat &qangle, - const cv::ocl::oclMat &gauss_w_lut, - cv::ocl::oclMat &block_hists) -{ - Context *clCxt = Context::getContext(); - std::vector< std::pair > args; - String kernelName = "compute_hists_lut_kernel"; - - int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) - / block_stride_x; - int img_block_height = (height - CELLS_PER_BLOCK_Y * CELL_HEIGHT + block_stride_y) - / block_stride_y; - int blocks_total = img_block_width * img_block_height; - - int grad_quadstep = grad.step >> 2; - int qangle_step = qangle.step >> qangle_step_shift; - - int blocks_in_group = 4; - size_t localThreads[3] = { blocks_in_group * 24, 2, 1 }; - size_t globalThreads[3] = { - divUp(img_block_width * img_block_height, blocks_in_group) * localThreads[0], 2, 1 }; - - int hists_size = (nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y * 12) * sizeof(float); - int final_hists_size = (nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y) * sizeof(float); - - int smem = (hists_size + final_hists_size) * blocks_in_group; - - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cblock_stride_x)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cblock_stride_y)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cnbins)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cblock_hist_size)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&img_block_width)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&blocks_in_group)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&blocks_total)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&grad_quadstep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&qangle_step)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&grad.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&qangle.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&gauss_w_lut.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&block_hists.data)); - args.push_back( std::make_pair( smem, (void *)NULL)); - - if(hog_device_cpu) - { - openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads, - localThreads, args, -1, -1, "-D CPU"); - } - else - { - cl_kernel kernel = openCLGetKernelFromSource(clCxt, &objdetect_hog, kernelName); - size_t wave_size = queryWaveFrontSize(kernel); - char opt[32] = {0}; - sprintf(opt, "-D WAVE_SIZE=%d", (int)wave_size); - openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads, - localThreads, args, -1, -1, opt); - } -} - -void cv::ocl::device::hog::normalize_hists(int nbins, - int block_stride_x, int block_stride_y, - int height, int width, - cv::ocl::oclMat &block_hists, - float threshold) -{ - Context *clCxt = Context::getContext(); - std::vector< std::pair > args; - String kernelName; - - int block_hist_size = nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y; - int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) - / block_stride_x; - int img_block_height = (height - CELLS_PER_BLOCK_Y * CELL_HEIGHT + block_stride_y) - / block_stride_y; - int nthreads; - size_t globalThreads[3] = { 1, 1, 1 }; - size_t localThreads[3] = { 1, 1, 1 }; - - if ( nbins == 9 ) - { - /* optimized for the case of 9 bins */ - kernelName = "normalize_hists_36_kernel"; - int blocks_in_group = NTHREADS / block_hist_size; - nthreads = blocks_in_group * block_hist_size; - int num_groups = divUp( img_block_width * img_block_height, blocks_in_group); - globalThreads[0] = nthreads * num_groups; - localThreads[0] = nthreads; - } - else - { - kernelName = "normalize_hists_kernel"; - nthreads = power_2up(block_hist_size); - globalThreads[0] = img_block_width * nthreads; - globalThreads[1] = img_block_height; - localThreads[0] = nthreads; - - if ((nthreads < 32) || (nthreads > 512) ) - cv::error(Error::StsBadArg, "normalize_hists: histogram's size is too small or too big", - "normalize_hists", __FILE__, __LINE__); - - args.push_back( std::make_pair( sizeof(cl_int), (void *)&nthreads)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&block_hist_size)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&img_block_width)); - } - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&block_hists.data)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&threshold)); - args.push_back( std::make_pair( nthreads * sizeof(float), (void *)NULL)); - - if(hog_device_cpu) - openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads, - localThreads, args, -1, -1, "-D CPU"); - else - { - cl_kernel kernel = openCLGetKernelFromSource(clCxt, &objdetect_hog, kernelName); - size_t wave_size = queryWaveFrontSize(kernel); - char opt[32] = {0}; - sprintf(opt, "-D WAVE_SIZE=%d", (int)wave_size); - openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads, - localThreads, args, -1, -1, opt); - } -} - -void cv::ocl::device::hog::classify_hists(int win_height, int win_width, - int block_stride_y, int block_stride_x, - int win_stride_y, int win_stride_x, - int height, int width, - const cv::ocl::oclMat &block_hists, - const cv::ocl::oclMat &coefs, - float free_coef, float threshold, - cv::ocl::oclMat &labels) -{ - Context *clCxt = Context::getContext(); - std::vector< std::pair > args; - - int nthreads; - String kernelName; - switch (cdescr_width) - { - case 180: - nthreads = 180; - kernelName = "classify_hists_180_kernel"; - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cdescr_width)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cdescr_height)); - break; - case 252: - nthreads = 256; - kernelName = "classify_hists_252_kernel"; - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cdescr_width)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cdescr_height)); - break; - default: - nthreads = 256; - kernelName = "classify_hists_kernel"; - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cdescr_size)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cdescr_width)); - } - - int win_block_stride_x = win_stride_x / block_stride_x; - int win_block_stride_y = win_stride_y / block_stride_y; - int img_win_width = (width - win_width + win_stride_x) / win_stride_x; - int img_win_height = (height - win_height + win_stride_y) / win_stride_y; - int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) / - block_stride_x; - - size_t globalThreads[3] = { img_win_width * nthreads, img_win_height, 1 }; - size_t localThreads[3] = { nthreads, 1, 1 }; - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cblock_hist_size)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&img_win_width)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&img_block_width)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&win_block_stride_x)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&win_block_stride_y)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&block_hists.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&coefs.data)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&free_coef)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&threshold)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&labels.data)); - - if(hog_device_cpu) - openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads, - localThreads, args, -1, -1, "-D CPU"); - else - { - cl_kernel kernel = openCLGetKernelFromSource(clCxt, &objdetect_hog, kernelName); - size_t wave_size = queryWaveFrontSize(kernel); - char opt[32] = {0}; - sprintf(opt, "-D WAVE_SIZE=%d", (int)wave_size); - openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads, - localThreads, args, -1, -1, opt); - } -} - -void cv::ocl::device::hog::extract_descrs_by_rows(int win_height, int win_width, - int block_stride_y, int block_stride_x, - int win_stride_y, int win_stride_x, - int height, int width, - const cv::ocl::oclMat &block_hists, - cv::ocl::oclMat &descriptors) -{ - Context *clCxt = Context::getContext(); - String kernelName = "extract_descrs_by_rows_kernel"; - std::vector< std::pair > args; - - int win_block_stride_x = win_stride_x / block_stride_x; - int win_block_stride_y = win_stride_y / block_stride_y; - int img_win_width = (width - win_width + win_stride_x) / win_stride_x; - int img_win_height = (height - win_height + win_stride_y) / win_stride_y; - int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) / - block_stride_x; - int descriptors_quadstep = descriptors.step >> 2; - - size_t globalThreads[3] = { img_win_width * NTHREADS, img_win_height, 1 }; - size_t localThreads[3] = { NTHREADS, 1, 1 }; - - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cblock_hist_size)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&descriptors_quadstep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cdescr_size)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cdescr_width)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&img_block_width)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&win_block_stride_x)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&win_block_stride_y)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&block_hists.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&descriptors.data)); - - openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads, - localThreads, args, -1, -1); -} - -void cv::ocl::device::hog::extract_descrs_by_cols(int win_height, int win_width, - int block_stride_y, int block_stride_x, - int win_stride_y, int win_stride_x, - int height, int width, - const cv::ocl::oclMat &block_hists, - cv::ocl::oclMat &descriptors) -{ - Context *clCxt = Context::getContext(); - String kernelName = "extract_descrs_by_cols_kernel"; - std::vector< std::pair > args; - - int win_block_stride_x = win_stride_x / block_stride_x; - int win_block_stride_y = win_stride_y / block_stride_y; - int img_win_width = (width - win_width + win_stride_x) / win_stride_x; - int img_win_height = (height - win_height + win_stride_y) / win_stride_y; - int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) / - block_stride_x; - int descriptors_quadstep = descriptors.step >> 2; - - size_t globalThreads[3] = { img_win_width * NTHREADS, img_win_height, 1 }; - size_t localThreads[3] = { NTHREADS, 1, 1 }; - - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cblock_hist_size)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&descriptors_quadstep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cdescr_size)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cnblocks_win_x)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cnblocks_win_y)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&img_block_width)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&win_block_stride_x)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&win_block_stride_y)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&block_hists.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&descriptors.data)); - - openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads, - localThreads, args, -1, -1); -} - -void cv::ocl::device::hog::compute_gradients_8UC1(int height, int width, - const cv::ocl::oclMat &img, - float angle_scale, - cv::ocl::oclMat &grad, - cv::ocl::oclMat &qangle, - bool correct_gamma) -{ - Context *clCxt = Context::getContext(); - String kernelName = "compute_gradients_8UC1_kernel"; - std::vector< std::pair > args; - - size_t localThreads[3] = { NTHREADS, 1, 1 }; - size_t globalThreads[3] = { width, height, 1 }; - char correctGamma = (correct_gamma) ? 1 : 0; - int img_step = img.step; - int grad_quadstep = grad.step >> 3; - int qangle_step = qangle.step >> (1 + qangle_step_shift); - - args.push_back( std::make_pair( sizeof(cl_int), (void *)&height)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&width)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&img_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&grad_quadstep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&qangle_step)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&img.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&grad.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&qangle.data)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&angle_scale)); - args.push_back( std::make_pair( sizeof(cl_char), (void *)&correctGamma)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cnbins)); - - openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads, - localThreads, args, -1, -1); -} - -void cv::ocl::device::hog::compute_gradients_8UC4(int height, int width, - const cv::ocl::oclMat &img, - float angle_scale, - cv::ocl::oclMat &grad, - cv::ocl::oclMat &qangle, - bool correct_gamma) -{ - Context *clCxt = Context::getContext(); - String kernelName = "compute_gradients_8UC4_kernel"; - std::vector< std::pair > args; - - size_t localThreads[3] = { NTHREADS, 1, 1 }; - size_t globalThreads[3] = { width, height, 1 }; - - char correctGamma = (correct_gamma) ? 1 : 0; - int img_step = img.step >> 2; - int grad_quadstep = grad.step >> 3; - int qangle_step = qangle.step >> (1 + qangle_step_shift); - - args.push_back( std::make_pair( sizeof(cl_int), (void *)&height)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&width)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&img_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&grad_quadstep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&qangle_step)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&img.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&grad.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&qangle.data)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&angle_scale)); - args.push_back( std::make_pair( sizeof(cl_char), (void *)&correctGamma)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cnbins)); - - openCLExecuteKernel2(clCxt, &objdetect_hog, kernelName, globalThreads, - localThreads, args, -1, -1); -} diff --git a/modules/ocl/src/hough.cpp b/modules/ocl/src/hough.cpp deleted file mode 100644 index dca1d8b4c..000000000 --- a/modules/ocl/src/hough.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/*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) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., 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*/ - -#include "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -#if !defined (HAVE_OPENCL) - -void cv::ocl::HoughCircles(const oclMat&, oclMat&, int, float, float, int, int, int, int, int) { throw_nogpu(); } -void cv::ocl::HoughCircles(const oclMat&, oclMat&, HoughCirclesBuf&, int, float, float, int, int, int, int, int) { throw_nogpu(); } -void cv::ocl::HoughCirclesDownload(const oclMat&, OutputArray) { throw_nogpu(); } - -#else /* !defined (HAVE_OPENCL) */ - -#define MUL_UP(a, b) ((a)/(b)+1)*(b) - -////////////////////////////////////////////////////////// -// common functions - -namespace -{ - int buildPointList_gpu(const oclMat& src, oclMat& list) - { - const int PIXELS_PER_THREAD = 16; - - int totalCount = 0; - int err = CL_SUCCESS; - cl_mem counter = clCreateBuffer(*(cl_context*)src.clCxt->getOpenCLContextPtr(), - CL_MEM_COPY_HOST_PTR, - sizeof(int), - &totalCount, - &err); - openCLSafeCall(err); - - const size_t blkSizeX = 32; - const size_t blkSizeY = 4; - size_t localThreads[3] = { blkSizeX, blkSizeY, 1 }; - - const int PIXELS_PER_BLOCK = blkSizeX * PIXELS_PER_THREAD; - const size_t glbSizeX = src.cols % (PIXELS_PER_BLOCK) == 0 ? src.cols : MUL_UP(src.cols, PIXELS_PER_BLOCK); - const size_t glbSizeY = src.rows % blkSizeY == 0 ? src.rows : MUL_UP(src.rows, blkSizeY); - size_t globalThreads[3] = { glbSizeX, glbSizeY, 1 }; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.rows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.step )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&list.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&counter )); - - // WARNING: disabled until - openCLExecuteKernel(src.clCxt, &imgproc_hough, "buildPointList", globalThreads, localThreads, args, -1, -1); - openCLSafeCall(clEnqueueReadBuffer(*(cl_command_queue*)src.clCxt->getOpenCLCommandQueuePtr(), counter, CL_TRUE, 0, sizeof(int), &totalCount, 0, NULL, NULL)); - openCLSafeCall(clReleaseMemObject(counter)); - - return totalCount; - } -} - -////////////////////////////////////////////////////////// -// HoughCircles - -namespace -{ - void circlesAccumCenters_gpu(const oclMat& list, int count, const oclMat& dx, const oclMat& dy, oclMat& accum, int minRadius, int maxRadius, float idp) - { - const size_t blkSizeX = 256; - size_t localThreads[3] = { 256, 1, 1 }; - - const size_t glbSizeX = count % blkSizeX == 0 ? count : MUL_UP(count, blkSizeX); - size_t globalThreads[3] = { glbSizeX, 1, 1 }; - - const int width = accum.cols - 2; - const int height = accum.rows - 2; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&list.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&count )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dx.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dx.step )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dy.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dy.step )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&accum.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&accum.step )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&width )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&height )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&minRadius)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&maxRadius)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&idp)); - - openCLExecuteKernel(accum.clCxt, &imgproc_hough, "circlesAccumCenters", globalThreads, localThreads, args, -1, -1); - } - - int buildCentersList_gpu(const oclMat& accum, oclMat& centers, int threshold) - { - int totalCount = 0; - int err = CL_SUCCESS; - cl_mem counter = clCreateBuffer(*(cl_context*)accum.clCxt->getOpenCLContextPtr(), - CL_MEM_COPY_HOST_PTR, - sizeof(int), - &totalCount, - &err); - openCLSafeCall(err); - - const size_t blkSizeX = 32; - const size_t blkSizeY = 8; - size_t localThreads[3] = { blkSizeX, blkSizeY, 1 }; - - const size_t glbSizeX = (accum.cols - 2) % blkSizeX == 0 ? accum.cols - 2 : MUL_UP(accum.cols - 2, blkSizeX); - const size_t glbSizeY = (accum.rows - 2) % blkSizeY == 0 ? accum.rows - 2 : MUL_UP(accum.rows - 2, blkSizeY); - size_t globalThreads[3] = { glbSizeX, glbSizeY, 1 }; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&accum.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&accum.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&accum.rows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&accum.step )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)¢ers.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&threshold )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&counter )); - - openCLExecuteKernel(accum.clCxt, &imgproc_hough, "buildCentersList", globalThreads, localThreads, args, -1, -1); - - openCLSafeCall(clEnqueueReadBuffer(*(cl_command_queue*)accum.clCxt->getOpenCLCommandQueuePtr(), counter, CL_TRUE, 0, sizeof(int), &totalCount, 0, NULL, NULL)); - openCLSafeCall(clReleaseMemObject(counter)); - - return totalCount; - } - - int circlesAccumRadius_gpu(const oclMat& centers, int centersCount, - const oclMat& list, int count, - oclMat& circles, int maxCircles, - float dp, int minRadius, int maxRadius, int threshold) - { - int totalCount = 0; - int err = CL_SUCCESS; - cl_mem counter = clCreateBuffer(*(cl_context*)circles.clCxt->getOpenCLContextPtr(), - CL_MEM_COPY_HOST_PTR, - sizeof(int), - &totalCount, - &err); - openCLSafeCall(err); - - const size_t blkSizeX = circles.clCxt->getDeviceInfo().maxWorkGroupSize; - size_t localThreads[3] = { blkSizeX, 1, 1 }; - - const size_t glbSizeX = centersCount * blkSizeX; - size_t globalThreads[3] = { glbSizeX, 1, 1 }; - - const int histSize = maxRadius - minRadius + 1; - size_t smemSize = (histSize + 2) * sizeof(int); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)¢ers.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&list.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&count )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&circles.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&maxCircles )); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&dp )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&minRadius )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&maxRadius )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&histSize )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&threshold )); - args.push_back( std::make_pair( smemSize , (void *)NULL )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&counter )); - - CV_Assert(circles.offset == 0); - - openCLExecuteKernel(circles.clCxt, &imgproc_hough, "circlesAccumRadius", globalThreads, localThreads, args, -1, -1); - - openCLSafeCall(clEnqueueReadBuffer(*(cl_command_queue*)circles.clCxt->getOpenCLCommandQueuePtr(), counter, CL_TRUE, 0, sizeof(int), &totalCount, 0, NULL, NULL)); - - openCLSafeCall(clReleaseMemObject(counter)); - - totalCount = std::min(totalCount, maxCircles); - - return totalCount; - } - - -} // namespace - - - -void cv::ocl::HoughCircles(const oclMat& src, oclMat& circles, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles) -{ - HoughCirclesBuf buf; - HoughCircles(src, circles, buf, method, dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius, maxCircles); -} - -void cv::ocl::HoughCircles(const oclMat& src, oclMat& circles, HoughCirclesBuf& buf, int method, - float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles) -{ - CV_Assert(src.type() == CV_8UC1); - CV_Assert(src.cols < std::numeric_limits::max()); - CV_Assert(src.rows < std::numeric_limits::max()); - CV_Assert(method == HOUGH_GRADIENT); - CV_Assert(dp > 0); - CV_Assert(minRadius > 0 && maxRadius > minRadius); - CV_Assert(cannyThreshold > 0); - CV_Assert(votesThreshold > 0); - CV_Assert(maxCircles > 0); - - const float idp = 1.0f / dp; - - cv::ocl::Canny(src, buf.cannyBuf, buf.edges, std::max(cannyThreshold / 2, 1), cannyThreshold); - - ensureSizeIsEnough(1, src.size().area(), CV_32SC1, buf.srcPoints); - const int pointsCount = buildPointList_gpu(buf.edges, buf.srcPoints); - if (pointsCount == 0) - { - circles.release(); - return; - } - - ensureSizeIsEnough(cvCeil(src.rows * idp) + 2, cvCeil(src.cols * idp) + 2, CV_32SC1, buf.accum); - buf.accum.setTo(Scalar::all(0)); - - circlesAccumCenters_gpu(buf.srcPoints, pointsCount, buf.cannyBuf.dx, buf.cannyBuf.dy, buf.accum, minRadius, maxRadius, idp); - - ensureSizeIsEnough(1, src.size().area(), CV_32SC1, buf.centers); - int centersCount = buildCentersList_gpu(buf.accum, buf.centers, votesThreshold); - if (centersCount == 0) - { - circles.release(); - return; - } - - if (minDist > 1) - { - cv::AutoBuffer oldBuf_(centersCount); - cv::AutoBuffer newBuf_(centersCount); - int newCount = 0; - - unsigned int* oldBuf = oldBuf_; - unsigned int* newBuf = newBuf_; - - openCLSafeCall(clEnqueueReadBuffer(*(cl_command_queue*)buf.centers.clCxt->getOpenCLCommandQueuePtr(), - (cl_mem)buf.centers.data, - CL_TRUE, - 0, - centersCount * sizeof(unsigned int), - oldBuf, - 0, - NULL, - NULL)); - - - const int cellSize = cvRound(minDist); - const int gridWidth = (src.cols + cellSize - 1) / cellSize; - const int gridHeight = (src.rows + cellSize - 1) / cellSize; - - std::vector< std::vector > grid(gridWidth * gridHeight); - - const float minDist2 = minDist * minDist; - - for (int i = 0; i < centersCount; ++i) - { - unsigned int p = oldBuf[i]; - const int px = p & 0xFFFF; - const int py = (p >> 16) & 0xFFFF; - - bool good = true; - - int xCell = static_cast(px / cellSize); - int yCell = static_cast(py / cellSize); - - int x1 = xCell - 1; - int y1 = yCell - 1; - int x2 = xCell + 1; - int y2 = yCell + 1; - - // boundary check - x1 = std::max(0, x1); - y1 = std::max(0, y1); - x2 = std::min(gridWidth - 1, x2); - y2 = std::min(gridHeight - 1, y2); - - for (int yy = y1; yy <= y2; ++yy) - { - for (int xx = x1; xx <= x2; ++xx) - { - std::vector& m = grid[yy * gridWidth + xx]; - - for(size_t j = 0; j < m.size(); ++j) - { - const int val = m[j]; - const int jx = val & 0xFFFF; - const int jy = (val >> 16) & 0xFFFF; - - float dx = (float)(px - jx); - float dy = (float)(py - jy); - - if (dx * dx + dy * dy < minDist2) - { - good = false; - goto break_out; - } - } - } - } - - break_out: - - if(good) - { - grid[yCell * gridWidth + xCell].push_back(p); - newBuf[newCount++] = p; - } - } - - openCLSafeCall(clEnqueueWriteBuffer(*(cl_command_queue*)buf.centers.clCxt->getOpenCLCommandQueuePtr(), - (cl_mem)buf.centers.data, - CL_TRUE, - 0, - newCount * sizeof(unsigned int), - newBuf, - 0, - 0, - 0)); - centersCount = newCount; - } - - ensureSizeIsEnough(1, maxCircles, CV_32FC3, circles); - - const int circlesCount = circlesAccumRadius_gpu(buf.centers, centersCount, - buf.srcPoints, pointsCount, - circles, maxCircles, - dp, minRadius, maxRadius, votesThreshold); - - if (circlesCount > 0) - circles.cols = circlesCount; - else - circles.release(); -} - -void cv::ocl::HoughCirclesDownload(const oclMat& d_circles, cv::OutputArray h_circles_) -{ - // FIX ME: garbage values are copied! - CV_Error(Error::StsNotImplemented, "HoughCirclesDownload is not implemented"); - - if (d_circles.empty()) - { - h_circles_.release(); - return; - } - - CV_Assert(d_circles.rows == 1 && d_circles.type() == CV_32FC3); - - h_circles_.create(1, d_circles.cols, CV_32FC3); - Mat h_circles = h_circles_.getMat(); - d_circles.download(h_circles); -} - -#endif /* !defined (HAVE_OPENCL) */ diff --git a/modules/ocl/src/imgproc.cpp b/modules/ocl/src/imgproc.cpp deleted file mode 100644 index 0ac627172..000000000 --- a/modules/ocl/src/imgproc.cpp +++ /dev/null @@ -1,2014 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Jia Haipeng, jiahaipeng95@gmail.com -// Shengen Yan, yanshengen@gmail.com -// Rock Li, Rock.Li@amd.com -// Zero Lin, Zero.Lin@amd.com -// Zhang Ying, zhangying913@gmail.com -// Xu Pang, pangxu010@163.com -// Wu Zailong, bullet@yeah.net -// Wenju He, wenju@multicorewareinc.com -// Peng Xiao, pengxiao@outlook.com -// Sen Liu, swjtuls1987@126.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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -namespace cv -{ - namespace ocl - { - ////////////////////////////////////OpenCL call wrappers//////////////////////////// - - template struct index_and_sizeof; - template <> struct index_and_sizeof - { - enum { index = 1 }; - }; - template <> struct index_and_sizeof - { - enum { index = 2 }; - }; - template <> struct index_and_sizeof - { - enum { index = 3 }; - }; - template <> struct index_and_sizeof - { - enum { index = 4 }; - }; - template <> struct index_and_sizeof - { - enum { index = 5 }; - }; - template <> struct index_and_sizeof - { - enum { index = 6 }; - }; - template <> struct index_and_sizeof - { - enum { index = 7 }; - }; - - ///////////////////////////////////////////////////////////////////////////////////// - // threshold - - static std::vector scalarToVector(const cv::Scalar & sc, int depth, int ocn, int cn) - { - CV_Assert(ocn == cn || (ocn == 4 && cn == 3)); - - static const int sizeMap[] = { sizeof(uchar), sizeof(char), sizeof(ushort), - sizeof(short), sizeof(int), sizeof(float), sizeof(double) }; - - int elemSize1 = sizeMap[depth]; - int bufSize = elemSize1 * ocn; - std::vector _buf(bufSize); - uchar * buf = &_buf[0]; - scalarToRawData(sc, buf, CV_MAKE_TYPE(depth, cn)); - memset(buf + elemSize1 * cn, 0, (ocn - cn) * elemSize1); - - return _buf; - } - - static void threshold_runner(const oclMat &src, oclMat &dst, double thresh, double maxVal, int thresholdType) - { - bool ival = src.depth() < CV_32F; - int cn = src.channels(), vecSize = 4, depth = src.depth(); - std::vector thresholdValue = scalarToVector(cv::Scalar::all(ival ? cvFloor(thresh) : thresh), dst.depth(), - dst.oclchannels(), dst.channels()); - std::vector maxValue = scalarToVector(cv::Scalar::all(maxVal), dst.depth(), dst.oclchannels(), dst.channels()); - - const char * const thresholdMap[] = { "THRESH_BINARY", "THRESH_BINARY_INV", "THRESH_TRUNC", - "THRESH_TOZERO", "THRESH_TOZERO_INV" }; - const char * const channelMap[] = { "", "", "2", "4", "4" }; - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - std::string buildOptions = format("-D T=%s%s -D %s", typeMap[depth], channelMap[cn], thresholdMap[thresholdType]); - - int elemSize = src.elemSize(); - int src_step = src.step / elemSize, src_offset = src.offset / elemSize; - int dst_step = dst.step / elemSize, dst_offset = dst.offset / elemSize; - - std::vector< std::pair > args; - args.push_back( std::make_pair(sizeof(cl_mem), (void *)&src.data)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&src_offset)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&src_step)); - args.push_back( std::make_pair(sizeof(cl_mem), (void *)&dst.data)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst_offset)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst_step)); - args.push_back( std::make_pair(thresholdValue.size(), (void *)&thresholdValue[0])); - args.push_back( std::make_pair(maxValue.size(), (void *)&maxValue[0])); - - int max_index = dst.cols, cols = dst.cols; - if (cn == 1 && vecSize > 1) - { - CV_Assert(((vecSize - 1) & vecSize) == 0 && vecSize <= 16); - cols = divUp(cols, vecSize); - buildOptions += format(" -D VECTORIZED -D VT=%s%d -D VLOADN=vload%d -D VECSIZE=%d -D VSTOREN=vstore%d", - typeMap[depth], vecSize, vecSize, vecSize, vecSize); - - int vecSizeBytes = vecSize * dst.elemSize1(); - if ((dst.offset % dst.step) % vecSizeBytes == 0 && dst.step % vecSizeBytes == 0) - buildOptions += " -D DST_ALIGNED"; - if ((src.offset % src.step) % vecSizeBytes == 0 && src.step % vecSizeBytes == 0) - buildOptions += " -D SRC_ALIGNED"; - - args.push_back( std::make_pair(sizeof(cl_int), (void *)&max_index)); - } - - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.rows)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&cols)); - - size_t localThreads[3] = { 16, 16, 1 }; - size_t globalThreads[3] = { cols, dst.rows, 1 }; - - openCLExecuteKernel(src.clCxt, &imgproc_threshold, "threshold", globalThreads, localThreads, args, - -1, -1, buildOptions.c_str()); - } - - double threshold(const oclMat &src, oclMat &dst, double thresh, double maxVal, int thresholdType) - { - CV_Assert(thresholdType == THRESH_BINARY || thresholdType == THRESH_BINARY_INV || thresholdType == THRESH_TRUNC - || thresholdType == THRESH_TOZERO || thresholdType == THRESH_TOZERO_INV); - - dst.create(src.size(), src.type()); - threshold_runner(src, dst, thresh, maxVal, thresholdType); - - return thresh; - } - - //////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////// remap ////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////// - - void remap( const oclMat &src, oclMat &dst, oclMat &map1, oclMat &map2, int interpolation, int borderType, const Scalar &borderValue ) - { - Context *clCxt = src.clCxt; - bool supportsDouble = clCxt->supportsFeature(FEATURE_CL_DOUBLE); - if (!supportsDouble && src.depth() == CV_64F) - { - CV_Error(CV_OpenCLDoubleNotSupported, "Selected device does not support double"); - return; - } - - if (map1.empty()) - map1.swap(map2); - - CV_Assert(interpolation == INTER_LINEAR || interpolation == INTER_NEAREST); - CV_Assert((map1.type() == CV_16SC2 && (map2.empty() || (map2.type() == CV_16UC1 || map2.type() == CV_16SC1)) ) || - (map1.type() == CV_32FC2 && !map2.data) || - (map1.type() == CV_32FC1 && map2.type() == CV_32FC1)); - CV_Assert(!map2.data || map2.size() == map1.size()); - CV_Assert(borderType == BORDER_CONSTANT || borderType == BORDER_REPLICATE || borderType == BORDER_WRAP - || borderType == BORDER_REFLECT_101 || borderType == BORDER_REFLECT); - - dst.create(map1.size(), src.type()); - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char * const channelMap[] = { "", "", "2", "4", "4" }; - const char * const interMap[] = { "INTER_NEAREST", "INTER_LINEAR", "INTER_CUBIC", "INTER_LINEAR", "INTER_LANCZOS" }; - const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", - "BORDER_REFLECT_101", "BORDER_TRANSPARENT" }; - - String kernelName = "remap"; - if (map1.type() == CV_32FC2 && map2.empty()) - kernelName += "_32FC2"; - else if (map1.type() == CV_16SC2) - { - kernelName += "_16SC2"; - if (!map2.empty()) - kernelName += "_16UC1"; - } - else if (map1.type() == CV_32FC1 && map2.type() == CV_32FC1) - kernelName += "_2_32FC1"; - else - CV_Error(Error::StsBadArg, "Unsupported map types"); - - int ocn = dst.oclchannels(); - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - - Mat scalar(1, 1, CV_MAKE_TYPE(dst.depth(), ocn), borderValue); - String buildOptions = format("-D %s -D %s -D T=%s%s", interMap[interpolation], - borderMap[borderType], typeMap[src.depth()], channelMap[ocn]); - - if (interpolation != INTER_NEAREST) - { - int wdepth = std::max(CV_32F, dst.depth()); - buildOptions = buildOptions - + format(" -D WT=%s%s -D convertToT=convert_%s%s%s -D convertToWT=convert_%s%s" - " -D convertToWT2=convert_%s2 -D WT2=%s2", - typeMap[wdepth], channelMap[ocn], - typeMap[src.depth()], channelMap[ocn], src.depth() < CV_32F ? "_sat_rte" : "", - typeMap[wdepth], channelMap[ocn], - typeMap[wdepth], typeMap[wdepth]); - } - - int src_step = src.step / src.elemSize(), src_offset = src.offset / src.elemSize(); - int map1_step = map1.step / map1.elemSize(), map1_offset = map1.offset / map1.elemSize(); - int map2_step = map2.step / map2.elemSize(), map2_offset = map2.offset / map2.elemSize(); - int dst_step = dst.step / dst.elemSize(), dst_offset = dst.offset / dst.elemSize(); - - std::vector< std::pair > args; - args.push_back( std::make_pair(sizeof(cl_mem), (void *)&src.data)); - args.push_back( std::make_pair(sizeof(cl_mem), (void *)&dst.data)); - args.push_back( std::make_pair(sizeof(cl_mem), (void *)&map1.data)); - if (!map2.empty()) - args.push_back( std::make_pair(sizeof(cl_mem), (void *)&map2.data)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&src_offset)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst_offset)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&map1_offset)); - if (!map2.empty()) - args.push_back( std::make_pair(sizeof(cl_int), (void *)&map2_offset)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&src_step)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst_step)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&map1_step)); - if (!map2.empty()) - args.push_back( std::make_pair(sizeof(cl_int), (void *)&map2_step)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.cols)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.rows)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.cols)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.rows)); - args.push_back( std::make_pair(scalar.elemSize(), (void *)scalar.data)); - -#ifdef ANDROID - openCLExecuteKernel(clCxt, &imgproc_remap, kernelName, globalThreads, NULL, args, -1, -1, buildOptions.c_str()); -#else - size_t localThreads[3] = { 256, 1, 1 }; - openCLExecuteKernel(clCxt, &imgproc_remap, kernelName, globalThreads, localThreads, args, -1, -1, buildOptions.c_str()); -#endif - } - - //////////////////////////////////////////////////////////////////////////////////////////// - // resize - - static void computeResizeAreaTabs(int ssize, int dsize, double scale, int * const map_tab, - float * const alpha_tab, int * const ofs_tab) - { - int k = 0, dx = 0; - for ( ; dx < dsize; dx++) - { - ofs_tab[dx] = k; - - double fsx1 = dx * scale; - double fsx2 = fsx1 + scale; - double cellWidth = std::min(scale, ssize - fsx1); - - int sx1 = cvCeil(fsx1), sx2 = cvFloor(fsx2); - - sx2 = std::min(sx2, ssize - 1); - sx1 = std::min(sx1, sx2); - - if (sx1 - fsx1 > 1e-3) - { - map_tab[k] = sx1 - 1; - alpha_tab[k++] = (float)((sx1 - fsx1) / cellWidth); - } - - for (int sx = sx1; sx < sx2; sx++) - { - map_tab[k] = sx; - alpha_tab[k++] = float(1.0 / cellWidth); - } - - if (fsx2 - sx2 > 1e-3) - { - map_tab[k] = sx2; - alpha_tab[k++] = (float)(std::min(std::min(fsx2 - sx2, 1.), cellWidth) / cellWidth); - } - } - ofs_tab[dx] = k; - } - - static void computeResizeAreaFastTabs(int * dmap_tab, int * smap_tab, int scale, int dcols, int scol) - { - for (int i = 0; i < dcols; ++i) - dmap_tab[i] = scale * i; - - for (int i = 0, size = dcols * scale; i < size; ++i) - smap_tab[i] = std::min(scol - 1, i); - } - - static void resize_gpu( const oclMat &src, oclMat &dst, double ifx, double ify, int interpolation) - { - float ifxf = (float)ifx, ifyf = (float)ify; - int src_step = src.step / src.elemSize(), src_offset = src.offset / src.elemSize(); - int dst_step = dst.step / dst.elemSize(), dst_offset = dst.offset / dst.elemSize(); - int ocn = dst.oclchannels(), depth = dst.depth(); - - const char * const interMap[] = { "NN", "LN", "CUBIC", "AREA", "LAN4" }; - std::string kernelName = std::string("resize") + interMap[interpolation]; - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char * const channelMap[] = { "" , "", "2", "4", "4" }; - std::string buildOption = format("-D %s -D T=%s%s", interMap[interpolation], typeMap[depth], channelMap[ocn]); - - int wdepth = std::max(src.depth(), CV_32F); - - // check if fx, fy is integer and then we have inter area fast mode - int iscale_x = saturate_cast(ifx); - int iscale_y = saturate_cast(ify); - - bool is_area_fast = std::abs(ifx - iscale_x) < DBL_EPSILON && - std::abs(ify - iscale_y) < DBL_EPSILON; - if (is_area_fast) - wdepth = std::max(src.depth(), CV_32S); - - if (interpolation != INTER_NEAREST) - { - buildOption += format(" -D WT=%s -D WTV=%s%s -D convertToWTV=convert_%s%s -D convertToT=convert_%s%s%s", - typeMap[wdepth], typeMap[wdepth], channelMap[ocn], - typeMap[wdepth], channelMap[ocn], - typeMap[src.depth()], channelMap[ocn], src.depth() <= CV_32S ? "_sat_rte" : ""); - } - -#ifdef ANDROID - size_t blkSizeX = 16, blkSizeY = 8; -#else - size_t blkSizeX = 16, blkSizeY = 16; -#endif - size_t glbSizeX; - if (src.type() == CV_8UC1 && interpolation == INTER_LINEAR) - { - size_t cols = (dst.cols + dst.offset % 4 + 3) / 4; - glbSizeX = cols % blkSizeX == 0 && cols != 0 ? cols : (cols / blkSizeX + 1) * blkSizeX; - } - else - glbSizeX = dst.cols; - - oclMat alphaOcl, mapOcl, tabofsOcl; - if (interpolation == INTER_AREA) - { - if (is_area_fast) - { - kernelName += "_FAST"; - int wdepth2 = std::max(CV_32F, src.depth()); - buildOption += format(" -D WT2V=%s%s -D convertToWT2V=convert_%s%s -D AREA_FAST -D XSCALE=%d -D YSCALE=%d -D SCALE=%f", - typeMap[wdepth2], channelMap[ocn], typeMap[wdepth2], channelMap[ocn], - iscale_x, iscale_y, 1.0f / (iscale_x * iscale_y)); - - int smap_tab_size = dst.cols * iscale_x + dst.rows * iscale_y; - AutoBuffer dmap_tab(dst.cols + dst.rows), smap_tab(smap_tab_size); - int * dxmap_tab = dmap_tab, * dymap_tab = dxmap_tab + dst.cols; - int * sxmap_tab = smap_tab, * symap_tab = smap_tab + dst.cols * iscale_y; - - computeResizeAreaFastTabs(dxmap_tab, sxmap_tab, iscale_x, dst.cols, src.cols); - computeResizeAreaFastTabs(dymap_tab, symap_tab, iscale_y, dst.rows, src.rows); - - tabofsOcl = oclMat(1, dst.cols + dst.rows, CV_32SC1, (void *)dmap_tab); - mapOcl = oclMat(1, smap_tab_size, CV_32SC1, (void *)smap_tab); - } - else - { - Size ssize = src.size(), dsize = dst.size(); - int xytab_size = (ssize.width + ssize.height) << 1; - int tabofs_size = dsize.height + dsize.width + 2; - - AutoBuffer _xymap_tab(xytab_size), _xyofs_tab(tabofs_size); - AutoBuffer _xyalpha_tab(xytab_size); - int * xmap_tab = _xymap_tab, * ymap_tab = _xymap_tab + (ssize.width << 1); - float * xalpha_tab = _xyalpha_tab, * yalpha_tab = _xyalpha_tab + (ssize.width << 1); - int * xofs_tab = _xyofs_tab, * yofs_tab = _xyofs_tab + dsize.width + 1; - - computeResizeAreaTabs(ssize.width, dsize.width, ifx, xmap_tab, xalpha_tab, xofs_tab); - computeResizeAreaTabs(ssize.height, dsize.height, ify, ymap_tab, yalpha_tab, yofs_tab); - - // loading precomputed arrays to GPU - alphaOcl = oclMat(1, xytab_size, CV_32FC1, (void *)_xyalpha_tab); - mapOcl = oclMat(1, xytab_size, CV_32SC1, (void *)_xymap_tab); - tabofsOcl = oclMat(1, tabofs_size, CV_32SC1, (void *)_xyofs_tab); - } - } - - size_t globalThreads[3] = { glbSizeX, dst.rows, 1 }; - size_t localThreads[3] = { blkSizeX, blkSizeY, 1 }; - - std::vector< std::pair > args; - args.push_back( std::make_pair(sizeof(cl_mem), (void *)&dst.data)); - args.push_back( std::make_pair(sizeof(cl_mem), (void *)&src.data)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst_offset)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&src_offset)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst_step)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&src_step)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.cols)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&src.rows)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.cols)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.rows)); - - if (wdepth == CV_64F) - { - args.push_back( std::make_pair(sizeof(cl_double), (void *)&ifx)); - args.push_back( std::make_pair(sizeof(cl_double), (void *)&ify)); - } - else - { - args.push_back( std::make_pair(sizeof(cl_float), (void *)&ifxf)); - args.push_back( std::make_pair(sizeof(cl_float), (void *)&ifyf)); - } - - // precomputed tabs - if (!tabofsOcl.empty()) - args.push_back( std::make_pair(sizeof(cl_mem), (void *)&tabofsOcl.data)); - - if (!mapOcl.empty()) - args.push_back( std::make_pair(sizeof(cl_mem), (void *)&mapOcl.data)); - - if (!alphaOcl.empty()) - args.push_back( std::make_pair(sizeof(cl_mem), (void *)&alphaOcl.data)); - - ocn = interpolation == INTER_LINEAR ? ocn : -1; - depth = interpolation == INTER_LINEAR ? depth : -1; - - openCLExecuteKernel(src.clCxt, &imgproc_resize, kernelName, globalThreads, localThreads, args, - ocn, depth, buildOption.c_str()); - } - - void resize(const oclMat &src, oclMat &dst, Size dsize, double fx, double fy, int interpolation) - { - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(CV_OpenCLDoubleNotSupported, "Selected device does not support double"); - return; - } - - CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4 - || src.type() == CV_32FC1 || src.type() == CV_32FC3 || src.type() == CV_32FC4); - CV_Assert(dsize.area() > 0 || (fx > 0 && fy > 0)); - - if (dsize.area() == 0) - { - dsize = Size(saturate_cast(src.cols * fx), saturate_cast(src.rows * fy)); - CV_Assert(dsize.area() > 0); - } - else - { - fx = (double)dsize.width / src.cols; - fy = (double)dsize.height / src.rows; - } - - double inv_fy = 1 / fy, inv_fx = 1 / fx; - CV_Assert(interpolation == INTER_LINEAR || interpolation == INTER_NEAREST || - (interpolation == INTER_AREA && inv_fx >= 1 && inv_fy >= 1)); - - dst.create(dsize, src.type()); - - resize_gpu( src, dst, inv_fx, inv_fy, interpolation); - } - - //////////////////////////////////////////////////////////////////////// - // medianFilter - - void medianFilter(const oclMat &src, oclMat &dst, int m) - { - CV_Assert( m % 2 == 1 && m > 1 ); - CV_Assert( (src.depth() == CV_8U || src.depth() == CV_32F) && (src.channels() == 1 || src.channels() == 4)); - dst.create(src.size(), src.type()); - - int srcStep = src.step / src.elemSize(), dstStep = dst.step / dst.elemSize(); - int srcOffset = src.offset / src.elemSize(), dstOffset = dst.offset / dst.elemSize(); - - Context *clCxt = src.clCxt; - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcOffset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstOffset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstStep)); - - size_t globalThreads[3] = {(src.cols + 18) / 16 * 16, (src.rows + 15) / 16 * 16, 1}; - size_t localThreads[3] = {16, 16, 1}; - - if (m == 3) - { - String kernelName = "medianFilter3"; - openCLExecuteKernel(clCxt, &imgproc_median, kernelName, globalThreads, localThreads, args, src.oclchannels(), src.depth()); - } - else if (m == 5) - { - String kernelName = "medianFilter5"; - openCLExecuteKernel(clCxt, &imgproc_median, kernelName, globalThreads, localThreads, args, src.oclchannels(), src.depth()); - } - else - CV_Error(Error::StsBadArg, "Non-supported filter length"); - } - - //////////////////////////////////////////////////////////////////////// - // copyMakeBorder - - void copyMakeBorder(const oclMat &src, oclMat &dst, int top, int bottom, int left, int right, int bordertype, const Scalar &scalar) - { - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device does not support double"); - return; - } - - oclMat _src = src; - - CV_Assert(top >= 0 && bottom >= 0 && left >= 0 && right >= 0); - - if( (_src.wholecols != _src.cols || _src.wholerows != _src.rows) && (bordertype & BORDER_ISOLATED) == 0 ) - { - Size wholeSize; - Point ofs; - _src.locateROI(wholeSize, ofs); - int dtop = std::min(ofs.y, top); - int dbottom = std::min(wholeSize.height - _src.rows - ofs.y, bottom); - int dleft = std::min(ofs.x, left); - int dright = std::min(wholeSize.width - _src.cols - ofs.x, right); - _src.adjustROI(dtop, dbottom, dleft, dright); - top -= dtop; - left -= dleft; - bottom -= dbottom; - right -= dright; - } - bordertype &= ~cv::BORDER_ISOLATED; - - dst.create(_src.rows + top + bottom, _src.cols + left + right, _src.type()); - int srcStep = _src.step / _src.elemSize(), dstStep = dst.step / dst.elemSize(); - int srcOffset = _src.offset / _src.elemSize(), dstOffset = dst.offset / dst.elemSize(); - int depth = _src.depth(), ochannels = _src.oclchannels(); - - int __bordertype[] = { BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT, BORDER_WRAP, BORDER_REFLECT_101 }; - const char *borderstr[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101" }; - - int bordertype_index = -1; - for (int i = 0, end = sizeof(__bordertype) / sizeof(int); i < end; i++) - if (__bordertype[i] == bordertype) - { - bordertype_index = i; - break; - } - if (bordertype_index < 0) - CV_Error(Error::StsBadArg, "Unsupported border type"); - - size_t localThreads[3] = { 16, 16, 1 }; - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&_src.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&_src.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&_src.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcOffset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstOffset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&top)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&left)); - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char * const channelMap[] = { "", "", "2", "4", "4" }; - std::string buildOptions = format("-D GENTYPE=%s%s -D %s", - typeMap[depth], channelMap[ochannels], - borderstr[bordertype_index]); - - int cn = src.channels(), ocn = src.oclchannels(); - int bufSize = src.elemSize1() * ocn; - AutoBuffer _buf(bufSize); - uchar * buf = (uchar *)_buf; - scalarToRawData(scalar, buf, dst.type()); - memset(buf + src.elemSize1() * cn, 0, (ocn - cn) * src.elemSize1()); - - args.push_back( std::make_pair( bufSize , (void *)buf )); - - openCLExecuteKernel(src.clCxt, &imgproc_copymakeboder, "copymakeborder", globalThreads, - localThreads, args, -1, -1, buildOptions.c_str()); - } - - //////////////////////////////////////////////////////////////////////// - // warp - - namespace - { -#define F double - - void convert_coeffs(F *M) - { - double D = M[0] * M[4] - M[1] * M[3]; - D = D != 0 ? 1. / D : 0; - double A11 = M[4] * D, A22 = M[0] * D; - M[0] = A11; - M[1] *= -D; - M[3] *= -D; - M[4] = A22; - double b1 = -M[0] * M[2] - M[1] * M[5]; - double b2 = -M[3] * M[2] - M[4] * M[5]; - M[2] = b1; - M[5] = b2; - } - - double invert(double *M) - { -#define Sd(y,x) (Sd[y*3+x]) -#define Dd(y,x) (Dd[y*3+x]) -#define det3(m) (m(0,0)*(m(1,1)*m(2,2) - m(1,2)*m(2,1)) - \ - m(0,1)*(m(1,0)*m(2,2) - m(1,2)*m(2,0)) + \ - m(0,2)*(m(1,0)*m(2,1) - m(1,1)*m(2,0))) - double *Sd = M; - double *Dd = M; - double d = det3(Sd); - double result = 0; - if ( d != 0) - { - double t[9]; - result = d; - d = 1. / d; - - t[0] = (Sd(1, 1) * Sd(2, 2) - Sd(1, 2) * Sd(2, 1)) * d; - t[1] = (Sd(0, 2) * Sd(2, 1) - Sd(0, 1) * Sd(2, 2)) * d; - t[2] = (Sd(0, 1) * Sd(1, 2) - Sd(0, 2) * Sd(1, 1)) * d; - - t[3] = (Sd(1, 2) * Sd(2, 0) - Sd(1, 0) * Sd(2, 2)) * d; - t[4] = (Sd(0, 0) * Sd(2, 2) - Sd(0, 2) * Sd(2, 0)) * d; - t[5] = (Sd(0, 2) * Sd(1, 0) - Sd(0, 0) * Sd(1, 2)) * d; - - t[6] = (Sd(1, 0) * Sd(2, 1) - Sd(1, 1) * Sd(2, 0)) * d; - t[7] = (Sd(0, 1) * Sd(2, 0) - Sd(0, 0) * Sd(2, 1)) * d; - t[8] = (Sd(0, 0) * Sd(1, 1) - Sd(0, 1) * Sd(1, 0)) * d; - - Dd(0, 0) = t[0]; - Dd(0, 1) = t[1]; - Dd(0, 2) = t[2]; - Dd(1, 0) = t[3]; - Dd(1, 1) = t[4]; - Dd(1, 2) = t[5]; - Dd(2, 0) = t[6]; - Dd(2, 1) = t[7]; - Dd(2, 2) = t[8]; - } - return result; - } - - void warpAffine_gpu(const oclMat &src, oclMat &dst, F coeffs[2][3], int interpolation) - { - CV_Assert( (src.oclchannels() == dst.oclchannels()) ); - int srcStep = src.step1(); - int dstStep = dst.step1(); - float float_coeffs[2][3]; - cl_mem coeffs_cm; - - Context *clCxt = src.clCxt; - String s[3] = {"NN", "Linear", "Cubic"}; - String kernelName = "warpAffine" + s[interpolation]; - - if (src.clCxt->supportsFeature(FEATURE_CL_DOUBLE)) - { - cl_int st; - coeffs_cm = clCreateBuffer(*(cl_context*)clCxt->getOpenCLContextPtr(), CL_MEM_READ_WRITE, sizeof(F) * 2 * 3, NULL, &st ); - openCLVerifyCall(st); - openCLSafeCall(clEnqueueWriteBuffer(*(cl_command_queue*)clCxt->getOpenCLCommandQueuePtr(), (cl_mem)coeffs_cm, 1, 0, - sizeof(F) * 2 * 3, coeffs, 0, 0, 0)); - } - else - { - cl_int st; - for(int m = 0; m < 2; m++) - for(int n = 0; n < 3; n++) - float_coeffs[m][n] = coeffs[m][n]; - - coeffs_cm = clCreateBuffer(*(cl_context*)clCxt->getOpenCLContextPtr(), CL_MEM_READ_WRITE, sizeof(float) * 2 * 3, NULL, &st ); - openCLSafeCall(clEnqueueWriteBuffer(*(cl_command_queue*)clCxt->getOpenCLCommandQueuePtr(), (cl_mem)coeffs_cm, - 1, 0, sizeof(float) * 2 * 3, float_coeffs, 0, 0, 0)); - - } - - //TODO: improve this kernel -#ifdef ANDROID - size_t blkSizeX = 16, blkSizeY = 4; -#else - size_t blkSizeX = 16, blkSizeY = 16; -#endif - size_t glbSizeX; - size_t cols; - - if (src.type() == CV_8UC1 && interpolation != 2) - { - cols = (dst.cols + dst.offset % 4 + 3) / 4; - glbSizeX = cols % blkSizeX == 0 ? cols : (cols / blkSizeX + 1) * blkSizeX; - } - else - { - cols = dst.cols; - glbSizeX = dst.cols % blkSizeX == 0 ? dst.cols : (dst.cols / blkSizeX + 1) * blkSizeX; - } - - size_t glbSizeY = dst.rows % blkSizeY == 0 ? dst.rows : (dst.rows / blkSizeY + 1) * blkSizeY; - size_t globalThreads[3] = {glbSizeX, glbSizeY, 1}; - size_t localThreads[3] = {blkSizeX, blkSizeY, 1}; - - std::vector< std::pair > args; - - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&src.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&dst.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&srcStep)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dstStep)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.offset)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.offset)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&coeffs_cm)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&cols)); - - openCLExecuteKernel(clCxt, &imgproc_warpAffine, kernelName, globalThreads, localThreads, args, src.oclchannels(), src.depth()); - openCLSafeCall(clReleaseMemObject(coeffs_cm)); - } - - void warpPerspective_gpu(const oclMat &src, oclMat &dst, double coeffs[3][3], int interpolation) - { - CV_Assert( (src.oclchannels() == dst.oclchannels()) ); - int srcStep = src.step1(); - int dstStep = dst.step1(); - float float_coeffs[3][3]; - cl_mem coeffs_cm; - - Context *clCxt = src.clCxt; - String s[3] = {"NN", "Linear", "Cubic"}; - String kernelName = "warpPerspective" + s[interpolation]; - - if (src.clCxt->supportsFeature(FEATURE_CL_DOUBLE)) - { - cl_int st; - coeffs_cm = clCreateBuffer(*(cl_context*)clCxt->getOpenCLContextPtr(), CL_MEM_READ_WRITE, sizeof(double) * 3 * 3, NULL, &st ); - openCLVerifyCall(st); - openCLSafeCall(clEnqueueWriteBuffer(*(cl_command_queue*)clCxt->getOpenCLCommandQueuePtr(), (cl_mem)coeffs_cm, 1, 0, - sizeof(double) * 3 * 3, coeffs, 0, 0, 0)); - } - else - { - cl_int st; - for(int m = 0; m < 3; m++) - for(int n = 0; n < 3; n++) - float_coeffs[m][n] = coeffs[m][n]; - - coeffs_cm = clCreateBuffer(*(cl_context*)clCxt->getOpenCLContextPtr(), CL_MEM_READ_WRITE, sizeof(float) * 3 * 3, NULL, &st ); - openCLVerifyCall(st); - openCLSafeCall(clEnqueueWriteBuffer(*(cl_command_queue*)clCxt->getOpenCLCommandQueuePtr(), (cl_mem)coeffs_cm, 1, 0, - sizeof(float) * 3 * 3, float_coeffs, 0, 0, 0)); - } - - //TODO: improve this kernel -#ifdef ANDROID - size_t blkSizeX = 16, blkSizeY = 8; -#else - size_t blkSizeX = 16, blkSizeY = 16; -#endif - size_t glbSizeX; - size_t cols; - if (src.type() == CV_8UC1 && interpolation == 0) - { - cols = (dst.cols + dst.offset % 4 + 3) / 4; - glbSizeX = cols % blkSizeX == 0 ? cols : (cols / blkSizeX + 1) * blkSizeX; - } - else - { - cols = dst.cols; - glbSizeX = dst.cols % blkSizeX == 0 ? dst.cols : (dst.cols / blkSizeX + 1) * blkSizeX; - } - - size_t glbSizeY = dst.rows % blkSizeY == 0 ? dst.rows : (dst.rows / blkSizeY + 1) * blkSizeY; - size_t globalThreads[3] = {glbSizeX, glbSizeY, 1}; - size_t localThreads[3] = {blkSizeX, blkSizeY, 1}; - - std::vector< std::pair > args; - - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&src.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&dst.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&srcStep)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dstStep)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.offset)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.offset)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&coeffs_cm)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&cols)); - - openCLExecuteKernel(clCxt, &imgproc_warpPerspective, kernelName, globalThreads, localThreads, args, src.oclchannels(), src.depth()); - openCLSafeCall(clReleaseMemObject(coeffs_cm)); - } - } - - void warpAffine(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags) - { - int interpolation = flags & INTER_MAX; - - CV_Assert((src.depth() == CV_8U || src.depth() == CV_32F) && src.oclchannels() != 2 && src.oclchannels() != 3); - CV_Assert(interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC); - - dst.create(dsize, src.type()); - - CV_Assert(M.rows == 2 && M.cols == 3); - - int warpInd = (flags & WARP_INVERSE_MAP) >> 4; - F coeffs[2][3]; - - double coeffsM[2*3]; - Mat coeffsMat(2, 3, CV_64F, (void *)coeffsM); - M.convertTo(coeffsMat, coeffsMat.type()); - if (!warpInd) - convert_coeffs(coeffsM); - - for(int i = 0; i < 2; ++i) - for(int j = 0; j < 3; ++j) - coeffs[i][j] = coeffsM[i*3+j]; - - warpAffine_gpu(src, dst, coeffs, interpolation); - } - - void warpPerspective(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags) - { - int interpolation = flags & INTER_MAX; - - CV_Assert((src.depth() == CV_8U || src.depth() == CV_32F) && src.oclchannels() != 2 && src.oclchannels() != 3); - CV_Assert(interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC); - - dst.create(dsize, src.type()); - - - CV_Assert(M.rows == 3 && M.cols == 3); - - int warpInd = (flags & WARP_INVERSE_MAP) >> 4; - double coeffs[3][3]; - - double coeffsM[3*3]; - Mat coeffsMat(3, 3, CV_64F, (void *)coeffsM); - M.convertTo(coeffsMat, coeffsMat.type()); - if (!warpInd) - invert(coeffsM); - - for(int i = 0; i < 3; ++i) - for(int j = 0; j < 3; ++j) - coeffs[i][j] = coeffsM[i*3+j]; - - warpPerspective_gpu(src, dst, coeffs, interpolation); - } - - //////////////////////////////////////////////////////////////////////// - // integral - - void integral(const oclMat &src, oclMat &sum, oclMat &sqsum, int sdepth) - { - CV_Assert(src.type() == CV_8UC1); - if (!src.clCxt->supportsFeature(ocl::FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Select device doesn't support double"); - return; - } - - if( sdepth <= 0 ) - sdepth = CV_32S; - sdepth = CV_MAT_DEPTH(sdepth); - int type = CV_MAKE_TYPE(sdepth, 1); - - int vlen = 4; - int offset = src.offset / vlen; - int pre_invalid = src.offset % vlen; - int vcols = (pre_invalid + src.cols + vlen - 1) / vlen; - - oclMat t_sum , t_sqsum; - int w = src.cols + 1, h = src.rows + 1; - - char build_option[250]; - if(Context::getContext()->supportsFeature(ocl::FEATURE_CL_DOUBLE)) - { - t_sqsum.create(src.cols, src.rows, CV_64FC1); - sqsum.create(h, w, CV_64FC1); - sprintf(build_option, "-D TYPE=double -D TYPE4=double4 -D convert_TYPE4=convert_double4"); - } - else - { - t_sqsum.create(src.cols, src.rows, CV_32FC1); - sqsum.create(h, w, CV_32FC1); - sprintf(build_option, "-D TYPE=float -D TYPE4=float4 -D convert_TYPE4=convert_float4"); - } - - t_sum.create(src.cols, src.rows, type); - sum.create(h, w, type); - - int sum_offset = sum.offset / sum.elemSize(); - int sqsum_offset = sqsum.offset / sqsum.elemSize(); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&t_sum.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&t_sqsum.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&pre_invalid )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.rows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.step )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sqsum.step)); - size_t gt[3] = {((vcols + 1) / 2) * 256, 1, 1}, lt[3] = {256, 1, 1}; - openCLExecuteKernel(src.clCxt, &imgproc_integral, "integral_cols", gt, lt, args, -1, sdepth, build_option); - - args.clear(); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&t_sum.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&t_sqsum.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&sum.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&sqsum.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.rows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.step )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sqsum.step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sum.step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sqsum.step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sum_offset)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sqsum_offset)); - size_t gt2[3] = {t_sum.cols * 32, 1, 1}, lt2[3] = {256, 1, 1}; - openCLExecuteKernel(src.clCxt, &imgproc_integral, "integral_rows", gt2, lt2, args, -1, sdepth, build_option); - } - - void integral(const oclMat &src, oclMat &sum, int sdepth) - { - CV_Assert(src.type() == CV_8UC1); - int vlen = 4; - int offset = src.offset / vlen; - int pre_invalid = src.offset % vlen; - int vcols = (pre_invalid + src.cols + vlen - 1) / vlen; - - if( sdepth <= 0 ) - sdepth = CV_32S; - sdepth = CV_MAT_DEPTH(sdepth); - int type = CV_MAKE_TYPE(sdepth, 1); - - oclMat t_sum; - int w = src.cols + 1, h = src.rows + 1; - - t_sum.create(src.cols, src.rows, type); - sum.create(h, w, type); - - int sum_offset = sum.offset / vlen; - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&t_sum.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&pre_invalid )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.rows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.step )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.step)); - size_t gt[3] = {((vcols + 1) / 2) * 256, 1, 1}, lt[3] = {256, 1, 1}; - openCLExecuteKernel(src.clCxt, &imgproc_integral_sum, "integral_sum_cols", gt, lt, args, -1, sdepth); - - args.clear(); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&t_sum.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&sum.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.rows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t_sum.step )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sum.step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sum_offset)); - size_t gt2[3] = {t_sum.cols * 32, 1, 1}, lt2[3] = {256, 1, 1}; - openCLExecuteKernel(src.clCxt, &imgproc_integral_sum, "integral_sum_rows", gt2, lt2, args, -1, sdepth); - } - - /////////////////////// corner ////////////////////////////// - - static void extractCovData(const oclMat &src, oclMat &Dx, oclMat &Dy, - int blockSize, int ksize, int borderType) - { - CV_Assert(src.type() == CV_8UC1 || src.type() == CV_32FC1); - double scale = static_cast(1 << ((ksize > 0 ? ksize : 3) - 1)) * blockSize; - if (ksize < 0) - scale *= 2.; - - if (src.depth() == CV_8U) - { - scale *= 255.; - scale = 1. / scale; - } - else - scale = 1. / scale; - - const int sobel_lsz = 16; - if((src.type() == CV_8UC1 || src.type() == CV_32FC1) && - (ksize==3 || ksize==5 || ksize==7 || ksize==-1) && - src.wholerows > sobel_lsz + (ksize>>1) && - src.wholecols > sobel_lsz + (ksize>>1)) - { - Dx.create(src.size(), CV_32FC1); - Dy.create(src.size(), CV_32FC1); - - CV_Assert(Dx.rows == Dy.rows && Dx.cols == Dy.cols); - - size_t lt2[3] = {sobel_lsz, sobel_lsz, 1}; - size_t gt2[3] = {lt2[0]*(1 + (src.cols-1) / lt2[0]), lt2[1]*(1 + (src.rows-1) / lt2[1]), 1}; - - unsigned int src_pitch = src.step; - unsigned int Dx_pitch = Dx.step; - unsigned int Dy_pitch = Dy.step; - - int src_offset_x = (src.offset % src.step) / src.elemSize(); - int src_offset_y = src.offset / src.step; - - float _scale = scale; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_uint) , (void *)&src_pitch )); - - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_offset_x )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_offset_y )); - - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&Dx.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dx.offset )); - args.push_back( std::make_pair( sizeof(cl_uint) , (void *)&Dx_pitch )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&Dy.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dy.offset )); - args.push_back( std::make_pair( sizeof(cl_uint) , (void *)&Dy_pitch )); - - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.wholecols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.wholerows )); - - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dx.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dx.rows )); - - args.push_back( std::make_pair( sizeof(cl_float), (void *)&_scale )); - - String option = cv::format("-D BLK_X=%d -D BLK_Y=%d",(int)lt2[0],(int)lt2[1]); - switch(src.type()) - { - case CV_8UC1: - option += " -D SRCTYPE=uchar"; - break; - case CV_32FC1: - option += " -D SRCTYPE=float"; - break; - } - switch(borderType) - { - case cv::BORDER_CONSTANT: - option += " -D BORDER_CONSTANT"; - break; - case cv::BORDER_REPLICATE: - option += " -D BORDER_REPLICATE"; - break; - case cv::BORDER_REFLECT: - option += " -D BORDER_REFLECT"; - break; - case cv::BORDER_REFLECT101: - option += " -D BORDER_REFLECT_101"; - break; - case cv::BORDER_WRAP: - option += " -D BORDER_WRAP"; - break; - default: - CV_Error(CV_StsBadFlag, "BORDER type is not supported!"); - break; - } - - String kernel_name; - switch(ksize) - { - case -1: - option += " -D SCHARR"; - kernel_name = "sobel3"; - break; - case 3: - kernel_name = "sobel3"; - break; - case 5: - kernel_name = "sobel5"; - break; - case 7: - kernel_name = "sobel7"; - break; - default: - CV_Error(CV_StsBadFlag, "Kernel size is not supported!"); - break; - } - openCLExecuteKernel(src.clCxt, &imgproc_sobel3, kernel_name, gt2, lt2, args, -1, -1, option.c_str() ); - } - else - { - if (ksize > 0) - { - Sobel(src, Dx, CV_32F, 1, 0, ksize, scale, 0, borderType); - Sobel(src, Dy, CV_32F, 0, 1, ksize, scale, 0, borderType); - } - else - { - Scharr(src, Dx, CV_32F, 1, 0, scale, 0, borderType); - Scharr(src, Dy, CV_32F, 0, 1, scale, 0, borderType); - } - } - CV_Assert(Dx.offset == 0 && Dy.offset == 0); - } - - static void corner_ocl(const cv::ocl::ProgramEntry* source, String kernelName, int block_size, float k, oclMat &Dx, oclMat &Dy, - oclMat &dst, int border_type) - { - char borderType[30]; - switch (border_type) - { - case cv::BORDER_CONSTANT: - sprintf(borderType, "BORDER_CONSTANT"); - break; - case cv::BORDER_REFLECT101: - sprintf(borderType, "BORDER_REFLECT101"); - break; - case cv::BORDER_REFLECT: - sprintf(borderType, "BORDER_REFLECT"); - break; - case cv::BORDER_REPLICATE: - sprintf(borderType, "BORDER_REPLICATE"); - break; - default: - CV_Error(Error::StsBadFlag, "BORDER type is not supported!"); - } - - std::string buildOptions = format("-D anX=%d -D anY=%d -D ksX=%d -D ksY=%d -D %s", - block_size / 2, block_size / 2, block_size, block_size, borderType); - - size_t blockSizeX = 256, blockSizeY = 1; - size_t gSize = blockSizeX - block_size / 2 * 2; - size_t globalSizeX = (Dx.cols) % gSize == 0 ? Dx.cols / gSize * blockSizeX : (Dx.cols / gSize + 1) * blockSizeX; - size_t rows_per_thread = 2; - size_t globalSizeY = ((Dx.rows + rows_per_thread - 1) / rows_per_thread) % blockSizeY == 0 ? - ((Dx.rows + rows_per_thread - 1) / rows_per_thread) : - (((Dx.rows + rows_per_thread - 1) / rows_per_thread) / blockSizeY + 1) * blockSizeY; - - size_t gt[3] = { globalSizeX, globalSizeY, 1 }; - size_t lt[3] = { blockSizeX, blockSizeY, 1 }; - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&Dx.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&Dy.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dx.offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dx.wholerows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dx.wholecols )); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&Dx.step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dy.offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dy.wholerows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&Dy.wholecols )); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&Dy.step)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.offset)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.rows)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.cols)); - args.push_back( std::make_pair(sizeof(cl_int), (void *)&dst.step)); - args.push_back( std::make_pair( sizeof(cl_float) , (void *)&k)); - - openCLExecuteKernel(dst.clCxt, source, kernelName, gt, lt, args, -1, -1, buildOptions.c_str()); - } - - void cornerHarris(const oclMat &src, oclMat &dst, int blockSize, int ksize, - double k, int borderType) - { - oclMat dx, dy; - cornerHarris_dxdy(src, dst, dx, dy, blockSize, ksize, k, borderType); - } - - void cornerHarris_dxdy(const oclMat &src, oclMat &dst, oclMat &dx, oclMat &dy, int blockSize, int ksize, - double k, int borderType) - { - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_Assert(borderType == cv::BORDER_CONSTANT || borderType == cv::BORDER_REFLECT101 || borderType == cv::BORDER_REPLICATE - || borderType == cv::BORDER_REFLECT); - - extractCovData(src, dx, dy, blockSize, ksize, borderType); - dst.create(src.size(), CV_32FC1); - corner_ocl(&imgproc_calcHarris, "calcHarris", blockSize, static_cast(k), dx, dy, dst, borderType); - } - - void cornerMinEigenVal(const oclMat &src, oclMat &dst, int blockSize, int ksize, int borderType) - { - oclMat dx, dy; - cornerMinEigenVal_dxdy(src, dst, dx, dy, blockSize, ksize, borderType); - } - - void cornerMinEigenVal_dxdy(const oclMat &src, oclMat &dst, oclMat &dx, oclMat &dy, int blockSize, int ksize, int borderType) - { - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_Assert(borderType == cv::BORDER_CONSTANT || borderType == cv::BORDER_REFLECT101 || - borderType == cv::BORDER_REPLICATE || borderType == cv::BORDER_REFLECT); - - extractCovData(src, dx, dy, blockSize, ksize, borderType); - dst.create(src.size(), CV_32F); - - corner_ocl(&imgproc_calcMinEigenVal, "calcMinEigenVal", blockSize, 0, dx, dy, dst, borderType); - } - - /////////////////////////////////// MeanShiftfiltering /////////////////////////////////////////////// - - static void meanShiftFiltering_gpu(const oclMat &src, oclMat dst, int sp, int sr, int maxIter, float eps) - { - CV_Assert( (src.cols == dst.cols) && (src.rows == dst.rows) ); - CV_Assert( !(dst.step & 0x3) ); - - //Arrange the NDRange - int col = src.cols, row = src.rows; - int ltx = 16, lty = 8; - if (src.cols % ltx != 0) - col = (col / ltx + 1) * ltx; - if (src.rows % lty != 0) - row = (row / lty + 1) * lty; - - size_t globalThreads[3] = {col, row, 1}; - size_t localThreads[3] = {ltx, lty, 1}; - - //set args - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.step )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.step )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sp )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sr )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&maxIter )); - args.push_back( std::make_pair( sizeof(cl_float) , (void *)&eps )); - - openCLExecuteKernel(src.clCxt, &meanShift, "meanshift_kernel", globalThreads, localThreads, args, -1, -1); - } - - void meanShiftFiltering(const oclMat &src, oclMat &dst, int sp, int sr, TermCriteria criteria) - { - if (src.empty()) - CV_Error(Error::StsBadArg, "The input image is empty"); - - if ( src.depth() != CV_8U || src.oclchannels() != 4 ) - CV_Error(Error::StsUnsupportedFormat, "Only 8-bit, 4-channel images are supported"); - - dst.create( src.size(), CV_8UC4 ); - - if ( !(criteria.type & TermCriteria::MAX_ITER) ) - criteria.maxCount = 5; - - int maxIter = std::min(std::max(criteria.maxCount, 1), 100); - - float eps; - if ( !(criteria.type & TermCriteria::EPS) ) - eps = 1.f; - eps = (float)std::max(criteria.epsilon, 0.0); - - meanShiftFiltering_gpu(src, dst, sp, sr, maxIter, eps); - } - - static void meanShiftProc_gpu(const oclMat &src, oclMat dstr, oclMat dstsp, int sp, int sr, int maxIter, float eps) - { - //sanity checks - CV_Assert( (src.cols == dstr.cols) && (src.rows == dstr.rows) && - (src.rows == dstsp.rows) && (src.cols == dstsp.cols)); - CV_Assert( !(dstsp.step & 0x3) ); - - //Arrange the NDRange - int col = src.cols, row = src.rows; - int ltx = 16, lty = 8; - if (src.cols % ltx != 0) - col = (col / ltx + 1) * ltx; - if (src.rows % lty != 0) - row = (row / lty + 1) * lty; - - size_t globalThreads[3] = {col, row, 1}; - size_t localThreads[3] = {ltx, lty, 1}; - - //set args - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dstr.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dstsp.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.step )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstr.step )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstsp.step )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstr.offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstsp.offset )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstr.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstr.rows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sp )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sr )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&maxIter )); - args.push_back( std::make_pair( sizeof(cl_float) , (void *)&eps )); - - openCLExecuteKernel(src.clCxt, &meanShift, "meanshiftproc_kernel", globalThreads, localThreads, args, -1, -1); - } - - void meanShiftProc(const oclMat &src, oclMat &dstr, oclMat &dstsp, int sp, int sr, TermCriteria criteria) - { - if (src.empty()) - CV_Error(Error::StsBadArg, "The input image is empty"); - - if ( src.depth() != CV_8U || src.oclchannels() != 4 ) - CV_Error(Error::StsUnsupportedFormat, "Only 8-bit, 4-channel images are supported"); - -// if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE)) -// { -// CV_Error(Error::OpenCLDoubleNotSupportedNotSupported, "Selected device doesn't support double, so a deviation exists.\nIf the accuracy is acceptable, the error can be ignored.\n"); -// return; -// } - - dstr.create( src.size(), CV_8UC4 ); - dstsp.create( src.size(), CV_16SC2 ); - - if ( !(criteria.type & TermCriteria::MAX_ITER) ) - criteria.maxCount = 5; - - int maxIter = std::min(std::max(criteria.maxCount, 1), 100); - - float eps; - if ( !(criteria.type & TermCriteria::EPS) ) - eps = 1.f; - eps = (float)std::max(criteria.epsilon, 0.0); - - meanShiftProc_gpu(src, dstr, dstsp, sp, sr, maxIter, eps); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////hist/////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////////////////////////////// - - namespace histograms - { - const int PARTIAL_HISTOGRAM256_COUNT = 256; - const int HISTOGRAM256_BIN_COUNT = 256; - } - ///////////////////////////////calcHist///////////////////////////////////////////////////////////////// - static void calc_sub_hist(const oclMat &mat_src, const oclMat &mat_sub_hist) - { - using namespace histograms; - - int depth = mat_src.depth(); - - size_t localThreads[3] = { HISTOGRAM256_BIN_COUNT, 1, 1 }; - size_t globalThreads[3] = { PARTIAL_HISTOGRAM256_COUNT *localThreads[0], 1, 1}; - - int dataWidth = 16; - int dataWidth_bits = 4; - int mask = dataWidth - 1; - - int cols = mat_src.cols * mat_src.oclchannels(); - int src_offset = mat_src.offset; - int hist_step = mat_sub_hist.step >> 2; - int left_col = 0, right_col = 0; - - if (cols >= dataWidth * 2 - 1) - { - left_col = dataWidth - (src_offset & mask); - left_col &= mask; - src_offset += left_col; - cols -= left_col; - right_col = cols & mask; - cols -= right_col; - } - else - { - left_col = cols; - right_col = 0; - cols = 0; - globalThreads[0] = 0; - } - - std::vector > args; - if (globalThreads[0] != 0) - { - int tempcols = cols >> dataWidth_bits; - int inc_x = globalThreads[0] % tempcols; - int inc_y = globalThreads[0] / tempcols; - src_offset >>= dataWidth_bits; - int src_step = mat_src.step >> dataWidth_bits; - int datacount = tempcols * mat_src.rows; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_src.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_offset)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_sub_hist.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&datacount)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&tempcols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&inc_x)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&inc_y)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&hist_step)); - - openCLExecuteKernel(mat_src.clCxt, &imgproc_histogram, "calc_sub_hist", globalThreads, localThreads, args, -1, depth); - } - - if (left_col != 0 || right_col != 0) - { - src_offset = mat_src.offset; - localThreads[0] = 1; - localThreads[1] = 256; - globalThreads[0] = left_col + right_col; - globalThreads[1] = mat_src.rows; - - args.clear(); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_src.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_offset)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_sub_hist.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&left_col)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&hist_step)); - - openCLExecuteKernel(mat_src.clCxt, &imgproc_histogram, "calc_sub_hist_border", globalThreads, localThreads, args, -1, depth); - } - } - - static void merge_sub_hist(const oclMat &sub_hist, oclMat &mat_hist) - { - using namespace histograms; - - size_t localThreads[3] = { 256, 1, 1 }; - size_t globalThreads[3] = { HISTOGRAM256_BIN_COUNT *localThreads[0], 1, 1}; - int src_step = sub_hist.step >> 2; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&sub_hist.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_hist.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_step)); - - openCLExecuteKernel(sub_hist.clCxt, &imgproc_histogram, "merge_hist", globalThreads, localThreads, args, -1, -1); - } - - void calcHist(const oclMat &mat_src, oclMat &mat_hist) - { - using namespace histograms; - CV_Assert(mat_src.type() == CV_8UC1); - mat_hist.create(1, 256, CV_32SC1); - - oclMat buf(PARTIAL_HISTOGRAM256_COUNT, HISTOGRAM256_BIN_COUNT, CV_32SC1); - buf.setTo(0); - - calc_sub_hist(mat_src, buf); - merge_sub_hist(buf, mat_hist); - } - - ///////////////////////////////////equalizeHist///////////////////////////////////////////////////// - void equalizeHist(const oclMat &mat_src, oclMat &mat_dst) - { - mat_dst.create(mat_src.rows, mat_src.cols, CV_8UC1); - - oclMat mat_hist(1, 256, CV_32SC1); - - calcHist(mat_src, mat_hist); - - size_t localThreads[3] = { 256, 1, 1}; - size_t globalThreads[3] = { 256, 1, 1}; - oclMat lut(1, 256, CV_8UC1); - int total = mat_src.rows * mat_src.cols; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&lut.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_hist.data)); - args.push_back( std::make_pair( sizeof(int), (void *)&total)); - - openCLExecuteKernel(mat_src.clCxt, &imgproc_histogram, "calLUT", globalThreads, localThreads, args, -1, -1); - LUT(mat_src, lut, mat_dst); - } - - //////////////////////////////////////////////////////////////////////// - // CLAHE - namespace clahe - { - static void calcLut(const oclMat &src, oclMat &dst, - const int tilesX, const int tilesY, const cv::Size tileSize, - const int clipLimit, const float lutScale) - { - cl_int2 tile_size; - tile_size.s[0] = tileSize.width; - tile_size.s[1] = tileSize.height; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.step )); - args.push_back( std::make_pair( sizeof(cl_int2), (void *)&tile_size )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&tilesX )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&clipLimit )); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&lutScale )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.offset )); - - String kernelName = "calcLut"; - size_t localThreads[3] = { 32, 8, 1 }; - size_t globalThreads[3] = { tilesX * localThreads[0], tilesY * localThreads[1], 1 }; - bool is_cpu = isCpuDevice(); - if (is_cpu) - openCLExecuteKernel(Context::getContext(), &imgproc_clahe, kernelName, globalThreads, localThreads, args, -1, -1, (char*)"-D CPU"); - else - { - cl_kernel kernel = openCLGetKernelFromSource(Context::getContext(), &imgproc_clahe, kernelName); - int wave_size = (int)queryWaveFrontSize(kernel); - openCLSafeCall(clReleaseKernel(kernel)); - - std::string opt = format("-D WAVE_SIZE=%d", wave_size); - openCLExecuteKernel(Context::getContext(), &imgproc_clahe, kernelName, globalThreads, localThreads, args, -1, -1, opt.c_str()); - } - } - - static void transform(const oclMat &src, oclMat &dst, const oclMat &lut, - const int tilesX, const int tilesY, const Size & tileSize) - { - cl_int2 tile_size; - tile_size.s[0] = tileSize.width; - tile_size.s[1] = tileSize.height; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&lut.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&lut.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows )); - args.push_back( std::make_pair( sizeof(cl_int2), (void *)&tile_size )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&tilesX )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&tilesY )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&lut.offset )); - - size_t localThreads[3] = { 32, 8, 1 }; - size_t globalThreads[3] = { src.cols, src.rows, 1 }; - - openCLExecuteKernel(Context::getContext(), &imgproc_clahe, "transform", globalThreads, localThreads, args, -1, -1); - } - } - - namespace - { - class CLAHE_Impl : public cv::CLAHE - { - public: - CLAHE_Impl(double clipLimit = 40.0, int tilesX = 8, int tilesY = 8); - - cv::AlgorithmInfo* info() const; - - void apply(cv::InputArray src, cv::OutputArray dst); - - void setClipLimit(double clipLimit); - double getClipLimit() const; - - void setTilesGridSize(cv::Size tileGridSize); - cv::Size getTilesGridSize() const; - - void collectGarbage(); - - private: - double clipLimit_; - int tilesX_; - int tilesY_; - - oclMat srcExt_; - oclMat lut_; - }; - - CLAHE_Impl::CLAHE_Impl(double clipLimit, int tilesX, int tilesY) : - clipLimit_(clipLimit), tilesX_(tilesX), tilesY_(tilesY) - { - } - - CV_INIT_ALGORITHM(CLAHE_Impl, "CLAHE_OCL", - obj.info()->addParam(obj, "clipLimit", obj.clipLimit_); - obj.info()->addParam(obj, "tilesX", obj.tilesX_); - obj.info()->addParam(obj, "tilesY", obj.tilesY_)) - - void CLAHE_Impl::apply(cv::InputArray src_raw, cv::OutputArray dst_raw) - { - oclMat& src = getOclMatRef(src_raw); - oclMat& dst = getOclMatRef(dst_raw); - CV_Assert( src.type() == CV_8UC1 ); - - dst.create( src.size(), src.type() ); - - const int histSize = 256; - - ensureSizeIsEnough(tilesX_ * tilesY_, histSize, CV_8UC1, lut_); - - cv::Size tileSize; - oclMat srcForLut; - - if (src.cols % tilesX_ == 0 && src.rows % tilesY_ == 0) - { - tileSize = cv::Size(src.cols / tilesX_, src.rows / tilesY_); - srcForLut = src; - } - else - { - ocl::copyMakeBorder(src, srcExt_, 0, tilesY_ - (src.rows % tilesY_), 0, - tilesX_ - (src.cols % tilesX_), BORDER_REFLECT_101, Scalar::all(0)); - - tileSize = Size(srcExt_.cols / tilesX_, srcExt_.rows / tilesY_); - srcForLut = srcExt_; - } - - const int tileSizeTotal = tileSize.area(); - const float lutScale = static_cast(histSize - 1) / tileSizeTotal; - - int clipLimit = 0; - if (clipLimit_ > 0.0) - { - clipLimit = static_cast(clipLimit_ * tileSizeTotal / histSize); - clipLimit = std::max(clipLimit, 1); - } - - clahe::calcLut(srcForLut, lut_, tilesX_, tilesY_, tileSize, clipLimit, lutScale); - clahe::transform(src, dst, lut_, tilesX_, tilesY_, tileSize); - } - - void CLAHE_Impl::setClipLimit(double clipLimit) - { - clipLimit_ = clipLimit; - } - - double CLAHE_Impl::getClipLimit() const - { - return clipLimit_; - } - - void CLAHE_Impl::setTilesGridSize(cv::Size tileGridSize) - { - tilesX_ = tileGridSize.width; - tilesY_ = tileGridSize.height; - } - - cv::Size CLAHE_Impl::getTilesGridSize() const - { - return cv::Size(tilesX_, tilesY_); - } - - void CLAHE_Impl::collectGarbage() - { - srcExt_.release(); - lut_.release(); - } - } - - cv::Ptr createCLAHE(double clipLimit, cv::Size tileGridSize) - { - return makePtr(clipLimit, tileGridSize.width, tileGridSize.height); - } - - //////////////////////////////////bilateralFilter//////////////////////////////////////////////////// - - static void oclbilateralFilter_8u( const oclMat &src, oclMat &dst, int d, - double sigma_color, double sigma_space, - int borderType ) - { - int cn = src.channels(); - int i, j, maxk, radius; - - CV_Assert( (src.channels() == 1 || src.channels() == 3) && - src.type() == dst.type() && src.size() == dst.size() && - src.data != dst.data ); - - if ( sigma_color <= 0 ) - sigma_color = 1; - if ( sigma_space <= 0 ) - sigma_space = 1; - - double gauss_color_coeff = -0.5 / (sigma_color * sigma_color); - double gauss_space_coeff = -0.5 / (sigma_space * sigma_space); - - if ( d <= 0 ) - radius = cvRound(sigma_space * 1.5); - else - radius = d / 2; - radius = MAX(radius, 1); - d = radius * 2 + 1; - - oclMat temp; - copyMakeBorder( src, temp, radius, radius, radius, radius, borderType ); - - std::vector _color_weight(cn * 256); - std::vector _space_weight(d * d); - std::vector _space_ofs(d * d); - float *color_weight = &_color_weight[0]; - float *space_weight = &_space_weight[0]; - int *space_ofs = &_space_ofs[0]; - - int dst_step_in_pixel = dst.step / dst.elemSize(); - int dst_offset_in_pixel = dst.offset / dst.elemSize(); - int temp_step_in_pixel = temp.step / temp.elemSize(); - - // initialize color-related bilateral filter coefficients - for( i = 0; i < 256 * cn; i++ ) - color_weight[i] = (float)std::exp(i * i * gauss_color_coeff); - - // initialize space-related bilateral filter coefficients - for( i = -radius, maxk = 0; i <= radius; i++ ) - for( j = -radius; j <= radius; j++ ) - { - double r = std::sqrt((double)i * i + (double)j * j); - if ( r > radius ) - continue; - space_weight[maxk] = (float)std::exp(r * r * gauss_space_coeff); - space_ofs[maxk++] = (int)(i * temp_step_in_pixel + j); - } - - oclMat oclcolor_weight(1, cn * 256, CV_32FC1, color_weight); - oclMat oclspace_weight(1, d * d, CV_32FC1, space_weight); - oclMat oclspace_ofs(1, d * d, CV_32SC1, space_ofs); - - String kernelName = "bilateral"; -#ifdef ANDROID - size_t localThreads[3] = { 16, 8, 1 }; -#else - size_t localThreads[3] = { 16, 16, 1 }; -#endif - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - - if ((dst.type() == CV_8UC1) && ((dst.offset & 3) == 0) && ((dst.cols & 3) == 0)) - { - kernelName = "bilateral2"; - globalThreads[0] = dst.cols >> 2; - } - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&temp.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&maxk )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&radius )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_step_in_pixel )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_offset_in_pixel )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&temp_step_in_pixel )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&temp.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&temp.cols )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&oclcolor_weight.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&oclspace_weight.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&oclspace_ofs.data )); - - openCLExecuteKernel(src.clCxt, &imgproc_bilateral, kernelName, globalThreads, localThreads, args, dst.oclchannels(), dst.depth()); - } - - void bilateralFilter(const oclMat &src, oclMat &dst, int radius, double sigmaclr, double sigmaspc, int borderType) - { - dst.create( src.size(), src.type() ); - if ( src.depth() == CV_8U ) - oclbilateralFilter_8u( src, dst, radius, sigmaclr, sigmaspc, borderType ); - else - CV_Error(Error::StsUnsupportedFormat, "Bilateral filtering is only implemented for CV_8U images"); - } - - } -} -//////////////////////////////////mulSpectrums//////////////////////////////////////////////////// -void cv::ocl::mulSpectrums(const oclMat &a, const oclMat &b, oclMat &c, int /*flags*/, float scale, bool conjB) -{ - CV_Assert(a.type() == CV_32FC2); - CV_Assert(b.type() == CV_32FC2); - - c.create(a.size(), CV_32FC2); - - size_t lt[3] = { 16, 16, 1 }; - size_t gt[3] = { a.cols, a.rows, 1 }; - - String kernelName = conjB ? "mulAndScaleSpectrumsKernel_CONJ":"mulAndScaleSpectrumsKernel"; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&a.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&b.data )); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&scale)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&c.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&a.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&a.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&a.step )); - - Context *clCxt = Context::getContext(); - openCLExecuteKernel(clCxt, &imgproc_mulAndScaleSpectrums, kernelName, gt, lt, args, -1, -1); -} -//////////////////////////////////convolve//////////////////////////////////////////////////// -// ported from CUDA module -void cv::ocl::ConvolveBuf::create(Size image_size, Size templ_size) -{ - result_size = Size(image_size.width - templ_size.width + 1, - image_size.height - templ_size.height + 1); - - block_size = user_block_size; - if (user_block_size.width == 0 || user_block_size.height == 0) - block_size = estimateBlockSize(result_size, templ_size); - - dft_size.width = 1 << int(ceil(std::log(block_size.width + templ_size.width - 1.) / std::log(2.))); - dft_size.height = 1 << int(ceil(std::log(block_size.height + templ_size.height - 1.) / std::log(2.))); - - // CUFFT has hard-coded kernels for power-of-2 sizes (up to 8192), - // see CUDA Toolkit 4.1 CUFFT Library Programming Guide - //if (dft_size.width > 8192) - dft_size.width = getOptimalDFTSize(block_size.width + templ_size.width - 1.); - //if (dft_size.height > 8192) - dft_size.height = getOptimalDFTSize(block_size.height + templ_size.height - 1.); - - // To avoid wasting time doing small DFTs - dft_size.width = std::max(dft_size.width, 512); - dft_size.height = std::max(dft_size.height, 512); - - image_block.create(dft_size, CV_32F); - templ_block.create(dft_size, CV_32F); - result_data.create(dft_size, CV_32F); - - //spect_len = dft_size.height * (dft_size.width / 2 + 1); - image_spect.create(dft_size.height, dft_size.width / 2 + 1, CV_32FC2); - templ_spect.create(dft_size.height, dft_size.width / 2 + 1, CV_32FC2); - result_spect.create(dft_size.height, dft_size.width / 2 + 1, CV_32FC2); - - // Use maximum result matrix block size for the estimated DFT block size - block_size.width = std::min(dft_size.width - templ_size.width + 1, result_size.width); - block_size.height = std::min(dft_size.height - templ_size.height + 1, result_size.height); -} - -Size cv::ocl::ConvolveBuf::estimateBlockSize(Size result_size, Size /*templ_size*/) -{ - int width = (result_size.width + 2) / 3; - int height = (result_size.height + 2) / 3; - width = std::min(width, result_size.width); - height = std::min(height, result_size.height); - return Size(width, height); -} - -static void convolve_run_fft(const oclMat &image, const oclMat &templ, oclMat &result, bool ccorr, ConvolveBuf& buf) -{ -#if defined HAVE_CLAMDFFT - CV_Assert(image.type() == CV_32F); - CV_Assert(templ.type() == CV_32F); - - buf.create(image.size(), templ.size()); - result.create(buf.result_size, CV_32F); - - Size& block_size = buf.block_size; - Size& dft_size = buf.dft_size; - - oclMat& image_block = buf.image_block; - oclMat& templ_block = buf.templ_block; - oclMat& result_data = buf.result_data; - - oclMat& image_spect = buf.image_spect; - oclMat& templ_spect = buf.templ_spect; - oclMat& result_spect = buf.result_spect; - - oclMat templ_roi = templ; - copyMakeBorder(templ_roi, templ_block, 0, templ_block.rows - templ_roi.rows, 0, - templ_block.cols - templ_roi.cols, 0, Scalar()); - - cv::ocl::dft(templ_block, templ_spect, dft_size); - - // Process all blocks of the result matrix - for (int y = 0; y < result.rows; y += block_size.height) - { - for (int x = 0; x < result.cols; x += block_size.width) - { - Size image_roi_size(std::min(x + dft_size.width, image.cols) - x, - std::min(y + dft_size.height, image.rows) - y); - Rect roi0(x, y, image_roi_size.width, image_roi_size.height); - - oclMat image_roi(image, roi0); - - copyMakeBorder(image_roi, image_block, 0, image_block.rows - image_roi.rows, - 0, image_block.cols - image_roi.cols, 0, Scalar()); - - cv::ocl::dft(image_block, image_spect, dft_size); - - mulSpectrums(image_spect, templ_spect, result_spect, 0, - 1.f / dft_size.area(), ccorr); - - cv::ocl::dft(result_spect, result_data, dft_size, cv::DFT_INVERSE | cv::DFT_REAL_OUTPUT); - - Size result_roi_size(std::min(x + block_size.width, result.cols) - x, - std::min(y + block_size.height, result.rows) - y); - - Rect roi1(x, y, result_roi_size.width, result_roi_size.height); - Rect roi2(0, 0, result_roi_size.width, result_roi_size.height); - - oclMat result_roi(result, roi1); - oclMat result_block(result_data, roi2); - - result_block.copyTo(result_roi); - } - } - -#else - CV_Error(Error::OpenCLNoAMDBlasFft, "OpenCL DFT is not implemented"); -#define UNUSED(x) (void)(x); - UNUSED(image) UNUSED(templ) UNUSED(result) UNUSED(ccorr) UNUSED(buf) -#undef UNUSED -#endif -} - -static void convolve_run(const oclMat &src, const oclMat &temp1, oclMat &dst, String kernelName, const cv::ocl::ProgramEntry* source) -{ - CV_Assert(src.depth() == CV_32FC1); - CV_Assert(temp1.depth() == CV_32F); - CV_Assert(temp1.cols <= 17 && temp1.rows <= 17); - - dst.create(src.size(), src.type()); - - CV_Assert(src.cols == dst.cols && src.rows == dst.rows); - CV_Assert(src.type() == dst.type()); - - size_t localThreads[3] = { 16, 16, 1 }; - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - - int src_step = src.step / src.elemSize(), src_offset = src.offset / src.elemSize(); - int dst_step = dst.step / dst.elemSize(), dst_offset = dst.offset / dst.elemSize(); - int temp1_step = temp1.step / temp1.elemSize(), temp1_offset = temp1.offset / temp1.elemSize(); - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&temp1.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&temp1_step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&temp1.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&temp1.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src_offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_offset )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&temp1_offset )); - - openCLExecuteKernel(src.clCxt, source, kernelName, globalThreads, localThreads, args, -1, dst.depth()); -} - -void cv::ocl::convolve(const oclMat &x, const oclMat &t, oclMat &y, bool ccorr) -{ - CV_Assert(x.depth() == CV_32F); - CV_Assert(t.depth() == CV_32F); - y.create(x.size(), x.type()); - String kernelName = "convolve"; - if(t.cols > 17 || t.rows > 17) - { - ConvolveBuf buf; - convolve_run_fft(x, t, y, ccorr, buf); - } - else - { - CV_Assert(ccorr == false); - convolve_run(x, t, y, kernelName, &imgproc_convolve); - } -} -void cv::ocl::convolve(const oclMat &image, const oclMat &templ, oclMat &result, bool ccorr, ConvolveBuf& buf) -{ - result.create(image.size(), image.type()); - convolve_run_fft(image, templ, result, ccorr, buf); -} diff --git a/modules/ocl/src/interpolate_frames.cpp b/modules/ocl/src/interpolate_frames.cpp deleted file mode 100644 index 47d6c837a..000000000 --- a/modules/ocl/src/interpolate_frames.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/*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 Comuter 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 -// Peng Xiao, pengxiao@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 urpose 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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -namespace cv -{ - namespace ocl - { - namespace interpolate - { - //The following are ported from NPP_staging.cu - // As it is not valid to do pointer offset operations on host for default oclMat's native cl_mem pointer, - // we may have to do this on kernel - void memsetKernel(float val, oclMat &img, int height, int offset); - void normalizeKernel(oclMat &buffer, int height, int factor_offset, int dst_offset); - void forwardWarpKernel(const oclMat &src, oclMat &buffer, const oclMat &u, const oclMat &v, const float time_scale, - int b_offset, int d_offset); // buffer, dst offset - - //OpenCL conversion of nppiStVectorWarp_PSF2x2_32f_C1 - void vectorWarp(const oclMat &src, const oclMat &u, const oclMat &v, - oclMat &buffer, int buf_offset, float timeScale, int dst_offset); - //OpenCL conversion of BlendFrames - void blendFrames(const oclMat &frame0, const oclMat &frame1, const oclMat &buffer, - float pos, oclMat &newFrame, cl_mem &, cl_mem &); - - // bind a buffer to an image - void bindImgTex(const oclMat &img, cl_mem &tex); - } - } -} - -void cv::ocl::interpolateFrames(const oclMat &frame0, const oclMat &frame1, - const oclMat &fu, const oclMat &fv, - const oclMat &bu, const oclMat &bv, - float pos, oclMat &newFrame, oclMat &buf) -{ - CV_Assert(frame0.type() == CV_32FC1); - CV_Assert(frame1.size() == frame0.size() && frame1.type() == frame0.type()); - CV_Assert(fu.size() == frame0.size() && fu.type() == frame0.type()); - CV_Assert(fv.size() == frame0.size() && fv.type() == frame0.type()); - CV_Assert(bu.size() == frame0.size() && bu.type() == frame0.type()); - CV_Assert(bv.size() == frame0.size() && bv.type() == frame0.type()); - - newFrame.create(frame0.size(), frame0.type()); - - buf.create(6 * frame0.rows, frame0.cols, CV_32FC1); - buf.setTo(Scalar::all(0)); - - size_t step = frame0.step; - - CV_Assert(frame1.step == step && fu.step == step && fv.step == step && bu.step == step && bv.step == step && newFrame.step == step && buf.step == step); - cl_mem tex_src0 = 0, tex_src1 = 0; - - // warp flow - using namespace interpolate; - - bindImgTex(frame0, tex_src0); - bindImgTex(frame1, tex_src1); - - // CUDA Offsets - enum - { - cov0 = 0, - cov1, - fwdU, - fwdV, - bwdU, - bwdV - }; - - vectorWarp(fu, fu, fv, buf, cov0, pos, fwdU); - vectorWarp(fv, fu, fv, buf, cov0, pos, fwdV); - vectorWarp(bu, bu, bv, buf, cov1, 1.0f - pos, bwdU); - vectorWarp(bv, bu, bv, buf, cov1, 1.0f - pos, bwdU); - - blendFrames(frame0, frame1, buf, pos, newFrame, tex_src0, tex_src1); - - openCLFree(tex_src0); - openCLFree(tex_src1); -} - -void interpolate::memsetKernel(float val, oclMat &img, int height, int offset) -{ - Context *clCxt = Context::getContext(); - String kernelName = "memsetKernel"; - std::vector< std::pair > args; - int step = img.step / sizeof(float); - offset = step * height * offset; - - args.push_back( std::make_pair( sizeof(cl_float), (void *)&val)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&img.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&img.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&height)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&offset)); - - size_t globalThreads[3] = {img.cols, height, 1}; - size_t localThreads[3] = {16, 16, 1}; - openCLExecuteKernel(clCxt, &interpolate_frames, kernelName, globalThreads, localThreads, args, -1, -1); -} -void interpolate::normalizeKernel(oclMat &buffer, int height, int factor_offset, int dst_offset) -{ - Context *clCxt = Context::getContext(); - String kernelName = "normalizeKernel"; - std::vector< std::pair > args; - int step = buffer.step / sizeof(float); - factor_offset = step * height * factor_offset; - dst_offset = step * height * dst_offset; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buffer.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buffer.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&height)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&factor_offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_offset)); - - size_t globalThreads[3] = {buffer.cols, height, 1}; - size_t localThreads[3] = {16, 16, 1}; - openCLExecuteKernel(clCxt, &interpolate_frames, kernelName, globalThreads, localThreads, args, -1, -1); -} - -void interpolate::forwardWarpKernel(const oclMat &src, oclMat &buffer, const oclMat &u, const oclMat &v, const float time_scale, - int b_offset, int d_offset) -{ - Context *clCxt = Context::getContext(); - String kernelName = "forwardWarpKernel"; - std::vector< std::pair > args; - int f_step = u.step / sizeof(float); // flow step - int b_step = buffer.step / sizeof(float); - - b_offset = b_step * src.rows * b_offset; - d_offset = b_step * src.rows * d_offset; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buffer.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&u.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&v.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&f_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&b_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&b_offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&d_offset)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&time_scale)); - - size_t globalThreads[3] = {src.cols, src.rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - openCLExecuteKernel(clCxt, &interpolate_frames, kernelName, globalThreads, localThreads, args, -1, -1); -} - -void interpolate::vectorWarp(const oclMat &src, const oclMat &u, const oclMat &v, - oclMat &buffer, int b_offset, float timeScale, int d_offset) -{ - memsetKernel(0, buffer, src.rows, b_offset); - forwardWarpKernel(src, buffer, u, v, timeScale, b_offset, d_offset); - normalizeKernel(buffer, src.rows, b_offset, d_offset); -} - -void interpolate::blendFrames(const oclMat &frame0, const oclMat &/*frame1*/, const oclMat &buffer, float pos, oclMat &newFrame, cl_mem &tex_src0, cl_mem &tex_src1) -{ - int step = buffer.step / sizeof(float); - - Context *clCxt = Context::getContext(); - String kernelName = "blendFramesKernel"; - std::vector< std::pair > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&tex_src0)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&tex_src1)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buffer.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&newFrame.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&frame0.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&frame0.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&step)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&pos)); - - size_t globalThreads[3] = {frame0.cols, frame0.rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - openCLExecuteKernel(clCxt, &interpolate_frames, kernelName, globalThreads, localThreads, args, -1, -1); -} - -void interpolate::bindImgTex(const oclMat &img, cl_mem &texture) -{ - if(texture) - { - openCLFree(texture); - } - texture = bindTexture(img); -} diff --git a/modules/ocl/src/kalman.cpp b/modules/ocl/src/kalman.cpp deleted file mode 100644 index 5a133a7b1..000000000 --- a/modules/ocl/src/kalman.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/*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 -// 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 "precomp.hpp" - -using namespace cv; -using namespace cv::ocl; - -KalmanFilter::KalmanFilter() -{ - -} - -KalmanFilter::KalmanFilter(int dynamParams, int measureParams, int controlParams, int type) -{ - init(dynamParams, measureParams, controlParams, type); -} - -void KalmanFilter::init(int DP, int MP, int CP, int type) -{ - CV_Assert( DP > 0 && MP > 0 ); - CV_Assert( type == CV_32F || type == CV_64F ); - CP = cv::max(CP, 0); - - statePre.create(DP, 1, type); - statePre.setTo(Scalar::all(0)); - - statePost.create(DP, 1, type); - statePost.setTo(Scalar::all(0)); - - transitionMatrix.create(DP, DP, type); - setIdentity(transitionMatrix, 1); - - processNoiseCov.create(DP, DP, type); - setIdentity(processNoiseCov, 1); - - measurementNoiseCov.create(MP, MP, type); - setIdentity(measurementNoiseCov, 1); - - measurementMatrix.create(MP, DP, type); - measurementMatrix.setTo(Scalar::all(0)); - - errorCovPre.create(DP, DP, type); - errorCovPre.setTo(Scalar::all(0)); - - errorCovPost.create(DP, DP, type); - errorCovPost.setTo(Scalar::all(0)); - - gain.create(DP, MP, type); - gain.setTo(Scalar::all(0)); - - if( CP > 0 ) - { - controlMatrix.create(DP, CP, type); - controlMatrix.setTo(Scalar::all(0)); - } - else - controlMatrix.release(); - - temp1.create(DP, DP, type); - temp2.create(MP, DP, type); - temp3.create(MP, MP, type); - temp4.create(MP, DP, type); - temp5.create(MP, 1, type); -} - -CV_EXPORTS const oclMat& KalmanFilter::predict(const oclMat& control) -{ - gemm(transitionMatrix, statePost, 1, oclMat(), 0, statePre); - oclMat temp; - - if(control.data) - gemm(controlMatrix, control, 1, statePre, 1, statePre); - gemm(transitionMatrix, errorCovPost, 1, oclMat(), 0, temp1); - gemm(temp1, transitionMatrix, 1, processNoiseCov, 1, errorCovPre, GEMM_2_T); - statePre.copyTo(statePost); - return statePre; -} - -CV_EXPORTS const oclMat& KalmanFilter::correct(const oclMat& measurement) -{ - CV_Assert(measurement.empty() == false); - gemm(measurementMatrix, errorCovPre, 1, oclMat(), 0, temp2); - gemm(temp2, measurementMatrix, 1, measurementNoiseCov, 1, temp3, GEMM_2_T); - Mat temp; - solve(Mat(temp3), Mat(temp2), temp, DECOMP_SVD); - temp4.upload(temp); - gain = temp4.t(); - gemm(measurementMatrix, statePre, -1, measurement, 1, temp5); - gemm(gain, temp5, 1, statePre, 1, statePost); - gemm(gain, temp2, -1, errorCovPre, 1, errorCovPost); - return statePost; -} diff --git a/modules/ocl/src/kmeans.cpp b/modules/ocl/src/kmeans.cpp deleted file mode 100644 index 9a5b1931d..000000000 --- a/modules/ocl/src/kmeans.cpp +++ /dev/null @@ -1,451 +0,0 @@ -/*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 -// Xiaopeng Fu, fuxiaopeng2222@163.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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -static void generateRandomCenter(const std::vector& box, float* center, RNG& rng) -{ - size_t j, dims = box.size(); - float margin = 1.f/dims; - for( j = 0; j < dims; j++ ) - center[j] = ((float)rng*(1.f+margin*2.f)-margin)*(box[j][1] - box[j][0]) + box[j][0]; -} - -// This class is copied from matrix.cpp in core module. -class KMeansPPDistanceComputer : public ParallelLoopBody -{ -public: - KMeansPPDistanceComputer( float *_tdist2, - const float *_data, - const float *_dist, - int _dims, - size_t _step, - size_t _stepci ) - : tdist2(_tdist2), - data(_data), - dist(_dist), - dims(_dims), - step(_step), - stepci(_stepci) { } - - void operator()( const cv::Range& range ) const - { - const int begin = range.start; - const int end = range.end; - - for ( int i = begin; i _centers(K); - int* centers = &_centers[0]; - std::vector _dist(N*3); - float* dist = &_dist[0], *tdist = dist + N, *tdist2 = tdist + N; - double sum0 = 0; - - centers[0] = (unsigned)rng % N; - - for( i = 0; i < N; i++ ) - { - dist[i] = normL2Sqr_(data + step*i, data + step*centers[0], dims); - sum0 += dist[i]; - } - - for( k = 1; k < K; k++ ) - { - double bestSum = DBL_MAX; - int bestCenter = -1; - - for( j = 0; j < trials; j++ ) - { - double p = (double)rng*sum0, s = 0; - for( i = 0; i < N-1; i++ ) - if( (p -= dist[i]) <= 0 ) - break; - int ci = i; - - parallel_for_(Range(0, N), - KMeansPPDistanceComputer(tdist2, data, dist, dims, step, step*ci)); - for( i = 0; i < N; i++ ) - { - s += tdist2[i]; - } - - if( s < bestSum ) - { - bestSum = s; - bestCenter = ci; - std::swap(tdist, tdist2); - } - } - centers[k] = bestCenter; - sum0 = bestSum; - std::swap(dist, tdist); - } - - for( k = 0; k < K; k++ ) - { - const float* src = data + step*centers[k]; - float* dst = _out_centers.ptr(k); - for( j = 0; j < dims; j++ ) - dst[j] = src[j]; - } -} - -void cv::ocl::distanceToCenters(const oclMat &src, const oclMat ¢ers, Mat &dists, Mat &labels, int distType) -{ - CV_Assert(src.cols * src.channels() == centers.cols * centers.channels()); - CV_Assert(src.depth() == CV_32F && centers.depth() == CV_32F); - CV_Assert(distType == NORM_L1 || distType == NORM_L2SQR); - - dists.create(src.rows, 1, CV_32FC1); - labels.create(src.rows, 1, CV_32SC1); - - std::stringstream build_opt_ss; - build_opt_ss << (distType == NORM_L1 ? "-D L1_DIST" : "-D L2SQR_DIST"); - - int src_step = src.step / src.elemSize1(); - int centers_step = centers.step / centers.elemSize1(); - int feature_width = centers.cols * centers.oclchannels(); - int src_offset = src.offset / src.elemSize1(); - int centers_offset = centers.offset / centers.elemSize1(); - - int all_dist_count = src.rows * centers.rows; - oclMat all_dist(1, all_dist_count, CV_32FC1); - - std::vector > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&src.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)¢ers.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&all_dist.data)); - - args.push_back(std::make_pair(sizeof(cl_int), (void *)&feature_width)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)¢ers_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)¢ers.rows)); - - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src_offset)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)¢ers_offset)); - - size_t globalThreads[3] = { all_dist_count, 1, 1 }; - - openCLExecuteKernel(Context::getContext(), &kmeans_kernel, - "distanceToCenters", globalThreads, NULL, args, -1, -1, build_opt_ss.str().c_str()); - - Mat all_dist_cpu; - all_dist.download(all_dist_cpu); - - for (int i = 0; i < src.rows; ++i) - { - Point p; - double minVal; - - Rect roi(i * centers.rows, 0, centers.rows, 1); - Mat hdr(all_dist_cpu, roi); - - cv::minMaxLoc(hdr, &minVal, NULL, &p); - - dists.at(i, 0) = static_cast(minVal); - labels.at(i, 0) = p.x; - } -} - -///////////////////////////////////k - means ///////////////////////////////////////////////////////// - -double cv::ocl::kmeans(const oclMat &_src, int K, oclMat &_bestLabels, - TermCriteria criteria, int attempts, int flags, oclMat &_centers) -{ - const int SPP_TRIALS = 3; - bool isrow = _src.rows == 1 && _src.oclchannels() > 1; - int N = !isrow ? _src.rows : _src.cols; - int dims = (!isrow ? _src.cols : 1) * _src.oclchannels(); - int type = _src.depth(); - - attempts = std::max(attempts, 1); - CV_Assert(type == CV_32F && K > 0 ); - CV_Assert( N >= K ); - - Mat _labels; - if( flags & KMEANS_USE_INITIAL_LABELS ) - { - CV_Assert( (_bestLabels.cols == 1 || _bestLabels.rows == 1) && - _bestLabels.cols * _bestLabels.rows == N && - _bestLabels.type() == CV_32S ); - _bestLabels.download(_labels); - } - else - { - if( !((_bestLabels.cols == 1 || _bestLabels.rows == 1) && - _bestLabels.cols * _bestLabels.rows == N && - _bestLabels.type() == CV_32S && - _bestLabels.isContinuous())) - _bestLabels.create(N, 1, CV_32S); - _labels.create(_bestLabels.size(), _bestLabels.type()); - } - int* labels = _labels.ptr(); - - Mat data; - _src.download(data); - Mat centers(K, dims, type), old_centers(K, dims, type), temp(1, dims, type); - std::vector counters(K); - std::vector _box(dims); - Vec2f* box = &_box[0]; - double best_compactness = DBL_MAX, compactness = 0; - RNG& rng = theRNG(); - int a, iter, i, j, k; - - if( criteria.type & TermCriteria::EPS ) - criteria.epsilon = std::max(criteria.epsilon, 0.); - else - criteria.epsilon = FLT_EPSILON; - criteria.epsilon *= criteria.epsilon; - - if( criteria.type & TermCriteria::COUNT ) - criteria.maxCount = std::min(std::max(criteria.maxCount, 2), 100); - else - criteria.maxCount = 100; - - if( K == 1 ) - { - attempts = 1; - criteria.maxCount = 2; - } - - const float* sample = data.ptr(); - for( j = 0; j < dims; j++ ) - box[j] = Vec2f(sample[j], sample[j]); - - for( i = 1; i < N; i++ ) - { - sample = data.ptr(i); - for( j = 0; j < dims; j++ ) - { - float v = sample[j]; - box[j][0] = std::min(box[j][0], v); - box[j][1] = std::max(box[j][1], v); - } - } - - for( a = 0; a < attempts; a++ ) - { - double max_center_shift = DBL_MAX; - for( iter = 0;; ) - { - swap(centers, old_centers); - - if( iter == 0 && (a > 0 || !(flags & KMEANS_USE_INITIAL_LABELS)) ) - { - if( flags & KMEANS_PP_CENTERS ) - generateCentersPP(data, centers, K, rng, SPP_TRIALS); - else - { - for( k = 0; k < K; k++ ) - generateRandomCenter(_box, centers.ptr(k), rng); - } - } - else - { - if( iter == 0 && a == 0 && (flags & KMEANS_USE_INITIAL_LABELS) ) - { - for( i = 0; i < N; i++ ) - CV_Assert( (unsigned)labels[i] < (unsigned)K ); - } - - // compute centers - centers = Scalar(0); - for( k = 0; k < K; k++ ) - counters[k] = 0; - - for( i = 0; i < N; i++ ) - { - sample = data.ptr(i); - k = labels[i]; - float* center = centers.ptr(k); - j=0; -#if CV_ENABLE_UNROLLED - for(; j <= dims - 4; j += 4 ) - { - float t0 = center[j] + sample[j]; - float t1 = center[j+1] + sample[j+1]; - - center[j] = t0; - center[j+1] = t1; - - t0 = center[j+2] + sample[j+2]; - t1 = center[j+3] + sample[j+3]; - - center[j+2] = t0; - center[j+3] = t1; - } -#endif - for( ; j < dims; j++ ) - center[j] += sample[j]; - counters[k]++; - } - - if( iter > 0 ) - max_center_shift = 0; - - for( k = 0; k < K; k++ ) - { - if( counters[k] != 0 ) - continue; - - // if some cluster appeared to be empty then: - // 1. find the biggest cluster - // 2. find the farthest from the center point in the biggest cluster - // 3. exclude the farthest point from the biggest cluster and form a new 1-point cluster. - int max_k = 0; - for( int k1 = 1; k1 < K; k1++ ) - { - if( counters[max_k] < counters[k1] ) - max_k = k1; - } - - double max_dist = 0; - int farthest_i = -1; - float* new_center = centers.ptr(k); - float* old_center = centers.ptr(max_k); - float* _old_center = temp.ptr(); // normalized - float scale = 1.f/counters[max_k]; - for( j = 0; j < dims; j++ ) - _old_center[j] = old_center[j]*scale; - - for( i = 0; i < N; i++ ) - { - if( labels[i] != max_k ) - continue; - sample = data.ptr(i); - double dist = normL2Sqr_(sample, _old_center, dims); - - if( max_dist <= dist ) - { - max_dist = dist; - farthest_i = i; - } - } - - counters[max_k]--; - counters[k]++; - labels[farthest_i] = k; - sample = data.ptr(farthest_i); - - for( j = 0; j < dims; j++ ) - { - old_center[j] -= sample[j]; - new_center[j] += sample[j]; - } - } - - for( k = 0; k < K; k++ ) - { - float* center = centers.ptr(k); - CV_Assert( counters[k] != 0 ); - - float scale = 1.f/counters[k]; - for( j = 0; j < dims; j++ ) - center[j] *= scale; - - if( iter > 0 ) - { - double dist = 0; - const float* old_center = old_centers.ptr(k); - for( j = 0; j < dims; j++ ) - { - double t = center[j] - old_center[j]; - dist += t*t; - } - max_center_shift = std::max(max_center_shift, dist); - } - } - } - - if( ++iter == MAX(criteria.maxCount, 2) || max_center_shift <= criteria.epsilon ) - break; - - // assign labels - Mat dists(1, N, CV_64F); - _centers.upload(centers); - distanceToCenters(_src, _centers, dists, _labels); - _bestLabels.upload(_labels); - - float* dist = dists.ptr(0); - compactness = 0; - for( i = 0; i < N; i++ ) - compactness += (double)dist[i]; - } - - if( compactness < best_compactness ) - best_compactness = compactness; - } - - return best_compactness; -} diff --git a/modules/ocl/src/knearest.cpp b/modules/ocl/src/knearest.cpp deleted file mode 100644 index 143e7aa7a..000000000 --- a/modules/ocl/src/knearest.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/*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, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// 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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -KNearestNeighbour::KNearestNeighbour() -{ - clear(); -} - -KNearestNeighbour::~KNearestNeighbour() -{ - clear(); - samples_ocl.release(); -} - -void KNearestNeighbour::clear() -{ - CvKNearest::clear(); -} - -bool KNearestNeighbour::train(const Mat& trainData, Mat& labels, Mat& sampleIdx, - bool isRegression, int _max_k, bool updateBase) -{ - max_k = _max_k; - bool cv_knn_train = CvKNearest::train(trainData, labels, sampleIdx, isRegression, max_k, updateBase); - - CvVectors* s = CvKNearest::samples; - - cv::Mat samples_mat(s->count, CvKNearest::var_count + 1, s->type); - - float* s1 = (float*)(s + 1); - for(int i = 0; i < s->count; i++) - { - float* t1 = s->data.fl[i]; - for(int j = 0; j < CvKNearest::var_count; j++) - { - Point pos(j, i); - samples_mat.at(pos) = t1[j]; - } - - Point pos_label(CvKNearest::var_count, i); - samples_mat.at(pos_label) = s1[i]; - } - - samples_ocl = samples_mat; - return cv_knn_train; -} - -void KNearestNeighbour::find_nearest(const oclMat& samples, int k, oclMat& lables) -{ - CV_Assert(!samples_ocl.empty()); - lables.create(samples.rows, 1, CV_32FC1); - - CV_Assert(samples.cols == CvKNearest::var_count); - CV_Assert(samples.type() == CV_32FC1); - CV_Assert(k >= 1 && k <= max_k); - - int k1 = KNearest::get_sample_count(); - k1 = MIN( k1, k ); - - String kernel_name = "knn_find_nearest"; - cl_ulong local_memory_size = (cl_ulong)Context::getContext()->getDeviceInfo().localMemorySize; - int nThreads = local_memory_size / (2 * k * 4); - if(nThreads >= 256) - nThreads = 256; - - int smem_size = nThreads * k * 4 * 2; - size_t local_thread[] = {1, nThreads, 1}; - size_t global_thread[] = {1, samples.rows, 1}; - - char build_option[50]; - if(!Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - { - sprintf(build_option, " "); - }else - sprintf(build_option, "-D DOUBLE_SUPPORT"); - - std::vector< std::pair > args; - - int samples_ocl_step = samples_ocl.step/samples_ocl.elemSize(); - int samples_step = samples.step/samples.elemSize(); - int lables_step = lables.step/lables.elemSize(); - - int _regression = 0; - if(CvKNearest::regression) - _regression = 1; - - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&samples.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&samples.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&samples.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&samples_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&k)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&samples_ocl.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&samples_ocl.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&samples_ocl_step)); - args.push_back(std::make_pair(sizeof(cl_mem), (void*)&lables.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&lables_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&_regression)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&k1)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&samples_ocl.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void*)&nThreads)); - args.push_back(std::make_pair(smem_size, (void*)NULL)); - openCLExecuteKernel(Context::getContext(), &knearest, kernel_name, global_thread, local_thread, args, -1, -1, build_option); -} \ No newline at end of file diff --git a/modules/ocl/src/match_template.cpp b/modules/ocl/src/match_template.cpp deleted file mode 100644 index c95ad8421..000000000 --- a/modules/ocl/src/match_template.cpp +++ /dev/null @@ -1,570 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -namespace cv -{ - namespace ocl - { - void matchTemplate_SQDIFF( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf &buf); - - void matchTemplate_SQDIFF_NORMED( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf &buf); - - void convolve_32F( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf &buf); - - void matchTemplate_CCORR( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf &buf); - - void matchTemplate_CCORR_NORMED( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf &buf); - - void matchTemplate_CCOFF( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf &buf); - - void matchTemplate_CCOFF_NORMED( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf &buf); - - - void matchTemplateNaive_SQDIFF( - const oclMat &image, const oclMat &templ, oclMat &result, int cn); - - void matchTemplateNaive_CCORR( - const oclMat &image, const oclMat &templ, oclMat &result, int cn); - - void extractFirstChannel_32F( - const oclMat &image, oclMat &result); - - // Evaluates optimal template's area threshold. If - // template's area is less than the threshold, we use naive match - // template version, otherwise FFT-based (if available) - static bool useNaive(int method, int depth, Size size) - { -#ifdef HAVE_CLAMDFFT - if (method == TM_SQDIFF && (depth == CV_32F || !Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE))) - { - return true; - } - else if(method == TM_CCORR || (method == TM_SQDIFF && depth == CV_8U)) - { - return size.height < 18 && size.width < 18; - } - else - return false; -#else -#define UNUSED(x) (void)(x); - UNUSED(method) UNUSED(depth) UNUSED(size) -#undef UNUSED - return true; -#endif - } - - ////////////////////////////////////////////////////////////////////// - // SQDIFF - void matchTemplate_SQDIFF( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf & buf) - { - result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); - if (useNaive(TM_SQDIFF, image.depth(), templ.size())) - { - matchTemplateNaive_SQDIFF(image, templ, result, image.oclchannels()); - return; - } - else - { - buf.image_sqsums.resize(1); - - // TODO, add double support for ocl::integral - // use CPU integral temporarily - Mat sums, sqsums; - cv::integral(Mat(image.reshape(1)), sums, sqsums); - buf.image_sqsums[0] = sqsums; - - unsigned long long templ_sqsum = (unsigned long long)sqrSum(templ.reshape(1))[0]; - matchTemplate_CCORR(image, templ, result, buf); - - //port CUDA's matchTemplatePrepared_SQDIFF_8U - Context *clCxt = image.clCxt; - String kernelName = "matchTemplate_Prepared_SQDIFF"; - std::vector< std::pair > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sqsums[0].data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&result.data)); - args.push_back( std::make_pair( sizeof(cl_ulong), (void *)&templ_sqsum)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sqsums[0].offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sqsums[0].step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.step)); - - size_t globalThreads[3] = {result.cols, result.rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - - const char * build_opt = image.oclchannels() == 4 ? "-D CN4" : ""; - openCLExecuteKernel(clCxt, &match_template, kernelName, globalThreads, localThreads, args, 1, CV_8U, build_opt); - } - } - - void matchTemplate_SQDIFF_NORMED( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf &buf) - { - matchTemplate_CCORR(image, templ, result, buf); - buf.image_sums.resize(1); - - integral(image.reshape(1), buf.image_sums[0]); - - unsigned long long templ_sqsum = (unsigned long long)sqrSum(templ.reshape(1))[0]; - - Context *clCxt = image.clCxt; - String kernelName = "matchTemplate_Prepared_SQDIFF_NORMED"; - std::vector< std::pair > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sums[0].data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&result.data)); - args.push_back( std::make_pair( sizeof(cl_ulong), (void *)&templ_sqsum)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sums[0].offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sums[0].step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.step)); - - size_t globalThreads[3] = {result.cols, result.rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - openCLExecuteKernel(clCxt, &match_template, kernelName, globalThreads, localThreads, args, 1, CV_8U); - } - - void matchTemplateNaive_SQDIFF( - const oclMat &image, const oclMat &templ, oclMat &result, int) - { - CV_Assert((image.depth() == CV_8U && templ.depth() == CV_8U ) - || ((image.depth() == CV_32F && templ.depth() == CV_32F) && result.depth() == CV_32F) - ); - CV_Assert(image.oclchannels() == templ.oclchannels() && (image.oclchannels() == 1 || image.oclchannels() == 4) && result.oclchannels() == 1); - CV_Assert(result.rows == image.rows - templ.rows + 1 && result.cols == image.cols - templ.cols + 1); - - Context *clCxt = image.clCxt; - String kernelName = "matchTemplate_Naive_SQDIFF"; - - std::vector< std::pair > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&image.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&templ.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&result.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.step)); - - size_t globalThreads[3] = {result.cols, result.rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - openCLExecuteKernel(clCxt, &match_template, kernelName, globalThreads, localThreads, args, image.oclchannels(), image.depth()); - } - - ////////////////////////////////////////////////////////////////////// - // CCORR - void convolve_32F( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf &buf) - { - ConvolveBuf convolve_buf; - convolve_buf.user_block_size = buf.user_block_size; - if (image.oclchannels() == 1) - convolve(image, templ, result, true, convolve_buf); - else - { - oclMat result_; - convolve(image.reshape(1), templ.reshape(1), result_, true, convolve_buf); - extractFirstChannel_32F(result_, result); - } - } - - void matchTemplate_CCORR( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf &buf) - { - result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); - if (useNaive(TM_CCORR, image.depth(), templ.size())) - { - matchTemplateNaive_CCORR(image, templ, result, image.oclchannels()); - return; - } - else - { - if(image.depth() == CV_8U && templ.depth() == CV_8U) - { - image.convertTo(buf.imagef, CV_32F); - templ.convertTo(buf.templf, CV_32F); - convolve_32F(buf.imagef, buf.templf, result, buf); - } - else - { - convolve_32F(image, templ, result, buf); - } - } - } - - void matchTemplate_CCORR_NORMED( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf &buf) - { - cv::ocl::oclMat temp; - matchTemplate_CCORR(image, templ, result, buf); - buf.image_sums.resize(1); - buf.image_sqsums.resize(1); - integral(image.reshape(1), buf.image_sums[0], temp); - if(temp.depth() == CV_64F) - temp.convertTo(buf.image_sqsums[0], CV_32FC1); - else - buf.image_sqsums[0] = temp; - unsigned long long templ_sqsum = (unsigned long long)sqrSum(templ.reshape(1))[0]; - - Context *clCxt = image.clCxt; - String kernelName = "normalizeKernel"; - std::vector< std::pair > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sqsums[0].data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&result.data)); - args.push_back( std::make_pair( sizeof(cl_ulong), (void *)&templ_sqsum)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sqsums[0].offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sqsums[0].step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.step)); - - size_t globalThreads[3] = {result.cols, result.rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - openCLExecuteKernel(clCxt, &match_template, kernelName, globalThreads, localThreads, args, 1, CV_8U); - } - - void matchTemplateNaive_CCORR( - const oclMat &image, const oclMat &templ, oclMat &result, int) - { - CV_Assert((image.depth() == CV_8U && templ.depth() == CV_8U ) - || ((image.depth() == CV_32F && templ.depth() == CV_32F) && result.depth() == CV_32F) - ); - CV_Assert(image.oclchannels() == templ.oclchannels() && (image.oclchannels() == 1 || image.oclchannels() == 4) && result.oclchannels() == 1); - CV_Assert(result.rows == image.rows - templ.rows + 1 && result.cols == image.cols - templ.cols + 1); - - Context *clCxt = image.clCxt; - String kernelName = "matchTemplate_Naive_CCORR"; - - std::vector< std::pair > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&image.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&templ.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&result.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.step)); - - size_t globalThreads[3] = {result.cols, result.rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - openCLExecuteKernel(clCxt, &match_template, kernelName, globalThreads, localThreads, args, image.oclchannels(), image.depth()); - } - ////////////////////////////////////////////////////////////////////// - // CCOFF - void matchTemplate_CCOFF( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf &buf) - { - CV_Assert(image.depth() == CV_8U && templ.depth() == CV_8U); - - matchTemplate_CCORR(image, templ, result, buf); - - Context *clCxt = image.clCxt; - String kernelName; - - kernelName = "matchTemplate_Prepared_CCOFF"; - size_t globalThreads[3] = {result.cols, result.rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&result.data) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.rows) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.cols) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.rows) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.cols) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.rows) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.cols) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.step)); - Vec4f templ_sum = Vec4f::all(0); - // to be continued in the following section - if(image.oclchannels() == 1) - { - buf.image_sums.resize(1); - integral(image, buf.image_sums[0]); - - templ_sum[0] = (float)sum(templ)[0] / templ.size().area(); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sums[0].data) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sums[0].offset) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sums[0].step) ); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&templ_sum[0]) ); - } - else - { - - split(image, buf.images); - templ_sum = sum(templ) / templ.size().area(); - buf.image_sums.resize(buf.images.size()); - - - for(int i = 0; i < image.oclchannels(); i ++) - { - integral(buf.images[i], buf.image_sums[i]); - } - switch(image.oclchannels()) - { - case 4: - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sums[0].data) ); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sums[1].data) ); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sums[2].data) ); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sums[3].data) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sums[0].offset) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sums[0].step) ); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&templ_sum[0]) ); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&templ_sum[1]) ); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&templ_sum[2]) ); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&templ_sum[3]) ); - break; - default: - CV_Error(Error::StsBadArg, "matchTemplate: unsupported number of channels"); - break; - } - } - openCLExecuteKernel(clCxt, &match_template, kernelName, globalThreads, localThreads, args, image.oclchannels(), image.depth()); - } - - void matchTemplate_CCOFF_NORMED( - const oclMat &image, const oclMat &templ, oclMat &result, MatchTemplateBuf &buf) - { - image.convertTo(buf.imagef, CV_32F); - templ.convertTo(buf.templf, CV_32F); - - matchTemplate_CCORR(buf.imagef, buf.templf, result, buf); - float scale = 1.f / templ.size().area(); - - Context *clCxt = image.clCxt; - String kernelName; - - kernelName = "matchTemplate_Prepared_CCOFF_NORMED"; - size_t globalThreads[3] = {result.cols, result.rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&result.data) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.rows) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.cols) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.rows) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&templ.cols) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.rows) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.cols) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.step)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&scale) ); - - Vec4f templ_sum = Vec4f::all(0); - Vec4f templ_sqsum = Vec4f::all(0); - // to be continued in the following section - if(image.oclchannels() == 1) - { - buf.image_sums.resize(1); - buf.image_sqsums.resize(1); - cv::ocl::oclMat temp; - integral(image, buf.image_sums[0], temp); - if(temp.depth() == CV_64F) - temp.convertTo(buf.image_sqsums[0], CV_32FC1); - else - buf.image_sqsums[0] = temp; - - templ_sum[0] = (float)sum(templ)[0]; - - templ_sqsum[0] = sqrSum(templ)[0]; - - templ_sqsum[0] -= scale * templ_sum[0] * templ_sum[0]; - templ_sum[0] *= scale; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sums[0].data) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sums[0].offset) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sums[0].step) ); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sqsums[0].data) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sqsums[0].offset) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sqsums[0].step) ); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&templ_sum[0]) ); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&templ_sqsum[0]) ); - } - else - { - - split(image, buf.images); - templ_sum = sum(templ); - - templ_sqsum = sqrSum(templ); - - templ_sqsum -= scale * templ_sum * templ_sum; - - float templ_sqsum_sum = 0; - for(int i = 0; i < image.oclchannels(); i ++) - { - templ_sqsum_sum += templ_sqsum[i] - scale * templ_sum[i] * templ_sum[i]; - } - templ_sum *= scale; - buf.image_sums.resize(buf.images.size()); - buf.image_sqsums.resize(buf.images.size()); - cv::ocl::oclMat temp; - for(int i = 0; i < image.oclchannels(); i ++) - { - integral(buf.images[i], buf.image_sums[i], temp); - if(temp.depth() == CV_64F) - temp.convertTo(buf.image_sqsums[i], CV_32FC1); - else - buf.image_sqsums[i] = temp; - } - - switch(image.oclchannels()) - { - case 4: - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sums[0].data) ); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sums[1].data) ); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sums[2].data) ); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sums[3].data) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sums[0].offset) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sums[0].step) ); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sqsums[0].data) ); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sqsums[1].data) ); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sqsums[2].data) ); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&buf.image_sqsums[3].data) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sqsums[0].offset) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&buf.image_sqsums[0].step) ); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&templ_sum[0]) ); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&templ_sum[1]) ); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&templ_sum[2]) ); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&templ_sum[3]) ); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&templ_sqsum_sum) ); - break; - default: - CV_Error(Error::StsBadArg, "matchTemplate: unsupported number of channels"); - break; - } - } - openCLExecuteKernel(clCxt, &match_template, kernelName, globalThreads, localThreads, args, image.oclchannels(), image.depth()); - } - void extractFirstChannel_32F(const oclMat &image, oclMat &result) - { - Context *clCxt = image.clCxt; - String kernelName; - - kernelName = "extractFirstChannel"; - size_t globalThreads[3] = {result.cols, result.rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&image.data) ); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&result.data) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.rows) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.cols) ); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&image.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&result.step)); - - openCLExecuteKernel(clCxt, &match_template, kernelName, globalThreads, localThreads, args, -1, -1); - } - }/*ocl*/ -} /*cv*/ - -void cv::ocl::matchTemplate(const oclMat &image, const oclMat &templ, oclMat &result, int method) -{ - MatchTemplateBuf buf; - matchTemplate(image, templ, result, method, buf); -} -void cv::ocl::matchTemplate(const oclMat &image, const oclMat &templ, oclMat &result, int method, MatchTemplateBuf &buf) -{ - CV_Assert(image.type() == templ.type()); - CV_Assert(image.cols >= templ.cols && image.rows >= templ.rows); - - typedef void (*Caller)(const oclMat &, const oclMat &, oclMat &, MatchTemplateBuf &); - - const Caller callers[] = - { - ::matchTemplate_SQDIFF, ::matchTemplate_SQDIFF_NORMED, - ::matchTemplate_CCORR, ::matchTemplate_CCORR_NORMED, - ::matchTemplate_CCOFF, ::matchTemplate_CCOFF_NORMED - }; - - Caller caller = callers[method]; - CV_Assert(caller); - caller(image, templ, result, buf); -} diff --git a/modules/ocl/src/matrix_operations.cpp b/modules/ocl/src/matrix_operations.cpp deleted file mode 100644 index c028fb729..000000000 --- a/modules/ocl/src/matrix_operations.cpp +++ /dev/null @@ -1,632 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Yao Wang, bitwangyaoyao@gmail.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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -#define ALIGN 32 -#define GPU_MATRIX_MALLOC_STEP(step) (((step) + ALIGN - 1) / ALIGN) * ALIGN - -// helper routines -namespace cv -{ - namespace ocl - { - extern DevMemType gDeviceMemType; - extern DevMemRW gDeviceMemRW; - } -} - -//////////////////////////////////////////////////////////////////////// -// convert_C3C4 - -static void convert_C3C4(const cl_mem &src, oclMat &dst) -{ - Context *clCxt = dst.clCxt; - int pixel_end = dst.wholecols * dst.wholerows - 1; - int dstStep_in_pixel = dst.step1() / dst.oclchannels(); - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - std::string buildOptions = format("-D GENTYPE4=%s4", typeMap[dst.depth()]); - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.wholecols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.wholerows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dstStep_in_pixel)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&pixel_end)); - - size_t globalThreads[3] = { divUp(dst.wholecols * dst.wholerows, 4), 1, 1 }; - -#ifdef ANDROID - openCLExecuteKernel(clCxt, &convertC3C4, "convertC3C4", globalThreads, NULL, - args, -1, -1, buildOptions.c_str()); -#else - size_t localThreads[3] = { 256, 1, 1 }; - openCLExecuteKernel(clCxt, &convertC3C4, "convertC3C4", globalThreads, localThreads, - args, -1, -1, buildOptions.c_str()); -#endif -} - -//////////////////////////////////////////////////////////////////////// -// convert_C4C3 - -static void convert_C4C3(const oclMat &src, cl_mem &dst) -{ - int srcStep_in_pixel = src.step1() / src.oclchannels(); - int pixel_end = src.wholecols * src.wholerows - 1; - Context *clCxt = src.clCxt; - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - std::string buildOptions = format("-D GENTYPE4=%s4", typeMap[src.depth()]); - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.wholecols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.wholerows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcStep_in_pixel)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&pixel_end)); - - size_t globalThreads[3] = { divUp(src.wholecols * src.wholerows, 4), 1, 1}; - -#ifdef ANDROID - openCLExecuteKernel(clCxt, &convertC3C4, "convertC4C3", globalThreads, NULL, args, -1, -1, buildOptions.c_str()); -#else - size_t localThreads[3] = { 256, 1, 1}; - openCLExecuteKernel(clCxt, &convertC3C4, "convertC4C3", globalThreads, localThreads, args, -1, -1, buildOptions.c_str()); -#endif -} - -void cv::ocl::oclMat::upload(const Mat &m) -{ - if (!Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE) && m.depth() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - CV_DbgAssert(!m.empty()); - Size wholeSize; - Point ofs; - m.locateROI(wholeSize, ofs); - create(wholeSize, m.type()); - - if (m.channels() == 3) - { - int pitch = wholeSize.width * 3 * m.elemSize1(); - int tail_padding = m.elemSize1() * 3072; - int err; - cl_mem temp = clCreateBuffer(*(cl_context*)clCxt->getOpenCLContextPtr(), CL_MEM_READ_WRITE, - (pitch * wholeSize.height + tail_padding - 1) / tail_padding * tail_padding, 0, &err); - openCLVerifyCall(err); - - openCLMemcpy2D(clCxt, temp, pitch, m.datastart, m.step, wholeSize.width * m.elemSize(), wholeSize.height, clMemcpyHostToDevice, 3); - convert_C3C4(temp, *this); - openCLSafeCall(clReleaseMemObject(temp)); - } - else - openCLMemcpy2D(clCxt, data, step, m.datastart, m.step, wholeSize.width * elemSize(), wholeSize.height, clMemcpyHostToDevice); - - rows = m.rows; - cols = m.cols; - offset = ofs.y * step + ofs.x * elemSize(); -} - -cv::ocl::oclMat::operator cv::_InputArray() -{ - return _InputArray(cv::_InputArray::OCL_MAT, this); -} - -cv::ocl::oclMat::operator cv::_OutputArray() -{ - return _OutputArray(cv::_InputArray::OCL_MAT, this); -} - -cv::ocl::oclMat& cv::ocl::getOclMatRef(InputArray src) -{ - CV_Assert(src.kind() == cv::_InputArray::OCL_MAT); - return *(oclMat*)src.getObj(); -} - -cv::ocl::oclMat& cv::ocl::getOclMatRef(OutputArray src) -{ - CV_Assert(src.kind() == cv::_InputArray::OCL_MAT); - return *(oclMat*)src.getObj(); -} - -void cv::ocl::oclMat::download(cv::Mat &m) const -{ - CV_DbgAssert(!this->empty()); - m.create(wholerows, wholecols, type()); - - if(m.channels() == 3) - { - int pitch = wholecols * 3 * m.elemSize1(); - int tail_padding = m.elemSize1() * 3072; - int err; - cl_mem temp = clCreateBuffer(*(cl_context*)clCxt->getOpenCLContextPtr(), CL_MEM_READ_WRITE, - (pitch * wholerows + tail_padding - 1) / tail_padding * tail_padding, 0, &err); - openCLVerifyCall(err); - - convert_C4C3(*this, temp); - openCLMemcpy2D(clCxt, m.data, m.step, temp, pitch, wholecols * m.elemSize(), wholerows, clMemcpyDeviceToHost, 3); - openCLSafeCall(clReleaseMemObject(temp)); - } - else - { - openCLMemcpy2D(clCxt, m.data, m.step, data, step, wholecols * elemSize(), wholerows, clMemcpyDeviceToHost); - } - - Size wholesize; - Point ofs; - locateROI(wholesize, ofs); - m.adjustROI(-ofs.y, ofs.y + rows - wholerows, -ofs.x, ofs.x + cols - wholecols); -} - -/////////////////////////////////////////////////////////////////////////// -////////////////////////////////// CopyTo ///////////////////////////////// -/////////////////////////////////////////////////////////////////////////// -static void copy_to_with_mask(const oclMat &src, oclMat &dst, const oclMat &mask, String kernelName) -{ - CV_DbgAssert( dst.rows == mask.rows && dst.cols == mask.cols && - src.rows == dst.rows && src.cols == dst.cols - && mask.type() == CV_8UC1); - - std::vector > args; - - String string_types[4][7] = {{"uchar", "char", "ushort", "short", "int", "float", "double"}, - {"uchar2", "char2", "ushort2", "short2", "int2", "float2", "double2"}, - {"uchar3", "char3", "ushort3", "short3", "int3", "float3", "double3"}, - {"uchar4", "char4", "ushort4", "short4", "int4", "float4", "double4"} - }; - - char compile_option[32]; - sprintf(compile_option, "-D GENTYPE=%s", string_types[dst.oclchannels() - 1][dst.depth()].c_str()); - size_t localThreads[3] = {16, 16, 1}; - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - - int dststep_in_pixel = dst.step / dst.elemSize(), dstoffset_in_pixel = dst.offset / dst.elemSize(); - int srcstep_in_pixel = src.step / src.elemSize(), srcoffset_in_pixel = src.offset / src.elemSize(); - - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.rows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&srcstep_in_pixel )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&srcoffset_in_pixel )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dststep_in_pixel )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstoffset_in_pixel )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&mask.step )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&mask.offset )); - - openCLExecuteKernel(dst.clCxt , &operator_copyToM, kernelName, globalThreads, - localThreads, args, -1, -1, compile_option); -} - -void cv::ocl::oclMat::copyTo( oclMat &mat, const oclMat &mask) const -{ - if (mask.empty()) - { - CV_DbgAssert(!this->empty()); - mat.create(size(), type()); - openCLCopyBuffer2D(clCxt, mat.data, mat.step, mat.offset, - data, step, cols * elemSize(), rows, offset); - } - else - { - mat.create(size(), type()); - copy_to_with_mask(*this, mat, mask, "copy_to_with_mask"); - } -} - -/////////////////////////////////////////////////////////////////////////// -//////////////////////////////// ConvertTo //////////////////////////////// -/////////////////////////////////////////////////////////////////////////// - -static void convert_run(const oclMat &src, oclMat &dst, double alpha, double beta) -{ - String kernelName = "convert_to"; - float alpha_f = alpha, beta_f = beta; - int sdepth = src.depth(), ddepth = dst.depth(); - int sstep1 = (int)src.step1(), dstep1 = (int)dst.step1(); - int cols1 = src.cols * src.oclchannels(); - - char buildOptions[150], convertString[50]; - const char * typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - sprintf(convertString, "convert_%s_sat_rte", typeMap[ddepth]); - sprintf(buildOptions, "-D srcT=%s -D dstT=%s -D convertToDstType=%s", typeMap[sdepth], - typeMap[ddepth], CV_32F == ddepth || ddepth == CV_64F ? "" : convertString); - - CV_DbgAssert(src.rows == dst.rows && src.cols == dst.cols); - std::vector > args; - - size_t localThreads[3] = { 16, 16, 1 }; - size_t globalThreads[3] = { divUp(cols1, localThreads[0]) * localThreads[0], - divUp(dst.rows, localThreads[1]) * localThreads[1], 1 }; - - int doffset1 = dst.offset / dst.elemSize1(); - int soffset1 = src.offset / src.elemSize1(); - - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&cols1 )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.rows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&sstep1 )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&soffset1 )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstep1 )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&doffset1 )); - args.push_back( std::make_pair( sizeof(cl_float) , (void *)&alpha_f )); - args.push_back( std::make_pair( sizeof(cl_float) , (void *)&beta_f )); - - openCLExecuteKernel(dst.clCxt , &operator_convertTo, kernelName, globalThreads, - localThreads, args, -1, -1, buildOptions); -} - -void cv::ocl::oclMat::convertTo( oclMat &dst, int rtype, double alpha, double beta ) const -{ - if (!clCxt->supportsFeature(FEATURE_CL_DOUBLE) && - (depth() == CV_64F || dst.depth() == CV_64F)) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - bool noScale = fabs(alpha - 1) < std::numeric_limits::epsilon() - && fabs(beta) < std::numeric_limits::epsilon(); - - if( rtype < 0 ) - rtype = type(); - else - rtype = CV_MAKETYPE(CV_MAT_DEPTH(rtype), channels()); - - int sdepth = depth(), ddepth = CV_MAT_DEPTH(rtype); - if( sdepth == ddepth && noScale ) - { - copyTo(dst); - return; - } - - oclMat temp; - const oclMat *psrc = this; - if( sdepth != ddepth && psrc == &dst ) - psrc = &(temp = *this); - - dst.create( size(), rtype ); - convert_run(*psrc, dst, alpha, beta); -} - -/////////////////////////////////////////////////////////////////////////// -//////////////////////////////// setTo //////////////////////////////////// -/////////////////////////////////////////////////////////////////////////// - -oclMat &cv::ocl::oclMat::operator = (const Scalar &s) -{ - setTo(s); - return *this; -} - -#ifdef CL_VERSION_1_2 - -template -static std::vector cvt1(const cv::Scalar & s) -{ - std::vector _buf(sizeof(CLT)); - CLT * const buf = reinterpret_cast(&_buf[0]); - buf[0] = saturate_cast(s[0]); - return _buf; -} - -template -static std::vector cvt2(const cv::Scalar & s) -{ - std::vector _buf(sizeof(CLT)); - CLT * const buf = reinterpret_cast(&_buf[0]); - buf->s[0] = saturate_cast(s[0]); - buf->s[1] = saturate_cast(s[1]); - return _buf; -} - -template -static std::vector cvt4(const cv::Scalar & s) -{ - std::vector _buf(sizeof(CLT)); - CLT * const buf = reinterpret_cast(&_buf[0]); - buf->s[0] = saturate_cast(s[0]); - buf->s[1] = saturate_cast(s[1]); - buf->s[2] = saturate_cast(s[2]); - buf->s[3] = saturate_cast(s[3]); - return _buf; -} - -typedef std::vector (*ConvertFunc)(const cv::Scalar & s); - -static std::vector scalarToCLVector(const cv::Scalar & s, int type) -{ - const int depth = CV_MAT_DEPTH(type); - const int channels = CV_MAT_CN(type); - - static const ConvertFunc funcs[4][7] = - { - { cvt1, cvt1, cvt1, cvt1, - cvt1, cvt1, cvt1 }, - - { cvt2, cvt2, cvt2, cvt2, - cvt2, cvt2, cvt2 }, - - { 0, 0, 0, 0, 0, 0, 0 }, - - { cvt4, cvt4, cvt4, cvt4, - cvt4, cvt4, cvt4 } - }; - - ConvertFunc func = funcs[channels - 1][depth]; - return func(s); -} - -#endif - -static void set_to_withoutmask_run(const oclMat &dst, const Scalar &scalar, String kernelName) -{ - std::vector > args; - - size_t localThreads[3] = {16, 16, 1}; - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - int step_in_pixel = dst.step / dst.elemSize(), offset_in_pixel = dst.offset / dst.elemSize(); - - if (dst.type() == CV_8UC1) - globalThreads[0] = ((dst.cols + 4) / 4 + localThreads[0] - 1) / localThreads[0] * localThreads[0]; - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char channelMap[] = { ' ', ' ', '2', '4', '4' }; - std::string buildOptions = format("-D GENTYPE=%s%c", typeMap[dst.depth()], channelMap[dst.channels()]); - - Mat mat(1, 1, dst.type(), scalar); - -#ifdef CL_VERSION_1_2 - // this enables backwards portability to - // run on OpenCL 1.1 platform if library binaries are compiled with OpenCL 1.2 support - if (Context::getContext()->supportsFeature(FEATURE_CL_VER_1_2) && dst.isContinuous()) - { - std::vector p = ::scalarToCLVector(scalar, CV_MAKE_TYPE(dst.depth(), dst.oclchannels())); - clEnqueueFillBuffer(getClCommandQueue(dst.clCxt), - (cl_mem)dst.data, (void*)&p[0], p.size(), - 0, dst.step * dst.rows, 0, NULL, NULL); - } - else -#endif - { - oclMat m(mat); - args.push_back( std::make_pair( sizeof(cl_mem) , (void*)&m.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&step_in_pixel )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&offset_in_pixel )); - - openCLExecuteKernel(dst.clCxt , &operator_setTo, kernelName, globalThreads, - localThreads, args, -1, -1, buildOptions.c_str()); - } -} - -static void set_to_withmask_run(const oclMat &dst, const Scalar &scalar, const oclMat &mask, String kernelName) -{ - CV_DbgAssert( dst.rows == mask.rows && dst.cols == mask.cols); - std::vector > args; - size_t localThreads[3] = { 16, 16, 1 }; - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; - int step_in_pixel = dst.step / dst.elemSize(), offset_in_pixel = dst.offset / dst.elemSize(); - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char channelMap[] = { ' ', ' ', '2', '4', '4' }; - std::string buildOptions = format("-D GENTYPE=%s%c", typeMap[dst.depth()], channelMap[dst.channels()]); - - oclMat m(Mat(1, 1, dst.type(), scalar)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&m.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.rows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&step_in_pixel )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&offset_in_pixel )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&mask.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&mask.step )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&mask.offset )); - openCLExecuteKernel(dst.clCxt , &operator_setToM, kernelName, globalThreads, - localThreads, args, -1, -1, buildOptions.c_str()); -} - -oclMat &cv::ocl::oclMat::setTo(const Scalar &scalar, const oclMat &mask) -{ - CV_Assert(mask.type() == CV_8UC1); - CV_Assert( this->depth() >= 0 && this->depth() <= 6 ); - CV_DbgAssert( !this->empty()); - if (mask.empty()) - { - set_to_withoutmask_run(*this, scalar, type() == CV_8UC1 ? - "set_to_without_mask_C1_D0" : "set_to_without_mask"); - } - else - set_to_withmask_run(*this, scalar, mask, "set_to_with_mask"); - - return *this; -} - -oclMat cv::ocl::oclMat::reshape(int new_cn, int new_rows) const -{ - if( new_rows != 0 && new_rows != rows) - { - CV_Error( Error::StsBadFunc, "oclMat's number of rows can not be changed for current version" ); - } - - oclMat hdr = *this; - - int cn = oclchannels(); - if (new_cn == 0) - new_cn = cn; - - int total_width = cols * cn; - if ((new_cn > total_width || total_width % new_cn != 0) && new_rows == 0) - new_rows = rows * total_width / new_cn; - - if (new_rows != 0 && new_rows != rows) - { - int total_size = total_width * rows; - - if (!isContinuous()) - CV_Error(Error::BadStep, "The matrix is not continuous, thus its number of rows can not be changed"); - - if ((unsigned)new_rows > (unsigned)total_size) - CV_Error(Error::StsOutOfRange, "Bad new number of rows"); - - total_width = total_size / new_rows; - if (total_width * new_rows != total_size) - CV_Error(Error::StsBadArg, "The total number of matrix elements is not divisible by the new number of rows"); - - hdr.rows = new_rows; - hdr.step = total_width * elemSize1(); - } - - int new_width = total_width / new_cn; - if (new_width * new_cn != total_width) - CV_Error(Error::BadNumChannels, "The total width is not divisible by the new number of channels"); - - hdr.cols = new_width; - hdr.wholecols = new_width; - hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn - 1) << CV_CN_SHIFT); - return hdr; - -} - -void cv::ocl::oclMat::createEx(Size size, int type, - DevMemRW rw_type, DevMemType mem_type) -{ - createEx(size.height, size.width, type, rw_type, mem_type); -} - -void cv::ocl::oclMat::create(int _rows, int _cols, int _type) -{ - createEx(_rows, _cols, _type, gDeviceMemRW, gDeviceMemType); -} - -void cv::ocl::oclMat::createEx(int _rows, int _cols, int _type, - DevMemRW rw_type, DevMemType mem_type) -{ - clCxt = Context::getContext(); - /* core logic */ - _type &= Mat::TYPE_MASK; - if( rows == _rows && cols == _cols && type() == _type && data ) - return; - if( data ) - release(); - CV_DbgAssert( _rows >= 0 && _cols >= 0 ); - if( _rows > 0 && _cols > 0 ) - { - flags = Mat::MAGIC_VAL + _type; - rows = _rows; - cols = _cols; - wholerows = _rows; - wholecols = _cols; - size_t esz = elemSize(); - - void *dev_ptr; - openCLMallocPitchEx(clCxt, &dev_ptr, &step, GPU_MATRIX_MALLOC_STEP(esz * cols), rows, rw_type, mem_type); - - if (esz * cols == step) - flags |= Mat::CONTINUOUS_FLAG; - - int64 _nettosize = (int64)step * rows; - size_t nettosize = (size_t)_nettosize; - - datastart = data = (uchar *)dev_ptr; - dataend = data + nettosize; - - refcount = (int *)fastMalloc(sizeof(*refcount)); - *refcount = 1; - } -} - -void cv::ocl::oclMat::release() -{ - if( refcount && CV_XADD(refcount, -1) == 1 ) - { - fastFree(refcount); - openCLFree(datastart); - } - data = datastart = dataend = 0; - step = rows = cols = 0; - offset = wholerows = wholecols = 0; - refcount = 0; -} - -oclMat& cv::ocl::oclMat::operator+=( const oclMat& m ) -{ - add(*this, m, *this); - return *this; -} - -oclMat& cv::ocl::oclMat::operator-=( const oclMat& m ) -{ - subtract(*this, m, *this); - return *this; -} - -oclMat& cv::ocl::oclMat::operator*=( const oclMat& m ) -{ - multiply(*this, m, *this); - return *this; -} - -oclMat& cv::ocl::oclMat::operator/=( const oclMat& m ) -{ - divide(*this, m, *this); - return *this; -} diff --git a/modules/ocl/src/mcwutil.cpp b/modules/ocl/src/mcwutil.cpp deleted file mode 100644 index e5dfdd44a..000000000 --- a/modules/ocl/src/mcwutil.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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 "precomp.hpp" - -using namespace std; - -namespace cv -{ - namespace ocl - { - // provide additional methods for the user to interact with the command queue after a task is fired - static void openCLExecuteKernel_2(Context *clCxt, const cv::ocl::ProgramEntry* source, String kernelName, size_t globalThreads[3], - size_t localThreads[3], std::vector< std::pair > &args, int channels, - int depth, const char *build_options, FLUSH_MODE finish_mode) - { - //construct kernel name - //The rule is functionName_Cn_Dn, C represent Channels, D Represent DataType Depth, n represent an integer number - //for exmaple split_C2_D2, represent the split kernel with channels =2 and dataType Depth = 2(Data type is char) - std::stringstream idxStr; - if(channels != -1) - idxStr << "_C" << channels; - if(depth != -1) - idxStr << "_D" << depth; - kernelName += idxStr.str().c_str(); - - cl_kernel kernel; - kernel = openCLGetKernelFromSource(clCxt, source, kernelName, build_options); - - if ( localThreads != NULL) - { - globalThreads[0] = divUp(globalThreads[0], localThreads[0]) * localThreads[0]; - globalThreads[1] = divUp(globalThreads[1], localThreads[1]) * localThreads[1]; - globalThreads[2] = divUp(globalThreads[2], localThreads[2]) * localThreads[2]; - - //size_t blockSize = localThreads[0] * localThreads[1] * localThreads[2]; - cv::ocl::openCLVerifyKernel(clCxt, kernel, localThreads); - } - for(size_t i = 0; i < args.size(); i ++) - openCLSafeCall(clSetKernelArg(kernel, i, args[i].first, args[i].second)); - - openCLSafeCall(clEnqueueNDRangeKernel(*(cl_command_queue*)clCxt->getOpenCLCommandQueuePtr(), kernel, 3, NULL, globalThreads, - localThreads, 0, NULL, NULL)); - - switch(finish_mode) - { - case CLFINISH: - clFinish(*(cl_command_queue*)clCxt->getOpenCLCommandQueuePtr()); - case CLFLUSH: - clFlush(*(cl_command_queue*)clCxt->getOpenCLCommandQueuePtr()); - break; - case DISABLE: - default: - break; - } - openCLSafeCall(clReleaseKernel(kernel)); - } - - void openCLExecuteKernel2(Context *clCxt, const cv::ocl::ProgramEntry* source, String kernelName, - size_t globalThreads[3], size_t localThreads[3], - std::vector< std::pair > &args, int channels, int depth, FLUSH_MODE finish_mode) - { - openCLExecuteKernel2(clCxt, source, kernelName, globalThreads, localThreads, args, - channels, depth, NULL, finish_mode); - } - void openCLExecuteKernel2(Context *clCxt, const cv::ocl::ProgramEntry* source, String kernelName, - size_t globalThreads[3], size_t localThreads[3], - std::vector< std::pair > &args, int channels, int depth, const char *build_options, FLUSH_MODE finish_mode) - - { - openCLExecuteKernel_2(clCxt, source, kernelName, globalThreads, localThreads, args, channels, depth, - build_options, finish_mode); - } - - cl_mem bindTexture(const oclMat &mat) - { - cl_mem texture; - cl_image_format format; - int err; - int depth = mat.depth(); - int channels = mat.oclchannels(); - - switch(depth) - { - case CV_8U: - format.image_channel_data_type = CL_UNSIGNED_INT8; - break; - case CV_32S: - format.image_channel_data_type = CL_UNSIGNED_INT32; - break; - case CV_32F: - format.image_channel_data_type = CL_FLOAT; - break; - default: - CV_Error(-1, "Image forma is not supported"); - break; - } - switch(channels) - { - case 1: - format.image_channel_order = CL_R; - break; - case 3: - format.image_channel_order = CL_RGB; - break; - case 4: - format.image_channel_order = CL_RGBA; - break; - default: - CV_Error(-1, "Image format is not supported"); - break; - } -#ifdef CL_VERSION_1_2 - //this enables backwards portability to - //run on OpenCL 1.1 platform if library binaries are compiled with OpenCL 1.2 support - if(Context::getContext()->supportsFeature(FEATURE_CL_VER_1_2)) - { - cl_image_desc desc; - desc.image_type = CL_MEM_OBJECT_IMAGE2D; - desc.image_width = mat.cols; - desc.image_height = mat.rows; - desc.image_depth = 0; - desc.image_array_size = 1; - desc.image_row_pitch = 0; - desc.image_slice_pitch = 0; - desc.buffer = NULL; - desc.num_mip_levels = 0; - desc.num_samples = 0; - texture = clCreateImage(*(cl_context*)mat.clCxt->getOpenCLContextPtr(), CL_MEM_READ_WRITE, &format, &desc, NULL, &err); - } - else -#endif - { - texture = clCreateImage2D( - *(cl_context*)mat.clCxt->getOpenCLContextPtr(), - CL_MEM_READ_WRITE, - &format, - mat.cols, - mat.rows, - 0, - NULL, - &err); - } - size_t origin[] = { 0, 0, 0 }; - size_t region[] = { mat.cols, mat.rows, 1 }; - - cl_mem devData; - if (mat.cols * mat.elemSize() != mat.step) - { - devData = clCreateBuffer(*(cl_context*)mat.clCxt->getOpenCLContextPtr(), CL_MEM_READ_ONLY, mat.cols * mat.rows - * mat.elemSize(), NULL, NULL); - const size_t regin[3] = {mat.cols * mat.elemSize(), mat.rows, 1}; - clEnqueueCopyBufferRect(*(cl_command_queue*)mat.clCxt->getOpenCLCommandQueuePtr(), (cl_mem)mat.data, devData, origin, origin, - regin, mat.step, 0, mat.cols * mat.elemSize(), 0, 0, NULL, NULL); - clFlush(*(cl_command_queue*)mat.clCxt->getOpenCLCommandQueuePtr()); - } - else - { - devData = (cl_mem)mat.data; - } - - clEnqueueCopyBufferToImage(*(cl_command_queue*)mat.clCxt->getOpenCLCommandQueuePtr(), devData, texture, 0, origin, region, 0, NULL, 0); - if ((mat.cols * mat.elemSize() != mat.step)) - { - clFlush(*(cl_command_queue*)mat.clCxt->getOpenCLCommandQueuePtr()); - clReleaseMemObject(devData); - } - - openCLSafeCall(err); - return texture; - } - - Ptr bindTexturePtr(const oclMat &mat) - { - return makePtr(bindTexture(mat), mat.rows, mat.cols, mat.type()); - } - - void releaseTexture(cl_mem& texture) - { - openCLFree(texture); - } - }//namespace ocl - -}//namespace cv diff --git a/modules/ocl/src/moments.cpp b/modules/ocl/src/moments.cpp deleted file mode 100644 index 0ba6e8ce0..000000000 --- a/modules/ocl/src/moments.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/*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, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jin Ma, jin@multicorewareinc.com -// Sen Liu, swjtuls1987@126.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 "precomp.hpp" - -#include "opencv2/imgproc/types_c.h" -#include "opencv2/imgproc/imgproc_c.h" - -#include "opencl_kernels.hpp" - -#if defined _MSC_VER -#define snprintf sprintf_s -#endif -namespace cv -{ - namespace ocl - { - // The function calculates center of gravity and the central second order moments - static void icvCompleteMomentState( CvMoments* moments ) - { - double cx = 0, cy = 0; - double mu20, mu11, mu02; - - assert( moments != 0 ); - moments->inv_sqrt_m00 = 0; - - if( fabs(moments->m00) > DBL_EPSILON ) - { - double inv_m00 = 1. / moments->m00; - cx = moments->m10 * inv_m00; - cy = moments->m01 * inv_m00; - moments->inv_sqrt_m00 = std::sqrt( fabs(inv_m00) ); - } - - // mu20 = m20 - m10*cx - mu20 = moments->m20 - moments->m10 * cx; - // mu11 = m11 - m10*cy - mu11 = moments->m11 - moments->m10 * cy; - // mu02 = m02 - m01*cy - mu02 = moments->m02 - moments->m01 * cy; - - moments->mu20 = mu20; - moments->mu11 = mu11; - moments->mu02 = mu02; - - // mu30 = m30 - cx*(3*mu20 + cx*m10) - moments->mu30 = moments->m30 - cx * (3 * mu20 + cx * moments->m10); - mu11 += mu11; - // mu21 = m21 - cx*(2*mu11 + cx*m01) - cy*mu20 - moments->mu21 = moments->m21 - cx * (mu11 + cx * moments->m01) - cy * mu20; - // mu12 = m12 - cy*(2*mu11 + cy*m10) - cx*mu02 - moments->mu12 = moments->m12 - cy * (mu11 + cy * moments->m10) - cx * mu02; - // mu03 = m03 - cy*(3*mu02 + cy*m01) - moments->mu03 = moments->m03 - cy * (3 * mu02 + cy * moments->m01); - } - - - static void icvContourMoments( CvSeq* contour, CvMoments* mom ) - { - if( contour->total ) - { - CvSeqReader reader; - int lpt = contour->total; - double a00, a10, a01, a20, a11, a02, a30, a21, a12, a03; - - cvStartReadSeq( contour, &reader, 0 ); - - size_t reader_size = lpt << 1; - cv::Mat reader_mat(1,reader_size,CV_32FC1); - - bool is_float = CV_SEQ_ELTYPE(contour) == CV_32FC2; - - if (!cv::ocl::Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE) && is_float) - { - CV_Error(CV_StsUnsupportedFormat, "Moments - double is not supported by your GPU!"); - } - - if( is_float ) - { - for(size_t i = 0; i < reader_size; ++i) - { - reader_mat.at(0, i++) = ((CvPoint2D32f*)(reader.ptr))->x; - reader_mat.at(0, i) = ((CvPoint2D32f*)(reader.ptr))->y; - CV_NEXT_SEQ_ELEM( contour->elem_size, reader ); - } - } - else - { - for(size_t i = 0; i < reader_size; ++i) - { - reader_mat.at(0, i++) = ((CvPoint*)(reader.ptr))->x; - reader_mat.at(0, i) = ((CvPoint*)(reader.ptr))->y; - CV_NEXT_SEQ_ELEM( contour->elem_size, reader ); - } - } - - cv::ocl::oclMat dst_a(10, lpt, CV_64FC1); - cv::ocl::oclMat reader_oclmat(reader_mat); - int llength = std::min(lpt,128); - size_t localThreads[3] = { llength, 1, 1}; - size_t globalThreads[3] = { lpt, 1, 1}; - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&contour->total )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&reader_oclmat.data )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst_a.data )); - cl_int dst_step = (cl_int)dst_a.step; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_step )); - - char builOption[128]; - snprintf(builOption, 128, "-D CV_8UC1"); - - openCLExecuteKernel(dst_a.clCxt, &moments, "icvContourMoments", globalThreads, localThreads, args, -1, -1, builOption); - - cv::Mat dst(dst_a); - a00 = a10 = a01 = a20 = a11 = a02 = a30 = a21 = a12 = a03 = 0.0; - if (!cv::ocl::Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - { - for (int i = 0; i < contour->total; ++i) - { - a00 += dst.at(0, i); - a10 += dst.at(1, i); - a01 += dst.at(2, i); - a20 += dst.at(3, i); - a11 += dst.at(4, i); - a02 += dst.at(5, i); - a30 += dst.at(6, i); - a21 += dst.at(7, i); - a12 += dst.at(8, i); - a03 += dst.at(9, i); - } - } - else - { - a00 = cv::sum(dst.row(0))[0]; - a10 = cv::sum(dst.row(1))[0]; - a01 = cv::sum(dst.row(2))[0]; - a20 = cv::sum(dst.row(3))[0]; - a11 = cv::sum(dst.row(4))[0]; - a02 = cv::sum(dst.row(5))[0]; - a30 = cv::sum(dst.row(6))[0]; - a21 = cv::sum(dst.row(7))[0]; - a12 = cv::sum(dst.row(8))[0]; - a03 = cv::sum(dst.row(9))[0]; - } - - double db1_2, db1_6, db1_12, db1_24, db1_20, db1_60; - if( fabs(a00) > FLT_EPSILON ) - { - if( a00 > 0 ) - { - db1_2 = 0.5; - db1_6 = 0.16666666666666666666666666666667; - db1_12 = 0.083333333333333333333333333333333; - db1_24 = 0.041666666666666666666666666666667; - db1_20 = 0.05; - db1_60 = 0.016666666666666666666666666666667; - } - else - { - db1_2 = -0.5; - db1_6 = -0.16666666666666666666666666666667; - db1_12 = -0.083333333333333333333333333333333; - db1_24 = -0.041666666666666666666666666666667; - db1_20 = -0.05; - db1_60 = -0.016666666666666666666666666666667; - } - - // spatial moments - mom->m00 = a00 * db1_2; - mom->m10 = a10 * db1_6; - mom->m01 = a01 * db1_6; - mom->m20 = a20 * db1_12; - mom->m11 = a11 * db1_24; - mom->m02 = a02 * db1_12; - mom->m30 = a30 * db1_20; - mom->m21 = a21 * db1_60; - mom->m12 = a12 * db1_60; - mom->m03 = a03 * db1_20; - - icvCompleteMomentState( mom ); - } - } - } - - Moments ocl_moments(oclMat& src, bool binary) //for image - { - CV_Assert(src.oclchannels() == 1); - if(src.type() == CV_64FC1 && !Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - { - CV_Error(CV_StsUnsupportedFormat, "Moments - double is not supported by your GPU!"); - } - - if(binary) - { - oclMat mask; - if(src.type() != CV_8UC1) - { - src.convertTo(mask, CV_8UC1); - } - oclMat src8u(src.size(), CV_8UC1); - src8u.setTo(Scalar(255), mask); - src = src8u; - } - const int TILE_SIZE = 256; - - CvMoments mom; - memset(&mom, 0, sizeof(mom)); - - cv::Size size = src.size(); - int blockx, blocky; - blockx = (size.width + TILE_SIZE - 1)/TILE_SIZE; - blocky = (size.height + TILE_SIZE - 1)/TILE_SIZE; - - oclMat dst_m; - int tile_height = TILE_SIZE; - - size_t localThreads[3] = {1, tile_height, 1}; - size_t globalThreads[3] = {blockx, size.height, 1}; - - if(Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - { - dst_m.create(blocky * 10, blockx, CV_64FC1); - }else - { - dst_m.create(blocky * 10, blockx, CV_32FC1); - } - - int src_step = (int)(src.step/src.elemSize()); - int dstm_step = (int)(dst_m.step/dst_m.elemSize()); - - std::vector > args,args_sum; - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.rows )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_step )); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst_m.data )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_m.cols )); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dstm_step )); - - int binary_; - if(binary) - binary_ = 1; - else - binary_ = 0; - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&binary_)); - - char builOption[128]; - if(binary || src.type() == CV_8UC1) - { - snprintf(builOption, 128, "-D CV_8UC1"); - }else if(src.type() == CV_16UC1) - { - snprintf(builOption, 128, "-D CV_16UC1"); - }else if(src.type() == CV_16SC1) - { - snprintf(builOption, 128, "-D CV_16SC1"); - }else if(src.type() == CV_32FC1) - { - snprintf(builOption, 128, "-D CV_32FC1"); - }else if(src.type() == CV_64FC1) - { - snprintf(builOption, 128, "-D CV_64FC1"); - }else - { - CV_Error( CV_StsUnsupportedFormat, "" ); - } - - openCLExecuteKernel(Context::getContext(), &moments, "CvMoments", globalThreads, localThreads, args, -1, -1, builOption); - - Mat tmp(dst_m); - tmp.convertTo(tmp, CV_64FC1); - - double tmp_m[10] = {0}; - - for(int j = 0; j < tmp.rows; j += 10) - { - for(int i = 0; i < tmp.cols; i++) - { - tmp_m[0] += tmp.at(j, i); - tmp_m[1] += tmp.at(j + 1, i); - tmp_m[2] += tmp.at(j + 2, i); - tmp_m[3] += tmp.at(j + 3, i); - tmp_m[4] += tmp.at(j + 4, i); - tmp_m[5] += tmp.at(j + 5, i); - tmp_m[6] += tmp.at(j + 6, i); - tmp_m[7] += tmp.at(j + 7, i); - tmp_m[8] += tmp.at(j + 8, i); - tmp_m[9] += tmp.at(j + 9, i); - } - } - - mom.m00 = tmp_m[0]; - mom.m10 = tmp_m[1]; - mom.m01 = tmp_m[2]; - mom.m20 = tmp_m[3]; - mom.m11 = tmp_m[4]; - mom.m02 = tmp_m[5]; - mom.m30 = tmp_m[6]; - mom.m21 = tmp_m[7]; - mom.m12 = tmp_m[8]; - mom.m03 = tmp_m[9]; - icvCompleteMomentState( &mom ); - return mom; - } - - Moments ocl_moments(InputArray _contour) //for contour - { - CvMoments mom; - memset(&mom, 0, sizeof(mom)); - - Mat arr = _contour.getMat(); - CvMat c_array = arr; - - const void* array = &c_array; - - CvSeq* contour = 0; - if( CV_IS_SEQ( array )) - { - contour = (CvSeq*)(array); - if( !CV_IS_SEQ_POINT_SET( contour )) - CV_Error( CV_StsBadArg, "The passed sequence is not a valid contour" ); - } - - int type, coi = 0; - - CvMat stub, *mat = (CvMat*)(array); - CvContour contourHeader; - CvSeqBlock block; - - if( !contour ) - { - mat = cvGetMat( mat, &stub, &coi ); - type = CV_MAT_TYPE( mat->type ); - - if( type == CV_32SC2 || type == CV_32FC2 ) - { - contour = cvPointSeqFromMat( - CV_SEQ_KIND_CURVE | CV_SEQ_FLAG_CLOSED, - mat, &contourHeader, &block ); - } - } - - CV_Assert(contour); - - icvContourMoments(contour, &mom); - return mom; - } - } -} diff --git a/modules/ocl/src/mssegmentation.cpp b/modules/ocl/src/mssegmentation.cpp deleted file mode 100644 index a569c127d..000000000 --- a/modules/ocl/src/mssegmentation.cpp +++ /dev/null @@ -1,402 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// -// 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 (__GNUC__ == 4) && (__GNUC_MINOR__ == 6) -# pragma GCC diagnostic ignored "-Warray-bounds" -#endif - -#include "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -// Auxiliray stuff -namespace -{ - - // - // Declarations - // - - class DjSets - { - public: - DjSets(int n); - int find(int elem); - int merge(int set1, int set2); - - std::vector parent; - std::vector rank; - std::vector size; - private: - DjSets(const DjSets &) {} - DjSets operator =(const DjSets &); - }; - - template - struct GraphEdge - { - GraphEdge() {} - GraphEdge(int to, int next, const T &val) : to(to), next(next), val(val) {} - int to; - int next; - T val; - }; - - - template - class Graph - { - public: - typedef GraphEdge Edge; - - Graph(int numv, int nume_max); - - void addEdge(int from, int to, const T &val = T()); - - std::vector start; - std::vector edges; - - int numv; - int nume_max; - int nume; - private: - Graph(const Graph &) {} - Graph operator =(const Graph &) {} - }; - - - struct SegmLinkVal - { - SegmLinkVal() {} - SegmLinkVal(int dr, int dsp) : dr(dr), dsp(dsp) {} - bool operator <(const SegmLinkVal &other) const - { - return dr + dsp < other.dr + other.dsp; - } - int dr; - int dsp; - }; - - - struct SegmLink - { - SegmLink() {} - SegmLink(int from, int to, const SegmLinkVal &val) - : from(from), to(to), val(val) {} - bool operator <(const SegmLink &other) const - { - return val < other.val; - } - int from; - int to; - SegmLinkVal val; - }; - - // - // Implementation - // - - DjSets DjSets::operator = (const DjSets &/*obj*/) - { - //cout << "Invalid DjSets constructor\n"; - CV_Error(-1, "Invalid DjSets constructor\n"); - return *this; - } - - DjSets::DjSets(int n) : parent(n), rank(n, 0), size(n, 1) - { - for (int i = 0; i < n; ++i) - parent[i] = i; - } - - - inline int DjSets::find(int elem) - { - int set = elem; - while (set != parent[set]) - set = parent[set]; - while (elem != parent[elem]) - { - int next = parent[elem]; - parent[elem] = set; - elem = next; - } - return set; - } - - - inline int DjSets::merge(int set1, int set2) - { - if (rank[set1] < rank[set2]) - { - parent[set1] = set2; - size[set2] += size[set1]; - return set2; - } - if (rank[set2] < rank[set1]) - { - parent[set2] = set1; - size[set1] += size[set2]; - return set1; - } - parent[set1] = set2; - rank[set2]++; - size[set2] += size[set1]; - return set2; - } - - - template - Graph::Graph(int numv, int nume_max) : start(numv, -1), edges(nume_max) - { - this->numv = numv; - this->nume_max = nume_max; - nume = 0; - } - - - template - inline void Graph::addEdge(int from, int to, const T &val) - { - edges[nume] = Edge(to, start[from], val); - start[from] = nume; - nume++; - } - - - inline int pix(int y, int x, int ncols) - { - return y * ncols + x; - } - - - inline int sqr(int x) - { - return x * x; - } - - - inline int dist2(const cv::Vec4b &lhs, const cv::Vec4b &rhs) - { - return sqr(lhs[0] - rhs[0]) + sqr(lhs[1] - rhs[1]) + sqr(lhs[2] - rhs[2]); - } - - - inline int dist2(const cv::Vec2s &lhs, const cv::Vec2s &rhs) - { - return sqr(lhs[0] - rhs[0]) + sqr(lhs[1] - rhs[1]); - } - -} // anonymous namespace - -namespace cv -{ - namespace ocl - { - - void meanShiftSegmentation(const oclMat &src, Mat &dst, int sp, int sr, int minsize, TermCriteria criteria) - { - CV_Assert(src.type() == CV_8UC4); - const int nrows = src.rows; - const int ncols = src.cols; - const int hr = sr; - const int hsp = sp; - - // Perform mean shift procedure and obtain region and spatial maps - oclMat h_rmap, h_spmap; - meanShiftProc(src, h_rmap, h_spmap, sp, sr, criteria); - Mat rmap = h_rmap; - Mat spmap = h_spmap; - - Graph g(nrows * ncols, 4 * (nrows - 1) * (ncols - 1) - + (nrows - 1) + (ncols - 1)); - - // Make region adjacent graph from image - Vec4b r1; - Vec4b r2[4]; - Vec2s sp1; - Vec2s sp2[4]; - int dr[4]; - int dsp[4]; - for (int y = 0; y < nrows - 1; ++y) - { - Vec4b *ry = rmap.ptr(y); - Vec4b *ryp = rmap.ptr(y + 1); - Vec2s *spy = spmap.ptr(y); - Vec2s *spyp = spmap.ptr(y + 1); - for (int x = 0; x < ncols - 1; ++x) - { - r1 = ry[x]; - sp1 = spy[x]; - - r2[0] = ry[x + 1]; - r2[1] = ryp[x]; - r2[2] = ryp[x + 1]; - r2[3] = ryp[x]; - - sp2[0] = spy[x + 1]; - sp2[1] = spyp[x]; - sp2[2] = spyp[x + 1]; - sp2[3] = spyp[x]; - - dr[0] = dist2(r1, r2[0]); - dr[1] = dist2(r1, r2[1]); - dr[2] = dist2(r1, r2[2]); - dsp[0] = dist2(sp1, sp2[0]); - dsp[1] = dist2(sp1, sp2[1]); - dsp[2] = dist2(sp1, sp2[2]); - - r1 = ry[x + 1]; - sp1 = spy[x + 1]; - - dr[3] = dist2(r1, r2[3]); - dsp[3] = dist2(sp1, sp2[3]); - - g.addEdge(pix(y, x, ncols), pix(y, x + 1, ncols), SegmLinkVal(dr[0], dsp[0])); - g.addEdge(pix(y, x, ncols), pix(y + 1, x, ncols), SegmLinkVal(dr[1], dsp[1])); - g.addEdge(pix(y, x, ncols), pix(y + 1, x + 1, ncols), SegmLinkVal(dr[2], dsp[2])); - g.addEdge(pix(y, x + 1, ncols), pix(y + 1, x, ncols), SegmLinkVal(dr[3], dsp[3])); - } - } - for (int y = 0; y < nrows - 1; ++y) - { - r1 = rmap.at(y, ncols - 1); - r2[0] = rmap.at(y + 1, ncols - 1); - sp1 = spmap.at(y, ncols - 1); - sp2[0] = spmap.at(y + 1, ncols - 1); - dr[0] = dist2(r1, r2[0]); - dsp[0] = dist2(sp1, sp2[0]); - g.addEdge(pix(y, ncols - 1, ncols), pix(y + 1, ncols - 1, ncols), SegmLinkVal(dr[0], dsp[0])); - } - for (int x = 0; x < ncols - 1; ++x) - { - r1 = rmap.at(nrows - 1, x); - r2[0] = rmap.at(nrows - 1, x + 1); - sp1 = spmap.at(nrows - 1, x); - sp2[0] = spmap.at(nrows - 1, x + 1); - dr[0] = dist2(r1, r2[0]); - dsp[0] = dist2(sp1, sp2[0]); - g.addEdge(pix(nrows - 1, x, ncols), pix(nrows - 1, x + 1, ncols), SegmLinkVal(dr[0], dsp[0])); - } - - DjSets comps(g.numv); - - // Find adjacent components - for (int v = 0; v < g.numv; ++v) - { - for (int e_it = g.start[v]; e_it != -1; e_it = g.edges[e_it].next) - { - int c1 = comps.find(v); - int c2 = comps.find(g.edges[e_it].to); - if (c1 != c2 && g.edges[e_it].val.dr < hr && g.edges[e_it].val.dsp < hsp) - comps.merge(c1, c2); - } - } - - std::vector edges; - edges.reserve(g.numv); - - // Prepare edges connecting differnet components - for (int v = 0; v < g.numv; ++v) - { - int c1 = comps.find(v); - for (int e_it = g.start[v]; e_it != -1; e_it = g.edges[e_it].next) - { - int c2 = comps.find(g.edges[e_it].to); - if (c1 != c2) - edges.push_back(SegmLink(c1, c2, g.edges[e_it].val)); - } - } - - // Sort all graph's edges connecting differnet components (in asceding order) - std::sort(edges.begin(), edges.end()); - - // Exclude small components (starting from the nearest couple) - for (size_t i = 0; i < edges.size(); ++i) - { - int c1 = comps.find(edges[i].from); - int c2 = comps.find(edges[i].to); - if (c1 != c2 && (comps.size[c1] < minsize || comps.size[c2] < minsize)) - comps.merge(c1, c2); - } - - // Compute sum of the pixel's colors which are in the same segment - Mat h_src = src; - std::vector sumcols(nrows * ncols, Vec4i(0, 0, 0, 0)); - for (int y = 0; y < nrows; ++y) - { - Vec4b *h_srcy = h_src.ptr(y); - for (int x = 0; x < ncols; ++x) - { - int parent = comps.find(pix(y, x, ncols)); - Vec4b col = h_srcy[x]; - Vec4i &sumcol = sumcols[parent]; - sumcol[0] += col[0]; - sumcol[1] += col[1]; - sumcol[2] += col[2]; - } - } - - // Create final image, color of each segment is the average color of its pixels - dst.create(src.size(), src.type()); - - for (int y = 0; y < nrows; ++y) - { - Vec4b *dsty = dst.ptr(y); - for (int x = 0; x < ncols; ++x) - { - int parent = comps.find(pix(y, x, ncols)); - const Vec4i &sumcol = sumcols[parent]; - Vec4b &dstcol = dsty[x]; - dstcol[0] = static_cast(sumcol[0] / comps.size[parent]); - dstcol[1] = static_cast(sumcol[1] / comps.size[parent]); - dstcol[2] = static_cast(sumcol[2] / comps.size[parent]); - } - } - } - - } -} diff --git a/modules/ocl/src/opencl/arithm_LUT.cl b/modules/ocl/src/opencl/arithm_LUT.cl deleted file mode 100644 index 30407bb88..000000000 --- a/modules/ocl/src/opencl/arithm_LUT.cl +++ /dev/null @@ -1,107 +0,0 @@ -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Rock Li, Rock.li@amd.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. -// -// - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -__kernel void LUT_C1( __global const srcT * src, __global const dstT *lut, - __global dstT *dst, - int cols1, int rows, - int src_offset1, - int lut_offset1, - int dst_offset1, - int src_step1, int dst_step1) -{ - int x1 = get_global_id(0); - int y = get_global_id(1); - - if (x1 < cols1 && y < rows) - { - int src_index = mad24(y, src_step1, src_offset1 + x1); - int dst_index = mad24(y, dst_step1, dst_offset1 + x1); - - dst[dst_index] = lut[lut_offset1 + src[src_index]]; - } -} - -__kernel void LUT_C2( __global const srcT * src, __global const dstT *lut, - __global dstT *dst, - int cols1, int rows, - int src_offset1, - int lut_offset1, - int dst_offset1, - int src_step1, int dst_step1) -{ - int x1 = get_global_id(0) << 1; - int y = get_global_id(1); - - if (x1 < cols1 && y < rows) - { - int src_index = mad24(y, src_step1, src_offset1 + x1); - int dst_index = mad24(y, dst_step1, dst_offset1 + x1); - - dst[dst_index ] = lut[lut_offset1 + (src[src_index ] << 1) ]; - dst[dst_index + 1] = x1 + 1 < cols1 ? lut[lut_offset1 + (src[src_index + 1] << 1) + 1] : dst[dst_index + 1]; - } -} - -__kernel void LUT_C4( __global const srcT * src, __global const dstT *lut, - __global dstT *dst, - int cols1, int rows, - int src_offset1, - int lut_offset1, - int dst_offset1, - int src_step1, int dst_step1) -{ - int x1 = get_global_id(0) << 2; - int y = get_global_id(1); - - if (x1 < cols1 && y < rows) - { - int src_index = mad24(y, src_step1, src_offset1 + x1); - int dst_index = mad24(y, dst_step1, dst_offset1 + x1); - - dst[dst_index ] = lut[lut_offset1 + (src[src_index ] << 2) ]; - dst[dst_index + 1] = x1 + 1 < cols1 ? lut[lut_offset1 + (src[src_index + 1] << 2) + 1] : dst[dst_index + 1]; - dst[dst_index + 2] = x1 + 2 < cols1 ? lut[lut_offset1 + (src[src_index + 2] << 2) + 2] : dst[dst_index + 2]; - dst[dst_index + 3] = x1 + 3 < cols1 ? lut[lut_offset1 + (src[src_index + 3] << 2) + 3] : dst[dst_index + 3]; - } -} diff --git a/modules/ocl/src/opencl/arithm_absdiff_nonsaturate.cl b/modules/ocl/src/opencl/arithm_absdiff_nonsaturate.cl deleted file mode 100644 index e07f31413..000000000 --- a/modules/ocl/src/opencl/arithm_absdiff_nonsaturate.cl +++ /dev/null @@ -1,107 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#ifdef BINARY - -__kernel void arithm_absdiff_nonsaturate_binary(__global srcT *src1, int src1_step, int src1_offset, - __global srcT *src2, int src2_step, int src2_offset, - __global dstT *dst, int dst_step, int dst_offset, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step, x + src1_offset); - int src2_index = mad24(y, src2_step, x + src2_offset); - int dst_index = mad24(y, dst_step, x + dst_offset); -#ifdef INTEL_DEVICE //workaround for intel compiler bug - if(src1_index >= 0 && src2_index >= 0) -#endif - { - dstT t0 = convertToDstT(src1[src1_index]); - dstT t1 = convertToDstT(src2[src2_index]); - dstT t2 = t0 - t1; - - dst[dst_index] = t2 >= (dstT)(0) ? t2 : -t2; - } - } -} - -#else - -__kernel void arithm_absdiff_nonsaturate(__global srcT *src1, int src1_step, int src1_offset, - __global dstT *dst, int dst_step, int dst_offset, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step, x + src1_offset); - int dst_index = mad24(y, dst_step, x + dst_offset); -#ifdef INTEL_DEVICE //workaround for intel compiler bug - if(src1_index >= 0) -#endif - { - dstT t0 = convertToDstT(src1[src1_index]); - - dst[dst_index] = t0 >= (dstT)(0) ? t0 : -t0; - } - } -} - -#endif diff --git a/modules/ocl/src/opencl/arithm_add.cl b/modules/ocl/src/opencl/arithm_add.cl deleted file mode 100644 index 04262b872..000000000 --- a/modules/ocl/src/opencl/arithm_add.cl +++ /dev/null @@ -1,143 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#if defined (FUNC_ADD) -#define EXPRESSION dst[dst_index] = convertToT(convertToWT(src1[src1_index]) + convertToWT(src2[src2_index])); -#endif - -#if defined (FUNC_SUB) -#define EXPRESSION dst[dst_index] = convertToT(convertToWT(src1[src1_index]) - convertToWT(src2[src2_index])); -#endif - -#if defined (FUNC_MUL) -#if defined (HAVE_SCALAR) -#define EXPRESSION dst[dst_index] = convertToT(convertToWT(src1[src1_index]) * scalar * convertToWT(src2[src2_index])); -#else -#define EXPRESSION dst[dst_index] = convertToT(convertToWT(src1[src1_index]) * convertToWT(src2[src2_index])); -#endif -#endif - -#if defined (FUNC_DIV) -#if defined (HAVE_SCALAR) -#define EXPRESSION T zero = (T)(0); \ - dst[dst_index] = src2[src2_index] == zero ? zero : \ - convertToT(convertToWT(src1[src1_index]) * scalar / convertToWT(src2[src2_index])); -#else -#define EXPRESSION T zero = (T)(0); \ - dst[dst_index] = src2[src2_index] == zero ? zero : \ - convertToT(convertToWT(src1[src1_index]) / convertToWT(src2[src2_index])); -#endif -#endif - -#if defined (FUNC_ABS_DIFF) -#define EXPRESSION WT value = convertToWT(src1[src1_index]) - convertToWT(src2[src2_index]); \ - value = value > (WT)(0) ? value : -value; \ - dst[dst_index] = convertToT(value); -#endif - -#if defined (FUNC_MIN) -#define EXPRESSION dst[dst_index] = min( src1[src1_index], src2[src2_index] ); -#endif - -#if defined (FUNC_MAX) -#define EXPRESSION dst[dst_index] = max( src1[src1_index], src2[src2_index] ); -#endif - -////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////// ADD //////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////// - -#ifndef HAVE_SCALAR - -__kernel void arithm_binary_op_mat(__global T *src1, int src1_step, int src1_offset, - __global T *src2, int src2_step, int src2_offset, - __global T *dst, int dst_step, int dst_offset, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step, x + src1_offset); - int src2_index = mad24(y, src2_step, x + src2_offset); - int dst_index = mad24(y, dst_step, x + dst_offset); - - EXPRESSION - } -} - -#else - -// add mat with scale -__kernel void arithm_binary_op_mat_scalar(__global T *src1, int src1_step, int src1_offset, - __global T *src2, int src2_step, int src2_offset, - WT scalar, - __global T *dst, int dst_step, int dst_offset, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step, x + src1_offset); - int src2_index = mad24(y, src2_step, x + src2_offset); - int dst_index = mad24(y, dst_step, x + dst_offset); - - EXPRESSION - } -} - -#endif diff --git a/modules/ocl/src/opencl/arithm_addWeighted.cl b/modules/ocl/src/opencl/arithm_addWeighted.cl deleted file mode 100644 index 872ee8535..000000000 --- a/modules/ocl/src/opencl/arithm_addWeighted.cl +++ /dev/null @@ -1,75 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -////////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////addWeighted////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void addWeighted(__global T * src1, int src1_step1, int src1_offset1, - __global T * src2, int src2_step1, int src2_offset1, - __global T * dst, int dst_step1, int dst_offset1, - WT alpha, WT beta, WT gama, - int cols1, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols1 && y < rows) - { - int src1_index = mad24(y, src1_step1, x + src1_offset1); - int src2_index = mad24(y, src2_step1, x + src2_offset1); - int dst_index = mad24(y, dst_step1, x + dst_offset1); - - dst[dst_index] = convertToT(src1[src1_index]*alpha + src2[src2_index]*beta + gama); - } -} diff --git a/modules/ocl/src/opencl/arithm_add_mask.cl b/modules/ocl/src/opencl/arithm_add_mask.cl deleted file mode 100644 index b115d9b76..000000000 --- a/modules/ocl/src/opencl/arithm_add_mask.cl +++ /dev/null @@ -1,97 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#if defined (FUNC_ADD) -#define EXPRESSION dst[dst_index] = convertToT(convertToWT(src1[src1_index]) + convertToWT(src2[src2_index])); -#endif - -#if defined (FUNC_SUB) -#define EXPRESSION dst[dst_index] = convertToT(convertToWT(src1[src1_index]) - convertToWT(src2[src2_index])); -#endif - -#if defined (FUNC_MUL) -#define EXPRESSION dst[dst_index] = convertToT(convertToWT(src1[src1_index]) * convertToWT(src2[src2_index])); -#endif - -#if defined (FUNC_DIV) -#define EXPRESSION T zero = (T)(0); \ - dst[dst_index] = src2[src2_index] == zero ? zero : \ - convertToT(convertToWT(src1[src1_index]) / convertToWT(src2[src2_index])); -#endif - -////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////// add with mask ////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_binary_op_mat_mask(__global T * src1, int src1_step, int src1_offset, - __global T * src2, int src2_step, int src2_offset, - __global uchar * mask, int mask_step, int mask_offset, - __global T * dst, int dst_step, int dst_offset, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int mask_index = mad24(y, mask_step, x + mask_offset); - if (mask[mask_index]) - { - int src1_index = mad24(y, src1_step, x + src1_offset); - int src2_index = mad24(y, src2_step, x + src2_offset); - int dst_index = mad24(y, dst_step, dst_offset + x); - - EXPRESSION - } - } -} diff --git a/modules/ocl/src/opencl/arithm_add_scalar.cl b/modules/ocl/src/opencl/arithm_add_scalar.cl deleted file mode 100644 index 05ea48da4..000000000 --- a/modules/ocl/src/opencl/arithm_add_scalar.cl +++ /dev/null @@ -1,103 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#if defined (FUNC_ADD) -#define EXPRESSION dst[dst_index] = convertToT(convertToWT(src1[src1_index]) + scalar); -#endif - -#if defined (FUNC_SUB) -#define EXPRESSION dst[dst_index] = convertToT(convertToWT(src1[src1_index]) - scalar); -#endif - -#if defined (FUNC_MUL) -#define EXPRESSION dst[dst_index] = convertToT(convertToWT(src1[src1_index]) * scalar); -#endif - -#if defined (FUNC_DIV) -#define EXPRESSION T zero = (T)(0); \ - dst[dst_index] = src1[src1_index] == zero ? zero : convertToT(scalar / convertToWT(src1[src1_index])); -#endif - -#if defined (FUNC_ABS) -#define EXPRESSION \ - T value = src1[src1_index] > (T)(0) ? src1[src1_index] : -src1[src1_index]; \ - dst[dst_index] = value; -#endif - -#if defined (FUNC_ABS_DIFF) -#define EXPRESSION WT value = convertToWT(src1[src1_index]) - scalar; \ - value = value > (WT)(0) ? value : -value; \ - dst[dst_index] = convertToT(value); -#endif - -/////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////// Add with scalar ///////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_binary_op_scalar (__global T *src1, int src1_step, int src1_offset, - WT scalar, - __global T *dst, int dst_step, int dst_offset, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step, x + src1_offset); - int dst_index = mad24(y, dst_step, x + dst_offset); - - EXPRESSION - - } -} diff --git a/modules/ocl/src/opencl/arithm_add_scalar_mask.cl b/modules/ocl/src/opencl/arithm_add_scalar_mask.cl deleted file mode 100644 index a8b965758..000000000 --- a/modules/ocl/src/opencl/arithm_add_scalar_mask.cl +++ /dev/null @@ -1,96 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#if defined (FUNC_ADD) -#define EXPRESSION dst[dst_index] = convertToT(convertToWT(src1[src1_index]) + scalar); -#endif - -#if defined (FUNC_SUB) -#define EXPRESSION dst[dst_index] = convertToT(convertToWT(src1[src1_index]) - scalar); -#endif - -#if defined (FUNC_MUL) -#define EXPRESSION dst[dst_index] = convertToT(convertToWT(src1[src1_index]) * scalar); -#endif - -#if defined (FUNC_DIV) -#define EXPRESSION T zero = (T)(0); \ - dst[dst_index] = src2[src2_index] == zero ? zero : \ - convertToT(convertToWT(src1[src1_index]) / scalar[0]); -#endif - -/////////////////////////////////////////////////////////////////////////////////// -//////////////////////////// Add with scalar with mask //////////////////////////// -/////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_binary_op_scalar_mask(__global T *src1, int src1_step, int src1_offset, - WT scalar, - __global uchar *mask, int mask_step, int mask_offset, - __global T *dst, int dst_step, int dst_offset, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int mask_index = mad24(y, mask_step, x + mask_offset); - if (mask[mask_index]) - { - int src1_index = mad24(y, src1_step, x + src1_offset); - int dst_index = mad24(y, dst_step, dst_offset + x); - - EXPRESSION - } - } -} diff --git a/modules/ocl/src/opencl/arithm_bitwise_binary.cl b/modules/ocl/src/opencl/arithm_bitwise_binary.cl deleted file mode 100644 index 56cd745d2..000000000 --- a/modules/ocl/src/opencl/arithm_bitwise_binary.cl +++ /dev/null @@ -1,82 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jiang Liyuan, jlyuan001.good@163.com -// Peng Xiao, pengxiao@outlook.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*/ - -///////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////// bitwise_binary ////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_bitwise_binary(__global uchar * src1, int src1_step, int src1_offset, - __global uchar * src2, int src2_step, int src2_offset, - __global uchar * dst, int dst_step, int dst_offset, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { -#if elemSize > 1 - x *= elemSize; -#endif - int src1_index = mad24(y, src1_step, x + src1_offset); - int src2_index = mad24(y, src2_step, x + src2_offset); - int dst_index = mad24(y, dst_step, x + dst_offset); - -#if elemSize > 1 - #pragma unroll - for (int i = 0; i < elemSize; i += vlen) - { - ucharv t0 = vloadn(0, src1 + src1_index + i); - ucharv t1 = vloadn(0, src2 + src2_index + i); - ucharv t2 = t0 Operation t1; - - vstoren(t2, 0, dst + dst_index + i); - } -#else - dst[dst_index] = src1[src1_index] Operation src2[src2_index]; -#endif - } -} diff --git a/modules/ocl/src/opencl/arithm_bitwise_binary_mask.cl b/modules/ocl/src/opencl/arithm_bitwise_binary_mask.cl deleted file mode 100644 index 328ccd91a..000000000 --- a/modules/ocl/src/opencl/arithm_bitwise_binary_mask.cl +++ /dev/null @@ -1,88 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jiang Liyuan, jlyuan001.good@163.com -// Peng Xiao, pengxiao@outlook.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*/ - -////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////bitwise_binary//////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_bitwise_binary_mask(__global uchar * src1, int src1_step, int src1_offset, - __global uchar * src2, int src2_step, int src2_offset, - __global uchar * mask, int mask_step, int mask_offset, - __global uchar * dst, int dst_step, int dst_offset, - int cols1, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols1 && y < rows) - { - int mask_index = mad24(y, mask_step, mask_offset + x); - - if (mask[mask_index]) - { -#if elemSize > 1 - x *= elemSize; -#endif - int src1_index = mad24(y, src1_step, x + src1_offset); - int src2_index = mad24(y, src2_step, x + src2_offset); - int dst_index = mad24(y, dst_step, x + dst_offset); - -#if elemSize > 1 - #pragma unroll - for (int i = 0; i < elemSize; i += vlen) - { - ucharv t0 = vloadn(0, src1 + src1_index + i); - ucharv t1 = vloadn(0, src2 + src2_index + i); - ucharv t2 = t0 Operation t1; - - vstoren(t2, 0, dst + dst_index + i); - } -#else - dst[dst_index] = src1[src1_index] Operation src2[src2_index]; -#endif - } - } -} diff --git a/modules/ocl/src/opencl/arithm_bitwise_binary_scalar.cl b/modules/ocl/src/opencl/arithm_bitwise_binary_scalar.cl deleted file mode 100644 index 434bd5eca..000000000 --- a/modules/ocl/src/opencl/arithm_bitwise_binary_scalar.cl +++ /dev/null @@ -1,82 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////////////// -// -// 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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jiang Liyuan, jlyuan001.good@163.com -// Peng Xiao, pengxiao@outlook.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. -// -// - -/////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////bitwise_binary///////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_bitwise_binary_scalar( - __global uchar *src1, int src1_step, int src1_offset, - __global uchar *src2, - __global uchar *dst, int dst_step, int dst_offset, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { -#if elemSize > 1 - x *= elemSize; -#endif - int src1_index = mad24(y, src1_step, src1_offset + x); - int dst_index = mad24(y, dst_step, dst_offset + x); - -#if elemSize > 1 - #pragma unroll - for (int i = 0; i < elemSize; i += vlen) - { - ucharv t0 = vloadn(0, src1 + src1_index + i); - ucharv t1 = vloadn(0, src2 + i); - ucharv t2 = t0 Operation t1; - - vstoren(t2, 0, dst + dst_index + i); - } -#else - dst[dst_index] = src1[src1_index] Operation src2[0]; -#endif - } -} diff --git a/modules/ocl/src/opencl/arithm_bitwise_binary_scalar_mask.cl b/modules/ocl/src/opencl/arithm_bitwise_binary_scalar_mask.cl deleted file mode 100644 index 756f20165..000000000 --- a/modules/ocl/src/opencl/arithm_bitwise_binary_scalar_mask.cl +++ /dev/null @@ -1,86 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jiang Liyuan, jlyuan001.good@163.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*/ - -////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////bitwise_binary//////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_bitwise_binary_scalar_mask(__global uchar *src1, int src1_step, int src1_offset, - __global uchar *src2, - __global uchar *mask, int mask_step, int mask_offset, - __global uchar *dst, int dst_step, int dst_offset, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int mask_index = mad24(y, mask_step, x + mask_offset); - - if (mask[mask_index]) - { -#if elemSize > 1 - x *= elemSize; -#endif - int src1_index = mad24(y, src1_step, x + src1_offset); - int dst_index = mad24(y, dst_step, x + dst_offset); - -#if elemSize > 1 - #pragma unroll - for (int i = 0; i < elemSize; i += vlen) - { - ucharv t0 = vloadn(0, src1 + src1_index + i); - ucharv t1 = vloadn(0, src2 + i); - ucharv t2 = t0 Operation t1; - - vstoren(t2, 0, dst + dst_index + i); - } -#else - dst[dst_index] = src1[src1_index] Operation src2[0]; -#endif - } - } -} diff --git a/modules/ocl/src/opencl/arithm_bitwise_not.cl b/modules/ocl/src/opencl/arithm_bitwise_not.cl deleted file mode 100644 index b6f76d606..000000000 --- a/modules/ocl/src/opencl/arithm_bitwise_not.cl +++ /dev/null @@ -1,253 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jiang Liyuan, jlyuan001.good@163.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////BITWISE_NOT//////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_bitwise_not_D0 (__global uchar *src1, int src1_step, int src1_offset, - __global uchar *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - x = x << 2; - int src1_index = mad24(y, src1_step, x + src1_offset); - - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + x); - - uchar4 src1_data = vload4(0, src1 + src1_index); - uchar4 dst_data = vload4(0, dst + dst_index); - uchar4 tmp_data = ~src1_data; - - dst_data.x = dst_index + 0 < dst_end ? tmp_data.x : dst_data.x; - dst_data.y = dst_index + 1 < dst_end ? tmp_data.y : dst_data.y; - dst_data.z = dst_index + 2 < dst_end ? tmp_data.z : dst_data.z; - dst_data.w = dst_index + 3 < dst_end ? tmp_data.w : dst_data.w; - - vstore4(dst_data, 0, dst + dst_index); - } -} - - -__kernel void arithm_bitwise_not_D1 (__global char *src1, int src1_step, int src1_offset, - __global char *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - x = x << 2; - int src1_index = mad24(y, src1_step, x + src1_offset); - - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + x); - - char4 src1_data = vload4(0, src1 + src1_index); - char4 dst_data = vload4(0, dst + dst_index); - char4 tmp_data = ~src1_data; - - dst_data.x = dst_index + 0 < dst_end ? tmp_data.x : dst_data.x; - dst_data.y = dst_index + 1 < dst_end ? tmp_data.y : dst_data.y; - dst_data.z = dst_index + 2 < dst_end ? tmp_data.z : dst_data.z; - dst_data.w = dst_index + 3 < dst_end ? tmp_data.w : dst_data.w; - - vstore4(dst_data, 0, dst + dst_index); - } -} - - -__kernel void arithm_bitwise_not_D2 (__global ushort *src1, int src1_step, int src1_offset, - __global ushort *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) - -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - x = x << 2; - -#ifdef dst_align -#undef dst_align -#endif -#define dst_align ((dst_offset >> 1) & 3) - int src1_index = mad24(y, src1_step, (x << 1) + src1_offset - (dst_align << 1)); - - int dst_start = mad24(y, dst_step, dst_offset); - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + (x << 1) & (int)0xfffffff8); - - ushort4 src1_data = vload4(0, (__global ushort *)((__global char *)src1 + src1_index)); - - ushort4 dst_data = *((__global ushort4 *)((__global char *)dst + dst_index)); - ushort4 tmp_data = ~ src1_data; - - dst_data.x = ((dst_index + 0 >= dst_start) && (dst_index + 0 < dst_end)) ? tmp_data.x : dst_data.x; - dst_data.y = ((dst_index + 2 >= dst_start) && (dst_index + 2 < dst_end)) ? tmp_data.y : dst_data.y; - dst_data.z = ((dst_index + 4 >= dst_start) && (dst_index + 4 < dst_end)) ? tmp_data.z : dst_data.z; - dst_data.w = ((dst_index + 6 >= dst_start) && (dst_index + 6 < dst_end)) ? tmp_data.w : dst_data.w; - - *((__global ushort4 *)((__global char *)dst + dst_index)) = dst_data; - } -} - - - -__kernel void arithm_bitwise_not_D3 (__global short *src1, int src1_step, int src1_offset, - __global short *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) - -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - x = x << 2; - -#ifdef dst_align -#undef dst_align -#endif -#define dst_align ((dst_offset >> 1) & 3) - int src1_index = mad24(y, src1_step, (x << 1) + src1_offset - (dst_align << 1)); - - int dst_start = mad24(y, dst_step, dst_offset); - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + (x << 1) & (int)0xfffffff8); - - short4 src1_data = vload4(0, (__global short *)((__global char *)src1 + src1_index)); - - short4 dst_data = *((__global short4 *)((__global char *)dst + dst_index)); - short4 tmp_data = ~ src1_data; - - dst_data.x = ((dst_index + 0 >= dst_start) && (dst_index + 0 < dst_end)) ? tmp_data.x : dst_data.x; - dst_data.y = ((dst_index + 2 >= dst_start) && (dst_index + 2 < dst_end)) ? tmp_data.y : dst_data.y; - dst_data.z = ((dst_index + 4 >= dst_start) && (dst_index + 4 < dst_end)) ? tmp_data.z : dst_data.z; - dst_data.w = ((dst_index + 6 >= dst_start) && (dst_index + 6 < dst_end)) ? tmp_data.w : dst_data.w; - - *((__global short4 *)((__global char *)dst + dst_index)) = dst_data; - } -} - - - -__kernel void arithm_bitwise_not_D4 (__global int *src1, int src1_step, int src1_offset, - __global int *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step, (x << 2) + src1_offset); - int dst_index = mad24(y, dst_step, (x << 2) + dst_offset); - - int data1 = *((__global int *)((__global char *)src1 + src1_index)); - int tmp = ~ data1; - - *((__global int *)((__global char *)dst + dst_index)) = tmp; - } -} - -__kernel void arithm_bitwise_not_D5 (__global char *src, int src_step, int src_offset, - __global char *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src_index = mad24(y, src_step, (x << 2) + src_offset); - int dst_index = mad24(y, dst_step, (x << 2) + dst_offset); - - char4 data; - - data = *((__global char4 *)((__global char *)src + src_index)); - data = ~ data; - - *((__global char4 *)((__global char *)dst + dst_index)) = data; - } -} - -#if defined (DOUBLE_SUPPORT) -__kernel void arithm_bitwise_not_D6 (__global char *src, int src_step, int src_offset, - __global char *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src_index = mad24(y, src_step, (x << 3) + src_offset); - int dst_index = mad24(y, dst_step, (x << 3) + dst_offset); - - char8 data; - - data = *((__global char8 *)((__global char *)src + src_index)); - data = ~ data; - - *((__global char8 *)((__global char *)dst + dst_index)) = data; - } -} -#endif diff --git a/modules/ocl/src/opencl/arithm_cartToPolar.cl b/modules/ocl/src/opencl/arithm_cartToPolar.cl deleted file mode 100644 index c65f899b7..000000000 --- a/modules/ocl/src/opencl/arithm_cartToPolar.cl +++ /dev/null @@ -1,141 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#define CV_PI M_PI -#else -#define CV_PI M_PI_F -#endif - -__kernel void arithm_cartToPolar_D5 (__global float *src1, int src1_step, int src1_offset, - __global float *src2, int src2_step, int src2_offset, - __global float *dst1, int dst1_step, int dst1_offset, // magnitude - __global float *dst2, int dst2_step, int dst2_offset, // cartToPolar - int rows, int cols) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step, x + src1_offset); - int src2_index = mad24(y, src2_step, x + src2_offset); - - int dst1_index = mad24(y, dst1_step, x + dst1_offset); - int dst2_index = mad24(y, dst2_step, x + dst2_offset); - - float x = src1[src1_index]; - float y = src2[src2_index]; - - float x2 = x * x; - float y2 = y * y; - - float magnitude = sqrt(x2 + y2); - - float tmp = y >= 0 ? 0 : CV_PI*2; - tmp = x < 0 ? CV_PI : tmp; - - float tmp1 = y >= 0 ? CV_PI*0.5f : CV_PI*1.5f; - float cartToPolar = y2 <= x2 ? x*y/(x2 + 0.28f*y2 + FLT_EPSILON) + tmp : - tmp1 - x*y/(y2 + 0.28f*x2 + FLT_EPSILON); - -#ifdef DEGREE - cartToPolar *= (180/CV_PI); -#endif - - dst1[dst1_index] = magnitude; - dst2[dst2_index] = cartToPolar; - } -} - -#if defined (DOUBLE_SUPPORT) - -__kernel void arithm_cartToPolar_D6 (__global double *src1, int src1_step, int src1_offset, - __global double *src2, int src2_step, int src2_offset, - __global double *dst1, int dst1_step, int dst1_offset, - __global double *dst2, int dst2_step, int dst2_offset, - int rows, int cols) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step, x + src1_offset); - int src2_index = mad24(y, src2_step, x + src2_offset); - - int dst1_index = mad24(y, dst1_step, x + dst1_offset); - int dst2_index = mad24(y, dst2_step, x + dst2_offset); - - double x = src1[src1_index]; - double y = src2[src2_index]; - - double x2 = x * x; - double y2 = y * y; - - double magnitude = sqrt(x2 + y2); - - float tmp = y >= 0 ? 0 : CV_PI*2; - tmp = x < 0 ? CV_PI : tmp; - - float tmp1 = y >= 0 ? CV_PI*0.5 : CV_PI*1.5; - double cartToPolar = y2 <= x2 ? x*y/(x2 + 0.28f*y2 + DBL_EPSILON) + tmp : - tmp1 - x*y/(y2 + 0.28f*x2 + DBL_EPSILON); - -#ifdef DEGREE - cartToPolar *= (180/CV_PI); -#endif - - dst1[dst1_index] = magnitude; - dst2[dst2_index] = cartToPolar; - } -} - -#endif diff --git a/modules/ocl/src/opencl/arithm_compare.cl b/modules/ocl/src/opencl/arithm_compare.cl deleted file mode 100644 index 73e6299bb..000000000 --- a/modules/ocl/src/opencl/arithm_compare.cl +++ /dev/null @@ -1,74 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -////////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////addWeighted////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_compare(__global T * src1, int src1_step1, int src1_offset1, - __global T * src2, int src2_step1, int src2_offset1, - __global uchar * dst, int dst_step1, int dst_offset1, - int cols1, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols1 && y < rows) - { - int src1_index = mad24(y, src1_step1, x + src1_offset1); - int src2_index = mad24(y, src2_step1, x + src2_offset1); - int dst_index = mad24(y, dst_step1, x + dst_offset1); - - dst[dst_index] = convert_uchar(src1[src1_index] Operation src2[src2_index] ? 255 : 0); - } -} diff --git a/modules/ocl/src/opencl/arithm_exp.cl b/modules/ocl/src/opencl/arithm_exp.cl deleted file mode 100644 index f0a189353..000000000 --- a/modules/ocl/src/opencl/arithm_exp.cl +++ /dev/null @@ -1,111 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Wu Zailong, bullet@yeah.net -// -// 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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -////////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////EXP////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_exp_C1(__global srcT *src, __global srcT *dst, - int cols1, int rows, - int srcOffset1, int dstOffset1, - int srcStep1, int dstStep1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if(x < cols1 && y < rows) - { - int srcIdx = mad24(y, srcStep1, x + srcOffset1); - int dstIdx = mad24(y, dstStep1, x + dstOffset1); - - dst[dstIdx] = exp(src[srcIdx]); - } -} - -__kernel void arithm_exp_C2(__global srcT *src, __global srcT *dst, - int cols1, int rows, - int srcOffset1, int dstOffset1, - int srcStep1, int dstStep1) -{ - int x1 = get_global_id(0) << 1; - int y = get_global_id(1); - - if(x1 < cols1 && y < rows) - { - int srcIdx = mad24(y, srcStep1, x1 + srcOffset1); - int dstIdx = mad24(y, dstStep1, x1 + dstOffset1); - - dst[dstIdx] = exp(src[srcIdx]); - dst[dstIdx + 1] = x1 + 1 < cols1 ? exp(src[srcIdx + 1]) : dst[dstIdx + 1]; - } -} - -__kernel void arithm_exp_C4(__global srcT *src, __global srcT *dst, - int cols1, int rows, - int srcOffset1, int dstOffset1, - int srcStep1, int dstStep1) -{ - int x1 = get_global_id(0) << 2; - int y = get_global_id(1); - - if(x1 < cols1 && y < rows) - { - int srcIdx = mad24(y, srcStep1, x1 + srcOffset1); - int dstIdx = mad24(y, dstStep1, x1 + dstOffset1); - - dst[dstIdx] = exp(src[srcIdx]); - dst[dstIdx + 1] = x1 + 1 < cols1 ? exp(src[srcIdx + 1]) : dst[dstIdx + 1]; - dst[dstIdx + 2] = x1 + 2 < cols1 ? exp(src[srcIdx + 2]) : dst[dstIdx + 2]; - dst[dstIdx + 3] = x1 + 3 < cols1 ? exp(src[srcIdx + 3]) : dst[dstIdx + 3]; - } -} diff --git a/modules/ocl/src/opencl/arithm_flip.cl b/modules/ocl/src/opencl/arithm_flip.cl deleted file mode 100644 index b9bacd339..000000000 --- a/modules/ocl/src/opencl/arithm_flip.cl +++ /dev/null @@ -1,125 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////// flip rows /////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_flip_rows(__global T * src, int src_step, int src_offset, - __global T * dst, int dst_step, int dst_offset, - int rows, int cols, int thread_rows, int thread_cols) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < thread_rows) - { - int src_index_0 = mad24(y, src_step, x + src_offset); - int src_index_1 = mad24(rows - y - 1, src_step, x + src_offset); - - int dst_index_0 = mad24(y, dst_step, x + dst_offset); - int dst_index_1 = mad24(rows - y - 1, dst_step, x + dst_offset); - - T data0 = src[src_index_0], data1 = src[src_index_1]; - - dst[dst_index_0] = data1; - dst[dst_index_1] = data0; - } -} - -__kernel void arithm_flip_rows_cols(__global T * src, int src_step, int src_offset, - __global T * dst, int dst_step, int dst_offset, - int rows, int cols, int thread_rows, int thread_cols) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < thread_rows) - { - int src_index_0 = mad24(y, src_step, x + src_offset); - int dst_index_0 = mad24(rows - y - 1, dst_step, cols - x - 1 + dst_offset); - - int src_index_1 = mad24(rows - y - 1, src_step, cols - x - 1 + src_offset); - int dst_index_1 = mad24(y, dst_step, x + dst_offset); - - T data0 = src[src_index_0], data1 = src[src_index_1]; - - dst[dst_index_0] = data0; - dst[dst_index_1] = data1; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////// flip cols /////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_flip_cols(__global T * src, int src_step, int src_offset, - __global T * dst, int dst_step, int dst_offset, - int rows, int cols, int thread_rows, int thread_cols) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < thread_cols && y < rows) - { - int src_index_0 = mad24(y, src_step, x + src_offset); - int dst_index_0 = mad24(y, dst_step, cols - x - 1 + dst_offset); - - int src_index_1 = mad24(y, src_step, cols - x - 1 + src_offset); - int dst_index_1 = mad24(y, dst_step, x + dst_offset); - - T data0 = src[src_index_0], data1 = src[src_index_1]; - dst[dst_index_1] = data1; - dst[dst_index_0] = data0; - } -} diff --git a/modules/ocl/src/opencl/arithm_log.cl b/modules/ocl/src/opencl/arithm_log.cl deleted file mode 100644 index ba5f32d6d..000000000 --- a/modules/ocl/src/opencl/arithm_log.cl +++ /dev/null @@ -1,111 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Wu Zailong, bullet@yeah.net -// -// 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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -////////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////LOG///////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_log_C1(__global srcT *src, __global srcT *dst, - int cols1, int rows, - int srcOffset1, int dstOffset1, - int srcStep1, int dstStep1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if(x < cols1 && y < rows) - { - int srcIdx = mad24(y, srcStep1, x + srcOffset1); - int dstIdx = mad24(y, dstStep1, x + dstOffset1); - - dst[dstIdx] = log(src[srcIdx]); - } -} - -__kernel void arithm_log_C2(__global srcT *src, __global srcT *dst, - int cols1, int rows, - int srcOffset1, int dstOffset1, - int srcStep1, int dstStep1) -{ - int x1 = get_global_id(0) << 1; - int y = get_global_id(1); - - if(x1 < cols1 && y < rows) - { - int srcIdx = mad24(y, srcStep1, x1 + srcOffset1); - int dstIdx = mad24(y, dstStep1, x1 + dstOffset1); - - dst[dstIdx] = log(src[srcIdx]); - dst[dstIdx + 1] = x1 + 1 < cols1 ? log(src[srcIdx + 1]) : dst[dstIdx + 1]; - } -} - -__kernel void arithm_log_C4(__global srcT *src, __global srcT *dst, - int cols1, int rows, - int srcOffset1, int dstOffset1, - int srcStep1, int dstStep1) -{ - int x1 = get_global_id(0) << 2; - int y = get_global_id(1); - - if(x1 < cols1 && y < rows) - { - int srcIdx = mad24(y, srcStep1, x1 + srcOffset1); - int dstIdx = mad24(y, dstStep1, x1 + dstOffset1); - - dst[dstIdx] = log(src[srcIdx]); - dst[dstIdx + 1] = x1 + 1 < cols1 ? log(src[srcIdx + 1]) : dst[dstIdx + 1]; - dst[dstIdx + 2] = x1 + 2 < cols1 ? log(src[srcIdx + 2]) : dst[dstIdx + 2]; - dst[dstIdx + 3] = x1 + 3 < cols1 ? log(src[srcIdx + 3]) : dst[dstIdx + 3]; - } -} diff --git a/modules/ocl/src/opencl/arithm_magnitude.cl b/modules/ocl/src/opencl/arithm_magnitude.cl deleted file mode 100644 index 1053efd00..000000000 --- a/modules/ocl/src/opencl/arithm_magnitude.cl +++ /dev/null @@ -1,74 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -__kernel void arithm_magnitude(__global T *src1, int src1_step, int src1_offset, - __global T *src2, int src2_step, int src2_offset, - __global T *dst, int dst_step, int dst_offset, - int rows, int cols) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step, x + src1_offset); - int src2_index = mad24(y, src2_step, x + src2_offset); - int dst_index = mad24(y, dst_step, x + dst_offset); - - T data1 = src1[src1_index]; - T data2 = src2[src2_index]; - - T tmp = hypot(data1, data2); - dst[dst_index] = tmp; - } -} diff --git a/modules/ocl/src/opencl/arithm_minMax.cl b/modules/ocl/src/opencl/arithm_minMax.cl deleted file mode 100644 index 01db7d064..000000000 --- a/modules/ocl/src/opencl/arithm_minMax.cl +++ /dev/null @@ -1,176 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Shengen Yan,yanshengen@gmail.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*/ - -/**************************************PUBLICFUNC*************************************/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#ifdef DEPTH_5 -#define MIN_VAL (-FLT_MAX) -#define MAX_VAL FLT_MAX -#elif defined DEPTH_6 -#define MIN_VAL (-DBL_MAX) -#define MAX_VAL DBL_MAX -#endif - -/**************************************Array minMax**************************************/ - -__kernel void arithm_op_minMax(__global const T * src, __global T * dst, - int cols, int invalid_cols, int offset, int elemnum, int groupnum) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - int id = get_global_id(0); - - int idx = offset + id + (id / cols) * invalid_cols; - - __local T localmem_max[128], localmem_min[128]; - T minval = (T)(MAX_VAL), maxval = (T)(MIN_VAL), temp; - - for (int grainSize = groupnum << 8; id < elemnum; id += grainSize) - { - idx = offset + id + (id / cols) * invalid_cols; - temp = src[idx]; - minval = min(minval, temp); - maxval = max(maxval, temp); - } - - if (lid > 127) - { - localmem_min[lid - 128] = minval; - localmem_max[lid - 128] = maxval; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if (lid < 128) - { - localmem_min[lid] = min(minval, localmem_min[lid]); - localmem_max[lid] = max(maxval, localmem_max[lid]); - } - barrier(CLK_LOCAL_MEM_FENCE); - - for (int lsize = 64; lsize > 0; lsize >>= 1) - { - if (lid < lsize) - { - int lid2 = lsize + lid; - localmem_min[lid] = min(localmem_min[lid], localmem_min[lid2]); - localmem_max[lid] = max(localmem_max[lid], localmem_max[lid2]); - } - barrier(CLK_LOCAL_MEM_FENCE); - } - - if (lid == 0) - { - dst[gid] = localmem_min[0]; - dst[gid + groupnum] = localmem_max[0]; - } -} - -__kernel void arithm_op_minMax_mask(__global const T * src, __global T * dst, - int cols, int invalid_cols, int offset, - int elemnum, int groupnum, - const __global uchar * mask, int minvalid_cols, int moffset) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - int id = get_global_id(0); - - int idx = offset + id + (id / cols) * invalid_cols; - int midx = moffset + id + (id / cols) * minvalid_cols; - - __local T localmem_max[128], localmem_min[128]; - T minval = (T)(MAX_VAL), maxval = (T)(MIN_VAL), temp; - - for (int grainSize = groupnum << 8; id < elemnum; id += grainSize) - { - idx = offset + id + (id / cols) * invalid_cols; - midx = moffset + id + (id / cols) * minvalid_cols; - - if (mask[midx]) - { - temp = src[idx]; - minval = min(minval, temp); - maxval = max(maxval, temp); - } - } - - if (lid > 127) - { - localmem_min[lid - 128] = minval; - localmem_max[lid - 128] = maxval; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if (lid < 128) - { - localmem_min[lid] = min(minval, localmem_min[lid]); - localmem_max[lid] = max(maxval, localmem_max[lid]); - } - barrier(CLK_LOCAL_MEM_FENCE); - - for (int lsize = 64; lsize > 0; lsize >>= 1) - { - if (lid < lsize) - { - int lid2 = lsize + lid; - localmem_min[lid] = min(localmem_min[lid], localmem_min[lid2]); - localmem_max[lid] = max(localmem_max[lid], localmem_max[lid2]); - } - barrier(CLK_LOCAL_MEM_FENCE); - } - - if (lid == 0) - { - dst[gid] = localmem_min[0]; - dst[gid + groupnum] = localmem_max[0]; - } -} diff --git a/modules/ocl/src/opencl/arithm_minMaxLoc.cl b/modules/ocl/src/opencl/arithm_minMaxLoc.cl deleted file mode 100644 index 1aac6c1f6..000000000 --- a/modules/ocl/src/opencl/arithm_minMaxLoc.cl +++ /dev/null @@ -1,258 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Shengen Yan, yanshengen@gmail.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*/ - -/**************************************PUBLICFUNC*************************************/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#define RES_TYPE double4 -#define CONVERT_RES_TYPE convert_double4 -#else -#define RES_TYPE float4 -#define CONVERT_RES_TYPE convert_float4 -#endif - -#if defined (DEPTH_0) -#define VEC_TYPE uchar4 -#define VEC_TYPE_LOC int4 -#define CONVERT_TYPE convert_uchar4 -#define CONDITION_FUNC(a,b,c) (convert_int4(a) ? b : c) -#define MIN_VAL 0 -#define MAX_VAL 255 -#endif -#if defined (DEPTH_1) -#define VEC_TYPE char4 -#define VEC_TYPE_LOC int4 -#define CONVERT_TYPE convert_char4 -#define CONDITION_FUNC(a,b,c) (convert_int4(a) ? b : c) -#define MIN_VAL -128 -#define MAX_VAL 127 -#endif -#if defined (DEPTH_2) -#define VEC_TYPE ushort4 -#define VEC_TYPE_LOC int4 -#define CONVERT_TYPE convert_ushort4 -#define CONDITION_FUNC(a,b,c) (convert_int4(a) ? b : c) -#define MIN_VAL 0 -#define MAX_VAL 65535 -#endif -#if defined (DEPTH_3) -#define VEC_TYPE short4 -#define VEC_TYPE_LOC int4 -#define CONVERT_TYPE convert_short4 -#define CONDITION_FUNC(a,b,c) (convert_int4(a) ? b : c) -#define MIN_VAL -32768 -#define MAX_VAL 32767 -#endif -#if defined (DEPTH_4) -#define VEC_TYPE int4 -#define VEC_TYPE_LOC int4 -#define CONVERT_TYPE convert_int4 -#define CONDITION_FUNC(a,b,c) ((a) ? b : c) -#define MIN_VAL INT_MIN -#define MAX_VAL INT_MAX -#endif -#if defined (DEPTH_5) -#define VEC_TYPE float4 -#define VEC_TYPE_LOC float4 -#define CONVERT_TYPE convert_float4 -#define CONDITION_FUNC(a,b,c) ((a) ? b : c) -#define MIN_VAL (-FLT_MAX) -#define MAX_VAL FLT_MAX -#endif -#if defined (DEPTH_6) -#define VEC_TYPE double4 -#define VEC_TYPE_LOC double4 -#define CONVERT_TYPE convert_double4 -#define CONDITION_FUNC(a,b,c) ((a) ? b : c) -#define MIN_VAL (-DBL_MAX) -#define MAX_VAL DBL_MAX -#endif - -#if defined (REPEAT_S0) -#define repeat_s(a) a=a; -#endif -#if defined (REPEAT_S1) -#define repeat_s(a) a.s0 = a.s1; -#endif -#if defined (REPEAT_S2) -#define repeat_s(a) a.s0 = a.s2;a.s1 = a.s2; -#endif -#if defined (REPEAT_S3) -#define repeat_s(a) a.s0 = a.s3;a.s1 = a.s3;a.s2 = a.s3; -#endif - - -#if defined (REPEAT_E0) -#define repeat_e(a) a=a; -#endif -#if defined (REPEAT_E1) -#define repeat_e(a) a.s3 = a.s2; -#endif -#if defined (REPEAT_E2) -#define repeat_e(a) a.s3 = a.s1;a.s2 = a.s1; -#endif -#if defined (REPEAT_E3) -#define repeat_e(a) a.s3 = a.s0;a.s2 = a.s0;a.s1 = a.s0; -#endif - -/**************************************Array minMax**************************************/ - -__kernel void arithm_op_minMaxLoc(int cols, int invalid_cols, int offset, int elemnum, int groupnum, - __global VEC_TYPE *src, __global RES_TYPE *dst) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - int id = get_global_id(0); - int idx = offset + id + (id / cols) * invalid_cols; - - __local VEC_TYPE localmem_max[128], localmem_min[128]; - VEC_TYPE minval, maxval, temp; - - __local VEC_TYPE_LOC localmem_maxloc[128], localmem_minloc[128]; - VEC_TYPE_LOC minloc, maxloc, temploc, negative = -1; - - int idx_c; - - if (id < elemnum) - { - temp = src[idx]; - idx_c = idx << 2; - temploc = (VEC_TYPE_LOC)(idx_c, idx_c + 1, idx_c + 2, idx_c + 3); - - if (id % cols == 0 ) - { - repeat_s(temp); - repeat_s(temploc); - } - if (id % cols == cols - 1) - { - repeat_e(temp); - repeat_e(temploc); - } - minval = temp; - maxval = temp; - minloc = temploc; - maxloc = temploc; - } - else - { - minval = MAX_VAL; - maxval = MIN_VAL; - minloc = negative; - maxloc = negative; - } - - int grainSize = (groupnum << 8); - for (id = id + grainSize; id < elemnum; id = id + grainSize) - { - idx = offset + id + (id / cols) * invalid_cols; - temp = src[idx]; - idx_c = idx << 2; - temploc = (VEC_TYPE_LOC)(idx_c, idx_c+1, idx_c+2, idx_c+3); - - if (id % cols == 0 ) - { - repeat_s(temp); - repeat_s(temploc); - } - if (id % cols == cols - 1) - { - repeat_e(temp); - repeat_e(temploc); - } - - minval = min(minval, temp); - maxval = max(maxval, temp); - minloc = CONDITION_FUNC(minval == temp, temploc, minloc); - maxloc = CONDITION_FUNC(maxval == temp, temploc, maxloc); - } - - if (lid > 127) - { - localmem_min[lid - 128] = minval; - localmem_max[lid - 128] = maxval; - localmem_minloc[lid - 128] = minloc; - localmem_maxloc[lid - 128] = maxloc; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if (lid < 128) - { - localmem_min[lid] = min(minval,localmem_min[lid]); - localmem_max[lid] = max(maxval,localmem_max[lid]); - VEC_TYPE minVal = localmem_min[lid], maxVal = localmem_max[lid]; - localmem_minloc[lid] = CONDITION_FUNC(minVal == minval, minloc, localmem_minloc[lid]); - localmem_maxloc[lid] = CONDITION_FUNC(maxVal == maxval, maxloc, localmem_maxloc[lid]); - } - barrier(CLK_LOCAL_MEM_FENCE); - - for (int lsize = 64; lsize > 0; lsize >>= 1) - { - if (lid < lsize) - { - int lid2 = lsize + lid; - localmem_min[lid] = min(localmem_min[lid], localmem_min[lid2]); - localmem_max[lid] = max(localmem_max[lid], localmem_max[lid2]); - VEC_TYPE min1 = localmem_min[lid], min2 = localmem_min[lid2]; - localmem_minloc[lid] = CONDITION_FUNC(min1 == min2, localmem_minloc[lid2], localmem_minloc[lid]); - VEC_TYPE max1 = localmem_max[lid], max2 = localmem_max[lid2]; - localmem_maxloc[lid] = CONDITION_FUNC(max1 == max2, localmem_maxloc[lid2], localmem_maxloc[lid]); - } - barrier(CLK_LOCAL_MEM_FENCE); - } - - if ( lid == 0) - { - dst[gid] = CONVERT_RES_TYPE(localmem_min[0]); - dst[gid + groupnum] = CONVERT_RES_TYPE(localmem_max[0]); - dst[gid + 2 * groupnum] = CONVERT_RES_TYPE(localmem_minloc[0]); - dst[gid + 3 * groupnum] = CONVERT_RES_TYPE(localmem_maxloc[0]); - } -} diff --git a/modules/ocl/src/opencl/arithm_minMaxLoc_mask.cl b/modules/ocl/src/opencl/arithm_minMaxLoc_mask.cl deleted file mode 100644 index 84b26cae3..000000000 --- a/modules/ocl/src/opencl/arithm_minMaxLoc_mask.cl +++ /dev/null @@ -1,256 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Shengen Yan, yanshengen@gmail.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*/ - -/**************************************PUBLICFUNC*************************************/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#define RES_TYPE double4 -#define CONVERT_RES_TYPE convert_double4 -#else -#define RES_TYPE float4 -#define CONVERT_RES_TYPE convert_float4 -#endif - -#if defined (DEPTH_0) -#define TYPE uchar -#define VEC_TYPE uchar4 -#define VEC_TYPE_LOC int4 -#define CONVERT_TYPE convert_uchar4 -#define CONDITION_FUNC(a,b,c) (convert_int4(a) ? b : c) -#define MIN_VAL 0 -#define MAX_VAL 255 -#endif -#if defined (DEPTH_1) -#define TYPE char -#define VEC_TYPE char4 -#define VEC_TYPE_LOC int4 -#define CONVERT_TYPE convert_char4 -#define CONDITION_FUNC(a,b,c) (convert_int4(a) ? b : c) -#define MIN_VAL -128 -#define MAX_VAL 127 -#endif -#if defined (DEPTH_2) -#define TYPE ushort -#define VEC_TYPE ushort4 -#define VEC_TYPE_LOC int4 -#define CONVERT_TYPE convert_ushort4 -#define CONDITION_FUNC(a,b,c) (convert_int4(a) ? b : c) -#define MIN_VAL 0 -#define MAX_VAL 65535 -#endif -#if defined (DEPTH_3) -#define TYPE short -#define VEC_TYPE short4 -#define VEC_TYPE_LOC int4 -#define CONVERT_TYPE convert_short4 -#define CONDITION_FUNC(a,b,c) (convert_int4(a) ? b : c) -#define MIN_VAL -32768 -#define MAX_VAL 32767 -#endif -#if defined (DEPTH_4) -#define TYPE int -#define VEC_TYPE int4 -#define VEC_TYPE_LOC int4 -#define CONVERT_TYPE convert_int4 -#define CONDITION_FUNC(a,b,c) ((a) ? b : c) -#define MIN_VAL INT_MIN -#define MAX_VAL INT_MAX -#endif -#if defined (DEPTH_5) -#define TYPE float -#define VEC_TYPE float4 -#define VEC_TYPE_LOC float4 -#define CONVERT_TYPE convert_float4 -#define CONDITION_FUNC(a,b,c) ((a) ? b : c) -#define MIN_VAL (-FLT_MAX) -#define MAX_VAL FLT_MAX -#endif -#if defined (DEPTH_6) -#define TYPE double -#define VEC_TYPE double4 -#define VEC_TYPE_LOC double4 -#define CONVERT_TYPE convert_double4 -#define CONDITION_FUNC(a,b,c) ((a) ? b : c) -#define MIN_VAL (-DBL_MAX) -#define MAX_VAL DBL_MAX -#endif - -#if defined (REPEAT_E0) -#define repeat_e(a) a=a; -#endif -#if defined (REPEAT_E1) -#define repeat_e(a) a.s3 = a.s2; -#endif -#if defined (REPEAT_E2) -#define repeat_e(a) a.s3 = a.s1;a.s2 = a.s1; -#endif -#if defined (REPEAT_E3) -#define repeat_e(a) a.s3 = a.s0;a.s2 = a.s0;a.s1 = a.s0; -#endif - -#if defined (REPEAT_E0) -#define repeat_me(a) a = a; -#endif -#if defined (REPEAT_E1) -#define repeat_me(a) a.s3 = 0; -#endif -#if defined (REPEAT_E2) -#define repeat_me(a) a.s3 = 0;a.s2 = 0; -#endif -#if defined (REPEAT_E3) -#define repeat_me(a) a.s3 = 0;a.s2 = 0;a.s1 = 0; -#endif - -/**************************************Array minMaxLoc mask**************************************/ -__kernel void arithm_op_minMaxLoc_mask (int cols,int invalid_cols,int offset,int elemnum,int groupnum,__global TYPE *src, - int minvalid_cols,int moffset,__global uchar *mask,__global RES_TYPE *dst) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - int id = get_global_id(0); - int idx = id + (id / cols) * invalid_cols; - int midx = id + (id / cols) * minvalid_cols; - - __local VEC_TYPE lm_max[128],lm_min[128]; - VEC_TYPE minval, maxval, temp, m_temp, zeroVal = (VEC_TYPE)(0); - __local VEC_TYPE_LOC lm_maxloc[128], lm_minloc[128]; - VEC_TYPE_LOC minloc, maxloc, temploc, negative = -1, one = 1, zero = 0; - - if(id < elemnum) - { - temp = vload4(idx, &src[offset]); - m_temp = CONVERT_TYPE(vload4(midx,&mask[moffset])); - int idx_c = (idx << 2) + offset; - temploc = (VEC_TYPE_LOC)(idx_c,idx_c+1,idx_c+2,idx_c+3); - if (id % cols == cols - 1) - { - repeat_me(m_temp); - repeat_e(temploc); - } - minval = m_temp != zeroVal ? temp : (VEC_TYPE)MAX_VAL; - maxval = m_temp != zeroVal ? temp : (VEC_TYPE)MIN_VAL; - minloc = CONDITION_FUNC(m_temp != zeroVal, temploc , negative); - maxloc = minloc; - } - else - { - minval = MAX_VAL; - maxval = MIN_VAL; - minloc = negative; - maxloc = negative; - } - - for(id=id + (groupnum << 8); id < elemnum;id = id + (groupnum << 8)) - { - idx = id + (id / cols) * invalid_cols; - midx = id + (id / cols) * minvalid_cols; - temp = vload4(idx, &src[offset]); - m_temp = CONVERT_TYPE(vload4(midx,&mask[moffset])); - int idx_c = (idx << 2) + offset; - temploc = (VEC_TYPE_LOC)(idx_c,idx_c+1,idx_c+2,idx_c+3); - if (id % cols == cols - 1) - { - repeat_me(m_temp); - repeat_e(temploc); - } - minval = min(minval, m_temp != zeroVal ? temp : minval); - maxval = max(maxval, m_temp != zeroVal ? temp : maxval); - - minloc = CONDITION_FUNC(minval == temp && m_temp != zeroVal, temploc , minloc); - maxloc = CONDITION_FUNC(maxval == temp && m_temp != zeroVal, temploc , maxloc); - } - - if(lid > 127) - { - lm_min[lid - 128] = minval; - lm_max[lid - 128] = maxval; - lm_minloc[lid - 128] = minloc; - lm_maxloc[lid - 128] = maxloc; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(lid < 128) - { - lm_min[lid] = min(minval, lm_min[lid]); - lm_max[lid] = max(maxval, lm_max[lid]); - VEC_TYPE con_min = CONVERT_TYPE(minloc != negative ? one : zero); - VEC_TYPE con_max = CONVERT_TYPE(maxloc != negative ? one : zero); - VEC_TYPE lmMinVal = lm_min[lid], lmMaxVal = lm_max[lid]; - lm_minloc[lid] = CONDITION_FUNC(lmMinVal == minval && con_min != zeroVal, minloc , lm_minloc[lid]); - lm_maxloc[lid] = CONDITION_FUNC(lmMaxVal == maxval && con_max != zeroVal, maxloc , lm_maxloc[lid]); - } - barrier(CLK_LOCAL_MEM_FENCE); - - for(int lsize = 64; lsize > 0; lsize >>= 1) - { - if(lid < lsize) - { - int lid2 = lsize + lid; - lm_min[lid] = min(lm_min[lid], lm_min[lid2]); - lm_max[lid] = max(lm_max[lid], lm_max[lid2]); - VEC_TYPE con_min = CONVERT_TYPE(lm_minloc[lid2] != negative ? one : zero); - VEC_TYPE con_max = CONVERT_TYPE(lm_maxloc[lid2] != negative ? one : zero); - - VEC_TYPE lmMinVal1 = lm_min[lid], lmMinVal2 = lm_min[lid2]; - VEC_TYPE lmMaxVal1 = lm_max[lid], lmMaxVal2 = lm_max[lid2]; - lm_minloc[lid] = CONDITION_FUNC(lmMinVal1 == lmMinVal2 && con_min != zeroVal, lm_minloc[lid2] , lm_minloc[lid]); - lm_maxloc[lid] = CONDITION_FUNC(lmMaxVal1 == lmMaxVal2 && con_max != zeroVal, lm_maxloc[lid2] , lm_maxloc[lid]); - } - barrier(CLK_LOCAL_MEM_FENCE); - } - - if( lid == 0) - { - dst[gid] = CONVERT_RES_TYPE(lm_min[0]); - dst[gid + groupnum] = CONVERT_RES_TYPE(lm_max[0]); - dst[gid + 2 * groupnum] = CONVERT_RES_TYPE(lm_minloc[0]); - dst[gid + 3 * groupnum] = CONVERT_RES_TYPE(lm_maxloc[0]); - } -} diff --git a/modules/ocl/src/opencl/arithm_nonzero.cl b/modules/ocl/src/opencl/arithm_nonzero.cl deleted file mode 100644 index 3180c26e8..000000000 --- a/modules/ocl/src/opencl/arithm_nonzero.cl +++ /dev/null @@ -1,93 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////////////// -// -// 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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Shengen Yan,yanshengen@gmail.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. -// - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -/**************************************Count NonZero**************************************/ - -__kernel void arithm_op_nonzero(int cols, int invalid_cols, int offset, int elemnum, int groupnum, - __global srcT *src, __global dstT *dst) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - int id = get_global_id(0); - - int idx = offset + id + (id / cols) * invalid_cols; - __local dstT localmem_nonzero[128]; - dstT nonzero = (dstT)(0); - srcT zero = (srcT)(0), one = (srcT)(1); - - for (int grain = groupnum << 8; id < elemnum; id += grain) - { - idx = offset + id + (id / cols) * invalid_cols; - nonzero += src[idx] == zero ? zero : one; - } - - if (lid > 127) - localmem_nonzero[lid - 128] = nonzero; - barrier(CLK_LOCAL_MEM_FENCE); - - if (lid < 128) - localmem_nonzero[lid] = nonzero + localmem_nonzero[lid]; - barrier(CLK_LOCAL_MEM_FENCE); - - for (int lsize = 64; lsize > 0; lsize >>= 1) - { - if (lid < lsize) - { - int lid2 = lsize + lid; - localmem_nonzero[lid] = localmem_nonzero[lid] + localmem_nonzero[lid2]; - } - barrier(CLK_LOCAL_MEM_FENCE); - } - - if (lid == 0) - dst[gid] = localmem_nonzero[0]; -} diff --git a/modules/ocl/src/opencl/arithm_phase.cl b/modules/ocl/src/opencl/arithm_phase.cl deleted file mode 100644 index 40346b2cd..000000000 --- a/modules/ocl/src/opencl/arithm_phase.cl +++ /dev/null @@ -1,171 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////////////// -// -// 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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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. -// -// - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#define CV_PI M_PI -#define CV_2PI (2 * CV_PI) -#else -#define CV_PI M_PI_F -#define CV_2PI (2 * CV_PI) -#endif - -/**************************************phase inradians**************************************/ - -__kernel void arithm_phase_inradians_D5(__global float *src1, int src1_step1, int src1_offset1, - __global float *src2, int src2_step1, int src2_offset1, - __global float *dst, int dst_step1, int dst_offset1, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step1, x + src1_offset1); - int src2_index = mad24(y, src2_step1, x + src2_offset1); - int dst_index = mad24(y, dst_step1, x + dst_offset1); - - float data1 = src1[src1_index]; - float data2 = src2[src2_index]; - float tmp = atan2(data2, data1); - - if (tmp < 0) - tmp += CV_2PI; - - dst[dst_index] = tmp; - } -} - - -#if defined (DOUBLE_SUPPORT) -__kernel void arithm_phase_inradians_D6(__global double *src1, int src1_step1, int src1_offset1, - __global double *src2, int src2_step1, int src2_offset1, - __global double *dst, int dst_step1, int dst_offset1, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step1, x + src1_offset1); - int src2_index = mad24(y, src2_step1, x + src2_offset1); - int dst_index = mad24(y, dst_step1, x + dst_offset1); - - double data1 = src1[src1_index]; - double data2 = src2[src2_index]; - double tmp = atan2(data2, data1); - - if (tmp < 0) - tmp += CV_2PI; - - dst[dst_index] = tmp; - } -} - -#endif - -/**************************************phase indegrees**************************************/ - -__kernel void arithm_phase_indegrees_D5(__global float *src1, int src1_step1, int src1_offset1, - __global float *src2, int src2_step1, int src2_offset1, - __global float *dst, int dst_step1, int dst_offset1, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step1, x + src1_offset1); - int src2_index = mad24(y, src2_step1, x + src2_offset1); - int dst_index = mad24(y, dst_step1, x + dst_offset1); - - float data1 = src1[src1_index]; - float data2 = src2[src2_index]; - float tmp = atan2(data2, data1); - tmp = 180 * tmp / CV_PI; - - if (tmp < 0) - tmp += 360; - - dst[dst_index] = tmp; - } -} - - -#if defined (DOUBLE_SUPPORT) -__kernel void arithm_phase_indegrees_D6 (__global double *src1, int src1_step1, int src1_offset1, - __global double *src2, int src2_step1, int src2_offset1, - __global double *dst, int dst_step1, int dst_offset1, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step1, x + src1_offset1); - int src2_index = mad24(y, src2_step1, x + src2_offset1); - int dst_index = mad24(y, dst_step1, x + dst_offset1); - - double data1 = src1[src1_index]; - double data2 = src2[src2_index]; - double tmp = atan2(data2, data1); - - tmp = 180 * tmp / CV_PI; - if (tmp < 0) - tmp += 360; - - dst[dst_index] = tmp; - } -} -#endif diff --git a/modules/ocl/src/opencl/arithm_polarToCart.cl b/modules/ocl/src/opencl/arithm_polarToCart.cl deleted file mode 100644 index 024f1f0ee..000000000 --- a/modules/ocl/src/opencl/arithm_polarToCart.cl +++ /dev/null @@ -1,197 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#define CV_PI M_PI -#else -#define CV_PI M_PI_F -#endif - -///////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////polarToCart with magnitude////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_polarToCart_mag_D5 (__global float *src1, int src1_step, int src1_offset,//magnitue - __global float *src2, int src2_step, int src2_offset,//angle - __global float *dst1, int dst1_step, int dst1_offset, - __global float *dst2, int dst2_step, int dst2_offset, - int rows, int cols) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step, x + src1_offset); - int src2_index = mad24(y, src2_step, x + src2_offset); - - int dst1_index = mad24(y, dst1_step, x + dst1_offset); - int dst2_index = mad24(y, dst2_step, x + dst2_offset); - - float x = src1[src1_index]; - float y = src2[src2_index]; - -#ifdef DEGREE - float ascale = CV_PI/180.0f; - float alpha = y * ascale; -#else - float alpha = y; -#endif - float a = cos(alpha) * x; - float b = sin(alpha) * x; - - dst1[dst1_index] = a; - dst2[dst2_index] = b; - } -} - -#if defined (DOUBLE_SUPPORT) -__kernel void arithm_polarToCart_mag_D6 (__global double *src1, int src1_step, int src1_offset,//magnitue - __global double *src2, int src2_step, int src2_offset,//angle - __global double *dst1, int dst1_step, int dst1_offset, - __global double *dst2, int dst2_step, int dst2_offset, - int rows, int cols) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step, x + src1_offset); - int src2_index = mad24(y, src2_step, x + src2_offset); - - int dst1_index = mad24(y, dst1_step, x + dst1_offset); - int dst2_index = mad24(y, dst2_step, x + dst2_offset); - - double x = src1[src1_index]; - double y = src2[src2_index]; - -#ifdef DEGREE - float ascale = CV_PI/180.0; - float alpha = y * ascale; -#else - float alpha = y; -#endif - double a = cos(alpha) * x; - double b = sin(alpha) * x; - - dst1[dst1_index] = a; - dst2[dst2_index] = b; - } -} -#endif - -///////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////polarToCart without magnitude////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_polarToCart_D5 (__global float *src, int src_step, int src_offset,//angle - __global float *dst1, int dst1_step, int dst1_offset, - __global float *dst2, int dst2_step, int dst2_offset, - int rows, int cols) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src_index = mad24(y, src_step, x + src_offset); - - int dst1_index = mad24(y, dst1_step, x + dst1_offset); - int dst2_index = mad24(y, dst2_step, x + dst2_offset); - - float y = src[src_index]; - -#ifdef DEGREE - float ascale = CV_PI/180.0f; - float alpha = y * ascale; -#else - float alpha = y; -#endif - float a = cos(alpha); - float b = sin(alpha); - - dst1[dst1_index] = a; - dst2[dst2_index] = b; - } -} - -#if defined (DOUBLE_SUPPORT) -__kernel void arithm_polarToCart_D6 (__global float *src, int src_step, int src_offset,//angle - __global float *dst1, int dst1_step, int dst1_offset, - __global float *dst2, int dst2_step, int dst2_offset, - int rows, int cols) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src_index = mad24(y, src_step, x + src_offset); - - int dst1_index = mad24(y, dst1_step, x + dst1_offset); - int dst2_index = mad24(y, dst2_step, x + dst2_offset); - - double y = src[src_index]; - -#ifdef DEGREE - float ascale = CV_PI/180.0f; - float alpha = y * ascale; -#else - float alpha = y; -#endif - double a = cos(alpha); - double b = sin(alpha); - - dst1[dst1_index] = a; - dst2[dst2_index] = b; - } -} -#endif diff --git a/modules/ocl/src/opencl/arithm_pow.cl b/modules/ocl/src/opencl/arithm_pow.cl deleted file mode 100644 index 385e4cc15..000000000 --- a/modules/ocl/src/opencl/arithm_pow.cl +++ /dev/null @@ -1,73 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jiang Liyuan, jlyuan001.good@163.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -/************************************** pow **************************************/ - -__kernel void arithm_pow(__global VT * src, int src_step, int src_offset, - __global VT * dst, int dst_step, int dst_offset, - int rows, int cols, T p) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src_index = mad24(y, src_step, x + src_offset); - int dst_index = mad24(y, dst_step, x + dst_offset); - - VT src_data = src[src_index]; - VT tmp = src_data > 0 ? exp(p * log(src_data)) : (src_data == 0 ? 0 : exp(p * log(fabs(src_data)))); - - dst[dst_index] = tmp; - } -} diff --git a/modules/ocl/src/opencl/arithm_setidentity.cl b/modules/ocl/src/opencl/arithm_setidentity.cl deleted file mode 100644 index 0ead5b003..000000000 --- a/modules/ocl/src/opencl/arithm_setidentity.cl +++ /dev/null @@ -1,69 +0,0 @@ -/*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 -// 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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -__kernel void setIdentity(__global T * src, int src_step, int src_offset, - int cols, int rows, __global const T * scalar) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src_index = mad24(y, src_step, src_offset + x); - - if (x == y) - src[src_index] = *scalar; - else - src[src_index] = 0; - } -} diff --git a/modules/ocl/src/opencl/arithm_sqrt.cl b/modules/ocl/src/opencl/arithm_sqrt.cl deleted file mode 100644 index 142a52ada..000000000 --- a/modules/ocl/src/opencl/arithm_sqrt.cl +++ /dev/null @@ -1,111 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Peter Andreas Entschev, peter@entschev.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -////////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////LOG///////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_sqrt_C1(__global srcT *src, __global srcT *dst, - int cols1, int rows, - int srcOffset1, int dstOffset1, - int srcStep1, int dstStep1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if(x < cols1 && y < rows) - { - int srcIdx = mad24(y, srcStep1, x + srcOffset1); - int dstIdx = mad24(y, dstStep1, x + dstOffset1); - - dst[dstIdx] = sqrt(src[srcIdx]); - } -} - -__kernel void arithm_sqrt_C2(__global srcT *src, __global srcT *dst, - int cols1, int rows, - int srcOffset1, int dstOffset1, - int srcStep1, int dstStep1) -{ - int x1 = get_global_id(0) << 1; - int y = get_global_id(1); - - if(x1 < cols1 && y < rows) - { - int srcIdx = mad24(y, srcStep1, x1 + srcOffset1); - int dstIdx = mad24(y, dstStep1, x1 + dstOffset1); - - dst[dstIdx] = sqrt(src[srcIdx]); - dst[dstIdx + 1] = x1 + 1 < cols1 ? sqrt(src[srcIdx + 1]) : dst[dstIdx + 1]; - } -} - -__kernel void arithm_sqrt_C4(__global srcT *src, __global srcT *dst, - int cols1, int rows, - int srcOffset1, int dstOffset1, - int srcStep1, int dstStep1) -{ - int x1 = get_global_id(0) << 2; - int y = get_global_id(1); - - if(x1 < cols1 && y < rows) - { - int srcIdx = mad24(y, srcStep1, x1 + srcOffset1); - int dstIdx = mad24(y, dstStep1, x1 + dstOffset1); - - dst[dstIdx] = sqrt(src[srcIdx]); - dst[dstIdx + 1] = x1 + 1 < cols1 ? sqrt(src[srcIdx + 1]) : dst[dstIdx + 1]; - dst[dstIdx + 2] = x1 + 2 < cols1 ? sqrt(src[srcIdx + 2]) : dst[dstIdx + 2]; - dst[dstIdx + 3] = x1 + 3 < cols1 ? sqrt(src[srcIdx + 3]) : dst[dstIdx + 3]; - } -} diff --git a/modules/ocl/src/opencl/arithm_sum.cl b/modules/ocl/src/opencl/arithm_sum.cl deleted file mode 100644 index 514cf2a7f..000000000 --- a/modules/ocl/src/opencl/arithm_sum.cl +++ /dev/null @@ -1,104 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Shengen Yan,yanshengen@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#if FUNC_SUM -#define FUNC(a, b) b += a; -#elif FUNC_ABS_SUM -#define FUNC(a, b) b += a >= (dstT)(0) ? a : -a; -#elif FUNC_SQR_SUM -#define FUNC(a, b) b += a * a; -#else -#error No sum function -#endif - -/**************************************Array buffer SUM**************************************/ - -__kernel void arithm_op_sum(int cols,int invalid_cols,int offset,int elemnum,int groupnum, - __global srcT *src, __global dstT *dst) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - int id = get_global_id(0); - int idx = offset + id + (id / cols) * invalid_cols; - - __local dstT localmem_sum[128]; - dstT sum = (dstT)(0), temp; - - for (int grainSize = groupnum << 8; id < elemnum; id += grainSize) - { - idx = offset + id + (id / cols) * invalid_cols; - temp = convertToDstT(src[idx]); - FUNC(temp, sum); - } - - if (lid > 127) - localmem_sum[lid - 128] = sum; - barrier(CLK_LOCAL_MEM_FENCE); - - if (lid < 128) - localmem_sum[lid] = sum + localmem_sum[lid]; - barrier(CLK_LOCAL_MEM_FENCE); - - for (int lsize = 64; lsize > 0; lsize >>= 1) - { - if (lid < lsize) - { - int lid2 = lsize + lid; - localmem_sum[lid] = localmem_sum[lid] + localmem_sum[lid2]; - } - barrier(CLK_LOCAL_MEM_FENCE); - } - - if (lid == 0) - dst[gid] = localmem_sum[0]; -} diff --git a/modules/ocl/src/opencl/arithm_transpose.cl b/modules/ocl/src/opencl/arithm_transpose.cl deleted file mode 100644 index 8cde6544e..000000000 --- a/modules/ocl/src/opencl/arithm_transpose.cl +++ /dev/null @@ -1,139 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#define TILE_DIM 32 -#define BLOCK_ROWS 8 -#define LDS_STEP TILE_DIM - -__kernel void transpose(__global const T* src, __global T* dst, - int src_cols, int src_rows, - int src_step, int dst_step, - int src_offset, int dst_offset) -{ - int gp_x = get_group_id(0), gp_y = get_group_id(1); - int gs_x = get_num_groups(0), gs_y = get_num_groups(1); - - int groupId_x, groupId_y; - - if(src_rows == src_cols) - { - groupId_y = gp_x; - groupId_x = (gp_x + gp_y) % gs_x; - } - else - { - int bid = gp_x + gs_x * gp_y; - groupId_y = bid % gs_y; - groupId_x = ((bid / gs_y) + groupId_y) % gs_x; - } - - int lx = get_local_id(0); - int ly = get_local_id(1); - - int x = groupId_x * TILE_DIM + lx; - int y = groupId_y * TILE_DIM + ly; - - int x_index = groupId_y * TILE_DIM + lx; - int y_index = groupId_x * TILE_DIM + ly; - - __local T title[TILE_DIM * LDS_STEP]; - - if (x < src_cols && y < src_rows) - { - int index_src = mad24(y, src_step, x); - - for(int i = 0; i < TILE_DIM; i += BLOCK_ROWS) - { - if (y + i < src_rows) - { - title[(ly + i) * LDS_STEP + lx] = src[src_offset + index_src]; - index_src = mad24(BLOCK_ROWS, src_step, index_src); - } - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (x_index < src_rows && y_index < src_cols) - { - int index_dst = mad24(y_index, dst_step, x_index); - - for(int i = 0; i < TILE_DIM; i += BLOCK_ROWS) - { - if ((y_index + i) < src_cols) - { - dst[dst_offset + index_dst] = title[lx * LDS_STEP + ly + i]; - index_dst += dst_step * BLOCK_ROWS; - } - } - } -} - -__kernel void transpose_inplace(__global T* src, __global T* dst, - int src_cols, int src_rows, - int src_step, int dst_step, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < src_rows && x < y) - { - int srcIdx = mad24(y, src_step, src_offset + x); - int dstIdx = mad24(x, dst_step, dst_offset + y); - - T tmp = dst[dstIdx]; - dst[dstIdx] = src[srcIdx]; - src[srcIdx] = tmp; - } -} diff --git a/modules/ocl/src/opencl/bgfg_mog.cl b/modules/ocl/src/opencl/bgfg_mog.cl deleted file mode 100644 index 6a95316f0..000000000 --- a/modules/ocl/src/opencl/bgfg_mog.cl +++ /dev/null @@ -1,540 +0,0 @@ -/*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-2013, Multicoreware, Inc., all rights reserved. -// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// 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*/ - -#if defined (CN1) -#define T_FRAME uchar -#define T_MEAN_VAR float -#define CONVERT_TYPE convert_uchar_sat -#define F_ZERO (0.0f) -inline float cvt(uchar val) -{ - return val; -} - -inline float sqr(float val) -{ - return val * val; -} - -inline float sum(float val) -{ - return val; -} - -inline float clamp1(float var, float learningRate, float diff, float minVar) -{ - return fmax(var + learningRate * (diff * diff - var), minVar); -} - -#else - -#define T_FRAME uchar4 -#define T_MEAN_VAR float4 -#define CONVERT_TYPE convert_uchar4_sat -#define F_ZERO (0.0f, 0.0f, 0.0f, 0.0f) - -inline float4 cvt(const uchar4 val) -{ - float4 result; - result.x = val.x; - result.y = val.y; - result.z = val.z; - result.w = val.w; - - return result; -} - -inline float sqr(const float4 val) -{ - return val.x * val.x + val.y * val.y + val.z * val.z; -} - -inline float sum(const float4 val) -{ - return (val.x + val.y + val.z); -} - -inline void swap4(__global float4* ptr, int x, int y, int k, int rows, int ptr_step) -{ - float4 val = ptr[(k * rows + y) * ptr_step + x]; - ptr[(k * rows + y) * ptr_step + x] = ptr[((k + 1) * rows + y) * ptr_step + x]; - ptr[((k + 1) * rows + y) * ptr_step + x] = val; -} - - -inline float4 clamp1(const float4 var, float learningRate, const float4 diff, float minVar) -{ - float4 result; - result.x = fmax(var.x + learningRate * (diff.x * diff.x - var.x), minVar); - result.y = fmax(var.y + learningRate * (diff.y * diff.y - var.y), minVar); - result.z = fmax(var.z + learningRate * (diff.z * diff.z - var.z), minVar); - result.w = 0.0f; - return result; -} - -#endif - -typedef struct -{ - float c_Tb; - float c_TB; - float c_Tg; - float c_varInit; - float c_varMin; - float c_varMax; - float c_tau; - uchar c_shadowVal; -} con_srtuct_t; - -inline void swap(__global float* ptr, int x, int y, int k, int rows, int ptr_step) -{ - float val = ptr[(k * rows + y) * ptr_step + x]; - ptr[(k * rows + y) * ptr_step + x] = ptr[((k + 1) * rows + y) * ptr_step + x]; - ptr[((k + 1) * rows + y) * ptr_step + x] = val; -} - -__kernel void mog_withoutLearning_kernel(__global T_FRAME* frame, __global uchar* fgmask, - __global float* weight, __global T_MEAN_VAR* mean, __global T_MEAN_VAR* var, - int frame_row, int frame_col, int frame_step, int fgmask_step, - int weight_step, int mean_step, int var_step, - float varThreshold, float backgroundRatio, int fgmask_offset_x, - int fgmask_offset_y, int frame_offset_x, int frame_offset_y) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < frame_col && y < frame_row) - { - T_MEAN_VAR pix = cvt(frame[(y + frame_offset_y) * frame_step + (x + frame_offset_x)]); - - int kHit = -1; - int kForeground = -1; - - for (int k = 0; k < (NMIXTURES); ++k) - { - if (weight[(k * frame_row + y) * weight_step + x] < 1.192092896e-07f) - break; - - T_MEAN_VAR mu = mean[(k * frame_row + y) * mean_step + x]; - T_MEAN_VAR _var = var[(k * frame_row + y) + var_step + x]; - - T_MEAN_VAR diff = pix - mu; - - if (sqr(diff) < varThreshold * sum(_var)) - { - kHit = k; - break; - } - } - - if (kHit >= 0) - { - float wsum = 0.0f; - for (int k = 0; k < (NMIXTURES); ++k) - { - wsum += weight[(k * frame_row + y) * weight_step + x]; - - if (wsum > backgroundRatio) - { - kForeground = k + 1; - break; - } - } - } - if(kHit < 0 || kHit >= kForeground) - fgmask[(y + fgmask_offset_y) * fgmask_step + (x + fgmask_offset_x)] = (uchar) (-1); - else - fgmask[(y + fgmask_offset_y) * fgmask_step + (x + fgmask_offset_x)] = (uchar) (0); - } -} - -__kernel void mog_withLearning_kernel(__global T_FRAME* frame, __global int* fgmask, - __global float* weight, __global float* sortKey, __global T_MEAN_VAR* mean, - __global T_MEAN_VAR* var, int frame_row, int frame_col, int frame_step, int fgmask_step, - int weight_step, int sortKey_step, int mean_step, int var_step, - float varThreshold, float backgroundRatio, float learningRate, float minVar, - int fgmask_offset_x, int fgmask_offset_y, int frame_offset_x, int frame_offset_y) -{ - const float w0 = 0.05f; - const float sk0 = w0 / 30.0f; - const float var0 = 900.f; - - int x = get_global_id(0); - int y = get_global_id(1); - - if(x >= frame_col || y >= frame_row) return; - float wsum = 0.0f; - int kHit = -1; - int kForeground = -1; - int k = 0; - - T_MEAN_VAR pix = cvt(frame[(y + frame_offset_y) * frame_step + (x + frame_offset_x)]); - - for (; k < (NMIXTURES); ++k) - { - float w = weight[(k * frame_row + y) * weight_step + x]; - wsum += w; - - if (w < 1.192092896e-07f) - break; - - T_MEAN_VAR mu = mean[(k * frame_row + y) * mean_step + x]; - T_MEAN_VAR _var = var[(k * frame_row + y) * var_step + x]; - - float sortKey_prev, weight_prev; - T_MEAN_VAR mean_prev, var_prev; - if (sqr(pix - mu) < varThreshold * sum(_var)) - { - wsum -= w; - float dw = learningRate * (1.0f - w); - - _var = clamp1(_var, learningRate, pix - mu, minVar); - - sortKey_prev = w / sqr(sum(_var)); - sortKey[(k * frame_row + y) * sortKey_step + x] = sortKey_prev; - - weight_prev = w + dw; - weight[(k * frame_row + y) * weight_step + x] = weight_prev; - - mean_prev = mu + learningRate * (pix - mu); - mean[(k * frame_row + y) * mean_step + x] = mean_prev; - - var_prev = _var; - var[(k * frame_row + y) * var_step + x] = var_prev; - } - - int k1 = k - 1; - - if (k1 >= 0 && sqr(pix - mu) < varThreshold * sum(_var)) - { - float sortKey_next = sortKey[(k1 * frame_row + y) * sortKey_step + x]; - float weight_next = weight[(k1 * frame_row + y) * weight_step + x]; - T_MEAN_VAR mean_next = mean[(k1 * frame_row + y) * mean_step + x]; - T_MEAN_VAR var_next = var[(k1 * frame_row + y) * var_step + x]; - - for (; sortKey_next < sortKey_prev && k1 >= 0; --k1) - { - sortKey[(k1 * frame_row + y) * sortKey_step + x] = sortKey_prev; - sortKey[((k1 + 1) * frame_row + y) * sortKey_step + x] = sortKey_next; - - weight[(k1 * frame_row + y) * weight_step + x] = weight_prev; - weight[((k1 + 1) * frame_row + y) * weight_step + x] = weight_next; - - mean[(k1 * frame_row + y) * mean_step + x] = mean_prev; - mean[((k1 + 1) * frame_row + y) * mean_step + x] = mean_next; - - var[(k1 * frame_row + y) * var_step + x] = var_prev; - var[((k1 + 1) * frame_row + y) * var_step + x] = var_next; - - sortKey_prev = sortKey_next; - sortKey_next = k1 > 0 ? sortKey[((k1 - 1) * frame_row + y) * sortKey_step + x] : 0.0f; - - weight_prev = weight_next; - weight_next = k1 > 0 ? weight[((k1 - 1) * frame_row + y) * weight_step + x] : 0.0f; - - mean_prev = mean_next; - mean_next = k1 > 0 ? mean[((k1 - 1) * frame_row + y) * mean_step + x] : (T_MEAN_VAR)F_ZERO; - - var_prev = var_next; - var_next = k1 > 0 ? var[((k1 - 1) * frame_row + y) * var_step + x] : (T_MEAN_VAR)F_ZERO; - } - } - - kHit = k1 + 1; - break; - } - - if (kHit < 0) - { - kHit = k = k < ((NMIXTURES) - 1) ? k : ((NMIXTURES) - 1); - wsum += w0 - weight[(k * frame_row + y) * weight_step + x]; - - weight[(k * frame_row + y) * weight_step + x] = w0; - mean[(k * frame_row + y) * mean_step + x] = pix; -#if defined (CN1) - var[(k * frame_row + y) * var_step + x] = (T_MEAN_VAR)(var0); -#else - var[(k * frame_row + y) * var_step + x] = (T_MEAN_VAR)(var0, var0, var0, var0); -#endif - sortKey[(k * frame_row + y) * sortKey_step + x] = sk0; - } - else - { - for( ; k < (NMIXTURES); k++) - wsum += weight[(k * frame_row + y) * weight_step + x]; - } - - float wscale = 1.0f / wsum; - wsum = 0; - for (k = 0; k < (NMIXTURES); ++k) - { - float w = weight[(k * frame_row + y) * weight_step + x]; - w *= wscale; - wsum += w; - - weight[(k * frame_row + y) * weight_step + x] = w; - sortKey[(k * frame_row + y) * sortKey_step + x] *= wscale; - - kForeground = select(kForeground, k + 1, wsum > backgroundRatio && kForeground < 0); - } - fgmask[(y + fgmask_offset_y) * fgmask_step + (x + fgmask_offset_x)] = (uchar)(-(kHit >= kForeground)); -} - - -__kernel void getBackgroundImage_kernel(__global float* weight, __global T_MEAN_VAR* mean, __global T_FRAME* dst, - int dst_row, int dst_col, int weight_step, int mean_step, int dst_step, - float backgroundRatio) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if(x < dst_col && y < dst_row) - { - T_MEAN_VAR meanVal = (T_MEAN_VAR)F_ZERO; - float totalWeight = 0.0f; - - for (int mode = 0; mode < (NMIXTURES); ++mode) - { - float _weight = weight[(mode * dst_row + y) * weight_step + x]; - - T_MEAN_VAR _mean = mean[(mode * dst_row + y) * mean_step + x]; - meanVal = meanVal + _weight * _mean; - - totalWeight += _weight; - - if(totalWeight > backgroundRatio) - break; - } - meanVal = meanVal * (1.f / totalWeight); - dst[y * dst_step + x] = CONVERT_TYPE(meanVal); - } -} - -__kernel void mog2_kernel(__global T_FRAME * frame, __global int* fgmask, __global float* weight, __global T_MEAN_VAR * mean, - __global int* modesUsed, __global float* variance, int frame_row, int frame_col, int frame_step, - int fgmask_step, int weight_step, int mean_step, int modesUsed_step, int var_step, float alphaT, float alpha1, float prune, - int detectShadows_flag, int fgmask_offset_x, int fgmask_offset_y, int frame_offset_x, int frame_offset_y, __constant con_srtuct_t* constants) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if(x < frame_col && y < frame_row) - { - T_MEAN_VAR pix = cvt(frame[(y + frame_offset_y) * frame_step + x + frame_offset_x]); - - bool background = false; // true - the pixel classified as background - - bool fitsPDF = false; //if it remains zero a new GMM mode will be added - - int nmodes = modesUsed[y * modesUsed_step + x]; - int nNewModes = nmodes; //current number of modes in GMM - - float totalWeight = 0.0f; - - for (int mode = 0; mode < nmodes; ++mode) - { - float _weight = alpha1 * weight[(mode * frame_row + y) * weight_step + x] + prune; - - if (!fitsPDF) - { - float var = variance[(mode * frame_row + y) * var_step + x]; - - T_MEAN_VAR _mean = mean[(mode * frame_row + y) * mean_step + x]; - - T_MEAN_VAR diff = _mean - pix; - float dist2 = sqr(diff); - - if (totalWeight < constants -> c_TB && dist2 < constants -> c_Tb * var) - background = true; - - if (dist2 < constants -> c_Tg * var) - { - fitsPDF = true; - _weight += alphaT; - float k = alphaT / _weight; - mean[(mode * frame_row + y) * mean_step + x] = _mean - k * diff; - float varnew = var + k * (dist2 - var); - varnew = fmax(varnew, constants -> c_varMin); - varnew = fmin(varnew, constants -> c_varMax); - - variance[(mode * frame_row + y) * var_step + x] = varnew; - for (int i = mode; i > 0; --i) - { - if (_weight < weight[((i - 1) * frame_row + y) * weight_step + x]) - break; - swap(weight, x, y, i - 1, frame_row, weight_step); - swap(variance, x, y, i - 1, frame_row, var_step); - #if defined (CN1) - swap(mean, x, y, i - 1, frame_row, mean_step); - #else - swap4(mean, x, y, i - 1, frame_row, mean_step); - #endif - } - } - } // !fitsPDF - - if (_weight < -prune) - { - _weight = 0.0f; - nmodes--; - } - - weight[(mode * frame_row + y) * weight_step + x] = _weight; //update weight by the calculated value - totalWeight += _weight; - } - - totalWeight = 1.f / totalWeight; - for (int mode = 0; mode < nmodes; ++mode) - weight[(mode * frame_row + y) * weight_step + x] *= totalWeight; - - nmodes = nNewModes; - - if (!fitsPDF) - { - int mode = nmodes == (NMIXTURES) ? (NMIXTURES) - 1 : nmodes++; - - if (nmodes == 1) - weight[(mode * frame_row + y) * weight_step + x] = 1.f; - else - { - weight[(mode * frame_row + y) * weight_step + x] = alphaT; - - for (int i = 0; i < nmodes - 1; ++i) - weight[(i * frame_row + y) * weight_step + x] *= alpha1; - } - - mean[(mode * frame_row + y) * mean_step + x] = pix; - variance[(mode * frame_row + y) * var_step + x] = constants -> c_varInit; - - for (int i = nmodes - 1; i > 0; --i) - { - // check one up - if (alphaT < weight[((i - 1) * frame_row + y) * weight_step + x]) - break; - - swap(weight, x, y, i - 1, frame_row, weight_step); - swap(variance, x, y, i - 1, frame_row, var_step); - #if defined (CN1) - swap(mean, x, y, i - 1, frame_row, mean_step); - #else - swap4(mean, x, y, i - 1, frame_row, mean_step); - #endif - } - } - - modesUsed[y * modesUsed_step + x] = nmodes; - - bool isShadow = false; - if (detectShadows_flag && !background) - { - float tWeight = 0.0f; - - for (int mode = 0; mode < nmodes; ++mode) - { - T_MEAN_VAR _mean = mean[(mode * frame_row + y) * mean_step + x]; - - T_MEAN_VAR pix_mean = pix * _mean; - - float numerator = sum(pix_mean); - float denominator = sqr(_mean); - - if (denominator == 0) - break; - - if (numerator <= denominator && numerator >= constants -> c_tau * denominator) - { - float a = numerator / denominator; - - T_MEAN_VAR dD = a * _mean - pix; - - if (sqr(dD) < constants -> c_Tb * variance[(mode * frame_row + y) * var_step + x] * a * a) - { - isShadow = true; - break; - } - } - - tWeight += weight[(mode * frame_row + y) * weight_step + x]; - if (tWeight > constants -> c_TB) - break; - } - } - - fgmask[(y + fgmask_offset_y) * fgmask_step + x + fgmask_offset_x] = background ? 0 : isShadow ? constants -> c_shadowVal : 255; - } -} - -__kernel void getBackgroundImage2_kernel(__global int* modesUsed, __global float* weight, __global T_MEAN_VAR* mean, - __global T_FRAME* dst, float c_TB, int modesUsed_row, int modesUsed_col, int modesUsed_step, int weight_step, - int mean_step, int dst_step, int dst_x, int dst_y) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if(x < modesUsed_col && y < modesUsed_row) - { - int nmodes = modesUsed[y * modesUsed_step + x]; - - T_MEAN_VAR meanVal = (T_MEAN_VAR)F_ZERO; - - float totalWeight = 0.0f; - - for (int mode = 0; mode < nmodes; ++mode) - { - float _weight = weight[(mode * modesUsed_row + y) * weight_step + x]; - - T_MEAN_VAR _mean = mean[(mode * modesUsed_row + y) * mean_step + x]; - meanVal = meanVal + _weight * _mean; - - totalWeight += _weight; - - if(totalWeight > c_TB) - break; - } - - meanVal = meanVal * (1.f / totalWeight); - dst[(y + dst_y) * dst_step + x + dst_x] = CONVERT_TYPE(meanVal); - } -} diff --git a/modules/ocl/src/opencl/blend_linear.cl b/modules/ocl/src/opencl/blend_linear.cl deleted file mode 100644 index bc7aa4685..000000000 --- a/modules/ocl/src/opencl/blend_linear.cl +++ /dev/null @@ -1,78 +0,0 @@ -/*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 -// Liu Liujun, liujun@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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -__kernel void blendLinear(__global const T * src1, int src1_offset, int src1_step, - __global const T * src2, int src2_offset, int src2_step, - __global const float * weight1, int weight1_offset, int weight1_step, - __global const float * weight2, int weight2_offset, int weight2_step, - __global T * dst, int dst_offset, int dst_step, - int rows, int cols) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step, src1_offset + x); - int src2_index = mad24(y, src2_step, src2_offset + x); - int weight1_index = mad24(y, weight1_step, weight1_offset + x); - int weight2_index = mad24(y, weight2_step, weight2_offset + x); - int dst_index = mad24(y, dst_step, dst_offset + x); - - FT w1 = (FT)(weight1[weight1_index]), w2 = (FT)(weight2[weight2_index]); - FT den = w1 + w2 + (FT)(1e-5f); - FT num = w1 * convertToFT(src1[src1_index]) + w2 * convertToFT(src2[src2_index]); - - dst[dst_index] = convertToT(num / den); - } -} diff --git a/modules/ocl/src/opencl/brief.cl b/modules/ocl/src/opencl/brief.cl deleted file mode 100644 index 343e95bf9..000000000 --- a/modules/ocl/src/opencl/brief.cl +++ /dev/null @@ -1,173 +0,0 @@ -/*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 -// -// Third party copyrights are property of their respective owners. -// -// @Authors -// Matthias Bady, aegirxx ==> gmail.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*/ - -#ifndef BYTES - #define BYTES 16 -#endif - -#ifndef KERNEL_SIZE - #define KERNEL_SIZE 9 -#endif - -#ifndef BORDER - #define BORDER 0 -#endif - -#define HALF_KERNEL (KERNEL_SIZE/2) - -__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST; - -__constant char tests[32 * BYTES] = -{ --2,-1,7,-1,-14,-1,-3,3,1,-2,11,2,1,6,-10,-7,13,2,-1,0,-14,5,5,-3,-2,8,2,4,-11,8,-15,5, --6,-23,8,-9,-12,6,-10,8,-3,-1,8,1,3,6,5,6,-7,-6,5,-5,22,-2,-11,-8,14,7,8,5,-1,14,-5,-14, --14,9,2,0,7,-3,22,6,-6,6,-8,-5,-5,9,7,-1,-3,-7,-10,-18,4,-5,0,11,2,3,9,10,-10,3,4,9, -0,12,-3,19,1,15,-11,-5,14,-1,7,8,7,-23,-5,5,0,-6,-10,17,13,-4,-3,-4,-12,1,-12,2,0,8,3,22, --13,13,3,-1,-16,17,6,10,7,15,-5,0,2,-12,19,-2,3,-6,-4,-15,8,3,0,14,4,-11,5,5,11,-7,7,1, -6,12,21,3,-3,2,14,1,5,1,-5,11,3,-17,-6,2,6,8,5,-10,-14,-2,0,4,5,-7,-6,5,10,4,4,-7, -22,0,7,-18,-1,-3,0,18,-4,22,-5,3,1,-7,2,-3,19,-20,17,-2,3,-10,-8,24,-5,-14,7,5,-2,12,-4,-15, -4,12,0,-19,20,13,3,5,-8,-12,5,0,-5,6,-7,-11,6,-11,-3,-22,15,4,10,1,-7,-4,15,-6,5,10,0,24, -3,6,22,-2,-13,14,4,-4,-13,8,-18,-22,-1,-1,-7,3,-19,-12,4,3,8,10,13,-2,-6,-1,-6,-5,2,-21,-3,2, -4,-7,0,16,-6,-5,-12,-1,1,-1,9,18,-7,10,-11,6,4,3,19,-7,-18,5,-4,5,4,0,-20,4,7,-11,18,12, --20,17,-18,7,2,15,19,-11,-18,6,-7,3,-4,1,-14,13,17,3,2,-8,-7,2,1,6,17,-9,-2,8,-8,-6,-1,12, --2,4,-1,6,-2,7,6,8,-8,-1,-7,-9,8,-9,15,0,0,22,-4,-15,-14,-1,3,-2,-7,-4,17,-7,-8,-2,9,-4, -5,-7,7,7,-5,13,-8,11,11,-4,0,8,5,-11,-9,-6,2,-6,3,-20,-6,2,6,10,-6,-6,-15,7,-6,-3,2,1, -11,0,-3,2,7,-12,14,5,0,-7,-1,-1,-16,0,6,8,22,11,0,-3,19,0,5,-17,-23,-14,-13,-19,-8,10,-11,-2, --11,6,-10,13,1,-7,14,0,-12,1,-5,-5,4,7,8,-1,-1,-5,15,2,-3,-1,7,-10,3,-6,10,-18,-7,-13,-13,10, -1,-1,13,-10,-19,14,8,-14,-4,-13,7,1,1,-2,12,-7,3,-5,1,-5,-2,-2,8,-10,2,14,8,7,3,9,8,2 -#if BYTES > 16 -,-9,1,-18,0,4,0,1,12,0,9,-14,-10,-13,-9,-2,6,1,5,10,10,-3,-6,-16,-5,11,6,-5,0,-23,10,1,2, -13,-5,-3,9,-4,-1,-13,-5,10,13,-11,8,19,20,-9,2,4,-8,0,-9,-14,10,15,19,-14,-12,-10,-3,-23,-3,17,-2, --3,-11,6,-14,19,-2,-4,2,-5,5,3,-13,2,-2,-5,4,17,4,17,-11,-7,-2,1,23,8,13,1,-16,-13,-5,1,-17, -4,6,-8,-3,-5,-9,-2,-10,-9,0,-7,-2,5,0,5,2,-4,-16,6,3,2,-15,-2,12,4,-1,6,2,1,1,-2,-8, --2,12,-5,-2,-8,8,-9,9,2,-10,3,1,-4,10,-9,4,6,12,2,5,-3,-8,0,5,-13,1,-7,2,-1,-10,7,-18, --1,8,-9,-10,-23,-1,6,2,-5,-3,3,2,0,11,-4,-7,15,2,-10,-3,-20,-8,-13,3,-19,-12,5,-11,-17,-13,-3,2, -7,4,-12,0,5,-1,-14,-6,-4,11,0,-4,3,10,7,-3,13,21,-11,6,-12,24,-7,-4,4,16,3,-14,-3,5,-7,-12, -0,-4,7,-5,-17,-9,13,-7,22,-6,-11,5,2,-8,23,-11,7,-10,-1,14,-3,-10,8,3,-13,1,-6,0,-7,-21,6,-14, -18,19,-4,-6,10,7,-1,-4,-1,21,1,-5,-10,6,-11,-2,18,-3,-1,7,-3,-9,-5,10,-13,14,17,-3,11,-19,-1,-18, -8,-2,-18,-23,0,-5,-2,-9,-4,-11,2,-8,14,6,-3,-6,-3,0,-15,0,-9,4,-15,-9,-1,11,3,11,-10,-16,-7,7, --2,-10,-10,-2,-5,-3,5,-23,13,-8,-15,-11,-15,11,6,-6,-16,-3,-2,2,6,12,-16,24,-10,0,8,11,-7,7,-19,-7, -5,16,9,-3,9,7,-7,-16,3,2,-10,9,21,1,8,7,7,0,1,17,-8,12,9,6,11,-7,-8,-6,19,0,9,3, -1,-7,-5,-11,0,8,-2,14,12,-2,-15,-6,4,12,0,-21,17,-4,-6,-7,-10,-9,-14,-7,-15,-10,-15,-14,-7,-5,5,-12, --4,0,15,-4,5,2,-6,-23,-4,-21,-6,4,-10,5,-15,6,4,-3,-1,5,-4,19,-23,-4,-4,17,13,-11,1,12,4,-14, --11,-6,-20,10,4,5,3,20,-8,-20,3,1,-19,9,9,-3,18,15,11,-4,12,16,8,7,-14,-8,-3,9,-6,0,2,-4, -1,-10,-1,2,8,-7,-6,18,9,12,-7,-23,8,-6,5,2,-9,6,-12,-7,-1,-2,-7,2,9,9,7,15,6,2,-6,6 -#endif -#if BYTES > 32 -,16,12,0,19,4,3,6,0,-2,-1,2,17,8,1,3,1,-12,-1,-11,0,-11,2,7,9,-1,3,-19,4,-1,-11,-1,3, -1,-10,-10,-4,-2,3,6,11,3,7,-9,-8,24,-14,-2,-10,-3,-3,-18,-6,-13,-10,-7,-1,2,-7,9,-6,2,-4,6,-13, -4,-4,-2,3,-4,2,9,13,-11,5,-6,-11,4,-2,11,-9,-19,0,-23,-5,-5,-7,-3,-6,-6,-4,12,14,12,-11,-8,-16, --21,15,-12,6,-2,-1,-8,16,6,-1,-8,-2,1,-1,-9,8,3,-4,-2,-2,-7,0,4,-8,11,-11,-12,2,2,3,11,7, --7,-4,-9,-6,3,-7,-5,0,3,-7,-10,-5,-3,-1,8,-10,0,8,5,1,9,0,1,16,8,4,-11,-3,-15,9,8,17, -0,2,-9,17,-6,-11,-10,-3,1,1,15,-8,-12,-13,-2,4,-6,4,-6,-10,5,-7,7,-5,10,6,8,9,-5,7,-18,-3, --6,3,5,4,-10,-13,-5,-3,-11,2,-16,0,7,-21,-5,-13,-14,-14,-4,-4,4,9,7,-3,4,11,10,-4,6,17,9,17, --10,8,0,-11,-6,-16,-6,8,-13,5,10,-5,3,2,12,16,13,-8,0,-6,10,0,4,-11,8,5,10,-2,11,-7,-13,3, -2,4,-7,-3,-14,-2,-11,16,11,-6,7,6,-3,15,8,-10,-3,8,12,-12,-13,6,-14,7,-11,-5,-8,-6,7,-6,6,3, --4,10,5,1,9,16,10,13,-17,10,2,8,-5,1,4,-4,-14,8,-5,2,4,-9,-6,-3,3,-7,-10,0,-2,-8,-10,4, --8,5,-9,24,2,-8,8,-9,-4,17,-5,2,14,0,-9,9,11,15,-6,5,-8,1,-3,4,9,-21,10,2,2,-1,4,11, -24,3,2,-2,-8,17,-14,-10,6,5,-13,7,11,10,0,-1,4,6,-10,6,-12,-2,5,6,3,-1,8,-15,1,-4,-7,11, -1,11,5,0,6,-12,10,1,-3,-2,-1,4,-2,-11,-1,12,7,-8,-20,-18,2,0,-9,2,-13,-1,-16,2,3,-1,-5,-17, -15,8,3,-14,-13,-12,6,15,2,-8,2,6,6,22,-3,-23,-2,-7,-6,0,13,-10,-6,6,6,7,-10,12,-6,7,-2,11, -0,-22,-2,-17,-4,-1,-11,-14,-2,-8,7,12,12,-5,7,-13,2,-2,-7,6,0,8,-3,23,6,12,13,-11,-21,-10,10,8, --3,0,7,15,7,-6,-5,-12,-21,-10,12,-11,-5,-11,8,-11,5,0,-11,-1,8,-9,7,-1,11,-23,21,-5,0,-5,-8,6, --6,8,8,12,-7,5,3,-2,-5,-20,-12,9,-6,12,-11,3,4,5,13,11,2,12,13,-12,-4,-13,4,7,0,15,-3,-16, --3,2,-2,14,4,-14,16,-11,-13,3,23,10,9,-19,2,5,5,3,14,-7,19,-13,-11,15,14,0,-2,-5,11,-4,0,-6, --2,5,-13,-8,-11,-15,-7,-17,1,3,-10,-8,-13,-10,7,-12,0,-13,23,-6,2,-17,-7,-3,1,3,4,-10,13,4,14,-6, --19,-2,-1,5,9,-8,10,-5,7,-1,5,7,9,-10,19,0,7,5,-4,-7,-11,1,-1,-11,2,-1,-4,11,-1,7,2,-2, -1,-20,-9,-6,-4,-18,8,-18,-16,-2,7,-6,-3,-6,-1,-4,0,-16,24,-5,-4,-2,-1,9,-8,2,-6,15,11,4,0,-3, -7,6,2,-10,-7,-9,12,-6,24,15,-8,-1,15,-9,-3,-15,17,-5,11,-10,-2,13,-15,4,-2,-1,4,-23,-16,3,-7,-14, --3,-5,-10,-9,-5,3,-2,-1,-1,4,1,8,12,9,9,-14,-9,17,-3,0,5,4,13,-6,-1,-8,19,10,8,-5,-15,2, --12,-9,-4,-5,12,0,24,4,8,-2,14,4,8,-4,-7,16,5,-1,-8,-4,-2,18,-5,17,8,-2,-9,-2,3,-7,1,-6, --5,-22,-5,-2,-8,-10,14,1,-3,-13,3,9,-4,-1,-1,0,-7,-21,12,-19,-8,8,24,8,12,-6,-2,3,-5,-11,-22,-4, --3,5,-4,4,-16,24,7,-9,-10,23,-9,18,1,12,17,21,24,-6,-3,-11,-7,17,1,-6,4,4,2,-7,14,6,-12,3, --6,0,-16,13,-10,5,7,12,5,2,6,-3,7,0,-23,1,15,-5,1,14,-3,-1,6,6,6,-9,-9,12,4,-2,-4,7, --4,-5,4,4,-13,0,6,-10,2,-12,-6,-3,16,0,-3,3,5,-14,6,11,5,11,0,-13,7,5,-1,-5,12,4,6,10, --10,4,-1,-11,4,10,-14,5,11,-14,-13,0,2,8,12,24,-1,3,-1,2,9,-14,-23,3,-8,-6,0,9,-15,14,10,-10, --10,-6,-7,-5,11,5,-3,-15,1,0,1,8,-11,-6,-4,-18,9,0,22,-4,-5,-1,-9,4,-20,2,1,6,1,2,-9,-12, -5,15,4,-6,19,4,4,11,17,-4,-8,-1,-8,-12,7,-3,11,9,8,1,9,22,-15,15,-7,-7,1,-23,-5,13,-8,2, -3,-5,11,-11,3,-18,14,-5,-20,7,-10,-23,-2,-5,6,0,-17,-13,-3,2,-6,-1,14,-2,-12,-16,15,6,-12,-2,3,-19 -#endif -}; - -inline int smoothedSum(__read_only image2d_t sum, const int2 kpPos, const int2 pt) -{ - return ( read_imagei( sum, sampler, kpPos + pt + (int2)( HALF_KERNEL + 1, HALF_KERNEL + 1 )) - - read_imagei( sum, sampler, kpPos + pt + (int2)( -HALF_KERNEL, HALF_KERNEL + 1 )) - - read_imagei( sum, sampler, kpPos + pt + (int2)( HALF_KERNEL + 1, -HALF_KERNEL )) - + read_imagei( sum, sampler, kpPos + pt + (int2)( -HALF_KERNEL, -HALF_KERNEL ))).x; -} - -__kernel void extractBriefDescriptors( - __read_only image2d_t sumImg, - __global float* keypoints, int kpRowStep, - __global uchar* descriptors, int dscRowStep, - __global uchar* mask) -{ - const int byte = get_local_id(0); - const int kpId = get_group_id(0); - - if( !mask[kpId]) - { - return; - } - const float2 kpPos = (float2)(keypoints[kpId], keypoints[kpRowStep/4 + kpId]); - if( kpPos.x < BORDER - || kpPos.y < BORDER - || kpPos.x >= (get_image_width( sumImg ) - BORDER) - || kpPos.y >= (get_image_height( sumImg ) - BORDER) ) - { - if( byte == 0) mask[kpId] = 0; - return; - } - uchar descByte = 0; - const int2 pt = (int2)( kpPos.x + 0.5f, kpPos.y + 0.5f ); - for(int i = 0; i<8; ++i) - { - descByte |= ( - smoothedSum(sumImg, pt, (int2)( tests[byte * 32 + (i * 4) + 1], tests[byte * 32 + (i * 4) + 0] )) - < smoothedSum(sumImg, pt, (int2)( tests[byte * 32 + (i * 4) + 3], tests[byte * 32 + (i * 4) + 2] )) - ) << (7-i); - } - descriptors[kpId * dscRowStep + byte] = descByte; - if( byte == 0) mask[kpId] = 1; -} diff --git a/modules/ocl/src/opencl/brute_force_match.cl b/modules/ocl/src/opencl/brute_force_match.cl deleted file mode 100644 index 544737053..000000000 --- a/modules/ocl/src/opencl/brute_force_match.cl +++ /dev/null @@ -1,789 +0,0 @@ -/*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 -// Nathan, liujun@multicorewareinc.com -// Peng Xiao, pengxiao@outlook.com -// Baichuan Su, baichuan@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*/ - -#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics:enable -#define MAX_FLOAT 3.40282e+038f - -#ifndef T -#define T float -#endif - -#ifndef BLOCK_SIZE -#define BLOCK_SIZE 16 -#endif -#ifndef MAX_DESC_LEN -#define MAX_DESC_LEN 64 -#endif - -#ifndef DIST_TYPE -#define DIST_TYPE 0 -#endif - -// dirty fix for non-template support -#if (DIST_TYPE == 0) // L1Dist -# ifdef T_FLOAT -# define DIST(x, y) fabs((x) - (y)) - typedef float value_type; - typedef float result_type; -# else -# define DIST(x, y) abs((x) - (y)) - typedef int value_type; - typedef int result_type; -# endif -#define DIST_RES(x) (x) -#elif (DIST_TYPE == 1) // L2Dist -#define DIST(x, y) (((x) - (y)) * ((x) - (y))) -typedef float value_type; -typedef float result_type; -#define DIST_RES(x) sqrt(x) -#elif (DIST_TYPE == 2) // Hamming -//http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel -inline int bit1Count(int v) -{ - v = v - ((v >> 1) & 0x55555555); // reuse input as temporary - v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp - return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count -} -#define DIST(x, y) bit1Count( (x) ^ (y) ) -typedef int value_type; -typedef int result_type; -#define DIST_RES(x) (x) -#endif - -inline result_type reduce_block( - __local value_type *s_query, - __local value_type *s_train, - int lidx, - int lidy - ) -{ - result_type result = 0; - #pragma unroll - for (int j = 0 ; j < BLOCK_SIZE ; j++) - { - result += DIST( - s_query[lidy * BLOCK_SIZE + j], - s_train[j * BLOCK_SIZE + lidx]); - } - return DIST_RES(result); -} - -inline result_type reduce_block_match( - __local value_type *s_query, - __local value_type *s_train, - int lidx, - int lidy - ) -{ - result_type result = 0; - #pragma unroll - for (int j = 0 ; j < BLOCK_SIZE ; j++) - { - result += DIST( - s_query[lidy * BLOCK_SIZE + j], - s_train[j * BLOCK_SIZE + lidx]); - } - return (result); -} - -inline result_type reduce_multi_block( - __local value_type *s_query, - __local value_type *s_train, - int block_index, - int lidx, - int lidy - ) -{ - result_type result = 0; - #pragma unroll - for (int j = 0 ; j < BLOCK_SIZE ; j++) - { - result += DIST( - s_query[lidy * MAX_DESC_LEN + block_index * BLOCK_SIZE + j], - s_train[j * BLOCK_SIZE + lidx]); - } - return result; -} - -/* 2dim launch, global size: dim0 is (query rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, dim1 is BLOCK_SIZE -local size: dim0 is BLOCK_SIZE, dim1 is BLOCK_SIZE. -*/ -__kernel void BruteForceMatch_UnrollMatch( - __global T *query, - __global T *train, - //__global float *mask, - __global int *bestTrainIdx, - __global float *bestDistance, - __local float *sharebuffer, - int query_rows, - int query_cols, - int train_rows, - int train_cols, - int step -) -{ - const int lidx = get_local_id(0); - const int lidy = get_local_id(1); - const int groupidx = get_group_id(0); - - __local value_type *s_query = (__local value_type *)sharebuffer; - __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * MAX_DESC_LEN; - - int queryIdx = groupidx * BLOCK_SIZE + lidy; - // load the query into local memory. - #pragma unroll - for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE; i ++) - { - int loadx = lidx + i * BLOCK_SIZE; - s_query[lidy * MAX_DESC_LEN + loadx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx] : 0; - } - - float myBestDistance = MAX_FLOAT; - int myBestTrainIdx = -1; - - // loopUnrolledCached to find the best trainIdx and best distance. - for (int t = 0, endt = (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE; t < endt; t++) - { - result_type result = 0; - #pragma unroll - for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE ; i++) - { - //load a BLOCK_SIZE * BLOCK_SIZE block into local train. - const int loadx = lidx + i * BLOCK_SIZE; - s_train[lidx * BLOCK_SIZE + lidy] = loadx < train_cols ? train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx] : 0; - - //synchronize to make sure each elem for reduceIteration in share memory is written already. - barrier(CLK_LOCAL_MEM_FENCE); - - result += reduce_multi_block(s_query, s_train, i, lidx, lidy); - - barrier(CLK_LOCAL_MEM_FENCE); - } - - result = DIST_RES(result); - - int trainIdx = t * BLOCK_SIZE + lidx; - - if (queryIdx < query_rows && trainIdx < train_rows && result < myBestDistance/* && mask(queryIdx, trainIdx)*/) - { - myBestDistance = result; - myBestTrainIdx = trainIdx; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - __local float *s_distance = (__local float*)(sharebuffer); - __local int* s_trainIdx = (__local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE); - - //find BestMatch - s_distance += lidy * BLOCK_SIZE; - s_trainIdx += lidy * BLOCK_SIZE; - s_distance[lidx] = myBestDistance; - s_trainIdx[lidx] = myBestTrainIdx; - - barrier(CLK_LOCAL_MEM_FENCE); - - //reduce -- now all reduce implement in each threads. - #pragma unroll - for (int k = 0 ; k < BLOCK_SIZE; k++) - { - if (myBestDistance > s_distance[k]) - { - myBestDistance = s_distance[k]; - myBestTrainIdx = s_trainIdx[k]; - } - } - - if (queryIdx < query_rows && lidx == 0) - { - bestTrainIdx[queryIdx] = myBestTrainIdx; - bestDistance[queryIdx] = myBestDistance; - } -} - -__kernel void BruteForceMatch_Match( - __global T *query, - __global T *train, - //__global float *mask, - __global int *bestTrainIdx, - __global float *bestDistance, - __local float *sharebuffer, - int query_rows, - int query_cols, - int train_rows, - int train_cols, - int step -) -{ - const int lidx = get_local_id(0); - const int lidy = get_local_id(1); - const int groupidx = get_group_id(0); - - const int queryIdx = groupidx * BLOCK_SIZE + lidy; - - float myBestDistance = MAX_FLOAT; - int myBestTrainIdx = -1; - - __local value_type *s_query = (__local value_type *)sharebuffer; - __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE; - - // loop - for (int t = 0 ; t < (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE ; t++) - { - result_type result = 0; - for (int i = 0 ; i < (query_cols + BLOCK_SIZE - 1) / BLOCK_SIZE ; i++) - { - const int loadx = lidx + i * BLOCK_SIZE; - //load query and train into local memory - s_query[lidy * BLOCK_SIZE + lidx] = 0; - s_train[lidx * BLOCK_SIZE + lidy] = 0; - - if (loadx < query_cols) - { - s_query[lidy * BLOCK_SIZE + lidx] = query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx]; - s_train[lidx * BLOCK_SIZE + lidy] = train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx]; - } - - barrier(CLK_LOCAL_MEM_FENCE); - - result += reduce_block_match(s_query, s_train, lidx, lidy); - - barrier(CLK_LOCAL_MEM_FENCE); - } - - result = DIST_RES(result); - - const int trainIdx = t * BLOCK_SIZE + lidx; - - if (queryIdx < query_rows && trainIdx < train_rows && result < myBestDistance /*&& mask(queryIdx, trainIdx)*/) - { - myBestDistance = result; - myBestTrainIdx = trainIdx; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - __local float *s_distance = (__local float *)sharebuffer; - __local int *s_trainIdx = (__local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE); - - //findBestMatch - s_distance += lidy * BLOCK_SIZE; - s_trainIdx += lidy * BLOCK_SIZE; - s_distance[lidx] = myBestDistance; - s_trainIdx[lidx] = myBestTrainIdx; - - barrier(CLK_LOCAL_MEM_FENCE); - - //reduce -- now all reduce implement in each threads. - for (int k = 0 ; k < BLOCK_SIZE; k++) - { - if (myBestDistance > s_distance[k]) - { - myBestDistance = s_distance[k]; - myBestTrainIdx = s_trainIdx[k]; - } - } - - if (queryIdx < query_rows && lidx == 0) - { - bestTrainIdx[queryIdx] = myBestTrainIdx; - bestDistance[queryIdx] = myBestDistance; - } -} - -//radius_unrollmatch -__kernel void BruteForceMatch_RadiusUnrollMatch( - __global T *query, - __global T *train, - float maxDistance, - //__global float *mask, - __global int *bestTrainIdx, - __global float *bestDistance, - __global int *nMatches, - __local float *sharebuffer, - int query_rows, - int query_cols, - int train_rows, - int train_cols, - int bestTrainIdx_cols, - int step, - int ostep -) -{ - const int lidx = get_local_id(0); - const int lidy = get_local_id(1); - const int groupidx = get_group_id(0); - const int groupidy = get_group_id(1); - - const int queryIdx = groupidy * BLOCK_SIZE + lidy; - const int trainIdx = groupidx * BLOCK_SIZE + lidx; - - __local value_type *s_query = (__local value_type *)sharebuffer; - __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE; - - result_type result = 0; - for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE ; ++i) - { - //load a BLOCK_SIZE * BLOCK_SIZE block into local train. - const int loadx = lidx + i * BLOCK_SIZE; - - s_query[lidy * BLOCK_SIZE + lidx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx] : 0; - s_train[lidx * BLOCK_SIZE + lidy] = loadx < query_cols ? train[min(groupidx * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx] : 0; - - //synchronize to make sure each elem for reduceIteration in share memory is written already. - barrier(CLK_LOCAL_MEM_FENCE); - - result += reduce_block(s_query, s_train, lidx, lidy); - - barrier(CLK_LOCAL_MEM_FENCE); - } - - if (queryIdx < query_rows && trainIdx < train_rows && - convert_float(result) < maxDistance/* && mask(queryIdx, trainIdx)*/) - { - int ind = atom_inc(nMatches + queryIdx/*, (unsigned int) -1*/); - - if(ind < bestTrainIdx_cols) - { - bestTrainIdx[queryIdx * (ostep / sizeof(int)) + ind] = trainIdx; - bestDistance[queryIdx * (ostep / sizeof(float)) + ind] = result; - } - } -} - -//radius_match -__kernel void BruteForceMatch_RadiusMatch( - __global T *query, - __global T *train, - float maxDistance, - //__global float *mask, - __global int *bestTrainIdx, - __global float *bestDistance, - __global int *nMatches, - __local float *sharebuffer, - int query_rows, - int query_cols, - int train_rows, - int train_cols, - int bestTrainIdx_cols, - int step, - int ostep -) -{ - const int lidx = get_local_id(0); - const int lidy = get_local_id(1); - const int groupidx = get_group_id(0); - const int groupidy = get_group_id(1); - - const int queryIdx = groupidy * BLOCK_SIZE + lidy; - const int trainIdx = groupidx * BLOCK_SIZE + lidx; - - __local value_type *s_query = (__local value_type *)sharebuffer; - __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE; - - result_type result = 0; - for (int i = 0 ; i < (query_cols + BLOCK_SIZE - 1) / BLOCK_SIZE ; ++i) - { - //load a BLOCK_SIZE * BLOCK_SIZE block into local train. - const int loadx = lidx + i * BLOCK_SIZE; - - s_query[lidy * BLOCK_SIZE + lidx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx] : 0; - s_train[lidx * BLOCK_SIZE + lidy] = loadx < query_cols ? train[min(groupidx * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx] : 0; - - //synchronize to make sure each elem for reduceIteration in share memory is written already. - barrier(CLK_LOCAL_MEM_FENCE); - - result += reduce_block(s_query, s_train, lidx, lidy); - - barrier(CLK_LOCAL_MEM_FENCE); - } - - if (queryIdx < query_rows && trainIdx < train_rows && - convert_float(result) < maxDistance/* && mask(queryIdx, trainIdx)*/) - { - int ind = atom_inc(nMatches + queryIdx); - - if(ind < bestTrainIdx_cols) - { - bestTrainIdx[queryIdx * (ostep / sizeof(int)) + ind] = trainIdx; - bestDistance[queryIdx * (ostep / sizeof(float)) + ind] = result; - } - } -} - - -__kernel void BruteForceMatch_knnUnrollMatch( - __global T *query, - __global T *train, - //__global float *mask, - __global int2 *bestTrainIdx, - __global float2 *bestDistance, - __local float *sharebuffer, - int query_rows, - int query_cols, - int train_rows, - int train_cols, - int step -) -{ - const int lidx = get_local_id(0); - const int lidy = get_local_id(1); - const int groupidx = get_group_id(0); - - const int queryIdx = groupidx * BLOCK_SIZE + lidy; - __local value_type *s_query = (__local value_type *)sharebuffer; - __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * MAX_DESC_LEN; - - // load the query into local memory. - for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE; i ++) - { - int loadx = lidx + i * BLOCK_SIZE; - s_query[lidy * MAX_DESC_LEN + loadx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx] : 0; - } - - float myBestDistance1 = MAX_FLOAT; - float myBestDistance2 = MAX_FLOAT; - int myBestTrainIdx1 = -1; - int myBestTrainIdx2 = -1; - - //loopUnrolledCached - for (int t = 0 ; t < (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE ; t++) - { - result_type result = 0; - for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE ; i++) - { - //load a BLOCK_SIZE * BLOCK_SIZE block into local train. - const int loadx = lidx + i * BLOCK_SIZE; - s_train[lidx * BLOCK_SIZE + lidy] = loadx < train_cols ? train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx] : 0; - - //synchronize to make sure each elem for reduceIteration in share memory is written already. - barrier(CLK_LOCAL_MEM_FENCE); - - result += reduce_multi_block(s_query, s_train, i, lidx, lidy); - - barrier(CLK_LOCAL_MEM_FENCE); - } - - result = DIST_RES(result); - - const int trainIdx = t * BLOCK_SIZE + lidx; - - if (queryIdx < query_rows && trainIdx < train_rows) - { - if (result < myBestDistance1) - { - myBestDistance2 = myBestDistance1; - myBestTrainIdx2 = myBestTrainIdx1; - myBestDistance1 = result; - myBestTrainIdx1 = trainIdx; - } - else if (result < myBestDistance2) - { - myBestDistance2 = result; - myBestTrainIdx2 = trainIdx; - } - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - __local float *s_distance = (local float *)sharebuffer; - __local int *s_trainIdx = (local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE); - - // find BestMatch - s_distance += lidy * BLOCK_SIZE; - s_trainIdx += lidy * BLOCK_SIZE; - - s_distance[lidx] = myBestDistance1; - s_trainIdx[lidx] = myBestTrainIdx1; - - float bestDistance1 = MAX_FLOAT; - float bestDistance2 = MAX_FLOAT; - int bestTrainIdx1 = -1; - int bestTrainIdx2 = -1; - barrier(CLK_LOCAL_MEM_FENCE); - - if (lidx == 0) - { - for (int i = 0 ; i < BLOCK_SIZE ; i++) - { - float val = s_distance[i]; - if (val < bestDistance1) - { - bestDistance2 = bestDistance1; - bestTrainIdx2 = bestTrainIdx1; - - bestDistance1 = val; - bestTrainIdx1 = s_trainIdx[i]; - } - else if (val < bestDistance2) - { - bestDistance2 = val; - bestTrainIdx2 = s_trainIdx[i]; - } - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - s_distance[lidx] = myBestDistance2; - s_trainIdx[lidx] = myBestTrainIdx2; - - barrier(CLK_LOCAL_MEM_FENCE); - - if (lidx == 0) - { - for (int i = 0 ; i < BLOCK_SIZE ; i++) - { - float val = s_distance[i]; - - if (val < bestDistance2) - { - bestDistance2 = val; - bestTrainIdx2 = s_trainIdx[i]; - } - } - } - - myBestDistance1 = bestDistance1; - myBestDistance2 = bestDistance2; - - myBestTrainIdx1 = bestTrainIdx1; - myBestTrainIdx2 = bestTrainIdx2; - - if (queryIdx < query_rows && lidx == 0) - { - bestTrainIdx[queryIdx] = (int2)(myBestTrainIdx1, myBestTrainIdx2); - bestDistance[queryIdx] = (float2)(myBestDistance1, myBestDistance2); - } -} - -__kernel void BruteForceMatch_knnMatch( - __global T *query, - __global T *train, - //__global float *mask, - __global int2 *bestTrainIdx, - __global float2 *bestDistance, - __local float *sharebuffer, - int query_rows, - int query_cols, - int train_rows, - int train_cols, - int step -) -{ - const int lidx = get_local_id(0); - const int lidy = get_local_id(1); - const int groupidx = get_group_id(0); - - const int queryIdx = groupidx * BLOCK_SIZE + lidy; - __local value_type *s_query = (__local value_type *)sharebuffer; - __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE; - - float myBestDistance1 = MAX_FLOAT; - float myBestDistance2 = MAX_FLOAT; - int myBestTrainIdx1 = -1; - int myBestTrainIdx2 = -1; - - //loop - for (int t = 0 ; t < (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE ; t++) - { - result_type result = 0.0f; - for (int i = 0 ; i < (query_cols + BLOCK_SIZE -1) / BLOCK_SIZE ; i++) - { - const int loadx = lidx + i * BLOCK_SIZE; - //load query and train into local memory - s_query[lidy * BLOCK_SIZE + lidx] = 0; - s_train[lidx * BLOCK_SIZE + lidy] = 0; - - if (loadx < query_cols) - { - s_query[lidy * BLOCK_SIZE + lidx] = query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx]; - s_train[lidx * BLOCK_SIZE + lidy] = train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx]; - } - - barrier(CLK_LOCAL_MEM_FENCE); - - result += reduce_block_match(s_query, s_train, lidx, lidy); - - barrier(CLK_LOCAL_MEM_FENCE); - } - - result = DIST_RES(result); - - const int trainIdx = t * BLOCK_SIZE + lidx; - - if (queryIdx < query_rows && trainIdx < train_rows /*&& mask(queryIdx, trainIdx)*/) - { - if (result < myBestDistance1) - { - myBestDistance2 = myBestDistance1; - myBestTrainIdx2 = myBestTrainIdx1; - myBestDistance1 = result; - myBestTrainIdx1 = trainIdx; - } - else if (result < myBestDistance2) - { - myBestDistance2 = result; - myBestTrainIdx2 = trainIdx; - } - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - __local float *s_distance = (__local float *)sharebuffer; - __local int *s_trainIdx = (__local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE); - - //findBestMatch - s_distance += lidy * BLOCK_SIZE; - s_trainIdx += lidy * BLOCK_SIZE; - - s_distance[lidx] = myBestDistance1; - s_trainIdx[lidx] = myBestTrainIdx1; - - float bestDistance1 = MAX_FLOAT; - float bestDistance2 = MAX_FLOAT; - int bestTrainIdx1 = -1; - int bestTrainIdx2 = -1; - barrier(CLK_LOCAL_MEM_FENCE); - - if (lidx == 0) - { - for (int i = 0 ; i < BLOCK_SIZE ; i++) - { - float val = s_distance[i]; - if (val < bestDistance1) - { - bestDistance2 = bestDistance1; - bestTrainIdx2 = bestTrainIdx1; - - bestDistance1 = val; - bestTrainIdx1 = s_trainIdx[i]; - } - else if (val < bestDistance2) - { - bestDistance2 = val; - bestTrainIdx2 = s_trainIdx[i]; - } - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - s_distance[lidx] = myBestDistance2; - s_trainIdx[lidx] = myBestTrainIdx2; - - barrier(CLK_LOCAL_MEM_FENCE); - - if (lidx == 0) - { - for (int i = 0 ; i < BLOCK_SIZE ; i++) - { - float val = s_distance[i]; - - if (val < bestDistance2) - { - bestDistance2 = val; - bestTrainIdx2 = s_trainIdx[i]; - } - } - } - - myBestDistance1 = bestDistance1; - myBestDistance2 = bestDistance2; - - myBestTrainIdx1 = bestTrainIdx1; - myBestTrainIdx2 = bestTrainIdx2; - - if (queryIdx < query_rows && lidx == 0) - { - bestTrainIdx[queryIdx] = (int2)(myBestTrainIdx1, myBestTrainIdx2); - bestDistance[queryIdx] = (float2)(myBestDistance1, myBestDistance2); - } -} - -kernel void BruteForceMatch_calcDistanceUnrolled( - __global T *query, - __global T *train, - //__global float *mask, - __global float *allDist, - __local float *sharebuffer, - int query_rows, - int query_cols, - int train_rows, - int train_cols, - int step) -{ - /* Todo */ -} - -kernel void BruteForceMatch_calcDistance( - __global T *query, - __global T *train, - //__global float *mask, - __global float *allDist, - __local float *sharebuffer, - int query_rows, - int query_cols, - int train_rows, - int train_cols, - int step) -{ - /* Todo */ -} - -kernel void BruteForceMatch_findBestMatch( - __global float *allDist, - __global int *bestTrainIdx, - __global float *bestDistance, - int k -) -{ - /* Todo */ -} diff --git a/modules/ocl/src/opencl/build_warps.cl b/modules/ocl/src/opencl/build_warps.cl deleted file mode 100644 index bd5e002b5..000000000 --- a/modules/ocl/src/opencl/build_warps.cl +++ /dev/null @@ -1,207 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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*/ - -__kernel void buildWarpPlaneMaps(__global float * xmap, __global float * ymap, - __constant float * KRT, - int tl_u, int tl_v, - int cols, int rows, - int xmap_step, int ymap_step, - int xmap_offset, int ymap_offset, - float scale) -{ - int du = get_global_id(0); - int dv = get_global_id(1); - - __constant float * ck_rinv = KRT; - __constant float * ct = KRT + 9; - - if (du < cols && dv < rows) - { - int xmap_index = mad24(dv, xmap_step, xmap_offset + du); - int ymap_index = mad24(dv, ymap_step, ymap_offset + du); - - float u = tl_u + du; - float v = tl_v + dv; - float x, y; - - float x_ = u / scale - ct[0]; - float y_ = v / scale - ct[1]; - - float z; - x = ck_rinv[0] * x_ + ck_rinv[1] * y_ + ck_rinv[2] * (1 - ct[2]); - y = ck_rinv[3] * x_ + ck_rinv[4] * y_ + ck_rinv[5] * (1 - ct[2]); - z = ck_rinv[6] * x_ + ck_rinv[7] * y_ + ck_rinv[8] * (1 - ct[2]); - - x /= z; - y /= z; - - xmap[xmap_index] = x; - ymap[ymap_index] = y; - } -} - -__kernel void buildWarpCylindricalMaps(__global float * xmap, __global float * ymap, - __constant float * ck_rinv, - int tl_u, int tl_v, - int cols, int rows, - int xmap_step, int ymap_step, - int xmap_offset, int ymap_offset, - float scale) -{ - int du = get_global_id(0); - int dv = get_global_id(1); - - if (du < cols && dv < rows) - { - int xmap_index = mad24(dv, xmap_step, xmap_offset + du); - int ymap_index = mad24(dv, ymap_step, ymap_offset + du); - - float u = tl_u + du; - float v = tl_v + dv; - float x, y; - - u /= scale; - float x_ = sin(u); - float y_ = v / scale; - float z_ = cos(u); - - float z; - x = ck_rinv[0] * x_ + ck_rinv[1] * y_ + ck_rinv[2] * z_; - y = ck_rinv[3] * x_ + ck_rinv[4] * y_ + ck_rinv[5] * z_; - z = ck_rinv[6] * x_ + ck_rinv[7] * y_ + ck_rinv[8] * z_; - - if (z > 0) { x /= z; y /= z; } - else x = y = -1; - - xmap[xmap_index] = x; - ymap[ymap_index] = y; - } -} - -__kernel void buildWarpSphericalMaps(__global float * xmap, __global float * ymap, - __constant float * ck_rinv, - int tl_u, int tl_v, - int cols, int rows, - int xmap_step, int ymap_step, - int xmap_offset, int ymap_offset, - float scale) -{ - int du = get_global_id(0); - int dv = get_global_id(1); - - if (du < cols && dv < rows) - { - int xmap_index = mad24(dv, xmap_step, xmap_offset + du); - int ymap_index = mad24(dv, ymap_step, ymap_offset + du); - - float u = tl_u + du; - float v = tl_v + dv; - float x, y; - - v /= scale; - u /= scale; - - float sinv = sin(v); - float x_ = sinv * sin(u); - float y_ = - cos(v); - float z_ = sinv * cos(u); - - float z; - x = ck_rinv[0] * x_ + ck_rinv[1] * y_ + ck_rinv[2] * z_; - y = ck_rinv[3] * x_ + ck_rinv[4] * y_ + ck_rinv[5] * z_; - z = ck_rinv[6] * x_ + ck_rinv[7] * y_ + ck_rinv[8] * z_; - - if (z > 0) { x /= z; y /= z; } - else x = y = -1; - - xmap[xmap_index] = x; - ymap[ymap_index] = y; - } -} - -__kernel void buildWarpAffineMaps(__global float * xmap, __global float * ymap, - __constant float * c_warpMat, - int cols, int rows, - int xmap_step, int ymap_step, - int xmap_offset, int ymap_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int xmap_index = mad24(y, xmap_step, x + xmap_offset); - int ymap_index = mad24(y, ymap_step, x + ymap_offset); - - float xcoo = c_warpMat[0] * x + c_warpMat[1] * y + c_warpMat[2]; - float ycoo = c_warpMat[3] * x + c_warpMat[4] * y + c_warpMat[5]; - - xmap[xmap_index] = xcoo; - ymap[ymap_index] = ycoo; - } -} - -__kernel void buildWarpPerspectiveMaps(__global float * xmap, __global float * ymap, - __constant float * c_warpMat, - int cols, int rows, - int xmap_step, int ymap_step, - int xmap_offset, int ymap_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int xmap_index = mad24(y, xmap_step, x + xmap_offset); - int ymap_index = mad24(y, ymap_step, x + ymap_offset); - - float coeff = 1.0f / (c_warpMat[6] * x + c_warpMat[7] * y + c_warpMat[8]); - float xcoo = coeff * (c_warpMat[0] * x + c_warpMat[1] * y + c_warpMat[2]); - float ycoo = coeff * (c_warpMat[3] * x + c_warpMat[4] * y + c_warpMat[5]); - - xmap[xmap_index] = xcoo; - ymap[ymap_index] = ycoo; - } -} diff --git a/modules/ocl/src/opencl/convertC3C4.cl b/modules/ocl/src/opencl/convertC3C4.cl deleted file mode 100644 index 4c519fdf7..000000000 --- a/modules/ocl/src/opencl/convertC3C4.cl +++ /dev/null @@ -1,153 +0,0 @@ -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.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. -// -// - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -__kernel void convertC3C4(__global const GENTYPE4 * restrict src, __global GENTYPE4 *dst, - int cols, int rows, - int dstStep_in_piexl, int pixel_end) -{ - int id = get_global_id(0); - int3 pixelid = (int3)(mul24(id,3),mad24(id,3,1),mad24(id,3,2)); - pixelid = clamp(pixelid,0,pixel_end); - GENTYPE4 pixel0, pixel1, pixel2, outpix0,outpix1,outpix2,outpix3; - - pixel0 = src[pixelid.x]; - pixel1 = src[pixelid.y]; - pixel2 = src[pixelid.z]; - - outpix0 = (GENTYPE4)(pixel0.x,pixel0.y,pixel0.z,0); - outpix1 = (GENTYPE4)(pixel0.w,pixel1.x,pixel1.y,0); - outpix2 = (GENTYPE4)(pixel1.z,pixel1.w,pixel2.x,0); - outpix3 = (GENTYPE4)(pixel2.y,pixel2.z,pixel2.w,0); - - int4 outy = (id<<2)/cols; - int4 outx = (id<<2)%cols; - - outx += (int4)(0, 1, 2, 3); - outy = select(outy, outy+1, outx>=cols); - outx = select(outx, outx-cols, outx>=cols); - - // when cols == 1 - outy = select(outy, outy + 1, outx >= cols); - outx = select(outx, outx-cols, outx >= cols); - outy = select(outy, outy + 1, outx >= cols); - outx = select(outx, outx-cols, outx >= cols); - - int4 addr = mad24(outy,(int4)dstStep_in_piexl,outx); - - if(outx.w=(int4)cols); - x4 = select(x4,x4-(int4)cols,x4>=(int4)cols); - - // when cols == 1 - y4 = select(y4, y4 + 1,x4>=(int4)cols); - x4 = select(x4, x4 - (int4)cols,x4>=(int4)cols); - y4 = select(y4, y4 + 1,x4>=(int4)cols); - x4 = select(x4, x4-(int4)cols,x4>=(int4)cols); - - y4=clamp(y4,(int4)0,(int4)(rows-1)); - int4 addr = mad24(y4, (int4)srcStep_in_pixel, x4); - - GENTYPE4 pixel0,pixel1,pixel2,pixel3, outpixel1, outpixel2; - pixel0 = src[addr.x]; - pixel1 = src[addr.y]; - pixel2 = src[addr.z]; - pixel3 = src[addr.w]; - - pixel0.w = pixel1.x; - outpixel1.x = pixel1.y; - outpixel1.y = pixel1.z; - outpixel1.z = pixel2.x; - outpixel1.w = pixel2.y; - outpixel2.x = pixel2.z; - outpixel2.y = pixel3.x; - outpixel2.z = pixel3.y; - outpixel2.w = pixel3.z; - - int4 outaddr = mul24(id>>2 , 3); - outaddr.y++; - outaddr.z+=2; - - if(outaddr.z <= pixel_end) - { - dst[outaddr.x] = pixel0; - dst[outaddr.y] = outpixel1; - dst[outaddr.z] = outpixel2; - } - else if(outaddr.y <= pixel_end) - { - dst[outaddr.x] = pixel0; - dst[outaddr.y] = outpixel1; - } - else if(outaddr.x <= pixel_end) - dst[outaddr.x] = pixel0; -} diff --git a/modules/ocl/src/opencl/cvt_color.cl b/modules/ocl/src/opencl/cvt_color.cl deleted file mode 100644 index 5c236f0e0..000000000 --- a/modules/ocl/src/opencl/cvt_color.cl +++ /dev/null @@ -1,1599 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.com -// Peng Xiao, pengxiao@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*/ - -/**************************************PUBLICFUNC*************************************/ - -#ifndef hscale -#define hscale 0 -#endif - -#ifndef hrange -#define hrange 0 -#endif - -#ifdef DEPTH_0 -#define DATA_TYPE uchar -#define VECTOR2 uchar2 -#define VECTOR4 uchar4 -#define VECTOR8 uchar8 -#define VECTOR16 uchar16 -#define COEFF_TYPE int -#define MAX_NUM 255 -#define HALF_MAX 128 -#define SAT_CAST(num) convert_uchar_sat_rte(num) -#define SAT_CAST2(num) convert_uchar2_sat(num) -#define SAT_CAST4(num) convert_uchar4_sat(num) -#endif - -#ifdef DEPTH_2 -#define DATA_TYPE ushort -#define VECTOR2 ushort2 -#define VECTOR4 ushort4 -#define VECTOR8 ushort8 -#define VECTOR16 ushort16 -#define COEFF_TYPE int -#define MAX_NUM 65535 -#define HALF_MAX 32768 -#define SAT_CAST(num) convert_ushort_sat_rte(num) -#define SAT_CAST2(num) convert_ushort2_sat(num) -#define SAT_CAST4(num) convert_ushort4_sat(num) -#endif - -#ifdef DEPTH_5 -#define DATA_TYPE float -#define VECTOR2 float2 -#define VECTOR4 float4 -#define VECTOR8 float8 -#define VECTOR16 float16 -#define COEFF_TYPE float -#define MAX_NUM 1.0f -#define HALF_MAX 0.5f -#define SAT_CAST(num) (num) -#endif - -#ifndef bidx - #define bidx 0 -#endif - -#ifndef pixels_per_work_item - #define pixels_per_work_item 1 -#endif - -#define CV_DESCALE(x, n) (((x) + (1 << ((n)-1))) >> (n)) - -enum -{ - yuv_shift = 14, - xyz_shift = 12, - hsv_shift = 12, - R2Y = 4899, - G2Y = 9617, - B2Y = 1868, - BLOCK_SIZE = 256 -}; - -///////////////////////////////////// RGB <-> GRAY ////////////////////////////////////// - -__constant float c_RGB2GrayCoeffs_f[3] = { 0.114f, 0.587f, 0.299f }; -__constant int c_RGB2GrayCoeffs_i[3] = { B2Y, G2Y, R2Y }; - -__kernel void RGB2Gray(int cols, int rows, int src_step, int dst_step, - __global const DATA_TYPE* src, __global DATA_TYPE* dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0) * pixels_per_work_item; - int y = get_global_id(1); - - if (y < rows && x < cols) - { - int src_idx = mad24(y, src_step, src_offset + (x << 2)); - int dst_idx = mad24(y, dst_step, dst_offset + x); - -#ifndef INTEL_DEVICE - -#ifdef DEPTH_5 - dst[dst_idx] = src[src_idx + bidx] * 0.114f + src[src_idx + 1] * 0.587f + src[src_idx + (bidx^2)] * 0.299f; -#else - dst[dst_idx] = (DATA_TYPE)CV_DESCALE((src[src_idx + bidx] * B2Y + src[src_idx + 1] * G2Y + src[src_idx + (bidx^2)] * R2Y), yuv_shift); -#endif - -#else //INTEL_DEVICE - global DATA_TYPE *src_ptr = (global DATA_TYPE *)(src + src_idx); - global DATA_TYPE *dst_ptr = (global DATA_TYPE *)(dst + dst_idx); - -#ifdef DEPTH_5 - __constant float * coeffs = c_RGB2GrayCoeffs_f; -#else - __constant int * coeffs = c_RGB2GrayCoeffs_i; -#endif - -#if (1 == pixels_per_work_item) - { -#ifdef DEPTH_5 - *dst_ptr = src_ptr[bidx] * coeffs[0] + src_ptr[1] * coeffs[1] + src_ptr[(bidx^2)] *coeffs[2]; -#else - *dst_ptr = (DATA_TYPE)CV_DESCALE((src_ptr[bidx] * coeffs[0] + src_ptr[1] * coeffs[1] + src_ptr[(bidx^2)] * coeffs[2]), yuv_shift); -#endif - } -#elif (2 == pixels_per_work_item) - { - const VECTOR8 r0 = vload8(0, src_ptr); - -#ifdef DEPTH_5 - const float2 c0 = r0.s04; - const float2 c1 = r0.s15; - const float2 c2 = r0.s26; - - const float2 Y = c0 * coeffs[bidx] + c1 * coeffs[1] + c2 * coeffs[bidx^2]; -#else - const int2 c0 = convert_int2(r0.s04); - const int2 c1 = convert_int2(r0.s15); - const int2 c2 = convert_int2(r0.s26); - - const int2 yi = CV_DESCALE(c0 * coeffs[bidx] + c1 * coeffs[1] + c2 * coeffs[bidx^2], yuv_shift); - const VECTOR2 Y = SAT_CAST2(yi); -#endif - - vstore2(Y, 0, dst_ptr); - } -#elif (4 == pixels_per_work_item) - { -#ifndef DEPTH_5 - const VECTOR16 r0 = vload16(0, src_ptr); - - const int4 c0 = convert_int4(r0.s048c); - const int4 c1 = convert_int4(r0.s159d); - const int4 c2 = convert_int4(r0.s26ae); - const int4 Y = CV_DESCALE(c0 * coeffs[bidx] + c1 * coeffs[1] + c2 * coeffs[bidx^2], yuv_shift); - - vstore4(SAT_CAST4(Y), 0, dst_ptr); -#endif - } -#endif //pixels_per_work_item -#endif //INTEL_DEVICE - } -} - -__kernel void Gray2RGB(int cols, int rows, int src_step, int dst_step, - __global const DATA_TYPE* src, __global DATA_TYPE* dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + (x << 2)); - - DATA_TYPE val = src[src_idx]; - dst[dst_idx] = val; - dst[dst_idx + 1] = val; - dst[dst_idx + 2] = val; -#if dcn == 4 - dst[dst_idx + 3] = MAX_NUM; -#endif - } -} - -///////////////////////////////////// RGB <-> YUV ////////////////////////////////////// - -__constant float c_RGB2YUVCoeffs_f[5] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f }; -__constant int c_RGB2YUVCoeffs_i[5] = { B2Y, G2Y, R2Y, 8061, 14369 }; - -__kernel void RGB2YUV(int cols, int rows, int src_step, int dst_step, - __global const DATA_TYPE* src, __global DATA_TYPE* dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0) * pixels_per_work_item; - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - global DATA_TYPE *src_ptr = (global DATA_TYPE *)(src + src_idx); - global DATA_TYPE *dst_ptr = (global DATA_TYPE *)(dst + dst_idx); - -#ifdef DEPTH_5 - __constant float * coeffs = c_RGB2YUVCoeffs_f; -#else - __constant int * coeffs = c_RGB2YUVCoeffs_i; - const int delta = HALF_MAX * (1 << yuv_shift); -#endif - -#if (1 == pixels_per_work_item) - { - const DATA_TYPE rgb[] = {src_ptr[0], src_ptr[1], src_ptr[2]}; - -#ifdef DEPTH_5 - float Y = rgb[0] * coeffs[bidx^2] + rgb[1] * coeffs[1] + rgb[2] * coeffs[bidx]; - float U = (rgb[bidx^2] - Y) * coeffs[3] + HALF_MAX; - float V = (rgb[bidx] - Y) * coeffs[4] + HALF_MAX; -#else - int Y = CV_DESCALE(rgb[0] * coeffs[bidx^2] + rgb[1] * coeffs[1] + rgb[2] * coeffs[bidx], yuv_shift); - int U = CV_DESCALE((rgb[bidx^2] - Y) * coeffs[3] + delta, yuv_shift); - int V = CV_DESCALE((rgb[bidx] - Y) * coeffs[4] + delta, yuv_shift); -#endif - - dst_ptr[0] = SAT_CAST( Y ); - dst_ptr[1] = SAT_CAST( U ); - dst_ptr[2] = SAT_CAST( V ); - } -#elif (2 == pixels_per_work_item) - { - const VECTOR8 r0 = vload8(0, src_ptr); - -#ifdef DEPTH_5 - const float2 c0 = r0.s04; - const float2 c1 = r0.s15; - const float2 c2 = r0.s26; - - const float2 Y = (bidx == 0) ? (c0 * coeffs[2] + c1 * coeffs[1] + c2 * coeffs[0]) : (c0 * coeffs[0] + c1 * coeffs[1] + c2 * coeffs[2]); - const float2 U = (bidx == 0) ? ((c2 - Y) * coeffs[3] + HALF_MAX) : ((c0 - Y) * coeffs[3] + HALF_MAX); - const float2 V = (bidx == 0) ? ((c0 - Y) * coeffs[4] + HALF_MAX) : ((c2 - Y) * coeffs[4] + HALF_MAX); -#else - const int2 c0 = convert_int2(r0.s04); - const int2 c1 = convert_int2(r0.s15); - const int2 c2 = convert_int2(r0.s26); - - const int2 yi = (bidx == 0) ? CV_DESCALE(c0 * coeffs[2] + c1 * coeffs[1] + c2 * coeffs[0], yuv_shift) : CV_DESCALE(c0 * coeffs[0] + c1 * coeffs[1] + c2 * coeffs[2], yuv_shift); - const int2 ui = (bidx == 0) ? CV_DESCALE((c2 - yi) * coeffs[3] + delta, yuv_shift) : CV_DESCALE((c0 - yi) * coeffs[3] + delta, yuv_shift); - const int2 vi = (bidx == 0) ? CV_DESCALE((c0 - yi) * coeffs[4] + delta, yuv_shift) : CV_DESCALE((c2 - yi) * coeffs[4] + delta, yuv_shift); - - const VECTOR2 Y = SAT_CAST2(yi); - const VECTOR2 U = SAT_CAST2(ui); - const VECTOR2 V = SAT_CAST2(vi); -#endif - - vstore8((VECTOR8)(Y.s0, U.s0, V.s0, 0, Y.s1, U.s1, V.s1, 0), 0, dst_ptr); - } -#elif (4 == pixels_per_work_item) - { -#ifndef DEPTH_5 - const VECTOR16 r0 = vload16(0, src_ptr); - - const int4 c0 = convert_int4(r0.s048c); - const int4 c1 = convert_int4(r0.s159d); - const int4 c2 = convert_int4(r0.s26ae); - - const int4 yi = (bidx == 0) ? CV_DESCALE(c0 * coeffs[2] + c1 * coeffs[1] + c2 * coeffs[0], yuv_shift) : CV_DESCALE(c0 * coeffs[0] + c1 * coeffs[1] + c2 * coeffs[2], yuv_shift); - const int4 ui = (bidx == 0) ? CV_DESCALE((c2 - yi) * coeffs[3] + delta, yuv_shift) : CV_DESCALE((c0 - yi) * coeffs[3] + delta, yuv_shift); - const int4 vi = (bidx == 0) ? CV_DESCALE((c0 - yi) * coeffs[4] + delta, yuv_shift) : CV_DESCALE((c2 - yi) * coeffs[4] + delta, yuv_shift); - - const VECTOR4 Y = SAT_CAST4(yi); - const VECTOR4 U = SAT_CAST4(ui); - const VECTOR4 V = SAT_CAST4(vi); - - vstore16((VECTOR16)(Y.s0, U.s0, V.s0, 0, Y.s1, U.s1, V.s1, 0, Y.s2, U.s2, V.s2, 0, Y.s3, U.s3, V.s3, 0), 0, dst_ptr); -#endif - } -#endif //pixels_per_work_item - } -} - -__constant float c_YUV2RGBCoeffs_f[5] = { 2.032f, -0.395f, -0.581f, 1.140f }; -__constant int c_YUV2RGBCoeffs_i[5] = { 33292, -6472, -9519, 18678 }; - -__kernel void YUV2RGB(int cols, int rows, int src_step, int dst_step, - __global const DATA_TYPE* src, __global DATA_TYPE* dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0) * pixels_per_work_item; - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - global DATA_TYPE *src_ptr = (global DATA_TYPE *)(src + src_idx); - global DATA_TYPE *dst_ptr = (global DATA_TYPE *)(dst + dst_idx); - -#ifdef DEPTH_5 - __constant float * coeffs = c_YUV2RGBCoeffs_f; -#else - __constant int * coeffs = c_YUV2RGBCoeffs_i; -#endif - -#if (1 == pixels_per_work_item) - { - const DATA_TYPE yuv[] = {src_ptr[0], src_ptr[1], src_ptr[2]}; - -#ifdef DEPTH_5 - float B = yuv[0] + (yuv[2] - HALF_MAX) * coeffs[3]; - float G = yuv[0] + (yuv[2] - HALF_MAX) * coeffs[2] + (yuv[1] - HALF_MAX) * coeffs[1]; - float R = yuv[0] + (yuv[1] - HALF_MAX) * coeffs[0]; -#else - int B = yuv[0] + CV_DESCALE((yuv[2] - HALF_MAX) * coeffs[3], yuv_shift); - int G = yuv[0] + CV_DESCALE((yuv[2] - HALF_MAX) * coeffs[2] + (yuv[1] - HALF_MAX) * coeffs[1], yuv_shift); - int R = yuv[0] + CV_DESCALE((yuv[1] - HALF_MAX) * coeffs[0], yuv_shift); -#endif - - dst_ptr[bidx] = SAT_CAST( B ); - dst_ptr[1] = SAT_CAST( G ); - dst_ptr[(bidx^2)] = SAT_CAST( R ); -#if dcn == 4 - dst_ptr[3] = MAX_NUM; -#endif - } -#elif (2 == pixels_per_work_item) - { - const VECTOR8 r0 = vload8(0, src_ptr); - -#ifdef DEPTH_5 - const float2 Y = r0.s04; - const float2 U = r0.s15; - const float2 V = r0.s26; - - const float2 c0 = (bidx == 0) ? (Y + (V - HALF_MAX) * coeffs[3]) : (Y + (U - HALF_MAX) * coeffs[0]); - const float2 c1 = Y + (V - HALF_MAX) * coeffs[2] + (U - HALF_MAX) * coeffs[1]; - const float2 c2 = (bidx == 0) ? (Y + (U - HALF_MAX) * coeffs[0]) : (Y + (V - HALF_MAX) * coeffs[3]); -#else - const int2 Y = convert_int2(r0.s04); - const int2 U = convert_int2(r0.s15); - const int2 V = convert_int2(r0.s26); - - const int2 c0i = (bidx == 0) ? (Y + CV_DESCALE((V - HALF_MAX) * coeffs[3], yuv_shift)) : (Y + CV_DESCALE((U - HALF_MAX) * coeffs[0], yuv_shift)); - const int2 c1i = Y + CV_DESCALE((V - HALF_MAX) * coeffs[2] + (U - HALF_MAX) * coeffs[1], yuv_shift); - const int2 c2i = (bidx == 0) ? (Y + CV_DESCALE((U - HALF_MAX) * coeffs[0], yuv_shift)) : (Y + CV_DESCALE((V - HALF_MAX) * coeffs[3], yuv_shift)); - - const VECTOR2 c0 = SAT_CAST2(c0i); - const VECTOR2 c1 = SAT_CAST2(c1i); - const VECTOR2 c2 = SAT_CAST2(c2i); -#endif - -#if dcn == 4 - vstore8((VECTOR8)(c0.s0, c1.s0, c2.s0, MAX_NUM, c0.s1, c1.s1, c2.s1, MAX_NUM), 0, dst_ptr); -#else - vstore8((VECTOR8)(c0.s0, c1.s0, c2.s0, 0, c0.s1, c1.s1, c2.s1, 0), 0, dst_ptr); -#endif - } -#elif (4 == pixels_per_work_item) - { -#ifndef DEPTH_5 - const VECTOR16 r0 = vload16(0, src_ptr); - - const int4 Y = convert_int4(r0.s048c); - const int4 U = convert_int4(r0.s159d); - const int4 V = convert_int4(r0.s26ae); - - const int4 c0i = (bidx == 0) ? (Y + CV_DESCALE((V - HALF_MAX) * coeffs[3], yuv_shift)) : (Y + CV_DESCALE((U - HALF_MAX) * coeffs[0], yuv_shift)); - const int4 c1i = Y + CV_DESCALE((V - HALF_MAX) * coeffs[2] + (U - HALF_MAX) * coeffs[1], yuv_shift); - const int4 c2i = (bidx == 0) ? (Y + CV_DESCALE((U - HALF_MAX) * coeffs[0], yuv_shift)) : (Y + CV_DESCALE((V - HALF_MAX) * coeffs[3], yuv_shift)); - - const VECTOR4 c0 = SAT_CAST4(c0i); - const VECTOR4 c1 = SAT_CAST4(c1i); - const VECTOR4 c2 = SAT_CAST4(c2i); - -#if dcn == 4 - vstore16((VECTOR16)(c0.s0, c1.s0, c2.s0, MAX_NUM, c0.s1, c1.s1, c2.s1, MAX_NUM, c0.s2, c1.s2, c2.s2, MAX_NUM, c0.s3, c1.s3, c2.s3, MAX_NUM), 0, dst_ptr); -#else - vstore16((VECTOR16)(c0.s0, c1.s0, c2.s0, 0, c0.s1, c1.s1, c2.s1, 0, c0.s2, c1.s2, c2.s2, 0, c0.s3, c1.s3, c2.s3, 0), 0, dst_ptr); -#endif -#endif - } -#endif //pixels_per_work_item - } -} - -__constant int ITUR_BT_601_CY = 1220542; -__constant int ITUR_BT_601_CUB = 2116026; -__constant int ITUR_BT_601_CUG = 409993; -__constant int ITUR_BT_601_CVG = 852492; -__constant int ITUR_BT_601_CVR = 1673527; -__constant int ITUR_BT_601_SHIFT = 20; - -__kernel void YUV2RGBA_NV12(int cols, int rows, int src_step, int dst_step, - __global const uchar* src, __global uchar* dst, - int src_offset, int dst_offset) -{ - const int x = get_global_id(0); - const int y = get_global_id(1); - - if (y < rows / 2 && x < cols / 2 ) - { - __global const uchar* ysrc = src + mad24(y << 1, src_step, (x << 1) + src_offset); - __global const uchar* usrc = src + mad24(rows + y, src_step, (x << 1) + src_offset); - __global uchar* dst1 = dst + mad24(y << 1, dst_step, (x << 3) + dst_offset); - __global uchar* dst2 = dst + mad24((y << 1) + 1, dst_step, (x << 3) + dst_offset); - - int Y1 = ysrc[0]; - int Y2 = ysrc[1]; - int Y3 = ysrc[src_step]; - int Y4 = ysrc[src_step + 1]; - - int U = usrc[0] - 128; - int V = usrc[1] - 128; - - int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * V; - int guv = (1 << (ITUR_BT_601_SHIFT - 1)) - ITUR_BT_601_CVG * V - ITUR_BT_601_CUG * U; - int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * U; - - Y1 = max(0, Y1 - 16) * ITUR_BT_601_CY; - dst1[2 - bidx] = convert_uchar_sat((Y1 + ruv) >> ITUR_BT_601_SHIFT); - dst1[1] = convert_uchar_sat((Y1 + guv) >> ITUR_BT_601_SHIFT); - dst1[bidx] = convert_uchar_sat((Y1 + buv) >> ITUR_BT_601_SHIFT); - dst1[3] = 255; - - Y2 = max(0, Y2 - 16) * ITUR_BT_601_CY; - dst1[6 - bidx] = convert_uchar_sat((Y2 + ruv) >> ITUR_BT_601_SHIFT); - dst1[5] = convert_uchar_sat((Y2 + guv) >> ITUR_BT_601_SHIFT); - dst1[4 + bidx] = convert_uchar_sat((Y2 + buv) >> ITUR_BT_601_SHIFT); - dst1[7] = 255; - - Y3 = max(0, Y3 - 16) * ITUR_BT_601_CY; - dst2[2 - bidx] = convert_uchar_sat((Y3 + ruv) >> ITUR_BT_601_SHIFT); - dst2[1] = convert_uchar_sat((Y3 + guv) >> ITUR_BT_601_SHIFT); - dst2[bidx] = convert_uchar_sat((Y3 + buv) >> ITUR_BT_601_SHIFT); - dst2[3] = 255; - - Y4 = max(0, Y4 - 16) * ITUR_BT_601_CY; - dst2[6 - bidx] = convert_uchar_sat((Y4 + ruv) >> ITUR_BT_601_SHIFT); - dst2[5] = convert_uchar_sat((Y4 + guv) >> ITUR_BT_601_SHIFT); - dst2[4 + bidx] = convert_uchar_sat((Y4 + buv) >> ITUR_BT_601_SHIFT); - dst2[7] = 255; - } -} - -///////////////////////////////////// RGB <-> YCrCb ////////////////////////////////////// - -__constant float c_RGB2YCrCbCoeffs_f[5] = {0.299f, 0.587f, 0.114f, 0.713f, 0.564f}; -__constant int c_RGB2YCrCbCoeffs_i[5] = {R2Y, G2Y, B2Y, 11682, 9241}; - -__kernel void RGB2YCrCb(int cols, int rows, int src_step, int dst_step, - __global const DATA_TYPE* src, __global DATA_TYPE* dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0) * pixels_per_work_item; - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - global DATA_TYPE *src_ptr = (global DATA_TYPE *)(src + src_idx); - global DATA_TYPE *dst_ptr = (global DATA_TYPE *)(dst + dst_idx); - -#ifdef DEPTH_5 - __constant float * coeffs = c_RGB2YCrCbCoeffs_f; -#else - __constant int * coeffs = c_RGB2YCrCbCoeffs_i; - const int delta = HALF_MAX * (1 << yuv_shift); -#endif - -#if (1 == pixels_per_work_item) - { - const DATA_TYPE rgb[] = {src_ptr[0], src_ptr[1], src_ptr[2]}; - -#ifdef DEPTH_5 - float Y = rgb[0] * coeffs[bidx^2] + rgb[1] * coeffs[1] + rgb[2] * coeffs[bidx]; - float Cr = (rgb[bidx^2] - Y) * coeffs[3] + HALF_MAX; - float Cb = (rgb[bidx] - Y) * coeffs[4] + HALF_MAX; -#else - int Y = CV_DESCALE(rgb[0] * coeffs[bidx^2] + rgb[1] * coeffs[1] + rgb[2] * coeffs[bidx], yuv_shift); - int Cr = CV_DESCALE((rgb[bidx^2] - Y) * coeffs[3] + delta, yuv_shift); - int Cb = CV_DESCALE((rgb[bidx] - Y) * coeffs[4] + delta, yuv_shift); -#endif - - dst_ptr[0] = SAT_CAST( Y ); - dst_ptr[1] = SAT_CAST( Cr ); - dst_ptr[2] = SAT_CAST( Cb ); - } -#elif (2 == pixels_per_work_item) - { - const VECTOR8 r0 = vload8(0, src_ptr); - -#ifdef DEPTH_5 - const float2 c0 = r0.s04; - const float2 c1 = r0.s15; - const float2 c2 = r0.s26; - - const float2 Y = (bidx == 0) ? (c0 * coeffs[2] + c1 * coeffs[1] + c2 * coeffs[0]) : (c0 * coeffs[0] + c1 * coeffs[1] + c2 * coeffs[2]); - const float2 Cr = (bidx == 0) ? ((c2 - Y) * coeffs[3] + HALF_MAX) : ((c0 - Y) * coeffs[3] + HALF_MAX); - const float2 Cb = (bidx == 0) ? ((c0 - Y) * coeffs[4] + HALF_MAX) : ((c2 - Y) * coeffs[4] + HALF_MAX); -#else - const int2 c0 = convert_int2(r0.s04); - const int2 c1 = convert_int2(r0.s15); - const int2 c2 = convert_int2(r0.s26); - - const int2 yi = (bidx == 0) ? CV_DESCALE(c0 * coeffs[2] + c1 * coeffs[1] + c2 * coeffs[0], yuv_shift) : CV_DESCALE(c0 * coeffs[0] + c1 * coeffs[1] + c2 * coeffs[2], yuv_shift); - const int2 ui = (bidx == 0) ? CV_DESCALE((c2 - yi) * coeffs[3] + delta, yuv_shift) : CV_DESCALE((c0 - yi) * coeffs[3] + delta, yuv_shift); - const int2 vi = (bidx == 0) ? CV_DESCALE((c0 - yi) * coeffs[4] + delta, yuv_shift) : CV_DESCALE((c2 - yi) * coeffs[4] + delta, yuv_shift); - - const VECTOR2 Y = SAT_CAST2(yi); - const VECTOR2 Cr = SAT_CAST2(ui); - const VECTOR2 Cb = SAT_CAST2(vi); -#endif - - vstore8((VECTOR8)(Y.s0, Cr.s0, Cb.s0, 0, Y.s1, Cr.s1, Cb.s1, 0), 0, dst_ptr); - } -#elif (4 == pixels_per_work_item) - { -#ifndef DEPTH_5 - const VECTOR16 r0 = vload16(0, src_ptr); - const int4 c0 = convert_int4(r0.s048c); - const int4 c1 = convert_int4(r0.s159d); - const int4 c2 = convert_int4(r0.s26ae); - - const int4 yi = (bidx == 0) ? CV_DESCALE(c0 * coeffs[2] + c1 * coeffs[1] + c2 * coeffs[0], yuv_shift) : CV_DESCALE(c0 * coeffs[0] + c1 * coeffs[1] + c2 * coeffs[2], yuv_shift); - const int4 ui = (bidx == 0) ? CV_DESCALE((c2 - yi) * coeffs[3] + delta, yuv_shift) : CV_DESCALE((c0 - yi) * coeffs[3] + delta, yuv_shift); - const int4 vi = (bidx == 0) ? CV_DESCALE((c0 - yi) * coeffs[4] + delta, yuv_shift) : CV_DESCALE((c2 - yi) * coeffs[4] + delta, yuv_shift); - - const VECTOR4 Y = SAT_CAST4(yi); - const VECTOR4 Cr = SAT_CAST4(ui); - const VECTOR4 Cb = SAT_CAST4(vi); - - vstore16((VECTOR16)(Y.s0, Cr.s0, Cb.s0, 0, Y.s1, Cr.s1, Cb.s1, 0, Y.s2, Cr.s2, Cb.s2, 0, Y.s3, Cr.s3, Cb.s3, 0), 0, dst_ptr); -#endif - } -#endif //pixels_per_work_item - } -} - -__constant float c_YCrCb2RGBCoeffs_f[4] = { 1.403f, -0.714f, -0.344f, 1.773f }; -__constant int c_YCrCb2RGBCoeffs_i[4] = { 22987, -11698, -5636, 29049 }; - -__kernel void YCrCb2RGB(int cols, int rows, int src_step, int dst_step, - __global const DATA_TYPE* src, __global DATA_TYPE* dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0) * pixels_per_work_item; - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - global DATA_TYPE *src_ptr = (global DATA_TYPE *)(src + src_idx); - global DATA_TYPE *dst_ptr = (global DATA_TYPE *)(dst + dst_idx); - -#ifdef DEPTH_5 - __constant float * coeffs = c_YCrCb2RGBCoeffs_f; -#else - __constant int * coeffs = c_YCrCb2RGBCoeffs_i; -#endif - -#if (1 == pixels_per_work_item) - { - const DATA_TYPE ycrcb[] = {src_ptr[0], src_ptr[1], src_ptr[2]}; - -#ifdef DEPTH_5 - float B = ycrcb[0] + (ycrcb[2] - HALF_MAX) * coeffs[3]; - float G = ycrcb[0] + (ycrcb[2] - HALF_MAX) * coeffs[2] + (ycrcb[1] - HALF_MAX) * coeffs[1]; - float R = ycrcb[0] + (ycrcb[1] - HALF_MAX) * coeffs[0]; -#else - int B = ycrcb[0] + CV_DESCALE((ycrcb[2] - HALF_MAX) * coeffs[3], yuv_shift); - int G = ycrcb[0] + CV_DESCALE((ycrcb[2] - HALF_MAX) * coeffs[2] + (ycrcb[1] - HALF_MAX) * coeffs[1], yuv_shift); - int R = ycrcb[0] + CV_DESCALE((ycrcb[1] - HALF_MAX) * coeffs[0], yuv_shift); -#endif - - dst_ptr[bidx] = SAT_CAST( B ); - dst_ptr[1] = SAT_CAST( G ); - dst_ptr[(bidx^2)] = SAT_CAST( R ); -#if dcn == 4 - dst_ptr[3] = MAX_NUM; -#endif - } -#elif (2 == pixels_per_work_item) - { - const VECTOR8 r0 = vload8(0, src_ptr); - -#ifdef DEPTH_5 - const float2 Y = r0.s04; - const float2 Cr = r0.s15; - const float2 Cb = r0.s26; - - const float2 c0 = (bidx == 0) ? (Y + (Cb - HALF_MAX) * coeffs[3]) : (Y + (Cr - HALF_MAX) * coeffs[0]); - const float2 c1 = Y + (Cb - HALF_MAX) * coeffs[2] + (Cr - HALF_MAX) * coeffs[1]; - const float2 c2 = (bidx == 0) ? (Y + (Cr - HALF_MAX) * coeffs[0]) : (Y + (Cb - HALF_MAX) * coeffs[3]); -#else - const int2 Y = convert_int2(r0.s04); - const int2 Cr = convert_int2(r0.s15); - const int2 Cb = convert_int2(r0.s26); - - const int2 c0i = (bidx == 0) ? (Y + CV_DESCALE((Cb - HALF_MAX) * coeffs[3], yuv_shift)) : (Y + CV_DESCALE((Cr - HALF_MAX) * coeffs[0], yuv_shift)); - const int2 c1i = Y + CV_DESCALE((Cb - HALF_MAX) * coeffs[2] + (Cr - HALF_MAX) * coeffs[1], yuv_shift); - const int2 c2i = (bidx == 0) ? (Y + CV_DESCALE((Cr - HALF_MAX) * coeffs[0], yuv_shift)) : (Y + CV_DESCALE((Cb - HALF_MAX) * coeffs[3], yuv_shift)); - - const VECTOR2 c0 = SAT_CAST2(c0i); - const VECTOR2 c1 = SAT_CAST2(c1i); - const VECTOR2 c2 = SAT_CAST2(c2i); -#endif - -#if dcn == 4 - vstore8((VECTOR8)(c0.s0, c1.s0, c2.s0, MAX_NUM, c0.s1, c1.s1, c2.s1, MAX_NUM), 0, dst_ptr); -#else - vstore8((VECTOR8)(c0.s0, c1.s0, c2.s0, 0, c0.s1, c1.s1, c2.s1, 0), 0, dst_ptr); -#endif - } -#elif (4 == pixels_per_work_item) - { -#ifndef DEPTH_5 - const VECTOR16 r0 = vload16(0, src_ptr); - - const int4 Y = convert_int4(r0.s048c); - const int4 Cr = convert_int4(r0.s159d); - const int4 Cb = convert_int4(r0.s26ae); - - const int4 c0i = (bidx == 0) ? (Y + CV_DESCALE((Cb - HALF_MAX) * coeffs[3], yuv_shift)) : (Y + CV_DESCALE((Cr - HALF_MAX) * coeffs[0], yuv_shift)); - const int4 c1i = Y + CV_DESCALE((Cb - HALF_MAX) * coeffs[2] + (Cr - HALF_MAX) * coeffs[1], yuv_shift); - const int4 c2i = (bidx == 0) ? (Y + CV_DESCALE((Cr - HALF_MAX) * coeffs[0], yuv_shift)) : (Y + CV_DESCALE((Cb - HALF_MAX) * coeffs[3], yuv_shift)); - - const VECTOR4 c0 = SAT_CAST4(c0i); - const VECTOR4 c1 = SAT_CAST4(c1i); - const VECTOR4 c2 = SAT_CAST4(c2i); - -#if dcn == 4 - vstore16((VECTOR16)(c0.s0, c1.s0, c2.s0, MAX_NUM, c0.s1, c1.s1, c2.s1, MAX_NUM, c0.s2, c1.s2, c2.s2, MAX_NUM, c0.s3, c1.s3, c2.s3, MAX_NUM), 0, dst_ptr); -#else - vstore16((VECTOR16)(c0.s0, c1.s0, c2.s0, 0, c0.s1, c1.s1, c2.s1, 0, c0.s2, c1.s2, c2.s2, 0, c0.s3, c1.s3, c2.s3, 0), 0, dst_ptr); -#endif -#endif - } -#endif //pixels_per_work_item - } -} - -///////////////////////////////////// RGB <-> XYZ ////////////////////////////////////// - -__kernel void RGB2XYZ(int cols, int rows, int src_step, int dst_step, - __global const DATA_TYPE* src, __global DATA_TYPE* dst, - int src_offset, int dst_offset, __constant COEFF_TYPE * coeffs) -{ - int dx = get_global_id(0) * pixels_per_work_item; - int dy = get_global_id(1); - - if (dy < rows && dx < cols) - { - dx <<= 2; - int src_idx = mad24(dy, src_step, src_offset + dx); - int dst_idx = mad24(dy, dst_step, dst_offset + dx); - - global DATA_TYPE *src_ptr = (global DATA_TYPE *)(src + src_idx); - global DATA_TYPE *dst_ptr = (global DATA_TYPE *)(dst + dst_idx); - -#if (1 == pixels_per_work_item) - { - DATA_TYPE R = src_ptr[0], G = src_ptr[1], B = src_ptr[2]; - -#ifdef DEPTH_5 - float X = R * coeffs[0] + G * coeffs[1] + B * coeffs[2]; - float Y = R * coeffs[3] + G * coeffs[4] + B * coeffs[5]; - float Z = R * coeffs[6] + G * coeffs[7] + B * coeffs[8]; -#else - int X = CV_DESCALE(R * coeffs[0] + G * coeffs[1] + B * coeffs[2], xyz_shift); - int Y = CV_DESCALE(R * coeffs[3] + G * coeffs[4] + B * coeffs[5], xyz_shift); - int Z = CV_DESCALE(R * coeffs[6] + G * coeffs[7] + B * coeffs[8], xyz_shift); -#endif - - dst_ptr[0] = SAT_CAST( X ); - dst_ptr[1] = SAT_CAST( Y ); - dst_ptr[2] = SAT_CAST( Z ); - } -#elif (2 == pixels_per_work_item) - { - const VECTOR8 r0 = vload8(0, src_ptr); - -#ifdef DEPTH_5 - const float2 R = r0.s04; - const float2 G = r0.s15; - const float2 B = r0.s26; - - const float2 X = R * coeffs[0] + G * coeffs[1] + B * coeffs[2]; - const float2 Y = R * coeffs[3] + G * coeffs[4] + B * coeffs[5]; - const float2 Z = R * coeffs[6] + G * coeffs[7] + B * coeffs[8]; -#else - const int2 R = convert_int2(r0.s04); - const int2 G = convert_int2(r0.s15); - const int2 B = convert_int2(r0.s26); - - const int2 xi = CV_DESCALE(R * coeffs[0] + G * coeffs[1] + B * coeffs[2], xyz_shift); - const int2 yi = CV_DESCALE(R * coeffs[3] + G * coeffs[4] + B * coeffs[5], xyz_shift); - const int2 zi = CV_DESCALE(R * coeffs[6] + G * coeffs[7] + B * coeffs[8], xyz_shift); - - const VECTOR2 X = SAT_CAST2(xi); - const VECTOR2 Y = SAT_CAST2(yi); - const VECTOR2 Z = SAT_CAST2(zi); -#endif - - vstore8((VECTOR8)(X.s0, Y.s0, Z.s0, 0, X.s1, Y.s1, Z.s1, 0), 0, dst_ptr); - } -#elif (4 == pixels_per_work_item) - { -#ifndef DEPTH_5 - const VECTOR16 r0 = vload16(0, src_ptr); - - const int4 R = convert_int4(r0.s048c); - const int4 G = convert_int4(r0.s159d); - const int4 B = convert_int4(r0.s26ae); - - const int4 xi = CV_DESCALE(R * coeffs[0] + G * coeffs[1] + B * coeffs[2], xyz_shift); - const int4 yi = CV_DESCALE(R * coeffs[3] + G * coeffs[4] + B * coeffs[5], xyz_shift); - const int4 zi = CV_DESCALE(R * coeffs[6] + G * coeffs[7] + B * coeffs[8], xyz_shift); - - const VECTOR4 X = SAT_CAST4(xi); - const VECTOR4 Y = SAT_CAST4(yi); - const VECTOR4 Z = SAT_CAST4(zi); - - vstore16((VECTOR16)(X.s0, Y.s0, Z.s0, 0, X.s1, Y.s1, Z.s1, 0, X.s2, Y.s2, Z.s2, 0, X.s3, Y.s3, Z.s3, 0), 0, dst_ptr); -#endif - } -#endif //pixels_per_work_item - } -} - -__kernel void XYZ2RGB(int cols, int rows, int src_step, int dst_step, - __global const DATA_TYPE* src, __global DATA_TYPE* dst, - int src_offset, int dst_offset, __constant COEFF_TYPE * coeffs) -{ - int dx = get_global_id(0) * pixels_per_work_item; - int dy = get_global_id(1); - - if (dy < rows && dx < cols) - { - dx <<= 2; - int src_idx = mad24(dy, src_step, src_offset + dx); - int dst_idx = mad24(dy, dst_step, dst_offset + dx); - - global DATA_TYPE *src_ptr = (global DATA_TYPE *)(src + src_idx); - global DATA_TYPE *dst_ptr = (global DATA_TYPE *)(dst + dst_idx); - -#if (1 == pixels_per_work_item) - { - const DATA_TYPE X = src_ptr[0], Y = src_ptr[1], Z = src_ptr[2]; - -#ifdef DEPTH_5 - float B = X * coeffs[0] + Y * coeffs[1] + Z * coeffs[2]; - float G = X * coeffs[3] + Y * coeffs[4] + Z * coeffs[5]; - float R = X * coeffs[6] + Y * coeffs[7] + Z * coeffs[8]; -#else - int B = CV_DESCALE(X * coeffs[0] + Y * coeffs[1] + Z * coeffs[2], xyz_shift); - int G = CV_DESCALE(X * coeffs[3] + Y * coeffs[4] + Z * coeffs[5], xyz_shift); - int R = CV_DESCALE(X * coeffs[6] + Y * coeffs[7] + Z * coeffs[8], xyz_shift); -#endif - - dst_ptr[0] = SAT_CAST( B ); - dst_ptr[1] = SAT_CAST( G ); - dst_ptr[2] = SAT_CAST( R ); -#if dcn == 4 - dst_ptr[3] = MAX_NUM; -#endif - } -#elif (2 == pixels_per_work_item) - { - const VECTOR8 r0 = vload8(0, src_ptr); - -#ifdef DEPTH_5 - const float2 X = r0.s04; - const float2 Y = r0.s15; - const float2 Z = r0.s26; - - float2 B = X * coeffs[0] + Y * coeffs[1] + Z * coeffs[2]; - float2 G = X * coeffs[3] + Y * coeffs[4] + Z * coeffs[5]; - float2 R = X * coeffs[6] + Y * coeffs[7] + Z * coeffs[8]; -#else - const int2 xi = convert_int2(r0.s04); - const int2 yi = convert_int2(r0.s15); - const int2 zi = convert_int2(r0.s26); - - const int2 bi = CV_DESCALE(xi * coeffs[0] + yi * coeffs[1] + zi * coeffs[2], xyz_shift); - const int2 gi = CV_DESCALE(xi * coeffs[3] + yi * coeffs[4] + zi * coeffs[5], xyz_shift); - const int2 ri = CV_DESCALE(xi * coeffs[6] + yi * coeffs[7] + zi * coeffs[8], xyz_shift); - - const VECTOR2 R = SAT_CAST2(ri); - const VECTOR2 G = SAT_CAST2(gi); - const VECTOR2 B = SAT_CAST2(bi); -#endif - -#if dcn == 4 - vstore8((VECTOR8)(B.s0, G.s0, R.s0, MAX_NUM, B.s1, G.s1, R.s1, MAX_NUM), 0, dst_ptr); -#else - vstore8((VECTOR8)(B.s0, G.s0, R.s0, 0, B.s1, G.s1, R.s1, 0), 0, dst_ptr); -#endif - } -#elif (4 == pixels_per_work_item) - { -#ifndef DEPTH_5 - const VECTOR16 r0 = vload16(0, src_ptr); - - const int4 xi = convert_int4(r0.s048c); - const int4 yi = convert_int4(r0.s159d); - const int4 zi = convert_int4(r0.s26ae); - - const int4 bi = CV_DESCALE(xi * coeffs[0] + yi * coeffs[1] + zi * coeffs[2], xyz_shift); - const int4 gi = CV_DESCALE(xi * coeffs[3] + yi * coeffs[4] + zi * coeffs[5], xyz_shift); - const int4 ri = CV_DESCALE(xi * coeffs[6] + yi * coeffs[7] + zi * coeffs[8], xyz_shift); - - const VECTOR4 R = SAT_CAST4(ri); - const VECTOR4 G = SAT_CAST4(gi); - const VECTOR4 B = SAT_CAST4(bi); - -#if dcn == 4 - vstore16((VECTOR16)(B.s0, G.s0, R.s0, MAX_NUM, B.s1, G.s1, R.s1, MAX_NUM, B.s2, G.s2, R.s2, MAX_NUM, B.s3, G.s3, R.s3, MAX_NUM), 0, dst_ptr); -#else - vstore16((VECTOR16)(B.s0, G.s0, R.s0, 0, B.s1, G.s1, R.s1, 0, B.s2, G.s2, R.s2, 0, B.s3, G.s3, R.s3, 0), 0, dst_ptr); -#endif -#endif - } -#endif // pixels_per_work_item - } -} - -///////////////////////////////////// RGB[A] <-> BGR[A] ////////////////////////////////////// - -__kernel void RGB(int cols, int rows, int src_step, int dst_step, - __global const DATA_TYPE * src, __global DATA_TYPE * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - -#ifndef INTEL_DEVICE -#ifdef REVERSE - dst[dst_idx] = src[src_idx + 2]; - dst[dst_idx + 1] = src[src_idx + 1]; - dst[dst_idx + 2] = src[src_idx]; -#elif defined ORDER - dst[dst_idx] = src[src_idx]; - dst[dst_idx + 1] = src[src_idx + 1]; - dst[dst_idx + 2] = src[src_idx + 2]; -#endif - -#if dcn == 4 -#if scn == 3 - dst[dst_idx + 3] = MAX_NUM; -#else - dst[dst_idx + 3] = src[src_idx + 3]; -#endif -#endif -#else //INTEL_DEVICE - global DATA_TYPE *src_ptr = (global DATA_TYPE *)(src + src_idx); - global DATA_TYPE *dst_ptr = (global DATA_TYPE *)(dst + dst_idx); - - const VECTOR4 r0 = vload4(0, src_ptr); -#ifdef REVERSE - if (3 == dcn) - { - vstore4((VECTOR4)(r0.s210, 0), 0, dst_ptr); - } - else if (3 == scn) - { - vstore4((VECTOR4)(r0.s210, MAX_NUM), 0, dst_ptr); - } - else { - vstore4((VECTOR4)(r0.s2103), 0, dst_ptr); - } -#elif defined ORDER - if (3 == dcn) - { - vstore4((VECTOR4)(r0.s012, 0), 0, dst_ptr); - } - else if (3 == scn) - { - vstore4((VECTOR4)(r0.s012, MAX_NUM), 0, dst_ptr); - } - else { - vstore4(r0, 0, dst_ptr); - } -#endif -#endif //INTEL_DEVICE - } -} - -///////////////////////////////////// RGB5x5 <-> RGB ////////////////////////////////////// - -__kernel void RGB5x52RGB(int cols, int rows, int src_step, int dst_step, - __global const ushort * src, __global uchar * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + (x << 2)); - ushort t = src[src_idx]; - -#if greenbits == 6 - dst[dst_idx + bidx] = (uchar)(t << 3); - dst[dst_idx + 1] = (uchar)((t >> 3) & ~3); - dst[dst_idx + (bidx^2)] = (uchar)((t >> 8) & ~7); -#else - dst[dst_idx + bidx] = (uchar)(t << 3); - dst[dst_idx + 1] = (uchar)((t >> 2) & ~7); - dst[dst_idx + (bidx^2)] = (uchar)((t >> 7) & ~7); -#endif - -#if dcn == 4 -#if greenbits == 6 - dst[dst_idx + 3] = 255; -#else - dst[dst_idx + 3] = t & 0x8000 ? 255 : 0; -#endif -#endif - } -} - -__kernel void RGB2RGB5x5(int cols, int rows, int src_step, int dst_step, - __global const uchar * src, __global ushort * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - int src_idx = mad24(y, src_step, src_offset + (x << 2)); - int dst_idx = mad24(y, dst_step, dst_offset + x); - -#if greenbits == 6 - dst[dst_idx] = (ushort)((src[src_idx + bidx] >> 3)|((src[src_idx + 1]&~3) << 3)|((src[src_idx + (bidx^2)]&~7) << 8)); -#elif scn == 3 - dst[dst_idx] = (ushort)((src[src_idx + bidx] >> 3)|((src[src_idx + 1]&~7) << 2)|((src[src_idx + (bidx^2)]&~7) << 7)); -#else - dst[dst_idx] = (ushort)((src[src_idx + bidx] >> 3)|((src[src_idx + 1]&~7) << 2)| - ((src[src_idx + (bidx^2)]&~7) << 7)|(src[src_idx + 3] ? 0x8000 : 0)); -#endif - } -} - -///////////////////////////////////// RGB5x5 <-> RGB ////////////////////////////////////// - -__kernel void BGR5x52Gray(int cols, int rows, int src_step, int dst_step, - __global const ushort * src, __global uchar * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - int t = src[src_idx]; - -#if greenbits == 6 - dst[dst_idx] = (uchar)CV_DESCALE(((t << 3) & 0xf8)*B2Y + - ((t >> 3) & 0xfc)*G2Y + - ((t >> 8) & 0xf8)*R2Y, yuv_shift); -#else - dst[dst_idx] = (uchar)CV_DESCALE(((t << 3) & 0xf8)*B2Y + - ((t >> 2) & 0xf8)*G2Y + - ((t >> 7) & 0xf8)*R2Y, yuv_shift); -#endif - } -} - -__kernel void Gray2BGR5x5(int cols, int rows, int src_step, int dst_step, - __global const uchar * src, __global ushort * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - int t = src[src_idx]; - -#if greenbits == 6 - dst[dst_idx] = (ushort)((t >> 3) | ((t & ~3) << 3) | ((t & ~7) << 8)); -#else - t >>= 3; - dst[dst_idx] = (ushort)(t|(t << 5)|(t << 10)); -#endif - } -} - -///////////////////////////////////// RGB <-> HSV ////////////////////////////////////// - -__constant int sector_data[][3] = { {1, 3, 0}, { 1, 0, 2 }, { 3, 0, 1 }, { 0, 2, 1 }, { 0, 1, 3 }, { 2, 1, 0 } }; - -#ifdef DEPTH_0 - -__kernel void RGB2HSV(int cols, int rows, int src_step, int dst_step, - __global const uchar * src, __global uchar * dst, - int src_offset, int dst_offset, - __constant int * sdiv_table, __constant int * hdiv_table) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - int b = src[src_idx + bidx], g = src[src_idx + 1], r = src[src_idx + (bidx^2)]; - int h, s, v = b; - int vmin = b, diff; - int vr, vg; - - v = max( v, g ); - v = max( v, r ); - vmin = min( vmin, g ); - vmin = min( vmin, r ); - - diff = v - vmin; - vr = v == r ? -1 : 0; - vg = v == g ? -1 : 0; - - s = (diff * sdiv_table[v] + (1 << (hsv_shift-1))) >> hsv_shift; - h = (vr & (g - b)) + - (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff)))); - h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift; - h += h < 0 ? hrange : 0; - - dst[dst_idx] = convert_uchar_sat_rte(h); - dst[dst_idx + 1] = (uchar)s; - dst[dst_idx + 2] = (uchar)v; - } -} - -__kernel void HSV2RGB(int cols, int rows, int src_step, int dst_step, - __global const uchar * src, __global uchar * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - float h = src[src_idx], s = src[src_idx + 1]*(1/255.f), v = src[src_idx + 2]*(1/255.f); - float b, g, r; - - if (s != 0) - { - float tab[4]; - int sector; - h *= hscale; - if( h < 0 ) - do h += 6; while( h < 0 ); - else if( h >= 6 ) - do h -= 6; while( h >= 6 ); - sector = convert_int_sat_rtn(h); - h -= sector; - if( (unsigned)sector >= 6u ) - { - sector = 0; - h = 0.f; - } - - tab[0] = v; - tab[1] = v*(1.f - s); - tab[2] = v*(1.f - s*h); - tab[3] = v*(1.f - s*(1.f - h)); - - b = tab[sector_data[sector][0]]; - g = tab[sector_data[sector][1]]; - r = tab[sector_data[sector][2]]; - } - else - b = g = r = v; - - dst[dst_idx + bidx] = convert_uchar_sat_rte(b*255.f); - dst[dst_idx + 1] = convert_uchar_sat_rte(g*255.f); - dst[dst_idx + (bidx^2)] = convert_uchar_sat_rte(r*255.f); -#if dcn == 4 - dst[dst_idx + 3] = MAX_NUM; -#endif - } -} - -#elif defined DEPTH_5 - -__kernel void RGB2HSV(int cols, int rows, int src_step, int dst_step, - __global const float * src, __global float * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - float b = src[src_idx + bidx], g = src[src_idx + 1], r = src[src_idx + (bidx^2)]; - float h, s, v; - - float vmin, diff; - - v = vmin = r; - if( v < g ) v = g; - if( v < b ) v = b; - if( vmin > g ) vmin = g; - if( vmin > b ) vmin = b; - - diff = v - vmin; - s = diff/(float)(fabs(v) + FLT_EPSILON); - diff = (float)(60./(diff + FLT_EPSILON)); - if( v == r ) - h = (g - b)*diff; - else if( v == g ) - h = (b - r)*diff + 120.f; - else - h = (r - g)*diff + 240.f; - - if( h < 0 ) h += 360.f; - - dst[dst_idx] = h*hscale; - dst[dst_idx + 1] = s; - dst[dst_idx + 2] = v; - } -} - -__kernel void HSV2RGB(int cols, int rows, int src_step, int dst_step, - __global const float * src, __global float * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - float h = src[src_idx], s = src[src_idx + 1], v = src[src_idx + 2]; - float b, g, r; - - if (s != 0) - { - float tab[4]; - int sector; - h *= hscale; - if(h < 0) - do h += 6; while (h < 0); - else if (h >= 6) - do h -= 6; while (h >= 6); - sector = convert_int_sat_rtn(h); - h -= sector; - if ((unsigned)sector >= 6u) - { - sector = 0; - h = 0.f; - } - - tab[0] = v; - tab[1] = v*(1.f - s); - tab[2] = v*(1.f - s*h); - tab[3] = v*(1.f - s*(1.f - h)); - - b = tab[sector_data[sector][0]]; - g = tab[sector_data[sector][1]]; - r = tab[sector_data[sector][2]]; - } - else - b = g = r = v; - - dst[dst_idx + bidx] = b; - dst[dst_idx + 1] = g; - dst[dst_idx + (bidx^2)] = r; -#if dcn == 4 - dst[dst_idx + 3] = MAX_NUM; -#endif - } -} - -#endif - -///////////////////////////////////// RGB <-> HLS ////////////////////////////////////// - -#ifdef DEPTH_0 - -__kernel void RGB2HLS(int cols, int rows, int src_step, int dst_step, - __global const uchar * src, __global uchar * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - float b = src[src_idx + bidx]*(1/255.f), g = src[src_idx + 1]*(1/255.f), r = src[src_idx + (bidx^2)]*(1/255.f); - float h = 0.f, s = 0.f, l; - float vmin, vmax, diff; - - vmax = vmin = r; - if (vmax < g) vmax = g; - if (vmax < b) vmax = b; - if (vmin > g) vmin = g; - if (vmin > b) vmin = b; - - diff = vmax - vmin; - l = (vmax + vmin)*0.5f; - - if (diff > FLT_EPSILON) - { - s = l < 0.5f ? diff/(vmax + vmin) : diff/(2 - vmax - vmin); - diff = 60.f/diff; - - if( vmax == r ) - h = (g - b)*diff; - else if( vmax == g ) - h = (b - r)*diff + 120.f; - else - h = (r - g)*diff + 240.f; - - if( h < 0.f ) h += 360.f; - } - - dst[dst_idx] = convert_uchar_sat_rte(h*hscale); - dst[dst_idx + 1] = convert_uchar_sat_rte(l*255.f); - dst[dst_idx + 2] = convert_uchar_sat_rte(s*255.f); - } -} - -__kernel void HLS2RGB(int cols, int rows, int src_step, int dst_step, - __global const uchar * src, __global uchar * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - float h = src[src_idx], l = src[src_idx + 1]*(1.f/255.f), s = src[src_idx + 2]*(1.f/255.f); - float b, g, r; - - if (s != 0) - { - float tab[4]; - - float p2 = l <= 0.5f ? l*(1 + s) : l + s - l*s; - float p1 = 2*l - p2; - - h *= hscale; - if( h < 0 ) - do h += 6; while( h < 0 ); - else if( h >= 6 ) - do h -= 6; while( h >= 6 ); - - int sector = convert_int_sat_rtn(h); - h -= sector; - - tab[0] = p2; - tab[1] = p1; - tab[2] = p1 + (p2 - p1)*(1-h); - tab[3] = p1 + (p2 - p1)*h; - - b = tab[sector_data[sector][0]]; - g = tab[sector_data[sector][1]]; - r = tab[sector_data[sector][2]]; - } - else - b = g = r = l; - - dst[dst_idx + bidx] = convert_uchar_sat_rte(b*255.f); - dst[dst_idx + 1] = convert_uchar_sat_rte(g*255.f); - dst[dst_idx + (bidx^2)] = convert_uchar_sat_rte(r*255.f); -#if dcn == 4 - dst[dst_idx + 3] = MAX_NUM; -#endif - } -} - -#elif defined DEPTH_5 - -__kernel void RGB2HLS(int cols, int rows, int src_step, int dst_step, - __global const float * src, __global float * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - float b = src[src_idx + bidx], g = src[src_idx + 1], r = src[src_idx + (bidx^2)]; - float h = 0.f, s = 0.f, l; - float vmin, vmax, diff; - - vmax = vmin = r; - if (vmax < g) vmax = g; - if (vmax < b) vmax = b; - if (vmin > g) vmin = g; - if (vmin > b) vmin = b; - - diff = vmax - vmin; - l = (vmax + vmin)*0.5f; - - if (diff > FLT_EPSILON) - { - s = l < 0.5f ? diff/(vmax + vmin) : diff/(2 - vmax - vmin); - diff = 60.f/diff; - - if( vmax == r ) - h = (g - b)*diff; - else if( vmax == g ) - h = (b - r)*diff + 120.f; - else - h = (r - g)*diff + 240.f; - - if( h < 0.f ) h += 360.f; - } - - dst[dst_idx] = h*hscale; - dst[dst_idx + 1] = l; - dst[dst_idx + 2] = s; - } -} - -__kernel void HLS2RGB(int cols, int rows, int src_step, int dst_step, - __global const float * src, __global float * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - float h = src[src_idx], l = src[src_idx + 1], s = src[src_idx + 2]; - float b, g, r; - - if (s != 0) - { - float tab[4]; - int sector; - - float p2 = l <= 0.5f ? l*(1 + s) : l + s - l*s; - float p1 = 2*l - p2; - - h *= hscale; - if( h < 0 ) - do h += 6; while( h < 0 ); - else if( h >= 6 ) - do h -= 6; while( h >= 6 ); - - sector = convert_int_sat_rtn(h); - h -= sector; - - tab[0] = p2; - tab[1] = p1; - tab[2] = p1 + (p2 - p1)*(1-h); - tab[3] = p1 + (p2 - p1)*h; - - b = tab[sector_data[sector][0]]; - g = tab[sector_data[sector][1]]; - r = tab[sector_data[sector][2]]; - } - else - b = g = r = l; - - dst[dst_idx + bidx] = b; - dst[dst_idx + 1] = g; - dst[dst_idx + (bidx^2)] = r; -#if dcn == 4 - dst[dst_idx + 3] = MAX_NUM; -#endif - } -} - -#endif - -/////////////////////////// RGBA <-> mRGBA (alpha premultiplied) ////////////// - -#ifdef DEPTH_0 - -__kernel void RGBA2mRGBA(int cols, int rows, int src_step, int dst_step, - __global const uchar * src, __global uchar * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0) * pixels_per_work_item; - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - global DATA_TYPE *src_ptr = (global DATA_TYPE *)(src + src_idx); - global DATA_TYPE *dst_ptr = (global DATA_TYPE *)(dst + dst_idx); - -#if (1 == pixels_per_work_item) - { - const uchar4 r0 = vload4(0, src_ptr); - - dst_ptr[0] = (r0.s0 * r0.s3 + HALF_MAX) / MAX_NUM; - dst_ptr[1] = (r0.s1 * r0.s3 + HALF_MAX) / MAX_NUM; - dst_ptr[2] = (r0.s2 * r0.s3 + HALF_MAX) / MAX_NUM; - dst_ptr[3] = r0.s3; - } -#elif (2 == pixels_per_work_item) - { - const uchar8 r0 = vload8(0, src_ptr); - - const int2 v0 = convert_int2(r0.s04); - const int2 v1 = convert_int2(r0.s15); - const int2 v2 = convert_int2(r0.s26); - const int2 v3 = convert_int2(r0.s37); - - const int2 ri = (v0 * v3 + HALF_MAX) / MAX_NUM; - const int2 gi = (v1 * v3 + HALF_MAX) / MAX_NUM; - const int2 bi = (v2 * v3 + HALF_MAX) / MAX_NUM; - - const uchar2 r = convert_uchar2(ri); - const uchar2 g = convert_uchar2(gi); - const uchar2 b = convert_uchar2(bi); - - vstore8((uchar8)(r.s0, g.s0, b.s0, v3.s0, r.s1, g.s1, b.s1, v3.s1), 0, dst_ptr); - } -#elif (4 == pixels_per_work_item) - { - const uchar16 r0 = vload16(0, src_ptr); - - const int4 v0 = convert_int4(r0.s048c); - const int4 v1 = convert_int4(r0.s159d); - const int4 v2 = convert_int4(r0.s26ae); - const int4 v3 = convert_int4(r0.s37bf); - - const int4 ri = (v0 * v3 + HALF_MAX) / MAX_NUM; - const int4 gi = (v1 * v3 + HALF_MAX) / MAX_NUM; - const int4 bi = (v2 * v3 + HALF_MAX) / MAX_NUM; - - const uchar4 r = convert_uchar4(ri); - const uchar4 g = convert_uchar4(gi); - const uchar4 b = convert_uchar4(bi); - - vstore16((uchar16)(r.s0, g.s0, b.s0, v3.s0, r.s1, g.s1, b.s1, v3.s1, r.s2, g.s2, b.s2, v3.s2, r.s3, g.s3, b.s3, v3.s3), 0, dst_ptr); - } -#endif // pixels_per_work_item - } -} - -__kernel void mRGBA2RGBA(int cols, int rows, int src_step, int dst_step, - __global const uchar * src, __global uchar * dst, - int src_offset, int dst_offset) -{ - int x = get_global_id(0) * pixels_per_work_item; - int y = get_global_id(1); - - if (y < rows && x < cols) - { - x <<= 2; - int src_idx = mad24(y, src_step, src_offset + x); - int dst_idx = mad24(y, dst_step, dst_offset + x); - - global DATA_TYPE *src_ptr = (global DATA_TYPE *)(src + src_idx); - global DATA_TYPE *dst_ptr = (global DATA_TYPE *)(dst + dst_idx); - -#if (1 == pixels_per_work_item) - { - const uchar4 r0 = vload4(0, src_ptr); - const uchar v3_half = r0.s3 / 2; - - const uchar r = (r0.s3 == 0) ? 0 : (r0.s0 * MAX_NUM + v3_half) / r0.s3; - const uchar g = (r0.s3 == 0) ? 0 : (r0.s1 * MAX_NUM + v3_half) / r0.s3; - const uchar b = (r0.s3 == 0) ? 0 : (r0.s2 * MAX_NUM + v3_half) / r0.s3; - - vstore4((uchar4)(r, g, b, r0.s3), 0, dst_ptr); - } -#elif (2 == pixels_per_work_item) - { - const uchar8 r0 = vload8(0, src_ptr); - - const int2 v0 = convert_int2(r0.s04); - const int2 v1 = convert_int2(r0.s15); - const int2 v2 = convert_int2(r0.s26); - const int2 v3 = convert_int2(r0.s37); - const int2 v3_half = v3 / 2; - - const int2 ri = (v3 == 0) ? 0 : (v0 * MAX_NUM + v3_half) / v3; - const int2 gi = (v3 == 0) ? 0 : (v1 * MAX_NUM + v3_half) / v3; - const int2 bi = (v3 == 0) ? 0 : (v2 * MAX_NUM + v3_half) / v3; - - const uchar2 r = convert_uchar2(ri); - const uchar2 g = convert_uchar2(gi); - const uchar2 b = convert_uchar2(bi); - - vstore8((uchar8)(r.s0, g.s0, b.s0, v3.s0, r.s1, g.s1, b.s1, v3.s1), 0, dst_ptr); - } -#elif (4 == pixels_per_work_item) - { - const uchar16 r0 = vload16(0, src_ptr); - - const int4 v0 = convert_int4(r0.s048c); - const int4 v1 = convert_int4(r0.s159d); - const int4 v2 = convert_int4(r0.s26ae); - const int4 v3 = convert_int4(r0.s37bf); - const int4 v3_half = v3 / 2; - - - const int4 ri = (v3 == 0) ? 0 : (v0 * MAX_NUM + v3_half) / v3; - const int4 gi = (v3 == 0) ? 0 : (v1 * MAX_NUM + v3_half) / v3; - const int4 bi = (v3 == 0) ? 0 : (v2 * MAX_NUM + v3_half) / v3; - - const uchar4 r = convert_uchar4(ri); - const uchar4 g = convert_uchar4(gi); - const uchar4 b = convert_uchar4(bi); - - vstore16((uchar16)(r.s0, g.s0, b.s0, v3.s0, r.s1, g.s1, b.s1, v3.s1, r.s2, g.s2, b.s2, v3.s2, r.s3, g.s3, b.s3, v3.s3), 0, dst_ptr); - } -#endif // pixels_per_work_item - } -} - -#endif diff --git a/modules/ocl/src/opencl/featdetect_fast.cl b/modules/ocl/src/opencl/featdetect_fast.cl deleted file mode 100644 index 44d4f44e6..000000000 --- a/modules/ocl/src/opencl/featdetect_fast.cl +++ /dev/null @@ -1,1331 +0,0 @@ -/*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. -// -// Authors: -// * Peter Andreas Entschev, peter@entschev.com -// -//M*/ - -#define X_ROW 0 -#define Y_ROW 1 -#define RESPONSE_ROW 2 -#define ROWS_COUNT 3 - - -__constant uchar c_table[] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x80, - 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, - 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, - 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, - 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, - 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, - 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, - 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, - 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, - 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, - 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, - 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, - 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, - 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, - 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xc0, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff }; - - -// 1 -> v > x + th -// 2 -> v < x - th -// 0 -> x - th <= v <= x + th -__inline int diffType(const int v, const int x, const int th) -{ - const int diff = x - v; - - return (int)(diff < -th) + ((int)(diff > th) << 1); -} - -// For OpenCL 1.1 compatibility -__inline int popCount(int x) { - x = x - ((x >> 1) & 0x55555555); - x = (x & 0x33333333) + ((x >> 2) & 0x33333333); - x = (x + (x >> 4)) & 0x0F0F0F0F; - x = x + (x >> 8); - x = x + (x >> 16); - - return x & 0x0000003F; -} - - -void calcMask( - const uint C[4], - const int v, - const int th, - int* mask1, - int* mask2) -{ - *mask1 = 0; - *mask2 = 0; - - int d1, d2; - - - - d1 = diffType(v, C[0] & 0xff, th); - d2 = diffType(v, C[2] & 0xff, th); - - if ((d1 | d2) == 0) - return; - - *mask1 |= (d1 & 1) << 0; - *mask2 |= ((d1 & 2) >> 1) << 0; - - *mask1 |= (d2 & 1) << 8; - *mask2 |= ((d2 & 2) >> 1) << 8; - - - - d1 = diffType(v, C[1] & 0xff, th); - d2 = diffType(v, C[3] & 0xff, th); - - if ((d1 | d2) == 0) - return; - - *mask1 |= (d1 & 1) << 4; - *mask2 |= ((d1 & 2) >> 1) << 4; - - *mask1 |= (d2 & 1) << 12; - *mask2 |= ((d2 & 2) >> 1) << 12; - - - - d1 = diffType(v, (C[0] >> (2 * 8)) & 0xff, th); - d2 = diffType(v, (C[2] >> (2 * 8)) & 0xff, th); - - if ((d1 | d2) == 0) - return; - - *mask1 |= (d1 & 1) << 2; - *mask2 |= ((d1 & 2) >> 1) << 2; - - *mask1 |= (d2 & 1) << 10; - *mask2 |= ((d2 & 2) >> 1) << 10; - - - - d1 = diffType(v, (C[1] >> (2 * 8)) & 0xff, th); - d2 = diffType(v, (C[3] >> (2 * 8)) & 0xff, th); - - if ((d1 | d2) == 0) - return; - - *mask1 |= (d1 & 1) << 6; - *mask2 |= ((d1 & 2) >> 1) << 6; - - *mask1 |= (d2 & 1) << 14; - *mask2 |= ((d2 & 2) >> 1) << 14; - - - - d1 = diffType(v, (C[0] >> (1 * 8)) & 0xff, th); - d2 = diffType(v, (C[2] >> (1 * 8)) & 0xff, th); - - /*if ((d1 | d2) == 0) - return;*/ - - *mask1 |= (d1 & 1) << 1; - *mask2 |= ((d1 & 2) >> 1) << 1; - - *mask1 |= (d2 & 1) << 9; - *mask2 |= ((d2 & 2) >> 1) << 9; - - - - d1 = diffType(v, (C[0] >> (3 * 8)) & 0xff, th); - d2 = diffType(v, (C[2] >> (3 * 8)) & 0xff, th); - - /*if ((d1 | d2) == 0) - return;*/ - - *mask1 |= (d1 & 1) << 3; - *mask2 |= ((d1 & 2) >> 1) << 3; - - *mask1 |= (d2 & 1) << 11; - *mask2 |= ((d2 & 2) >> 1) << 11; - - - - d1 = diffType(v, (C[1] >> (1 * 8)) & 0xff, th); - d2 = diffType(v, (C[3] >> (1 * 8)) & 0xff, th); - - /*if ((d1 | d2) == 0) - return;*/ - - *mask1 |= (d1 & 1) << 5; - *mask2 |= ((d1 & 2) >> 1) << 5; - - *mask1 |= (d2 & 1) << 13; - *mask2 |= ((d2 & 2) >> 1) << 13; - - - - d1 = diffType(v, (C[1] >> (3 * 8)) & 0xff, th); - d2 = diffType(v, (C[3] >> (3 * 8)) & 0xff, th); - - *mask1 |= (d1 & 1) << 7; - *mask2 |= ((d1 & 2) >> 1) << 7; - - *mask1 |= (d2 & 1) << 15; - *mask2 |= ((d2 & 2) >> 1) << 15; -} - -// 1 -> v > x + th -// 2 -> v < x - th -// 0 -> not a keypoint -__inline bool isKeyPoint(int mask1, int mask2) -{ - // TODO: Use OpenCL's popcount() function if OpenCL version >= 1.2 - return (popCount(mask1) > 8 && (c_table[(mask1 >> 3) - 63] & (1 << (mask1 & 7)))) || - (popCount(mask2) > 8 && (c_table[(mask2 >> 3) - 63] & (1 << (mask2 & 7)))); -} - -int cornerScore(const uint C[4], const int v, const int threshold) -{ - // binary search in [threshold + 1, 255] - - int min = threshold + 1; - int max = 255; - - while (min <= max) - { - const int mid = (min + max) >> 1; - - int mask1 = 0; - int mask2 = 0; - - calcMask(C, v, mid, &mask1, &mask2); - - int isKp = (int)isKeyPoint(mask1, mask2); - - min = isKp * (mid + 1) + (isKp ^ 1) * min; - max = (isKp ^ 1) * (mid - 1) + isKp * max; - } - - return min - 1; -} - -/////////////////////////////////////////////////////////////////////////// -// calcKeypoints - -__kernel -void calcKeypointsWithMask( - __global const uchar* img, - __global const uchar* mask, - __global int* kpLoc, - __global uint* score, - __global int* counter, - const int calcScore, - const unsigned int maxKeypoints, - const int threshold, - const int c_img_step, - const int c_img_rows, - const int c_img_cols, - const int c_mask_step, - const int c_kploc_step, - const int c_score_step) -{ - const int j = get_global_id(0) + 3; - const int i = get_global_id(1) + 3; - - if (i < c_img_rows - 3 && j < c_img_cols - 3 && mask[i * c_mask_step + j]) - { - int v; - uint C[4] = {0,0,0,0}; - - C[2] |= (uint)img[(i - 3) * c_img_step + j - 1] << 8; - C[2] |= (uint)img[(i - 3) * c_img_step + j]; - C[1] |= (uint)img[(i - 3) * c_img_step + j + 1] << (3 * 8); - - C[2] |= (uint)img[(i - 2) * c_img_step + j - 2] << (2 * 8); - C[1] |= (uint)img[(i - 2) * c_img_step + j + 2] << (2 * 8); - - C[2] |= (uint)img[(i - 1) * c_img_step + j - 3] << (3 * 8); - C[1] |= (uint)img[(i - 1) * c_img_step + j + 3] << 8; - - C[3] |= (uint)img[i * c_img_step + j - 3]; - v = (int) img[i * c_img_step + j]; - C[1] |= (uint)img[i * c_img_step + j + 3]; - - int d1 = diffType(v, C[1] & 0xff, threshold); - int d2 = diffType(v, C[3] & 0xff, threshold); - - if ((d1 | d2) == 0) - return; - - C[3] |= (uint)img[(i + 1) * c_img_step + j - 3] << 8; - C[0] |= (uint)img[(i + 1) * c_img_step + j + 3] << (3 * 8); - - C[3] |= (uint)img[(i + 2) * c_img_step + j - 2] << (2 * 8); - C[0] |= (uint)img[(i + 2) * c_img_step + j + 2] << (2 * 8); - - C[3] |= (uint)img[(i + 3) * c_img_step + j - 1] << (3 * 8); - C[0] |= (uint)img[(i + 3) * c_img_step + j]; - C[0] |= (uint)img[(i + 3) * c_img_step + j + 1] << 8; - - int mask1 = 0; - int mask2 = 0; - - calcMask(C, v, threshold, &mask1, &mask2); - - if (isKeyPoint(mask1, mask2)) - { - if (calcScore) score[i * c_score_step + j] = cornerScore(C, v, threshold); - - uint idx = atomic_inc(counter); - - if (idx < maxKeypoints) - { - kpLoc[X_ROW * c_kploc_step + idx] = j; - kpLoc[Y_ROW * c_kploc_step + idx] = i; - } - } - } -} - -__kernel -void calcKeypoints( - __global const uchar* img, - __global int* kpLoc, - __global uint* score, - __global int* counter, - const int calcScore, - const unsigned int maxKeypoints, - const int threshold, - const int c_img_step, - const int c_img_rows, - const int c_img_cols, - const int c_kploc_step, - const int c_score_step) -{ - const int j = get_global_id(0) + 3; - const int i = get_global_id(1) + 3; - - if (i < c_img_rows - 3 && j < c_img_cols - 3) - { - int v; - uint C[4] = {0,0,0,0}; - - C[2] |= (uint)img[(i - 3) * c_img_step + j - 1] << 8; - C[2] |= (uint)img[(i - 3) * c_img_step + j]; - C[1] |= (uint)img[(i - 3) * c_img_step + j + 1] << (3 * 8); - - C[2] |= (uint)img[(i - 2) * c_img_step + j - 2] << (2 * 8); - C[1] |= (uint)img[(i - 2) * c_img_step + j + 2] << (2 * 8); - - C[2] |= (uint)img[(i - 1) * c_img_step + j - 3] << (3 * 8); - C[1] |= (uint)img[(i - 1) * c_img_step + j + 3] << 8; - - C[3] |= (uint)img[i * c_img_step + j - 3]; - v = (int) img[i * c_img_step + j]; - C[1] |= (uint)img[i * c_img_step + j + 3]; - - int d1 = diffType(v, C[1] & 0xff, threshold); - int d2 = diffType(v, C[3] & 0xff, threshold); - - if ((d1 | d2) == 0) - return; - - C[3] |= (uint)img[(i + 1) * c_img_step + j - 3] << 8; - C[0] |= (uint)img[(i + 1) * c_img_step + j + 3] << (3 * 8); - - C[3] |= (uint)img[(i + 2) * c_img_step + j - 2] << (2 * 8); - C[0] |= (uint)img[(i + 2) * c_img_step + j + 2] << (2 * 8); - - C[3] |= (uint)img[(i + 3) * c_img_step + j - 1] << (3 * 8); - C[0] |= (uint)img[(i + 3) * c_img_step + j]; - C[0] |= (uint)img[(i + 3) * c_img_step + j + 1] << 8; - - int mask1 = 0; - int mask2 = 0; - - calcMask(C, v, threshold, &mask1, &mask2); - - if (isKeyPoint(mask1, mask2)) - { - if (calcScore) score[i * c_score_step + j] = cornerScore(C, v, threshold); - - uint idx = atomic_inc(counter); - - if (idx < maxKeypoints) - { - kpLoc[X_ROW * c_kploc_step + idx] = j; - kpLoc[Y_ROW * c_kploc_step + idx] = i; - } - } - } -} - -/////////////////////////////////////////////////////////////////////////// -// nonmaxSupression - -__kernel -void nonmaxSupression( - __global const int* kpLoc, - __global const uint* score, - __global float* keypoints, - __global int* new_counter, - const int counter, - const int c_kploc_step, - const int c_score_step, - const int c_keypoints_step) -{ - const int i = get_global_id(0); - - if (i < counter) - { - int loc_x = kpLoc[X_ROW * c_kploc_step + i]; - int loc_y = kpLoc[Y_ROW * c_kploc_step + i]; - - int s = score[loc_y * c_score_step + loc_x]; - - bool ismax = - s > score[(loc_y - 1) * c_score_step + loc_x - 1] && - s > score[(loc_y - 1) * c_score_step + loc_x ] && - s > score[(loc_y - 1) * c_score_step + loc_x + 1] && - - s > score[loc_y * c_score_step + loc_x - 1] && - s > score[loc_y * c_score_step + loc_x + 1] && - - s > score[(loc_y + 1) * c_score_step + loc_x - 1] && - s > score[(loc_y + 1) * c_score_step + loc_x ] && - s > score[(loc_y + 1) * c_score_step + loc_x + 1]; - - if (ismax) - { - uint idx = atomic_inc(new_counter); - - keypoints[X_ROW * c_keypoints_step + idx] = (float)loc_x; - keypoints[Y_ROW * c_keypoints_step + idx] = (float)loc_y; - keypoints[RESPONSE_ROW * c_keypoints_step + idx] = (float)s; - } - } -} diff --git a/modules/ocl/src/opencl/filter_sep_col.cl b/modules/ocl/src/opencl/filter_sep_col.cl deleted file mode 100644 index 0d1998ce9..000000000 --- a/modules/ocl/src/opencl/filter_sep_col.cl +++ /dev/null @@ -1,118 +0,0 @@ -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.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. -// -// - -#define READ_TIMES_COL ((2*(RADIUSY+LSIZE1)-1)/LSIZE1) -#define RADIUS 1 -#if CN ==1 -#define ALIGN (((RADIUS)+3)>>2<<2) -#elif CN==2 -#define ALIGN (((RADIUS)+1)>>1<<1) -#elif CN==3 -#define ALIGN (((RADIUS)+3)>>2<<2) -#elif CN==4 -#define ALIGN (RADIUS) -#define READ_TIMES_ROW ((2*(RADIUS+LSIZE0)-1)/LSIZE0) -#endif - -/********************************************************************************** -These kernels are written for separable filters such as Sobel, Scharr, GaussianBlur. -Now(6/29/2011) the kernels only support 8U data type and the anchor of the convovle -kernel must be in the center. ROI is not supported either. -Each kernels read 4 elements(not 4 pixels), save them to LDS and read the data needed -from LDS to calculate the result. -The length of the convovle kernel supported is only related to the MAX size of LDS, -which is HW related. -Niko -6/29/2011 -The info above maybe obsolete. -***********************************************************************************/ - - -__kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void col_filter - (__global const GENTYPE_SRC * restrict src, - __global GENTYPE_DST * dst, - const int dst_cols, - const int dst_rows, - const int src_whole_cols, - const int src_whole_rows, - const int src_step_in_pixel, - //const int src_offset_x, - //const int src_offset_y, - const int dst_step_in_pixel, - const int dst_offset_in_pixel, - __constant float * mat_kernel __attribute__((max_constant_size(4*(2*RADIUSY+1))))) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - int l_x = get_local_id(0); - int l_y = get_local_id(1); - - int start_addr = mad24(y, src_step_in_pixel, x); - int end_addr = mad24(src_whole_rows - 1, src_step_in_pixel, src_whole_cols); - - int i; - GENTYPE_SRC sum, temp[READ_TIMES_COL]; - __local GENTYPE_SRC LDS_DAT[LSIZE1 * READ_TIMES_COL][LSIZE0 + 1]; - - //read pixels from src - for(i = 0;i>2<<2) -#elif CN==2 -#define ALIGN (((RADIUS)+1)>>1<<1) -#elif CN==3 -#define ALIGN (((RADIUS)+3)>>2<<2) -#elif CN==4 -#define ALIGN (RADIUS) -#endif - -#ifdef BORDER_CONSTANT -#define ELEM(i,l_edge,r_edge,elem1,elem2) (i)<(l_edge) | (i) >= (r_edge) ? (elem1) : (elem2) -#elif defined BORDER_REPLICATE -#define EXTRAPOLATE(x, maxV) \ - { \ - x = max(min(x, maxV - 1), 0); \ - } -#elif defined BORDER_WRAP -#define EXTRAPOLATE(x, maxV) \ - { \ - if (x < 0) \ - x -= ((x - maxV + 1) / maxV) * maxV; \ - if (x >= maxV) \ - x %= maxV; \ - } -#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT_101) -#define EXTRAPOLATE_(x, maxV, delta) \ - { \ - if (maxV == 1) \ - x = 0; \ - else \ - do \ - { \ - if ( x < 0 ) \ - x = -x - 1 + delta; \ - else \ - x = maxV - 1 - (x - maxV) - delta; \ - } \ - while (x >= maxV || x < 0); \ - } -#ifdef BORDER_REFLECT -#define EXTRAPOLATE(x, maxV) EXTRAPOLATE_(x, maxV, 0) -#else -#define EXTRAPOLATE(x, maxV) EXTRAPOLATE_(x, maxV, 1) -#endif -#else -#error No extrapolation method -#endif - -/********************************************************************************** -These kernels are written for separable filters such as Sobel, Scharr, GaussianBlur. -Now(6/29/2011) the kernels only support 8U data type and the anchor of the convovle -kernel must be in the center. ROI is not supported either. -For channels =1,2,4, each kernels read 4 elements(not 4 pixels), and for channels =3, -the kernel read 4 pixels, save them to LDS and read the data needed from LDS to -calculate the result. -The length of the convovle kernel supported is related to the LSIZE0 and the MAX size -of LDS, which is HW related. -For channels = 1,3 the RADIUS is no more than LSIZE0*2 -For channels = 2, the RADIUS is no more than LSIZE0 -For channels = 4, arbitary RADIUS is supported unless the LDS is not enough -Niko -6/29/2011 -The info above maybe obsolete. -***********************************************************************************/ - -__kernel __attribute__((reqd_work_group_size(LSIZE0,LSIZE1,1))) void row_filter_C1_D0 - (__global uchar * restrict src, - __global float * dst, - int dst_cols, int dst_rows, - int src_whole_cols, int src_whole_rows, - int src_step_in_pixel, - int src_offset_x, int src_offset_y, - int dst_step_in_pixel, int radiusy, - __constant float * mat_kernel __attribute__((max_constant_size(4*(2*RADIUSX+1))))) -{ - int x = get_global_id(0)<<2; - int y = get_global_id(1); - int l_x = get_local_id(0); - int l_y = get_local_id(1); - - int start_x = x+src_offset_x - RADIUSX & 0xfffffffc; - int offset = src_offset_x - RADIUSX & 3; - int start_y = y + src_offset_y - radiusy; - int start_addr = mad24(start_y, src_step_in_pixel, start_x); - int i; - float4 sum; - uchar4 temp[READ_TIMES_ROW]; - - __local uchar4 LDS_DAT[LSIZE1][READ_TIMES_ROW*LSIZE0+1]; -#ifdef BORDER_CONSTANT - int end_addr = mad24(src_whole_rows - 1, src_step_in_pixel, src_whole_cols); - - // read pixels from src - for (i = 0; i < READ_TIMES_ROW; i++) - { - int current_addr = start_addr+i*LSIZE0*4; - current_addr = ((current_addr < end_addr) && (current_addr > 0)) ? current_addr : 0; - temp[i] = *(__global uchar4*)&src[current_addr]; - } - - // judge if read out of boundary - for (i = 0; isrc_whole_cols)| (start_y<0) | (start_y >= src_whole_rows); - int4 index[READ_TIMES_ROW]; - int4 addr; - int s_y; - - if (not_all_in_range) - { - // judge if read out of boundary - for (i = 0; i < READ_TIMES_ROW; i++) - { - index[i] = (int4)(start_x+i*LSIZE0*4) + (int4)(0, 1, 2, 3); - EXTRAPOLATE(index[i].x, src_whole_cols); - EXTRAPOLATE(index[i].y, src_whole_cols); - EXTRAPOLATE(index[i].z, src_whole_cols); - EXTRAPOLATE(index[i].w, src_whole_cols); - } - s_y = start_y; - EXTRAPOLATE(s_y, src_whole_rows); - - // read pixels from src - for (i = 0; i 0)) ? current_addr : 0; - temp[i] = src[current_addr]; - } - - //judge if read out of boundary - for (i = 0; i 0)) ? current_addr : 0; - temp[i] = src[current_addr]; - } - - // judge if read out of boundary - for (i = 0; i 0)) ? current_addr : 0; - temp[i] = src[current_addr]; - } - - // judge if read out of boundary - for (i = 0; i= (r_edge) ? (elem1) : (elem2) -#elif defined BORDER_REPLICATE -#define EXTRAPOLATE(x, maxV) \ - { \ - x = max(min(x, maxV - 1), 0); \ - } -#elif defined BORDER_WRAP -#define EXTRAPOLATE(x, maxV) \ - { \ - if (x < 0) \ - x -= ((x - maxV + 1) / maxV) * maxV; \ - if (x >= maxV) \ - x %= maxV; \ - } -#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT_101) -#define EXTRAPOLATE_(x, maxV, delta) \ - { \ - if (maxV == 1) \ - x = 0; \ - else \ - do \ - { \ - if ( x < 0 ) \ - x = -x - 1 + delta; \ - else \ - x = maxV - 1 - (x - maxV) - delta; \ - } \ - while (x >= maxV || x < 0); \ - } -#ifdef BORDER_REFLECT -#define EXTRAPOLATE(x, maxV) EXTRAPOLATE_(x, maxV, 0) -#else -#define EXTRAPOLATE(x, maxV) EXTRAPOLATE_(x, maxV, 1) -#endif -#else -#error No extrapolation method -#endif - -__kernel void -adaptiveBilateralFilter_C4_D0( - __global const uchar4 * restrict src, - __global uchar4 *dst, - float alpha, - int src_offset, - int src_whole_rows, - int src_whole_cols, - int src_step, - int dst_offset, - int dst_rows, - int dst_cols, - int dst_step, - __global const float* lut, - int lut_step) -{ - int col = get_local_id(0); - const int gX = get_group_id(0); - const int gY = get_group_id(1); - - int src_x_off = (src_offset % src_step) >> 2; - int src_y_off = src_offset / src_step; - int dst_x_off = (dst_offset % dst_step) >> 2; - int dst_y_off = dst_offset / dst_step; - - int startX = gX * (THREADS-ksX+1) - anX + src_x_off; - int startY = (gY * (1+EXTRA)) - anY + src_y_off; - - int dst_startX = gX * (THREADS-ksX+1) + dst_x_off; - int dst_startY = (gY * (1+EXTRA)) + dst_y_off; - - int posX = dst_startX - dst_x_off + col; - int posY = (gY * (1+EXTRA)) ; - - __local uchar4 data[ksY+EXTRA][THREADS]; - - float4 tmp_sum[1+EXTRA]; - for(int tmpint = 0; tmpint < 1+EXTRA; tmpint++) - tmp_sum[tmpint] = (float4)(0,0,0,0); - -#ifdef BORDER_CONSTANT - bool con; - uchar4 ss; - for(int j = 0; j < ksY+EXTRA; j++) - { - con = (startX+col >= 0 && startX+col < src_whole_cols && startY+j >= 0 && startY+j < src_whole_rows); - int cur_col = clamp(startX + col, 0, src_whole_cols); - if (con) - ss = src[(startY+j)*(src_step>>2) + cur_col]; - - data[j][col] = con ? ss : (uchar4)0; - } -#else - for(int j= 0; j < ksY+EXTRA; j++) - { - int selected_row = startY+j, selected_col = startX+col; - EXTRAPOLATE(selected_row, src_whole_rows) - EXTRAPOLATE(selected_col, src_whole_cols) - - data[j][col] = src[selected_row * (src_step>>2) + selected_col]; - } -#endif - - barrier(CLK_LOCAL_MEM_FENCE); - - float4 var[1+EXTRA]; - -#if VAR_PER_CHANNEL - float4 weight; - float4 totalWeight = (float4)(0,0,0,0); -#else - float weight; - float totalWeight = 0; -#endif - - int4 currValCenter; - int4 currWRTCenter; - - int4 sumVal = 0; - int4 sumValSqr = 0; - - if(col < (THREADS-(ksX-1))) - { - int4 currVal; - int howManyAll = (2*anX+1)*(ksY); - - //find variance of all data - int startLMj; - int endLMj ; - // Top row: don't sum the very last element - for(int extraCnt = 0; extraCnt <=EXTRA; extraCnt++) - { -#if CALCVAR - startLMj = extraCnt; - endLMj = ksY+extraCnt-1; - sumVal = (int4)0; - sumValSqr= (int4)0; - for(int j = startLMj; j < endLMj; j++) - for(int i=-anX; i<=anX; i++) - { - currVal = convert_int4(data[j][col+anX+i]); - - sumVal += currVal; - sumValSqr += mul24(currVal, currVal); - } - - var[extraCnt] = clamp( convert_float4( ( (sumValSqr * howManyAll)- mul24(sumVal , sumVal) ) ) / ( (float)(howManyAll*howManyAll) ), (float4)(0.1f, 0.1f, 0.1f, 0.1f), (float4)(MAX_VAR_VAL, MAX_VAR_VAL, MAX_VAR_VAL, MAX_VAR_VAL)) ; - -#else - var[extraCnt] = (float4)(MAX_VAR_VAL, MAX_VAR_VAL, MAX_VAR_VAL, MAX_VAR_VAL); -#endif - } - - for(int extraCnt = 0; extraCnt <= EXTRA; extraCnt++) - { - - // top row: include the very first element, even on first time - startLMj = extraCnt; - // go all the way, unless this is the last local mem chunk, - // then stay within limits - 1 - endLMj = extraCnt + ksY; - - // Top row: don't sum the very last element - currValCenter = convert_int4( data[ (startLMj + endLMj)/2][col+anX] ); - - for(int j = startLMj, lut_j = 0; j < endLMj; j++, lut_j++) - { - for(int i=-anX; i<=anX; i++) - { -#if FIXED_WEIGHT -#if VAR_PER_CHANNEL - weight.x = 1.0f; - weight.y = 1.0f; - weight.z = 1.0f; - weight.w = 1.0f; -#else - weight = 1.0f; -#endif -#else // !FIXED_WEIGHT - currVal = convert_int4(data[j][col+anX+i]); - currWRTCenter = currVal-currValCenter; - -#if ABF_GAUSSIAN - -#if VAR_PER_CHANNEL - weight = exp( (float4)(-0.5f, -0.5f, -0.5f, -0.5f) * convert_float4(currWRTCenter * currWRTCenter) / var[extraCnt] )* - (float4)(lut[lut_j*lut_step+anX+i]); -#else - weight = exp( -0.5f * (mul24(currWRTCenter.x, currWRTCenter.x) + mul24(currWRTCenter.y, currWRTCenter.y) + - mul24(currWRTCenter.z, currWRTCenter.z) ) / (var[extraCnt].x+var[extraCnt].y+var[extraCnt].z) ) * lut[lut_j*lut_step+anX+i]; -#endif - -#else // !ABF_GAUSSIAN - -#if VAR_PER_CHANNEL - weight = var[extraCnt] / (var[extraCnt] + convert_float4(currWRTCenter * currWRTCenter)) * - (float4)(lut[lut_j*lut_step+anX+i]); -#else - weight = ((float)lut[lut_j*lut_step+anX+i]) /(1.0f+( mul24(currWRTCenter.x, currWRTCenter.x) + mul24(currWRTCenter.y, currWRTCenter.y) + - mul24(currWRTCenter.z, currWRTCenter.z))/(var[extraCnt].x+var[extraCnt].y+var[extraCnt].z)); -#endif - -#endif //ABF_GAUSSIAN - - - -#endif // FIXED_WEIGHT - - tmp_sum[extraCnt] += convert_float4(data[j][col+anX+i]) * weight; - totalWeight += weight; - } - } - - if(posX >= 0 && posX < dst_cols && (posY+extraCnt) >= 0 && (posY+extraCnt) < dst_rows) - dst[(dst_startY+extraCnt) * (dst_step>>2)+ dst_startX + col] = convert_uchar4_rtz( (tmp_sum[extraCnt] / (float4)totalWeight) + (float4)0.5f); - -#if VAR_PER_CHANNEL - totalWeight = (float4)(0,0,0,0); -#else - totalWeight = 0.0f; -#endif - } - } -} - - -__kernel void -adaptiveBilateralFilter_C1_D0( - __global const uchar * restrict src, - __global uchar *dst, - float alpha, - int src_offset, - int src_whole_rows, - int src_whole_cols, - int src_step, - int dst_offset, - int dst_rows, - int dst_cols, - int dst_step, - __global const float * lut, - int lut_step) -{ - int col = get_local_id(0); - const int gX = get_group_id(0); - const int gY = get_group_id(1); - - int src_x_off = (src_offset % src_step); - int src_y_off = src_offset / src_step; - int dst_x_off = (dst_offset % dst_step); - int dst_y_off = dst_offset / dst_step; - - int startX = gX * (THREADS-ksX+1) - anX + src_x_off; - int startY = (gY * (1+EXTRA)) - anY + src_y_off; - - int dst_startX = gX * (THREADS-ksX+1) + dst_x_off; - int dst_startY = (gY * (1+EXTRA)) + dst_y_off; - - int posX = dst_startX - dst_x_off + col; - int posY = (gY * (1+EXTRA)) ; - - __local uchar data[ksY+EXTRA][THREADS]; - - float tmp_sum[1+EXTRA]; - for(int tmpint = 0; tmpint < 1+EXTRA; tmpint++) - { - tmp_sum[tmpint] = (float)(0); - } - -#ifdef BORDER_CONSTANT - bool con; - uchar ss; - for(int j = 0; j < ksY+EXTRA; j++) - { - con = (startX+col >= 0 && startX+col < src_whole_cols && startY+j >= 0 && startY+j < src_whole_rows); - - int cur_col = clamp(startX + col, 0, src_whole_cols); - if(con) - { - ss = src[(startY+j)*(src_step) + cur_col]; - } - - data[j][col] = con ? ss : 0; - } -#else - for(int j= 0; j < ksY+EXTRA; j++) - { - int selected_row = startY+j, selected_col = startX+col; - EXTRAPOLATE(selected_row, src_whole_rows) - EXTRAPOLATE(selected_col, src_whole_cols) - - data[j][col] = src[selected_row * (src_step) + selected_col]; - } -#endif - - barrier(CLK_LOCAL_MEM_FENCE); - - float var[1+EXTRA]; - - float weight; - float totalWeight = 0; - - int currValCenter; - int currWRTCenter; - - int sumVal = 0; - int sumValSqr = 0; - - if(col < (THREADS-(ksX-1))) - { - int currVal; - - int howManyAll = (2*anX+1)*(ksY); - - //find variance of all data - int startLMj; - int endLMj; - - // Top row: don't sum the very last element - for(int extraCnt=0; extraCnt<=EXTRA; extraCnt++) - { -#if CALCVAR - startLMj = extraCnt; - endLMj = ksY+extraCnt-1; - sumVal = 0; - sumValSqr =0; - for(int j = startLMj; j < endLMj; j++) - { - for(int i=-anX; i<=anX; i++) - { - currVal = (uint)(data[j][col+anX+i]) ; - - sumVal += currVal; - sumValSqr += mul24(currVal, currVal); - } - } - var[extraCnt] = clamp((float)( ( (sumValSqr * howManyAll)- mul24(sumVal , sumVal) ) ) / ( (float)(howManyAll*howManyAll) ) , 0.1f, (float)(MAX_VAR_VAL) ); -#else - var[extraCnt] = (float)(MAX_VAR_VAL); -#endif - } - - for(int extraCnt = 0; extraCnt <= EXTRA; extraCnt++) - { - - // top row: include the very first element, even on first time - startLMj = extraCnt; - // go all the way, unless this is the last local mem chunk, - // then stay within limits - 1 - endLMj = extraCnt + ksY; - - // Top row: don't sum the very last element - currValCenter = (int)( data[ (startLMj + endLMj)/2][col+anX] ); - - for(int j = startLMj, lut_j = 0; j < endLMj; j++, lut_j++) - { - for(int i=-anX; i<=anX; i++) - { -#if FIXED_WEIGHT - weight = 1.0f; -#else - currVal = (int)(data[j][col+anX+i]) ; - currWRTCenter = currVal-currValCenter; - -#if ABF_GAUSSIAN - weight = exp( -0.5f * (float)mul24(currWRTCenter,currWRTCenter)/var[extraCnt]) * lut[lut_j*lut_step+anX+i] ; -#else - weight = var[extraCnt] / (var[extraCnt] + (float)mul24(currWRTCenter,currWRTCenter)) * lut[lut_j*lut_step+anX+i] ; -#endif -#endif - tmp_sum[extraCnt] += (float)(data[j][col+anX+i] * weight); - totalWeight += weight; - } - } - - if(posX >= 0 && posX < dst_cols && (posY+extraCnt) >= 0 && (posY+extraCnt) < dst_rows) - { - dst[(dst_startY+extraCnt) * (dst_step)+ dst_startX + col] = convert_uchar_rtz(tmp_sum[extraCnt]/totalWeight+0.5f); - } - - totalWeight = 0; - } - } -} diff --git a/modules/ocl/src/opencl/filtering_boxFilter.cl b/modules/ocl/src/opencl/filtering_boxFilter.cl deleted file mode 100644 index 96091ce6e..000000000 --- a/modules/ocl/src/opencl/filtering_boxFilter.cl +++ /dev/null @@ -1,376 +0,0 @@ -/*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-2013, Advanced Micro Devices, Inc., 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*/ - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////Macro for border type//////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////// -#ifdef BORDER_REPLICATE -//BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh -#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? (l_edge) : (i)) -#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? (r_edge)-1 : (addr)) -#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? (t_edge) :(i)) -#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? (b_edge)-1 :(addr)) -#endif - -#ifdef BORDER_REFLECT -//BORDER_REFLECT: fedcba|abcdefgh|hgfedcb -#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? -(i)-1 : (i)) -#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? -(i)-1+((r_edge)<<1) : (addr)) -#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? -(i)-1 : (i)) -#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? -(i)-1+((b_edge)<<1) : (addr)) -#endif - -#ifdef BORDER_REFLECT_101 -//BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba -#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? -(i) : (i)) -#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? -(i)-2+((r_edge)<<1) : (addr)) -#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? -(i) : (i)) -#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? -(i)-2+((b_edge)<<1) : (addr)) -#endif - -//blur function does not support BORDER_WRAP -#ifdef BORDER_WRAP -//BORDER_WRAP: cdefgh|abcdefgh|abcdefg -#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? (i)+(r_edge) : (i)) -#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? (i)-(r_edge) : (addr)) -#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? (i)+(b_edge) : (i)) -#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? (i)-(b_edge) : (addr)) -#endif - -#ifdef EXTRA_EXTRAPOLATION // border > src image size -#ifdef BORDER_CONSTANT -// None -#elif defined BORDER_REPLICATE -#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \ - { \ - x = max(min(x, maxX - 1), minX); \ - y = max(min(y, maxY - 1), minY); \ - } -#elif defined BORDER_WRAP -#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \ - { \ - if (x < minX) \ - x -= ((x - maxX + 1) / maxX) * maxX; \ - if (x >= maxX) \ - x %= maxX; \ - if (y < minY) \ - y -= ((y - maxY + 1) / maxY) * maxY; \ - if (y >= maxY) \ - y %= maxY; \ - } -#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT_101) -#define EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, delta) \ - { \ - if (maxX - minX == 1) \ - x = minX; \ - else \ - do \ - { \ - if (x < minX) \ - x = -(x - minX) - 1 + delta; \ - else \ - x = maxX - 1 - (x - maxX) - delta; \ - } \ - while (x >= maxX || x < minX); \ - \ - if (maxY - minY == 1) \ - y = minY; \ - else \ - do \ - { \ - if (y < minY) \ - y = -(y - minY) - 1 + delta; \ - else \ - y = maxY - 1 - (y - maxY) - delta; \ - } \ - while (y >= maxY || y < minY); \ - } -#ifdef BORDER_REFLECT -#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, 0) -#elif defined(BORDER_REFLECT_101) -#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, 1) -#endif -#else -#error No extrapolation method -#endif -#else -#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \ - { \ - int _row = y - minY, _col = x - minX; \ - _row = ADDR_H(_row, 0, maxY - minY); \ - _row = ADDR_B(_row, maxY - minY, _row); \ - y = _row + minY; \ - \ - _col = ADDR_L(_col, 0, maxX - minX); \ - _col = ADDR_R(_col, maxX - minX, _col); \ - x = _col + minX; \ - } -#endif - -#if USE_DOUBLE -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#define FPTYPE double -#define CONVERT_TO_FPTYPE CAT(convert_double, VEC_SIZE) -#else -#define FPTYPE float -#define CONVERT_TO_FPTYPE CAT(convert_float, VEC_SIZE) -#endif - -#if DATA_DEPTH == 0 -#define BASE_TYPE uchar -#elif DATA_DEPTH == 1 -#define BASE_TYPE char -#elif DATA_DEPTH == 2 -#define BASE_TYPE ushort -#elif DATA_DEPTH == 3 -#define BASE_TYPE short -#elif DATA_DEPTH == 4 -#define BASE_TYPE int -#elif DATA_DEPTH == 5 -#define BASE_TYPE float -#elif DATA_DEPTH == 6 -#define BASE_TYPE double -#else -#error data_depth -#endif - -#define __CAT(x, y) x##y -#define CAT(x, y) __CAT(x, y) - -#define uchar1 uchar -#define char1 char -#define ushort1 ushort -#define short1 short -#define int1 int -#define float1 float -#define double1 double - -#define convert_uchar1_sat_rte convert_uchar_sat_rte -#define convert_char1_sat_rte convert_char_sat_rte -#define convert_ushort1_sat_rte convert_ushort_sat_rte -#define convert_short1_sat_rte convert_short_sat_rte -#define convert_int1_sat_rte convert_int_sat_rte -#define convert_float1 -#define convert_double1 - -#if DATA_DEPTH == 5 || DATA_DEPTH == 6 -#define CONVERT_TO_TYPE CAT(CAT(convert_, BASE_TYPE), VEC_SIZE) -#else -#define CONVERT_TO_TYPE CAT(CAT(CAT(convert_, BASE_TYPE), VEC_SIZE), _sat_rte) -#endif - -#define VEC_SIZE DATA_CHAN - -#define VEC_TYPE CAT(BASE_TYPE, VEC_SIZE) -#define TYPE VEC_TYPE - -#define SCALAR_TYPE CAT(FPTYPE, VEC_SIZE) - -#define INTERMEDIATE_TYPE CAT(FPTYPE, VEC_SIZE) - -struct RectCoords -{ - int x1, y1, x2, y2; -}; - -//#define DEBUG -#ifdef DEBUG -#define DEBUG_ONLY(x) x -#define ASSERT(condition) do { if (!(condition)) { printf("BUG in boxFilter kernel (global=%d,%d): " #condition "\n", get_global_id(0), get_global_id(1)); } } while (0) -#else -#define DEBUG_ONLY(x) -#define ASSERT(condition) -#endif - - -inline INTERMEDIATE_TYPE readSrcPixel(int2 pos, __global TYPE *src, const unsigned int srcStepBytes, const struct RectCoords srcCoords -#ifdef BORDER_CONSTANT - , SCALAR_TYPE borderValue -#endif - ) -{ -#ifdef BORDER_ISOLATED - if(pos.x >= srcCoords.x1 && pos.y >= srcCoords.y1 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) -#else - if(pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) -#endif - { - __global TYPE* ptr = (__global TYPE*)((__global char*)src + pos.x * sizeof(TYPE) + pos.y * srcStepBytes); - return CONVERT_TO_FPTYPE(*ptr); - } - else - { -#ifdef BORDER_CONSTANT - return borderValue; -#else - int selected_col = pos.x; - int selected_row = pos.y; - - EXTRAPOLATE(selected_col, selected_row, -#ifdef BORDER_ISOLATED - srcCoords.x1, srcCoords.y1, -#else - 0, 0, -#endif - srcCoords.x2, srcCoords.y2 - ); - - // debug border mapping - //printf("pos=%d,%d --> %d, %d\n", pos.x, pos.y, selected_col, selected_row); - - pos = (int2)(selected_col, selected_row); - if(pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) - { - __global TYPE* ptr = (__global TYPE*)((__global char*)src + pos.x * sizeof(TYPE) + pos.y * srcStepBytes); - return CONVERT_TO_FPTYPE(*ptr); - } - else - { - // for debug only - DEBUG_ONLY(printf("BUG in boxFilter kernel\n")); - return (FPTYPE)(0.0f); - } -#endif - } -} - -// INPUT PARAMETER: BLOCK_SIZE_Y (via defines) - -__kernel -__attribute__((reqd_work_group_size(LOCAL_SIZE, 1, 1))) -void boxFilter(__global TYPE *src, const unsigned int srcStepBytes, const int4 srcRC, - __global TYPE *dst, const unsigned int dstStepBytes, const int4 dstRC, -#ifdef BORDER_CONSTANT - SCALAR_TYPE borderValue, -#endif - FPTYPE alpha - ) -{ - const struct RectCoords srcCoords = {srcRC.s0, srcRC.s1, srcRC.s2, srcRC.s3}; // for non-isolated border: offsetX, offsetY, wholeX, wholeY - const struct RectCoords dstCoords = {dstRC.s0, dstRC.s1, dstRC.s2, dstRC.s3}; - - const int x = get_local_id(0) + (LOCAL_SIZE - (KERNEL_SIZE_X - 1)) * get_group_id(0) - ANCHOR_X; - const int y = get_global_id(1) * BLOCK_SIZE_Y; - - const int local_id = get_local_id(0); - - INTERMEDIATE_TYPE data[KERNEL_SIZE_Y]; - __local INTERMEDIATE_TYPE sumOfCols[LOCAL_SIZE]; - - int2 srcPos = (int2)(srcCoords.x1 + x, srcCoords.y1 + y - ANCHOR_Y); - for(int sy = 0; sy < KERNEL_SIZE_Y; sy++, srcPos.y++) - { - data[sy] = readSrcPixel(srcPos, src, srcStepBytes, srcCoords -#ifdef BORDER_CONSTANT - , borderValue -#endif - ); - } - - INTERMEDIATE_TYPE tmp_sum = 0; - for(int sy = 0; sy < KERNEL_SIZE_Y; sy++) - { - tmp_sum += (data[sy]); - } - - sumOfCols[local_id] = tmp_sum; - barrier(CLK_LOCAL_MEM_FENCE); - - int2 pos = (int2)(dstCoords.x1 + x, dstCoords.y1 + y); - __global TYPE* dstPtr = (__global TYPE*)((__global char*)dst + pos.x * sizeof(TYPE) + pos.y * dstStepBytes); // Pointer can be out of bounds! - - int sy_index = 0; // current index in data[] array - int stepsY = min(dstCoords.y2 - pos.y, BLOCK_SIZE_Y); - ASSERT(stepsY > 0); - for (; ;) - { - ASSERT(pos.y < dstCoords.y2); - - if(local_id >= ANCHOR_X && local_id < LOCAL_SIZE - (KERNEL_SIZE_X - 1 - ANCHOR_X) && - pos.x >= dstCoords.x1 && pos.x < dstCoords.x2) - { - ASSERT(pos.y >= dstCoords.y1 && pos.y < dstCoords.y2); - - INTERMEDIATE_TYPE total_sum = 0; -#pragma unroll - for (int sx = 0; sx < KERNEL_SIZE_X; sx++) - { - total_sum += sumOfCols[local_id + sx - ANCHOR_X]; - } - *dstPtr = CONVERT_TO_TYPE(((INTERMEDIATE_TYPE)alpha) * total_sum); - } - -#if BLOCK_SIZE_Y == 1 - break; -#else - if (--stepsY == 0) - break; - - barrier(CLK_LOCAL_MEM_FENCE); - - tmp_sum = sumOfCols[local_id]; // TODO FIX IT: workaround for BUG in OpenCL compiler - // only works with scalars: ASSERT(fabs(tmp_sum - sumOfCols[local_id]) < (INTERMEDIATE_TYPE)1e-6); - tmp_sum -= data[sy_index]; - - data[sy_index] = readSrcPixel(srcPos, src, srcStepBytes, srcCoords -#ifdef BORDER_CONSTANT - , borderValue -#endif - ); - srcPos.y++; - - tmp_sum += data[sy_index]; - sumOfCols[local_id] = tmp_sum; - - sy_index = (sy_index + 1 < KERNEL_SIZE_Y) ? sy_index + 1 : 0; - - barrier(CLK_LOCAL_MEM_FENCE); - - // next line - DEBUG_ONLY(pos.y++); - dstPtr = (__global TYPE*)((__global char*)dstPtr + dstStepBytes); // Pointer can be out of bounds! -#endif // BLOCK_SIZE_Y == 1 - } -} diff --git a/modules/ocl/src/opencl/filtering_filter2D.cl b/modules/ocl/src/opencl/filtering_filter2D.cl deleted file mode 100644 index fb7dca509..000000000 --- a/modules/ocl/src/opencl/filtering_filter2D.cl +++ /dev/null @@ -1,374 +0,0 @@ -/*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-2013, Advanced Micro Devices, Inc., 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*/ - -#ifdef BORDER_REPLICATE -//BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh -#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? (l_edge) : (i)) -#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? (r_edge)-1 : (addr)) -#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? (t_edge) :(i)) -#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? (b_edge)-1 :(addr)) -#endif - -#ifdef BORDER_REFLECT -//BORDER_REFLECT: fedcba|abcdefgh|hgfedcb -#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? -(i)-1 : (i)) -#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? -(i)-1+((r_edge)<<1) : (addr)) -#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? -(i)-1 : (i)) -#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? -(i)-1+((b_edge)<<1) : (addr)) -#endif - -#ifdef BORDER_REFLECT_101 -//BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba -#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? -(i) : (i)) -#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? -(i)-2+((r_edge)<<1) : (addr)) -#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? -(i) : (i)) -#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? -(i)-2+((b_edge)<<1) : (addr)) -#endif - -//blur function does not support BORDER_WRAP -#ifdef BORDER_WRAP -//BORDER_WRAP: cdefgh|abcdefgh|abcdefg -#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? (i)+(r_edge) : (i)) -#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? (i)-(r_edge) : (addr)) -#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? (i)+(b_edge) : (i)) -#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? (i)-(b_edge) : (addr)) -#endif - -#ifdef EXTRA_EXTRAPOLATION // border > src image size -#ifdef BORDER_CONSTANT -// None -#elif defined BORDER_REPLICATE -#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \ - { \ - x = max(min(x, maxX - 1), minX); \ - y = max(min(y, maxY - 1), minY); \ - } -#elif defined BORDER_WRAP -#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \ - { \ - if (x < minX) \ - x -= ((x - maxX + 1) / maxX) * maxX; \ - if (x >= maxX) \ - x %= maxX; \ - if (y < minY) \ - y -= ((y - maxY + 1) / maxY) * maxY; \ - if (y >= maxY) \ - y %= maxY; \ - } -#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT_101) -#define EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, delta) \ - { \ - if (maxX - minX == 1) \ - x = minX; \ - else \ - do \ - { \ - if (x < minX) \ - x = -(x - minX) - 1 + delta; \ - else \ - x = maxX - 1 - (x - maxX) - delta; \ - } \ - while (x >= maxX || x < minX); \ - \ - if (maxY - minY == 1) \ - y = minY; \ - else \ - do \ - { \ - if (y < minY) \ - y = -(y - minY) - 1 + delta; \ - else \ - y = maxY - 1 - (y - maxY) - delta; \ - } \ - while (y >= maxY || y < minY); \ - } -#ifdef BORDER_REFLECT -#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, 0) -#elif defined(BORDER_REFLECT_101) -#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, 1) -#endif -#else -#error No extrapolation method -#endif -#else -#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \ - { \ - int _row = y - minY, _col = x - minX; \ - _row = ADDR_H(_row, 0, maxY - minY); \ - _row = ADDR_B(_row, maxY - minY, _row); \ - y = _row + minY; \ - \ - _col = ADDR_L(_col, 0, maxX - minX); \ - _col = ADDR_R(_col, maxX - minX, _col); \ - x = _col + minX; \ - } -#endif - -#if USE_DOUBLE -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#define FPTYPE double -#define CONVERT_TO_FPTYPE CAT(convert_double, VEC_SIZE) -#else -#define FPTYPE float -#define CONVERT_TO_FPTYPE CAT(convert_float, VEC_SIZE) -#endif - -#if DATA_DEPTH == 0 -#define BASE_TYPE uchar -#elif DATA_DEPTH == 1 -#define BASE_TYPE char -#elif DATA_DEPTH == 2 -#define BASE_TYPE ushort -#elif DATA_DEPTH == 3 -#define BASE_TYPE short -#elif DATA_DEPTH == 4 -#define BASE_TYPE int -#elif DATA_DEPTH == 5 -#define BASE_TYPE float -#elif DATA_DEPTH == 6 -#define BASE_TYPE double -#else -#error data_depth -#endif - -#define __CAT(x, y) x##y -#define CAT(x, y) __CAT(x, y) - -#define uchar1 uchar -#define char1 char -#define ushort1 ushort -#define short1 short -#define int1 int -#define float1 float -#define double1 double - -#define convert_uchar1_sat_rte convert_uchar_sat_rte -#define convert_char1_sat_rte convert_char_sat_rte -#define convert_ushort1_sat_rte convert_ushort_sat_rte -#define convert_short1_sat_rte convert_short_sat_rte -#define convert_int1_sat_rte convert_int_sat_rte -#define convert_float1 -#define convert_double1 - -#if DATA_DEPTH == 5 || DATA_DEPTH == 6 -#define CONVERT_TO_TYPE CAT(CAT(convert_, BASE_TYPE), VEC_SIZE) -#else -#define CONVERT_TO_TYPE CAT(CAT(CAT(convert_, BASE_TYPE), VEC_SIZE), _sat_rte) -#endif - -#define VEC_SIZE DATA_CHAN - -#define VEC_TYPE CAT(BASE_TYPE, VEC_SIZE) -#define TYPE VEC_TYPE - -#define SCALAR_TYPE CAT(FPTYPE, VEC_SIZE) - -#define INTERMEDIATE_TYPE CAT(FPTYPE, VEC_SIZE) - -struct RectCoords -{ - int x1, y1, x2, y2; -}; - -//#define DEBUG -#ifdef DEBUG -#define DEBUG_ONLY(x) x -#define ASSERT(condition) do { if (!(condition)) { printf("BUG in boxFilter kernel (global=%d,%d): " #condition "\n", get_global_id(0), get_global_id(1)); } } while (0) -#else -#define DEBUG_ONLY(x) (void)0 -#define ASSERT(condition) (void)0 -#endif - - -inline INTERMEDIATE_TYPE readSrcPixel(int2 pos, __global TYPE *src, const unsigned int srcStepBytes, const struct RectCoords srcCoords -#ifdef BORDER_CONSTANT - , SCALAR_TYPE borderValue -#endif - ) -{ -#ifdef BORDER_ISOLATED - if(pos.x >= srcCoords.x1 && pos.y >= srcCoords.y1 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) -#else - if(pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) -#endif - { - __global TYPE* ptr = (__global TYPE*)((__global char*)src + pos.x * sizeof(TYPE) + pos.y * srcStepBytes); - return CONVERT_TO_FPTYPE(*ptr); - } - else - { -#ifdef BORDER_CONSTANT - return borderValue; -#else - int selected_col = pos.x; - int selected_row = pos.y; - - EXTRAPOLATE(selected_col, selected_row, -#ifdef BORDER_ISOLATED - srcCoords.x1, srcCoords.y1, -#else - 0, 0, -#endif - srcCoords.x2, srcCoords.y2 - ); - - // debug border mapping - //printf("pos=%d,%d --> %d, %d\n", pos.x, pos.y, selected_col, selected_row); - - pos = (int2)(selected_col, selected_row); - if(pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) - { - __global TYPE* ptr = (__global TYPE*)((__global char*)src + pos.x * sizeof(TYPE) + pos.y * srcStepBytes); - return CONVERT_TO_FPTYPE(*ptr); - } - else - { - // for debug only - DEBUG_ONLY(printf("BUG in boxFilter kernel\n")); - return (FPTYPE)(0.0f); - } -#endif - } -} - -// INPUT PARAMETER: BLOCK_SIZE_Y (via defines) - -__kernel -__attribute__((reqd_work_group_size(LOCAL_SIZE, 1, 1))) -void filter2D(__global TYPE *src, const unsigned int srcStepBytes, const int4 srcRC, - __global TYPE *dst, const unsigned int dstStepBytes, const int4 dstRC, -#ifdef BORDER_CONSTANT - SCALAR_TYPE borderValue, -#endif - __constant FPTYPE* kernelData // transposed: [KERNEL_SIZE_X][KERNEL_SIZE_Y2_ALIGNED] - ) -{ - const struct RectCoords srcCoords = {srcRC.s0, srcRC.s1, srcRC.s2, srcRC.s3}; // for non-isolated border: offsetX, offsetY, wholeX, wholeY - struct RectCoords dstCoords = {dstRC.s0, dstRC.s1, dstRC.s2, dstRC.s3}; - - const int local_id = get_local_id(0); - const int x = local_id + (LOCAL_SIZE - (KERNEL_SIZE_X - 1)) * get_group_id(0) - ANCHOR_X; - const int y = get_global_id(1) * BLOCK_SIZE_Y; - - INTERMEDIATE_TYPE data[KERNEL_SIZE_Y]; - __local INTERMEDIATE_TYPE sumOfCols[LOCAL_SIZE]; - - int2 srcPos = (int2)(srcCoords.x1 + x, srcCoords.y1 + y - ANCHOR_Y); - - int2 pos = (int2)(dstCoords.x1 + x, dstCoords.y1 + y); - __global TYPE* dstPtr = (__global TYPE*)((__global char*)dst + pos.x * sizeof(TYPE) + pos.y * dstStepBytes); // Pointer can be out of bounds! - bool writeResult = (local_id >= ANCHOR_X && local_id < LOCAL_SIZE - (KERNEL_SIZE_X - 1 - ANCHOR_X) && - pos.x >= dstCoords.x1 && pos.x < dstCoords.x2); - -#if BLOCK_SIZE_Y > 1 - bool readAllpixels = true; - int sy_index = 0; // current index in data[] array - - dstCoords.y2 = min(dstCoords.y2, pos.y + BLOCK_SIZE_Y); - for (; - pos.y < dstCoords.y2; - pos.y++, - dstPtr = (__global TYPE*)((__global char*)dstPtr + dstStepBytes)) -#endif - { - ASSERT(pos.y < dstCoords.y2); - - for ( -#if BLOCK_SIZE_Y > 1 - int sy = readAllpixels ? 0 : -1; sy < (readAllpixels ? KERNEL_SIZE_Y : 0); -#else - int sy = 0, sy_index = 0; sy < KERNEL_SIZE_Y; -#endif - sy++, srcPos.y++) - { - data[sy + sy_index] = readSrcPixel(srcPos, src, srcStepBytes, srcCoords -#ifdef BORDER_CONSTANT - , borderValue -#endif - ); - } - - INTERMEDIATE_TYPE total_sum = 0; - for (int sx = 0; sx < KERNEL_SIZE_X; sx++) - { - { - __constant FPTYPE* k = &kernelData[KERNEL_SIZE_Y2_ALIGNED * sx -#if BLOCK_SIZE_Y > 1 - + KERNEL_SIZE_Y - sy_index -#endif - ]; - INTERMEDIATE_TYPE tmp_sum = 0; - for (int sy = 0; sy < KERNEL_SIZE_Y; sy++) - { - tmp_sum += data[sy] * k[sy]; - } - - sumOfCols[local_id] = tmp_sum; - barrier(CLK_LOCAL_MEM_FENCE); - } - - int id = local_id + sx - ANCHOR_X; - if (id >= 0 && id < LOCAL_SIZE) - total_sum += sumOfCols[id]; - - barrier(CLK_LOCAL_MEM_FENCE); - } - - if (writeResult) - { - ASSERT(pos.y >= dstCoords.y1 && pos.y < dstCoords.y2); - *dstPtr = CONVERT_TO_TYPE(total_sum); - } - -#if BLOCK_SIZE_Y > 1 - readAllpixels = false; -#if BLOCK_SIZE_Y > KERNEL_SIZE_Y - sy_index = (sy_index + 1 <= KERNEL_SIZE_Y) ? sy_index + 1 : 1; -#else - sy_index++; -#endif -#endif // BLOCK_SIZE_Y == 1 - } -} diff --git a/modules/ocl/src/opencl/filtering_morph.cl b/modules/ocl/src/opencl/filtering_morph.cl deleted file mode 100644 index c402ff721..000000000 --- a/modules/ocl/src/opencl/filtering_morph.cl +++ /dev/null @@ -1,228 +0,0 @@ -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Zero Lin, zero.lin@amd.com -// Yao Wang, bitwangyaoyao@gmail.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. -// -// - - -#ifdef ERODE -#define MORPH_OP(A,B) min((A),(B)) -#endif -#ifdef DILATE -#define MORPH_OP(A,B) max((A),(B)) -#endif -//BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii -#define ELEM(i,l_edge,r_edge,elem1,elem2) (i)<(l_edge) | (i) >= (r_edge) ? (elem1) : (elem2) -#ifndef GENTYPE - -__kernel void morph_C1_D0(__global const uchar * restrict src, - __global uchar *dst, - int src_offset_x, int src_offset_y, - int cols, int rows, - int src_step_in_pixel, int dst_step_in_pixel, - __constant uchar * mat_kernel, - int src_whole_cols, int src_whole_rows, - int dst_offset_in_pixel) -{ - int l_x = get_local_id(0); - int l_y = get_local_id(1); - int x = get_group_id(0)*4*LSIZE0; - int y = get_group_id(1)*LSIZE1; - int start_x = x+src_offset_x-RADIUSX & 0xfffffffc; - int end_x = x + src_offset_x+LSIZE0*4+RADIUSX & 0xfffffffc; - int width = (end_x -start_x+4)>>2; - int offset = src_offset_x-RADIUSX & 3; - int start_y = y+src_offset_y-RADIUSY; - int point1 = mad24(l_y,LSIZE0,l_x); - int point2 = point1 + LSIZE0*LSIZE1; - int tl_x = (point1 % width)<<2; - int tl_y = point1 / width; - int tl_x2 = (point2 % width)<<2; - int tl_y2 = point2 / width; - int cur_x = start_x + tl_x; - int cur_y = start_y + tl_y; - int cur_x2 = start_x + tl_x2; - int cur_y2 = start_y + tl_y2; - int start_addr = mad24(cur_y,src_step_in_pixel,cur_x); - int start_addr2 = mad24(cur_y2,src_step_in_pixel,cur_x2); - uchar4 temp0,temp1; - __local uchar4 LDS_DAT[2*LSIZE1*LSIZE0]; - - int end_addr = mad24(src_whole_rows - 1,src_step_in_pixel,src_whole_cols); - //read pixels from src - start_addr = ((start_addr < end_addr) && (start_addr > 0)) ? start_addr : 0; - start_addr2 = ((start_addr2 < end_addr) && (start_addr2 > 0)) ? start_addr2 : 0; - temp0 = *(__global uchar4*)&src[start_addr]; - temp1 = *(__global uchar4*)&src[start_addr2]; - //judge if read out of boundary - temp0.x= ELEM(cur_x,0,src_whole_cols,VAL,temp0.x); - temp0.y= ELEM(cur_x+1,0,src_whole_cols,VAL,temp0.y); - temp0.z= ELEM(cur_x+2,0,src_whole_cols,VAL,temp0.z); - temp0.w= ELEM(cur_x+3,0,src_whole_cols,VAL,temp0.w); - temp0= ELEM(cur_y,0,src_whole_rows,(uchar4)VAL,temp0); - - temp1.x= ELEM(cur_x2,0,src_whole_cols,VAL,temp1.x); - temp1.y= ELEM(cur_x2+1,0,src_whole_cols,VAL,temp1.y); - temp1.z= ELEM(cur_x2+2,0,src_whole_cols,VAL,temp1.z); - temp1.w= ELEM(cur_x2+3,0,src_whole_cols,VAL,temp1.w); - temp1= ELEM(cur_y2,0,src_whole_rows,(uchar4)VAL,temp1); - - LDS_DAT[point1] = temp0; - LDS_DAT[point2] = temp1; - barrier(CLK_LOCAL_MEM_FENCE); - uchar4 res = (uchar4)VAL; - - for(int i=0; i<2*RADIUSY+1; i++) - for(int j=0; j<2*RADIUSX+1; j++) - { - res = -#ifndef RECTKERNEL - mat_kernel[i*(2*RADIUSX+1)+j] ? -#endif - MORPH_OP(res,vload4(0,(__local uchar*)&LDS_DAT[mad24((l_y+i),width,l_x)]+offset+j)) -#ifndef RECTKERNEL - :res -#endif - ; - } - - int gidx = get_global_id(0)<<2; - int gidy = get_global_id(1); - int out_addr = mad24(gidy,dst_step_in_pixel,gidx+dst_offset_in_pixel); - - if(gidx+3 0)) ? start_addr : 0; - start_addr2 = ((start_addr2 < end_addr) && (start_addr2 > 0)) ? start_addr2 : 0; - temp0 = src[start_addr]; - temp1 = src[start_addr2]; - //judge if read out of boundary - temp0= ELEM(cur_x,0,src_whole_cols,(GENTYPE)VAL,temp0); - temp0= ELEM(cur_y,0,src_whole_rows,(GENTYPE)VAL,temp0); - - temp1= ELEM(cur_x2,0,src_whole_cols,(GENTYPE)VAL,temp1); - temp1= ELEM(cur_y2,0,src_whole_rows,(GENTYPE)VAL,temp1); - - LDS_DAT[point1] = temp0; - LDS_DAT[point2] = temp1; - barrier(CLK_LOCAL_MEM_FENCE); - GENTYPE res = (GENTYPE)VAL; - for(int i=0; i<2*RADIUSY+1; i++) - for(int j=0; j<2*RADIUSX+1; j++) - { - res = -#ifndef RECTKERNEL - mat_kernel[i*(2*RADIUSX+1)+j] ? -#endif - MORPH_OP(res,LDS_DAT[mad24(l_y+i,width,l_x+j)]) -#ifndef RECTKERNEL - :res -#endif - ; - } - int gidx = get_global_id(0); - int gidy = get_global_id(1); - int out_addr = mad24(gidy,dst_step_in_pixel,gidx+dst_offset_in_pixel); - if(gidx= (r_edge) | (_y)<0 | (_y) >= (t_edge) ? (const_v) : SRC((_x),(_y)) -#else -#define ELEM(_x,_y,r_edge,t_edge,const_v) SRC((_x),(_y)) -#endif - -#define DST(_x,_y) (((global DSTTYPE*)(Dst+DstOffset+(_y)*DstPitch))[_x]) - -//horizontal and vertical filter kernels -//should be defined on host during compile time to avoid overhead -__constant uint mat_kernelX[] = {KERNEL_MATRIX_X}; -__constant uint mat_kernelY[] = {KERNEL_MATRIX_Y}; - -__kernel __attribute__((reqd_work_group_size(BLK_X,BLK_Y,1))) void sep_filter_singlepass - ( - __global uchar* Src, - const uint SrcPitch, - const int srcOffsetX, - const int srcOffsetY, - __global uchar* Dst, - const int DstOffset, - const uint DstPitch, - int width, - int height, - int dstWidth, - int dstHeight - ) -{ - //RADIUSX, RADIUSY are filter dimensions - //BLK_X, BLK_Y are local wrogroup sizes - //all these should be defined on host during compile time - //first lsmem array for source pixels used in first pass, - //second lsmemDy for storing first pass results - __local WORKTYPE lsmem[BLK_Y+2*RADIUSY][BLK_X+2*RADIUSX]; - __local WORKTYPE lsmemDy[BLK_Y][BLK_X+2*RADIUSX]; - - //get local and global ids - used as image and local memory array indexes - int lix = get_local_id(0); - int liy = get_local_id(1); - - int x = (int)get_global_id(0); - int y = (int)get_global_id(1); - - //calculate pixel position in source image taking image offset into account - int srcX = x + srcOffsetX - RADIUSX; - int srcY = y + srcOffsetY - RADIUSY; - int xb = srcX; - int yb = srcY; - - //extrapolate coordinates, if needed - //and read my own source pixel into local memory - //with account for extra border pixels, which will be read by starting workitems - int clocY = liy; - int cSrcY = srcY; - do - { - int yb = cSrcY; - EXTRAPOLATE(yb, (height)); - - int clocX = lix; - int cSrcX = srcX; - do - { - int xb = cSrcX; - EXTRAPOLATE(xb,(width)); - lsmem[clocY][clocX] = ELEM(xb, yb, (width), (height), 0 ); - - clocX += BLK_X; - cSrcX += BLK_X; - } - while(clocX < BLK_X+(RADIUSX*2)); - - clocY += BLK_Y; - cSrcY += BLK_Y; - } - while(clocY < BLK_Y+(RADIUSY*2)); - barrier(CLK_LOCAL_MEM_FENCE); - - //do vertical filter pass - //and store intermediate results to second local memory array - int i; - WORKTYPE sum = 0.0f; - int clocX = lix; - do - { - sum = 0.0f; - for(i=0; i<=2*RADIUSY; i++) - sum = mad(lsmem[liy+i][clocX], as_float(mat_kernelY[i]), sum); - lsmemDy[liy][clocX] = sum; - clocX += BLK_X; - } - while(clocX < BLK_X+(RADIUSX*2)); - barrier(CLK_LOCAL_MEM_FENCE); - - //if this pixel happened to be out of image borders because of global size rounding, - //then just return - if( x >= dstWidth || y >=dstHeight ) return; - - //do second horizontal filter pass - //and calculate final result - sum = 0.0f; - for(i=0; i<=2*RADIUSX; i++) - sum = mad(lsmemDy[liy][lix+i], as_float(mat_kernelX[i]), sum); - - //store result into destination image - DST(x,y) = CONVERT_DSTTYPE(sum); -} diff --git a/modules/ocl/src/opencl/haarobjectdetect.cl b/modules/ocl/src/opencl/haarobjectdetect.cl deleted file mode 100644 index d6e5fb9ba..000000000 --- a/modules/ocl/src/opencl/haarobjectdetect.cl +++ /dev/null @@ -1,596 +0,0 @@ -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Wang Weiyan, wangweiyanster@gmail.com -// Jia Haipeng, jiahaipeng95@gmail.com -// Nathan, liujun@multicorewareinc.com -// Peng Xiao, pengxiao@outlook.com -// Erping Pang, erping@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. -// -// - -#define CV_HAAR_FEATURE_MAX 3 - -#define calc_sum(rect,offset) (sum[(rect).p0+offset] - sum[(rect).p1+offset] - sum[(rect).p2+offset] + sum[(rect).p3+offset]) -#define calc_sum1(rect,offset,i) (sum[(rect).p0[i]+offset] - sum[(rect).p1[i]+offset] - sum[(rect).p2[i]+offset] + sum[(rect).p3[i]+offset]) - -typedef int sumtype; -typedef float sqsumtype; - -#ifndef STUMP_BASED -#define STUMP_BASED 1 -#endif - -typedef struct __attribute__((aligned (128) )) GpuHidHaarTreeNode -{ - int p[CV_HAAR_FEATURE_MAX][4] __attribute__((aligned (64))); - float weight[CV_HAAR_FEATURE_MAX]; - float threshold; - float alpha[3] __attribute__((aligned (16))); - int left __attribute__((aligned (4))); - int right __attribute__((aligned (4))); -} -GpuHidHaarTreeNode; - - -//typedef struct __attribute__((aligned (32))) GpuHidHaarClassifier -//{ -// int count __attribute__((aligned (4))); -// GpuHidHaarTreeNode* node __attribute__((aligned (8))); -// float* alpha __attribute__((aligned (8))); -//} -//GpuHidHaarClassifier; - - -typedef struct __attribute__((aligned (64))) GpuHidHaarStageClassifier -{ - int count __attribute__((aligned (4))); - float threshold __attribute__((aligned (4))); - int two_rects __attribute__((aligned (4))); - int reserved0 __attribute__((aligned (8))); - int reserved1 __attribute__((aligned (8))); - int reserved2 __attribute__((aligned (8))); - int reserved3 __attribute__((aligned (8))); -} -GpuHidHaarStageClassifier; - - -//typedef struct __attribute__((aligned (64))) GpuHidHaarClassifierCascade -//{ -// int count __attribute__((aligned (4))); -// int is_stump_based __attribute__((aligned (4))); -// int has_tilted_features __attribute__((aligned (4))); -// int is_tree __attribute__((aligned (4))); -// int pq0 __attribute__((aligned (4))); -// int pq1 __attribute__((aligned (4))); -// int pq2 __attribute__((aligned (4))); -// int pq3 __attribute__((aligned (4))); -// int p0 __attribute__((aligned (4))); -// int p1 __attribute__((aligned (4))); -// int p2 __attribute__((aligned (4))); -// int p3 __attribute__((aligned (4))); -// float inv_window_area __attribute__((aligned (4))); -//} GpuHidHaarClassifierCascade; - - -#ifdef PACKED_CLASSIFIER -// this code is scalar, one pixel -> one workitem -__kernel void gpuRunHaarClassifierCascadePacked( - global const GpuHidHaarStageClassifier * stagecascadeptr, - global const int4 * info, - global const GpuHidHaarTreeNode * nodeptr, - global const int * restrict sum, - global const float * restrict sqsum, - volatile global int4 * candidate, - const int pixelstep, - const int loopcount, - const int start_stage, - const int split_stage, - const int end_stage, - const int startnode, - const int splitnode, - const int4 p, - const int4 pq, - const float correction, - global const int* pNodesPK, - global const int4* pWGInfo - ) - -{ - int gid = (int)get_group_id(0); - int lid_x = (int)get_local_id(0); - int lid_y = (int)get_local_id(1); - int lid = lid_y*LSx+lid_x; - int4 WGInfo = pWGInfo[WGSTART+gid]; - int GroupX = (WGInfo.y >> 16)&0xFFFF; - int GroupY = (WGInfo.y >> 0 )& 0xFFFF; - int Width = (WGInfo.x >> 16)&0xFFFF; - int Height = (WGInfo.x >> 0 )& 0xFFFF; - int ImgOffset = WGInfo.z; - float ScaleFactor = as_float(WGInfo.w); - -#define DATA_SIZE_X (PIXEL_STEP*LSx+WND_SIZE_X) -#define DATA_SIZE_Y (PIXEL_STEP*LSy+WND_SIZE_Y) -#define DATA_SIZE (DATA_SIZE_X*DATA_SIZE_Y) - - local int SumL[DATA_SIZE]; - - // read input data window into local mem - for(int i = 0; i=0.f) ? sqrt(variance_norm_factor) : 1.f; - }// end calc variance_norm_factor for all stages - - int result = (1.0f>0.0f); - for(int stageloop = start_stage; (stageloop < end_stage) && result; stageloop++ ) - {// iterate until candidate is valid - float stage_sum = 0.0f; - __global GpuHidHaarStageClassifier* stageinfo = (__global GpuHidHaarStageClassifier*) - ((__global uchar*)stagecascadeptr+stageloop*sizeof(GpuHidHaarStageClassifier)); - int lcl_off = (yl*DATA_SIZE_X)+(xl); - int stagecount = stageinfo->count; - float stagethreshold = stageinfo->threshold; - for(int nodeloop = 0; nodeloop < stagecount; nodecounter++,nodeloop++ ) - { - // simple macro to extract shorts from int -#define M0(_t) ((_t)&0xFFFF) -#define M1(_t) (((_t)>>16)&0xFFFF) - // load packed node data from global memory (L3) into registers - global const int4* pN = (__global int4*)(pNodesPK+nodecounter*NODE_SIZE); - int4 n0 = pN[0]; - int4 n1 = pN[1]; - int4 n2 = pN[2]; - float nodethreshold = as_float(n2.y) * variance_norm_factor; - // calc sum of intensity pixels according to classifier node information - float classsum = - (SumL[M0(n0.x)+lcl_off] - SumL[M1(n0.x)+lcl_off] - SumL[M0(n0.y)+lcl_off] + SumL[M1(n0.y)+lcl_off]) * as_float(n1.z) + - (SumL[M0(n0.z)+lcl_off] - SumL[M1(n0.z)+lcl_off] - SumL[M0(n0.w)+lcl_off] + SumL[M1(n0.w)+lcl_off]) * as_float(n1.w) + - (SumL[M0(n1.x)+lcl_off] - SumL[M1(n1.x)+lcl_off] - SumL[M0(n1.y)+lcl_off] + SumL[M1(n1.y)+lcl_off]) * as_float(n2.x); - //accumulate stage responce - stage_sum += (classsum >= nodethreshold) ? as_float(n2.w) : as_float(n2.z); - } - result = (stage_sum >= stagethreshold); - }// next stage if needed - - if(result) - {// all stages will be passed and there is a detected face on the tested position - int index = 1+atomic_inc((volatile global int*)candidate); //get index to write global data with face info - if(index>2)<<2; - int readheight = grpszy-1+WINDOWSIZE; - int read_horiz_cnt = readwidth >> 2;//each read int4 - int total_read = mul24(read_horiz_cnt,readheight); - int read_loop = (total_read + lcl_sz - 1) >> 6; - candidate[outputoff+(lcl_id<<2)] = (int4)0; - candidate[outputoff+(lcl_id<<2)+1] = (int4)0; - candidate[outputoff+(lcl_id<<2)+2] = (int4)0; - candidate[outputoff+(lcl_id<<2)+3] = (int4)0; - for(int scalei = 0; scalei > 16; - int totalgrp = scaleinfo1.y & 0xffff; - int imgoff = scaleinfo1.z; - float factor = as_float(scaleinfo1.w); - - __global const int * sum = sum1 + imgoff; - __global const float * sqsum = sqsum1 + imgoff; - for(int grploop=grpidx; grploop=0.f ? sqrt(variance_norm_factor) : 1.f; - - for(int stageloop = start_stage; (stageloop < split_stage) && result; stageloop++ ) - { - float stage_sum = 0.f; - __global GpuHidHaarStageClassifier* stageinfo = (__global GpuHidHaarStageClassifier*) - ((__global uchar*)stagecascadeptr+stageloop*sizeof(GpuHidHaarStageClassifier)); - int stagecount = stageinfo->count; - float stagethreshold = stageinfo->threshold; - for(int nodeloop = 0; nodeloop < stagecount; ) - { - __global GpuHidHaarTreeNode* currentnodeptr = (__global GpuHidHaarTreeNode*) - (((__global uchar*)nodeptr) + nodecounter * sizeof(GpuHidHaarTreeNode)); - - int4 info1 = *(__global int4*)(&(currentnodeptr->p[0][0])); - int4 info2 = *(__global int4*)(&(currentnodeptr->p[1][0])); - int4 info3 = *(__global int4*)(&(currentnodeptr->p[2][0])); - float4 w = *(__global float4*)(&(currentnodeptr->weight[0])); - float3 alpha3 = *(__global float3*)(&(currentnodeptr->alpha[0])); - - float nodethreshold = w.w * variance_norm_factor; - - info1.x +=lcl_off; - info1.z +=lcl_off; - info2.x +=lcl_off; - info2.z +=lcl_off; - - float classsum = (lcldata[mad24(info1.y,readwidth,info1.x)] - lcldata[mad24(info1.y,readwidth,info1.z)] - - lcldata[mad24(info1.w,readwidth,info1.x)] + lcldata[mad24(info1.w,readwidth,info1.z)]) * w.x; - - classsum += (lcldata[mad24(info2.y,readwidth,info2.x)] - lcldata[mad24(info2.y,readwidth,info2.z)] - - lcldata[mad24(info2.w,readwidth,info2.x)] + lcldata[mad24(info2.w,readwidth,info2.z)]) * w.y; - - info3.x +=lcl_off; - info3.z +=lcl_off; - classsum += (lcldata[mad24(info3.y,readwidth,info3.x)] - lcldata[mad24(info3.y,readwidth,info3.z)] - - lcldata[mad24(info3.w,readwidth,info3.x)] + lcldata[mad24(info3.w,readwidth,info3.z)]) * w.z; - - bool passThres = classsum >= nodethreshold; -#if STUMP_BASED - stage_sum += passThres ? alpha3.y : alpha3.x; - nodecounter++; - nodeloop++; -#else - bool isRootNode = (nodecounter & 1) == 0; - if(isRootNode) - { - if( (passThres && currentnodeptr->right) || - (!passThres && currentnodeptr->left)) - { - nodecounter ++; - } - else - { - stage_sum += alpha3.x; - nodecounter += 2; - nodeloop ++; - } - } - else - { - stage_sum += passThres ? alpha3.z : alpha3.y; - nodecounter ++; - nodeloop ++; - } -#endif - } - - result = (stage_sum >= stagethreshold) ? 1 : 0; - } - if(factor < 2) - { - if(result && lclidx %2 ==0 && lclidy %2 ==0 ) - { - int queueindex = atomic_inc(lclcount); - lcloutindex[queueindex<<1] = (lclidy << 16) | lclidx; - lcloutindex[(queueindex<<1)+1] = as_int((float)variance_norm_factor); - } - } - else - { - if(result) - { - int queueindex = atomic_inc(lclcount); - lcloutindex[queueindex<<1] = (lclidy << 16) | lclidx; - lcloutindex[(queueindex<<1)+1] = as_int((float)variance_norm_factor); - } - } - barrier(CLK_LOCAL_MEM_FENCE); - int queuecount = lclcount[0]; - barrier(CLK_LOCAL_MEM_FENCE); - nodecounter = splitnode; - for(int stageloop = split_stage; stageloop< end_stage && queuecount>0; stageloop++) - { - lclcount[0]=0; - barrier(CLK_LOCAL_MEM_FENCE); - - //int2 stageinfo = *(global int2*)(stagecascadeptr+stageloop); - __global GpuHidHaarStageClassifier* stageinfo = (__global GpuHidHaarStageClassifier*) - ((__global uchar*)stagecascadeptr+stageloop*sizeof(GpuHidHaarStageClassifier)); - int stagecount = stageinfo->count; - float stagethreshold = stageinfo->threshold; - - int perfscale = queuecount > 4 ? 3 : 2; - int queuecount_loop = (queuecount + (1<> perfscale; - int lcl_compute_win = lcl_sz >> perfscale; - int lcl_compute_win_id = (lcl_id >>(6-perfscale)); - int lcl_loops = (stagecount + lcl_compute_win -1) >> (6-perfscale); - int lcl_compute_id = lcl_id - (lcl_compute_win_id << (6-perfscale)); - for(int queueloop=0; queueloop>16),readwidth,temp_coord & 0xffff); - - if(lcl_compute_win_id < queuecount) - { - int tempnodecounter = lcl_compute_id; - float part_sum = 0.f; - const int stump_factor = STUMP_BASED ? 1 : 2; - int root_offset = 0; - for(int lcl_loop=0; lcl_loopp[0][0])); - int4 info2 = *(__global int4*)(&(currentnodeptr->p[1][0])); - int4 info3 = *(__global int4*)(&(currentnodeptr->p[2][0])); - float4 w = *(__global float4*)(&(currentnodeptr->weight[0])); - float3 alpha3 = *(__global float3*)(&(currentnodeptr->alpha[0])); - float nodethreshold = w.w * variance_norm_factor; - - info1.x +=queue_pixel; - info1.z +=queue_pixel; - info2.x +=queue_pixel; - info2.z +=queue_pixel; - - float classsum = (lcldata[mad24(info1.y,readwidth,info1.x)] - lcldata[mad24(info1.y,readwidth,info1.z)] - - lcldata[mad24(info1.w,readwidth,info1.x)] + lcldata[mad24(info1.w,readwidth,info1.z)]) * w.x; - - - classsum += (lcldata[mad24(info2.y,readwidth,info2.x)] - lcldata[mad24(info2.y,readwidth,info2.z)] - - lcldata[mad24(info2.w,readwidth,info2.x)] + lcldata[mad24(info2.w,readwidth,info2.z)]) * w.y; - - info3.x +=queue_pixel; - info3.z +=queue_pixel; - classsum += (lcldata[mad24(info3.y,readwidth,info3.x)] - lcldata[mad24(info3.y,readwidth,info3.z)] - - lcldata[mad24(info3.w,readwidth,info3.x)] + lcldata[mad24(info3.w,readwidth,info3.z)]) * w.z; - - bool passThres = classsum >= nodethreshold; -#if STUMP_BASED - part_sum += passThres ? alpha3.y : alpha3.x; - tempnodecounter += lcl_compute_win; - lcl_loop++; -#else - if(root_offset == 0) - { - if( (passThres && currentnodeptr->right) || - (!passThres && currentnodeptr->left)) - { - root_offset = 1; - } - else - { - part_sum += alpha3.x; - tempnodecounter += lcl_compute_win; - lcl_loop++; - } - } - else - { - part_sum += passThres ? alpha3.z : alpha3.y; - tempnodecounter += lcl_compute_win; - lcl_loop++; - root_offset = 0; - } -#endif - }//end for(int lcl_loop=0;lcl_loop= stagethreshold && (lcl_compute_id==0)) - { - int queueindex = atomic_inc(lclcount); - lcloutindex[queueindex<<1] = temp_coord; - lcloutindex[(queueindex<<1)+1] = as_int(variance_norm_factor); - } - lcl_compute_win_id +=(1<0;stageloop++) - - if(lcl_id> 16)); - temp = glboutindex[0]; - int4 candidate_result; - candidate_result.zw = (int2)convert_int_rte(factor*20.f); - candidate_result.x = convert_int_rte(x*factor); - candidate_result.y = convert_int_rte(y*factor); - atomic_inc(glboutindex); - - int i = outputoff+temp+lcl_id; - if(candidate[i].z == 0) - { - candidate[i] = candidate_result; - } - else - { - for(i=i+1;;i++) - { - if(candidate[i].z == 0) - { - candidate[i] = candidate_result; - break; - } - } - } - } - barrier(CLK_LOCAL_MEM_FENCE); - }//end for(int grploop=grpidx;grploop> 16; - int totalgrp = scaleinfo1.y & 0xffff; - float factor = as_float(scaleinfo1.w); - float correction_t = correction[scalei]; - float ystep = max(2.0f, factor); - - for (int grploop = get_group_id(0); grploop < totalgrp; grploop += grpnumx) - { - int4 cascadeinfo = p[scalei]; - int grpidy = grploop / grpnumperline; - int grpidx = grploop - mul24(grpidy, grpnumperline); - int ix = mad24(grpidx, grpszx, lclidx); - int iy = mad24(grpidy, grpszy, lclidy); - int x = round(ix * ystep); - int y = round(iy * ystep); - lcloutindex[lcl_id] = 0; - lclcount[0] = 0; - int nodecounter; - float mean, variance_norm_factor; - //if((ix < width) && (iy < height)) - { - const int p_offset = mad24(y, step, x); - cascadeinfo.x += p_offset; - cascadeinfo.z += p_offset; - mean = (sum[clamp(mad24(cascadeinfo.y, step, cascadeinfo.x), 0, max_idx)] - - sum[clamp(mad24(cascadeinfo.y, step, cascadeinfo.z), 0, max_idx)] - - sum[clamp(mad24(cascadeinfo.w, step, cascadeinfo.x), 0, max_idx)] - + sum[clamp(mad24(cascadeinfo.w, step, cascadeinfo.z), 0, max_idx)]) - * correction_t; - variance_norm_factor = sqsum[clamp(mad24(cascadeinfo.y, step, cascadeinfo.x), 0, max_idx)] - - sqsum[clamp(mad24(cascadeinfo.y, step, cascadeinfo.z), 0, max_idx)] - - sqsum[clamp(mad24(cascadeinfo.w, step, cascadeinfo.x), 0, max_idx)] - + sqsum[clamp(mad24(cascadeinfo.w, step, cascadeinfo.z), 0, max_idx)]; - variance_norm_factor = variance_norm_factor * correction_t - mean * mean; - variance_norm_factor = variance_norm_factor >= 0.f ? sqrt(variance_norm_factor) : 1.f; - bool result = true; - nodecounter = startnode + nodecount * scalei; - for (int stageloop = start_stage; (stageloop < end_stage) && result; stageloop++) - { - float stage_sum = 0.f; - __global GpuHidHaarStageClassifier* stageinfo = (__global GpuHidHaarStageClassifier*) - (((__global uchar*)stagecascadeptr_)+stageloop*sizeof(GpuHidHaarStageClassifier)); - int stagecount = stageinfo->count; - for (int nodeloop = 0; nodeloop < stagecount;) - { - __global GpuHidHaarTreeNode* currentnodeptr = (__global GpuHidHaarTreeNode*) - (((__global uchar*)nodeptr_) + nodecounter * sizeof(GpuHidHaarTreeNode)); - int4 info1 = *(__global int4 *)(&(currentnodeptr->p[0][0])); - int4 info2 = *(__global int4 *)(&(currentnodeptr->p[1][0])); - int4 info3 = *(__global int4 *)(&(currentnodeptr->p[2][0])); - float4 w = *(__global float4 *)(&(currentnodeptr->weight[0])); - float3 alpha3 = *(__global float3*)(&(currentnodeptr->alpha[0])); - float nodethreshold = w.w * variance_norm_factor; - - info1.x += p_offset; - info1.z += p_offset; - info2.x += p_offset; - info2.z += p_offset; - info3.x += p_offset; - info3.z += p_offset; - float classsum = (sum[clamp(mad24(info1.y, step, info1.x), 0, max_idx)] - - sum[clamp(mad24(info1.y, step, info1.z), 0, max_idx)] - - sum[clamp(mad24(info1.w, step, info1.x), 0, max_idx)] - + sum[clamp(mad24(info1.w, step, info1.z), 0, max_idx)]) * w.x; - classsum += (sum[clamp(mad24(info2.y, step, info2.x), 0, max_idx)] - - sum[clamp(mad24(info2.y, step, info2.z), 0, max_idx)] - - sum[clamp(mad24(info2.w, step, info2.x), 0, max_idx)] - + sum[clamp(mad24(info2.w, step, info2.z), 0, max_idx)]) * w.y; - classsum += (sum[clamp(mad24(info3.y, step, info3.x), 0, max_idx)] - - sum[clamp(mad24(info3.y, step, info3.z), 0, max_idx)] - - sum[clamp(mad24(info3.w, step, info3.x), 0, max_idx)] - + sum[clamp(mad24(info3.w, step, info3.z), 0, max_idx)]) * w.z; - - bool passThres = (classsum >= nodethreshold) ? 1 : 0; - -#if STUMP_BASED - stage_sum += passThres ? alpha3.y : alpha3.x; - nodecounter++; - nodeloop++; -#else - bool isRootNode = (nodecounter & 1) == 0; - if(isRootNode) - { - if( (passThres && currentnodeptr->right) || - (!passThres && currentnodeptr->left)) - { - nodecounter ++; - } - else - { - stage_sum += alpha3.x; - nodecounter += 2; - nodeloop ++; - } - } - else - { - stage_sum += (passThres ? alpha3.z : alpha3.y); - nodecounter ++; - nodeloop ++; - } -#endif - } - - result = (stage_sum >= stageinfo->threshold) ? 1 : 0; - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (result) - { - int queueindex = atomic_inc(lclcount); - lcloutindex[queueindex] = (y << 16) | x; - } - barrier(CLK_LOCAL_MEM_FENCE); - int queuecount = lclcount[0]; - - if (lcl_id < queuecount) - { - int temp = lcloutindex[lcl_id]; - int x = temp & 0xffff; - int y = (temp & (int)0xffff0000) >> 16; - temp = atomic_inc(glboutindex); - int4 candidate_result; - candidate_result.zw = (int2)convert_int_rte(factor * 20.f); - candidate_result.x = x; - candidate_result.y = y; - - int i = outputoff+temp+lcl_id; - if(candidate[i].z == 0) - { - candidate[i] = candidate_result; - } - else - { - for(i=i+1;;i++) - { - if(candidate[i].z == 0) - { - candidate[i] = candidate_result; - break; - } - } - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - } - } - } -} -__kernel void gpuscaleclassifier(global GpuHidHaarTreeNode *orinode, global GpuHidHaarTreeNode *newnode, float scale, float weight_scale, const int nodenum) -{ - const int counter = get_global_id(0); - int tr_x[3], tr_y[3], tr_h[3], tr_w[3], i = 0; - GpuHidHaarTreeNode t1 = *(__global GpuHidHaarTreeNode*) - (((__global uchar*)orinode) + counter * sizeof(GpuHidHaarTreeNode)); - __global GpuHidHaarTreeNode* pNew = (__global GpuHidHaarTreeNode*) - (((__global uchar*)newnode) + (counter + nodenum) * sizeof(GpuHidHaarTreeNode)); - - #pragma unroll - for (i = 0; i < 3; i++) - { - tr_x[i] = (int)(t1.p[i][0] * scale + 0.5f); - tr_y[i] = (int)(t1.p[i][1] * scale + 0.5f); - tr_w[i] = (int)(t1.p[i][2] * scale + 0.5f); - tr_h[i] = (int)(t1.p[i][3] * scale + 0.5f); - } - - t1.weight[0] = -(t1.weight[1] * tr_h[1] * tr_w[1] + t1.weight[2] * tr_h[2] * tr_w[2]) / (tr_h[0] * tr_w[0]); - - #pragma unroll - for (i = 0; i < 3; i++) - { - pNew->p[i][0] = tr_x[i]; - pNew->p[i][1] = tr_y[i]; - pNew->p[i][2] = tr_x[i] + tr_w[i]; - pNew->p[i][3] = tr_y[i] + tr_h[i]; - pNew->weight[i] = t1.weight[i] * weight_scale; - } - - pNew->left = t1.left; - pNew->right = t1.right; - pNew->threshold = t1.threshold; - pNew->alpha[0] = t1.alpha[0]; - pNew->alpha[1] = t1.alpha[1]; - pNew->alpha[2] = t1.alpha[2]; -} diff --git a/modules/ocl/src/opencl/imgproc_bilateral.cl b/modules/ocl/src/opencl/imgproc_bilateral.cl deleted file mode 100644 index cb317a005..000000000 --- a/modules/ocl/src/opencl/imgproc_bilateral.cl +++ /dev/null @@ -1,145 +0,0 @@ -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Rock Li, Rock.li@amd.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. - -__kernel void bilateral_C1_D0(__global uchar *dst, - __global const uchar *src, - const int dst_rows, - const int dst_cols, - const int maxk, - const int radius, - const int dst_step, - const int dst_offset, - const int src_step, - const int src_rows, - const int src_cols, - __constant float *color_weight, - __constant float *space_weight, - __constant int *space_ofs) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < dst_rows && x < dst_cols) - { - int src_index = mad24(y + radius, src_step, x + radius); - int dst_index = mad24(y, dst_step, x + dst_offset); - float sum = 0.f, wsum = 0.f; - - int val0 = (int)src[src_index]; - for(int k = 0; k < maxk; k++ ) - { - int val = (int)src[src_index + space_ofs[k]]; - float w = space_weight[k] * color_weight[abs(val - val0)]; - sum += (float)(val) * w; - wsum += w; - } - dst[dst_index] = convert_uchar_rtz(sum / wsum + 0.5f); - } -} - -__kernel void bilateral2_C1_D0(__global uchar *dst, - __global const uchar *src, - const int dst_rows, - const int dst_cols, - const int maxk, - const int radius, - const int dst_step, - const int dst_offset, - const int src_step, - const int src_rows, - const int src_cols, - __constant float *color_weight, - __constant float *space_weight, - __constant int *space_ofs) -{ - int x = get_global_id(0) << 2; - int y = get_global_id(1); - - if (y < dst_rows && x < dst_cols) - { - int src_index = mad24(y + radius, src_step, x + radius); - int dst_index = mad24(y, dst_step, x + dst_offset); - float4 sum = (float4)(0.f), wsum = (float4)(0.f); - - int4 val0 = convert_int4(vload4(0,src + src_index)); - for(int k = 0; k < maxk; k++ ) - { - int4 val = convert_int4(vload4(0,src+src_index + space_ofs[k])); - float4 w = (float4)(space_weight[k]) * (float4)(color_weight[abs(val.x - val0.x)], color_weight[abs(val.y - val0.y)], - color_weight[abs(val.z - val0.z)], color_weight[abs(val.w - val0.w)]); - sum += convert_float4(val) * w; - wsum += w; - } - *(__global uchar4*)(dst+dst_index) = convert_uchar4_rtz(sum/wsum+0.5f); - } -} - -__kernel void bilateral_C4_D0(__global uchar4 *dst, - __global const uchar4 *src, - const int dst_rows, - const int dst_cols, - const int maxk, - const int radius, - const int dst_step, - const int dst_offset, - const int src_step, - const int src_rows, - const int src_cols, - __constant float *color_weight, - __constant float *space_weight, - __constant int *space_ofs) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < dst_rows && x < dst_cols) - { - int src_index = mad24(y + radius, src_step, x + radius); - int dst_index = mad24(y, dst_step, x + dst_offset); - float4 sum = (float4)0.f; - float wsum = 0.f; - - int4 val0 = convert_int4(src[src_index]); - for(int k = 0; k < maxk; k++ ) - { - int4 val = convert_int4(src[src_index + space_ofs[k]]); - float w = space_weight[k] * color_weight[abs(val.x - val0.x) + abs(val.y - val0.y) + abs(val.z - val0.z)]; - sum += convert_float4(val) * (float4)w; - wsum += w; - } - - wsum = 1.f / wsum; - dst[dst_index] = convert_uchar4_rtz(sum * (float4)wsum + (float4)0.5f); - } -} diff --git a/modules/ocl/src/opencl/imgproc_calcHarris.cl b/modules/ocl/src/opencl/imgproc_calcHarris.cl deleted file mode 100644 index 4fc179260..000000000 --- a/modules/ocl/src/opencl/imgproc_calcHarris.cl +++ /dev/null @@ -1,214 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Shengen Yan,yanshengen@gmail.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*/ - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////Macro for border type//////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////// - -#if defined (DOUBLE_SUPPORT) && defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#define FPTYPE double -#else -#define FPTYPE float -#endif - -#ifdef BORDER_CONSTANT -#elif defined BORDER_REPLICATE -#define EXTRAPOLATE(x, maxV) \ - { \ - x = max(min(x, maxV - 1), 0); \ - } -#elif defined BORDER_WRAP -#define EXTRAPOLATE(x, maxV) \ - { \ - if (x < 0) \ - x -= ((x - maxV + 1) / maxV) * maxV; \ - if (x >= maxV) \ - x %= maxV; \ - } -#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT101) -#define EXTRAPOLATE_(x, maxV, delta) \ - { \ - if (maxV == 1) \ - x = 0; \ - else \ - do \ - { \ - if ( x < 0 ) \ - x = -x - 1 + delta; \ - else \ - x = maxV - 1 - (x - maxV) - delta; \ - } \ - while (x >= maxV || x < 0); \ - } -#ifdef BORDER_REFLECT -#define EXTRAPOLATE(x, maxV) EXTRAPOLATE_(x, maxV, 0) -#else -#define EXTRAPOLATE(x, maxV) EXTRAPOLATE_(x, maxV, 1) -#endif -#else -#error No extrapolation method -#endif - -#define THREADS 256 - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////calcHarris//////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void calcHarris(__global const float *Dx, __global const float *Dy, __global float *dst, - int dx_offset, int dx_whole_rows, int dx_whole_cols, int dx_step, - int dy_offset, int dy_whole_rows, int dy_whole_cols, int dy_step, - int dst_offset, int dst_rows, int dst_cols, int dst_step, float k) -{ - int col = get_local_id(0); - int gX = get_group_id(0); - int gY = get_group_id(1); - int gly = get_global_id(1); - - int dx_x_off = (dx_offset % dx_step) >> 2; - int dx_y_off = dx_offset / dx_step; - int dy_x_off = (dy_offset % dy_step) >> 2; - int dy_y_off = dy_offset / dy_step; - int dst_x_off = (dst_offset % dst_step) >> 2; - int dst_y_off = dst_offset / dst_step; - - int dx_startX = gX * (THREADS-ksX+1) - anX + dx_x_off; - int dx_startY = (gY << 1) - anY + dx_y_off; - int dy_startX = gX * (THREADS-ksX+1) - anX + dy_x_off; - int dy_startY = (gY << 1) - anY + dy_y_off; - int dst_startX = gX * (THREADS-ksX+1) + dst_x_off; - int dst_startY = (gY << 1) + dst_y_off; - - float dx_data[ksY+1],dy_data[ksY+1], data[3][ksY+1]; - __local FPTYPE temp[6][THREADS]; - -#ifdef BORDER_CONSTANT - for (int i=0; i < ksY+1; i++) - { - bool dx_con = dx_startX+col >= 0 && dx_startX+col < dx_whole_cols && dx_startY+i >= 0 && dx_startY+i < dx_whole_rows; - int indexDx = (dx_startY+i)*(dx_step>>2)+(dx_startX+col); - float dx_s = dx_con ? Dx[indexDx] : 0.0f; - dx_data[i] = dx_s; - - bool dy_con = dy_startX+col >= 0 && dy_startX+col < dy_whole_cols && dy_startY+i >= 0 && dy_startY+i < dy_whole_rows; - int indexDy = (dy_startY+i)*(dy_step>>2)+(dy_startX+col); - float dy_s = dy_con ? Dy[indexDy] : 0.0f; - dy_data[i] = dy_s; - - data[0][i] = dx_data[i] * dx_data[i]; - data[1][i] = dx_data[i] * dy_data[i]; - data[2][i] = dy_data[i] * dy_data[i]; - } -#else - int clamped_col = min(2*dst_cols, col); - for (int i=0; i < ksY+1; i++) - { - int dx_selected_row = dx_startY+i, dx_selected_col = dx_startX+clamped_col; - EXTRAPOLATE(dx_selected_row, dx_whole_rows) - EXTRAPOLATE(dx_selected_col, dx_whole_cols) - dx_data[i] = Dx[dx_selected_row * (dx_step>>2) + dx_selected_col]; - - int dy_selected_row = dy_startY+i, dy_selected_col = dy_startX+clamped_col; - EXTRAPOLATE(dy_selected_row, dy_whole_rows) - EXTRAPOLATE(dy_selected_col, dy_whole_cols) - dy_data[i] = Dy[dy_selected_row * (dy_step>>2) + dy_selected_col]; - - data[0][i] = dx_data[i] * dx_data[i]; - data[1][i] = dx_data[i] * dy_data[i]; - data[2][i] = dy_data[i] * dy_data[i]; - } -#endif - FPTYPE sum0 = 0.0f, sum1 = 0.0f, sum2 = 0.0f; - for (int i=1; i < ksY; i++) - { - sum0 += data[0][i]; - sum1 += data[1][i]; - sum2 += data[2][i]; - } - - FPTYPE sum01 = sum0 + data[0][0]; - FPTYPE sum02 = sum0 + data[0][ksY]; - temp[0][col] = sum01; - temp[1][col] = sum02; - FPTYPE sum11 = sum1 + data[1][0]; - FPTYPE sum12 = sum1 + data[1][ksY]; - temp[2][col] = sum11; - temp[3][col] = sum12; - FPTYPE sum21 = sum2 + data[2][0]; - FPTYPE sum22 = sum2 + data[2][ksY]; - temp[4][col] = sum21; - temp[5][col] = sum22; - barrier(CLK_LOCAL_MEM_FENCE); - - if (col < (THREADS- (ksX - 1))) - { - col += anX; - int posX = dst_startX - dst_x_off + col - anX; - int posY = (gly << 1); - int till = (ksX + 1)%2; - float tmp_sum[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - for (int k=0; k<6; k++) - { - FPTYPE temp_sum = 0; - for (int i=-anX; i<=anX - till; i++) - { - temp_sum += temp[k][col+i]; - } - tmp_sum[k] = temp_sum; - } - - if (posX < dst_cols && (posY) < dst_rows) - { - dst[(dst_startY+0) * (dst_step>>2)+ dst_startX + col - anX] = - tmp_sum[0] * tmp_sum[4] - tmp_sum[2] * tmp_sum[2] - k * (tmp_sum[0] + tmp_sum[4]) * (tmp_sum[0] + tmp_sum[4]); - } - if (posX < dst_cols && (posY + 1) < dst_rows) - { - dst[(dst_startY+1) * (dst_step>>2)+ dst_startX + col - anX] = - tmp_sum[1] * tmp_sum[5] - tmp_sum[3] * tmp_sum[3] - k * (tmp_sum[1] + tmp_sum[5]) * (tmp_sum[1] + tmp_sum[5]); - } - } -} diff --git a/modules/ocl/src/opencl/imgproc_calcMinEigenVal.cl b/modules/ocl/src/opencl/imgproc_calcMinEigenVal.cl deleted file mode 100644 index 7cb4c8ff3..000000000 --- a/modules/ocl/src/opencl/imgproc_calcMinEigenVal.cl +++ /dev/null @@ -1,204 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Shengen Yan,yanshengen@gmail.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*/ - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////Macro for border type//////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////// - -#ifdef BORDER_CONSTANT -#elif defined BORDER_REPLICATE -#define EXTRAPOLATE(x, maxV) \ - { \ - x = max(min(x, maxV - 1), 0); \ - } -#elif defined BORDER_WRAP -#define EXTRAPOLATE(x, maxV) \ - { \ - if (x < 0) \ - x -= ((x - maxV + 1) / maxV) * maxV; \ - if (x >= maxV) \ - x %= maxV; \ - } -#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT101) -#define EXTRAPOLATE_(x, maxV, delta) \ - { \ - if (maxV == 1) \ - x = 0; \ - else \ - do \ - { \ - if ( x < 0 ) \ - x = -x - 1 + delta; \ - else \ - x = maxV - 1 - (x - maxV) - delta; \ - } \ - while (x >= maxV || x < 0); \ - } -#ifdef BORDER_REFLECT -#define EXTRAPOLATE(x, maxV) EXTRAPOLATE_(x, maxV, 0) -#else -#define EXTRAPOLATE(x, maxV) EXTRAPOLATE_(x, maxV, 1) -#endif -#else -#error No extrapolation method -#endif - -#define THREADS 256 - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////calcHarris//////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -__kernel void calcMinEigenVal(__global const float *Dx,__global const float *Dy, __global float *dst, - int dx_offset, int dx_whole_rows, int dx_whole_cols, int dx_step, - int dy_offset, int dy_whole_rows, int dy_whole_cols, int dy_step, - int dst_offset, int dst_rows, int dst_cols, int dst_step, float k) -{ - int col = get_local_id(0); - int gX = get_group_id(0); - int gY = get_group_id(1); - int gly = get_global_id(1); - - int dx_x_off = (dx_offset % dx_step) >> 2; - int dx_y_off = dx_offset / dx_step; - int dy_x_off = (dy_offset % dy_step) >> 2; - int dy_y_off = dy_offset / dy_step; - int dst_x_off = (dst_offset % dst_step) >> 2; - int dst_y_off = dst_offset / dst_step; - - int dx_startX = gX * (THREADS-ksX+1) - anX + dx_x_off; - int dx_startY = (gY << 1) - anY + dx_y_off; - int dy_startX = gX * (THREADS-ksX+1) - anX + dy_x_off; - int dy_startY = (gY << 1) - anY + dy_y_off; - int dst_startX = gX * (THREADS-ksX+1) + dst_x_off; - int dst_startY = (gY << 1) + dst_y_off; - - float dx_data[ksY+1], dy_data[ksY+1], data[3][ksY+1]; - __local float temp[6][THREADS]; - -#ifdef BORDER_CONSTANT - for (int i=0; i < ksY+1; i++) - { - bool dx_con = dx_startX+col >= 0 && dx_startX+col < dx_whole_cols && dx_startY+i >= 0 && dx_startY+i < dx_whole_rows; - int indexDx = (dx_startY+i)*(dx_step>>2)+(dx_startX+col); - float dx_s = dx_con ? Dx[indexDx] : 0.0f; - dx_data[i] = dx_s; - - bool dy_con = dy_startX+col >= 0 && dy_startX+col < dy_whole_cols && dy_startY+i >= 0 && dy_startY+i < dy_whole_rows; - int indexDy = (dy_startY+i)*(dy_step>>2)+(dy_startX+col); - float dy_s = dy_con ? Dy[indexDy] : 0.0f; - dy_data[i] = dy_s; - - data[0][i] = dx_data[i] * dx_data[i]; - data[1][i] = dx_data[i] * dy_data[i]; - data[2][i] = dy_data[i] * dy_data[i]; - } -#else - int clamped_col = min(dst_cols, col); - for (int i=0; i < ksY+1; i++) - { - int dx_selected_row = dx_startY+i, dx_selected_col = dx_startX+clamped_col; - EXTRAPOLATE(dx_selected_row, dx_whole_rows) - EXTRAPOLATE(dx_selected_col, dx_whole_cols) - dx_data[i] = Dx[dx_selected_row * (dx_step>>2) + dx_selected_col]; - - int dy_selected_row = dy_startY+i, dy_selected_col = dy_startX+clamped_col; - EXTRAPOLATE(dy_selected_row, dy_whole_rows) - EXTRAPOLATE(dy_selected_col, dy_whole_cols) - dy_data[i] = Dy[dy_selected_row * (dy_step>>2) + dy_selected_col]; - - data[0][i] = dx_data[i] * dx_data[i]; - data[1][i] = dx_data[i] * dy_data[i]; - data[2][i] = dy_data[i] * dy_data[i]; - } -#endif - float sum0 = 0.0f, sum1 = 0.0f, sum2 = 0.0f; - for (int i=1; i < ksY; i++) - { - sum0 += (data[0][i]); - sum1 += (data[1][i]); - sum2 += (data[2][i]); - } - - float sum01 = sum0 + (data[0][0]); - float sum02 = sum0 + (data[0][ksY]); - temp[0][col] = sum01; - temp[1][col] = sum02; - float sum11 = sum1 + (data[1][0]); - float sum12 = sum1 + (data[1][ksY]); - temp[2][col] = sum11; - temp[3][col] = sum12; - float sum21 = sum2 + (data[2][0]); - float sum22 = sum2 + (data[2][ksY]); - temp[4][col] = sum21; - temp[5][col] = sum22; - barrier(CLK_LOCAL_MEM_FENCE); - - if(col < (THREADS-(ksX-1))) - { - col += anX; - int posX = dst_startX - dst_x_off + col - anX; - int posY = (gly << 1); - int till = (ksX + 1)%2; - float tmp_sum[6] = { 0.0f, 0.0f , 0.0f, 0.0f, 0.0f, 0.0f }; - for (int k=0; k<6; k++) - for (int i=-anX; i<=anX - till; i++) - tmp_sum[k] += temp[k][col+i]; - - if(posX < dst_cols && (posY) < dst_rows) - { - float a = tmp_sum[0] * 0.5f; - float b = tmp_sum[2]; - float c = tmp_sum[4] * 0.5f; - dst[(dst_startY+0) * (dst_step>>2)+ dst_startX + col - anX] = (float)((a+c) - sqrt((a-c)*(a-c) + b*b)); - } - if (posX < dst_cols && (posY + 1) < dst_rows) - { - float a = tmp_sum[1] * 0.5f; - float b = tmp_sum[3]; - float c = tmp_sum[5] * 0.5f; - dst[(dst_startY+1) * (dst_step>>2)+ dst_startX + col - anX] = (float)((a+c) - sqrt((a-c)*(a-c) + b*b)); - } - } -} diff --git a/modules/ocl/src/opencl/imgproc_canny.cl b/modules/ocl/src/opencl/imgproc_canny.cl deleted file mode 100644 index 2ddfdae5f..000000000 --- a/modules/ocl/src/opencl/imgproc_canny.cl +++ /dev/null @@ -1,721 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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*/ - -#ifdef L2GRAD -inline float calc(int x, int y) -{ - return sqrt((float)(x * x + y * y)); -} -#else -inline float calc(int x, int y) -{ - return (float)abs(x) + abs(y); -} -#endif // - -// Smoothing perpendicular to the derivative direction with a triangle filter -// only support 3x3 Sobel kernel -// h (-1) = 1, h (0) = 2, h (1) = 1 -// h'(-1) = -1, h'(0) = 0, h'(1) = 1 -// thus sobel 2D operator can be calculated as: -// h'(x, y) = h'(x)h(y) for x direction -// -// src input 8bit single channel image data -// dx_buf output dx buffer -// dy_buf output dy buffer -__kernel -void -__attribute__((reqd_work_group_size(16,16,1))) -calcSobelRowPass -( - __global const uchar * src, - __global int * dx_buf, - __global int * dy_buf, - int rows, - int cols, - int src_step, - int src_offset, - int dx_buf_step, - int dx_buf_offset, - int dy_buf_step, - int dy_buf_offset -) -{ - dx_buf_step /= sizeof(*dx_buf); - dx_buf_offset /= sizeof(*dx_buf); - dy_buf_step /= sizeof(*dy_buf); - dy_buf_offset /= sizeof(*dy_buf); - - int gidx = get_global_id(0); - int gidy = get_global_id(1); - - int lidx = get_local_id(0); - int lidy = get_local_id(1); - - __local int smem[16][18]; - - smem[lidy][lidx + 1] = - src[gidx + min(gidy, rows - 1) * src_step + src_offset]; - if(lidx == 0) - { - smem[lidy][0] = - src[max(gidx - 1, 0) + min(gidy, rows - 1) * src_step + src_offset]; - smem[lidy][17] = - src[min(gidx + 16, cols - 1) + min(gidy, rows - 1) * src_step + src_offset]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(gidy < rows && gidx < cols) - { - dx_buf[gidx + gidy * dx_buf_step + dx_buf_offset] = - -smem[lidy][lidx] + smem[lidy][lidx + 2]; - dy_buf[gidx + gidy * dy_buf_step + dy_buf_offset] = - smem[lidy][lidx] + 2 * smem[lidy][lidx + 1] + smem[lidy][lidx + 2]; - } -} - -// calculate the magnitude of the filter pass combining both x and y directions -// This is the buffered version(3x3 sobel) -// -// dx_buf dx buffer, calculated from calcSobelRowPass -// dy_buf dy buffer, calculated from calcSobelRowPass -// dx direvitive in x direction output -// dy direvitive in y direction output -// mag magnitude direvitive of xy output -__kernel -void -__attribute__((reqd_work_group_size(16,16,1))) -calcMagnitude_buf -( - __global const int * dx_buf, - __global const int * dy_buf, - __global int * dx, - __global int * dy, - __global float * mag, - int rows, - int cols, - int dx_buf_step, - int dx_buf_offset, - int dy_buf_step, - int dy_buf_offset, - int dx_step, - int dx_offset, - int dy_step, - int dy_offset, - int mag_step, - int mag_offset -) -{ - dx_buf_step /= sizeof(*dx_buf); - dx_buf_offset /= sizeof(*dx_buf); - dy_buf_step /= sizeof(*dy_buf); - dy_buf_offset /= sizeof(*dy_buf); - dx_step /= sizeof(*dx); - dx_offset /= sizeof(*dx); - dy_step /= sizeof(*dy); - dy_offset /= sizeof(*dy); - mag_step /= sizeof(*mag); - mag_offset /= sizeof(*mag); - - int gidx = get_global_id(0); - int gidy = get_global_id(1); - - int lidx = get_local_id(0); - int lidy = get_local_id(1); - - __local int sdx[18][16]; - __local int sdy[18][16]; - - sdx[lidy + 1][lidx] = - dx_buf[gidx + min(gidy, rows - 1) * dx_buf_step + dx_buf_offset]; - sdy[lidy + 1][lidx] = - dy_buf[gidx + min(gidy, rows - 1) * dy_buf_step + dy_buf_offset]; - if(lidy == 0) - { - sdx[0][lidx] = - dx_buf[gidx + min(max(gidy-1,0),rows-1) * dx_buf_step + dx_buf_offset]; - sdx[17][lidx] = - dx_buf[gidx + min(gidy + 16, rows - 1) * dx_buf_step + dx_buf_offset]; - - sdy[0][lidx] = - dy_buf[gidx + min(max(gidy-1,0),rows-1) * dy_buf_step + dy_buf_offset]; - sdy[17][lidx] = - dy_buf[gidx + min(gidy + 16, rows - 1) * dy_buf_step + dy_buf_offset]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(gidx < cols && gidy < rows) - { - int x = sdx[lidy][lidx] + 2 * sdx[lidy + 1][lidx] + sdx[lidy + 2][lidx]; - int y = -sdy[lidy][lidx] + sdy[lidy + 2][lidx]; - - dx[gidx + gidy * dx_step + dx_offset] = x; - dy[gidx + gidy * dy_step + dy_offset] = y; - - mag[(gidx + 1) + (gidy + 1) * mag_step + mag_offset] = calc(x, y); - } -} - -// calculate the magnitude of the filter pass combining both x and y directions -// This is the non-buffered version(non-3x3 sobel) -// -// dx_buf dx buffer, calculated from calcSobelRowPass -// dy_buf dy buffer, calculated from calcSobelRowPass -// dx direvitive in x direction output -// dy direvitive in y direction output -// mag magnitude direvitive of xy output -__kernel -void calcMagnitude -( - __global const int * dx, - __global const int * dy, - __global float * mag, - int rows, - int cols, - int dx_step, - int dx_offset, - int dy_step, - int dy_offset, - int mag_step, - int mag_offset -) -{ - dx_step /= sizeof(*dx); - dx_offset /= sizeof(*dx); - dy_step /= sizeof(*dy); - dy_offset /= sizeof(*dy); - mag_step /= sizeof(*mag); - mag_offset /= sizeof(*mag); - - int gidx = get_global_id(0); - int gidy = get_global_id(1); - - if(gidy < rows && gidx < cols) - { - mag[(gidx + 1) + (gidy + 1) * mag_step + mag_offset] = - calc( - dx[gidx + gidy * dx_step + dx_offset], - dy[gidx + gidy * dy_step + dy_offset] - ); - } -} - -////////////////////////////////////////////////////////////////////////////////////////// -// 0.4142135623730950488016887242097 is tan(22.5) -#define CANNY_SHIFT 15 - -#ifdef DOUBLE_SUPPORT - #define TG22 (int)(0.4142135623730950488016887242097*(1< low_thresh) - { - const int tg22x = x * TG22; - const int tg67x = tg22x + (x << (1 + CANNY_SHIFT)); - y <<= CANNY_SHIFT; - if(y < tg22x) - { - if(m > smem[lidy + 1][lidx] && m >= smem[lidy + 1][lidx + 2]) - { - edge_type = 1 + (int)(m > high_thresh); - } - } - else if (y > tg67x) - { - if(m > smem[lidy][lidx + 1]&& m >= smem[lidy + 2][lidx + 1]) - { - edge_type = 1 + (int)(m > high_thresh); - } - } - else - { - if(m > smem[lidy][lidx + 1 - s]&& m > smem[lidy + 2][lidx + 1 + s]) - { - edge_type = 1 + (int)(m > high_thresh); - } - } - } - map[gidx + 1 + (gidy + 1) * map_step] = edge_type; - } -} - -#undef CANNY_SHIFT -#undef TG22 - -struct PtrStepSz { - __global int *ptr; - int step; - int rows, cols; -}; -inline int get(struct PtrStepSz data, int y, int x) { return *((__global int *)((__global char*)data.ptr + data.step * (y + 1) + sizeof(int) * (x + 1))); } -inline void set(struct PtrStepSz data, int y, int x, int value) { *((__global int *)((__global char*)data.ptr + data.step * (y + 1) + sizeof(int) * (x + 1))) = value; } - -////////////////////////////////////////////////////////////////////////////////////////// -// do Hysteresis for pixel whose edge type is 1 -// -// If candidate pixel (edge type is 1) has a neighbour pixel (in 3x3 area) with type 2, it is believed to be part of an edge and -// marked as edge. Each thread will iterate for 16 times to connect local edges. -// Candidate pixel being identified as edge will then be tested if there is nearby potiential edge points. If there is, counter will -// be incremented by 1 and the point location is stored. These potiential candidates will be processed further in next kernel. -// -// map raw edge type results calculated from calcMap. -// st the potiential edge points found in this kernel call -// counter the number of potiential edge points -__kernel -void -__attribute__((reqd_work_group_size(16,16,1))) -edgesHysteresisLocal -( - __global int * map_ptr, - __global ushort2 * st, - __global unsigned int * counter, - int rows, - int cols, - int map_step, - int map_offset -) -{ -#if 0 - map_step /= sizeof(*map); - map_offset /= sizeof(*map); - - const __global int* map = map_ptr + map_offset; - - __local int smem[18][18]; - - int gidx = get_global_id(0); - int gidy = get_global_id(1); - - int lidx = get_local_id(0); - int lidy = get_local_id(1); - - int grp_idx = get_global_id(0) & 0xFFFFF0; - int grp_idy = get_global_id(1) & 0xFFFFF0; - - int tid = lidx + lidy * 16; - int lx = tid % 18; - int ly = tid / 18; - if(ly < 14) - { - smem[ly][lx] = - map[grp_idx + lx + min(grp_idy + ly, rows - 1) * map_step]; - } - if(ly < 4 && grp_idy + ly + 14 <= rows && grp_idx + lx <= cols) - { - smem[ly + 14][lx] = - map[grp_idx + lx + min(grp_idy + ly + 14, rows - 1) * map_step]; - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if(gidy < rows && gidx < cols) - { - int n; - - #pragma unroll - for (int k = 0; k < 16; ++k) - { - n = 0; - - if (smem[lidy + 1][lidx + 1] == 1) - { - n += smem[lidy ][lidx ] == 2; - n += smem[lidy ][lidx + 1] == 2; - n += smem[lidy ][lidx + 2] == 2; - - n += smem[lidy + 1][lidx ] == 2; - n += smem[lidy + 1][lidx + 2] == 2; - - n += smem[lidy + 2][lidx ] == 2; - n += smem[lidy + 2][lidx + 1] == 2; - n += smem[lidy + 2][lidx + 2] == 2; - } - - if (n > 0) - smem[lidy + 1][lidx + 1] = 2; - } - - const int e = smem[lidy + 1][lidx + 1]; - map[gidx + 1 + (gidy + 1) * map_step] = e; - - n = 0; - if(e == 2) - { - n += smem[lidy ][lidx ] == 1; - n += smem[lidy ][lidx + 1] == 1; - n += smem[lidy ][lidx + 2] == 1; - - n += smem[lidy + 1][lidx ] == 1; - n += smem[lidy + 1][lidx + 2] == 1; - - n += smem[lidy + 2][lidx ] == 1; - n += smem[lidy + 2][lidx + 1] == 1; - n += smem[lidy + 2][lidx + 2] == 1; - } - - if(n > 0) - { - unsigned int ind = atomic_inc(counter); - st[ind] = (ushort2)(gidx + 1, gidy + 1); - } - } -#else - struct PtrStepSz map = {((__global int *)((__global char*)map_ptr + map_offset)), map_step, rows + 1, cols + 1}; - - __local int smem[18][18]; - - int2 blockIdx = (int2)(get_group_id(0), get_group_id(1)); - int2 blockDim = (int2)(get_local_size(0), get_local_size(1)); - int2 threadIdx = (int2)(get_local_id(0), get_local_id(1)); - - const int x = blockIdx.x * blockDim.x + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - smem[threadIdx.y + 1][threadIdx.x + 1] = x < map.cols && y < map.rows ? get(map, y, x) : 0; - if (threadIdx.y == 0) - smem[0][threadIdx.x + 1] = x < map.cols ? get(map, y - 1, x) : 0; - if (threadIdx.y == blockDim.y - 1) - smem[blockDim.y + 1][threadIdx.x + 1] = y + 1 < map.rows ? get(map, y + 1, x) : 0; - if (threadIdx.x == 0) - smem[threadIdx.y + 1][0] = y < map.rows ? get(map, y, x - 1) : 0; - if (threadIdx.x == blockDim.x - 1) - smem[threadIdx.y + 1][blockDim.x + 1] = x + 1 < map.cols && y < map.rows ? get(map, y, x + 1) : 0; - if (threadIdx.x == 0 && threadIdx.y == 0) - smem[0][0] = y > 0 && x > 0 ? get(map, y - 1, x - 1) : 0; - if (threadIdx.x == blockDim.x - 1 && threadIdx.y == 0) - smem[0][blockDim.x + 1] = y > 0 && x + 1 < map.cols ? get(map, y - 1, x + 1) : 0; - if (threadIdx.x == 0 && threadIdx.y == blockDim.y - 1) - smem[blockDim.y + 1][0] = y + 1 < map.rows && x > 0 ? get(map, y + 1, x - 1) : 0; - if (threadIdx.x == blockDim.x - 1 && threadIdx.y == blockDim.y - 1) - smem[blockDim.y + 1][blockDim.x + 1] = y + 1 < map.rows && x + 1 < map.cols ? get(map, y + 1, x + 1) : 0; - - barrier(CLK_LOCAL_MEM_FENCE); - - if (x >= cols || y >= rows) - return; - - int n; - - #pragma unroll - for (int k = 0; k < 16; ++k) - { - n = 0; - - if (smem[threadIdx.y + 1][threadIdx.x + 1] == 1) - { - n += smem[threadIdx.y ][threadIdx.x ] == 2; - n += smem[threadIdx.y ][threadIdx.x + 1] == 2; - n += smem[threadIdx.y ][threadIdx.x + 2] == 2; - - n += smem[threadIdx.y + 1][threadIdx.x ] == 2; - n += smem[threadIdx.y + 1][threadIdx.x + 2] == 2; - - n += smem[threadIdx.y + 2][threadIdx.x ] == 2; - n += smem[threadIdx.y + 2][threadIdx.x + 1] == 2; - n += smem[threadIdx.y + 2][threadIdx.x + 2] == 2; - } - - if (n > 0) - smem[threadIdx.y + 1][threadIdx.x + 1] = 2; - } - - const int e = smem[threadIdx.y + 1][threadIdx.x + 1]; - - set(map, y, x, e); - - n = 0; - - if (e == 2) - { - n += smem[threadIdx.y ][threadIdx.x ] == 1; - n += smem[threadIdx.y ][threadIdx.x + 1] == 1; - n += smem[threadIdx.y ][threadIdx.x + 2] == 1; - - n += smem[threadIdx.y + 1][threadIdx.x ] == 1; - n += smem[threadIdx.y + 1][threadIdx.x + 2] == 1; - - n += smem[threadIdx.y + 2][threadIdx.x ] == 1; - n += smem[threadIdx.y + 2][threadIdx.x + 1] == 1; - n += smem[threadIdx.y + 2][threadIdx.x + 2] == 1; - } - - if (n > 0) - { - const int ind = atomic_inc(counter); - st[ind] = (ushort2)(x + 1, y + 1); - } -#endif -} - -__constant int c_dx[8] = {-1, 0, 1, -1, 1, -1, 0, 1}; -__constant int c_dy[8] = {-1, -1, -1, 0, 0, 1, 1, 1}; - - -#define stack_size 512 -__kernel -void -__attribute__((reqd_work_group_size(128,1,1))) -edgesHysteresisGlobal -( - __global int * map, - __global ushort2 * st1, - __global ushort2 * st2, - __global int * counter, - int rows, - int cols, - int count, - int map_step, - int map_offset -) -{ - map_step /= sizeof(*map); - map_offset /= sizeof(*map); - - map += map_offset; - - int lidx = get_local_id(0); - - int grp_idx = get_group_id(0); - int grp_idy = get_group_id(1); - - __local unsigned int s_counter; - __local unsigned int s_ind; - - __local ushort2 s_st[stack_size]; - - if(lidx == 0) - { - s_counter = 0; - } - barrier(CLK_LOCAL_MEM_FENCE); - - int ind = mad24(grp_idy, (int)get_local_size(0), grp_idx); - - if(ind < count) - { - ushort2 pos = st1[ind]; - if (lidx < 8) - { - pos.x += c_dx[lidx]; - pos.y += c_dy[lidx]; - if (pos.x > 0 && pos.x <= cols && pos.y > 0 && pos.y <= rows && map[pos.x + pos.y * map_step] == 1) - { - map[pos.x + pos.y * map_step] = 2; - - ind = atomic_inc(&s_counter); - - s_st[ind] = pos; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - while (s_counter > 0 && s_counter <= stack_size - get_local_size(0)) - { - const int subTaskIdx = lidx >> 3; - const int portion = min(s_counter, (uint)(get_local_size(0)>> 3)); - - if (subTaskIdx < portion) - pos = s_st[s_counter - 1 - subTaskIdx]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (lidx == 0) - s_counter -= portion; - barrier(CLK_LOCAL_MEM_FENCE); - - if (subTaskIdx < portion) - { - pos.x += c_dx[lidx & 7]; - pos.y += c_dy[lidx & 7]; - if (pos.x > 0 && pos.x <= cols && pos.y > 0 && pos.y <= rows && map[pos.x + pos.y * map_step] == 1) - { - map[pos.x + pos.y * map_step] = 2; - - ind = atomic_inc(&s_counter); - - s_st[ind] = pos; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - } - - if (s_counter > 0) - { - if (lidx == 0) - { - ind = atomic_add(counter, s_counter); - s_ind = ind - s_counter; - } - barrier(CLK_LOCAL_MEM_FENCE); - - ind = s_ind; - - for (int i = lidx; i < (int)s_counter; i += get_local_size(0)) - { - st2[ind + i] = s_st[i]; - } - } - } -} -#undef stack_size - -//Get the edge result. egde type of value 2 will be marked as an edge point and set to 255. Otherwise 0. -// map edge type mappings -// dst edge output -__kernel -void getEdges -( - __global const int * map, - __global uchar * dst, - int rows, - int cols, - int map_step, - int map_offset, - int dst_step, - int dst_offset -) -{ - map_step /= sizeof(*map); - map_offset /= sizeof(*map); - - int gidx = get_global_id(0); - int gidy = get_global_id(1); - - if(gidy < rows && gidx < cols) - { - dst[gidx + gidy * dst_step] = (uchar)(-(map[gidx + 1 + (gidy + 1) * map_step + map_offset] >> 1)); - } -} diff --git a/modules/ocl/src/opencl/imgproc_clahe.cl b/modules/ocl/src/opencl/imgproc_clahe.cl deleted file mode 100644 index 71a6f895d..000000000 --- a/modules/ocl/src/opencl/imgproc_clahe.cl +++ /dev/null @@ -1,255 +0,0 @@ -/*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 -// Sen Liu, swjtuls1987@126.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*/ - -#ifndef WAVE_SIZE -#define WAVE_SIZE 1 -#endif - -inline int calc_lut(__local int* smem, int val, int tid) -{ - smem[tid] = val; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid == 0) - for (int i = 1; i < 256; ++i) - smem[i] += smem[i - 1]; - barrier(CLK_LOCAL_MEM_FENCE); - - return smem[tid]; -} - -#ifdef CPU -inline void reduce(volatile __local int* smem, int val, int tid) -{ - smem[tid] = val; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 128) - smem[tid] = val += smem[tid + 128]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 64) - smem[tid] = val += smem[tid + 64]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 32) - smem[tid] += smem[tid + 32]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 16) - smem[tid] += smem[tid + 16]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 8) - smem[tid] += smem[tid + 8]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 4) - smem[tid] += smem[tid + 4]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 2) - smem[tid] += smem[tid + 2]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 1) - smem[256] = smem[tid] + smem[tid + 1]; - barrier(CLK_LOCAL_MEM_FENCE); -} - -#else - -inline void reduce(__local volatile int* smem, int val, int tid) -{ - smem[tid] = val; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 128) - smem[tid] = val += smem[tid + 128]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 64) - smem[tid] = val += smem[tid + 64]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 32) - { - smem[tid] += smem[tid + 32]; -#if WAVE_SIZE < 32 - } barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 16) - { -#endif - smem[tid] += smem[tid + 16]; -#if WAVE_SIZE < 16 - } - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 8) - { -#endif - smem[tid] += smem[tid + 8]; - smem[tid] += smem[tid + 4]; - smem[tid] += smem[tid + 2]; - smem[tid] += smem[tid + 1]; - } -} -#endif - -__kernel void calcLut(__global __const uchar * src, __global uchar * lut, - const int srcStep, const int dstStep, - const int2 tileSize, const int tilesX, - const int clipLimit, const float lutScale, - const int src_offset, const int dst_offset) -{ - __local int smem[512]; - - int tx = get_group_id(0); - int ty = get_group_id(1); - int tid = get_local_id(1) * get_local_size(0) - + get_local_id(0); - - smem[tid] = 0; - barrier(CLK_LOCAL_MEM_FENCE); - - for (int i = get_local_id(1); i < tileSize.y; i += get_local_size(1)) - { - __global const uchar* srcPtr = src + mad24(ty * tileSize.y + i, srcStep, tx * tileSize.x + src_offset); - for (int j = get_local_id(0); j < tileSize.x; j += get_local_size(0)) - { - const int data = srcPtr[j]; - atomic_inc(&smem[data]); - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - int tHistVal = smem[tid]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (clipLimit > 0) - { - // clip histogram bar - int clipped = 0; - if (tHistVal > clipLimit) - { - clipped = tHistVal - clipLimit; - tHistVal = clipLimit; - } - - // find number of overall clipped samples - reduce(smem, clipped, tid); - barrier(CLK_LOCAL_MEM_FENCE); -#ifdef CPU - clipped = smem[256]; -#else - clipped = smem[0]; -#endif - - // broadcast evaluated value - - __local int totalClipped; - - if (tid == 0) - totalClipped = clipped; - barrier(CLK_LOCAL_MEM_FENCE); - - // redistribute clipped samples evenly - - int redistBatch = totalClipped / 256; - tHistVal += redistBatch; - - int residual = totalClipped - redistBatch * 256; - if (tid < residual) - ++tHistVal; - } - - const int lutVal = calc_lut(smem, tHistVal, tid); - uint ires = (uint)convert_int_rte(lutScale * lutVal); - lut[(ty * tilesX + tx) * dstStep + tid + dst_offset] = - convert_uchar(clamp(ires, (uint)0, (uint)255)); -} - -__kernel void transform(__global __const uchar * src, - __global uchar * dst, - __global uchar * lut, - const int srcStep, const int dstStep, const int lutStep, - const int cols, const int rows, - const int2 tileSize, - const int tilesX, const int tilesY, - const int src_offset, const int dst_offset, int lut_offset) -{ - const int x = get_global_id(0); - const int y = get_global_id(1); - - if (x >= cols || y >= rows) - return; - - const float tyf = (convert_float(y) / tileSize.y) - 0.5f; - int ty1 = convert_int_rtn(tyf); - int ty2 = ty1 + 1; - const float ya = tyf - ty1; - ty1 = max(ty1, 0); - ty2 = min(ty2, tilesY - 1); - - const float txf = (convert_float(x) / tileSize.x) - 0.5f; - int tx1 = convert_int_rtn(txf); - int tx2 = tx1 + 1; - const float xa = txf - tx1; - tx1 = max(tx1, 0); - tx2 = min(tx2, tilesX - 1); - - const int srcVal = src[mad24(y, srcStep, x + src_offset)]; - - float res = 0; - - res += lut[mad24(ty1 * tilesX + tx1, lutStep, srcVal + lut_offset)] * ((1.0f - xa) * (1.0f - ya)); - res += lut[mad24(ty1 * tilesX + tx2, lutStep, srcVal + lut_offset)] * ((xa) * (1.0f - ya)); - res += lut[mad24(ty2 * tilesX + tx1, lutStep, srcVal + lut_offset)] * ((1.0f - xa) * (ya)); - res += lut[mad24(ty2 * tilesX + tx2, lutStep, srcVal + lut_offset)] * ((xa) * (ya)); - - uint ires = (uint)convert_int_rte(res); - dst[mad24(y, dstStep, x + dst_offset)] = convert_uchar(clamp(ires, (uint)0, (uint)255)); -} diff --git a/modules/ocl/src/opencl/imgproc_columnsum.cl b/modules/ocl/src/opencl/imgproc_columnsum.cl deleted file mode 100644 index 6b596a322..000000000 --- a/modules/ocl/src/opencl/imgproc_columnsum.cl +++ /dev/null @@ -1,70 +0,0 @@ -/*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 -// Chunpeng Zhang chunpeng@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*/ - -//////////////////////////////////////////////////////////////////// -///////////////////////// columnSum //////////////////////////////// -//////////////////////////////////////////////////////////////////// - -__kernel void columnSum_C1_D5(__global float * src, __global float * dst, - int cols, int rows, int src_step, int dst_step, int src_offset, int dst_offset) -{ - const int x = get_global_id(0); - - if (x < cols) - { - int srcIdx = x + src_offset; - int dstIdx = x + dst_offset; - - float sum = 0; - - for (int y = 0; y < rows; ++y) - { - sum += src[srcIdx]; - dst[dstIdx] = sum; - srcIdx += src_step; - dstIdx += dst_step; - } - } -} diff --git a/modules/ocl/src/opencl/imgproc_convolve.cl b/modules/ocl/src/opencl/imgproc_convolve.cl deleted file mode 100644 index b8f974219..000000000 --- a/modules/ocl/src/opencl/imgproc_convolve.cl +++ /dev/null @@ -1,111 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jiang Liyuan, jlyuan001.good@163.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -/************************************** convolve **************************************/ - -__kernel void convolve_D5(__global float *src, __global float *temp1, __global float *dst, - int rows, int cols, int src_step, int dst_step,int k_step, int kWidth, int kHeight, - int src_offset, int dst_offset, int koffset) -{ - __local float smem[16 + 2 * 8][16 + 2 * 8]; - - int x = get_local_id(0); - int y = get_local_id(1); - int gx = get_global_id(0); - int gy = get_global_id(1); - - // x | x 0 | 0 - // ----------- - // x | x 0 | 0 - // 0 | 0 0 | 0 - // ----------- - // 0 | 0 0 | 0 - smem[y][x] = src[min(max(gy - 8, 0), rows - 1) * src_step + min(max(gx - 8, 0), cols - 1) + src_offset]; - - // 0 | 0 x | x - // ----------- - // 0 | 0 x | x - // 0 | 0 0 | 0 - // ----------- - // 0 | 0 0 | 0 - smem[y][x + 16] = src[min(max(gy - 8, 0), rows - 1) * src_step + min(gx + 8, cols - 1) + src_offset]; - - // 0 | 0 0 | 0 - // ----------- - // 0 | 0 0 | 0 - // x | x 0 | 0 - // ----------- - // x | x 0 | 0 - smem[y + 16][x] = src[min(gy + 8, rows - 1) * src_step + min(max(gx - 8, 0), cols - 1) + src_offset]; - - // 0 | 0 0 | 0 - // ----------- - // 0 | 0 0 | 0 - // 0 | 0 x | x - // ----------- - // 0 | 0 x | x - smem[y + 16][x + 16] = src[min(gy + 8, rows - 1) * src_step + min(gx + 8, cols - 1) + src_offset]; - - barrier(CLK_LOCAL_MEM_FENCE); - - if (gx < cols && gy < rows) - { - float res = 0; - - for (int i = 0; i < kHeight; ++i) - for (int j = 0; j < kWidth; ++j) - res += smem[y + 8 - kHeight / 2 + i][x + 8 - kWidth / 2 + j] * temp1[i * k_step + j + koffset]; - - dst[gy * dst_step + gx + dst_offset] = res; - } -} diff --git a/modules/ocl/src/opencl/imgproc_copymakeboder.cl b/modules/ocl/src/opencl/imgproc_copymakeboder.cl deleted file mode 100644 index ac149a46b..000000000 --- a/modules/ocl/src/opencl/imgproc_copymakeboder.cl +++ /dev/null @@ -1,134 +0,0 @@ -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Zero Lin zero.lin@amd.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. -// -// - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#ifdef BORDER_CONSTANT -#define EXTRAPOLATE(x, y, v) v = scalar; -#elif defined BORDER_REPLICATE -#define EXTRAPOLATE(x, y, v) \ - { \ - x = max(min(x, src_cols - 1), 0); \ - y = max(min(y, src_rows - 1), 0); \ - v = src[mad24(y, src_step, x + src_offset)]; \ - } -#elif defined BORDER_WRAP -#define EXTRAPOLATE(x, y, v) \ - { \ - if (x < 0) \ - x -= ((x - src_cols + 1) / src_cols) * src_cols; \ - if (x >= src_cols) \ - x %= src_cols; \ - \ - if (y < 0) \ - y -= ((y - src_rows + 1) / src_rows) * src_rows; \ - if( y >= src_rows ) \ - y %= src_rows; \ - v = src[mad24(y, src_step, x + src_offset)]; \ - } -#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT_101) -#ifdef BORDER_REFLECT -#define DELTA int delta = 0 -#else -#define DELTA int delta = 1 -#endif -#define EXTRAPOLATE(x, y, v) \ - { \ - DELTA; \ - if (src_cols == 1) \ - x = 0; \ - else \ - do \ - { \ - if( x < 0 ) \ - x = -x - 1 + delta; \ - else \ - x = src_cols - 1 - (x - src_cols) - delta; \ - } \ - while (x >= src_cols || x < 0); \ - \ - if (src_rows == 1) \ - y = 0; \ - else \ - do \ - { \ - if( y < 0 ) \ - y = -y - 1 + delta; \ - else \ - y = src_rows - 1 - (y - src_rows) - delta; \ - } \ - while (y >= src_rows || y < 0); \ - v = src[mad24(y, src_step, x + src_offset)]; \ - } -#else -#error No extrapolation method -#endif - -#define NEED_EXTRAPOLATION(gx, gy) (gx >= src_cols || gy >= src_rows || gx < 0 || gy < 0) - -__kernel void copymakeborder - (__global const GENTYPE *src, - __global GENTYPE *dst, - int dst_cols, int dst_rows, - int src_cols, int src_rows, - int src_step, int src_offset, - int dst_step, int dst_offset, - int top, int left, GENTYPE scalar) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < dst_cols && y < dst_rows) - { - int src_x = x - left; - int src_y = y - top; - int dst_index = mad24(y, dst_step, x + dst_offset); - - if (NEED_EXTRAPOLATION(src_x, src_y)) - EXTRAPOLATE(src_x, src_y, dst[dst_index]) - else - { - int src_index = mad24(src_y, src_step, src_x + src_offset); - dst[dst_index] = src[src_index]; - } - } -} diff --git a/modules/ocl/src/opencl/imgproc_gftt.cl b/modules/ocl/src/opencl/imgproc_gftt.cl deleted file mode 100644 index 9cd57678f..000000000 --- a/modules/ocl/src/opencl/imgproc_gftt.cl +++ /dev/null @@ -1,129 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@outlook.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*/ - -#ifndef WITH_MASK -#define WITH_MASK 0 -#endif - -//macro to read eigenvalue matrix -#define GET_SRC_32F(_x, _y) ((__global const float*)(eig + (_y)*eig_pitch))[_x] - -__kernel - void findCorners - ( - __global const char* eig, - const int eig_pitch, - __global const char* mask, - __global float2* corners, - const int mask_strip,// in pixels - __global const float* pMinMax, - const float qualityLevel, - const int rows, - const int cols, - const int max_count, - __global int* g_counter - ) -{ - float threshold = qualityLevel*pMinMax[1]; - const int j = get_global_id(0); - const int i = get_global_id(1); - - if (i > 0 && i < rows - 1 && j > 0 && j < cols - 1 -#if WITH_MASK - && mask[i * mask_strip + j] != 0 -#endif - ) - { - const float val = GET_SRC_32F(j, i); - - if (val > threshold) - { - float maxVal = val; - maxVal = fmax(GET_SRC_32F(j - 1, i - 1), maxVal); - maxVal = fmax(GET_SRC_32F(j , i - 1), maxVal); - maxVal = fmax(GET_SRC_32F(j + 1, i - 1), maxVal); - - maxVal = fmax(GET_SRC_32F(j - 1, i), maxVal); - maxVal = fmax(GET_SRC_32F(j + 1, i), maxVal); - - maxVal = fmax(GET_SRC_32F(j - 1, i + 1), maxVal); - maxVal = fmax(GET_SRC_32F(j , i + 1), maxVal); - maxVal = fmax(GET_SRC_32F(j + 1, i + 1), maxVal); - - if (val == maxVal) - { - const int ind = atomic_inc(g_counter); - - if (ind < max_count) - {// pack and store eigenvalue and its coordinates - corners[ind].x = val; - corners[ind].y = as_float(j|(i<<16)); - } - } - } - } -} -#undef GET_SRC_32F - - -// this is simple short serial kernel that makes some short reduction and initialization work -// it makes HOST like work to avoid additional sync with HOST to do this short work -// data - input/output float2. -// input data are sevral (min,max) pairs -// output data is one reduced (min,max) pair -// g_counter - counter that have to be initialized by 0 for next findCorner call. -__kernel void arithm_op_minMax_final(__global float * data, int groupnum,__global int * g_counter) -{ - g_counter[0] = 0; - float minVal = data[0]; - float maxVal = data[groupnum]; - for(int i=1;i> 2); i++, idx += lsize) - { - subhist[idx] = 0; - subhist[idx+=lsize] = 0; - subhist[idx+=lsize] = 0; - subhist[idx+=lsize] = 0; - } - barrier(CLK_LOCAL_MEM_FENCE); - - //read and scatter - int y = gid/cols; - int x = gid - mul24(y, cols); - for(int idx=gid; idx>= shift; - temp2 = ((data & mask) << NBANKS_BIT) + offset; - data >>= shift; - temp3 = ((data & mask) << NBANKS_BIT) + offset; - data >>= shift; - temp4 = ((data & mask) << NBANKS_BIT) + offset; - - atomic_inc(subhist + temp1.x); - atomic_inc(subhist + temp1.y); - atomic_inc(subhist + temp1.z); - atomic_inc(subhist + temp1.w); - - atomic_inc(subhist + temp2.x); - atomic_inc(subhist + temp2.y); - atomic_inc(subhist + temp2.z); - atomic_inc(subhist + temp2.w); - - atomic_inc(subhist + temp3.x); - atomic_inc(subhist + temp3.y); - atomic_inc(subhist + temp3.z); - atomic_inc(subhist + temp3.w); - - atomic_inc(subhist + temp4.x); - atomic_inc(subhist + temp4.y); - atomic_inc(subhist + temp4.z); - atomic_inc(subhist + temp4.w); - - x += inc_x; - int off = ((x>=cols) ? -1 : 0); - x = mad24(off, cols, x); - y += inc_y - off; - } - barrier(CLK_LOCAL_MEM_FENCE); - - //reduce local banks to single histogram per workgroup - int bin1=0, bin2=0, bin3=0, bin4=0; - for(int i=0; i=left_col) ? (gidx+cols) : gidx); - if(gidy= rows ? HISTOGRAM256_LOCAL_MEM_SIZE : p; - atomic_inc(subhist + p); - } - barrier(CLK_LOCAL_MEM_FENCE); - - globalHist[mad24(rowIndex, hist_step, lidy)] += subhist[lidy]; -} - -__kernel __attribute__((reqd_work_group_size(256,1,1)))void merge_hist(__global int* buf, - __global int* hist, - int src_step) -{ - int lx = get_local_id(0); - int gx = get_group_id(0); - - int sum = 0; - - for(int i = lx; i < PARTIAL_HISTOGRAM256_COUNT; i += HISTOGRAM256_WORK_GROUP_SIZE) - sum += buf[ mad24(i, src_step, gx)]; - - __local int data[HISTOGRAM256_WORK_GROUP_SIZE]; - data[lx] = sum; - - for(int stride = HISTOGRAM256_WORK_GROUP_SIZE /2; stride > 0; stride >>= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - if(lx < stride) - data[lx] += data[lx + stride]; - } - - if(lx == 0) - hist[gx] = data[0]; -} - -__kernel __attribute__((reqd_work_group_size(256,1,1))) -void calLUT(__global uchar * dst, __constant int * hist, int total) -{ - int lid = get_local_id(0); - __local int sumhist[HISTOGRAM256_BIN_COUNT]; - __local float scale; - - sumhist[lid] = hist[lid]; - barrier(CLK_LOCAL_MEM_FENCE); - if (lid == 0) - { - int sum = 0, i = 0; - while (!sumhist[i]) - ++i; - - if (total == sumhist[i]) - { - scale = 1; - for (int j = 0; j < HISTOGRAM256_BIN_COUNT; ++j) - sumhist[i] = i; - } - else - { - scale = 255.f/(total - sumhist[i]); - - for (sumhist[i++] = 0; i < HISTOGRAM256_BIN_COUNT; i++) - { - sum += sumhist[i]; - sumhist[i] = sum; - } - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - dst[lid]= convert_uchar_sat_rte(convert_float(sumhist[lid])*scale); -} - -/* -///////////////////////////////equalizeHist////////////////////////////////////////////////// -__kernel __attribute__((reqd_work_group_size(256,1,1)))void equalizeHist( - __global uchar * src, - __global uchar * dst, - __constant int * hist, - int srcstep, - int srcoffset, - int dststep, - int dstoffset, - int width, - int height, - float scale, - int inc_x, - int inc_y) -{ - int gidx = get_global_id(0); - int lid = get_local_id(0); - int glb_size = get_global_size(0); - src+=srcoffset; - dst+=dstoffset; - __local int sumhist[HISTOGRAM256_BIN_COUNT]; - __local uchar lut[HISTOGRAM256_BIN_COUNT+1]; - - sumhist[lid]=hist[lid]; - barrier(CLK_LOCAL_MEM_FENCE); - if(lid==0) - { - int sum = 0; - for(int i=0;i= width ? -1 : 0); - pos_x = mad24(off,width,pos_x); - pos_y += inc_y - off; - } -} -*/ diff --git a/modules/ocl/src/opencl/imgproc_hough.cl b/modules/ocl/src/opencl/imgproc_hough.cl deleted file mode 100644 index fd1c5b9a8..000000000 --- a/modules/ocl/src/opencl/imgproc_hough.cl +++ /dev/null @@ -1,280 +0,0 @@ -/*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) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., 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 bpied warranties, including, but not limited to, the bpied -// 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*/ - -#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable -#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable - -//////////////////////////////////////////////////////////////////////// -// buildPointList - -#define PIXELS_PER_THREAD 16 - -// TODO: add offset to support ROI -__kernel void buildPointList(__global const uchar* src, - int cols, - int rows, - int step, - __global unsigned int* list, - __global int* counter) -{ - __local unsigned int s_queues[4][32 * PIXELS_PER_THREAD]; - __local int s_qsize[4]; - __local int s_globStart[4]; - - const int x = get_group_id(0) * get_local_size(0) * PIXELS_PER_THREAD + get_local_id(0); - const int y = get_global_id(1); - - if (get_local_id(0) == 0) - s_qsize[get_local_id(1)] = 0; - barrier(CLK_LOCAL_MEM_FENCE); - - if (y < rows) - { - // fill the queue - __global const uchar* srcRow = &src[y * step]; - for (int i = 0, xx = x; i < PIXELS_PER_THREAD && xx < cols; ++i, xx += get_local_size(0)) - { - if (srcRow[xx]) - { - const unsigned int val = (y << 16) | xx; - const int qidx = atomic_add(&s_qsize[get_local_id(1)], 1); - s_queues[get_local_id(1)][qidx] = val; - } - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - // let one work-item reserve the space required in the global list - if (get_local_id(0) == 0 && get_local_id(1) == 0) - { - // find how many items are stored in each list - int totalSize = 0; - for (int i = 0; i < get_local_size(1); ++i) - { - s_globStart[i] = totalSize; - totalSize += s_qsize[i]; - } - - // calculate the offset in the global list - const int globalOffset = atomic_add(counter, totalSize); - for (int i = 0; i < get_local_size(1); ++i) - s_globStart[i] += globalOffset; - } - - barrier(CLK_GLOBAL_MEM_FENCE); - - // copy local queues to global queue - const int qsize = s_qsize[get_local_id(1)]; - int gidx = s_globStart[get_local_id(1)] + get_local_id(0); - for(int i = get_local_id(0); i < qsize; i += get_local_size(0), gidx += get_local_size(0)) - list[gidx] = s_queues[get_local_id(1)][i]; -} - -//////////////////////////////////////////////////////////////////////// -// circlesAccumCenters - -// TODO: add offset to support ROI -__kernel void circlesAccumCenters(__global const unsigned int* list, - const int count, - __global const int* dx, - const int dxStep, - __global const int* dy, - const int dyStep, - __global int* accum, - const int accumStep, - const int width, - const int height, - const int minRadius, - const int maxRadius, - const float idp) -{ - const int dxStepInPixel = dxStep / sizeof(int); - const int dyStepInPixel = dyStep / sizeof(int); - const int accumStepInPixel = accumStep / sizeof(int); - - const int SHIFT = 10; - const int ONE = 1 << SHIFT; - - // const int tid = blockIdx.x * blockDim.x + threadIdx.x; - const int wid = get_global_id(0); - - if (wid >= count) - return; - - const unsigned int val = list[wid]; - - const int x = (val & 0xFFFF); - const int y = (val >> 16) & 0xFFFF; - - const int vx = dx[mad24(y, dxStepInPixel, x)]; - const int vy = dy[mad24(y, dyStepInPixel, x)]; - - if (vx == 0 && vy == 0) - return; - - const float mag = sqrt(convert_float(vx * vx + vy * vy)); - - const int x0 = convert_int_rte((x * idp) * ONE); - const int y0 = convert_int_rte((y * idp) * ONE); - - int sx = convert_int_rte((vx * idp) * ONE / mag); - int sy = convert_int_rte((vy * idp) * ONE / mag); - - // Step from minRadius to maxRadius in both directions of the gradient - for (int k1 = 0; k1 < 2; ++k1) - { - int x1 = x0 + minRadius * sx; - int y1 = y0 + minRadius * sy; - - for (int r = minRadius; r <= maxRadius; x1 += sx, y1 += sy, ++r) - { - const int x2 = x1 >> SHIFT; - const int y2 = y1 >> SHIFT; - - if (x2 < 0 || x2 >= width || y2 < 0 || y2 >= height) - break; - - atomic_add(&accum[mad24(y2+1, accumStepInPixel, x2+1)], 1); - } - - sx = -sx; - sy = -sy; - } -} - -// //////////////////////////////////////////////////////////////////////// -// // buildCentersList - -// TODO: add offset to support ROI -__kernel void buildCentersList(__global const int* accum, - const int accumCols, - const int accumRows, - const int accumStep, - __global unsigned int* centers, - const int threshold, - __global int* counter) -{ - const int accumStepInPixel = accumStep/sizeof(int); - - const int x = get_global_id(0); - const int y = get_global_id(1); - - if (x < accumCols - 2 && y < accumRows - 2) - { - const int top = accum[mad24(y, accumStepInPixel, x + 1)]; - - const int left = accum[mad24(y + 1, accumStepInPixel, x)]; - const int cur = accum[mad24(y + 1, accumStepInPixel, x + 1)]; - const int right = accum[mad24(y + 1, accumStepInPixel, x + 2)]; - - const int bottom = accum[mad24(y + 2, accumStepInPixel, x + 1)];; - - if (cur > threshold && cur > top && cur >= bottom && cur > left && cur >= right) - { - const unsigned int val = (y << 16) | x; - const int idx = atomic_add(counter, 1); - centers[idx] = val; - } - } -} - - -// //////////////////////////////////////////////////////////////////////// -// // circlesAccumRadius - -// TODO: add offset to support ROI -__kernel void circlesAccumRadius(__global const unsigned int* centers, - __global const unsigned int* list, const int count, - __global float4* circles, const int maxCircles, - const float dp, - const int minRadius, const int maxRadius, - const int histSize, - const int threshold, - __local int* smem, - __global int* counter) -{ - for (int i = get_local_id(0); i < histSize + 2; i += get_local_size(0)) - smem[i] = 0; - barrier(CLK_LOCAL_MEM_FENCE); - - unsigned int val = centers[get_group_id(0)]; - - float cx = convert_float(val & 0xFFFF); - float cy = convert_float((val >> 16) & 0xFFFF); - - cx = (cx + 0.5f) * dp; - cy = (cy + 0.5f) * dp; - - for (int i = get_local_id(0); i < count; i += get_local_size(0)) - { - val = list[i]; - - const int x = (val & 0xFFFF); - const int y = (val >> 16) & 0xFFFF; - - const float rad = sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)); - if (rad >= minRadius && rad <= maxRadius) - { - const int r = convert_int_rte(rad - minRadius); - - atomic_add(&smem[r + 1], 1); - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - for (int i = get_local_id(0); i < histSize; i += get_local_size(0)) - { - const int curVotes = smem[i + 1]; - - if (curVotes >= threshold && curVotes > smem[i] && curVotes >= smem[i + 2]) - - { - const int ind = atomic_add(counter, 1); - if (ind < maxCircles) - { - circles[ind] = (float4)(cx, cy, convert_float(i + minRadius), 0.0f); - } - } - } -} diff --git a/modules/ocl/src/opencl/imgproc_integral.cl b/modules/ocl/src/opencl/imgproc_integral.cl deleted file mode 100644 index 1d90e507f..000000000 --- a/modules/ocl/src/opencl/imgproc_integral.cl +++ /dev/null @@ -1,503 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Shengen Yan,yanshengen@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#define CONVERT(step) ((step)>>1) -#else -#define CONVERT(step) ((step)) -#endif - -#define LSIZE 256 -#define LSIZE_1 255 -#define LSIZE_2 254 -#define HF_LSIZE 128 -#define LOG_LSIZE 8 -#define LOG_NUM_BANKS 5 -#define NUM_BANKS 32 -#define GET_CONFLICT_OFFSET(lid) ((lid) >> LOG_NUM_BANKS) - - -kernel void integral_cols_D4(__global uchar4 *src,__global int *sum ,__global TYPE *sqsum, - int src_offset,int pre_invalid,int rows,int cols,int src_step,int dst_step,int dst1_step) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - int4 src_t[2], sum_t[2]; - TYPE4 sqsum_t[2]; - __local int4 lm_sum[2][LSIZE + LOG_LSIZE]; - __local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE]; - __local int* sum_p; - __local TYPE* sqsum_p; - src_step = src_step >> 2; - gid = gid << 1; - for(int i = 0; i < rows; i =i + LSIZE_1) - { - src_t[0] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + min(gid, cols - 1)]) : 0); - src_t[1] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + min(gid + 1, cols - 1)]) : 0); - - sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); - sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]); - sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); - sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]); - barrier(CLK_LOCAL_MEM_FENCE); - - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); - lm_sum[0][bf_loc] = src_t[0]; - lm_sqsum[0][bf_loc] = convert_TYPE4(src_t[0] * src_t[0]); - - lm_sum[1][bf_loc] = src_t[1]; - lm_sqsum[1][bf_loc] = convert_TYPE4(src_t[1] * src_t[1]); - - int offset = 1; - for(int d = LSIZE >> 1 ; d > 0; d>>=1) - { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - } - offset <<= 1; - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for(int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step /4, loc_s1 = loc_s0 + dst_step ; - int loc_sq0 = gid * CONVERT(dst1_step) + i + lid - 1 - pre_invalid * dst1_step / sizeof(TYPE),loc_sq1 = loc_sq0 + CONVERT(dst1_step); - if(lid > 0 && (i+lid) <= rows) - { - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - lm_sqsum[0][bf_loc] += sqsum_t[0]; - lm_sqsum[1][bf_loc] += sqsum_t[1]; - sum_p = (__local int*)(&(lm_sum[0][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue; - sum[loc_s0 + k * dst_step / 4] = sum_p[k]; - sqsum[loc_sq0 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k]; - } - sum_p = (__local int*)(&(lm_sum[1][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k + 4 >= cols + pre_invalid) break; - sum[loc_s1 + k * dst_step / 4] = sum_p[k]; - sqsum[loc_sq1 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} - - -kernel void integral_rows_D4(__global int4 *srcsum,__global TYPE4 * srcsqsum,__global int *sum , - __global TYPE *sqsum,int rows,int cols,int src_step,int src1_step,int sum_step, - int sqsum_step,int sum_offset,int sqsum_offset) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - int4 src_t[2], sum_t[2]; - TYPE4 sqsrc_t[2],sqsum_t[2]; - __local int4 lm_sum[2][LSIZE + LOG_LSIZE]; - __local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE]; - __local int *sum_p; - __local TYPE *sqsum_p; - src_step = src_step >> 4; - src1_step = (src1_step / sizeof(TYPE)) >> 2 ; - gid <<= 1; - for(int i = 0; i < rows; i =i + LSIZE_1) - { - src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid ] : (int4)0; - sqsrc_t[0] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid ] : (TYPE4)0; - src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid + 1] : (int4)0; - sqsrc_t[1] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid + 1] : (TYPE4)0; - - sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); - sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]); - sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); - sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]); - barrier(CLK_LOCAL_MEM_FENCE); - - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); - lm_sum[0][bf_loc] = src_t[0]; - lm_sqsum[0][bf_loc] = sqsrc_t[0]; - - lm_sum[1][bf_loc] = src_t[1]; - lm_sqsum[1][bf_loc] = sqsrc_t[1]; - - int offset = 1; - for(int d = LSIZE >> 1 ; d > 0; d>>=1) - { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - } - offset <<= 1; - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for(int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - if(gid == 0 && (i + lid) <= rows) - { - sum[sum_offset + i + lid] = 0; - sqsum[sqsum_offset + i + lid] = 0; - } - if(i + lid == 0) - { - int loc0 = gid * sum_step; - int loc1 = gid * CONVERT(sqsum_step); - for(int k = 1; k <= 8; k++) - { - if(gid * 4 + k > cols) break; - sum[sum_offset + loc0 + k * sum_step / 4] = 0; - sqsum[sqsum_offset + loc1 + k * sqsum_step / sizeof(TYPE)] = 0; - } - } - int loc_s0 = sum_offset + gid * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ; - int loc_sq0 = sqsum_offset + gid * CONVERT(sqsum_step) + sqsum_step / sizeof(TYPE) + i + lid, loc_sq1 = loc_sq0 + CONVERT(sqsum_step) ; - - if(lid > 0 && (i+lid) <= rows) - { - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - lm_sqsum[0][bf_loc] += sqsum_t[0]; - lm_sqsum[1][bf_loc] += sqsum_t[1]; - sum_p = (__local int*)(&(lm_sum[0][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k >= cols) break; - sum[loc_s0 + k * sum_step / 4] = sum_p[k]; - sqsum[loc_sq0 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k]; - } - sum_p = (__local int*)(&(lm_sum[1][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + 4 + k >= cols) break; - sum[loc_s1 + k * sum_step / 4] = sum_p[k]; - sqsum[loc_sq1 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} - -kernel void integral_cols_D5(__global uchar4 *src,__global float *sum ,__global TYPE *sqsum, - int src_offset,int pre_invalid,int rows,int cols,int src_step,int dst_step, int dst1_step) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - float4 src_t[2], sum_t[2]; - TYPE4 sqsum_t[2]; - __local float4 lm_sum[2][LSIZE + LOG_LSIZE]; - __local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE]; - __local float* sum_p; - __local TYPE* sqsum_p; - src_step = src_step >> 2; - gid = gid << 1; - for(int i = 0; i < rows; i =i + LSIZE_1) - { - src_t[0] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + min(gid, cols - 1)]) : (float4)0); - src_t[1] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + min(gid + 1, cols - 1)]) : (float4)0); - - sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); - sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]); - sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); - sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]); - barrier(CLK_LOCAL_MEM_FENCE); - - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); - lm_sum[0][bf_loc] = src_t[0]; - lm_sqsum[0][bf_loc] = convert_TYPE4(src_t[0] * src_t[0]); - - lm_sum[1][bf_loc] = src_t[1]; - lm_sqsum[1][bf_loc] = convert_TYPE4(src_t[1] * src_t[1]); - - int offset = 1; - for(int d = LSIZE >> 1 ; d > 0; d>>=1) - { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - } - offset <<= 1; - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for(int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step / 4, loc_s1 = loc_s0 + dst_step ; - int loc_sq0 = gid * CONVERT(dst1_step) + i + lid - 1 - pre_invalid * dst1_step / sizeof(TYPE), loc_sq1 = loc_sq0 + CONVERT(dst1_step); - if(lid > 0 && (i+lid) <= rows) - { - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - lm_sqsum[0][bf_loc] += sqsum_t[0]; - lm_sqsum[1][bf_loc] += sqsum_t[1]; - sum_p = (__local float*)(&(lm_sum[0][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue; - sum[loc_s0 + k * dst_step / 4] = sum_p[k]; - sqsum[loc_sq0 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k]; - } - sum_p = (__local float*)(&(lm_sum[1][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k + 4 >= cols + pre_invalid) break; - sum[loc_s1 + k * dst_step / 4] = sum_p[k]; - sqsum[loc_sq1 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} - - -kernel void integral_rows_D5(__global float4 *srcsum,__global TYPE4 * srcsqsum,__global float *sum , - __global TYPE *sqsum,int rows,int cols,int src_step,int src1_step, int sum_step, - int sqsum_step,int sum_offset,int sqsum_offset) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - float4 src_t[2], sum_t[2]; - TYPE4 sqsrc_t[2],sqsum_t[2]; - __local float4 lm_sum[2][LSIZE + LOG_LSIZE]; - __local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE]; - __local float *sum_p; - __local TYPE *sqsum_p; - src_step = src_step >> 4; - src1_step = (src1_step / sizeof(TYPE)) >> 2; - for(int i = 0; i < rows; i =i + LSIZE_1) - { - src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2] : (float4)0; - sqsrc_t[0] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid * 2] : (TYPE4)0; - src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2 + 1] : (float4)0; - sqsrc_t[1] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid * 2 + 1] : (TYPE4)0; - - sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); - sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]); - sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); - sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]); - barrier(CLK_LOCAL_MEM_FENCE); - - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); - lm_sum[0][bf_loc] = src_t[0]; - lm_sqsum[0][bf_loc] = sqsrc_t[0]; - - lm_sum[1][bf_loc] = src_t[1]; - lm_sqsum[1][bf_loc] = sqsrc_t[1]; - - int offset = 1; - for(int d = LSIZE >> 1 ; d > 0; d>>=1) - { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - } - offset <<= 1; - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for(int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - - lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; - lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - if(gid == 0 && (i + lid) <= rows) - { - sum[sum_offset + i + lid] = 0; - sqsum[sqsum_offset + i + lid] = 0; - } - if(i + lid == 0) - { - int loc0 = gid * 2 * sum_step; - int loc1 = gid * 2 * CONVERT(sqsum_step); - for(int k = 1; k <= 8; k++) - { - if(gid * 8 + k > cols) break; - sum[sum_offset + loc0 + k * sum_step / 4] = 0; - sqsum[sqsum_offset + loc1 + k * sqsum_step / sizeof(TYPE)] = 0; - } - } - int loc_s0 = sum_offset + gid * 2 * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ; - int loc_sq0 = sqsum_offset + gid * 2 * CONVERT(sqsum_step) + sqsum_step / sizeof(TYPE) + i + lid, loc_sq1 = loc_sq0 + CONVERT(sqsum_step) ; - if(lid > 0 && (i+lid) <= rows) - { - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - lm_sqsum[0][bf_loc] += sqsum_t[0]; - lm_sqsum[1][bf_loc] += sqsum_t[1]; - sum_p = (__local float*)(&(lm_sum[0][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 8 + k >= cols) break; - sum[loc_s0 + k * sum_step / 4] = sum_p[k]; - sqsum[loc_sq0 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k]; - } - sum_p = (__local float*)(&(lm_sum[1][bf_loc])); - sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 8 + 4 + k >= cols) break; - sum[loc_s1 + k * sum_step / 4] = sum_p[k]; - sqsum[loc_sq1 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} diff --git a/modules/ocl/src/opencl/imgproc_integral_sum.cl b/modules/ocl/src/opencl/imgproc_integral_sum.cl deleted file mode 100644 index 662406140..000000000 --- a/modules/ocl/src/opencl/imgproc_integral_sum.cl +++ /dev/null @@ -1,412 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Shengen Yan,yanshengen@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#define LSIZE 256 -#define LSIZE_1 255 -#define LSIZE_2 254 -#define HF_LSIZE 128 -#define LOG_LSIZE 8 -#define LOG_NUM_BANKS 5 -#define NUM_BANKS 32 -#define GET_CONFLICT_OFFSET(lid) ((lid) >> LOG_NUM_BANKS) - - -kernel void integral_sum_cols_D4(__global uchar4 *src,__global int *sum , - int src_offset,int pre_invalid,int rows,int cols,int src_step,int dst_step) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - int4 src_t[2], sum_t[2]; - __local int4 lm_sum[2][LSIZE + LOG_LSIZE]; - __local int* sum_p; - src_step = src_step >> 2; - gid = gid << 1; - for(int i = 0; i < rows; i =i + LSIZE_1) - { - src_t[0] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + gid]) : 0); - src_t[1] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + gid + 1]) : 0); - - sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); - sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); - barrier(CLK_LOCAL_MEM_FENCE); - - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); - lm_sum[0][bf_loc] = src_t[0]; - - lm_sum[1][bf_loc] = src_t[1]; - - int offset = 1; - for(int d = LSIZE >> 1 ; d > 0; d>>=1) - { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - } - offset <<= 1; - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for(int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid > 0 && (i+lid) <= rows) - { - int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step / 4, loc_s1 = loc_s0 + dst_step ; - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - sum_p = (__local int*)(&(lm_sum[0][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue; - sum[loc_s0 + k * dst_step / 4] = sum_p[k]; - } - sum_p = (__local int*)(&(lm_sum[1][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k + 4 >= cols + pre_invalid) break; - sum[loc_s1 + k * dst_step / 4] = sum_p[k]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} - - -kernel void integral_sum_rows_D4(__global int4 *srcsum,__global int *sum , - int rows,int cols,int src_step,int sum_step, - int sum_offset) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - int4 src_t[2], sum_t[2]; - __local int4 lm_sum[2][LSIZE + LOG_LSIZE]; - __local int *sum_p; - src_step = src_step >> 4; - for(int i = 0; i < rows; i =i + LSIZE_1) - { - src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2] : 0; - src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2 + 1] : 0; - - sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); - sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); - barrier(CLK_LOCAL_MEM_FENCE); - - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); - lm_sum[0][bf_loc] = src_t[0]; - - lm_sum[1][bf_loc] = src_t[1]; - - int offset = 1; - for(int d = LSIZE >> 1 ; d > 0; d>>=1) - { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - } - offset <<= 1; - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for(int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - if(gid == 0 && (i + lid) <= rows) - { - sum[sum_offset + i + lid] = 0; - } - if(i + lid == 0) - { - int loc0 = gid * 2 * sum_step; - for(int k = 1; k <= 8; k++) - { - if(gid * 8 + k > cols) break; - sum[sum_offset + loc0 + k * sum_step / 4] = 0; - } - } - - if(lid > 0 && (i+lid) <= rows) - { - int loc_s0 = sum_offset + gid * 2 * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ; - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - sum_p = (__local int*)(&(lm_sum[0][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 8 + k >= cols) break; - sum[loc_s0 + k * sum_step / 4] = sum_p[k]; - } - sum_p = (__local int*)(&(lm_sum[1][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 8 + 4 + k >= cols) break; - sum[loc_s1 + k * sum_step / 4] = sum_p[k]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} - -kernel void integral_sum_cols_D5(__global uchar4 *src,__global float *sum , - int src_offset,int pre_invalid,int rows,int cols,int src_step,int dst_step) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - float4 src_t[2], sum_t[2]; - __local float4 lm_sum[2][LSIZE + LOG_LSIZE]; - __local float* sum_p; - src_step = src_step >> 2; - gid = gid << 1; - for(int i = 0; i < rows; i =i + LSIZE_1) - { - src_t[0] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + gid]) : (float4)0); - src_t[1] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + gid + 1]) : (float4)0); - - sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); - sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); - barrier(CLK_LOCAL_MEM_FENCE); - - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); - lm_sum[0][bf_loc] = src_t[0]; - - lm_sum[1][bf_loc] = src_t[1]; - - int offset = 1; - for(int d = LSIZE >> 1 ; d > 0; d>>=1) - { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - } - offset <<= 1; - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for(int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid > 0 && (i+lid) <= rows) - { - int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step / 4, loc_s1 = loc_s0 + dst_step ; - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - sum_p = (__local float*)(&(lm_sum[0][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue; - sum[loc_s0 + k * dst_step / 4] = sum_p[k]; - } - sum_p = (__local float*)(&(lm_sum[1][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 4 + k + 4 >= cols + pre_invalid) break; - sum[loc_s1 + k * dst_step / 4] = sum_p[k]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} - - -kernel void integral_sum_rows_D5(__global float4 *srcsum,__global float *sum , - int rows,int cols,int src_step,int sum_step, - int sum_offset) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - float4 src_t[2], sum_t[2]; - __local float4 lm_sum[2][LSIZE + LOG_LSIZE]; - __local float *sum_p; - src_step = src_step >> 4; - for(int i = 0; i < rows; i =i + LSIZE_1) - { - src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2] : (float4)0; - src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2 + 1] : (float4)0; - - sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); - sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); - barrier(CLK_LOCAL_MEM_FENCE); - - int bf_loc = lid + GET_CONFLICT_OFFSET(lid); - lm_sum[0][bf_loc] = src_t[0]; - - lm_sum[1][bf_loc] = src_t[1]; - - int offset = 1; - for(int d = LSIZE >> 1 ; d > 0; d>>=1) - { - barrier(CLK_LOCAL_MEM_FENCE); - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - } - offset <<= 1; - } - barrier(CLK_LOCAL_MEM_FENCE); - if(lid < 2) - { - lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; - } - for(int d = 1; d < LSIZE; d <<= 1) - { - barrier(CLK_LOCAL_MEM_FENCE); - offset >>= 1; - int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; - ai += GET_CONFLICT_OFFSET(ai); - bi += GET_CONFLICT_OFFSET(bi); - - if((lid & 127) < d) - { - lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; - lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - if(gid == 0 && (i + lid) <= rows) - { - sum[sum_offset + i + lid] = 0; - } - if(i + lid == 0) - { - int loc0 = gid * 2 * sum_step; - for(int k = 1; k <= 8; k++) - { - if(gid * 8 + k > cols) break; - sum[sum_offset + loc0 + k * sum_step / 4] = 0; - } - } - - if(lid > 0 && (i+lid) <= rows) - { - int loc_s0 = sum_offset + gid * 2 * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ; - lm_sum[0][bf_loc] += sum_t[0]; - lm_sum[1][bf_loc] += sum_t[1]; - sum_p = (__local float*)(&(lm_sum[0][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 8 + k >= cols) break; - sum[loc_s0 + k * sum_step / 4] = sum_p[k]; - } - sum_p = (__local float*)(&(lm_sum[1][bf_loc])); - for(int k = 0; k < 4; k++) - { - if(gid * 8 + 4 + k >= cols) break; - sum[loc_s1 + k * sum_step / 4] = sum_p[k]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} diff --git a/modules/ocl/src/opencl/imgproc_median.cl b/modules/ocl/src/opencl/imgproc_median.cl deleted file mode 100644 index 5fa7a17b8..000000000 --- a/modules/ocl/src/opencl/imgproc_median.cl +++ /dev/null @@ -1,486 +0,0 @@ -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Zero Lin, zero.lin@amd.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. -// -// - - -/* -__kernel void medianFilter_C1(__global uchar * src, __global uchar * dst, int srcOffset, int dstOffset, int cols, - int rows, int srcStep, int dstStep, int m) -{ - int dx = get_global_id(0)-(m>>1); - int dy = get_global_id(1)-(m>>1); - - short histom[256]; - for(int i=0;i<256;++i) - histom[i]=0; - - - for(int i=0;i>1; - int v; - for(int i=0;i<256;++i) - { - v=(now= src_cols) \ - v2.x %= src_cols; \ - \ - if (v2.y < 0) \ - v2.y -= ((v2.y - src_rows + 1) / src_rows) * src_rows; \ - if( v2.y >= src_rows ) \ - v2.y %= src_rows; \ - v = convertToWT(src[mad24(v2.y, src_step, v2.x + src_offset)]); \ - } -#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT_101) -#ifdef BORDER_REFLECT -#define DELTA int delta = 0 -#else -#define DELTA int delta = 1 -#endif -#define EXTRAPOLATE(v2, v) \ - { \ - DELTA; \ - if (src_cols == 1) \ - v2.x = 0; \ - else \ - do \ - { \ - if( v2.x < 0 ) \ - v2.x = -v2.x - 1 + delta; \ - else \ - v2.x = src_cols - 1 - (v2.x - src_cols) - delta; \ - } \ - while (v2.x >= src_cols || v2.x < 0); \ - \ - if (src_rows == 1) \ - v2.y = 0; \ - else \ - do \ - { \ - if( v2.y < 0 ) \ - v2.y = -v2.y - 1 + delta; \ - else \ - v2.y = src_rows - 1 - (v2.y - src_rows) - delta; \ - } \ - while (v2.y >= src_rows || v2.y < 0); \ - v = convertToWT(src[mad24(v2.y, src_step, v2.x + src_offset)]); \ - } -#else -#error No extrapolation method -#endif - -#define NEED_EXTRAPOLATION(gx, gy) (gx >= src_cols || gy >= src_rows || gx < 0 || gy < 0) - -#ifdef INTER_NEAREST - -__kernel void remap_2_32FC1(__global const T * restrict src, __global T * dst, - __global float * map1, __global float * map2, - int src_offset, int dst_offset, int map1_offset, int map2_offset, - int src_step, int dst_step, int map1_step, int map2_step, - int src_cols, int src_rows, int dst_cols, int dst_rows, T scalar) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < dst_cols && y < dst_rows) - { - int dstIdx = mad24(y, dst_step, x + dst_offset); - int map1Idx = mad24(y, map1_step, x + map1_offset); - int map2Idx = mad24(y, map2_step, x + map2_offset); - - int gx = convert_int_sat_rte(map1[map1Idx]); - int gy = convert_int_sat_rte(map2[map2Idx]); - - if (NEED_EXTRAPOLATION(gx, gy)) - { -#ifndef BORDER_CONSTANT - int2 gxy = (int2)(gx, gy); -#endif - EXTRAPOLATE(gxy, dst[dstIdx]); - } - else - { - int srcIdx = mad24(gy, src_step, gx + src_offset); - dst[dstIdx] = src[srcIdx]; - } - } -} - -__kernel void remap_32FC2(__global const T * restrict src, __global T * dst, __global float2 * map1, - int src_offset, int dst_offset, int map1_offset, - int src_step, int dst_step, int map1_step, - int src_cols, int src_rows, int dst_cols, int dst_rows, T scalar) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < dst_cols && y < dst_rows) - { - int dstIdx = mad24(y, dst_step, x + dst_offset); - int map1Idx = mad24(y, map1_step, x + map1_offset); - - int2 gxy = convert_int2_sat_rte(map1[map1Idx]); - int gx = gxy.x, gy = gxy.y; - - if (NEED_EXTRAPOLATION(gx, gy)) - EXTRAPOLATE(gxy, dst[dstIdx]) - else - { - int srcIdx = mad24(gy, src_step, gx + src_offset); - dst[dstIdx] = src[srcIdx]; - } - } -} - -__kernel void remap_16SC2(__global const T * restrict src, __global T * dst, __global short2 * map1, - int src_offset, int dst_offset, int map1_offset, - int src_step, int dst_step, int map1_step, - int src_cols, int src_rows, int dst_cols, int dst_rows, T scalar) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < dst_cols && y < dst_rows) - { - int dstIdx = mad24(y, dst_step, x + dst_offset); - int map1Idx = mad24(y, map1_step, x + map1_offset); - - int2 gxy = convert_int2(map1[map1Idx]); - int gx = gxy.x, gy = gxy.y; - - if (NEED_EXTRAPOLATION(gx, gy)) - EXTRAPOLATE(gxy, dst[dstIdx]) - else - { - int srcIdx = mad24(gy, src_step, gx + src_offset); - dst[dstIdx] = src[srcIdx]; - } - } -} - -__kernel void remap_16SC2_16UC1(__global const T * restrict src, __global T * dst, __global short2 * map1, __global ushort * map2, - int src_offset, int dst_offset, int map1_offset, int map2_offset, - int src_step, int dst_step, int map1_step, int map2_step, - int src_cols, int src_rows, int dst_cols, int dst_rows, T scalar) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < dst_cols && y < dst_rows) - { - int dstIdx = mad24(y, dst_step, x + dst_offset); - int map1Idx = mad24(y, map1_step, x + map1_offset); - int map2Idx = mad24(y, map2_step, x + map2_offset); - - int map2Value = convert_int(map2[map2Idx]) & (INTER_TAB_SIZE2 - 1); - int dx = (map2Value & (INTER_TAB_SIZE - 1)) < (INTER_TAB_SIZE >> 1) ? 1 : 0; - int dy = (map2Value >> INTER_BITS) < (INTER_TAB_SIZE >> 1) ? 1 : 0; - int2 gxy = convert_int2(map1[map1Idx]) + (int2)(dx, dy); - int gx = gxy.x, gy = gxy.y; - - if (NEED_EXTRAPOLATION(gx, gy)) - EXTRAPOLATE(gxy, dst[dstIdx]) - else - { - int srcIdx = mad24(gy, src_step, gx + src_offset); - dst[dstIdx] = src[srcIdx]; - } - } -} - -#elif INTER_LINEAR - -__kernel void remap_16SC2_16UC1(__global T const * restrict src, __global T * dst, - __global short2 * restrict map1, __global ushort * restrict map2, - int src_offset, int dst_offset, int map1_offset, int map2_offset, - int src_step, int dst_step, int map1_step, int map2_step, - int src_cols, int src_rows, int dst_cols, int dst_rows, T nVal) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < dst_cols && y < dst_rows) - { - int dstIdx = mad24(y, dst_step, x + dst_offset); - int map1Idx = mad24(y, map1_step, x + map1_offset); - int map2Idx = mad24(y, map2_step, x + map2_offset); - - int2 map_dataA = convert_int2(map1[map1Idx]); - int2 map_dataB = (int2)(map_dataA.x + 1, map_dataA.y); - int2 map_dataC = (int2)(map_dataA.x, map_dataA.y + 1); - int2 map_dataD = (int2)(map_dataA.x + 1, map_dataA.y + 1); - - ushort map2Value = (ushort)(map2[map2Idx] & (INTER_TAB_SIZE2 - 1)); - WT2 u = (WT2)(map2Value & (INTER_TAB_SIZE - 1), map2Value >> INTER_BITS) / (WT2)(INTER_TAB_SIZE); - - WT scalar = convertToWT(nVal); - WT a = scalar, b = scalar, c = scalar, d = scalar; - - if (!NEED_EXTRAPOLATION(map_dataA.x, map_dataA.y)) - a = convertToWT(src[mad24(map_dataA.y, src_step, map_dataA.x + src_offset)]); - else - EXTRAPOLATE(map_dataA, a); - - if (!NEED_EXTRAPOLATION(map_dataB.x, map_dataB.y)) - b = convertToWT(src[mad24(map_dataB.y, src_step, map_dataB.x + src_offset)]); - else - EXTRAPOLATE(map_dataB, b); - - if (!NEED_EXTRAPOLATION(map_dataC.x, map_dataC.y)) - c = convertToWT(src[mad24(map_dataC.y, src_step, map_dataC.x + src_offset)]); - else - EXTRAPOLATE(map_dataC, c); - - if (!NEED_EXTRAPOLATION(map_dataD.x, map_dataD.y)) - d = convertToWT(src[mad24(map_dataD.y, src_step, map_dataD.x + src_offset)]); - else - EXTRAPOLATE(map_dataD, d); - - WT dst_data = a * (1 - u.x) * (1 - u.y) + - b * (u.x) * (1 - u.y) + - c * (1 - u.x) * (u.y) + - d * (u.x) * (u.y); - dst[dstIdx] = convertToT(dst_data); - } -} - -__kernel void remap_2_32FC1(__global T const * restrict src, __global T * dst, - __global float * map1, __global float * map2, - int src_offset, int dst_offset, int map1_offset, int map2_offset, - int src_step, int dst_step, int map1_step, int map2_step, - int src_cols, int src_rows, int dst_cols, int dst_rows, T nVal) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < dst_cols && y < dst_rows) - { - int dstIdx = mad24(y, dst_step, x + dst_offset); - int map1Idx = mad24(y, map1_step, x + map1_offset); - int map2Idx = mad24(y, map2_step, x + map2_offset); - - float2 map_data = (float2)(map1[map1Idx], map2[map2Idx]); - - int2 map_dataA = convert_int2_sat_rtn(map_data); - int2 map_dataB = (int2)(map_dataA.x + 1, map_dataA.y); - int2 map_dataC = (int2)(map_dataA.x, map_dataA.y + 1); - int2 map_dataD = (int2)(map_dataA.x + 1, map_dataA.y + 1); - - float2 _u = map_data - convert_float2(map_dataA); - WT2 u = convertToWT2(convert_int2_rte(convertToWT2(_u) * (WT2)INTER_TAB_SIZE)) / (WT2)INTER_TAB_SIZE; - WT scalar = convertToWT(nVal); - WT a = scalar, b = scalar, c = scalar, d = scalar; - - if (!NEED_EXTRAPOLATION(map_dataA.x, map_dataA.y)) - a = convertToWT(src[mad24(map_dataA.y, src_step, map_dataA.x + src_offset)]); - else - EXTRAPOLATE(map_dataA, a); - - if (!NEED_EXTRAPOLATION(map_dataB.x, map_dataB.y)) - b = convertToWT(src[mad24(map_dataB.y, src_step, map_dataB.x + src_offset)]); - else - EXTRAPOLATE(map_dataB, b); - - if (!NEED_EXTRAPOLATION(map_dataC.x, map_dataC.y)) - c = convertToWT(src[mad24(map_dataC.y, src_step, map_dataC.x + src_offset)]); - else - EXTRAPOLATE(map_dataC, c); - - if (!NEED_EXTRAPOLATION(map_dataD.x, map_dataD.y)) - d = convertToWT(src[mad24(map_dataD.y, src_step, map_dataD.x + src_offset)]); - else - EXTRAPOLATE(map_dataD, d); - - WT dst_data = a * (1 - u.x) * (1 - u.y) + - b * (u.x) * (1 - u.y) + - c * (1 - u.x) * (u.y) + - d * (u.x) * (u.y); - dst[dstIdx] = convertToT(dst_data); - } -} - -__kernel void remap_32FC2(__global T const * restrict src, __global T * dst, - __global float2 * map1, - int src_offset, int dst_offset, int map1_offset, - int src_step, int dst_step, int map1_step, - int src_cols, int src_rows, int dst_cols, int dst_rows, T nVal) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < dst_cols && y < dst_rows) - { - int dstIdx = mad24(y, dst_step, x + dst_offset); - int map1Idx = mad24(y, map1_step, x + map1_offset); - - float2 map_data = map1[map1Idx]; - int2 map_dataA = convert_int2_sat_rtn(map_data); - int2 map_dataB = (int2)(map_dataA.x + 1, map_dataA.y); - int2 map_dataC = (int2)(map_dataA.x, map_dataA.y + 1); - int2 map_dataD = (int2)(map_dataA.x + 1, map_dataA.y + 1); - - float2 _u = map_data - convert_float2(map_dataA); - WT2 u = convertToWT2(convert_int2_rte(convertToWT2(_u) * (WT2)INTER_TAB_SIZE)) / (WT2)INTER_TAB_SIZE; - WT scalar = convertToWT(nVal); - WT a = scalar, b = scalar, c = scalar, d = scalar; - - if (!NEED_EXTRAPOLATION(map_dataA.x, map_dataA.y)) - a = convertToWT(src[mad24(map_dataA.y, src_step, map_dataA.x + src_offset)]); - else - EXTRAPOLATE(map_dataA, a); - - if (!NEED_EXTRAPOLATION(map_dataB.x, map_dataB.y)) - b = convertToWT(src[mad24(map_dataB.y, src_step, map_dataB.x + src_offset)]); - else - EXTRAPOLATE(map_dataB, b); - - if (!NEED_EXTRAPOLATION(map_dataC.x, map_dataC.y)) - c = convertToWT(src[mad24(map_dataC.y, src_step, map_dataC.x + src_offset)]); - else - EXTRAPOLATE(map_dataC, c); - - if (!NEED_EXTRAPOLATION(map_dataD.x, map_dataD.y)) - d = convertToWT(src[mad24(map_dataD.y, src_step, map_dataD.x + src_offset)]); - else - EXTRAPOLATE(map_dataD, d); - - WT dst_data = a * (1 - u.x) * (1 - u.y) + - b * (u.x) * (1 - u.y) + - c * (1 - u.x) * (u.y) + - d * (u.x) * (u.y); - dst[dstIdx] = convertToT(dst_data); - } -} - -#endif diff --git a/modules/ocl/src/opencl/imgproc_resize.cl b/modules/ocl/src/opencl/imgproc_resize.cl deleted file mode 100644 index ebf8c712b..000000000 --- a/modules/ocl/src/opencl/imgproc_resize.cl +++ /dev/null @@ -1,405 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Zhang Ying, zhangying913@gmail.com -// Niko Li, newlife20080214@gmail.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*/ - - -// resize kernel -// Currently, CV_8UC1, CV_8UC4, CV_32FC1 and CV_32FC4 are supported. -// We shall support other types later if necessary. - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#define INTER_RESIZE_COEF_BITS 11 -#define INTER_RESIZE_COEF_SCALE (1 << INTER_RESIZE_COEF_BITS) -#define CAST_BITS (INTER_RESIZE_COEF_BITS << 1) -#define CAST_SCALE (1.0f/(1<= (l) ? (x):((x)+1)) - -#ifdef LN - -__kernel void resizeLN_C1_D0(__global uchar * dst, __global uchar const * restrict src, - int dst_offset, int src_offset,int dst_step, int src_step, - int src_cols, int src_rows, int dst_cols, int dst_rows, float ifx, float ify ) -{ - int gx = get_global_id(0); - int dy = get_global_id(1); - - float4 sx, u, xf; - int4 x, DX; - gx = (gx<<2) - (dst_offset&3); - DX = (int4)(gx, gx+1, gx+2, gx+3); - sx = (convert_float4(DX) + 0.5f) * ifx - 0.5f; - xf = floor(sx); - x = convert_int4(xf); - u = sx - xf; - float sy = ((dy+0.5f) * ify - 0.5f); - int y = floor(sy); - float v = sy - y; - - u = x < 0 ? 0 : u; - u = (x >= src_cols) ? 0 : u; - x = x < 0 ? 0 : x; - x = (x >= src_cols) ? src_cols-1 : x; - - y<0 ? y=0,v=0 : y; - y>=src_rows ? y=src_rows-1,v=0 : y; - - int4 U, U1; - int V, V1; - float4 utmp1, utmp2; - float vtmp; - float4 scale_vec = INTER_RESIZE_COEF_SCALE; - utmp1 = u * scale_vec; - utmp2 = scale_vec - utmp1; - U = convert_int4(rint(utmp1)); - U1 = convert_int4(rint(utmp2)); - vtmp = v * INTER_RESIZE_COEF_SCALE; - V = rint(vtmp); - V1= rint(INTER_RESIZE_COEF_SCALE - vtmp); - - int y_ = INC(y,src_rows); - int4 x_; - x_ = ((x+1 >= src_cols) != 0) ? x : x+1; - - int4 val1, val2, val; - int4 sdata1, sdata2, sdata3, sdata4; - - int4 pos1 = mad24((int4)y, (int4)src_step, x+(int4)src_offset); - int4 pos2 = mad24((int4)y, (int4)src_step, x_+(int4)src_offset); - int4 pos3 = mad24((int4)y_, (int4)src_step, x+(int4)src_offset); - int4 pos4 = mad24((int4)y_, (int4)src_step, x_+(int4)src_offset); - - sdata1.s0 = src[pos1.s0]; - sdata1.s1 = src[pos1.s1]; - sdata1.s2 = src[pos1.s2]; - sdata1.s3 = src[pos1.s3]; - - sdata2.s0 = src[pos2.s0]; - sdata2.s1 = src[pos2.s1]; - sdata2.s2 = src[pos2.s2]; - sdata2.s3 = src[pos2.s3]; - - sdata3.s0 = src[pos3.s0]; - sdata3.s1 = src[pos3.s1]; - sdata3.s2 = src[pos3.s2]; - sdata3.s3 = src[pos3.s3]; - - sdata4.s0 = src[pos4.s0]; - sdata4.s1 = src[pos4.s1]; - sdata4.s2 = src[pos4.s2]; - sdata4.s3 = src[pos4.s3]; - - val1 = mul24(U1 , sdata1) + mul24(U , sdata2); - val2 = mul24(U1 , sdata3) + mul24(U , sdata4); - val = mul24((int4)V1 , val1) + mul24((int4)V , val2); - - val = ((val + (1<<(CAST_BITS-1))) >> CAST_BITS); - - pos4 = mad24(dy, dst_step, gx+dst_offset); - pos4.y++; - pos4.z+=2; - pos4.w+=3; - uchar4 uval = convert_uchar4_sat(val); - int con = (gx >= 0 && gx+3 < dst_cols && dy >= 0 && dy < dst_rows && (dst_offset&3)==0); - if(con) - { - *(__global uchar4*)(dst + pos4.x)=uval; - } - else - { - if(gx >= 0 && gx < dst_cols && dy >= 0 && dy < dst_rows) - { - dst[pos4.x]=uval.x; - } - if(gx+1 >= 0 && gx+1 < dst_cols && dy >= 0 && dy < dst_rows) - { - dst[pos4.y]=uval.y; - } - if(gx+2 >= 0 && gx+2 < dst_cols && dy >= 0 && dy < dst_rows) - { - dst[pos4.z]=uval.z; - } - if(gx+3 >= 0 && gx+3 < dst_cols && dy >= 0 && dy < dst_rows) - { - dst[pos4.w]=uval.w; - } - } -} - -__kernel void resizeLN_C4_D0(__global uchar4 * dst, __global uchar4 * src, - int dst_offset, int src_offset,int dst_step, int src_step, - int src_cols, int src_rows, int dst_cols, int dst_rows, float ifx, float ify ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - float sx = ((dx+0.5f) * ifx - 0.5f), sy = ((dy+0.5f) * ify - 0.5f); - int x = floor(sx), y = floor(sy); - float u = sx - x, v = sy - y; - - if ( x<0 ) x=0,u=0; - if ( x>=src_cols ) x=src_cols-1,u=0; - if ( y<0 ) y=0,v=0; - if (y>=src_rows ) y=src_rows-1,v=0; - - u = u * INTER_RESIZE_COEF_SCALE; - v = v * INTER_RESIZE_COEF_SCALE; - - int U = rint(u); - int V = rint(v); - int U1= rint(INTER_RESIZE_COEF_SCALE - u); - int V1= rint(INTER_RESIZE_COEF_SCALE - v); - - int y_ = INC(y,src_rows); - int x_ = INC(x,src_cols); - int4 srcpos; - srcpos.x = mad24(y, src_step, x+src_offset); - srcpos.y = mad24(y, src_step, x_+src_offset); - srcpos.z = mad24(y_, src_step, x+src_offset); - srcpos.w = mad24(y_, src_step, x_+src_offset); - int4 data0 = convert_int4(src[srcpos.x]); - int4 data1 = convert_int4(src[srcpos.y]); - int4 data2 = convert_int4(src[srcpos.z]); - int4 data3 = convert_int4(src[srcpos.w]); - int4 val = mul24((int4)mul24(U1, V1) , data0) + mul24((int4)mul24(U, V1) , data1) - +mul24((int4)mul24(U1, V) , data2)+mul24((int4)mul24(U, V) , data3); - int dstpos = mad24(dy, dst_step, dx+dst_offset); - uchar4 uval = convert_uchar4((val + (1<<(CAST_BITS-1)))>>CAST_BITS); - if(dx>=0 && dx=0 && dy=src_cols ) x=src_cols-1,u=0; - if ( y<0 ) y=0,v=0; - if (y>=src_rows ) y=src_rows-1,v=0; - - int y_ = INC(y,src_rows); - int x_ = INC(x,src_cols); - float u1 = 1.f-u; - float v1 = 1.f-v; - int4 srcpos; - srcpos.x = mad24(y, src_step, x+src_offset); - srcpos.y = mad24(y, src_step, x_+src_offset); - srcpos.z = mad24(y_, src_step, x+src_offset); - srcpos.w = mad24(y_, src_step, x_+src_offset); - float data0 = src[srcpos.x]; - float data1 = src[srcpos.y]; - float data2 = src[srcpos.z]; - float data3 = src[srcpos.w]; - float val1 = u1 * data0 + - u * data1 ; - float val2 = u1 * data2 + - u * data3; - float val = v1 * val1 + v * val2; - int dstpos = mad24(dy, dst_step, dx+dst_offset); - if(dx>=0 && dx=0 && dy=src_cols ) x=src_cols-1,u=0; - if ( y<0 ) y=0,v=0; - if (y>=src_rows ) y=src_rows-1,v=0; - - int y_ = INC(y,src_rows); - int x_ = INC(x,src_cols); - float u1 = 1.f-u; - float v1 = 1.f-v; - int4 srcpos; - srcpos.x = mad24(y, src_step, x+src_offset); - srcpos.y = mad24(y, src_step, x_+src_offset); - srcpos.z = mad24(y_, src_step, x+src_offset); - srcpos.w = mad24(y_, src_step, x_+src_offset); - float4 s_data1, s_data2, s_data3, s_data4; - s_data1 = src[srcpos.x]; - s_data2 = src[srcpos.y]; - s_data3 = src[srcpos.z]; - s_data4 = src[srcpos.w]; - float4 val = u1 * v1 * s_data1 + u * v1 * s_data2 - +u1 * v *s_data3 + u * v *s_data4; - int dstpos = mad24(dy, dst_step, dx+dst_offset); - - if(dx>=0 && dx=0 && dy= (r_edge) | (_y)<0 | (_y) >= (t_edge) ? (const_v) : SRC((_x),(_y)) -#else -#define ELEM(_x,_y,r_edge,t_edge,const_v) SRC((_x),(_y)) -#endif - -#define DSTX(_x,_y) (((global float*)(DstX+DstXOffset+(_y)*DstXPitch))[_x]) -#define DSTY(_x,_y) (((global float*)(DstY+DstYOffset+(_y)*DstYPitch))[_x]) - -#define INIT_AND_READ_LOCAL_SOURCE(width, height, fill_const, kernel_border) \ - int srcX = x + srcOffsetX - (kernel_border); \ - int srcY = y + srcOffsetY - (kernel_border); \ - int xb = srcX; \ - int yb = srcY; \ - \ - EXTRAPOLATE(xb, (width)); \ - EXTRAPOLATE(yb, (height)); \ - lsmem[liy][lix] = ELEM(xb, yb, (width), (height), (fill_const) ); \ - \ - if(lix < ((kernel_border)*2)) \ - { \ - int xb = srcX+BLK_X; \ - EXTRAPOLATE(xb,(width)); \ - lsmem[liy][lix+BLK_X] = ELEM(xb, yb, (width), (height), (fill_const) ); \ - } \ - if(liy< ((kernel_border)*2)) \ - { \ - int yb = srcY+BLK_Y; \ - EXTRAPOLATE(yb, (height)); \ - lsmem[liy+BLK_Y][lix] = ELEM(xb, yb, (width), (height), (fill_const) ); \ - } \ - if(lix<((kernel_border)*2) && liy<((kernel_border)*2)) \ - { \ - int xb = srcX+BLK_X; \ - int yb = srcY+BLK_Y; \ - EXTRAPOLATE(xb,(width)); \ - EXTRAPOLATE(yb,(height)); \ - lsmem[liy+BLK_Y][lix+BLK_X] = ELEM(xb, yb, (width), (height), (fill_const) ); \ - } - -__kernel void sobel3( - __global uchar* Src, - const uint SrcPitch, - const int srcOffsetX, - const int srcOffsetY, - __global uchar* DstX, - const int DstXOffset, - const uint DstXPitch, - __global uchar* DstY, - const int DstYOffset, - const uint DstYPitch, - int width, - int height, - int dstWidth, - int dstHeight, - float scale - ) -{ - __local float lsmem[BLK_Y+2][BLK_X+2]; - - int lix = get_local_id(0); - int liy = get_local_id(1); - - int x = (int)get_global_id(0); - int y = (int)get_global_id(1); - - INIT_AND_READ_LOCAL_SOURCE(width, height, 0, 1) - barrier(CLK_LOCAL_MEM_FENCE); - - if( x >= dstWidth || y >=dstHeight ) return; - - float u1 = lsmem[liy][lix]; - float u2 = lsmem[liy][lix+1]; - float u3 = lsmem[liy][lix+2]; - - float m1 = lsmem[liy+1][lix]; - float m3 = lsmem[liy+1][lix+2]; - - float b1 = lsmem[liy+2][lix]; - float b2 = lsmem[liy+2][lix+1]; - float b3 = lsmem[liy+2][lix+2]; - - //calc and store dx and dy;// -#ifdef SCHARR - DSTX(x,y) = mad(10.0f, m3 - m1, 3.0f * (u3 - u1 + b3 - b1)) * scale; - DSTY(x,y) = mad(10.0f, b2 - u2, 3.0f * (b1 - u1 + b3 - u3)) * scale; -#else - DSTX(x,y) = mad(2.0f, m3 - m1, u3 - u1 + b3 - b1) * scale; - DSTY(x,y) = mad(2.0f, b2 - u2, b1 - u1 + b3 - u3) * scale; -#endif -} - -__kernel void sobel5( - __global uchar* Src, - const uint SrcPitch, - const int srcOffsetX, - const int srcOffsetY, - __global uchar* DstX, - const int DstXOffset, - const uint DstXPitch, - __global uchar* DstY, - const int DstYOffset, - const uint DstYPitch, - int width, - int height, - int dstWidth, - int dstHeight, - float scale - ) -{ - __local float lsmem[BLK_Y+4][BLK_X+4]; - - int lix = get_local_id(0); - int liy = get_local_id(1); - - int x = (int)get_global_id(0); - int y = (int)get_global_id(1); - - INIT_AND_READ_LOCAL_SOURCE(width, height, 0, 2) - barrier(CLK_LOCAL_MEM_FENCE); - - if( x >= dstWidth || y >=dstHeight ) return; - - float t1 = lsmem[liy][lix]; - float t2 = lsmem[liy][lix+1]; - float t3 = lsmem[liy][lix+2]; - float t4 = lsmem[liy][lix+3]; - float t5 = lsmem[liy][lix+4]; - - float u1 = lsmem[liy+1][lix]; - float u2 = lsmem[liy+1][lix+1]; - float u3 = lsmem[liy+1][lix+2]; - float u4 = lsmem[liy+1][lix+3]; - float u5 = lsmem[liy+1][lix+4]; - - float m1 = lsmem[liy+2][lix]; - float m2 = lsmem[liy+2][lix+1]; - float m4 = lsmem[liy+2][lix+3]; - float m5 = lsmem[liy+2][lix+4]; - - float l1 = lsmem[liy+3][lix]; - float l2 = lsmem[liy+3][lix+1]; - float l3 = lsmem[liy+3][lix+2]; - float l4 = lsmem[liy+3][lix+3]; - float l5 = lsmem[liy+3][lix+4]; - - float b1 = lsmem[liy+4][lix]; - float b2 = lsmem[liy+4][lix+1]; - float b3 = lsmem[liy+4][lix+2]; - float b4 = lsmem[liy+4][lix+3]; - float b5 = lsmem[liy+4][lix+4]; - - //calc and store dx and dy;// - DSTX(x,y) = scale * - mad(12.0f, m4 - m2, - mad(6.0f, m5 - m1, - mad(8.0f, u4 - u2 + l4 - l2, - mad(4.0f, u5 - u1 + l5 - l1, - mad(2.0f, t4 - t2 + b4 - b2, t5 - t1 + b5 - b1 ) - ) - ) - ) - ); - - DSTY(x,y) = scale * - mad(12.0f, l3 - u3, - mad(6.0f, b3 - t3, - mad(8.0f, l2 - u2 + l4 - u4, - mad(4.0f, b2 - t2 + b4 - t4, - mad(2.0f, l1 - u1 + l5 - u5, b1 - t1 + b5 - t5 ) - ) - ) - ) - ); -} - -__kernel void sobel7( - __global uchar* Src, - const uint SrcPitch, - const int srcOffsetX, - const int srcOffsetY, - __global uchar* DstX, - const int DstXOffset, - const uint DstXPitch, - __global uchar* DstY, - const int DstYOffset, - const uint DstYPitch, - int width, - int height, - int dstWidth, - int dstHeight, - float scale - ) -{ - __local float lsmem[BLK_Y+6][BLK_X+6]; - - int lix = get_local_id(0); - int liy = get_local_id(1); - - int x = (int)get_global_id(0); - int y = (int)get_global_id(1); - - INIT_AND_READ_LOCAL_SOURCE(width, height, 0, 3) - barrier(CLK_LOCAL_MEM_FENCE); - - if( x >= dstWidth || y >=dstHeight ) return; - - float tt1 = lsmem[liy][lix]; - float tt2 = lsmem[liy][lix+1]; - float tt3 = lsmem[liy][lix+2]; - float tt4 = lsmem[liy][lix+3]; - float tt5 = lsmem[liy][lix+4]; - float tt6 = lsmem[liy][lix+5]; - float tt7 = lsmem[liy][lix+6]; - - float t1 = lsmem[liy+1][lix]; - float t2 = lsmem[liy+1][lix+1]; - float t3 = lsmem[liy+1][lix+2]; - float t4 = lsmem[liy+1][lix+3]; - float t5 = lsmem[liy+1][lix+4]; - float t6 = lsmem[liy+1][lix+5]; - float t7 = lsmem[liy+1][lix+6]; - - float u1 = lsmem[liy+2][lix]; - float u2 = lsmem[liy+2][lix+1]; - float u3 = lsmem[liy+2][lix+2]; - float u4 = lsmem[liy+2][lix+3]; - float u5 = lsmem[liy+2][lix+4]; - float u6 = lsmem[liy+2][lix+5]; - float u7 = lsmem[liy+2][lix+6]; - - float m1 = lsmem[liy+3][lix]; - float m2 = lsmem[liy+3][lix+1]; - float m3 = lsmem[liy+3][lix+2]; - float m5 = lsmem[liy+3][lix+4]; - float m6 = lsmem[liy+3][lix+5]; - float m7 = lsmem[liy+3][lix+6]; - - float l1 = lsmem[liy+4][lix]; - float l2 = lsmem[liy+4][lix+1]; - float l3 = lsmem[liy+4][lix+2]; - float l4 = lsmem[liy+4][lix+3]; - float l5 = lsmem[liy+4][lix+4]; - float l6 = lsmem[liy+4][lix+5]; - float l7 = lsmem[liy+4][lix+6]; - - float b1 = lsmem[liy+5][lix]; - float b2 = lsmem[liy+5][lix+1]; - float b3 = lsmem[liy+5][lix+2]; - float b4 = lsmem[liy+5][lix+3]; - float b5 = lsmem[liy+5][lix+4]; - float b6 = lsmem[liy+5][lix+5]; - float b7 = lsmem[liy+5][lix+6]; - - float bb1 = lsmem[liy+6][lix]; - float bb2 = lsmem[liy+6][lix+1]; - float bb3 = lsmem[liy+6][lix+2]; - float bb4 = lsmem[liy+6][lix+3]; - float bb5 = lsmem[liy+6][lix+4]; - float bb6 = lsmem[liy+6][lix+5]; - float bb7 = lsmem[liy+6][lix+6]; - - //calc and store dx and dy - DSTX(x,y) = scale * - mad(100.0f, m5 - m3, - mad(80.0f, m6 - m2, - mad(20.0f, m7 - m1, - mad(75.0f, u5 - u3 + l5 - l3, - mad(60.0f, u6 - u2 + l6 - l2, - mad(15.0f, u7 - u1 + l7 - l1, - mad(30.0f, t5 - t3 + b5 - b3, - mad(24.0f, t6 - t2 + b6 - b2, - mad(6.0f, t7 - t1 + b7 - b1, - mad(5.0f, tt5 - tt3 + bb5 - bb3, - mad(4.0f, tt6 - tt2 + bb6 - bb2, tt7 - tt1 + bb7 - bb1 ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ); - - DSTY(x,y) = scale * - mad(100.0f, l4 - u4, - mad(80.0f, b4 - t4, - mad(20.0f, bb4 - tt4, - mad(75.0f, l5 - u5 + l3 - u3, - mad(60.0f, b5 - t5 + b3 - t3, - mad(15.0f, bb5 - tt5 + bb3 - tt3, - mad(30.0f, l6 - u6 + l2 - u2, - mad(24.0f, b6 - t6 + b2 - t2, - mad(6.0f, bb6 - tt6 + bb2 - tt2, - mad(5.0f, l7 - u7 + l1 - u1, - mad(4.0f, b7 - t7 + b1 - t1, bb7 - tt7 + bb1 - tt1 ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ); -} diff --git a/modules/ocl/src/opencl/imgproc_threshold.cl b/modules/ocl/src/opencl/imgproc_threshold.cl deleted file mode 100644 index 85631be36..000000000 --- a/modules/ocl/src/opencl/imgproc_threshold.cl +++ /dev/null @@ -1,136 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Zhang Ying, zhangying913@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#ifdef VECTORIZED - -__kernel void threshold(__global const T * restrict src, int src_offset, int src_step, - __global T * dst, int dst_offset, int dst_step, - T thresh, T max_val, int max_index, int rows, int cols) -{ - int gx = get_global_id(0); - int gy = get_global_id(1); - - if (gx < cols && gy < rows) - { - gx *= VECSIZE; - int src_index = mad24(gy, src_step, src_offset + gx); - int dst_index = mad24(gy, dst_step, dst_offset + gx); - -#ifdef SRC_ALIGNED - VT sdata = *((__global VT *)(src + src_index)); -#else - VT sdata = VLOADN(0, src + src_index); -#endif - VT vthresh = (VT)(thresh); - -#ifdef THRESH_BINARY - VT vecValue = sdata > vthresh ? (VT)max_val : (VT)(0); -#elif defined THRESH_BINARY_INV - VT vecValue = sdata > vthresh ? (VT)(0) : (VT)max_val; -#elif defined THRESH_TRUNC - VT vecValue = sdata > vthresh ? (VT)thresh : sdata; -#elif defined THRESH_TOZERO - VT vecValue = sdata > vthresh ? sdata : (VT)(0); -#elif defined THRESH_TOZERO_INV - VT vecValue = sdata > vthresh ? (VT)(0) : sdata; -#endif - - if (gx + VECSIZE <= max_index) -#ifdef DST_ALIGNED - *(__global VT*)(dst + dst_index) = vecValue; -#else - VSTOREN(vecValue, 0, dst + dst_index); -#endif - else - { - __attribute__(( aligned(sizeof(VT)) )) T array[VECSIZE]; - *((VT*)array) = vecValue; - #pragma unroll - for (int i = 0; i < VECSIZE; ++i) - if (gx + i < max_index) - dst[dst_index + i] = array[i]; - } - } -} - -#else - -__kernel void threshold(__global const T * restrict src, int src_offset, int src_step, - __global T * dst, int dst_offset, int dst_step, - T thresh, T max_val, int rows, int cols) -{ - int gx = get_global_id(0); - int gy = get_global_id(1); - - if (gx < cols && gy < rows) - { - int src_index = mad24(gy, src_step, src_offset + gx); - int dst_index = mad24(gy, dst_step, dst_offset + gx); - - T sdata = src[src_index]; - -#ifdef THRESH_BINARY - dst[dst_index] = sdata > thresh ? max_val : (T)(0); -#elif defined THRESH_BINARY_INV - dst[dst_index] = sdata > thresh ? (T)(0) : max_val; -#elif defined THRESH_TRUNC - dst[dst_index] = sdata > thresh ? thresh : sdata; -#elif defined THRESH_TOZERO - dst[dst_index] = sdata > thresh ? sdata : (T)(0); -#elif defined THRESH_TOZERO_INV - dst[dst_index] = sdata > thresh ? (T)(0) : sdata; -#endif - } -} - -#endif diff --git a/modules/ocl/src/opencl/imgproc_warpAffine.cl b/modules/ocl/src/opencl/imgproc_warpAffine.cl deleted file mode 100644 index 27f99e005..000000000 --- a/modules/ocl/src/opencl/imgproc_warpAffine.cl +++ /dev/null @@ -1,761 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Zhang Ying, zhangying913@gmail.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*/ - - -//warpAffine kernel -//support data types: CV_8UC1, CV_8UC4, CV_32FC1, CV_32FC4, and three interpolation methods: NN, Linear, Cubic. - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -typedef double F; -typedef double4 F4; -#define convert_F4 convert_double4 -#else -typedef float F; -typedef float4 F4; -#define convert_F4 convert_float4 -#endif - -#define INTER_BITS 5 -#define INTER_TAB_SIZE (1 << INTER_BITS) -#define INTER_SCALE 1.f/INTER_TAB_SIZE -#define AB_BITS max(10, (int)INTER_BITS) -#define AB_SCALE (1 << AB_BITS) -#define INTER_REMAP_COEF_BITS 15 -#define INTER_REMAP_COEF_SCALE (1 << INTER_REMAP_COEF_BITS) - -inline void interpolateCubic( float x, float* coeffs ) -{ - const float A = -0.75f; - - coeffs[0] = ((A*(x + 1.f) - 5.0f*A)*(x + 1.f) + 8.0f*A)*(x + 1.f) - 4.0f*A; - coeffs[1] = ((A + 2.f)*x - (A + 3.f))*x*x + 1.f; - coeffs[2] = ((A + 2.f)*(1.f - x) - (A + 3.f))*(1.f - x)*(1.f - x) + 1.f; - coeffs[3] = 1.f - coeffs[0] - coeffs[1] - coeffs[2]; -} - - -/**********************************************8UC1********************************************* -***********************************************************************************************/ -__kernel void warpAffineNN_C1_D0(__global uchar const * restrict src, __global uchar * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - dx = (dx<<2) - (dst_offset&3); - - int round_delta = (AB_SCALE>>1); - - int4 X, Y; - int4 sx, sy; - int4 DX = (int4)(dx, dx+1, dx+2, dx+3); - DX = (DX << AB_BITS); - F4 M0DX, M3DX; - M0DX = M[0] * convert_F4(DX); - M3DX = M[3] * convert_F4(DX); - X = convert_int4(rint(M0DX)); - Y = convert_int4(rint(M3DX)); - int tmp1, tmp2; - tmp1 = rint((M[1]*dy + M[2]) * AB_SCALE); - tmp2 = rint((M[4]*dy + M[5]) * AB_SCALE); - - X += tmp1 + round_delta; - Y += tmp2 + round_delta; - - sx = convert_int4(convert_short4(X >> AB_BITS)); - sy = convert_int4(convert_short4(Y >> AB_BITS)); - - __global uchar4 * d = (__global uchar4 *)(dst+dst_offset+dy*dstStep+dx); - uchar4 dval = *d; - DX = (int4)(dx, dx+1, dx+2, dx+3); - int4 dcon = DX >= 0 && DX < dst_cols && dy >= 0 && dy < dst_rows; - int4 scon = sx >= 0 && sx < src_cols && sy >= 0 && sy < src_rows; - int4 spos = src_offset + sy * srcStep + sx; - uchar4 sval; - sval.s0 = scon.s0 ? src[spos.s0] : 0; - sval.s1 = scon.s1 ? src[spos.s1] : 0; - sval.s2 = scon.s2 ? src[spos.s2] : 0; - sval.s3 = scon.s3 ? src[spos.s3] : 0; - dval = convert_uchar4(dcon) != (uchar4)(0,0,0,0) ? sval : dval; - *d = dval; - } -} - -__kernel void warpAffineLinear_C1_D0(__global const uchar * restrict src, __global uchar * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - - if( dx < threadCols && dy < dst_rows) - { - dx = (dx<<2) - (dst_offset&3); - - int round_delta = ((AB_SCALE >> INTER_BITS) >> 1); - - int4 X, Y; - short4 ax, ay; - int4 sx, sy; - int4 DX = (int4)(dx, dx+1, dx+2, dx+3); - DX = (DX << AB_BITS); - F4 M0DX, M3DX; - M0DX = M[0] * convert_F4(DX); - M3DX = M[3] * convert_F4(DX); - X = convert_int4(rint(M0DX)); - Y = convert_int4(rint(M3DX)); - - int tmp1, tmp2; - tmp1 = rint((M[1]*dy + M[2]) * AB_SCALE); - tmp2 = rint((M[4]*dy + M[5]) * AB_SCALE); - - X += tmp1 + round_delta; - Y += tmp2 + round_delta; - - X = X >> (AB_BITS - INTER_BITS); - Y = Y >> (AB_BITS - INTER_BITS); - - sx = convert_int4(convert_short4(X >> INTER_BITS)); - sy = convert_int4(convert_short4(Y >> INTER_BITS)); - ax = convert_short4(X & (INTER_TAB_SIZE-1)); - ay = convert_short4(Y & (INTER_TAB_SIZE-1)); - - uchar4 v0, v1, v2,v3; - int4 scon0, scon1, scon2, scon3; - int4 spos0, spos1, spos2, spos3; - - scon0 = (sx >= 0 && sx < src_cols && sy >= 0 && sy < src_rows); - scon1 = (sx+1 >= 0 && sx+1 < src_cols && sy >= 0 && sy < src_rows); - scon2 = (sx >= 0 && sx < src_cols && sy+1 >= 0 && sy+1 < src_rows); - scon3 = (sx+1 >= 0 && sx+1 < src_cols && sy+1 >= 0 && sy+1 < src_rows); - spos0 = src_offset + sy * srcStep + sx; - spos1 = src_offset + sy * srcStep + sx + 1; - spos2 = src_offset + (sy+1) * srcStep + sx; - spos3 = src_offset + (sy+1) * srcStep + sx + 1; - - v0.s0 = scon0.s0 ? src[spos0.s0] : 0; - v1.s0 = scon1.s0 ? src[spos1.s0] : 0; - v2.s0 = scon2.s0 ? src[spos2.s0] : 0; - v3.s0 = scon3.s0 ? src[spos3.s0] : 0; - - v0.s1 = scon0.s1 ? src[spos0.s1] : 0; - v1.s1 = scon1.s1 ? src[spos1.s1] : 0; - v2.s1 = scon2.s1 ? src[spos2.s1] : 0; - v3.s1 = scon3.s1 ? src[spos3.s1] : 0; - - v0.s2 = scon0.s2 ? src[spos0.s2] : 0; - v1.s2 = scon1.s2 ? src[spos1.s2] : 0; - v2.s2 = scon2.s2 ? src[spos2.s2] : 0; - v3.s2 = scon3.s2 ? src[spos3.s2] : 0; - - v0.s3 = scon0.s3 ? src[spos0.s3] : 0; - v1.s3 = scon1.s3 ? src[spos1.s3] : 0; - v2.s3 = scon2.s3 ? src[spos2.s3] : 0; - v3.s3 = scon3.s3 ? src[spos3.s3] : 0; - - short4 itab0, itab1, itab2, itab3; - float4 taby, tabx; - taby = INTER_SCALE * convert_float4(ay); - tabx = INTER_SCALE * convert_float4(ax); - - itab0 = convert_short4_sat(( (1.0f-taby)*(1.0f-tabx) * (float4)INTER_REMAP_COEF_SCALE )); - itab1 = convert_short4_sat(( (1.0f-taby)*tabx * (float4)INTER_REMAP_COEF_SCALE )); - itab2 = convert_short4_sat(( taby*(1.0f-tabx) * (float4)INTER_REMAP_COEF_SCALE )); - itab3 = convert_short4_sat(( taby*tabx * (float4)INTER_REMAP_COEF_SCALE )); - - - int4 val; - uchar4 tval; - val = convert_int4(v0) * convert_int4(itab0) + convert_int4(v1) * convert_int4(itab1) - + convert_int4(v2) * convert_int4(itab2) + convert_int4(v3) * convert_int4(itab3); - tval = convert_uchar4_sat ( (val + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ; - - __global uchar4 * d =(__global uchar4 *)(dst+dst_offset+dy*dstStep+dx); - uchar4 dval = *d; - DX = (int4)(dx, dx+1, dx+2, dx+3); - int4 dcon = DX >= 0 && DX < dst_cols && dy >= 0 && dy < dst_rows; - dval = convert_uchar4(dcon != 0) ? tval : dval; - *d = dval; - } -} - -__kernel void warpAffineCubic_C1_D0(__global uchar * src, __global uchar * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - int round_delta = ((AB_SCALE>>INTER_BITS)>>1); - - int X0 = rint(M[0] * dx * AB_SCALE); - int Y0 = rint(M[3] * dx * AB_SCALE); - X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta; - Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta; - int X = X0 >> (AB_BITS - INTER_BITS); - int Y = Y0 >> (AB_BITS - INTER_BITS); - - short sx = (short)(X >> INTER_BITS) - 1; - short sy = (short)(Y >> INTER_BITS) - 1; - short ay = (short)(Y & (INTER_TAB_SIZE-1)); - short ax = (short)(X & (INTER_TAB_SIZE-1)); - - uchar v[16]; - int i, j; - -#pragma unroll 4 - for(i=0; i<4; i++) - for(j=0; j<4; j++) - { - v[i*4+j] = (sx+j >= 0 && sx+j < src_cols && sy+i >= 0 && sy+i < src_rows) ? src[src_offset+(sy+i) * srcStep + (sx+j)] : 0; - } - - short itab[16]; - float tab1y[4], tab1x[4]; - float axx, ayy; - - ayy = 1.f/INTER_TAB_SIZE * ay; - axx = 1.f/INTER_TAB_SIZE * ax; - interpolateCubic(ayy, tab1y); - interpolateCubic(axx, tab1x); - int isum = 0; - -#pragma unroll 16 - for( i=0; i<16; i++ ) - { - F v = tab1y[(i>>2)] * tab1x[(i&3)]; - isum += itab[i] = convert_short_sat( rint( v * INTER_REMAP_COEF_SCALE ) ); - } - - if( isum != INTER_REMAP_COEF_SCALE ) - { - int k1, k2; - int diff = isum - INTER_REMAP_COEF_SCALE; - int Mk1=2, Mk2=2, mk1=2, mk2=2; - for( k1 = 2; k1 < 4; k1++ ) - for( k2 = 2; k2 < 4; k2++ ) - { - if( itab[(k1<<2)+k2] < itab[(mk1<<2)+mk2] ) - mk1 = k1, mk2 = k2; - else if( itab[(k1<<2)+k2] > itab[(Mk1<<2)+Mk2] ) - Mk1 = k1, Mk2 = k2; - } - diff<0 ? (itab[(Mk1<<2)+Mk2]=(short)(itab[(Mk1<<2)+Mk2]-diff)) : (itab[(mk1<<2)+mk2]=(short)(itab[(mk1<<2)+mk2]-diff)); - } - - if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - { - int sum=0; - for ( i =0; i<16; i++ ) - { - sum += v[i] * itab[i] ; - } - dst[dst_offset+dy*dstStep+dx] = convert_uchar_sat( (sum + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ; - } - } -} - -/**********************************************8UC4********************************************* -***********************************************************************************************/ - -__kernel void warpAffineNN_C4_D0(__global uchar4 const * restrict src, __global uchar4 * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - int round_delta = (AB_SCALE >> 1); - - int X0 = rint(M[0] * dx * AB_SCALE); - int Y0 = rint(M[3] * dx * AB_SCALE); - X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta; - Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta; - - int sx0 = (short)(X0 >> AB_BITS); - int sy0 = (short)(Y0 >> AB_BITS); - - if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - dst[(dst_offset>>2)+dy*(dstStep>>2)+dx]= (sx0>=0 && sx0=0 && sy0>2)+sy0*(srcStep>>2)+sx0] : (uchar4)0; - } -} - -__kernel void warpAffineLinear_C4_D0(__global uchar4 const * restrict src, __global uchar4 * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - - if( dx < threadCols && dy < dst_rows) - { - int round_delta = AB_SCALE/INTER_TAB_SIZE/2; - - src_offset = (src_offset>>2); - srcStep = (srcStep>>2); - - int tmp = (dx << AB_BITS); - int X0 = rint(M[0] * tmp); - int Y0 = rint(M[3] * tmp); - X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta; - Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta; - X0 = X0 >> (AB_BITS - INTER_BITS); - Y0 = Y0 >> (AB_BITS - INTER_BITS); - - short sx0 = (short)(X0 >> INTER_BITS); - short sy0 = (short)(Y0 >> INTER_BITS); - short ax0 = (short)(X0 & (INTER_TAB_SIZE-1)); - short ay0 = (short)(Y0 & (INTER_TAB_SIZE-1)); - - int4 v0, v1, v2, v3; - - v0 = (sx0 >= 0 && sx0 < src_cols && sy0 >= 0 && sy0 < src_rows) ? convert_int4(src[src_offset+sy0 * srcStep + sx0]) : 0; - v1 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0 >= 0 && sy0 < src_rows) ? convert_int4(src[src_offset+sy0 * srcStep + sx0+1]) : 0; - v2 = (sx0 >= 0 && sx0 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? convert_int4(src[src_offset+(sy0+1) * srcStep + sx0]) : 0; - v3 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? convert_int4(src[src_offset+(sy0+1) * srcStep + sx0+1]) : 0; - - int itab0, itab1, itab2, itab3; - float taby, tabx; - taby = 1.f/INTER_TAB_SIZE*ay0; - tabx = 1.f/INTER_TAB_SIZE*ax0; - - itab0 = convert_short_sat(rint( (1.0f-taby)*(1.0f-tabx) * INTER_REMAP_COEF_SCALE )); - itab1 = convert_short_sat(rint( (1.0f-taby)*tabx * INTER_REMAP_COEF_SCALE )); - itab2 = convert_short_sat(rint( taby*(1.0f-tabx) * INTER_REMAP_COEF_SCALE )); - itab3 = convert_short_sat(rint( taby*tabx * INTER_REMAP_COEF_SCALE )); - - int4 val; - val = v0 * itab0 + v1 * itab1 + v2 * itab2 + v3 * itab3; - - if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - dst[(dst_offset>>2)+dy*(dstStep>>2)+dx] = convert_uchar4_sat ( (val + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ; - } -} - -__kernel void warpAffineCubic_C4_D0(__global uchar4 const * restrict src, __global uchar4 * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - int round_delta = ((AB_SCALE>>INTER_BITS)>>1); - - src_offset = (src_offset>>2); - srcStep = (srcStep>>2); - dst_offset = (dst_offset>>2); - dstStep = (dstStep>>2); - - int tmp = (dx << AB_BITS); - int X0 = rint(M[0] * tmp); - int Y0 = rint(M[3] * tmp); - X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta; - Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta; - X0 = X0 >> (AB_BITS - INTER_BITS); - Y0 = Y0 >> (AB_BITS - INTER_BITS); - - int sx = (short)(X0 >> INTER_BITS) - 1; - int sy = (short)(Y0 >> INTER_BITS) - 1; - int ay = (short)(Y0 & (INTER_TAB_SIZE-1)); - int ax = (short)(X0 & (INTER_TAB_SIZE-1)); - - uchar4 v[16]; - int i,j; -#pragma unroll 4 - for(i=0; i<4; i++) - for(j=0; j<4; j++) - { - v[i*4+j] = (sx+j >= 0 && sx+j < src_cols && sy+i >= 0 && sy+i < src_rows) ? (src[src_offset+(sy+i) * srcStep + (sx+j)]) : (uchar4)0; - } - int itab[16]; - float tab1y[4], tab1x[4]; - float axx, ayy; - - ayy = INTER_SCALE * ay; - axx = INTER_SCALE * ax; - interpolateCubic(ayy, tab1y); - interpolateCubic(axx, tab1x); - int isum = 0; - -#pragma unroll 16 - for( i=0; i<16; i++ ) - { - float tmp; - tmp = tab1y[(i>>2)] * tab1x[(i&3)] * INTER_REMAP_COEF_SCALE; - itab[i] = rint(tmp); - isum += itab[i]; - } - - if( isum != INTER_REMAP_COEF_SCALE ) - { - int k1, k2; - int diff = isum - INTER_REMAP_COEF_SCALE; - int Mk1=2, Mk2=2, mk1=2, mk2=2; - - for( k1 = 2; k1 < 4; k1++ ) - for( k2 = 2; k2 < 4; k2++ ) - { - - if( itab[(k1<<2)+k2] < itab[(mk1<<2)+mk2] ) - mk1 = k1, mk2 = k2; - else if( itab[(k1<<2)+k2] > itab[(Mk1<<2)+Mk2] ) - Mk1 = k1, Mk2 = k2; - } - - diff<0 ? (itab[(Mk1<<2)+Mk2]=(short)(itab[(Mk1<<2)+Mk2]-diff)) : (itab[(mk1<<2)+mk2]=(short)(itab[(mk1<<2)+mk2]-diff)); - } - - if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - { - int4 sum=0; - for ( i =0; i<16; i++ ) - { - sum += convert_int4(v[i]) * itab[i]; - } - dst[dst_offset+dy*dstStep+dx] = convert_uchar4_sat( (sum + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ; - } - } -} - - -/**********************************************32FC1******************************************** -***********************************************************************************************/ - -__kernel void warpAffineNN_C1_D5(__global float * src, __global float * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - int round_delta = AB_SCALE/2; - - int X0 = rint(M[0] * dx * AB_SCALE); - int Y0 = rint(M[3] * dx * AB_SCALE); - X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta; - Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta; - - short sx0 = (short)(X0 >> AB_BITS); - short sy0 = (short)(Y0 >> AB_BITS); - - if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - dst[(dst_offset>>2)+dy*dstStep+dx]= (sx0>=0 && sx0=0 && sy0>2)+sy0*srcStep+sx0] : 0; - } -} - -__kernel void warpAffineLinear_C1_D5(__global float * src, __global float * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - int round_delta = AB_SCALE/INTER_TAB_SIZE/2; - - src_offset = (src_offset>>2); - - int X0 = rint(M[0] * dx * AB_SCALE); - int Y0 = rint(M[3] * dx * AB_SCALE); - X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta; - Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta; - X0 = X0 >> (AB_BITS - INTER_BITS); - Y0 = Y0 >> (AB_BITS - INTER_BITS); - - short sx0 = (short)(X0 >> INTER_BITS); - short sy0 = (short)(Y0 >> INTER_BITS); - short ax0 = (short)(X0 & (INTER_TAB_SIZE-1)); - short ay0 = (short)(Y0 & (INTER_TAB_SIZE-1)); - - float v0, v1, v2, v3; - - v0 = (sx0 >= 0 && sx0 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0] : 0; - v1 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0+1] : 0; - v2 = (sx0 >= 0 && sx0 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0] : 0; - v3 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0+1] : 0; - - float tab[4]; - float taby[2], tabx[2]; - taby[0] = 1.0f - 1.f/INTER_TAB_SIZE*ay0; - taby[1] = 1.f/INTER_TAB_SIZE*ay0; - tabx[0] = 1.0f - 1.f/INTER_TAB_SIZE*ax0; - tabx[1] = 1.f/INTER_TAB_SIZE*ax0; - - tab[0] = taby[0] * tabx[0]; - tab[1] = taby[0] * tabx[1]; - tab[2] = taby[1] * tabx[0]; - tab[3] = taby[1] * tabx[1]; - - float sum = 0; - sum += v0 * tab[0] + v1 * tab[1] + v2 * tab[2] + v3 * tab[3]; - if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - dst[(dst_offset>>2)+dy*dstStep+dx] = sum; - } -} - -__kernel void warpAffineCubic_C1_D5(__global float * src, __global float * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - int round_delta = AB_SCALE/INTER_TAB_SIZE/2; - - src_offset = (src_offset>>2); - dst_offset = (dst_offset>>2); - - int X0 = rint(M[0] * dx * AB_SCALE); - int Y0 = rint(M[3] * dx * AB_SCALE); - X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta; - Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta; - X0 = X0 >> (AB_BITS - INTER_BITS); - Y0 = Y0 >> (AB_BITS - INTER_BITS); - - short sx = (short)(X0 >> INTER_BITS) - 1; - short sy = (short)(Y0 >> INTER_BITS) - 1; - short ay = (short)(Y0 & (INTER_TAB_SIZE-1)); - short ax = (short)(X0 & (INTER_TAB_SIZE-1)); - - float v[16]; - int i; - - for(i=0; i<16; i++) - v[i] = (sx+(i&3) >= 0 && sx+(i&3) < src_cols && sy+(i>>2) >= 0 && sy+(i>>2) < src_rows) ? src[src_offset+(sy+(i>>2)) * srcStep + (sx+(i&3))] : 0; - - float tab[16]; - float tab1y[4], tab1x[4]; - float axx, ayy; - - ayy = 1.f/INTER_TAB_SIZE * ay; - axx = 1.f/INTER_TAB_SIZE * ax; - interpolateCubic(ayy, tab1y); - interpolateCubic(axx, tab1x); - -#pragma unroll 4 - for( i=0; i<16; i++ ) - { - tab[i] = tab1y[(i>>2)] * tab1x[(i&3)]; - } - - if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - { - float sum = 0; -#pragma unroll 4 - for ( i =0; i<16; i++ ) - { - sum += v[i] * tab[i]; - } - dst[dst_offset+dy*dstStep+dx] = sum; - - } - } -} - - -/**********************************************32FC4******************************************** -***********************************************************************************************/ - -__kernel void warpAffineNN_C4_D5(__global float4 * src, __global float4 * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - int round_delta = AB_SCALE/2; - - int X0 = rint(M[0] * dx * AB_SCALE); - int Y0 = rint(M[3] * dx * AB_SCALE); - X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta; - Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta; - - short sx0 = (short)(X0 >> AB_BITS); - short sy0 = (short)(Y0 >> AB_BITS); - - if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - dst[(dst_offset>>4)+dy*(dstStep>>2)+dx]= (sx0>=0 && sx0=0 && sy0>4)+sy0*(srcStep>>2)+sx0] : (float4)0; - } -} - -__kernel void warpAffineLinear_C4_D5(__global float4 * src, __global float4 * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - int round_delta = AB_SCALE/INTER_TAB_SIZE/2; - - src_offset = (src_offset>>4); - dst_offset = (dst_offset>>4); - srcStep = (srcStep>>2); - dstStep = (dstStep>>2); - - int X0 = rint(M[0] * dx * AB_SCALE); - int Y0 = rint(M[3] * dx * AB_SCALE); - X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta; - Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta; - X0 = X0 >> (AB_BITS - INTER_BITS); - Y0 = Y0 >> (AB_BITS - INTER_BITS); - - short sx0 = (short)(X0 >> INTER_BITS); - short sy0 = (short)(Y0 >> INTER_BITS); - short ax0 = (short)(X0 & (INTER_TAB_SIZE-1)); - short ay0 = (short)(Y0 & (INTER_TAB_SIZE-1)); - - float4 v0, v1, v2, v3; - - v0 = (sx0 >= 0 && sx0 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0] : (float4)0; - v1 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0+1] : (float4)0; - v2 = (sx0 >= 0 && sx0 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0] : (float4)0; - v3 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0+1] : (float4)0; - - float tab[4]; - float taby[2], tabx[2]; - taby[0] = 1.0f - 1.f/INTER_TAB_SIZE*ay0; - taby[1] = 1.f/INTER_TAB_SIZE*ay0; - tabx[0] = 1.0f - 1.f/INTER_TAB_SIZE*ax0; - tabx[1] = 1.f/INTER_TAB_SIZE*ax0; - - tab[0] = taby[0] * tabx[0]; - tab[1] = taby[0] * tabx[1]; - tab[2] = taby[1] * tabx[0]; - tab[3] = taby[1] * tabx[1]; - - float4 sum = 0; - sum += v0 * tab[0] + v1 * tab[1] + v2 * tab[2] + v3 * tab[3]; - if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - dst[dst_offset+dy*dstStep+dx] = sum; - } -} - -__kernel void warpAffineCubic_C4_D5(__global float4 * src, __global float4 * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - int round_delta = AB_SCALE/INTER_TAB_SIZE/2; - - src_offset = (src_offset>>4); - dst_offset = (dst_offset>>4); - srcStep = (srcStep>>2); - dstStep = (dstStep>>2); - - int X0 = rint(M[0] * dx * AB_SCALE); - int Y0 = rint(M[3] * dx * AB_SCALE); - X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta; - Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta; - X0 = X0 >> (AB_BITS - INTER_BITS); - Y0 = Y0 >> (AB_BITS - INTER_BITS); - - short sx = (short)(X0 >> INTER_BITS) - 1; - short sy = (short)(Y0 >> INTER_BITS) - 1; - short ay = (short)(Y0 & (INTER_TAB_SIZE-1)); - short ax = (short)(X0 & (INTER_TAB_SIZE-1)); - - float4 v[16]; - int i; - - for(i=0; i<16; i++) - v[i] = (sx+(i&3) >= 0 && sx+(i&3) < src_cols && sy+(i>>2) >= 0 && sy+(i>>2) < src_rows) ? src[src_offset+(sy+(i>>2)) * srcStep + (sx+(i&3))] : (float4)0; - - float tab[16]; - float tab1y[4], tab1x[4]; - float axx, ayy; - - ayy = 1.f/INTER_TAB_SIZE * ay; - axx = 1.f/INTER_TAB_SIZE * ax; - interpolateCubic(ayy, tab1y); - interpolateCubic(axx, tab1x); - -#pragma unroll 4 - for( i=0; i<16; i++ ) - { - tab[i] = tab1y[(i>>2)] * tab1x[(i&3)]; - } - - if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - { - float4 sum = 0; -#pragma unroll 4 - for ( i =0; i<16; i++ ) - { - sum += v[i] * tab[i]; - } - dst[dst_offset+dy*dstStep+dx] = sum; - - } - } -} diff --git a/modules/ocl/src/opencl/imgproc_warpPerspective.cl b/modules/ocl/src/opencl/imgproc_warpPerspective.cl deleted file mode 100644 index 97f86640b..000000000 --- a/modules/ocl/src/opencl/imgproc_warpPerspective.cl +++ /dev/null @@ -1,682 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Zhang Ying, zhangying913@gmail.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*/ - - -//wrapPerspective kernel -//support data types: CV_8UC1, CV_8UC4, CV_32FC1, CV_32FC4, and three interpolation methods: NN, Linear, Cubic. - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -typedef double F; -typedef double4 F4; -#define convert_F4 convert_double4 -#else -typedef float F; -typedef float4 F4; -#define convert_F4 convert_float4 -#endif - - -#define INTER_BITS 5 -#define INTER_TAB_SIZE (1 << INTER_BITS) -#define INTER_SCALE 1.f/INTER_TAB_SIZE -#define AB_BITS max(10, (int)INTER_BITS) -#define AB_SCALE (1 << AB_BITS) -#define INTER_REMAP_COEF_BITS 15 -#define INTER_REMAP_COEF_SCALE (1 << INTER_REMAP_COEF_BITS) - -inline void interpolateCubic( float x, float* coeffs ) -{ - const float A = -0.75f; - - coeffs[0] = ((A*(x + 1.f) - 5.0f*A)*(x + 1.f) + 8.0f*A)*(x + 1.f) - 4.0f*A; - coeffs[1] = ((A + 2.f)*x - (A + 3.f))*x*x + 1.f; - coeffs[2] = ((A + 2.f)*(1.f - x) - (A + 3.f))*(1.f - x)*(1.f - x) + 1.f; - coeffs[3] = 1.f - coeffs[0] - coeffs[1] - coeffs[2]; -} - - -/**********************************************8UC1********************************************* -***********************************************************************************************/ -__kernel void warpPerspectiveNN_C1_D0(__global uchar const * restrict src, __global uchar * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - dx = (dx<<2) - (dst_offset&3); - - F4 DX = (F4)(dx, dx+1, dx+2, dx+3); - F4 X0 = M[0]*DX + M[1]*dy + M[2]; - F4 Y0 = M[3]*DX + M[4]*dy + M[5]; - F4 W = M[6]*DX + M[7]*dy + M[8],one=1,zero=0; - W = (W!=zero) ? one/W : zero; - short4 X = convert_short4_sat_rte(X0*W); - short4 Y = convert_short4_sat_rte(Y0*W); - int4 sx = convert_int4(X); - int4 sy = convert_int4(Y); - - int4 DXD = (int4)(dx, dx+1, dx+2, dx+3); - __global uchar4 * d = (__global uchar4 *)(dst+dst_offset+dy*dstStep+dx); - uchar4 dval = *d; - int4 dcon = DXD >= 0 && DXD < dst_cols && dy >= 0 && dy < dst_rows; - int4 scon = sx >= 0 && sx < src_cols && sy >= 0 && sy < src_rows; - int4 spos = src_offset + sy * srcStep + sx; - uchar4 sval; - sval.s0 = scon.s0 ? src[spos.s0] : 0; - sval.s1 = scon.s1 ? src[spos.s1] : 0; - sval.s2 = scon.s2 ? src[spos.s2] : 0; - sval.s3 = scon.s3 ? src[spos.s3] : 0; - dval = convert_uchar4(dcon) != (uchar4)(0,0,0,0) ? sval : dval; - *d = dval; - } -} - -__kernel void warpPerspectiveLinear_C1_D0(__global const uchar * restrict src, __global uchar * dst, - int src_cols, int src_rows, int dst_cols, int dst_rows, int srcStep, - int dstStep, int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - F X0 = M[0]*dx + M[1]*dy + M[2]; - F Y0 = M[3]*dx + M[4]*dy + M[5]; - F W = M[6]*dx + M[7]*dy + M[8]; - W = (W != 0.0f) ? INTER_TAB_SIZE/W : 0.0f; - int X = rint(X0*W); - int Y = rint(Y0*W); - - int sx = convert_short_sat(X >> INTER_BITS); - int sy = convert_short_sat(Y >> INTER_BITS); - int ay = (short)(Y & (INTER_TAB_SIZE-1)); - int ax = (short)(X & (INTER_TAB_SIZE-1)); - - uchar v[4]; - int i; -#pragma unroll 4 - for(i=0; i<4; i++) - v[i] = (sx+(i&1) >= 0 && sx+(i&1) < src_cols && sy+(i>>1) >= 0 && sy+(i>>1) < src_rows) ? src[src_offset + (sy+(i>>1)) * srcStep + (sx+(i&1))] : (uchar)0; - - short itab[4]; - float tab1y[2], tab1x[2]; - tab1y[0] = 1.0f - 1.f/INTER_TAB_SIZE*ay; - tab1y[1] = 1.f/INTER_TAB_SIZE*ay; - tab1x[0] = 1.0f - 1.f/INTER_TAB_SIZE*ax; - tab1x[1] = 1.f/INTER_TAB_SIZE*ax; - -#pragma unroll 4 - for(i=0; i<4; i++) - { - float v = tab1y[(i>>1)] * tab1x[(i&1)]; - itab[i] = convert_short_sat_rte( v * INTER_REMAP_COEF_SCALE ); - } - if(dx >=0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - { - int sum = 0; - for ( i =0; i<4; i++ ) - { - sum += v[i] * itab[i] ; - } - dst[dst_offset+dy*dstStep+dx] = convert_uchar_sat ( (sum + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ; - } - } -} - -__kernel void warpPerspectiveCubic_C1_D0(__global uchar * src, __global uchar * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - F X0 = M[0]*dx + M[1]*dy + M[2]; - F Y0 = M[3]*dx + M[4]*dy + M[5]; - F W = M[6]*dx + M[7]*dy + M[8]; - W = (W != 0.0f) ? INTER_TAB_SIZE/W : 0.0f; - int X = rint(X0*W); - int Y = rint(Y0*W); - - short sx = convert_short_sat(X >> INTER_BITS) - 1; - short sy = convert_short_sat(Y >> INTER_BITS) - 1; - short ay = (short)(Y & (INTER_TAB_SIZE-1)); - short ax = (short)(X & (INTER_TAB_SIZE-1)); - - uchar v[16]; - int i, j; - -#pragma unroll 4 - for(i=0; i<4; i++) - for(j=0; j<4; j++) - { - v[i*4+j] = (sx+j >= 0 && sx+j < src_cols && sy+i >= 0 && sy+i < src_rows) ? src[src_offset+(sy+i) * srcStep + (sx+j)] : (uchar)0; - } - - short itab[16]; - float tab1y[4], tab1x[4]; - float axx, ayy; - - ayy = 1.f/INTER_TAB_SIZE * ay; - axx = 1.f/INTER_TAB_SIZE * ax; - interpolateCubic(ayy, tab1y); - interpolateCubic(axx, tab1x); - - int isum = 0; -#pragma unroll 16 - for( i=0; i<16; i++ ) - { - F v = tab1y[(i>>2)] * tab1x[(i&3)]; - isum += itab[i] = convert_short_sat( rint( v * INTER_REMAP_COEF_SCALE ) ); - } - if( isum != INTER_REMAP_COEF_SCALE ) - { - int k1, k2; - int diff = isum - INTER_REMAP_COEF_SCALE; - int Mk1=2, Mk2=2, mk1=2, mk2=2; - for( k1 = 2; k1 < 4; k1++ ) - for( k2 = 2; k2 < 4; k2++ ) - { - if( itab[(k1<<2)+k2] < itab[(mk1<<2)+mk2] ) - mk1 = k1, mk2 = k2; - else if( itab[(k1<<2)+k2] > itab[(Mk1<<2)+Mk2] ) - Mk1 = k1, Mk2 = k2; - } - diff<0 ? (itab[(Mk1<<2)+Mk2]=(short)(itab[(Mk1<<2)+Mk2]-diff)) : (itab[(mk1<<2)+mk2]=(short)(itab[(mk1<<2)+mk2]-diff)); - } - - - if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - { - int sum=0; - for ( i =0; i<16; i++ ) - { - sum += v[i] * itab[i] ; - } - dst[dst_offset+dy*dstStep+dx] = convert_uchar_sat( (sum + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ; - } - } -} - -/**********************************************8UC4********************************************* -***********************************************************************************************/ - -__kernel void warpPerspectiveNN_C4_D0(__global uchar4 const * restrict src, __global uchar4 * dst, - int src_cols, int src_rows, int dst_cols, int dst_rows, int srcStep, - int dstStep, int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - - F X0 = M[0]*dx + M[1]*dy + M[2]; - F Y0 = M[3]*dx + M[4]*dy + M[5]; - F W = M[6]*dx + M[7]*dy + M[8]; - W = (W != 0.0f) ? 1.f/W : 0.0f; - short sx = convert_short_sat_rte(X0*W); - short sy = convert_short_sat_rte(Y0*W); - - if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - dst[(dst_offset>>2)+dy*(dstStep>>2)+dx]= (sx>=0 && sx=0 && sy>2)+sy*(srcStep>>2)+sx] : (uchar4)0; - } -} - -__kernel void warpPerspectiveLinear_C4_D0(__global uchar4 const * restrict src, __global uchar4 * dst, - int src_cols, int src_rows, int dst_cols, int dst_rows, int srcStep, - int dstStep, int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - src_offset = (src_offset>>2); - srcStep = (srcStep>>2); - - F X0 = M[0]*dx + M[1]*dy + M[2]; - F Y0 = M[3]*dx + M[4]*dy + M[5]; - F W = M[6]*dx + M[7]*dy + M[8]; - W = (W != 0.0f) ? INTER_TAB_SIZE/W : 0.0f; - int X = rint(X0*W); - int Y = rint(Y0*W); - - short sx = convert_short_sat(X >> INTER_BITS); - short sy = convert_short_sat(Y >> INTER_BITS); - short ay = (short)(Y & (INTER_TAB_SIZE-1)); - short ax = (short)(X & (INTER_TAB_SIZE-1)); - - - int4 v0, v1, v2, v3; - - v0 = (sx >= 0 && sx < src_cols && sy >= 0 && sy < src_rows) ? convert_int4(src[src_offset+sy * srcStep + sx]) : (int4)0; - v1 = (sx+1 >= 0 && sx+1 < src_cols && sy >= 0 && sy < src_rows) ? convert_int4(src[src_offset+sy * srcStep + sx+1]) : (int4)0; - v2 = (sx >= 0 && sx < src_cols && sy+1 >= 0 && sy+1 < src_rows) ? convert_int4(src[src_offset+(sy+1) * srcStep + sx]) : (int4)0; - v3 = (sx+1 >= 0 && sx+1 < src_cols && sy+1 >= 0 && sy+1 < src_rows) ? convert_int4(src[src_offset+(sy+1) * srcStep + sx+1]) : (int4)0; - - int itab0, itab1, itab2, itab3; - float taby, tabx; - taby = 1.f/INTER_TAB_SIZE*ay; - tabx = 1.f/INTER_TAB_SIZE*ax; - - itab0 = convert_short_sat(rint( (1.0f-taby)*(1.0f-tabx) * INTER_REMAP_COEF_SCALE )); - itab1 = convert_short_sat(rint( (1.0f-taby)*tabx * INTER_REMAP_COEF_SCALE )); - itab2 = convert_short_sat(rint( taby*(1.0f-tabx) * INTER_REMAP_COEF_SCALE )); - itab3 = convert_short_sat(rint( taby*tabx * INTER_REMAP_COEF_SCALE )); - - int4 val; - val = v0 * itab0 + v1 * itab1 + v2 * itab2 + v3 * itab3; - - if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - dst[(dst_offset>>2)+dy*(dstStep>>2)+dx] = convert_uchar4_sat ( (val + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ; - } -} - -__kernel void warpPerspectiveCubic_C4_D0(__global uchar4 const * restrict src, __global uchar4 * dst, - int src_cols, int src_rows, int dst_cols, int dst_rows, int srcStep, - int dstStep, int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - src_offset = (src_offset>>2); - srcStep = (srcStep>>2); - dst_offset = (dst_offset>>2); - dstStep = (dstStep>>2); - - F X0 = M[0]*dx + M[1]*dy + M[2]; - F Y0 = M[3]*dx + M[4]*dy + M[5]; - F W = M[6]*dx + M[7]*dy + M[8]; - W = (W != 0.0f) ? INTER_TAB_SIZE/W : 0.0f; - int X = rint(X0*W); - int Y = rint(Y0*W); - - short sx = convert_short_sat(X >> INTER_BITS) - 1; - short sy = convert_short_sat(Y >> INTER_BITS) - 1; - short ay = (short)(Y & (INTER_TAB_SIZE-1)); - short ax = (short)(X & (INTER_TAB_SIZE-1)); - - uchar4 v[16]; - int i,j; -#pragma unroll 4 - for(i=0; i<4; i++) - for(j=0; j<4; j++) - { - v[i*4+j] = (sx+j >= 0 && sx+j < src_cols && sy+i >= 0 && sy+i < src_rows) ? (src[src_offset+(sy+i) * srcStep + (sx+j)]) : (uchar4)0; - } - int itab[16]; - float tab1y[4], tab1x[4]; - float axx, ayy; - - ayy = INTER_SCALE * ay; - axx = INTER_SCALE * ax; - interpolateCubic(ayy, tab1y); - interpolateCubic(axx, tab1x); - int isum = 0; - -#pragma unroll 16 - for( i=0; i<16; i++ ) - { - float tmp; - tmp = tab1y[(i>>2)] * tab1x[(i&3)] * INTER_REMAP_COEF_SCALE; - itab[i] = rint(tmp); - isum += itab[i]; - } - - if( isum != INTER_REMAP_COEF_SCALE ) - { - int k1, k2; - int diff = isum - INTER_REMAP_COEF_SCALE; - int Mk1=2, Mk2=2, mk1=2, mk2=2; - - for( k1 = 2; k1 < 4; k1++ ) - for( k2 = 2; k2 < 4; k2++ ) - { - - if( itab[(k1<<2)+k2] < itab[(mk1<<2)+mk2] ) - mk1 = k1, mk2 = k2; - else if( itab[(k1<<2)+k2] > itab[(Mk1<<2)+Mk2] ) - Mk1 = k1, Mk2 = k2; - } - - diff<0 ? (itab[(Mk1<<2)+Mk2]=(short)(itab[(Mk1<<2)+Mk2]-diff)) : (itab[(mk1<<2)+mk2]=(short)(itab[(mk1<<2)+mk2]-diff)); - } - - if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - { - int4 sum=0; - for ( i =0; i<16; i++ ) - { - sum += convert_int4(v[i]) * itab[i]; - } - dst[dst_offset+dy*dstStep+dx] = convert_uchar4_sat( (sum + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ; - } - } -} - - -/**********************************************32FC1******************************************** -***********************************************************************************************/ - -__kernel void warpPerspectiveNN_C1_D5(__global float * src, __global float * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - F X0 = M[0]*dx + M[1]*dy + M[2]; - F Y0 = M[3]*dx + M[4]*dy + M[5]; - F W = M[6]*dx + M[7]*dy + M[8]; - W = (W != 0.0f) ? 1.f/W : 0.0f; - short sx = convert_short_sat_rte(X0*W); - short sy = convert_short_sat_rte(Y0*W); - - if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - dst[(dst_offset>>2)+dy*dstStep+dx]= (sx>=0 && sx=0 && sy>2)+sy*srcStep+sx] : 0; - } -} - -__kernel void warpPerspectiveLinear_C1_D5(__global float * src, __global float * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - src_offset = (src_offset>>2); - - F X0 = M[0]*dx + M[1]*dy + M[2]; - F Y0 = M[3]*dx + M[4]*dy + M[5]; - F W = M[6]*dx + M[7]*dy + M[8]; - W = (W != 0.0f) ? INTER_TAB_SIZE/W : 0.0f; - int X = rint(X0*W); - int Y = rint(Y0*W); - - short sx = convert_short_sat(X >> INTER_BITS); - short sy = convert_short_sat(Y >> INTER_BITS); - short ay = (short)(Y & (INTER_TAB_SIZE-1)); - short ax = (short)(X & (INTER_TAB_SIZE-1)); - - float v0, v1, v2, v3; - - v0 = (sx >= 0 && sx < src_cols && sy >= 0 && sy < src_rows) ? src[src_offset+sy * srcStep + sx] : (float)0; - v1 = (sx+1 >= 0 && sx+1 < src_cols && sy >= 0 && sy < src_rows) ? src[src_offset+sy * srcStep + sx+1] : (float)0; - v2 = (sx >= 0 && sx < src_cols && sy+1 >= 0 && sy+1 < src_rows) ? src[src_offset+(sy+1) * srcStep + sx] : (float)0; - v3 = (sx+1 >= 0 && sx+1 < src_cols && sy+1 >= 0 && sy+1 < src_rows) ? src[src_offset+(sy+1) * srcStep + sx+1] : (float)0; - - float tab[4]; - float taby[2], tabx[2]; - taby[0] = 1.0f - 1.f/INTER_TAB_SIZE*ay; - taby[1] = 1.f/INTER_TAB_SIZE*ay; - tabx[0] = 1.0f - 1.f/INTER_TAB_SIZE*ax; - tabx[1] = 1.f/INTER_TAB_SIZE*ax; - - tab[0] = taby[0] * tabx[0]; - tab[1] = taby[0] * tabx[1]; - tab[2] = taby[1] * tabx[0]; - tab[3] = taby[1] * tabx[1]; - - float sum = 0; - sum += v0 * tab[0] + v1 * tab[1] + v2 * tab[2] + v3 * tab[3]; - if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - dst[(dst_offset>>2)+dy*dstStep+dx] = sum; - } -} - -__kernel void warpPerspectiveCubic_C1_D5(__global float * src, __global float * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - src_offset = (src_offset>>2); - dst_offset = (dst_offset>>2); - - F X0 = M[0]*dx + M[1]*dy + M[2]; - F Y0 = M[3]*dx + M[4]*dy + M[5]; - F W = M[6]*dx + M[7]*dy + M[8]; - W = (W != 0.0f) ? INTER_TAB_SIZE/W : 0.0f; - int X = rint(X0*W); - int Y = rint(Y0*W); - - short sx = convert_short_sat(X >> INTER_BITS) - 1; - short sy = convert_short_sat(Y >> INTER_BITS) - 1; - short ay = (short)(Y & (INTER_TAB_SIZE-1)); - short ax = (short)(X & (INTER_TAB_SIZE-1)); - - float v[16]; - int i; - - for(i=0; i<16; i++) - v[i] = (sx+(i&3) >= 0 && sx+(i&3) < src_cols && sy+(i>>2) >= 0 && sy+(i>>2) < src_rows) ? src[src_offset+(sy+(i>>2)) * srcStep + (sx+(i&3))] : (float)0; - - float tab[16]; - float tab1y[4], tab1x[4]; - float axx, ayy; - - ayy = 1.f/INTER_TAB_SIZE * ay; - axx = 1.f/INTER_TAB_SIZE * ax; - interpolateCubic(ayy, tab1y); - interpolateCubic(axx, tab1x); - -#pragma unroll 4 - for( i=0; i<16; i++ ) - { - tab[i] = tab1y[(i>>2)] * tab1x[(i&3)]; - } - - if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - { - float sum = 0; -#pragma unroll 4 - for ( i =0; i<16; i++ ) - { - sum += v[i] * tab[i]; - } - dst[dst_offset+dy*dstStep+dx] = sum; - - } - } -} - - -/**********************************************32FC4******************************************** -***********************************************************************************************/ - -__kernel void warpPerspectiveNN_C4_D5(__global float4 * src, __global float4 * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - F X0 = M[0]*dx + M[1]*dy + M[2]; - F Y0 = M[3]*dx + M[4]*dy + M[5]; - F W = M[6]*dx + M[7]*dy + M[8]; - W =(W != 0.0f)? 1.f/W : 0.0f; - short sx = convert_short_sat_rte(X0*W); - short sy = convert_short_sat_rte(Y0*W); - - if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - dst[(dst_offset>>4)+dy*(dstStep>>2)+dx]= (sx>=0 && sx=0 && sy>4)+sy*(srcStep>>2)+sx] : (float)0; - } -} - -__kernel void warpPerspectiveLinear_C4_D5(__global float4 * src, __global float4 * dst, int src_cols, int src_rows, - int dst_cols, int dst_rows, int srcStep, int dstStep, - int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows) - { - src_offset = (src_offset>>4); - dst_offset = (dst_offset>>4); - srcStep = (srcStep>>2); - dstStep = (dstStep>>2); - - F X0 = M[0]*dx + M[1]*dy + M[2]; - F Y0 = M[3]*dx + M[4]*dy + M[5]; - F W = M[6]*dx + M[7]*dy + M[8]; - W = (W != 0.0f) ? INTER_TAB_SIZE/W : 0.0f; - int X = rint(X0*W); - int Y = rint(Y0*W); - - short sx0 = convert_short_sat(X >> INTER_BITS); - short sy0 = convert_short_sat(Y >> INTER_BITS); - short ay0 = (short)(Y & (INTER_TAB_SIZE-1)); - short ax0 = (short)(X & (INTER_TAB_SIZE-1)); - - - float4 v0, v1, v2, v3; - - v0 = (sx0 >= 0 && sx0 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0] : (float4)0; - v1 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0+1] : (float4)0; - v2 = (sx0 >= 0 && sx0 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0] : (float4)0; - v3 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0+1] : (float4)0; - - float tab[4]; - float taby[2], tabx[2]; - taby[0] = 1.0f - 1.f/INTER_TAB_SIZE*ay0; - taby[1] = 1.f/INTER_TAB_SIZE*ay0; - tabx[0] = 1.0f - 1.f/INTER_TAB_SIZE*ax0; - tabx[1] = 1.f/INTER_TAB_SIZE*ax0; - - tab[0] = taby[0] * tabx[0]; - tab[1] = taby[0] * tabx[1]; - tab[2] = taby[1] * tabx[0]; - tab[3] = taby[1] * tabx[1]; - - float4 sum = 0; - sum += v0 * tab[0] + v1 * tab[1] + v2 * tab[2] + v3 * tab[3]; - if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - dst[dst_offset+dy*dstStep+dx] = sum; - } -} - -__kernel void warpPerspectiveCubic_C4_D5(__global float4 * src, __global float4 * dst, - int src_cols, int src_rows, int dst_cols, int dst_rows, int srcStep, - int dstStep, int src_offset, int dst_offset, __constant F * M, int threadCols ) -{ - int dx = get_global_id(0); - int dy = get_global_id(1); - - if( dx < threadCols && dy < dst_rows ) - { - src_offset = (src_offset>>4); - dst_offset = (dst_offset>>4); - srcStep = (srcStep>>2); - dstStep = (dstStep>>2); - - F X0 = M[0]*dx + M[1]*dy + M[2]; - F Y0 = M[3]*dx + M[4]*dy + M[5]; - F W = M[6]*dx + M[7]*dy + M[8]; - W = (W != 0.0f) ? INTER_TAB_SIZE/W : 0.0f; - int X = rint(X0*W); - int Y = rint(Y0*W); - - short sx = convert_short_sat(X >> INTER_BITS)-1; - short sy = convert_short_sat(Y >> INTER_BITS)-1; - short ay = (short)(Y & (INTER_TAB_SIZE-1)); - short ax = (short)(X & (INTER_TAB_SIZE-1)); - - - float4 v[16]; - int i; - - for(i=0; i<16; i++) - v[i] = (sx+(i&3) >= 0 && sx+(i&3) < src_cols && sy+(i>>2) >= 0 && sy+(i>>2) < src_rows) ? src[src_offset+(sy+(i>>2)) * srcStep + (sx+(i&3))] : (float4)0; - - float tab[16]; - float tab1y[4], tab1x[4]; - float axx, ayy; - - ayy = 1.f/INTER_TAB_SIZE * ay; - axx = 1.f/INTER_TAB_SIZE * ax; - interpolateCubic(ayy, tab1y); - interpolateCubic(axx, tab1x); - -#pragma unroll 4 - for( i=0; i<16; i++ ) - { - tab[i] = tab1y[(i>>2)] * tab1x[(i&3)]; - } - - if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows) - { - float4 sum = 0; -#pragma unroll 4 - for ( i =0; i<16; i++ ) - { - sum += v[i] * tab[i]; - } - dst[dst_offset+dy*dstStep+dx] = sum; - - } - } -} diff --git a/modules/ocl/src/opencl/interpolate_frames.cl b/modules/ocl/src/opencl/interpolate_frames.cl deleted file mode 100644 index eb0b55f33..000000000 --- a/modules/ocl/src/opencl/interpolate_frames.cl +++ /dev/null @@ -1,252 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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*/ - -#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable -#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable - -// Image read mode -__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR; - -// atomic add for 32bit floating point -inline void atomic_addf(volatile __global float *source, const float operand) { - union { - unsigned int intVal; - float floatVal; - } newVal; - union { - unsigned int intVal; - float floatVal; - } prevVal; - do { - prevVal.floatVal = *source; - newVal.floatVal = prevVal.floatVal + operand; - } while (atomic_cmpxchg((volatile __global unsigned int *)source, prevVal.intVal, newVal.intVal) != prevVal.intVal); -} - -__kernel void memsetKernel( - float val, - __global float * image, - int width, - int height, - int step, // in element - int offset - ) -{ - if(get_global_id(0) >= width || get_global_id(1) >= height) - { - return; - } - image += offset; - image[get_global_id(0) + get_global_id(1) * step] = val; -} - -__kernel void normalizeKernel( - __global float * buffer, - int width, - int height, - int step, - int f_offset, - int d_offset - ) -{ - __global float * factors = buffer + f_offset; - __global float * dst = buffer + d_offset; - - int j = get_global_id(0); - int i = get_global_id(1); - - if(j >= width || i >= height) - { - return; - } - float scale = factors[step * i + j]; - float invScale = (scale == 0.0f) ? 1.0f : (1.0f / scale); - - dst[step * i + j] *= invScale; -} - -__kernel void forwardWarpKernel( - __global const float * src, - __global float * buffer, - __global const float * u, - __global const float * v, - const int w, - const int h, - const int flow_stride, - const int image_stride, - const int factor_offset, - const int dst_offset, - const float time_scale - ) -{ - int j = get_global_id(0); - int i = get_global_id(1); - - if (i >= h || j >= w) return; - - volatile __global float * normalization_factor = (volatile __global float *) buffer + factor_offset; - volatile __global float * dst = (volatile __global float *)buffer + dst_offset; - - int flow_row_offset = i * flow_stride; - int image_row_offset = i * image_stride; - - //bottom left corner of a target pixel - float cx = u[flow_row_offset + j] * time_scale + (float)j + 1.0f; - float cy = v[flow_row_offset + j] * time_scale + (float)i + 1.0f; - // pixel containing bottom left corner - float px; - float py; - float dx = modf(cx, &px); - float dy = modf(cy, &py); - // target pixel integer coords - int tx; - int ty; - tx = (int) px; - ty = (int) py; - float value = src[image_row_offset + j]; - float weight; - // fill pixel containing bottom right corner - if (!((tx >= w) || (tx < 0) || (ty >= h) || (ty < 0))) - { - weight = dx * dy; - atomic_addf(dst + ty * image_stride + tx, value * weight); - atomic_addf(normalization_factor + ty * image_stride + tx, weight); - } - - // fill pixel containing bottom left corner - tx -= 1; - if (!((tx >= w) || (tx < 0) || (ty >= h) || (ty < 0))) - { - weight = (1.0f - dx) * dy; - atomic_addf(dst + ty * image_stride + tx, value * weight); - atomic_addf(normalization_factor + ty * image_stride + tx, weight); - } - - // fill pixel containing upper left corner - ty -= 1; - if (!((tx >= w) || (tx < 0) || (ty >= h) || (ty < 0))) - { - weight = (1.0f - dx) * (1.0f - dy); - atomic_addf(dst + ty * image_stride + tx, value * weight); - atomic_addf(normalization_factor + ty * image_stride + tx, weight); - } - - // fill pixel containing upper right corner - tx += 1; - if (!((tx >= w) || (tx < 0) || (ty >= h) || (ty < 0))) - { - weight = dx * (1.0f - dy); - atomic_addf(dst + ty * image_stride + tx, value * weight); - atomic_addf(normalization_factor + ty * image_stride + tx, weight); - } -} - -// define buffer offsets -enum -{ - O0_OS = 0, - O1_OS, - U_OS, - V_OS, - UR_OS, - VR_OS -}; - -__kernel void blendFramesKernel( - image2d_t tex_src0, - image2d_t tex_src1, - __global float * buffer, - __global float * out, - int w, - int h, - int step, - float theta - ) -{ - __global float * u = buffer + h * step * U_OS; - __global float * v = buffer + h * step * V_OS; - __global float * ur = buffer + h * step * UR_OS; - __global float * vr = buffer + h * step * VR_OS; - __global float * o0 = buffer + h * step * O0_OS; - __global float * o1 = buffer + h * step * O1_OS; - - int ix = get_global_id(0); - int iy = get_global_id(1); - - if(ix >= w || iy >= h) return; - - int pos = ix + step * iy; - - float _u = u[pos]; - float _v = v[pos]; - - float _ur = ur[pos]; - float _vr = vr[pos]; - - float x = (float)ix + 0.5f; - float y = (float)iy + 0.5f; - bool b0 = o0[pos] > 1e-4f; - bool b1 = o1[pos] > 1e-4f; - - float2 coord0 = (float2)(x - _u * theta, y - _v * theta); - float2 coord1 = (float2)(x + _u * (1.0f - theta), y + _v * (1.0f - theta)); - - if (b0 && b1) - { - // pixel is visible on both frames - out[pos] = read_imagef(tex_src0, sampler, coord0).x * (1.0f - theta) + - read_imagef(tex_src1, sampler, coord1).x * theta; - } - else if (b0) - { - // visible on the first frame only - out[pos] = read_imagef(tex_src0, sampler, coord0).x; - } - else - { - // visible on the second frame only - out[pos] = read_imagef(tex_src1, sampler, coord1).x; - } -} diff --git a/modules/ocl/src/opencl/kernel_radix_sort_by_key.cl b/modules/ocl/src/opencl/kernel_radix_sort_by_key.cl deleted file mode 100644 index 7e09f3fc5..000000000 --- a/modules/ocl/src/opencl/kernel_radix_sort_by_key.cl +++ /dev/null @@ -1,176 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@outlook.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*/ - -#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable - -#ifndef N // number of radices -#define N 4 -#endif - -#ifndef K_T -#define K_T float -#endif - -#ifndef V_T -#define V_T float -#endif - -#ifndef IS_GT -#define IS_GT 0 -#endif - - -// from Thrust::b40c, link: -// https://github.com/thrust/thrust/blob/master/thrust/system/cuda/detail/detail/b40c/radixsort_key_conversion.h -__inline uint convertKey(uint converted_key) -{ -#ifdef K_FLT - unsigned int mask = (converted_key & 0x80000000) ? 0xffffffff : 0x80000000; - converted_key ^= mask; -#elif defined(K_INT) - const uint SIGN_MASK = 1u << ((sizeof(int) * 8) - 1); - converted_key ^= SIGN_MASK; -#else - -#endif - return converted_key; -} - -//FIXME(pengx17): -// exclusive scan, need to be optimized as this is too naive... -kernel - void naiveScanAddition( - __global int * input, - __global int * output, - int size - ) -{ - if(get_global_id(0) == 0) - { - output[0] = 0; - for(int i = 1; i < size; i ++) - { - output[i] = output[i - 1] + input[i - 1]; - } - } -} - -// following is ported from -// https://github.com/HSA-Libraries/Bolt/blob/master/include/bolt/cl/sort_uint_kernels.cl -kernel - void histogramRadixN ( - __global K_T* unsortedKeys, - __global int * buckets, - uint shiftCount - ) -{ - const int RADIX_T = N; - const int RADICES_T = (1 << RADIX_T); - const int NUM_OF_ELEMENTS_PER_WORK_ITEM_T = RADICES_T; - const int MASK_T = (1 << RADIX_T) - 1; - int localBuckets[16] = {0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0}; - int globalId = get_global_id(0); - int numOfGroups = get_num_groups(0); - - /* Calculate thread-histograms */ - for(int i = 0; i < NUM_OF_ELEMENTS_PER_WORK_ITEM_T; ++i) - { - uint value = convertKey(as_uint(unsortedKeys[mad24(globalId, NUM_OF_ELEMENTS_PER_WORK_ITEM_T, i)])); - value = (value >> shiftCount) & MASK_T; -#if IS_GT - localBuckets[RADICES_T - value - 1]++; -#else - localBuckets[value]++; -#endif - } - - for(int i = 0; i < NUM_OF_ELEMENTS_PER_WORK_ITEM_T; ++i) - { - buckets[mad24(i, RADICES_T * numOfGroups, globalId) ] = localBuckets[i]; - } -} - -kernel - void permuteRadixN ( - __global K_T* unsortedKeys, - __global V_T* unsortedVals, - __global int* scanedBuckets, - uint shiftCount, - __global K_T* sortedKeys, - __global V_T* sortedVals - ) -{ - const int RADIX_T = N; - const int RADICES_T = (1 << RADIX_T); - const int MASK_T = (1<> shiftCount) & MASK_T; - uint index = localIndex[maskedValue]; - sortedKeys[index] = ovalue; - sortedVals[index] = unsortedVals[old_idx]; - localIndex[maskedValue] = index + 1; - } -} diff --git a/modules/ocl/src/opencl/kernel_sort_by_key.cl b/modules/ocl/src/opencl/kernel_sort_by_key.cl deleted file mode 100644 index 0e8d581b7..000000000 --- a/modules/ocl/src/opencl/kernel_sort_by_key.cl +++ /dev/null @@ -1,244 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@outlook.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*/ - -#ifndef K_T -#define K_T float -#endif - -#ifndef V_T -#define V_T float -#endif - -#ifndef IS_GT -#define IS_GT false -#endif - -#if IS_GT -#define my_comp(x,y) ((x) > (y)) -#else -#define my_comp(x,y) ((x) < (y)) -#endif - -/////////////////////// Bitonic sort //////////////////////////// -// ported from -// https://github.com/HSA-Libraries/Bolt/blob/master/include/bolt/cl/sort_by_key_kernels.cl -__kernel - void bitonicSort - ( - __global K_T * keys, - __global V_T * vals, - int count, - int stage, - int passOfStage - ) -{ - const int threadId = get_global_id(0); - if(threadId >= count / 2) - { - return; - } - const int pairDistance = 1 << (stage - passOfStage); - const int blockWidth = 2 * pairDistance; - - int leftId = min( (threadId % pairDistance) - + (threadId / pairDistance) * blockWidth, count ); - - int rightId = min( leftId + pairDistance, count ); - - int temp; - - const V_T lval = vals[leftId]; - const V_T rval = vals[rightId]; - - const K_T lkey = keys[leftId]; - const K_T rkey = keys[rightId]; - - int sameDirectionBlockWidth = 1 << stage; - - if((threadId/sameDirectionBlockWidth) % 2 == 1) - { - temp = rightId; - rightId = leftId; - leftId = temp; - } - - const bool compareResult = my_comp(lkey, rkey); - - if(compareResult) - { - keys[rightId] = rkey; - keys[leftId] = lkey; - vals[rightId] = rval; - vals[leftId] = lval; - } - else - { - keys[rightId] = lkey; - keys[leftId] = rkey; - vals[rightId] = lval; - vals[leftId] = rval; - } -} - -/////////////////////// Selection sort //////////////////////////// -//kernel is ported from Bolt library: -//https://github.com/HSA-Libraries/Bolt/blob/master/include/bolt/cl/sort_kernels.cl -__kernel - void selectionSortLocal - ( - __global K_T * keys, - __global V_T * vals, - const int count, - __local K_T * scratch - ) -{ - int i = get_local_id(0); // index in workgroup - int numOfGroups = get_num_groups(0); // index in workgroup - int groupID = get_group_id(0); - int wg = get_local_size(0); // workgroup size = block size - int n; // number of elements to be processed for this work group - - int offset = groupID * wg; - int same = 0; - - vals += offset; - keys += offset; - n = (groupID == (numOfGroups-1))? (count - wg*(numOfGroups-1)) : wg; - - int clamped_i= min(i, n - 1); - - K_T key1 = keys[clamped_i], key2; - V_T val1 = vals[clamped_i]; - scratch[i] = key1; - barrier(CLK_LOCAL_MEM_FENCE); - - if(i >= n) - { - return; - } - - int pos = 0; - for (int j=0;j= count) - return; - V_T val1 = vals[offset + i]; - - K_T key1 = keys[offset + i]; - K_T key2; - - for(int j=0; j (y)) -#else -#define my_comp(x,y) ((x) < (y)) -#endif - -// This implements a binary search routine to look for an 'insertion point' in a sequence, denoted -// by a base pointer and left and right index for a particular candidate value. The comparison operator is -// passed as a functor parameter my_comp -// This function returns an index that is the first index whos value would be equal to the searched value -inline uint lowerBoundBinary( global K_T* data, uint left, uint right, K_T searchVal) -{ - // The values firstIndex and lastIndex get modified within the loop, narrowing down the potential sequence - uint firstIndex = left; - uint lastIndex = right; - - // This loops through [firstIndex, lastIndex) - // Since firstIndex and lastIndex will be different for every thread depending on the nested branch, - // this while loop will be divergent within a wavefront - while( firstIndex < lastIndex ) - { - // midIndex is the average of first and last, rounded down - uint midIndex = ( firstIndex + lastIndex ) / 2; - K_T midValue = data[ midIndex ]; - - // This branch will create divergent wavefronts - if( my_comp( midValue, searchVal ) ) - { - firstIndex = midIndex+1; - // printf( "lowerBound: lastIndex[ %i ]=%i\n", get_local_id( 0 ), lastIndex ); - } - else - { - lastIndex = midIndex; - // printf( "lowerBound: firstIndex[ %i ]=%i\n", get_local_id( 0 ), firstIndex ); - } - } - - return firstIndex; -} - -// This implements a binary search routine to look for an 'insertion point' in a sequence, denoted -// by a base pointer and left and right index for a particular candidate value. The comparison operator is -// passed as a functor parameter my_comp -// This function returns an index that is the first index whos value would be greater than the searched value -// If the search value is not found in the sequence, upperbound returns the same result as lowerbound -inline uint upperBoundBinary( global K_T* data, uint left, uint right, K_T searchVal) -{ - uint upperBound = lowerBoundBinary( data, left, right, searchVal ); - - // printf( "upperBoundBinary: upperBound[ %i, %i ]= %i\n", left, right, upperBound ); - // If upperBound == right, then searchVal was not found in the sequence. Just return. - if( upperBound != right ) - { - // While the values are equal i.e. !(x < y) && !(y < x) increment the index - K_T upperValue = data[ upperBound ]; - while( !my_comp( upperValue, searchVal ) && !my_comp( searchVal, upperValue) && (upperBound != right) ) - { - upperBound++; - upperValue = data[ upperBound ]; - } - } - - return upperBound; -} - -// This kernel implements merging of blocks of sorted data. The input to this kernel most likely is -// the output of blockInsertionSortTemplate. It is expected that the source array contains multiple -// blocks, each block is independently sorted. The goal is to write into the output buffer half as -// many blocks, of double the size. The even and odd blocks are stably merged together to form -// a new sorted block of twice the size. The algorithm is out-of-place. -kernel void merge( - global K_T* iKey_ptr, - global V_T* iValue_ptr, - global K_T* oKey_ptr, - global V_T* oValue_ptr, - const uint srcVecSize, - const uint srcLogicalBlockSize, - local K_T* key_lds, - local V_T* val_lds -) -{ - size_t globalID = get_global_id( 0 ); - - // Abort threads that are passed the end of the input vector - if( globalID >= srcVecSize ) - return; // on SI this doesn't mess-up barriers - - // For an element in sequence A, find the lowerbound index for it in sequence B - uint srcBlockNum = globalID / srcLogicalBlockSize; - uint srcBlockIndex = globalID % srcLogicalBlockSize; - - // printf( "mergeTemplate: srcBlockNum[%i]=%i\n", srcBlockNum, srcBlockIndex ); - - // Pairs of even-odd blocks will be merged together - // An even block should search for an insertion point in the next odd block, - // and the odd block should look for an insertion point in the corresponding previous even block - uint dstLogicalBlockSize = srcLogicalBlockSize<<1; - uint leftBlockIndex = globalID & ~((dstLogicalBlockSize) - 1 ); - leftBlockIndex += (srcBlockNum & 0x1) ? 0 : srcLogicalBlockSize; - leftBlockIndex = min( leftBlockIndex, srcVecSize ); - uint rightBlockIndex = min( leftBlockIndex + srcLogicalBlockSize, srcVecSize ); - - // if( localID == 0 ) - // { - // printf( "mergeTemplate: wavefront[ %i ] logicalBlock[ %i ] logicalIndex[ %i ] leftBlockIndex[ %i ] <=> rightBlockIndex[ %i ]\n", groupID, srcBlockNum, srcBlockIndex, leftBlockIndex, rightBlockIndex ); - // } - - // For a particular element in the input array, find the lowerbound index for it in the search sequence given by leftBlockIndex & rightBlockIndex - // uint insertionIndex = lowerBoundLinear( iKey_ptr, leftBlockIndex, rightBlockIndex, iKey_ptr[ globalID ], my_comp ) - leftBlockIndex; - uint insertionIndex = 0; - if( (srcBlockNum & 0x1) == 0 ) - { - insertionIndex = lowerBoundBinary( iKey_ptr, leftBlockIndex, rightBlockIndex, iKey_ptr[ globalID ] ) - leftBlockIndex; - } - else - { - insertionIndex = upperBoundBinary( iKey_ptr, leftBlockIndex, rightBlockIndex, iKey_ptr[ globalID ] ) - leftBlockIndex; - } - - // The index of an element in the result sequence is the summation of it's indixes in the two input - // sequences - uint dstBlockIndex = srcBlockIndex + insertionIndex; - uint dstBlockNum = srcBlockNum/2; - - // if( (dstBlockNum*dstLogicalBlockSize)+dstBlockIndex == 395 ) - // { - // printf( "mergeTemplate: (dstBlockNum[ %i ] * dstLogicalBlockSize[ %i ]) + dstBlockIndex[ %i ] = srcBlockIndex[ %i ] + insertionIndex[ %i ]\n", dstBlockNum, dstLogicalBlockSize, dstBlockIndex, srcBlockIndex, insertionIndex ); - // printf( "mergeTemplate: dstBlockIndex[ %i ] = iKey_ptr[ %i ] ( %i )\n", (dstBlockNum*dstLogicalBlockSize)+dstBlockIndex, globalID, iKey_ptr[ globalID ] ); - // } - oKey_ptr[ (dstBlockNum*dstLogicalBlockSize)+dstBlockIndex ] = iKey_ptr[ globalID ]; - oValue_ptr[ (dstBlockNum*dstLogicalBlockSize)+dstBlockIndex ] = iValue_ptr[ globalID ]; - // printf( "mergeTemplate: leftResultIndex[ %i ]=%i + %i\n", leftResultIndex, srcBlockIndex, leftInsertionIndex ); -} - -kernel void blockInsertionSort( - global K_T* key_ptr, - global V_T* value_ptr, - const uint vecSize, - local K_T* key_lds, - local V_T* val_lds -) -{ - int gloId = get_global_id( 0 ); - int groId = get_group_id( 0 ); - int locId = get_local_id( 0 ); - int wgSize = get_local_size( 0 ); - - bool in_range = gloId < (int)vecSize; - K_T key; - V_T val; - // Abort threads that are passed the end of the input vector - if (in_range) - { - // Make a copy of the entire input array into fast local memory - key = key_ptr[ gloId ]; - val = value_ptr[ gloId ]; - key_lds[ locId ] = key; - val_lds[ locId ] = val; - } - barrier( CLK_LOCAL_MEM_FENCE ); - // Sorts a workgroup using a naive insertion sort - // The sort uses one thread within a workgroup to sort the entire workgroup - if( locId == 0 && in_range ) - { - // The last workgroup may have an irregular size, so we calculate a per-block endIndex - // endIndex is essentially emulating a mod operator with subtraction and multiply - int endIndex = vecSize - ( groId * wgSize ); - endIndex = min( endIndex, wgSize ); - - // printf( "Debug: endIndex[%i]=%i\n", groId, endIndex ); - - // Indices are signed because the while loop will generate a -1 index inside of the max function - for( int currIndex = 1; currIndex < endIndex; ++currIndex ) - { - key = key_lds[ currIndex ]; - val = val_lds[ currIndex ]; - int scanIndex = currIndex; - K_T ldsKey = key_lds[scanIndex - 1]; - while( scanIndex > 0 && my_comp( key, ldsKey ) ) - { - V_T ldsVal = val_lds[scanIndex - 1]; - - // If the keys are being swapped, make sure the values are swapped identicaly - key_lds[ scanIndex ] = ldsKey; - val_lds[ scanIndex ] = ldsVal; - - scanIndex = scanIndex - 1; - ldsKey = key_lds[ max( 0, scanIndex - 1 ) ]; // scanIndex-1 may be -1 - } - key_lds[ scanIndex ] = key; - val_lds[ scanIndex ] = val; - } - } - barrier( CLK_LOCAL_MEM_FENCE ); - - if(in_range) - { - key = key_lds[ locId ]; - key_ptr[ gloId ] = key; - - val = val_lds[ locId ]; - value_ptr[ gloId ] = val; - } -} - -///////////// Radix sort from b40c library ///////////// diff --git a/modules/ocl/src/opencl/kmeans_kernel.cl b/modules/ocl/src/opencl/kmeans_kernel.cl deleted file mode 100644 index bb0e9c9a4..000000000 --- a/modules/ocl/src/opencl/kmeans_kernel.cl +++ /dev/null @@ -1,107 +0,0 @@ -/*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 -// Xiaopeng Fu, fuxiaopeng2222@163.com -// Peng Xiao, pengxiao@outlook.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*/ - -inline float distance_(__global const float * center, __global const float * src, int feature_length) -{ - float res = 0; - float4 v0, v1, v2; - int i = 0; - -#ifdef L1_DIST - float4 sum = (float4)(0.0f); -#endif - - for ( ; i <= feature_length - 4; i += 4) - { - v0 = vload4(0, center + i); - v1 = vload4(0, src + i); - v2 = v1 - v0; -#ifdef L1_DIST - v0 = fabs(v2); - sum += v0; -#else - res += dot(v2, v2); -#endif - } - -#ifdef L1_DIST - res = sum.x + sum.y + sum.z + sum.w; -#endif - - for ( ; i < feature_length; ++i) - { - float t0 = src[i]; - float t1 = center[i]; -#ifdef L1_DIST - res += fabs(t0 - t1); -#else - float t2 = t0 - t1; - res += t2 * t2; -#endif - } - - return res; -} - -__kernel void distanceToCenters(__global const float * src, __global const float * centers, - __global float * dists, int feature_length, - int src_step, int centers_step, - int features_count, int centers_count, - int src_offset, int centers_offset) -{ - int gid = get_global_id(0); - - if (gid < (features_count * centers_count)) - { - int feature_index = gid / centers_count; - int center_index = gid % centers_count; - - int center_idx = mad24(center_index, centers_step, centers_offset); - int src_idx = mad24(feature_index, src_step, src_offset); - - dists[gid] = distance_(centers + center_idx, src + src_idx, feature_length); - } -} diff --git a/modules/ocl/src/opencl/knearest.cl b/modules/ocl/src/opencl/knearest.cl deleted file mode 100644 index 85e24517d..000000000 --- a/modules/ocl/src/opencl/knearest.cl +++ /dev/null @@ -1,186 +0,0 @@ -/*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 -// 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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#define TYPE double -#else -#define TYPE float -#endif - -#define CV_SWAP(a,b,t) ((t) = (a), (a) = (b), (b) = (t)) -///////////////////////////////////// find_nearest ////////////////////////////////////// -__kernel void knn_find_nearest(__global float* sample, int sample_row, int sample_col, int sample_step, - int k, __global float* samples_ocl, int sample_ocl_row, int sample_ocl_step, - __global float* _results, int _results_step, int _regression, int K1, - int sample_ocl_col, int nThreads, __local float* nr) -{ - int k1 = 0; - int k2 = 0; - - bool regression = false; - - if(_regression) - regression = true; - - TYPE inv_scale; -#ifdef DOUBLE_SUPPORT - inv_scale = 1.0/K1; -#else - inv_scale = 1.0f/K1; -#endif - - int y = get_global_id(1); - int j, j1; - int threadY = (y % nThreads); - __local float* dd = nr + nThreads * k; - if(y >= sample_row) - { - return; - } - for(j = 0; j < sample_ocl_row; j++) - { - TYPE sum; -#ifdef DOUBLE_SUPPORT - sum = 0.0; -#else - sum = 0.0f; -#endif - float si; - int t, ii, ii1; - for(t = 0; t < sample_col - 16; t += 16) - { - float16 t0 = vload16(0, sample + y * sample_step + t) - vload16(0, samples_ocl + j * sample_ocl_step + t); - t0 *= t0; - sum += t0.s0 + t0.s1 + t0.s2 + t0.s3 + t0.s4 + t0.s5 + t0.s6 + t0.s7 + - t0.s8 + t0.s9 + t0.sa + t0.sb + t0.sc + t0.sd + t0.se + t0.sf; - } - - for(; t < sample_col; t++) - { -#ifdef DOUBLE_SUPPORT - double t0 = sample[y * sample_step + t] - samples_ocl[j * sample_ocl_step + t]; -#else - float t0 = sample[y * sample_step + t] - samples_ocl[j * sample_ocl_step + t]; -#endif - sum = sum + t0 * t0; - } - - si = (float)sum; - for(ii = k1 - 1; ii >= 0; ii--) - { - if(as_int(si) > as_int(dd[ii * nThreads + threadY])) - break; - } - if(ii < k - 1) - { - for(ii1 = k2 - 1; ii1 > ii; ii1--) - { - dd[(ii1 + 1) * nThreads + threadY] = dd[ii1 * nThreads + threadY]; - nr[(ii1 + 1) * nThreads + threadY] = nr[ii1 * nThreads + threadY]; - } - - dd[(ii + 1) * nThreads + threadY] = si; - nr[(ii + 1) * nThreads + threadY] = samples_ocl[sample_col + j * sample_ocl_step]; - } - k1 = (k1 + 1) < k ? (k1 + 1) : k; - k2 = k1 < (k - 1) ? k1 : (k - 1); - } - /*! find_nearest_neighbor done!*/ - /*! write_results start!*/ - if (regression) - { - TYPE s; -#ifdef DOUBLE_SUPPORT - s = 0.0; -#else - s = 0.0f; -#endif - for(j = 0; j < K1; j++) - s += nr[j * nThreads + threadY]; - - _results[y * _results_step] = (float)(s * inv_scale); - } - else - { - int prev_start = 0, best_count = 0, cur_count; - float best_val; - - for(j = K1 - 1; j > 0; j--) - { - bool swap_f1 = false; - for(j1 = 0; j1 < j; j1++) - { - if(nr[j1 * nThreads + threadY] > nr[(j1 + 1) * nThreads + threadY]) - { - int t; - CV_SWAP(nr[j1 * nThreads + threadY], nr[(j1 + 1) * nThreads + threadY], t); - swap_f1 = true; - } - } - if(!swap_f1) - break; - } - - best_val = 0; - for(j = 1; j <= K1; j++) - if(j == K1 || nr[j * nThreads + threadY] != nr[(j - 1) * nThreads + threadY]) - { - cur_count = j - prev_start; - if(best_count < cur_count) - { - best_count = cur_count; - best_val = nr[(j - 1) * nThreads + threadY]; - } - prev_start = j; - } - _results[y * _results_step] = best_val; - } - ///*! write_results done!*/ -} diff --git a/modules/ocl/src/opencl/match_template.cl b/modules/ocl/src/opencl/match_template.cl deleted file mode 100644 index 4d46d0084..000000000 --- a/modules/ocl/src/opencl/match_template.cl +++ /dev/null @@ -1,853 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#define TYPE_IMAGE_SQSUM double -#else -#define TYPE_IMAGE_SQSUM float -#endif - -#ifndef CN4 -#define CN4 1 -#else -#define CN4 4 -#endif - -////////////////////////////////////////////////// -// utilities -#define SQSUMS_PTR(ox, oy) mad24(gidy + oy, img_sqsums_step, (gidx + img_sqsums_offset + ox) * CN4) -#define SUMS_PTR(ox, oy) mad24(gidy + oy, img_sums_step, gidx + img_sums_offset + ox) -// normAcc* are accurate normalization routines which make GPU matchTemplate -// consistent with CPU one -inline float normAcc(float num, float denum) -{ - if(fabs(num) < denum) - { - return num / denum; - } - if(fabs(num) < denum * 1.125f) - { - return num > 0 ? 1 : -1; - } - return 0; -} - -inline float normAcc_SQDIFF(float num, float denum) -{ - if(fabs(num) < denum) - { - return num / denum; - } - if(fabs(num) < denum * 1.125f) - { - return num > 0 ? 1 : -1; - } - return 1; -} -////////////////////////////////////////////////////////////////////// -// normalize - -__kernel -void normalizeKernel_C1_D0 -( - __global const float * img_sqsums, - __global float * res, - ulong tpl_sqsum, - int res_rows, - int res_cols, - int tpl_rows, - int tpl_cols, - int img_sqsums_offset, - int img_sqsums_step, - int res_offset, - int res_step -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - img_sqsums_step /= sizeof(*img_sqsums); - img_sqsums_offset /= sizeof(*img_sqsums); - int res_idx = mad24(gidy, res_step, res_offset + gidx); - if(gidx < res_cols && gidy < res_rows) - { - float image_sqsum_ = (float)( - (img_sqsums[SQSUMS_PTR(tpl_cols, tpl_rows)] - img_sqsums[SQSUMS_PTR(tpl_cols, 0)]) - - (img_sqsums[SQSUMS_PTR(0, tpl_rows)] - img_sqsums[SQSUMS_PTR(0, 0)])); - res[res_idx] = normAcc(res[res_idx], sqrt(image_sqsum_ * tpl_sqsum)); - } -} - -__kernel -void matchTemplate_Prepared_SQDIFF_C1_D0 -( - __global const TYPE_IMAGE_SQSUM * img_sqsums, - __global float * res, - ulong tpl_sqsum, - int res_rows, - int res_cols, - int tpl_rows, - int tpl_cols, - int img_sqsums_offset, - int img_sqsums_step, - int res_offset, - int res_step -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - img_sqsums_step /= sizeof(*img_sqsums); - img_sqsums_offset /= sizeof(*img_sqsums); - int res_idx = mad24(gidy, res_step, res_offset + gidx); - if(gidx < res_cols && gidy < res_rows) - { - float image_sqsum_ = (float)( - (img_sqsums[SQSUMS_PTR(tpl_cols, tpl_rows)] - img_sqsums[SQSUMS_PTR(tpl_cols, 0)]) - - (img_sqsums[SQSUMS_PTR(0, tpl_rows)] - img_sqsums[SQSUMS_PTR(0, 0)])); - res[res_idx] = image_sqsum_ - 2.f * res[res_idx] + tpl_sqsum; - } -} - -__kernel -void matchTemplate_Prepared_SQDIFF_NORMED_C1_D0 -( - __global const float * img_sqsums, - __global float * res, - ulong tpl_sqsum, - int res_rows, - int res_cols, - int tpl_rows, - int tpl_cols, - int img_sqsums_offset, - int img_sqsums_step, - int res_offset, - int res_step -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - img_sqsums_step /= sizeof(*img_sqsums); - img_sqsums_offset /= sizeof(*img_sqsums); - int res_idx = mad24(gidy, res_step, res_offset + gidx); - if(gidx < res_cols && gidy < res_rows) - { - float image_sqsum_ = (float)( - (img_sqsums[SQSUMS_PTR(tpl_cols, tpl_rows)] - img_sqsums[SQSUMS_PTR(tpl_cols, 0)]) - - (img_sqsums[SQSUMS_PTR(0, tpl_rows)] - img_sqsums[SQSUMS_PTR(0, 0)])); - res[res_idx] = normAcc_SQDIFF(image_sqsum_ - 2.f * res[res_idx] + tpl_sqsum, - sqrt(image_sqsum_ * tpl_sqsum)); - } -} - -////////////////////////////////////////////////// -// SQDIFF -__kernel -void matchTemplate_Naive_SQDIFF_C1_D0 -( - __global const uchar * img, - __global const uchar * tpl, - __global float * res, - int img_rows, - int img_cols, - int tpl_rows, - int tpl_cols, - int res_rows, - int res_cols, - int img_offset, - int tpl_offset, - int res_offset, - int img_step, - int tpl_step, - int res_step -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - int i,j; - int delta; - int sum = 0; - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - int res_idx = mad24(gidy, res_step, res_offset + gidx); - - if(gidx < res_cols && gidy < res_rows) - { - for(i = 0; i < tpl_rows; i ++) - { - // get specific rows of img data - __global const uchar * img_ptr = img + mad24(gidy + i, img_step, gidx + img_offset); - __global const uchar * tpl_ptr = tpl + mad24(i, tpl_step, tpl_offset); - for(j = 0; j < tpl_cols; j ++) - { - delta = img_ptr[j] - tpl_ptr[j]; - sum = mad24(delta, delta, sum); - } - } - res[res_idx] = sum; - } -} - -__kernel -void matchTemplate_Naive_SQDIFF_C1_D5 -( - __global const float * img, - __global const float * tpl, - __global float * res, - int img_rows, - int img_cols, - int tpl_rows, - int tpl_cols, - int res_rows, - int res_cols, - int img_offset, - int tpl_offset, - int res_offset, - int img_step, - int tpl_step, - int res_step -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - int i,j; - float delta; - float sum = 0; - img_step /= sizeof(*img); - img_offset /= sizeof(*img); - tpl_step /= sizeof(*tpl); - tpl_offset /= sizeof(*tpl); - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); - - if(gidx < res_cols && gidy < res_rows) - { - for(i = 0; i < tpl_rows; i ++) - { - // get specific rows of img data - __global const float * img_ptr = img + mad24(gidy + i, img_step, gidx + img_offset); - __global const float * tpl_ptr = tpl + mad24(i, tpl_step, tpl_offset); - for(j = 0; j < tpl_cols; j ++) - { - delta = img_ptr[j] - tpl_ptr[j]; - sum = mad(delta, delta, sum); - } - } - res[res_idx] = sum; - } -} - -__kernel -void matchTemplate_Naive_SQDIFF_C4_D0 -( - __global const uchar4 * img, - __global const uchar4 * tpl, - __global float * res, - int img_rows, - int img_cols, - int tpl_rows, - int tpl_cols, - int res_rows, - int res_cols, - int img_offset, - int tpl_offset, - int res_offset, - int img_step, - int tpl_step, - int res_step -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - int i,j; - int4 delta; - int4 sum = (int4)(0, 0, 0, 0); - img_step /= sizeof(*img); - img_offset /= sizeof(*img); - tpl_step /= sizeof(*tpl); - tpl_offset /= sizeof(*tpl); - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); - - if(gidx < res_cols && gidy < res_rows) - { - for(i = 0; i < tpl_rows; i ++) - { - // get specific rows of img data - __global const uchar4 * img_ptr = img + mad24(gidy + i, img_step, gidx + img_offset); - __global const uchar4 * tpl_ptr = tpl + mad24(i, tpl_step, tpl_offset); - for(j = 0; j < tpl_cols; j ++) - { - //delta = convert_int4(img_ptr[j] - tpl_ptr[j]); // this alternative is incorrect - delta.x = img_ptr[j].x - tpl_ptr[j].x; - delta.y = img_ptr[j].y - tpl_ptr[j].y; - delta.z = img_ptr[j].z - tpl_ptr[j].z; - delta.w = img_ptr[j].w - tpl_ptr[j].w; - sum = mad24(delta, delta, sum); - } - } - res[res_idx] = sum.x + sum.y + sum.z + sum.w; - } -} - -__kernel -void matchTemplate_Naive_SQDIFF_C4_D5 -( - __global const float4 * img, - __global const float4 * tpl, - __global float * res, - int img_rows, - int img_cols, - int tpl_rows, - int tpl_cols, - int res_rows, - int res_cols, - int img_offset, - int tpl_offset, - int res_offset, - int img_step, - int tpl_step, - int res_step -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - int i,j; - float4 delta; - float4 sum = (float4)(0, 0, 0, 0); - img_step /= sizeof(*img); - img_offset /= sizeof(*img); - tpl_step /= sizeof(*tpl); - tpl_offset /= sizeof(*tpl); - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); - - if(gidx < res_cols && gidy < res_rows) - { - for(i = 0; i < tpl_rows; i ++) - { - // get specific rows of img data - __global const float4 * img_ptr = img + mad24(gidy + i, img_step, gidx + img_offset); - __global const float4 * tpl_ptr = tpl + mad24(i, tpl_step, tpl_offset); - for(j = 0; j < tpl_cols; j ++) - { - //delta = convert_int4(img_ptr[j] - tpl_ptr[j]); // this alternative is incorrect - delta.x = img_ptr[j].x - tpl_ptr[j].x; - delta.y = img_ptr[j].y - tpl_ptr[j].y; - delta.z = img_ptr[j].z - tpl_ptr[j].z; - delta.w = img_ptr[j].w - tpl_ptr[j].w; - sum = mad(delta, delta, sum); - } - } - res[res_idx] = sum.x + sum.y + sum.z + sum.w; - } -} - -////////////////////////////////////////////////// -// CCORR -__kernel -void matchTemplate_Naive_CCORR_C1_D0 -( - __global const uchar * img, - __global const uchar * tpl, - __global float * res, - int img_rows, - int img_cols, - int tpl_rows, - int tpl_cols, - int res_rows, - int res_cols, - int img_offset, - int tpl_offset, - int res_offset, - int img_step, - int tpl_step, - int res_step -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - int i,j; - int sum = 0; - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); - - if(gidx < res_cols && gidy < res_rows) - { - for(i = 0; i < tpl_rows; i ++) - { - // get specific rows of img data - __global const uchar * img_ptr = img + mad24(gidy + i, img_step, gidx + img_offset); - __global const uchar * tpl_ptr = tpl + mad24(i, tpl_step, tpl_offset); - for(j = 0; j < tpl_cols; j ++) - { - sum = mad24(convert_int(img_ptr[j]), convert_int(tpl_ptr[j]), sum); - } - } - res[res_idx] = (float)sum; - } -} - -__kernel -void matchTemplate_Naive_CCORR_C1_D5 -( - __global const float * img, - __global const float * tpl, - __global float * res, - int img_rows, - int img_cols, - int tpl_rows, - int tpl_cols, - int res_rows, - int res_cols, - int img_offset, - int tpl_offset, - int res_offset, - int img_step, - int tpl_step, - int res_step -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - int i,j; - float sum = 0; - img_step /= sizeof(*img); - img_offset /= sizeof(*img); - tpl_step /= sizeof(*tpl); - tpl_offset /= sizeof(*tpl); - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); - - if(gidx < res_cols && gidy < res_rows) - { - for(i = 0; i < tpl_rows; i ++) - { - // get specific rows of img data - __global const float * img_ptr = img + mad24(gidy + i, img_step, gidx + img_offset); - __global const float * tpl_ptr = tpl + mad24(i, tpl_step, tpl_offset); - for(j = 0; j < tpl_cols; j ++) - { - sum = mad(img_ptr[j], tpl_ptr[j], sum); - } - } - res[res_idx] = sum; - } -} - -__kernel -void matchTemplate_Naive_CCORR_C4_D0 -( - __global const uchar4 * img, - __global const uchar4 * tpl, - __global float * res, - int img_rows, - int img_cols, - int tpl_rows, - int tpl_cols, - int res_rows, - int res_cols, - int img_offset, - int tpl_offset, - int res_offset, - int img_step, - int tpl_step, - int res_step -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - int i,j; - int4 sum = (int4)(0, 0, 0, 0); - img_step /= sizeof(*img); - img_offset /= sizeof(*img); - tpl_step /= sizeof(*tpl); - tpl_offset /= sizeof(*tpl); - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); - - if(gidx < res_cols && gidy < res_rows) - { - for(i = 0; i < tpl_rows; i ++) - { - // get specific rows of img data - __global const uchar4 * img_ptr = img + mad24(gidy + i, img_step, gidx + img_offset); - __global const uchar4 * tpl_ptr = tpl + mad24(i, tpl_step, tpl_offset); - for(j = 0; j < tpl_cols; j ++) - { - sum = mad24(convert_int4(img_ptr[j]), convert_int4(tpl_ptr[j]), sum); - } - } - res[res_idx] = (float)(sum.x + sum.y + sum.z + sum.w); - } -} - -__kernel -void matchTemplate_Naive_CCORR_C4_D5 -( - __global const float4 * img, - __global const float4 * tpl, - __global float * res, - int img_rows, - int img_cols, - int tpl_rows, - int tpl_cols, - int res_rows, - int res_cols, - int img_offset, - int tpl_offset, - int res_offset, - int img_step, - int tpl_step, - int res_step -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - int i,j; - float4 sum = (float4)(0, 0, 0, 0); - img_step /= sizeof(*img); - img_offset /= sizeof(*img); - tpl_step /= sizeof(*tpl); - tpl_offset /= sizeof(*tpl); - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); - - if(gidx < res_cols && gidy < res_rows) - { - for(i = 0; i < tpl_rows; i ++) - { - // get specific rows of img data - __global const float4 * img_ptr = img + mad24(gidy + i, img_step, gidx + img_offset); - __global const float4 * tpl_ptr = tpl + mad24(i, tpl_step, tpl_offset); - for(j = 0; j < tpl_cols; j ++) - { - sum = mad(convert_float4(img_ptr[j]), convert_float4(tpl_ptr[j]), sum); - } - } - res[res_idx] = sum.x + sum.y + sum.z + sum.w; - } -} - -////////////////////////////////////////////////// -// CCOFF -__kernel -void matchTemplate_Prepared_CCOFF_C1_D0 -( - __global float * res, - int img_rows, - int img_cols, - int tpl_rows, - int tpl_cols, - int res_rows, - int res_cols, - int res_offset, - int res_step, - __global const uint * img_sums, - int img_sums_offset, - int img_sums_step, - float tpl_sum -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - - img_sums_offset /= sizeof(*img_sums); - img_sums_step /= sizeof(*img_sums); - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); - - if(gidx < res_cols && gidy < res_rows) - { - float sum = (float)((img_sums[SUMS_PTR(tpl_cols, tpl_rows)] - img_sums[SUMS_PTR(tpl_cols, 0)]) - -(img_sums[SUMS_PTR(0, tpl_rows)] - img_sums[SUMS_PTR(0, 0)])); - res[res_idx] -= sum * tpl_sum; - } -} -__kernel -void matchTemplate_Prepared_CCOFF_C4_D0 -( - __global float * res, - int img_rows, - int img_cols, - int tpl_rows, - int tpl_cols, - int res_rows, - int res_cols, - int res_offset, - int res_step, - __global const uint * img_sums_c0, - __global const uint * img_sums_c1, - __global const uint * img_sums_c2, - __global const uint * img_sums_c3, - int img_sums_offset, - int img_sums_step, - float tpl_sum_c0, - float tpl_sum_c1, - float tpl_sum_c2, - float tpl_sum_c3 -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - - img_sums_offset /= sizeof(*img_sums_c0); - img_sums_step /= sizeof(*img_sums_c0); - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); - - if(gidx < res_cols && gidy < res_rows) - { - float ccorr = res[res_idx]; - ccorr -= tpl_sum_c0*(float)( - (img_sums_c0[SUMS_PTR(tpl_cols, tpl_rows)] - img_sums_c0[SUMS_PTR(tpl_cols, 0)]) - - (img_sums_c0[SUMS_PTR(0, tpl_rows)] - img_sums_c0[SUMS_PTR(0, 0)])); - ccorr -= tpl_sum_c1*(float)( - (img_sums_c1[SUMS_PTR(tpl_cols, tpl_rows)] - img_sums_c1[SUMS_PTR(tpl_cols, 0)]) - - (img_sums_c1[SUMS_PTR(0, tpl_rows)] - img_sums_c1[SUMS_PTR(0, 0)])); - ccorr -= tpl_sum_c2*(float)( - (img_sums_c2[SUMS_PTR(tpl_cols, tpl_rows)] - img_sums_c2[SUMS_PTR(tpl_cols, 0)]) - - (img_sums_c2[SUMS_PTR(0, tpl_rows)] - img_sums_c2[SUMS_PTR(0, 0)])); - ccorr -= tpl_sum_c3*(float)( - (img_sums_c3[SUMS_PTR(tpl_cols, tpl_rows)] - img_sums_c3[SUMS_PTR(tpl_cols, 0)]) - - (img_sums_c3[SUMS_PTR(0, tpl_rows)] - img_sums_c3[SUMS_PTR(0, 0)])); - res[res_idx] = ccorr; - } -} - -__kernel -void matchTemplate_Prepared_CCOFF_NORMED_C1_D0 -( - __global float * res, - int img_rows, - int img_cols, - int tpl_rows, - int tpl_cols, - int res_rows, - int res_cols, - int res_offset, - int res_step, - float weight, - __global const uint * img_sums, - int img_sums_offset, - int img_sums_step, - __global const float * img_sqsums, - int img_sqsums_offset, - int img_sqsums_step, - float tpl_sum, - float tpl_sqsum -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - - img_sqsums_step /= sizeof(*img_sqsums); - img_sqsums_offset /= sizeof(*img_sqsums); - img_sums_offset /= sizeof(*img_sums); - img_sums_step /= sizeof(*img_sums); - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - - int res_idx = mad24(gidy, res_step, res_offset + gidx); - - if(gidx < res_cols && gidy < res_rows) - { - float image_sum_ = (float)( - (img_sums[SUMS_PTR(tpl_cols, tpl_rows)] - img_sums[SUMS_PTR(tpl_cols, 0)]) - - (img_sums[SUMS_PTR(0, tpl_rows)] - img_sums[SUMS_PTR(0, 0)])); - - float image_sqsum_ = (float)( - (img_sqsums[SQSUMS_PTR(tpl_cols, tpl_rows)] - img_sqsums[SQSUMS_PTR(tpl_cols, 0)]) - - (img_sqsums[SQSUMS_PTR(0, tpl_rows)] - img_sqsums[SQSUMS_PTR(0, 0)])); - res[res_idx] = normAcc(res[res_idx] - image_sum_ * tpl_sum, - sqrt(tpl_sqsum * (image_sqsum_ - weight * image_sum_ * image_sum_))); - } -} -__kernel -void matchTemplate_Prepared_CCOFF_NORMED_C4_D0 -( - __global float * res, - int img_rows, - int img_cols, - int tpl_rows, - int tpl_cols, - int res_rows, - int res_cols, - int res_offset, - int res_step, - float weight, - __global const uint * img_sums_c0, - __global const uint * img_sums_c1, - __global const uint * img_sums_c2, - __global const uint * img_sums_c3, - int img_sums_offset, - int img_sums_step, - __global const float * img_sqsums_c0, - __global const float * img_sqsums_c1, - __global const float * img_sqsums_c2, - __global const float * img_sqsums_c3, - int img_sqsums_offset, - int img_sqsums_step, - float tpl_sum_c0, - float tpl_sum_c1, - float tpl_sum_c2, - float tpl_sum_c3, - float tpl_sqsum -) -{ - int gidx = get_global_id(0); - int gidy = get_global_id(1); - - img_sqsums_step /= sizeof(*img_sqsums_c0); - img_sqsums_offset /= sizeof(*img_sqsums_c0); - img_sums_offset /= sizeof(*img_sums_c0); - img_sums_step /= sizeof(*img_sums_c0); - res_step /= sizeof(*res); - res_offset /= sizeof(*res); - - int res_idx = mad24(gidy, res_step, res_offset + gidx); - - if(gidx < res_cols && gidy < res_rows) - { - float image_sum_c0 = (float)( - (img_sums_c0[SUMS_PTR(tpl_cols, tpl_rows)] - img_sums_c0[SUMS_PTR(tpl_cols, 0)]) - - (img_sums_c0[SUMS_PTR(0, tpl_rows)] - img_sums_c0[SUMS_PTR(0, 0)])); - float image_sum_c1 = (float)( - (img_sums_c1[SUMS_PTR(tpl_cols, tpl_rows)] - img_sums_c1[SUMS_PTR(tpl_cols, 0)]) - - (img_sums_c1[SUMS_PTR(0, tpl_rows)] - img_sums_c1[SUMS_PTR(0, 0)])); - float image_sum_c2 = (float)( - (img_sums_c2[SUMS_PTR(tpl_cols, tpl_rows)] - img_sums_c2[SUMS_PTR(tpl_cols, 0)]) - - (img_sums_c2[SUMS_PTR(0, tpl_rows)] - img_sums_c2[SUMS_PTR(0, 0)])); - float image_sum_c3 = (float)( - (img_sums_c3[SUMS_PTR(tpl_cols, tpl_rows)] - img_sums_c3[SUMS_PTR(tpl_cols, 0)]) - - (img_sums_c3[SUMS_PTR(0, tpl_rows)] - img_sums_c3[SUMS_PTR(0, 0)])); - - float image_sqsum_c0 = (float)( - (img_sqsums_c0[SQSUMS_PTR(tpl_cols, tpl_rows)] - img_sqsums_c0[SQSUMS_PTR(tpl_cols, 0)]) - - (img_sqsums_c0[SQSUMS_PTR(0, tpl_rows)] - img_sqsums_c0[SQSUMS_PTR(0, 0)])); - float image_sqsum_c1 = (float)( - (img_sqsums_c1[SQSUMS_PTR(tpl_cols, tpl_rows)] - img_sqsums_c1[SQSUMS_PTR(tpl_cols, 0)]) - - (img_sqsums_c1[SQSUMS_PTR(0, tpl_rows)] - img_sqsums_c1[SQSUMS_PTR(0, 0)])); - float image_sqsum_c2 = (float)( - (img_sqsums_c2[SQSUMS_PTR(tpl_cols, tpl_rows)] - img_sqsums_c2[SQSUMS_PTR(tpl_cols, 0)]) - - (img_sqsums_c2[SQSUMS_PTR(0, tpl_rows)] - img_sqsums_c2[SQSUMS_PTR(0, 0)])); - float image_sqsum_c3 = (float)( - (img_sqsums_c3[SQSUMS_PTR(tpl_cols, tpl_rows)] - img_sqsums_c3[SQSUMS_PTR(tpl_cols, 0)]) - - (img_sqsums_c3[SQSUMS_PTR(0, tpl_rows)] - img_sqsums_c3[SQSUMS_PTR(0, 0)])); - - float num = res[res_idx] - - image_sum_c0 * tpl_sum_c0 - - image_sum_c1 * tpl_sum_c1 - - image_sum_c2 * tpl_sum_c2 - - image_sum_c3 * tpl_sum_c3; - float denum = sqrt( tpl_sqsum * ( - image_sqsum_c0 - weight * image_sum_c0 * image_sum_c0 + - image_sqsum_c1 - weight * image_sum_c1 * image_sum_c1 + - image_sqsum_c2 - weight * image_sum_c2 * image_sum_c2 + - image_sqsum_c3 - weight * image_sum_c0 * image_sum_c3) - ); - res[res_idx] = normAcc(num, denum); - } -} - -////////////////////////////////////////////////////////////////////// -// extractFirstChannel -__kernel -void extractFirstChannel -( - const __global float4* img, - __global float* res, - int rows, - int cols, - int img_offset, - int res_offset, - int img_step, - int res_step -) -{ - img_step /= sizeof(float4); - res_step /= sizeof(float); - img_offset /= sizeof(float4); - res_offset /= sizeof(float); - img += img_offset; - res += res_offset; - int gidx = get_global_id(0); - int gidy = get_global_id(1); - if(gidx < cols && gidy < rows) - { - res[gidx + gidy * res_step] = img[gidx + gidy * img_step].x; - } -} diff --git a/modules/ocl/src/opencl/meanShift.cl b/modules/ocl/src/opencl/meanShift.cl deleted file mode 100644 index 3fff473a8..000000000 --- a/modules/ocl/src/opencl/meanShift.cl +++ /dev/null @@ -1,241 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Shengen Yan,yanshengen@gmail.com -// Xu Pang, pangxu010@163.com -// Wenju He, wenju@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*/ - -inline short2 do_mean_shift(int x0, int y0, __global uchar4* out,int out_step, - __global uchar4* in, int in_step, int dst_off, int src_off, - int cols, int rows, int sp, int sr, int maxIter, float eps) -{ - int isr2 = sr*sr; - in_step = in_step >> 2; - out_step = out_step >> 2; - src_off = src_off >> 2; - dst_off = dst_off >> 2; - int idx = src_off + y0 * in_step + x0; - uchar4 c = in[idx]; - int base = dst_off + get_global_id(1)*out_step + get_global_id(0) ; - - // iterate meanshift procedure - for( int iter = 0; iter < maxIter; iter++ ) - { - int count = 0; - int4 s = (int4)0; - int sx = 0, sy = 0; - - //mean shift: process pixels in window (p-sigmaSp)x(p+sigmaSp) - //deal with the image boundary - int minx = (x0-sp)>0 ? x0-sp : 0; - int miny = (y0-sp)>0 ? y0-sp : 0; - int maxx = (x0+sp)>= 2; - outspstep >>= 2; - int basesp = outsp_off + y0 * outspstep + x0; - outsp[basesp] = do_mean_shift(x0, y0, outr, outrstep, in, instep, outr_off, in_off, cols, rows, sp, sr, maxIter, eps); -// outsp[basesp] =(short2)((short)x0,(short)y0); - } -} diff --git a/modules/ocl/src/opencl/merge_mat.cl b/modules/ocl/src/opencl/merge_mat.cl deleted file mode 100644 index aea05aeb8..000000000 --- a/modules/ocl/src/opencl/merge_mat.cl +++ /dev/null @@ -1,1378 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////optimized code using vector roi////////////////////////// -////////////vector fuction name format: merge_vector_C(channels number)D_(data type depth)////// -//////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void merge_vector_C2_D0(__global uchar *mat_dst, int dst_step, int dst_offset, - __global uchar *mat_src0, int src0_step, int src0_offset, - __global uchar *mat_src1, int src1_step, int src1_offset, - int rows, int cols, int dst_step1) - -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - x = x << 1; - - #define dst_align ((dst_offset & 3) >> 1) - int src0_index = mad24(y, src0_step, src0_offset + x - dst_align); - int src1_index = mad24(y, src1_step, src1_offset + x - dst_align); - - int dst_start = mad24(y, dst_step, dst_offset); - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + (x << 1) & (int)0xfffffffc); - - __global uchar4 * dst = (__global uchar4 *)(mat_dst + dst_index); - __global uchar * src0 = mat_src0 + src0_index; - __global uchar * src1 = src0 + 1; - __global uchar * src2 = mat_src1 + src1_index; - __global uchar * src3 = src2 + 1; - - uchar4 dst_data = *dst; - uchar data_0 = *(src0); - uchar data_1 = *(src1); - uchar data_2 = *(src2); - uchar data_3 = *(src3); - - uchar4 tmp_data = (uchar4)(data_0, data_2, data_1, data_3); - - tmp_data.xy = dst_index + 0 >= dst_start ? tmp_data.xy : dst_data.xy; - tmp_data.zw = dst_index + 2 < dst_end ? tmp_data.zw : dst_data.zw; - - *dst = tmp_data; - } -} -__kernel void merge_vector_C2_D1(__global char *mat_dst, int dst_step, int dst_offset, - __global char *mat_src0, int src0_step, int src0_offset, - __global char *mat_src1, int src1_step, int src1_offset, - int rows, int cols, int dst_step1) - -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - x = x << 1; - - #define dst_align ((dst_offset & 3) >> 1) - int src0_index = mad24(y, src0_step, src0_offset + x - dst_align); - int src1_index = mad24(y, src1_step, src1_offset + x - dst_align); - - int dst_start = mad24(y, dst_step, dst_offset); - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + (x << 1) & (int)0xfffffffc); - - __global char4 * dst = (__global char4 *)(mat_dst + dst_index); - __global char * src0 = mat_src0 + src0_index; - __global char * src1 = src0 + 1; - __global char * src2 = mat_src1 + src1_index; - __global char * src3 = src2 + 1; - - char4 dst_data = *dst; - char data_0 = *(src0); - char data_1 = *(src1); - char data_2 = *(src2); - char data_3 = *(src3); - - char4 tmp_data = (char4)(data_0, data_2, data_1, data_3); - - tmp_data.xy = dst_index + 0 >= dst_start ? tmp_data.xy : dst_data.xy; - tmp_data.zw = dst_index + 2 < dst_end ? tmp_data.zw : dst_data.zw; - - *dst = tmp_data; - } -} -__kernel void merge_vector_C2_D2(__global ushort *mat_dst, int dst_step, int dst_offset, - __global ushort *mat_src0, int src0_step, int src0_offset, - __global ushort *mat_src1, int src1_step, int src1_offset, - int rows, int cols, int dst_step1) - -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - - int dst_index = mad24(y, dst_step , dst_offset); - - __global ushort* src0 = (__global ushort * )((__global uchar *)mat_src0 + src0_index + (x << 1)); - __global ushort* src1 = (__global ushort * )((__global uchar *)mat_src1 + src1_index + (x << 1)); - __global ushort2* dist = (__global ushort2 *)((__global uchar *)mat_dst + dst_index + (x << 2)); - - ushort src0_data = *src0; - ushort src1_data = *src1; - - *dist = (ushort2)(src0_data, src1_data); - - } -} -__kernel void merge_vector_C2_D3(__global short *mat_dst, int dst_step, int dst_offset, - __global short *mat_src0, int src0_step, int src0_offset, - __global short *mat_src1, int src1_step, int src1_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - - int dst_index = mad24(y, dst_step , dst_offset); - - __global short* src0 = (__global short * )((__global uchar *)mat_src0 + src0_index + (x << 1)); - __global short* src1 = (__global short * )((__global uchar *)mat_src1 + src1_index + (x << 1)); - __global short2* dist = (__global short2 *)((__global uchar *)mat_dst + dst_index + (x << 2)); - - short src0_data = *src0; - short src1_data = *src1; - - *dist = (short2)(src0_data, src1_data); - } -} - -__kernel void merge_vector_C2_D4(__global int *mat_dst, int dst_step, int dst_offset, - __global int *mat_src0, int src0_step, int src0_offset, - __global int *mat_src1, int src1_step, int src1_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - int dst_index = mad24(y, dst_step , dst_offset); - - int src0 = *((__global int *)((__global uchar *)mat_src0 + src0_index + (x << 2))); - int src1 = *((__global int *)((__global uchar *)mat_src1 + src1_index + (x << 2))); - - *((__global int2 *)((__global uchar *)mat_dst + dst_index + (x << 3))) = (int2)(src0, src1); - } -} -__kernel void merge_vector_C2_D5(__global float *mat_dst, int dst_step, int dst_offset, - __global float *mat_src0, int src0_step, int src0_offset, - __global float *mat_src1, int src1_step, int src1_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - int dst_index = mad24(y, dst_step , dst_offset); - - float src0 = *((__global float *)((__global uchar *)mat_src0 + src0_index + (x << 2))); - float src1 = *((__global float *)((__global uchar *)mat_src1 + src1_index + (x << 2))); - - *((__global float2 *)((__global uchar *)mat_dst + dst_index + (x << 3))) = (float2)(src0, src1); - } -} - -#if defined (DOUBLE_SUPPORT) -__kernel void merge_vector_C2_D6(__global double *mat_dst, int dst_step, int dst_offset, - __global double *mat_src0, int src0_step, int src0_offset, - __global double *mat_src1, int src1_step, int src1_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - int dst_index = mad24(y, dst_step , dst_offset); - - double src0 = *((__global double *)((__global uchar *)mat_src0 + src0_index + (x << 3))); - double src1 = *((__global double *)((__global uchar *)mat_src1 + src1_index + (x << 3))); - - *((__global double2 *)((__global uchar *)mat_dst + dst_index + (x << 4))) = (double2)(src0, src1); - } -} -#endif - -__kernel void merge_vector_C3_D0(__global uchar *mat_dst, int dst_step, int dst_offset, - __global uchar *mat_src0, int src0_step, int src0_offset, - __global uchar *mat_src1, int src1_step, int src1_offset, - __global uchar *mat_src2, int src2_step, int src2_offset, int offset_cols, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - x = x << 2; - - int src0_index = mad24(y, src0_step, x + src0_offset - offset_cols); - int src1_index = mad24(y, src1_step, x + src1_offset - offset_cols); - int src2_index = mad24(y, src2_step, x + src2_offset - offset_cols); - - int dst_start = mad24(y, dst_step, dst_offset); - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + 3 * x - offset_cols * 3); - - uchar data0_0 = *(mat_src0 + src0_index + 0); - uchar data0_1 = *(mat_src0 + src0_index + 1); - uchar data0_2 = *(mat_src0 + src0_index + 2); - uchar data0_3 = *(mat_src0 + src0_index + 3); - - uchar data1_0 = *(mat_src1 + src1_index + 0); - uchar data1_1 = *(mat_src1 + src1_index + 1); - uchar data1_2 = *(mat_src1 + src1_index + 2); - uchar data1_3 = *(mat_src1 + src1_index + 3); - - uchar data2_0 = *(mat_src2 + src2_index + 0); - uchar data2_1 = *(mat_src2 + src2_index + 1); - uchar data2_2 = *(mat_src2 + src2_index + 2); - uchar data2_3 = *(mat_src2 + src2_index + 3); - - uchar4 tmp_data0 = (uchar4)(data0_0, data1_0, data2_0, data0_1); - uchar4 tmp_data1 = (uchar4)(data1_1, data2_1, data0_2, data1_2); - uchar4 tmp_data2 = (uchar4)(data2_2, data0_3, data1_3, data2_3); - - uchar4 dst_data0 = *((__global uchar4*)(mat_dst + dst_index + 0)); - uchar4 dst_data1 = *((__global uchar4*)(mat_dst + dst_index + 4)); - uchar4 dst_data2 = *((__global uchar4*)(mat_dst + dst_index + 8)); - - tmp_data0.x = ((dst_index + 0 >= dst_start) && (dst_index + 0 < dst_end)) ? tmp_data0.x : dst_data0.x; - tmp_data0.y = ((dst_index + 1 >= dst_start) && (dst_index + 1 < dst_end)) ? tmp_data0.y : dst_data0.y; - tmp_data0.z = ((dst_index + 2 >= dst_start) && (dst_index + 2 < dst_end)) ? tmp_data0.z : dst_data0.z; - tmp_data0.w = ((dst_index + 3 >= dst_start) && (dst_index + 3 < dst_end)) ? tmp_data0.w : dst_data0.w; - - tmp_data1.x = ((dst_index + 4 >= dst_start) && (dst_index + 4 < dst_end)) ? tmp_data1.x : dst_data1.x; - tmp_data1.y = ((dst_index + 5 >= dst_start) && (dst_index + 5 < dst_end)) ? tmp_data1.y : dst_data1.y; - tmp_data1.z = ((dst_index + 6 >= dst_start) && (dst_index + 6 < dst_end)) ? tmp_data1.z : dst_data1.z; - tmp_data1.w = ((dst_index + 7 >= dst_start) && (dst_index + 7 < dst_end)) ? tmp_data1.w : dst_data1.w; - - tmp_data2.x = ((dst_index + 8 >= dst_start) && (dst_index + 8 < dst_end)) ? tmp_data2.x : dst_data2.x; - tmp_data2.y = ((dst_index + 9 >= dst_start) && (dst_index + 9 < dst_end)) ? tmp_data2.y : dst_data2.y; - tmp_data2.z = ((dst_index + 10 >= dst_start) && (dst_index + 10 < dst_end)) ? tmp_data2.z : dst_data2.z; - tmp_data2.w = ((dst_index + 11 >= dst_start) && (dst_index + 11 < dst_end)) ? tmp_data2.w : dst_data2.w; - - *((__global uchar4*)(mat_dst + dst_index + 0)) = tmp_data0; - *((__global uchar4*)(mat_dst + dst_index + 4)) = tmp_data1; - *((__global uchar4*)(mat_dst + dst_index + 8)) = tmp_data2; - } -} -__kernel void merge_vector_C3_D1(__global char *mat_dst, int dst_step, int dst_offset, - __global char *mat_src0, int src0_step, int src0_offset, - __global char *mat_src1, int src1_step, int src1_offset, - __global char *mat_src2, int src2_step, int src2_offset, int offset_cols, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - x = x << 2; - - int src0_index = mad24(y, src0_step, x + src0_offset - offset_cols); - int src1_index = mad24(y, src1_step, x + src1_offset - offset_cols); - int src2_index = mad24(y, src2_step, x + src2_offset - offset_cols); - - int dst_start = mad24(y, dst_step, dst_offset); - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + 3 * x - offset_cols * 3); - - char data0_0 = *(mat_src0 + src0_index + 0); - char data0_1 = *(mat_src0 + src0_index + 1); - char data0_2 = *(mat_src0 + src0_index + 2); - char data0_3 = *(mat_src0 + src0_index + 3); - - char data1_0 = *(mat_src1 + src1_index + 0); - char data1_1 = *(mat_src1 + src1_index + 1); - char data1_2 = *(mat_src1 + src1_index + 2); - char data1_3 = *(mat_src1 + src1_index + 3); - - char data2_0 = *(mat_src2 + src2_index + 0); - char data2_1 = *(mat_src2 + src2_index + 1); - char data2_2 = *(mat_src2 + src2_index + 2); - char data2_3 = *(mat_src2 + src2_index + 3); - - char4 tmp_data0 = (char4)(data0_0, data1_0, data2_0, data0_1); - char4 tmp_data1 = (char4)(data1_1, data2_1, data0_2, data1_2); - char4 tmp_data2 = (char4)(data2_2, data0_3, data1_3, data2_3); - - char4 dst_data0 = *((__global char4*)(mat_dst + dst_index + 0)); - char4 dst_data1 = *((__global char4*)(mat_dst + dst_index + 4)); - char4 dst_data2 = *((__global char4*)(mat_dst + dst_index + 8)); - - tmp_data0.x = ((dst_index + 0 >= dst_start) && (dst_index + 0 < dst_end)) ? tmp_data0.x : dst_data0.x; - tmp_data0.y = ((dst_index + 1 >= dst_start) && (dst_index + 1 < dst_end)) ? tmp_data0.y : dst_data0.y; - tmp_data0.z = ((dst_index + 2 >= dst_start) && (dst_index + 2 < dst_end)) ? tmp_data0.z : dst_data0.z; - tmp_data0.w = ((dst_index + 3 >= dst_start) && (dst_index + 3 < dst_end)) ? tmp_data0.w : dst_data0.w; - - tmp_data1.x = ((dst_index + 4 >= dst_start) && (dst_index + 4 < dst_end)) ? tmp_data1.x : dst_data1.x; - tmp_data1.y = ((dst_index + 5 >= dst_start) && (dst_index + 5 < dst_end)) ? tmp_data1.y : dst_data1.y; - tmp_data1.z = ((dst_index + 6 >= dst_start) && (dst_index + 6 < dst_end)) ? tmp_data1.z : dst_data1.z; - tmp_data1.w = ((dst_index + 7 >= dst_start) && (dst_index + 7 < dst_end)) ? tmp_data1.w : dst_data1.w; - - tmp_data2.x = ((dst_index + 8 >= dst_start) && (dst_index + 8 < dst_end)) ? tmp_data2.x : dst_data2.x; - tmp_data2.y = ((dst_index + 9 >= dst_start) && (dst_index + 9 < dst_end)) ? tmp_data2.y : dst_data2.y; - tmp_data2.z = ((dst_index + 10 >= dst_start) && (dst_index + 10 < dst_end)) ? tmp_data2.z : dst_data2.z; - tmp_data2.w = ((dst_index + 11 >= dst_start) && (dst_index + 11 < dst_end)) ? tmp_data2.w : dst_data2.w; - - *((__global char4*)(mat_dst + dst_index + 0)) = tmp_data0; - *((__global char4*)(mat_dst + dst_index + 4)) = tmp_data1; - *((__global char4*)(mat_dst + dst_index + 8)) = tmp_data2; - } -} -__kernel void merge_vector_C3_D2(__global ushort *mat_dst, int dst_step, int dst_offset, - __global ushort *mat_src0, int src0_step, int src0_offset, - __global ushort *mat_src1, int src1_step, int src1_offset, - __global ushort *mat_src2, int src2_step, int src2_offset, int offset_cols, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - x = x << 1; - - int src0_index = mad24(y, src0_step, (x << 1) + src0_offset - offset_cols); - int src1_index = mad24(y, src1_step, (x << 1) + src1_offset - offset_cols); - int src2_index = mad24(y, src2_step, (x << 1) + src2_offset - offset_cols); - - int dst_start = mad24(y, dst_step, dst_offset); - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + 6 * x - offset_cols * 6); - - ushort data0_0 = *((__global ushort *)((__global char *)mat_src0 + src0_index + 0)); - ushort data0_1 = *((__global ushort *)((__global char *)mat_src0 + src0_index + 2)); - - ushort data1_0 = *((__global ushort *)((__global char *)mat_src1 + src1_index + 0)); - ushort data1_1 = *((__global ushort *)((__global char *)mat_src1 + src1_index + 2)); - - ushort data2_0 = *((__global ushort *)((__global char *)mat_src2 + src2_index + 0)); - ushort data2_1 = *((__global ushort *)((__global char *)mat_src2 + src2_index + 2)); - - ushort2 tmp_data0 = (ushort2)(data0_0, data1_0); - ushort2 tmp_data1 = (ushort2)(data2_0, data0_1); - ushort2 tmp_data2 = (ushort2)(data1_1, data2_1); - - ushort2 dst_data0 = *((__global ushort2*)((__global char *)mat_dst + dst_index + 0)); - ushort2 dst_data1 = *((__global ushort2*)((__global char *)mat_dst + dst_index + 4)); - ushort2 dst_data2 = *((__global ushort2*)((__global char *)mat_dst + dst_index + 8)); - - tmp_data0.x = ((dst_index + 0 >= dst_start) && (dst_index + 0 < dst_end)) ? tmp_data0.x : dst_data0.x; - tmp_data0.y = ((dst_index + 2 >= dst_start) && (dst_index + 2 < dst_end)) ? tmp_data0.y : dst_data0.y; - - tmp_data1.x = ((dst_index + 4 >= dst_start) && (dst_index + 4 < dst_end)) ? tmp_data1.x : dst_data1.x; - tmp_data1.y = ((dst_index + 6 >= dst_start) && (dst_index + 6 < dst_end)) ? tmp_data1.y : dst_data1.y; - - tmp_data2.x = ((dst_index + 8 >= dst_start) && (dst_index + 8 < dst_end)) ? tmp_data2.x : dst_data2.x; - tmp_data2.y = ((dst_index + 10 >= dst_start) && (dst_index + 10 < dst_end)) ? tmp_data2.y : dst_data2.y; - - *((__global ushort2*)((__global char *)mat_dst + dst_index + 0)) = tmp_data0; - *((__global ushort2*)((__global char *)mat_dst + dst_index + 4)) = tmp_data1; - *((__global ushort2*)((__global char *)mat_dst + dst_index + 8)) = tmp_data2; - } -} -__kernel void merge_vector_C3_D3(__global short *mat_dst, int dst_step, int dst_offset, - __global short *mat_src0, int src0_step, int src0_offset, - __global short *mat_src1, int src1_step, int src1_offset, - __global short *mat_src2, int src2_step, int src2_offset, int offset_cols, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - x = x << 1; - - int src0_index = mad24(y, src0_step, (x << 1) + src0_offset - offset_cols); - int src1_index = mad24(y, src1_step, (x << 1) + src1_offset - offset_cols); - int src2_index = mad24(y, src2_step, (x << 1) + src2_offset - offset_cols); - - int dst_start = mad24(y, dst_step, dst_offset); - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + 6 * x - offset_cols * 6); - - short data0_0 = *((__global short *)((__global char *)mat_src0 + src0_index + 0)); - short data0_1 = *((__global short *)((__global char *)mat_src0 + src0_index + 2)); - - short data1_0 = *((__global short *)((__global char *)mat_src1 + src1_index + 0)); - short data1_1 = *((__global short *)((__global char *)mat_src1 + src1_index + 2)); - - short data2_0 = *((__global short *)((__global char *)mat_src2 + src2_index + 0)); - short data2_1 = *((__global short *)((__global char *)mat_src2 + src2_index + 2)); - - short2 tmp_data0 = (short2)(data0_0, data1_0); - short2 tmp_data1 = (short2)(data2_0, data0_1); - short2 tmp_data2 = (short2)(data1_1, data2_1); - - short2 dst_data0 = *((__global short2*)((__global char *)mat_dst + dst_index + 0)); - short2 dst_data1 = *((__global short2*)((__global char *)mat_dst + dst_index + 4)); - short2 dst_data2 = *((__global short2*)((__global char *)mat_dst + dst_index + 8)); - - tmp_data0.x = ((dst_index + 0 >= dst_start) && (dst_index + 0 < dst_end)) ? tmp_data0.x : dst_data0.x; - tmp_data0.y = ((dst_index + 2 >= dst_start) && (dst_index + 2 < dst_end)) ? tmp_data0.y : dst_data0.y; - - tmp_data1.x = ((dst_index + 4 >= dst_start) && (dst_index + 4 < dst_end)) ? tmp_data1.x : dst_data1.x; - tmp_data1.y = ((dst_index + 6 >= dst_start) && (dst_index + 6 < dst_end)) ? tmp_data1.y : dst_data1.y; - - tmp_data2.x = ((dst_index + 8 >= dst_start) && (dst_index + 8 < dst_end)) ? tmp_data2.x : dst_data2.x; - tmp_data2.y = ((dst_index + 10 >= dst_start) && (dst_index + 10 < dst_end)) ? tmp_data2.y : dst_data2.y; - - *((__global short2*)((__global char *)mat_dst + dst_index + 0)) = tmp_data0; - *((__global short2*)((__global char *)mat_dst + dst_index + 4)) = tmp_data1; - *((__global short2*)((__global char *)mat_dst + dst_index + 8)) = tmp_data2; - } -} -__kernel void merge_vector_C3_D4(__global int *mat_dst, int dst_step, int dst_offset, - __global int *mat_src0, int src0_step, int src0_offset, - __global int *mat_src1, int src1_step, int src1_offset, - __global int *mat_src2, int src2_step, int src2_offset, int offset_cols, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - int src2_index = mad24(y, src2_step, src2_offset); - - int dst_index = mad24(y, dst_step , dst_offset); - - __global int* src0 = (__global int * )((__global uchar *)mat_src0 + src0_index + (x << 2)); - __global int* src1 = (__global int * )((__global uchar *)mat_src1 + src1_index + (x << 2)); - __global int* src2 = (__global int * )((__global uchar *)mat_src2 + src2_index + (x << 2)); - - __global int* dist0 = (__global int *)((__global uchar *)mat_dst + dst_index + 3 * (x << 2)); - __global int* dist1 = dist0 + 1; - __global int* dist2 = dist0 + 2; - - int src0_data = *src0; - int src1_data = *src1; - int src2_data = *src2; - - *dist0 = src0_data; - *dist1 = src1_data; - *dist2 = src2_data; - } -} -__kernel void merge_vector_C3_D5(__global float *mat_dst, int dst_step, int dst_offset, - __global float *mat_src0, int src0_step, int src0_offset, - __global float *mat_src1, int src1_step, int src1_offset, - __global float *mat_src2, int src2_step, int src2_offset, int offset_cols, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - int src2_index = mad24(y, src2_step, src2_offset); - - int dst_index = mad24(y, dst_step , dst_offset); - - __global float* src0 = (__global float * )((__global uchar *)mat_src0 + src0_index + (x << 2)); - __global float* src1 = (__global float * )((__global uchar *)mat_src1 + src1_index + (x << 2)); - __global float* src2 = (__global float * )((__global uchar *)mat_src2 + src2_index + (x << 2)); - - __global float* dist0 = (__global float *)((__global uchar *)mat_dst + dst_index + 3 * (x << 2)); - __global float* dist1 = dist0 + 1; - __global float* dist2 = dist0 + 2; - - float src0_data = *src0; - float src1_data = *src1; - float src2_data = *src2; - - *dist0 = src0_data; - *dist1 = src1_data; - *dist2 = src2_data; - } -} - -#if defined (DOUBLE_SUPPORT) -__kernel void merge_vector_C3_D6(__global double *mat_dst, int dst_step, int dst_offset, - __global double *mat_src0, int src0_step, int src0_offset, - __global double *mat_src1, int src1_step, int src1_offset, - __global double *mat_src2, int src2_step, int src2_offset, int offset_cols, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - int src2_index = mad24(y, src2_step, src2_offset); - - int dst_index = mad24(y, dst_step , dst_offset); - - __global double* src0 = (__global double * )((__global uchar *)mat_src0 + src0_index + (x << 3)); - __global double* src1 = (__global double * )((__global uchar *)mat_src1 + src1_index + (x << 3)); - __global double* src2 = (__global double * )((__global uchar *)mat_src2 + src2_index + (x << 3)); - - __global double* dist0 = (__global double *)((__global uchar *)mat_dst + dst_index + 3 * (x << 3)); - __global double* dist1 = dist0 + 1; - __global double* dist2 = dist0 + 2; - - double src0_data = *src0; - double src1_data = *src1; - double src2_data = *src2; - - *dist0 = src0_data; - *dist1 = src1_data; - *dist2 = src2_data; - } -} -#endif -__kernel void merge_vector_C4_D0(__global uchar *mat_dst, int dst_step, int dst_offset, - __global uchar *mat_src0, int src0_step, int src0_offset, - __global uchar *mat_src1, int src1_step, int src1_offset, - __global uchar *mat_src2, int src2_step, int src2_offset, - __global uchar *mat_src3, int src3_step, int src3_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - int src2_index = mad24(y, src2_step, src2_offset); - int src3_index = mad24(y, src3_step, src3_offset); - int dst_index = mad24(y, dst_step , dst_offset); - - uchar src0 = *(mat_src0 + src0_index + x ); - uchar src1 = *(mat_src1 + src1_index + x); - uchar src2 = *(mat_src2 + src2_index + x); - uchar src3 = *(mat_src3 + src3_index + x); - - *((__global uchar4 *)(mat_dst + dst_index + (x << 2))) = (uchar4)(src0, src1, src2, src3); - } -} -__kernel void merge_vector_C4_D1(__global char *mat_dst, int dst_step, int dst_offset, - __global char *mat_src0, int src0_step, int src0_offset, - __global char *mat_src1, int src1_step, int src1_offset, - __global char *mat_src2, int src2_step, int src2_offset, - __global char *mat_src3, int src3_step, int src3_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - int src2_index = mad24(y, src2_step, src2_offset); - int src3_index = mad24(y, src3_step, src3_offset); - int dst_index = mad24(y, dst_step , dst_offset); - - char src0 = *(mat_src0 + src0_index + x ); - char src1 = *(mat_src1 + src1_index + x); - char src2 = *(mat_src2 + src2_index + x); - char src3 = *(mat_src3 + src3_index + x); - - *((__global char4 *)(mat_dst + dst_index + (x << 2))) = (char4)(src0, src1, src2, src3); - } -} -__kernel void merge_vector_C4_D2(__global ushort *mat_dst, int dst_step, int dst_offset, - __global ushort *mat_src0, int src0_step, int src0_offset, - __global ushort *mat_src1, int src1_step, int src1_offset, - __global ushort *mat_src2, int src2_step, int src2_offset, - __global ushort *mat_src3, int src3_step, int src3_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - int src2_index = mad24(y, src2_step, src2_offset); - int src3_index = mad24(y, src3_step, src3_offset); - int dst_index = mad24(y, dst_step , dst_offset); - - ushort src0 = *((__global ushort *)((__global uchar *)mat_src0 + src0_index + (x << 1))); - ushort src1 = *((__global ushort *)((__global uchar *)mat_src1 + src1_index + (x << 1))); - ushort src2 = *((__global ushort *)((__global uchar *)mat_src2 + src2_index + (x << 1))); - ushort src3 = *((__global ushort *)((__global uchar *)mat_src3 + src3_index + (x << 1))); - - *((__global ushort4 *)((__global uchar *)mat_dst + dst_index + (x << 3))) = (ushort4)(src0, src1, src2, src3); - } -} -__kernel void merge_vector_C4_D3(__global short *mat_dst, int dst_step, int dst_offset, - __global short *mat_src0, int src0_step, int src0_offset, - __global short *mat_src1, int src1_step, int src1_offset, - __global short *mat_src2, int src2_step, int src2_offset, - __global short *mat_src3, int src3_step, int src3_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - int src2_index = mad24(y, src2_step, src2_offset); - int src3_index = mad24(y, src3_step, src3_offset); - int dst_index = mad24(y, dst_step , dst_offset); - - short src0 = *((__global short *)((__global uchar *)mat_src0 + src0_index + (x << 1))); - short src1 = *((__global short *)((__global uchar *)mat_src1 + src1_index + (x << 1))); - short src2 = *((__global short *)((__global uchar *)mat_src2 + src2_index + (x << 1))); - short src3 = *((__global short *)((__global uchar *)mat_src3 + src3_index + (x << 1))); - - *((__global short4 *)((__global uchar *)mat_dst + dst_index + (x << 3))) = (short4)(src0, src1, src2, src3); - } -} -__kernel void merge_vector_C4_D4(__global int *mat_dst, int dst_step, int dst_offset, - __global int *mat_src0, int src0_step, int src0_offset, - __global int *mat_src1, int src1_step, int src1_offset, - __global int *mat_src2, int src2_step, int src2_offset, - __global int *mat_src3, int src3_step, int src3_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - int src2_index = mad24(y, src2_step, src2_offset); - int src3_index = mad24(y, src3_step, src3_offset); - int dst_index = mad24(y, dst_step , dst_offset); - - int src0 = *((__global int *)((__global uchar *)mat_src0 + src0_index + (x << 2))); - int src1 = *((__global int *)((__global uchar *)mat_src1 + src1_index + (x << 2))); - int src2 = *((__global int *)((__global uchar *)mat_src2 + src2_index + (x << 2))); - int src3 = *((__global int *)((__global uchar *)mat_src3 + src3_index + (x << 2))); - - *((__global int4 *)((__global uchar *)mat_dst + dst_index + (x << 4))) = (int4)(src0, src1, src2, src3); - } -} -__kernel void merge_vector_C4_D5(__global float *mat_dst, int dst_step, int dst_offset, - __global float *mat_src0, int src0_step, int src0_offset, - __global float *mat_src1, int src1_step, int src1_offset, - __global float *mat_src2, int src2_step, int src2_offset, - __global float *mat_src3, int src3_step, int src3_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - int src2_index = mad24(y, src2_step, src2_offset); - int src3_index = mad24(y, src3_step, src3_offset); - int dst_index = mad24(y, dst_step , dst_offset); - - float src0 = *((__global float *)((__global uchar *)mat_src0 + src0_index + (x << 2))); - float src1 = *((__global float *)((__global uchar *)mat_src1 + src1_index + (x << 2))); - float src2 = *((__global float *)((__global uchar *)mat_src2 + src2_index + (x << 2))); - float src3 = *((__global float *)((__global uchar *)mat_src3 + src3_index + (x << 2))); - - *((__global float4 *)((__global uchar *)mat_dst + dst_index + (x << 4))) = (float4)(src0, src1, src2, src3); - } -} - -#if defined (DOUBLE_SUPPORT) -__kernel void merge_vector_C4_D6(__global double *mat_dst, int dst_step, int dst_offset, - __global double *mat_src0, int src0_step, int src0_offset, - __global double *mat_src1, int src1_step, int src1_offset, - __global double *mat_src2, int src2_step, int src2_offset, - __global double *mat_src3, int src3_step, int src3_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - int src0_index = mad24(y, src0_step, src0_offset); - int src1_index = mad24(y, src1_step, src1_offset); - int src2_index = mad24(y, src2_step, src2_offset); - int src3_index = mad24(y, src3_step, src3_offset); - int dst_index = mad24(y, dst_step , dst_offset); - - double src0 = *((__global double *)((__global uchar *)mat_src0 + src0_index + (x << 3))); - double src1 = *((__global double *)((__global uchar *)mat_src1 + src1_index + (x << 3))); - double src2 = *((__global double *)((__global uchar *)mat_src2 + src2_index + (x << 3))); - double src3 = *((__global double *)((__global uchar *)mat_src3 + src3_index + (x << 3))); - - *((__global double4 *)((__global uchar *)mat_dst + dst_index + (x << 5))) = (double4)(src0, src1, src2, src3); - } -} -#endif -/////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////optimized code using vector no roi////////////////////////// -////////////vector fuction name format: merge_vector_C(channels number)D_(data type depth)////// -//////////////////////////////////////////////////////////////////////////////////////////////// -__kernel void merge_vector_C2_D0_1(int rows, int cols, - __global uchar *mat_dst, int dst_step, - __global uchar *mat_src0, int src0_step, - __global uchar *mat_src1, int src1_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global uchar4 *src0_y = (__global uchar4 * )(mat_src0 + y * src0_step); - __global uchar4 *src1_y = (__global uchar4 * )(mat_src1 + y * src1_step); - __global uchar8 *dst_y = (__global uchar8 *)(mat_dst + y * dst_step); - - uchar4 value1 = src0_y[x]; - uchar4 value2 = src1_y[x]; - - uchar8 value; - value.even = value1; - value.odd = value2; - - dst_y[x] = value; - } -} -__kernel void merge_vector_C2_D1_1(int rows, int cols, - __global char *mat_dst, int dst_step, - __global char *mat_src0, int src0_step, - __global char *mat_src1, int src1_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global char4 *src0_y = (__global char4 * )(mat_src0 + y * src0_step); - __global char4 *src1_y = (__global char4 * )(mat_src1 + y * src1_step); - __global char8 *dst_y = (__global char8 *)(mat_dst + y * dst_step); - - char4 value1 = src0_y[x]; - char4 value2 = src1_y[x]; - - char8 value; - value.even = value1; - value.odd = value2; - - dst_y[x] = value; - } -} -__kernel void merge_vector_C2_D2_1(int rows, int cols, - __global ushort *mat_dst, int dst_step, - __global ushort *mat_src0, int src0_step, - __global ushort *mat_src1, int src1_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global ushort2 *src0_y = (__global ushort2 *)((__global uchar *)mat_src0 + y * src0_step); - __global ushort2 *src1_y = (__global ushort2 *)((__global uchar *)mat_src1 + y * src1_step); - __global ushort4 *dst_y = (__global ushort4 *)((__global uchar *)mat_dst + y * dst_step); - - ushort2 value1 = src0_y[x]; - ushort2 value2 = src1_y[x]; - - ushort4 value; - value.even = value1; - value.odd = value2; - - dst_y[x] = value; - } -} -__kernel void merge_vector_C2_D3_1(int rows, int cols, - __global short *mat_dst, int dst_step, - __global short *mat_src0, int src0_step, - __global short *mat_src1, int src1_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global short2 *src0_y = (__global short2 *)((__global uchar *)mat_src0 + y * src0_step); - __global short2 *src1_y = (__global short2 *)((__global uchar *)mat_src1 + y * src1_step); - __global short4 *dst_y = (__global short4 *)((__global uchar *)mat_dst + y * dst_step); - - short2 value1 = src0_y[x]; - short2 value2 = src1_y[x]; - - short4 value; - value.even = value1; - value.odd = value2; - - dst_y[x] = value; - } -} - -__kernel void merge_vector_C2_D4_1(int rows, int cols, - __global int *mat_dst, int dst_step, - __global int *mat_src0, int src0_step, - __global int *mat_src1, int src1_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global int *src0_y = (__global int *)((__global uchar *)mat_src0 + y * src0_step); - __global int *src1_y = (__global int *)((__global uchar *)mat_src1 + y * src1_step); - __global int2 *dst_y = (__global int2 *)((__global uchar *)mat_dst + y * dst_step); - - int value1 = src0_y[x]; - int value2 = src1_y[x]; - - int2 value; - value.even = value1; - value.odd = value2; - - dst_y[x] = value; - } -} -__kernel void merge_vector_C2_D5_1(int rows, int cols, - __global float *mat_dst, int dst_step, - __global float *mat_src0, int src0_step, - __global float *mat_src1, int src1_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global float *src0_y = (__global float *)((__global uchar *)mat_src0 + y * src0_step); - __global float *src1_y = (__global float *)((__global uchar *)mat_src1 + y * src1_step); - __global float2 *dst_y = (__global float2 *)((__global uchar *)mat_dst + y * dst_step); - - float value1 = src0_y[x]; - float value2 = src1_y[x]; - - dst_y[x] = (float2)(value1, value2); - } -} - -#if defined (DOUBLE_SUPPORT) -__kernel void merge_vector_C2_D6_1(int rows, int cols, - __global double *mat_dst, int dst_step, - __global double *mat_src0, int src0_step, - __global double *mat_src1, int src1_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global double *src0_y = (__global double *)((__global uchar *)mat_src0 + y * src0_step); - __global double *src1_y = (__global double *)((__global uchar *)mat_src1 + y * src1_step); - __global double2 *dst_y = (__global double2 *)((__global uchar *)mat_dst + y * dst_step); - - double value1 = src0_y[x]; - double value2 = src1_y[x]; - - dst_y[x] = (double2)(value1, value2); - } -} -#endif - -__kernel void merge_vector_C3_D0_1(int rows, int cols, - __global uchar *mat_dst, int dst_step, - __global uchar *mat_src0, int src0_step, - __global uchar *mat_src1, int src1_step, - __global uchar *mat_src2, int src2_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global uchar4 *src0_y = (__global uchar4 * )(mat_src0 + y * src0_step); - __global uchar4 *src1_y = (__global uchar4 * )(mat_src1 + y * src1_step); - __global uchar4 *src2_y = (__global uchar4 * )(mat_src2 + y * src0_step); - - __global uchar4 *dst_y = (__global uchar4 *)(mat_dst + y * dst_step); - - uchar4 value0 = src0_y[x]; - uchar4 value1 = src1_y[x]; - uchar4 value2 = src2_y[x]; - - dst_y[3 * x + 0] = (uchar4)(value0.s0, value1.s0, value2.s0, - value0.s1); - - dst_y[3 * x + 1] = (uchar4)(value1.s1, value2.s1, - value0.s2, value1.s2); - - dst_y[3 * x + 2] = (uchar4)(value2.s2, - value0.s3, value1.s3, value2.s3); - - } -} -__kernel void merge_vector_C3_D1_1(int rows, int cols, - __global char *mat_dst, int dst_step, - __global char *mat_src0, int src0_step, - __global char *mat_src1, int src1_step, - __global char *mat_src2, int src2_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global char4 *src0_y = (__global char4 * )(mat_src0 + y * src0_step); - __global char4 *src1_y = (__global char4 * )(mat_src1 + y * src1_step); - __global char4 *src2_y = (__global char4 * )(mat_src2 + y * src0_step); - - __global char4 *dst_y = (__global char4 *)(mat_dst + y * dst_step); - - char4 value0 = src0_y[x]; - char4 value1 = src1_y[x]; - char4 value2 = src2_y[x]; - - dst_y[3 * x + 0] = (char4)(value0.s0, value1.s0, value2.s0, - value0.s1); - - dst_y[3 * x + 1] = (char4)(value1.s1, value2.s1, - value0.s2, value1.s2); - - dst_y[3 * x + 2] = (char4)(value2.s2, - value0.s3, value1.s3, value2.s3); - - /* for test do not delete - dst_y[3 * x + 0] = (char8)(value0.s0, value1.s0, value2.s0, - value0.s1, value1.s1, value2.s1, - value0.s2, value1.s2); - - dst_y[3 * x + 1] = (char8)(value2.s2, - value0.s3, value1.s3, value2.s3, - value0.s4, value1.s4, value2.s4, - value0.s5); - - dst_y[3 * x + 2] = (char8)(value1.s5, value2.s5, - value0.s6, value1.s6, value2.s6, - value0.s7, value1.s7, value2.s7); - */ - } -} -__kernel void merge_vector_C3_D2_1(int rows, int cols, - __global ushort *mat_dst, int dst_step, - __global ushort *mat_src0, int src0_step, - __global ushort *mat_src1, int src1_step, - __global ushort *mat_src2, int src2_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global ushort2 *src0_y = (__global ushort2 * )((__global char *)mat_src0 + y * src0_step); - __global ushort2 *src1_y = (__global ushort2 * )((__global char *)mat_src1 + y * src1_step); - __global ushort2 *src2_y = (__global ushort2 * )((__global char *)mat_src2 + y * src0_step); - - __global ushort2 *dst_y = (__global ushort2 *)((__global char *)mat_dst + y * dst_step); - - ushort2 value0 = src0_y[x]; - ushort2 value1 = src1_y[x]; - ushort2 value2 = src2_y[x]; - - dst_y[3 * x + 0] = (ushort2)(value0.x, value1.x); - dst_y[3 * x + 1] = (ushort2)(value2.x, value0.y); - dst_y[3 * x + 2] = (ushort2)(value1.y, value2.y); - - } -} -__kernel void merge_vector_C3_D3_1(int rows, int cols, - __global short *mat_dst, int dst_step, - __global short *mat_src0, int src0_step, - __global short *mat_src1, int src1_step, - __global short *mat_src2, int src2_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global short2 *src0_y = (__global short2 * )((__global char *)mat_src0 + y * src0_step); - __global short2 *src1_y = (__global short2 * )((__global char *)mat_src1 + y * src1_step); - __global short2 *src2_y = (__global short2 * )((__global char *)mat_src2 + y * src0_step); - - __global short2 *dst_y = (__global short2 *)((__global char *)mat_dst + y * dst_step); - - short2 value0 = src0_y[x]; - short2 value1 = src1_y[x]; - short2 value2 = src2_y[x]; - - dst_y[3 * x + 0] = (short2)(value0.x, value1.x); - dst_y[3 * x + 1] = (short2)(value2.x, value0.y); - dst_y[3 * x + 2] = (short2)(value1.y, value2.y); - - /* - dst_y[3 * x + 0] = (short4)(value0.s0, value1.s0, value2.s0, - value0.s1); - - dst_y[3 * x + 1] = (short4)(value1.s1, value2.s1, - value0.s2, value1.s2); - - dst_y[3 * x + 2] = (short4)(value2.s2, - value0.s3, value1.s3, value2.s3); - */ - } -} -__kernel void merge_vector_C3_D4_1(int rows, int cols, - __global int *mat_dst, int dst_step, - __global int *mat_src0, int src0_step, - __global int *mat_src1, int src1_step, - __global int *mat_src2, int src2_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global int *src0_y = (__global int * )((__global char *)mat_src0 + y * src0_step); - __global int *src1_y = (__global int * )((__global char *)mat_src1 + y * src1_step); - __global int *src2_y = (__global int * )((__global char *)mat_src2 + y * src0_step); - - __global int *dst_y = (__global int *)((__global char *)mat_dst + y * dst_step); - - int value0 = src0_y[x]; - int value1 = src1_y[x]; - int value2 = src2_y[x]; - - dst_y[3 * x + 0] = value0; - dst_y[3 * x + 1] = value1; - dst_y[3 * x + 2] = value2; - - /*for test do not delete - dst_y[3 * x + 0] = (int2)(value0.x, value1.x); - dst_y[3 * x + 1] = (int2)(value2.x, value0.y); - dst_y[3 * x + 2] = (int2)(value1.y, value2.y); - */ - } -} -__kernel void merge_vector_C3_D5_1(int rows, int cols, - __global float *mat_dst, int dst_step, - __global float *mat_src0, int src0_step, - __global float *mat_src1, int src1_step, - __global float *mat_src2, int src2_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global float *src0_y = (__global float * )((__global char *)mat_src0 + y * src0_step); - __global float *src1_y = (__global float * )((__global char *)mat_src1 + y * src1_step); - __global float *src2_y = (__global float * )((__global char *)mat_src2 + y * src0_step); - - __global float *dst_y = (__global float *)((__global char *)mat_dst + y * dst_step); - - float value0 = src0_y[x]; - float value1 = src1_y[x]; - float value2 = src2_y[x]; - - dst_y[3 * x + 0] = value0; - dst_y[3 * x + 1] = value1; - dst_y[3 * x + 2] = value2; - } -} - -#if defined (DOUBLE_SUPPORT) -__kernel void merge_vector_C3_D6_1(int rows, int cols, - __global double *mat_dst, int dst_step, - __global double *mat_src0, int src0_step, - __global double *mat_src1, int src1_step, - __global double *mat_src2, int src2_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global double *src0_y = (__global double * )((__global char *)mat_src0 + y * src0_step); - __global double *src1_y = (__global double * )((__global char *)mat_src1 + y * src1_step); - __global double *src2_y = (__global double * )((__global char *)mat_src2 + y * src0_step); - - __global double *dst_y = (__global double *)((__global char *)mat_dst + y * dst_step); - - double value0 = src0_y[x]; - double value1 = src1_y[x]; - double value2 = src2_y[x]; - - dst_y[3 * x + 0] = value0; - dst_y[3 * x + 1] = value1; - dst_y[3 * x + 2] = value2; - } -} -#endif -__kernel void merge_vector_C4_D0_1(int rows, int cols, - __global uchar *mat_dst, int dst_step, - __global uchar *mat_src0, int src0_step, - __global uchar *mat_src1, int src1_step, - __global uchar *mat_src2, int src2_step, - __global uchar *mat_src3, int src3_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global uchar4 *src0_y = (__global uchar4 * )(mat_src0 + y * src0_step); - __global uchar4 *src1_y = (__global uchar4 * )(mat_src1 + y * src1_step); - __global uchar4 *src2_y = (__global uchar4 * )(mat_src2 + y * src0_step); - __global uchar4 *src3_y = (__global uchar4 * )(mat_src3 + y * src1_step); - - __global uchar16 *dst_y = (__global uchar16 *)(mat_dst + y * dst_step); - - uchar4 value0 = src0_y[x]; - uchar4 value1 = src1_y[x]; - uchar4 value2 = src2_y[x]; - uchar4 value3 = src3_y[x]; - - dst_y[x] = (uchar16)(value0.x, value1.x, value2.x, value3.x, - value0.y, value1.y, value2.y, value3.y, - value0.z, value1.z, value2.z, value3.z, - value0.w, value1.w, value2.w, value3.w); - } -} - -__kernel void merge_vector_C4_D1_1(int rows, int cols, - __global char *mat_dst, int dst_step, - __global char *mat_src0, int src0_step, - __global char *mat_src1, int src1_step, - __global char *mat_src2, int src2_step, - __global char *mat_src3, int src3_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global char4 *src0_y = (__global char4 * )(mat_src0 + y * src0_step); - __global char4 *src1_y = (__global char4 * )(mat_src1 + y * src1_step); - __global char4 *src2_y = (__global char4 * )(mat_src2 + y * src0_step); - __global char4 *src3_y = (__global char4 * )(mat_src3 + y * src1_step); - - __global char16 *dst_y = (__global char16 *)(mat_dst + y * dst_step); - - char4 value0 = src0_y[x]; - char4 value1 = src1_y[x]; - char4 value2 = src2_y[x]; - char4 value3 = src3_y[x]; - - dst_y[x] = (char16)(value0.x, value1.x, value2.x, value3.x, - value0.y, value1.y, value2.y, value3.y, - value0.z, value1.z, value2.z, value3.z, - value0.w, value1.w, value2.w, value3.w); - } -} -__kernel void merge_vector_C4_D2_1(int rows, int cols, - __global ushort *mat_dst, int dst_step, - __global ushort *mat_src0, int src0_step, - __global ushort *mat_src1, int src1_step, - __global ushort *mat_src2, int src2_step, - __global ushort *mat_src3, int src3_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global ushort2 *src0_y = (__global ushort2 * )((__global uchar*)mat_src0 + y * src0_step); - __global ushort2 *src1_y = (__global ushort2 * )((__global uchar*)mat_src1 + y * src1_step); - __global ushort2 *src2_y = (__global ushort2 * )((__global uchar*)mat_src2 + y * src0_step); - __global ushort2 *src3_y = (__global ushort2 * )((__global uchar*)mat_src3 + y * src1_step); - - __global ushort8 *dst_y = (__global ushort8 *)((__global uchar*)mat_dst + y * dst_step); - - ushort2 value0 = src0_y[x]; - ushort2 value1 = src1_y[x]; - ushort2 value2 = src2_y[x]; - ushort2 value3 = src3_y[x]; - - dst_y[x] = (ushort8)(value0.x, value1.x, value2.x, value3.x, - value0.y, value1.y, value2.y, value3.y); - } -} -__kernel void merge_vector_C4_D3_1(int rows, int cols, - __global short *mat_dst, int dst_step, - __global short *mat_src0, int src0_step, - __global short *mat_src1, int src1_step, - __global short *mat_src2, int src2_step, - __global short *mat_src3, int src3_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global short2 *src0_y = (__global short2 * )((__global uchar*)mat_src0 + y * src0_step); - __global short2 *src1_y = (__global short2 * )((__global uchar*)mat_src1 + y * src1_step); - __global short2 *src2_y = (__global short2 * )((__global uchar*)mat_src2 + y * src0_step); - __global short2 *src3_y = (__global short2 * )((__global uchar*)mat_src3 + y * src1_step); - - __global short8 *dst_y = (__global short8 *)((__global uchar*)mat_dst + y * dst_step); - - short2 value0 = src0_y[x]; - short2 value1 = src1_y[x]; - short2 value2 = src2_y[x]; - short2 value3 = src3_y[x]; - - dst_y[x] = (short8)(value0.x, value1.x, value2.x, value3.x, - value0.y, value1.y, value2.y, value3.y); - } -} -__kernel void merge_vector_C4_D4_1(int rows, int cols, - __global int *mat_dst, int dst_step, - __global int *mat_src0, int src0_step, - __global int *mat_src1, int src1_step, - __global int *mat_src2, int src2_step, - __global int *mat_src3, int src3_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global int *src0_y = (__global int * )((__global uchar*)mat_src0 + y * src0_step); - __global int *src1_y = (__global int * )((__global uchar*)mat_src1 + y * src1_step); - __global int *src2_y = (__global int * )((__global uchar*)mat_src2 + y * src0_step); - __global int *src3_y = (__global int * )((__global uchar*)mat_src3 + y * src1_step); - - __global int4 *dst_y = (__global int4 *)((__global uchar*)mat_dst + y * dst_step); - - int value0 = src0_y[x]; - int value1 = src1_y[x]; - int value2 = src2_y[x]; - int value3 = src3_y[x]; - - dst_y[x] = (int4)(value0, value1, value2, value3); - } -} -__kernel void merge_vector_C4_D5_1(int rows, int cols, - __global float *mat_dst, int dst_step, - __global float *mat_src0, int src0_step, - __global float *mat_src1, int src1_step, - __global float *mat_src2, int src2_step, - __global float *mat_src3, int src3_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global float *src0_y = (__global float * )((__global uchar*)mat_src0 + y * src0_step); - __global float *src1_y = (__global float * )((__global uchar*)mat_src1 + y * src1_step); - __global float *src2_y = (__global float * )((__global uchar*)mat_src2 + y * src0_step); - __global float *src3_y = (__global float * )((__global uchar*)mat_src3 + y * src1_step); - - __global float4 *dst_y = (__global float4 *)((__global uchar*)mat_dst + y * dst_step); - - float value0 = src0_y[x]; - float value1 = src1_y[x]; - float value2 = src2_y[x]; - float value3 = src3_y[x]; - - dst_y[x] = (float4)(value0, value1, value2, value3); - } -} - -#if defined (DOUBLE_SUPPORT) -__kernel void merge_vector_C4_D6_1(int rows, int cols, - __global double *mat_dst, int dst_step, - __global double *mat_src0, int src0_step, - __global double *mat_src1, int src1_step, - __global double *mat_src2, int src2_step, - __global double *mat_src3, int src3_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if ((x < cols) && (y < rows)) - { - __global double *src0_y = (__global double * )((__global uchar*)mat_src0 + y * src0_step); - __global double *src1_y = (__global double * )((__global uchar*)mat_src1 + y * src1_step); - __global double *src2_y = (__global double * )((__global uchar*)mat_src2 + y * src0_step); - __global double *src3_y = (__global double * )((__global uchar*)mat_src3 + y * src1_step); - - __global double4 *dst_y = (__global double4 *)((__global uchar*)mat_dst + y * dst_step); - - double value0 = src0_y[x]; - double value1 = src1_y[x]; - double value2 = src2_y[x]; - double value3 = src3_y[x]; - - dst_y[x] = (double4)(value0, value1, value2, value3); - } -} -#endif diff --git a/modules/ocl/src/opencl/moments.cl b/modules/ocl/src/opencl/moments.cl deleted file mode 100644 index 09c79c4b5..000000000 --- a/modules/ocl/src/opencl/moments.cl +++ /dev/null @@ -1,432 +0,0 @@ -/*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 -// Jin Ma, jin@multicorewareinc.com -// Sen Liu, swjtuls1987@126.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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -typedef double T; -#else -typedef long T; -#endif - -#define DST_ROW_00 0 -#define DST_ROW_10 1 -#define DST_ROW_01 2 -#define DST_ROW_20 3 -#define DST_ROW_11 4 -#define DST_ROW_02 5 -#define DST_ROW_30 6 -#define DST_ROW_21 7 -#define DST_ROW_12 8 -#define DST_ROW_03 9 - -__kernel void icvContourMoments(int contour_total, - __global float* reader_oclmat_data, - __global T* dst_a, - int dst_step) -{ - T xi_1, yi_1, xi_12, yi_12, xi, yi, xi2, yi2, dxy, xii_1, yii_1; - int idx = get_global_id(0); - - if (idx < 0 || idx >= contour_total) - return; - - xi_1 = (T)(*(reader_oclmat_data + (get_global_id(0) << 1))); - yi_1 = (T)(*(reader_oclmat_data + (get_global_id(0) << 1) + 1)); - xi_12 = xi_1 * xi_1; - yi_12 = yi_1 * yi_1; - - if(idx == contour_total - 1) - { - xi = (T)(*(reader_oclmat_data)); - yi = (T)(*(reader_oclmat_data + 1)); - } - else - { - xi = (T)(*(reader_oclmat_data + (idx + 1) * 2)); - yi = (T)(*(reader_oclmat_data + (idx + 1) * 2 + 1)); - } - xi2 = xi * xi; - yi2 = yi * yi; - dxy = xi_1 * yi - xi * yi_1; - xii_1 = xi_1 + xi; - yii_1 = yi_1 + yi; - - dst_step /= sizeof(T); - *( dst_a + DST_ROW_00 * dst_step + idx) = dxy; - *( dst_a + DST_ROW_10 * dst_step + idx) = dxy * xii_1; - *( dst_a + DST_ROW_01 * dst_step + idx) = dxy * yii_1; - *( dst_a + DST_ROW_20 * dst_step + idx) = dxy * (xi_1 * xii_1 + xi2); - *( dst_a + DST_ROW_11 * dst_step + idx) = dxy * (xi_1 * (yii_1 + yi_1) + xi * (yii_1 + yi)); - *( dst_a + DST_ROW_02 * dst_step + idx) = dxy * (yi_1 * yii_1 + yi2); - *( dst_a + DST_ROW_30 * dst_step + idx) = dxy * xii_1 * (xi_12 + xi2); - *( dst_a + DST_ROW_03 * dst_step + idx) = dxy * yii_1 * (yi_12 + yi2); - *( dst_a + DST_ROW_21 * dst_step + idx) = - dxy * (xi_12 * (3 * yi_1 + yi) + 2 * xi * xi_1 * yii_1 + - xi2 * (yi_1 + 3 * yi)); - *( dst_a + DST_ROW_12 * dst_step + idx) = - dxy * (yi_12 * (3 * xi_1 + xi) + 2 * yi * yi_1 * xii_1 + - yi2 * (xi_1 + 3 * xi)); -} - -#if defined (DOUBLE_SUPPORT) -#define WT double -#define WT4 double4 -#define convert_T4 convert_double4 -#define convert_T convert_double -#else -#define WT float -#define WT4 float4 -#define convert_T4 convert_float4 -#define convert_T convert_float -#endif - -#ifdef CV_8UC1 -#define TT uchar -#elif defined CV_16UC1 -#define TT ushort -#elif defined CV_16SC1 -#define TT short -#elif defined CV_32FC1 -#define TT float -#elif defined CV_64FC1 -#ifdef DOUBLE_SUPPORT -#define TT double -#else -#define TT float -#endif -#endif -__kernel void CvMoments(__global TT* src_data, int src_rows, int src_cols, int src_step, - __global WT* dst_m, - int dst_cols, int dst_step, int binary) -{ - int dy = get_global_id(1); - int ly = get_local_id(1); - int gidx = get_group_id(0); - int gidy = get_group_id(1); - int x_rest = src_cols % 256; - int y_rest = src_rows % 256; - __local int codxy[256]; - codxy[ly] = ly; - barrier(CLK_LOCAL_MEM_FENCE); - - WT4 x0 = (WT4)(0.f); - WT4 x1 = (WT4)(0.f); - WT4 x2 = (WT4)(0.f); - WT4 x3 = (WT4)(0.f); - - __global TT* row = src_data + gidy * src_step + ly * src_step + gidx * 256; - - WT4 p; - WT4 x; - WT4 xp; - WT4 xxp; - - WT py = 0.f, sy = 0.f; - - if(dy < src_rows) - { - if((x_rest > 0) && (gidx == ((int)get_num_groups(0) - 1))) - { - int i; - for(i = 0; i < x_rest - 4; i += 4) - { - p = convert_T4(vload4(0, row + i)); - x = convert_T4(vload4(0, codxy + i)); - xp = x * p; - xxp = xp * x; - - x0 += p; - x1 += xp; - x2 += xxp; - x3 += convert_T4(xxp * x); - } - - x0.s0 = x0.s0 + x0.s1 + x0.s2 + x0.s3; - x1.s0 = x1.s0 + x1.s1 + x1.s2 + x1.s3; - x2.s0 = x2.s0 + x2.s1 + x2.s2 + x2.s3; - x3.s0 = x3.s0 + x3.s1 + x3.s2 + x3.s3; - - WT x0_ = 0; - WT x1_ = 0; - WT x2_ = 0; - WT x3_ = 0; - - for(; i < x_rest; i++) - { - WT p_ = 0; - p_ = row[i]; - WT x_ = convert_T(codxy[i]); - - - WT xp_ = x_ * p_; - WT xxp_ = xp_ * x_; - - x0_ += p_; - x1_ += xp_; - x2_ += xxp_; - x3_ += xxp_ * x_; - } - - x0.s0 += x0_; - x1.s0 += x1_; - x2.s0 += x2_; - x3.s0 += x3_; - }else - { - for(int i = 0; i < 256; i += 4) - { - p = convert_T4(vload4(0, row + i)); - x = convert_T4(vload4(0, codxy + i)); - xp = x * p; - xxp = xp * x; - - x0 += p; - x1 += xp; - x2 += xxp; - x3 += convert_T4(xxp * x); - } - - x0.s0 = x0.s0 + x0.s1 + x0.s2 + x0.s3; - x1.s0 = x1.s0 + x1.s1 + x1.s2 + x1.s3; - x2.s0 = x2.s0 + x2.s1 + x2.s2 + x2.s3; - x3.s0 = x3.s0 + x3.s1 + x3.s2 + x3.s3; - } - - py = ly * x0.s0; - sy = ly * ly; - } - __local WT mom[10][256]; - - if((y_rest > 0) && (gidy == ((int)get_num_groups(1) - 1))) - { - if(ly < y_rest) - { - mom[9][ly] = py * sy; - mom[8][ly] = x1.s0 * sy; - mom[7][ly] = x2.s0 * ly; - mom[6][ly] = x3.s0; - mom[5][ly] = x0.s0 * sy; - mom[4][ly] = x1.s0 * ly; - mom[3][ly] = x2.s0; - mom[2][ly] = py; - mom[1][ly] = x1.s0; - mom[0][ly] = x0.s0; - } - barrier(CLK_LOCAL_MEM_FENCE); - if(ly < 10) - for(int i = 1; i < y_rest; i++) - mom[ly][0] = mom[ly][i] + mom[ly][0]; - } - else - { - mom[9][ly] = py * sy; - mom[8][ly] = x1.s0 * sy; - mom[7][ly] = x2.s0 * ly; - mom[6][ly] = x3.s0; - mom[5][ly] = x0.s0 * sy; - mom[4][ly] = x1.s0 * ly; - mom[3][ly] = x2.s0; - mom[2][ly] = py; - mom[1][ly] = x1.s0; - mom[0][ly] = x0.s0; - - barrier(CLK_LOCAL_MEM_FENCE); - - if(ly < 128) - { - mom[0][ly] = mom[0][ly] + mom[0][ly + 128]; - mom[1][ly] = mom[1][ly] + mom[1][ly + 128]; - mom[2][ly] = mom[2][ly] + mom[2][ly + 128]; - mom[3][ly] = mom[3][ly] + mom[3][ly + 128]; - mom[4][ly] = mom[4][ly] + mom[4][ly + 128]; - mom[5][ly] = mom[5][ly] + mom[5][ly + 128]; - mom[6][ly] = mom[6][ly] + mom[6][ly + 128]; - mom[7][ly] = mom[7][ly] + mom[7][ly + 128]; - mom[8][ly] = mom[8][ly] + mom[8][ly + 128]; - mom[9][ly] = mom[9][ly] + mom[9][ly + 128]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(ly < 64) - { - mom[0][ly] = mom[0][ly] + mom[0][ly + 64]; - mom[1][ly] = mom[1][ly] + mom[1][ly + 64]; - mom[2][ly] = mom[2][ly] + mom[2][ly + 64]; - mom[3][ly] = mom[3][ly] + mom[3][ly + 64]; - mom[4][ly] = mom[4][ly] + mom[4][ly + 64]; - mom[5][ly] = mom[5][ly] + mom[5][ly + 64]; - mom[6][ly] = mom[6][ly] + mom[6][ly + 64]; - mom[7][ly] = mom[7][ly] + mom[7][ly + 64]; - mom[8][ly] = mom[8][ly] + mom[8][ly + 64]; - mom[9][ly] = mom[9][ly] + mom[9][ly + 64]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(ly < 32) - { - mom[0][ly] = mom[0][ly] + mom[0][ly + 32]; - mom[1][ly] = mom[1][ly] + mom[1][ly + 32]; - mom[2][ly] = mom[2][ly] + mom[2][ly + 32]; - mom[3][ly] = mom[3][ly] + mom[3][ly + 32]; - mom[4][ly] = mom[4][ly] + mom[4][ly + 32]; - mom[5][ly] = mom[5][ly] + mom[5][ly + 32]; - mom[6][ly] = mom[6][ly] + mom[6][ly + 32]; - mom[7][ly] = mom[7][ly] + mom[7][ly + 32]; - mom[8][ly] = mom[8][ly] + mom[8][ly + 32]; - mom[9][ly] = mom[9][ly] + mom[9][ly + 32]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(ly < 16) - { - mom[0][ly] = mom[0][ly] + mom[0][ly + 16]; - mom[1][ly] = mom[1][ly] + mom[1][ly + 16]; - mom[2][ly] = mom[2][ly] + mom[2][ly + 16]; - mom[3][ly] = mom[3][ly] + mom[3][ly + 16]; - mom[4][ly] = mom[4][ly] + mom[4][ly + 16]; - mom[5][ly] = mom[5][ly] + mom[5][ly + 16]; - mom[6][ly] = mom[6][ly] + mom[6][ly + 16]; - mom[7][ly] = mom[7][ly] + mom[7][ly + 16]; - mom[8][ly] = mom[8][ly] + mom[8][ly + 16]; - mom[9][ly] = mom[9][ly] + mom[9][ly + 16]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(ly < 8) - { - mom[0][ly] = mom[0][ly] + mom[0][ly + 8]; - mom[1][ly] = mom[1][ly] + mom[1][ly + 8]; - mom[2][ly] = mom[2][ly] + mom[2][ly + 8]; - mom[3][ly] = mom[3][ly] + mom[3][ly + 8]; - mom[4][ly] = mom[4][ly] + mom[4][ly + 8]; - mom[5][ly] = mom[5][ly] + mom[5][ly + 8]; - mom[6][ly] = mom[6][ly] + mom[6][ly + 8]; - mom[7][ly] = mom[7][ly] + mom[7][ly + 8]; - mom[8][ly] = mom[8][ly] + mom[8][ly + 8]; - mom[9][ly] = mom[9][ly] + mom[9][ly + 8]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(ly < 4) - { - mom[0][ly] = mom[0][ly] + mom[0][ly + 4]; - mom[1][ly] = mom[1][ly] + mom[1][ly + 4]; - mom[2][ly] = mom[2][ly] + mom[2][ly + 4]; - mom[3][ly] = mom[3][ly] + mom[3][ly + 4]; - mom[4][ly] = mom[4][ly] + mom[4][ly + 4]; - mom[5][ly] = mom[5][ly] + mom[5][ly + 4]; - mom[6][ly] = mom[6][ly] + mom[6][ly + 4]; - mom[7][ly] = mom[7][ly] + mom[7][ly + 4]; - mom[8][ly] = mom[8][ly] + mom[8][ly + 4]; - mom[9][ly] = mom[9][ly] + mom[9][ly + 4]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(ly < 2) - { - mom[0][ly] = mom[0][ly] + mom[0][ly + 2]; - mom[1][ly] = mom[1][ly] + mom[1][ly + 2]; - mom[2][ly] = mom[2][ly] + mom[2][ly + 2]; - mom[3][ly] = mom[3][ly] + mom[3][ly + 2]; - mom[4][ly] = mom[4][ly] + mom[4][ly + 2]; - mom[5][ly] = mom[5][ly] + mom[5][ly + 2]; - mom[6][ly] = mom[6][ly] + mom[6][ly + 2]; - mom[7][ly] = mom[7][ly] + mom[7][ly + 2]; - mom[8][ly] = mom[8][ly] + mom[8][ly + 2]; - mom[9][ly] = mom[9][ly] + mom[9][ly + 2]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(ly < 1) - { - mom[0][ly] = mom[0][ly] + mom[0][ly + 1]; - mom[1][ly] = mom[1][ly] + mom[1][ly + 1]; - mom[2][ly] = mom[2][ly] + mom[2][ly + 1]; - mom[3][ly] = mom[3][ly] + mom[3][ly + 1]; - mom[4][ly] = mom[4][ly] + mom[4][ly + 1]; - mom[5][ly] = mom[5][ly] + mom[5][ly + 1]; - mom[6][ly] = mom[6][ly] + mom[6][ly + 1]; - mom[7][ly] = mom[7][ly] + mom[7][ly + 1]; - mom[8][ly] = mom[8][ly] + mom[8][ly + 1]; - mom[9][ly] = mom[9][ly] + mom[9][ly + 1]; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if(binary) - { - WT s = 1.0f/255; - if(ly < 10) - mom[ly][0] *= s; - barrier(CLK_LOCAL_MEM_FENCE); - } - WT xm = (gidx * 256) * mom[0][0]; - WT ym = (gidy * 256) * mom[0][0]; - - if(ly == 0) - { - mom[0][1] = mom[0][0]; - mom[1][1] = mom[1][0] + xm; - mom[2][1] = mom[2][0] + ym; - mom[3][1] = mom[3][0] + gidx * 256 * (mom[1][0] * 2 + xm); - mom[4][1] = mom[4][0] + gidx * 256 * (mom[2][0] + ym) + gidy * 256 * mom[1][0]; - mom[5][1] = mom[5][0] + gidy * 256 * (mom[2][0] * 2 + ym); - mom[6][1] = mom[6][0] + gidx * 256 * (3 * mom[3][0] + 256 * gidx * (3 * mom[1][0] + xm)); - mom[7][1] = mom[7][0] + gidx * 256 * (2 * (mom[4][0] + 256 * gidy * mom[1][0]) + 256 * gidx * (mom[2][0] + ym)) + 256 * gidy * mom[3][0]; - mom[8][1] = mom[8][0] + gidy * 256 * (2 * (mom[4][0] + 256 * gidx * mom[2][0]) + 256 * gidy * (mom[1][0] + xm)) + 256 * gidx * mom[5][0]; - mom[9][1] = mom[9][0] + gidy * 256 * (3 * mom[5][0] + 256 * gidy * (3 * mom[2][0] + ym)); - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if(ly < 10) - dst_m[10 * gidy * dst_step + ly * dst_step + gidx] = mom[ly][1]; -} diff --git a/modules/ocl/src/opencl/objdetect_hog.cl b/modules/ocl/src/opencl/objdetect_hog.cl deleted file mode 100644 index e931e82b5..000000000 --- a/modules/ocl/src/opencl/objdetect_hog.cl +++ /dev/null @@ -1,726 +0,0 @@ -/*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 -// Wenju He, wenju@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*/ - -#define CELL_WIDTH 8 -#define CELL_HEIGHT 8 -#define CELLS_PER_BLOCK_X 2 -#define CELLS_PER_BLOCK_Y 2 -#define NTHREADS 256 -#define CV_PI_F 3.1415926535897932384626433832795f - -#ifdef INTEL_DEVICE -#define QANGLE_TYPE int -#define QANGLE_TYPE2 int2 -#else -#define QANGLE_TYPE uchar -#define QANGLE_TYPE2 uchar2 -#endif - -//---------------------------------------------------------------------------- -// Histogram computation -// 12 threads for a cell, 12x4 threads per block -// Use pre-computed gaussian and interp_weight lookup tables -__kernel void compute_hists_lut_kernel( - const int cblock_stride_x, const int cblock_stride_y, - const int cnbins, const int cblock_hist_size, const int img_block_width, - const int blocks_in_group, const int blocks_total, - const int grad_quadstep, const int qangle_step, - __global const float* grad, __global const QANGLE_TYPE* qangle, - __global const float* gauss_w_lut, - __global float* block_hists, __local float* smem) -{ - const int lx = get_local_id(0); - const int lp = lx / 24; /* local group id */ - const int gid = get_group_id(0) * blocks_in_group + lp;/* global group id */ - const int gidY = gid / img_block_width; - const int gidX = gid - gidY * img_block_width; - - const int lidX = lx - lp * 24; - const int lidY = get_local_id(1); - - const int cell_x = lidX / 12; - const int cell_y = lidY; - const int cell_thread_x = lidX - cell_x * 12; - - __local float* hists = smem + lp * cnbins * (CELLS_PER_BLOCK_X * - CELLS_PER_BLOCK_Y * 12 + CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y); - __local float* final_hist = hists + cnbins * - (CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y * 12); - - const int offset_x = gidX * cblock_stride_x + (cell_x << 2) + cell_thread_x; - const int offset_y = gidY * cblock_stride_y + (cell_y << 2); - - __global const float* grad_ptr = (gid < blocks_total) ? - grad + offset_y * grad_quadstep + (offset_x << 1) : grad; - __global const QANGLE_TYPE* qangle_ptr = (gid < blocks_total) ? - qangle + offset_y * qangle_step + (offset_x << 1) : qangle; - - __local float* hist = hists + 12 * (cell_y * CELLS_PER_BLOCK_Y + cell_x) + - cell_thread_x; - for (int bin_id = 0; bin_id < cnbins; ++bin_id) - hist[bin_id * 48] = 0.f; - - const int dist_x = -4 + cell_thread_x - 4 * cell_x; - const int dist_center_x = dist_x - 4 * (1 - 2 * cell_x); - - const int dist_y_begin = -4 - 4 * lidY; - for (int dist_y = dist_y_begin; dist_y < dist_y_begin + 12; ++dist_y) - { - float2 vote = (float2) (grad_ptr[0], grad_ptr[1]); - QANGLE_TYPE2 bin = (QANGLE_TYPE2) (qangle_ptr[0], qangle_ptr[1]); - - grad_ptr += grad_quadstep; - qangle_ptr += qangle_step; - - int dist_center_y = dist_y - 4 * (1 - 2 * cell_y); - - int idx = (dist_center_y + 8) * 16 + (dist_center_x + 8); - float gaussian = gauss_w_lut[idx]; - idx = (dist_y + 8) * 16 + (dist_x + 8); - float interp_weight = gauss_w_lut[256+idx]; - - hist[bin.x * 48] += gaussian * interp_weight * vote.x; - hist[bin.y * 48] += gaussian * interp_weight * vote.y; - } - barrier(CLK_LOCAL_MEM_FENCE); - - volatile __local float* hist_ = hist; - for (int bin_id = 0; bin_id < cnbins; ++bin_id, hist_ += 48) - { - if (cell_thread_x < 6) - hist_[0] += hist_[6]; - barrier(CLK_LOCAL_MEM_FENCE); - if (cell_thread_x < 3) - hist_[0] += hist_[3]; -#ifdef CPU - barrier(CLK_LOCAL_MEM_FENCE); -#endif - if (cell_thread_x == 0) - final_hist[(cell_x * 2 + cell_y) * cnbins + bin_id] = - hist_[0] + hist_[1] + hist_[2]; - } -#ifdef CPU - barrier(CLK_LOCAL_MEM_FENCE); -#endif - - int tid = (cell_y * CELLS_PER_BLOCK_Y + cell_x) * 12 + cell_thread_x; - if ((tid < cblock_hist_size) && (gid < blocks_total)) - { - __global float* block_hist = block_hists + - (gidY * img_block_width + gidX) * cblock_hist_size; - block_hist[tid] = final_hist[tid]; - } -} - -//------------------------------------------------------------- -// Normalization of histograms via L2Hys_norm -// optimized for the case of 9 bins -__kernel void normalize_hists_36_kernel(__global float* block_hists, - const float threshold, __local float *squares) -{ - const int tid = get_local_id(0); - const int gid = get_global_id(0); - const int bid = tid / 36; /* block-hist id, (0 - 6) */ - const int boffset = bid * 36; /* block-hist offset in the work-group */ - const int hid = tid - boffset; /* histogram bin id, (0 - 35) */ - - float elem = block_hists[gid]; - squares[tid] = elem * elem; - barrier(CLK_LOCAL_MEM_FENCE); - - __local float* smem = squares + boffset; - float sum = smem[hid]; - if (hid < 18) - smem[hid] = sum = sum + smem[hid + 18]; - barrier(CLK_LOCAL_MEM_FENCE); - if (hid < 9) - smem[hid] = sum = sum + smem[hid + 9]; - barrier(CLK_LOCAL_MEM_FENCE); - if (hid < 4) - smem[hid] = sum + smem[hid + 4]; - barrier(CLK_LOCAL_MEM_FENCE); - sum = smem[0] + smem[1] + smem[2] + smem[3] + smem[8]; - - elem = elem / (sqrt(sum) + 3.6f); - elem = min(elem, threshold); - - barrier(CLK_LOCAL_MEM_FENCE); - squares[tid] = elem * elem; - barrier(CLK_LOCAL_MEM_FENCE); - - sum = smem[hid]; - if (hid < 18) - smem[hid] = sum = sum + smem[hid + 18]; - barrier(CLK_LOCAL_MEM_FENCE); - if (hid < 9) - smem[hid] = sum = sum + smem[hid + 9]; - barrier(CLK_LOCAL_MEM_FENCE); - if (hid < 4) - smem[hid] = sum + smem[hid + 4]; - barrier(CLK_LOCAL_MEM_FENCE); - sum = smem[0] + smem[1] + smem[2] + smem[3] + smem[8]; - - block_hists[gid] = elem / (sqrt(sum) + 1e-3f); -} - -//------------------------------------------------------------- -// Normalization of histograms via L2Hys_norm -// -inline float reduce_smem(volatile __local float* smem, int size) -{ - unsigned int tid = get_local_id(0); - float sum = smem[tid]; - - if (size >= 512) { if (tid < 256) smem[tid] = sum = sum + smem[tid + 256]; - barrier(CLK_LOCAL_MEM_FENCE); } - if (size >= 256) { if (tid < 128) smem[tid] = sum = sum + smem[tid + 128]; - barrier(CLK_LOCAL_MEM_FENCE); } - if (size >= 128) { if (tid < 64) smem[tid] = sum = sum + smem[tid + 64]; - barrier(CLK_LOCAL_MEM_FENCE); } -#ifdef CPU - if (size >= 64) { if (tid < 32) smem[tid] = sum = sum + smem[tid + 32]; - barrier(CLK_LOCAL_MEM_FENCE); } - if (size >= 32) { if (tid < 16) smem[tid] = sum = sum + smem[tid + 16]; - barrier(CLK_LOCAL_MEM_FENCE); } - if (size >= 16) { if (tid < 8) smem[tid] = sum = sum + smem[tid + 8]; - barrier(CLK_LOCAL_MEM_FENCE); } - if (size >= 8) { if (tid < 4) smem[tid] = sum = sum + smem[tid + 4]; - barrier(CLK_LOCAL_MEM_FENCE); } - if (size >= 4) { if (tid < 2) smem[tid] = sum = sum + smem[tid + 2]; - barrier(CLK_LOCAL_MEM_FENCE); } - if (size >= 2) { if (tid < 1) smem[tid] = sum = sum + smem[tid + 1]; - barrier(CLK_LOCAL_MEM_FENCE); } -#else - if (tid < 32) - { - if (size >= 64) smem[tid] = sum = sum + smem[tid + 32]; -#if WAVE_SIZE < 32 - } barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 16) { -#endif - if (size >= 32) smem[tid] = sum = sum + smem[tid + 16]; - if (size >= 16) smem[tid] = sum = sum + smem[tid + 8]; - if (size >= 8) smem[tid] = sum = sum + smem[tid + 4]; - if (size >= 4) smem[tid] = sum = sum + smem[tid + 2]; - if (size >= 2) smem[tid] = sum = sum + smem[tid + 1]; - } -#endif - - return sum; -} - -__kernel void normalize_hists_kernel( - const int nthreads, const int block_hist_size, const int img_block_width, - __global float* block_hists, const float threshold, __local float *squares) -{ - const int tid = get_local_id(0); - const int gidX = get_group_id(0); - const int gidY = get_group_id(1); - - __global float* hist = block_hists + (gidY * img_block_width + gidX) * - block_hist_size + tid; - - float elem = 0.f; - if (tid < block_hist_size) - elem = hist[0]; - - squares[tid] = elem * elem; - - barrier(CLK_LOCAL_MEM_FENCE); - float sum = reduce_smem(squares, nthreads); - - float scale = 1.0f / (sqrt(sum) + 0.1f * block_hist_size); - elem = min(elem * scale, threshold); - - barrier(CLK_LOCAL_MEM_FENCE); - squares[tid] = elem * elem; - - barrier(CLK_LOCAL_MEM_FENCE); - sum = reduce_smem(squares, nthreads); - scale = 1.0f / (sqrt(sum) + 1e-3f); - - if (tid < block_hist_size) - hist[0] = elem * scale; -} - -//--------------------------------------------------------------------- -// Linear SVM based classification -// 48x96 window, 9 bins and default parameters -// 180 threads, each thread corresponds to a bin in a row -__kernel void classify_hists_180_kernel( - const int cdescr_width, const int cdescr_height, const int cblock_hist_size, - const int img_win_width, const int img_block_width, - const int win_block_stride_x, const int win_block_stride_y, - __global const float * block_hists, __global const float* coefs, - float free_coef, float threshold, __global uchar* labels) -{ - const int tid = get_local_id(0); - const int gidX = get_group_id(0); - const int gidY = get_group_id(1); - - __global const float* hist = block_hists + (gidY * win_block_stride_y * - img_block_width + gidX * win_block_stride_x) * cblock_hist_size; - - float product = 0.f; - - for (int i = 0; i < cdescr_height; i++) - { - product += coefs[i * cdescr_width + tid] * - hist[i * img_block_width * cblock_hist_size + tid]; - } - - __local float products[180]; - - products[tid] = product; - - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 90) products[tid] = product = product + products[tid + 90]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 45) products[tid] = product = product + products[tid + 45]; - barrier(CLK_LOCAL_MEM_FENCE); - - volatile __local float* smem = products; -#ifdef CPU - if (tid < 13) smem[tid] = product = product + smem[tid + 32]; - barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 16) smem[tid] = product = product + smem[tid + 16]; - barrier(CLK_LOCAL_MEM_FENCE); - if(tid<8) smem[tid] = product = product + smem[tid + 8]; - barrier(CLK_LOCAL_MEM_FENCE); - if(tid<4) smem[tid] = product = product + smem[tid + 4]; - barrier(CLK_LOCAL_MEM_FENCE); - if(tid<2) smem[tid] = product = product + smem[tid + 2]; - barrier(CLK_LOCAL_MEM_FENCE); -#else - if (tid < 13) - { - smem[tid] = product = product + smem[tid + 32]; - } -#if WAVE_SIZE < 32 - barrier(CLK_LOCAL_MEM_FENCE); -#endif - if (tid < 16) - { - smem[tid] = product = product + smem[tid + 16]; - smem[tid] = product = product + smem[tid + 8]; - smem[tid] = product = product + smem[tid + 4]; - smem[tid] = product = product + smem[tid + 2]; - } -#endif - - if (tid == 0){ - product = product + smem[tid + 1]; - labels[gidY * img_win_width + gidX] = (product + free_coef >= threshold); - } -} - -//--------------------------------------------------------------------- -// Linear SVM based classification -// 64x128 window, 9 bins and default parameters -// 256 threads, 252 of them are used -__kernel void classify_hists_252_kernel( - const int cdescr_width, const int cdescr_height, const int cblock_hist_size, - const int img_win_width, const int img_block_width, - const int win_block_stride_x, const int win_block_stride_y, - __global const float * block_hists, __global const float* coefs, - float free_coef, float threshold, __global uchar* labels) -{ - const int tid = get_local_id(0); - const int gidX = get_group_id(0); - const int gidY = get_group_id(1); - - __global const float* hist = block_hists + (gidY * win_block_stride_y * - img_block_width + gidX * win_block_stride_x) * cblock_hist_size; - - float product = 0.f; - if (tid < cdescr_width) - { - for (int i = 0; i < cdescr_height; i++) - product += coefs[i * cdescr_width + tid] * - hist[i * img_block_width * cblock_hist_size + tid]; - } - - __local float products[NTHREADS]; - - products[tid] = product; - - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 128) products[tid] = product = product + products[tid + 128]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 64) products[tid] = product = product + products[tid + 64]; - barrier(CLK_LOCAL_MEM_FENCE); - - volatile __local float* smem = products; -#ifdef CPU - if(tid<32) smem[tid] = product = product + smem[tid + 32]; - barrier(CLK_LOCAL_MEM_FENCE); - if(tid<16) smem[tid] = product = product + smem[tid + 16]; - barrier(CLK_LOCAL_MEM_FENCE); - if(tid<8) smem[tid] = product = product + smem[tid + 8]; - barrier(CLK_LOCAL_MEM_FENCE); - if(tid<4) smem[tid] = product = product + smem[tid + 4]; - barrier(CLK_LOCAL_MEM_FENCE); - if(tid<2) smem[tid] = product = product + smem[tid + 2]; - barrier(CLK_LOCAL_MEM_FENCE); -#else - if (tid < 32) - { - smem[tid] = product = product + smem[tid + 32]; -#if WAVE_SIZE < 32 - } barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 16) { -#endif - smem[tid] = product = product + smem[tid + 16]; - smem[tid] = product = product + smem[tid + 8]; - smem[tid] = product = product + smem[tid + 4]; - smem[tid] = product = product + smem[tid + 2]; - } -#endif - if (tid == 0){ - product = product + smem[tid + 1]; - labels[gidY * img_win_width + gidX] = (product + free_coef >= threshold); - } -} - -//--------------------------------------------------------------------- -// Linear SVM based classification -// 256 threads -__kernel void classify_hists_kernel( - const int cdescr_size, const int cdescr_width, const int cblock_hist_size, - const int img_win_width, const int img_block_width, - const int win_block_stride_x, const int win_block_stride_y, - __global const float * block_hists, __global const float* coefs, - float free_coef, float threshold, __global uchar* labels) -{ - const int tid = get_local_id(0); - const int gidX = get_group_id(0); - const int gidY = get_group_id(1); - - __global const float* hist = block_hists + (gidY * win_block_stride_y * - img_block_width + gidX * win_block_stride_x) * cblock_hist_size; - - float product = 0.f; - for (int i = tid; i < cdescr_size; i += NTHREADS) - { - int offset_y = i / cdescr_width; - int offset_x = i - offset_y * cdescr_width; - product += coefs[i] * - hist[offset_y * img_block_width * cblock_hist_size + offset_x]; - } - - __local float products[NTHREADS]; - - products[tid] = product; - - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 128) products[tid] = product = product + products[tid + 128]; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 64) products[tid] = product = product + products[tid + 64]; - barrier(CLK_LOCAL_MEM_FENCE); - - volatile __local float* smem = products; -#ifdef CPU - if(tid<32) smem[tid] = product = product + smem[tid + 32]; - barrier(CLK_LOCAL_MEM_FENCE); - if(tid<16) smem[tid] = product = product + smem[tid + 16]; - barrier(CLK_LOCAL_MEM_FENCE); - if(tid<8) smem[tid] = product = product + smem[tid + 8]; - barrier(CLK_LOCAL_MEM_FENCE); - if(tid<4) smem[tid] = product = product + smem[tid + 4]; - barrier(CLK_LOCAL_MEM_FENCE); - if(tid<2) smem[tid] = product = product + smem[tid + 2]; - barrier(CLK_LOCAL_MEM_FENCE); -#else - if (tid < 32) - { - smem[tid] = product = product + smem[tid + 32]; -#if WAVE_SIZE < 32 - } barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 16) { -#endif - smem[tid] = product = product + smem[tid + 16]; - smem[tid] = product = product + smem[tid + 8]; - smem[tid] = product = product + smem[tid + 4]; - smem[tid] = product = product + smem[tid + 2]; - } -#endif - if (tid == 0){ - smem[tid] = product = product + smem[tid + 1]; - labels[gidY * img_win_width + gidX] = (product + free_coef >= threshold); - } -} - -//---------------------------------------------------------------------------- -// Extract descriptors - -__kernel void extract_descrs_by_rows_kernel( - const int cblock_hist_size, const int descriptors_quadstep, - const int cdescr_size, const int cdescr_width, const int img_block_width, - const int win_block_stride_x, const int win_block_stride_y, - __global const float* block_hists, __global float* descriptors) -{ - int tid = get_local_id(0); - int gidX = get_group_id(0); - int gidY = get_group_id(1); - - // Get left top corner of the window in src - __global const float* hist = block_hists + (gidY * win_block_stride_y * - img_block_width + gidX * win_block_stride_x) * cblock_hist_size; - - // Get left top corner of the window in dst - __global float* descriptor = descriptors + - (gidY * get_num_groups(0) + gidX) * descriptors_quadstep; - - // Copy elements from src to dst - for (int i = tid; i < cdescr_size; i += NTHREADS) - { - int offset_y = i / cdescr_width; - int offset_x = i - offset_y * cdescr_width; - descriptor[i] = hist[offset_y * img_block_width * cblock_hist_size + offset_x]; - } -} - -__kernel void extract_descrs_by_cols_kernel( - const int cblock_hist_size, const int descriptors_quadstep, const int cdescr_size, - const int cnblocks_win_x, const int cnblocks_win_y, const int img_block_width, - const int win_block_stride_x, const int win_block_stride_y, - __global const float* block_hists, __global float* descriptors) -{ - int tid = get_local_id(0); - int gidX = get_group_id(0); - int gidY = get_group_id(1); - - // Get left top corner of the window in src - __global const float* hist = block_hists + (gidY * win_block_stride_y * - img_block_width + gidX * win_block_stride_x) * cblock_hist_size; - - // Get left top corner of the window in dst - __global float* descriptor = descriptors + - (gidY * get_num_groups(0) + gidX) * descriptors_quadstep; - - // Copy elements from src to dst - for (int i = tid; i < cdescr_size; i += NTHREADS) - { - int block_idx = i / cblock_hist_size; - int idx_in_block = i - block_idx * cblock_hist_size; - - int y = block_idx / cnblocks_win_x; - int x = block_idx - y * cnblocks_win_x; - - descriptor[(x * cnblocks_win_y + y) * cblock_hist_size + idx_in_block] = - hist[(y * img_block_width + x) * cblock_hist_size + idx_in_block]; - } -} - -//---------------------------------------------------------------------------- -// Gradients computation - -__kernel void compute_gradients_8UC4_kernel( - const int height, const int width, - const int img_step, const int grad_quadstep, const int qangle_step, - const __global uchar4 * img, __global float * grad, __global QANGLE_TYPE * qangle, - const float angle_scale, const char correct_gamma, const int cnbins) -{ - const int x = get_global_id(0); - const int tid = get_local_id(0); - const int gSizeX = get_local_size(0); - const int gidY = get_group_id(1); - - __global const uchar4* row = img + gidY * img_step; - - __local float sh_row[(NTHREADS + 2) * 3]; - - uchar4 val; - if (x < width) - val = row[x]; - else - val = row[width - 2]; - - sh_row[tid + 1] = val.x; - sh_row[tid + 1 + (NTHREADS + 2)] = val.y; - sh_row[tid + 1 + 2 * (NTHREADS + 2)] = val.z; - - if (tid == 0) - { - val = row[max(x - 1, 1)]; - sh_row[0] = val.x; - sh_row[(NTHREADS + 2)] = val.y; - sh_row[2 * (NTHREADS + 2)] = val.z; - } - - if (tid == gSizeX - 1) - { - val = row[min(x + 1, width - 2)]; - sh_row[gSizeX + 1] = val.x; - sh_row[gSizeX + 1 + (NTHREADS + 2)] = val.y; - sh_row[gSizeX + 1 + 2 * (NTHREADS + 2)] = val.z; - } - - barrier(CLK_LOCAL_MEM_FENCE); - if (x < width) - { - float3 a = (float3) (sh_row[tid], sh_row[tid + (NTHREADS + 2)], - sh_row[tid + 2 * (NTHREADS + 2)]); - float3 b = (float3) (sh_row[tid + 2], sh_row[tid + 2 + (NTHREADS + 2)], - sh_row[tid + 2 + 2 * (NTHREADS + 2)]); - - float3 dx; - if (correct_gamma == 1) - dx = sqrt(b) - sqrt(a); - else - dx = b - a; - - float3 dy = (float3) 0.f; - - if (gidY > 0 && gidY < height - 1) - { - a = convert_float3(img[(gidY - 1) * img_step + x].xyz); - b = convert_float3(img[(gidY + 1) * img_step + x].xyz); - - if (correct_gamma == 1) - dy = sqrt(b) - sqrt(a); - else - dy = b - a; - } - - float best_dx = dx.x; - float best_dy = dy.x; - - float mag0 = dx.x * dx.x + dy.x * dy.x; - float mag1 = dx.y * dx.y + dy.y * dy.y; - if (mag0 < mag1) - { - best_dx = dx.y; - best_dy = dy.y; - mag0 = mag1; - } - - mag1 = dx.z * dx.z + dy.z * dy.z; - if (mag0 < mag1) - { - best_dx = dx.z; - best_dy = dy.z; - mag0 = mag1; - } - - mag0 = sqrt(mag0); - - float ang = (atan2(best_dy, best_dx) + CV_PI_F) * angle_scale - 0.5f; - int hidx = (int)floor(ang); - ang -= hidx; - hidx = (hidx + cnbins) % cnbins; - - qangle[(gidY * qangle_step + x) << 1] = hidx; - qangle[((gidY * qangle_step + x) << 1) + 1] = (hidx + 1) % cnbins; - grad[(gidY * grad_quadstep + x) << 1] = mag0 * (1.f - ang); - grad[((gidY * grad_quadstep + x) << 1) + 1] = mag0 * ang; - } -} - -__kernel void compute_gradients_8UC1_kernel( - const int height, const int width, - const int img_step, const int grad_quadstep, const int qangle_step, - __global const uchar * img, __global float * grad, __global QANGLE_TYPE * qangle, - const float angle_scale, const char correct_gamma, const int cnbins) -{ - const int x = get_global_id(0); - const int tid = get_local_id(0); - const int gSizeX = get_local_size(0); - const int gidY = get_group_id(1); - - __global const uchar* row = img + gidY * img_step; - - __local float sh_row[NTHREADS + 2]; - - if (x < width) - sh_row[tid + 1] = row[x]; - else - sh_row[tid + 1] = row[width - 2]; - - if (tid == 0) - sh_row[0] = row[max(x - 1, 1)]; - - if (tid == gSizeX - 1) - sh_row[gSizeX + 1] = row[min(x + 1, width - 2)]; - - barrier(CLK_LOCAL_MEM_FENCE); - if (x < width) - { - float dx; - - if (correct_gamma == 1) - dx = sqrt(sh_row[tid + 2]) - sqrt(sh_row[tid]); - else - dx = sh_row[tid + 2] - sh_row[tid]; - - float dy = 0.f; - if (gidY > 0 && gidY < height - 1) - { - float a = (float) img[ (gidY + 1) * img_step + x ]; - float b = (float) img[ (gidY - 1) * img_step + x ]; - if (correct_gamma == 1) - dy = sqrt(a) - sqrt(b); - else - dy = a - b; - } - float mag = sqrt(dx * dx + dy * dy); - - float ang = (atan2(dy, dx) + CV_PI_F) * angle_scale - 0.5f; - int hidx = (int)floor(ang); - ang -= hidx; - hidx = (hidx + cnbins) % cnbins; - - qangle[ (gidY * qangle_step + x) << 1 ] = hidx; - qangle[ ((gidY * qangle_step + x) << 1) + 1 ] = (hidx + 1) % cnbins; - grad[ (gidY * grad_quadstep + x) << 1 ] = mag * (1.f - ang); - grad[ ((gidY * grad_quadstep + x) << 1) + 1 ] = mag * ang; - } -} diff --git a/modules/ocl/src/opencl/operator_convertTo.cl b/modules/ocl/src/opencl/operator_convertTo.cl deleted file mode 100644 index ca38bd550..000000000 --- a/modules/ocl/src/opencl/operator_convertTo.cl +++ /dev/null @@ -1,64 +0,0 @@ -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.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. -// -// - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -__kernel void convert_to( - __global const srcT* restrict srcMat, - __global dstT* dstMat, - int cols1, int rows, - int sstep1, int soffset1, - int dstep1, int doffset1, - float alpha, float beta) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - int srcidx = mad24(y, sstep1, x + soffset1); - int dstidx = mad24(y, dstep1, x + doffset1); - - if ( (x < cols1) && (y < rows) ) - { - float temp_src = convert_float(srcMat[srcidx]); - dstMat[dstidx] = convertToDstType(temp_src*alpha+beta); - } -} diff --git a/modules/ocl/src/opencl/operator_copyToM.cl b/modules/ocl/src/opencl/operator_copyToM.cl deleted file mode 100644 index 69e1798ad..000000000 --- a/modules/ocl/src/opencl/operator_copyToM.cl +++ /dev/null @@ -1,71 +0,0 @@ -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Jia Haipeng, jiahaipeng95@gmail.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. -// -// - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -__kernel void copy_to_with_mask( - __global const GENTYPE* restrict srcMat, - __global GENTYPE* dstMat, - __global const uchar* restrict maskMat, - int cols, - int rows, - int srcStep_in_pixel, - int srcoffset_in_pixel, - int dstStep_in_pixel, - int dstoffset_in_pixel, - int maskStep, - int maskoffset) -{ - int x=get_global_id(0); - int y=get_global_id(1); - - if (x < cols && y < rows) - { - int maskidx = mad24(y,maskStep,x+ maskoffset); - if ( maskMat[maskidx]) - { - int srcidx = mad24(y,srcStep_in_pixel,x+ srcoffset_in_pixel); - int dstidx = mad24(y,dstStep_in_pixel,x+ dstoffset_in_pixel); - dstMat[dstidx] = srcMat[srcidx]; - } - } -} diff --git a/modules/ocl/src/opencl/operator_setTo.cl b/modules/ocl/src/opencl/operator_setTo.cl deleted file mode 100644 index 20c5cf211..000000000 --- a/modules/ocl/src/opencl/operator_setTo.cl +++ /dev/null @@ -1,95 +0,0 @@ -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.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. -// -// - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -__kernel void set_to_without_mask_C1_D0(__global uchar * scalar,__global uchar * dstMat, - int cols,int rows,int dstStep_in_pixel,int offset_in_pixel) -{ - int x=get_global_id(0)<<2; - int y=get_global_id(1); - int idx = mad24(y,dstStep_in_pixel,x+ offset_in_pixel); - uchar4 out; - out.x = out.y = out.z = out.w = scalar[0]; - - if ( (x+3 < cols) && (y < rows)&& ((offset_in_pixel&3) == 0)) - { - *(__global uchar4*)(dstMat+idx) = out; - } - else - { - if((x+3 < cols) && (y < rows)) - { - dstMat[idx] = out.x; - dstMat[idx+1] = out.y; - dstMat[idx+2] = out.z; - dstMat[idx+3] = out.w; - } - if((x+2 < cols) && (y < rows)) - { - dstMat[idx] = out.x; - dstMat[idx+1] = out.y; - dstMat[idx+2] = out.z; - } - else if((x+1 < cols) && (y < rows)) - { - dstMat[idx] = out.x; - dstMat[idx+1] = out.y; - } - else if((x < cols) && (y < rows)) - { - dstMat[idx] = out.x; - } - } -} - -__kernel void set_to_without_mask(__global GENTYPE * scalar,__global GENTYPE * dstMat, - int cols, int rows, int dstStep_in_pixel, int offset_in_pixel) -{ - int x = get_global_id(0); - int y = get_global_id(1); - if ( (x < cols) & (y < rows)) - { - int idx = mad24(y, dstStep_in_pixel, x + offset_in_pixel); - dstMat[idx] = scalar[0]; - } -} diff --git a/modules/ocl/src/opencl/operator_setToM.cl b/modules/ocl/src/opencl/operator_setToM.cl deleted file mode 100644 index afaa2e61f..000000000 --- a/modules/ocl/src/opencl/operator_setToM.cl +++ /dev/null @@ -1,68 +0,0 @@ -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.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. -// -// - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -__kernel void set_to_with_mask( - __global GENTYPE * scalar, - __global GENTYPE * dstMat, - int cols, - int rows, - int dstStep_in_pixel, - int dstoffset_in_pixel, - __global const uchar * restrict maskMat, - int maskStep, - int maskoffset) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int maskidx = mad24(y,maskStep,x+ maskoffset); - if (maskMat[maskidx]) - { - int dstidx = mad24(y,dstStep_in_pixel,x+ dstoffset_in_pixel); - dstMat[dstidx] = scalar[0]; - } - } -} diff --git a/modules/ocl/src/opencl/optical_flow_farneback.cl b/modules/ocl/src/opencl/optical_flow_farneback.cl deleted file mode 100644 index 4725662c6..000000000 --- a/modules/ocl/src/opencl/optical_flow_farneback.cl +++ /dev/null @@ -1,450 +0,0 @@ -/*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 -// Sen Liu, swjtuls1987@126.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*/ - - -#define tx (int)get_local_id(0) -#define ty get_local_id(1) -#define bx get_group_id(0) -#define bdx (int)get_local_size(0) - -#define BORDER_SIZE 5 -#define MAX_KSIZE_HALF 100 - -#ifndef polyN -#define polyN 5 -#endif - -__kernel void polynomialExpansion(__global float * dst, - __global __const float * src, - __global __const float * c_g, - __global __const float * c_xg, - __global __const float * c_xxg, - __local float * smem, - const float4 ig, - const int height, const int width, - int dstStep, int srcStep) -{ - const int y = get_global_id(1); - const int x = bx * (bdx - 2*polyN) + tx - polyN; - - dstStep /= sizeof(*dst); - srcStep /= sizeof(*src); - - int xWarped; - __local float *row = smem + tx; - - if (y < height && y >= 0) - { - xWarped = min(max(x, 0), width - 1); - - row[0] = src[mad24(y, srcStep, xWarped)] * c_g[0]; - row[bdx] = 0.f; - row[2*bdx] = 0.f; - -#pragma unroll - for (int k = 1; k <= polyN; ++k) - { - float t0 = src[mad24(max(y - k, 0), srcStep, xWarped)]; - float t1 = src[mad24(min(y + k, height - 1), srcStep, xWarped)]; - - row[0] += c_g[k] * (t0 + t1); - row[bdx] += c_xg[k] * (t1 - t0); - row[2*bdx] += c_xxg[k] * (t0 + t1); - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (y < height && y >= 0 && tx >= polyN && tx + polyN < bdx && x < width) - { - float b1 = c_g[0] * row[0]; - float b3 = c_g[0] * row[bdx]; - float b5 = c_g[0] * row[2*bdx]; - float b2 = 0, b4 = 0, b6 = 0; - -#pragma unroll - for (int k = 1; k <= polyN; ++k) - { - b1 += (row[k] + row[-k]) * c_g[k]; - b4 += (row[k] + row[-k]) * c_xxg[k]; - b2 += (row[k] - row[-k]) * c_xg[k]; - b3 += (row[k + bdx] + row[-k + bdx]) * c_g[k]; - b6 += (row[k + bdx] - row[-k + bdx]) * c_xg[k]; - b5 += (row[k + 2*bdx] + row[-k + 2*bdx]) * c_g[k]; - } - - dst[mad24(y, dstStep, xWarped)] = b3*ig.s0; - dst[mad24(height + y, dstStep, xWarped)] = b2*ig.s0; - dst[mad24(2*height + y, dstStep, xWarped)] = b1*ig.s1 + b5*ig.s2; - dst[mad24(3*height + y, dstStep, xWarped)] = b1*ig.s1 + b4*ig.s2; - dst[mad24(4*height + y, dstStep, xWarped)] = b6*ig.s3; - } -} - -inline int idx_row_low(const int y, const int last_row) -{ - return abs(y) % (last_row + 1); -} - -inline int idx_row_high(const int y, const int last_row) -{ - return abs(last_row - abs(last_row - y)) % (last_row + 1); -} - -inline int idx_row(const int y, const int last_row) -{ - return idx_row_low(idx_row_high(y, last_row), last_row); -} - -inline int idx_col_low(const int x, const int last_col) -{ - return abs(x) % (last_col + 1); -} - -inline int idx_col_high(const int x, const int last_col) -{ - return abs(last_col - abs(last_col - x)) % (last_col + 1); -} - -inline int idx_col(const int x, const int last_col) -{ - return idx_col_low(idx_col_high(x, last_col), last_col); -} - -__kernel void gaussianBlur(__global float * dst, - __global const float * src, - __global const float * c_gKer, - __local float * smem, - const int height, const int width, - int dstStep, int srcStep, - const int ksizeHalf) -{ - const int y = get_global_id(1); - const int x = get_global_id(0); - - dstStep /= sizeof(*dst); - srcStep /= sizeof(*src); - - __local float *row = smem + ty * (bdx + 2*ksizeHalf); - - if (y < height) - { - // Vertical pass - for (int i = tx; i < bdx + 2*ksizeHalf; i += bdx) - { - int xExt = (int)(bx * bdx) + i - ksizeHalf; - xExt = idx_col(xExt, width - 1); - row[i] = src[mad24(y, srcStep, xExt)] * c_gKer[0]; - for (int j = 1; j <= ksizeHalf; ++j) - row[i] += (src[mad24(idx_row_low(y - j, height - 1), srcStep, xExt)] - + src[mad24(idx_row_high(y + j, height - 1), srcStep, xExt)]) * c_gKer[j]; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (y < height && y >= 0 && x < width && x >= 0) - { - // Horizontal pass - row += tx + ksizeHalf; - float res = row[0] * c_gKer[0]; - for (int i = 1; i <= ksizeHalf; ++i) - res += (row[-i] + row[i]) * c_gKer[i]; - - dst[mad24(y, dstStep, x)] = res; - } -} - -__constant float c_border[BORDER_SIZE + 1] = { 0.14f, 0.14f, 0.4472f, 0.4472f, 0.4472f, 1.f }; - -__kernel void updateMatrices(__global float * M, - __global const float * flowx, __global const float * flowy, - __global const float * R0, __global const float * R1, - const int height, const int width, - int mStep, int xStep, int yStep, int R0Step, int R1Step) -{ - const int y = get_global_id(1); - const int x = get_global_id(0); - - mStep /= sizeof(*M); - xStep /= sizeof(*flowx); - yStep /= sizeof(*flowy); - R0Step /= sizeof(*R0); - R1Step /= sizeof(*R1); - - if (y < height && y >= 0 && x < width && x >= 0) - { - float dx = flowx[mad24(y, xStep, x)]; - float dy = flowy[mad24(y, yStep, x)]; - float fx = x + dx; - float fy = y + dy; - - int x1 = convert_int(floor(fx)); - int y1 = convert_int(floor(fy)); - fx -= x1; - fy -= y1; - - float r2, r3, r4, r5, r6; - - if (x1 >= 0 && y1 >= 0 && x1 < width - 1 && y1 < height - 1) - { - float a00 = (1.f - fx) * (1.f - fy); - float a01 = fx * (1.f - fy); - float a10 = (1.f - fx) * fy; - float a11 = fx * fy; - - r2 = a00 * R1[mad24(y1, R1Step, x1)] + - a01 * R1[mad24(y1, R1Step, x1 + 1)] + - a10 * R1[mad24(y1 + 1, R1Step, x1)] + - a11 * R1[mad24(y1 + 1, R1Step, x1 + 1)]; - - r3 = a00 * R1[mad24(height + y1, R1Step, x1)] + - a01 * R1[mad24(height + y1, R1Step, x1 + 1)] + - a10 * R1[mad24(height + y1 + 1, R1Step, x1)] + - a11 * R1[mad24(height + y1 + 1, R1Step, x1 + 1)]; - - r4 = a00 * R1[mad24(2*height + y1, R1Step, x1)] + - a01 * R1[mad24(2*height + y1, R1Step, x1 + 1)] + - a10 * R1[mad24(2*height + y1 + 1, R1Step, x1)] + - a11 * R1[mad24(2*height + y1 + 1, R1Step, x1 + 1)]; - - r5 = a00 * R1[mad24(3*height + y1, R1Step, x1)] + - a01 * R1[mad24(3*height + y1, R1Step, x1 + 1)] + - a10 * R1[mad24(3*height + y1 + 1, R1Step, x1)] + - a11 * R1[mad24(3*height + y1 + 1, R1Step, x1 + 1)]; - - r6 = a00 * R1[mad24(4*height + y1, R1Step, x1)] + - a01 * R1[mad24(4*height + y1, R1Step, x1 + 1)] + - a10 * R1[mad24(4*height + y1 + 1, R1Step, x1)] + - a11 * R1[mad24(4*height + y1 + 1, R1Step, x1 + 1)]; - - r4 = (R0[mad24(2*height + y, R0Step, x)] + r4) * 0.5f; - r5 = (R0[mad24(3*height + y, R0Step, x)] + r5) * 0.5f; - r6 = (R0[mad24(4*height + y, R0Step, x)] + r6) * 0.25f; - } - else - { - r2 = r3 = 0.f; - r4 = R0[mad24(2*height + y, R0Step, x)]; - r5 = R0[mad24(3*height + y, R0Step, x)]; - r6 = R0[mad24(4*height + y, R0Step, x)] * 0.5f; - } - - r2 = (R0[mad24(y, R0Step, x)] - r2) * 0.5f; - r3 = (R0[mad24(height + y, R0Step, x)] - r3) * 0.5f; - - r2 += r4*dy + r6*dx; - r3 += r6*dy + r5*dx; - - float scale = - c_border[min(x, BORDER_SIZE)] * - c_border[min(y, BORDER_SIZE)] * - c_border[min(width - x - 1, BORDER_SIZE)] * - c_border[min(height - y - 1, BORDER_SIZE)]; - - r2 *= scale; - r3 *= scale; - r4 *= scale; - r5 *= scale; - r6 *= scale; - - M[mad24(y, mStep, x)] = r4*r4 + r6*r6; - M[mad24(height + y, mStep, x)] = (r4 + r5)*r6; - M[mad24(2*height + y, mStep, x)] = r5*r5 + r6*r6; - M[mad24(3*height + y, mStep, x)] = r4*r2 + r6*r3; - M[mad24(4*height + y, mStep, x)] = r6*r2 + r5*r3; - } -} - -__kernel void boxFilter5(__global float * dst, - __global const float * src, - __local float * smem, - const int height, const int width, - int dstStep, int srcStep, - const int ksizeHalf) -{ - const int y = get_global_id(1); - const int x = get_global_id(0); - - const float boxAreaInv = 1.f / ((1 + 2*ksizeHalf) * (1 + 2*ksizeHalf)); - const int smw = bdx + 2*ksizeHalf; // shared memory "width" - __local float *row = smem + 5 * ty * smw; - - dstStep /= sizeof(*dst); - srcStep /= sizeof(*src); - - if (y < height) - { - // Vertical pass - for (int i = tx; i < bdx + 2*ksizeHalf; i += bdx) - { - int xExt = (int)(bx * bdx) + i - ksizeHalf; - xExt = min(max(xExt, 0), width - 1); - -#pragma unroll - for (int k = 0; k < 5; ++k) - row[k*smw + i] = src[mad24(k*height + y, srcStep, xExt)]; - - for (int j = 1; j <= ksizeHalf; ++j) -#pragma unroll - for (int k = 0; k < 5; ++k) - row[k*smw + i] += - src[mad24(k*height + max(y - j, 0), srcStep, xExt)] + - src[mad24(k*height + min(y + j, height - 1), srcStep, xExt)]; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (y < height && y >= 0 && x < width && x >= 0) - { - // Horizontal pass - - row += tx + ksizeHalf; - float res[5]; - -#pragma unroll - for (int k = 0; k < 5; ++k) - res[k] = row[k*smw]; - - for (int i = 1; i <= ksizeHalf; ++i) -#pragma unroll - for (int k = 0; k < 5; ++k) - res[k] += row[k*smw - i] + row[k*smw + i]; - -#pragma unroll - for (int k = 0; k < 5; ++k) - dst[mad24(k*height + y, dstStep, x)] = res[k] * boxAreaInv; - } -} - -__kernel void updateFlow(__global float4 * flowx, __global float4 * flowy, - __global const float4 * M, - const int height, const int width, - int xStep, int yStep, int mStep) -{ - const int y = get_global_id(1); - const int x = get_global_id(0); - - xStep /= sizeof(*flowx); - yStep /= sizeof(*flowy); - mStep /= sizeof(*M); - - if (y < height && y >= 0 && x < width && x >= 0) - { - float4 g11 = M[mad24(y, mStep, x)]; - float4 g12 = M[mad24(height + y, mStep, x)]; - float4 g22 = M[mad24(2*height + y, mStep, x)]; - float4 h1 = M[mad24(3*height + y, mStep, x)]; - float4 h2 = M[mad24(4*height + y, mStep, x)]; - - float4 detInv = (float4)(1.f) / (g11*g22 - g12*g12 + (float4)(1e-3f)); - - flowx[mad24(y, xStep, x)] = (g11*h2 - g12*h1) * detInv; - flowy[mad24(y, yStep, x)] = (g22*h1 - g12*h2) * detInv; - } -} - -__kernel void gaussianBlur5(__global float * dst, - __global const float * src, - __global const float * c_gKer, - __local float * smem, - const int height, const int width, - int dstStep, int srcStep, - const int ksizeHalf) -{ - const int y = get_global_id(1); - const int x = get_global_id(0); - - const int smw = bdx + 2*ksizeHalf; // shared memory "width" - __local volatile float *row = smem + 5 * ty * smw; - - dstStep /= sizeof(*dst); - srcStep /= sizeof(*src); - - if (y < height) - { - // Vertical pass - for (int i = tx; i < bdx + 2*ksizeHalf; i += bdx) - { - int xExt = (int)(bx * bdx) + i - ksizeHalf; - xExt = idx_col(xExt, width - 1); - -#pragma unroll - for (int k = 0; k < 5; ++k) - row[k*smw + i] = src[mad24(k*height + y, srcStep, xExt)] * c_gKer[0]; - - for (int j = 1; j <= ksizeHalf; ++j) -#pragma unroll - for (int k = 0; k < 5; ++k) - row[k*smw + i] += - (src[mad24(k*height + idx_row_low(y - j, height - 1), srcStep, xExt)] + - src[mad24(k*height + idx_row_high(y + j, height - 1), srcStep, xExt)]) * c_gKer[j]; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (y < height && y >= 0 && x < width && x >= 0) - { - // Horizontal pass - - row += tx + ksizeHalf; - float res[5]; - -#pragma unroll - for (int k = 0; k < 5; ++k) - res[k] = row[k*smw] * c_gKer[0]; - - for (int i = 1; i <= ksizeHalf; ++i) -#pragma unroll - for (int k = 0; k < 5; ++k) - res[k] += (row[k*smw - i] + row[k*smw + i]) * c_gKer[i]; - -#pragma unroll - for (int k = 0; k < 5; ++k) - dst[mad24(k*height + y, dstStep, x)] = res[k]; - } -} diff --git a/modules/ocl/src/opencl/orb.cl b/modules/ocl/src/opencl/orb.cl deleted file mode 100644 index 36176021a..000000000 --- a/modules/ocl/src/opencl/orb.cl +++ /dev/null @@ -1,503 +0,0 @@ -/*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. -// -// Authors: -// * Peter Andreas Entschev, peter@entschev.com -// -//M*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#define CV_PI M_PI -#else -#define CV_PI M_PI_F -#endif - -#define X_ROW 0 -#define Y_ROW 1 -#define RESPONSE_ROW 2 -#define ANGLE_ROW 3 -#define OCTAVE_ROW 4 -#define SIZE_ROW 5 -#define ROWS_COUNT 6 - - -#ifdef CPU -void reduce_32(volatile __local int* smem, volatile int* val, int tid) -{ -#define op(A, B) (*A)+(B) - - smem[tid] = *val; - barrier(CLK_LOCAL_MEM_FENCE); - - for(int i = 16; i > 0; i >>= 1) - { - if(tid < i) - { - smem[tid] = *val = op(val, smem[tid + i]); - } - barrier(CLK_LOCAL_MEM_FENCE); - } -#undef op -} -#else -void reduce_32(volatile __local int* smem, volatile int* val, int tid) -{ -#define op(A, B) (*A)+(B) - - smem[tid] = *val; - barrier(CLK_LOCAL_MEM_FENCE); - -#ifndef WAVE_SIZE -#define WAVE_SIZE 1 -#endif - if (tid < 16) - { - smem[tid] = *val = op(val, smem[tid + 16]); -#if WAVE_SIZE < 16 - } - barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 8) - { -#endif - smem[tid] = *val = op(val, smem[tid + 8]); -#if WAVE_SIZE < 8 - } - barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 4) - { -#endif - smem[tid] = *val = op(val, smem[tid + 4]); -#if WAVE_SIZE < 4 - } - barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 2) - { -#endif - smem[tid] = *val = op(val, smem[tid + 2]); -#if WAVE_SIZE < 2 - } - barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 1) - { -#endif - smem[tid] = *val = op(val, smem[tid + 1]); - } -#undef WAVE_SIZE -#undef op -} -#endif - -//////////////////////////////////////////////////////////////////////////////////////////////////////// -// HarrisResponses - -__kernel -void HarrisResponses(__global const uchar* img, - __global float* keypoints, - const int npoints, - const int blockSize, - const float harris_k, - const int img_step, - const int keypoints_step) -{ - __local int smem0[8 * 32]; - __local int smem1[8 * 32]; - __local int smem2[8 * 32]; - - const int ptidx = mad24(get_group_id(0), get_local_size(1), get_local_id(1)); - - if (ptidx < npoints) - { - const int pt_x = keypoints[mad24(keypoints_step, X_ROW, ptidx)]; - const int pt_y = keypoints[mad24(keypoints_step, Y_ROW, ptidx)]; - - const int r = blockSize / 2; - const int x0 = pt_x - r; - const int y0 = pt_y - r; - - int a = 0, b = 0, c = 0; - - for (int ind = get_local_id(0); ind < blockSize * blockSize; ind += get_local_size(0)) - { - const int i = ind / blockSize; - const int j = ind % blockSize; - - int center = mad24(y0+i, img_step, x0+j); - - int Ix = (img[center+1] - img[center-1]) * 2 + - (img[center-img_step+1] - img[center-img_step-1]) + - (img[center+img_step+1] - img[center+img_step-1]); - - int Iy = (img[center+img_step] - img[center-img_step]) * 2 + - (img[center+img_step-1] - img[center-img_step-1]) + - (img[center+img_step+1] - img[center-img_step+1]); - - a += Ix * Ix; - b += Iy * Iy; - c += Ix * Iy; - } - - __local int* srow0 = smem0 + get_local_id(1) * get_local_size(0); - __local int* srow1 = smem1 + get_local_id(1) * get_local_size(0); - __local int* srow2 = smem2 + get_local_id(1) * get_local_size(0); - - reduce_32(srow0, &a, get_local_id(0)); - reduce_32(srow1, &b, get_local_id(0)); - reduce_32(srow2, &c, get_local_id(0)); - - if (get_local_id(0) == 0) - { - float scale = (1 << 2) * blockSize * 255.0f; - scale = 1.0f / scale; - const float scale_sq_sq = scale * scale * scale * scale; - - float response = ((float)a * b - (float)c * c - harris_k * ((float)a + b) * ((float)a + b)) * scale_sq_sq; - keypoints[mad24(keypoints_step, RESPONSE_ROW, ptidx)] = response; - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////// -// IC_Angle - -__kernel -void IC_Angle(__global const uchar* img, - __global float* keypoints_, - __global const int* u_max, - const int npoints, - const int half_k, - const int img_step, - const int keypoints_step) -{ - __local int smem0[8 * 32]; - __local int smem1[8 * 32]; - - __local int* srow0 = smem0 + get_local_id(1) * get_local_size(0); - __local int* srow1 = smem1 + get_local_id(1) * get_local_size(0); - - const int ptidx = mad24(get_group_id(0), get_local_size(1), get_local_id(1)); - - if (ptidx < npoints) - { - int m_01 = 0, m_10 = 0; - - const int pt_x = keypoints_[mad24(keypoints_step, X_ROW, ptidx)]; - const int pt_y = keypoints_[mad24(keypoints_step, Y_ROW, ptidx)]; - - // Treat the center line differently, v=0 - for (int u = get_local_id(0) - half_k; u <= half_k; u += get_local_size(0)) - m_10 += u * img[mad24(pt_y, img_step, pt_x+u)]; - - reduce_32(srow0, &m_10, get_local_id(0)); - - for (int v = 1; v <= half_k; ++v) - { - // Proceed over the two lines - int v_sum = 0; - int m_sum = 0; - const int d = u_max[v]; - - for (int u = get_local_id(0) - d; u <= d; u += get_local_size(0)) - { - int val_plus = img[mad24(pt_y+v, img_step, pt_x+u)]; - int val_minus = img[mad24(pt_y-v, img_step, pt_x+u)]; - - v_sum += (val_plus - val_minus); - m_sum += u * (val_plus + val_minus); - } - - reduce_32(srow0, &v_sum, get_local_id(0)); - reduce_32(srow1, &m_sum, get_local_id(0)); - - m_10 += m_sum; - m_01 += v * v_sum; - } - - if (get_local_id(0) == 0) - { - float kp_dir = atan2((float)m_01, (float)m_10); - kp_dir += (kp_dir < 0) * (2.0f * CV_PI); - kp_dir *= 180.0f / CV_PI; - - keypoints_[mad24(keypoints_step, ANGLE_ROW, ptidx)] = kp_dir; - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////// -// computeOrbDescriptor - -#define GET_VALUE(idx) \ - img[mad24(loc.y + (int)round(pattern[idx] * sina + pattern[pattern_step+idx] * cosa), img_step, \ - loc.x + (int)round(pattern[idx] * cosa - pattern[pattern_step+idx] * sina))] - -int calcOrbDescriptor_2(__global const uchar* img, - __global const int* pattern, - const int2 loc, - const float sina, - const float cosa, - const int i, - const int img_step, - const int pattern_step) -{ - pattern += 16 * i; - - int t0, t1, val; - - t0 = GET_VALUE(0); t1 = GET_VALUE(1); - val = t0 < t1; - - t0 = GET_VALUE(2); t1 = GET_VALUE(3); - val |= (t0 < t1) << 1; - - t0 = GET_VALUE(4); t1 = GET_VALUE(5); - val |= (t0 < t1) << 2; - - t0 = GET_VALUE(6); t1 = GET_VALUE(7); - val |= (t0 < t1) << 3; - - t0 = GET_VALUE(8); t1 = GET_VALUE(9); - val |= (t0 < t1) << 4; - - t0 = GET_VALUE(10); t1 = GET_VALUE(11); - val |= (t0 < t1) << 5; - - t0 = GET_VALUE(12); t1 = GET_VALUE(13); - val |= (t0 < t1) << 6; - - t0 = GET_VALUE(14); t1 = GET_VALUE(15); - val |= (t0 < t1) << 7; - - return val; -} - -int calcOrbDescriptor_3(__global const uchar* img, - __global const int* pattern, - const int2 loc, - const float sina, - const float cosa, - const int i, - const int img_step, - const int pattern_step) -{ - pattern += 12 * i; - - int t0, t1, t2, val; - - t0 = GET_VALUE(0); t1 = GET_VALUE(1); t2 = GET_VALUE(2); - val = t2 > t1 ? (t2 > t0 ? 2 : 0) : (t1 > t0); - - t0 = GET_VALUE(3); t1 = GET_VALUE(4); t2 = GET_VALUE(5); - val |= (t2 > t1 ? (t2 > t0 ? 2 : 0) : (t1 > t0)) << 2; - - t0 = GET_VALUE(6); t1 = GET_VALUE(7); t2 = GET_VALUE(8); - val |= (t2 > t1 ? (t2 > t0 ? 2 : 0) : (t1 > t0)) << 4; - - t0 = GET_VALUE(9); t1 = GET_VALUE(10); t2 = GET_VALUE(11); - val |= (t2 > t1 ? (t2 > t0 ? 2 : 0) : (t1 > t0)) << 6; - - return val; -} - -int calcOrbDescriptor_4(__global const uchar* img, - __global const int* pattern, - const int2 loc, - const float sina, - const float cosa, - const int i, - const int img_step, - const int pattern_step) -{ - pattern += 16 * i; - - int t0, t1, t2, t3, k, val; - int a, b; - - t0 = GET_VALUE(0); t1 = GET_VALUE(1); - t2 = GET_VALUE(2); t3 = GET_VALUE(3); - a = 0, b = 2; - if( t1 > t0 ) t0 = t1, a = 1; - if( t3 > t2 ) t2 = t3, b = 3; - k = t0 > t2 ? a : b; - val = k; - - t0 = GET_VALUE(4); t1 = GET_VALUE(5); - t2 = GET_VALUE(6); t3 = GET_VALUE(7); - a = 0, b = 2; - if( t1 > t0 ) t0 = t1, a = 1; - if( t3 > t2 ) t2 = t3, b = 3; - k = t0 > t2 ? a : b; - val |= k << 2; - - t0 = GET_VALUE(8); t1 = GET_VALUE(9); - t2 = GET_VALUE(10); t3 = GET_VALUE(11); - a = 0, b = 2; - if( t1 > t0 ) t0 = t1, a = 1; - if( t3 > t2 ) t2 = t3, b = 3; - k = t0 > t2 ? a : b; - val |= k << 4; - - t0 = GET_VALUE(12); t1 = GET_VALUE(13); - t2 = GET_VALUE(14); t3 = GET_VALUE(15); - a = 0, b = 2; - if( t1 > t0 ) t0 = t1, a = 1; - if( t3 > t2 ) t2 = t3, b = 3; - k = t0 > t2 ? a : b; - val |= k << 6; - - return val; -} - -#undef GET_VALUE - -__kernel -void computeOrbDescriptor(__global const uchar* img, - __global const float* keypoints, - __global const int* pattern, - __global uchar* desc, - const int npoints, - const int dsize, - const int WTA_K, - const int offset, - const int img_step, - const int keypoints_step, - const int pattern_step, - const int desc_step) -{ - const int descidx = mad24(get_group_id(0), get_local_size(0), get_local_id(0)); - const int ptidx = mad24(get_group_id(1), get_local_size(1), get_local_id(1)); - - if (ptidx < npoints && descidx < dsize) - { - int2 loc = {(int)keypoints[mad24(keypoints_step, X_ROW, ptidx)], - (int)keypoints[mad24(keypoints_step, Y_ROW, ptidx)]}; - - float angle = keypoints[mad24(keypoints_step, ANGLE_ROW, ptidx)]; - angle *= (float)(CV_PI / 180.f); - - float sina = sin(angle); - float cosa = cos(angle); - - if (WTA_K == 2) - desc[mad24(ptidx+offset, desc_step, descidx)] = calcOrbDescriptor_2(img, pattern, loc, sina, cosa, descidx, img_step, pattern_step); - else if (WTA_K == 3) - desc[mad24(ptidx+offset, desc_step, descidx)] = calcOrbDescriptor_3(img, pattern, loc, sina, cosa, descidx, img_step, pattern_step); - else if (WTA_K == 4) - desc[mad24(ptidx+offset, desc_step, descidx)] = calcOrbDescriptor_4(img, pattern, loc, sina, cosa, descidx, img_step, pattern_step); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////// -// mergeLocation - -__kernel -void mergeLocation(__global const float* keypoints_in, - __global float* keypoints_out, - const int npoints, - const int offset, - const float scale, - const int octave, - const float size, - const int keypoints_in_step, - const int keypoints_out_step) -{ - //const int ptidx = blockIdx.x * blockDim.x + threadIdx.x; - const int ptidx = mad24(get_group_id(0), get_local_size(0), get_local_id(0)); - - if (ptidx < npoints) - { - float pt_x = keypoints_in[mad24(keypoints_in_step, X_ROW, ptidx)] * scale; - float pt_y = keypoints_in[mad24(keypoints_in_step, Y_ROW, ptidx)] * scale; - float response = keypoints_in[mad24(keypoints_in_step, RESPONSE_ROW, ptidx)]; - float angle = keypoints_in[mad24(keypoints_in_step, ANGLE_ROW, ptidx)]; - - keypoints_out[mad24(keypoints_out_step, X_ROW, ptidx+offset)] = pt_x; - keypoints_out[mad24(keypoints_out_step, Y_ROW, ptidx+offset)] = pt_y; - keypoints_out[mad24(keypoints_out_step, RESPONSE_ROW, ptidx+offset)] = response; - keypoints_out[mad24(keypoints_out_step, ANGLE_ROW, ptidx+offset)] = angle; - keypoints_out[mad24(keypoints_out_step, OCTAVE_ROW, ptidx+offset)] = (float)octave; - keypoints_out[mad24(keypoints_out_step, SIZE_ROW, ptidx+offset)] = size; - } -} - -__kernel -void convertRowsToChannels(__global const float* keypoints_in, - __global float* keypoints_out, - const int npoints, - const int keypoints_in_step, - const int keypoints_out_step) -{ - const int ptidx = mad24(get_group_id(0), get_local_size(0), get_local_id(0)); - - if (ptidx < npoints) - { - const int pt_x = keypoints_in[mad24(keypoints_in_step, X_ROW, ptidx)]; - const int pt_y = keypoints_in[mad24(keypoints_in_step, Y_ROW, ptidx)]; - - keypoints_out[ptidx*2] = pt_x; - keypoints_out[ptidx*2+1] = pt_y; - } -} - -__kernel -void convertChannelsToRows(__global const float* keypoints_pos, - __global const float* keypoints_resp, - __global float* keypoints_out, - const int npoints, - const int keypoints_pos_step, - const int keypoints_resp_step, - const int keypoints_out_step) -{ - const int ptidx = mad24(get_group_id(0), get_local_size(0), get_local_id(0)); - - if (ptidx < npoints) - { - const float pt_x = keypoints_pos[ptidx*2]; - const float pt_y = keypoints_pos[ptidx*2+1]; - const float resp = keypoints_resp[ptidx]; - - keypoints_out[mad24(keypoints_out_step, X_ROW, ptidx)] = pt_x; - keypoints_out[mad24(keypoints_out_step, Y_ROW, ptidx)] = pt_y; - keypoints_out[mad24(keypoints_out_step, RESPONSE_ROW, ptidx)] = resp; - } -} diff --git a/modules/ocl/src/opencl/pyr_down.cl b/modules/ocl/src/opencl/pyr_down.cl deleted file mode 100644 index 6f10067e9..000000000 --- a/modules/ocl/src/opencl/pyr_down.cl +++ /dev/null @@ -1,1010 +0,0 @@ -/*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 -// Dachuan Zhao, dachuan@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*/ - -inline int idx_row_low(int y, int last_row) -{ - return abs(y) % (last_row + 1); -} - -inline int idx_row_high(int y, int last_row) -{ - return abs(last_row - (int)abs(last_row - y)) % (last_row + 1); -} - -inline int idx_row(int y, int last_row) -{ - return idx_row_low(idx_row_high(y, last_row), last_row); -} - -inline int idx_col_low(int x, int last_col) -{ - return abs(x) % (last_col + 1); -} - -inline int idx_col_high(int x, int last_col) -{ - return abs(last_col - (int)abs(last_col - x)) % (last_col + 1); -} - -inline int idx_col(int x, int last_col) -{ - return idx_col_low(idx_col_high(x, last_col), last_col); -} - -/////////////////////////////////////////////////////////////////////// -////////////////////////// CV_8UC1 /////////////////////////////////// -/////////////////////////////////////////////////////////////////////// - -__kernel void pyrDown_C1_D0(__global uchar * srcData, int srcStep, int srcRows, int srcCols, __global uchar *dst, int dstStep, int dstCols) -{ - const int x = get_global_id(0); - const int y = get_group_id(1); - - __local float smem[256 + 4]; - - float sum; - - const int src_y = 2*y; - const int last_row = srcRows - 1; - const int last_col = srcCols - 1; - - if (src_y >= 2 && src_y < srcRows - 2 && x >= 2 && x < srcCols - 2) - { - sum = 0.0625f * (((srcData + (src_y - 2) * srcStep))[x]); - sum = sum + 0.25f * (((srcData + (src_y - 1) * srcStep))[x]); - sum = sum + 0.375f * (((srcData + (src_y ) * srcStep))[x]); - sum = sum + 0.25f * (((srcData + (src_y + 1) * srcStep))[x]); - sum = sum + 0.0625f * (((srcData + (src_y + 2) * srcStep))[x]); - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - sum = 0.0625f * (((srcData + (src_y - 2) * srcStep))[left_x]); - sum = sum + 0.25f * (((srcData + (src_y - 1) * srcStep))[left_x]); - sum = sum + 0.375f * (((srcData + (src_y ) * srcStep))[left_x]); - sum = sum + 0.25f * (((srcData + (src_y + 1) * srcStep))[left_x]); - sum = sum + 0.0625f * (((srcData + (src_y + 2) * srcStep))[left_x]); - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - sum = 0.0625f * (((srcData + (src_y - 2) * srcStep))[right_x]); - sum = sum + 0.25f * (((srcData + (src_y - 1) * srcStep))[right_x]); - sum = sum + 0.375f * (((srcData + (src_y ) * srcStep))[right_x]); - sum = sum + 0.25f * (((srcData + (src_y + 1) * srcStep))[right_x]); - sum = sum + 0.0625f * (((srcData + (src_y + 2) * srcStep))[right_x]); - - smem[4 + get_local_id(0)] = sum; - } - } - else - { - int col = idx_col(x, last_col); - - sum = 0.0625f * (((srcData + idx_row(src_y - 2, last_row) * srcStep))[col]); - sum = sum + 0.25f * (((srcData + idx_row(src_y - 1, last_row) * srcStep))[col]); - sum = sum + 0.375f * (((srcData + idx_row(src_y , last_row) * srcStep))[col]); - sum = sum + 0.25f * (((srcData + idx_row(src_y + 1, last_row) * srcStep))[col]); - sum = sum + 0.0625f * (((srcData + idx_row(src_y + 2, last_row) * srcStep))[col]); - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - col = idx_col(left_x, last_col); - - sum = 0.0625f * (((srcData + idx_row(src_y - 2, last_row) * srcStep))[col]); - sum = sum + 0.25f * (((srcData + idx_row(src_y - 1, last_row) * srcStep))[col]); - sum = sum + 0.375f * (((srcData + idx_row(src_y , last_row) * srcStep))[col]); - sum = sum + 0.25f * (((srcData + idx_row(src_y + 1, last_row) * srcStep))[col]); - sum = sum + 0.0625f * (((srcData + idx_row(src_y + 2, last_row) * srcStep))[col]); - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - col = idx_col(right_x, last_col); - - sum = 0.0625f * (((srcData + idx_row(src_y - 2, last_row) * srcStep))[col]); - sum = sum + 0.25f * (((srcData + idx_row(src_y - 1, last_row) * srcStep))[col]); - sum = sum + 0.375f * (((srcData + idx_row(src_y , last_row) * srcStep))[col]); - sum = sum + 0.25f * (((srcData + idx_row(src_y + 1, last_row) * srcStep))[col]); - sum = sum + 0.0625f * (((srcData + idx_row(src_y + 2, last_row) * srcStep))[col]); - - smem[4 + get_local_id(0)] = sum; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (get_local_id(0) < 128) - { - const int tid2 = get_local_id(0) * 2; - - sum = 0.0625f * smem[2 + tid2 - 2]; - sum = sum + 0.25f * smem[2 + tid2 - 1]; - sum = sum + 0.375f * smem[2 + tid2 ]; - sum = sum + 0.25f * smem[2 + tid2 + 1]; - sum = sum + 0.0625f * smem[2 + tid2 + 2]; - - const int dst_x = (get_group_id(0) * get_local_size(0) + tid2) / 2; - - if (dst_x < dstCols) - dst[y * dstStep + dst_x] = convert_uchar_sat_rte(sum); - } -} - -/////////////////////////////////////////////////////////////////////// -////////////////////////// CV_8UC4 /////////////////////////////////// -/////////////////////////////////////////////////////////////////////// - -__kernel void pyrDown_C4_D0(__global uchar4 * srcData, int srcStep, int srcRows, int srcCols, __global uchar4 *dst, int dstStep, int dstCols) -{ - const int x = get_global_id(0); - const int y = get_group_id(1); - - __local float4 smem[256 + 4]; - - float4 sum; - - const int src_y = 2*y; - const int last_row = srcRows - 1; - const int last_col = srcCols - 1; - - float4 co1 = 0.375f; - float4 co2 = 0.25f; - float4 co3 = 0.0625f; - - if (src_y >= 2 && src_y < srcRows - 2 && x >= 2 && x < srcCols - 2) - { - sum = co3 * convert_float4((((srcData + (src_y - 2) * srcStep / 4))[x])); - sum = sum + co2 * convert_float4((((srcData + (src_y - 1) * srcStep / 4))[x])); - sum = sum + co1 * convert_float4((((srcData + (src_y ) * srcStep / 4))[x])); - sum = sum + co2 * convert_float4((((srcData + (src_y + 1) * srcStep / 4))[x])); - sum = sum + co3 * convert_float4((((srcData + (src_y + 2) * srcStep / 4))[x])); - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - sum = co3 * convert_float4((((srcData + (src_y - 2) * srcStep / 4))[left_x])); - sum = sum + co2 * convert_float4((((srcData + (src_y - 1) * srcStep / 4))[left_x])); - sum = sum + co1 * convert_float4((((srcData + (src_y ) * srcStep / 4))[left_x])); - sum = sum + co2 * convert_float4((((srcData + (src_y + 1) * srcStep / 4))[left_x])); - sum = sum + co3 * convert_float4((((srcData + (src_y + 2) * srcStep / 4))[left_x])); - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - sum = co3 * convert_float4((((srcData + (src_y - 2) * srcStep / 4))[right_x])); - sum = sum + co2 * convert_float4((((srcData + (src_y - 1) * srcStep / 4))[right_x])); - sum = sum + co1 * convert_float4((((srcData + (src_y ) * srcStep / 4))[right_x])); - sum = sum + co2 * convert_float4((((srcData + (src_y + 1) * srcStep / 4))[right_x])); - sum = sum + co3 * convert_float4((((srcData + (src_y + 2) * srcStep / 4))[right_x])); - - smem[4 + get_local_id(0)] = sum; - } - } - else - { - int col = idx_col(x, last_col); - - sum = co3 * convert_float4((((srcData + idx_row(src_y - 2, last_row) * srcStep / 4))[col])); - sum = sum + co2 * convert_float4((((srcData + idx_row(src_y - 1, last_row) * srcStep / 4))[col])); - sum = sum + co1 * convert_float4((((srcData + idx_row(src_y , last_row) * srcStep / 4))[col])); - sum = sum + co2 * convert_float4((((srcData + idx_row(src_y + 1, last_row) * srcStep / 4))[col])); - sum = sum + co3 * convert_float4((((srcData + idx_row(src_y + 2, last_row) * srcStep / 4))[col])); - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - col = idx_col(left_x, last_col); - - sum = co3 * convert_float4((((srcData + idx_row(src_y - 2, last_row) * srcStep / 4))[col])); - sum = sum + co2 * convert_float4((((srcData + idx_row(src_y - 1, last_row) * srcStep / 4))[col])); - sum = sum + co1 * convert_float4((((srcData + idx_row(src_y , last_row) * srcStep / 4))[col])); - sum = sum + co2 * convert_float4((((srcData + idx_row(src_y + 1, last_row) * srcStep / 4))[col])); - sum = sum + co3 * convert_float4((((srcData + idx_row(src_y + 2, last_row) * srcStep / 4))[col])); - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - col = idx_col(right_x, last_col); - - sum = co3 * convert_float4((((srcData + idx_row(src_y - 2, last_row) * srcStep / 4))[col])); - sum = sum + co2 * convert_float4((((srcData + idx_row(src_y - 1, last_row) * srcStep / 4))[col])); - sum = sum + co1 * convert_float4((((srcData + idx_row(src_y , last_row) * srcStep / 4))[col])); - sum = sum + co2 * convert_float4((((srcData + idx_row(src_y + 1, last_row) * srcStep / 4))[col])); - sum = sum + co3 * convert_float4((((srcData + idx_row(src_y + 2, last_row) * srcStep / 4))[col])); - - smem[4 + get_local_id(0)] = sum; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (get_local_id(0) < 128) - { - const int tid2 = get_local_id(0) * 2; - - sum = co3 * smem[2 + tid2 - 2]; - sum = sum + co2 * smem[2 + tid2 - 1]; - sum = sum + co1 * smem[2 + tid2 ]; - sum = sum + co2 * smem[2 + tid2 + 1]; - sum = sum + co3 * smem[2 + tid2 + 2]; - - const int dst_x = (get_group_id(0) * get_local_size(0) + tid2) / 2; - - if (dst_x < dstCols) - dst[y * dstStep / 4 + dst_x] = convert_uchar4_sat_rte(sum); - } -} - -/////////////////////////////////////////////////////////////////////// -////////////////////////// CV_16UC1 ////////////////////////////////// -/////////////////////////////////////////////////////////////////////// - -__kernel void pyrDown_C1_D2(__global ushort * srcData, int srcStep, int srcRows, int srcCols, __global ushort *dst, int dstStep, int dstCols) -{ - const int x = get_global_id(0); - const int y = get_group_id(1); - - __local float smem[256 + 4]; - - float sum; - - const int src_y = 2*y; - const int last_row = srcRows - 1; - const int last_col = srcCols - 1; - - if (src_y >= 2 && src_y < srcRows - 2 && x >= 2 && x < srcCols - 2) - { - sum = 0.0625f * ((__global ushort*)((__global char*)srcData + (src_y - 2) * srcStep))[x]; - sum = sum + 0.25f * ((__global ushort*)((__global char*)srcData + (src_y - 1) * srcStep))[x]; - sum = sum + 0.375f * ((__global ushort*)((__global char*)srcData + (src_y ) * srcStep))[x]; - sum = sum + 0.25f * ((__global ushort*)((__global char*)srcData + (src_y + 1) * srcStep))[x]; - sum = sum + 0.0625f * ((__global ushort*)((__global char*)srcData + (src_y + 2) * srcStep))[x]; - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - sum = 0.0625f * ((__global ushort*)((__global char*)srcData + (src_y - 2) * srcStep))[left_x]; - sum = sum + 0.25f * ((__global ushort*)((__global char*)srcData + (src_y - 1) * srcStep))[left_x]; - sum = sum + 0.375f * ((__global ushort*)((__global char*)srcData + (src_y ) * srcStep))[left_x]; - sum = sum + 0.25f * ((__global ushort*)((__global char*)srcData + (src_y + 1) * srcStep))[left_x]; - sum = sum + 0.0625f * ((__global ushort*)((__global char*)srcData + (src_y + 2) * srcStep))[left_x]; - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - sum = 0.0625f * ((__global ushort*)((__global char*)srcData + (src_y - 2) * srcStep))[right_x]; - sum = sum + 0.25f * ((__global ushort*)((__global char*)srcData + (src_y - 1) * srcStep))[right_x]; - sum = sum + 0.375f * ((__global ushort*)((__global char*)srcData + (src_y ) * srcStep))[right_x]; - sum = sum + 0.25f * ((__global ushort*)((__global char*)srcData + (src_y + 1) * srcStep))[right_x]; - sum = sum + 0.0625f * ((__global ushort*)((__global char*)srcData + (src_y + 2) * srcStep))[right_x]; - - smem[4 + get_local_id(0)] = sum; - } - } - else - { - int col = idx_col(x, last_col); - - sum = 0.0625f * ((__global ushort*)((__global char*)srcData + idx_row(src_y - 2, last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global ushort*)((__global char*)srcData + idx_row(src_y - 1, last_row) * srcStep))[col]; - sum = sum + 0.375f * ((__global ushort*)((__global char*)srcData + idx_row(src_y , last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global ushort*)((__global char*)srcData + idx_row(src_y + 1, last_row) * srcStep))[col]; - sum = sum + 0.0625f * ((__global ushort*)((__global char*)srcData + idx_row(src_y + 2, last_row) * srcStep))[col]; - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - col = idx_col(left_x, last_col); - - sum = 0.0625f * ((__global ushort*)((__global char*)srcData + idx_row(src_y - 2, last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global ushort*)((__global char*)srcData + idx_row(src_y - 1, last_row) * srcStep))[col]; - sum = sum + 0.375f * ((__global ushort*)((__global char*)srcData + idx_row(src_y , last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global ushort*)((__global char*)srcData + idx_row(src_y + 1, last_row) * srcStep))[col]; - sum = sum + 0.0625f * ((__global ushort*)((__global char*)srcData + idx_row(src_y + 2, last_row) * srcStep))[col]; - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - col = idx_col(right_x, last_col); - - sum = 0.0625f * ((__global ushort*)((__global char*)srcData + idx_row(src_y - 2, last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global ushort*)((__global char*)srcData + idx_row(src_y - 1, last_row) * srcStep))[col]; - sum = sum + 0.375f * ((__global ushort*)((__global char*)srcData + idx_row(src_y , last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global ushort*)((__global char*)srcData + idx_row(src_y + 1, last_row) * srcStep))[col]; - sum = sum + 0.0625f * ((__global ushort*)((__global char*)srcData + idx_row(src_y + 2, last_row) * srcStep))[col]; - - smem[4 + get_local_id(0)] = sum; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (get_local_id(0) < 128) - { - const int tid2 = get_local_id(0) * 2; - - sum = 0.0625f * smem[2 + tid2 - 2]; - sum = sum + 0.25f * smem[2 + tid2 - 1]; - sum = sum + 0.375f * smem[2 + tid2 ]; - sum = sum + 0.25f * smem[2 + tid2 + 1]; - sum = sum + 0.0625f * smem[2 + tid2 + 2]; - - const int dst_x = (get_group_id(0) * get_local_size(0) + tid2) / 2; - - if (dst_x < dstCols) - dst[y * dstStep / 2 + dst_x] = convert_ushort_sat_rte(sum); - } -} - -/////////////////////////////////////////////////////////////////////// -////////////////////////// CV_16UC4 ////////////////////////////////// -/////////////////////////////////////////////////////////////////////// - -__kernel void pyrDown_C4_D2(__global ushort4 * srcData, int srcStep, int srcRows, int srcCols, __global ushort4 *dst, int dstStep, int dstCols) -{ - const int x = get_global_id(0); - const int y = get_group_id(1); - - __local float4 smem[256 + 4]; - - float4 sum; - - const int src_y = 2*y; - const int last_row = srcRows - 1; - const int last_col = srcCols - 1; - - float4 co1 = 0.375f; - float4 co2 = 0.25f; - float4 co3 = 0.0625f; - - if (src_y >= 2 && src_y < srcRows - 2 && x >= 2 && x < srcCols - 2) - { - sum = co3 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y - 2) * srcStep / 4))[x]); - sum = sum + co2 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y - 1) * srcStep / 4))[x]); - sum = sum + co1 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y ) * srcStep / 4))[x]); - sum = sum + co2 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y + 1) * srcStep / 4))[x]); - sum = sum + co3 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y + 2) * srcStep / 4))[x]); - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - sum = co3 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y - 2) * srcStep / 4))[left_x]); - sum = sum + co2 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y - 1) * srcStep / 4))[left_x]); - sum = sum + co1 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y ) * srcStep / 4))[left_x]); - sum = sum + co2 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y + 1) * srcStep / 4))[left_x]); - sum = sum + co3 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y + 2) * srcStep / 4))[left_x]); - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - sum = co3 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y - 2) * srcStep / 4))[right_x]); - sum = sum + co2 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y - 1) * srcStep / 4))[right_x]); - sum = sum + co1 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y ) * srcStep / 4))[right_x]); - sum = sum + co2 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y + 1) * srcStep / 4))[right_x]); - sum = sum + co3 * convert_float4(((__global ushort4*)((__global char4*)srcData + (src_y + 2) * srcStep / 4))[right_x]); - - smem[4 + get_local_id(0)] = sum; - } - } - else - { - int col = idx_col(x, last_col); - - sum = co3 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y - 2, last_row) * srcStep / 4))[col]); - sum = sum + co2 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y - 1, last_row) * srcStep / 4))[col]); - sum = sum + co1 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y , last_row) * srcStep / 4))[col]); - sum = sum + co2 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y + 1, last_row) * srcStep / 4))[col]); - sum = sum + co3 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y + 2, last_row) * srcStep / 4))[col]); - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - col = idx_col(left_x, last_col); - - sum = co3 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y - 2, last_row) * srcStep / 4))[col]); - sum = sum + co2 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y - 1, last_row) * srcStep / 4))[col]); - sum = sum + co1 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y , last_row) * srcStep / 4))[col]); - sum = sum + co2 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y + 1, last_row) * srcStep / 4))[col]); - sum = sum + co3 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y + 2, last_row) * srcStep / 4))[col]); - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - col = idx_col(right_x, last_col); - - sum = co3 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y - 2, last_row) * srcStep / 4))[col]); - sum = sum + co2 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y - 1, last_row) * srcStep / 4))[col]); - sum = sum + co1 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y , last_row) * srcStep / 4))[col]); - sum = sum + co2 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y + 1, last_row) * srcStep / 4))[col]); - sum = sum + co3 * convert_float4(((__global ushort4*)((__global char4*)srcData + idx_row(src_y + 2, last_row) * srcStep / 4))[col]); - - smem[4 + get_local_id(0)] = sum; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (get_local_id(0) < 128) - { - const int tid2 = get_local_id(0) * 2; - - sum = co3 * smem[2 + tid2 - 2]; - sum = sum + co2 * smem[2 + tid2 - 1]; - sum = sum + co1 * smem[2 + tid2 ]; - sum = sum + co2 * smem[2 + tid2 + 1]; - sum = sum + co3 * smem[2 + tid2 + 2]; - - const int dst_x = (get_group_id(0) * get_local_size(0) + tid2) / 2; - - if (dst_x < dstCols) - dst[y * dstStep / 8 + dst_x] = convert_ushort4_sat_rte(sum); - } -} - -/////////////////////////////////////////////////////////////////////// -////////////////////////// CV_16SC1 ////////////////////////////////// -/////////////////////////////////////////////////////////////////////// - -__kernel void pyrDown_C1_D3(__global short * srcData, int srcStep, int srcRows, int srcCols, __global short *dst, int dstStep, int dstCols) -{ - const int x = get_global_id(0); - const int y = get_group_id(1); - - __local float smem[256 + 4]; - - float sum; - - const int src_y = 2*y; - const int last_row = srcRows - 1; - const int last_col = srcCols - 1; - - if (src_y >= 2 && src_y < srcRows - 2 && x >= 2 && x < srcCols - 2) - { - sum = 0.0625f * ((__global short*)((__global char*)srcData + (src_y - 2) * srcStep))[x]; - sum = sum + 0.25f * ((__global short*)((__global char*)srcData + (src_y - 1) * srcStep))[x]; - sum = sum + 0.375f * ((__global short*)((__global char*)srcData + (src_y ) * srcStep))[x]; - sum = sum + 0.25f * ((__global short*)((__global char*)srcData + (src_y + 1) * srcStep))[x]; - sum = sum + 0.0625f * ((__global short*)((__global char*)srcData + (src_y + 2) * srcStep))[x]; - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - sum = 0.0625f * ((__global short*)((__global char*)srcData + (src_y - 2) * srcStep))[left_x]; - sum = sum + 0.25f * ((__global short*)((__global char*)srcData + (src_y - 1) * srcStep))[left_x]; - sum = sum + 0.375f * ((__global short*)((__global char*)srcData + (src_y ) * srcStep))[left_x]; - sum = sum + 0.25f * ((__global short*)((__global char*)srcData + (src_y + 1) * srcStep))[left_x]; - sum = sum + 0.0625f * ((__global short*)((__global char*)srcData + (src_y + 2) * srcStep))[left_x]; - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - sum = 0.0625f * ((__global short*)((__global char*)srcData + (src_y - 2) * srcStep))[right_x]; - sum = sum + 0.25f * ((__global short*)((__global char*)srcData + (src_y - 1) * srcStep))[right_x]; - sum = sum + 0.375f * ((__global short*)((__global char*)srcData + (src_y ) * srcStep))[right_x]; - sum = sum + 0.25f * ((__global short*)((__global char*)srcData + (src_y + 1) * srcStep))[right_x]; - sum = sum + 0.0625f * ((__global short*)((__global char*)srcData + (src_y + 2) * srcStep))[right_x]; - - smem[4 + get_local_id(0)] = sum; - } - } - else - { - int col = idx_col(x, last_col); - - sum = 0.0625f * ((__global short*)((__global char*)srcData + idx_row(src_y - 2, last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global short*)((__global char*)srcData + idx_row(src_y - 1, last_row) * srcStep))[col]; - sum = sum + 0.375f * ((__global short*)((__global char*)srcData + idx_row(src_y , last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global short*)((__global char*)srcData + idx_row(src_y + 1, last_row) * srcStep))[col]; - sum = sum + 0.0625f * ((__global short*)((__global char*)srcData + idx_row(src_y + 2, last_row) * srcStep))[col]; - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - col = idx_col(left_x, last_col); - - sum = 0.0625f * ((__global short*)((__global char*)srcData + idx_row(src_y - 2, last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global short*)((__global char*)srcData + idx_row(src_y - 1, last_row) * srcStep))[col]; - sum = sum + 0.375f * ((__global short*)((__global char*)srcData + idx_row(src_y , last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global short*)((__global char*)srcData + idx_row(src_y + 1, last_row) * srcStep))[col]; - sum = sum + 0.0625f * ((__global short*)((__global char*)srcData + idx_row(src_y + 2, last_row) * srcStep))[col]; - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - col = idx_col(right_x, last_col); - - sum = 0.0625f * ((__global short*)((__global char*)srcData + idx_row(src_y - 2, last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global short*)((__global char*)srcData + idx_row(src_y - 1, last_row) * srcStep))[col]; - sum = sum + 0.375f * ((__global short*)((__global char*)srcData + idx_row(src_y , last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global short*)((__global char*)srcData + idx_row(src_y + 1, last_row) * srcStep))[col]; - sum = sum + 0.0625f * ((__global short*)((__global char*)srcData + idx_row(src_y + 2, last_row) * srcStep))[col]; - - smem[4 + get_local_id(0)] = sum; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (get_local_id(0) < 128) - { - const int tid2 = get_local_id(0) * 2; - - sum = 0.0625f * smem[2 + tid2 - 2]; - sum = sum + 0.25f * smem[2 + tid2 - 1]; - sum = sum + 0.375f * smem[2 + tid2 ]; - sum = sum + 0.25f * smem[2 + tid2 + 1]; - sum = sum + 0.0625f * smem[2 + tid2 + 2]; - - const int dst_x = (get_group_id(0) * get_local_size(0) + tid2) / 2; - - if (dst_x < dstCols) - dst[y * dstStep / 2 + dst_x] = convert_short_sat_rte(sum); - } -} - -/////////////////////////////////////////////////////////////////////// -////////////////////////// CV_16SC4 ////////////////////////////////// -/////////////////////////////////////////////////////////////////////// - -__kernel void pyrDown_C4_D3(__global short4 * srcData, int srcStep, int srcRows, int srcCols, __global short4 *dst, int dstStep, int dstCols) -{ - const int x = get_global_id(0); - const int y = get_group_id(1); - - __local float4 smem[256 + 4]; - - float4 sum; - - const int src_y = 2*y; - const int last_row = srcRows - 1; - const int last_col = srcCols - 1; - - float4 co1 = 0.375f; - float4 co2 = 0.25f; - float4 co3 = 0.0625f; - - if (src_y >= 2 && src_y < srcRows - 2 && x >= 2 && x < srcCols - 2) - { - sum = co3 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y - 2) * srcStep / 4))[x]); - sum = sum + co2 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y - 1) * srcStep / 4))[x]); - sum = sum + co1 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y ) * srcStep / 4))[x]); - sum = sum + co2 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y + 1) * srcStep / 4))[x]); - sum = sum + co3 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y + 2) * srcStep / 4))[x]); - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - sum = co3 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y - 2) * srcStep / 4))[left_x]); - sum = sum + co2 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y - 1) * srcStep / 4))[left_x]); - sum = sum + co1 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y ) * srcStep / 4))[left_x]); - sum = sum + co2 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y + 1) * srcStep / 4))[left_x]); - sum = sum + co3 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y + 2) * srcStep / 4))[left_x]); - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - sum = co3 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y - 2) * srcStep / 4))[right_x]); - sum = sum + co2 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y - 1) * srcStep / 4))[right_x]); - sum = sum + co1 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y ) * srcStep / 4))[right_x]); - sum = sum + co2 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y + 1) * srcStep / 4))[right_x]); - sum = sum + co3 * convert_float4(((__global short4*)((__global char4*)srcData + (src_y + 2) * srcStep / 4))[right_x]); - - smem[4 + get_local_id(0)] = sum; - } - } - else - { - int col = idx_col(x, last_col); - - sum = co3 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y - 2, last_row) * srcStep / 4))[col]); - sum = sum + co2 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y - 1, last_row) * srcStep / 4))[col]); - sum = sum + co1 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y , last_row) * srcStep / 4))[col]); - sum = sum + co2 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y + 1, last_row) * srcStep / 4))[col]); - sum = sum + co3 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y + 2, last_row) * srcStep / 4))[col]); - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - col = idx_col(left_x, last_col); - - sum = co3 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y - 2, last_row) * srcStep / 4))[col]); - sum = sum + co2 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y - 1, last_row) * srcStep / 4))[col]); - sum = sum + co1 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y , last_row) * srcStep / 4))[col]); - sum = sum + co2 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y + 1, last_row) * srcStep / 4))[col]); - sum = sum + co3 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y + 2, last_row) * srcStep / 4))[col]); - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - col = idx_col(right_x, last_col); - - sum = co3 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y - 2, last_row) * srcStep / 4))[col]); - sum = sum + co2 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y - 1, last_row) * srcStep / 4))[col]); - sum = sum + co1 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y , last_row) * srcStep / 4))[col]); - sum = sum + co2 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y + 1, last_row) * srcStep / 4))[col]); - sum = sum + co3 * convert_float4(((__global short4*)((__global char4*)srcData + idx_row(src_y + 2, last_row) * srcStep / 4))[col]); - - smem[4 + get_local_id(0)] = sum; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (get_local_id(0) < 128) - { - const int tid2 = get_local_id(0) * 2; - - sum = co3 * smem[2 + tid2 - 2]; - sum = sum + co2 * smem[2 + tid2 - 1]; - sum = sum + co1 * smem[2 + tid2 ]; - sum = sum + co2 * smem[2 + tid2 + 1]; - sum = sum + co3 * smem[2 + tid2 + 2]; - - const int dst_x = (get_group_id(0) * get_local_size(0) + tid2) / 2; - - if (dst_x < dstCols) - dst[y * dstStep / 8 + dst_x] = convert_short4_sat_rte(sum); - } -} - -/////////////////////////////////////////////////////////////////////// -////////////////////////// CV_32FC1 ////////////////////////////////// -/////////////////////////////////////////////////////////////////////// - -__kernel void pyrDown_C1_D5(__global float * srcData, int srcStep, int srcRows, int srcCols, __global float *dst, int dstStep, int dstCols) -{ - const int x = get_global_id(0); - const int y = get_group_id(1); - - __local float smem[256 + 4]; - - float sum; - - const int src_y = 2*y; - const int last_row = srcRows - 1; - const int last_col = srcCols - 1; - - if (src_y >= 2 && src_y < srcRows - 2 && x >= 2 && x < srcCols - 2) - { - sum = 0.0625f * ((__global float*)((__global char*)srcData + (src_y - 2) * srcStep))[x]; - sum = sum + 0.25f * ((__global float*)((__global char*)srcData + (src_y - 1) * srcStep))[x]; - sum = sum + 0.375f * ((__global float*)((__global char*)srcData + (src_y ) * srcStep))[x]; - sum = sum + 0.25f * ((__global float*)((__global char*)srcData + (src_y + 1) * srcStep))[x]; - sum = sum + 0.0625f * ((__global float*)((__global char*)srcData + (src_y + 2) * srcStep))[x]; - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - sum = 0.0625f * ((__global float*)((__global char*)srcData + (src_y - 2) * srcStep))[left_x]; - sum = sum + 0.25f * ((__global float*)((__global char*)srcData + (src_y - 1) * srcStep))[left_x]; - sum = sum + 0.375f * ((__global float*)((__global char*)srcData + (src_y ) * srcStep))[left_x]; - sum = sum + 0.25f * ((__global float*)((__global char*)srcData + (src_y + 1) * srcStep))[left_x]; - sum = sum + 0.0625f * ((__global float*)((__global char*)srcData + (src_y + 2) * srcStep))[left_x]; - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - sum = 0.0625f * ((__global float*)((__global char*)srcData + (src_y - 2) * srcStep))[right_x]; - sum = sum + 0.25f * ((__global float*)((__global char*)srcData + (src_y - 1) * srcStep))[right_x]; - sum = sum + 0.375f * ((__global float*)((__global char*)srcData + (src_y ) * srcStep))[right_x]; - sum = sum + 0.25f * ((__global float*)((__global char*)srcData + (src_y + 1) * srcStep))[right_x]; - sum = sum + 0.0625f * ((__global float*)((__global char*)srcData + (src_y + 2) * srcStep))[right_x]; - - smem[4 + get_local_id(0)] = sum; - } - } - else - { - int col = idx_col(x, last_col); - - sum = 0.0625f * ((__global float*)((__global char*)srcData + idx_row(src_y - 2, last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global float*)((__global char*)srcData + idx_row(src_y - 1, last_row) * srcStep))[col]; - sum = sum + 0.375f * ((__global float*)((__global char*)srcData + idx_row(src_y , last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global float*)((__global char*)srcData + idx_row(src_y + 1, last_row) * srcStep))[col]; - sum = sum + 0.0625f * ((__global float*)((__global char*)srcData + idx_row(src_y + 2, last_row) * srcStep))[col]; - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - col = idx_col(left_x, last_col); - - sum = 0.0625f * ((__global float*)((__global char*)srcData + idx_row(src_y - 2, last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global float*)((__global char*)srcData + idx_row(src_y - 1, last_row) * srcStep))[col]; - sum = sum + 0.375f * ((__global float*)((__global char*)srcData + idx_row(src_y , last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global float*)((__global char*)srcData + idx_row(src_y + 1, last_row) * srcStep))[col]; - sum = sum + 0.0625f * ((__global float*)((__global char*)srcData + idx_row(src_y + 2, last_row) * srcStep))[col]; - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - col = idx_col(right_x, last_col); - - sum = 0.0625f * ((__global float*)((__global char*)srcData + idx_row(src_y - 2, last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global float*)((__global char*)srcData + idx_row(src_y - 1, last_row) * srcStep))[col]; - sum = sum + 0.375f * ((__global float*)((__global char*)srcData + idx_row(src_y , last_row) * srcStep))[col]; - sum = sum + 0.25f * ((__global float*)((__global char*)srcData + idx_row(src_y + 1, last_row) * srcStep))[col]; - sum = sum + 0.0625f * ((__global float*)((__global char*)srcData + idx_row(src_y + 2, last_row) * srcStep))[col]; - - smem[4 + get_local_id(0)] = sum; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (get_local_id(0) < 128) - { - const int tid2 = get_local_id(0) * 2; - - sum = 0.0625f * smem[2 + tid2 - 2]; - sum = sum + 0.25f * smem[2 + tid2 - 1]; - sum = sum + 0.375f * smem[2 + tid2 ]; - sum = sum + 0.25f * smem[2 + tid2 + 1]; - sum = sum + 0.0625f * smem[2 + tid2 + 2]; - - const int dst_x = (get_group_id(0) * get_local_size(0) + tid2) / 2; - - if (dst_x < dstCols) - dst[y * dstStep / 4 + dst_x] = sum; - } -} - -/////////////////////////////////////////////////////////////////////// -////////////////////////// CV_32FC4 ////////////////////////////////// -/////////////////////////////////////////////////////////////////////// - -__kernel void pyrDown_C4_D5(__global float4 * srcData, int srcStep, int srcRows, int srcCols, __global float4 *dst, int dstStep, int dstCols) -{ - const int x = get_global_id(0); - const int y = get_group_id(1); - - __local float4 smem[256 + 4]; - - float4 sum; - - const int src_y = 2*y; - const int last_row = srcRows - 1; - const int last_col = srcCols - 1; - - float4 co1 = 0.375f; - float4 co2 = 0.25f; - float4 co3 = 0.0625f; - - if (src_y >= 2 && src_y < srcRows - 2 && x >= 2 && x < srcCols - 2) - { - sum = co3 * ((__global float4*)((__global char4*)srcData + (src_y - 2) * srcStep / 4))[x]; - sum = sum + co2 * ((__global float4*)((__global char4*)srcData + (src_y - 1) * srcStep / 4))[x]; - sum = sum + co1 * ((__global float4*)((__global char4*)srcData + (src_y ) * srcStep / 4))[x]; - sum = sum + co2 * ((__global float4*)((__global char4*)srcData + (src_y + 1) * srcStep / 4))[x]; - sum = sum + co3 * ((__global float4*)((__global char4*)srcData + (src_y + 2) * srcStep / 4))[x]; - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - sum = co3 * ((__global float4*)((__global char4*)srcData + (src_y - 2) * srcStep / 4))[left_x]; - sum = sum + co2 * ((__global float4*)((__global char4*)srcData + (src_y - 1) * srcStep / 4))[left_x]; - sum = sum + co1 * ((__global float4*)((__global char4*)srcData + (src_y ) * srcStep / 4))[left_x]; - sum = sum + co2 * ((__global float4*)((__global char4*)srcData + (src_y + 1) * srcStep / 4))[left_x]; - sum = sum + co3 * ((__global float4*)((__global char4*)srcData + (src_y + 2) * srcStep / 4))[left_x]; - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - sum = co3 * ((__global float4*)((__global char4*)srcData + (src_y - 2) * srcStep / 4))[right_x]; - sum = sum + co2 * ((__global float4*)((__global char4*)srcData + (src_y - 1) * srcStep / 4))[right_x]; - sum = sum + co1 * ((__global float4*)((__global char4*)srcData + (src_y ) * srcStep / 4))[right_x]; - sum = sum + co2 * ((__global float4*)((__global char4*)srcData + (src_y + 1) * srcStep / 4))[right_x]; - sum = sum + co3 * ((__global float4*)((__global char4*)srcData + (src_y + 2) * srcStep / 4))[right_x]; - - smem[4 + get_local_id(0)] = sum; - } - } - else - { - int col = idx_col(x, last_col); - - sum = co3 * ((__global float4*)((__global char4*)srcData + idx_row(src_y - 2, last_row) * srcStep / 4))[col]; - sum = sum + co2 * ((__global float4*)((__global char4*)srcData + idx_row(src_y - 1, last_row) * srcStep / 4))[col]; - sum = sum + co1 * ((__global float4*)((__global char4*)srcData + idx_row(src_y , last_row) * srcStep / 4))[col]; - sum = sum + co2 * ((__global float4*)((__global char4*)srcData + idx_row(src_y + 1, last_row) * srcStep / 4))[col]; - sum = sum + co3 * ((__global float4*)((__global char4*)srcData + idx_row(src_y + 2, last_row) * srcStep / 4))[col]; - - smem[2 + get_local_id(0)] = sum; - - if (get_local_id(0) < 2) - { - const int left_x = x - 2; - - col = idx_col(left_x, last_col); - - sum = co3 * ((__global float4*)((__global char4*)srcData + idx_row(src_y - 2, last_row) * srcStep / 4))[col]; - sum = sum + co2 * ((__global float4*)((__global char4*)srcData + idx_row(src_y - 1, last_row) * srcStep / 4))[col]; - sum = sum + co1 * ((__global float4*)((__global char4*)srcData + idx_row(src_y , last_row) * srcStep / 4))[col]; - sum = sum + co2 * ((__global float4*)((__global char4*)srcData + idx_row(src_y + 1, last_row) * srcStep / 4))[col]; - sum = sum + co3 * ((__global float4*)((__global char4*)srcData + idx_row(src_y + 2, last_row) * srcStep / 4))[col]; - - smem[get_local_id(0)] = sum; - } - - if (get_local_id(0) > 253) - { - const int right_x = x + 2; - - col = idx_col(right_x, last_col); - - sum = co3 * ((__global float4*)((__global char4*)srcData + idx_row(src_y - 2, last_row) * srcStep / 4))[col]; - sum = sum + co2 * ((__global float4*)((__global char4*)srcData + idx_row(src_y - 1, last_row) * srcStep / 4))[col]; - sum = sum + co1 * ((__global float4*)((__global char4*)srcData + idx_row(src_y , last_row) * srcStep / 4))[col]; - sum = sum + co2 * ((__global float4*)((__global char4*)srcData + idx_row(src_y + 1, last_row) * srcStep / 4))[col]; - sum = sum + co3 * ((__global float4*)((__global char4*)srcData + idx_row(src_y + 2, last_row) * srcStep / 4))[col]; - - smem[4 + get_local_id(0)] = sum; - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (get_local_id(0) < 128) - { - const int tid2 = get_local_id(0) * 2; - - sum = co3 * smem[2 + tid2 - 2]; - sum = sum + co2 * smem[2 + tid2 - 1]; - sum = sum + co1 * smem[2 + tid2 ]; - sum = sum + co2 * smem[2 + tid2 + 1]; - sum = sum + co3 * smem[2 + tid2 + 2]; - - const int dst_x = (get_group_id(0) * get_local_size(0) + tid2) / 2; - - if (dst_x < dstCols) - dst[y * dstStep / 16 + dst_x] = sum; - } -} diff --git a/modules/ocl/src/opencl/pyr_up.cl b/modules/ocl/src/opencl/pyr_up.cl deleted file mode 100644 index 157fee894..000000000 --- a/modules/ocl/src/opencl/pyr_up.cl +++ /dev/null @@ -1,146 +0,0 @@ -/*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 -// Zhang Chunpeng chunpeng@multicorewareinc.com -// Dachuan Zhao, dachuan@multicorewareinc.com -// Yao Wang, yao@multicorewareinc.com -// Peng Xiao, pengxiao@outlook.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*/ - -/////////////////////////////////////////////////////////////////////// -//////////////////////// Generic PyrUp ////////////////////////////// -/////////////////////////////////////////////////////////////////////// - -__kernel void pyrUp(__global Type* src, __global Type* dst, - int srcRows, int dstRows, int srcCols, int dstCols, - int srcOffset, int dstOffset, int srcStep, int dstStep) -{ - const int x = get_global_id(0); - const int y = get_global_id(1); - - const int lsizex = get_local_size(0); - const int lsizey = get_local_size(1); - - const int tidx = get_local_id(0); - const int tidy = get_local_id(1); - - __local floatType s_srcPatch[10][10]; - __local floatType s_dstPatch[20][16]; - - if( tidx < 10 && tidy < 10 ) - { - int srcx = mad24((int)get_group_id(0), lsizex>>1, tidx) - 1; - int srcy = mad24((int)get_group_id(1), lsizey>>1, tidy) - 1; - - srcx = abs(srcx); - srcx = min(srcCols - 1,srcx); - - srcy = abs(srcy); - srcy = min(srcRows -1 ,srcy); - - s_srcPatch[tidy][tidx] = convertToFloat(src[srcx + srcy * srcStep]); - } - - barrier(CLK_LOCAL_MEM_FENCE); - - floatType sum = (floatType)0; - const floatType evenFlag = (floatType)((tidx & 1) == 0); - const floatType oddFlag = (floatType)((tidx & 1) != 0); - const bool eveny = ((tidy & 1) == 0); - - const floatType co1 = (floatType)0.375f; - const floatType co2 = (floatType)0.25f; - const floatType co3 = (floatType)0.0625f; - - if(eveny) - { - sum = ( evenFlag* co3 ) * s_srcPatch[1 + (tidy >> 1)][1 + ((tidx - 2) >> 1)]; - sum = sum + ( oddFlag * co2 ) * s_srcPatch[1 + (tidy >> 1)][1 + ((tidx - 1) >> 1)]; - sum = sum + ( evenFlag* co1 ) * s_srcPatch[1 + (tidy >> 1)][1 + ((tidx ) >> 1)]; - sum = sum + ( oddFlag * co2 ) * s_srcPatch[1 + (tidy >> 1)][1 + ((tidx + 1) >> 1)]; - sum = sum + ( evenFlag* co3 ) * s_srcPatch[1 + (tidy >> 1)][1 + ((tidx + 2) >> 1)]; - } - - s_dstPatch[2 + tidy][tidx] = sum; - - if (tidy < 2) - { - sum = 0; - - if (eveny) - { - sum = (evenFlag * co3 ) * s_srcPatch[lsizey-16][1 + ((tidx - 2) >> 1)]; - sum = sum + ( oddFlag * co2 ) * s_srcPatch[lsizey-16][1 + ((tidx - 1) >> 1)]; - sum = sum + (evenFlag * co1 ) * s_srcPatch[lsizey-16][1 + ((tidx ) >> 1)]; - sum = sum + ( oddFlag * co2 ) * s_srcPatch[lsizey-16][1 + ((tidx + 1) >> 1)]; - sum = sum + (evenFlag * co3 ) * s_srcPatch[lsizey-16][1 + ((tidx + 2) >> 1)]; - } - - s_dstPatch[tidy][tidx] = sum; - } - - if (tidy > 13) - { - sum = 0; - - if (eveny) - { - sum = (evenFlag * co3) * s_srcPatch[lsizey-7][1 + ((tidx - 2) >> 1)]; - sum = sum + ( oddFlag * co2) * s_srcPatch[lsizey-7][1 + ((tidx - 1) >> 1)]; - sum = sum + (evenFlag * co1) * s_srcPatch[lsizey-7][1 + ((tidx ) >> 1)]; - sum = sum + ( oddFlag * co2) * s_srcPatch[lsizey-7][1 + ((tidx + 1) >> 1)]; - sum = sum + (evenFlag * co3) * s_srcPatch[lsizey-7][1 + ((tidx + 2) >> 1)]; - } - s_dstPatch[4 + tidy][tidx] = sum; - } - - barrier(CLK_LOCAL_MEM_FENCE); - - sum = co3 * s_dstPatch[2 + tidy - 2][tidx]; - sum = sum + co2 * s_dstPatch[2 + tidy - 1][tidx]; - sum = sum + co1 * s_dstPatch[2 + tidy ][tidx]; - sum = sum + co2 * s_dstPatch[2 + tidy + 1][tidx]; - sum = sum + co3 * s_dstPatch[2 + tidy + 2][tidx]; - - if ((x < dstCols) && (y < dstRows)) - dst[x + y * dstStep] = convertToType(4.0f * sum); -} diff --git a/modules/ocl/src/opencl/pyrlk.cl b/modules/ocl/src/opencl/pyrlk.cl deleted file mode 100644 index f34aee900..000000000 --- a/modules/ocl/src/opencl/pyrlk.cl +++ /dev/null @@ -1,1019 +0,0 @@ -/*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 -// Dachuan Zhao, dachuan@multicorewareinc.com -// Yao Wang, bitwangyaoyao@gmail.com -// Xiaopeng Fu, fuxiaopeng2222@163.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*/ - -#define BUFFER 64 -#define BUFFER2 BUFFER>>1 -#ifndef WAVE_SIZE -#define WAVE_SIZE 1 -#endif -#ifdef CPU - -inline void reduce3(float val1, float val2, float val3, __local float* smem1, __local float* smem2, __local float* smem3, int tid) -{ - smem1[tid] = val1; - smem2[tid] = val2; - smem3[tid] = val3; - barrier(CLK_LOCAL_MEM_FENCE); - - for(int i = BUFFER2; i > 0; i >>= 1) - { - if(tid < i) - { - smem1[tid] += smem1[tid + i]; - smem2[tid] += smem2[tid + i]; - smem3[tid] += smem3[tid + i]; - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} - -inline void reduce2(float val1, float val2, volatile __local float* smem1, volatile __local float* smem2, int tid) -{ - smem1[tid] = val1; - smem2[tid] = val2; - barrier(CLK_LOCAL_MEM_FENCE); - - for(int i = BUFFER2; i > 0; i >>= 1) - { - if(tid < i) - { - smem1[tid] += smem1[tid + i]; - smem2[tid] += smem2[tid + i]; - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} - -inline void reduce1(float val1, volatile __local float* smem1, int tid) -{ - smem1[tid] = val1; - barrier(CLK_LOCAL_MEM_FENCE); - - for(int i = BUFFER2; i > 0; i >>= 1) - { - if(tid < i) - { - smem1[tid] += smem1[tid + i]; - } - barrier(CLK_LOCAL_MEM_FENCE); - } -} -#else -inline void reduce3(float val1, float val2, float val3, - __local volatile float* smem1, __local volatile float* smem2, __local volatile float* smem3, int tid) -{ - smem1[tid] = val1; - smem2[tid] = val2; - smem3[tid] = val3; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 32) - { - smem1[tid] += smem1[tid + 32]; - smem2[tid] += smem2[tid + 32]; - smem3[tid] += smem3[tid + 32]; -#if WAVE_SIZE < 32 - } - barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 16) - { -#endif - smem1[tid] += smem1[tid + 16]; - smem2[tid] += smem2[tid + 16]; - smem3[tid] += smem3[tid + 16]; -#if WAVE_SIZE <16 - } - barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 8) - { -#endif - smem1[tid] += smem1[tid + 8]; - smem2[tid] += smem2[tid + 8]; - smem3[tid] += smem3[tid + 8]; - - smem1[tid] += smem1[tid + 4]; - smem2[tid] += smem2[tid + 4]; - smem3[tid] += smem3[tid + 4]; - - smem1[tid] += smem1[tid + 2]; - smem2[tid] += smem2[tid + 2]; - smem3[tid] += smem3[tid + 2]; - - smem1[tid] += smem1[tid + 1]; - smem2[tid] += smem2[tid + 1]; - smem3[tid] += smem3[tid + 1]; - } - barrier(CLK_LOCAL_MEM_FENCE); -} - -inline void reduce2(float val1, float val2, __local volatile float* smem1, __local volatile float* smem2, int tid) -{ - smem1[tid] = val1; - smem2[tid] = val2; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 32) - { - smem1[tid] += smem1[tid + 32]; - smem2[tid] += smem2[tid + 32]; -#if WAVE_SIZE < 32 - } - barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 16) - { -#endif - smem1[tid] += smem1[tid + 16]; - smem2[tid] += smem2[tid + 16]; -#if WAVE_SIZE <16 - } - barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 8) - { -#endif - smem1[tid] += smem1[tid + 8]; - smem2[tid] += smem2[tid + 8]; - - smem1[tid] += smem1[tid + 4]; - smem2[tid] += smem2[tid + 4]; - - smem1[tid] += smem1[tid + 2]; - smem2[tid] += smem2[tid + 2]; - - smem1[tid] += smem1[tid + 1]; - smem2[tid] += smem2[tid + 1]; - } - barrier(CLK_LOCAL_MEM_FENCE); -} - -inline void reduce1(float val1, __local volatile float* smem1, int tid) -{ - smem1[tid] = val1; - barrier(CLK_LOCAL_MEM_FENCE); - - if (tid < 32) - { - smem1[tid] += smem1[tid + 32]; -#if WAVE_SIZE < 32 - } - barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 16) - { -#endif - smem1[tid] += smem1[tid + 16]; -#if WAVE_SIZE <16 - } - barrier(CLK_LOCAL_MEM_FENCE); - if (tid < 8) - { -#endif - smem1[tid] += smem1[tid + 8]; - smem1[tid] += smem1[tid + 4]; - smem1[tid] += smem1[tid + 2]; - smem1[tid] += smem1[tid + 1]; - } - barrier(CLK_LOCAL_MEM_FENCE); -} -#endif - -#define SCALE (1.0f / (1 << 20)) -#define THRESHOLD 0.01f - -// Image read mode -__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR; - -inline void SetPatch(image2d_t I, float x, float y, - float* Pch, float* Dx, float* Dy, - float* A11, float* A12, float* A22) -{ - *Pch = read_imagef(I, sampler, (float2)(x, y)).x; - - float dIdx = 3.0f * read_imagef(I, sampler, (float2)(x + 1, y - 1)).x + 10.0f * read_imagef(I, sampler, (float2)(x + 1, y)).x + 3.0f * read_imagef(I, sampler, (float2)(x + 1, y + 1)).x - - (3.0f * read_imagef(I, sampler, (float2)(x - 1, y - 1)).x + 10.0f * read_imagef(I, sampler, (float2)(x - 1, y)).x + 3.0f * read_imagef(I, sampler, (float2)(x - 1, y + 1)).x); - - float dIdy = 3.0f * read_imagef(I, sampler, (float2)(x - 1, y + 1)).x + 10.0f * read_imagef(I, sampler, (float2)(x, y + 1)).x + 3.0f * read_imagef(I, sampler, (float2)(x + 1, y + 1)).x - - (3.0f * read_imagef(I, sampler, (float2)(x - 1, y - 1)).x + 10.0f * read_imagef(I, sampler, (float2)(x, y - 1)).x + 3.0f * read_imagef(I, sampler, (float2)(x + 1, y - 1)).x); - - - *Dx = dIdx; - *Dy = dIdy; - - *A11 += dIdx * dIdx; - *A12 += dIdx * dIdy; - *A22 += dIdy * dIdy; -} - -inline void GetPatch(image2d_t J, float x, float y, - float* Pch, float* Dx, float* Dy, - float* b1, float* b2) -{ - float J_val = read_imagef(J, sampler, (float2)(x, y)).x; - float diff = (J_val - *Pch) * 32.0f; - *b1 += diff**Dx; - *b2 += diff**Dy; -} - -inline void GetError(image2d_t J, const float x, const float y, const float* Pch, float* errval) -{ - float diff = read_imagef(J, sampler, (float2)(x,y)).x-*Pch; - *errval += fabs(diff); -} - -inline void SetPatch4(image2d_t I, const float x, const float y, - float4* Pch, float4* Dx, float4* Dy, - float* A11, float* A12, float* A22) -{ - *Pch = read_imagef(I, sampler, (float2)(x, y)); - - float4 dIdx = 3.0f * read_imagef(I, sampler, (float2)(x + 1, y - 1)) + 10.0f * read_imagef(I, sampler, (float2)(x + 1, y)) + 3.0f * read_imagef(I, sampler, (float2)(x + 1, y + 1)) - - (3.0f * read_imagef(I, sampler, (float2)(x - 1, y - 1)) + 10.0f * read_imagef(I, sampler, (float2)(x - 1, y)) + 3.0f * read_imagef(I, sampler, (float2)(x - 1, y + 1))); - - float4 dIdy = 3.0f * read_imagef(I, sampler, (float2)(x - 1, y + 1)) + 10.0f * read_imagef(I, sampler, (float2)(x, y + 1)) + 3.0f * read_imagef(I, sampler, (float2)(x + 1, y + 1)) - - (3.0f * read_imagef(I, sampler, (float2)(x - 1, y - 1)) + 10.0f * read_imagef(I, sampler, (float2)(x, y - 1)) + 3.0f * read_imagef(I, sampler, (float2)(x + 1, y - 1))); - - - *Dx = dIdx; - *Dy = dIdy; - float4 sqIdx = dIdx * dIdx; - *A11 += sqIdx.x + sqIdx.y + sqIdx.z; - sqIdx = dIdx * dIdy; - *A12 += sqIdx.x + sqIdx.y + sqIdx.z; - sqIdx = dIdy * dIdy; - *A22 += sqIdx.x + sqIdx.y + sqIdx.z; -} - -inline void GetPatch4(image2d_t J, const float x, const float y, - const float4* Pch, const float4* Dx, const float4* Dy, - float* b1, float* b2) -{ - float4 J_val = read_imagef(J, sampler, (float2)(x, y)); - float4 diff = (J_val - *Pch) * 32.0f; - float4 xdiff = diff* *Dx; - *b1 += xdiff.x + xdiff.y + xdiff.z; - xdiff = diff* *Dy; - *b2 += xdiff.x + xdiff.y + xdiff.z; -} - -inline void GetError4(image2d_t J, const float x, const float y, const float4* Pch, float* errval) -{ - float4 diff = read_imagef(J, sampler, (float2)(x,y))-*Pch; - *errval += fabs(diff.x) + fabs(diff.y) + fabs(diff.z); -} - -#define GRIDSIZE 3 -__kernel void lkSparse_C1_D5(image2d_t I, image2d_t J, - __global const float2* prevPts, int prevPtsStep, __global float2* nextPts, int nextPtsStep, __global uchar* status, __global float* err, - const int level, const int rows, const int cols, int PATCH_X, int PATCH_Y, int cn, int c_winSize_x, int c_winSize_y, int c_iters, char calcErr) -{ - __local float smem1[BUFFER]; - __local float smem2[BUFFER]; - __local float smem3[BUFFER]; - - unsigned int xid=get_local_id(0); - unsigned int yid=get_local_id(1); - unsigned int gid=get_group_id(0); - unsigned int xsize=get_local_size(0); - unsigned int ysize=get_local_size(1); - int xBase, yBase, k; - - float2 c_halfWin = (float2)((c_winSize_x - 1)>>1, (c_winSize_y - 1)>>1); - - const int tid = mad24(yid, xsize, xid); - - float2 prevPt = prevPts[gid] / (float2)(1 << level); - - if (prevPt.x < 0 || prevPt.x >= cols || prevPt.y < 0 || prevPt.y >= rows) - { - if (tid == 0 && level == 0) - { - status[gid] = 0; - } - - return; - } - prevPt -= c_halfWin; - - // extract the patch from the first image, compute covariation matrix of derivatives - - float A11 = 0; - float A12 = 0; - float A22 = 0; - - float I_patch[GRIDSIZE][GRIDSIZE]; - float dIdx_patch[GRIDSIZE][GRIDSIZE]; - float dIdy_patch[GRIDSIZE][GRIDSIZE]; - - yBase=yid; - { - xBase=xid; - SetPatch(I, prevPt.x + xBase + 0.5f, prevPt.y + yBase + 0.5f, - &I_patch[0][0], &dIdx_patch[0][0], &dIdy_patch[0][0], - &A11, &A12, &A22); - - - xBase+=xsize; - SetPatch(I, prevPt.x + xBase + 0.5f, prevPt.y + yBase + 0.5f, - &I_patch[0][1], &dIdx_patch[0][1], &dIdy_patch[0][1], - &A11, &A12, &A22); - - xBase+=xsize; - if(xBase= cols || prevPt.y < -c_halfWin.y || prevPt.y >= rows) - { - if (tid == 0 && level == 0) - status[gid] = 0; - return; - } - - float b1 = 0; - float b2 = 0; - - yBase=yid; - { - xBase=xid; - GetPatch(J, prevPt.x + xBase + 0.5f, prevPt.y + yBase + 0.5f, - &I_patch[0][0], &dIdx_patch[0][0], &dIdy_patch[0][0], - &b1, &b2); - - - xBase+=xsize; - GetPatch(J, prevPt.x + xBase + 0.5f, prevPt.y + yBase + 0.5f, - &I_patch[0][1], &dIdx_patch[0][1], &dIdy_patch[0][1], - &b1, &b2); - - xBase+=xsize; - if(xBase>1, (c_winSize_y - 1)>>1); - - const int tid = mad24(yid, xsize, xid); - - float2 nextPt = prevPts[gid]/(float2)(1<= cols || nextPt.y < 0 || nextPt.y >= rows) - { - if (tid == 0 && level == 0) - { - status[gid] = 0; - } - - return; - } - - nextPt -= c_halfWin; - - // extract the patch from the first image, compute covariation matrix of derivatives - - float A11 = 0.0f; - float A12 = 0.0f; - float A22 = 0.0f; - - float4 I_patch[8]; - float4 dIdx_patch[8]; - float4 dIdy_patch[8]; - float4 I_add,Dx_add,Dy_add; - - yBase=yid; - { - xBase=xid; - SetPatch4(I, nextPt.x + xBase + 0.5f, nextPt.y + yBase + 0.5f, - &I_patch[0], &dIdx_patch[0], &dIdy_patch[0], - &A11, &A12, &A22); - - - xBase+=xsize; - SetPatch4(I, nextPt.x + xBase + 0.5f, nextPt.y + yBase + 0.5f, - &I_patch[1], &dIdx_patch[1], &dIdy_patch[1], - &A11, &A12, &A22); - - xBase+=xsize; - if(xBase= cols || nextPt.y < -c_halfWin.y || nextPt.y >= rows) - { - if (tid == 0 && level == 0) - status[gid] = 0; - return; - } - - float b1 = 0; - float b2 = 0; - - yBase=yid; - { - xBase=xid; - GetPatch4(J, nextPt.x + xBase + 0.5f, nextPt.y + yBase + 0.5f, - &I_patch[0], &dIdx_patch[0], &dIdy_patch[0], - &b1, &b2); - - - xBase+=xsize; - GetPatch4(J, nextPt.x + xBase + 0.5f, nextPt.y + yBase + 0.5f, - &I_patch[1], &dIdx_patch[1], &dIdy_patch[1], - &b1, &b2); - - xBase+=xsize; - if(xBase= cols || y >= rows) - return; - - int A11i = 0; - int A12i = 0; - int A22i = 0; - - for (int i = 0; i < c_winSize_y; ++i) - { - for (int j = 0; j < c_winSize_x; ++j) - { - int dIdx = dIdx_patch[(get_local_id(1) + i) * patchWidth + (get_local_id(0) + j)]; - int dIdy = dIdy_patch[(get_local_id(1) + i) * patchWidth + (get_local_id(0) + j)]; - - A11i += dIdx * dIdx; - A12i += dIdx * dIdy; - A22i += dIdy * dIdy; - } - } - - float A11 = A11i; - float A12 = A12i; - float A22 = A22i; - - float D = A11 * A22 - A12 * A12; - - //if (calcErr && GET_MIN_EIGENVALS) - // (err + y * errStep)[x] = minEig; - - if (D < 1.192092896e-07f) - { - //if (calcErr) - // err(y, x) = 3.402823466e+38f; - - return; - } - - D = 1.f / D; - - A11 *= D; - A12 *= D; - A22 *= D; - - float2 nextPt; - nextPt.x = x + prevU[y/2 * prevUStep / 4 + x/2] * 2.0f; - nextPt.y = y + prevV[y/2 * prevVStep / 4 + x/2] * 2.0f; - - for (int k = 0; k < c_iters; ++k) - { - if (nextPt.x < 0 || nextPt.x >= cols || nextPt.y < 0 || nextPt.y >= rows) - { - //if (calcErr) - // err(y, x) = 3.402823466e+38f; - - return; - } - - int b1 = 0; - int b2 = 0; - - for (int i = 0; i < c_winSize_y; ++i) - { - for (int j = 0; j < c_winSize_x; ++j) - { - int iI = I_patch[(get_local_id(1) + i) * patchWidth + get_local_id(0) + j]; - int iJ = read_imagei(J, sampler, (float2)(nextPt.x - c_halfWin_x + j + 0.5f, nextPt.y - c_halfWin_y + i + 0.5f)).x; - - int diff = (iJ - iI) * 32; - - int dIdx = dIdx_patch[(get_local_id(1) + i) * patchWidth + (get_local_id(0) + j)]; - int dIdy = dIdy_patch[(get_local_id(1) + i) * patchWidth + (get_local_id(0) + j)]; - - b1 += diff * dIdx; - b2 += diff * dIdy; - } - } - - float2 delta; - delta.x = A12 * b2 - A22 * b1; - delta.y = A12 * b1 - A11 * b2; - - nextPt.x += delta.x; - nextPt.y += delta.y; - - if (fabs(delta.x) < 0.01f && fabs(delta.y) < 0.01f) - break; - } - - u[y * uStep / 4 + x] = nextPt.x - x; - v[y * vStep / 4 + x] = nextPt.y - y; - - if (calcErr) - { - int errval = 0; - - for (int i = 0; i < c_winSize_y; ++i) - { - for (int j = 0; j < c_winSize_x; ++j) - { - int iI = I_patch[(get_local_id(1) + i) * patchWidth + get_local_id(0) + j]; - int iJ = read_imagei(J, sampler, (float2)(nextPt.x - c_halfWin_x + j + 0.5f, nextPt.y - c_halfWin_y + i + 0.5f)).x; - - errval += abs(iJ - iI); - } - } - - //err[y * errStep / 4 + x] = static_cast(errval) / (c_winSize_x * c_winSize_y); - } -} diff --git a/modules/ocl/src/opencl/split_mat.cl b/modules/ocl/src/opencl/split_mat.cl deleted file mode 100644 index b52b3c206..000000000 --- a/modules/ocl/src/opencl/split_mat.cl +++ /dev/null @@ -1,217 +0,0 @@ -/*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-2013, Advanced Micro Devices, Inc., 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*/ - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#if DATA_DEPTH == 0 -#define BASE_TYPE uchar -#elif DATA_DEPTH == 1 -#error data_depth char, use uchar datatype instead -#elif DATA_DEPTH == 2 -#define BASE_TYPE ushort -#elif DATA_DEPTH == 3 -#error data_depth short, use ushort datatype instead -#elif DATA_DEPTH == 4 -#define BASE_TYPE int -#elif DATA_DEPTH == 5 -#define BASE_TYPE float -#elif DATA_DEPTH == 6 -#define BASE_TYPE double -#else -#error data_depth -#endif - -#if DATA_CHAN == 2 -#define SRC_VEC_SIZE 2 -#elif DATA_CHAN == 3 -#define SRC_VEC_SIZE 4 // C3 is stored as C4 -#elif DATA_CHAN == 4 -#define SRC_VEC_SIZE 4 -#else -#error data_chan -#endif - -#define __CAT(x, y) x##y -#define CAT(x, y) __CAT(x, y) - -#define uchar1 uchar -#define char1 char -#define ushort1 ushort -#define short1 short -#define int1 int -#define float1 float -#define double1 double - -#define TYPE BASE_TYPE - -#define SRC_TYPE CAT(BASE_TYPE, SRC_VEC_SIZE) - -#define DST_VEC_TYPE CAT(BASE_TYPE, VEC_SIZE) - -#define vstore1 vstore -#define VSTORE CAT(vstore, VEC_SIZE) -#define VSTORE_ALIGNED(ptr, v) *((__global DST_VEC_TYPE*)(ptr)) = (v) -#define VSTORE_UNALIGNED(ptr, v) VSTORE((v), 0, (__global TYPE*)(ptr)) - -#ifdef DST0_ALIGNED -#define VSTORE_dst0 VSTORE_ALIGNED -#else -#define VSTORE_dst0 VSTORE_UNALIGNED -#endif -#ifdef DST1_ALIGNED -#define VSTORE_dst1 VSTORE_ALIGNED -#else -#define VSTORE_dst1 VSTORE_UNALIGNED -#endif -#ifdef DST2_ALIGNED -#define VSTORE_dst2 VSTORE_ALIGNED -#else -#define VSTORE_dst2 VSTORE_UNALIGNED -#endif -#ifdef DST3_ALIGNED -#define VSTORE_dst3 VSTORE_ALIGNED -#else -#define VSTORE_dst3 VSTORE_UNALIGNED -#endif - -__kernel void split_vector( - __global SRC_TYPE* src, int srcStepBytes, int2 srcOffset, // offset.x in bytes - __global TYPE* dst0, int dst0StepBytes, int2 dst0Offset, - __global TYPE* dst1, int dst1StepBytes, int2 dst1Offset, -#if DATA_CHAN > 2 - __global TYPE* dst2, int dst2StepBytes, int2 dst2Offset, -#endif -#if DATA_CHAN > 3 - __global TYPE* dst3, int dst3StepBytes, int2 dst3Offset, -#endif - int2 size) - -{ - int x = get_global_id(0) * VEC_SIZE; - int y = get_global_id(1); - - if (x < size.x && y < size.y) - { - SRC_TYPE srcData[VEC_SIZE]; - int xOffsetLimitBytes = srcOffset.x + size.x * sizeof(SRC_TYPE); - int xOffsetBytes = srcOffset.x + x * sizeof(SRC_TYPE); - int yOffsetBytes = (srcOffset.y + y) * srcStepBytes; -#pragma unroll - for (int i = 0; i < VEC_SIZE; i++, xOffsetBytes += sizeof(SRC_TYPE)) - { - srcData[i] = (xOffsetBytes >= xOffsetLimitBytes) ? (SRC_TYPE)0 : - *(__global SRC_TYPE*)((__global char*)src + yOffsetBytes + xOffsetBytes); - } - -#if VEC_SIZE == 1 - TYPE dstC0 = srcData[0].s0; - TYPE dstC1 = srcData[0].s1; -#if DATA_CHAN > 2 - TYPE dstC2 = srcData[0].s2; -#endif -#if DATA_CHAN > 3 - TYPE dstC3 = srcData[0].s3; -#endif -# define VEC_TO_ARRAY(v, a) TYPE a[1] = {v}; -#elif VEC_SIZE == 2 - DST_VEC_TYPE dstC0 = (DST_VEC_TYPE)(srcData[0].s0, srcData[1].s0); - DST_VEC_TYPE dstC1 = (DST_VEC_TYPE)(srcData[0].s1, srcData[1].s1); -#if DATA_CHAN > 2 - DST_VEC_TYPE dstC2 = (DST_VEC_TYPE)(srcData[0].s2, srcData[1].s2); -#endif -#if DATA_CHAN > 3 - DST_VEC_TYPE dstC3 = (DST_VEC_TYPE)(srcData[0].s3, srcData[1].s3); -#endif -# define VEC_TO_ARRAY(v, a) TYPE a[2] = {v.s0, v.s1}; -#elif VEC_SIZE == 4 - DST_VEC_TYPE dstC0 = (DST_VEC_TYPE)(srcData[0].s0, srcData[1].s0, srcData[2].s0, srcData[3].s0); - DST_VEC_TYPE dstC1 = (DST_VEC_TYPE)(srcData[0].s1, srcData[1].s1, srcData[2].s1, srcData[3].s1); -#if DATA_CHAN > 2 - DST_VEC_TYPE dstC2 = (DST_VEC_TYPE)(srcData[0].s2, srcData[1].s2, srcData[2].s2, srcData[3].s2); -#endif -#if DATA_CHAN > 3 - DST_VEC_TYPE dstC3 = (DST_VEC_TYPE)(srcData[0].s3, srcData[1].s3, srcData[2].s3, srcData[3].s3); -#endif -# define VEC_TO_ARRAY(v, a) TYPE a[4] = {v.s0, v.s1, v.s2, v.s3}; -#endif - -#ifndef BYPASS_VSTORE -#define BYPASS_VSTORE false -#endif - -#define WRITE_VEC_DST(dst, vecValue) \ -{ \ - int dst ## xOffsetLimitBytes = dst ## Offset.x + size.x * sizeof(TYPE); \ - int dst ## xOffsetBytes = dst ## Offset.x + x * sizeof(TYPE); \ - int dst ## yOffsetBytes = (dst ## Offset.y + y) * dst ## StepBytes; \ - if (!BYPASS_VSTORE && dst ## xOffsetBytes + (int)sizeof(DST_VEC_TYPE) <= dst ## xOffsetLimitBytes) \ - { \ - VSTORE_ ## dst(((__global char*)dst + dst ## yOffsetBytes + dst ## xOffsetBytes), vecValue); \ - } \ - else \ - { \ - VEC_TO_ARRAY(vecValue, vecValue##Array); \ - for (int i = 0; i < VEC_SIZE; i++, dst ## xOffsetBytes += sizeof(TYPE)) \ - { \ - if (dst ## xOffsetBytes + (int)sizeof(TYPE) <= dst ## xOffsetLimitBytes) \ - *(__global TYPE*)((__global char*)dst + dst ## yOffsetBytes + dst ## xOffsetBytes) = vecValue##Array[i]; \ - else \ - break; \ - } \ - } \ -} - - WRITE_VEC_DST(dst0, dstC0); - WRITE_VEC_DST(dst1, dstC1); -#if DATA_CHAN > 2 - WRITE_VEC_DST(dst2, dstC2); -#endif -#if DATA_CHAN > 3 - WRITE_VEC_DST(dst3, dstC3); -#endif - } -} diff --git a/modules/ocl/src/opencl/stereobm.cl b/modules/ocl/src/opencl/stereobm.cl deleted file mode 100644 index d3efb5eb4..000000000 --- a/modules/ocl/src/opencl/stereobm.cl +++ /dev/null @@ -1,338 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.com -// Sen Liu, swjtuls1987@126.com -// Peng Xiao, pengxiao@outlook.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*/ - -#define ROWSperTHREAD 21 // the number of rows a thread will process -#define BLOCK_W 128 // the thread block width (464) -#define N_DISPARITIES 8 - -#define STEREO_MIND 0 // The minimum d range to check -#define STEREO_DISP_STEP N_DISPARITIES // the d step, must be <= 1 to avoid aliasing - -#ifndef radius -#define radius 64 -#endif - -inline unsigned int CalcSSD(__local unsigned int *col_ssd) -{ - unsigned int cache = col_ssd[0]; - -#pragma unroll - for(int i = 1; i <= (radius << 1); i++) - cache += col_ssd[i]; - - return cache; -} - -inline uint2 MinSSD(__local unsigned int *col_ssd) -{ - unsigned int ssd[N_DISPARITIES]; - const int win_size = (radius << 1); - - //See above: #define COL_SSD_SIZE (BLOCK_W + WIN_SIZE) - ssd[0] = CalcSSD(col_ssd + 0 * (BLOCK_W + win_size)); - ssd[1] = CalcSSD(col_ssd + 1 * (BLOCK_W + win_size)); - ssd[2] = CalcSSD(col_ssd + 2 * (BLOCK_W + win_size)); - ssd[3] = CalcSSD(col_ssd + 3 * (BLOCK_W + win_size)); - ssd[4] = CalcSSD(col_ssd + 4 * (BLOCK_W + win_size)); - ssd[5] = CalcSSD(col_ssd + 5 * (BLOCK_W + win_size)); - ssd[6] = CalcSSD(col_ssd + 6 * (BLOCK_W + win_size)); - ssd[7] = CalcSSD(col_ssd + 7 * (BLOCK_W + win_size)); - - unsigned int mssd = min(min(min(ssd[0], ssd[1]), min(ssd[4], ssd[5])), min(min(ssd[2], ssd[3]), min(ssd[6], ssd[7]))); - - int bestIdx = 0; - - for (int i = 0; i < N_DISPARITIES; i++) - { - if (mssd == ssd[i]) - bestIdx = i; - } - - return (uint2)(mssd, bestIdx); -} - -inline void StepDown(int idx1, int idx2, __global unsigned char* imageL, - __global unsigned char* imageR, int d, __local unsigned int *col_ssd) -{ - uint8 imgR1 = convert_uint8(vload8(0, imageR + (idx1 - d - 7))); - uint8 imgR2 = convert_uint8(vload8(0, imageR + (idx2 - d - 7))); - uint8 diff1 = (uint8)(imageL[idx1]) - imgR1; - uint8 diff2 = (uint8)(imageL[idx2]) - imgR2; - uint8 res = diff2 * diff2 - diff1 * diff1; - const int win_size = (radius << 1); - col_ssd[0 * (BLOCK_W + win_size)] += res.s7; - col_ssd[1 * (BLOCK_W + win_size)] += res.s6; - col_ssd[2 * (BLOCK_W + win_size)] += res.s5; - col_ssd[3 * (BLOCK_W + win_size)] += res.s4; - col_ssd[4 * (BLOCK_W + win_size)] += res.s3; - col_ssd[5 * (BLOCK_W + win_size)] += res.s2; - col_ssd[6 * (BLOCK_W + win_size)] += res.s1; - col_ssd[7 * (BLOCK_W + win_size)] += res.s0; -} - -inline void InitColSSD(int x_tex, int y_tex, int im_pitch, __global unsigned char* imageL, - __global unsigned char* imageR, int d, - __local unsigned int *col_ssd) -{ - uint8 leftPixel1; - uint8 diffa = 0; - int idx = y_tex * im_pitch + x_tex; - const int win_size = (radius << 1); - for(int i = 0; i < (win_size + 1); i++) - { - leftPixel1 = (uint8)(imageL[idx]); - uint8 imgR = convert_uint8(vload8(0, imageR + (idx - d - 7))); - uint8 res = leftPixel1 - imgR; - diffa += res * res; - - idx += im_pitch; - } - //See above: #define COL_SSD_SIZE (BLOCK_W + WIN_SIZE) - col_ssd[0 * (BLOCK_W + win_size)] = diffa.s7; - col_ssd[1 * (BLOCK_W + win_size)] = diffa.s6; - col_ssd[2 * (BLOCK_W + win_size)] = diffa.s5; - col_ssd[3 * (BLOCK_W + win_size)] = diffa.s4; - col_ssd[4 * (BLOCK_W + win_size)] = diffa.s3; - col_ssd[5 * (BLOCK_W + win_size)] = diffa.s2; - col_ssd[6 * (BLOCK_W + win_size)] = diffa.s1; - col_ssd[7 * (BLOCK_W + win_size)] = diffa.s0; -} - -__kernel void stereoKernel(__global unsigned char *left, __global unsigned char *right, - __global unsigned int *cminSSDImage, int cminSSD_step, - __global unsigned char *disp, int disp_step,int cwidth, int cheight, - int img_step, int maxdisp, - __local unsigned int *col_ssd_cache) -{ - __local unsigned int *col_ssd = col_ssd_cache + get_local_id(0); - __local unsigned int *col_ssd_extra = get_local_id(0) < (radius << 1) ? col_ssd + BLOCK_W : 0; - - int X = get_group_id(0) * BLOCK_W + get_local_id(0) + maxdisp + radius; - -#define Y (int)(get_group_id(1) * ROWSperTHREAD + radius) - - __global unsigned int* minSSDImage = cminSSDImage + X + Y * cminSSD_step; - __global unsigned char* disparImage = disp + X + Y * disp_step; - - int end_row = ROWSperTHREAD < (cheight - Y) ? ROWSperTHREAD:(cheight - Y); - int y_tex; - int x_tex = X - radius; - - //if (x_tex >= cwidth) - // return; - - for(int d = STEREO_MIND; d < maxdisp; d += STEREO_DISP_STEP) - { - y_tex = Y - radius; - - InitColSSD(x_tex, y_tex, img_step, left, right, d, col_ssd); - if (col_ssd_extra > 0) - if (x_tex + BLOCK_W < cwidth) - InitColSSD(x_tex + BLOCK_W, y_tex, img_step, left, right, d, col_ssd_extra); - - barrier(CLK_LOCAL_MEM_FENCE); //before MinSSD function - - uint2 minSSD = MinSSD(col_ssd); - if (X < cwidth - radius && Y < cheight - radius) - { - if (minSSD.x < minSSDImage[0]) - { - disparImage[0] = (unsigned char)(d + minSSD.y); - minSSDImage[0] = minSSD.x; - } - } - - for(int row = 1; row < end_row; row++) - { - int idx1 = y_tex * img_step + x_tex; - int idx2 = min(y_tex + ((radius << 1) + 1), cheight - 1) * img_step + x_tex; - - barrier(CLK_LOCAL_MEM_FENCE); - - StepDown(idx1, idx2, left, right, d, col_ssd); - if (col_ssd_extra > 0) - if (x_tex + BLOCK_W < cwidth) - StepDown(idx1, idx2, left + BLOCK_W, right + BLOCK_W, d, col_ssd_extra); - - barrier(CLK_LOCAL_MEM_FENCE); - - uint2 minSSD = MinSSD(col_ssd); - if (X < cwidth - radius && row < cheight - radius - Y) - { - int idx = row * cminSSD_step; - if (minSSD.x < minSSDImage[idx]) - { - disparImage[disp_step * row] = (unsigned char)(d + minSSD.y); - minSSDImage[idx] = minSSD.x; - } - } - - y_tex++; - } // for row loop - } // for d loop -} -////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////// Sobel Prefiler (signal channel)////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void prefilter_xsobel(__global unsigned char *input, __global unsigned char *output, - int rows, int cols, int prefilterCap) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if(x < cols && y < rows) - { - int cov = input[(y-1) * cols + (x-1)] * (-1) + input[(y-1) * cols + (x+1)] * (1) + - input[(y) * cols + (x-1)] * (-2) + input[(y) * cols + (x+1)] * (2) + - input[(y+1) * cols + (x-1)] * (-1) + input[(y+1) * cols + (x+1)] * (1); - - cov = min(min(max(-prefilterCap, cov), prefilterCap) + prefilterCap, 255); - output[y * cols + x] = cov & 0xFF; - } -} - - -////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////// Textureness filtering //////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -inline float sobel(__global unsigned char *input, int x, int y, int rows, int cols) -{ - float conv = 0; - int y1 = y==0? 0 : y-1; - int x1 = x==0? 0 : x-1; - if(x < cols && y < rows && x > 0 && y > 0) - { - conv = (float)input[(y1) * cols + (x1)] * (-1) + (float)input[(y1) * cols + (x+1)] * (1) + - (float)input[(y) * cols + (x1)] * (-2) + (float)input[(y) * cols + (x+1)] * (2) + - (float)input[(y+1) * cols + (x1)] * (-1) + (float)input[(y+1) * cols + (x+1)] * (1); - - } - return fabs(conv); -} - -inline float CalcSums(__local float *cols, __local float *cols_cache, int winsz) -{ - unsigned int cache = cols[0]; - - for(int i = 1; i <= winsz; i++) - cache += cols[i]; - - return cache; -} - -#define RpT (2 * ROWSperTHREAD) // got experimentally -__kernel void textureness_kernel(__global unsigned char *disp, int disp_rows, int disp_cols, - int disp_step, __global unsigned char *input, int input_rows, - int input_cols,int winsz, float threshold, - __local float *cols_cache) -{ - int winsz2 = winsz/2; - int n_dirty_pixels = (winsz2) * 2; - - int local_id_x = get_local_id(0); - int group_size_x = get_local_size(0); - int group_id_y = get_group_id(1); - - __local float *cols = cols_cache + group_size_x + local_id_x; - __local float *cols_extra = local_id_x < n_dirty_pixels ? cols + group_size_x : 0; - - int x = get_global_id(0); - int beg_row = group_id_y * RpT; - int end_row = min(beg_row + RpT, disp_rows); - - - int y = beg_row; - - float sum = 0; - float sum_extra = 0; - - for(int i = y - winsz2; i <= y + winsz2; ++i) - { - sum += sobel(input, x - winsz2, i, input_rows, input_cols); - if (cols_extra) - sum_extra += sobel(input, x + group_size_x - winsz2, i, input_rows, input_cols); - } - *cols = sum; - if (cols_extra) - *cols_extra = sum_extra; - - barrier(CLK_LOCAL_MEM_FENCE); - - float sum_win = CalcSums(cols, cols_cache + local_id_x, winsz) * 255; - if (sum_win < threshold) - disp[y * disp_step + x] = 0; - - barrier(CLK_LOCAL_MEM_FENCE); - - for(int y = beg_row + 1; y < end_row; ++y) - { - sum = sum - sobel(input, x - winsz2, y - winsz2 - 1, input_rows, input_cols) + - sobel(input, x - winsz2, y + winsz2, input_rows, input_cols); - *cols = sum; - - if (cols_extra) - { - sum_extra = sum_extra - sobel(input, x + group_size_x - winsz2, y - winsz2 - 1,input_rows, input_cols) - + sobel(input, x + group_size_x - winsz2, y + winsz2, input_rows, input_cols); - *cols_extra = sum_extra; - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if (x < disp_cols) - { - float sum_win = CalcSums(cols, cols_cache + local_id_x, winsz) * 255; - if (sum_win < threshold) - disp[y * disp_step + x] = 0; - } - - barrier(CLK_LOCAL_MEM_FENCE); - } - -} diff --git a/modules/ocl/src/opencl/stereobp.cl b/modules/ocl/src/opencl/stereobp.cl deleted file mode 100644 index 5a1bf088c..000000000 --- a/modules/ocl/src/opencl/stereobp.cl +++ /dev/null @@ -1,393 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.com -// Peng Xiao, pengxiao@outlook.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*/ - -#if defined (DOUBLE_SUPPORT) -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#endif - -#ifdef T_FLOAT -#define T float -#define T4 float4 -#else -#define T short -#define T4 short4 -#endif - -/////////////////////////////////////////////////////////////// -/////////////////common/////////////////////////////////////// -///////////////////////////////////////////////////////////// -inline T saturate_cast(float v){ -#ifdef T_SHORT - return convert_short_sat_rte(v); -#else - return v; -#endif -} - -inline T4 saturate_cast4(float4 v){ -#ifdef T_SHORT - return convert_short4_sat_rte(v); -#else - return v; -#endif -} - -#define FLOAT_MAX 3.402823466e+38f -typedef struct -{ - int cndisp; - float cmax_data_term; - float cdata_weight; - float cmax_disc_term; - float cdisc_single_jump; -}con_srtuct_t; -/////////////////////////////////////////////////////////////// -////////////////////////// comp data ////////////////////////// -/////////////////////////////////////////////////////////////// - -inline float pix_diff_1(const uchar4 l, __global const uchar *rs) -{ - return abs((int)(l.x) - *rs); -} - -inline float pix_diff_4(const uchar4 l, __global const uchar *rs) -{ - uchar4 r; - r = *((__global uchar4 *)rs); - - const float tr = 0.299f; - const float tg = 0.587f; - const float tb = 0.114f; - - float val; - - val = tb * abs((int)l.x - r.x); - val += tg * abs((int)l.y - r.y); - val += tr * abs((int)l.z - r.z); - - return val; -} - -inline float pix_diff_3(const uchar4 l, __global const uchar *rs) -{ - return pix_diff_4(l, rs); -} - -#ifndef CN -#define CN 4 -#endif - -#ifndef CNDISP -#define CNDISP 64 -#endif - -#define CAT(X,Y) X##Y -#define CAT2(X,Y) CAT(X,Y) - -#define PIX_DIFF CAT2(pix_diff_, CN) - -__kernel void comp_data(__global uchar *left, int left_rows, int left_cols, int left_step, - __global uchar *right, int right_step, - __global T *data, int data_step, - __constant con_srtuct_t *con_st) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y > 0 && y < (left_rows - 1) && x > 0 && x < (left_cols - 1)) - { - data_step /= sizeof(T); - const __global uchar* ls = left + y * left_step + x * CN; - const __global uchar* rs = right + y * right_step + x * CN; - - __global T *ds = data + y * data_step + x; - - const unsigned int disp_step = data_step * left_rows; - const float weightXterm = con_st -> cdata_weight * con_st -> cmax_data_term; - const uchar4 ls_data = vload4(0, ls); - - for (int disp = 0; disp < con_st -> cndisp; disp++) - { - if (x - disp >= 1) - { - float val = 0; - val = PIX_DIFF(ls_data, rs - disp * CN); - ds[disp * disp_step] = saturate_cast(fmin(con_st -> cdata_weight * val, weightXterm)); - } - else - { - ds[disp * disp_step] = saturate_cast(weightXterm); - } - } - } -} - -/////////////////////////////////////////////////////////////// -//////////////////////// data step down /////////////////////// -/////////////////////////////////////////////////////////////// -__kernel void data_step_down(__global T *src, int src_rows, - __global T *dst, int dst_rows, int dst_cols, - int src_step, int dst_step, - int cndisp) -{ - const int x = get_global_id(0); - const int y = get_global_id(1); - - if (x < dst_cols && y < dst_rows) - { - src_step /= sizeof(T); - dst_step /= sizeof(T); - int4 coor_step = (int4)(src_rows * src_step); - int4 coor = (int4)(min(2*y+0, src_rows-1) * src_step + 2*x+0, - min(2*y+1, src_rows-1) * src_step + 2*x+0, - min(2*y+0, src_rows-1) * src_step + 2*x+1, - min(2*y+1, src_rows-1) * src_step + 2*x+1); - - for (int d = 0; d < cndisp; ++d) - { - float dst_reg; - dst_reg = src[coor.x]; - dst_reg += src[coor.y]; - dst_reg += src[coor.z]; - dst_reg += src[coor.w]; - coor += coor_step; - - dst[(d * dst_rows + y) * dst_step + x] = saturate_cast(dst_reg); - } - } -} - -/////////////////////////////////////////////////////////////// -/////////////////// level up messages //////////////////////// -/////////////////////////////////////////////////////////////// -__kernel void level_up_message(__global T *src, int src_rows, int src_step, - __global T *dst, int dst_rows, int dst_cols, int dst_step, - int cndisp) -{ - const int x = get_global_id(0); - const int y = get_global_id(1); - - if (x < dst_cols && y < dst_rows) - { - src_step /= sizeof(T); - dst_step /= sizeof(T); - - const int dst_disp_step = dst_step * dst_rows; - const int src_disp_step = src_step * src_rows; - - __global T *dstr = dst + y * dst_step + x; - __global const T *srcr = src + (y / 2 * src_step) + (x / 2); - - for (int d = 0; d < cndisp; ++d) - dstr[d * dst_disp_step] = srcr[d * src_disp_step]; - } -} - -/////////////////////////////////////////////////////////////// -//////////////////// calc all iterations ///////////////////// -/////////////////////////////////////////////////////////////// -inline void message(__global T *us_, __global T *ds_, __global T *ls_, __global T *rs_, - const __global T *dt, - int u_step, int msg_disp_step, int data_disp_step, - float4 cmax_disc_term, float4 cdisc_single_jump) -{ - __global T *us = us_ + u_step; - __global T *ds = ds_ - u_step; - __global T *ls = ls_ + 1; - __global T *rs = rs_ - 1; - - float4 minimum = (float4)(FLOAT_MAX); - - T4 t_dst[CNDISP]; - float4 dst_reg; - float4 prev; - float4 cur; - - T t_us = us[0]; - T t_ds = ds[0]; - T t_ls = ls[0]; - T t_rs = rs[0]; - T t_dt = dt[0]; - - prev = (float4)(t_us + t_ls + t_rs + t_dt, - t_ds + t_ls + t_rs + t_dt, - t_us + t_ds + t_rs + t_dt, - t_us + t_ds + t_ls + t_dt); - - minimum = min(prev, minimum); - - t_dst[0] = saturate_cast4(prev); - - for(int i = 1, idx = msg_disp_step; i < CNDISP; ++i, idx+=msg_disp_step) - { - t_us = us[idx]; - t_ds = ds[idx]; - t_ls = ls[idx]; - t_rs = rs[idx]; - t_dt = dt[data_disp_step * i]; - - dst_reg = (float4)(t_us + t_ls + t_rs + t_dt, - t_ds + t_ls + t_rs + t_dt, - t_us + t_ds + t_rs + t_dt, - t_us + t_ds + t_ls + t_dt); - - minimum = min(dst_reg, minimum); - - prev += cdisc_single_jump; - prev = min(prev, dst_reg); - - t_dst[i] = saturate_cast4(prev); - } - - minimum += cmax_disc_term; - - float4 sum = (float4)(0); - prev = convert_float4(t_dst[CNDISP - 1]); - for (int disp = CNDISP - 2; disp >= 0; disp--) - { - prev += cdisc_single_jump; - cur = convert_float4(t_dst[disp]); - prev = min(prev, cur); - cur = min(prev, minimum); - sum += cur; - - t_dst[disp] = saturate_cast4(cur); - } - - dst_reg = convert_float4(t_dst[CNDISP - 1]); - dst_reg = min(dst_reg, minimum); - t_dst[CNDISP - 1] = saturate_cast4(dst_reg); - sum += dst_reg; - - sum /= (float4)(CNDISP); -#pragma unroll - for(int i = 0, idx = 0; i < CNDISP; ++i, idx+=msg_disp_step) - { - T4 dst = t_dst[i]; - us_[idx] = dst.x - sum.x; - ds_[idx] = dst.y - sum.y; - rs_[idx] = dst.z - sum.z; - ls_[idx] = dst.w - sum.w; - } -} -__kernel void one_iteration(__global T *u, int u_step, - __global T *data, int data_step, - __global T *d, __global T *l, __global T *r, - int t, int cols, int rows, - float cmax_disc_term, float cdisc_single_jump) -{ - const int y = get_global_id(1); - const int x = ((get_global_id(0)) << 1) + ((y + t) & 1); - - if ((y > 0) && (y < rows - 1) && (x > 0) && (x < cols - 1)) - { - u_step /= sizeof(T); - data_step /= sizeof(T); - - __global T *us = u + y * u_step + x; - __global T *ds = d + y * u_step + x; - __global T *ls = l + y * u_step + x; - __global T *rs = r + y * u_step + x; - const __global T *dt = data + y * data_step + x; - - int msg_disp_step = u_step * rows; - int data_disp_step = data_step * rows; - - message(us, ds, ls, rs, dt, - u_step, msg_disp_step, data_disp_step, - (float4)(cmax_disc_term), (float4)(cdisc_single_jump)); - } -} - -/////////////////////////////////////////////////////////////// -/////////////////////////// output //////////////////////////// -/////////////////////////////////////////////////////////////// -__kernel void output(const __global T *u, int u_step, - const __global T *d, const __global T *l, - const __global T *r, const __global T *data, - __global T *disp, int disp_rows, int disp_cols, int disp_step, - int cndisp) -{ - const int x = get_global_id(0); - const int y = get_global_id(1); - - if (y > 0 && y < disp_rows - 1 && x > 0 && x < disp_cols - 1) - { - u_step /= sizeof(T); - disp_step /= sizeof(T); - const __global T *us = u + (y + 1) * u_step + x; - const __global T *ds = d + (y - 1) * u_step + x; - const __global T *ls = l + y * u_step + (x + 1); - const __global T *rs = r + y * u_step + (x - 1); - const __global T *dt = data + y * u_step + x; - - int disp_steps = disp_rows * u_step; - - int best = 0; - float best_val = FLOAT_MAX; - for (int d = 0; d < cndisp; ++d) - { - float val; - val = us[d * disp_steps]; - val += ds[d * disp_steps]; - val += ls[d * disp_steps]; - val += rs[d * disp_steps]; - val += dt[d * disp_steps]; - - if (val < best_val) - { - best_val = val; - best = d; - } - } - - (disp + y * disp_step)[x] = convert_short_sat(best); - } -} diff --git a/modules/ocl/src/opencl/stereocsbp.cl b/modules/ocl/src/opencl/stereocsbp.cl deleted file mode 100644 index 23fc81481..000000000 --- a/modules/ocl/src/opencl/stereocsbp.cl +++ /dev/null @@ -1,1382 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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*/ - -/////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////get_first_k_initial_global////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void get_first_k_initial_global_0(__global short *data_cost_selected_, __global short *selected_disp_pyr, - __global short *ctemp, int h, int w, int nr_plane, - int cmsg_step1, int cdisp_step1, int cndisp) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < h && x < w) - { - __global short *selected_disparity = selected_disp_pyr + y * cmsg_step1 + x; - __global short *data_cost_selected = data_cost_selected_ + y * cmsg_step1 + x; - __global short *data_cost = ctemp + y * cmsg_step1 + x; - - for(int i = 0; i < nr_plane; i++) - { - short minimum = SHRT_MAX; - int id = 0; - - for(int d = 0; d < cndisp; d++) - { - short cur = data_cost[d * cdisp_step1]; - if(cur < minimum) - { - minimum = cur; - id = d; - } - } - - data_cost_selected[i * cdisp_step1] = minimum; - selected_disparity[i * cdisp_step1] = id; - data_cost [id * cdisp_step1] = SHRT_MAX; - } - } -} - -__kernel void get_first_k_initial_global_1(__global float *data_cost_selected_, __global float *selected_disp_pyr, - __global float *ctemp, int h, int w, int nr_plane, - int cmsg_step1, int cdisp_step1, int cndisp) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < h && x < w) - { - __global float *selected_disparity = selected_disp_pyr + y * cmsg_step1 + x; - __global float *data_cost_selected = data_cost_selected_ + y * cmsg_step1 + x; - __global float *data_cost = ctemp + y * cmsg_step1 + x; - - for(int i = 0; i < nr_plane; i++) - { - float minimum = FLT_MAX; - int id = 0; - - for(int d = 0; d < cndisp; d++) - { - float cur = data_cost[d * cdisp_step1]; - if(cur < minimum) - { - minimum = cur; - id = d; - } - } - - data_cost_selected[i * cdisp_step1] = minimum; - selected_disparity[i * cdisp_step1] = id; - data_cost [id * cdisp_step1] = FLT_MAX; - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////get_first_k_initial_local//////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void get_first_k_initial_local_0(__global short *data_cost_selected_, __global short *selected_disp_pyr, - __global short *ctemp,int h, int w, int nr_plane, - int cmsg_step1, int cdisp_step1, int cndisp) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < h && x < w) - { - __global short *selected_disparity = selected_disp_pyr + y * cmsg_step1 + x; - __global short *data_cost_selected = data_cost_selected_ + y * cmsg_step1 + x; - __global short *data_cost = ctemp + y * cmsg_step1 + x; - - int nr_local_minimum = 0; - - short prev = data_cost[0 * cdisp_step1]; - short cur = data_cost[1 * cdisp_step1]; - short next = data_cost[2 * cdisp_step1]; - - for (int d = 1; d < cndisp - 1 && nr_local_minimum < nr_plane; d++) - { - - if (cur < prev && cur < next) - { - data_cost_selected[nr_local_minimum * cdisp_step1] = cur; - selected_disparity[nr_local_minimum * cdisp_step1] = d; - data_cost[d * cdisp_step1] = SHRT_MAX; - - nr_local_minimum++; - } - - prev = cur; - cur = next; - next = data_cost[(d + 1) * cdisp_step1]; - } - - for (int i = nr_local_minimum; i < nr_plane; i++) - { - short minimum = SHRT_MAX; - int id = 0; - - for (int d = 0; d < cndisp; d++) - { - cur = data_cost[d * cdisp_step1]; - if (cur < minimum) - { - minimum = cur; - id = d; - } - } - - data_cost_selected[i * cdisp_step1] = minimum; - selected_disparity[i * cdisp_step1] = id; - data_cost[id * cdisp_step1] = SHRT_MAX; - } - } -} - -__kernel void get_first_k_initial_local_1(__global float *data_cost_selected_, __global float *selected_disp_pyr, - __global float *ctemp,int h, int w, int nr_plane, - int cmsg_step1, int cdisp_step1, int cndisp) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < h && x < w) - { - __global float *selected_disparity = selected_disp_pyr + y * cmsg_step1 + x; - __global float *data_cost_selected = data_cost_selected_ + y * cmsg_step1 + x; - __global float *data_cost = ctemp + y * cmsg_step1 + x; - - int nr_local_minimum = 0; - - float prev = data_cost[0 * cdisp_step1]; - float cur = data_cost[1 * cdisp_step1]; - float next = data_cost[2 * cdisp_step1]; - - for (int d = 1; d < cndisp - 1 && nr_local_minimum < nr_plane; d++) - { - if (cur < prev && cur < next) - { - data_cost_selected[nr_local_minimum * cdisp_step1] = cur; - selected_disparity[nr_local_minimum * cdisp_step1] = d; - data_cost[d * cdisp_step1] = FLT_MAX ; - - nr_local_minimum++; - } - - prev = cur; - cur = next; - next = data_cost[(d + 1) * cdisp_step1]; - } - - - for (int i = nr_local_minimum; i < nr_plane; i++) - { - float minimum = FLT_MAX; - int id = 0; - - for (int d = 0; d < cndisp; d++) - { - cur = data_cost[d * cdisp_step1]; - if (cur < minimum) - { - minimum = cur; - id = d; - } - } - - data_cost_selected[i * cdisp_step1] = minimum; - selected_disparity[i * cdisp_step1] = id; - data_cost[id * cdisp_step1] = FLT_MAX; - } - } -} - -/////////////////////////////////////////////////////////////// -/////////////////////// init data cost //////////////////////// -/////////////////////////////////////////////////////////////// - -inline float compute_3(__global uchar* left, __global uchar* right, - float cdata_weight, float cmax_data_term) -{ - float tb = 0.114f * abs((int)left[0] - right[0]); - float tg = 0.587f * abs((int)left[1] - right[1]); - float tr = 0.299f * abs((int)left[2] - right[2]); - - return fmin(cdata_weight * (tr + tg + tb), cdata_weight * cmax_data_term); -} - -inline float compute_1(__global uchar* left, __global uchar* right, - float cdata_weight, float cmax_data_term) -{ - return fmin(cdata_weight * abs((int)*left - (int)*right), cdata_weight * cmax_data_term); -} - -inline short round_short(float v) -{ - return convert_short_sat_rte(v); -} - -/////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////init_data_cost/////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void init_data_cost_0(__global short *ctemp, __global uchar *cleft, __global uchar *cright, - int h, int w, int level, int channels, - int cmsg_step1, float cdata_weight, float cmax_data_term, int cdisp_step1, - int cth, int cimg_step, int cndisp) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < h && x < w) - { - int y0 = y << level; - int yt = (y + 1) << level; - - int x0 = x << level; - int xt = (x + 1) << level; - - __global short *data_cost = ctemp + y * cmsg_step1 + x; - - for(int d = 0; d < cndisp; ++d) - { - float val = 0.0f; - for(int yi = y0; yi < yt; yi++) - { - for(int xi = x0; xi < xt; xi++) - { - int xr = xi - d; - if(d < cth || xr < 0) - val += cdata_weight * cmax_data_term; - else - { - __global uchar *lle = cleft + yi * cimg_step + xi * channels; - __global uchar *lri = cright + yi * cimg_step + xr * channels; - - if(channels == 1) - val += compute_1(lle, lri, cdata_weight, cmax_data_term); - else - val += compute_3(lle, lri, cdata_weight, cmax_data_term); - } - } - } - data_cost[cdisp_step1 * d] = round_short(val); - } - } -} - -__kernel void init_data_cost_1(__global float *ctemp, __global uchar *cleft, __global uchar *cright, - int h, int w, int level, int channels, - int cmsg_step1, float cdata_weight, float cmax_data_term, int cdisp_step1, - int cth, int cimg_step, int cndisp) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < h && x < w) - { - int y0 = y << level; - int yt = (y + 1) << level; - - int x0 = x << level; - int xt = (x + 1) << level; - - __global float *data_cost = ctemp + y * cmsg_step1 + x; - - for(int d = 0; d < cndisp; ++d) - { - float val = 0.0f; - for(int yi = y0; yi < yt; yi++) - { - for(int xi = x0; xi < xt; xi++) - { - int xr = xi - d; - if(d < cth || xr < 0) - val += cdata_weight * cmax_data_term; - else - { - __global uchar* lle = cleft + yi * cimg_step + xi * channels; - __global uchar* lri = cright + yi * cimg_step + xr * channels; - - if(channels == 1) - val += compute_1(lle, lri, cdata_weight, cmax_data_term); - else - val += compute_3(lle, lri, cdata_weight, cmax_data_term); - } - } - } - data_cost[cdisp_step1 * d] = val; - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////init_data_cost_reduce////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void init_data_cost_reduce_0(__global short *ctemp, __global uchar *cleft, __global uchar *cright, - __local float *smem, int level, int rows, int cols, int h, int winsz, int channels, - int cndisp,int cimg_step, float cdata_weight, float cmax_data_term, int cth, - int cdisp_step1, int cmsg_step1) -{ - int x_out = get_group_id(0); - int y_out = get_group_id(1) % h; - //int d = (blockIdx.y / h) * blockDim.z + threadIdx.z; - int d = (get_group_id(1) / h ) * get_local_size(2) + get_local_id(2); - - int tid = get_local_id(0); - - if (d < cndisp) - { - int x0 = x_out << level; - int y0 = y_out << level; - - int len = min(y0 + winsz, rows) - y0; - - float val = 0.0f; - if (x0 + tid < cols) - { - if (x0 + tid - d < 0 || d < cth) - val = cdata_weight * cmax_data_term * len; - else - { - __global uchar* lle = cleft + y0 * cimg_step + channels * (x0 + tid ); - __global uchar* lri = cright + y0 * cimg_step + channels * (x0 + tid - d); - - for(int y = 0; y < len; ++y) - { - if(channels == 1) - val += compute_1(lle, lri, cdata_weight, cmax_data_term); - else - val += compute_3(lle, lri, cdata_weight, cmax_data_term); - - lle += cimg_step; - lri += cimg_step; - } - } - } - - __local float* dline = smem + winsz * get_local_id(2); - - dline[tid] = val; - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __local float* dline = smem + winsz * get_local_id(2); - if (winsz >= 256) - { - if (tid < 128) - dline[tid] += dline[tid + 128]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __local float* dline = smem + winsz * get_local_id(2); - if (winsz >= 128) - { - if (tid < 64) - dline[tid] += dline[tid + 64]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 64) - if (tid < 32) - vdline[tid] += vdline[tid + 32]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 32) - if (tid < 16) - vdline[tid] += vdline[tid + 16]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d= 16) - if (tid < 8) - vdline[tid] += vdline[tid + 8]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d= 8) - if (tid < 4) - vdline[tid] += vdline[tid + 4]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d= 4) - if (tid < 2) - vdline[tid] += vdline[tid + 2]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d= 2) - if (tid < 1) - vdline[tid] += vdline[tid + 1]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __local float* dline = smem + winsz * get_local_id(2); - __global short* data_cost = ctemp + y_out * cmsg_step1 + x_out; - if (tid == 0) - data_cost[cdisp_step1 * d] = convert_short_sat_rte(dline[0]); - } -} - -__kernel void init_data_cost_reduce_1(__global float *ctemp, __global uchar *cleft, __global uchar *cright, - __local float *smem, int level, int rows, int cols, int h, int winsz, int channels, - int cndisp,int cimg_step, float cdata_weight, float cmax_data_term, int cth, - int cdisp_step1, int cmsg_step1) -{ - int x_out = get_group_id(0); - int y_out = get_group_id(1) % h; - int d = (get_group_id(1) / h ) * get_local_size(2) + get_local_id(2); - - int tid = get_local_id(0); - - if (d < cndisp) - { - int x0 = x_out << level; - int y0 = y_out << level; - - int len = min(y0 + winsz, rows) - y0; - - float val = 0.0f; - //float val = 528.0f; - - if (x0 + tid < cols) - { - if (x0 + tid - d < 0 || d < cth) - val = cdata_weight * cmax_data_term * len; - else - { - __global uchar* lle = cleft + y0 * cimg_step + channels * (x0 + tid ); - __global uchar* lri = cright + y0 * cimg_step + channels * (x0 + tid - d); - - for(int y = 0; y < len; ++y) - { - if(channels == 1) - val += compute_1(lle, lri, cdata_weight, cmax_data_term); - else - val += compute_3(lle, lri, cdata_weight, cmax_data_term); - - lle += cimg_step; - lri += cimg_step; - } - } - } - - __local float* dline = smem + winsz * get_local_id(2); - - dline[tid] = val; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __local float* dline = smem + winsz * get_local_id(2); - if (winsz >= 256) - if (tid < 128) - dline[tid] += dline[tid + 128]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __local float* dline = smem + winsz * get_local_id(2); - if (winsz >= 128) - if (tid < 64) - dline[tid] += dline[tid + 64]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 64) - if (tid < 32) - vdline[tid] += vdline[tid + 32]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 32) - if (tid < 16) - vdline[tid] += vdline[tid + 16]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 16) - if (tid < 8) - vdline[tid] += vdline[tid + 8]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 8) - if (tid < 4) - vdline[tid] += vdline[tid + 4]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 4) - if (tid < 2) - vdline[tid] += vdline[tid + 2]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 2) - if (tid < 1) - vdline[tid] += vdline[tid + 1]; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < cndisp) - { - __global float *data_cost = ctemp + y_out * cmsg_step1 + x_out; - __local float* dline = smem + winsz * get_local_id(2); - if (tid == 0) - data_cost[cdisp_step1 * d] = dline[0]; - } -} - -/////////////////////////////////////////////////////////////// -////////////////////// compute data cost ////////////////////// -/////////////////////////////////////////////////////////////// - -__kernel void compute_data_cost_0(__global const short *selected_disp_pyr, __global short *data_cost_, - __global uchar *cleft, __global uchar *cright, - int h, int w, int level, int nr_plane, int channels, - int cmsg_step1, int cmsg_step2, int cdisp_step1, int cdisp_step2, float cdata_weight, - float cmax_data_term, int cimg_step, int cth) -{ - - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < h && x < w) - { - int y0 = y << level; - int yt = (y + 1) << level; - - int x0 = x << level; - int xt = (x + 1) << level; - - __global const short *selected_disparity = selected_disp_pyr + y/2 * cmsg_step2 + x/2; - __global short *data_cost = data_cost_ + y * cmsg_step1 + x; - - for(int d = 0; d < nr_plane; d++) - { - float val = 0.0f; - for(int yi = y0; yi < yt; yi++) - { - for(int xi = x0; xi < xt; xi++) - { - int sel_disp = selected_disparity[d * cdisp_step2]; - int xr = xi - sel_disp; - - if (xr < 0 || sel_disp < cth) - val += cdata_weight * cmax_data_term; - - else - { - __global uchar* left_x = cleft + yi * cimg_step + xi * channels; - __global uchar* right_x = cright + yi * cimg_step + xr * channels; - - if(channels == 1) - val += compute_1(left_x, right_x, cdata_weight, cmax_data_term); - else - val += compute_3(left_x, right_x, cdata_weight, cmax_data_term); - } - } - } - data_cost[cdisp_step1 * d] = convert_short_sat_rte(val); - } - } -} - -__kernel void compute_data_cost_1(__global const float *selected_disp_pyr, __global float *data_cost_, - __global uchar *cleft, __global uchar *cright, - int h, int w, int level, int nr_plane, int channels, - int cmsg_step1, int cmsg_step2, int cdisp_step1, int cdisp_step2, float cdata_weight, - float cmax_data_term, int cimg_step, int cth) -{ - - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < h && x < w) - { - int y0 = y << level; - int yt = (y + 1) << level; - - int x0 = x << level; - int xt = (x + 1) << level; - - __global const float *selected_disparity = selected_disp_pyr + y/2 * cmsg_step2 + x/2; - __global float *data_cost = data_cost_ + y * cmsg_step1 + x; - - for(int d = 0; d < nr_plane; d++) - { - float val = 0.0f; - for(int yi = y0; yi < yt; yi++) - { - for(int xi = x0; xi < xt; xi++) - { - int sel_disp = selected_disparity[d * cdisp_step2]; - int xr = xi - sel_disp; - - if (xr < 0 || sel_disp < cth) - val += cdata_weight * cmax_data_term; - else - { - __global uchar* left_x = cleft + yi * cimg_step + xi * channels; - __global uchar* right_x = cright + yi * cimg_step + xr * channels; - - if(channels == 1) - val += compute_1(left_x, right_x, cdata_weight, cmax_data_term); - else - val += compute_3(left_x, right_x, cdata_weight, cmax_data_term); - } - } - } - data_cost[cdisp_step1 * d] = val; - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////compute_data_cost_reduce////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void compute_data_cost_reduce_0(__global const short* selected_disp_pyr, __global short* data_cost_, - __global uchar *cleft, __global uchar *cright,__local float *smem, - int level, int rows, int cols, int h, int nr_plane, - int channels, int winsz, - int cmsg_step1, int cmsg_step2, int cdisp_step1, int cdisp_step2, - float cdata_weight, float cmax_data_term, int cimg_step,int cth) - -{ - int x_out = get_group_id(0); - int y_out = get_group_id(1) % h; - int d = (get_group_id(1)/ h) * get_local_size(2) + get_local_id(2); - - int tid = get_local_id(0); - - __global const short* selected_disparity = selected_disp_pyr + y_out/2 * cmsg_step2 + x_out/2; - __global short* data_cost = data_cost_ + y_out * cmsg_step1 + x_out; - - if (d < nr_plane) - { - int sel_disp = selected_disparity[d * cdisp_step2]; - - int x0 = x_out << level; - int y0 = y_out << level; - - int len = min(y0 + winsz, rows) - y0; - - float val = 0.0f; - if (x0 + tid < cols) - { - if (x0 + tid - sel_disp < 0 || sel_disp < cth) - val = cdata_weight * cmax_data_term * len; - else - { - __global uchar* lle = cleft + y0 * cimg_step + channels * (x0 + tid ); - __global uchar* lri = cright + y0 * cimg_step + channels * (x0 + tid - sel_disp); - - for(int y = 0; y < len; ++y) - { - if(channels == 1) - val += compute_1(lle, lri, cdata_weight, cmax_data_term); - else - val += compute_3(lle, lri, cdata_weight, cmax_data_term); - - lle += cimg_step; - lri += cimg_step; - } - } - } - - __local float* dline = smem + winsz * get_local_id(2); - - dline[tid] = val; - } - - barrier(CLK_LOCAL_MEM_FENCE); - // if (winsz >= 256) { if (tid < 128) { dline[tid] += dline[tid + 128]; } barrier(CLK_LOCAL_MEM_FENCE); } - //if (winsz >= 128) { if (tid < 64) { dline[tid] += dline[tid + 64]; } barrier(CLK_LOCAL_MEM_FENCE); } - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 64) - { - if (tid < 32) - vdline[tid] += vdline[tid + 32]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 32) - { - if (tid < 16) - vdline[tid] += vdline[tid + 16]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 16) - { - if (tid < 8) - vdline[tid] += vdline[tid + 8]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 8) - { - if (tid < 4) - vdline[tid] += vdline[tid + 4]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 4) - { - if (tid < 2) - vdline[tid] += vdline[tid + 2]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 2) - { - if (tid < 1) - vdline[tid] += vdline[tid + 1]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (tid == 0) - data_cost[cdisp_step1 * d] = convert_short_sat_rte(vdline[0]); - } -} - -__kernel void compute_data_cost_reduce_1(__global const float *selected_disp_pyr, __global float *data_cost_, - __global uchar *cleft, __global uchar *cright, __local float *smem, - int level, int rows, int cols, int h, int nr_plane, - int channels, int winsz, - int cmsg_step1, int cmsg_step2, int cdisp_step1,int cdisp_step2, float cdata_weight, - float cmax_data_term, int cimg_step, int cth) - -{ - int x_out = get_group_id(0); - int y_out = get_group_id(1) % h; - int d = (get_group_id(1)/ h) * get_local_size(2) + get_local_id(2); - - int tid = get_local_id(0); - - __global const float *selected_disparity = selected_disp_pyr + y_out/2 * cmsg_step2 + x_out/2; - __global float *data_cost = data_cost_ + y_out * cmsg_step1 + x_out; - - if (d < nr_plane) - { - int sel_disp = selected_disparity[d * cdisp_step2]; - - int x0 = x_out << level; - int y0 = y_out << level; - - int len = min(y0 + winsz, rows) - y0; - - float val = 0.0f; - if (x0 + tid < cols) - { - if (x0 + tid - sel_disp < 0 || sel_disp < cth) - val = cdata_weight * cmax_data_term * len; - else - { - __global uchar* lle = cleft + y0 * cimg_step + channels * (x0 + tid ); - __global uchar* lri = cright + y0 * cimg_step + channels * (x0 + tid - sel_disp); - - for(int y = 0; y < len; ++y) - { - if(channels == 1) - val += compute_1(lle, lri, cdata_weight, cmax_data_term); - else - val += compute_3(lle, lri, cdata_weight, cmax_data_term); - - lle += cimg_step; - lri += cimg_step; - } - } - } - - __local float* dline = smem + winsz * get_local_id(2); - - dline[tid] = val; - } - - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 64) - { - if (tid < 32) - vdline[tid] += vdline[tid + 32]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 32) - { - if (tid < 16) - vdline[tid] += vdline[tid + 16]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 16) - { - if (tid < 8) - vdline[tid] += vdline[tid + 8]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 8) - { - if (tid < 4) - vdline[tid] += vdline[tid + 4]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 4) - { - if (tid < 2) - vdline[tid] += vdline[tid + 2]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (winsz >= 2) - { - if (tid < 1) - vdline[tid] += vdline[tid + 1]; - } - } - barrier(CLK_LOCAL_MEM_FENCE); - - if(d < nr_plane) - { - __local volatile float* vdline = smem + winsz * get_local_id(2); - if (tid == 0) - data_cost[cdisp_step1 * d] = vdline[0]; - } -} - -/////////////////////////////////////////////////////////////// -//////////////////////// init message ///////////////////////// -/////////////////////////////////////////////////////////////// - -inline void get_first_k_element_increase_0(__global short* u_new, __global short *d_new, __global short *l_new, - __global short *r_new, __global const short *u_cur, __global const short *d_cur, - __global const short *l_cur, __global const short *r_cur, - __global short *data_cost_selected, __global short *disparity_selected_new, - __global short *data_cost_new, __global const short* data_cost_cur, - __global const short *disparity_selected_cur, - int nr_plane, int nr_plane2, - int cdisp_step1, int cdisp_step2) -{ - for(int i = 0; i < nr_plane; i++) - { - short minimum = SHRT_MAX; - int id = 0; - for(int j = 0; j < nr_plane2; j++) - { - short cur = data_cost_new[j * cdisp_step1]; - if(cur < minimum) - { - minimum = cur; - id = j; - } - } - - data_cost_selected[i * cdisp_step1] = data_cost_cur[id * cdisp_step1]; - disparity_selected_new[i * cdisp_step1] = disparity_selected_cur[id * cdisp_step2]; - - u_new[i * cdisp_step1] = u_cur[id * cdisp_step2]; - d_new[i * cdisp_step1] = d_cur[id * cdisp_step2]; - l_new[i * cdisp_step1] = l_cur[id * cdisp_step2]; - r_new[i * cdisp_step1] = r_cur[id * cdisp_step2]; - - data_cost_new[id * cdisp_step1] = SHRT_MAX; - } -} - -__kernel void init_message_0(__global short *u_new_, __global short *d_new_, __global short *l_new_, - __global short *r_new_, __global short *u_cur_, __global const short *d_cur_, - __global const short *l_cur_, __global const short *r_cur_, __global short *ctemp, - __global short *selected_disp_pyr_new, __global const short *selected_disp_pyr_cur, - __global short *data_cost_selected_, __global const short *data_cost_, - int h, int w, int nr_plane, int h2, int w2, int nr_plane2, - int cdisp_step1, int cdisp_step2, int cmsg_step1, int cmsg_step2) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y < h && x < w) - { - __global const short *u_cur = u_cur_ + min(h2-1, y/2 + 1) * cmsg_step2 + x/2; - __global const short *d_cur = d_cur_ + max(0, y/2 - 1) * cmsg_step2 + x/2; - __global const short *l_cur = l_cur_ + y/2 * cmsg_step2 + min(w2-1, x/2 + 1); - __global const short *r_cur = r_cur_ + y/2 * cmsg_step2 + max(0, x/2 - 1); - - __global short *data_cost_new = ctemp + y * cmsg_step1 + x; - - __global const short *disparity_selected_cur = selected_disp_pyr_cur + y/2 * cmsg_step2 + x/2; - __global const short *data_cost = data_cost_ + y * cmsg_step1 + x; - - for(int d = 0; d < nr_plane2; d++) - { - int idx2 = d * cdisp_step2; - - short val = data_cost[d * cdisp_step1] + u_cur[idx2] + d_cur[idx2] + l_cur[idx2] + r_cur[idx2]; - data_cost_new[d * cdisp_step1] = val; - } - - __global short *data_cost_selected = data_cost_selected_ + y * cmsg_step1 + x; - __global short *disparity_selected_new = selected_disp_pyr_new + y * cmsg_step1 + x; - - __global short *u_new = u_new_ + y * cmsg_step1 + x; - __global short *d_new = d_new_ + y * cmsg_step1 + x; - __global short *l_new = l_new_ + y * cmsg_step1 + x; - __global short *r_new = r_new_ + y * cmsg_step1 + x; - - u_cur = u_cur_ + y/2 * cmsg_step2 + x/2; - d_cur = d_cur_ + y/2 * cmsg_step2 + x/2; - l_cur = l_cur_ + y/2 * cmsg_step2 + x/2; - r_cur = r_cur_ + y/2 * cmsg_step2 + x/2; - - get_first_k_element_increase_0(u_new, d_new, l_new, r_new, u_cur, d_cur, l_cur, r_cur, - data_cost_selected, disparity_selected_new, data_cost_new, - data_cost, disparity_selected_cur, nr_plane, nr_plane2, - cdisp_step1, cdisp_step2); - } -} - -__kernel void init_message_1(__global float *u_new_, __global float *d_new_, __global float *l_new_, - __global float *r_new_, __global const float *u_cur_, __global const float *d_cur_, - __global const float *l_cur_, __global const float *r_cur_, __global float *ctemp, - __global float *selected_disp_pyr_new, __global const float *selected_disp_pyr_cur, - __global float *data_cost_selected_, __global const float *data_cost_, - int h, int w, int nr_plane, int h2, int w2, int nr_plane2, - int cdisp_step1, int cdisp_step2, int cmsg_step1, int cmsg_step2) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - - __global const float *u_cur = u_cur_ + min(h2-1, y/2 + 1) * cmsg_step2 + x/2; - __global const float *d_cur = d_cur_ + max(0, y/2 - 1) * cmsg_step2 + x/2; - __global const float *l_cur = l_cur_ + y/2 * cmsg_step2 + min(w2-1, x/2 + 1); - __global const float *r_cur = r_cur_ + y/2 * cmsg_step2 + max(0, x/2 - 1); - - __global float *data_cost_new = ctemp + y * cmsg_step1 + x; - - __global const float *disparity_selected_cur = selected_disp_pyr_cur + y/2 * cmsg_step2 + x/2; - __global const float *data_cost = data_cost_ + y * cmsg_step1 + x; - - if (y < h && x < w) - { - for(int d = 0; d < nr_plane2; d++) - { - int idx2 = d * cdisp_step2; - - float val = data_cost[d * cdisp_step1] + u_cur[idx2] + d_cur[idx2] + l_cur[idx2] + r_cur[idx2]; - data_cost_new[d * cdisp_step1] = val; - } - } - - __global float *data_cost_selected = data_cost_selected_ + y * cmsg_step1 + x; - __global float *disparity_selected_new = selected_disp_pyr_new + y * cmsg_step1 + x; - - __global float *u_new = u_new_ + y * cmsg_step1 + x; - __global float *d_new = d_new_ + y * cmsg_step1 + x; - __global float *l_new = l_new_ + y * cmsg_step1 + x; - __global float *r_new = r_new_ + y * cmsg_step1 + x; - - barrier(CLK_LOCAL_MEM_FENCE); - - if(y < h && x < w) - { - u_cur = u_cur_ + y/2 * cmsg_step2 + x/2; - d_cur = d_cur_ + y/2 * cmsg_step2 + x/2; - l_cur = l_cur_ + y/2 * cmsg_step2 + x/2; - r_cur = r_cur_ + y/2 * cmsg_step2 + x/2; - - for(int i = 0; i < nr_plane; i++) - { - float minimum = FLT_MAX; - int id = 0; - - for(int j = 0; j < nr_plane2; j++) - { - float cur = data_cost_new[j * cdisp_step1]; - if(cur < minimum) - { - minimum = cur; - id = j; - } - } - data_cost_selected[i * cdisp_step1] = data_cost[id * cdisp_step1]; - disparity_selected_new[i * cdisp_step1] = disparity_selected_cur[id * cdisp_step2]; - u_new[i * cdisp_step1] = u_cur[id * cdisp_step2]; - d_new[i * cdisp_step1] = d_cur[id * cdisp_step2]; - l_new[i * cdisp_step1] = l_cur[id * cdisp_step2]; - r_new[i * cdisp_step1] = r_cur[id * cdisp_step2]; - data_cost_new[id * cdisp_step1] = FLT_MAX; - } - } -} - -/////////////////////////////////////////////////////////////// -//////////////////// calc all iterations ///////////////////// -/////////////////////////////////////////////////////////////// - -inline void message_per_pixel_0(__global const short *data, __global short *msg_dst, __global const short *msg1, - __global const short *msg2, __global const short *msg3, - __global const short *dst_disp, __global const short *src_disp, - int nr_plane, __global short *temp, - float cmax_disc_term, int cdisp_step1, float cdisc_single_jump) -{ - short minimum = SHRT_MAX; - for(int d = 0; d < nr_plane; d++) - { - int idx = d * cdisp_step1; - short val = data[idx] + msg1[idx] + msg2[idx] + msg3[idx]; - - if(val < minimum) - minimum = val; - - msg_dst[idx] = val; - } - - float sum = 0; - for(int d = 0; d < nr_plane; d++) - { - float cost_min = minimum + cmax_disc_term; - short src_disp_reg = src_disp[d * cdisp_step1]; - - for(int d2 = 0; d2 < nr_plane; d2++) - cost_min = fmin(cost_min, (msg_dst[d2 * cdisp_step1] + - cdisc_single_jump * abs(dst_disp[d2 * cdisp_step1] - src_disp_reg))); - - temp[d * cdisp_step1] = convert_short_sat_rte(cost_min); - sum += cost_min; - } - sum /= nr_plane; - - for(int d = 0; d < nr_plane; d++) - msg_dst[d * cdisp_step1] = convert_short_sat_rte(temp[d * cdisp_step1] - sum); -} - -inline void message_per_pixel_1(__global const float *data, __global float *msg_dst, __global const float *msg1, - __global const float *msg2, __global const float *msg3, - __global const float *dst_disp, __global const float *src_disp, - int nr_plane, __global float *temp, - float cmax_disc_term, int cdisp_step1, float cdisc_single_jump) -{ - float minimum = FLT_MAX; - for(int d = 0; d < nr_plane; d++) - { - int idx = d * cdisp_step1; - float val = data[idx] + msg1[idx] + msg2[idx] + msg3[idx]; - - if(val < minimum) - minimum = val; - - msg_dst[idx] = val; - } - - float sum = 0; - for(int d = 0; d < nr_plane; d++) - { - float cost_min = minimum + cmax_disc_term; - float src_disp_reg = src_disp[d * cdisp_step1]; - - for(int d2 = 0; d2 < nr_plane; d2++) - cost_min = fmin(cost_min, (msg_dst[d2 * cdisp_step1] + - cdisc_single_jump * fabs(dst_disp[d2 * cdisp_step1] - src_disp_reg))); - - temp[d * cdisp_step1] = cost_min; - sum += cost_min; - } - sum /= nr_plane; - - for(int d = 0; d < nr_plane; d++) - msg_dst[d * cdisp_step1] = temp[d * cdisp_step1] - sum; -} - -__kernel void compute_message_0(__global short *u_, __global short *d_, __global short *l_, __global short *r_, - __global const short *data_cost_selected, __global const short *selected_disp_pyr_cur, - __global short *ctemp, int h, int w, int nr_plane, int i, - float cmax_disc_term, int cdisp_step1, int cmsg_step1, float cdisc_single_jump) -{ - int y = get_global_id(1); - int x = ((get_global_id(0)) << 1) + ((y + i) & 1); - - if (y > 0 && y < h - 1 && x > 0 && x < w - 1) - { - __global const short *data = data_cost_selected + y * cmsg_step1 + x; - - __global short *u = u_ + y * cmsg_step1 + x; - __global short *d = d_ + y * cmsg_step1 + x; - __global short *l = l_ + y * cmsg_step1 + x; - __global short *r = r_ + y * cmsg_step1 + x; - - __global const short *disp = selected_disp_pyr_cur + y * cmsg_step1 + x; - - __global short *temp = ctemp + y * cmsg_step1 + x; - - message_per_pixel_0(data, u, r - 1, u + cmsg_step1, l + 1, disp, disp - cmsg_step1, nr_plane, temp, - cmax_disc_term, cdisp_step1, cdisc_single_jump); - message_per_pixel_0(data, d, d - cmsg_step1, r - 1, l + 1, disp, disp + cmsg_step1, nr_plane, temp, - cmax_disc_term, cdisp_step1, cdisc_single_jump); - message_per_pixel_0(data, l, u + cmsg_step1, d - cmsg_step1, l + 1, disp, disp - 1, nr_plane, temp, - cmax_disc_term, cdisp_step1, cdisc_single_jump); - message_per_pixel_0(data, r, u + cmsg_step1, d - cmsg_step1, r - 1, disp, disp + 1, nr_plane, temp, - cmax_disc_term, cdisp_step1, cdisc_single_jump); - } -} - -__kernel void compute_message_1(__global float *u_, __global float *d_, __global float *l_, __global float *r_, - __global const float *data_cost_selected, __global const float *selected_disp_pyr_cur, - __global float *ctemp, int h, int w, int nr_plane, int i, - float cmax_disc_term, int cdisp_step1, int cmsg_step1, float cdisc_single_jump) -{ - int y = get_global_id(1); - int x = ((get_global_id(0)) << 1) + ((y + i) & 1); - - if (y > 0 && y < h - 1 && x > 0 && x < w - 1) - { - __global const float *data = data_cost_selected + y * cmsg_step1 + x; - - __global float *u = u_ + y * cmsg_step1 + x; - __global float *d = d_ + y * cmsg_step1 + x; - __global float *l = l_ + y * cmsg_step1 + x; - __global float *r = r_ + y * cmsg_step1 + x; - - __global const float *disp = selected_disp_pyr_cur + y * cmsg_step1 + x; - __global float *temp = ctemp + y * cmsg_step1 + x; - - message_per_pixel_1(data, u, r - 1, u + cmsg_step1, l + 1, disp, disp - cmsg_step1, nr_plane, temp, - cmax_disc_term, cdisp_step1, cdisc_single_jump); - message_per_pixel_1(data, d, d - cmsg_step1, r - 1, l + 1, disp, disp + cmsg_step1, nr_plane, temp, - cmax_disc_term, cdisp_step1, cdisc_single_jump); - message_per_pixel_1(data, l, u + cmsg_step1, d - cmsg_step1, l + 1, disp, disp - 1, nr_plane, temp, - cmax_disc_term, cdisp_step1, cdisc_single_jump); - message_per_pixel_1(data, r, u + cmsg_step1, d - cmsg_step1, r - 1, disp, disp + 1, nr_plane, temp, - cmax_disc_term, cdisp_step1, cdisc_single_jump); - } -} - -/////////////////////////////////////////////////////////////// -/////////////////////////// output //////////////////////////// -/////////////////////////////////////////////////////////////// - -__kernel void compute_disp_0(__global const short *u_, __global const short *d_, __global const short *l_, - __global const short *r_, __global const short * data_cost_selected, - __global const short *disp_selected_pyr, - __global short* disp, - int res_step, int cols, int rows, int nr_plane, - int cmsg_step1, int cdisp_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y > 0 && y < rows - 1 && x > 0 && x < cols - 1) - { - __global const short *data = data_cost_selected + y * cmsg_step1 + x; - __global const short *disp_selected = disp_selected_pyr + y * cmsg_step1 + x; - - __global const short *u = u_ + (y+1) * cmsg_step1 + (x+0); - __global const short *d = d_ + (y-1) * cmsg_step1 + (x+0); - __global const short *l = l_ + (y+0) * cmsg_step1 + (x+1); - __global const short *r = r_ + (y+0) * cmsg_step1 + (x-1); - - short best = 0; - short best_val = SHRT_MAX; - - for (int i = 0; i < nr_plane; ++i) - { - int idx = i * cdisp_step1; - short val = data[idx]+ u[idx] + d[idx] + l[idx] + r[idx]; - - if (val < best_val) - { - best_val = val; - best = disp_selected[idx]; - } - } - disp[res_step * y + x] = best; - } -} - -__kernel void compute_disp_1(__global const float *u_, __global const float *d_, __global const float *l_, - __global const float *r_, __global const float *data_cost_selected, - __global const float *disp_selected_pyr, - __global short *disp, - int res_step, int cols, int rows, int nr_plane, - int cmsg_step1, int cdisp_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (y > 0 && y < rows - 1 && x > 0 && x < cols - 1) - { - __global const float *data = data_cost_selected + y * cmsg_step1 + x; - __global const float *disp_selected = disp_selected_pyr + y * cmsg_step1 + x; - - __global const float *u = u_ + (y+1) * cmsg_step1 + (x+0); - __global const float *d = d_ + (y-1) * cmsg_step1 + (x+0); - __global const float *l = l_ + (y+0) * cmsg_step1 + (x+1); - __global const float *r = r_ + (y+0) * cmsg_step1 + (x-1); - - short best = 0; - short best_val = SHRT_MAX; - for (int i = 0; i < nr_plane; ++i) - { - int idx = i * cdisp_step1; - float val = data[idx]+ u[idx] + d[idx] + l[idx] + r[idx]; - - if (val < best_val) - { - best_val = val; - best = convert_short_sat_rte(disp_selected[idx]); - } - } - disp[res_step * y + x] = best; - } -} diff --git a/modules/ocl/src/opencl/svm.cl b/modules/ocl/src/opencl/svm.cl deleted file mode 100644 index c10494070..000000000 --- a/modules/ocl/src/opencl/svm.cl +++ /dev/null @@ -1,211 +0,0 @@ -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2013, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Erping Pang, erping@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. -// -// - -#ifdef DOUBLE_SUPPORT -#ifdef cl_amd_fp64 -#pragma OPENCL EXTENSION cl_amd_fp64:enable -#elif defined (cl_khr_fp64) -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#endif -#define TYPE double -#else -#define TYPE float -#endif -#if defined ADDEXP -#define EXP(X) exp(X) -#else -#define EXP(X) X -#endif -#if defined ADDPOW -#define POW(X,Y) pow(fabs(X),(Y)) -#else -#define POW(X,Y) X -#endif -#define MAX_VAL (FLT_MAX*1e-3) - -#define BLOCK_SIZE 16 - -__kernel void svm_linear(__global float* src, int src_step, __global float* src2, int src2_step, __global TYPE* dst, int dst_step, int src_rows, int src2_cols, - int width, TYPE alpha, TYPE beta) -{ - const int col = get_global_id(0); - const int row = get_global_id(1); - - if(row < src_rows && col < src2_cols) - { - int t = 0; - TYPE temp = 0.0; - for(t = 0; t < width - BLOCK_SIZE; t += BLOCK_SIZE) - { - float16 t0 = vload16(0, src + row * src_step + t); - float16 t1 = vload16(0, src2 + col * src2_step + t); - t0 *= t1; - temp += t0.s0 + t0.s1 + t0.s2 + t0.s3 + t0.s4 + t0.s5 + t0.s6 + t0.s7 + - t0.s8 + t0.s9 + t0.sa + t0.sb + t0.sc + t0.sd + t0.se + t0.sf; - } - for(; t < width; t++) - { - temp += src[row * src_step + t] * src2[col * src2_step + t]; - } - - TYPE temp1 = (TYPE) (temp * alpha + beta); - - if( temp1 > MAX_VAL ) - { - dst[row * dst_step + col] = MAX_VAL; - } - else - { - dst[row * dst_step + col] = temp1; - } - - } - -} -__kernel void svm_sigmod(__global float* src, int src_step, __global float* src2, int src2_step, __global TYPE* dst, int dst_step, int src_rows, int src2_cols, - int width, TYPE alpha, TYPE beta) -{ - const int col = get_global_id(0); - const int row = get_global_id(1); - - if(row < src_rows && col < src2_cols) - { - int t = 0; - TYPE temp = 0.0; - for(t = 0; t < width - BLOCK_SIZE; t += BLOCK_SIZE) - { - float16 t0 = vload16(0, src + row * src_step + t); - float16 t1 = vload16(0, src2 + col * src2_step + t); - t0 *= t1; - temp += t0.s0 + t0.s1 + t0.s2 + t0.s3 + t0.s4 + t0.s5 + t0.s6 + t0.s7 + - t0.s8 + t0.s9 + t0.sa + t0.sb + t0.sc + t0.sd + t0.se + t0.sf; - } - for(; t < width; t++) - { - temp += src[row * src_step + t] * src2[col * src2_step + t]; - } - TYPE tp = (TYPE) (temp * alpha + beta); - TYPE e = exp(-fabs(tp)); - TYPE temp1; - if(tp > 0) - { - temp1 = (TYPE)((1. - e) / (1. + e)); - } - else - { - temp1 = (TYPE)((e - 1.) / (e + 1.)); - } - - if( temp1 > MAX_VAL ) - { - dst[row * dst_step + col] = MAX_VAL; - } - else - { - dst[row * dst_step + col] = temp1; - } - } - -} -__kernel void svm_poly(__global float* src, int src_step, __global float* src2, int src2_step, __global TYPE* dst, int dst_step, int src_rows, int src2_cols, - int width, TYPE alpha, TYPE beta, TYPE degree) -{ - const int col = get_global_id(0); - const int row = get_global_id(1); - - if(row < src_rows && col < src2_cols) - { - int t = 0; - TYPE temp = 0.0; - for(t = 0; t < width - BLOCK_SIZE; t += BLOCK_SIZE) - { - float16 t0 = vload16(0, src + row * src_step + t); - float16 t1 = vload16(0, src2 + col * src2_step + t); - t0 *= t1; - temp += t0.s0 + t0.s1 + t0.s2 + t0.s3 + t0.s4 + t0.s5 + t0.s6 + t0.s7 + - t0.s8 + t0.s9 + t0.sa + t0.sb + t0.sc + t0.sd + t0.se + t0.sf; - } - for(; t < width; t++) - { - temp += src[row * src_step + t] * src2[col * src2_step + t]; - } - TYPE temp1 = (TYPE)(POW((temp * alpha + beta), degree)); - - if( temp1 > MAX_VAL ) - { - dst[row * dst_step + col] = MAX_VAL; - } - else - { - dst[row * dst_step + col] = temp1; - } - } - -} -__kernel void svm_rbf(__global float* src, int src_step, __global float* src2, int src2_step, __global TYPE* dst, int dst_step, int src_rows, int src2_cols, - int width, TYPE gamma) -{ - const int col = get_global_id(0); - const int row = get_global_id(1); - - if(row < src_rows && col < src2_cols) - { - int t = 0; - TYPE temp = 0.0; - for(t = 0; t < width - BLOCK_SIZE; t += BLOCK_SIZE) - { - float16 t0 = vload16(0, src + row * src_step + t); - float16 t1 = vload16(0, src2 + col * src2_step + t); - t0 = (t0 - t1) * (t0 - t1); - temp += t0.s0 + t0.s1 + t0.s2 + t0.s3 + t0.s4 + t0.s5 + t0.s6 + t0.s7 + - t0.s8 + t0.s9 + t0.sa + t0.sb + t0.sc + t0.sd + t0.se + t0.sf; - } - for(; t < width; t++) - { - temp += (src[row * src_step + t] - src2[col * src2_step + t]) * (src[row * src_step + t] - src2[col * src2_step + t]); - } - TYPE temp1 = EXP((TYPE)(temp * gamma)); - - if( temp1 > MAX_VAL ) - { - dst[row * dst_step + col] = MAX_VAL; - } - else - { - dst[row * dst_step + col] = temp1; - } - } -} diff --git a/modules/ocl/src/opencl/tvl1flow.cl b/modules/ocl/src/opencl/tvl1flow.cl deleted file mode 100644 index b488e8969..000000000 --- a/modules/ocl/src/opencl/tvl1flow.cl +++ /dev/null @@ -1,386 +0,0 @@ -/*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 -// 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*/ - -__kernel void centeredGradientKernel(__global const float* src, int src_col, int src_row, int src_step, - __global float* dx, __global float* dy, int dx_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if((x < src_col)&&(y < src_row)) - { - int src_x1 = (x + 1) < (src_col -1)? (x + 1) : (src_col - 1); - int src_x2 = (x - 1) > 0 ? (x -1) : 0; - dx[y * dx_step+ x] = 0.5f * (src[y * src_step + src_x1] - src[y * src_step+ src_x2]); - - int src_y1 = (y+1) < (src_row - 1) ? (y + 1) : (src_row - 1); - int src_y2 = (y - 1) > 0 ? (y - 1) : 0; - dy[y * dx_step+ x] = 0.5f * (src[src_y1 * src_step + x] - src[src_y2 * src_step+ x]); - } - -} - -inline float bicubicCoeff(float x_) -{ - - float x = fabs(x_); - if (x <= 1.0f) - return x * x * (1.5f * x - 2.5f) + 1.0f; - else if (x < 2.0f) - return x * (x * (-0.5f * x + 2.5f) - 4.0f) + 2.0f; - else - return 0.0f; -} - -__kernel void warpBackwardKernel(__global const float* I0, int I0_step, int I0_col, int I0_row, - image2d_t tex_I1, image2d_t tex_I1x, image2d_t tex_I1y, - __global const float* u1, int u1_step, - __global const float* u2, - __global float* I1w, - __global float* I1wx, /*int I1wx_step,*/ - __global float* I1wy, /*int I1wy_step,*/ - __global float* grad, /*int grad_step,*/ - __global float* rho, - int I1w_step, - int u2_step, - int u1_offset_x, - int u1_offset_y, - int u2_offset_x, - int u2_offset_y) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if(x < I0_col&&y < I0_row) - { - //float u1Val = u1(y, x); - float u1Val = u1[(y + u1_offset_y) * u1_step + x + u1_offset_x]; - //float u2Val = u2(y, x); - float u2Val = u2[(y + u2_offset_y) * u2_step + x + u2_offset_x]; - - float wx = x + u1Val; - float wy = y + u2Val; - - int xmin = ceil(wx - 2.0f); - int xmax = floor(wx + 2.0f); - - int ymin = ceil(wy - 2.0f); - int ymax = floor(wy + 2.0f); - - float sum = 0.0f; - float sumx = 0.0f; - float sumy = 0.0f; - float wsum = 0.0f; - sampler_t sampleri = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST; - - for (int cy = ymin; cy <= ymax; ++cy) - { - for (int cx = xmin; cx <= xmax; ++cx) - { - float w = bicubicCoeff(wx - cx) * bicubicCoeff(wy - cy); - - //sum += w * tex2D(tex_I1 , cx, cy); - int2 cood = (int2)(cx, cy); - sum += w * read_imagef(tex_I1, sampleri, cood).x; - //sumx += w * tex2D(tex_I1x, cx, cy); - sumx += w * read_imagef(tex_I1x, sampleri, cood).x; - //sumy += w * tex2D(tex_I1y, cx, cy); - sumy += w * read_imagef(tex_I1y, sampleri, cood).x; - - wsum += w; - } - } - - float coeff = 1.0f / wsum; - - float I1wVal = sum * coeff; - float I1wxVal = sumx * coeff; - float I1wyVal = sumy * coeff; - - I1w[y * I1w_step + x] = I1wVal; - I1wx[y * I1w_step + x] = I1wxVal; - I1wy[y * I1w_step + x] = I1wyVal; - - float Ix2 = I1wxVal * I1wxVal; - float Iy2 = I1wyVal * I1wyVal; - - // store the |Grad(I1)|^2 - grad[y * I1w_step + x] = Ix2 + Iy2; - - // compute the constant part of the rho function - float I0Val = I0[y * I0_step + x]; - rho[y * I1w_step + x] = I1wVal - I1wxVal * u1Val - I1wyVal * u2Val - I0Val; - } - -} - -inline float readImage(__global float *image, int x, int y, int rows, int cols, int elemCntPerRow) -{ - int i0 = clamp(x, 0, cols - 1); - int j0 = clamp(y, 0, rows - 1); - - return image[j0 * elemCntPerRow + i0]; -} - -__kernel void warpBackwardKernelNoImage2d(__global const float* I0, int I0_step, int I0_col, int I0_row, - __global const float* tex_I1, __global const float* tex_I1x, __global const float* tex_I1y, - __global const float* u1, int u1_step, - __global const float* u2, - __global float* I1w, - __global float* I1wx, /*int I1wx_step,*/ - __global float* I1wy, /*int I1wy_step,*/ - __global float* grad, /*int grad_step,*/ - __global float* rho, - int I1w_step, - int u2_step, - int I1_step, - int I1x_step) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if(x < I0_col&&y < I0_row) - { - //float u1Val = u1(y, x); - float u1Val = u1[y * u1_step + x]; - //float u2Val = u2(y, x); - float u2Val = u2[y * u2_step + x]; - - float wx = x + u1Val; - float wy = y + u2Val; - - int xmin = ceil(wx - 2.0f); - int xmax = floor(wx + 2.0f); - - int ymin = ceil(wy - 2.0f); - int ymax = floor(wy + 2.0f); - - float sum = 0.0f; - float sumx = 0.0f; - float sumy = 0.0f; - float wsum = 0.0f; - - for (int cy = ymin; cy <= ymax; ++cy) - { - for (int cx = xmin; cx <= xmax; ++cx) - { - float w = bicubicCoeff(wx - cx) * bicubicCoeff(wy - cy); - - int2 cood = (int2)(cx, cy); - sum += w * readImage(tex_I1, cood.x, cood.y, I0_col, I0_row, I1_step); - sumx += w * readImage(tex_I1x, cood.x, cood.y, I0_col, I0_row, I1x_step); - sumy += w * readImage(tex_I1y, cood.x, cood.y, I0_col, I0_row, I1x_step); - wsum += w; - } - } - - float coeff = 1.0f / wsum; - - float I1wVal = sum * coeff; - float I1wxVal = sumx * coeff; - float I1wyVal = sumy * coeff; - - I1w[y * I1w_step + x] = I1wVal; - I1wx[y * I1w_step + x] = I1wxVal; - I1wy[y * I1w_step + x] = I1wyVal; - - float Ix2 = I1wxVal * I1wxVal; - float Iy2 = I1wyVal * I1wyVal; - - // store the |Grad(I1)|^2 - grad[y * I1w_step + x] = Ix2 + Iy2; - - // compute the constant part of the rho function - float I0Val = I0[y * I0_step + x]; - rho[y * I1w_step + x] = I1wVal - I1wxVal * u1Val - I1wyVal * u2Val - I0Val; - } - -} - - -__kernel void estimateDualVariablesKernel(__global const float* u1, int u1_col, int u1_row, int u1_step, - __global const float* u2, - __global float* p11, int p11_step, - __global float* p12, - __global float* p21, - __global float* p22, - float taut, - int u2_step, - int u1_offset_x, - int u1_offset_y, - int u2_offset_x, - int u2_offset_y) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if(x < u1_col && y < u1_row) - { - int src_x1 = (x + 1) < (u1_col - 1) ? (x + 1) : (u1_col - 1); - float u1x = u1[(y + u1_offset_y) * u1_step + src_x1 + u1_offset_x] - u1[(y + u1_offset_y) * u1_step + x + u1_offset_x]; - - int src_y1 = (y + 1) < (u1_row - 1) ? (y + 1) : (u1_row - 1); - float u1y = u1[(src_y1 + u1_offset_y) * u1_step + x + u1_offset_x] - u1[(y + u1_offset_y) * u1_step + x + u1_offset_x]; - - int src_x2 = (x + 1) < (u1_col - 1) ? (x + 1) : (u1_col - 1); - float u2x = u2[(y + u2_offset_y) * u2_step + src_x2 + u2_offset_x] - u2[(y + u2_offset_y) * u2_step + x + u2_offset_x]; - - int src_y2 = (y + 1) < (u1_row - 1) ? (y + 1) : (u1_row - 1); - float u2y = u2[(src_y2 + u2_offset_y) * u2_step + x + u2_offset_x] - u2[(y + u2_offset_y) * u2_step + x + u2_offset_x]; - - float g1 = hypot(u1x, u1y); - float g2 = hypot(u2x, u2y); - - float ng1 = 1.0f + taut * g1; - float ng2 = 1.0f + taut * g2; - - p11[y * p11_step + x] = (p11[y * p11_step + x] + taut * u1x) / ng1; - p12[y * p11_step + x] = (p12[y * p11_step + x] + taut * u1y) / ng1; - p21[y * p11_step + x] = (p21[y * p11_step + x] + taut * u2x) / ng2; - p22[y * p11_step + x] = (p22[y * p11_step + x] + taut * u2y) / ng2; - } - -} - -inline float divergence(__global const float* v1, __global const float* v2, int y, int x, int v1_step, int v2_step) -{ - - if (x > 0 && y > 0) - { - float v1x = v1[y * v1_step + x] - v1[y * v1_step + x - 1]; - float v2y = v2[y * v2_step + x] - v2[(y - 1) * v2_step + x]; - return v1x + v2y; - } - else - { - if (y > 0) - return v1[y * v1_step + 0] + v2[y * v2_step + 0] - v2[(y - 1) * v2_step + 0]; - else - { - if (x > 0) - return v1[0 * v1_step + x] - v1[0 * v1_step + x - 1] + v2[0 * v2_step + x]; - else - return v1[0 * v1_step + 0] + v2[0 * v2_step + 0]; - } - } - -} - -__kernel void estimateUKernel(__global const float* I1wx, int I1wx_col, int I1wx_row, int I1wx_step, - __global const float* I1wy, /*int I1wy_step,*/ - __global const float* grad, /*int grad_step,*/ - __global const float* rho_c, /*int rho_c_step,*/ - __global const float* p11, /*int p11_step,*/ - __global const float* p12, /*int p12_step,*/ - __global const float* p21, /*int p21_step,*/ - __global const float* p22, /*int p22_step,*/ - __global float* u1, int u1_step, - __global float* u2, - __global float* error, float l_t, float theta, int u2_step, - int u1_offset_x, - int u1_offset_y, - int u2_offset_x, - int u2_offset_y, - char calc_error) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if(x < I1wx_col && y < I1wx_row) - { - float I1wxVal = I1wx[y * I1wx_step + x]; - float I1wyVal = I1wy[y * I1wx_step + x]; - float gradVal = grad[y * I1wx_step + x]; - float u1OldVal = u1[(y + u1_offset_y) * u1_step + x + u1_offset_x]; - float u2OldVal = u2[(y + u2_offset_y) * u2_step + x + u2_offset_x]; - - float rho = rho_c[y * I1wx_step + x] + (I1wxVal * u1OldVal + I1wyVal * u2OldVal); - - // estimate the values of the variable (v1, v2) (thresholding operator TH) - - float d1 = 0.0f; - float d2 = 0.0f; - - if (rho < -l_t * gradVal) - { - d1 = l_t * I1wxVal; - d2 = l_t * I1wyVal; - } - else if (rho > l_t * gradVal) - { - d1 = -l_t * I1wxVal; - d2 = -l_t * I1wyVal; - } - else if (gradVal > 1.192092896e-07f) - { - float fi = -rho / gradVal; - d1 = fi * I1wxVal; - d2 = fi * I1wyVal; - } - - float v1 = u1OldVal + d1; - float v2 = u2OldVal + d2; - - // compute the divergence of the dual variable (p1, p2) - - float div_p1 = divergence(p11, p12, y, x, I1wx_step, I1wx_step); - float div_p2 = divergence(p21, p22, y, x, I1wx_step, I1wx_step); - - // estimate the values of the optical flow (u1, u2) - - float u1NewVal = v1 + theta * div_p1; - float u2NewVal = v2 + theta * div_p2; - - u1[(y + u1_offset_y) * u1_step + x + u1_offset_x] = u1NewVal; - u2[(y + u2_offset_y) * u2_step + x + u2_offset_x] = u2NewVal; - - if(calc_error) - { - float n1 = (u1OldVal - u1NewVal) * (u1OldVal - u1NewVal); - float n2 = (u2OldVal - u2NewVal) * (u2OldVal - u2NewVal); - error[y * I1wx_step + x] = n1 + n2; - } - } -} diff --git a/modules/ocl/src/optical_flow_farneback.cpp b/modules/ocl/src/optical_flow_farneback.cpp deleted file mode 100644 index 198f9106b..000000000 --- a/modules/ocl/src/optical_flow_farneback.cpp +++ /dev/null @@ -1,542 +0,0 @@ -/*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 -// Sen Liu, swjtuls1987@126.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 "precomp.hpp" -#include "opencl_kernels.hpp" -#include "opencv2/video/tracking.hpp" - -using namespace cv; -using namespace cv::ocl; - -#define MIN_SIZE 32 - -namespace cv { -namespace ocl { -namespace optflow_farneback -{ -oclMat g; -oclMat xg; -oclMat xxg; -oclMat gKer; - -float ig[4]; - -inline void setGaussianBlurKernel(const float *c_gKer, int ksizeHalf) -{ - cv::Mat t_gKer(1, ksizeHalf + 1, CV_32FC1, const_cast(c_gKer)); - gKer.upload(t_gKer); -} - -static void gaussianBlurOcl(const oclMat &src, int ksizeHalf, oclMat &dst) -{ - String kernelName("gaussianBlur"); -#ifdef ANDROID - size_t localThreads[3] = { 128, 1, 1 }; -#else - size_t localThreads[3] = { 256, 1, 1 }; -#endif - size_t globalThreads[3] = { src.cols, src.rows, 1 }; - int smem_size = (localThreads[0] + 2*ksizeHalf) * sizeof(float); - - CV_Assert(dst.size() == src.size()); - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&dst.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&src.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&gKer.data)); - args.push_back(std::make_pair(smem_size, (void *)NULL)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&ksizeHalf)); - - openCLExecuteKernel(Context::getContext(), &optical_flow_farneback, kernelName, - globalThreads, localThreads, args, -1, -1); -} - -static void polynomialExpansionOcl(const oclMat &src, int polyN, oclMat &dst) -{ - String kernelName("polynomialExpansion"); - -#ifdef ANDROID - size_t localThreads[3] = { 128, 1, 1 }; -#else - size_t localThreads[3] = { 256, 1, 1 }; -#endif - size_t globalThreads[3] = { divUp(src.cols, localThreads[0] - 2*polyN) * localThreads[0], src.rows, 1 }; - int smem_size = 3 * localThreads[0] * sizeof(float); - - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&dst.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&src.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&g.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&xg.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&xxg.data)); - args.push_back(std::make_pair(smem_size, (void *)NULL)); - args.push_back(std::make_pair(sizeof(cl_float4), (void *)&ig)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.step)); - - char opt [128]; - sprintf(opt, "-D polyN=%d", polyN); - - openCLExecuteKernel(Context::getContext(), &optical_flow_farneback, kernelName, - globalThreads, localThreads, args, -1, -1, opt); -} - -static void updateMatricesOcl(const oclMat &flowx, const oclMat &flowy, const oclMat &R0, const oclMat &R1, oclMat &M) -{ - String kernelName("updateMatrices"); -#ifdef ANDROID - size_t localThreads[3] = { 32, 4, 1 }; -#else - size_t localThreads[3] = { 32, 8, 1 }; -#endif - size_t globalThreads[3] = { flowx.cols, flowx.rows, 1 }; - - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&M.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&flowx.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&flowy.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&R0.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&R1.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&flowx.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&flowx.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&M.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&flowx.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&flowy.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&R0.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&R1.step)); - - openCLExecuteKernel(Context::getContext(), &optical_flow_farneback, kernelName, - globalThreads, localThreads, args, -1, -1); -} - -static void boxFilter5Ocl(const oclMat &src, int ksizeHalf, oclMat &dst) -{ - String kernelName("boxFilter5"); - int height = src.rows / 5; -#ifdef ANDROID - size_t localThreads[3] = { 128, 1, 1 }; -#else - size_t localThreads[3] = { 256, 1, 1 }; -#endif - size_t globalThreads[3] = { src.cols, height, 1 }; - int smem_size = (localThreads[0] + 2*ksizeHalf) * 5 * sizeof(float); - - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&dst.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&src.data)); - args.push_back(std::make_pair(smem_size, (void *)NULL)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&height)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&ksizeHalf)); - - openCLExecuteKernel(Context::getContext(), &optical_flow_farneback, kernelName, - globalThreads, localThreads, args, -1, -1); -} - -static void updateFlowOcl(const oclMat &M, oclMat &flowx, oclMat &flowy) -{ - String kernelName("updateFlow"); - int cols = divUp(flowx.cols, 4); -#ifdef ANDROID - size_t localThreads[3] = { 32, 4, 1 }; -#else - size_t localThreads[3] = { 32, 8, 1 }; -#endif - size_t globalThreads[3] = { cols, flowx.rows, 1 }; - - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&flowx.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&flowy.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&M.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&flowx.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&flowx.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&flowy.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&M.step)); - - openCLExecuteKernel(Context::getContext(), &optical_flow_farneback, kernelName, - globalThreads, localThreads, args, -1, -1); -} - -static void gaussianBlur5Ocl(const oclMat &src, int ksizeHalf, oclMat &dst) -{ - String kernelName("gaussianBlur5"); - int height = src.rows / 5; -#ifdef ANDROID - size_t localThreads[3] = { 128, 1, 1 }; -#else - size_t localThreads[3] = { 256, 1, 1 }; -#endif - size_t globalThreads[3] = { src.cols, height, 1 }; - int smem_size = (localThreads[0] + 2*ksizeHalf) * 5 * sizeof(float); - - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&dst.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&src.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&gKer.data)); - args.push_back(std::make_pair(smem_size, (void *)NULL)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&height)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&dst.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&src.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&ksizeHalf)); - - openCLExecuteKernel(Context::getContext(), &optical_flow_farneback, kernelName, - globalThreads, localThreads, args, -1, -1); -} -} -} -} // namespace cv { namespace ocl { namespace optflow_farneback - -static oclMat allocMatFromBuf(int rows, int cols, int type, oclMat &mat) -{ - if (!mat.empty() && mat.type() == type && mat.rows >= rows && mat.cols >= cols) - return mat(Rect(0, 0, cols, rows)); - return mat = oclMat(rows, cols, type); -} - -cv::ocl::FarnebackOpticalFlow::FarnebackOpticalFlow() -{ - numLevels = 5; - pyrScale = 0.5; - fastPyramids = false; - winSize = 13; - numIters = 10; - polyN = 5; - polySigma = 1.1; - flags = 0; -} - -void cv::ocl::FarnebackOpticalFlow::releaseMemory() -{ - frames_[0].release(); - frames_[1].release(); - pyrLevel_[0].release(); - pyrLevel_[1].release(); - M_.release(); - bufM_.release(); - R_[0].release(); - R_[1].release(); - blurredFrame_[0].release(); - blurredFrame_[1].release(); - pyramid0_.clear(); - pyramid1_.clear(); -} - -void cv::ocl::FarnebackOpticalFlow::prepareGaussian( - int n, double sigma, float *g, float *xg, float *xxg, - double &ig11, double &ig03, double &ig33, double &ig55) -{ - double s = 0.; - for (int x = -n; x <= n; x++) - { - g[x] = (float)std::exp(-x*x/(2*sigma*sigma)); - s += g[x]; - } - - s = 1./s; - for (int x = -n; x <= n; x++) - { - g[x] = (float)(g[x]*s); - xg[x] = (float)(x*g[x]); - xxg[x] = (float)(x*x*g[x]); - } - - Mat_ G(6, 6); - G.setTo(0); - - for (int y = -n; y <= n; y++) - { - for (int x = -n; x <= n; x++) - { - G(0,0) += g[y]*g[x]; - G(1,1) += g[y]*g[x]*x*x; - G(3,3) += g[y]*g[x]*x*x*x*x; - G(5,5) += g[y]*g[x]*x*x*y*y; - } - } - - //G[0][0] = 1.; - G(2,2) = G(0,3) = G(0,4) = G(3,0) = G(4,0) = G(1,1); - G(4,4) = G(3,3); - G(3,4) = G(4,3) = G(5,5); - - // invG: - // [ x e e ] - // [ y ] - // [ y ] - // [ e z ] - // [ e z ] - // [ u ] - Mat_ invG = G.inv(DECOMP_CHOLESKY); - - ig11 = invG(1,1); - ig03 = invG(0,3); - ig33 = invG(3,3); - ig55 = invG(5,5); -} - -void cv::ocl::FarnebackOpticalFlow::setPolynomialExpansionConsts(int n, double sigma) -{ - std::vector buf(n*6 + 3); - float* g = &buf[0] + n; - float* xg = g + n*2 + 1; - float* xxg = xg + n*2 + 1; - - if (sigma < FLT_EPSILON) - sigma = n*0.3; - - double ig11, ig03, ig33, ig55; - prepareGaussian(n, sigma, g, xg, xxg, ig11, ig03, ig33, ig55); - - cv::Mat t_g(1, n + 1, CV_32FC1, g); - cv::Mat t_xg(1, n + 1, CV_32FC1, xg); - cv::Mat t_xxg(1, n + 1, CV_32FC1, xxg); - - optflow_farneback::g.upload(t_g); - optflow_farneback::xg.upload(t_xg); - optflow_farneback::xxg.upload(t_xxg); - - optflow_farneback::ig[0] = static_cast(ig11); - optflow_farneback::ig[1] = static_cast(ig03); - optflow_farneback::ig[2] = static_cast(ig33); - optflow_farneback::ig[3] = static_cast(ig55); -} - -void cv::ocl::FarnebackOpticalFlow::updateFlow_boxFilter( - const oclMat& R0, const oclMat& R1, oclMat& flowx, oclMat &flowy, - oclMat& M, oclMat &bufM, int blockSize, bool updateMatrices) -{ - optflow_farneback::boxFilter5Ocl(M, blockSize/2, bufM); - - swap(M, bufM); - - optflow_farneback::updateFlowOcl(M, flowx, flowy); - - if (updateMatrices) - optflow_farneback::updateMatricesOcl(flowx, flowy, R0, R1, M); -} - - -void cv::ocl::FarnebackOpticalFlow::updateFlow_gaussianBlur( - const oclMat& R0, const oclMat& R1, oclMat& flowx, oclMat& flowy, - oclMat& M, oclMat &bufM, int blockSize, bool updateMatrices) -{ - optflow_farneback::gaussianBlur5Ocl(M, blockSize/2, bufM); - - swap(M, bufM); - - optflow_farneback::updateFlowOcl(M, flowx, flowy); - - if (updateMatrices) - optflow_farneback::updateMatricesOcl(flowx, flowy, R0, R1, M); -} - - -void cv::ocl::FarnebackOpticalFlow::operator ()( - const oclMat &frame0, const oclMat &frame1, oclMat &flowx, oclMat &flowy) -{ - CV_Assert(frame0.channels() == 1 && frame1.channels() == 1); - CV_Assert(frame0.size() == frame1.size()); - CV_Assert(polyN == 5 || polyN == 7); - CV_Assert(!fastPyramids || std::abs(pyrScale - 0.5) < 1e-6); - - Size size = frame0.size(); - oclMat prevFlowX, prevFlowY, curFlowX, curFlowY; - - flowx.create(size, CV_32F); - flowy.create(size, CV_32F); - oclMat flowx0 = flowx; - oclMat flowy0 = flowy; - - // Crop unnecessary levels - double scale = 1; - int numLevelsCropped = 0; - for (; numLevelsCropped < numLevels; numLevelsCropped++) - { - scale *= pyrScale; - if (size.width*scale < MIN_SIZE || size.height*scale < MIN_SIZE) - break; - } - - frame0.convertTo(frames_[0], CV_32F); - frame1.convertTo(frames_[1], CV_32F); - - if (fastPyramids) - { - // Build Gaussian pyramids using pyrDown() - pyramid0_.resize(numLevelsCropped + 1); - pyramid1_.resize(numLevelsCropped + 1); - pyramid0_[0] = frames_[0]; - pyramid1_[0] = frames_[1]; - for (int i = 1; i <= numLevelsCropped; ++i) - { - pyrDown(pyramid0_[i - 1], pyramid0_[i]); - pyrDown(pyramid1_[i - 1], pyramid1_[i]); - } - } - - setPolynomialExpansionConsts(polyN, polySigma); - - for (int k = numLevelsCropped; k >= 0; k--) - { - scale = 1; - for (int i = 0; i < k; i++) - scale *= pyrScale; - - double sigma = (1./scale - 1) * 0.5; - int smoothSize = cvRound(sigma*5) | 1; - smoothSize = std::max(smoothSize, 3); - - int width = cvRound(size.width*scale); - int height = cvRound(size.height*scale); - - if (fastPyramids) - { - width = pyramid0_[k].cols; - height = pyramid0_[k].rows; - } - - if (k > 0) - { - curFlowX.create(height, width, CV_32F); - curFlowY.create(height, width, CV_32F); - } - else - { - curFlowX = flowx0; - curFlowY = flowy0; - } - - if (!prevFlowX.data) - { - if (flags & cv::OPTFLOW_USE_INITIAL_FLOW) - { - resize(flowx0, curFlowX, Size(width, height), 0, 0, INTER_LINEAR); - resize(flowy0, curFlowY, Size(width, height), 0, 0, INTER_LINEAR); - multiply(scale, curFlowX, curFlowX); - multiply(scale, curFlowY, curFlowY); - } - else - { - curFlowX.setTo(0); - curFlowY.setTo(0); - } - } - else - { - resize(prevFlowX, curFlowX, Size(width, height), 0, 0, INTER_LINEAR); - resize(prevFlowY, curFlowY, Size(width, height), 0, 0, INTER_LINEAR); - multiply(1./pyrScale, curFlowX, curFlowX); - multiply(1./pyrScale, curFlowY, curFlowY); - } - - oclMat M = allocMatFromBuf(5*height, width, CV_32F, M_); - oclMat bufM = allocMatFromBuf(5*height, width, CV_32F, bufM_); - oclMat R[2] = - { - allocMatFromBuf(5*height, width, CV_32F, R_[0]), - allocMatFromBuf(5*height, width, CV_32F, R_[1]) - }; - - if (fastPyramids) - { - optflow_farneback::polynomialExpansionOcl(pyramid0_[k], polyN, R[0]); - optflow_farneback::polynomialExpansionOcl(pyramid1_[k], polyN, R[1]); - } - else - { - oclMat blurredFrame[2] = - { - allocMatFromBuf(size.height, size.width, CV_32F, blurredFrame_[0]), - allocMatFromBuf(size.height, size.width, CV_32F, blurredFrame_[1]) - }; - oclMat pyrLevel[2] = - { - allocMatFromBuf(height, width, CV_32F, pyrLevel_[0]), - allocMatFromBuf(height, width, CV_32F, pyrLevel_[1]) - }; - - Mat g = getGaussianKernel(smoothSize, sigma, CV_32F); - optflow_farneback::setGaussianBlurKernel(g.ptr(smoothSize/2), smoothSize/2); - - for (int i = 0; i < 2; i++) - { - optflow_farneback::gaussianBlurOcl(frames_[i], smoothSize/2, blurredFrame[i]); - resize(blurredFrame[i], pyrLevel[i], Size(width, height), INTER_LINEAR); - optflow_farneback::polynomialExpansionOcl(pyrLevel[i], polyN, R[i]); - } - } - - optflow_farneback::updateMatricesOcl(curFlowX, curFlowY, R[0], R[1], M); - - if (flags & OPTFLOW_FARNEBACK_GAUSSIAN) - { - Mat g = getGaussianKernel(winSize, winSize/2*0.3f, CV_32F); - optflow_farneback::setGaussianBlurKernel(g.ptr(winSize/2), winSize/2); - } - for (int i = 0; i < numIters; i++) - { - if (flags & OPTFLOW_FARNEBACK_GAUSSIAN) - updateFlow_gaussianBlur(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize, i < numIters-1); - else - updateFlow_boxFilter(R[0], R[1], curFlowX, curFlowY, M, bufM, winSize, i < numIters-1); - } - - prevFlowX = curFlowX; - prevFlowY = curFlowY; - } - - flowx = curFlowX; - flowy = curFlowY; -} diff --git a/modules/ocl/src/orb.cpp b/modules/ocl/src/orb.cpp deleted file mode 100644 index 4bd022c8d..000000000 --- a/modules/ocl/src/orb.cpp +++ /dev/null @@ -1,916 +0,0 @@ -/*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. -// -// Authors: -// * Peter Andreas Entschev, peter@entschev.com -// -//M*/ - -#include "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -namespace -{ - const float HARRIS_K = 0.04f; - const int DESCRIPTOR_SIZE = 32; - - const int bit_pattern_31_[256 * 4] = - { - 8,-3, 9,5/*mean (0), correlation (0)*/, - 4,2, 7,-12/*mean (1.12461e-05), correlation (0.0437584)*/, - -11,9, -8,2/*mean (3.37382e-05), correlation (0.0617409)*/, - 7,-12, 12,-13/*mean (5.62303e-05), correlation (0.0636977)*/, - 2,-13, 2,12/*mean (0.000134953), correlation (0.085099)*/, - 1,-7, 1,6/*mean (0.000528565), correlation (0.0857175)*/, - -2,-10, -2,-4/*mean (0.0188821), correlation (0.0985774)*/, - -13,-13, -11,-8/*mean (0.0363135), correlation (0.0899616)*/, - -13,-3, -12,-9/*mean (0.121806), correlation (0.099849)*/, - 10,4, 11,9/*mean (0.122065), correlation (0.093285)*/, - -13,-8, -8,-9/*mean (0.162787), correlation (0.0942748)*/, - -11,7, -9,12/*mean (0.21561), correlation (0.0974438)*/, - 7,7, 12,6/*mean (0.160583), correlation (0.130064)*/, - -4,-5, -3,0/*mean (0.228171), correlation (0.132998)*/, - -13,2, -12,-3/*mean (0.00997526), correlation (0.145926)*/, - -9,0, -7,5/*mean (0.198234), correlation (0.143636)*/, - 12,-6, 12,-1/*mean (0.0676226), correlation (0.16689)*/, - -3,6, -2,12/*mean (0.166847), correlation (0.171682)*/, - -6,-13, -4,-8/*mean (0.101215), correlation (0.179716)*/, - 11,-13, 12,-8/*mean (0.200641), correlation (0.192279)*/, - 4,7, 5,1/*mean (0.205106), correlation (0.186848)*/, - 5,-3, 10,-3/*mean (0.234908), correlation (0.192319)*/, - 3,-7, 6,12/*mean (0.0709964), correlation (0.210872)*/, - -8,-7, -6,-2/*mean (0.0939834), correlation (0.212589)*/, - -2,11, -1,-10/*mean (0.127778), correlation (0.20866)*/, - -13,12, -8,10/*mean (0.14783), correlation (0.206356)*/, - -7,3, -5,-3/*mean (0.182141), correlation (0.198942)*/, - -4,2, -3,7/*mean (0.188237), correlation (0.21384)*/, - -10,-12, -6,11/*mean (0.14865), correlation (0.23571)*/, - 5,-12, 6,-7/*mean (0.222312), correlation (0.23324)*/, - 5,-6, 7,-1/*mean (0.229082), correlation (0.23389)*/, - 1,0, 4,-5/*mean (0.241577), correlation (0.215286)*/, - 9,11, 11,-13/*mean (0.00338507), correlation (0.251373)*/, - 4,7, 4,12/*mean (0.131005), correlation (0.257622)*/, - 2,-1, 4,4/*mean (0.152755), correlation (0.255205)*/, - -4,-12, -2,7/*mean (0.182771), correlation (0.244867)*/, - -8,-5, -7,-10/*mean (0.186898), correlation (0.23901)*/, - 4,11, 9,12/*mean (0.226226), correlation (0.258255)*/, - 0,-8, 1,-13/*mean (0.0897886), correlation (0.274827)*/, - -13,-2, -8,2/*mean (0.148774), correlation (0.28065)*/, - -3,-2, -2,3/*mean (0.153048), correlation (0.283063)*/, - -6,9, -4,-9/*mean (0.169523), correlation (0.278248)*/, - 8,12, 10,7/*mean (0.225337), correlation (0.282851)*/, - 0,9, 1,3/*mean (0.226687), correlation (0.278734)*/, - 7,-5, 11,-10/*mean (0.00693882), correlation (0.305161)*/, - -13,-6, -11,0/*mean (0.0227283), correlation (0.300181)*/, - 10,7, 12,1/*mean (0.125517), correlation (0.31089)*/, - -6,-3, -6,12/*mean (0.131748), correlation (0.312779)*/, - 10,-9, 12,-4/*mean (0.144827), correlation (0.292797)*/, - -13,8, -8,-12/*mean (0.149202), correlation (0.308918)*/, - -13,0, -8,-4/*mean (0.160909), correlation (0.310013)*/, - 3,3, 7,8/*mean (0.177755), correlation (0.309394)*/, - 5,7, 10,-7/*mean (0.212337), correlation (0.310315)*/, - -1,7, 1,-12/*mean (0.214429), correlation (0.311933)*/, - 3,-10, 5,6/*mean (0.235807), correlation (0.313104)*/, - 2,-4, 3,-10/*mean (0.00494827), correlation (0.344948)*/, - -13,0, -13,5/*mean (0.0549145), correlation (0.344675)*/, - -13,-7, -12,12/*mean (0.103385), correlation (0.342715)*/, - -13,3, -11,8/*mean (0.134222), correlation (0.322922)*/, - -7,12, -4,7/*mean (0.153284), correlation (0.337061)*/, - 6,-10, 12,8/*mean (0.154881), correlation (0.329257)*/, - -9,-1, -7,-6/*mean (0.200967), correlation (0.33312)*/, - -2,-5, 0,12/*mean (0.201518), correlation (0.340635)*/, - -12,5, -7,5/*mean (0.207805), correlation (0.335631)*/, - 3,-10, 8,-13/*mean (0.224438), correlation (0.34504)*/, - -7,-7, -4,5/*mean (0.239361), correlation (0.338053)*/, - -3,-2, -1,-7/*mean (0.240744), correlation (0.344322)*/, - 2,9, 5,-11/*mean (0.242949), correlation (0.34145)*/, - -11,-13, -5,-13/*mean (0.244028), correlation (0.336861)*/, - -1,6, 0,-1/*mean (0.247571), correlation (0.343684)*/, - 5,-3, 5,2/*mean (0.000697256), correlation (0.357265)*/, - -4,-13, -4,12/*mean (0.00213675), correlation (0.373827)*/, - -9,-6, -9,6/*mean (0.0126856), correlation (0.373938)*/, - -12,-10, -8,-4/*mean (0.0152497), correlation (0.364237)*/, - 10,2, 12,-3/*mean (0.0299933), correlation (0.345292)*/, - 7,12, 12,12/*mean (0.0307242), correlation (0.366299)*/, - -7,-13, -6,5/*mean (0.0534975), correlation (0.368357)*/, - -4,9, -3,4/*mean (0.099865), correlation (0.372276)*/, - 7,-1, 12,2/*mean (0.117083), correlation (0.364529)*/, - -7,6, -5,1/*mean (0.126125), correlation (0.369606)*/, - -13,11, -12,5/*mean (0.130364), correlation (0.358502)*/, - -3,7, -2,-6/*mean (0.131691), correlation (0.375531)*/, - 7,-8, 12,-7/*mean (0.160166), correlation (0.379508)*/, - -13,-7, -11,-12/*mean (0.167848), correlation (0.353343)*/, - 1,-3, 12,12/*mean (0.183378), correlation (0.371916)*/, - 2,-6, 3,0/*mean (0.228711), correlation (0.371761)*/, - -4,3, -2,-13/*mean (0.247211), correlation (0.364063)*/, - -1,-13, 1,9/*mean (0.249325), correlation (0.378139)*/, - 7,1, 8,-6/*mean (0.000652272), correlation (0.411682)*/, - 1,-1, 3,12/*mean (0.00248538), correlation (0.392988)*/, - 9,1, 12,6/*mean (0.0206815), correlation (0.386106)*/, - -1,-9, -1,3/*mean (0.0364485), correlation (0.410752)*/, - -13,-13, -10,5/*mean (0.0376068), correlation (0.398374)*/, - 7,7, 10,12/*mean (0.0424202), correlation (0.405663)*/, - 12,-5, 12,9/*mean (0.0942645), correlation (0.410422)*/, - 6,3, 7,11/*mean (0.1074), correlation (0.413224)*/, - 5,-13, 6,10/*mean (0.109256), correlation (0.408646)*/, - 2,-12, 2,3/*mean (0.131691), correlation (0.416076)*/, - 3,8, 4,-6/*mean (0.165081), correlation (0.417569)*/, - 2,6, 12,-13/*mean (0.171874), correlation (0.408471)*/, - 9,-12, 10,3/*mean (0.175146), correlation (0.41296)*/, - -8,4, -7,9/*mean (0.183682), correlation (0.402956)*/, - -11,12, -4,-6/*mean (0.184672), correlation (0.416125)*/, - 1,12, 2,-8/*mean (0.191487), correlation (0.386696)*/, - 6,-9, 7,-4/*mean (0.192668), correlation (0.394771)*/, - 2,3, 3,-2/*mean (0.200157), correlation (0.408303)*/, - 6,3, 11,0/*mean (0.204588), correlation (0.411762)*/, - 3,-3, 8,-8/*mean (0.205904), correlation (0.416294)*/, - 7,8, 9,3/*mean (0.213237), correlation (0.409306)*/, - -11,-5, -6,-4/*mean (0.243444), correlation (0.395069)*/, - -10,11, -5,10/*mean (0.247672), correlation (0.413392)*/, - -5,-8, -3,12/*mean (0.24774), correlation (0.411416)*/, - -10,5, -9,0/*mean (0.00213675), correlation (0.454003)*/, - 8,-1, 12,-6/*mean (0.0293635), correlation (0.455368)*/, - 4,-6, 6,-11/*mean (0.0404971), correlation (0.457393)*/, - -10,12, -8,7/*mean (0.0481107), correlation (0.448364)*/, - 4,-2, 6,7/*mean (0.050641), correlation (0.455019)*/, - -2,0, -2,12/*mean (0.0525978), correlation (0.44338)*/, - -5,-8, -5,2/*mean (0.0629667), correlation (0.457096)*/, - 7,-6, 10,12/*mean (0.0653846), correlation (0.445623)*/, - -9,-13, -8,-8/*mean (0.0858749), correlation (0.449789)*/, - -5,-13, -5,-2/*mean (0.122402), correlation (0.450201)*/, - 8,-8, 9,-13/*mean (0.125416), correlation (0.453224)*/, - -9,-11, -9,0/*mean (0.130128), correlation (0.458724)*/, - 1,-8, 1,-2/*mean (0.132467), correlation (0.440133)*/, - 7,-4, 9,1/*mean (0.132692), correlation (0.454)*/, - -2,1, -1,-4/*mean (0.135695), correlation (0.455739)*/, - 11,-6, 12,-11/*mean (0.142904), correlation (0.446114)*/, - -12,-9, -6,4/*mean (0.146165), correlation (0.451473)*/, - 3,7, 7,12/*mean (0.147627), correlation (0.456643)*/, - 5,5, 10,8/*mean (0.152901), correlation (0.455036)*/, - 0,-4, 2,8/*mean (0.167083), correlation (0.459315)*/, - -9,12, -5,-13/*mean (0.173234), correlation (0.454706)*/, - 0,7, 2,12/*mean (0.18312), correlation (0.433855)*/, - -1,2, 1,7/*mean (0.185504), correlation (0.443838)*/, - 5,11, 7,-9/*mean (0.185706), correlation (0.451123)*/, - 3,5, 6,-8/*mean (0.188968), correlation (0.455808)*/, - -13,-4, -8,9/*mean (0.191667), correlation (0.459128)*/, - -5,9, -3,-3/*mean (0.193196), correlation (0.458364)*/, - -4,-7, -3,-12/*mean (0.196536), correlation (0.455782)*/, - 6,5, 8,0/*mean (0.1972), correlation (0.450481)*/, - -7,6, -6,12/*mean (0.199438), correlation (0.458156)*/, - -13,6, -5,-2/*mean (0.211224), correlation (0.449548)*/, - 1,-10, 3,10/*mean (0.211718), correlation (0.440606)*/, - 4,1, 8,-4/*mean (0.213034), correlation (0.443177)*/, - -2,-2, 2,-13/*mean (0.234334), correlation (0.455304)*/, - 2,-12, 12,12/*mean (0.235684), correlation (0.443436)*/, - -2,-13, 0,-6/*mean (0.237674), correlation (0.452525)*/, - 4,1, 9,3/*mean (0.23962), correlation (0.444824)*/, - -6,-10, -3,-5/*mean (0.248459), correlation (0.439621)*/, - -3,-13, -1,1/*mean (0.249505), correlation (0.456666)*/, - 7,5, 12,-11/*mean (0.00119208), correlation (0.495466)*/, - 4,-2, 5,-7/*mean (0.00372245), correlation (0.484214)*/, - -13,9, -9,-5/*mean (0.00741116), correlation (0.499854)*/, - 7,1, 8,6/*mean (0.0208952), correlation (0.499773)*/, - 7,-8, 7,6/*mean (0.0220085), correlation (0.501609)*/, - -7,-4, -7,1/*mean (0.0233806), correlation (0.496568)*/, - -8,11, -7,-8/*mean (0.0236505), correlation (0.489719)*/, - -13,6, -12,-8/*mean (0.0268781), correlation (0.503487)*/, - 2,4, 3,9/*mean (0.0323324), correlation (0.501938)*/, - 10,-5, 12,3/*mean (0.0399235), correlation (0.494029)*/, - -6,-5, -6,7/*mean (0.0420153), correlation (0.486579)*/, - 8,-3, 9,-8/*mean (0.0548021), correlation (0.484237)*/, - 2,-12, 2,8/*mean (0.0616622), correlation (0.496642)*/, - -11,-2, -10,3/*mean (0.0627755), correlation (0.498563)*/, - -12,-13, -7,-9/*mean (0.0829622), correlation (0.495491)*/, - -11,0, -10,-5/*mean (0.0843342), correlation (0.487146)*/, - 5,-3, 11,8/*mean (0.0929937), correlation (0.502315)*/, - -2,-13, -1,12/*mean (0.113327), correlation (0.48941)*/, - -1,-8, 0,9/*mean (0.132119), correlation (0.467268)*/, - -13,-11, -12,-5/*mean (0.136269), correlation (0.498771)*/, - -10,-2, -10,11/*mean (0.142173), correlation (0.498714)*/, - -3,9, -2,-13/*mean (0.144141), correlation (0.491973)*/, - 2,-3, 3,2/*mean (0.14892), correlation (0.500782)*/, - -9,-13, -4,0/*mean (0.150371), correlation (0.498211)*/, - -4,6, -3,-10/*mean (0.152159), correlation (0.495547)*/, - -4,12, -2,-7/*mean (0.156152), correlation (0.496925)*/, - -6,-11, -4,9/*mean (0.15749), correlation (0.499222)*/, - 6,-3, 6,11/*mean (0.159211), correlation (0.503821)*/, - -13,11, -5,5/*mean (0.162427), correlation (0.501907)*/, - 11,11, 12,6/*mean (0.16652), correlation (0.497632)*/, - 7,-5, 12,-2/*mean (0.169141), correlation (0.484474)*/, - -1,12, 0,7/*mean (0.169456), correlation (0.495339)*/, - -4,-8, -3,-2/*mean (0.171457), correlation (0.487251)*/, - -7,1, -6,7/*mean (0.175), correlation (0.500024)*/, - -13,-12, -8,-13/*mean (0.175866), correlation (0.497523)*/, - -7,-2, -6,-8/*mean (0.178273), correlation (0.501854)*/, - -8,5, -6,-9/*mean (0.181107), correlation (0.494888)*/, - -5,-1, -4,5/*mean (0.190227), correlation (0.482557)*/, - -13,7, -8,10/*mean (0.196739), correlation (0.496503)*/, - 1,5, 5,-13/*mean (0.19973), correlation (0.499759)*/, - 1,0, 10,-13/*mean (0.204465), correlation (0.49873)*/, - 9,12, 10,-1/*mean (0.209334), correlation (0.49063)*/, - 5,-8, 10,-9/*mean (0.211134), correlation (0.503011)*/, - -1,11, 1,-13/*mean (0.212), correlation (0.499414)*/, - -9,-3, -6,2/*mean (0.212168), correlation (0.480739)*/, - -1,-10, 1,12/*mean (0.212731), correlation (0.502523)*/, - -13,1, -8,-10/*mean (0.21327), correlation (0.489786)*/, - 8,-11, 10,-6/*mean (0.214159), correlation (0.488246)*/, - 2,-13, 3,-6/*mean (0.216993), correlation (0.50287)*/, - 7,-13, 12,-9/*mean (0.223639), correlation (0.470502)*/, - -10,-10, -5,-7/*mean (0.224089), correlation (0.500852)*/, - -10,-8, -8,-13/*mean (0.228666), correlation (0.502629)*/, - 4,-6, 8,5/*mean (0.22906), correlation (0.498305)*/, - 3,12, 8,-13/*mean (0.233378), correlation (0.503825)*/, - -4,2, -3,-3/*mean (0.234323), correlation (0.476692)*/, - 5,-13, 10,-12/*mean (0.236392), correlation (0.475462)*/, - 4,-13, 5,-1/*mean (0.236842), correlation (0.504132)*/, - -9,9, -4,3/*mean (0.236977), correlation (0.497739)*/, - 0,3, 3,-9/*mean (0.24314), correlation (0.499398)*/, - -12,1, -6,1/*mean (0.243297), correlation (0.489447)*/, - 3,2, 4,-8/*mean (0.00155196), correlation (0.553496)*/, - -10,-10, -10,9/*mean (0.00239541), correlation (0.54297)*/, - 8,-13, 12,12/*mean (0.0034413), correlation (0.544361)*/, - -8,-12, -6,-5/*mean (0.003565), correlation (0.551225)*/, - 2,2, 3,7/*mean (0.00835583), correlation (0.55285)*/, - 10,6, 11,-8/*mean (0.00885065), correlation (0.540913)*/, - 6,8, 8,-12/*mean (0.0101552), correlation (0.551085)*/, - -7,10, -6,5/*mean (0.0102227), correlation (0.533635)*/, - -3,-9, -3,9/*mean (0.0110211), correlation (0.543121)*/, - -1,-13, -1,5/*mean (0.0113473), correlation (0.550173)*/, - -3,-7, -3,4/*mean (0.0140913), correlation (0.554774)*/, - -8,-2, -8,3/*mean (0.017049), correlation (0.55461)*/, - 4,2, 12,12/*mean (0.01778), correlation (0.546921)*/, - 2,-5, 3,11/*mean (0.0224022), correlation (0.549667)*/, - 6,-9, 11,-13/*mean (0.029161), correlation (0.546295)*/, - 3,-1, 7,12/*mean (0.0303081), correlation (0.548599)*/, - 11,-1, 12,4/*mean (0.0355151), correlation (0.523943)*/, - -3,0, -3,6/*mean (0.0417904), correlation (0.543395)*/, - 4,-11, 4,12/*mean (0.0487292), correlation (0.542818)*/, - 2,-4, 2,1/*mean (0.0575124), correlation (0.554888)*/, - -10,-6, -8,1/*mean (0.0594242), correlation (0.544026)*/, - -13,7, -11,1/*mean (0.0597391), correlation (0.550524)*/, - -13,12, -11,-13/*mean (0.0608974), correlation (0.55383)*/, - 6,0, 11,-13/*mean (0.065126), correlation (0.552006)*/, - 0,-1, 1,4/*mean (0.074224), correlation (0.546372)*/, - -13,3, -9,-2/*mean (0.0808592), correlation (0.554875)*/, - -9,8, -6,-3/*mean (0.0883378), correlation (0.551178)*/, - -13,-6, -8,-2/*mean (0.0901035), correlation (0.548446)*/, - 5,-9, 8,10/*mean (0.0949843), correlation (0.554694)*/, - 2,7, 3,-9/*mean (0.0994152), correlation (0.550979)*/, - -1,-6, -1,-1/*mean (0.10045), correlation (0.552714)*/, - 9,5, 11,-2/*mean (0.100686), correlation (0.552594)*/, - 11,-3, 12,-8/*mean (0.101091), correlation (0.532394)*/, - 3,0, 3,5/*mean (0.101147), correlation (0.525576)*/, - -1,4, 0,10/*mean (0.105263), correlation (0.531498)*/, - 3,-6, 4,5/*mean (0.110785), correlation (0.540491)*/, - -13,0, -10,5/*mean (0.112798), correlation (0.536582)*/, - 5,8, 12,11/*mean (0.114181), correlation (0.555793)*/, - 8,9, 9,-6/*mean (0.117431), correlation (0.553763)*/, - 7,-4, 8,-12/*mean (0.118522), correlation (0.553452)*/, - -10,4, -10,9/*mean (0.12094), correlation (0.554785)*/, - 7,3, 12,4/*mean (0.122582), correlation (0.555825)*/, - 9,-7, 10,-2/*mean (0.124978), correlation (0.549846)*/, - 7,0, 12,-2/*mean (0.127002), correlation (0.537452)*/, - -1,-6, 0,-11/*mean (0.127148), correlation (0.547401)*/ - }; - - void initializeOrbPattern(const Point* pattern0, Mat& pattern, int ntuples, int tupleSize, int poolSize) - { - RNG rng(0x12345678); - - pattern.create(2, ntuples * tupleSize, CV_32SC1); - pattern.setTo(Scalar::all(0)); - - int* pattern_x_ptr = pattern.ptr(0); - int* pattern_y_ptr = pattern.ptr(1); - - for (int i = 0; i < ntuples; i++) - { - for (int k = 0; k < tupleSize; k++) - { - for(;;) - { - int idx = rng.uniform(0, poolSize); - Point pt = pattern0[idx]; - - int k1; - for (k1 = 0; k1 < k; k1++) - if (pattern_x_ptr[tupleSize * i + k1] == pt.x && pattern_y_ptr[tupleSize * i + k1] == pt.y) - break; - - if (k1 == k) - { - pattern_x_ptr[tupleSize * i + k] = pt.x; - pattern_y_ptr[tupleSize * i + k] = pt.y; - break; - } - } - } - } - } - - void makeRandomPattern(int patchSize, Point* pattern, int npoints) - { - // we always start with a fixed seed, - // to make patterns the same on each run - RNG rng(0x34985739); - - for (int i = 0; i < npoints; i++) - { - pattern[i].x = rng.uniform(-patchSize / 2, patchSize / 2 + 1); - pattern[i].y = rng.uniform(-patchSize / 2, patchSize / 2 + 1); - } - } -} - -cv::ocl::ORB_OCL::ORB_OCL(int nFeatures, float scaleFactor, int nLevels, int edgeThreshold, int firstLevel, int WTA_K, int scoreType, int patchSize) : - nFeatures_(nFeatures), scaleFactor_(scaleFactor), nLevels_(nLevels), edgeThreshold_(edgeThreshold), firstLevel_(firstLevel), WTA_K_(WTA_K), - scoreType_(scoreType), patchSize_(patchSize), - fastDetector_(DEFAULT_FAST_THRESHOLD) -{ - CV_Assert(patchSize_ >= 2); - - // fill the extractors and descriptors for the corresponding scales - float factor = 1.0f / scaleFactor_; - float n_desired_features_per_scale = nFeatures_ * (1.0f - factor) / (1.0f - std::pow(factor, nLevels_)); - - n_features_per_level_.resize(nLevels_); - size_t sum_n_features = 0; - for (int level = 0; level < nLevels_ - 1; ++level) - { - n_features_per_level_[level] = cvRound(n_desired_features_per_scale); - sum_n_features += n_features_per_level_[level]; - n_desired_features_per_scale *= factor; - } - n_features_per_level_[nLevels_ - 1] = nFeatures - sum_n_features; - - // pre-compute the end of a row in a circular patch - int half_patch_size = patchSize_ / 2; - std::vector u_max(half_patch_size + 2); - for (int v = 0; v <= half_patch_size * std::sqrt(2.f) / 2 + 1; ++v) - u_max[v] = cvRound(std::sqrt(static_cast(half_patch_size * half_patch_size - v * v))); - - // Make sure we are symmetric - for (int v = half_patch_size, v_0 = 0; v >= half_patch_size * std::sqrt(2.f) / 2; --v) - { - while (u_max[v_0] == u_max[v_0 + 1]) - ++v_0; - u_max[v] = v_0; - ++v_0; - } - CV_Assert(u_max.size() < 32); - //cv::cuda::device::orb::loadUMax(&u_max[0], static_cast(u_max.size())); - uMax_ = oclMat(1, u_max.size(), CV_32SC1, &u_max[0]); - - // Calc pattern - const int npoints = 512; - Point pattern_buf[npoints]; - const Point* pattern0 = (const Point*)bit_pattern_31_; - if (patchSize_ != 31) - { - pattern0 = pattern_buf; - makeRandomPattern(patchSize_, pattern_buf, npoints); - } - - CV_Assert(WTA_K_ == 2 || WTA_K_ == 3 || WTA_K_ == 4); - - Mat h_pattern; - - if (WTA_K_ == 2) - { - h_pattern.create(2, npoints, CV_32SC1); - - int* pattern_x_ptr = h_pattern.ptr(0); - int* pattern_y_ptr = h_pattern.ptr(1); - - for (int i = 0; i < npoints; ++i) - { - pattern_x_ptr[i] = pattern0[i].x; - pattern_y_ptr[i] = pattern0[i].y; - } - } - else - { - int ntuples = descriptorSize() * 4; - initializeOrbPattern(pattern0, h_pattern, ntuples, WTA_K_, npoints); - } - - pattern_.upload(h_pattern); - - //blurFilter = ocl::createGaussianFilter(CV_8UC1, -1, Size(7, 7), 2, 2, BORDER_REFLECT_101); - blurFilter = ocl::createGaussianFilter_GPU(CV_8UC1, Size(7, 7), 2, 2, BORDER_REFLECT_101); - - blurForDescriptor = true; -} - -namespace -{ - inline float getScale(float scaleFactor, int firstLevel, int level) - { - return pow(scaleFactor, level - firstLevel); - } -} - -void cv::ocl::ORB_OCL::buildScalePyramids(const oclMat& image, const oclMat& mask) -{ - CV_Assert(image.type() == CV_8UC1); - CV_Assert(mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size())); - - imagePyr_.resize(nLevels_); - maskPyr_.resize(nLevels_); - - for (int level = 0; level < nLevels_; ++level) - { - float scale = 1.0f / getScale(scaleFactor_, firstLevel_, level); - - Size sz(cvRound(image.cols * scale), cvRound(image.rows * scale)); - - ensureSizeIsEnough(sz, image.type(), imagePyr_[level]); - ensureSizeIsEnough(sz, CV_8UC1, maskPyr_[level]); - maskPyr_[level].setTo(Scalar::all(255)); - - // Compute the resized image - if (level != firstLevel_) - { - if (level < firstLevel_) - { - ocl::resize(image, imagePyr_[level], sz, 0, 0, INTER_LINEAR); - - if (!mask.empty()) - ocl::resize(mask, maskPyr_[level], sz, 0, 0, INTER_LINEAR); - } - else - { - ocl::resize(imagePyr_[level - 1], imagePyr_[level], sz, 0, 0, INTER_LINEAR); - - if (!mask.empty()) - { - ocl::resize(maskPyr_[level - 1], maskPyr_[level], sz, 0, 0, INTER_LINEAR); - ocl::threshold(maskPyr_[level], maskPyr_[level], 254, 0, THRESH_TOZERO); - } - } - } - else - { - image.copyTo(imagePyr_[level]); - - if (!mask.empty()) - mask.copyTo(maskPyr_[level]); - } - - // Filter keypoints by image border - ensureSizeIsEnough(sz, CV_8UC1, buf_); - buf_.setTo(Scalar::all(0)); - Rect inner(edgeThreshold_, edgeThreshold_, sz.width - 2 * edgeThreshold_, sz.height - 2 * edgeThreshold_); - buf_(inner).setTo(Scalar::all(255)); - - ocl::bitwise_and(maskPyr_[level], buf_, maskPyr_[level]); - } -} - -static void HarrisResponses_OCL(const oclMat& img, oclMat& keypoints, const int npoints, int blockSize, float harris_k) -{ - size_t localThreads[3] = {32, 8, 1}; - size_t globalThreads[3] = {divUp(npoints, localThreads[1]) * localThreads[1] * localThreads[0], - 1, - 1}; - - Context *clCxt = Context::getContext(); - String kernelName = "HarrisResponses"; - std::vector< std::pair > args; - - int imgStep = img.step / img.elemSize(); - int keypointsStep = keypoints.step / keypoints.elemSize(); - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&img.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&keypoints.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&npoints)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&blockSize)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&harris_k)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&imgStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&keypointsStep)); - - bool is_cpu = isCpuDevice(); - if (is_cpu) - openCLExecuteKernel(clCxt, &orb, kernelName, globalThreads, localThreads, args, -1, -1, (char*)"-D CPU"); - else - { - cl_kernel kernel = openCLGetKernelFromSource(Context::getContext(), &orb, kernelName); - int wave_size = (int)queryWaveFrontSize(kernel); - openCLSafeCall(clReleaseKernel(kernel)); - - std::string opt = format("-D WAVE_SIZE=%d", wave_size); - openCLExecuteKernel(Context::getContext(), &orb, kernelName, globalThreads, localThreads, args, -1, -1, opt.c_str()); - } -} - -static void IC_Angle_OCL(const oclMat& image, oclMat& keypoints, const oclMat& uMax, int npoints, int half_k) -{ - size_t localThreads[3] = {32, 8, 1}; - size_t globalThreads[3] = {divUp(npoints, localThreads[1]) * localThreads[1] * localThreads[0], - 1, - 1}; - - Context *clCxt = Context::getContext(); - String kernelName = "IC_Angle"; - std::vector< std::pair > args; - - int imageStep = image.step / image.elemSize(); - int keypointsStep = keypoints.step / keypoints.elemSize(); - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&image.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&keypoints.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&uMax.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&npoints)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&half_k)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&imageStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&keypointsStep)); - - bool is_cpu = isCpuDevice(); - if (is_cpu) - openCLExecuteKernel(clCxt, &orb, kernelName, globalThreads, localThreads, args, -1, -1, (char*)"-D CPU"); - else - { - cl_kernel kernel = openCLGetKernelFromSource(Context::getContext(), &orb, kernelName); - int wave_size = (int)queryWaveFrontSize(kernel); - openCLSafeCall(clReleaseKernel(kernel)); - - std::string opt = format("-D WAVE_SIZE=%d", wave_size); - openCLExecuteKernel(Context::getContext(), &orb, kernelName, globalThreads, localThreads, args, -1, -1, opt.c_str()); - } -} - -static void convertRowsToChannels_OCL(const oclMat& keypointsIn, oclMat& keypointsOut, int npoints) -{ - size_t localThreads[3] = {256, 1, 1}; - size_t globalThreads[3] = {divUp(npoints, localThreads[0]) * localThreads[0], - 1, - 1}; - - Context *clCxt = Context::getContext(); - String kernelName = "convertRowsToChannels"; - std::vector< std::pair > args; - - int keypointsInStep = keypointsIn.step / keypointsIn.elemSize(); - int keypointsOutStep = keypointsOut.step / keypointsOut.elemSize(); - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&keypointsIn.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&keypointsOut.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&npoints)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&keypointsInStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&keypointsOutStep)); - - openCLExecuteKernel(clCxt, &orb, kernelName, globalThreads, localThreads, args, -1, -1); -} - -static void convertChannelsToRows_OCL(const oclMat& keypointsPos, const oclMat& keypointsResp, - oclMat& keypointsOut, int npoints) -{ - size_t localThreads[3] = {256, 1, 1}; - size_t globalThreads[3] = {divUp(npoints, localThreads[0]) * localThreads[0], - 1, - 1}; - - Context *clCxt = Context::getContext(); - String kernelName = "convertChannelsToRows"; - std::vector< std::pair > args; - - int keypointsPosStep = keypointsPos.step / keypointsResp.elemSize(); - int keypointsRespStep = keypointsResp.step / keypointsResp.elemSize(); - int keypointsOutStep = keypointsOut.step / keypointsOut.elemSize(); - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&keypointsPos.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&keypointsResp.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&keypointsOut.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&npoints)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&keypointsPosStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&keypointsRespStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&keypointsOutStep)); - - openCLExecuteKernel(clCxt, &orb, kernelName, globalThreads, localThreads, args, -1, -1); -} - -void cv::ocl::ORB_OCL::computeKeyPointsPyramid() -{ - int half_patch_size = patchSize_ / 2; - - keyPointsPyr_.resize(nLevels_); - keyPointsCount_.resize(nLevels_); - - for (int level = 0; level < nLevels_; ++level) - { - keyPointsCount_[level] = fastDetector_.calcKeyPointsLocation(imagePyr_[level], maskPyr_[level]); - - if (keyPointsCount_[level] == 0) - continue; - - keyPointsCount_[level] = fastDetector_.getKeyPoints(keyPointsPyr_[level]); - - if (keyPointsCount_[level] == 0) - continue; - - int n_features = static_cast(n_features_per_level_[level]); - - if (scoreType_ == ORB::HARRIS_SCORE) - { - int featuresToIncrease = 2 * n_features - keyPointsPyr_[level].cols; - if (featuresToIncrease < 0) featuresToIncrease = 0; - - // Keeps more points than necessary as FAST does not give amazing corners - // and expands rows in the keypoint matrix to store angle, octave and size - copyMakeBorder(keyPointsPyr_[level], keyPointsPyr_[level], - 0, ROWS_COUNT-keyPointsPyr_[level].rows, - 0, featuresToIncrease, - BORDER_CONSTANT, 0.f); - - // Compute the Harris cornerness (better scoring than FAST) - HarrisResponses_OCL(imagePyr_[level], keyPointsPyr_[level], keyPointsCount_[level], 7, HARRIS_K); - } - else - { - // Expands rows in the keypoint matrix to store angle, octave and size - copyMakeBorder(keyPointsPyr_[level], keyPointsPyr_[level], - 0, ROWS_COUNT-keyPointsPyr_[level].rows, - 0, 0, - BORDER_CONSTANT, 0.f); - } - - - // To use sortByKey the keypoint locations have to be reorganized as one row and two channels, - // leaving the keys (responses) as a one row, one channel matrix. - // TODO: change this when sortByRow is implemented. - oclMat keypointsResp, keypointsPos(1,keyPointsCount_[level],CV_32FC2); - keyPointsPyr_[level].row(RESPONSE_ROW).colRange(0,keyPointsCount_[level]).copyTo(keypointsResp); - - convertRowsToChannels_OCL(keyPointsPyr_[level].rowRange(0,2), keypointsPos, keyPointsCount_[level]); - ocl::sortByKey(keypointsResp, keypointsPos, SORT_MERGE, true); - - keyPointsCount_[level] = std::min(n_features,keyPointsCount_[level]); - - // The data is then reorganized back to one channel, three rows (X_ROW, Y_ROW, RESPONSE_ROW) - convertChannelsToRows_OCL(keypointsPos, keypointsResp, keyPointsPyr_[level], keyPointsCount_[level]); - - // Compute orientation - IC_Angle_OCL(imagePyr_[level], keyPointsPyr_[level], uMax_, keyPointsCount_[level], half_patch_size); - } -} - -static void computeOrbDescriptor_OCL(const oclMat& img, const oclMat& keypoints, const oclMat& pattern, - oclMat& desc, const int npoints, const int dsize, const int WTA_K, - const int offset) -{ - size_t localThreads[3] = {32, 8, 1}; - size_t globalThreads[3] = {divUp(dsize, localThreads[0]) * localThreads[0], - divUp(npoints, localThreads[1]) * localThreads[1], - 1}; - - Context *clCxt = Context::getContext(); - String kernelName = "computeOrbDescriptor"; - std::vector< std::pair > args; - - int imgStep = img.step / img.elemSize(); - int keypointsStep = keypoints.step / keypoints.elemSize(); - int patternStep = pattern.step / pattern.elemSize(); - int descStep = desc.step / desc.elemSize(); - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&img.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&keypoints.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&pattern.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&desc.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&npoints)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dsize)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&WTA_K)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&imgStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&keypointsStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&patternStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&descStep)); - - openCLExecuteKernel(clCxt, &orb, kernelName, globalThreads, localThreads, args, -1, -1); -} - -void cv::ocl::ORB_OCL::computeDescriptors(oclMat& descriptors) -{ - int nAllkeypoints = 0; - - for (int level = 0; level < nLevels_; ++level) - nAllkeypoints += keyPointsCount_[level]; - - if (nAllkeypoints == 0) - { - descriptors.release(); - return; - } - - ensureSizeIsEnough(nAllkeypoints, descriptorSize(), CV_8UC1, descriptors); - - int offset = 0; - - for (int level = 0; level < nLevels_; ++level) - { - if (keyPointsCount_[level] == 0) - continue; - - if (blurForDescriptor) - { - // preprocess the resized image - ensureSizeIsEnough(imagePyr_[level].size(), imagePyr_[level].type(), buf_); - blurFilter->apply(imagePyr_[level], buf_); - } - - computeOrbDescriptor_OCL(blurForDescriptor ? buf_ : imagePyr_[level], keyPointsPyr_[level], - pattern_, descriptors, keyPointsCount_[level], descriptorSize(), WTA_K_, offset); - - offset += keyPointsCount_[level]; - } -} - -static void mergeLocation_OCL(const oclMat& keypointsIn, oclMat& keypointsOut, const int npoints, - const int offset, const float scale, const int octave, const float size) -{ - size_t localThreads[3] = {256, 1, 1}; - size_t globalThreads[3] = {divUp(npoints, localThreads[0]) * localThreads[0], - 1, - 1}; - - Context *clCxt = Context::getContext(); - String kernelName = "mergeLocation"; - std::vector< std::pair > args; - - int keypointsInStep = keypointsIn.step / keypointsIn.elemSize(); - int keypointsOutStep = keypointsOut.step / keypointsOut.elemSize(); - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&keypointsIn.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&keypointsOut.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&npoints)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&offset)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&scale)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&octave)); - args.push_back( std::make_pair( sizeof(cl_float), (void *)&size)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&keypointsInStep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&keypointsOutStep)); - - openCLExecuteKernel(clCxt, &orb, kernelName, globalThreads, localThreads, args, -1, -1); -} - -void cv::ocl::ORB_OCL::mergeKeyPoints(oclMat& keypoints) -{ - int nAllkeypoints = 0; - - for (int level = 0; level < nLevels_; ++level) - nAllkeypoints += keyPointsCount_[level]; - - if (nAllkeypoints == 0) - { - keypoints.release(); - return; - } - - ensureSizeIsEnough(ROWS_COUNT, nAllkeypoints, CV_32FC1, keypoints); - - int offset = 0; - - for (int level = 0; level < nLevels_; ++level) - { - if (keyPointsCount_[level] == 0) - continue; - - float sf = getScale(scaleFactor_, firstLevel_, level); - - float locScale = level != firstLevel_ ? sf : 1.0f; - float size = patchSize_ * sf; - - mergeLocation_OCL(keyPointsPyr_[level], keypoints, keyPointsCount_[level], offset, locScale, level, size); - - offset += keyPointsCount_[level]; - } -} - -void cv::ocl::ORB_OCL::downloadKeyPoints(const oclMat &d_keypoints, std::vector& keypoints) -{ - if (d_keypoints.empty()) - { - keypoints.clear(); - return; - } - - Mat h_keypoints(d_keypoints); - - convertKeyPoints(h_keypoints, keypoints); -} - -void cv::ocl::ORB_OCL::convertKeyPoints(const Mat &d_keypoints, std::vector& keypoints) -{ - if (d_keypoints.empty()) - { - keypoints.clear(); - return; - } - - CV_Assert(d_keypoints.type() == CV_32FC1 && d_keypoints.rows == ROWS_COUNT); - - const float* x_ptr = d_keypoints.ptr(X_ROW); - const float* y_ptr = d_keypoints.ptr(Y_ROW); - const float* response_ptr = d_keypoints.ptr(RESPONSE_ROW); - const float* angle_ptr = d_keypoints.ptr(ANGLE_ROW); - const float* octave_ptr = d_keypoints.ptr(OCTAVE_ROW); - const float* size_ptr = d_keypoints.ptr(SIZE_ROW); - - keypoints.resize(d_keypoints.cols); - - for (int i = 0; i < d_keypoints.cols; ++i) - { - KeyPoint kp; - - kp.pt.x = x_ptr[i]; - kp.pt.y = y_ptr[i]; - kp.response = response_ptr[i]; - kp.angle = angle_ptr[i]; - kp.octave = static_cast(octave_ptr[i]); - kp.size = size_ptr[i]; - - keypoints[i] = kp; - } -} - -void cv::ocl::ORB_OCL::operator()(const oclMat& image, const oclMat& mask, oclMat& keypoints) -{ - buildScalePyramids(image, mask); - computeKeyPointsPyramid(); - mergeKeyPoints(keypoints); -} - -void cv::ocl::ORB_OCL::operator()(const oclMat& image, const oclMat& mask, oclMat& keypoints, oclMat& descriptors) -{ - buildScalePyramids(image, mask); - computeKeyPointsPyramid(); - computeDescriptors(descriptors); - mergeKeyPoints(keypoints); -} - -void cv::ocl::ORB_OCL::operator()(const oclMat& image, const oclMat& mask, std::vector& keypoints) -{ - (*this)(image, mask, d_keypoints_); - downloadKeyPoints(d_keypoints_, keypoints); -} - -void cv::ocl::ORB_OCL::operator()(const oclMat& image, const oclMat& mask, std::vector& keypoints, oclMat& descriptors) -{ - (*this)(image, mask, d_keypoints_, descriptors); - downloadKeyPoints(d_keypoints_, keypoints); -} - -void cv::ocl::ORB_OCL::release() -{ - imagePyr_.clear(); - maskPyr_.clear(); - - buf_.release(); - - keyPointsPyr_.clear(); - - fastDetector_.release(); - - d_keypoints_.release(); - - uMax_.release(); -} diff --git a/modules/ocl/src/precomp.hpp b/modules/ocl/src/precomp.hpp deleted file mode 100644 index 4cd700a16..000000000 --- a/modules/ocl/src/precomp.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Guoping Long, longguoping@gmail.com -// Yao Wang, bitwangyaoyao@gmail.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*/ - -#ifndef __OPENCV_PRECOMP_H__ -#define __OPENCV_PRECOMP_H__ - -#if defined _MSC_VER && _MSC_VER >= 1200 -#pragma warning( disable: 4127 4267 4324 4244 4251 4710 4711 4514 4996 ) -#endif - -#if defined(_WIN32) -#include -#endif - -#include "cvconfig.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#undef OPENCV_NOSTL - -#include "opencv2/imgproc.hpp" -#include "opencv2/objdetect/objdetect_c.h" -#include "opencv2/ocl.hpp" -#include "opencv2/features2d.hpp" - -#include "opencv2/core/utility.hpp" -#include "opencv2/core/private.hpp" -#include "opencv2/core/ocl.hpp" - -#define __ATI__ - -#if defined (HAVE_OPENCL) - -#define CL_USE_DEPRECATED_OPENCL_1_1_APIS -#include "opencv2/ocl/private/util.hpp" -#include "safe_call.hpp" - -#else /* defined(HAVE_OPENCL) */ - -static inline void throw_nogpu() -{ - CV_Error(CV_GpuNotSupported, "The library is compilled without OpenCL support.\n"); -} - -#endif /* defined(HAVE_OPENCL) */ - -#endif /* __OPENCV_PRECOMP_H__ */ diff --git a/modules/ocl/src/pyrdown.cpp b/modules/ocl/src/pyrdown.cpp deleted file mode 100644 index 7e5e35a3e..000000000 --- a/modules/ocl/src/pyrdown.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/*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 -// Dachuan Zhao, dachuan@multicorewareinc.com -// Yao Wang, yao@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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -////////////////////////////////////////////////////////////////////////////// -/////////////////////// add subtract multiply divide ///////////////////////// -////////////////////////////////////////////////////////////////////////////// -static void pyrdown_run(const oclMat &src, const oclMat &dst) -{ - - CV_Assert(src.type() == dst.type()); - CV_Assert(src.depth() != CV_8S); - - Context *clCxt = src.clCxt; - String kernelName = "pyrDown"; - - size_t localThreads[3] = { 256, 1, 1 }; - size_t globalThreads[3] = { src.cols, dst.rows, 1}; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.cols)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.cols)); - - openCLExecuteKernel(clCxt, &pyr_down, kernelName, globalThreads, localThreads, args, src.oclchannels(), src.depth()); -} -////////////////////////////////////////////////////////////////////////////// -// pyrDown - -void cv::ocl::pyrDown(const oclMat &src, oclMat &dst) -{ - int depth = src.depth(), channels = src.channels(); - CV_Assert(depth == CV_8U || depth == CV_16U || depth == CV_16S || depth == CV_32F); - CV_Assert(channels == 1 || channels == 3 || channels == 4); - - dst.create((src.rows + 1) / 2, (src.cols + 1) / 2, src.type()); - - pyrdown_run(src, dst); -} diff --git a/modules/ocl/src/pyrlk.cpp b/modules/ocl/src/pyrlk.cpp deleted file mode 100644 index 2ff3dcd1b..000000000 --- a/modules/ocl/src/pyrlk.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/*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 -// Dachuan Zhao, dachuan@multicorewareinc.com -// Yao Wang, yao@multicorewareinc.com -// Nathan, liujun@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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -struct dim3 -{ - unsigned int x, y, z; -}; - -static void calcPatchSize(cv::Size winSize, int cn, dim3 &block, dim3 &patch, bool isDeviceArch11) -{ - winSize.width *= cn; - - if (winSize.width > 32 && winSize.width > 2 * winSize.height) - { - block.x = isDeviceArch11 ? 16 : 32; - block.y = 8; - } - else - { - block.x = 16; - block.y = isDeviceArch11 ? 8 : 16; - } - - patch.x = (winSize.width + block.x - 1) / block.x; - patch.y = (winSize.height + block.y - 1) / block.y; - - block.z = patch.z = 1; -} - -static void pyrdown_run_cus(const oclMat &src, const oclMat &dst) -{ - - CV_Assert(src.type() == dst.type()); - CV_Assert(src.depth() != CV_8S); - - Context *clCxt = src.clCxt; - - String kernelName = "pyrDown"; - - size_t localThreads[3] = { 256, 1, 1 }; - size_t globalThreads[3] = { src.cols, dst.rows, 1}; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.cols)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.cols)); - - openCLExecuteKernel2(clCxt, &pyr_down, kernelName, globalThreads, localThreads, args, src.oclchannels(), src.depth(), CLFLUSH); -} - -static void pyrDown_cus(const oclMat &src, oclMat &dst) -{ - CV_Assert(src.depth() <= CV_32F && src.channels() <= 4); - - dst.create((src.rows + 1) / 2, (src.cols + 1) / 2, src.type()); - pyrdown_run_cus(src, dst); -} - -static void lkSparse_run(oclMat &I, oclMat &J, - const oclMat &prevPts, oclMat &nextPts, oclMat &status, oclMat& err, bool /*GET_MIN_EIGENVALS*/, int ptcount, - int level, /*dim3 block, */dim3 patch, Size winSize, int iters) -{ - Context *clCxt = I.clCxt; - String kernelName = "lkSparse"; - size_t localThreads[3] = { 8, 8, 1 }; - size_t globalThreads[3] = { 8 * ptcount, 8, 1}; - int cn = I.oclchannels(); - char calcErr = level==0?1:0; - - std::vector > args; - - cl_mem ITex = bindTexture(I); - cl_mem JTex = bindTexture(J); - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&ITex )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&JTex )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&prevPts.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&prevPts.step )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&nextPts.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&nextPts.step )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&status.data )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&err.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&level )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&I.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&I.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&patch.x )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&patch.y )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cn )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&winSize.width )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&winSize.height )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&iters )); - args.push_back( std::make_pair( sizeof(cl_char), (void *)&calcErr )); - - bool is_cpu = isCpuDevice(); - if (is_cpu) - { - openCLExecuteKernel(clCxt, &pyrlk, kernelName, globalThreads, localThreads, args, I.oclchannels(), I.depth(), (char*)" -D CPU"); - } - else - { - std::stringstream idxStr; - idxStr << kernelName << "_C" << I.oclchannels() << "_D" << I.depth(); - cl_kernel kernel = openCLGetKernelFromSource(clCxt, &pyrlk, idxStr.str()); - int wave_size = (int)queryWaveFrontSize(kernel); - openCLSafeCall(clReleaseKernel(kernel)); - - static char opt[32] = {0}; - sprintf(opt, "-D WAVE_SIZE=%d", wave_size); - - openCLExecuteKernel(clCxt, &pyrlk, kernelName, globalThreads, localThreads, - args, I.oclchannels(), I.depth(), opt); - } - releaseTexture(ITex); - releaseTexture(JTex); -} - -void cv::ocl::PyrLKOpticalFlow::sparse(const oclMat &prevImg, const oclMat &nextImg, const oclMat &prevPts, oclMat &nextPts, oclMat &status, oclMat *err) -{ - if (prevPts.empty()) - { - nextPts.release(); - status.release(); - return; - } - - derivLambda = std::min(std::max(derivLambda, 0.0), 1.0); - - iters = std::min(std::max(iters, 0), 100); - - const int cn = prevImg.oclchannels(); - - dim3 block, patch; - calcPatchSize(winSize, cn, block, patch, isDeviceArch11_); - - CV_Assert(derivLambda >= 0); - CV_Assert(maxLevel >= 0 && winSize.width > 2 && winSize.height > 2); - CV_Assert(prevImg.size() == nextImg.size() && prevImg.type() == nextImg.type()); - CV_Assert(patch.x > 0 && patch.x < 6 && patch.y > 0 && patch.y < 6); - CV_Assert(prevPts.rows == 1 && prevPts.type() == CV_32FC2); - - if (useInitialFlow) - CV_Assert(nextPts.size() == prevPts.size() && nextPts.type() == CV_32FC2); - else - ensureSizeIsEnough(1, prevPts.cols, prevPts.type(), nextPts); - - oclMat temp1 = (useInitialFlow ? nextPts : prevPts).reshape(1); - oclMat temp2 = nextPts.reshape(1); - multiply(1.0f/(1<= 0; level--) - { - lkSparse_run(prevPyr_[level], nextPyr_[level], - prevPts, nextPts, status, *err, getMinEigenVals, prevPts.cols, - level, /*block, */patch, winSize, iters); - } - - clFinish(*(cl_command_queue*)prevImg.clCxt->getOpenCLCommandQueuePtr()); - - if(errMat) - delete err; -} - -static void lkDense_run(oclMat &I, oclMat &J, oclMat &u, oclMat &v, - oclMat &prevU, oclMat &prevV, oclMat *err, Size winSize, int iters) -{ - Context *clCxt = I.clCxt; - - String kernelName = "lkDense"; - - size_t localThreads[3] = { 16, 16, 1 }; - size_t globalThreads[3] = { I.cols, I.rows, 1}; - - cl_char calcErr = err ? 1 : 0; - - cl_mem ITex; - cl_mem JTex; - - ITex = bindTexture(I); - JTex = bindTexture(J); - - std::vector > args; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&ITex )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&JTex )); - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&u.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&u.step )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&v.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&v.step )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&prevU.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&prevU.step )); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&prevV.data )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&prevV.step )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&I.rows )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&I.cols )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&winSize.width )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&winSize.height )); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&iters )); - args.push_back( std::make_pair( sizeof(cl_char), (void *)&calcErr )); - - openCLExecuteKernel(clCxt, &pyrlk, kernelName, globalThreads, localThreads, args, I.oclchannels(), I.depth()); - - releaseTexture(ITex); - releaseTexture(JTex); -} - -void cv::ocl::PyrLKOpticalFlow::dense(const oclMat &prevImg, const oclMat &nextImg, oclMat &u, oclMat &v, oclMat *err) -{ - CV_Assert(prevImg.type() == CV_8UC1); - CV_Assert(prevImg.size() == nextImg.size() && prevImg.type() == nextImg.type()); - CV_Assert(maxLevel >= 0); - CV_Assert(winSize.width > 2 && winSize.height > 2); - - if (err) - err->create(prevImg.size(), CV_32FC1); - - prevPyr_.resize(maxLevel + 1); - nextPyr_.resize(maxLevel + 1); - - prevPyr_[0] = prevImg; - nextImg.convertTo(nextPyr_[0], CV_32F); - - for (int level = 1; level <= maxLevel; ++level) - { - pyrDown_cus(prevPyr_[level - 1], prevPyr_[level]); - pyrDown_cus(nextPyr_[level - 1], nextPyr_[level]); - } - - ensureSizeIsEnough(prevImg.size(), CV_32FC1, uPyr_[0]); - ensureSizeIsEnough(prevImg.size(), CV_32FC1, vPyr_[0]); - ensureSizeIsEnough(prevImg.size(), CV_32FC1, uPyr_[1]); - ensureSizeIsEnough(prevImg.size(), CV_32FC1, vPyr_[1]); - uPyr_[1].setTo(Scalar::all(0)); - vPyr_[1].setTo(Scalar::all(0)); - - Size winSize2i(winSize.width, winSize.height); - - int idx = 0; - - for (int level = maxLevel; level >= 0; level--) - { - int idx2 = (idx + 1) & 1; - - lkDense_run(prevPyr_[level], nextPyr_[level], uPyr_[idx], vPyr_[idx], uPyr_[idx2], vPyr_[idx2], - level == 0 ? err : 0, winSize2i, iters); - - if (level > 0) - idx = idx2; - } - - uPyr_[idx].copyTo(u); - vPyr_[idx].copyTo(v); - - clFinish(*(cl_command_queue*)prevImg.clCxt->getOpenCLCommandQueuePtr()); -} diff --git a/modules/ocl/src/pyrup.cpp b/modules/ocl/src/pyrup.cpp deleted file mode 100644 index 95d3a3443..000000000 --- a/modules/ocl/src/pyrup.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/*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 -// Zhang Chunpeng chunpeng@multicorewareinc.com -// Yao Wang, yao@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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -/* Haar features calculation */ -//#define EMU - -namespace cv -{ - namespace ocl - { - void pyrUp(const cv::ocl::oclMat &src, cv::ocl::oclMat &dst) - { - int depth = src.depth(), channels = src.channels(), oclChannels = src.oclchannels(); - - CV_Assert(depth == CV_8U || depth == CV_16U || depth == CV_16S || depth == CV_32F); - CV_Assert(channels == 1 || channels == 3 || channels == 4); - - dst.create(src.rows * 2, src.cols * 2, src.type()); - - Context *clCxt = src.clCxt; - - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float" }; - char buildOptions[250], convertString[50]; - const char * const channelsString = oclChannels == 1 ? "" : "4"; - sprintf(convertString, "convert_%s%s_sat_rte", typeMap[depth], channelsString); - sprintf(buildOptions, "-D Type=%s%s -D floatType=float%s -D convertToType=%s -D convertToFloat=%s", - typeMap[depth], channelsString, channelsString, - depth == CV_32F ? "" : convertString, - oclChannels == 4 ? "convert_float4" : "(float)"); - - const String kernelName = "pyrUp"; - int dststep = dst.step / dst.elemSize(), srcstep = src.step / src.elemSize(); - - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst.offset)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&srcstep)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dststep)); - - size_t globalThreads[3] = {dst.cols, dst.rows, 1}; - size_t localThreads[3] = {16, 16, 1}; - - - openCLExecuteKernel(clCxt, &pyr_up, kernelName, globalThreads, localThreads, args, -1, -1, - buildOptions); - } - } -} diff --git a/modules/ocl/src/safe_call.hpp b/modules/ocl/src/safe_call.hpp deleted file mode 100644 index 14cbb6df0..000000000 --- a/modules/ocl/src/safe_call.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Long Guoping , longguoping@gmail.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*/ - -#ifndef __OPENCV_OPENCL_SAFE_CALL_HPP__ -#define __OPENCV_OPENCL_SAFE_CALL_HPP__ - -#include "opencv2/core/opencl/runtime/opencl_core.hpp" - -#define openCLSafeCall(expr) ___openCLSafeCall(expr, __FILE__, __LINE__, CV_Func) -#define openCLVerifyCall(res) ___openCLSafeCall(res, __FILE__, __LINE__, CV_Func) - - -namespace cv -{ - namespace ocl - { - const char *getOpenCLErrorString( int err ); - - static inline void ___openCLSafeCall(int err, const char *file, const int line, const char *func = "") - { - if (CL_SUCCESS != err) - cv::error(Error::OpenCLApiCallError, getOpenCLErrorString(err), func, file, line); - } - } -} - -#endif /* __OPENCV_OPENCL_SAFE_CALL_HPP__ */ diff --git a/modules/ocl/src/sort_by_key.cpp b/modules/ocl/src/sort_by_key.cpp deleted file mode 100644 index 596f94e1c..000000000 --- a/modules/ocl/src/sort_by_key.cpp +++ /dev/null @@ -1,472 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@outlook.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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -namespace cv -{ -namespace ocl -{ -void sortByKey(oclMat& keys, oclMat& vals, size_t vecSize, int method, bool isGreaterThan); - -#ifndef ANDROID -//TODO(pengx17): change this value depending on device other than a constant -const static unsigned int GROUP_SIZE = 256; -#endif - -const char * depth_strings[] = -{ - "uchar", //CV_8U - "char", //CV_8S - "ushort", //CV_16U - "short", //CV_16S - "int", //CV_32S - "float", //CV_32F - "double" //CV_64F -}; - -void static genSortBuildOption(const oclMat& keys, const oclMat& vals, bool isGreaterThan, char * build_opt_buf) -{ - sprintf(build_opt_buf, "-D IS_GT=%d -D K_T=%s -D V_T=%s", - isGreaterThan?1:0, depth_strings[keys.depth()], depth_strings[vals.depth()]); - if(vals.oclchannels() > 1) - { - sprintf( build_opt_buf + strlen(build_opt_buf), "%d", vals.oclchannels()); - } -} -inline bool isSizePowerOf2(size_t size) -{ - return ((size - 1) & (size)) == 0; -} - -namespace bitonic_sort -{ -static void sortByKey(oclMat& keys, oclMat& vals, size_t vecSize, bool isGreaterThan) -{ - CV_Assert(isSizePowerOf2(vecSize)); - - Context * cxt = Context::getContext(); - size_t globalThreads[3] = {vecSize / 2, 1, 1}; - - // 2^numStages should be equal to vecSize or the output is invalid - int numStages = 0; - for(int i = vecSize; i > 1; i >>= 1) - { - ++numStages; - } - char build_opt_buf [100]; - genSortBuildOption(keys, vals, isGreaterThan, build_opt_buf); - const int argc = 5; - std::vector< std::pair > args(argc); - String kernelname = "bitonicSort"; - - args[0] = std::make_pair(sizeof(cl_mem), (void *)&keys.data); - args[1] = std::make_pair(sizeof(cl_mem), (void *)&vals.data); - args[2] = std::make_pair(sizeof(cl_int), (void *)&vecSize); - - for(int stage = 0; stage < numStages; ++stage) - { - args[3] = std::make_pair(sizeof(cl_int), (void *)&stage); - for(int passOfStage = 0; passOfStage < stage + 1; ++passOfStage) - { - args[4] = std::make_pair(sizeof(cl_int), (void *)&passOfStage); -#ifdef ANDROID - openCLExecuteKernel(cxt, &kernel_sort_by_key, kernelname, globalThreads, NULL, args, -1, -1, build_opt_buf); -#else - size_t localThreads[3] = {GROUP_SIZE, 1, 1}; - openCLExecuteKernel(cxt, &kernel_sort_by_key, kernelname, globalThreads, localThreads, args, -1, -1, build_opt_buf); -#endif - } - } -} -} /* bitonic_sort */ - -namespace selection_sort -{ -// FIXME: -// This function cannot sort arrays with duplicated keys -static void sortByKey(oclMat& keys, oclMat& vals, size_t vecSize, bool isGreaterThan) -{ - CV_Error(-1, "This function is incorrect at the moment."); - Context * cxt = Context::getContext(); - - size_t globalThreads[3] = {vecSize, 1, 1}; - - std::vector< std::pair > args; - char build_opt_buf [100]; - genSortBuildOption(keys, vals, isGreaterThan, build_opt_buf); - - //local - String kernelname = "selectionSortLocal"; -#ifdef ANDROID - int lds_size = cxt->getDeviceInfo().maxWorkGroupSize * keys.elemSize(); -#else - int lds_size = GROUP_SIZE * keys.elemSize(); -#endif - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&keys.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&vals.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&vecSize)); - args.push_back(std::make_pair(lds_size, (void*)NULL)); - -#ifdef ANDROID - openCLExecuteKernel(cxt, &kernel_sort_by_key, kernelname, globalThreads, NULL, args, -1, -1, build_opt_buf); -#else - size_t localThreads[3] = {GROUP_SIZE, 1, 1}; - openCLExecuteKernel(cxt, &kernel_sort_by_key, kernelname, globalThreads, localThreads, args, -1, -1, build_opt_buf); -#endif - - //final - kernelname = "selectionSortFinal"; - args.pop_back(); -#ifdef ANDROID - openCLExecuteKernel(cxt, &kernel_sort_by_key, kernelname, globalThreads, NULL, args, -1, -1, build_opt_buf); -#else - openCLExecuteKernel(cxt, &kernel_sort_by_key, kernelname, globalThreads, localThreads, args, -1, -1, build_opt_buf); -#endif -} - -} /* selection_sort */ - - -namespace radix_sort -{ -//FIXME(pengx17): -// exclusive scan, need to be optimized as this is too naive... -//void naive_scan_addition(oclMat& input, oclMat& output) -//{ -// Context * cxt = Context::getContext(); -// size_t vecSize = input.cols; -// size_t globalThreads[3] = {1, 1, 1}; -// size_t localThreads[3] = {1, 1, 1}; -// -// String kernelname = "naiveScanAddition"; -// -// std::vector< std::pair > args; -// args.push_back(std::make_pair(sizeof(cl_mem), (void *)&input.data)); -// args.push_back(std::make_pair(sizeof(cl_mem), (void *)&output.data)); -// args.push_back(std::make_pair(sizeof(cl_int), (void *)&vecSize)); -// openCLExecuteKernel(cxt, &kernel_radix_sort_by_key, kernelname, globalThreads, localThreads, args, -1, -1); -//} - -void static naive_scan_addition_cpu(oclMat& input, oclMat& output) -{ - Mat m_input = input, m_output(output.size(), output.type()); - MatIterator_ i_mit = m_input.begin(); - MatIterator_ o_mit = m_output.begin(); - *o_mit = 0; - ++i_mit; - ++o_mit; - for(; i_mit != m_input.end(); ++i_mit, ++o_mit) - { - *o_mit = *(o_mit - 1) + *(i_mit - 1); - } - output = m_output; -} - - -//radix sort ported from Bolt -static void sortByKey(oclMat& keys, oclMat& vals, size_t origVecSize, bool isGreaterThan) -{ - CV_Assert(keys.depth() == CV_32S || keys.depth() == CV_32F); // we assume keys are 4 bytes - - bool isKeyFloat = keys.type() == CV_32F; - - const int RADIX = 4; //Now you cannot replace this with Radix 8 since there is a - //local array of 16 elements in the histogram kernel. - const int RADICES = (1 << RADIX); //Values handeled by each work-item? - - bool newBuffer = false; - size_t vecSize = origVecSize; - - unsigned int groupSize = RADICES; - - size_t mulFactor = groupSize * RADICES; - - oclMat buffer_keys, buffer_vals; - - if(origVecSize % mulFactor != 0) - { - vecSize = ((vecSize + mulFactor) / mulFactor) * mulFactor; - buffer_keys.create(1, vecSize, keys.type()); - buffer_vals.create(1, vecSize, vals.type()); - Scalar padding_value; - oclMat roi_buffer_vals = buffer_vals(Rect(0,0,origVecSize,1)); - - if(isGreaterThan) - { - switch(buffer_keys.depth()) - { - case CV_32F: - padding_value = Scalar::all(-FLT_MAX); - break; - case CV_32S: - padding_value = Scalar::all(INT_MIN); - break; - } - } - else - { - switch(buffer_keys.depth()) - { - case CV_32F: - padding_value = Scalar::all(FLT_MAX); - break; - case CV_32S: - padding_value = Scalar::all(INT_MAX); - break; - } - } - ocl::copyMakeBorder( - keys(Rect(0,0,origVecSize,1)), buffer_keys, - 0, 0, 0, vecSize - origVecSize, - BORDER_CONSTANT, padding_value); - vals(Rect(0,0,origVecSize,1)).copyTo(roi_buffer_vals); - newBuffer = true; - } - else - { - buffer_keys = keys; - buffer_vals = vals; - newBuffer = false; - } - oclMat swap_input_keys(1, vecSize, keys.type()); - oclMat swap_input_vals(1, vecSize, vals.type()); - oclMat hist_bin_keys(1, vecSize, CV_32SC1); - oclMat hist_bin_dest_keys(1, vecSize, CV_32SC1); - - Context * cxt = Context::getContext(); - - size_t globalThreads[3] = {vecSize / RADICES, 1, 1}; - size_t localThreads[3] = {groupSize, 1, 1}; - - std::vector< std::pair > args; - char build_opt_buf [100]; - genSortBuildOption(keys, vals, isGreaterThan, build_opt_buf); - - //additional build option for radix sort - sprintf(build_opt_buf + strlen(build_opt_buf), " -D K_%s", isKeyFloat?"FLT":"INT"); - - String kernelnames[2] = {String("histogramRadixN"), String("permuteRadixN")}; - - int swap = 0; - for(int bits = 0; bits < (static_cast(keys.elemSize()) * 8); bits += RADIX) - { - args.clear(); - //Do a histogram pass locally - if(swap == 0) - { - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&buffer_keys.data)); - } - else - { - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&swap_input_keys.data)); - } - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&hist_bin_keys.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&bits)); - openCLExecuteKernel(cxt, &kernel_radix_sort_by_key, kernelnames[0], globalThreads, localThreads, - args, -1, -1, build_opt_buf); - - args.clear(); - //Perform a global scan - naive_scan_addition_cpu(hist_bin_keys, hist_bin_dest_keys); - // end of scan - if(swap == 0) - { - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&buffer_keys.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&buffer_vals.data)); - } - else - { - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&swap_input_keys.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&swap_input_vals.data)); - } - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&hist_bin_dest_keys.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&bits)); - - if(swap == 0) - { - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&swap_input_keys.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&swap_input_vals.data)); - } - else - { - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&buffer_keys.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&buffer_vals.data)); - } - openCLExecuteKernel(cxt, &kernel_radix_sort_by_key, kernelnames[1], globalThreads, localThreads, - args, -1, -1, build_opt_buf); - swap = swap ? 0 : 1; - } - if(newBuffer) - { - buffer_keys(Rect(0,0,origVecSize,1)).copyTo(keys); - buffer_vals(Rect(0,0,origVecSize,1)).copyTo(vals); - } -} - -} /* radix_sort */ - -namespace merge_sort -{ -static void sortByKey(oclMat& keys, oclMat& vals, size_t vecSize, bool isGreaterThan) -{ - Context * cxt = Context::getContext(); - - const size_t GROUP_SIZE = cxt->getDeviceInfo().maxWorkGroupSize >= 256 ? 256: 128; - - size_t globalThreads[3] = {vecSize, 1, 1}; - size_t localThreads[3] = {GROUP_SIZE, 1, 1}; - - std::vector< std::pair > args; - char build_opt_buf [100]; - genSortBuildOption(keys, vals, isGreaterThan, build_opt_buf); - - String kernelname[] = {String("blockInsertionSort"), String("merge")}; - int keylds_size = GROUP_SIZE * keys.elemSize(); - int vallds_size = GROUP_SIZE * vals.elemSize(); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&keys.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&vals.data)); - args.push_back(std::make_pair(sizeof(cl_uint), (void *)&vecSize)); - args.push_back(std::make_pair(keylds_size, (void*)NULL)); - args.push_back(std::make_pair(vallds_size, (void*)NULL)); - - openCLExecuteKernel(cxt, &kernel_stablesort_by_key, kernelname[0], globalThreads, localThreads, args, -1, -1, build_opt_buf); - - // Early exit for the case of no merge passes, values are already in destination vector - if(vecSize <= GROUP_SIZE) - { - return; - } - - // An odd number of elements requires an extra merge pass to sort - size_t numMerges = 0; - // Calculate the log2 of vecSize, taking into acvecSize our block size from kernel 1 is 64 - // this is how many merge passes we want - size_t log2BlockSize = vecSize >> 6; - for( ; log2BlockSize > 1; log2BlockSize >>= 1 ) - { - ++numMerges; - } - // Check to see if the input vector size is a power of 2, if not we will need last merge pass - numMerges += isSizePowerOf2(vecSize)? 1: 0; - - // Allocate a flipflop buffer because the merge passes are out of place - oclMat tmpKeyBuffer(keys.size(), keys.type()); - oclMat tmpValBuffer(vals.size(), vals.type()); - args.resize(8); - - args[4] = std::make_pair(sizeof(cl_uint), (void *)&vecSize); - args[6] = std::make_pair(keylds_size, (void*)NULL); - args[7] = std::make_pair(vallds_size, (void*)NULL); - - for(size_t pass = 1; pass <= numMerges; ++pass ) - { - // For each pass, flip the input-output buffers - if( pass & 0x1 ) - { - args[0] = std::make_pair(sizeof(cl_mem), (void *)&keys.data); - args[1] = std::make_pair(sizeof(cl_mem), (void *)&vals.data); - args[2] = std::make_pair(sizeof(cl_mem), (void *)&tmpKeyBuffer.data); - args[3] = std::make_pair(sizeof(cl_mem), (void *)&tmpValBuffer.data); - } - else - { - args[0] = std::make_pair(sizeof(cl_mem), (void *)&tmpKeyBuffer.data); - args[1] = std::make_pair(sizeof(cl_mem), (void *)&tmpValBuffer.data); - args[2] = std::make_pair(sizeof(cl_mem), (void *)&keys.data); - args[3] = std::make_pair(sizeof(cl_mem), (void *)&vals.data); - } - // For each pass, the merge window doubles - unsigned int srcLogicalBlockSize = static_cast( localThreads[0] << (pass-1) ); - args[5] = std::make_pair(sizeof(cl_uint), (void *)&srcLogicalBlockSize); - openCLExecuteKernel(cxt, &kernel_stablesort_by_key, kernelname[1], globalThreads, localThreads, args, -1, -1, build_opt_buf); - } - // If there are an odd number of merges, then the output data is sitting in the temp buffer. We need to copy - // the results back into the input array - if( numMerges & 1 ) - { - tmpKeyBuffer.copyTo(keys); - tmpValBuffer.copyTo(vals); - } -} -} /* merge_sort */ - -} -} /* namespace cv { namespace ocl */ - - -void cv::ocl::sortByKey(oclMat& keys, oclMat& vals, size_t vecSize, int method, bool isGreaterThan) -{ - CV_Assert( keys.rows == 1 ); // we only allow one dimensional input - CV_Assert( keys.channels() == 1 ); // we only allow one channel keys - CV_Assert( vecSize <= static_cast(keys.cols) ); - switch(method) - { - case SORT_BITONIC: - bitonic_sort::sortByKey(keys, vals, vecSize, isGreaterThan); - break; - case SORT_SELECTION: - selection_sort::sortByKey(keys, vals, vecSize, isGreaterThan); - break; - case SORT_RADIX: - radix_sort::sortByKey(keys, vals, vecSize, isGreaterThan); - break; - case SORT_MERGE: - merge_sort::sortByKey(keys, vals, vecSize, isGreaterThan); - break; - } -} - -void cv::ocl::sortByKey(oclMat& keys, oclMat& vals, int method, bool isGreaterThan) -{ - CV_Assert( keys.size() == vals.size() ); - CV_Assert( keys.rows == 1 ); // we only allow one dimensional input - size_t vecSize = static_cast(keys.cols); - sortByKey(keys, vals, vecSize, method, isGreaterThan); -} diff --git a/modules/ocl/src/split_merge.cpp b/modules/ocl/src/split_merge.cpp deleted file mode 100644 index 583869747..000000000 --- a/modules/ocl/src/split_merge.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; -namespace cv -{ - namespace ocl - { - namespace split_merge - { - static void merge_vector_run(const oclMat *mat_src, size_t n, oclMat &mat_dst) - { - if(!mat_dst.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && mat_dst.type() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - Context *clCxt = mat_dst.clCxt; - int channels = mat_dst.oclchannels(); - int depth = mat_dst.depth(); - - String kernelName = "merge_vector"; - - int vector_lengths[4][7] = {{0, 0, 0, 0, 0, 0, 0}, - {2, 2, 1, 1, 1, 1, 1}, - {4, 4, 2, 2 , 1, 1, 1}, - {1, 1, 1, 1, 1, 1, 1} - }; - - size_t vector_length = vector_lengths[channels - 1][depth]; - int offset_cols = (mat_dst.offset / mat_dst.elemSize()) & (vector_length - 1); - int cols = divUp(mat_dst.cols + offset_cols, vector_length); - - size_t localThreads[3] = { 64, 4, 1 }; - size_t globalThreads[3] = { cols, mat_dst.rows, 1 }; - - int dst_step1 = mat_dst.cols * mat_dst.elemSize(); - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_dst.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_dst.step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_dst.offset)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_src[0].data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src[0].step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src[0].offset)); - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_src[1].data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src[1].step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src[1].offset)); - - if(channels == 4) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_src[2].data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src[2].step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src[2].offset)); - - if(n == 3) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_src[2].data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src[2].step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src[2].offset)); - } - else if( n == 4) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&mat_src[3].data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src[3].step)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_src[3].offset)); - } - } - - args.push_back( std::make_pair( sizeof(cl_int), (void *)&mat_dst.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst_step1)); - - openCLExecuteKernel(clCxt, &merge_mat, kernelName, globalThreads, localThreads, args, channels, depth); - } - static void merge(const oclMat *mat_src, size_t n, oclMat &mat_dst) - { - CV_Assert(mat_src); - CV_Assert(n > 0); - - int depth = mat_src[0].depth(); - Size size = mat_src[0].size(); - - int total_channels = 0; - - for(size_t i = 0; i < n; ++i) - { - CV_Assert(depth == mat_src[i].depth()); - CV_Assert(size == mat_src[i].size()); - - total_channels += mat_src[i].oclchannels(); - } - - CV_Assert(total_channels <= 4); - - if(total_channels == 1) - { - mat_src[0].copyTo(mat_dst); - return; - } - - mat_dst.create(size, CV_MAKETYPE(depth, total_channels)); - merge_vector_run(mat_src, n, mat_dst); - } - static void split_vector_run(const oclMat &src, oclMat *dst) - { - - if(!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.type() == CV_64F) - { - CV_Error(Error::OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - Context *clCtx = src.clCxt; - int channels = src.channels(); - int depth = src.depth(); - depth = (depth == CV_8S) ? CV_8U : depth; - depth = (depth == CV_16S) ? CV_16U : depth; - - String kernelName = "split_vector"; - - size_t VEC_SIZE = 4; - - std::vector > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&src.step)); - int srcOffsetXBytes = src.offset % src.step; - int srcOffsetY = src.offset / src.step; - cl_int2 srcOffset = {{srcOffsetXBytes, srcOffsetY}}; - args.push_back( std::make_pair( sizeof(cl_int2), (void *)&srcOffset)); - - bool dst0Aligned = false, dst1Aligned = false, dst2Aligned = false, dst3Aligned = false; - int alignSize = dst[0].elemSize1() * VEC_SIZE; - int alignMask = alignSize - 1; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst[0].data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst[0].step)); - int dst0OffsetXBytes = dst[0].offset % dst[0].step; - int dst0OffsetY = dst[0].offset / dst[0].step; - cl_int2 dst0Offset = {{dst0OffsetXBytes, dst0OffsetY}}; - args.push_back( std::make_pair( sizeof(cl_int2), (void *)&dst0Offset)); - if ((dst0OffsetXBytes & alignMask) == 0) - dst0Aligned = true; - - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst[1].data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst[1].step)); - int dst1OffsetXBytes = dst[1].offset % dst[1].step; - int dst1OffsetY = dst[1].offset / dst[1].step; - cl_int2 dst1Offset = {{dst1OffsetXBytes, dst1OffsetY}}; - args.push_back( std::make_pair( sizeof(cl_int2), (void *)&dst1Offset)); - if ((dst1OffsetXBytes & alignMask) == 0) - dst1Aligned = true; - - // DON'T MOVE VARIABLES INTO 'IF' BODY - int dst2OffsetXBytes, dst2OffsetY; - cl_int2 dst2Offset; - int dst3OffsetXBytes, dst3OffsetY; - cl_int2 dst3Offset; - if (channels >= 3) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst[2].data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst[2].step)); - dst2OffsetXBytes = dst[2].offset % dst[2].step; - dst2OffsetY = dst[2].offset / dst[2].step; - dst2Offset.s[0] = dst2OffsetXBytes; dst2Offset.s[1] = dst2OffsetY; - args.push_back( std::make_pair( sizeof(cl_int2), (void *)&dst2Offset)); - if ((dst2OffsetXBytes & alignMask) == 0) - dst2Aligned = true; - } - - if (channels >= 4) - { - args.push_back( std::make_pair( sizeof(cl_mem), (void *)&dst[3].data)); - args.push_back( std::make_pair( sizeof(cl_int), (void *)&dst[3].step)); - dst3OffsetXBytes = dst[3].offset % dst[3].step; - dst3OffsetY = dst[3].offset / dst[3].step; - dst3Offset.s[0] = dst3OffsetXBytes; dst3Offset.s[1] = dst3OffsetY; - args.push_back( std::make_pair( sizeof(cl_int2), (void *)&dst3Offset)); - if ((dst3OffsetXBytes & alignMask) == 0) - dst3Aligned = true; - } - - cl_int2 size = {{ src.cols, src.rows }}; - args.push_back( std::make_pair( sizeof(cl_int2), (void *)&size)); - - String build_options = - cv::format("-D VEC_SIZE=%d -D DATA_DEPTH=%d -D DATA_CHAN=%d", - (int)VEC_SIZE, depth, channels); - - if (dst0Aligned) - build_options += " -D DST0_ALIGNED"; - if (dst1Aligned) - build_options += " -D DST1_ALIGNED"; - if (dst2Aligned) - build_options += " -D DST2_ALIGNED"; - if (dst3Aligned) - build_options += " -D DST3_ALIGNED"; - - const DeviceInfo& devInfo = clCtx->getDeviceInfo(); - - // TODO Workaround for issues. Need to investigate a problem. - if (channels == 2 - && devInfo.deviceType == CVCL_DEVICE_TYPE_CPU - && devInfo.platform->platformVendor.find("Intel") != std::string::npos - && (devInfo.deviceVersion.find("Build 56860") != std::string::npos - || devInfo.deviceVersion.find("Build 76921") != std::string::npos - || devInfo.deviceVersion.find("Build 78712") != std::string::npos)) - build_options += " -D BYPASS_VSTORE=true"; - - size_t globalThreads[3] = { divUp(src.cols, VEC_SIZE), src.rows, 1 }; - openCLExecuteKernel(clCtx, &split_mat, kernelName, globalThreads, NULL, args, -1, -1, build_options.c_str()); - } - static void split(const oclMat &mat_src, oclMat *mat_dst) - { - CV_Assert(mat_dst); - - int depth = mat_src.depth(); - int num_channels = mat_src.channels(); - Size size = mat_src.size(); - - if (num_channels == 1) - { - mat_src.copyTo(mat_dst[0]); - return; - } - - for (int i = 0; i < mat_src.oclchannels(); i++) - mat_dst[i].create(size, CV_MAKETYPE(depth, 1)); - - split_vector_run(mat_src, mat_dst); - } - } - } -} - -void cv::ocl::merge(const oclMat *src, size_t n, oclMat &dst) -{ - split_merge::merge(src, n, dst); -} -void cv::ocl::merge(const std::vector &src, oclMat &dst) -{ - split_merge::merge(&src[0], src.size(), dst); -} - -void cv::ocl::split(const oclMat &src, oclMat *dst) -{ - split_merge::split(src, dst); -} -void cv::ocl::split(const oclMat &src, std::vector &dst) -{ - dst.resize(src.oclchannels()); // TODO Why oclchannels? - if(src.oclchannels() > 0) - split_merge::split(src, &dst[0]); -} diff --git a/modules/ocl/src/stereo_csbp.cpp b/modules/ocl/src/stereo_csbp.cpp deleted file mode 100644 index 2f9391c00..000000000 --- a/modules/ocl/src/stereo_csbp.cpp +++ /dev/null @@ -1,698 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -namespace cv -{ - namespace ocl - { - namespace stereoCSBP - { - static inline int divUp(int total, int grain) - { - return (total + grain - 1) / grain; - } - static String get_kernel_name(String kernel_name, int data_type) - { - return kernel_name + (data_type == CV_16S ? "0" : "1"); - } - using cv::ocl::StereoConstantSpaceBP; - ////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////init_data_cost////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - static void init_data_cost_caller(const oclMat &left, const oclMat &right, oclMat &temp, - StereoConstantSpaceBP &rthis, - int msg_step, int h, int w, int level) - { - Context *clCxt = left.clCxt; - int data_type = rthis.msg_type; - int channels = left.oclchannels(); - - String kernelName = get_kernel_name("init_data_cost_", data_type); - - cl_kernel kernel = openCLGetKernelFromSource(clCxt, &stereocsbp, kernelName); - - //size_t blockSize = 256; - size_t localThreads[] = {32, 8 ,1}; - size_t globalThreads[] = {divUp(w, localThreads[0]) *localThreads[0], - divUp(h, localThreads[1]) *localThreads[1], - 1 - }; - - int cdisp_step1 = msg_step * h; - openCLVerifyKernel(clCxt, kernel, localThreads); - openCLSafeCall(clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&temp.data)); - openCLSafeCall(clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&left.data)); - openCLSafeCall(clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&right.data)); - openCLSafeCall(clSetKernelArg(kernel, 3, sizeof(cl_int), (void *)&h)); - openCLSafeCall(clSetKernelArg(kernel, 4, sizeof(cl_int), (void *)&w)); - openCLSafeCall(clSetKernelArg(kernel, 5, sizeof(cl_int), (void *)&level)); - openCLSafeCall(clSetKernelArg(kernel, 6, sizeof(cl_int), (void *)&channels)); - openCLSafeCall(clSetKernelArg(kernel, 7, sizeof(cl_int), (void *)&msg_step)); - openCLSafeCall(clSetKernelArg(kernel, 8, sizeof(cl_float), (void *)&rthis.data_weight)); - openCLSafeCall(clSetKernelArg(kernel, 9, sizeof(cl_float), (void *)&rthis.max_data_term)); - openCLSafeCall(clSetKernelArg(kernel, 10, sizeof(cl_int), (void *)&cdisp_step1)); - openCLSafeCall(clSetKernelArg(kernel, 11, sizeof(cl_int), (void *)&rthis.min_disp_th)); - openCLSafeCall(clSetKernelArg(kernel, 12, sizeof(cl_int), (void *)&left.step)); - openCLSafeCall(clSetKernelArg(kernel, 13, sizeof(cl_int), (void *)&rthis.ndisp)); - openCLSafeCall(clEnqueueNDRangeKernel(*(cl_command_queue*)getClCommandQueuePtr(), kernel, 2, NULL, - globalThreads, localThreads, 0, NULL, NULL)); - - clFinish(*(cl_command_queue*)getClCommandQueuePtr()); - openCLSafeCall(clReleaseKernel(kernel)); - } - - static void init_data_cost_reduce_caller(const oclMat &left, const oclMat &right, oclMat &temp, - StereoConstantSpaceBP &rthis, - int msg_step, int h, int w, int level) - { - - Context *clCxt = left.clCxt; - int data_type = rthis.msg_type; - int channels = left.oclchannels(); - int win_size = (int)std::pow(2.f, level); - - String kernelName = get_kernel_name("init_data_cost_reduce_", data_type); - - cl_kernel kernel = openCLGetKernelFromSource(clCxt, &stereocsbp, kernelName); - - const int threadsNum = 256; - //size_t blockSize = threadsNum; - size_t localThreads[3] = {win_size, 1, threadsNum / win_size}; - size_t globalThreads[3] = { w *localThreads[0], - h * divUp(rthis.ndisp, localThreads[2]) *localThreads[1], 1 * localThreads[2] - }; - - int local_mem_size = threadsNum * sizeof(float); - int cdisp_step1 = msg_step * h; - - openCLVerifyKernel(clCxt, kernel, localThreads); - - openCLSafeCall(clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&temp.data)); - openCLSafeCall(clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&left.data)); - openCLSafeCall(clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&right.data)); - openCLSafeCall(clSetKernelArg(kernel, 3, local_mem_size, (void *)NULL)); - openCLSafeCall(clSetKernelArg(kernel, 4, sizeof(cl_int), (void *)&level)); - openCLSafeCall(clSetKernelArg(kernel, 5, sizeof(cl_int), (void *)&left.rows)); - openCLSafeCall(clSetKernelArg(kernel, 6, sizeof(cl_int), (void *)&left.cols)); - openCLSafeCall(clSetKernelArg(kernel, 7, sizeof(cl_int), (void *)&h)); - openCLSafeCall(clSetKernelArg(kernel, 8, sizeof(cl_int), (void *)&win_size)); - openCLSafeCall(clSetKernelArg(kernel, 9, sizeof(cl_int), (void *)&channels)); - openCLSafeCall(clSetKernelArg(kernel, 10, sizeof(cl_int), (void *)&rthis.ndisp)); - openCLSafeCall(clSetKernelArg(kernel, 11, sizeof(cl_int), (void *)&left.step)); - openCLSafeCall(clSetKernelArg(kernel, 12, sizeof(cl_float), (void *)&rthis.data_weight)); - openCLSafeCall(clSetKernelArg(kernel, 13, sizeof(cl_float), (void *)&rthis.max_data_term)); - openCLSafeCall(clSetKernelArg(kernel, 14, sizeof(cl_int), (void *)&rthis.min_disp_th)); - openCLSafeCall(clSetKernelArg(kernel, 15, sizeof(cl_int), (void *)&cdisp_step1)); - openCLSafeCall(clSetKernelArg(kernel, 16, sizeof(cl_int), (void *)&msg_step)); - openCLSafeCall(clEnqueueNDRangeKernel(*(cl_command_queue*)getClCommandQueuePtr(), kernel, 3, NULL, - globalThreads, localThreads, 0, NULL, NULL)); - clFinish(*(cl_command_queue*)getClCommandQueuePtr()); - openCLSafeCall(clReleaseKernel(kernel)); - } - - static void get_first_initial_local_caller(uchar *data_cost_selected, uchar *disp_selected_pyr, - oclMat &temp, StereoConstantSpaceBP &rthis, - int h, int w, int nr_plane, int msg_step) - { - Context *clCxt = temp.clCxt; - int data_type = rthis.msg_type; - - String kernelName = get_kernel_name("get_first_k_initial_local_", data_type); - - cl_kernel kernel = openCLGetKernelFromSource(clCxt, &stereocsbp, kernelName); - - //size_t blockSize = 256; - size_t localThreads[] = {32, 8 ,1}; - size_t globalThreads[] = { roundUp(w, localThreads[0]), roundUp(h, localThreads[1]), 1 }; - - int disp_step = msg_step * h; - openCLVerifyKernel(clCxt, kernel, localThreads); - openCLSafeCall(clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&data_cost_selected)); - openCLSafeCall(clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&disp_selected_pyr)); - openCLSafeCall(clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&temp.data)); - openCLSafeCall(clSetKernelArg(kernel, 3, sizeof(cl_int), (void *)&h)); - openCLSafeCall(clSetKernelArg(kernel, 4, sizeof(cl_int), (void *)&w)); - openCLSafeCall(clSetKernelArg(kernel, 5, sizeof(cl_int), (void *)&nr_plane)); - openCLSafeCall(clSetKernelArg(kernel, 6, sizeof(cl_int), (void *)&msg_step)); - openCLSafeCall(clSetKernelArg(kernel, 7, sizeof(cl_int), (void *)&disp_step)); - openCLSafeCall(clSetKernelArg(kernel, 8, sizeof(cl_int), (void *)&rthis.ndisp)); - openCLSafeCall(clEnqueueNDRangeKernel(*(cl_command_queue*)getClCommandQueuePtr(), kernel, 2, NULL, - globalThreads, localThreads, 0, NULL, NULL)); - - clFinish(*(cl_command_queue*)getClCommandQueuePtr()); - openCLSafeCall(clReleaseKernel(kernel)); - } - static void get_first_initial_global_caller(uchar *data_cost_selected, uchar *disp_selected_pyr, - oclMat &temp, StereoConstantSpaceBP &rthis, - int h, int w, int nr_plane, int msg_step) - { - Context *clCxt = temp.clCxt; - int data_type = rthis.msg_type; - - String kernelName = get_kernel_name("get_first_k_initial_global_", data_type); - - cl_kernel kernel = openCLGetKernelFromSource(clCxt, &stereocsbp, kernelName); - - //size_t blockSize = 256; - size_t localThreads[] = {32, 8, 1}; - size_t globalThreads[] = {divUp(w, localThreads[0]) *localThreads[0], - divUp(h, localThreads[1]) *localThreads[1], - 1 - }; - - int disp_step = msg_step * h; - openCLVerifyKernel(clCxt, kernel, localThreads); - openCLSafeCall(clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&data_cost_selected)); - openCLSafeCall(clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&disp_selected_pyr)); - openCLSafeCall(clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&temp.data)); - openCLSafeCall(clSetKernelArg(kernel, 3, sizeof(cl_int), (void *)&h)); - openCLSafeCall(clSetKernelArg(kernel, 4, sizeof(cl_int), (void *)&w)); - openCLSafeCall(clSetKernelArg(kernel, 5, sizeof(cl_int), (void *)&nr_plane)); - openCLSafeCall(clSetKernelArg(kernel, 6, sizeof(cl_int), (void *)&msg_step)); - openCLSafeCall(clSetKernelArg(kernel, 7, sizeof(cl_int), (void *)&disp_step)); - openCLSafeCall(clSetKernelArg(kernel, 8, sizeof(cl_int), (void *)&rthis.ndisp)); - openCLSafeCall(clEnqueueNDRangeKernel(*(cl_command_queue*)getClCommandQueuePtr(), kernel, 2, NULL, - globalThreads, localThreads, 0, NULL, NULL)); - - clFinish(*(cl_command_queue*)getClCommandQueuePtr()); - openCLSafeCall(clReleaseKernel(kernel)); - } - - static void init_data_cost(const oclMat &left, const oclMat &right, oclMat &temp, StereoConstantSpaceBP &rthis, - uchar *disp_selected_pyr, uchar *data_cost_selected, - size_t msg_step, int h, int w, int level, int nr_plane) - { - - if(level <= 1) - init_data_cost_caller(left, right, temp, rthis, msg_step, h, w, level); - else - init_data_cost_reduce_caller(left, right, temp, rthis, msg_step, h, w, level); - - if(rthis.use_local_init_data_cost == true) - { - get_first_initial_local_caller(data_cost_selected, disp_selected_pyr, temp, rthis, h, w, nr_plane, msg_step); - } - else - { - get_first_initial_global_caller(data_cost_selected, disp_selected_pyr, temp, rthis, h, w, - nr_plane, msg_step); - } - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////compute_data_cost////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////////// - static void compute_data_cost_caller(uchar *disp_selected_pyr, uchar *data_cost, - StereoConstantSpaceBP &rthis, int msg_step1, - int msg_step2, const oclMat &left, const oclMat &right, int h, - int w, int h2, int level, int nr_plane) - { - Context *clCxt = left.clCxt; - int channels = left.oclchannels(); - int data_type = rthis.msg_type; - - String kernelName = get_kernel_name("compute_data_cost_", data_type); - - cl_kernel kernel = openCLGetKernelFromSource(clCxt, &stereocsbp, kernelName); - - size_t localThreads[] = { 32, 8, 1 }; - size_t globalThreads[] = { roundUp(w, localThreads[0]), roundUp(h, localThreads[1]), 1 }; - - int disp_step1 = msg_step1 * h; - int disp_step2 = msg_step2 * h2; - openCLVerifyKernel(clCxt, kernel, localThreads); - openCLSafeCall(clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&disp_selected_pyr)); - openCLSafeCall(clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&data_cost)); - openCLSafeCall(clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&left.data)); - openCLSafeCall(clSetKernelArg(kernel, 3, sizeof(cl_mem), (void *)&right.data)); - openCLSafeCall(clSetKernelArg(kernel, 4, sizeof(cl_int), (void *)&h)); - openCLSafeCall(clSetKernelArg(kernel, 5, sizeof(cl_int), (void *)&w)); - openCLSafeCall(clSetKernelArg(kernel, 6, sizeof(cl_int), (void *)&level)); - openCLSafeCall(clSetKernelArg(kernel, 7, sizeof(cl_int), (void *)&nr_plane)); - openCLSafeCall(clSetKernelArg(kernel, 8, sizeof(cl_int), (void *)&channels)); - openCLSafeCall(clSetKernelArg(kernel, 9, sizeof(cl_int), (void *)&msg_step1)); - openCLSafeCall(clSetKernelArg(kernel, 10, sizeof(cl_int), (void *)&msg_step2)); - openCLSafeCall(clSetKernelArg(kernel, 11, sizeof(cl_int), (void *)&disp_step1)); - openCLSafeCall(clSetKernelArg(kernel, 12, sizeof(cl_int), (void *)&disp_step2)); - openCLSafeCall(clSetKernelArg(kernel, 13, sizeof(cl_float), (void *)&rthis.data_weight)); - openCLSafeCall(clSetKernelArg(kernel, 14, sizeof(cl_float), (void *)&rthis.max_data_term)); - openCLSafeCall(clSetKernelArg(kernel, 15, sizeof(cl_int), (void *)&left.step)); - openCLSafeCall(clSetKernelArg(kernel, 16, sizeof(cl_int), (void *)&rthis.min_disp_th)); - openCLSafeCall(clEnqueueNDRangeKernel(*(cl_command_queue*)getClCommandQueuePtr(), kernel, 2, NULL, - globalThreads, localThreads, 0, NULL, NULL)); - - clFinish(*(cl_command_queue*)getClCommandQueuePtr()); - openCLSafeCall(clReleaseKernel(kernel)); - } - static void compute_data_cost_reduce_caller(uchar *disp_selected_pyr, uchar *data_cost, - StereoConstantSpaceBP &rthis, int msg_step1, - int msg_step2, const oclMat &left, const oclMat &right, int h, - int w, int h2, int level, int nr_plane) - { - Context *clCxt = left.clCxt; - int data_type = rthis.msg_type; - int channels = left.oclchannels(); - int win_size = (int)std::pow(2.f, level); - - String kernelName = get_kernel_name("compute_data_cost_reduce_", data_type); - - cl_kernel kernel = openCLGetKernelFromSource(clCxt, &stereocsbp, kernelName); - - const size_t threadsNum = 256; - //size_t blockSize = threadsNum; - size_t localThreads[3] = { win_size, 1, threadsNum / win_size }; - size_t globalThreads[3] = { w *localThreads[0], - h * divUp(nr_plane, localThreads[2]) *localThreads[1], 1 * localThreads[2] - }; - - int disp_step1 = msg_step1 * h; - int disp_step2 = msg_step2 * h2; - size_t local_mem_size = threadsNum * sizeof(float); - openCLVerifyKernel(clCxt, kernel, localThreads); - openCLSafeCall(clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&disp_selected_pyr)); - openCLSafeCall(clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&data_cost)); - openCLSafeCall(clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&left.data)); - openCLSafeCall(clSetKernelArg(kernel, 3, sizeof(cl_mem), (void *)&right.data)); - openCLSafeCall(clSetKernelArg(kernel, 4, local_mem_size, (void *)NULL)); - openCLSafeCall(clSetKernelArg(kernel, 5, sizeof(cl_int), (void *)&level)); - openCLSafeCall(clSetKernelArg(kernel, 6, sizeof(cl_int), (void *)&left.rows)); - openCLSafeCall(clSetKernelArg(kernel, 7, sizeof(cl_int), (void *)&left.cols)); - openCLSafeCall(clSetKernelArg(kernel, 8, sizeof(cl_int), (void *)&h)); - openCLSafeCall(clSetKernelArg(kernel, 9, sizeof(cl_int), (void *)&nr_plane)); - openCLSafeCall(clSetKernelArg(kernel, 10, sizeof(cl_int), (void *)&channels)); - openCLSafeCall(clSetKernelArg(kernel, 11, sizeof(cl_int), (void *)&win_size)); - openCLSafeCall(clSetKernelArg(kernel, 12, sizeof(cl_int), (void *)&msg_step1)); - openCLSafeCall(clSetKernelArg(kernel, 13, sizeof(cl_int), (void *)&msg_step2)); - openCLSafeCall(clSetKernelArg(kernel, 14, sizeof(cl_int), (void *)&disp_step1)); - openCLSafeCall(clSetKernelArg(kernel, 15, sizeof(cl_int), (void *)&disp_step2)); - openCLSafeCall(clSetKernelArg(kernel, 16, sizeof(cl_float), (void *)&rthis.data_weight)); - openCLSafeCall(clSetKernelArg(kernel, 17, sizeof(cl_float), (void *)&rthis.max_data_term)); - openCLSafeCall(clSetKernelArg(kernel, 18, sizeof(cl_int), (void *)&left.step)); - openCLSafeCall(clSetKernelArg(kernel, 19, sizeof(cl_int), (void *)&rthis.min_disp_th)); - openCLSafeCall(clEnqueueNDRangeKernel(*(cl_command_queue*)getClCommandQueuePtr(), kernel, 3, NULL, - globalThreads, localThreads, 0, NULL, NULL)); - - clFinish(*(cl_command_queue*)getClCommandQueuePtr()); - openCLSafeCall(clReleaseKernel(kernel)); - } - static void compute_data_cost(uchar *disp_selected_pyr, uchar *data_cost, StereoConstantSpaceBP &rthis, - int msg_step1, int msg_step2, const oclMat &left, const oclMat &right, int h, int w, - int h2, int level, int nr_plane) - { - if(level <= 1) - compute_data_cost_caller(disp_selected_pyr, data_cost, rthis, msg_step1, msg_step2, - left, right, h, w, h2, level, nr_plane); - else - compute_data_cost_reduce_caller(disp_selected_pyr, data_cost, rthis, msg_step1, msg_step2, - left, right, h, w, h2, level, nr_plane); - } - //////////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////init message////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////////// - static void init_message(uchar *u_new, uchar *d_new, uchar *l_new, uchar *r_new, - uchar *u_cur, uchar *d_cur, uchar *l_cur, uchar *r_cur, - uchar *disp_selected_pyr_new, uchar *disp_selected_pyr_cur, - uchar *data_cost_selected, uchar *data_cost, oclMat &temp, StereoConstantSpaceBP rthis, - size_t msg_step1, size_t msg_step2, int h, int w, int nr_plane, - int h2, int w2, int nr_plane2) - { - Context *clCxt = temp.clCxt; - int data_type = rthis.msg_type; - - String kernelName = get_kernel_name("init_message_", data_type); - - cl_kernel kernel = openCLGetKernelFromSource(clCxt, &stereocsbp, kernelName); - - //size_t blockSize = 256; - size_t localThreads[] = {32, 8, 1}; - size_t globalThreads[] = { roundUp(w, localThreads[0]), roundUp(h, localThreads[1]), 1 }; - - int disp_step1 = msg_step1 * h; - int disp_step2 = msg_step2 * h2; - openCLVerifyKernel(clCxt, kernel, localThreads); - openCLSafeCall(clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&u_new)); - openCLSafeCall(clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&d_new)); - openCLSafeCall(clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&l_new)); - openCLSafeCall(clSetKernelArg(kernel, 3, sizeof(cl_mem), (void *)&r_new)); - openCLSafeCall(clSetKernelArg(kernel, 4, sizeof(cl_mem), (void *)&u_cur)); - openCLSafeCall(clSetKernelArg(kernel, 5, sizeof(cl_mem), (void *)&d_cur)); - openCLSafeCall(clSetKernelArg(kernel, 6, sizeof(cl_mem), (void *)&l_cur)); - openCLSafeCall(clSetKernelArg(kernel, 7, sizeof(cl_mem), (void *)&r_cur)); - openCLSafeCall(clSetKernelArg(kernel, 8, sizeof(cl_mem), (void *)&temp.data)); - openCLSafeCall(clSetKernelArg(kernel, 9, sizeof(cl_mem), (void *)&disp_selected_pyr_new)); - openCLSafeCall(clSetKernelArg(kernel, 10, sizeof(cl_mem), (void *)&disp_selected_pyr_cur)); - openCLSafeCall(clSetKernelArg(kernel, 11, sizeof(cl_mem), (void *)&data_cost_selected)); - openCLSafeCall(clSetKernelArg(kernel, 12, sizeof(cl_mem), (void *)&data_cost)); - openCLSafeCall(clSetKernelArg(kernel, 13, sizeof(cl_int), (void *)&h)); - openCLSafeCall(clSetKernelArg(kernel, 14, sizeof(cl_int), (void *)&w)); - openCLSafeCall(clSetKernelArg(kernel, 15, sizeof(cl_int), (void *)&nr_plane)); - openCLSafeCall(clSetKernelArg(kernel, 16, sizeof(cl_int), (void *)&h2)); - openCLSafeCall(clSetKernelArg(kernel, 17, sizeof(cl_int), (void *)&w2)); - openCLSafeCall(clSetKernelArg(kernel, 18, sizeof(cl_int), (void *)&nr_plane2)); - openCLSafeCall(clSetKernelArg(kernel, 19, sizeof(cl_int), (void *)&disp_step1)); - openCLSafeCall(clSetKernelArg(kernel, 20, sizeof(cl_int), (void *)&disp_step2)); - openCLSafeCall(clSetKernelArg(kernel, 21, sizeof(cl_int), (void *)&msg_step1)); - openCLSafeCall(clSetKernelArg(kernel, 22, sizeof(cl_int), (void *)&msg_step2)); - openCLSafeCall(clEnqueueNDRangeKernel(*(cl_command_queue*)getClCommandQueuePtr(), kernel, 2, NULL, - globalThreads, localThreads, 0, NULL, NULL)); - - clFinish(*(cl_command_queue*)getClCommandQueuePtr()); - openCLSafeCall(clReleaseKernel(kernel)); - } - //////////////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////calc_all_iterations//////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////////// - static void calc_all_iterations_caller(uchar *u, uchar *d, uchar *l, uchar *r, uchar *data_cost_selected, - uchar *disp_selected_pyr, oclMat &temp, StereoConstantSpaceBP rthis, - int msg_step, int h, int w, int nr_plane, int i) - { - Context *clCxt = temp.clCxt; - int data_type = rthis.msg_type; - - String kernelName = get_kernel_name("compute_message_", data_type); - - cl_kernel kernel = openCLGetKernelFromSource(clCxt, &stereocsbp, kernelName); - size_t localThreads[] = {32, 8, 1}; - size_t globalThreads[] = {divUp(w, (localThreads[0]) << 1) *localThreads[0], - divUp(h, localThreads[1]) *localThreads[1], - 1 - }; - - int disp_step = msg_step * h; - openCLVerifyKernel(clCxt, kernel, localThreads); - openCLSafeCall(clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&u)); - openCLSafeCall(clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&d)); - openCLSafeCall(clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&l)); - openCLSafeCall(clSetKernelArg(kernel, 3, sizeof(cl_mem), (void *)&r)); - openCLSafeCall(clSetKernelArg(kernel, 4, sizeof(cl_mem), (void *)&data_cost_selected)); - openCLSafeCall(clSetKernelArg(kernel, 5, sizeof(cl_mem), (void *)&disp_selected_pyr)); - openCLSafeCall(clSetKernelArg(kernel, 6, sizeof(cl_mem), (void *)&temp.data)); - openCLSafeCall(clSetKernelArg(kernel, 7, sizeof(cl_int), (void *)&h)); - openCLSafeCall(clSetKernelArg(kernel, 8, sizeof(cl_int), (void *)&w)); - openCLSafeCall(clSetKernelArg(kernel, 9, sizeof(cl_int), (void *)&nr_plane)); - openCLSafeCall(clSetKernelArg(kernel, 10, sizeof(cl_int), (void *)&i)); - openCLSafeCall(clSetKernelArg(kernel, 11, sizeof(cl_float), (void *)&rthis.max_disc_term)); - openCLSafeCall(clSetKernelArg(kernel, 12, sizeof(cl_int), (void *)&disp_step)); - openCLSafeCall(clSetKernelArg(kernel, 13, sizeof(cl_int), (void *)&msg_step)); - openCLSafeCall(clSetKernelArg(kernel, 14, sizeof(cl_float), (void *)&rthis.disc_single_jump)); - openCLSafeCall(clEnqueueNDRangeKernel(*(cl_command_queue*)getClCommandQueuePtr(), kernel, 2, NULL, - globalThreads, localThreads, 0, NULL, NULL)); - - clFinish(*(cl_command_queue*)getClCommandQueuePtr()); - openCLSafeCall(clReleaseKernel(kernel)); - } - static void calc_all_iterations(uchar *u, uchar *d, uchar *l, uchar *r, uchar *data_cost_selected, - uchar *disp_selected_pyr, oclMat &temp, StereoConstantSpaceBP rthis, - int msg_step, int h, int w, int nr_plane) - { - for(int t = 0; t < rthis.iters; t++) - calc_all_iterations_caller(u, d, l, r, data_cost_selected, disp_selected_pyr, temp, rthis, - msg_step, h, w, nr_plane, t & 1); - } - - /////////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////compute_disp//////////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////////////////////// - static void compute_disp(uchar *u, uchar *d, uchar *l, uchar *r, uchar *data_cost_selected, - uchar *disp_selected_pyr, StereoConstantSpaceBP &rthis, size_t msg_step, - oclMat &disp, int nr_plane) - { - Context *clCxt = disp.clCxt; - int data_type = rthis.msg_type; - - String kernelName = get_kernel_name("compute_disp_", data_type); - - cl_kernel kernel = openCLGetKernelFromSource(clCxt, &stereocsbp, kernelName); - - //size_t blockSize = 256; - size_t localThreads[] = { 32, 8, 1 }; - size_t globalThreads[] = { roundUp(disp.cols, localThreads[0]), roundUp(disp.rows, localThreads[1]), 1 }; - - int step_size = disp.step / disp.elemSize(); - int disp_step = disp.rows * msg_step; - openCLVerifyKernel(clCxt, kernel, localThreads); - openCLSafeCall(clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&u)); - openCLSafeCall(clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&d)); - openCLSafeCall(clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&l)); - openCLSafeCall(clSetKernelArg(kernel, 3, sizeof(cl_mem), (void *)&r)); - openCLSafeCall(clSetKernelArg(kernel, 4, sizeof(cl_mem), (void *)&data_cost_selected)); - openCLSafeCall(clSetKernelArg(kernel, 5, sizeof(cl_mem), (void *)&disp_selected_pyr)); - openCLSafeCall(clSetKernelArg(kernel, 6, sizeof(cl_mem), (void *)&disp.data)); - openCLSafeCall(clSetKernelArg(kernel, 7, sizeof(cl_int), (void *)&step_size)); - openCLSafeCall(clSetKernelArg(kernel, 8, sizeof(cl_int), (void *)&disp.cols)); - openCLSafeCall(clSetKernelArg(kernel, 9, sizeof(cl_int), (void *)&disp.rows)); - openCLSafeCall(clSetKernelArg(kernel, 10, sizeof(cl_int), (void *)&nr_plane)); - openCLSafeCall(clSetKernelArg(kernel, 11, sizeof(cl_int), (void *)&msg_step)); - openCLSafeCall(clSetKernelArg(kernel, 12, sizeof(cl_int), (void *)&disp_step)); - openCLSafeCall(clEnqueueNDRangeKernel(*(cl_command_queue*)getClCommandQueuePtr(), kernel, 2, NULL, - globalThreads, localThreads, 0, NULL, NULL)); - - clFinish(*(cl_command_queue*)getClCommandQueuePtr()); - openCLSafeCall(clReleaseKernel(kernel)); - } - } - } -} -namespace -{ - const float DEFAULT_MAX_DATA_TERM = 30.0f; - const float DEFAULT_DATA_WEIGHT = 1.0f; - const float DEFAULT_MAX_DISC_TERM = 160.0f; - const float DEFAULT_DISC_SINGLE_JUMP = 10.0f; -} - -void cv::ocl::StereoConstantSpaceBP::estimateRecommendedParams(int width, int height, int &ndisp, int &iters, int &levels, int &nr_plane) -{ - ndisp = (int) ((float) width / 3.14f); - if ((ndisp & 1) != 0) - ndisp++; - - int mm = ::max(width, height); - iters = mm / 100 + ((mm > 1200) ? - 4 : 4); - - levels = (int)::log(static_cast(mm)) * 2 / 3; - if (levels == 0) levels++; - - nr_plane = (int) ((float) ndisp / std::pow(2.0, levels + 1)); -} - -cv::ocl::StereoConstantSpaceBP::StereoConstantSpaceBP(int ndisp_, int iters_, int levels_, int nr_plane_, - int msg_type_) - - : ndisp(ndisp_), iters(iters_), levels(levels_), nr_plane(nr_plane_), - max_data_term(DEFAULT_MAX_DATA_TERM), data_weight(DEFAULT_DATA_WEIGHT), - max_disc_term(DEFAULT_MAX_DISC_TERM), disc_single_jump(DEFAULT_DISC_SINGLE_JUMP), min_disp_th(0), - msg_type(msg_type_), use_local_init_data_cost(true) -{ - CV_Assert(msg_type_ == CV_32F || msg_type_ == CV_16S); -} - - -cv::ocl::StereoConstantSpaceBP::StereoConstantSpaceBP(int ndisp_, int iters_, int levels_, int nr_plane_, - float max_data_term_, float data_weight_, float max_disc_term_, float disc_single_jump_, - int min_disp_th_, int msg_type_) - : ndisp(ndisp_), iters(iters_), levels(levels_), nr_plane(nr_plane_), - max_data_term(max_data_term_), data_weight(data_weight_), - max_disc_term(max_disc_term_), disc_single_jump(disc_single_jump_), min_disp_th(min_disp_th_), - msg_type(msg_type_), use_local_init_data_cost(true) -{ - CV_Assert(msg_type_ == CV_32F || msg_type_ == CV_16S); -} - -template -static void csbp_operator(StereoConstantSpaceBP &rthis, oclMat u[2], oclMat d[2], oclMat l[2], oclMat r[2], - oclMat disp_selected_pyr[2], oclMat &data_cost, oclMat &data_cost_selected, - oclMat &temp, oclMat &out, const oclMat &left, const oclMat &right, oclMat &disp) -{ - CV_DbgAssert(0 < rthis.ndisp && 0 < rthis.iters && 0 < rthis.levels && 0 < rthis.nr_plane - && left.rows == right.rows && left.cols == right.cols && left.type() == right.type()); - - CV_Assert(rthis.levels <= 8 && (left.type() == CV_8UC1 || left.type() == CV_8UC3)); - - const Scalar zero = Scalar::all(0); - - ////////////////////////////////////Init/////////////////////////////////////////////////// - int rows = left.rows; - int cols = left.cols; - - rthis.levels = min(rthis.levels, int(log((double)rthis.ndisp) / log(2.0))); - int levels = rthis.levels; - - AutoBuffer buf(levels * 4); - - int *cols_pyr = buf; - int *rows_pyr = cols_pyr + levels; - int *nr_plane_pyr = rows_pyr + levels; - int *step_pyr = nr_plane_pyr + levels; - - cols_pyr[0] = cols; - rows_pyr[0] = rows; - nr_plane_pyr[0] = rthis.nr_plane; - - const int n = 64; - step_pyr[0] = alignSize(cols * sizeof(T), n) / sizeof(T); - for (int i = 1; i < levels; i++) - { - cols_pyr[i] = cols_pyr[i - 1] / 2; - rows_pyr[i] = rows_pyr[i - 1]/ 2; - - nr_plane_pyr[i] = nr_plane_pyr[i - 1] * 2; - - step_pyr[i] = alignSize(cols_pyr[i] * sizeof(T), n) / sizeof(T); - } - - Size msg_size(step_pyr[0], rows * nr_plane_pyr[0]); - Size data_cost_size(step_pyr[0], rows * nr_plane_pyr[0] * 2); - - u[0].create(msg_size, DataType::type); - d[0].create(msg_size, DataType::type); - l[0].create(msg_size, DataType::type); - r[0].create(msg_size, DataType::type); - - u[1].create(msg_size, DataType::type); - d[1].create(msg_size, DataType::type); - l[1].create(msg_size, DataType::type); - r[1].create(msg_size, DataType::type); - - disp_selected_pyr[0].create(msg_size, DataType::type); - disp_selected_pyr[1].create(msg_size, DataType::type); - - data_cost.create(data_cost_size, DataType::type); - data_cost_selected.create(msg_size, DataType::type); - - Size temp_size = data_cost_size; - if (data_cost_size.width * data_cost_size.height < step_pyr[0] * rows_pyr[levels - 1] * rthis.ndisp) - temp_size = Size(step_pyr[0], rows_pyr[levels - 1] * rthis.ndisp); - - temp.create(temp_size, DataType::type); - temp = zero; - - ///////////////////////////////// Compute//////////////////////////////////////////////// - - //csbp::load_constants(rthis.ndisp, rthis.max_data_term, rthis.data_weight, - // rthis.max_disc_term, rthis.disc_single_jump, rthis.min_disp_th, left, right, temp); - - l[0] = zero; - d[0] = zero; - r[0] = zero; - u[0] = zero; - disp_selected_pyr[0] = zero; - - l[1] = zero; - d[1] = zero; - r[1] = zero; - u[1] = zero; - disp_selected_pyr[1] = zero; - - data_cost = zero; - - data_cost_selected = zero; - - int cur_idx = 0; - - for (int i = levels - 1; i >= 0; i--) - { - if (i == levels - 1) - { - cv::ocl::stereoCSBP::init_data_cost(left, right, temp, rthis, disp_selected_pyr[cur_idx].data, - data_cost_selected.data, step_pyr[0], rows_pyr[i], cols_pyr[i], - i, nr_plane_pyr[i]); - } - else - { - cv::ocl::stereoCSBP::compute_data_cost( - disp_selected_pyr[cur_idx].data, data_cost.data, rthis, step_pyr[0], - step_pyr[0], left, right, rows_pyr[i], cols_pyr[i], rows_pyr[i + 1], i, - nr_plane_pyr[i + 1]); - - int new_idx = (cur_idx + 1) & 1; - - cv::ocl::stereoCSBP::init_message(u[new_idx].data, d[new_idx].data, l[new_idx].data, r[new_idx].data, - u[cur_idx].data, d[cur_idx].data, l[cur_idx].data, r[cur_idx].data, - disp_selected_pyr[new_idx].data, disp_selected_pyr[cur_idx].data, - data_cost_selected.data, data_cost.data, temp, rthis, step_pyr[0], - step_pyr[0], rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], rows_pyr[i + 1], - cols_pyr[i + 1], nr_plane_pyr[i + 1]); - cur_idx = new_idx; - } - cv::ocl::stereoCSBP::calc_all_iterations(u[cur_idx].data, d[cur_idx].data, l[cur_idx].data, r[cur_idx].data, - data_cost_selected.data, disp_selected_pyr[cur_idx].data, temp, - rthis, step_pyr[0], rows_pyr[i], cols_pyr[i], nr_plane_pyr[i]); - } - - if (disp.empty()) - disp.create(rows, cols, CV_16S); - - out = ((disp.type() == CV_16S) ? disp : (out.create(rows, cols, CV_16S), out)); - out = zero; - - stereoCSBP::compute_disp(u[cur_idx].data, d[cur_idx].data, l[cur_idx].data, r[cur_idx].data, - data_cost_selected.data, disp_selected_pyr[cur_idx].data, rthis, step_pyr[0], - out, nr_plane_pyr[0]); - if (disp.type() != CV_16S) - out.convertTo(disp, disp.type()); -} - - -typedef void (*csbp_operator_t)(StereoConstantSpaceBP &rthis, oclMat u[2], oclMat d[2], oclMat l[2], oclMat r[2], - oclMat disp_selected_pyr[2], oclMat &data_cost, oclMat &data_cost_selected, - oclMat &temp, oclMat &out, const oclMat &left, const oclMat &right, oclMat &disp); - -const static csbp_operator_t operators[] = {0, 0, 0, csbp_operator, 0, csbp_operator, 0, 0}; - -void cv::ocl::StereoConstantSpaceBP::operator()(const oclMat &left, const oclMat &right, oclMat &disp) -{ - - CV_Assert(msg_type == CV_32F || msg_type == CV_16S); - operators[msg_type](*this, u, d, l, r, disp_selected_pyr, data_cost, data_cost_selected, temp, out, - left, right, disp); -} diff --git a/modules/ocl/src/stereobm.cpp b/modules/ocl/src/stereobm.cpp deleted file mode 100644 index 4bfa80f8f..000000000 --- a/modules/ocl/src/stereobm.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.com -// Xiaopeng Fu, xiaopeng@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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; -namespace cv -{ -namespace ocl -{ -namespace stereoBM -{ -///////////////////////////////////////////////////////////////////////// -//////////////////////////prefilter_xsbel//////////////////////////////// -//////////////////////////////////////////////////////////////////////// -static void prefilter_xsobel(const oclMat &input, oclMat &output, int prefilterCap) -{ - String kernelName = "prefilter_xsobel"; - - size_t blockSize = 1; - size_t globalThreads[3] = { input.cols, input.rows, 1 }; - size_t localThreads[3] = { blockSize, blockSize, 1 }; - - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&input.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&output.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&input.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&input.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&prefilterCap)); - - openCLExecuteKernel(Context::getContext(), &stereobm, kernelName, - globalThreads, localThreads, args, -1, -1); -} -////////////////////////////////////////////////////////////////////////// -//////////////////////////////common//////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -#define N_DISPARITIES 8 -#define ROWSperTHREAD 21 -#define BLOCK_W 128 - -//////////////////////////////////////////////////////////////////////////// -///////////////////////////////stereoBM_GPU//////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -static void stereo_bm(const oclMat &left, const oclMat &right, oclMat &disp, - int maxdisp, int winSize, oclMat &minSSD_buf) -{ - int winsz2 = winSize >> 1; - - String kernelName = "stereoKernel"; - - disp.setTo(Scalar_::all(0)); - minSSD_buf.setTo(Scalar_::all(0xFFFFFFFF)); - - size_t minssd_step = minSSD_buf.step / minSSD_buf.elemSize(); - size_t local_mem_size = (N_DISPARITIES * (BLOCK_W + 2 * winsz2)) * - sizeof(cl_uint); - //size_t blockSize = 1; - size_t localThreads[] = { BLOCK_W, 1, 1 }; - size_t globalThreads[] = { left.cols - maxdisp - 2 * winsz2, - divUp(left.rows - 2 * winsz2, ROWSperTHREAD), - 1 }; - - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&left.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&right.data)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&minSSD_buf.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&minssd_step)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&disp.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&disp.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&left.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&left.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&left.step)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&maxdisp)); - args.push_back(std::make_pair(local_mem_size, (void *)NULL)); - - char opt [128]; - sprintf(opt, "-D radius=%d", winsz2); - openCLExecuteKernel(Context::getContext(), &stereobm, kernelName, - globalThreads, localThreads, args, -1, -1, opt); -} -//////////////////////////////////////////////////////////////////////////// -///////////////////////////////postfilter_textureness/////////////////////// -//////////////////////////////////////////////////////////////////////////// -static void postfilter_textureness(oclMat &left, int winSize, - float avergeTexThreshold, oclMat &disparity) -{ - String kernelName = "textureness_kernel"; - - size_t blockSize = 1; - size_t localThreads[] = { BLOCK_W, blockSize ,1}; - size_t globalThreads[] = { left.cols, - divUp(left.rows, 2 * ROWSperTHREAD), - 1 }; - - size_t local_mem_size = (localThreads[0] + localThreads[0] + (winSize / 2) * 2) * sizeof(float); - - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&disparity.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&disparity.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&disparity.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&disparity.step)); - args.push_back(std::make_pair(sizeof(cl_mem), (void *)&left.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&left.rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&left.cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void *)&winSize)); - args.push_back(std::make_pair(sizeof(cl_float), (void *)&avergeTexThreshold)); - args.push_back(std::make_pair(local_mem_size, (void*)NULL)); - openCLExecuteKernel(Context::getContext(), &stereobm, kernelName, - globalThreads, localThreads, args, -1, -1); -} -////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////operator///////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -static void operator_(oclMat &minSSD, oclMat &leBuf, oclMat &riBuf, int preset, int ndisp, - int winSize, float avergeTexThreshold, const oclMat &left, - const oclMat &right, oclMat &disparity) - -{ - CV_DbgAssert(left.rows == right.rows && left.cols == right.cols); - CV_DbgAssert(left.type() == CV_8UC1); - CV_DbgAssert(right.type() == CV_8UC1); - - disparity.create(left.size(), CV_8UC1); - minSSD.create(left.size(), CV_32SC1); - - oclMat le_for_bm = left; - oclMat ri_for_bm = right; - - if (preset == cv::ocl::StereoBM_OCL::PREFILTER_XSOBEL) - { - leBuf.create( left.size(), left.type()); - riBuf.create(right.size(), right.type()); - - prefilter_xsobel( left, leBuf, 31); - prefilter_xsobel(right, riBuf, 31); - - le_for_bm = leBuf; - ri_for_bm = riBuf; - } - - stereo_bm(le_for_bm, ri_for_bm, disparity, ndisp, winSize, minSSD); - - if (avergeTexThreshold) - { - postfilter_textureness(le_for_bm, winSize, avergeTexThreshold, disparity); - } -} -} -} -} -const float defaultAvgTexThreshold = 3; - -cv::ocl::StereoBM_OCL::StereoBM_OCL() - : preset(BASIC_PRESET), ndisp(DEFAULT_NDISP), winSize(DEFAULT_WINSZ), - avergeTexThreshold(defaultAvgTexThreshold) {} - -cv::ocl::StereoBM_OCL::StereoBM_OCL(int preset_, int ndisparities_, int winSize_) - : preset(preset_), ndisp(ndisparities_), winSize(winSize_), - avergeTexThreshold(defaultAvgTexThreshold) -{ - const int max_supported_ndisp = 1 << (sizeof(unsigned char) * 8); - CV_Assert(0 < ndisp && ndisp <= max_supported_ndisp); - CV_Assert(ndisp % 8 == 0); - CV_Assert(winSize % 2 == 1); -} - -bool cv::ocl::StereoBM_OCL::checkIfGpuCallReasonable() -{ - return true; -} - -void cv::ocl::StereoBM_OCL::operator() ( const oclMat &left, const oclMat &right, - oclMat &disparity) -{ - cv::ocl::stereoBM::operator_(minSSD, leBuf, riBuf, preset, ndisp, winSize, avergeTexThreshold, left, right, disparity); -} diff --git a/modules/ocl/src/stereobp.cpp b/modules/ocl/src/stereobp.cpp deleted file mode 100644 index a564c3d33..000000000 --- a/modules/ocl/src/stereobp.cpp +++ /dev/null @@ -1,502 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.com -// Peng Xiao, pengxiao@outlook.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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -namespace cv -{ - namespace ocl - { - namespace stereoBP - { - ////////////////////////////////////////////////////////////////////////// - //////////////////////////////common//////////////////////////////////// - //////////////////////////////////////////////////////////////////////// - typedef struct - { - int cndisp; - float cmax_data_term; - float cdata_weight; - float cmax_disc_term; - float cdisc_single_jump; - } con_struct_t; - - cl_mem cl_con_struct = NULL; - static void load_constants(int ndisp, float max_data_term, float data_weight, - float max_disc_term, float disc_single_jump) - { - con_struct_t *con_struct = new con_struct_t; - con_struct -> cndisp = ndisp; - con_struct -> cmax_data_term = max_data_term; - con_struct -> cdata_weight = data_weight; - con_struct -> cmax_disc_term = max_disc_term; - con_struct -> cdisc_single_jump = disc_single_jump; - - Context* clCtx = Context::getContext(); - cl_context clContext = *(cl_context*)(clCtx->getOpenCLContextPtr()); - cl_command_queue clCmdQueue = *(cl_command_queue*)(clCtx->getOpenCLCommandQueuePtr()); - cl_con_struct = load_constant(clContext, clCmdQueue, (void *)con_struct, - sizeof(con_struct_t)); - - delete con_struct; - } - static void release_constants() - { - openCLFree(cl_con_struct); - } - - ///////////////////////////////////////////////////////////////////////////// - ///////////////////////////comp data//////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////// - static void comp_data_call(const oclMat &left, const oclMat &right, oclMat &data, int /*disp*/, - float /*cmax_data_term*/, float /*cdata_weight*/) - { - Context *clCxt = left.clCxt; - int channels = left.oclchannels(); - int data_type = data.type(); - - String kernelName = "comp_data"; - - std::vector > args; - - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&left.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&left.rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&left.cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&left.step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&right.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&right.step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&data.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&data.step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&cl_con_struct)); - - size_t gt[3] = {left.cols, left.rows, 1}, lt[3] = {16, 16, 1}; - - const int OPT_SIZE = 50; - char cn_opt [OPT_SIZE] = ""; - sprintf( cn_opt, "%s -D CN=%d", - (data_type == CV_16S ? "-D T_SHORT":"-D T_FLOAT"), - channels - ); - openCLExecuteKernel(clCxt, &stereobp, kernelName, gt, lt, args, -1, -1, cn_opt); - } - /////////////////////////////////////////////////////////////////////////////////// - /////////////////////////data set down//////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////////// - static void data_step_down_call(int dst_cols, int dst_rows, int src_rows, - const oclMat &src, oclMat &dst, int disp) - { - Context *clCxt = src.clCxt; - int data_type = src.type(); - - String kernelName = "data_step_down"; - - std::vector > args; - - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_rows)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&disp)); - - size_t gt[3] = {dst_cols, dst_rows, 1}, lt[3] = {16, 16, 1}; - const char* t_opt = data_type == CV_16S ? "-D T_SHORT":"-D T_FLOAT"; - openCLExecuteKernel(clCxt, &stereobp, kernelName, gt, lt, args, -1, -1, t_opt); - } - ///////////////////////////////////////////////////////////////////////////////// - ///////////////////////////live up message//////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////////// - static void level_up_message_call(int dst_cols, int dst_rows, int src_rows, - oclMat &src, oclMat &dst, int ndisp) - { - Context *clCxt = src.clCxt; - int data_type = src.type(); - - String kernelName = "level_up_message"; - std::vector > args; - - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src_rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&src.step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&dst.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst_cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&dst.step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&ndisp)); - - size_t gt[3] = {dst_cols, dst_rows, 1}, lt[3] = {16, 16, 1}; - const char* t_opt = data_type == CV_16S ? "-D T_SHORT":"-D T_FLOAT"; - openCLExecuteKernel(clCxt, &stereobp, kernelName, gt, lt, args, -1, -1, t_opt); - } - static void level_up_messages_calls(int dst_idx, int dst_cols, int dst_rows, int src_rows, - oclMat *mus, oclMat *mds, oclMat *mls, oclMat *mrs, - int ndisp) - { - int src_idx = (dst_idx + 1) & 1; - - level_up_message_call(dst_cols, dst_rows, src_rows, - mus[src_idx], mus[dst_idx], ndisp); - - level_up_message_call(dst_cols, dst_rows, src_rows, - mds[src_idx], mds[dst_idx], ndisp); - - level_up_message_call(dst_cols, dst_rows, src_rows, - mls[src_idx], mls[dst_idx], ndisp); - - level_up_message_call(dst_cols, dst_rows, src_rows, - mrs[src_idx], mrs[dst_idx], ndisp); - } - ////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////cals_all_iterations_call/////////////////////////// - ///////////////////////////////////////////////////////////////////////////////// - static void calc_all_iterations_call(int cols, int rows, oclMat &u, oclMat &d, - oclMat &l, oclMat &r, oclMat &data, - int t, int cndisp, float cmax_disc_term, - float cdisc_single_jump) - { - Context *clCxt = l.clCxt; - int data_type = u.type(); - - String kernelName = "one_iteration"; - - std::vector > args; - - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&u.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&u.step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&data.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&data.step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&d.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&l.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&r.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&t)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&rows)); - args.push_back( std::make_pair( sizeof(cl_float) , (void *)&cmax_disc_term)); - args.push_back( std::make_pair( sizeof(cl_float) , (void *)&cdisc_single_jump)); - - size_t gt[3] = {cols, rows, 1}, lt[3] = {16, 16, 1}; - char opt[80] = ""; - sprintf(opt, "-D %s -D CNDISP=%d", data_type == CV_16S ? "T_SHORT":"T_FLOAT", cndisp); - openCLExecuteKernel(clCxt, &stereobp, kernelName, gt, lt, args, -1, -1, opt); - } - - static void calc_all_iterations_calls(int cols, int rows, int iters, oclMat &u, - oclMat &d, oclMat &l, oclMat &r, - oclMat &data, int cndisp, float cmax_disc_term, - float cdisc_single_jump) - { - for(int t = 0; t < iters; ++t) - calc_all_iterations_call(cols, rows, u, d, l, r, data, t, cndisp, - cmax_disc_term, cdisc_single_jump); - } - /////////////////////////////////////////////////////////////////////////////// - ///////////////////////output/////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - static void output_call(const oclMat &u, const oclMat &d, const oclMat l, const oclMat &r, - const oclMat &data, oclMat &disp, int ndisp) - { - Context *clCxt = u.clCxt; - int data_type = u.type(); - - String kernelName = "output"; - - std::vector > args; - - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&u.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&u.step)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&d.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&l.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&r.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&data.data)); - args.push_back( std::make_pair( sizeof(cl_mem) , (void *)&disp.data)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&disp.rows)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&disp.cols)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&disp.step)); - args.push_back( std::make_pair( sizeof(cl_int) , (void *)&ndisp)); - - size_t gt[3] = {disp.cols, disp.rows, 1}, lt[3] = {16, 16, 1}; - const char* t_opt = data_type == CV_16S ? "-D T_SHORT":"-D T_FLOAT"; - openCLExecuteKernel(clCxt, &stereobp, kernelName, gt, lt, args, -1, -1, t_opt); - } - } - } -} -namespace -{ - const float DEFAULT_MAX_DATA_TERM = 10.0f; - const float DEFAULT_DATA_WEIGHT = 0.07f; - const float DEFAULT_MAX_DISC_TERM = 1.7f; - const float DEFAULT_DISC_SINGLE_JUMP = 1.0f; -} - -void cv::ocl::StereoBeliefPropagation::estimateRecommendedParams(int width, int height, int &ndisp, int &iters, int &levels) -{ - ndisp = width / 4; - if ((ndisp & 1) != 0) - ndisp++; - - int mm = ::max(width, height); - iters = mm / 100 + 2; - - levels = (int)(::log(static_cast(mm)) + 1) * 4 / 5; - if (levels == 0) levels++; -} - -cv::ocl::StereoBeliefPropagation::StereoBeliefPropagation(int ndisp_, int iters_, int levels_, int msg_type_) - : ndisp(ndisp_), iters(iters_), levels(levels_), - max_data_term(DEFAULT_MAX_DATA_TERM), data_weight(DEFAULT_DATA_WEIGHT), - max_disc_term(DEFAULT_MAX_DISC_TERM), disc_single_jump(DEFAULT_DISC_SINGLE_JUMP), - msg_type(msg_type_), datas(levels_) -{ -} - -cv::ocl::StereoBeliefPropagation::StereoBeliefPropagation(int ndisp_, int iters_, int levels_, float max_data_term_, float data_weight_, float max_disc_term_, float disc_single_jump_, int msg_type_) - : ndisp(ndisp_), iters(iters_), levels(levels_), - max_data_term(max_data_term_), data_weight(data_weight_), - max_disc_term(max_disc_term_), disc_single_jump(disc_single_jump_), - msg_type(msg_type_), datas(levels_) -{ -} - -namespace -{ - class StereoBeliefPropagationImpl - { - public: - StereoBeliefPropagationImpl(StereoBeliefPropagation &rthis_, - oclMat &u_, oclMat &d_, oclMat &l_, oclMat &r_, - oclMat &u2_, oclMat &d2_, oclMat &l2_, oclMat &r2_, - std::vector &datas_, oclMat &out_) - : rthis(rthis_), u(u_), d(d_), l(l_), r(r_), u2(u2_), d2(d2_), l2(l2_), r2(r2_), datas(datas_), out(out_), - zero(Scalar::all(0)), scale(rthis_.msg_type == CV_32F ? 1.0f : 10.0f) - { - CV_Assert(0 < rthis.ndisp && 0 < rthis.iters && 0 < rthis.levels); - CV_Assert(rthis.msg_type == CV_32F || rthis.msg_type == CV_16S); - CV_Assert(rthis.msg_type == CV_32F || (1 << (rthis.levels - 1)) * scale * rthis.max_data_term < std::numeric_limits::max()); - } - - void operator()(const oclMat &left, const oclMat &right, oclMat &disp) - { - CV_Assert(left.size() == right.size() && left.type() == right.type()); - CV_Assert(left.type() == CV_8UC1 || left.type() == CV_8UC3 || left.type() == CV_8UC4); - - rows = left.rows; - cols = left.cols; - - int divisor = (int)pow(2.f, rthis.levels - 1.0f); - int lowest_cols = cols / divisor; - int lowest_rows = rows / divisor; - const int min_image_dim_size = 2; - CV_Assert(min(lowest_cols, lowest_rows) > min_image_dim_size); - - init(); - - datas[0].create(rows * rthis.ndisp, cols, rthis.msg_type); - datas[0].setTo(Scalar_::all(0)); - - cv::ocl::stereoBP::comp_data_call(left, right, datas[0], rthis.ndisp, rthis.max_data_term, scale * rthis.data_weight); - calcBP(disp); - } - - void operator()(const oclMat &data, oclMat &disp) - { - CV_Assert((data.type() == rthis.msg_type) && (data.rows % rthis.ndisp == 0)); - - rows = data.rows / rthis.ndisp; - cols = data.cols; - - int divisor = (int)pow(2.f, rthis.levels - 1.0f); - int lowest_cols = cols / divisor; - int lowest_rows = rows / divisor; - const int min_image_dim_size = 2; - CV_Assert(min(lowest_cols, lowest_rows) > min_image_dim_size); - - init(); - - datas[0] = data; - - calcBP(disp); - } - private: - void init() - { - u.create(rows * rthis.ndisp, cols, rthis.msg_type); - d.create(rows * rthis.ndisp, cols, rthis.msg_type); - l.create(rows * rthis.ndisp, cols, rthis.msg_type); - r.create(rows * rthis.ndisp, cols, rthis.msg_type); - - if (rthis.levels & 1) - { - //can clear less area - u = zero; - d = zero; - l = zero; - r = zero; - } - - if (rthis.levels > 1) - { - int less_rows = (rows + 1) / 2; - int less_cols = (cols + 1) / 2; - - u2.create(less_rows * rthis.ndisp, less_cols, rthis.msg_type); - d2.create(less_rows * rthis.ndisp, less_cols, rthis.msg_type); - l2.create(less_rows * rthis.ndisp, less_cols, rthis.msg_type); - r2.create(less_rows * rthis.ndisp, less_cols, rthis.msg_type); - - if ((rthis.levels & 1) == 0) - { - u2 = zero; - d2 = zero; - l2 = zero; - r2 = zero; - } - } - - cv::ocl::stereoBP::load_constants(rthis.ndisp, rthis.max_data_term, scale * rthis.data_weight, - scale * rthis.max_disc_term, scale * rthis.disc_single_jump); - - datas.resize(rthis.levels); - cols_all.resize(rthis.levels); - rows_all.resize(rthis.levels); - - cols_all[0] = cols; - rows_all[0] = rows; - } - - void calcBP(oclMat &disp) - { - using namespace cv::ocl::stereoBP; - - for (int i = 1; i < rthis.levels; ++i) - { - cols_all[i] = (cols_all[i - 1] + 1) / 2; - rows_all[i] = (rows_all[i - 1] + 1) / 2; - - datas[i].create(rows_all[i] * rthis.ndisp, cols_all[i], rthis.msg_type); - datas[i].setTo(Scalar_::all(0)); - - data_step_down_call(cols_all[i], rows_all[i], rows_all[i - 1], - datas[i - 1], datas[i], rthis.ndisp); - } - - oclMat mus[] = {u, u2}; - oclMat mds[] = {d, d2}; - oclMat mrs[] = {r, r2}; - oclMat mls[] = {l, l2}; - - int mem_idx = (rthis.levels & 1) ? 0 : 1; - - for (int i = rthis.levels - 1; i >= 0; --i) - { - // for lower level we have already computed messages by setting to zero - if (i != rthis.levels - 1) - level_up_messages_calls(mem_idx, cols_all[i], rows_all[i], rows_all[i + 1], - mus, mds, mls, mrs, rthis.ndisp); - - calc_all_iterations_calls(cols_all[i], rows_all[i], rthis.iters, mus[mem_idx], - mds[mem_idx], mls[mem_idx], mrs[mem_idx], datas[i], - rthis.ndisp, scale * rthis.max_disc_term, - scale * rthis.disc_single_jump); - - mem_idx = (mem_idx + 1) & 1; - } - if (disp.empty()) - disp.create(rows, cols, CV_16S); - - out = ((disp.type() == CV_16S) ? disp : (out.create(rows, cols, CV_16S), out)); - out = zero; - - output_call(u, d, l, r, datas.front(), out, rthis.ndisp); - - if (disp.type() != CV_16S) - out.convertTo(disp, disp.type()); - - release_constants(); - } - StereoBeliefPropagationImpl& operator=(const StereoBeliefPropagationImpl&); - - StereoBeliefPropagation &rthis; - - oclMat &u; - oclMat &d; - oclMat &l; - oclMat &r; - - oclMat &u2; - oclMat &d2; - oclMat &l2; - oclMat &r2; - - std::vector &datas; - oclMat &out; - - const Scalar zero; - const float scale; - - int rows, cols; - - std::vector cols_all, rows_all; - }; -} - -void cv::ocl::StereoBeliefPropagation::operator()(const oclMat &left, const oclMat &right, oclMat &disp) -{ - ::StereoBeliefPropagationImpl impl(*this, u, d, l, r, u2, d2, l2, r2, datas, out); - impl(left, right, disp); -} - -void cv::ocl::StereoBeliefPropagation::operator()(const oclMat &data, oclMat &disp) -{ - ::StereoBeliefPropagationImpl impl(*this, u, d, l, r, u2, d2, l2, r2, datas, out); - impl(data, disp); -} diff --git a/modules/ocl/src/svm.cpp b/modules/ocl/src/svm.cpp deleted file mode 100644 index 892743888..000000000 --- a/modules/ocl/src/svm.cpp +++ /dev/null @@ -1,1136 +0,0 @@ -/*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-2013, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Erping Pang, erping@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 "precomp.hpp" -#include "opencl_kernels.hpp" - -// TODO Remove this after HAVE_CLAMDBLAS eliminating -#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) -# pragma GCC diagnostic ignored "-Wunused-but-set-variable" -#endif - -using namespace cv; -using namespace ocl; - -namespace cv { namespace ocl { - -#if 1 -typedef float Qfloat; -#define QFLOAT_TYPE CV_32F -#else -typedef double Qfloat; -#define QFLOAT_TYPE CV_64F -#endif - -class CvSVMKernel_ocl: public CvSVMKernel -{ -public: - typedef void (CvSVMKernel_ocl::*Calc_ocl)( int vec_count, const int row_idx, Qfloat* results, Mat& src); - CvSVMKernel_ocl(const CvSVMParams* params, Calc_ocl _calc_func , Calc _calc_func1); - - Calc_ocl calc_func_ocl; - bool create( const CvSVMParams* params, Calc_ocl _calc_func, Calc _calc_func1); - - void calc( int vcount, const int row_idx, Qfloat* results, Mat& src); - void calc_linear( int vec_count, const int row_idx, Qfloat* results, Mat& src); - - void calc_poly( int vec_count, const int row_idx, Qfloat* results, Mat& src); - void calc_sigmoid( int vec_count, const int row_idx, Qfloat* results, Mat& src); - void calc_non_rbf_base( int vec_count, const int row_idx, Qfloat* results, Mat& src); - void calc_rbf( int vec_count, const int row_idx, Qfloat* results, Mat& src); -}; - -class CvSVMSolver_ocl: public CvSVMSolver -{ -public: - CvSVMSolver_ocl(); - CvSVMSolver_ocl(const CvSVMParams *); - float* get_row_base( int i, bool* _existed, Mat& src); - bool solve_generic( CvSVMSolutionInfo& si ); - float* get_row( int i, float* dst, Mat& src); -}; - -typedef struct CvSparseVecElem32f -{ - int idx; - float val; -} CvSparseVecElem32f; - -static int icvCmpSparseVecElems( const void* a, const void* b ) -{ - return ((CvSparseVecElem32f*)a)->idx - ((CvSparseVecElem32f*)b)->idx; -} - -void cvPreparePredictData( const CvArr* sample, int dims_all, const CvMat* comp_idx, - int class_count, const CvMat* prob, float** row_sample, - int as_sparse CV_DEFAULT(0) ); - -void cvPreparePredictData( const CvArr* _sample, int dims_all, - const CvMat* comp_idx, int class_count, - const CvMat* prob, float** _row_sample, - int as_sparse ) -{ - float* row_sample = 0; - int* inverse_comp_idx = 0; - - CV_FUNCNAME( "cvPreparePredictData" ); - - __CV_BEGIN__; - - const CvMat* sample = (const CvMat*)_sample; - float* sample_data; - int sample_step; - int is_sparse = CV_IS_SPARSE_MAT(sample); - int d, sizes[CV_MAX_DIM]; - int i, dims_selected; - int vec_size; - - if( !is_sparse && !CV_IS_MAT(sample) ) - { - CV_ERROR( !sample ? CV_StsNullPtr : CV_StsBadArg, "The sample is not a valid vector" ); - } - - if( cvGetElemType( sample ) != CV_32FC1 ) - { - CV_ERROR( CV_StsUnsupportedFormat, "Input sample must have 32fC1 type" ); - } - - CV_CALL( d = cvGetDims( sample, sizes )); - - if( !((is_sparse && d == 1) || (!is_sparse && d == 2 && (sample->rows == 1 || sample->cols == 1))) ) - { - CV_ERROR( CV_StsBadSize, "Input sample must be 1-dimensional vector" ); - } - - if( d == 1 ) - sizes[1] = 1; - - if( sizes[0] + sizes[1] - 1 != dims_all ) - CV_ERROR( CV_StsUnmatchedSizes, - "The sample size is different from what has been used for training" ); - - if( !_row_sample ) - { - CV_ERROR( CV_StsNullPtr, "INTERNAL ERROR: The row_sample pointer is NULL" ); - } - - if( comp_idx && (!CV_IS_MAT(comp_idx) || comp_idx->rows != 1 || - CV_MAT_TYPE(comp_idx->type) != CV_32SC1) ) - { - CV_ERROR( CV_StsBadArg, "INTERNAL ERROR: invalid comp_idx" ); - } - - dims_selected = comp_idx ? comp_idx->cols : dims_all; - - if( prob ) - { - if( !CV_IS_MAT(prob) ) - { - CV_ERROR( CV_StsBadArg, "The output matrix of probabilities is invalid" ); - } - - if( (prob->rows != 1 && prob->cols != 1) || - (CV_MAT_TYPE(prob->type) != CV_32FC1 && - CV_MAT_TYPE(prob->type) != CV_64FC1) ) - CV_ERROR( CV_StsBadSize, - "The matrix of probabilities must be 1-dimensional vector of 32fC1 type" ); - - if( prob->rows + prob->cols - 1 != class_count ) - CV_ERROR( CV_StsUnmatchedSizes, - "The vector of probabilities must contain as many elements as " - "the number of classes in the training set" ); - } - - vec_size = !as_sparse ? dims_selected * sizeof(row_sample[0]) : - (dims_selected + 1) * sizeof(CvSparseVecElem32f); - - if( CV_IS_MAT(sample) ) - { - sample_data = sample->data.fl; - sample_step = CV_IS_MAT_CONT(sample->type) ? 1 : sample->step / sizeof(row_sample[0]); - - if( !comp_idx && CV_IS_MAT_CONT(sample->type) && !as_sparse ) - *_row_sample = sample_data; - else - { - CV_CALL( row_sample = (float*)cvAlloc( vec_size )); - - if( !comp_idx ) - for( i = 0; i < dims_selected; i++ ) - row_sample[i] = sample_data[sample_step * i]; - else - { - int* comp = comp_idx->data.i; - for( i = 0; i < dims_selected; i++ ) - row_sample[i] = sample_data[sample_step * comp[i]]; - } - - *_row_sample = row_sample; - } - - if( as_sparse ) - { - const float* src = (const float*)row_sample; - CvSparseVecElem32f* dst = (CvSparseVecElem32f*)row_sample; - - dst[dims_selected].idx = -1; - for( i = dims_selected - 1; i >= 0; i-- ) - { - dst[i].idx = i; - dst[i].val = src[i]; - } - } - } - else - { - CvSparseNode* node; - CvSparseMatIterator mat_iterator; - const CvSparseMat* sparse = (const CvSparseMat*)sample; - assert( is_sparse ); - - node = cvInitSparseMatIterator( sparse, &mat_iterator ); - CV_CALL( row_sample = (float*)cvAlloc( vec_size )); - - if( comp_idx ) - { - CV_CALL( inverse_comp_idx = (int*)cvAlloc( dims_all * sizeof(int) )); - memset( inverse_comp_idx, -1, dims_all * sizeof(int) ); - for( i = 0; i < dims_selected; i++ ) - inverse_comp_idx[comp_idx->data.i[i]] = i; - } - - if( !as_sparse ) - { - memset( row_sample, 0, vec_size ); - - for( ; node != 0; node = cvGetNextSparseNode(&mat_iterator) ) - { - int idx = *CV_NODE_IDX( sparse, node ); - if( inverse_comp_idx ) - { - idx = inverse_comp_idx[idx]; - if( idx < 0 ) - continue; - } - row_sample[idx] = *(float*)CV_NODE_VAL( sparse, node ); - } - } - else - { - CvSparseVecElem32f* ptr = (CvSparseVecElem32f*)row_sample; - - for( ; node != 0; node = cvGetNextSparseNode(&mat_iterator) ) - { - int idx = *CV_NODE_IDX( sparse, node ); - if( inverse_comp_idx ) - { - idx = inverse_comp_idx[idx]; - if( idx < 0 ) - continue; - } - ptr->idx = idx; - ptr->val = *(float*)CV_NODE_VAL( sparse, node ); - ptr++; - } - - qsort( row_sample, ptr - (CvSparseVecElem32f*)row_sample, - sizeof(ptr[0]), icvCmpSparseVecElems ); - ptr->idx = -1; - } - - *_row_sample = row_sample; - } - - __CV_END__; - - if( inverse_comp_idx ) - cvFree( &inverse_comp_idx ); - - if( cvGetErrStatus() < 0 && _row_sample ) - { - cvFree( &row_sample ); - *_row_sample = 0; - } -} - -float CvSVM_OCL::predict( const int row_index, int row_len, Mat& src, bool returnDFVal ) const -{ - assert( kernel ); - - (void)row_len; - - int class_count = class_labels ? class_labels->cols : - params.svm_type == ONE_CLASS ? 1 : 0; - - float result = 0; - cv::AutoBuffer _buffer(sv_total + (class_count + 1) * 2); - float* buffer = _buffer; - - if( params.svm_type == EPS_SVR || - params.svm_type == NU_SVR || - params.svm_type == ONE_CLASS ) - { - CvSVMDecisionFunc* df = (CvSVMDecisionFunc*)decision_func; - int i, sv_count = df->sv_count; - double sum = -df->rho; - - ((CvSVMKernel_ocl*)kernel)->calc( sv_count, row_index, buffer, src); - for( i = 0; i < sv_count; i++ ) - sum += buffer[i] * df->alpha[i]; - - result = params.svm_type == ONE_CLASS ? (float)(sum > 0) : (float)sum; - } - else if( params.svm_type == C_SVC || - params.svm_type == NU_SVC ) - { - CvSVMDecisionFunc* df = (CvSVMDecisionFunc*)decision_func; - int* vote = (int*)(buffer + sv_total); - int i, j, k; - - memset( vote, 0, class_count * sizeof(vote[0])); - ((CvSVMKernel_ocl*)kernel)->calc( sv_total, row_index, buffer, src); - double sum = 0.; - - for( i = 0; i < class_count; i++ ) - for( j = i + 1; j < class_count; j++, df++ ) - { - sum = -df->rho; - int sv_count = df->sv_count; - for( k = 0; k < sv_count; k++ ) - sum += df->alpha[k] * buffer[df->sv_index[k]]; - - vote[sum > 0 ? i : j]++; - } - - for( i = 1, k = 0; i < class_count; i++ ) - if( vote[i] > vote[k] ) - k = i; - - result = returnDFVal && class_count == 2 ? (float)sum : (float)(class_labels->data.i[k]); - } - else - CV_Error( CV_StsBadArg, "INTERNAL ERROR: Unknown SVM type, " - "the SVM structure is probably corrupted" ); - - return result; -} - -float CvSVM_OCL::predict( const Mat& _sample, bool returnDFVal ) const -{ - CvMat sample = _sample; - return CvSVM::predict(&sample, returnDFVal); -} - -float CvSVM_OCL::predict( const int row_index, Mat& src, bool returnDFVal) const -{ - float result = 0; - - result = predict( row_index, get_var_count(), src, returnDFVal); - - return result; -} - -#undef get_C -#define get_C(i) (C[y[i]>0]) -#undef is_upper_bound -#define is_upper_bound(i) (alpha_status[i] > 0) -#undef is_lower_bound -#define is_lower_bound(i) (alpha_status[i] < 0) -#undef update_alpha_status -#define update_alpha_status(i) \ - alpha_status[i] = (schar)(alpha[i] >= get_C(i) ? 1 : alpha[i] <= 0 ? -1 : 0) - -CvSVMSolver_ocl::CvSVMSolver_ocl(const CvSVMParams* _params) -{ - params = _params; -} - -float* CvSVMSolver_ocl::get_row( int i, float* dst, Mat& src ) -{ - bool existed = false; - float* row = get_row_base( i, &existed, src); - return (this->*get_row_func)( i, row, dst, existed ); -} - -float* CvSVMSolver_ocl::get_row_base( int i, bool* _existed, Mat& src ) -{ - int i1 = i < sample_count ? i : i - sample_count; - CvSVMKernelRow* row = rows + i1; - bool existed = row->data != 0; - Qfloat* data; - - if( existed || cache_size <= 0 ) - { - CvSVMKernelRow* del_row = existed ? row : lru_list.prev; - data = del_row->data; - assert( data != 0 ); - - // delete row from the LRU list - del_row->data = 0; - del_row->prev->next = del_row->next; - del_row->next->prev = del_row->prev; - } - else - { - data = (Qfloat*)cvMemStorageAlloc( storage, cache_line_size ); - cache_size -= cache_line_size; - } - - // insert row into the LRU list - row->data = data; - row->prev = &lru_list; - row->next = lru_list.next; - row->prev->next = row->next->prev = row; - - if( !existed ) - ((CvSVMKernel_ocl*)kernel)->calc( sample_count, i1, row->data, src); - - if( _existed ) - *_existed = existed; - - return row->data; -} - -#ifndef HAVE_CLAMDBLAS - -static void matmul_sigmod(oclMat & src, oclMat & src2, oclMat & dst, int src_rows, int src2_cols, int var_count, double alpha1, double beta1) -{ - Context *clCxt = Context::getContext(); - String kernelName = "svm_sigmod"; - int src_step = (int)src.step / src.elemSize(); - int src2_step = (int)src2.step / src2.elemSize(); - int dst_step = (int)dst.step / dst.elemSize(); - int x = MIN(16, src_rows); - int y = MIN(16, src2_cols); - size_t localThreads[] = {x, y, 1}; - size_t globalThreads[] = {src2_cols, src_rows, 1}; - int width = var_count; - - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void* )&src.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src_step)); - args.push_back(std::make_pair(sizeof(cl_mem), (void* )&src2.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src2_step)); - args.push_back(std::make_pair(sizeof(cl_mem), (void* )&dst.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&dst_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src_rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src2_cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&width)); - - float alpha = 0.0f, beta = 0.0f; - if(!Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - { - alpha = (float)alpha1; - beta = (float)beta1; - args.push_back(std::make_pair(sizeof(cl_float), (void* )&alpha)); - args.push_back(std::make_pair(sizeof(cl_float), (void* )&beta)); - } - else - { - args.push_back(std::make_pair(sizeof(cl_double), (void* )&alpha1)); - args.push_back(std::make_pair(sizeof(cl_double), (void* )&beta1)); - } - openCLExecuteKernel(clCxt, &svm, kernelName, globalThreads, localThreads, args, -1, -1); -} - -static void matmul_poly(oclMat & src, oclMat & src2, oclMat & dst, int src_rows, int src2_cols, int var_count, double alpha1, double beta1, double degree1, bool flag) -{ - Context *clCxt = Context::getContext(); - String kernelName = "svm_poly"; - int src_step = (int)src.step / src.elemSize(); - int src2_step = (int)src2.step / src2.elemSize(); - int dst_step = (int)dst.step / dst.elemSize(); - int x = MIN(16, src_rows); - int y = MIN(16, src2_cols); - size_t localThreads[] = {x, y, 1}; - size_t globalThreads[] = {src2_cols, src_rows, 1}; - int width = var_count; - - char build_options[50]; - - if(flag) - { - sprintf(build_options, "-D ADDPOW"); - } - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void* )&src.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src_step)); - args.push_back(std::make_pair(sizeof(cl_mem), (void* )&src2.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src2_step)); - args.push_back(std::make_pair(sizeof(cl_mem), (void* )&dst.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&dst_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src_rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src2_cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&width)); - - float alpha = 0.0f, beta = 0.0f, degree = 0.0f; - if(!Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - { - alpha = (float)alpha1; - beta = (float)beta1; - degree = (float)degree1; - args.push_back(std::make_pair(sizeof(cl_float), (void* )&alpha)); - args.push_back(std::make_pair(sizeof(cl_float), (void* )&beta)); - args.push_back(std::make_pair(sizeof(cl_float), (void* )°ree)); - } - else - { - args.push_back(std::make_pair(sizeof(cl_double), (void* )&alpha1)); - args.push_back(std::make_pair(sizeof(cl_double), (void* )&beta1)); - args.push_back(std::make_pair(sizeof(cl_double), (void* )°ree1)); - } - openCLExecuteKernel(clCxt, &svm, kernelName, globalThreads, localThreads, args, -1, -1, build_options); -} - -static void matmul_linear(oclMat & src, oclMat & src2, oclMat & dst, int src_rows, int src2_cols, int var_count, double alpha1, double beta1) -{ - Context *clCxt = Context::getContext(); - String kernelName = "svm_linear"; - int src_step = (int)src.step / src.elemSize(); - int src2_step = (int)src2.step / src2.elemSize(); - int dst_step = (int)dst.step / dst.elemSize(); - int x = MIN(16, src_rows); - int y = MIN(16, src2_cols); - size_t localThreads[] = {x, y, 1}; - size_t globalThreads[] = {src2_cols, src_rows, 1}; - int width = var_count; - - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void* )&src.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src_step)); - args.push_back(std::make_pair(sizeof(cl_mem), (void* )&src2.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src2_step)); - args.push_back(std::make_pair(sizeof(cl_mem), (void* )&dst.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&dst_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src_rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src2_cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&width)); - - float alpha = 0.0f, beta = 0.0f; - if(!Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - { - alpha = (float)alpha1; - beta = (float)beta1; - args.push_back(std::make_pair(sizeof(cl_float), (void* )&alpha)); - args.push_back(std::make_pair(sizeof(cl_float), (void* )&beta)); - } - else - { - args.push_back(std::make_pair(sizeof(cl_double), (void* )&alpha1)); - args.push_back(std::make_pair(sizeof(cl_double), (void* )&beta1)); - } - openCLExecuteKernel(clCxt, &svm, kernelName, globalThreads, localThreads, args, -1, -1); -} - -#endif // #ifndef HAVE_CLAMDBLAS - -static void matmul_rbf(oclMat& src, oclMat& src_e, oclMat& dst, int src_rows, int src2_cols, int var_count, double gamma1, bool flag) -{ - - Context *clCxt = Context::getContext(); - - String kernelName = "svm_rbf"; - - int width = var_count; - int src_step = (int)src.step / src.elemSize(); - int src_e_step = (int)src_e.step / src_e.elemSize(); - int dst_step = (int)dst.step / dst.elemSize(); - - int x = MIN(16, src_rows); - int y = MIN(16, src2_cols); - size_t localThreads[] = {x, y, 1}; - size_t globalThreads[] = {src2_cols, src_rows, 1}; - char build_options[50]; - - if(flag) - sprintf(build_options, "-D ADDEXP"); - - std::vector< std::pair > args; - args.push_back(std::make_pair(sizeof(cl_mem), (void* )&src.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src_step)); - args.push_back(std::make_pair(sizeof(cl_mem), (void* )&src_e.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src_e_step)); - args.push_back(std::make_pair(sizeof(cl_mem), (void* )&dst.data)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&dst_step)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src_rows)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&src2_cols)); - args.push_back(std::make_pair(sizeof(cl_int), (void* )&width)); - float gamma = 0.0f; - if(!Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - { - gamma = (float)gamma1; - args.push_back(std::make_pair(sizeof(cl_float), (void* )&gamma)); - } - else - args.push_back(std::make_pair(sizeof(cl_double), (void* )&gamma1)); - - openCLExecuteKernel(clCxt, &svm, kernelName, globalThreads, localThreads, args, -1, -1, build_options); -} - -float CvSVM_OCL::predict(const CvMat* samples, CV_OUT CvMat* results) const -{ - int var_count = get_var_count(); - int sample_count = samples->rows; - - //float* row_sample = 0; - Mat src_temp = Mat(sample_count, var_count, CV_32FC1); - CV_FUNCNAME( "CvSVM::predict" ); - - - for(int i = 0; i < samples->rows; i++) - { - __CV_BEGIN__; - CvMat sample; - float* row_sample = 0; - cvGetRow( samples, &sample, i ); - int class_count; - if( !kernel ) - { - CV_ERROR( CV_StsBadArg, "The SVM should be trained first" ); - } - - class_count = class_labels ? class_labels->cols : - params.svm_type == ONE_CLASS ? 1 : 0; - - CV_CALL( cvPreparePredictData(&sample, var_all, var_idx, - class_count, 0, &row_sample )); - for(int j = 0; j < var_count; ++j) - src_temp.at(i, j) = row_sample[j]; - __CV_END__; - } - - Mat dst1; - double alpha1 = 0.0, beta1 = 0.0, gamma1 = 0.0; - if(params.kernel_type == CvSVM::LINEAR) - { - alpha1 = 1; - beta1 = 0; - } - if(params.kernel_type == CvSVM::POLY) - { - alpha1 = params.gamma; - beta1 = params.coef0; - } - if(params.kernel_type == CvSVM::SIGMOID) - { - alpha1 = - 2 * params.gamma; - beta1 = - 2 * params.coef0; - } - if(params.kernel_type == CvSVM::RBF) - gamma1 = - params.gamma; - - Mat sv_temp = Mat(sv_total, var_count, CV_32FC1, Scalar::all(0)); - - - for(int i = 0; i < sv_total; ++i) - for(int j = 0; j < var_count; ++j) - sv_temp.at(i, j) = sv[i][j]; - - oclMat src(sample_count, var_count, CV_32FC1, Scalar::all(0)); - oclMat sv_; - - src.upload(src_temp); - oclMat dst; - -#ifdef HAVE_CLAMDBLAS - - dst = oclMat(sample_count, sv_total, CV_32FC1); - oclMat src3(sample_count, sv_total, CV_32FC1, Scalar::all(1)); - if(params.kernel_type != CvSVM::RBF) - { - Mat sv_temp1; - transpose(sv_temp, sv_temp1); - sv_.upload(sv_temp1); - gemm(src, sv_, alpha1, src3, beta1, dst); - } - -#else - double degree1 = 0.0; - if (params.kernel_type == CvSVM::POLY) - degree1 = params.degree; - - if(!Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - dst = oclMat(sample_count, sv_total, CV_32FC1); - else - dst = oclMat(sample_count, sv_total, CV_64FC1); - - if(params.kernel_type == CvSVM::LINEAR) - { - sv_.upload(sv_temp); - matmul_linear(src, sv_, dst, sample_count, sv_total, var_count, alpha1, beta1); - } - if( params.kernel_type == CvSVM::SIGMOID) - { - sv_.upload(sv_temp); - matmul_sigmod(src, sv_, dst, sample_count, sv_total, var_count, alpha1, beta1); - } - - if(params.kernel_type == CvSVM::POLY) - { - sv_.upload(sv_temp); - if(sample_count > 0) - matmul_poly(src, sv_, dst, sample_count, sv_total, var_count, alpha1, beta1, degree1, true); - else - matmul_poly(src, sv_, dst, sample_count, sv_total, var_count, alpha1, beta1, degree1, false); - } -#endif - - if(params.kernel_type == CvSVM::RBF) - { - sv_.upload(sv_temp); - if(!Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - dst = oclMat(sample_count, sv_total, CV_32FC1); - else - dst = oclMat(sample_count, sv_total, CV_64FC1); - - if(sample_count > 0) - matmul_rbf(src, sv_, dst, sample_count, sv_total, var_count, gamma1, true); - else - matmul_rbf(src, sv_, dst, sample_count, sv_total, var_count, gamma1, false); - } - dst.download(dst1); - - float result = 0; - for(int i = 0; i < samples->rows; i++ ) - { - int r = (int)this->predict(i, dst1); - if (results) - results->data.fl[i] = (float)r; - if (i == 0) - result = (float)r; - } - return result; -} - -void CvSVM_OCL::predict( cv::InputArray _samples, cv::OutputArray _results ) const -{ - _results.create(_samples.size().height, 1, CV_32F); - CvMat samples = _samples.getMat(), results = _results.getMat(); - predict(&samples, &results); -} - -bool CvSVMSolver_ocl::solve_generic( CvSVMSolutionInfo& si ) -{ - int iter = 0; - int i, j, k; - - // 1. initialize gradient and alpha status - for( i = 0; i < alpha_count; i++ ) - { - update_alpha_status(i); - G[i] = b[i]; - if( fabs(G[i]) > 1e200 ) - { - return false; - } - } - Mat dst1; - double alpha1 = 0.0, beta1 = 0.0, gamma1 = 0.0; - if(params->kernel_type == CvSVM::LINEAR) - { - alpha1 = 1; - beta1 = 0; - } - if(params->kernel_type == CvSVM::POLY) - { - alpha1 = params->gamma; - beta1 = params->coef0; - } - if(params->kernel_type == CvSVM::SIGMOID) - { - alpha1 = -2 * params->gamma; - beta1 = -2 * params->coef0; - } - if(params->kernel_type == CvSVM::RBF) - { - gamma1 = -params->gamma; - } - Mat src1 = Mat(sample_count, var_count, CV_32FC1); - - for(int i = 0; i < sample_count; ++i) - { - for(int j = 0; j < var_count; ++j) - { - src1.at(i, j) = samples[i][j]; - } - } - oclMat src, src_e; - src.upload(src1); - oclMat dst; - -#ifdef HAVE_CLAMDBLAS - - dst = oclMat(sample_count, sample_count, CV_32FC1); - oclMat src3(sample_count, sample_count, CV_32FC1, Scalar::all(1)); - if(params->kernel_type != CvSVM::RBF) - { - ocl::transpose(src, src_e); - gemm(src, src_e, alpha1, src3, beta1, dst); - } - -#else - double degree1 = 0.0; - if(params->kernel_type == CvSVM::POLY) - degree1 = params->degree; - - if(!Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - dst = oclMat(sample_count, sample_count, CV_32FC1); - else - dst = oclMat(sample_count, sample_count, CV_64FC1); - - if(params->kernel_type == CvSVM::LINEAR ) - { - src_e = src; - matmul_linear(src, src_e, dst, sample_count, sample_count, var_count, alpha1, beta1); - } - if( params->kernel_type == CvSVM::SIGMOID) - { - src_e = src; - matmul_sigmod(src, src_e, dst, sample_count, sample_count, var_count, alpha1, beta1); - } - - if(params->kernel_type == CvSVM::POLY) - { - src_e = src; - if(sample_count > 0) - matmul_poly(src, src_e, dst, sample_count, sample_count, var_count, alpha1, beta1, degree1, true); - else - matmul_poly(src, src_e, dst, sample_count, sample_count, var_count, alpha1, beta1, degree1, false); - } - -#endif - - if(params->kernel_type == CvSVM::RBF) - { - src_e = src; - if(!Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - dst = oclMat(sample_count, sample_count, CV_32FC1); - else - dst = oclMat(sample_count, sample_count, CV_64FC1); - - if(sample_count > 0) - matmul_rbf(src, src_e, dst, sample_count, sample_count, var_count, gamma1, true); - else - matmul_rbf(src, src_e, dst, sample_count, sample_count, var_count, gamma1, false); - } - dst.download(dst1); - for( i = 0; i < alpha_count; i++ ) - { - if( !is_lower_bound(i) ) - { - const Qfloat *Q_i = CvSVMSolver::get_row( i, buf[0]); - double alpha_i = alpha[i]; - - for( j = 0; j < alpha_count; j++ ) - G[j] += alpha_i * Q_i[j]; - } - } - - // 2. optimization loop - for(;;) - { - const Qfloat *Q_i, *Q_j; - double C_i, C_j; - double old_alpha_i, old_alpha_j, alpha_i, alpha_j; - double delta_alpha_i, delta_alpha_j; - -#ifdef _DEBUG - for( i = 0; i < alpha_count; i++ ) - { - if( fabs(G[i]) > 1e+300 ) - return false; - - if( fabs(alpha[i]) > 1e16 ) - return false; - } -#endif - - if( (this->*select_working_set_func)( i, j ) != 0 || iter++ >= max_iter ) - { - break; - } - Q_i = get_row( i, buf[0], dst1); - Q_j = get_row( j, buf[1], dst1); - - C_i = get_C(i); - C_j = get_C(j); - - alpha_i = old_alpha_i = alpha[i]; - alpha_j = old_alpha_j = alpha[j]; - - if( y[i] != y[j] ) - { - double denom = Q_i[i] + Q_j[j] + 2 * Q_i[j]; - double delta = (-G[i] - G[j]) / MAX(fabs(denom), FLT_EPSILON); - double diff = alpha_i - alpha_j; - alpha_i += delta; - alpha_j += delta; - - if( diff > 0 && alpha_j < 0 ) - { - alpha_j = 0; - alpha_i = diff; - } - else if( diff <= 0 && alpha_i < 0 ) - { - alpha_i = 0; - alpha_j = -diff; - } - - if( diff > C_i - C_j && alpha_i > C_i ) - { - alpha_i = C_i; - alpha_j = C_i - diff; - } - else if( diff <= C_i - C_j && alpha_j > C_j ) - { - alpha_j = C_j; - alpha_i = C_j + diff; - } - } - else - { - double denom = Q_i[i] + Q_j[j] - 2 * Q_i[j]; - double delta = (G[i] - G[j]) / MAX(fabs(denom), FLT_EPSILON); - double sum = alpha_i + alpha_j; - alpha_i -= delta; - alpha_j += delta; - - if( sum > C_i && alpha_i > C_i ) - { - alpha_i = C_i; - alpha_j = sum - C_i; - } - else if( sum <= C_i && alpha_j < 0) - { - alpha_j = 0; - alpha_i = sum; - } - - if( sum > C_j && alpha_j > C_j ) - { - alpha_j = C_j; - alpha_i = sum - C_j; - } - else if( sum <= C_j && alpha_i < 0 ) - { - alpha_i = 0; - alpha_j = sum; - } - } - // update alpha - alpha[i] = alpha_i; - alpha[j] = alpha_j; - update_alpha_status(i); - update_alpha_status(j); - - // update G - delta_alpha_i = alpha_i - old_alpha_i; - delta_alpha_j = alpha_j - old_alpha_j; - - for( k = 0; k < alpha_count; k++ ) - G[k] += Q_i[k] * delta_alpha_i + Q_j[k] * delta_alpha_j; - } - - // calculate rho - (this->*calc_rho_func)( si.rho, si.r ); - - // calculate objective value - for( i = 0, si.obj = 0; i < alpha_count; i++ ) - si.obj += alpha[i] * (G[i] + b[i]); - - si.obj *= 0.5; - - si.upper_bound_p = C[1]; - si.upper_bound_n = C[0]; - - return true; -} - -void CvSVMKernel_ocl::calc( int vcount, const int row_idx, Qfloat* results, Mat& src) -{ - //const Qfloat max_val = (Qfloat)(FLT_MAX*1e-3); - //int j; - (this->*calc_func_ocl)( vcount, row_idx, results, src); - -#if !defined(HAVE_CLAMDBLAS) - // nothing -#else - const Qfloat max_val = (Qfloat)(FLT_MAX * 1e-3); - int j; - for( j = 0; j < vcount; j++ ) - if( results[j] > max_val ) - results[j] = max_val; -#endif -} - -bool CvSVMKernel_ocl::create( const CvSVMParams* _params, Calc_ocl _calc_func, Calc _calc_func1 ) -{ - clear(); - params = _params; - calc_func_ocl = _calc_func; - calc_func = _calc_func1; - if( !calc_func_ocl ) - calc_func_ocl = params->kernel_type == CvSVM::RBF ? &CvSVMKernel_ocl::calc_rbf : - params->kernel_type == CvSVM::POLY ? &CvSVMKernel_ocl::calc_poly : - params->kernel_type == CvSVM::SIGMOID ? &CvSVMKernel_ocl::calc_sigmoid : - &CvSVMKernel_ocl::calc_linear; - if( !calc_func) - calc_func = params->kernel_type == CvSVM::RBF ? &CvSVMKernel::calc_rbf : - params->kernel_type == CvSVM::POLY ? &CvSVMKernel::calc_poly : - params->kernel_type == CvSVM::SIGMOID ? &CvSVMKernel::calc_sigmoid : - &CvSVMKernel::calc_linear; - return true; -} -CvSVMKernel_ocl::CvSVMKernel_ocl(const CvSVMParams* params, CvSVMKernel_ocl::Calc_ocl _calc_func, CvSVMKernel::Calc _calc_func1) -{ - CvSVMKernel::clear(); - CvSVMKernel_ocl::create( params, _calc_func, _calc_func1 ); -} - -void CvSVMKernel_ocl::calc_non_rbf_base( int vcount, const int row_idx, Qfloat* results, Mat& src) -{ -#ifdef HAVE_CLAMDBLAS - - for(int i = 0; i < vcount; i++) - { - results[i] = (Qfloat) * src.ptr(row_idx, i); - } -#else - if(!Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - { - for(int i = 0; i < vcount; i++) - { - results[i] = (Qfloat) * src.ptr(row_idx, i); - } - } - else - { - for(int i = 0; i < vcount; i++) - { - results[i] = (Qfloat) * src.ptr(row_idx, i); - } - } -#endif -} - -void CvSVMKernel_ocl::calc_rbf( int vcount, const int row_idx, Qfloat* results, Mat& src) -{ - if(!Context::getContext()->supportsFeature(FEATURE_CL_DOUBLE)) - for(int m = 0; m < vcount; m++) - results[m] = (Qfloat) * src.ptr(row_idx, m); - else - for(int m = 0; m < vcount; m++) - results[m] = (Qfloat) * src.ptr(row_idx, m); -} - -void CvSVMKernel_ocl::calc_linear( int vcount, const int row_idx, Qfloat* results, Mat& src ) -{ - calc_non_rbf_base( vcount, row_idx, results, src); -} - -void CvSVMKernel_ocl::calc_poly( int vcount, const int row_idx, Qfloat* results, Mat& src) -{ - calc_non_rbf_base( vcount, row_idx, results, src); - -#if !defined(HAVE_CLAMDBLAS) - // nothing -#else - CvMat R = cvMat( 1, vcount, QFLOAT_TYPE, results ); - if( vcount > 0 ) - cvPow( &R, &R, params->degree ); -#endif -} - - -void CvSVMKernel_ocl::calc_sigmoid( int vcount, const int row_idx, Qfloat* results, Mat& src) -{ - calc_non_rbf_base( vcount, row_idx, results, src); - // TODO: speedup this -#if !defined(HAVE_CLAMDBLAS) - // nothing -#else - for(int j = 0; j < vcount; j++ ) - { - Qfloat t = results[j]; - double e = ::exp(-fabs(t)); - if( t > 0 ) - results[j] = (Qfloat)((1. - e) / (1. + e)); - else - results[j] = (Qfloat)((e - 1.) / (e + 1.)); - } -#endif -} - -CvSVM_OCL::CvSVM_OCL() -{ - CvSVM(); -} - -CvSVM_OCL::CvSVM_OCL( const Mat& _train_data, const Mat& _responses, - const Mat& _var_idx, const Mat& _sample_idx, CvSVMParams _params ) -{ - decision_func = 0; - class_labels = 0; - class_weights = 0; - storage = 0; - var_idx = 0; - kernel = 0; - solver = 0; - default_model_name = "my_svm"; - - train( _train_data, _responses, _var_idx, _sample_idx, _params ); -} - -void CvSVM_OCL::create_kernel() -{ - kernel = new CvSVMKernel_ocl(¶ms, 0, 0); -} - -void CvSVM_OCL::create_solver( ) -{ - solver = new CvSVMSolver_ocl(¶ms); -} - -} } diff --git a/modules/ocl/src/tvl1flow.cpp b/modules/ocl/src/tvl1flow.cpp deleted file mode 100644 index 6e75ee238..000000000 --- a/modules/ocl/src/tvl1flow.cpp +++ /dev/null @@ -1,477 +0,0 @@ -/*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 -// 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 "precomp.hpp" -#include "opencl_kernels.hpp" - -using namespace cv; -using namespace cv::ocl; - -cv::ocl::OpticalFlowDual_TVL1_OCL::OpticalFlowDual_TVL1_OCL() -{ - tau = 0.25; - lambda = 0.15; - theta = 0.3; - nscales = 5; - warps = 5; - epsilon = 0.01; - iterations = 300; - useInitialFlow = false; -} - -void cv::ocl::OpticalFlowDual_TVL1_OCL::operator()(const oclMat& I0, const oclMat& I1, oclMat& flowx, oclMat& flowy) -{ - CV_Assert( I0.type() == CV_8UC1 || I0.type() == CV_32FC1 ); - CV_Assert( I0.size() == I1.size() ); - CV_Assert( I0.type() == I1.type() ); - CV_Assert( !useInitialFlow || (flowx.size() == I0.size() && flowx.type() == CV_32FC1 && flowy.size() == flowx.size() && flowy.type() == flowx.type()) ); - CV_Assert( nscales > 0 ); - - // allocate memory for the pyramid structure - I0s.resize(nscales); - I1s.resize(nscales); - u1s.resize(nscales); - u2s.resize(nscales); - //I0s_step == I1s_step - I0.convertTo(I0s[0], CV_32F, I0.depth() == CV_8U ? 1.0 : 255.0); - I1.convertTo(I1s[0], CV_32F, I1.depth() == CV_8U ? 1.0 : 255.0); - - - if (!useInitialFlow) - { - flowx.create(I0.size(), CV_32FC1); - flowy.create(I0.size(), CV_32FC1); - } - //u1s_step != u2s_step - u1s[0] = flowx; - u2s[0] = flowy; - - I1x_buf.create(I0.size(), CV_32FC1); - I1y_buf.create(I0.size(), CV_32FC1); - - I1w_buf.create(I0.size(), CV_32FC1); - I1wx_buf.create(I0.size(), CV_32FC1); - I1wy_buf.create(I0.size(), CV_32FC1); - - grad_buf.create(I0.size(), CV_32FC1); - rho_c_buf.create(I0.size(), CV_32FC1); - - p11_buf.create(I0.size(), CV_32FC1); - p12_buf.create(I0.size(), CV_32FC1); - p21_buf.create(I0.size(), CV_32FC1); - p22_buf.create(I0.size(), CV_32FC1); - - diff_buf.create(I0.size(), CV_32FC1); - - // create the scales - for (int s = 1; s < nscales; ++s) - { - ocl::pyrDown(I0s[s - 1], I0s[s]); - ocl::pyrDown(I1s[s - 1], I1s[s]); - - if (I0s[s].cols < 16 || I0s[s].rows < 16) - { - nscales = s; - break; - } - - if (useInitialFlow) - { - ocl::pyrDown(u1s[s - 1], u1s[s]); - ocl::pyrDown(u2s[s - 1], u2s[s]); - - ocl::multiply(0.5, u1s[s], u1s[s]); - ocl::multiply(0.5, u2s[s], u2s[s]); - } - } - - // pyramidal structure for computing the optical flow - for (int s = nscales - 1; s >= 0; --s) - { - // compute the optical flow at the current scale - procOneScale(I0s[s], I1s[s], u1s[s], u2s[s]); - - // if this was the last scale, finish now - if (s == 0) - break; - - // otherwise, upsample the optical flow - - // zoom the optical flow for the next finer scale - ocl::resize(u1s[s], u1s[s - 1], I0s[s - 1].size()); - ocl::resize(u2s[s], u2s[s - 1], I0s[s - 1].size()); - - // scale the optical flow with the appropriate zoom factor - multiply(2, u1s[s - 1], u1s[s - 1]); - multiply(2, u2s[s - 1], u2s[s - 1]); - - } - -} - -namespace ocl_tvl1flow -{ - void centeredGradient(const oclMat &src, oclMat &dx, oclMat &dy); - - void warpBackward(const oclMat &I0, const oclMat &I1, oclMat &I1x, oclMat &I1y, - oclMat &u1, oclMat &u2, oclMat &I1w, oclMat &I1wx, oclMat &I1wy, - oclMat &grad, oclMat &rho); - - void estimateU(oclMat &I1wx, oclMat &I1wy, oclMat &grad, - oclMat &rho_c, oclMat &p11, oclMat &p12, - oclMat &p21, oclMat &p22, oclMat &u1, - oclMat &u2, oclMat &error, float l_t, float theta, char calc_error); - - void estimateDualVariables(oclMat &u1, oclMat &u2, - oclMat &p11, oclMat &p12, oclMat &p21, oclMat &p22, float taut); -} - -void cv::ocl::OpticalFlowDual_TVL1_OCL::procOneScale(const oclMat &I0, const oclMat &I1, oclMat &u1, oclMat &u2) -{ - using namespace ocl_tvl1flow; - - const double scaledEpsilon = epsilon * epsilon * I0.size().area(); - - CV_DbgAssert( I1.size() == I0.size() ); - CV_DbgAssert( I1.type() == I0.type() ); - CV_DbgAssert( u1.empty() || u1.size() == I0.size() ); - CV_DbgAssert( u2.size() == u1.size() ); - - if (u1.empty()) - { - u1.create(I0.size(), CV_32FC1); - u1.setTo(Scalar::all(0)); - - u2.create(I0.size(), CV_32FC1); - u2.setTo(Scalar::all(0)); - } - - oclMat I1x = I1x_buf(Rect(0, 0, I0.cols, I0.rows)); - oclMat I1y = I1y_buf(Rect(0, 0, I0.cols, I0.rows)); - - centeredGradient(I1, I1x, I1y); - - oclMat I1w = I1w_buf(Rect(0, 0, I0.cols, I0.rows)); - oclMat I1wx = I1wx_buf(Rect(0, 0, I0.cols, I0.rows)); - oclMat I1wy = I1wy_buf(Rect(0, 0, I0.cols, I0.rows)); - - oclMat grad = grad_buf(Rect(0, 0, I0.cols, I0.rows)); - oclMat rho_c = rho_c_buf(Rect(0, 0, I0.cols, I0.rows)); - - oclMat p11 = p11_buf(Rect(0, 0, I0.cols, I0.rows)); - oclMat p12 = p12_buf(Rect(0, 0, I0.cols, I0.rows)); - oclMat p21 = p21_buf(Rect(0, 0, I0.cols, I0.rows)); - oclMat p22 = p22_buf(Rect(0, 0, I0.cols, I0.rows)); - p11.setTo(Scalar::all(0)); - p12.setTo(Scalar::all(0)); - p21.setTo(Scalar::all(0)); - p22.setTo(Scalar::all(0)); - - oclMat diff = diff_buf(Rect(0, 0, I0.cols, I0.rows)); - - const float l_t = static_cast(lambda * theta); - const float taut = static_cast(tau / theta); - - for (int warpings = 0; warpings < warps; ++warpings) - { - warpBackward(I0, I1, I1x, I1y, u1, u2, I1w, I1wx, I1wy, grad, rho_c); - - double error = std::numeric_limits::max(); - double prev_error = 0; - for (int n = 0; error > scaledEpsilon && n < iterations; ++n) - { - // some tweaks to make sum operation less frequently - char calc_error = (n & 0x1) && (prev_error < scaledEpsilon); - estimateU(I1wx, I1wy, grad, rho_c, p11, p12, p21, p22, - u1, u2, diff, l_t, static_cast(theta), calc_error); - if(calc_error) - { - error = ocl::sum(diff)[0]; - prev_error = error; - } - else - { - error = std::numeric_limits::max(); - prev_error -= scaledEpsilon; - } - estimateDualVariables(u1, u2, p11, p12, p21, p22, taut); - - } - } - - -} - -void cv::ocl::OpticalFlowDual_TVL1_OCL::collectGarbage() -{ - I0s.clear(); - I1s.clear(); - u1s.clear(); - u2s.clear(); - - I1x_buf.release(); - I1y_buf.release(); - - I1w_buf.release(); - I1wx_buf.release(); - I1wy_buf.release(); - - grad_buf.release(); - rho_c_buf.release(); - - p11_buf.release(); - p12_buf.release(); - p21_buf.release(); - p22_buf.release(); - - diff_buf.release(); - norm_buf.release(); -} - -void ocl_tvl1flow::centeredGradient(const oclMat &src, oclMat &dx, oclMat &dy) -{ - Context *clCxt = src.clCxt; - size_t localThreads[3] = {32, 8, 1}; - size_t globalThreads[3] = {src.cols, src.rows, 1}; - - int srcElementSize = src.elemSize(); - int src_step = src.step/srcElementSize; - - int dElememntSize = dx.elemSize(); - int dx_step = dx.step/dElememntSize; - - String kernelName = "centeredGradientKernel"; - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&src.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&src.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&src.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&src_step)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&dx.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&dy.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&dx_step)); - openCLExecuteKernel(clCxt, &tvl1flow, kernelName, globalThreads, localThreads, args, -1, -1); - -} - -void ocl_tvl1flow::estimateDualVariables(oclMat &u1, oclMat &u2, oclMat &p11, oclMat &p12, oclMat &p21, oclMat &p22, float taut) -{ - Context *clCxt = u1.clCxt; - - size_t localThread[] = {32, 8, 1}; - size_t globalThread[] = - { - u1.cols, - u1.rows, - 1 - }; - - int u1_element_size = u1.elemSize(); - int u1_step = u1.step/u1_element_size; - - int u2_element_size = u2.elemSize(); - int u2_step = u2.step/u2_element_size; - - int p11_element_size = p11.elemSize(); - int p11_step = p11.step/p11_element_size; - - int u1_offset_y = u1.offset/u1.step; - int u1_offset_x = u1.offset%u1.step; - u1_offset_x = u1_offset_x/u1.elemSize(); - - int u2_offset_y = u2.offset/u2.step; - int u2_offset_x = u2.offset%u2.step; - u2_offset_x = u2_offset_x/u2.elemSize(); - - String kernelName = "estimateDualVariablesKernel"; - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&u1.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u1.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u1.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u1_step)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&u2.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&p11.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&p11_step)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&p12.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&p21.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&p22.data)); - args.push_back( std::make_pair( sizeof(cl_float), (void*)&taut)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u2_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u1_offset_x)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u1_offset_y)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u2_offset_x)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u2_offset_y)); - - openCLExecuteKernel(clCxt, &tvl1flow, kernelName, globalThread, localThread, args, -1, -1); -} - -void ocl_tvl1flow::estimateU(oclMat &I1wx, oclMat &I1wy, oclMat &grad, - oclMat &rho_c, oclMat &p11, oclMat &p12, - oclMat &p21, oclMat &p22, oclMat &u1, - oclMat &u2, oclMat &error, float l_t, float theta, char calc_error) -{ - Context* clCxt = I1wx.clCxt; - - size_t localThread[] = {32, 8, 1}; - size_t globalThread[] = - { - I1wx.cols, - I1wx.rows, - 1 - }; - - int I1wx_element_size = I1wx.elemSize(); - int I1wx_step = I1wx.step/I1wx_element_size; - - int u1_element_size = u1.elemSize(); - int u1_step = u1.step/u1_element_size; - - int u2_element_size = u2.elemSize(); - int u2_step = u2.step/u2_element_size; - - int u1_offset_y = u1.offset/u1.step; - int u1_offset_x = u1.offset%u1.step; - u1_offset_x = u1_offset_x/u1.elemSize(); - - int u2_offset_y = u2.offset/u2.step; - int u2_offset_x = u2.offset%u2.step; - u2_offset_x = u2_offset_x/u2.elemSize(); - - String kernelName = "estimateUKernel"; - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&I1wx.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&I1wx.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&I1wx.rows)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&I1wx_step)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&I1wy.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&grad.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&rho_c.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&p11.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&p12.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&p21.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&p22.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&u1.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u1_step)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&u2.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&error.data)); - args.push_back( std::make_pair( sizeof(cl_float), (void*)&l_t)); - args.push_back( std::make_pair( sizeof(cl_float), (void*)&theta)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u2_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u1_offset_x)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u1_offset_y)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u2_offset_x)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u2_offset_y)); - args.push_back( std::make_pair( sizeof(cl_char), (void*)&calc_error)); - - openCLExecuteKernel(clCxt, &tvl1flow, kernelName, globalThread, localThread, args, -1, -1); -} - -void ocl_tvl1flow::warpBackward(const oclMat &I0, const oclMat &I1, oclMat &I1x, oclMat &I1y, oclMat &u1, oclMat &u2, oclMat &I1w, oclMat &I1wx, oclMat &I1wy, oclMat &grad, oclMat &rho) -{ - Context* clCxt = I0.clCxt; - - int u1ElementSize = u1.elemSize(); - int u1Step = u1.step/u1ElementSize; - - int u2ElementSize = u2.elemSize(); - int u2Step = u2.step/u2ElementSize; - - int I0ElementSize = I0.elemSize(); - int I0Step = I0.step/I0ElementSize; - - int I1w_element_size = I1w.elemSize(); - int I1w_step = I1w.step/I1w_element_size; - - int u1_offset_y = u1.offset/u1.step; - int u1_offset_x = u1.offset%u1.step; - u1_offset_x = u1_offset_x/u1.elemSize(); - - int u2_offset_y = u2.offset/u2.step; - int u2_offset_x = u2.offset%u2.step; - u2_offset_x = u2_offset_x/u2.elemSize(); - - size_t localThread[] = {32, 8, 1}; - size_t globalThread[] = - { - I0.cols, - I0.rows, - 1 - }; - - cl_mem I1_tex; - cl_mem I1x_tex; - cl_mem I1y_tex; - I1_tex = bindTexture(I1); - I1x_tex = bindTexture(I1x); - I1y_tex = bindTexture(I1y); - - String kernelName = "warpBackwardKernel"; - std::vector< std::pair > args; - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&I0.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&I0Step)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&I0.cols)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&I0.rows)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&I1_tex)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&I1x_tex)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&I1y_tex)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&u1.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u1Step)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&u2.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&I1w.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&I1wx.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&I1wy.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&grad.data)); - args.push_back( std::make_pair( sizeof(cl_mem), (void*)&rho.data)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&I1w_step)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u2Step)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u1_offset_x)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u1_offset_y)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u2_offset_x)); - args.push_back( std::make_pair( sizeof(cl_int), (void*)&u2_offset_y)); - - openCLExecuteKernel(clCxt, &tvl1flow, kernelName, globalThread, localThread, args, -1, -1); - - releaseTexture(I1_tex); - releaseTexture(I1x_tex); - releaseTexture(I1y_tex); -} diff --git a/modules/ocl/test/main.cpp b/modules/ocl/test/main.cpp deleted file mode 100644 index d284fcf4a..000000000 --- a/modules/ocl/test/main.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/*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. -// -// -// Intel 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. -// -// 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 Intel Corporation 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 "test_precomp.hpp" - -#define DUMP_PROPERTY_XML(propertyName, propertyValue) \ - do { \ - std::stringstream ssName, ssValue;\ - ssName << propertyName;\ - ssValue << propertyValue; \ - ::testing::Test::RecordProperty(ssName.str(), ssValue.str()); \ - } while (false) - -#define DUMP_MESSAGE_STDOUT(msg) \ - do { \ - std::cout << msg << std::endl; \ - } while (false) - -#include "opencv2/ocl/private/opencl_dumpinfo.hpp" - -int LOOP_TIMES = 1; - -void readLoopTimes(int argc, char ** argv) -{ - const char * const command_line_keys = - "{ test_loop_times |1 |count of iterations per each test}" - "{h help |false |print help info}"; - - cv::CommandLineParser parser(argc, argv, command_line_keys); - if (parser.has("help")) - { - std::cout << "\nAvailable options besides google test option: \n"; - parser.printMessage(); - } - - LOOP_TIMES = parser.get("test_loop_times"); - CV_Assert(LOOP_TIMES > 0); -} - -CV_TEST_MAIN(".", ::dumpOpenCLDevice(), - readLoopTimes(argc, argv)) diff --git a/modules/ocl/test/test_api.cpp b/modules/ocl/test/test_api.cpp deleted file mode 100644 index 6ca40270d..000000000 --- a/modules/ocl/test/test_api.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/*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-2013, Advanced Micro Devices, Inc., 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 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 "test_precomp.hpp" -#include "opencv2/core/opencl/runtime/opencl_core.hpp" // for OpenCL types & functions -#include "opencv2/core/ocl.hpp" - -TEST(TestAPI, openCLExecuteKernelInterop) -{ - cv::RNG rng; - Size sz(10000, 1); - cv::Mat cpuMat = cvtest::randomMat(rng, sz, CV_32FC4, -10, 10, false); - - cv::ocl::oclMat gpuMat(cpuMat); - cv::ocl::oclMat gpuMatDst(sz, CV_32FC4); - - const char* kernelStr = -"__kernel void test_kernel(__global float4* src, __global float4* dst) {\n" -" int x = get_global_id(0);\n" -" dst[x] = src[x];\n" -"}\n"; - - cv::ocl::ProgramSource program("test_interop", kernelStr); - - using namespace std; - vector > args; - args.push_back( make_pair( sizeof(cl_mem), (void *) &gpuMat.data )); - args.push_back( make_pair( sizeof(cl_mem), (void *) &gpuMatDst.data )); - - size_t globalThreads[3] = { sz.width, 1, 1 }; - cv::ocl::openCLExecuteKernelInterop( - gpuMat.clCxt, - program, - "test_kernel", - globalThreads, NULL, args, - -1, -1, - ""); - - cv::Mat dst; - gpuMatDst.download(dst); - - EXPECT_LE(checkNorm(cpuMat, dst), 1e-3); -} - -TEST(OCL_TestTAPI, performance) -{ - cv::RNG rng; - cv::Mat src(1280,768,CV_8UC4), dst; - rng.fill(src, RNG::UNIFORM, 0, 255); - - cv::UMat usrc, udst; - src.copyTo(usrc); - - cv::ocl::oclMat osrc(src); - cv::ocl::oclMat odst; - - int cvtcode = cv::COLOR_BGR2GRAY; - int i, niters = 10; - double t; - - cv::ocl::cvtColor(osrc, odst, cvtcode); - cv::ocl::finish(); - t = (double)cv::getTickCount(); - for(i = 0; i < niters; i++) - { - cv::ocl::cvtColor(osrc, odst, cvtcode); - } - cv::ocl::finish(); - t = (double)cv::getTickCount() - t; - printf("ocl exec time = %gms per iter\n", t*1000./niters/cv::getTickFrequency()); - - cv::cvtColor(usrc, udst, cvtcode); - cv::ocl::finish2(); - t = (double)cv::getTickCount(); - for(i = 0; i < niters; i++) - { - cv::cvtColor(usrc, udst, cvtcode); - } - cv::ocl::finish2(); - t = (double)cv::getTickCount() - t; - printf("t-api exec time = %gms per iter\n", t*1000./niters/cv::getTickFrequency()); - - cv::cvtColor(src, dst, cvtcode); - t = (double)cv::getTickCount(); - for(i = 0; i < niters; i++) - { - cv::cvtColor(src, dst, cvtcode); - } - t = (double)cv::getTickCount() - t; - printf("cpu exec time = %gms per iter\n", t*1000./niters/cv::getTickFrequency()); -} - -// This test must be DISABLED by default! -// (We can't restore original context for other tests) -TEST(TestAPI, DISABLED_InitializationFromHandles) -{ -#define MAX_PLATFORMS 16 - cl_platform_id platforms[MAX_PLATFORMS] = { NULL }; - cl_uint numPlatforms = 0; - cl_int status = ::clGetPlatformIDs(MAX_PLATFORMS, &platforms[0], &numPlatforms); - ASSERT_EQ(CL_SUCCESS, status) << "clGetPlatformIDs"; - ASSERT_NE(0, (int)numPlatforms); - - int selectedPlatform = 0; - cl_platform_id platform = platforms[selectedPlatform]; - - ASSERT_NE((void*)NULL, platform); - - cl_device_id device = NULL; - status = ::clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1, &device, NULL); - ASSERT_EQ(CL_SUCCESS, status) << "clGetDeviceIDs"; - ASSERT_NE((void*)NULL, device); - - cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(platform), 0 }; - cl_context context = ::clCreateContext(cps, 1, &device, NULL, NULL, &status); - ASSERT_EQ(CL_SUCCESS, status) << "clCreateContext"; - ASSERT_NE((void*)NULL, context); - - ASSERT_NO_THROW(cv::ocl::initializeContext(&platform, &context, &device)); - - status = ::clReleaseContext(context); - ASSERT_EQ(CL_SUCCESS, status) << "clReleaseContext"; - -#ifdef CL_VERSION_1_2 -#if 1 - { - cv::ocl::Context* ctx = cv::ocl::Context::getContext(); - ASSERT_NE((void*)NULL, ctx); - if (ctx->supportsFeature(cv::ocl::FEATURE_CL_VER_1_2)) // device supports OpenCL 1.2+ - { - status = ::clReleaseDevice(device); - ASSERT_EQ(CL_SUCCESS, status) << "clReleaseDevice"; - } - } -#else // code below doesn't work on Linux (SEGFAULTs on 1.1- devices are not handled via exceptions) - try - { - status = ::clReleaseDevice(device); // NOTE This works only with !DEVICES! that supports OpenCL 1.2 - (void)status; // no check - } - catch (...) - { - // nothing, there is no problem - } -#endif -#endif - - // print the name of current device - cv::ocl::Context* ctx = cv::ocl::Context::getContext(); - ASSERT_NE((void*)NULL, ctx); - const cv::ocl::DeviceInfo& deviceInfo = ctx->getDeviceInfo(); - std::cout << "Device name: " << deviceInfo.deviceName << std::endl; - std::cout << "Platform name: " << deviceInfo.platform->platformName << std::endl; - - ASSERT_EQ(context, *(cl_context*)ctx->getOpenCLContextPtr()); - ASSERT_EQ(device, *(cl_device_id*)ctx->getOpenCLDeviceIDPtr()); - - // do some calculations and check results - cv::RNG rng; - Size sz(100, 100); - cv::Mat srcMat = cvtest::randomMat(rng, sz, CV_32FC4, -10, 10, false); - cv::Mat dstMat; - - cv::ocl::oclMat srcGpuMat(srcMat); - cv::ocl::oclMat dstGpuMat; - - cv::Scalar v = cv::Scalar::all(1); - cv::add(srcMat, v, dstMat); - cv::ocl::add(srcGpuMat, v, dstGpuMat); - - cv::Mat dstGpuMatMap; - dstGpuMat.download(dstGpuMatMap); - - EXPECT_LE(checkNorm(dstMat, dstGpuMatMap), 1e-3); -} diff --git a/modules/ocl/test/test_arithm.cpp b/modules/ocl/test/test_arithm.cpp deleted file mode 100644 index bf37afdf5..000000000 --- a/modules/ocl/test/test_arithm.cpp +++ /dev/null @@ -1,1621 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////// -// -// 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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Jia Haipeng, jiahaipeng95@gmail.com -// Shengen Yan, yanshengen@gmail.com -// Jiang Liyuan,jlyuan001.good@163.com -// Rock Li, Rock.Li@amd.com -// Zailong Wu, bullet@yeah.net -// Yao Wang, bitwangyaoyao@gmail.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 "test_precomp.hpp" -#include - -#ifdef HAVE_OPENCL - -using namespace cv; -using namespace cv::ocl; -using namespace cvtest; -using namespace testing; -using namespace std; - -static bool relativeError(double actual, double expected, double eps) -{ - return std::abs(actual - expected) / actual < eps; -} - -//////////////////////////////// LUT ///////////////////////////////////////////////// - -PARAM_TEST_CASE(Lut, MatDepth, MatDepth, bool, bool) -{ - int lut_depth; - int cn; - bool use_roi, same_cn; - - // src mat - cv::Mat src; - cv::Mat lut; - cv::Mat dst; - - // src mat with roi - cv::Mat src_roi; - cv::Mat lut_roi; - cv::Mat dst_roi; - - // ocl dst mat for testing - cv::ocl::oclMat gsrc_whole; - cv::ocl::oclMat glut_whole; - cv::ocl::oclMat gdst_whole; - - // ocl mat with roi - cv::ocl::oclMat gsrc_roi; - cv::ocl::oclMat glut_roi; - cv::ocl::oclMat gdst_roi; - - virtual void SetUp() - { - lut_depth = GET_PARAM(0); - cn = GET_PARAM(1); - same_cn = GET_PARAM(2); - use_roi = GET_PARAM(3); - } - - void random_roi() - { - const int src_type = CV_MAKE_TYPE(CV_8U, cn); - const int lut_type = CV_MAKE_TYPE(lut_depth, same_cn ? cn : 1); - const int dst_type = CV_MAKE_TYPE(lut_depth, cn); - - Size roiSize = randomSize(1, MAX_VALUE); - Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, src_type, 0, 256); - - Size lutRoiSize = Size(256, 1); - Border lutBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(lut, lut_roi, lutRoiSize, lutBorder, lut_type, 5, 16); - - Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(dst, dst_roi, roiSize, dstBorder, dst_type, 5, 16); - - generateOclMat(gsrc_whole, gsrc_roi, src, roiSize, srcBorder); - generateOclMat(glut_whole, glut_roi, lut, lutRoiSize, lutBorder); - generateOclMat(gdst_whole, gdst_roi, dst, roiSize, dstBorder); - } - - void Near(double threshold = 0.) - { - Mat whole, roi; - gdst_whole.download(whole); - gdst_roi.download(roi); - - EXPECT_MAT_NEAR(dst, whole, threshold); - EXPECT_MAT_NEAR(dst_roi, roi, threshold); - } -}; - -OCL_TEST_P(Lut, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::LUT(src_roi, lut_roi, dst_roi); - cv::ocl::LUT(gsrc_roi, glut_roi, gdst_roi); - - Near(); - } -} - -///////////////////////// ArithmTestBase /////////////////////////// - -PARAM_TEST_CASE(ArithmTestBase, MatDepth, Channels, bool) -{ - int depth; - int cn; - bool use_roi; - cv::Scalar val; - - // src mat - cv::Mat src1; - cv::Mat src2; - cv::Mat mask; - cv::Mat dst1; - cv::Mat dst2; - - // src mat with roi - cv::Mat src1_roi; - cv::Mat src2_roi; - cv::Mat mask_roi; - cv::Mat dst1_roi; - cv::Mat dst2_roi; - - // ocl dst mat for testing - cv::ocl::oclMat gsrc1_whole; - cv::ocl::oclMat gsrc2_whole; - cv::ocl::oclMat gdst1_whole; - cv::ocl::oclMat gdst2_whole; - cv::ocl::oclMat gmask_whole; - - // ocl mat with roi - cv::ocl::oclMat gsrc1_roi; - cv::ocl::oclMat gsrc2_roi; - cv::ocl::oclMat gdst1_roi; - cv::ocl::oclMat gdst2_roi; - cv::ocl::oclMat gmask_roi; - - virtual void SetUp() - { - depth = GET_PARAM(0); - cn = GET_PARAM(1); - use_roi = GET_PARAM(2); - } - - virtual void random_roi() - { - const int type = CV_MAKE_TYPE(depth, cn); - - Size roiSize = randomSize(1, MAX_VALUE); - Border src1Border = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(src1, src1_roi, roiSize, src1Border, type, 2, 11); - - Border src2Border = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(src2, src2_roi, roiSize, src2Border, type, -1540, 1740); - - Border dst1Border = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(dst1, dst1_roi, roiSize, dst1Border, type, 5, 16); - - Border dst2Border = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(dst2, dst2_roi, roiSize, dst2Border, type, 5, 16); - - Border maskBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(mask, mask_roi, roiSize, maskBorder, CV_8UC1, 0, 2); - cv::threshold(mask, mask, 0.5, 255., CV_8UC1); - - - generateOclMat(gsrc1_whole, gsrc1_roi, src1, roiSize, src1Border); - generateOclMat(gsrc2_whole, gsrc2_roi, src2, roiSize, src2Border); - generateOclMat(gdst1_whole, gdst1_roi, dst1, roiSize, dst1Border); - generateOclMat(gdst2_whole, gdst2_roi, dst2, roiSize, dst2Border); - generateOclMat(gmask_whole, gmask_roi, mask, roiSize, maskBorder); - - val = cv::Scalar(rng.uniform(-100.0, 100.0), rng.uniform(-100.0, 100.0), - rng.uniform(-100.0, 100.0), rng.uniform(-100.0, 100.0)); - } - - void Near(double threshold = 0.) - { - Mat whole, roi; - gdst1_whole.download(whole); - gdst1_roi.download(roi); - - EXPECT_MAT_NEAR(dst1, whole, threshold); - EXPECT_MAT_NEAR(dst1_roi, roi, threshold); - } - - void Near1(double threshold = 0.) - { - Mat whole, roi; - gdst2_whole.download(whole); - gdst2_roi.download(roi); - - EXPECT_MAT_NEAR(dst2, whole, threshold); - EXPECT_MAT_NEAR(dst2_roi, roi, threshold); - } -}; - -//////////////////////////////// Exp ///////////////////////////////////////////////// - -typedef ArithmTestBase Exp; - -OCL_TEST_P(Exp, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::exp(src1_roi, dst1_roi); - cv::ocl::exp(gsrc1_roi, gdst1_roi); - - Near(2); - } -} - -//////////////////////////////// Log ///////////////////////////////////////////////// - -typedef ArithmTestBase Log; - -OCL_TEST_P(Log, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::log(src1_roi, dst1_roi); - cv::ocl::log(gsrc1_roi, gdst1_roi); - Near(1); - } -} - -//////////////////////////////// Sqrt //////////////////////////////////////////////// - -typedef ArithmTestBase Sqrt; - -OCL_TEST_P(Sqrt, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::sqrt(src1_roi, dst1_roi); - cv::ocl::sqrt(gsrc1_roi, gdst1_roi); - Near(1); - } -} - -//////////////////////////////// Add ///////////////////////////////////////////////// - -typedef ArithmTestBase Add; - -OCL_TEST_P(Add, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::add(src1_roi, src2_roi, dst1_roi); - cv::ocl::add(gsrc1_roi, gsrc2_roi, gdst1_roi); - Near(0); - } -} - -OCL_TEST_P(Add, Mat_Mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::add(src1_roi, src2_roi, dst1_roi, mask_roi); - cv::ocl::add(gsrc1_roi, gsrc2_roi, gdst1_roi, gmask_roi); - Near(0); - } -} - -OCL_TEST_P(Add, Scalar) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::add(src1_roi, val, dst1_roi); - cv::ocl::add(gsrc1_roi, val, gdst1_roi); - Near(1e-5); - } -} - -OCL_TEST_P(Add, Scalar_Mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::add(src1_roi, val, dst1_roi, mask_roi); - cv::ocl::add(gsrc1_roi, val, gdst1_roi, gmask_roi); - Near(1e-5); - } -} - -//////////////////////////////// Sub ///////////////////////////////////////////////// - -typedef ArithmTestBase Sub; - -OCL_TEST_P(Sub, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::subtract(src1_roi, src2_roi, dst1_roi); - cv::ocl::subtract(gsrc1_roi, gsrc2_roi, gdst1_roi); - - Near(0); - } -} - -OCL_TEST_P(Sub, Mat_Mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::subtract(src1_roi, src2_roi, dst1_roi, mask_roi); - cv::ocl::subtract(gsrc1_roi, gsrc2_roi, gdst1_roi, gmask_roi); - Near(0); - } -} - -OCL_TEST_P(Sub, Scalar) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::subtract(src1_roi, val, dst1_roi); - cv::ocl::subtract(gsrc1_roi, val, gdst1_roi); - - Near(1e-5); - } -} - -OCL_TEST_P(Sub, Scalar_Mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::subtract(src1_roi, val, dst1_roi, mask_roi); - cv::ocl::subtract(gsrc1_roi, val, gdst1_roi, gmask_roi); - Near(1e-5); - } -} - -//////////////////////////////// Mul ///////////////////////////////////////////////// - -typedef ArithmTestBase Mul; - -OCL_TEST_P(Mul, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::multiply(src1_roi, src2_roi, dst1_roi); - cv::ocl::multiply(gsrc1_roi, gsrc2_roi, gdst1_roi); - Near(0); - } -} - -OCL_TEST_P(Mul, Scalar) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::multiply(Scalar::all(val[0]), src1_roi, dst1_roi); - cv::ocl::multiply(val[0], gsrc1_roi, gdst1_roi); - - Near(gdst1_roi.depth() >= CV_32F ? 1e-3 : 1); - } -} - -OCL_TEST_P(Mul, Mat_Scalar) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::multiply(src1_roi, src2_roi, dst1_roi, val[0]); - cv::ocl::multiply(gsrc1_roi, gsrc2_roi, gdst1_roi, val[0]); - - Near(gdst1_roi.depth() >= CV_32F ? 1e-3 : 1); - } -} - -//////////////////////////////// Div ///////////////////////////////////////////////// - -typedef ArithmTestBase Div; - -OCL_TEST_P(Div, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::divide(src1_roi, src2_roi, dst1_roi); - cv::ocl::divide(gsrc1_roi, gsrc2_roi, gdst1_roi); - Near(1); - } -} - -OCL_TEST_P(Div, Scalar) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::divide(val[0], src1_roi, dst1_roi); - cv::ocl::divide(val[0], gsrc1_roi, gdst1_roi); - - Near(gdst1_roi.depth() >= CV_32F ? 1e-3 : 1); - } -} - -OCL_TEST_P(Div, Mat_Scalar) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::divide(src1_roi, src2_roi, dst1_roi, val[0]); - cv::ocl::divide(gsrc1_roi, gsrc2_roi, gdst1_roi, val[0]); - - Near(gdst1_roi.depth() >= CV_32F ? 4e-3 : 1); - } -} - -//////////////////////////////// Absdiff ///////////////////////////////////////////////// - -typedef ArithmTestBase Min; - -OCL_TEST_P(Min, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - dst1_roi = cv::min(src1_roi, src2_roi); - cv::ocl::min(gsrc1_roi, gsrc2_roi, gdst1_roi); - Near(0); - } -} - -typedef ArithmTestBase Max; - -OCL_TEST_P(Max, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - dst1_roi = cv::min(src1_roi, src2_roi); - cv::ocl::min(gsrc1_roi, gsrc2_roi, gdst1_roi); - Near(0); - } -} - -//////////////////////////////// Abs ///////////////////////////////////////////////////// - -typedef ArithmTestBase Abs; - -OCL_TEST_P(Abs, Abs) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - dst1_roi = cv::abs(src1_roi); - cv::ocl::abs(gsrc1_roi, gdst1_roi); - Near(0); - } -} - -//////////////////////////////// Absdiff ///////////////////////////////////////////////// - -typedef ArithmTestBase Absdiff; - -OCL_TEST_P(Absdiff, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::absdiff(src1_roi, src2_roi, dst1_roi); - cv::ocl::absdiff(gsrc1_roi, gsrc2_roi, gdst1_roi); - Near(0); - } -} - -OCL_TEST_P(Absdiff, Scalar) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::absdiff(src1_roi, val, dst1_roi); - cv::ocl::absdiff(gsrc1_roi, val, gdst1_roi); - Near(1e-5); - } -} - -//////////////////////////////// CartToPolar ///////////////////////////////////////////////// - -typedef ArithmTestBase CartToPolar; - -OCL_TEST_P(CartToPolar, angleInDegree) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::cartToPolar(src1_roi, src2_roi, dst1_roi, dst2_roi, true); - cv::ocl::cartToPolar(gsrc1_roi, gsrc2_roi, gdst1_roi, gdst2_roi, true); - Near(.5); - Near1(.5); - } -} - -OCL_TEST_P(CartToPolar, angleInRadians) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::cartToPolar(src1_roi, src2_roi, dst1_roi, dst2_roi); - cv::ocl::cartToPolar(gsrc1_roi, gsrc2_roi, gdst1_roi, gdst2_roi); - Near(.5); - Near1(.5); - } -} - -//////////////////////////////// PolarToCart ///////////////////////////////////////////////// - -typedef ArithmTestBase PolarToCart; - -OCL_TEST_P(PolarToCart, angleInDegree) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::polarToCart(src1_roi, src2_roi, dst1_roi, dst2_roi, true); - cv::ocl::polarToCart(gsrc1_roi, gsrc2_roi, gdst1_roi, gdst2_roi, true); - - Near(.5); - Near1(.5); - } -} - -OCL_TEST_P(PolarToCart, angleInRadians) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::polarToCart(src1_roi, src2_roi, dst1_roi, dst2_roi); - cv::ocl::polarToCart(gsrc1_roi, gsrc2_roi, gdst1_roi, gdst2_roi); - - Near(.5); - Near1(.5); - } -} - -//////////////////////////////// Magnitude ///////////////////////////////////////////////// - -typedef ArithmTestBase Magnitude; - -OCL_TEST_P(Magnitude, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::magnitude(src1_roi, src2_roi, dst1_roi); - cv::ocl::magnitude(gsrc1_roi, gsrc2_roi, gdst1_roi); - Near(depth == CV_64F ? 1e-5 : 1e-2); - } -} - -//////////////////////////////// Transpose ///////////////////////////////////////////////// - -typedef ArithmTestBase Transpose; - -OCL_TEST_P(Transpose, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::transpose(src1_roi, dst1_roi); - cv::ocl::transpose(gsrc1_roi, gdst1_roi); - - Near(1e-5); - } -} - -OCL_TEST_P(Transpose, SquareInplace) -{ - const int type = CV_MAKE_TYPE(depth, cn); - - for (int j = 0; j < LOOP_TIMES; j++) - { - Size roiSize = randomSize(1, MAX_VALUE); - roiSize.height = roiSize.width; // make it square - - Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(src1, src1_roi, roiSize, srcBorder, type, 5, 16); - - generateOclMat(gsrc1_whole, gsrc1_roi, src1, roiSize, srcBorder); - - cv::transpose(src1_roi, src1_roi); - cv::ocl::transpose(gsrc1_roi, gsrc1_roi); - - EXPECT_MAT_NEAR(src1, Mat(gsrc1_whole), 0.0); - EXPECT_MAT_NEAR(src1_roi, Mat(gsrc1_roi), 0.0); - } -} - -//////////////////////////////// Flip ///////////////////////////////////////////////// - -typedef ArithmTestBase Flip; - -OCL_TEST_P(Flip, X) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::flip(src1_roi, dst1_roi, 0); - cv::ocl::flip(gsrc1_roi, gdst1_roi, 0); - Near(1e-5); - } -} - -OCL_TEST_P(Flip, Y) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::flip(src1_roi, dst1_roi, 1); - cv::ocl::flip(gsrc1_roi, gdst1_roi, 1); - Near(1e-5); - } -} - -OCL_TEST_P(Flip, BOTH) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::flip(src1_roi, dst1_roi, -1); - cv::ocl::flip(gsrc1_roi, gdst1_roi, -1); - Near(1e-5); - } -} - -//////////////////////////////// MinMax ///////////////////////////////////////////////// - -typedef ArithmTestBase MinMax; - -OCL_TEST_P(MinMax, MAT) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - double minVal, maxVal; - - if (src1.depth() != CV_8S) - cv::minMaxIdx(src1_roi, &minVal, &maxVal, NULL, NULL); - else - { - minVal = std::numeric_limits::max(); - maxVal = -std::numeric_limits::max(); - for (int i = 0; i < src1_roi.rows; ++i) - for (int j = 0; j < src1_roi.cols; ++j) - { - signed char val = src1_roi.at(i, j); - if (val < minVal) minVal = val; - if (val > maxVal) maxVal = val; - } - } - - double minVal_, maxVal_; - cv::ocl::minMax(gsrc1_roi, &minVal_, &maxVal_); - - EXPECT_DOUBLE_EQ(minVal_, minVal); - EXPECT_DOUBLE_EQ(maxVal_, maxVal); - } -} - -OCL_TEST_P(MinMax, MASK) -{ - enum { MAX_IDX = 0, MIN_IDX }; - static const double minMaxGolds[2][7] = - { - { std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), - std::numeric_limits::min(), std::numeric_limits::min(), -std::numeric_limits::max(), -std::numeric_limits::max() }, - { std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), - std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max() }, - }; - - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - double minVal, maxVal; - cv::Point minLoc, maxLoc; - - if (src1.depth() != CV_8S) - cv::minMaxLoc(src1_roi, &minVal, &maxVal, &minLoc, &maxLoc, mask_roi); - else - { - minVal = std::numeric_limits::max(); - maxVal = -std::numeric_limits::max(); - for (int i = 0; i < src1_roi.rows; ++i) - for (int j = 0; j < src1_roi.cols; ++j) - { - signed char val = src1_roi.at(i, j); - unsigned char m = mask_roi.at(i, j); - if (val < minVal && m) minVal = val; - if (val > maxVal && m) maxVal = val; - } - } - - double minVal_, maxVal_; - cv::ocl::minMax(gsrc1_roi, &minVal_, &maxVal_, gmask_roi); - - if (cv::countNonZero(mask_roi) == 0) - { - EXPECT_DOUBLE_EQ(minMaxGolds[MIN_IDX][depth], minVal_); - EXPECT_DOUBLE_EQ(minMaxGolds[MAX_IDX][depth], maxVal_); - } - else - { - EXPECT_DOUBLE_EQ(minVal, minVal_); - EXPECT_DOUBLE_EQ(maxVal, maxVal_); - } - } -} - -//////////////////////////////// MinMaxLoc ///////////////////////////////////////////////// - -typedef ArithmTestBase MinMaxLoc; - -OCL_TEST_P(MinMaxLoc, MAT) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - double minVal, maxVal; - cv::Point minLoc, maxLoc; - int depth = src1.depth(); - - if (depth != CV_8S) - cv::minMaxLoc(src1_roi, &minVal, &maxVal, &minLoc, &maxLoc); - else - { - minVal = std::numeric_limits::max(); - maxVal = -std::numeric_limits::max(); - for (int i = 0; i < src1_roi.rows; ++i) - for (int j = 0; j < src1_roi.cols; ++j) - { - signed char val = src1_roi.at(i, j); - if (val < minVal) - { - minVal = val; - minLoc.x = j; - minLoc.y = i; - } - if (val > maxVal) - { - maxVal = val; - maxLoc.x = j; - maxLoc.y = i; - } - } - } - - double minVal_, maxVal_; - cv::Point minLoc_, maxLoc_; - cv::ocl::minMaxLoc(gsrc1_roi, &minVal_, &maxVal_, &minLoc_, &maxLoc_, cv::ocl::oclMat()); - - double error0 = 0., error1 = 0., minlocVal = 0., minlocVal_ = 0., maxlocVal = 0., maxlocVal_ = 0.; - if (depth == 0) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - if (depth == 1) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - if (depth == 2) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - if (depth == 3) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - if (depth == 4) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - if (depth == 5) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - if (depth == 6) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - - EXPECT_DOUBLE_EQ(minVal_, minVal); - EXPECT_DOUBLE_EQ(maxVal_, maxVal); - EXPECT_DOUBLE_EQ(minlocVal_, minlocVal); - EXPECT_DOUBLE_EQ(maxlocVal_, maxlocVal); - - EXPECT_DOUBLE_EQ(error0, 0.0); - EXPECT_DOUBLE_EQ(error1, 0.0); - } -} - -OCL_TEST_P(MinMaxLoc, MASK) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - double minVal, maxVal; - cv::Point minLoc, maxLoc; - int depth = src1.depth(); - if (depth != CV_8S) - cv::minMaxLoc(src1_roi, &minVal, &maxVal, &minLoc, &maxLoc, mask_roi); - else - { - minVal = std::numeric_limits::max(); - maxVal = -std::numeric_limits::max(); - for (int i = 0; i < src1_roi.rows; ++i) - for (int j = 0; j < src1_roi.cols; ++j) - { - signed char val = src1_roi.at(i, j); - unsigned char m = mask_roi.at(i , j); - if (val < minVal && m) - { - minVal = val; - minLoc.x = j; - minLoc.y = i; - } - if (val > maxVal && m) - { - maxVal = val; - maxLoc.x = j; - maxLoc.y = i; - } - } - } - - double minVal_, maxVal_; - cv::Point minLoc_, maxLoc_; - cv::ocl::minMaxLoc(gsrc1_roi, &minVal_, &maxVal_, &minLoc_, &maxLoc_, gmask_roi); - - double error0 = 0., error1 = 0., minlocVal = 0., minlocVal_ = 0., maxlocVal = 0., maxlocVal_ = 0.; - if (minLoc_.x == -1 || minLoc_.y == -1 || maxLoc_.x == -1 || maxLoc_.y == -1) continue; - if (depth == 0) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - if (depth == 1) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - if (depth == 2) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - if (depth == 3) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - if (depth == 4) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - if (depth == 5) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - if (depth == 6) - { - minlocVal = src1_roi.at(minLoc); - minlocVal_ = src1_roi.at(minLoc_); - maxlocVal = src1_roi.at(maxLoc); - maxlocVal_ = src1_roi.at(maxLoc_); - error0 = ::abs(src1_roi.at(minLoc_) - src1_roi.at(minLoc)); - error1 = ::abs(src1_roi.at(maxLoc_) - src1_roi.at(maxLoc)); - } - - EXPECT_DOUBLE_EQ(minVal_, minVal); - EXPECT_DOUBLE_EQ(maxVal_, maxVal); - EXPECT_DOUBLE_EQ(minlocVal_, minlocVal); - EXPECT_DOUBLE_EQ(maxlocVal_, maxlocVal); - - EXPECT_DOUBLE_EQ(error0, 0.0); - EXPECT_DOUBLE_EQ(error1, 0.0); - } -} - -//////////////////////////////// Sum ///////////////////////////////////////////////// - -typedef ArithmTestBase Sum; - -OCL_TEST_P(Sum, MAT) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - Scalar cpures = cv::sum(src1_roi); - Scalar gpures = cv::ocl::sum(gsrc1_roi); - - // check results - EXPECT_NEAR(cpures[0], gpures[0], 0.1); - EXPECT_NEAR(cpures[1], gpures[1], 0.1); - EXPECT_NEAR(cpures[2], gpures[2], 0.1); - EXPECT_NEAR(cpures[3], gpures[3], 0.1); - } -} - -typedef ArithmTestBase SqrSum; - -template -static Scalar sqrSum(const Mat & src) -{ - Scalar sum = Scalar::all(0); - int cn = src.channels(); - WT data[4] = { 0, 0, 0, 0 }; - - int cols = src.cols * cn; - for (int y = 0; y < src.rows; ++y) - { - const T * const sdata = src.ptr(y); - for (int x = 0; x < cols; ) - for (int i = 0; i < cn; ++i, ++x) - { - WT t = static_cast(sdata[x]); - data[i] += t * t; - } - } - - for (int i = 0; i < cn; ++i) - sum[i] = static_cast(data[i]); - - return sum; -} - -typedef Scalar (*sumFunc)(const Mat &); - -OCL_TEST_P(SqrSum, MAT) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - static sumFunc funcs[] = { sqrSum, - sqrSum, - sqrSum, - sqrSum, - sqrSum, - sqrSum, - sqrSum, - 0 }; - - sumFunc func = funcs[src1_roi.depth()]; - CV_Assert(func != 0); - - Scalar cpures = func(src1_roi); - Scalar gpures = cv::ocl::sqrSum(gsrc1_roi); - - // check results - EXPECT_NEAR(cpures[0], gpures[0], 1.0); - EXPECT_NEAR(cpures[1], gpures[1], 1.0); - EXPECT_NEAR(cpures[2], gpures[2], 1.0); - EXPECT_NEAR(cpures[3], gpures[3], 1.0); - } -} - -typedef ArithmTestBase AbsSum; - -template -static Scalar absSum(const Mat & src) -{ - Scalar sum = Scalar::all(0); - int cn = src.channels(); - WT data[4] = { 0, 0, 0, 0 }; - - int cols = src.cols * cn; - for (int y = 0; y < src.rows; ++y) - { - const T * const sdata = src.ptr(y); - for (int x = 0; x < cols; ) - for (int i = 0; i < cn; ++i, ++x) - { - WT t = static_cast(sdata[x]); - data[i] += t >= 0 ? t : -t; - } - } - - for (int i = 0; i < cn; ++i) - sum[i] = static_cast(data[i]); - - return sum; -} - -OCL_TEST_P(AbsSum, MAT) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - static sumFunc funcs[] = { absSum, - absSum, - absSum, - absSum, - absSum, - absSum, - absSum, - 0 }; - - sumFunc func = funcs[src1_roi.depth()]; - CV_Assert(func != 0); - - Scalar cpures = func(src1_roi); - Scalar gpures = cv::ocl::absSum(gsrc1_roi); - - // check results - EXPECT_NEAR(cpures[0], gpures[0], 0.1); - EXPECT_NEAR(cpures[1], gpures[1], 0.1); - EXPECT_NEAR(cpures[2], gpures[2], 0.1); - EXPECT_NEAR(cpures[3], gpures[3], 0.1); - } -} - -//////////////////////////////// CountNonZero ///////////////////////////////////////////////// - -typedef ArithmTestBase CountNonZero; - -OCL_TEST_P(CountNonZero, MAT) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - int cpures = cv::countNonZero(src1_roi); - int gpures = cv::ocl::countNonZero(gsrc1_roi); - - EXPECT_DOUBLE_EQ((double)cpures, (double)gpures); - } -} - -//////////////////////////////// Phase ///////////////////////////////////////////////// - -typedef ArithmTestBase Phase; - -OCL_TEST_P(Phase, angleInDegrees) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - cv::phase(src1_roi, src2_roi, dst1_roi, true); - cv::ocl::phase(gsrc1_roi, gsrc2_roi, gdst1_roi, true); - - Near(1e-2); - } -} - -OCL_TEST_P(Phase, angleInRadians) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - cv::phase(src1_roi, src2_roi, dst1_roi); - cv::ocl::phase(gsrc1_roi, gsrc2_roi, gdst1_roi); - - Near(1e-2); - } -} - -//////////////////////////////// Bitwise_and ///////////////////////////////////////////////// - -typedef ArithmTestBase Bitwise_and; - -OCL_TEST_P(Bitwise_and, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::bitwise_and(src1_roi, src2_roi, dst1_roi); - cv::ocl::bitwise_and(gsrc1_roi, gsrc2_roi, gdst1_roi); - Near(0); - } -} - -OCL_TEST_P(Bitwise_and, Mat_Mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::bitwise_and(src1_roi, src2_roi, dst1_roi, mask_roi); - cv::ocl::bitwise_and(gsrc1_roi, gsrc2_roi, gdst1_roi, gmask_roi); - Near(0); - } -} - -OCL_TEST_P(Bitwise_and, Scalar) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::bitwise_and(src1_roi, val, dst1_roi); - cv::ocl::bitwise_and(gsrc1_roi, val, gdst1_roi); - Near(1e-5); - } -} - -OCL_TEST_P(Bitwise_and, Scalar_Mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::bitwise_and(src1_roi, val, dst1_roi, mask_roi); - cv::ocl::bitwise_and(gsrc1_roi, val, gdst1_roi, gmask_roi); - Near(1e-5); - } -} - -//////////////////////////////// Bitwise_or ///////////////////////////////////////////////// - -typedef ArithmTestBase Bitwise_or; - -OCL_TEST_P(Bitwise_or, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::bitwise_or(src1_roi, src2_roi, dst1_roi); - cv::ocl::bitwise_or(gsrc1_roi, gsrc2_roi, gdst1_roi); - Near(0); - } -} - -OCL_TEST_P(Bitwise_or, Mat_Mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::bitwise_or(src1_roi, src2_roi, dst1_roi, mask_roi); - cv::ocl::bitwise_or(gsrc1_roi, gsrc2_roi, gdst1_roi, gmask_roi); - Near(0); - } -} - -OCL_TEST_P(Bitwise_or, Scalar) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::bitwise_or(src1_roi, val, dst1_roi); - cv::ocl::bitwise_or(gsrc1_roi, val, gdst1_roi); - Near(1e-5); - } -} - -OCL_TEST_P(Bitwise_or, Scalar_Mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::bitwise_or(src1_roi, val, dst1_roi, mask_roi); - cv::ocl::bitwise_or(gsrc1_roi, val, gdst1_roi, gmask_roi); - Near(1e-5); - } -} - -//////////////////////////////// Bitwise_xor ///////////////////////////////////////////////// - -typedef ArithmTestBase Bitwise_xor; - -OCL_TEST_P(Bitwise_xor, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::bitwise_xor(src1_roi, src2_roi, dst1_roi); - cv::ocl::bitwise_xor(gsrc1_roi, gsrc2_roi, gdst1_roi); - Near(0); - } -} - -OCL_TEST_P(Bitwise_xor, Mat_Mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::bitwise_xor(src1_roi, src2_roi, dst1_roi, mask_roi); - cv::ocl::bitwise_xor(gsrc1_roi, gsrc2_roi, gdst1_roi, gmask_roi); - Near(0); - } -} - -OCL_TEST_P(Bitwise_xor, Scalar) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::bitwise_xor(src1_roi, val, dst1_roi); - cv::ocl::bitwise_xor(gsrc1_roi, val, gdst1_roi); - Near(1e-5); - } -} - -OCL_TEST_P(Bitwise_xor, Scalar_Mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::bitwise_xor(src1_roi, val, dst1_roi, mask_roi); - cv::ocl::bitwise_xor(gsrc1_roi, val, gdst1_roi, gmask_roi); - Near(1e-5); - } -} - -//////////////////////////////// Bitwise_not ///////////////////////////////////////////////// - -typedef ArithmTestBase Bitwise_not; - -OCL_TEST_P(Bitwise_not, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::bitwise_not(src1_roi, dst1_roi); - cv::ocl::bitwise_not(gsrc1_roi, gdst1_roi); - Near(0); - } -} - -//////////////////////////////// Compare ///////////////////////////////////////////////// - -typedef ArithmTestBase Compare; - -OCL_TEST_P(Compare, Mat) -{ - int cmp_codes[] = { CMP_EQ, CMP_GT, CMP_GE, CMP_LT, CMP_LE, CMP_NE }; - int cmp_num = sizeof(cmp_codes) / sizeof(int); - - for (int i = 0; i < cmp_num; ++i) - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::compare(src1_roi, src2_roi, dst1_roi, cmp_codes[i]); - cv::ocl::compare(gsrc1_roi, gsrc2_roi, gdst1_roi, cmp_codes[i]); - - Near(0); - } -} - -//////////////////////////////// Pow ///////////////////////////////////////////////// - -typedef ArithmTestBase Pow; - -OCL_TEST_P(Pow, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - double p = 4.5; - cv::pow(src1_roi, p, dst1_roi); - cv::ocl::pow(gsrc1_roi, p, gdst1_roi); - Near(1); - } -} - -//////////////////////////////// AddWeighted ///////////////////////////////////////////////// - -typedef ArithmTestBase AddWeighted; - -OCL_TEST_P(AddWeighted, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - const double alpha = 2.0, beta = 1.0, gama = 3.0; - - cv::addWeighted(src1_roi, alpha, src2_roi, beta, gama, dst1_roi); - cv::ocl::addWeighted(gsrc1_roi, alpha, gsrc2_roi, beta, gama, gdst1_roi); - - Near(3e-4); - } -} - -//////////////////////////////// setIdentity ///////////////////////////////////////////////// - -typedef ArithmTestBase SetIdentity; - -OCL_TEST_P(SetIdentity, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::setIdentity(dst1_roi, val); - cv::ocl::setIdentity(gdst1_roi, val); - - Near(0); - } -} - -//////////////////////////////// meanStdDev ///////////////////////////////////////////////// - -typedef ArithmTestBase MeanStdDev; - -OCL_TEST_P(MeanStdDev, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - Scalar cpu_mean, cpu_stddev; - Scalar gpu_mean, gpu_stddev; - - cv::meanStdDev(src1_roi, cpu_mean, cpu_stddev); - cv::ocl::meanStdDev(gsrc1_roi, gpu_mean, gpu_stddev); - - for (int i = 0; i < 4; ++i) - { - EXPECT_NEAR(cpu_mean[i], gpu_mean[i], 0.1); - EXPECT_NEAR(cpu_stddev[i], gpu_stddev[i], 0.1); - } - } -} - -//////////////////////////////// Norm ///////////////////////////////////////////////// - -typedef ArithmTestBase Norm; - -OCL_TEST_P(Norm, NORM_INF) -{ - for (int relative = 0; relative < 2; ++relative) - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - int type = NORM_INF; - if (relative == 1) - type |= NORM_RELATIVE; - - const double cpuRes = cv::norm(src1_roi, src2_roi, type); - const double gpuRes = cv::ocl::norm(gsrc1_roi, gsrc2_roi, type); - - EXPECT_NEAR(cpuRes, gpuRes, 0.1); - } -} - -OCL_TEST_P(Norm, NORM_L1) -{ - for (int relative = 0; relative < 2; ++relative) - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - int type = NORM_L1; - if (relative == 1) - type |= NORM_RELATIVE; - - const double cpuRes = cv::norm(src1_roi, src2_roi, type); - const double gpuRes = cv::ocl::norm(gsrc1_roi, gsrc2_roi, type); - - EXPECT_PRED3(relativeError, cpuRes, gpuRes, 1e-6); - } -} - -OCL_TEST_P(Norm, NORM_L2) -{ - for (int relative = 0; relative < 2; ++relative) - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - int type = NORM_L2; - if (relative == 1) - type |= NORM_RELATIVE; - - const double cpuRes = cv::norm(src1_roi, src2_roi, type); - const double gpuRes = cv::ocl::norm(gsrc1_roi, gsrc2_roi, type); - - EXPECT_PRED3(relativeError, cpuRes, gpuRes, 1e-6); - } -} - -//// Repeat - -struct RepeatTestCase : - public ArithmTestBase -{ - int nx, ny; - - virtual void random_roi() - { - const int type = CV_MAKE_TYPE(depth, cn); - - nx = randomInt(1, 4); - ny = randomInt(1, 4); - - Size srcRoiSize = randomSize(1, MAX_VALUE); - Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(src1, src1_roi, srcRoiSize, srcBorder, type, 2, 11); - - Size dstRoiSize(srcRoiSize.width * nx, srcRoiSize.height * ny); - Border dst1Border = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(dst1, dst1_roi, dstRoiSize, dst1Border, type, 5, 16); - - generateOclMat(gsrc1_whole, gsrc1_roi, src1, srcRoiSize, srcBorder); - generateOclMat(gdst1_whole, gdst1_roi, dst1, dstRoiSize, dst1Border); - } -}; - -typedef RepeatTestCase Repeat; - -OCL_TEST_P(Repeat, Mat) -{ - for (int i = 0; i < LOOP_TIMES; ++i) - { - random_roi(); - - cv::repeat(src1_roi, ny, nx, dst1_roi); - cv::ocl::repeat(gsrc1_roi, ny, nx, gdst1_roi); - - Near(); - } -} - -//////////////////////////////////////// Instantiation ///////////////////////////////////////// - -INSTANTIATE_TEST_CASE_P(Arithm, Lut, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool(), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Exp, Combine(testing::Values(CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Log, Combine(testing::Values(CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Sqrt, Combine(testing::Values(CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Add, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Sub, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Mul, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Div, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Min, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Max, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Abs, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Absdiff, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, CartToPolar, Combine(Values(CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, PolarToCart, Combine(Values(CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Magnitude, Combine(Values(CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Transpose, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Flip, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, MinMax, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(Channels(1)), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, MinMaxLoc, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(Channels(1)), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Sum, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, SqrSum, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, AbsSum, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, CountNonZero, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(Channels(1)), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Phase, Combine(Values(CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_and, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_or, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_xor, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_not, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Compare, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(Channels(1)), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Pow, Combine(Values(CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, AddWeighted, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, SetIdentity, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, MeanStdDev, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Norm, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); -INSTANTIATE_TEST_CASE_P(Arithm, Repeat, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); - -#endif // HAVE_OPENCL diff --git a/modules/ocl/test/test_bgfg.cpp b/modules/ocl/test/test_bgfg.cpp deleted file mode 100644 index 8b4c865c3..000000000 --- a/modules/ocl/test/test_bgfg.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/*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-2013, Multicoreware, Inc., all rights reserved. -// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// 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 "test_precomp.hpp" - -#ifdef HAVE_OPENCL - -using namespace cv; -using namespace cv::ocl; -using namespace cvtest; -using namespace testing; -using namespace std; - -#if defined(HAVE_XINE) || \ - defined(HAVE_GSTREAMER) || \ - defined(HAVE_QUICKTIME) || \ - defined(HAVE_AVFOUNDATION) || \ - defined(HAVE_FFMPEG) || \ - defined(WIN32) - -# define BUILD_WITH_VIDEO_INPUT_SUPPORT 1 -#else -# define BUILD_WITH_VIDEO_INPUT_SUPPORT 0 -#endif - -#if BUILD_WITH_VIDEO_INPUT_SUPPORT - -////////////////////////////////////////////////////// -// MOG - -namespace -{ - IMPLEMENT_PARAM_CLASS(UseGray, bool) - IMPLEMENT_PARAM_CLASS(LearningRate, double) -} - -PARAM_TEST_CASE(mog, UseGray, LearningRate, bool) -{ - bool useGray; - double learningRate; - bool useRoi; - - virtual void SetUp() - { - useGray = GET_PARAM(0); - learningRate = GET_PARAM(1); - useRoi = GET_PARAM(2); - } -}; - -OCL_TEST_P(mog, Update) -{ - std::string inputFile = string(cvtest::TS::ptr()->get_data_path()) + "gpu/video/768x576.avi"; - cv::VideoCapture cap(inputFile); - ASSERT_TRUE(cap.isOpened()); - - cv::Mat frame; - cap >> frame; - ASSERT_FALSE(frame.empty()); - - cv::ocl::MOG mog; - cv::ocl::oclMat foreground = createMat_ocl(rng, frame.size(), CV_8UC1, useRoi); - - Ptr mog_gold = createBackgroundSubtractorMOG(); - cv::Mat foreground_gold; - - for (int i = 0; i < 10; ++i) - { - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (useGray) - { - cv::Mat temp; - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - cv::swap(temp, frame); - } - - mog(loadMat_ocl(rng, frame, useRoi), foreground, (float)learningRate); - - mog_gold->apply(frame, foreground_gold, learningRate); - - EXPECT_MAT_NEAR(foreground_gold, foreground, 0.0); - } -} -INSTANTIATE_TEST_CASE_P(OCL_Video, mog, testing::Combine( - testing::Values(UseGray(false), UseGray(true)), - testing::Values(LearningRate(0.0), LearningRate(0.01)), - Values(true, false))); - -////////////////////////////////////////////////////// -// MOG2 - -namespace -{ - IMPLEMENT_PARAM_CLASS(DetectShadow, bool) -} - -PARAM_TEST_CASE(mog2, UseGray, DetectShadow, bool) -{ - bool useGray; - bool detectShadow; - bool useRoi; - virtual void SetUp() - { - useGray = GET_PARAM(0); - detectShadow = GET_PARAM(1); - useRoi = GET_PARAM(2); - } -}; - -OCL_TEST_P(mog2, Update) -{ - std::string inputFile = string(cvtest::TS::ptr()->get_data_path()) + "gpu/video/768x576.avi"; - cv::VideoCapture cap(inputFile); - ASSERT_TRUE(cap.isOpened()); - - cv::Mat frame; - cap >> frame; - ASSERT_FALSE(frame.empty()); - - cv::ocl::MOG2 mog2; - mog2.bShadowDetection = detectShadow; - cv::ocl::oclMat foreground = createMat_ocl(rng, frame.size(), CV_8UC1, useRoi); - - cv::Ptr mog2_gold = createBackgroundSubtractorMOG2(); - mog2_gold->setDetectShadows(detectShadow); - cv::Mat foreground_gold; - - for (int i = 0; i < 10; ++i) - { - cap >> frame; - ASSERT_FALSE(frame.empty()); - - if (useGray) - { - cv::Mat temp; - cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY); - cv::swap(temp, frame); - } - - mog2(loadMat_ocl(rng, frame, useRoi), foreground); - - mog2_gold->apply(frame, foreground_gold); - - if (detectShadow) - EXPECT_MAT_SIMILAR(foreground_gold, foreground, 15e-3) - else - EXPECT_MAT_NEAR(foreground_gold, foreground, 0) - } -} - -OCL_TEST_P(mog2, getBackgroundImage) -{ - if (useGray) - return; - - std::string inputFile = string(cvtest::TS::ptr()->get_data_path()) + "gpu/video/768x576.avi"; - cv::VideoCapture cap(inputFile); - ASSERT_TRUE(cap.isOpened()); - - cv::Mat frame; - - cv::ocl::MOG2 mog2; - mog2.bShadowDetection = detectShadow; - cv::ocl::oclMat foreground; - - cv::Ptr mog2_gold = createBackgroundSubtractorMOG2(); - mog2_gold->setDetectShadows(detectShadow); - cv::Mat foreground_gold; - - for (int i = 0; i < 10; ++i) - { - cap >> frame; - ASSERT_FALSE(frame.empty()); - - mog2(loadMat_ocl(rng, frame, useRoi), foreground); - - mog2_gold->apply(frame, foreground_gold); - } - - cv::ocl::oclMat background = createMat_ocl(rng, frame.size(), frame.type(), useRoi); - mog2.getBackgroundImage(background); - - cv::Mat background_gold; - mog2_gold->getBackgroundImage(background_gold); - - EXPECT_MAT_NEAR(background_gold, background, 1.0); -} - -INSTANTIATE_TEST_CASE_P(OCL_Video, mog2, testing::Combine( - testing::Values(UseGray(true), UseGray(false)), - testing::Values(DetectShadow(true), DetectShadow(false)), - Values(true, false))); - -#endif - -#endif diff --git a/modules/ocl/test/test_blend.cpp b/modules/ocl/test/test_blend.cpp deleted file mode 100644 index 1576891a4..000000000 --- a/modules/ocl/test/test_blend.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/*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 -// Nathan, liujun@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 "test_precomp.hpp" -#include - -using namespace cv; -using namespace cv::ocl; -using namespace testing; -using namespace std; - -template -static void blendLinearGold(const Mat &img1, const Mat &img2, - const Mat &weights1, const Mat &weights2, - Mat &result_gold) -{ - CV_Assert(img1.size() == img2.size() && img1.type() == img2.type()); - CV_Assert(weights1.size() == weights2.size() && weights1.size() == img1.size() && - weights1.type() == CV_32FC1 && weights2.type() == CV_32FC1); - - result_gold.create(img1.size(), img1.type()); - - int cn = img1.channels(); - int step1 = img1.cols * img1.channels(); - - for (int y = 0; y < img1.rows; ++y) - { - const float * const weights1_row = weights1.ptr(y); - const float * const weights2_row = weights2.ptr(y); - const T * const img1_row = img1.ptr(y); - const T * const img2_row = img2.ptr(y); - T * const result_gold_row = result_gold.ptr(y); - - for (int x = 0; x < step1; ++x) - { - int x1 = x / cn; - float w1 = weights1_row[x1], w2 = weights2_row[x1]; - result_gold_row[x] = saturate_cast(((float)img1_row[x] * w1 - + (float)img2_row[x] * w2) / (w1 + w2 + 1e-5f)); - } - } -} - -PARAM_TEST_CASE(Blend, MatDepth, int, bool) -{ - int depth, channels; - bool useRoi; - - Mat src1, src2, weights1, weights2, dst; - Mat src1_roi, src2_roi, weights1_roi, weights2_roi, dst_roi; - oclMat gsrc1, gsrc2, gweights1, gweights2, gdst, gst; - oclMat gsrc1_roi, gsrc2_roi, gweights1_roi, gweights2_roi, gdst_roi; - - virtual void SetUp() - { - depth = GET_PARAM(0); - channels = GET_PARAM(1); - useRoi = GET_PARAM(2); - } - - void random_roi() - { - const int type = CV_MAKE_TYPE(depth, channels); - - const double upValue = 256; - const double sumMinValue = 0.01; // we don't want to divide by "zero" - - Size roiSize = randomSize(1, 20); - Border src1Border = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(src1, src1_roi, roiSize, src1Border, type, -upValue, upValue); - - Border src2Border = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(src2, src2_roi, roiSize, src2Border, type, -upValue, upValue); - - Border weights1Border = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(weights1, weights1_roi, roiSize, weights1Border, CV_32FC1, -upValue, upValue); - - Border weights2Border = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(weights2, weights2_roi, roiSize, weights2Border, CV_32FC1, sumMinValue, upValue); // fill it as a (w1 + w12) - - weights2_roi = weights2_roi - weights1_roi; - // check that weights2_roi is still a part of weights2 (not a new matrix) - CV_Assert(checkNorm(weights2_roi, - weights2(Rect(weights2Border.lef, weights2Border.top, roiSize.width, roiSize.height))) < 1e-6); - - Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(dst, dst_roi, roiSize, dstBorder, type, 5, 16); - - generateOclMat(gsrc1, gsrc1_roi, src1, roiSize, src1Border); - generateOclMat(gsrc2, gsrc2_roi, src2, roiSize, src2Border); - generateOclMat(gweights1, gweights1_roi, weights1, roiSize, weights1Border); - generateOclMat(gweights2, gweights2_roi, weights2, roiSize, weights2Border); - generateOclMat(gdst, gdst_roi, dst, roiSize, dstBorder); - } - - void Near(double eps = 0.0) - { - Mat whole, roi; - gdst.download(whole); - gdst_roi.download(roi); - - EXPECT_MAT_NEAR(dst, whole, eps); - EXPECT_MAT_NEAR(dst_roi, roi, eps); - } -}; - -typedef void (*blendLinearFunc)(const cv::Mat &img1, const cv::Mat &img2, const cv::Mat &weights1, const cv::Mat &weights2, cv::Mat &result_gold); - -OCL_TEST_P(Blend, Accuracy) -{ - for (int i = 0; i < LOOP_TIMES; ++i) - { - random_roi(); - - cv::ocl::blendLinear(gsrc1_roi, gsrc2_roi, gweights1_roi, gweights2_roi, gdst_roi); - - static blendLinearFunc funcs[] = { - blendLinearGold, - blendLinearGold, - blendLinearGold, - blendLinearGold, - blendLinearGold, - blendLinearGold, - }; - - blendLinearFunc func = funcs[depth]; - func(src1_roi, src2_roi, weights1_roi, weights2_roi, dst_roi); - - Near(depth <= CV_32S ? 1.0 : 0.2); - } -} - -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, Blend, - Combine(testing::Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F), - testing::Range(1, 5), Bool())); diff --git a/modules/ocl/test/test_brief.cpp b/modules/ocl/test/test_brief.cpp deleted file mode 100644 index 8ca2c90c7..000000000 --- a/modules/ocl/test/test_brief.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/*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) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009-2010, Willow Garage Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Matthias Bady aegirxx ==> gmail.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 "test_precomp.hpp" - -using namespace std; -using namespace cv; -using namespace ocl; - -#ifdef HAVE_OPENCL - -namespace -{ -IMPLEMENT_PARAM_CLASS( BRIEF_Bytes, int ) -} - -PARAM_TEST_CASE( BRIEF, BRIEF_Bytes ) -{ - int bytes; - - virtual void SetUp( ) - { - bytes = GET_PARAM( 0 ); - } -}; - -OCL_TEST_P( BRIEF, Accuracy ) -{ - Mat img = readImage( "gpu/opticalflow/rubberwhale1.png", IMREAD_GRAYSCALE ); - ASSERT_TRUE( !img.empty( ) ) << "no input image"; - - FastFeatureDetector fast( 20 ); - std::vector keypoints; - fast.detect( img, keypoints, Mat( ) ); - - Mat descriptorsGold; - BriefDescriptorExtractor brief( bytes ); - brief.compute( img, keypoints, descriptorsGold ); - - Mat kpMat( 2, int( keypoints.size() ), CV_32FC1 ); - for ( int i = 0, size = (int)keypoints.size( ); i < size; ++i ) - { - kpMat.col( i ).row( 0 ) = int( keypoints[i].pt.x ); - kpMat.col( i ).row( 1 ) = int( keypoints[i].pt.y ); - } - oclMat imgOcl( img ), keypointsOcl( kpMat ), descriptorsOcl, maskOcl; - - BRIEF_OCL briefOcl( bytes ); - briefOcl.compute( imgOcl, keypointsOcl, maskOcl, descriptorsOcl ); - Mat mask, descriptors; - maskOcl.download( mask ); - descriptorsOcl.download( descriptors ); - - const int numDesc = cv::countNonZero( mask ); - if ( numDesc != descriptors.cols ) - { - int idx = 0; - Mat tmp( numDesc, bytes, CV_8UC1 ); - for ( int i = 0; i < descriptors.rows; ++i ) - { - if ( mask.at(i) ) - { - descriptors.row( i ).copyTo( tmp.row( idx++ ) ); - } - } - descriptors = tmp; - } - ASSERT_TRUE( descriptors.size( ) == descriptorsGold.size( ) ) << "Different number of descriptors"; - ASSERT_TRUE( 0 == norm( descriptors, descriptorsGold, NORM_HAMMING ) ) << "Descriptors different"; -} - -INSTANTIATE_TEST_CASE_P( OCL_Features2D, BRIEF, testing::Values( 16, 32, 64 ) ); -#endif diff --git a/modules/ocl/test/test_brute_force_matcher.cpp b/modules/ocl/test/test_brute_force_matcher.cpp deleted file mode 100644 index 04ca9e297..000000000 --- a/modules/ocl/test/test_brute_force_matcher.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/*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 -// Nathan, liujun@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 "test_precomp.hpp" -#ifdef HAVE_OPENCL -namespace -{ - ///////////////////////////////////////////////////////////////////////////////////////////////// - // BruteForceMatcher - CV_ENUM(DistType, BruteForceMatcher_OCL_base::L1Dist, - BruteForceMatcher_OCL_base::L2Dist, - BruteForceMatcher_OCL_base::HammingDist) - IMPLEMENT_PARAM_CLASS(DescriptorSize, int) - PARAM_TEST_CASE(BruteForceMatcher, DistType, DescriptorSize) - { - cv::ocl::BruteForceMatcher_OCL_base::DistType distType; - int normCode; - int dim; - - int queryDescCount; - int countFactor; - - cv::Mat query, train; - - virtual void SetUp() - { - distType = (cv::ocl::BruteForceMatcher_OCL_base::DistType)(int)GET_PARAM(0); - dim = GET_PARAM(1); - - queryDescCount = 300; // must be even number because we split train data in some cases in two - countFactor = 4; // do not change it - - cv::Mat queryBuf, trainBuf; - - // Generate query descriptors randomly. - // Descriptor vector elements are integer values. - queryBuf.create(queryDescCount, dim, CV_32SC1); - rng.fill(queryBuf, cv::RNG::UNIFORM, cv::Scalar::all(0), cv::Scalar::all(3)); - queryBuf.convertTo(queryBuf, CV_32FC1); - - // Generate train decriptors as follows: - // copy each query descriptor to train set countFactor times - // and perturb some one element of the copied descriptors in - // in ascending order. General boundaries of the perturbation - // are (0.f, 1.f). - trainBuf.create(queryDescCount * countFactor, dim, CV_32FC1); - float step = 1.f / countFactor; - for (int qIdx = 0; qIdx < queryDescCount; qIdx++) - { - cv::Mat queryDescriptor = queryBuf.row(qIdx); - for (int c = 0; c < countFactor; c++) - { - int tIdx = qIdx * countFactor + c; - cv::Mat trainDescriptor = trainBuf.row(tIdx); - queryDescriptor.copyTo(trainDescriptor); - int elem = rng(dim); - float diff = rng.uniform(step * c, step * (c + 1)); - trainDescriptor.at(0, elem) += diff; - } - } - - queryBuf.convertTo(query, CV_32F); - trainBuf.convertTo(train, CV_32F); - } - }; - -#ifdef ANDROID - OCL_TEST_P(BruteForceMatcher, DISABLED_Match_Single) -#else - OCL_TEST_P(BruteForceMatcher, Match_Single) -#endif - { - cv::ocl::BruteForceMatcher_OCL_base matcher(distType); - - std::vector matches; - matcher.match(cv::ocl::oclMat(query), cv::ocl::oclMat(train), matches); - - ASSERT_EQ(static_cast(queryDescCount), matches.size()); - - int badCount = 0; - for (size_t i = 0; i < matches.size(); i++) - { - cv::DMatch match = matches[i]; - if ((match.queryIdx != (int)i) || (match.trainIdx != (int)i * countFactor) || (match.imgIdx != 0)) - badCount++; - } - - ASSERT_EQ(0, badCount); - } - -#ifdef ANDROID - OCL_TEST_P(BruteForceMatcher, DISABLED_KnnMatch_2_Single) -#else - OCL_TEST_P(BruteForceMatcher, KnnMatch_2_Single) -#endif - { - const int knn = 2; - - cv::ocl::BruteForceMatcher_OCL_base matcher(distType); - - std::vector< std::vector > matches; - matcher.knnMatch(cv::ocl::oclMat(query), cv::ocl::oclMat(train), matches, knn); - - ASSERT_EQ(static_cast(queryDescCount), matches.size()); - - int badCount = 0; - for (size_t i = 0; i < matches.size(); i++) - { - if ((int)matches[i].size() != knn) - badCount++; - else - { - int localBadCount = 0; - for (int k = 0; k < knn; k++) - { - cv::DMatch match = matches[i][k]; - if ((match.queryIdx != (int)i) || (match.trainIdx != (int)i * countFactor + k) || (match.imgIdx != 0)) - localBadCount++; - } - badCount += localBadCount > 0 ? 1 : 0; - } - } - - ASSERT_EQ(0, badCount); - } - -#ifdef ANDROID - OCL_TEST_P(BruteForceMatcher, DISABLED_RadiusMatch_Single) -#else - OCL_TEST_P(BruteForceMatcher, RadiusMatch_Single) -#endif - { - float radius = 1.f / countFactor; - - cv::ocl::BruteForceMatcher_OCL_base matcher(distType); - - std::vector< std::vector > matches; - matcher.radiusMatch(cv::ocl::oclMat(query), cv::ocl::oclMat(train), matches, radius); - - ASSERT_EQ(static_cast(queryDescCount), matches.size()); - - int badCount = 0; - for (size_t i = 0; i < matches.size(); i++) - { - if ((int)matches[i].size() != 1) - { - badCount++; - } - else - { - cv::DMatch match = matches[i][0]; - if ((match.queryIdx != (int)i) || (match.trainIdx != (int)i * countFactor) || (match.imgIdx != 0)) - badCount++; - } - } - - ASSERT_EQ(0, badCount); - } - - INSTANTIATE_TEST_CASE_P(OCL_Features2D, BruteForceMatcher, - testing::Combine( - testing::Values( - DistType(cv::ocl::BruteForceMatcher_OCL_base::L1Dist), - DistType(cv::ocl::BruteForceMatcher_OCL_base::L2Dist)/*, - DistType(cv::ocl::BruteForceMatcher_OCL_base::HammingDist)*/ - ), - testing::Values( - DescriptorSize(57), - DescriptorSize(64), - DescriptorSize(83), - DescriptorSize(128), - DescriptorSize(179), - DescriptorSize(256), - DescriptorSize(304)) - ) - ); -} // namespace -#endif diff --git a/modules/ocl/test/test_calib3d.cpp b/modules/ocl/test/test_calib3d.cpp deleted file mode 100644 index 9fd0b2329..000000000 --- a/modules/ocl/test/test_calib3d.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////// -// -// 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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Peng Xiao, pengxiao@outlook.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 "test_precomp.hpp" -#include - -using namespace cv; - -#ifdef HAVE_OPENCL - -PARAM_TEST_CASE(StereoMatchBM, int, int) -{ - int n_disp; - int winSize; - - virtual void SetUp() - { - n_disp = GET_PARAM(0); - winSize = GET_PARAM(1); - } -}; - -OCL_TEST_P(StereoMatchBM, Regression) -{ - - Mat left_image = readImage("gpu/stereobm/aloe-L.png", IMREAD_GRAYSCALE); - Mat right_image = readImage("gpu/stereobm/aloe-R.png", IMREAD_GRAYSCALE); - Mat disp_gold = readImage("gpu/stereobm/aloe-disp.png", IMREAD_GRAYSCALE); - ocl::oclMat d_left, d_right; - ocl::oclMat d_disp(left_image.size(), CV_8U); - Mat disp; - - ASSERT_FALSE(left_image.empty()); - ASSERT_FALSE(right_image.empty()); - ASSERT_FALSE(disp_gold.empty()); - d_left.upload(left_image); - d_right.upload(right_image); - - ocl::StereoBM_OCL bm(0, n_disp, winSize); - - - bm(d_left, d_right, d_disp); - d_disp.download(disp); - - EXPECT_MAT_SIMILAR(disp_gold, disp, 1e-3); -} - -INSTANTIATE_TEST_CASE_P(OCL_Calib3D, StereoMatchBM, testing::Combine(testing::Values(128), - testing::Values(19))); - -PARAM_TEST_CASE(StereoMatchBP, int, int, int, float, float, float, float) -{ - int ndisp_; - int iters_; - int levels_; - float max_data_term_; - float data_weight_; - float max_disc_term_; - float disc_single_jump_; - virtual void SetUp() - { - ndisp_ = GET_PARAM(0); - iters_ = GET_PARAM(1); - levels_ = GET_PARAM(2); - max_data_term_ = GET_PARAM(3); - data_weight_ = GET_PARAM(4); - max_disc_term_ = GET_PARAM(5); - disc_single_jump_ = GET_PARAM(6); - } -}; -OCL_TEST_P(StereoMatchBP, Regression) -{ - Mat left_image = readImage("gpu/stereobp/aloe-L.png"); - Mat right_image = readImage("gpu/stereobp/aloe-R.png"); - Mat disp_gold = readImage("gpu/stereobp/aloe-disp.png", IMREAD_GRAYSCALE); - ocl::oclMat d_left, d_right; - ocl::oclMat d_disp; - Mat disp; - ASSERT_FALSE(left_image.empty()); - ASSERT_FALSE(right_image.empty()); - ASSERT_FALSE(disp_gold.empty()); - d_left.upload(left_image); - d_right.upload(right_image); - ocl::StereoBeliefPropagation bp(ndisp_, iters_, levels_, max_data_term_, data_weight_, - max_disc_term_, disc_single_jump_, CV_16S); - bp(d_left, d_right, d_disp); - d_disp.download(disp); - disp.convertTo(disp, disp_gold.depth()); - EXPECT_MAT_NEAR(disp_gold, disp, 0.0); -} -INSTANTIATE_TEST_CASE_P(OCL_Calib3D, StereoMatchBP, testing::Combine(testing::Values(64), - testing::Values(8),testing::Values(2),testing::Values(25.0f), - testing::Values(0.1f),testing::Values(15.0f),testing::Values(1.0f))); - -////////////////////////////////////////////////////////////////////////// -// ConstSpaceBeliefPropagation -PARAM_TEST_CASE(StereoMatchConstSpaceBP, int, int, int, int, float, float, float, float, int, int) -{ - int ndisp_; - int iters_; - int levels_; - int nr_plane_; - float max_data_term_; - float data_weight_; - float max_disc_term_; - float disc_single_jump_; - int min_disp_th_; - int msg_type_; - - virtual void SetUp() - { - ndisp_ = GET_PARAM(0); - iters_ = GET_PARAM(1); - levels_ = GET_PARAM(2); - nr_plane_ = GET_PARAM(3); - max_data_term_ = GET_PARAM(4); - data_weight_ = GET_PARAM(5); - max_disc_term_ = GET_PARAM(6); - disc_single_jump_ = GET_PARAM(7); - min_disp_th_ = GET_PARAM(8); - msg_type_ = GET_PARAM(9); - } -}; -OCL_TEST_P(StereoMatchConstSpaceBP, Regression) -{ - Mat left_image = readImage("gpu/csstereobp/aloe-L.png"); - Mat right_image = readImage("gpu/csstereobp/aloe-R.png"); - Mat disp_gold = readImage("gpu/csstereobp/aloe-disp.png", IMREAD_GRAYSCALE); - - ocl::oclMat d_left, d_right; - ocl::oclMat d_disp; - - Mat disp; - ASSERT_FALSE(left_image.empty()); - ASSERT_FALSE(right_image.empty()); - ASSERT_FALSE(disp_gold.empty()); - - d_left.upload(left_image); - d_right.upload(right_image); - - ocl::StereoConstantSpaceBP bp(ndisp_, iters_, levels_, nr_plane_, max_data_term_, data_weight_, - max_disc_term_, disc_single_jump_, 0, CV_32F); - bp(d_left, d_right, d_disp); - d_disp.download(disp); - disp.convertTo(disp, disp_gold.depth()); - - EXPECT_MAT_SIMILAR(disp_gold, disp, 1e-4); - //EXPECT_MAT_NEAR(disp_gold, disp, 1.0, ""); -} -INSTANTIATE_TEST_CASE_P(OCL_Calib3D, StereoMatchConstSpaceBP, testing::Combine(testing::Values(128), - testing::Values(16),testing::Values(4), testing::Values(4), testing::Values(30.0f), - testing::Values(1.0f),testing::Values(160.0f), - testing::Values(10.0f), testing::Values(0), testing::Values(CV_32F))); -#endif // HAVE_OPENCL diff --git a/modules/ocl/test/test_canny.cpp b/modules/ocl/test/test_canny.cpp deleted file mode 100644 index 6bd7f26ad..000000000 --- a/modules/ocl/test/test_canny.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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 "test_precomp.hpp" -#ifdef HAVE_OPENCL - -//////////////////////////////////////////////////////// -// Canny -IMPLEMENT_PARAM_CLASS(AppertureSize, int) -IMPLEMENT_PARAM_CLASS(L2gradient, bool) - -PARAM_TEST_CASE(Canny, AppertureSize, L2gradient) -{ - int apperture_size; - bool useL2gradient; - - cv::Mat edges_gold; - virtual void SetUp() - { - apperture_size = GET_PARAM(0); - useL2gradient = GET_PARAM(1); - } -}; - -OCL_TEST_P(Canny, Accuracy) -{ - cv::Mat img = readImage("cv/shared/fruits.png", cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(img.empty()); - - double low_thresh = 50.0; - double high_thresh = 100.0; - - cv::ocl::oclMat ocl_img = cv::ocl::oclMat(img); - - cv::ocl::oclMat edges; - cv::ocl::Canny(ocl_img, edges, low_thresh, high_thresh, apperture_size, useL2gradient); - - cv::Mat edges_gold; - cv::Canny(img, edges_gold, low_thresh, high_thresh, apperture_size, useL2gradient); - - EXPECT_MAT_SIMILAR(edges_gold, edges, 1e-2); -} - -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, Canny, testing::Combine( - testing::Values(AppertureSize(3), AppertureSize(5)), - testing::Values(L2gradient(false), L2gradient(true)))); -#endif diff --git a/modules/ocl/test/test_color.cpp b/modules/ocl/test/test_color.cpp deleted file mode 100644 index c4641d42c..000000000 --- a/modules/ocl/test/test_color.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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 "test_precomp.hpp" - -using namespace cv; - -#ifdef HAVE_OPENCL - -using namespace testing; -using namespace cv; - -/////////////////////////////////////////////////////////////////////////////////////////////////////// -// cvtColor - -PARAM_TEST_CASE(CvtColor, MatDepth, bool) -{ - int depth; - bool use_roi; - - // src mat - Mat src; - Mat dst; - - // src mat with roi - Mat src_roi; - Mat dst_roi; - - // ocl dst mat for testing - ocl::oclMat gsrc_whole; - ocl::oclMat gdst_whole; - - // ocl mat with roi - ocl::oclMat gsrc_roi; - ocl::oclMat gdst_roi; - - virtual void SetUp() - { - depth = GET_PARAM(0); - use_roi = GET_PARAM(1); - } - - virtual void random_roi(int channelsIn, int channelsOut) - { - const int srcType = CV_MAKE_TYPE(depth, channelsIn); - const int dstType = CV_MAKE_TYPE(depth, channelsOut); - - Size roiSize = randomSize(1, MAX_VALUE); - Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, srcType, 2, 100); - - Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(dst, dst_roi, roiSize, dstBorder, dstType, 5, 16); - - generateOclMat(gsrc_whole, gsrc_roi, src, roiSize, srcBorder); - generateOclMat(gdst_whole, gdst_roi, dst, roiSize, dstBorder); - } - - void Near(double threshold) - { - Mat whole, roi; - gdst_whole.download(whole); - gdst_roi.download(roi); - - EXPECT_MAT_NEAR(dst, whole, threshold); - EXPECT_MAT_NEAR(dst_roi, roi, threshold); - } - - void doTest(int channelsIn, int channelsOut, int code, double threshold = 1e-3) - { - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(channelsIn, channelsOut); - - cvtColor(src_roi, dst_roi, code, channelsOut); - ocl::cvtColor(gsrc_roi, gdst_roi, code, channelsOut); - - Near(threshold); - } - } -}; - -#define CVTCODE(name) COLOR_ ## name - -// RGB[A] <-> BGR[A] - -OCL_TEST_P(CvtColor, BGR2BGRA) { doTest(3, 4, CVTCODE(BGR2BGRA)); } -OCL_TEST_P(CvtColor, RGB2RGBA) { doTest(3, 4, CVTCODE(RGB2RGBA)); } -OCL_TEST_P(CvtColor, BGRA2BGR) { doTest(4, 3, CVTCODE(BGRA2BGR)); } -OCL_TEST_P(CvtColor, RGBA2RGB) { doTest(4, 3, CVTCODE(RGBA2RGB)); } -OCL_TEST_P(CvtColor, BGR2RGBA) { doTest(3, 4, CVTCODE(BGR2RGBA)); } -OCL_TEST_P(CvtColor, RGB2BGRA) { doTest(3, 4, CVTCODE(RGB2BGRA)); } -OCL_TEST_P(CvtColor, RGBA2BGR) { doTest(4, 3, CVTCODE(RGBA2BGR)); } -OCL_TEST_P(CvtColor, BGRA2RGB) { doTest(4, 3, CVTCODE(BGRA2RGB)); } -OCL_TEST_P(CvtColor, BGR2RGB) { doTest(3, 3, CVTCODE(BGR2RGB)); } -OCL_TEST_P(CvtColor, RGB2BGR) { doTest(3, 3, CVTCODE(RGB2BGR)); } -OCL_TEST_P(CvtColor, BGRA2RGBA) { doTest(4, 4, CVTCODE(BGRA2RGBA)); } -OCL_TEST_P(CvtColor, RGBA2BGRA) { doTest(4, 4, CVTCODE(RGBA2BGRA)); } - -// RGB <-> Gray - -OCL_TEST_P(CvtColor, RGB2GRAY) { doTest(3, 1, CVTCODE(RGB2GRAY)); } -OCL_TEST_P(CvtColor, GRAY2RGB) { doTest(1, 3, CVTCODE(GRAY2RGB)); } -OCL_TEST_P(CvtColor, BGR2GRAY) { doTest(3, 1, CVTCODE(BGR2GRAY)); } -OCL_TEST_P(CvtColor, GRAY2BGR) { doTest(1, 3, CVTCODE(GRAY2BGR)); } -OCL_TEST_P(CvtColor, RGBA2GRAY) { doTest(4, 1, CVTCODE(RGBA2GRAY)); } -OCL_TEST_P(CvtColor, GRAY2RGBA) { doTest(1, 4, CVTCODE(GRAY2RGBA)); } -OCL_TEST_P(CvtColor, BGRA2GRAY) { doTest(4, 1, CVTCODE(BGRA2GRAY)); } -OCL_TEST_P(CvtColor, GRAY2BGRA) { doTest(1, 4, CVTCODE(GRAY2BGRA)); } - -// RGB <-> YUV - -OCL_TEST_P(CvtColor, RGB2YUV) { doTest(3, 3, CVTCODE(RGB2YUV)); } -OCL_TEST_P(CvtColor, BGR2YUV) { doTest(3, 3, CVTCODE(BGR2YUV)); } -OCL_TEST_P(CvtColor, RGBA2YUV) { doTest(4, 3, CVTCODE(RGB2YUV)); } -OCL_TEST_P(CvtColor, BGRA2YUV) { doTest(4, 3, CVTCODE(BGR2YUV)); } -OCL_TEST_P(CvtColor, YUV2RGB) { doTest(3, 3, CVTCODE(YUV2RGB)); } -OCL_TEST_P(CvtColor, YUV2BGR) { doTest(3, 3, CVTCODE(YUV2BGR)); } -OCL_TEST_P(CvtColor, YUV2RGBA) { doTest(3, 4, CVTCODE(YUV2RGB)); } -OCL_TEST_P(CvtColor, YUV2BGRA) { doTest(3, 4, CVTCODE(YUV2BGR)); } - -// RGB <-> YCrCb - -OCL_TEST_P(CvtColor, RGB2YCrCb) { doTest(3, 3, CVTCODE(RGB2YCrCb)); } -OCL_TEST_P(CvtColor, BGR2YCrCb) { doTest(3, 3, CVTCODE(BGR2YCrCb)); } -OCL_TEST_P(CvtColor, RGBA2YCrCb) { doTest(4, 3, CVTCODE(RGB2YCrCb)); } -OCL_TEST_P(CvtColor, BGRA2YCrCb) { doTest(4, 3, CVTCODE(BGR2YCrCb)); } -OCL_TEST_P(CvtColor, YCrCb2RGB) { doTest(3, 3, CVTCODE(YCrCb2RGB)); } -OCL_TEST_P(CvtColor, YCrCb2BGR) { doTest(3, 3, CVTCODE(YCrCb2BGR)); } -OCL_TEST_P(CvtColor, YCrCb2RGBA) { doTest(3, 4, CVTCODE(YCrCb2RGB)); } -OCL_TEST_P(CvtColor, YCrCb2BGRA) { doTest(3, 4, CVTCODE(YCrCb2BGR)); } - -// RGB <-> XYZ - -OCL_TEST_P(CvtColor, RGB2XYZ) { doTest(3, 3, CVTCODE(RGB2XYZ)); } -OCL_TEST_P(CvtColor, BGR2XYZ) { doTest(3, 3, CVTCODE(BGR2XYZ)); } -OCL_TEST_P(CvtColor, RGBA2XYZ) { doTest(4, 3, CVTCODE(RGB2XYZ)); } -OCL_TEST_P(CvtColor, BGRA2XYZ) { doTest(4, 3, CVTCODE(BGR2XYZ)); } - -OCL_TEST_P(CvtColor, XYZ2RGB) { doTest(3, 3, CVTCODE(XYZ2RGB)); } -OCL_TEST_P(CvtColor, XYZ2BGR) { doTest(3, 3, CVTCODE(XYZ2BGR)); } -OCL_TEST_P(CvtColor, XYZ2RGBA) { doTest(3, 4, CVTCODE(XYZ2RGB)); } -OCL_TEST_P(CvtColor, XYZ2BGRA) { doTest(3, 4, CVTCODE(XYZ2BGR)); } - -// RGB <-> HSV - -typedef CvtColor CvtColor8u32f; - -OCL_TEST_P(CvtColor8u32f, RGB2HSV) { doTest(3, 3, CVTCODE(RGB2HSV)); } -OCL_TEST_P(CvtColor8u32f, BGR2HSV) { doTest(3, 3, CVTCODE(BGR2HSV)); } -OCL_TEST_P(CvtColor8u32f, RGBA2HSV) { doTest(4, 3, CVTCODE(RGB2HSV)); } -OCL_TEST_P(CvtColor8u32f, BGRA2HSV) { doTest(4, 3, CVTCODE(BGR2HSV)); } - -OCL_TEST_P(CvtColor8u32f, RGB2HSV_FULL) { doTest(3, 3, CVTCODE(RGB2HSV_FULL)); } -OCL_TEST_P(CvtColor8u32f, BGR2HSV_FULL) { doTest(3, 3, CVTCODE(BGR2HSV_FULL)); } -OCL_TEST_P(CvtColor8u32f, RGBA2HSV_FULL) { doTest(4, 3, CVTCODE(RGB2HSV_FULL)); } -OCL_TEST_P(CvtColor8u32f, BGRA2HSV_FULL) { doTest(4, 3, CVTCODE(BGR2HSV_FULL)); } - -OCL_TEST_P(CvtColor8u32f, HSV2RGB) { doTest(3, 3, CVTCODE(HSV2RGB), depth == CV_8U ? 1 : 4e-1); } -OCL_TEST_P(CvtColor8u32f, HSV2BGR) { doTest(3, 3, CVTCODE(HSV2BGR), depth == CV_8U ? 1 : 4e-1); } -OCL_TEST_P(CvtColor8u32f, HSV2RGBA) { doTest(3, 4, CVTCODE(HSV2RGB), depth == CV_8U ? 1 : 4e-1); } -OCL_TEST_P(CvtColor8u32f, HSV2BGRA) { doTest(3, 4, CVTCODE(HSV2BGR), depth == CV_8U ? 1 : 4e-1); } - -OCL_TEST_P(CvtColor8u32f, HSV2RGB_FULL) { doTest(3, 3, CVTCODE(HSV2RGB_FULL), depth == CV_8U ? 1 : 4e-1); } -OCL_TEST_P(CvtColor8u32f, HSV2BGR_FULL) { doTest(3, 3, CVTCODE(HSV2BGR_FULL), depth == CV_8U ? 1 : 4e-1); } -OCL_TEST_P(CvtColor8u32f, HSV2RGBA_FULL) { doTest(3, 4, CVTCODE(HSV2BGR_FULL), depth == CV_8U ? 1 : 4e-1); } -OCL_TEST_P(CvtColor8u32f, HSV2BGRA_FULL) { doTest(3, 4, CVTCODE(HSV2BGR_FULL), depth == CV_8U ? 1 : 4e-1); } - -// RGB <-> HLS - -OCL_TEST_P(CvtColor8u32f, RGB2HLS) { doTest(3, 3, CVTCODE(RGB2HLS), depth == CV_8U ? 1 : 1e-3); } -OCL_TEST_P(CvtColor8u32f, BGR2HLS) { doTest(3, 3, CVTCODE(BGR2HLS), depth == CV_8U ? 1 : 1e-3); } -OCL_TEST_P(CvtColor8u32f, RGBA2HLS) { doTest(4, 3, CVTCODE(RGB2HLS), depth == CV_8U ? 1 : 1e-3); } -OCL_TEST_P(CvtColor8u32f, BGRA2HLS) { doTest(4, 3, CVTCODE(BGR2HLS), depth == CV_8U ? 1 : 1e-3); } - -OCL_TEST_P(CvtColor8u32f, RGB2HLS_FULL) { doTest(3, 3, CVTCODE(RGB2HLS_FULL), depth == CV_8U ? 1 : 1e-3); } -OCL_TEST_P(CvtColor8u32f, BGR2HLS_FULL) { doTest(3, 3, CVTCODE(BGR2HLS_FULL), depth == CV_8U ? 1 : 1e-3); } -OCL_TEST_P(CvtColor8u32f, RGBA2HLS_FULL) { doTest(4, 3, CVTCODE(RGB2HLS_FULL), depth == CV_8U ? 1 : 1e-3); } -OCL_TEST_P(CvtColor8u32f, BGRA2HLS_FULL) { doTest(4, 3, CVTCODE(BGR2HLS_FULL), depth == CV_8U ? 1 : 1e-3); } - -OCL_TEST_P(CvtColor8u32f, HLS2RGB) { doTest(3, 3, CVTCODE(HLS2RGB), 1); } -OCL_TEST_P(CvtColor8u32f, HLS2BGR) { doTest(3, 3, CVTCODE(HLS2BGR), 1); } -OCL_TEST_P(CvtColor8u32f, HLS2RGBA) { doTest(3, 4, CVTCODE(HLS2RGB), 1); } -OCL_TEST_P(CvtColor8u32f, HLS2BGRA) { doTest(3, 4, CVTCODE(HLS2BGR), 1); } - -OCL_TEST_P(CvtColor8u32f, HLS2RGB_FULL) { doTest(3, 3, CVTCODE(HLS2RGB_FULL), 1); } -OCL_TEST_P(CvtColor8u32f, HLS2BGR_FULL) { doTest(3, 3, CVTCODE(HLS2BGR_FULL), 1); } -OCL_TEST_P(CvtColor8u32f, HLS2RGBA_FULL) { doTest(3, 4, CVTCODE(HLS2RGB_FULL), 1); } -OCL_TEST_P(CvtColor8u32f, HLS2BGRA_FULL) { doTest(3, 4, CVTCODE(HLS2BGR_FULL), 1); } - -// RGB5x5 <-> RGB - -typedef CvtColor CvtColor8u; - -OCL_TEST_P(CvtColor8u, BGR5652BGR) { doTest(2, 3, CVTCODE(BGR5652BGR)); } -OCL_TEST_P(CvtColor8u, BGR5652RGB) { doTest(2, 3, CVTCODE(BGR5652RGB)); } -OCL_TEST_P(CvtColor8u, BGR5652BGRA) { doTest(2, 4, CVTCODE(BGR5652BGRA)); } -OCL_TEST_P(CvtColor8u, BGR5652RGBA) { doTest(2, 4, CVTCODE(BGR5652RGBA)); } - -OCL_TEST_P(CvtColor8u, BGR5552BGR) { doTest(2, 3, CVTCODE(BGR5552BGR)); } -OCL_TEST_P(CvtColor8u, BGR5552RGB) { doTest(2, 3, CVTCODE(BGR5552RGB)); } -OCL_TEST_P(CvtColor8u, BGR5552BGRA) { doTest(2, 4, CVTCODE(BGR5552BGRA)); } -OCL_TEST_P(CvtColor8u, BGR5552RGBA) { doTest(2, 4, CVTCODE(BGR5552RGBA)); } - -OCL_TEST_P(CvtColor8u, BGR2BGR565) { doTest(3, 2, CVTCODE(BGR2BGR565)); } -OCL_TEST_P(CvtColor8u, RGB2BGR565) { doTest(3, 2, CVTCODE(RGB2BGR565)); } -OCL_TEST_P(CvtColor8u, BGRA2BGR565) { doTest(4, 2, CVTCODE(BGRA2BGR565)); } -OCL_TEST_P(CvtColor8u, RGBA2BGR565) { doTest(4, 2, CVTCODE(RGBA2BGR565)); } - -OCL_TEST_P(CvtColor8u, BGR2BGR555) { doTest(3, 2, CVTCODE(BGR2BGR555)); } -OCL_TEST_P(CvtColor8u, RGB2BGR555) { doTest(3, 2, CVTCODE(RGB2BGR555)); } -OCL_TEST_P(CvtColor8u, BGRA2BGR555) { doTest(4, 2, CVTCODE(BGRA2BGR555)); } -OCL_TEST_P(CvtColor8u, RGBA2BGR555) { doTest(4, 2, CVTCODE(RGBA2BGR555)); } - -// RGB5x5 <-> Gray - -OCL_TEST_P(CvtColor8u, BGR5652GRAY) { doTest(2, 1, CVTCODE(BGR5652GRAY)); } -OCL_TEST_P(CvtColor8u, BGR5552GRAY) { doTest(2, 1, CVTCODE(BGR5552GRAY)); } - -OCL_TEST_P(CvtColor8u, GRAY2BGR565) { doTest(1, 2, CVTCODE(GRAY2BGR565)); } -OCL_TEST_P(CvtColor8u, GRAY2BGR555) { doTest(1, 2, CVTCODE(GRAY2BGR555)); } - -// RGBA <-> mRGBA - -OCL_TEST_P(CvtColor8u, RGBA2mRGBA) { doTest(4, 4, CVTCODE(RGBA2mRGBA)); } -OCL_TEST_P(CvtColor8u, mRGBA2RGBA) { doTest(4, 4, CVTCODE(mRGBA2RGBA)); } - -// YUV -> RGBA_NV12 - -struct CvtColor_YUV420 : - public CvtColor -{ - void random_roi(int channelsIn, int channelsOut) - { - const int srcType = CV_MAKE_TYPE(depth, channelsIn); - const int dstType = CV_MAKE_TYPE(depth, channelsOut); - - Size roiSize = randomSize(1, MAX_VALUE); - roiSize.width *= 2; - roiSize.height *= 3; - Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, srcType, 2, 100); - - Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(dst, dst_roi, roiSize, dstBorder, dstType, 5, 16); - - generateOclMat(gsrc_whole, gsrc_roi, src, roiSize, srcBorder); - generateOclMat(gdst_whole, gdst_roi, dst, roiSize, dstBorder); - } -}; - -OCL_TEST_P(CvtColor_YUV420, YUV2RGBA_NV12) { doTest(1, 4, COLOR_YUV2RGBA_NV12); } -OCL_TEST_P(CvtColor_YUV420, YUV2BGRA_NV12) { doTest(1, 4, COLOR_YUV2BGRA_NV12); } -OCL_TEST_P(CvtColor_YUV420, YUV2RGB_NV12) { doTest(1, 3, COLOR_YUV2RGB_NV12); } -OCL_TEST_P(CvtColor_YUV420, YUV2BGR_NV12) { doTest(1, 3, COLOR_YUV2BGR_NV12); } - - -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, CvtColor8u, - testing::Combine(testing::Values(MatDepth(CV_8U)), Bool())); - -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, CvtColor8u32f, - testing::Combine(testing::Values(MatDepth(CV_8U), MatDepth(CV_32F)), Bool())); - -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, CvtColor, - testing::Combine( - testing::Values(MatDepth(CV_8U), MatDepth(CV_16U), MatDepth(CV_32F)), - Bool())); - -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, CvtColor_YUV420, - testing::Combine( - testing::Values(MatDepth(CV_8U)), - Bool())); - -#endif diff --git a/modules/ocl/test/test_fast.cpp b/modules/ocl/test/test_fast.cpp deleted file mode 100644 index 19ff68e12..000000000 --- a/modules/ocl/test/test_fast.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/*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. -// -// Authors: -// * Peter Andreas Entschev, peter@entschev.com -// -//M*/ - -#include "test_precomp.hpp" - -#ifdef HAVE_OPENCL - -//////////////////////////////////////////////////////// -// FAST - -namespace -{ - IMPLEMENT_PARAM_CLASS(FAST_Threshold, int) - IMPLEMENT_PARAM_CLASS(FAST_NonmaxSupression, bool) -} - -PARAM_TEST_CASE(FAST, FAST_Threshold, FAST_NonmaxSupression) -{ - int threshold; - bool nonmaxSupression; - - virtual void SetUp() - { - threshold = GET_PARAM(0); - nonmaxSupression = GET_PARAM(1); - } -}; - -OCL_TEST_P(FAST, Accuracy) -{ - cv::Mat image = readImage("gpu/perf/aloe.png", cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(image.empty()); - - cv::ocl::FAST_OCL fast(threshold); - fast.nonmaxSupression = nonmaxSupression; - - cv::ocl::oclMat ocl_image = cv::ocl::oclMat(image); - - std::vector keypoints; - fast(ocl_image, cv::ocl::oclMat(), keypoints); - - std::vector keypoints_gold; - cv::FAST(image, keypoints_gold, threshold, nonmaxSupression); - - ASSERT_KEYPOINTS_EQ(keypoints_gold, keypoints); -} - -INSTANTIATE_TEST_CASE_P(OCL_Features2D, FAST, testing::Combine( - testing::Values(FAST_Threshold(25), FAST_Threshold(50)), - testing::Values(FAST_NonmaxSupression(false), FAST_NonmaxSupression(true)))); - -#endif diff --git a/modules/ocl/test/test_fft.cpp b/modules/ocl/test/test_fft.cpp deleted file mode 100644 index ddc26e360..000000000 --- a/modules/ocl/test/test_fft.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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 "test_precomp.hpp" - -using namespace std; - -//////////////////////////////////////////////////////////////////////////// -// Dft - -PARAM_TEST_CASE(Dft, cv::Size, int, bool) -{ - cv::Size dft_size; - int dft_flags; - bool doubleFP; - - virtual void SetUp() - { - dft_size = GET_PARAM(0); - dft_flags = GET_PARAM(1); - doubleFP = GET_PARAM(2); - } -}; - -OCL_TEST_P(Dft, C2C) -{ - cv::Mat a = randomMat(dft_size, doubleFP ? CV_64FC2 : CV_32FC2, 0.0, 100.0); - cv::Mat b_gold; - - cv::ocl::oclMat d_b; - - cv::dft(a, b_gold, dft_flags); - cv::ocl::dft(cv::ocl::oclMat(a), d_b, a.size(), dft_flags); - - EXPECT_MAT_NEAR(b_gold, cv::Mat(d_b), a.size().area() * 1e-4); -} - -OCL_TEST_P(Dft, R2C) -{ - cv::Mat a = randomMat(dft_size, doubleFP ? CV_64FC1 : CV_32FC1, 0.0, 100.0); - cv::Mat b_gold, b_gold_roi; - - cv::ocl::oclMat d_b, d_c; - cv::ocl::dft(cv::ocl::oclMat(a), d_b, a.size(), dft_flags); - cv::dft(a, b_gold, cv::DFT_COMPLEX_OUTPUT | dft_flags); - - b_gold_roi = b_gold(cv::Rect(0, 0, d_b.cols, d_b.rows)); - EXPECT_MAT_NEAR(b_gold_roi, cv::Mat(d_b), a.size().area() * 1e-4); - - cv::Mat c_gold; - cv::dft(b_gold, c_gold, cv::DFT_INVERSE | cv::DFT_REAL_OUTPUT | cv::DFT_SCALE); - EXPECT_MAT_NEAR(b_gold_roi, cv::Mat(d_b), a.size().area() * 1e-4); -} - -OCL_TEST_P(Dft, R2CthenC2R) -{ - cv::Mat a = randomMat(dft_size, doubleFP ? CV_64FC1 : CV_32FC1, 0.0, 10.0); - - cv::ocl::oclMat d_b, d_c; - cv::ocl::dft(cv::ocl::oclMat(a), d_b, a.size(), 0); - cv::ocl::dft(d_b, d_c, a.size(), cv::DFT_SCALE | cv::DFT_INVERSE | cv::DFT_REAL_OUTPUT); - EXPECT_MAT_NEAR(a, d_c, a.size().area() * 1e-4); -} - -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, Dft, testing::Combine( - testing::Values(cv::Size(2, 3), cv::Size(5, 4), cv::Size(25, 20), cv::Size(512, 1), cv::Size(1024, 768)), - testing::Values(0, (int)cv::DFT_ROWS, (int)cv::DFT_SCALE), testing::Bool())); - -//////////////////////////////////////////////////////////////////////////// -// MulSpectrums - -PARAM_TEST_CASE(MulSpectrums, cv::Size, DftFlags, bool) -{ - cv::Size size; - int flag; - bool ccorr; - cv::Mat a, b; - - virtual void SetUp() - { - size = GET_PARAM(0); - flag = GET_PARAM(1); - ccorr = GET_PARAM(2); - - a = randomMat(size, CV_32FC2, -100, 100, false); - b = randomMat(size, CV_32FC2, -100, 100, false); - } -}; - -OCL_TEST_P(MulSpectrums, Simple) -{ - cv::ocl::oclMat c; - cv::ocl::mulSpectrums(cv::ocl::oclMat(a), cv::ocl::oclMat(b), c, flag, 1.0, ccorr); - - cv::Mat c_gold; - cv::mulSpectrums(a, b, c_gold, flag, ccorr); - - EXPECT_MAT_NEAR(c_gold, c, 1e-2); -} - -OCL_TEST_P(MulSpectrums, Scaled) -{ - float scale = 1.f / size.area(); - - cv::ocl::oclMat c; - cv::ocl::mulSpectrums(cv::ocl::oclMat(a), cv::ocl::oclMat(b), c, flag, scale, ccorr); - - cv::Mat c_gold; - cv::mulSpectrums(a, b, c_gold, flag, ccorr); - c_gold.convertTo(c_gold, c_gold.type(), scale); - - EXPECT_MAT_NEAR(c_gold, c, 1e-2); -} - -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, MulSpectrums, testing::Combine( - DIFFERENT_SIZES, - testing::Values(DftFlags(0)), - testing::Values(false, true))); - - -//////////////////////////////////////////////////////// -// Convolve - -void static convolveDFT(const cv::Mat& A, const cv::Mat& B, cv::Mat& C, bool ccorr = false) -{ - // reallocate the output array if needed - C.create(std::abs(A.rows - B.rows) + 1, std::abs(A.cols - B.cols) + 1, A.type()); - cv::Size dftSize; - - // compute the size of DFT transform - dftSize.width = cv::getOptimalDFTSize(A.cols + B.cols - 1); - dftSize.height = cv::getOptimalDFTSize(A.rows + B.rows - 1); - - // allocate temporary buffers and initialize them with 0s - cv::Mat tempA(dftSize, A.type(), cv::Scalar::all(0)); - cv::Mat tempB(dftSize, B.type(), cv::Scalar::all(0)); - - // copy A and B to the top-left corners of tempA and tempB, respectively - cv::Mat roiA(tempA, cv::Rect(0, 0, A.cols, A.rows)); - A.copyTo(roiA); - cv::Mat roiB(tempB, cv::Rect(0, 0, B.cols, B.rows)); - B.copyTo(roiB); - - // now transform the padded A & B in-place; - // use "nonzeroRows" hint for faster processing - cv::dft(tempA, tempA, 0, A.rows); - cv::dft(tempB, tempB, 0, B.rows); - - // multiply the spectrums; - // the function handles packed spectrum representations well - cv::mulSpectrums(tempA, tempB, tempA, 0, ccorr); - - // transform the product back from the frequency domain. - // Even though all the result rows will be non-zero, - // you need only the first C.rows of them, and thus you - // pass nonzeroRows == C.rows - cv::dft(tempA, tempA, cv::DFT_INVERSE + cv::DFT_SCALE, C.rows); - - // now copy the result back to C. - tempA(cv::Rect(0, 0, C.cols, C.rows)).copyTo(C); -} - -IMPLEMENT_PARAM_CLASS(KSize, int) -IMPLEMENT_PARAM_CLASS(Ccorr, bool) - -PARAM_TEST_CASE(Convolve_DFT, cv::Size, KSize, Ccorr) -{ - cv::Size size; - int ksize; - bool ccorr; - - cv::Mat src; - cv::Mat kernel; - - cv::Mat dst_gold; - - virtual void SetUp() - { - size = GET_PARAM(0); - ksize = GET_PARAM(1); - ccorr = GET_PARAM(2); - } -}; - -OCL_TEST_P(Convolve_DFT, Accuracy) -{ - cv::Mat src = randomMat(size, CV_32FC1, 0.0, 100.0); - cv::Mat kernel = randomMat(cv::Size(ksize, ksize), CV_32FC1, 0.0, 1.0); - - cv::ocl::oclMat dst; - cv::ocl::convolve(cv::ocl::oclMat(src), cv::ocl::oclMat(kernel), dst, ccorr); - - cv::Mat dst_gold; - convolveDFT(src, kernel, dst_gold, ccorr); - - EXPECT_MAT_NEAR(dst, dst_gold, 1e-1); -} -#define DIFFERENT_CONVOLVE_SIZES testing::Values(cv::Size(251, 257), cv::Size(113, 113), cv::Size(200, 480), cv::Size(1300, 1300)) -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, Convolve_DFT, testing::Combine( - DIFFERENT_CONVOLVE_SIZES, - testing::Values(KSize(19), KSize(23), KSize(45)), - testing::Values(Ccorr(true)/*, Ccorr(false)*/))); // TODO false ccorr cannot pass for some instances diff --git a/modules/ocl/test/test_filters.cpp b/modules/ocl/test/test_filters.cpp deleted file mode 100644 index b2caeaf6f..000000000 --- a/modules/ocl/test/test_filters.cpp +++ /dev/null @@ -1,476 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Jia Haipeng, jiahaipeng95@gmail.com -// Zero Lin, Zero.Lin@amd.com -// Zhang Ying, zhangying913@gmail.com -// Yao Wang, bitwangyaoyao@gmail.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 "test_precomp.hpp" - -#ifdef HAVE_OPENCL - -using namespace testing; -using namespace std; -using namespace cv; - -PARAM_TEST_CASE(FilterTestBase, MatType, - int, // kernel size - Size, // dx, dy - int, // border type - double, // optional parameter - bool) // roi or not -{ - bool isFP; - - int type, borderType, ksize; - Size size; - double param; - bool useRoi; - - Mat src, dst_whole, src_roi, dst_roi; - ocl::oclMat gsrc_whole, gsrc_roi, gdst_whole, gdst_roi; - - virtual void SetUp() - { - type = GET_PARAM(0); - ksize = GET_PARAM(1); - size = GET_PARAM(2); - borderType = GET_PARAM(3); - param = GET_PARAM(4); - useRoi = GET_PARAM(5); - - isFP = (CV_MAT_DEPTH(type) == CV_32F || CV_MAT_DEPTH(type) == CV_64F); - } - - void random_roi(int minSize = 1) - { - if (minSize == 0) - minSize = ksize; - Size roiSize = randomSize(minSize, MAX_VALUE); - Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, type, isFP ? 0 : 5, isFP ? 1 : 256); - - Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(dst_whole, dst_roi, roiSize, dstBorder, type, isFP ? 0.20 : 60, isFP ? 0.25 : 70); - - generateOclMat(gsrc_whole, gsrc_roi, src, roiSize, srcBorder); - generateOclMat(gdst_whole, gdst_roi, dst_whole, roiSize, dstBorder); - } - - void Near() - { - if (isFP) - Near(1e-6, true); - else - Near(1, false); - } - - void Near(double threshold, bool relative) - { - Mat roi, whole; - gdst_whole.download(whole); - gdst_roi.download(roi); - - if (relative) - { - EXPECT_MAT_NEAR_RELATIVE(dst_whole, whole, threshold); - EXPECT_MAT_NEAR_RELATIVE(dst_roi, roi, threshold); - } - else - { - EXPECT_MAT_NEAR(dst_whole, whole, threshold); - EXPECT_MAT_NEAR(dst_roi, roi, threshold); - } - } -}; - -///////////////////////////////////////////////////////////////////////////////////////////////// -// blur - -typedef FilterTestBase Blur; - -#ifdef ANDROID -OCL_TEST_P(Blur, DISABLED_Mat) -#else -OCL_TEST_P(Blur, Mat) -#endif -{ - Size kernelSize(ksize, ksize); - - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(0); // TODO NOTE: min value for size is kernel size (temporary bypass border issues in CPU implementation) - - blur(src_roi, dst_roi, kernelSize, Point(-1, -1), borderType); - ocl::blur(gsrc_roi, gdst_roi, kernelSize, Point(-1, -1), borderType); // TODO anchor - - Near(); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////// -// Laplacian - -typedef FilterTestBase LaplacianTest; - -OCL_TEST_P(LaplacianTest, Accuracy) -{ - double scale = param; - - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - Laplacian(src_roi, dst_roi, -1, ksize, scale, 0, borderType); - ocl::Laplacian(gsrc_roi, gdst_roi, -1, ksize, scale, 0, borderType); - - Near(); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////// -// erode & dilate - -typedef FilterTestBase Erode; - -OCL_TEST_P(Erode, Mat) -{ - // erode or dilate kernel - Size kernelSize(ksize, ksize); - Mat kernel; - int iterations = (int)param; - - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - kernel = randomMat(kernelSize, CV_8UC1, 0, 3); - - cv::erode(src_roi, dst_roi, kernel, Point(-1, -1), iterations);//, borderType); - ocl::erode(gsrc_roi, gdst_roi, kernel, Point(-1, -1), iterations);//, borderType); - - Near(); - } -} - -typedef FilterTestBase Dilate; - -OCL_TEST_P(Dilate, Mat) -{ - // erode or dilate kernel - Mat kernel; - int iterations = (int)param; - - for (int j = 0; j < LOOP_TIMES; j++) - { - kernel = randomMat(Size(3, 3), CV_8UC1, 0, 3); - - random_roi(); - - cv::dilate(src_roi, dst_roi, kernel, Point(-1, -1), iterations); - ocl::dilate(gsrc_roi, gdst_roi, kernel, Point(-1, -1), iterations); // TODO iterations, borderType - - Near(); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////// -// Sobel - -typedef FilterTestBase SobelTest; - -OCL_TEST_P(SobelTest, Mat) -{ - int dx = size.width, dy = size.height; - double scale = param; - - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - Sobel(src_roi, dst_roi, -1, dx, dy, ksize, scale, /* delta */0, borderType); - ocl::Sobel(gsrc_roi, gdst_roi, -1, dx, dy, ksize, scale, /* delta */0, borderType); - - Near(); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////// -// Scharr - -typedef FilterTestBase ScharrTest; - -OCL_TEST_P(ScharrTest, Mat) -{ - int dx = size.width, dy = size.height; - double scale = param; - - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - Scharr(src_roi, dst_roi, -1, dx, dy, scale, /* delta */ 0, borderType); - ocl::Scharr(gsrc_roi, gdst_roi, -1, dx, dy, scale, /* delta */ 0, borderType); - - Near(); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////// -// GaussianBlur - -typedef FilterTestBase GaussianBlurTest; - -OCL_TEST_P(GaussianBlurTest, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - double sigma1 = rng.uniform(0.1, 1.0); - double sigma2 = rng.uniform(0.1, 1.0); - - GaussianBlur(src_roi, dst_roi, Size(ksize, ksize), sigma1, sigma2, borderType); - ocl::GaussianBlur(gsrc_roi, gdst_roi, Size(ksize, ksize), sigma1, sigma2, borderType); - - Near(CV_MAT_DEPTH(type) == CV_8U ? 3 : 5e-5, false); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Filter2D - -typedef FilterTestBase Filter2D; - -OCL_TEST_P(Filter2D, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - Point anchor(-1, -1); - if (size.width >= 0) - anchor.x = size.width % ksize; - if (size.height >= 0) - anchor.y = size.height % ksize; - - const Size kernelSize(ksize, ksize); - Mat kernel = randomMat(kernelSize, CV_32FC1, 0, 1.0); - kernel *= 1.0 / (double)(ksize * ksize); - - cv::filter2D(src_roi, dst_roi, -1, kernel, anchor, 0.0, borderType); - ocl::filter2D(gsrc_roi, gdst_roi, -1, kernel, anchor, 0.0, borderType); - - Near(); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Bilateral - -typedef FilterTestBase Bilateral; - -OCL_TEST_P(Bilateral, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - double sigmacolor = rng.uniform(20, 100); - double sigmaspace = rng.uniform(10, 40); - - cv::bilateralFilter(src_roi, dst_roi, ksize, sigmacolor, sigmaspace, borderType); - ocl::bilateralFilter(gsrc_roi, gdst_roi, ksize, sigmacolor, sigmaspace, borderType); - - Near(); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// AdaptiveBilateral - -typedef FilterTestBase AdaptiveBilateral; - -OCL_TEST_P(AdaptiveBilateral, Mat) -{ - const Size kernelSize(ksize, ksize); - - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - adaptiveBilateralFilter(src_roi, dst_roi, kernelSize, 5, 1, Point(-1, -1), borderType); // TODO anchor - ocl::adaptiveBilateralFilter(gsrc_roi, gdst_roi, kernelSize, 5, 1, Point(-1, -1), borderType); - - Near(); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////// -// MedianFilter - -typedef FilterTestBase MedianFilter; - -OCL_TEST_P(MedianFilter, Mat) -{ - for (int i = 0; i < LOOP_TIMES; ++i) - { - random_roi(); - - medianBlur(src_roi, dst_roi, ksize); - ocl::medianFilter(gsrc_roi, gdst_roi, ksize); - - Near(); - } -} - -////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#define FILTER_BORDER_SET_NO_ISOLATED \ - Values((int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, (int)BORDER_WRAP, (int)BORDER_REFLECT_101/*, \ - (int)BORDER_CONSTANT|BORDER_ISOLATED, (int)BORDER_REPLICATE|BORDER_ISOLATED, \ - (int)BORDER_REFLECT|BORDER_ISOLATED, (int)BORDER_WRAP|BORDER_ISOLATED, \ - (int)BORDER_REFLECT_101|BORDER_ISOLATED*/) // WRAP and ISOLATED are not supported by cv:: version - -#define FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED \ - Values((int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, /*(int)BORDER_WRAP,*/ (int)BORDER_REFLECT_101/*, \ - (int)BORDER_CONSTANT|BORDER_ISOLATED, (int)BORDER_REPLICATE|BORDER_ISOLATED, \ - (int)BORDER_REFLECT|BORDER_ISOLATED, (int)BORDER_WRAP|BORDER_ISOLATED, \ - (int)BORDER_REFLECT_101|BORDER_ISOLATED*/) // WRAP and ISOLATED are not supported by cv:: version - -#define FILTER_DATATYPES Values(CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4, \ - CV_32FC1, CV_32FC3, CV_32FC4, \ - CV_64FC1, CV_64FC3, CV_64FC4) - -INSTANTIATE_TEST_CASE_P(Filter, Blur, Combine( - FILTER_DATATYPES, - Values(3, 5, 7), - Values(Size(0, 0)), // not used - FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, - Values(0.0), // not used - Bool())); - -INSTANTIATE_TEST_CASE_P(Filter, LaplacianTest, Combine( - FILTER_DATATYPES, - Values(1, 3), - Values(Size(0, 0)), // not used - FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, - Values(1.0, 0.2, 3.0), // scalar - Bool())); - -INSTANTIATE_TEST_CASE_P(Filter, Erode, Combine( - Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4), - Values(3, 5, 7), - Values(Size(0, 0)), // not used - Values(0), // not used - Values(1.0, 2.0, 3.0), - Bool())); - -INSTANTIATE_TEST_CASE_P(Filter, Dilate, Combine( - Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4), - Values(3, 5, 7), - Values(Size(0, 0)), // not used - Values(0), // not used - Values(1.0, 2.0, 3.0), - Bool())); - -INSTANTIATE_TEST_CASE_P(Filter, SobelTest, Combine( - Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4), - Values(3, 5), - Values(Size(1, 0), Size(1, 1), Size(2, 0), Size(2, 1)), // dx, dy - FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, - Values(0.0), // not used - Bool())); - -INSTANTIATE_TEST_CASE_P(Filter, ScharrTest, Combine( - Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4), - Values(1), - Values(Size(0, 1), Size(1, 0)), // dx, dy - FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, - Values(1.0, 0.2), // scalar - Bool())); - -INSTANTIATE_TEST_CASE_P(Filter, GaussianBlurTest, Combine( - Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC4), - Values(3, 5), - Values(Size(0, 0)), // not used - FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, - Values(0.0), // not used - Bool())); - -INSTANTIATE_TEST_CASE_P(Filter, Filter2D, testing::Combine( - FILTER_DATATYPES, - Values(3, 15), // TODO 25: CPU implementation has some issues - Values(Size(-1, -1), Size(0, 0), Size(2, 1)), // anchor - FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, - Values(0.0), // not used - Bool())); - -INSTANTIATE_TEST_CASE_P(Filter, Bilateral, Combine( - Values(CV_8UC1, CV_8UC3), - Values(5, 9), - Values(Size(0, 0)), // not used - FILTER_BORDER_SET_NO_ISOLATED, - Values(0.0), // not used - Bool())); - -INSTANTIATE_TEST_CASE_P(Filter, AdaptiveBilateral, Combine( - Values(CV_8UC1, CV_8UC3), - Values(5, 9), - Values(Size(0, 0)), // not used - FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, - Values(0.0), // not used - Bool())); - -INSTANTIATE_TEST_CASE_P(Filter, MedianFilter, Combine( - Values(CV_8UC1, CV_8UC4, CV_32FC1, CV_32FC4), - Values(3, 5), - Values(Size(0, 0)), // not used - Values(0), // not used - Values(0.0), // not used - Bool())); - -#endif // HAVE_OPENCL diff --git a/modules/ocl/test/test_gemm.cpp b/modules/ocl/test/test_gemm.cpp deleted file mode 100644 index c2a44842c..000000000 --- a/modules/ocl/test/test_gemm.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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 "test_precomp.hpp" - -using namespace std; - -//////////////////////////////////////////////////////////////////////////// -// GEMM - -PARAM_TEST_CASE(Gemm, int, cv::Size, int) -{ - int type; - cv::Size mat_size; - int flags; - - virtual void SetUp() - { - type = GET_PARAM(0); - mat_size = GET_PARAM(1); - flags = GET_PARAM(2); - } -}; - -OCL_TEST_P(Gemm, Accuracy) -{ - cv::Mat a = randomMat(mat_size, type, 0.0, 10.0); - cv::Mat b = randomMat(mat_size, type, 0.0, 10.0); - cv::Mat c = randomMat(mat_size, type, 0.0, 10.0); - - cv::Mat dst; - cv::ocl::oclMat ocl_dst; - - cv::gemm(a, b, 1.0, c, 1.0, dst, flags); - cv::ocl::gemm(cv::ocl::oclMat(a), cv::ocl::oclMat(b), 1.0, cv::ocl::oclMat(c), 1.0, ocl_dst, flags); - - EXPECT_MAT_NEAR(dst, ocl_dst, mat_size.area() * 1e-4); -} - -INSTANTIATE_TEST_CASE_P(ocl_gemm, Gemm, testing::Combine( - testing::Values(CV_32FC1, CV_32FC2/*, CV_64FC1, CV_64FC2*/), - testing::Values(cv::Size(20, 20), cv::Size(300, 300)), - testing::Values(0, (int)cv::GEMM_1_T, (int)cv::GEMM_2_T, (int)(cv::GEMM_1_T + cv::GEMM_2_T)))); diff --git a/modules/ocl/test/test_hough.cpp b/modules/ocl/test/test_hough.cpp deleted file mode 100644 index f5d257801..000000000 --- a/modules/ocl/test/test_hough.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/*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) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2008-2011, Willow Garage Inc., 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 Intel Corporation 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 "test_precomp.hpp" - -#ifdef HAVE_OPENCL - -/////////////////////////////////////////////////////////////////////////////////////////////////////// -// HoughCircles - -PARAM_TEST_CASE(HoughCircles, cv::Size) -{ - static void drawCircles(cv::Mat& dst, const std::vector& circles, bool fill) - { - dst.setTo(cv::Scalar::all(0)); - - for (size_t i = 0; i < circles.size(); ++i) - cv::circle(dst, cv::Point2f(circles[i][0], circles[i][1]), (int)circles[i][2], cv::Scalar::all(255), fill ? -1 : 1); - } -}; - -OCL_TEST_P(HoughCircles, Accuracy) -{ - const cv::Size size = GET_PARAM(0); - - const float dp = 2.0f; - const float minDist = 10.0f; - const int minRadius = 10; - const int maxRadius = 20; - const int cannyThreshold = 100; - const int votesThreshold = 15; - - std::vector circles_gold(4); - circles_gold[0] = cv::Vec3i(20, 20, minRadius); - circles_gold[1] = cv::Vec3i(90, 87, minRadius + 3); - circles_gold[2] = cv::Vec3i(30, 70, minRadius + 8); - circles_gold[3] = cv::Vec3i(80, 10, maxRadius); - - cv::Mat src(size, CV_8UC1); - drawCircles(src, circles_gold, true); - cv::ocl::oclMat d_src(src); - - cv::ocl::oclMat d_circles; - cv::ocl::HoughCircles(d_src, d_circles, cv::HOUGH_GRADIENT, dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius); - ASSERT_TRUE(d_circles.rows > 0); - - cv::Mat circles; - d_circles.download(circles); - - for (int i = 0; i < circles.cols; ++i) - { - cv::Vec3f cur = circles.at(i); - - bool found = false; - - for (size_t j = 0; j < circles_gold.size(); ++j) - { - cv::Vec3f gold = circles_gold[j]; - - if (std::fabs(cur[0] - gold[0]) < minDist && std::fabs(cur[1] - gold[1]) < minDist && std::fabs(cur[2] - gold[2]) < minDist) - { - found = true; - break; - } - } - - ASSERT_TRUE(found); - } -} - -INSTANTIATE_TEST_CASE_P(Hough, HoughCircles, DIFFERENT_SIZES); - -#endif // HAVE_OPENCL diff --git a/modules/ocl/test/test_imgproc.cpp b/modules/ocl/test/test_imgproc.cpp deleted file mode 100644 index 9b25d9f9c..000000000 --- a/modules/ocl/test/test_imgproc.cpp +++ /dev/null @@ -1,622 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Jia Haipeng, jiahaipeng95@gmail.com -// Shengen Yan, yanshengen@gmail.com -// Jiang Liyuan, lyuan001.good@163.com -// Rock Li, Rock.Li@amd.com -// Wu Zailong, bullet@yeah.net -// Xu Pang, pangxu010@163.com -// Sen Liu, swjtuls1987@126.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 "test_precomp.hpp" - -#ifdef HAVE_OPENCL - -using namespace testing; -using namespace std; -using namespace cv; - -/////////////////////////////////////////////////////////////////////////////// - -PARAM_TEST_CASE(ImgprocTestBase, MatType, - int, // blockSize - int, // border type - bool) // roi or not -{ - int type, borderType, blockSize; - bool useRoi; - - Mat src, dst_whole, src_roi, dst_roi; - ocl::oclMat gsrc_whole, gsrc_roi, gdst_whole, gdst_roi; - - virtual void SetUp() - { - type = GET_PARAM(0); - blockSize = GET_PARAM(1); - borderType = GET_PARAM(2); - useRoi = GET_PARAM(3); - } - - virtual void random_roi() - { - Size roiSize = randomSize(1, MAX_VALUE); - Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, type, 5, 256); - - Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(dst_whole, dst_roi, roiSize, dstBorder, type, 5, 16); - - generateOclMat(gsrc_whole, gsrc_roi, src, roiSize, srcBorder); - generateOclMat(gdst_whole, gdst_roi, dst_whole, roiSize, dstBorder); - } - - void Near(double threshold = 0.0, bool relative = false) - { - Mat roi, whole; - gdst_whole.download(whole); - gdst_roi.download(roi); - - if (relative) - { - EXPECT_MAT_NEAR_RELATIVE(dst_whole, whole, threshold); - EXPECT_MAT_NEAR_RELATIVE(dst_roi, roi, threshold); - } - else - { - EXPECT_MAT_NEAR(dst_whole, whole, threshold); - EXPECT_MAT_NEAR(dst_roi, roi, threshold); - } - } -}; - -////////////////////////////////copyMakeBorder//////////////////////////////////////////// - -PARAM_TEST_CASE(CopyMakeBorder, MatDepth, // depth - Channels, // channels - bool, // isolated or not - Border, // border type - bool) // roi or not -{ - int type, borderType; - bool useRoi; - - Border border; - Scalar val; - - Mat src, dst_whole, src_roi, dst_roi; - ocl::oclMat gsrc_whole, gsrc_roi, gdst_whole, gdst_roi; - - virtual void SetUp() - { - type = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1)); - borderType = GET_PARAM(3); - - if (GET_PARAM(2)) - borderType |= BORDER_ISOLATED; - - useRoi = GET_PARAM(4); - } - - void random_roi() - { - border = randomBorder(0, MAX_VALUE << 2); - val = randomScalar(-MAX_VALUE, MAX_VALUE); - - Size roiSize = randomSize(1, MAX_VALUE); - Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE); - - Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - dstBorder.top += border.top; - dstBorder.lef += border.lef; - dstBorder.rig += border.rig; - dstBorder.bot += border.bot; - - randomSubMat(dst_whole, dst_roi, roiSize, dstBorder, type, -MAX_VALUE, MAX_VALUE); - - generateOclMat(gsrc_whole, gsrc_roi, src, roiSize, srcBorder); - generateOclMat(gdst_whole, gdst_roi, dst_whole, roiSize, dstBorder); - } - - void Near(double threshold = 0.0) - { - Mat whole, roi; - gdst_whole.download(whole); - gdst_roi.download(roi); - - EXPECT_MAT_NEAR(dst_whole, whole, threshold); - EXPECT_MAT_NEAR(dst_roi, roi, threshold); - } -}; - -OCL_TEST_P(CopyMakeBorder, Mat) -{ - for (int i = 0; i < LOOP_TIMES; ++i) - { - random_roi(); - - cv::copyMakeBorder(src_roi, dst_roi, border.top, border.bot, border.lef, border.rig, borderType, val); - ocl::copyMakeBorder(gsrc_roi, gdst_roi, border.top, border.bot, border.lef, border.rig, borderType, val); - - Near(); - } -} - -////////////////////////////////equalizeHist////////////////////////////////////////////// - -typedef ImgprocTestBase EqualizeHist; - -OCL_TEST_P(EqualizeHist, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - equalizeHist(src_roi, dst_roi); - ocl::equalizeHist(gsrc_roi, gdst_roi); - - Near(1.1); - } -} - -////////////////////////////////cornerMinEigenVal////////////////////////////////////////// - -struct CornerTestBase : - public ImgprocTestBase -{ - virtual void random_roi() - { - Mat image = readImageType("gpu/stereobm/aloe-L.png", type); - ASSERT_FALSE(image.empty()); - - bool isFP = CV_MAT_DEPTH(type) >= CV_32F; - float val = 255.0f; - if (isFP) - { - image.convertTo(image, -1, 1.0 / 255); - val /= 255.0f; - } - - Size roiSize = image.size(); - Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - - Size wholeSize = Size(roiSize.width + srcBorder.lef + srcBorder.rig, roiSize.height + srcBorder.top + srcBorder.bot); - src = randomMat(wholeSize, type, -val, val, false); - src_roi = src(Rect(srcBorder.lef, srcBorder.top, roiSize.width, roiSize.height)); - image.copyTo(src_roi); - - Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(dst_whole, dst_roi, roiSize, dstBorder, CV_32FC1, 5, 16); - - generateOclMat(gsrc_whole, gsrc_roi, src, roiSize, srcBorder); - generateOclMat(gdst_whole, gdst_roi, dst_whole, roiSize, dstBorder); - } -}; - -typedef CornerTestBase CornerMinEigenVal; - -OCL_TEST_P(CornerMinEigenVal, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - int apertureSize = 3; - - cornerMinEigenVal(src_roi, dst_roi, blockSize, apertureSize, borderType); - ocl::cornerMinEigenVal(gsrc_roi, gdst_roi, blockSize, apertureSize, borderType); - - Near(1e-5, true); - } -} - -////////////////////////////////cornerHarris////////////////////////////////////////// -struct CornerHarris : - public ImgprocTestBase -{ - void Near(double threshold = 0.0) - { - Mat whole, roi; - gdst_whole.download(whole); - gdst_roi.download(roi); - - absdiff(whole, dst_whole, whole); - absdiff(roi, dst_roi, roi); - - divide(whole, dst_whole, whole); - divide(roi, dst_roi, roi); - - absdiff(dst_whole, dst_whole, dst_whole); - absdiff(dst_roi, dst_roi, dst_roi); - - EXPECT_MAT_NEAR(dst_whole, whole, threshold); - EXPECT_MAT_NEAR(dst_roi, roi, threshold); - } -}; - -OCL_TEST_P(CornerHarris, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - int apertureSize = 3; - double k = randomDouble(0.01, 0.9); - - cornerHarris(src_roi, dst_roi, blockSize, apertureSize, k, borderType); - ocl::cornerHarris(gsrc_roi, gdst_roi, blockSize, apertureSize, k, borderType); - - Near(1e-5); - } -} - -//////////////////////////////////integral///////////////////////////////////////////////// - -struct Integral : - public ImgprocTestBase -{ - int sdepth; - - virtual void SetUp() - { - type = GET_PARAM(0); - blockSize = GET_PARAM(1); - sdepth = GET_PARAM(2); - useRoi = GET_PARAM(3); - } -}; -OCL_TEST_P(Integral, Mat1) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - ocl::integral(gsrc_roi, gdst_roi, sdepth); - integral(src_roi, dst_roi, sdepth); - - Near(); - } -} - -OCL_TEST_P(Integral, Mat2) -{ - Mat dst1; - ocl::oclMat gdst1; - - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - integral(src_roi, dst_roi, dst1, sdepth); - ocl::integral(gsrc_roi, gdst_roi, gdst1, sdepth); - - Near(); - if(gdst1.clCxt->supportsFeature(ocl::FEATURE_CL_DOUBLE)) - EXPECT_MAT_NEAR(dst1, Mat(gdst1), 0.); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -//// threshold - -struct Threshold : - public ImgprocTestBase -{ - int thresholdType; - - virtual void SetUp() - { - type = GET_PARAM(0); - blockSize = GET_PARAM(1); - thresholdType = GET_PARAM(2); - useRoi = GET_PARAM(3); - } -}; - -OCL_TEST_P(Threshold, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - double maxVal = randomDouble(20.0, 127.0); - double thresh = randomDouble(0.0, maxVal); - - threshold(src_roi, dst_roi, thresh, maxVal, thresholdType); - ocl::threshold(gsrc_roi, gdst_roi, thresh, maxVal, thresholdType); - - Near(1); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// calcHist - -static void calcHistGold(const Mat &src, Mat &hist) -{ - hist = Mat(1, 256, CV_32SC1, Scalar::all(0)); - - int * const hist_row = hist.ptr(); - for (int y = 0; y < src.rows; ++y) - { - const uchar * const src_row = src.ptr(y); - - for (int x = 0; x < src.cols; ++x) - ++hist_row[src_row[x]]; - } -} - -typedef ImgprocTestBase CalcHist; - -OCL_TEST_P(CalcHist, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - calcHistGold(src_roi, dst_roi); - ocl::calcHist(gsrc_roi, gdst_roi); - - Near(); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////// -//// CLAHE - -PARAM_TEST_CASE(CLAHETest, Size, double, bool) -{ - Size gridSize; - double clipLimit; - bool useRoi; - - Mat src, dst_whole, src_roi, dst_roi; - ocl::oclMat gsrc_whole, gsrc_roi, gdst_whole, gdst_roi; - - virtual void SetUp() - { - gridSize = GET_PARAM(0); - clipLimit = GET_PARAM(1); - useRoi = GET_PARAM(2); - } - - void random_roi() - { - Size roiSize = randomSize(std::max(gridSize.height, gridSize.width), MAX_VALUE); - Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, CV_8UC1, 5, 256); - - Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(dst_whole, dst_roi, roiSize, dstBorder, CV_8UC1, 5, 16); - - generateOclMat(gsrc_whole, gsrc_roi, src, roiSize, srcBorder); - generateOclMat(gdst_whole, gdst_roi, dst_whole, roiSize, dstBorder); - } - - void Near(double threshold = 0.0) - { - Mat whole, roi; - gdst_whole.download(whole); - gdst_roi.download(roi); - - EXPECT_MAT_NEAR(dst_whole, whole, threshold); - EXPECT_MAT_NEAR(dst_roi, roi, threshold); - } -}; - -OCL_TEST_P(CLAHETest, Accuracy) -{ - for (int i = 0; i < LOOP_TIMES; ++i) - { - random_roi(); - - Ptr clahe = ocl::createCLAHE(clipLimit, gridSize); - clahe->apply(gsrc_roi, gdst_roi); - - Ptr clahe_gold = createCLAHE(clipLimit, gridSize); - clahe_gold->apply(src_roi, dst_roi); - - Near(1.0); - } -} - -/////////////////////////////Convolve////////////////////////////////// - -static void convolve_gold(const Mat & src, const Mat & kernel, Mat & dst) -{ - for (int i = 0; i < src.rows; i++) - { - float * const dstptr = dst.ptr(i); - - for (int j = 0; j < src.cols; j++) - { - float temp = 0; - - for (int m = 0; m < kernel.rows; m++) - { - const float * const kptr = kernel.ptr(m); - for (int n = 0; n < kernel.cols; n++) - { - int r = clipInt(i - kernel.rows / 2 + m, 0, src.rows - 1); - int c = clipInt(j - kernel.cols / 2 + n, 0, src.cols - 1); - - temp += src.ptr(r)[c] * kptr[n]; - } - } - - dstptr[j] = temp; - } - } -} - -typedef ImgprocTestBase Convolve; - -OCL_TEST_P(Convolve, Mat) -{ - Mat kernel, kernel_roi; - ocl::oclMat gkernel, gkernel_roi; - const Size roiSize(7, 7); - - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - Border kernelBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(kernel, kernel_roi, roiSize, kernelBorder, type, 5, 16); - generateOclMat(gkernel, gkernel_roi, kernel, roiSize, kernelBorder); - - convolve_gold(src_roi, kernel_roi, dst_roi); - ocl::convolve(gsrc_roi, gkernel_roi, gdst_roi); - - Near(1); - } -} - -////////////////////////////////// ColumnSum ////////////////////////////////////// - -static void columnSum_gold(const Mat & src, Mat & dst) -{ - float * prevdptr = dst.ptr(0); - const float * sptr = src.ptr(0); - - for (int x = 0; x < src.cols; ++x) - prevdptr[x] = sptr[x]; - - for (int y = 1; y < src.rows; ++y) - { - sptr = src.ptr(y); - float * const dptr = dst.ptr(y); - - for (int x = 0; x < src.cols; ++x) - dptr[x] = prevdptr[x] + sptr[x]; - - prevdptr = dptr; - } -} - -typedef ImgprocTestBase ColumnSum; - -OCL_TEST_P(ColumnSum, Accuracy) -{ - for (int i = 0; i < LOOP_TIMES; ++i) - { - random_roi(); - - columnSum_gold(src_roi, dst_roi); - ocl::columnSum(gsrc_roi, gdst_roi); - - Near(1e-5); - } -} - -///////////////////////////////////////////////////////////////////////////////////// - -INSTANTIATE_TEST_CASE_P(Imgproc, EqualizeHist, Combine( - Values((MatType)CV_8UC1), - Values(0), // not used - Values(0), // not used - Bool())); - -INSTANTIATE_TEST_CASE_P(Imgproc, CornerMinEigenVal, Combine( - Values((MatType)CV_8UC1, (MatType)CV_32FC1), - Values(3, 5), - Values((int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, (int)BORDER_REFLECT101), - Bool())); - -INSTANTIATE_TEST_CASE_P(Imgproc, CornerHarris, Combine( - Values((MatType)CV_8UC1, CV_32FC1), - Values(3, 5), - Values( (int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, (int)BORDER_REFLECT_101), - Bool())); - -INSTANTIATE_TEST_CASE_P(Imgproc, Integral, Combine( - Values((MatType)CV_8UC1), // TODO does not work with CV_32F, CV_64F - Values(0), // not used - Values((MatType)CV_32SC1, (MatType)CV_32FC1), - Bool())); - -INSTANTIATE_TEST_CASE_P(Imgproc, Threshold, Combine( - Values(CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4, - CV_16SC1, CV_16SC2, CV_16SC3, CV_16SC4, - CV_32FC1, CV_32FC2, CV_32FC3, CV_32FC4), - Values(0), - Values(ThreshOp(THRESH_BINARY), - ThreshOp(THRESH_BINARY_INV), ThreshOp(THRESH_TRUNC), - ThreshOp(THRESH_TOZERO), ThreshOp(THRESH_TOZERO_INV)), - Bool())); - -INSTANTIATE_TEST_CASE_P(Imgproc, CalcHist, Combine( - Values((MatType)CV_8UC1), - Values(0), // not used - Values(0), // not used - Bool())); - -INSTANTIATE_TEST_CASE_P(Imgproc, CLAHETest, Combine( - Values(Size(4, 4), Size(32, 8), Size(8, 64)), - Values(0.0, 10.0, 62.0, 300.0), - Bool())); - -INSTANTIATE_TEST_CASE_P(Imgproc, Convolve, Combine( - Values((MatType)CV_32FC1), - Values(0), // not used - Values(0), // not used - Bool())); - -INSTANTIATE_TEST_CASE_P(Imgproc, ColumnSum, Combine( - Values(MatType(CV_32FC1)), - Values(0), // not used - Values(0), // not used - Bool())); - -INSTANTIATE_TEST_CASE_P(ImgprocTestBase, CopyMakeBorder, Combine( - testing::Values((MatDepth)CV_8U, (MatDepth)CV_16S, (MatDepth)CV_32S, (MatDepth)CV_32F), - testing::Values(Channels(1), Channels(3), (Channels)4), - Bool(), // border isolated or not - Values((Border)BORDER_REPLICATE, (Border)BORDER_REFLECT, - (Border)BORDER_WRAP, (Border)BORDER_REFLECT_101), - Bool())); - -#endif // HAVE_OPENCL diff --git a/modules/ocl/test/test_kalman.cpp b/modules/ocl/test/test_kalman.cpp deleted file mode 100644 index 045cd9815..000000000 --- a/modules/ocl/test/test_kalman.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////// -// -// 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 -// 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 "test_precomp.hpp" - -#ifdef HAVE_OPENCL - -using namespace cv; -using namespace cv::ocl; -using namespace cvtest; -using namespace testing; -using namespace std; - -////////////////////////////////////////////////////////////////////////// - -PARAM_TEST_CASE(Kalman, int, int) -{ - int size_; - int iteration; - virtual void SetUp() - { - size_ = GET_PARAM(0); - iteration = GET_PARAM(1); - } -}; - -OCL_TEST_P(Kalman, Accuracy) -{ - const int Dim = size_; - const int Steps = iteration; - const double max_init = 1; - const double max_noise = 0.1; - - Mat sample_mat(Dim, 1, CV_32F), temp_mat; - oclMat Sample(Dim, 1, CV_32F); - oclMat Temp(Dim, 1, CV_32F); - Mat Temp_cpu(Dim, 1, CV_32F); - - Size size(Sample.cols, Sample.rows); - - sample_mat = randomMat(size, Sample.type(), -max_init, max_init, false); - Sample.upload(sample_mat); - - //ocl start - cv::ocl::KalmanFilter kalman_filter_ocl; - kalman_filter_ocl.init(Dim, Dim); - - cv::ocl::setIdentity(kalman_filter_ocl.errorCovPre, 1); - cv::ocl::setIdentity(kalman_filter_ocl.measurementMatrix, 1); - cv::ocl::setIdentity(kalman_filter_ocl.errorCovPost, 1); - - kalman_filter_ocl.measurementNoiseCov.setTo(Scalar::all(0)); - kalman_filter_ocl.statePre.setTo(Scalar::all(0)); - kalman_filter_ocl.statePost.setTo(Scalar::all(0)); - - kalman_filter_ocl.correct(Sample); - //ocl end - - //cpu start - cv::KalmanFilter kalman_filter_cpu; - - kalman_filter_cpu.init(Dim, Dim); - - cv::setIdentity(kalman_filter_cpu.errorCovPre, 1); - cv::setIdentity(kalman_filter_cpu.measurementMatrix, 1); - cv::setIdentity(kalman_filter_cpu.errorCovPost, 1); - - kalman_filter_cpu.measurementNoiseCov.setTo(Scalar::all(0)); - kalman_filter_cpu.statePre.setTo(Scalar::all(0)); - kalman_filter_cpu.statePost.setTo(Scalar::all(0)); - - kalman_filter_cpu.correct(sample_mat); - //cpu end - //test begin - for(int i = 0; i(0, i*nchannel+j) = 50000.0; - - for(int j = 0; (j < max_neighbour) || - (i == K-1 && j < max_neighbour + MHEIGHT%K); j ++) - { - Mat cur_row_header = src.row(row_idx + 1 + j); - center_row_header.copyTo(cur_row_header); - Mat tmpmat = randomMat(cur_row_header.size(), cur_row_header.type(), -200, 200, false); - cur_row_header += tmpmat; - } - row_idx += 1 + max_neighbour; - } - } -}; -OCL_TEST_P(Kmeans, Mat){ - if(flags & KMEANS_USE_INITIAL_LABELS) - { - // inital a given labels - labels.create(src.rows, 1, CV_32S); - int *label = labels.ptr(); - for(int i = 0; i < src.rows; i++) - label[i] = rng.uniform(0, K); - d_labels.upload(labels); - } - d_src.upload(src); - - for(int j = 0; j < LOOP_TIMES; j++) - { - kmeans(src, K, labels, - TermCriteria( TermCriteria::EPS + TermCriteria::MAX_ITER, 100, 0), - 1, flags, centers); - ocl::kmeans(d_src, K, d_labels, - TermCriteria( TermCriteria::EPS + TermCriteria::MAX_ITER, 100, 0), - 1, flags, d_centers); - Mat dd_labels(d_labels); - Mat dd_centers(d_centers); - if(flags & KMEANS_USE_INITIAL_LABELS) - { - EXPECT_MAT_NEAR(labels, dd_labels, 0); - EXPECT_MAT_NEAR(centers, dd_centers, 1e-3); - } - else - { - int row_idx = 0; - for(int i = 0; i < K; i++) - { - // verify lables with ground truth resutls - int label = labels.at(row_idx); - int header_label = dd_labels.at(row_idx); - for(int j = 0; (j < MHEIGHT/K)||(i == K-1 && j < MHEIGHT/K+MHEIGHT%K); j++) - { - ASSERT_NEAR(labels.at(row_idx+j), label, 0); - ASSERT_NEAR(dd_labels.at(row_idx+j), header_label, 0); - } - - // verify centers - float *center = centers.ptr(label); - float *header_center = dd_centers.ptr(header_label); - for(int t = 0; t < centers.cols; t++) - ASSERT_NEAR(center[t], header_center[t], 1e-3); - - row_idx += MHEIGHT/K; - } - } - } -} - -INSTANTIATE_TEST_CASE_P(OCL_ML, Kmeans, Combine( - Values(3, 5, 8), - Values(CV_32FC1, CV_32FC2, CV_32FC4), - Values(OCL_KMEANS_USE_INITIAL_LABELS/*, OCL_KMEANS_PP_CENTERS*/))); - - -/////////////////////////////// DistanceToCenters ////////////////////////////////////////// - -CV_ENUM(DistType, NORM_L1, NORM_L2SQR) - -PARAM_TEST_CASE(distanceToCenters, DistType, bool) -{ - int distType; - bool useRoi; - - Mat src, centers, src_roi, centers_roi; - ocl::oclMat ocl_src, ocl_centers, ocl_src_roi, ocl_centers_roi; - - virtual void SetUp() - { - distType = GET_PARAM(0); - useRoi = GET_PARAM(1); - } - - void random_roi() - { - Size roiSizeSrc = randomSize(1, MAX_VALUE); - Size roiSizeCenters = randomSize(1, MAX_VALUE); - roiSizeSrc.width = roiSizeCenters.width; - - Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSizeSrc, srcBorder, CV_32FC1, -MAX_VALUE, MAX_VALUE); - - Border centersBorder = randomBorder(0, useRoi ? 500 : 0); - randomSubMat(centers, centers_roi, roiSizeCenters, centersBorder, CV_32FC1, -MAX_VALUE, MAX_VALUE); - - for (int i = 0; i < centers.rows; i++) - centers.at(i, randomInt(0, centers.cols)) = (float)randomDouble(SHRT_MAX, INT_MAX); - - generateOclMat(ocl_src, ocl_src_roi, src, roiSizeSrc, srcBorder); - generateOclMat(ocl_centers, ocl_centers_roi, centers, roiSizeCenters, centersBorder); - } -}; - -OCL_TEST_P(distanceToCenters, Accuracy) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - Mat labels, dists; - ocl::distanceToCenters(ocl_src_roi, ocl_centers_roi, dists, labels, distType); - - EXPECT_EQ(dists.size(), labels.size()); - - Mat batch_dists; - cv::batchDistance(src_roi, centers_roi, batch_dists, CV_32FC1, noArray(), distType); - - std::vector gold_dists_v; - gold_dists_v.reserve(batch_dists.rows); - - for (int i = 0; i < batch_dists.rows; i++) - { - Mat r = batch_dists.row(i); - double mVal; - Point mLoc; - minMaxLoc(r, &mVal, NULL, &mLoc, NULL); - - int ocl_label = labels.at(i, 0); - EXPECT_EQ(mLoc.x, ocl_label); - - gold_dists_v.push_back(static_cast(mVal)); - } - - double relative_error = cv::norm(Mat(gold_dists_v), dists, NORM_INF | NORM_RELATIVE); - ASSERT_LE(relative_error, 1e-5); - } -} - -INSTANTIATE_TEST_CASE_P (OCL_ML, distanceToCenters, Combine(DistType::all(), Bool())); - -#endif diff --git a/modules/ocl/test/test_match_template.cpp b/modules/ocl/test/test_match_template.cpp deleted file mode 100644 index aa63f3d9e..000000000 --- a/modules/ocl/test/test_match_template.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@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 "test_precomp.hpp" - -#ifdef HAVE_OPENCL -//////////////////////////////////////////////////////////////////////////////// -// MatchTemplate -#define ALL_TEMPLATE_METHODS testing::Values(TemplateMethod(cv::TM_SQDIFF), TemplateMethod(cv::TM_CCORR), TemplateMethod(cv::TM_CCOEFF), TemplateMethod(cv::TM_SQDIFF_NORMED), TemplateMethod(cv::TM_CCORR_NORMED), TemplateMethod(cv::TM_CCOEFF_NORMED)) - -IMPLEMENT_PARAM_CLASS(TemplateSize, cv::Size) - -#define MTEMP_SIZES testing::Values(cv::Size(128, 256), cv::Size(1024, 768)) - -PARAM_TEST_CASE(MatchTemplate8U, cv::Size, TemplateSize, Channels, TemplateMethod) -{ - cv::Size size; - cv::Size templ_size; - int cn; - int method; - - virtual void SetUp() - { - size = GET_PARAM(0); - templ_size = GET_PARAM(1); - cn = GET_PARAM(2); - method = GET_PARAM(3); - } -}; - -OCL_TEST_P(MatchTemplate8U, Accuracy) -{ - cv::Mat image = randomMat(size, CV_MAKETYPE(CV_8U, cn), 0, 255); - cv::Mat templ = randomMat(templ_size, CV_MAKETYPE(CV_8U, cn), 0, 255); - - cv::ocl::oclMat dst, ocl_image(image), ocl_templ(templ); - cv::ocl::matchTemplate(ocl_image, ocl_templ, dst, method); - - cv::Mat dst_gold; - cv::matchTemplate(image, templ, dst_gold, method); - - cv::Mat mat_dst; - dst.download(mat_dst); - - EXPECT_MAT_NEAR(dst_gold, mat_dst, templ_size.area() * 1e-1); -} - -PARAM_TEST_CASE(MatchTemplate32F, cv::Size, TemplateSize, Channels, TemplateMethod) -{ - cv::Size size; - cv::Size templ_size; - int cn; - int method; - - virtual void SetUp() - { - size = GET_PARAM(0); - templ_size = GET_PARAM(1); - cn = GET_PARAM(2); - method = GET_PARAM(3); - } -}; - -OCL_TEST_P(MatchTemplate32F, Accuracy) -{ - cv::Mat image = randomMat(size, CV_MAKETYPE(CV_32F, cn), 0, 255); - cv::Mat templ = randomMat(templ_size, CV_MAKETYPE(CV_32F, cn), 0, 255); - - cv::ocl::oclMat dst, ocl_image(image), ocl_templ(templ); - cv::ocl::matchTemplate(ocl_image, ocl_templ, dst, method); - - cv::Mat dst_gold; - cv::matchTemplate(image, templ, dst_gold, method); - - cv::Mat mat_dst; - dst.download(mat_dst); - - EXPECT_MAT_NEAR(dst_gold, mat_dst, templ_size.area() * 1e-1); -} - -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, MatchTemplate8U, - testing::Combine( - MTEMP_SIZES, - testing::Values(TemplateSize(cv::Size(5, 5)), TemplateSize(cv::Size(16, 16)), TemplateSize(cv::Size(30, 30))), - testing::Values(Channels(1), Channels(3), Channels(4)), - ALL_TEMPLATE_METHODS - ) - ); - -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, MatchTemplate32F, testing::Combine( - MTEMP_SIZES, - testing::Values(TemplateSize(cv::Size(5, 5)), TemplateSize(cv::Size(16, 16)), TemplateSize(cv::Size(30, 30))), - testing::Values(Channels(1), Channels(3), Channels(4)), - testing::Values(TemplateMethod(cv::TM_SQDIFF), TemplateMethod(cv::TM_CCORR)))); -#endif diff --git a/modules/ocl/test/test_matrix_operation.cpp b/modules/ocl/test/test_matrix_operation.cpp deleted file mode 100644 index c7ceef453..000000000 --- a/modules/ocl/test/test_matrix_operation.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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 "test_precomp.hpp" - -#ifdef HAVE_OPENCL - -using namespace cv; -using namespace testing; -using namespace std; - -////////////////////////////////converto///////////////////////////////////////////////// - -PARAM_TEST_CASE(MatrixTestBase, MatDepth, MatDepth, int, bool) -{ - int src_depth, cn, dstType; - bool use_roi; - - Mat src, dst, src_roi, dst_roi; - ocl::oclMat gdst, gsrc, gdst_roi, gsrc_roi; - - virtual void SetUp() - { - src_depth = GET_PARAM(0); - cn = GET_PARAM(2); - dstType = CV_MAKE_TYPE(GET_PARAM(1), cn); - - use_roi = GET_PARAM(3); - } - - virtual void random_roi() - { - Size roiSize = randomSize(1, MAX_VALUE); - Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, CV_MAKE_TYPE(src_depth, cn), -MAX_VALUE, MAX_VALUE); - - Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(dst, dst_roi, roiSize, dstBorder, dstType, 5, 16); - - generateOclMat(gsrc, gsrc_roi, src, roiSize, srcBorder); - generateOclMat(gdst, gdst_roi, dst, roiSize, dstBorder); - } -}; - -typedef MatrixTestBase ConvertTo; - -OCL_TEST_P(ConvertTo, Accuracy) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - src_roi.convertTo(dst_roi, dstType); - gsrc_roi.convertTo(gdst_roi, dstType); - - EXPECT_MAT_NEAR(dst, Mat(gdst), src_depth == CV_64F ? 1.0 : 0.0); - EXPECT_MAT_NEAR(dst_roi, Mat(gdst_roi), src_depth == CV_64F ? 1.0 : 0.0); - } -} - -///////////////////////////////////////////copyto///////////////////////////////////////////////////////////// - -struct CopyTo : - public MatrixTestBase -{ - Mat mask, mask_roi; - ocl::oclMat gmask, gmask_roi; - - virtual void random_roi() - { - int type = CV_MAKE_TYPE(src_depth, cn); - Size roiSize = randomSize(1, MAX_VALUE); - Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE); - - Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(dst, dst_roi, roiSize, dstBorder, type, 5, 16); - - Border maskBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(mask, mask_roi, roiSize, maskBorder, CV_8UC1, 5, 16); - - generateOclMat(gsrc, gsrc_roi, src, roiSize, srcBorder); - generateOclMat(gdst, gdst_roi, dst, roiSize, dstBorder); - generateOclMat(gmask, gmask_roi, mask, roiSize, maskBorder); - } -}; - -OCL_TEST_P(CopyTo, Without_mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - src_roi.copyTo(dst_roi); - gsrc_roi.copyTo(gdst_roi); - - EXPECT_MAT_NEAR(dst, Mat(gdst), 0.0); - EXPECT_MAT_NEAR(dst_roi, Mat(gdst_roi), 0.0); - } -} - -OCL_TEST_P(CopyTo, With_mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - src_roi.copyTo(dst_roi, mask_roi); - gsrc_roi.copyTo(gdst_roi, gmask_roi); - - EXPECT_MAT_NEAR(dst, Mat(gdst), 0.0); - EXPECT_MAT_NEAR(dst_roi, Mat(gdst_roi), 0.0); - } -} - -/////////////////////////////////////////// setTo ///////////////////////////////////////////////////////////// - -typedef CopyTo SetTo; - -OCL_TEST_P(SetTo, Without_mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - Scalar scalar = randomScalar(-MAX_VALUE, MAX_VALUE); - - src_roi.setTo(scalar); - gsrc_roi.setTo(scalar); - - EXPECT_MAT_NEAR(dst, Mat(gdst), 0.0); - EXPECT_MAT_NEAR(dst_roi, Mat(gdst_roi), 0.0);; - } -} - -OCL_TEST_P(SetTo, With_mask) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - Scalar scalar = randomScalar(-MAX_VALUE, MAX_VALUE); - - src_roi.setTo(scalar, mask_roi); - gsrc_roi.setTo(scalar, gmask_roi); - - EXPECT_MAT_NEAR(src, Mat(gsrc), 1.); - EXPECT_MAT_NEAR(src_roi, Mat(gsrc_roi), 1.); - } -} - -// convertC3C4 - -PARAM_TEST_CASE(convertC3C4, MatDepth, bool) -{ - int depth; - bool use_roi; - - Mat src, src_roi; - ocl::oclMat gsrc, gsrc_roi; - - virtual void SetUp() - { - depth = GET_PARAM(0); - use_roi = GET_PARAM(1); - } - - void random_roi() - { - int type = CV_MAKE_TYPE(depth, 3); - Size roiSize = randomSize(1, MAX_VALUE); - Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE); - generateOclMat(gsrc, gsrc_roi, src, roiSize, srcBorder); - } -}; - -OCL_TEST_P(convertC3C4, Accuracy) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - gsrc_roi = src_roi; - - EXPECT_MAT_NEAR(src_roi, Mat(gsrc_roi), 0.0); - EXPECT_MAT_NEAR(src, Mat(gsrc), 0.0); - } -} - -INSTANTIATE_TEST_CASE_P(MatrixOperation, ConvertTo, Combine( - Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), - Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), - testing::Range(1, 5), Bool())); - -INSTANTIATE_TEST_CASE_P(MatrixOperation, CopyTo, Combine( - Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), - Values(MatDepth(0)), // not used - testing::Range(1, 5), Bool())); - -INSTANTIATE_TEST_CASE_P(MatrixOperation, SetTo, Combine( - Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), - Values((MatDepth)0), // not used - testing::Range(1, 5), Bool())); - -INSTANTIATE_TEST_CASE_P(MatrixOperation, convertC3C4, Combine( - Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), - Bool())); -#endif diff --git a/modules/ocl/test/test_mean_shift.cpp b/modules/ocl/test/test_mean_shift.cpp deleted file mode 100644 index 6ee3e35a7..000000000 --- a/modules/ocl/test/test_mean_shift.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Jia Haipeng, jiahaipeng95@gmail.com -// Shengen Yan, yanshengen@gmail.com -// Jiang Liyuan, lyuan001.good@163.com -// Rock Li, Rock.Li@amd.com -// Wu Zailong, bullet@yeah.net -// Xu Pang, pangxu010@163.com -// Sen Liu, swjtuls1987@126.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 "test_precomp.hpp" - -#ifdef HAVE_OPENCL - -using namespace testing; -using namespace std; -using namespace cv; - -typedef struct -{ - short x; - short y; -} COOR; - -COOR do_meanShift(int x0, int y0, uchar *sptr, uchar *dptr, int sstep, Size size, int sp, int sr, int maxIter, float eps, int *tab) -{ - - int isr2 = sr * sr; - int c0, c1, c2, c3; - int iter; - uchar *ptr = NULL; - uchar *pstart = NULL; - int revx = 0, revy = 0; - c0 = sptr[0]; - c1 = sptr[1]; - c2 = sptr[2]; - c3 = sptr[3]; - // iterate meanshift procedure - for(iter = 0; iter < maxIter; iter++ ) - { - int count = 0; - int s0 = 0, s1 = 0, s2 = 0, sx = 0, sy = 0; - - //mean shift: process pixels in window (p-sigmaSp)x(p+sigmaSp) - int minx = x0 - sp; - int miny = y0 - sp; - int maxx = x0 + sp; - int maxy = y0 + sp; - - //deal with the image boundary - if(minx < 0) minx = 0; - if(miny < 0) miny = 0; - if(maxx >= size.width) maxx = size.width - 1; - if(maxy >= size.height) maxy = size.height - 1; - if(iter == 0) - { - pstart = sptr; - } - else - { - pstart = pstart + revy * sstep + (revx << 2); //point to the new position - } - ptr = pstart; - ptr = ptr + (miny - y0) * sstep + ((minx - x0) << 2); //point to the start in the row - - for( int y = miny; y <= maxy; y++, ptr += sstep - ((maxx - minx + 1) << 2)) - { - int rowCount = 0; - int x = minx; -#if CV_ENABLE_UNROLLED - for( ; x + 4 <= maxx; x += 4, ptr += 16) - { - int t0, t1, t2; - t0 = ptr[0], t1 = ptr[1], t2 = ptr[2]; - if(tab[t0 - c0 + 255] + tab[t1 - c1 + 255] + tab[t2 - c2 + 255] <= isr2) - { - s0 += t0; - s1 += t1; - s2 += t2; - sx += x; - rowCount++; - } - t0 = ptr[4], t1 = ptr[5], t2 = ptr[6]; - if(tab[t0 - c0 + 255] + tab[t1 - c1 + 255] + tab[t2 - c2 + 255] <= isr2) - { - s0 += t0; - s1 += t1; - s2 += t2; - sx += x + 1; - rowCount++; - } - t0 = ptr[8], t1 = ptr[9], t2 = ptr[10]; - if(tab[t0 - c0 + 255] + tab[t1 - c1 + 255] + tab[t2 - c2 + 255] <= isr2) - { - s0 += t0; - s1 += t1; - s2 += t2; - sx += x + 2; - rowCount++; - } - t0 = ptr[12], t1 = ptr[13], t2 = ptr[14]; - if(tab[t0 - c0 + 255] + tab[t1 - c1 + 255] + tab[t2 - c2 + 255] <= isr2) - { - s0 += t0; - s1 += t1; - s2 += t2; - sx += x + 3; - rowCount++; - } - } -#endif - for(; x <= maxx; x++, ptr += 4) - { - int t0 = ptr[0], t1 = ptr[1], t2 = ptr[2]; - if(tab[t0 - c0 + 255] + tab[t1 - c1 + 255] + tab[t2 - c2 + 255] <= isr2) - { - s0 += t0; - s1 += t1; - s2 += t2; - sx += x; - rowCount++; - } - } - if(rowCount == 0) - continue; - count += rowCount; - sy += y * rowCount; - } - - if( count == 0 ) - break; - - int x1 = sx / count; - int y1 = sy / count; - s0 = s0 / count; - s1 = s1 / count; - s2 = s2 / count; - - bool stopFlag = (x0 == x1 && y0 == y1) || (abs(x1 - x0) + abs(y1 - y0) + - tab[s0 - c0 + 255] + tab[s1 - c1 + 255] + tab[s2 - c2 + 255] <= eps); - - //revise the pointer corresponding to the new (y0,x0) - revx = x1 - x0; - revy = y1 - y0; - - x0 = x1; - y0 = y1; - c0 = s0; - c1 = s1; - c2 = s2; - - if( stopFlag ) - break; - } //for iter - - dptr[0] = (uchar)c0; - dptr[1] = (uchar)c1; - dptr[2] = (uchar)c2; - dptr[3] = (uchar)c3; - - COOR coor; - coor.x = (short)x0; - coor.y = (short)y0; - return coor; -} - -void meanShiftFiltering_(const Mat &src_roi, Mat &dst_roi, int sp, int sr, TermCriteria crit) -{ - if( src_roi.empty() ) - CV_Error( CV_StsBadArg, "The input image is empty" ); - - if( src_roi.depth() != CV_8U || src_roi.channels() != 4 ) - CV_Error( CV_StsUnsupportedFormat, "Only 8-bit, 4-channel images are supported" ); - - CV_Assert( (src_roi.cols == dst_roi.cols) && (src_roi.rows == dst_roi.rows) ); - CV_Assert( !(dst_roi.step & 0x3) ); - - if( !(crit.type & TermCriteria::MAX_ITER) ) - crit.maxCount = 5; - int maxIter = std::min(std::max(crit.maxCount, 1), 100); - float eps; - if( !(crit.type & TermCriteria::EPS) ) - eps = 1.f; - eps = (float)std::max(crit.epsilon, 0.0); - - int tab[512]; - for(int i = 0; i < 512; i++) - tab[i] = (i - 255) * (i - 255); - uchar *sptr = src_roi.data; - uchar *dptr = dst_roi.data; - int sstep = (int)src_roi.step; - int dstep = (int)dst_roi.step; - Size size = src_roi.size(); - - for(int i = 0; i < size.height; i++, sptr += sstep - (size.width << 2), - dptr += dstep - (size.width << 2)) - { - for(int j = 0; j < size.width; j++, sptr += 4, dptr += 4) - { - do_meanShift(j, i, sptr, dptr, sstep, size, sp, sr, maxIter, eps, tab); - } - } -} - -void meanShiftProc_(const Mat &src_roi, Mat &dst_roi, Mat &dstCoor_roi, int sp, int sr, TermCriteria crit) -{ - if( src_roi.empty() ) - CV_Error( CV_StsBadArg, "The input image is empty" ); - if( src_roi.depth() != CV_8U || src_roi.channels() != 4 ) - CV_Error( CV_StsUnsupportedFormat, "Only 8-bit, 4-channel images are supported" ); - CV_Assert( (src_roi.cols == dst_roi.cols) && (src_roi.rows == dst_roi.rows) && - (src_roi.cols == dstCoor_roi.cols) && (src_roi.rows == dstCoor_roi.rows)); - CV_Assert( !(dstCoor_roi.step & 0x3) ); - - if( !(crit.type & TermCriteria::MAX_ITER) ) - crit.maxCount = 5; - int maxIter = std::min(std::max(crit.maxCount, 1), 100); - float eps; - if( !(crit.type & TermCriteria::EPS) ) - eps = 1.f; - eps = (float)std::max(crit.epsilon, 0.0); - - int tab[512]; - for(int i = 0; i < 512; i++) - tab[i] = (i - 255) * (i - 255); - uchar *sptr = src_roi.data; - uchar *dptr = dst_roi.data; - short *dCoorptr = (short *)dstCoor_roi.data; - int sstep = (int)src_roi.step; - int dstep = (int)dst_roi.step; - int dCoorstep = (int)dstCoor_roi.step >> 1; - Size size = src_roi.size(); - - for(int i = 0; i < size.height; i++, sptr += sstep - (size.width << 2), - dptr += dstep - (size.width << 2), dCoorptr += dCoorstep - (size.width << 1)) - { - for(int j = 0; j < size.width; j++, sptr += 4, dptr += 4, dCoorptr += 2) - { - *((COOR *)dCoorptr) = do_meanShift(j, i, sptr, dptr, sstep, size, sp, sr, maxIter, eps, tab); - } - } - -} - -//////////////////////////////// meanShift ////////////////////////////////////////// - -PARAM_TEST_CASE(meanShiftTestBase, MatType, MatType, int, int, TermCriteria, bool) -{ - int type, typeCoor; - int sp, sr; - TermCriteria crit; - bool useRoi; - - // src mat - Mat src, src_roi; - Mat dst, dst_roi; - Mat dstCoor, dstCoor_roi; - - // ocl dst mat - ocl::oclMat gsrc, gsrc_roi; - ocl::oclMat gdst, gdst_roi; - ocl::oclMat gdstCoor, gdstCoor_roi; - - virtual void SetUp() - { - type = GET_PARAM(0); - typeCoor = GET_PARAM(1); - sp = GET_PARAM(2); - sr = GET_PARAM(3); - crit = GET_PARAM(4); - useRoi = GET_PARAM(5); - } - - void random_roi() - { - Size roiSize = randomSize(1, MAX_VALUE); - Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, type, 5, 256); - generateOclMat(gsrc, gsrc_roi, src, roiSize, srcBorder); - - Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(dst, dst_roi, roiSize, dstBorder, type, 5, 256); - generateOclMat(gdst, gdst_roi, dst, roiSize, dstBorder); - - randomSubMat(dstCoor, dstCoor_roi, roiSize, dstBorder, typeCoor, 5, 256); - generateOclMat(gdstCoor, gdstCoor_roi, dstCoor, roiSize, dstBorder); - } - - void Near(double threshold = 0.0) - { - Mat whole, roi; - gdst.download(whole); - gdst_roi.download(roi); - - EXPECT_MAT_NEAR(dst, whole, threshold); - EXPECT_MAT_NEAR(dst_roi, roi, threshold); - } - - void Near1(double threshold = 0.0) - { - Mat whole, roi; - gdstCoor.download(whole); - gdstCoor_roi.download(roi); - - EXPECT_MAT_NEAR(dstCoor, whole, threshold); - EXPECT_MAT_NEAR(dstCoor_roi, roi, threshold); - } -}; - -/////////////////////////meanShiftFiltering///////////////////////////// - -typedef meanShiftTestBase meanShiftFiltering; - -OCL_TEST_P(meanShiftFiltering, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - meanShiftFiltering_(src_roi, dst_roi, sp, sr, crit); - ocl::meanShiftFiltering(gsrc_roi, gdst_roi, sp, sr, crit); - - Near(); - } -} - -///////////////////////////meanShiftProc////////////////////////////////// - -typedef meanShiftTestBase meanShiftProc; - -OCL_TEST_P(meanShiftProc, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - meanShiftProc_(src_roi, dst_roi, dstCoor_roi, sp, sr, crit); - ocl::meanShiftProc(gsrc_roi, gdst_roi, gdstCoor_roi, sp, sr, crit); - - Near(); - Near1(); - } -} - -///////////////////////////////////////////////////////////////////////////////////// - -INSTANTIATE_TEST_CASE_P(Imgproc, meanShiftFiltering, Combine( - Values((MatType)CV_8UC4), - Values((MatType)CV_16SC2), - Values(5), - Values(6), - Values(TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 5, 1)), - Bool() - )); - -INSTANTIATE_TEST_CASE_P(Imgproc, meanShiftProc, Combine( - Values((MatType)CV_8UC4), - Values((MatType)CV_16SC2), - Values(5), - Values(6), - Values(TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 5, 1)), - Bool() - )); - -#endif // HAVE_OPENCL diff --git a/modules/ocl/test/test_ml.cpp b/modules/ocl/test/test_ml.cpp deleted file mode 100644 index 00f9fa941..000000000 --- a/modules/ocl/test/test_ml.cpp +++ /dev/null @@ -1,309 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////// -// -// 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 -// Jin Ma, jin@multicorewareinc.com -// Xiaopeng Fu, fuxiaopeng2222@163.com -// Erping Pang, pang_er_ping@163.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 "test_precomp.hpp" - -#ifdef HAVE_OPENCL - -using namespace cv; -using namespace cv::ocl; -using namespace cvtest; -using namespace testing; - -///////K-NEAREST NEIGHBOR////////////////////////// - -static void genTrainData(cv::RNG& rng, Mat& trainData, int trainDataRow, int trainDataCol, - Mat& trainLabel = Mat().setTo(Scalar::all(0)), int nClasses = 0) -{ - cv::Size size(trainDataCol, trainDataRow); - trainData = randomMat(rng, size, CV_32FC1, 1.0, 1000.0, false); - if(nClasses != 0) - { - cv::Size size1(trainDataRow, 1); - trainLabel = randomMat(rng, size1, CV_8UC1, 0, nClasses - 1, false); - trainLabel.convertTo(trainLabel, CV_32FC1); - } -} - -PARAM_TEST_CASE(KNN, int, Size, int, bool) -{ - int k; - int trainDataCol; - int testDataRow; - int nClass; - bool regression; - virtual void SetUp() - { - k = GET_PARAM(0); - nClass = GET_PARAM(2); - trainDataCol = GET_PARAM(1).width; - testDataRow = GET_PARAM(1).height; - regression = GET_PARAM(3); - } -}; - -OCL_TEST_P(KNN, Accuracy) -{ - Mat trainData, trainLabels; - const int trainDataRow = 500; - genTrainData(rng, trainData, trainDataRow, trainDataCol, trainLabels, nClass); - - Mat testData, testLabels; - genTrainData(rng, testData, testDataRow, trainDataCol); - - KNearestNeighbour knn_ocl; - CvKNearest knn_cpu; - Mat best_label_cpu; - oclMat best_label_ocl; - - /*ocl k-Nearest_Neighbor start*/ - oclMat trainData_ocl; - trainData_ocl.upload(trainData); - Mat simpleIdx; - knn_ocl.train(trainData, trainLabels, simpleIdx, regression); - - oclMat testdata; - testdata.upload(testData); - knn_ocl.find_nearest(testdata, k, best_label_ocl); - /*ocl k-Nearest_Neighbor end*/ - - /*cpu k-Nearest_Neighbor start*/ - knn_cpu.train(trainData, trainLabels, simpleIdx, regression); - knn_cpu.find_nearest(testData, k, &best_label_cpu); - /*cpu k-Nearest_Neighbor end*/ - if(regression) - { - EXPECT_MAT_SIMILAR(Mat(best_label_ocl), best_label_cpu, 1e-5); - } - else - { - EXPECT_MAT_NEAR(Mat(best_label_ocl), best_label_cpu, 0.0); - } -} - -INSTANTIATE_TEST_CASE_P(OCL_ML, KNN, Combine(Values(6, 5), Values(Size(200, 400), Size(300, 600)), - Values(4, 3), Values(false, true))); - -////////////////////////////////SVM///////////////////////////////////////////////// - -PARAM_TEST_CASE(SVM_OCL, int, int, int) -{ - cv::Size size; - int kernel_type; - int svm_type; - Mat src, labels, samples, labels_predict; - int K; - - virtual void SetUp() - { - - kernel_type = GET_PARAM(0); - svm_type = GET_PARAM(1); - K = GET_PARAM(2); - cv::Size size = cv::Size(MWIDTH, MHEIGHT); - src.create(size, CV_32FC1); - labels.create(1, size.height, CV_32SC1); - int row_idx = 0; - const int max_number = size.height / K - 1; - CV_Assert(K <= size.height); - for(int i = 0; i < K; i++ ) - { - Mat center_row_header = src.row(row_idx); - center_row_header.setTo(0); - int nchannel = center_row_header.channels(); - for(int j = 0; j < nchannel; j++) - { - center_row_header.at(0, i * nchannel + j) = 500.0; - } - labels.at(0, row_idx) = i; - for(int j = 0; (j < max_number) || - (i == K - 1 && j < max_number + size.height % K); j ++) - { - Mat cur_row_header = src.row(row_idx + 1 + j); - center_row_header.copyTo(cur_row_header); - Mat tmpmat = randomMat(cur_row_header.size(), cur_row_header.type(), 1, 100, false); - cur_row_header += tmpmat; - labels.at(0, row_idx + 1 + j) = i; - } - row_idx += 1 + max_number; - } - labels.convertTo(labels, CV_32FC1); - cv::Size test_size = cv::Size(MWIDTH, 100); - samples.create(test_size, CV_32FC1); - labels_predict.create(1, test_size.height, CV_32SC1); - const int max_number_test = test_size.height / K - 1; - row_idx = 0; - for(int i = 0; i < K; i++ ) - { - Mat center_row_header = samples.row(row_idx); - center_row_header.setTo(0); - int nchannel = center_row_header.channels(); - for(int j = 0; j < nchannel; j++) - { - center_row_header.at(0, i * nchannel + j) = 500.0; - } - labels_predict.at(0, row_idx) = i; - for(int j = 0; (j < max_number_test) || - (i == K - 1 && j < max_number_test + test_size.height % K); j ++) - { - Mat cur_row_header = samples.row(row_idx + 1 + j); - center_row_header.copyTo(cur_row_header); - Mat tmpmat = randomMat(cur_row_header.size(), cur_row_header.type(), 1, 100, false); - cur_row_header += tmpmat; - labels_predict.at(0, row_idx + 1 + j) = i; - } - row_idx += 1 + max_number_test; - } - labels_predict.convertTo(labels_predict, CV_32FC1); - } -}; - -OCL_TEST_P(SVM_OCL, Accuracy) -{ - CvSVMParams params; - params.degree = 0.4; - params.gamma = 1; - params.coef0 = 1; - params.C = 1; - params.nu = 0.5; - params.p = 1; - params.svm_type = svm_type; - params.kernel_type = kernel_type; - - params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 1000, 0.001); - - CvSVM SVM; - SVM.train(src, labels, Mat(), Mat(), params); - - cv::ocl::CvSVM_OCL SVM_OCL; - SVM_OCL.train(src, labels, Mat(), Mat(), params); - - int c = SVM.get_support_vector_count(); - int c1 = SVM_OCL.get_support_vector_count(); - - Mat sv(c, MHEIGHT, CV_32FC1); - Mat sv_ocl(c1, MHEIGHT, CV_32FC1); - for(int i = 0; i < c; i++) - { - const float* v = SVM.get_support_vector(i); - - for(int j = 0; j < MHEIGHT; j++) - { - sv.at(i, j) = v[j]; - } - } - for(int i = 0; i < c1; i++) - { - const float* v_ocl = SVM_OCL.get_support_vector(i); - - for(int j = 0; j < MHEIGHT; j++) - { - sv_ocl.at(i, j) = v_ocl[j]; - } - } - cv::BFMatcher matcher(cv::NORM_L2); - std::vector matches; - matcher.match(sv, sv_ocl, matches); - int count = 0; - - for(std::vector::iterator itr = matches.begin(); itr != matches.end(); itr++) - { - if((*itr).distance < 0.1) - { - count ++; - } - } - if(c != 0) - { - float matchedRatio = (float)count / c; - EXPECT_GT(matchedRatio, 0.95); - } - if(c != 0) - { - CvMat *result = cvCreateMat(1, samples.rows, CV_32FC1); - CvMat test_samples = samples; - - CvMat *result_ocl = cvCreateMat(1, samples.rows, CV_32FC1); - - SVM.predict(&test_samples, result); - - SVM_OCL.predict(&test_samples, result_ocl); - - int true_resp = 0, true_resp_ocl = 0; - for (int i = 0; i < samples.rows; i++) - { - if (result->data.fl[i] == labels_predict.at(0, i)) - { - true_resp++; - } - } - float matchedRatio = (float)true_resp / samples.rows; - - for (int i = 0; i < samples.rows; i++) - { - if (result_ocl->data.fl[i] == labels_predict.at(0, i)) - { - true_resp_ocl++; - } - } - float matchedRatio_ocl = (float)true_resp_ocl / samples.rows; - - if(matchedRatio != 0 && true_resp_ocl < true_resp) - { - EXPECT_NEAR(matchedRatio_ocl, matchedRatio, 0.03); - } - } -} - -// TODO FIXIT: CvSVM::EPS_SVR case is crashed inside CPU implementation -// Anonymous enums are not supported well so cast them to 'int' - -INSTANTIATE_TEST_CASE_P(OCL_ML, SVM_OCL, testing::Combine( - Values((int)CvSVM::LINEAR, (int)CvSVM::POLY, (int)CvSVM::RBF, (int)CvSVM::SIGMOID), - Values((int)CvSVM::C_SVC, (int)CvSVM::NU_SVC, (int)CvSVM::ONE_CLASS, (int)CvSVM::NU_SVR), - Values(2, 3, 4) - )); - -#endif // HAVE_OPENCL diff --git a/modules/ocl/test/test_moments.cpp b/modules/ocl/test/test_moments.cpp deleted file mode 100644 index e978bb28f..000000000 --- a/modules/ocl/test/test_moments.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "test_precomp.hpp" -#include - -#ifdef HAVE_OPENCL - -using namespace cv; -using namespace cv::ocl; -using namespace cvtest; -using namespace testing; -PARAM_TEST_CASE(MomentsTest, MatType, bool, bool) -{ - int type; - cv::Mat mat; - bool test_contours; - bool binaryImage; - virtual void SetUp() - { - type = GET_PARAM(0); - test_contours = GET_PARAM(1); - cv::Size size(10 * MWIDTH, 10 * MHEIGHT); - mat = randomMat(size, type, 0, 256, false); - binaryImage = GET_PARAM(2); - } - - void Compare(Moments& cpu_moments, Moments& gpu_moments) - { - Mat gpu_dst, cpu_dst; - HuMoments(cpu_moments, cpu_dst); - HuMoments(gpu_moments, gpu_dst); - EXPECT_MAT_NEAR(gpu_dst, cpu_dst, 1e-3); - } -}; - -OCL_TEST_P(MomentsTest, Mat) -{ - oclMat src_d(mat); - for(int j = 0; j < LOOP_TIMES; j++) - { - if(test_contours) - { - Mat src = readImage( "cv/shared/pic3.png", IMREAD_GRAYSCALE ); - ASSERT_FALSE(src.empty()); - Mat canny_output; - vector > contours; - vector hierarchy; - Canny( src, canny_output, 100, 200, 3 ); - findContours( canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) ); - for( size_t i = 0; i < contours.size(); i++ ) - { - Moments m = moments( contours[i], false ); - Moments dm = ocl::ocl_moments( contours[i]); - Compare(m, dm); - } - } - cv::Moments CvMom = cv::moments(mat, binaryImage); - cv::Moments oclMom = cv::ocl::ocl_moments(src_d, binaryImage); - - Compare(CvMom, oclMom); - } -} -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, MomentsTest, Combine( - Values(CV_8UC1, CV_16UC1, CV_16SC1, CV_32FC1, CV_64FC1), Values(false, true), Values(false, true))); - -#endif // HAVE_OPENCL diff --git a/modules/ocl/test/test_objdetect.cpp b/modules/ocl/test/test_objdetect.cpp deleted file mode 100644 index f179e9e91..000000000 --- a/modules/ocl/test/test_objdetect.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/*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. -// -// -// Intel 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 -// Yao Wang, bitwangyaoyao@gmail.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 Intel Corporation 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 "test_precomp.hpp" -#include "opencv2/objdetect.hpp" - -using namespace cv; -using namespace testing; - -///////////////////// HOG ///////////////////////////// -PARAM_TEST_CASE(HOG, Size, int) -{ - Size winSize; - int type; - Mat img_rgb; - virtual void SetUp() - { - winSize = GET_PARAM(0); - type = GET_PARAM(1); - img_rgb = readImage("gpu/hog/road.png"); - ASSERT_FALSE(img_rgb.empty()); - } -}; - -OCL_TEST_P(HOG, GetDescriptors) -{ - // Convert image - Mat img; - switch (type) - { - case CV_8UC1: - cvtColor(img_rgb, img, COLOR_BGR2GRAY); - break; - case CV_8UC4: - default: - cvtColor(img_rgb, img, COLOR_BGR2BGRA); - break; - } - ocl::oclMat d_img(img); - - // HOGs - ocl::HOGDescriptor ocl_hog; - ocl_hog.gamma_correction = true; - HOGDescriptor hog; - hog.gammaCorrection = true; - - // Compute descriptor - ocl::oclMat d_descriptors; - ocl_hog.getDescriptors(d_img, ocl_hog.win_size, d_descriptors, ocl_hog.DESCR_FORMAT_COL_BY_COL); - Mat down_descriptors; - d_descriptors.download(down_descriptors); - down_descriptors = down_descriptors.reshape(0, down_descriptors.cols * down_descriptors.rows); - - hog.setSVMDetector(hog.getDefaultPeopleDetector()); - std::vector descriptors; - switch (type) - { - case CV_8UC1: - hog.compute(img, descriptors, ocl_hog.win_size); - break; - case CV_8UC4: - default: - hog.compute(img_rgb, descriptors, ocl_hog.win_size); - break; - } - Mat cpu_descriptors(descriptors); - - EXPECT_MAT_SIMILAR(down_descriptors, cpu_descriptors, 1e-2); -} - -OCL_TEST_P(HOG, Detect) -{ - // Convert image - Mat img; - switch (type) - { - case CV_8UC1: - cvtColor(img_rgb, img, COLOR_BGR2GRAY); - break; - case CV_8UC4: - default: - cvtColor(img_rgb, img, COLOR_BGR2BGRA); - break; - } - ocl::oclMat d_img(img); - - // HOGs - if ((winSize != Size(48, 96)) && (winSize != Size(64, 128))) - winSize = Size(64, 128); - ocl::HOGDescriptor ocl_hog(winSize); - ocl_hog.gamma_correction = true; - - HOGDescriptor hog; - hog.winSize = winSize; - hog.gammaCorrection = true; - - if (winSize.width == 48 && winSize.height == 96) - { - // daimler's base - ocl_hog.setSVMDetector(hog.getDaimlerPeopleDetector()); - hog.setSVMDetector(hog.getDaimlerPeopleDetector()); - } - else if (winSize.width == 64 && winSize.height == 128) - { - ocl_hog.setSVMDetector(hog.getDefaultPeopleDetector()); - hog.setSVMDetector(hog.getDefaultPeopleDetector()); - } - else - { - ocl_hog.setSVMDetector(hog.getDefaultPeopleDetector()); - hog.setSVMDetector(hog.getDefaultPeopleDetector()); - } - - // OpenCL detection - std::vector d_found; - ocl_hog.detectMultiScale(d_img, d_found, 0, Size(8, 8), Size(0, 0), 1.05, 6); - - // CPU detection - std::vector found; - switch (type) - { - case CV_8UC1: - hog.detectMultiScale(img, found, 0, Size(8, 8), Size(0, 0), 1.05, 6); - break; - case CV_8UC4: - default: - hog.detectMultiScale(img_rgb, found, 0, Size(8, 8), Size(0, 0), 1.05, 6); - break; - } - - EXPECT_LT(checkRectSimilarity(img.size(), found, d_found), 1.0); -} - - -INSTANTIATE_TEST_CASE_P(OCL_ObjDetect, HOG, testing::Combine( - testing::Values(Size(64, 128), Size(48, 96)), - testing::Values(MatType(CV_8UC1), MatType(CV_8UC4)))); - - -///////////////////////////// Haar ////////////////////////////// -IMPLEMENT_PARAM_CLASS(CascadeName, std::string) -CascadeName cascade_frontalface_alt(std::string("haarcascade_frontalface_alt.xml")); -CascadeName cascade_frontalface_alt2(std::string("haarcascade_frontalface_alt2.xml")); - -PARAM_TEST_CASE(Haar, int, CascadeName) -{ - ocl::OclCascadeClassifier cascade, nestedCascade; - CascadeClassifier cpucascade, cpunestedCascade; - - int flags; - std::string cascadeName; - std::vector faces, oclfaces; - Mat img; - ocl::oclMat d_img; - - virtual void SetUp() - { - flags = GET_PARAM(0); - cascadeName = (std::string(cvtest::TS::ptr()->get_data_path()) + "cv/cascadeandhog/cascades/").append(GET_PARAM(1)); - ASSERT_TRUE(cascade.load( cascadeName )); - ASSERT_TRUE(cpucascade.load(cascadeName)); - img = readImage("cv/shared/lena.png", IMREAD_GRAYSCALE); - ASSERT_FALSE(img.empty()); - equalizeHist(img, img); - d_img.upload(img); - } -}; - -OCL_TEST_P(Haar, FaceDetect) -{ - cascade.detectMultiScale(d_img, oclfaces, 1.1, 3, - flags, - Size(30, 30), Size(0, 0)); - - cpucascade.detectMultiScale(img, faces, 1.1, 3, - flags, - Size(30, 30), Size(0, 0)); - - EXPECT_LT(checkRectSimilarity(img.size(), faces, oclfaces), 1.0); -} - -INSTANTIATE_TEST_CASE_P(OCL_ObjDetect, Haar, - Combine(Values((int)CASCADE_SCALE_IMAGE, 0), - Values(cascade_frontalface_alt, cascade_frontalface_alt2))); diff --git a/modules/ocl/test/test_optflow.cpp b/modules/ocl/test/test_optflow.cpp deleted file mode 100644 index 7296a6b7e..000000000 --- a/modules/ocl/test/test_optflow.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////// -// -// 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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// -// -// 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 "test_precomp.hpp" -#include - -#ifdef HAVE_OPENCL - -using namespace cv; -using namespace cv::ocl; -using namespace cvtest; -using namespace testing; -using namespace std; - -////////////////////////////////////////////////////// -// GoodFeaturesToTrack -namespace -{ - IMPLEMENT_PARAM_CLASS(MinDistance, double) -} -PARAM_TEST_CASE(GoodFeaturesToTrack, MinDistance) -{ - double minDistance; - - virtual void SetUp() - { - minDistance = GET_PARAM(0); - } -}; - -OCL_TEST_P(GoodFeaturesToTrack, Accuracy) -{ - cv::Mat frame = readImage("gpu/opticalflow/rubberwhale1.png", cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame.empty()); - - int maxCorners = 1000; - double qualityLevel = 0.01; - - cv::ocl::GoodFeaturesToTrackDetector_OCL detector(maxCorners, qualityLevel, minDistance); - - cv::ocl::oclMat d_pts; - detector(oclMat(frame), d_pts); - - ASSERT_FALSE(d_pts.empty()); - - std::vector pts(d_pts.cols); - - detector.downloadPoints(d_pts, pts); - - std::vector pts_gold; - cv::goodFeaturesToTrack(frame, pts_gold, maxCorners, qualityLevel, minDistance); - - ASSERT_EQ(pts_gold.size(), pts.size()); - - size_t mistmatch = 0; - for (size_t i = 0; i < pts.size(); ++i) - { - cv::Point2i a = pts_gold[i]; - cv::Point2i b = pts[i]; - - bool eq = std::abs(a.x - b.x) < 1 && std::abs(a.y - b.y) < 1; - - if (!eq) - ++mistmatch; - } - - double bad_ratio = static_cast(mistmatch) / pts.size(); - - ASSERT_LE(bad_ratio, 0.01); -} - -OCL_TEST_P(GoodFeaturesToTrack, EmptyCorners) -{ - int maxCorners = 1000; - double qualityLevel = 0.01; - - cv::ocl::GoodFeaturesToTrackDetector_OCL detector(maxCorners, qualityLevel, minDistance); - - cv::ocl::oclMat src(100, 100, CV_8UC1, cv::Scalar::all(0)); - cv::ocl::oclMat corners(1, maxCorners, CV_32FC2); - - detector(src, corners); - - ASSERT_TRUE(corners.empty()); -} - -INSTANTIATE_TEST_CASE_P(OCL_Video, GoodFeaturesToTrack, - testing::Values(MinDistance(0.0), MinDistance(3.0))); - -////////////////////////////////////////////////////////////////////////// -PARAM_TEST_CASE(TVL1, bool) -{ - bool useRoi; - - virtual void SetUp() - { - useRoi = GET_PARAM(0); - } - -}; - -OCL_TEST_P(TVL1, DISABLED_Accuracy) // TODO implementations of TV1 in video module are different in 2.4 and master branches -{ - cv::Mat frame0 = readImage("gpu/opticalflow/rubberwhale1.png", cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame0.empty()); - - cv::Mat frame1 = readImage("gpu/opticalflow/rubberwhale2.png", cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame1.empty()); - - cv::ocl::OpticalFlowDual_TVL1_OCL d_alg; - cv::Mat flowx = randomMat(frame0.size(), CV_32FC1, 0, 0, useRoi); - cv::Mat flowy = randomMat(frame0.size(), CV_32FC1, 0, 0, useRoi); - cv::ocl::oclMat d_flowx(flowx), d_flowy(flowy); - d_alg(oclMat(frame0), oclMat(frame1), d_flowx, d_flowy); - - cv::Ptr alg = cv::createOptFlow_DualTVL1(); - cv::Mat flow; - alg->calc(frame0, frame1, flow); - cv::Mat gold[2]; - cv::split(flow, gold); - - EXPECT_MAT_SIMILAR(gold[0], d_flowx, 3e-3); - EXPECT_MAT_SIMILAR(gold[1], d_flowy, 3e-3); -} -INSTANTIATE_TEST_CASE_P(OCL_Video, TVL1, Values(false, true)); - - -///////////////////////////////////////////////////////////////////////////////////////////////// -// PyrLKOpticalFlow - -PARAM_TEST_CASE(Sparse, bool, bool) -{ - bool useGray; - bool UseSmart; - - virtual void SetUp() - { - UseSmart = GET_PARAM(0); - useGray = GET_PARAM(1); - } -}; - -OCL_TEST_P(Sparse, Mat) -{ - cv::Mat frame0 = readImage("gpu/opticalflow/rubberwhale1.png", useGray ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR); - ASSERT_FALSE(frame0.empty()); - - cv::Mat frame1 = readImage("gpu/opticalflow/rubberwhale2.png", useGray ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR); - ASSERT_FALSE(frame1.empty()); - - cv::Mat gray_frame; - if (useGray) - gray_frame = frame0; - else - cv::cvtColor(frame0, gray_frame, cv::COLOR_BGR2GRAY); - - std::vector pts; - cv::goodFeaturesToTrack(gray_frame, pts, 1000, 0.01, 0.0); - - cv::ocl::oclMat d_pts; - cv::Mat pts_mat(1, (int)pts.size(), CV_32FC2, (void *)&pts[0]); - d_pts.upload(pts_mat); - - cv::ocl::PyrLKOpticalFlow pyrLK; - - cv::ocl::oclMat oclFrame0; - cv::ocl::oclMat oclFrame1; - cv::ocl::oclMat d_nextPts; - cv::ocl::oclMat d_status; - cv::ocl::oclMat d_err; - - oclFrame0 = frame0; - oclFrame1 = frame1; - - pyrLK.sparse(oclFrame0, oclFrame1, d_pts, d_nextPts, d_status, &d_err); - - std::vector nextPts(d_nextPts.cols); - cv::Mat nextPts_mat(1, d_nextPts.cols, CV_32FC2, (void *)&nextPts[0]); - d_nextPts.download(nextPts_mat); - - std::vector status(d_status.cols); - cv::Mat status_mat(1, d_status.cols, CV_8UC1, (void *)&status[0]); - d_status.download(status_mat); - - std::vector err(d_err.cols); - cv::Mat err_mat(1, d_err.cols, CV_32FC1, (void*)&err[0]); - d_err.download(err_mat); - - std::vector nextPts_gold; - std::vector status_gold; - std::vector err_gold; - cv::calcOpticalFlowPyrLK(frame0, frame1, pts, nextPts_gold, status_gold, err_gold); - - ASSERT_EQ(nextPts_gold.size(), nextPts.size()); - ASSERT_EQ(status_gold.size(), status.size()); - - size_t mistmatch = 0; - for (size_t i = 0; i < nextPts.size(); ++i) - { - if (status[i] != status_gold[i]) - { - ++mistmatch; - continue; - } - - if (status[i]) - { - cv::Point2i a = nextPts[i]; - cv::Point2i b = nextPts_gold[i]; - - bool eq = std::abs(a.x - b.x) < 1 && std::abs(a.y - b.y) < 1; - float errdiff = 0.0f; - - if (!eq || errdiff > 1e-1) - ++mistmatch; - } - } - - double bad_ratio = static_cast(mistmatch) / (nextPts.size()); - - ASSERT_LE(bad_ratio, 0.02f); -} - -INSTANTIATE_TEST_CASE_P(OCL_Video, Sparse, Combine(Bool(), Bool())); - -////////////////////////////////////////////////////// -// FarnebackOpticalFlow - -namespace -{ - IMPLEMENT_PARAM_CLASS(PyrScale, double) - IMPLEMENT_PARAM_CLASS(PolyN, int) - CV_FLAGS(FarnebackOptFlowFlags, 0, OPTFLOW_FARNEBACK_GAUSSIAN) - IMPLEMENT_PARAM_CLASS(UseInitFlow, bool) -} - -PARAM_TEST_CASE(Farneback, PyrScale, PolyN, FarnebackOptFlowFlags, UseInitFlow) -{ - double pyrScale; - int polyN; - int flags; - bool useInitFlow; - - virtual void SetUp() - { - pyrScale = GET_PARAM(0); - polyN = GET_PARAM(1); - flags = GET_PARAM(2); - useInitFlow = GET_PARAM(3); - } -}; - -OCL_TEST_P(Farneback, Accuracy) -{ - cv::Mat frame0 = readImage("gpu/opticalflow/rubberwhale1.png", cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame0.empty()); - - cv::Mat frame1 = readImage("gpu/opticalflow/rubberwhale2.png", cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(frame1.empty()); - - double polySigma = polyN <= 5 ? 1.1 : 1.5; - - cv::ocl::FarnebackOpticalFlow farn; - farn.pyrScale = pyrScale; - farn.polyN = polyN; - farn.polySigma = polySigma; - farn.flags = flags; - - cv::ocl::oclMat d_flowx, d_flowy; - farn(oclMat(frame0), oclMat(frame1), d_flowx, d_flowy); - - cv::Mat flow; - if (useInitFlow) - { - cv::Mat flowxy[] = {cv::Mat(d_flowx), cv::Mat(d_flowy)}; - cv::merge(flowxy, 2, flow); - - farn.flags |= cv::OPTFLOW_USE_INITIAL_FLOW; - farn(oclMat(frame0), oclMat(frame1), d_flowx, d_flowy); - } - - cv::calcOpticalFlowFarneback( - frame0, frame1, flow, farn.pyrScale, farn.numLevels, farn.winSize, - farn.numIters, farn.polyN, farn.polySigma, farn.flags); - - std::vector flowxy; - cv::split(flow, flowxy); - - EXPECT_MAT_SIMILAR(flowxy[0], d_flowx, 0.1); - EXPECT_MAT_SIMILAR(flowxy[1], d_flowy, 0.1); -} - -INSTANTIATE_TEST_CASE_P(OCL_Video, Farneback, testing::Combine( - testing::Values(PyrScale(0.3), PyrScale(0.5), PyrScale(0.8)), - testing::Values(PolyN(5), PolyN(7)), - testing::Values(FarnebackOptFlowFlags(0), FarnebackOptFlowFlags(cv::OPTFLOW_FARNEBACK_GAUSSIAN)), - testing::Values(UseInitFlow(false), UseInitFlow(true)))); - -#endif // HAVE_OPENCL diff --git a/modules/ocl/test/test_orb.cpp b/modules/ocl/test/test_orb.cpp deleted file mode 100644 index 8df7e4862..000000000 --- a/modules/ocl/test/test_orb.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/*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. -// -// Authors: -// * Peter Andreas Entschev, peter@entschev.com -// -//M*/ - -#include "test_precomp.hpp" - -#ifdef HAVE_OPENCL - -//////////////////////////////////////////////////////// -// ORB - -namespace -{ - IMPLEMENT_PARAM_CLASS(ORB_FeaturesCount, int) - IMPLEMENT_PARAM_CLASS(ORB_ScaleFactor, float) - IMPLEMENT_PARAM_CLASS(ORB_LevelsCount, int) - IMPLEMENT_PARAM_CLASS(ORB_EdgeThreshold, int) - IMPLEMENT_PARAM_CLASS(ORB_firstLevel, int) - IMPLEMENT_PARAM_CLASS(ORB_WTA_K, int) - IMPLEMENT_PARAM_CLASS(ORB_PatchSize, int) - IMPLEMENT_PARAM_CLASS(ORB_BlurForDescriptor, bool) -} - -CV_ENUM(ORB_ScoreType, ORB::HARRIS_SCORE, ORB::FAST_SCORE) - -PARAM_TEST_CASE(ORB, ORB_FeaturesCount, ORB_ScaleFactor, ORB_LevelsCount, ORB_EdgeThreshold, - ORB_firstLevel, ORB_WTA_K, ORB_ScoreType, ORB_PatchSize, ORB_BlurForDescriptor) -{ - int nFeatures; - float scaleFactor; - int nLevels; - int edgeThreshold; - int firstLevel; - int WTA_K; - int scoreType; - int patchSize; - bool blurForDescriptor; - - virtual void SetUp() - { - nFeatures = GET_PARAM(0); - scaleFactor = GET_PARAM(1); - nLevels = GET_PARAM(2); - edgeThreshold = GET_PARAM(3); - firstLevel = GET_PARAM(4); - WTA_K = GET_PARAM(5); - scoreType = GET_PARAM(6); - patchSize = GET_PARAM(7); - blurForDescriptor = GET_PARAM(8); - } -}; - -OCL_TEST_P(ORB, Accuracy) -{ - cv::Mat image = readImage("gpu/perf/aloe.png", cv::IMREAD_GRAYSCALE); - ASSERT_FALSE(image.empty()); - - cv::Mat mask(image.size(), CV_8UC1, cv::Scalar::all(1)); - mask(cv::Range(0, image.rows / 2), cv::Range(0, image.cols / 2)).setTo(cv::Scalar::all(0)); - - cv::ocl::oclMat ocl_image = cv::ocl::oclMat(image); - cv::ocl::oclMat ocl_mask = cv::ocl::oclMat(mask); - - cv::ocl::ORB_OCL orb(nFeatures, scaleFactor, nLevels, edgeThreshold, firstLevel, WTA_K, scoreType, patchSize); - orb.blurForDescriptor = blurForDescriptor; - - std::vector keypoints; - cv::ocl::oclMat descriptors; - orb(ocl_image, ocl_mask, keypoints, descriptors); - - cv::ORB orb_gold(nFeatures, scaleFactor, nLevels, edgeThreshold, firstLevel, WTA_K, scoreType, patchSize); - - std::vector keypoints_gold; - cv::Mat descriptors_gold; - orb_gold(image, mask, keypoints_gold, descriptors_gold); - - cv::BFMatcher matcher(cv::NORM_HAMMING); - std::vector matches; - matcher.match(descriptors_gold, cv::Mat(descriptors), matches); - - int matchedCount = getMatchedPointsCount(keypoints_gold, keypoints, matches); - double matchedRatio = static_cast(matchedCount) / keypoints.size(); - - EXPECT_GT(matchedRatio, 0.35); -} - -INSTANTIATE_TEST_CASE_P(OCL_Features2D, ORB, testing::Combine( - testing::Values(ORB_FeaturesCount(1000)), - testing::Values(ORB_ScaleFactor(1.2f)), - testing::Values(ORB_LevelsCount(4), ORB_LevelsCount(8)), - testing::Values(ORB_EdgeThreshold(31)), - testing::Values(ORB_firstLevel(0), ORB_firstLevel(2)), - testing::Values(ORB_WTA_K(2), ORB_WTA_K(3), ORB_WTA_K(4)), - testing::Values(ORB_ScoreType(cv::ORB::HARRIS_SCORE)), - testing::Values(ORB_PatchSize(31), ORB_PatchSize(29)), - testing::Values(ORB_BlurForDescriptor(false), ORB_BlurForDescriptor(true)))); - -#endif diff --git a/modules/ocl/test/test_precomp.hpp b/modules/ocl/test/test_precomp.hpp deleted file mode 100644 index f1887db39..000000000 --- a/modules/ocl/test/test_precomp.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/*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. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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*/ - -#ifdef __GNUC__ -# pragma GCC diagnostic ignored "-Wmissing-declarations" -# if defined __clang__ || defined __APPLE__ -# pragma GCC diagnostic ignored "-Wmissing-prototypes" -# pragma GCC diagnostic ignored "-Wextra" -# endif -#endif - -#ifndef __OPENCV_TEST_PRECOMP_HPP__ -#define __OPENCV_TEST_PRECOMP_HPP__ - -#define CV_BUILD_OCL_MODULE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "opencv2/ts.hpp" -#include "opencv2/highgui.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/features2d.hpp" -#include "opencv2/video.hpp" -#include "opencv2/ocl.hpp" - -#include "utility.hpp" - -#include "opencv2/core/private.hpp" - -using namespace cvtest; - -#endif diff --git a/modules/ocl/test/test_pyramids.cpp b/modules/ocl/test/test_pyramids.cpp deleted file mode 100644 index 2d861b627..000000000 --- a/modules/ocl/test/test_pyramids.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////// -// -// 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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Yao Wang yao@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 "test_precomp.hpp" -#include - -#ifdef HAVE_OPENCL - -using namespace cv; -using namespace testing; -using namespace std; - -PARAM_TEST_CASE(PyrBase, MatDepth, Channels) -{ - int depth; - int channels; - - Mat dst_cpu; - ocl::oclMat gdst; - - virtual void SetUp() - { - depth = GET_PARAM(0); - channels = GET_PARAM(1); - } -}; - -/////////////////////// PyrDown ////////////////////////// - -typedef PyrBase PyrDown; - -OCL_TEST_P(PyrDown, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - Size size(MWIDTH, MHEIGHT); - Mat src = randomMat(size, CV_MAKETYPE(depth, channels), 0, 255); - ocl::oclMat gsrc(src); - - pyrDown(src, dst_cpu); - ocl::pyrDown(gsrc, gdst); - - EXPECT_MAT_NEAR(dst_cpu, Mat(gdst), depth == CV_32F ? 1e-4f : 1.0f); - } -} - -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, PyrDown, Combine( - Values(CV_8U, CV_16U, CV_16S, CV_32F), - Values(1, 3, 4))); - -/////////////////////// PyrUp ////////////////////////// - -typedef PyrBase PyrUp; - -OCL_TEST_P(PyrUp, Accuracy) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - Size size(MWIDTH, MHEIGHT); - Mat src = randomMat(size, CV_MAKETYPE(depth, channels), 0, 255); - ocl::oclMat gsrc(src); - - pyrUp(src, dst_cpu); - ocl::pyrUp(gsrc, gdst); - - EXPECT_MAT_NEAR(dst_cpu, Mat(gdst), (depth == CV_32F ? 1e-4f : 1.0)); - } -} - - -INSTANTIATE_TEST_CASE_P(OCL_ImgProc, PyrUp, Combine( - Values(CV_8U, CV_16U, CV_16S, CV_32F), - Values(1, 3, 4))); -#endif // HAVE_OPENCL diff --git a/modules/ocl/test/test_sort.cpp b/modules/ocl/test/test_sort.cpp deleted file mode 100644 index b25914968..000000000 --- a/modules/ocl/test/test_sort.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/*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 -// Peng Xiao, pengxiao@outlook.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 -#include -#include "test_precomp.hpp" - -using namespace std; -using namespace cvtest; -using namespace testing; -using namespace cv; - - -namespace -{ -IMPLEMENT_PARAM_CLASS(IsGreaterThan, bool) -IMPLEMENT_PARAM_CLASS(InputSize, int) -IMPLEMENT_PARAM_CLASS(SortMethod, int) - - -template -struct KV_CVTYPE{ static int toType() {return 0;} }; - -template<> struct KV_CVTYPE { static int toType() {return CV_32SC1;} }; -template<> struct KV_CVTYPE{ static int toType() {return CV_32FC1;} }; -template<> struct KV_CVTYPE{ static int toType() {return CV_32SC2;} }; -template<> struct KV_CVTYPE{ static int toType() {return CV_32FC2;} }; - -template -bool kvgreater(pair p1, pair p2) -{ - return p1.first > p2.first; -} - -template -bool kvless(pair p1, pair p2) -{ - return p1.first < p2.first; -} - -template -void toKVPair( - MatConstIterator_ kit, - MatConstIterator_ vit, - int vecSize, - vector >& kvres - ) -{ - kvres.clear(); - for(int i = 0; i < vecSize; i ++) - { - kvres.push_back(make_pair(*kit, *vit)); - ++kit; - ++vit; - } -} - -template -void kvquicksort(Mat& keys, Mat& vals, bool isGreater = false) -{ - vector > kvres; - toKVPair(keys.begin(), vals.begin(), keys.cols, kvres); - - if(isGreater) - { - std::sort(kvres.begin(), kvres.end(), kvgreater); - } - else - { - std::sort(kvres.begin(), kvres.end(), kvless); - } - key_type * kptr = keys.ptr(); - val_type * vptr = vals.ptr(); - for(int i = 0; i < keys.cols; i ++) - { - kptr[i] = kvres[i].first; - vptr[i] = kvres[i].second; - } -} - -class SortByKey_STL -{ -public: - static void sort(cv::Mat&, cv::Mat&, bool is_gt); -private: - typedef void (*quick_sorter)(cv::Mat&, cv::Mat&, bool); - SortByKey_STL(); - quick_sorter quick_sorters[CV_64FC4][CV_64FC4]; - static SortByKey_STL instance; -}; - -SortByKey_STL SortByKey_STL::instance = SortByKey_STL(); - -SortByKey_STL::SortByKey_STL() -{ - memset(instance.quick_sorters, 0, sizeof(quick_sorters)); -#define NEW_SORTER(KT, VT) \ - instance.quick_sorters[KV_CVTYPE::toType()][KV_CVTYPE::toType()] = kvquicksort; - - NEW_SORTER(int, int); - NEW_SORTER(int, Vec2i); - NEW_SORTER(int, float); - NEW_SORTER(int, Vec2f); - - NEW_SORTER(float, int); - NEW_SORTER(float, Vec2i); - NEW_SORTER(float, float); - NEW_SORTER(float, Vec2f); -#undef NEW_SORTER -} - -void SortByKey_STL::sort(cv::Mat& keys, cv::Mat& vals, bool is_gt) -{ - instance.quick_sorters[keys.type()][vals.type()](keys, vals, is_gt); -} - -bool checkUnstableSorterResult(const Mat& gkeys_, const Mat& gvals_, - const Mat& /*dkeys_*/, const Mat& dvals_) -{ - int cn_val = gvals_.channels(); - int count = gkeys_.cols; - - //for convenience we convert depth to float and channels to 1 - Mat gkeys, gvals, dkeys, dvals; - gkeys_.reshape(1).convertTo(gkeys, CV_32F); - gvals_.reshape(1).convertTo(gvals, CV_32F); - //dkeys_.reshape(1).convertTo(dkeys, CV_32F); - dvals_.reshape(1).convertTo(dvals, CV_32F); - float * gkptr = gkeys.ptr(); - float * gvptr = gvals.ptr(); - //float * dkptr = dkeys.ptr(); - float * dvptr = dvals.ptr(); - - for(int i = 0; i < count - 1; ++i) - { - int iden_count = 0; - // firstly calculate the number of identical keys - while(gkptr[i + iden_count] == gkptr[i + 1 + iden_count]) - { - ++ iden_count; - } - - // sort dv and gv - int num_of_val = (iden_count + 1) * cn_val; - std::sort(gvptr + i * cn_val, gvptr + i * cn_val + num_of_val); - std::sort(dvptr + i * cn_val, dvptr + i * cn_val + num_of_val); - - // then check if [i, i + iden_count) is the same - for(int j = 0; j < num_of_val; ++j) - { - if(gvptr[i + j] != dvptr[i + j]) - { - return false; - } - } - i += iden_count; - } - return true; -} -} - -#define INPUT_SIZES Values(InputSize(0x10), InputSize(0x100), InputSize(0x10000)) //2^4, 2^8, 2^16 -#define KEY_TYPES Values(MatType(CV_32SC1), MatType(CV_32FC1)) -#define VAL_TYPES Values(MatType(CV_32SC1), MatType(CV_32SC2), MatType(CV_32FC1), MatType(CV_32FC2)) -#define SORT_METHODS Values(SortMethod(cv::ocl::SORT_BITONIC),SortMethod(cv::ocl::SORT_MERGE),SortMethod(cv::ocl::SORT_RADIX)/*,SortMethod(cv::ocl::SORT_SELECTION)*/) -#define F_OR_T Values(IsGreaterThan(false), IsGreaterThan(true)) - -PARAM_TEST_CASE(SortByKey, InputSize, MatType, MatType, SortMethod, IsGreaterThan) -{ - InputSize input_size; - MatType key_type, val_type; - SortMethod method; - IsGreaterThan is_gt; - - Mat mat_key, mat_val; - virtual void SetUp() - { - input_size = GET_PARAM(0); - key_type = GET_PARAM(1); - val_type = GET_PARAM(2); - method = GET_PARAM(3); - is_gt = GET_PARAM(4); - - using namespace cv; - // fill key and val - mat_key = randomMat(Size(input_size, 1), key_type, INT_MIN, INT_MAX); - mat_val = randomMat(Size(input_size, 1), val_type, INT_MIN, INT_MAX); - } -}; - -OCL_TEST_P(SortByKey, Accuracy) -{ - using namespace cv; - ocl::oclMat oclmat_key(mat_key); - ocl::oclMat oclmat_val(mat_val); - - ocl::sortByKey(oclmat_key, oclmat_val, method, is_gt); - SortByKey_STL::sort(mat_key, mat_val, is_gt); - - EXPECT_MAT_NEAR(mat_key, oclmat_key, 0.0); - EXPECT_TRUE(checkUnstableSorterResult(mat_key, mat_val, oclmat_key, oclmat_val)); -} -INSTANTIATE_TEST_CASE_P(OCL_SORT, SortByKey, Combine(INPUT_SIZES, KEY_TYPES, VAL_TYPES, SORT_METHODS, F_OR_T)); diff --git a/modules/ocl/test/test_split_merge.cpp b/modules/ocl/test/test_split_merge.cpp deleted file mode 100644 index b21fedd77..000000000 --- a/modules/ocl/test/test_split_merge.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Jia Haipeng, jiahaipeng95@gmail.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 "test_precomp.hpp" - -#ifdef HAVE_OPENCL - -using namespace cvtest; -using namespace testing; -using namespace std; - -#define MAX_CHANNELS 4 - -PARAM_TEST_CASE(MergeTestBase, MatDepth, Channels, bool) -{ - int type; - int channels; - bool use_roi; - - //src mat - cv::Mat mat[MAX_CHANNELS]; - //dst mat - cv::Mat dst; - - // set up roi - int roicols, roirows; - int srcx[MAX_CHANNELS]; - int srcy[MAX_CHANNELS]; - int dstx, dsty; - - //src mat with roi - cv::Mat mat_roi[MAX_CHANNELS]; - - //dst mat with roi - cv::Mat dst_roi; - - //ocl dst mat for testing - cv::ocl::oclMat gdst_whole; - - //ocl mat with roi - cv::ocl::oclMat gmat[MAX_CHANNELS]; - cv::ocl::oclMat gdst; - - virtual void SetUp() - { - type = GET_PARAM(0); - channels = GET_PARAM(1); - use_roi = GET_PARAM(2); - - cv::Size size(MWIDTH, MHEIGHT); - - for (int i = 0; i < channels; ++i) - mat[i] = randomMat(size, CV_MAKETYPE(type, 1), 5, 16, false); - dst = randomMat(size, CV_MAKETYPE(type, channels), 5, 16, false); - } - - void random_roi() - { - if (use_roi) - { - //randomize ROI - roicols = rng.uniform(1, mat[0].cols); - roirows = rng.uniform(1, mat[0].rows); - - for (int i = 0; i < channels; ++i) - { - srcx[i] = rng.uniform(0, mat[i].cols - roicols); - srcy[i] = rng.uniform(0, mat[i].rows - roirows); - } - - dstx = rng.uniform(0, dst.cols - roicols); - dsty = rng.uniform(0, dst.rows - roirows); - } - else - { - roicols = mat[0].cols; - roirows = mat[0].rows; - for (int i = 0; i < channels; ++i) - srcx[i] = srcy[i] = 0; - - dstx = dsty = 0; - } - - for (int i = 0; i < channels; ++i) - mat_roi[i] = mat[i](Rect(srcx[i], srcy[i], roicols, roirows)); - - dst_roi = dst(Rect(dstx, dsty, roicols, roirows)); - - gdst_whole = dst; - gdst = gdst_whole(Rect(dstx, dsty, roicols, roirows)); - - for (int i = 0; i < channels; ++i) - gmat[i] = mat_roi[i]; - } -}; - -struct Merge : MergeTestBase {}; - -OCL_TEST_P(Merge, Accuracy) -{ - for(int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::merge(mat_roi, channels, dst_roi); - cv::ocl::merge(gmat, channels, gdst); - - EXPECT_MAT_NEAR(dst, Mat(gdst_whole), 0.0); - } -} - -PARAM_TEST_CASE(SplitTestBase, MatType, int, bool) -{ - int type; - int channels; - bool use_roi; - - cv::Mat src, src_roi; - cv::Mat dst[MAX_CHANNELS], dst_roi[MAX_CHANNELS]; - - cv::ocl::oclMat gsrc_whole, gsrc_roi; - cv::ocl::oclMat gdst_whole[MAX_CHANNELS], gdst_roi[MAX_CHANNELS]; - - virtual void SetUp() - { - type = GET_PARAM(0); - channels = GET_PARAM(1); - use_roi = GET_PARAM(2); - } - - void random_roi() - { - Size roiSize = randomSize(1, MAX_VALUE); - Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, CV_MAKETYPE(type, channels), 0, 256); - generateOclMat(gsrc_whole, gsrc_roi, src, roiSize, srcBorder); - - for (int i = 0; i < channels; ++i) - { - Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(dst[i], dst_roi[i], roiSize, dstBorder, CV_MAKETYPE(type, 1), 5, 16); - generateOclMat(gdst_whole[i], gdst_roi[i], dst[i], roiSize, dstBorder); - } - } -}; - -struct Split : SplitTestBase {}; - -#ifdef ANDROID -// NOTE: The test fail on Android is the top of the iceberg only -// The real fail reason is memory access vialation somewhere else -OCL_TEST_P(Split, DISABLED_Accuracy) -#else -OCL_TEST_P(Split, Accuracy) -#endif -{ - for(int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::split(src_roi, dst_roi); - cv::ocl::split(gsrc_roi, gdst_roi); - - for (int i = 0; i < channels; ++i) - { - EXPECT_MAT_NEAR(dst[i], gdst_whole[i], 0.0); - EXPECT_MAT_NEAR(dst_roi[i], gdst_roi[i], 0.0); - } - } -} - - -INSTANTIATE_TEST_CASE_P(SplitMerge, Merge, Combine( - Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F), Values(1, 2, 3, 4), Bool())); - - -INSTANTIATE_TEST_CASE_P(SplitMerge, Split , Combine( - Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F), Values(1, 2, 3, 4), Bool())); - - -#endif // HAVE_OPENCL diff --git a/modules/ocl/test/test_warp.cpp b/modules/ocl/test/test_warp.cpp deleted file mode 100644 index 85f33754e..000000000 --- a/modules/ocl/test/test_warp.cpp +++ /dev/null @@ -1,494 +0,0 @@ -/*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, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// Jia Haipeng, jiahaipeng95@gmail.com -// Shengen Yan, yanshengen@gmail.com -// Jiang Liyuan, lyuan001.good@163.com -// Rock Li, Rock.Li@amd.com -// Wu Zailong, bullet@yeah.net -// Xu Pang, pangxu010@163.com -// Sen Liu, swjtuls1987@126.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 "test_precomp.hpp" - -#ifdef HAVE_OPENCL - -using namespace cv; -using namespace testing; -using namespace std; - -static MatType noType = -1; - -///////////////////////////////////////////////////////////////////////////////////////////////// -// warpAffine & warpPerspective - -PARAM_TEST_CASE(WarpTestBase, MatType, Interpolation, bool, bool) -{ - int type, interpolation; - Size dsize; - bool useRoi, mapInverse; - - Mat src, dst_whole, src_roi, dst_roi; - ocl::oclMat gsrc_whole, gsrc_roi, gdst_whole, gdst_roi; - - virtual void SetUp() - { - type = GET_PARAM(0); - interpolation = GET_PARAM(1); - mapInverse = GET_PARAM(2); - useRoi = GET_PARAM(3); - - if (mapInverse) - interpolation |= WARP_INVERSE_MAP; - } - - void random_roi() - { - dsize = randomSize(1, MAX_VALUE); - - Size roiSize = randomSize(1, MAX_VALUE); - Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE); - - Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(dst_whole, dst_roi, dsize, dstBorder, type, -MAX_VALUE, MAX_VALUE); - - generateOclMat(gsrc_whole, gsrc_roi, src, roiSize, srcBorder); - generateOclMat(gdst_whole, gdst_roi, dst_whole, dsize, dstBorder); - } - - void Near(double threshold = 0.0) - { - Mat whole, roi; - gdst_whole.download(whole); - gdst_roi.download(roi); - - EXPECT_MAT_NEAR(dst_whole, whole, threshold); - EXPECT_MAT_NEAR(dst_roi, roi, threshold); - } -}; - -/////warpAffine - -typedef WarpTestBase WarpAffine; - -OCL_TEST_P(WarpAffine, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - Mat M = getRotationMatrix2D(Point2f(src_roi.cols / 2.0f, src_roi.rows / 2.0f), - rng.uniform(-180.f, 180.f), rng.uniform(0.4f, 2.0f)); - - warpAffine(src_roi, dst_roi, M, dsize, interpolation); - ocl::warpAffine(gsrc_roi, gdst_roi, M, dsize, interpolation); - - Near(1.0); - } -} - -// warpPerspective - -typedef WarpTestBase WarpPerspective; - -OCL_TEST_P(WarpPerspective, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - float cols = static_cast(src_roi.cols), rows = static_cast(src_roi.rows); - float cols2 = cols / 2.0f, rows2 = rows / 2.0f; - Point2f sp[] = { Point2f(0.0f, 0.0f), Point2f(cols, 0.0f), Point2f(0.0f, rows), Point2f(cols, rows) }; - Point2f dp[] = { Point2f(rng.uniform(0.0f, cols2), rng.uniform(0.0f, rows2)), - Point2f(rng.uniform(cols2, cols), rng.uniform(0.0f, rows2)), - Point2f(rng.uniform(0.0f, cols2), rng.uniform(rows2, rows)), - Point2f(rng.uniform(cols2, cols), rng.uniform(rows2, rows)) }; - Mat M = getPerspectiveTransform(sp, dp); - - warpPerspective(src_roi, dst_roi, M, dsize, interpolation); - ocl::warpPerspective(gsrc_roi, gdst_roi, M, dsize, interpolation); - - Near(1.0); - } -} - -// buildWarpPerspectiveMaps - -PARAM_TEST_CASE(BuildWarpPerspectiveMaps, bool, bool) -{ - bool useRoi, mapInverse; - Size dsize; - - Mat xmap_whole, ymap_whole, xmap_roi, ymap_roi; - ocl::oclMat gxmap_whole, gymap_whole, gxmap_roi, gymap_roi; - - void SetUp() - { - mapInverse = GET_PARAM(0); - useRoi = GET_PARAM(1); - } - - void random_roi() - { - dsize = randomSize(1, MAX_VALUE); - - Border xmapBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(xmap_whole, xmap_roi, dsize, xmapBorder, CV_32FC1, -MAX_VALUE, MAX_VALUE); - - Border ymapBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(ymap_whole, ymap_roi, dsize, ymapBorder, CV_32FC1, -MAX_VALUE, MAX_VALUE); - - generateOclMat(gxmap_whole, gxmap_roi, xmap_whole, dsize, xmapBorder); - generateOclMat(gymap_whole, gymap_roi, ymap_whole, dsize, ymapBorder); - } - - void Near(double threshold = 0.0) - { - Mat whole, roi; - gxmap_whole.download(whole); - gxmap_roi.download(roi); - - EXPECT_MAT_NEAR(xmap_whole, whole, threshold); - EXPECT_MAT_NEAR(xmap_roi, roi, threshold); - } - - void Near1(double threshold = 0.0) - { - Mat whole, roi; - gymap_whole.download(whole); - gymap_roi.download(roi); - - EXPECT_MAT_NEAR(ymap_whole, whole, threshold); - EXPECT_MAT_NEAR(ymap_roi, roi, threshold); - } -}; - -static void buildWarpPerspectiveMaps(const Mat &M, bool inverse, Size dsize, Mat &xmap, Mat &ymap) -{ - CV_Assert(M.rows == 3 && M.cols == 3); - CV_Assert(dsize.area() > 0); - - xmap.create(dsize, CV_32FC1); - ymap.create(dsize, CV_32FC1); - - float coeffs[3 * 3]; - Mat coeffsMat(3, 3, CV_32F, (void *)coeffs); - - if (inverse) - M.convertTo(coeffsMat, coeffsMat.type()); - else - { - cv::Mat iM; - invert(M, iM); - iM.convertTo(coeffsMat, coeffsMat.type()); - } - - for (int y = 0; y < dsize.height; ++y) - { - float * const xmap_ptr = xmap.ptr(y); - float * const ymap_ptr = ymap.ptr(y); - - for (int x = 0; x < dsize.width; ++x) - { - float coeff = 1.0f / (x * coeffs[6] + y * coeffs[7] + coeffs[8]); - xmap_ptr[x] = (x * coeffs[0] + y * coeffs[1] + coeffs[2]) * coeff; - ymap_ptr[x] = (x * coeffs[3] + y * coeffs[4] + coeffs[5]) * coeff; - } - } -} - -OCL_TEST_P(BuildWarpPerspectiveMaps, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - float cols = static_cast(MAX_VALUE), rows = static_cast(MAX_VALUE); - float cols2 = cols / 2.0f, rows2 = rows / 2.0f; - Point2f sp[] = { Point2f(0.0f, 0.0f), Point2f(cols, 0.0f), Point2f(0.0f, rows), Point2f(cols, rows) }; - Point2f dp[] = { Point2f(rng.uniform(0.0f, cols2), rng.uniform(0.0f, rows2)), - Point2f(rng.uniform(cols2, cols), rng.uniform(0.0f, rows2)), - Point2f(rng.uniform(0.0f, cols2), rng.uniform(rows2, rows)), - Point2f(rng.uniform(cols2, cols), rng.uniform(rows2, rows)) }; - Mat M = getPerspectiveTransform(sp, dp); - - buildWarpPerspectiveMaps(M, mapInverse, dsize, xmap_roi, ymap_roi); - ocl::buildWarpPerspectiveMaps(M, mapInverse, dsize, gxmap_roi, gymap_roi); - - Near(5e-3); - Near1(5e-3); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////// -// remap - -PARAM_TEST_CASE(Remap, MatDepth, Channels, pair, Border, bool) -{ - int srcType, map1Type, map2Type; - int borderType; - bool useRoi; - - Scalar val; - - Mat src, src_roi; - Mat dst, dst_roi; - Mat map1, map1_roi; - Mat map2, map2_roi; - - // ocl mat with roi - ocl::oclMat gsrc, gsrc_roi; - ocl::oclMat gdst, gdst_roi; - ocl::oclMat gmap1, gmap1_roi; - ocl::oclMat gmap2, gmap2_roi; - - virtual void SetUp() - { - srcType = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1)); - map1Type = GET_PARAM(2).first; - map2Type = GET_PARAM(2).second; - borderType = GET_PARAM(3); - useRoi = GET_PARAM(4); - } - - void random_roi() - { - val = randomScalar(-MAX_VALUE, MAX_VALUE); - Size srcROISize = randomSize(1, MAX_VALUE); - Size dstROISize = randomSize(1, MAX_VALUE); - - Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, srcROISize, srcBorder, srcType, 5, 256); - - Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(dst, dst_roi, dstROISize, dstBorder, srcType, -MAX_VALUE, MAX_VALUE); - - int mapMaxValue = MAX_VALUE << 2; - Border map1Border = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(map1, map1_roi, dstROISize, map1Border, map1Type, -mapMaxValue, mapMaxValue); - - Border map2Border = randomBorder(0, useRoi ? MAX_VALUE : 0); - if (map2Type != noType) - { - int mapMinValue = -mapMaxValue; - if (map2Type == CV_16UC1 || map2Type == CV_16SC1) - mapMinValue = 0, mapMaxValue = INTER_TAB_SIZE2; - randomSubMat(map2, map2_roi, dstROISize, map2Border, map2Type, mapMinValue, mapMaxValue); - } - - generateOclMat(gsrc, gsrc_roi, src, srcROISize, srcBorder); - generateOclMat(gdst, gdst_roi, dst, dstROISize, dstBorder); - generateOclMat(gmap1, gmap1_roi, map1, dstROISize, map1Border); - if (noType != map2Type) - generateOclMat(gmap2, gmap2_roi, map2, dstROISize, map2Border); - } - - void Near(double threshold = 0.0) - { - Mat whole, roi; - gdst.download(whole); - gdst_roi.download(roi); - - EXPECT_MAT_NEAR(dst, whole, threshold); - EXPECT_MAT_NEAR(dst_roi, roi, threshold); - } -}; - -typedef Remap Remap_INTER_NEAREST; - -OCL_TEST_P(Remap_INTER_NEAREST, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - remap(src_roi, dst_roi, map1_roi, map2_roi, INTER_NEAREST, borderType, val); - ocl::remap(gsrc_roi, gdst_roi, gmap1_roi, gmap2_roi, INTER_NEAREST, borderType, val); - - Near(1.0); - } -} - -typedef Remap Remap_INTER_LINEAR; - -OCL_TEST_P(Remap_INTER_LINEAR, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::remap(src_roi, dst_roi, map1_roi, map2_roi, INTER_LINEAR, borderType, val); - ocl::remap(gsrc_roi, gdst_roi, gmap1_roi, gmap2_roi, INTER_LINEAR, borderType, val); - - Near(2.0); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////// -// resize - -PARAM_TEST_CASE(Resize, MatType, double, double, Interpolation, bool) -{ - int type, interpolation; - double fx, fy; - bool useRoi; - - Mat src, dst_whole, src_roi, dst_roi; - ocl::oclMat gsrc_whole, gsrc_roi, gdst_whole, gdst_roi; - - virtual void SetUp() - { - type = GET_PARAM(0); - fx = GET_PARAM(1); - fy = GET_PARAM(2); - interpolation = GET_PARAM(3); - useRoi = GET_PARAM(4); - } - - void random_roi() - { - CV_Assert(fx > 0 && fy > 0); - - Size srcRoiSize = randomSize(1, MAX_VALUE), dstRoiSize; - dstRoiSize.width = cvRound(srcRoiSize.width * fx); - dstRoiSize.height = cvRound(srcRoiSize.height * fy); - - if (dstRoiSize.area() == 0) - return random_roi(); - - Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, srcRoiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE); - - Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(dst_whole, dst_roi, dstRoiSize, dstBorder, type, -MAX_VALUE, MAX_VALUE); - - generateOclMat(gsrc_whole, gsrc_roi, src, srcRoiSize, srcBorder); - generateOclMat(gdst_whole, gdst_roi, dst_whole, dstRoiSize, dstBorder); - } - - void Near(double threshold = 0.0) - { - Mat whole, roi; - gdst_whole.download(whole); - gdst_roi.download(roi); - - EXPECT_MAT_NEAR(dst_whole, whole, threshold); - EXPECT_MAT_NEAR(dst_roi, roi, threshold); - } -}; - -OCL_TEST_P(Resize, Mat) -{ - for (int j = 0; j < LOOP_TIMES; j++) - { - random_roi(); - - cv::resize(src_roi, dst_roi, Size(), fx, fy, interpolation); - ocl::resize(gsrc_roi, gdst_roi, Size(), fx, fy, interpolation); - - Near(1.0); - } -} - -///////////////////////////////////////////////////////////////////////////////////// - -INSTANTIATE_TEST_CASE_P(ImgprocWarp, WarpAffine, Combine( - Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4), - Values((Interpolation)INTER_NEAREST, (Interpolation)INTER_LINEAR, (Interpolation)INTER_CUBIC), - Bool(), - Bool())); - -INSTANTIATE_TEST_CASE_P(ImgprocWarp, WarpPerspective, Combine( - Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4), - Values((Interpolation)INTER_NEAREST, (Interpolation)INTER_LINEAR, (Interpolation)INTER_CUBIC), - Bool(), - Bool())); - -INSTANTIATE_TEST_CASE_P(ImgprocWarp, BuildWarpPerspectiveMaps, Combine(Bool(), Bool())); - -INSTANTIATE_TEST_CASE_P(ImgprocWarp, Remap_INTER_LINEAR, Combine( - Values(CV_8U, CV_16U, CV_16S, CV_32F, CV_64F), - Values(1, 2, 3, 4), - Values(pair((MatType)CV_32FC1, (MatType)CV_32FC1), - pair((MatType)CV_16SC2, (MatType)CV_16UC1), - pair((MatType)CV_32FC2, noType)), - Values((Border)BORDER_CONSTANT, - (Border)BORDER_REPLICATE, - (Border)BORDER_WRAP, - (Border)BORDER_REFLECT, - (Border)BORDER_REFLECT_101), - Bool())); - -INSTANTIATE_TEST_CASE_P(ImgprocWarp, Remap_INTER_NEAREST, Combine( - Values(CV_8U, CV_16U, CV_16S, CV_32F, CV_64F), - Values(1, 2, 3, 4), - Values(pair((MatType)CV_32FC1, (MatType)CV_32FC1), - pair((MatType)CV_32FC2, noType), - pair((MatType)CV_16SC2, (MatType)CV_16UC1), - pair((MatType)CV_16SC2, noType)), - Values((Border)BORDER_CONSTANT, - (Border)BORDER_REPLICATE, - (Border)BORDER_WRAP, - (Border)BORDER_REFLECT, - (Border)BORDER_REFLECT_101), - Bool())); - -INSTANTIATE_TEST_CASE_P(ImgprocWarpResize, Resize, Combine( - Values((MatType)CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4), - Values(0.7, 0.4, 2.0), - Values(0.3, 0.6, 2.0), - Values((Interpolation)INTER_NEAREST, (Interpolation)INTER_LINEAR), - Bool())); - -INSTANTIATE_TEST_CASE_P(ImgprocWarpResizeArea, Resize, Combine( - Values((MatType)CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4), - Values(0.7, 0.4, 0.5), - Values(0.3, 0.6, 0.5), - Values((Interpolation)INTER_AREA), - Bool())); - -#endif // HAVE_OPENCL diff --git a/modules/ocl/test/utility.cpp b/modules/ocl/test/utility.cpp deleted file mode 100644 index 3195019ca..000000000 --- a/modules/ocl/test/utility.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/*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. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 "test_precomp.hpp" -#define VARNAME(A) #A -using namespace std; -using namespace cv; -using namespace cvtest; - -namespace cvtest { -//std::string generateVarList(int first,...) -//{ -// vector varname; -// -// va_list argp; -// string s; -// stringstream ss; -// va_start(argp,first); -// int i=first; -// while(i!=-1) -// { -// ss< types(int depth_start, int depth_end, int cn_start, int cn_end) -{ - vector v; - - v.reserve((depth_end - depth_start + 1) * (cn_end - cn_start + 1)); - - for (int depth = depth_start; depth <= depth_end; ++depth) - { - for (int cn = cn_start; cn <= cn_end; ++cn) - { - v.push_back(CV_MAKETYPE(depth, cn)); - } - } - - return v; -} - -const vector &all_types() -{ - static vector v = types(CV_8U, CV_64F, 1, 4); - - return v; -} - -Mat readImage(const string &fileName, int flags) -{ - return imread(string(cvtest::TS::ptr()->get_data_path()) + fileName, flags); -} - -Mat readImageType(const string &fname, int type) -{ - Mat src = readImage(fname, CV_MAT_CN(type) == 1 ? IMREAD_GRAYSCALE : IMREAD_COLOR); - if (CV_MAT_CN(type) == 4) - { - Mat temp; - cvtColor(src, temp, cv::COLOR_BGR2BGRA); - swap(src, temp); - } - src.convertTo(src, CV_MAT_DEPTH(type)); - return src; -} - -double checkNorm(const Mat &m) -{ - return norm(m, NORM_INF); -} - -double checkNorm(const Mat &m1, const Mat &m2) -{ - return norm(m1, m2, NORM_INF); -} - -double checkSimilarity(const Mat &m1, const Mat &m2) -{ - Mat diff; - matchTemplate(m1, m2, diff, TM_CCORR_NORMED); - return std::abs(diff.at(0, 0) - 1.f); -} - -/* -void cv::ocl::PrintTo(const DeviceInfo& info, ostream* os) -{ - (*os) << info.name(); -} -*/ - -void PrintTo(const Inverse &inverse, std::ostream *os) -{ - if (inverse) - (*os) << "inverse"; - else - (*os) << "direct"; -} - -double checkRectSimilarity(Size sz, std::vector& ob1, std::vector& ob2) -{ - double final_test_result = 0.0; - size_t sz1 = ob1.size(); - size_t sz2 = ob2.size(); - - if(sz1 != sz2) - { - return sz1 > sz2 ? (double)(sz1 - sz2) : (double)(sz2 - sz1); - } - else - { - if(sz1==0 && sz2==0) - return 0; - cv::Mat cpu_result(sz, CV_8UC1); - cpu_result.setTo(0); - - for(vector::const_iterator r = ob1.begin(); r != ob1.end(); r++) - { - cv::Mat cpu_result_roi(cpu_result, *r); - cpu_result_roi.setTo(1); - cpu_result.copyTo(cpu_result); - } - int cpu_area = cv::countNonZero(cpu_result > 0); - - cv::Mat gpu_result(sz, CV_8UC1); - gpu_result.setTo(0); - for(vector::const_iterator r2 = ob2.begin(); r2 != ob2.end(); r2++) - { - cv::Mat gpu_result_roi(gpu_result, *r2); - gpu_result_roi.setTo(1); - gpu_result.copyTo(gpu_result); - } - - cv::Mat result_; - multiply(cpu_result, gpu_result, result_); - int result = cv::countNonZero(result_ > 0); - if(cpu_area!=0 && result!=0) - final_test_result = 1.0 - (double)result/(double)cpu_area; - else if(cpu_area==0 && result!=0) - final_test_result = -1; - } - return final_test_result; -} - -void showDiff(const Mat& src, const Mat& gold, const Mat& actual, double eps, bool alwaysShow) -{ - Mat diff, diff_thresh; - absdiff(gold, actual, diff); - diff.convertTo(diff, CV_32F); - threshold(diff, diff_thresh, eps, 255.0, cv::THRESH_BINARY); - - if (alwaysShow || cv::countNonZero(diff_thresh.reshape(1)) > 0) - { -#if 0 - std::cout << "Src: " << std::endl << src << std::endl; - std::cout << "Reference: " << std::endl << gold << std::endl; - std::cout << "OpenCL: " << std::endl << actual << std::endl; -#endif - - namedWindow("src", WINDOW_NORMAL); - namedWindow("gold", WINDOW_NORMAL); - namedWindow("actual", WINDOW_NORMAL); - namedWindow("diff", WINDOW_NORMAL); - - imshow("src", src); - imshow("gold", gold); - imshow("actual", actual); - imshow("diff", diff); - - waitKey(); - } -} - -namespace -{ - bool keyPointsEquals(const cv::KeyPoint& p1, const cv::KeyPoint& p2) - { - const double maxPtDif = 1.0; - const double maxSizeDif = 1.0; - const double maxAngleDif = 2.0; - const double maxResponseDif = 0.1; - - double dist = cv::norm(p1.pt - p2.pt); - - if (dist < maxPtDif && - fabs(p1.size - p2.size) < maxSizeDif && - abs(p1.angle - p2.angle) < maxAngleDif && - abs(p1.response - p2.response) < maxResponseDif && - p1.octave == p2.octave && - p1.class_id == p2.class_id) - { - return true; - } - - return false; - } - - struct KeyPointLess : std::binary_function - { - bool operator()(const cv::KeyPoint& kp1, const cv::KeyPoint& kp2) const - { - return kp1.pt.y < kp2.pt.y || (kp1.pt.y == kp2.pt.y && kp1.pt.x < kp2.pt.x); - } - }; -} - -testing::AssertionResult assertKeyPointsEquals(const char* gold_expr, const char* actual_expr, std::vector& gold, std::vector& actual) -{ - if (gold.size() != actual.size()) - { - return testing::AssertionFailure() << "KeyPoints size mistmach\n" - << "\"" << gold_expr << "\" : " << gold.size() << "\n" - << "\"" << actual_expr << "\" : " << actual.size(); - } - - std::sort(actual.begin(), actual.end(), KeyPointLess()); - std::sort(gold.begin(), gold.end(), KeyPointLess()); - - for (size_t i = 0; i < gold.size(); ++i) - { - const cv::KeyPoint& p1 = gold[i]; - const cv::KeyPoint& p2 = actual[i]; - - if (!keyPointsEquals(p1, p2)) - { - return testing::AssertionFailure() << "KeyPoints differ at " << i << "\n" - << "\"" << gold_expr << "\" vs \"" << actual_expr << "\" : \n" - << "pt : " << testing::PrintToString(p1.pt) << " vs " << testing::PrintToString(p2.pt) << "\n" - << "size : " << p1.size << " vs " << p2.size << "\n" - << "angle : " << p1.angle << " vs " << p2.angle << "\n" - << "response : " << p1.response << " vs " << p2.response << "\n" - << "octave : " << p1.octave << " vs " << p2.octave << "\n" - << "class_id : " << p1.class_id << " vs " << p2.class_id; - } - } - - return ::testing::AssertionSuccess(); -} - -int getMatchedPointsCount(std::vector& gold, std::vector& actual) -{ - std::sort(actual.begin(), actual.end(), KeyPointLess()); - std::sort(gold.begin(), gold.end(), KeyPointLess()); - - int validCount = 0; - - size_t sz = std::min(gold.size(), actual.size()); - for (size_t i = 0; i < sz; ++i) - { - const cv::KeyPoint& p1 = gold[i]; - const cv::KeyPoint& p2 = actual[i]; - - if (keyPointsEquals(p1, p2)) - ++validCount; - } - - return validCount; -} - -int getMatchedPointsCount(const std::vector& keypoints1, const std::vector& keypoints2, const std::vector& matches) -{ - int validCount = 0; - - for (size_t i = 0; i < matches.size(); ++i) - { - const cv::DMatch& m = matches[i]; - - const cv::KeyPoint& p1 = keypoints1[m.queryIdx]; - const cv::KeyPoint& p2 = keypoints2[m.trainIdx]; - - if (keyPointsEquals(p1, p2)) - ++validCount; - } - - return validCount; -} - -} // namespace cvtest diff --git a/modules/ocl/test/utility.hpp b/modules/ocl/test/utility.hpp deleted file mode 100644 index 4ecc9f0ac..000000000 --- a/modules/ocl/test/utility.hpp +++ /dev/null @@ -1,328 +0,0 @@ -/*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. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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_TEST_UTILITY_HPP__ -#define __OPENCV_TEST_UTILITY_HPP__ -#include "opencv2/core.hpp" - - -extern int LOOP_TIMES; - -#define MWIDTH 256 -#define MHEIGHT 256 - -#define MIN_VALUE 171 -#define MAX_VALUE 357 - -namespace cvtest { - -testing::AssertionResult assertKeyPointsEquals(const char* gold_expr, const char* actual_expr, std::vector& gold, std::vector& actual); -#define ASSERT_KEYPOINTS_EQ(gold, actual) EXPECT_PRED_FORMAT2(assertKeyPointsEquals, gold, actual) -CV_EXPORTS int getMatchedPointsCount(std::vector& gold, std::vector& actual); -CV_EXPORTS int getMatchedPointsCount(const std::vector& keypoints1, const std::vector& keypoints2, const std::vector& matches); - -void showDiff(const Mat& src, const Mat& gold, const Mat& actual, double eps, bool alwaysShow = false); - -cv::ocl::oclMat createMat_ocl(cv::RNG& rng, Size size, int type, bool useRoi); -cv::ocl::oclMat loadMat_ocl(cv::RNG& rng, const Mat& m, bool useRoi); - -// This function test if gpu_rst matches cpu_rst. -// If the two vectors are not equal, it will return the difference in vector size -// Else it will return (total diff of each cpu and gpu rects covered pixels)/(total cpu rects covered pixels) -// The smaller, the better matched -double checkRectSimilarity(cv::Size sz, std::vector& ob1, std::vector& ob2); - - -//! read image from testdata folder. -cv::Mat readImage(const std::string &fileName, int flags = cv::IMREAD_COLOR); -cv::Mat readImageType(const std::string &fname, int type); - -double checkNorm(const cv::Mat &m); -double checkNorm(const cv::Mat &m1, const cv::Mat &m2); -double checkSimilarity(const cv::Mat &m1, const cv::Mat &m2); - -inline double checkNormRelative(const Mat &m1, const Mat &m2) -{ - return cv::norm(m1, m2, cv::NORM_INF) / - std::max((double)std::numeric_limits::epsilon(), - (double)std::max(cv::norm(m1, cv::NORM_INF), norm(m2, cv::NORM_INF))); -} - -#define EXPECT_MAT_NORM(mat, eps) \ -{ \ - EXPECT_LE(checkNorm(cv::Mat(mat)), eps) \ -} - -#define EXPECT_MAT_NEAR(mat1, mat2, eps) \ -{ \ - ASSERT_EQ(mat1.type(), mat2.type()); \ - ASSERT_EQ(mat1.size(), mat2.size()); \ - EXPECT_LE(checkNorm(cv::Mat(mat1), cv::Mat(mat2)), eps) \ - << cv::format("Size: %d x %d", mat1.cols, mat1.rows) << std::endl; \ -} - -#define EXPECT_MAT_NEAR_RELATIVE(mat1, mat2, eps) \ -{ \ - ASSERT_EQ(mat1.type(), mat2.type()); \ - ASSERT_EQ(mat1.size(), mat2.size()); \ - EXPECT_LE(checkNormRelative(cv::Mat(mat1), cv::Mat(mat2)), eps) \ - << cv::format("Size: %d x %d", mat1.cols, mat1.rows) << std::endl; \ -} - -#define EXPECT_MAT_SIMILAR(mat1, mat2, eps) \ -{ \ - ASSERT_EQ(mat1.type(), mat2.type()); \ - ASSERT_EQ(mat1.size(), mat2.size()); \ - EXPECT_LE(checkSimilarity(cv::Mat(mat1), cv::Mat(mat2)), eps); \ -} - - -using perf::MatDepth; -using perf::MatType; - -//! return vector with types from specified range. -std::vector types(int depth_start, int depth_end, int cn_start, int cn_end); - -//! return vector with all types (depth: CV_8U-CV_64F, channels: 1-4). -const std::vector &all_types(); - -class Inverse -{ -public: - inline Inverse(bool val = false) : val_(val) {} - - inline operator bool() const - { - return val_; - } - -private: - bool val_; -}; - -void PrintTo(const Inverse &useRoi, std::ostream *os); - -#define OCL_RNG_SEED 123456 - -template -struct TSTestWithParam : public ::testing::TestWithParam -{ - cv::RNG rng; - - TSTestWithParam() - { - rng = cv::RNG(OCL_RNG_SEED); - } - - int randomInt(int minVal, int maxVal) - { - return rng.uniform(minVal, maxVal); - } - - double randomDouble(double minVal, double maxVal) - { - return rng.uniform(minVal, maxVal); - } - - double randomDoubleLog(double minVal, double maxVal) - { - double logMin = log((double)minVal + 1); - double logMax = log((double)maxVal + 1); - double pow = rng.uniform(logMin, logMax); - double v = exp(pow) - 1; - CV_Assert(v >= minVal && (v < maxVal || (v == minVal && v == maxVal))); - return v; - } - - Size randomSize(int minVal, int maxVal) - { -#if 1 - return cv::Size((int)randomDoubleLog(minVal, maxVal), (int)randomDoubleLog(minVal, maxVal)); -#else - return cv::Size(randomInt(minVal, maxVal), randomInt(minVal, maxVal)); -#endif - } - - Size randomSize(int minValX, int maxValX, int minValY, int maxValY) - { -#if 1 - return cv::Size(randomDoubleLog(minValX, maxValX), randomDoubleLog(minValY, maxValY)); -#else - return cv::Size(randomInt(minVal, maxVal), randomInt(minVal, maxVal)); -#endif - } - - Scalar randomScalar(double minVal, double maxVal) - { - return Scalar(randomDouble(minVal, maxVal), randomDouble(minVal, maxVal), randomDouble(minVal, maxVal), randomDouble(minVal, maxVal)); - } - - Mat randomMat(Size size, int type, double minVal, double maxVal, bool useRoi = false) - { - RNG dataRng(rng.next()); - return cvtest::randomMat(dataRng, size, type, minVal, maxVal, useRoi); - } - - struct Border - { - int top, bot, lef, rig; - }; - - Border randomBorder(int minValue = 0, int maxValue = MAX_VALUE) - { - Border border = { - (int)randomDoubleLog(minValue, maxValue), - (int)randomDoubleLog(minValue, maxValue), - (int)randomDoubleLog(minValue, maxValue), - (int)randomDoubleLog(minValue, maxValue) - }; - return border; - } - - void randomSubMat(Mat& whole, Mat& subMat, const Size& roiSize, const Border& border, int type, double minVal, double maxVal) - { - Size wholeSize = Size(roiSize.width + border.lef + border.rig, roiSize.height + border.top + border.bot); - whole = randomMat(wholeSize, type, minVal, maxVal, false); - subMat = whole(Rect(border.lef, border.top, roiSize.width, roiSize.height)); - } - - void generateOclMat(cv::ocl::oclMat& whole, cv::ocl::oclMat& subMat, const Mat& wholeMat, const Size& roiSize, const Border& border) - { - whole = wholeMat; - subMat = whole(Rect(border.lef, border.top, roiSize.width, roiSize.height)); - } -}; - -#define PARAM_TEST_CASE(name, ...) struct name : public TSTestWithParam< std::tr1::tuple< __VA_ARGS__ > > - -#define GET_PARAM(k) std::tr1::get< k >(GetParam()) - -#define ALL_TYPES testing::ValuesIn(all_types()) -#define TYPES(depth_start, depth_end, cn_start, cn_end) testing::ValuesIn(types(depth_start, depth_end, cn_start, cn_end)) - -#define DIFFERENT_SIZES testing::Values(cv::Size(128, 128), cv::Size(113, 113), cv::Size(1300, 1300)) - -#define IMAGE_CHANNELS testing::Values(Channels(1), Channels(3), Channels(4)) -#ifndef IMPLEMENT_PARAM_CLASS -#define IMPLEMENT_PARAM_CLASS(name, type) \ - class name \ - { \ - public: \ - name ( type arg = type ()) : val_(arg) {} \ - operator type () const {return val_;} \ - private: \ - type val_; \ - }; \ - inline void PrintTo( name param, std::ostream* os) \ - { \ - *os << #name << "(" << testing::PrintToString(static_cast< type >(param)) << ")"; \ - } - -IMPLEMENT_PARAM_CLASS(Channels, int) -#endif // IMPLEMENT_PARAM_CLASS - -} // namespace cvtest - -enum {FLIP_BOTH = 0, FLIP_X = 1, FLIP_Y = -1}; -CV_ENUM(FlipCode, FLIP_BOTH, FLIP_X, FLIP_Y) - -CV_ENUM(CmpCode, CMP_EQ, CMP_GT, CMP_GE, CMP_LT, CMP_LE, CMP_NE) -CV_ENUM(NormCode, NORM_INF, NORM_L1, NORM_L2, NORM_TYPE_MASK, NORM_RELATIVE, NORM_MINMAX) -CV_ENUM(ReduceOp, REDUCE_SUM, REDUCE_AVG, REDUCE_MAX, REDUCE_MIN) -CV_ENUM(MorphOp, MORPH_OPEN, MORPH_CLOSE, MORPH_GRADIENT, MORPH_TOPHAT, MORPH_BLACKHAT) -CV_ENUM(ThreshOp, THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV) -CV_ENUM(Interpolation, INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, INTER_AREA) -CV_ENUM(Border, BORDER_REFLECT101, BORDER_REPLICATE, BORDER_CONSTANT, BORDER_REFLECT, BORDER_WRAP) -CV_ENUM(TemplateMethod, TM_SQDIFF, TM_SQDIFF_NORMED, TM_CCORR, TM_CCORR_NORMED, TM_CCOEFF, TM_CCOEFF_NORMED) - -CV_FLAGS(GemmFlags, GEMM_1_T, GEMM_2_T, GEMM_3_T) -CV_FLAGS(WarpFlags, INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, WARP_INVERSE_MAP) -CV_FLAGS(DftFlags, DFT_INVERSE, DFT_SCALE, DFT_ROWS, DFT_COMPLEX_OUTPUT, DFT_REAL_OUTPUT) - -# define OCL_TEST_P(test_case_name, test_name) \ - class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : \ - public test_case_name { \ - public: \ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() { } \ - virtual void TestBody(); \ - void OCLTestBody(); \ - private: \ - static int AddToRegistry() \ - { \ - ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ - GetTestCasePatternHolder(\ - #test_case_name, __FILE__, __LINE__)->AddTestPattern(\ - #test_case_name, \ - #test_name, \ - new ::testing::internal::TestMetaFactory< \ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \ - return 0; \ - } \ - \ - static int gtest_registering_dummy_; \ - GTEST_DISALLOW_COPY_AND_ASSIGN_(\ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ - }; \ - \ - int GTEST_TEST_CLASS_NAME_(test_case_name, \ - test_name)::gtest_registering_dummy_ = \ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ - \ - void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() \ - { \ - try \ - { \ - OCLTestBody(); \ - } \ - catch (const cv::Exception & ex) \ - { \ - if (ex.code == cv::Error::OpenCLDoubleNotSupported)\ - std::cout << "Test skipped (selected device does not support double)" << std::endl; \ - else if (ex.code == cv::Error::OpenCLNoAMDBlasFft) \ - std::cout << "Test skipped (AMD Blas / Fft libraries are not available)" << std::endl; \ - else \ - throw; \ - } \ - } \ - \ - void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::OCLTestBody() - -#endif // __OPENCV_TEST_UTILITY_HPP__ diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 01f376dd3..1d30f5b8b 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -13,7 +13,6 @@ if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_LIST_DIR) add_subdirectory(c) add_subdirectory(cpp) add_subdirectory(gpu) -add_subdirectory(ocl) add_subdirectory(tapi) if(WIN32 AND HAVE_DIRECTX) diff --git a/samples/ocl/CMakeLists.txt b/samples/ocl/CMakeLists.txt deleted file mode 100644 index 04f5d1728..000000000 --- a/samples/ocl/CMakeLists.txt +++ /dev/null @@ -1,58 +0,0 @@ -SET(OPENCV_OCL_SAMPLES_REQUIRED_DEPS opencv_core opencv_flann opencv_imgproc opencv_highgui - opencv_ml opencv_video opencv_objdetect opencv_features2d - opencv_calib3d opencv_legacy opencv_contrib opencv_ocl opencv_nonfree) - -ocv_check_dependencies(${OPENCV_OCL_SAMPLES_REQUIRED_DEPS}) - -if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND) - set(project "ocl") - string(TOUPPER "${project}" project_upper) - - project("${project}_samples") - - ocv_include_modules(${OPENCV_OCL_SAMPLES_REQUIRED_DEPS}) - - if(HAVE_OPENCL) - ocv_include_directories(${OPENCL_INCLUDE_DIR}) - endif() - - # --------------------------------------------- - # Define executable targets - # --------------------------------------------- - MACRO(OPENCV_DEFINE_OCL_EXAMPLE name srcs) - set(the_target "example_${project}_${name}") - add_executable(${the_target} ${srcs}) - - target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${OPENCV_OCL_SAMPLES_REQUIRED_DEPS}) - - set_target_properties(${the_target} PROPERTIES - OUTPUT_NAME "${project}-example-${name}" - PROJECT_LABEL "(EXAMPLE_${project_upper}) ${name}") - - if(ENABLE_SOLUTION_FOLDERS) - set_target_properties(${the_target} PROPERTIES FOLDER "samples//${project}") - endif() - - if(WIN32) - if(MSVC AND NOT BUILD_SHARED_LIBS) - set_target_properties(${the_target} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:atlsd.lib /DEBUG") - endif() - install(TARGETS ${the_target} RUNTIME DESTINATION "${OPENCV_SAMPLES_BIN_INSTALL_PATH}/${project}" COMPONENT samples) - endif() - ENDMACRO() - - file(GLOB all_samples RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) - - foreach(sample_filename ${all_samples}) - get_filename_component(sample ${sample_filename} NAME_WE) - file(GLOB sample_srcs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${sample}.*) - OPENCV_DEFINE_OCL_EXAMPLE(${sample} ${sample_srcs}) - endforeach() -endif() - -if(INSTALL_C_EXAMPLES AND NOT WIN32) - file(GLOB install_list *.c *.cpp *.jpg *.png *.data makefile.* build_all.sh *.dsp *.cmd ) - install(FILES ${install_list} - DESTINATION share/OpenCV/samples/${project} - PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT samples) -endif() diff --git a/samples/ocl/adaptive_bilateral_filter.cpp b/samples/ocl/adaptive_bilateral_filter.cpp deleted file mode 100644 index df085c49d..000000000 --- a/samples/ocl/adaptive_bilateral_filter.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// This sample shows the difference of adaptive bilateral filter and bilateral filter. -#include "opencv2/core.hpp" -#include "opencv2/core/utility.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" -#include "opencv2/ocl.hpp" - -using namespace cv; -using namespace std; - - -int main( int argc, const char** argv ) -{ - const char* keys = - "{ i input | | specify input image }" - "{ k ksize | 11 | specify kernel size }" - "{ s sSpace | 3 | specify sigma space }" - "{ c sColor | 30 | specify max color }" - "{ h help | false | print help message }"; - - CommandLineParser cmd(argc, argv, keys); - if (cmd.has("help")) - { - cout << "Usage : adaptive_bilateral_filter [options]" << endl; - cout << "Available options:" << endl; - cmd.printMessage(); - return EXIT_SUCCESS; - } - - string src_path = cmd.get("i"); - int ks = cmd.get("k"); - const char * winName[] = {"input", "ABF OpenCL", "BF OpenCL"}; - - Mat src = imread(src_path); - if (src.empty()) - { - cout << "error read image: " << src_path << endl; - return EXIT_FAILURE; - } - - double sigmaSpace = cmd.get("s"); - - // sigma for checking pixel values. This is used as is in the "normal" bilateral filter, - // and it is used as an upper clamp on the adaptive case. - double sigmacolor = cmd.get("c"); - - ocl::oclMat dsrc(src), dABFilter, dBFilter; - Size ksize(ks, ks); - - // ksize is the total width/height of neighborhood used to calculate local variance. - // sigmaSpace is not a priori related to ksize/2. - ocl::adaptiveBilateralFilter(dsrc, dABFilter, ksize, sigmaSpace, sigmacolor); - ocl::bilateralFilter(dsrc, dBFilter, ks, sigmacolor, sigmaSpace); - Mat abFilter = dABFilter, bFilter = dBFilter; - - ocl::finish(); - - imshow(winName[0], src); - imshow(winName[1], abFilter); - imshow(winName[2], bFilter); - - waitKey(); - - return EXIT_SUCCESS; -} diff --git a/samples/ocl/bgfg_segm.cpp b/samples/ocl/bgfg_segm.cpp deleted file mode 100644 index 19d87ef03..000000000 --- a/samples/ocl/bgfg_segm.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include -#include - -#include "opencv2/core.hpp" -#include "opencv2/core/utility.hpp" -#include "opencv2/ocl.hpp" -#include "opencv2/highgui.hpp" - -using namespace std; -using namespace cv; -using namespace cv::ocl; - -#define M_MOG 1 -#define M_MOG2 2 - -int main(int argc, const char** argv) -{ - cv::CommandLineParser cmd(argc, argv, - "{ c camera | false | use camera }" - "{ f file | 768x576.avi | input video file }" - "{ m method | mog | method (mog, mog2) }" - "{ h help | false | print help message }"); - - if (cmd.has("help")) - { - cout << "Usage : bgfg_segm [options]" << endl; - cout << "Available options:" << endl; - cmd.printMessage(); - return EXIT_SUCCESS; - } - - bool useCamera = cmd.get("camera"); - string file = cmd.get("file"); - string method = cmd.get("method"); - - if (method != "mog" && method != "mog2") - { - cerr << "Incorrect method" << endl; - return EXIT_FAILURE; - } - - int m = method == "mog" ? M_MOG : M_MOG2; - - VideoCapture cap; - if (useCamera) - cap.open(0); - else - cap.open(file); - - if (!cap.isOpened()) - { - cout << "can not open camera or video file" << endl; - return EXIT_FAILURE; - } - - Mat frame; - cap >> frame; - - oclMat d_frame(frame); - - cv::ocl::MOG mog; - cv::ocl::MOG2 mog2; - - oclMat d_fgmask, d_fgimg, d_bgimg; - - d_fgimg.create(d_frame.size(), d_frame.type()); - - Mat fgmask, fgimg, bgimg; - - switch (m) - { - case M_MOG: - mog(d_frame, d_fgmask, 0.01f); - break; - - case M_MOG2: - mog2(d_frame, d_fgmask); - break; - } - - for (;;) - { - cap >> frame; - if (frame.empty()) - break; - d_frame.upload(frame); - - int64 start = cv::getTickCount(); - - //update the model - switch (m) - { - case M_MOG: - mog(d_frame, d_fgmask, 0.01f); - mog.getBackgroundImage(d_bgimg); - break; - - case M_MOG2: - mog2(d_frame, d_fgmask); - mog2.getBackgroundImage(d_bgimg); - break; - } - - double fps = cv::getTickFrequency() / (cv::getTickCount() - start); - std::cout << "FPS : " << fps << std::endl; - - d_fgimg.setTo(Scalar::all(0)); - d_frame.copyTo(d_fgimg, d_fgmask); - - d_fgmask.download(fgmask); - d_fgimg.download(fgimg); - if (!d_bgimg.empty()) - d_bgimg.download(bgimg); - - imshow("image", frame); - imshow("foreground mask", fgmask); - imshow("foreground image", fgimg); - if (!bgimg.empty()) - imshow("mean background image", bgimg); - - if (27 == waitKey(30)) - break; - } - - return EXIT_SUCCESS; -} diff --git a/samples/ocl/clahe.cpp b/samples/ocl/clahe.cpp deleted file mode 100644 index 894a41483..000000000 --- a/samples/ocl/clahe.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include "opencv2/core/core.hpp" -#include "opencv2/core/utility.hpp" -#include "opencv2/imgproc/imgproc.hpp" -#include "opencv2/highgui/highgui.hpp" -#include "opencv2/ocl/ocl.hpp" -using namespace cv; -using namespace std; - -Ptr pFilter; -int tilesize; -int cliplimit; - -static void TSize_Callback(int pos) -{ - if(pos==0) - pFilter->setTilesGridSize(Size(1,1)); - else - pFilter->setTilesGridSize(Size(tilesize,tilesize)); -} - -static void Clip_Callback(int) -{ - pFilter->setClipLimit(cliplimit); -} - -int main(int argc, char** argv) -{ - const char* keys = - "{ i input | | specify input image }" - "{ c camera | 0 | specify camera id }" - "{ s use_cpu | false | use cpu algorithm }" - "{ o output | clahe_output.jpg | specify output save path}" - "{ h help | false | print help message }"; - - cv::CommandLineParser cmd(argc, argv, keys); - if (cmd.has("help")) - { - cout << "Usage : clahe [options]" << endl; - cout << "Available options:" << endl; - cmd.printMessage(); - return EXIT_SUCCESS; - } - - string infile = cmd.get("i"), outfile = cmd.get("o"); - int camid = cmd.get("c"); - bool use_cpu = cmd.get("s"); - VideoCapture capture; - - namedWindow("CLAHE"); - createTrackbar("Tile Size", "CLAHE", &tilesize, 32, (TrackbarCallback)TSize_Callback); - createTrackbar("Clip Limit", "CLAHE", &cliplimit, 20, (TrackbarCallback)Clip_Callback); - - Mat frame, outframe; - ocl::oclMat d_outframe, d_frame; - - int cur_clip; - Size cur_tilesize; - pFilter = use_cpu ? createCLAHE() : ocl::createCLAHE(); - - cur_clip = (int)pFilter->getClipLimit(); - cur_tilesize = pFilter->getTilesGridSize(); - setTrackbarPos("Tile Size", "CLAHE", cur_tilesize.width); - setTrackbarPos("Clip Limit", "CLAHE", cur_clip); - - if(infile != "") - { - frame = imread(infile); - if(frame.empty()) - { - cout << "error read image: " << infile << endl; - return EXIT_FAILURE; - } - } - else - capture.open(camid); - - cout << "\nControls:\n" - << "\to - save output image\n" - << "\tESC - exit\n"; - - for (;;) - { - if(capture.isOpened()) - capture.read(frame); - else - frame = imread(infile); - if(frame.empty()) - continue; - - if(use_cpu) - { - cvtColor(frame, frame, COLOR_BGR2GRAY); - pFilter->apply(frame, outframe); - } - else - { - ocl::cvtColor(d_frame = frame, d_outframe, COLOR_BGR2GRAY); - pFilter->apply(d_outframe, d_outframe); - d_outframe.download(outframe); - } - - imshow("CLAHE", outframe); - - char key = (char)waitKey(3); - if(key == 'o') - imwrite(outfile, outframe); - else if(key == 27) - break; - } - return EXIT_SUCCESS; -} diff --git a/samples/ocl/facedetect.cpp b/samples/ocl/facedetect.cpp deleted file mode 100644 index c5059323e..000000000 --- a/samples/ocl/facedetect.cpp +++ /dev/null @@ -1,390 +0,0 @@ -#include "opencv2/objdetect/objdetect.hpp" -#include "opencv2/highgui/highgui.hpp" -#include "opencv2/imgproc/imgproc.hpp" -#include "opencv2/ocl/ocl.hpp" - -#include "opencv2/highgui/highgui_c.h" - -#include -#include - -#if defined(_MSC_VER) && (_MSC_VER >= 1700) - # include -#endif - -using namespace std; -using namespace cv; - -#define LOOP_NUM 1 -#define MAX_THREADS 10 - - -///////////////////////////single-threading faces detecting/////////////////////////////// - -const static Scalar colors[] = { CV_RGB(0,0,255), - CV_RGB(0,128,255), - CV_RGB(0,255,255), - CV_RGB(0,255,0), - CV_RGB(255,128,0), - CV_RGB(255,255,0), - CV_RGB(255,0,0), - CV_RGB(255,0,255) - } ; - - -int64 work_begin[MAX_THREADS] = {0}; -int64 work_total[MAX_THREADS] = {0}; -string inputName, outputName, cascadeName; - -static void workBegin(int i = 0) -{ - work_begin[i] = getTickCount(); -} - -static void workEnd(int i = 0) -{ - work_total[i] += (getTickCount() - work_begin[i]); -} - -static double getTotalTime(int i = 0) -{ - return work_total[i] /getTickFrequency() * 1000.; -} - - -static void detect( Mat& img, vector& faces, - ocl::OclCascadeClassifier& cascade, - double scale); - - -static void detectCPU( Mat& img, vector& faces, - CascadeClassifier& cascade, - double scale); - -static void Draw(Mat& img, vector& faces, double scale); - - -// This function test if gpu_rst matches cpu_rst. -// If the two vectors are not equal, it will return the difference in vector size -// Else if will return (total diff of each cpu and gpu rects covered pixels)/(total cpu rects covered pixels) -double checkRectSimilarity(Size sz, vector& cpu_rst, vector& gpu_rst); - -static int facedetect_one_thread(bool useCPU, double scale ) -{ - CvCapture* capture = 0; - Mat frame, frameCopy0, frameCopy, image; - - ocl::OclCascadeClassifier cascade; - CascadeClassifier cpu_cascade; - - if( !cascade.load( cascadeName ) || !cpu_cascade.load(cascadeName) ) - { - cout << "ERROR: Could not load classifier cascade: " << cascadeName << endl; - return EXIT_FAILURE; - } - - if( inputName.empty() ) - { - capture = cvCaptureFromCAM(0); - if(!capture) - cout << "Capture from CAM 0 didn't work" << endl; - } - else - { - image = imread( inputName, CV_LOAD_IMAGE_COLOR ); - if( image.empty() ) - { - capture = cvCaptureFromAVI( inputName.c_str() ); - if(!capture) - cout << "Capture from AVI didn't work" << endl; - return EXIT_FAILURE; - } - } - - if( capture ) - { - cout << "In capture ..." << endl; - for(;;) - { - IplImage* iplImg = cvQueryFrame( capture ); - frame = cv::cvarrToMat(iplImg); - vector faces; - if( frame.empty() ) - break; - if( iplImg->origin == IPL_ORIGIN_TL ) - frame.copyTo( frameCopy0 ); - else - flip( frame, frameCopy0, 0 ); - if( scale == 1) - frameCopy0.copyTo(frameCopy); - else - resize(frameCopy0, frameCopy, Size(), 1./scale, 1./scale, INTER_LINEAR); - - if(useCPU) - detectCPU(frameCopy, faces, cpu_cascade, 1); - else - detect(frameCopy, faces, cascade, 1); - - Draw(frameCopy, faces, 1); - if( waitKey( 10 ) >= 0 ) - break; - } - cvReleaseCapture( &capture ); - } - else - { - cout << "In image read " << image.size() << endl; - vector faces; - vector ref_rst; - double accuracy = 0.; - detectCPU(image, ref_rst, cpu_cascade, scale); - - cout << "loops: "; - for(int i = 0; i <= LOOP_NUM; i ++) - { - cout << i << ", "; - if(useCPU) - detectCPU(image, faces, cpu_cascade, scale); - else - { - detect(image, faces, cascade, scale); - if(i == 0) - { - accuracy = checkRectSimilarity(image.size(), ref_rst, faces); - } - } - } - cout << "done!" << endl; - if (useCPU) - cout << "average CPU time (noCamera) : "; - else - cout << "average GPU time (noCamera) : "; - cout << getTotalTime() / LOOP_NUM << " ms" << endl; - cout << "accuracy value: " << accuracy <= 1700) - -static void detectFaces(std::string fileName, int threadNum) -{ - ocl::OclCascadeClassifier cascade; - if(!cascade.load(cascadeName)) - { - std::cout << "ERROR: Could not load classifier cascade: " << cascadeName << std::endl; - return; - } - - Mat img = imread(fileName, CV_LOAD_IMAGE_COLOR); - if (img.empty()) - { - std::cout << '[' << threadNum << "] " << "can't open file " + fileName < oclfaces; - std::thread::id tid = std::this_thread::get_id(); - std::cout << '[' << threadNum << "] " - << "ThreadID = " << tid - << ", CommandQueue = " << *(void**)ocl::getClCommandQueuePtr() - << endl; - for(int i = 0; i <= LOOP_NUM; i++) - { - if(i>0) workBegin(threadNum); - cascade.detectMultiScale(d_img, oclfaces, 1.1, 3, 0|CASCADE_SCALE_IMAGE, Size(30, 30), Size(0, 0)); - if(i>0) workEnd(threadNum); - } - std::cout << '[' << threadNum << "] " << "Average time = " << getTotalTime(threadNum) / LOOP_NUM << " ms" << endl; - - for(unsigned int i = 0; i threads; - for(int i = 0; i= 1 }"; - - CommandLineParser cmd(argc, argv, keys); - if (cmd.has("help")) - { - cout << "Usage : facedetect [options]" << endl; - cout << "Available options:" << endl; - cmd.printMessage(); - return EXIT_SUCCESS; - } - bool useCPU = cmd.get("s"); - inputName = cmd.get("i"); - outputName = cmd.get("o"); - cascadeName = cmd.get("t"); - double scale = cmd.get("c"); - int n = cmd.get("n"); - - if(n > 1) - { -#if defined(_MSC_VER) && (_MSC_VER >= 1700) - std::cout<<"multi-threaded sample is running" <& faces, - ocl::OclCascadeClassifier& cascade, - double scale) -{ - ocl::oclMat image(img); - ocl::oclMat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 ); - workBegin(); - ocl::cvtColor( image, gray, COLOR_BGR2GRAY ); - ocl::resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR ); - ocl::equalizeHist( smallImg, smallImg ); - - cascade.detectMultiScale( smallImg, faces, 1.1, - 3, 0 - |CASCADE_SCALE_IMAGE - , Size(30,30), Size(0, 0) ); - workEnd(); -} - -void detectCPU( Mat& img, vector& faces, - CascadeClassifier& cascade, - double scale) -{ - workBegin(); - Mat cpu_gray, cpu_smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 ); - cvtColor(img, cpu_gray, COLOR_BGR2GRAY); - resize(cpu_gray, cpu_smallImg, cpu_smallImg.size(), 0, 0, INTER_LINEAR); - equalizeHist(cpu_smallImg, cpu_smallImg); - cascade.detectMultiScale(cpu_smallImg, faces, 1.1, - 3, 0 | CASCADE_SCALE_IMAGE, - Size(30, 30), Size(0, 0)); - workEnd(); -} - - -void Draw(Mat& img, vector& faces, double scale) -{ - int i = 0; - for( vector::const_iterator r = faces.begin(); r != faces.end(); r++, i++ ) - { - Point center; - Scalar color = colors[i%8]; - int radius; - center.x = cvRound((r->x + r->width*0.5)*scale); - center.y = cvRound((r->y + r->height*0.5)*scale); - radius = cvRound((r->width + r->height)*0.25*scale); - circle( img, center, radius, color, 3, 8, 0 ); - } - //if( !outputName.empty() ) imwrite( outputName, img ); - if( abs(scale-1.0)>.001 ) - { - resize(img, img, Size((int)(img.cols/scale), (int)(img.rows/scale))); - } - imshow( "result", img ); - -} - - -double checkRectSimilarity(Size sz, vector& ob1, vector& ob2) -{ - double final_test_result = 0.0; - size_t sz1 = ob1.size(); - size_t sz2 = ob2.size(); - - if(sz1 != sz2) - { - return sz1 > sz2 ? (double)(sz1 - sz2) : (double)(sz2 - sz1); - } - else - { - if(sz1==0 && sz2==0) - return 0; - Mat cpu_result(sz, CV_8UC1); - cpu_result.setTo(0); - - for(vector::const_iterator r = ob1.begin(); r != ob1.end(); r++) - { - Mat cpu_result_roi(cpu_result, *r); - cpu_result_roi.setTo(1); - cpu_result.copyTo(cpu_result); - } - int cpu_area = countNonZero(cpu_result > 0); - - - Mat gpu_result(sz, CV_8UC1); - gpu_result.setTo(0); - for(vector::const_iterator r2 = ob2.begin(); r2 != ob2.end(); r2++) - { - cv::Mat gpu_result_roi(gpu_result, *r2); - gpu_result_roi.setTo(1); - gpu_result.copyTo(gpu_result); - } - - Mat result_; - multiply(cpu_result, gpu_result, result_); - int result = countNonZero(result_ > 0); - if(cpu_area!=0 && result!=0) - final_test_result = 1.0 - (double)result/(double)cpu_area; - else if(cpu_area==0 && result!=0) - final_test_result = -1; - } - return final_test_result; -} diff --git a/samples/ocl/hog.cpp b/samples/ocl/hog.cpp deleted file mode 100644 index a3c5c9936..000000000 --- a/samples/ocl/hog.cpp +++ /dev/null @@ -1,448 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "opencv2/ocl.hpp" -#include "opencv2/highgui.hpp" - -using namespace std; -using namespace cv; - -class App -{ -public: - App(CommandLineParser& cmd); - void run(); - void handleKey(char key); - void hogWorkBegin(); - void hogWorkEnd(); - string hogWorkFps() const; - void workBegin(); - void workEnd(); - string workFps() const; - string message() const; - - -// This function test if gpu_rst matches cpu_rst. -// If the two vectors are not equal, it will return the difference in vector size -// Else if will return -// (total diff of each cpu and gpu rects covered pixels)/(total cpu rects covered pixels) - double checkRectSimilarity(Size sz, - std::vector& cpu_rst, - std::vector& gpu_rst); -private: - App operator=(App&); - - //Args args; - bool running; - bool use_gpu; - bool make_gray; - double scale; - double resize_scale; - int win_width; - int win_stride_width, win_stride_height; - int gr_threshold; - int nlevels; - double hit_threshold; - bool gamma_corr; - - int64 hog_work_begin; - double hog_work_fps; - int64 work_begin; - double work_fps; - - string img_source; - string vdo_source; - string output; - int camera_id; - bool write_once; -}; - -int main(int argc, char** argv) -{ - const char* keys = - "{ h | help | false | print help message }" - "{ i | input | | specify input image}" - "{ c | camera | -1 | enable camera capturing }" - "{ v | video | | use video as input }" - "{ g | gray | false | convert image to gray one or not}" - "{ s | scale | 1.0 | resize the image before detect}" - "{ l |larger_win| false | use 64x128 window}" - "{ o | output | | specify output path when input is images}"; - CommandLineParser cmd(argc, argv, keys); - if (cmd.has("help")) - { - cout << "Usage : hog [options]" << endl; - cout << "Available options:" << endl; - cmd.printMessage(); - return EXIT_SUCCESS; - } - - App app(cmd); - try - { - app.run(); - } - catch (const Exception& e) - { - return cout << "error: " << e.what() << endl, 1; - } - catch (const exception& e) - { - return cout << "error: " << e.what() << endl, 1; - } - catch(...) - { - return cout << "unknown exception" << endl, 1; - } - return EXIT_SUCCESS; -} - -App::App(CommandLineParser& cmd) -{ - cout << "\nControls:\n" - << "\tESC - exit\n" - << "\tm - change mode GPU <-> CPU\n" - << "\tg - convert image to gray or not\n" - << "\to - save output image once, or switch on/off video save\n" - << "\t1/q - increase/decrease HOG scale\n" - << "\t2/w - increase/decrease levels count\n" - << "\t3/e - increase/decrease HOG group threshold\n" - << "\t4/r - increase/decrease hit threshold\n" - << endl; - - - use_gpu = true; - make_gray = cmd.get("g"); - resize_scale = cmd.get("s"); - win_width = cmd.get("l") == true ? 64 : 48; - vdo_source = cmd.get("v"); - img_source = cmd.get("i"); - output = cmd.get("o"); - camera_id = cmd.get("c"); - - win_stride_width = 8; - win_stride_height = 8; - gr_threshold = 8; - nlevels = 13; - hit_threshold = win_width == 48 ? 1.4 : 0.; - scale = 1.05; - gamma_corr = true; - write_once = false; - - cout << "Group threshold: " << gr_threshold << endl; - cout << "Levels number: " << nlevels << endl; - cout << "Win width: " << win_width << endl; - cout << "Win stride: (" << win_stride_width << ", " << win_stride_height << ")\n"; - cout << "Hit threshold: " << hit_threshold << endl; - cout << "Gamma correction: " << gamma_corr << endl; - cout << endl; -} - -void App::run() -{ - running = true; - VideoWriter video_writer; - - Size win_size(win_width, win_width * 2); - Size win_stride(win_stride_width, win_stride_height); - - // Create HOG descriptors and detectors here - vector detector; - if (win_size == Size(64, 128)) - detector = ocl::HOGDescriptor::getPeopleDetector64x128(); - else - detector = ocl::HOGDescriptor::getPeopleDetector48x96(); - - - ocl::HOGDescriptor gpu_hog(win_size, Size(16, 16), Size(8, 8), Size(8, 8), 9, - ocl::HOGDescriptor::DEFAULT_WIN_SIGMA, 0.2, gamma_corr, - ocl::HOGDescriptor::DEFAULT_NLEVELS); - HOGDescriptor cpu_hog(win_size, Size(16, 16), Size(8, 8), Size(8, 8), 9, 1, -1, - HOGDescriptor::L2Hys, 0.2, gamma_corr, cv::HOGDescriptor::DEFAULT_NLEVELS); - gpu_hog.setSVMDetector(detector); - cpu_hog.setSVMDetector(detector); - - while (running) - { - VideoCapture vc; - Mat frame; - - if (vdo_source!="") - { - vc.open(vdo_source.c_str()); - if (!vc.isOpened()) - throw runtime_error(string("can't open video file: " + vdo_source)); - vc >> frame; - } - else if (camera_id != -1) - { - vc.open(camera_id); - if (!vc.isOpened()) - { - stringstream msg; - msg << "can't open camera: " << camera_id; - throw runtime_error(msg.str()); - } - vc >> frame; - } - else - { - frame = imread(img_source); - if (frame.empty()) - throw runtime_error(string("can't open image file: " + img_source)); - } - - Mat img_aux, img, img_to_show; - ocl::oclMat gpu_img; - - // Iterate over all frames - bool verify = false; - while (running && !frame.empty()) - { - workBegin(); - - // Change format of the image - if (make_gray) cvtColor(frame, img_aux, COLOR_BGR2GRAY); - else if (use_gpu) cvtColor(frame, img_aux, COLOR_BGR2BGRA); - else frame.copyTo(img_aux); - - // Resize image - if (abs(scale-1.0)>0.001) - { - Size sz((int)((double)img_aux.cols/resize_scale), (int)((double)img_aux.rows/resize_scale)); - resize(img_aux, img, sz); - } - else img = img_aux; - img_to_show = img; - gpu_hog.nlevels = nlevels; - cpu_hog.nlevels = nlevels; - vector found; - - // Perform HOG classification - hogWorkBegin(); - if (use_gpu) - { - gpu_img.upload(img); - gpu_hog.detectMultiScale(gpu_img, found, hit_threshold, win_stride, - Size(0, 0), scale, gr_threshold); - if (!verify) - { - // verify if GPU output same objects with CPU at 1st run - verify = true; - vector ref_rst; - cvtColor(img, img, COLOR_BGRA2BGR); - cpu_hog.detectMultiScale(img, ref_rst, hit_threshold, win_stride, - Size(0, 0), scale, gr_threshold-2); - double accuracy = checkRectSimilarity(img.size(), ref_rst, found); - cout << "\naccuracy value: " << accuracy << endl; - } - } - else cpu_hog.detectMultiScale(img, found, hit_threshold, win_stride, - Size(0, 0), scale, gr_threshold); - hogWorkEnd(); - - - // Draw positive classified windows - for (size_t i = 0; i < found.size(); i++) - { - Rect r = found[i]; - rectangle(img_to_show, r.tl(), r.br(), Scalar(0, 255, 0), 3); - } - - if (use_gpu) - putText(img_to_show, "Mode: GPU", Point(5, 25), FONT_HERSHEY_SIMPLEX, 1., Scalar(255, 100, 0), 2); - else - putText(img_to_show, "Mode: CPU", Point(5, 25), FONT_HERSHEY_SIMPLEX, 1., Scalar(255, 100, 0), 2); - putText(img_to_show, "FPS (HOG only): " + hogWorkFps(), Point(5, 65), FONT_HERSHEY_SIMPLEX, 1., Scalar(255, 100, 0), 2); - putText(img_to_show, "FPS (total): " + workFps(), Point(5, 105), FONT_HERSHEY_SIMPLEX, 1., Scalar(255, 100, 0), 2); - imshow("opencv_gpu_hog", img_to_show); - if (vdo_source!="" || camera_id!=-1) vc >> frame; - - workEnd(); - - if (output!="" && write_once) - { - if (img_source!="") // wirte image - { - write_once = false; - imwrite(output, img_to_show); - } - else //write video - { - if (!video_writer.isOpened()) - { - video_writer.open(output, VideoWriter::fourcc('x','v','i','d'), 24, - img_to_show.size(), true); - if (!video_writer.isOpened()) - throw std::runtime_error("can't create video writer"); - } - - if (make_gray) cvtColor(img_to_show, img, COLOR_GRAY2BGR); - else cvtColor(img_to_show, img, COLOR_BGRA2BGR); - - video_writer << img; - } - } - - handleKey((char)waitKey(3)); - } - } -} - -void App::handleKey(char key) -{ - switch (key) - { - case 27: - running = false; - break; - case 'm': - case 'M': - use_gpu = !use_gpu; - cout << "Switched to " << (use_gpu ? "CUDA" : "CPU") << " mode\n"; - break; - case 'g': - case 'G': - make_gray = !make_gray; - cout << "Convert image to gray: " << (make_gray ? "YES" : "NO") << endl; - break; - case '1': - scale *= 1.05; - cout << "Scale: " << scale << endl; - break; - case 'q': - case 'Q': - scale /= 1.05; - cout << "Scale: " << scale << endl; - break; - case '2': - nlevels++; - cout << "Levels number: " << nlevels << endl; - break; - case 'w': - case 'W': - nlevels = max(nlevels - 1, 1); - cout << "Levels number: " << nlevels << endl; - break; - case '3': - gr_threshold++; - cout << "Group threshold: " << gr_threshold << endl; - break; - case 'e': - case 'E': - gr_threshold = max(0, gr_threshold - 1); - cout << "Group threshold: " << gr_threshold << endl; - break; - case '4': - hit_threshold+=0.25; - cout << "Hit threshold: " << hit_threshold << endl; - break; - case 'r': - case 'R': - hit_threshold = max(0.0, hit_threshold - 0.25); - cout << "Hit threshold: " << hit_threshold << endl; - break; - case 'c': - case 'C': - gamma_corr = !gamma_corr; - cout << "Gamma correction: " << gamma_corr << endl; - break; - case 'o': - case 'O': - write_once = !write_once; - break; - } -} - - -inline void App::hogWorkBegin() -{ - hog_work_begin = getTickCount(); -} - -inline void App::hogWorkEnd() -{ - int64 delta = getTickCount() - hog_work_begin; - double freq = getTickFrequency(); - hog_work_fps = freq / delta; -} - -inline string App::hogWorkFps() const -{ - stringstream ss; - ss << hog_work_fps; - return ss.str(); -} - -inline void App::workBegin() -{ - work_begin = getTickCount(); -} - -inline void App::workEnd() -{ - int64 delta = getTickCount() - work_begin; - double freq = getTickFrequency(); - work_fps = freq / delta; -} - -inline string App::workFps() const -{ - stringstream ss; - ss << work_fps; - return ss.str(); -} - - -double App::checkRectSimilarity(Size sz, - std::vector& ob1, - std::vector& ob2) -{ - double final_test_result = 0.0; - size_t sz1 = ob1.size(); - size_t sz2 = ob2.size(); - - if(sz1 != sz2) - { - return sz1 > sz2 ? (double)(sz1 - sz2) : (double)(sz2 - sz1); - } - else - { - if(sz1==0 && sz2==0) - return 0; - cv::Mat cpu_result(sz, CV_8UC1); - cpu_result.setTo(0); - - - for(vector::const_iterator r = ob1.begin(); r != ob1.end(); r++) - { - cv::Mat cpu_result_roi(cpu_result, *r); - cpu_result_roi.setTo(1); - cpu_result.copyTo(cpu_result); - } - int cpu_area = cv::countNonZero(cpu_result > 0); - - - cv::Mat gpu_result(sz, CV_8UC1); - gpu_result.setTo(0); - for(vector::const_iterator r2 = ob2.begin(); r2 != ob2.end(); r2++) - { - cv::Mat gpu_result_roi(gpu_result, *r2); - gpu_result_roi.setTo(1); - gpu_result.copyTo(gpu_result); - } - - cv::Mat result_; - multiply(cpu_result, gpu_result, result_); - int result = cv::countNonZero(result_ > 0); - if(cpu_area!=0 && result!=0) - final_test_result = 1.0 - (double)result/(double)cpu_area; - else if(cpu_area==0 && result!=0) - final_test_result = -1; - } - return final_test_result; -} diff --git a/samples/ocl/pyrlk_optical_flow.cpp b/samples/ocl/pyrlk_optical_flow.cpp deleted file mode 100644 index 89137d96e..000000000 --- a/samples/ocl/pyrlk_optical_flow.cpp +++ /dev/null @@ -1,264 +0,0 @@ -#include -#include -#include - -#include "opencv2/core/utility.hpp" -#include "opencv2/highgui/highgui.hpp" -#include "opencv2/ocl/ocl.hpp" -#include "opencv2/video/video.hpp" - -using namespace std; -using namespace cv; -using namespace cv::ocl; - -typedef unsigned char uchar; -#define LOOP_NUM 10 -int64 work_begin = 0; -int64 work_end = 0; - -static void workBegin() -{ - work_begin = getTickCount(); -} -static void workEnd() -{ - work_end += (getTickCount() - work_begin); -} -static double getTime() -{ - return work_end * 1000. / getTickFrequency(); -} - -static void download(const oclMat& d_mat, vector& vec) -{ - vec.clear(); - vec.resize(d_mat.cols); - Mat mat(1, d_mat.cols, CV_32FC2, (void*)&vec[0]); - d_mat.download(mat); -} - -static void download(const oclMat& d_mat, vector& vec) -{ - vec.clear(); - vec.resize(d_mat.cols); - Mat mat(1, d_mat.cols, CV_8UC1, (void*)&vec[0]); - d_mat.download(mat); -} - -static void drawArrows(Mat& frame, const vector& prevPts, const vector& nextPts, const vector& status, - Scalar line_color = Scalar(0, 0, 255)) -{ - for (size_t i = 0; i < prevPts.size(); ++i) - { - if (status[i]) - { - int line_thickness = 1; - - Point p = prevPts[i]; - Point q = nextPts[i]; - - double angle = atan2((double) p.y - q.y, (double) p.x - q.x); - - double hypotenuse = sqrt( (double)(p.y - q.y)*(p.y - q.y) + (double)(p.x - q.x)*(p.x - q.x) ); - - if (hypotenuse < 1.0) - continue; - - // Here we lengthen the arrow by a factor of three. - q.x = (int) (p.x - 3 * hypotenuse * cos(angle)); - q.y = (int) (p.y - 3 * hypotenuse * sin(angle)); - - // Now we draw the main line of the arrow. - line(frame, p, q, line_color, line_thickness); - - // Now draw the tips of the arrow. I do some scaling so that the - // tips look proportional to the main line of the arrow. - - p.x = (int) (q.x + 9 * cos(angle + CV_PI / 4)); - p.y = (int) (q.y + 9 * sin(angle + CV_PI / 4)); - line(frame, p, q, line_color, line_thickness); - - p.x = (int) (q.x + 9 * cos(angle - CV_PI / 4)); - p.y = (int) (q.y + 9 * sin(angle - CV_PI / 4)); - line(frame, p, q, line_color, line_thickness); - } - } -} - - -int main(int argc, const char* argv[]) -{ - const char* keys = - "{ help h | false | print help message }" - "{ left l | | specify left image }" - "{ right r | | specify right image }" - "{ camera c | 0 | enable camera capturing }" - "{ use_cpu s | false | use cpu or gpu to process the image }" - "{ video v | | use video as input }" - "{ output o | pyrlk_output.jpg| specify output save path when input is images }" - "{ points | 1000 | specify points count [GoodFeatureToTrack] }" - "{ min_dist | 0 | specify minimal distance between points [GoodFeatureToTrack] }"; - - CommandLineParser cmd(argc, argv, keys); - - if (cmd.has("help")) - { - cout << "Usage: pyrlk_optical_flow [options]" << endl; - cout << "Available options:" << endl; - cmd.printMessage(); - return EXIT_SUCCESS; - } - - bool defaultPicturesFail = false; - string fname0 = cmd.get("left"); - string fname1 = cmd.get("right"); - string vdofile = cmd.get("video"); - string outfile = cmd.get("output"); - int points = cmd.get("points"); - double minDist = cmd.get("min_dist"); - bool useCPU = cmd.has("s"); - int inputName = cmd.get("c"); - - oclMat d_nextPts, d_status; - GoodFeaturesToTrackDetector_OCL d_features(points); - Mat frame0 = imread(fname0, cv::IMREAD_GRAYSCALE); - Mat frame1 = imread(fname1, cv::IMREAD_GRAYSCALE); - PyrLKOpticalFlow d_pyrLK; - vector pts(points); - vector nextPts(points); - vector status(points); - vector err; - - cout << "Points count : " << points << endl << endl; - - if (frame0.empty() || frame1.empty()) - { - VideoCapture capture; - Mat frame, frameCopy; - Mat frame0Gray, frame1Gray; - Mat ptr0, ptr1; - - if(vdofile.empty()) - capture.open( inputName ); - else - capture.open(vdofile.c_str()); - - int c = inputName ; - if(!capture.isOpened()) - { - if(vdofile.empty()) - cout << "Capture from CAM " << c << " didn't work" << endl; - else - cout << "Capture from file " << vdofile << " failed" <= 0 ) - break; - } - - capture.release(); - } - else - { -nocamera: - for(int i = 0; i <= LOOP_NUM; i ++) - { - cout << "loop" << i << endl; - if (i > 0) workBegin(); - - if (useCPU) - { - goodFeaturesToTrack(frame0, pts, points, 0.01, minDist); - calcOpticalFlowPyrLK(frame0, frame1, pts, nextPts, status, err); - } - else - { - oclMat d_img(frame0), d_prevPts; - d_features(d_img, d_prevPts); - d_pyrLK.sparse(d_img, oclMat(frame1), d_prevPts, d_nextPts, d_status); - d_features.downloadPoints(d_prevPts, pts); - download(d_nextPts, nextPts); - download(d_status, status); - } - - if (i > 0 && i <= LOOP_NUM) - workEnd(); - - if (i == LOOP_NUM) - { - if (useCPU) - cout << "average CPU time (noCamera) : "; - else - cout << "average GPU time (noCamera) : "; - - cout << getTime() / LOOP_NUM << " ms" << endl; - - drawArrows(frame0, pts, nextPts, status, Scalar(255, 0, 0)); - imshow("PyrLK [Sparse]", frame0); - imwrite(outfile, frame0); - } - } - } - - waitKey(); - - return EXIT_SUCCESS; -} diff --git a/samples/ocl/squares.cpp b/samples/ocl/squares.cpp deleted file mode 100644 index b53648f3f..000000000 --- a/samples/ocl/squares.cpp +++ /dev/null @@ -1,341 +0,0 @@ -// The "Square Detector" program. -// It loads several images sequentially and tries to find squares in -// each image - -#include "opencv2/core.hpp" -#include "opencv2/core/utility.hpp" -#include "opencv2/imgproc/imgproc.hpp" -#include "opencv2/highgui/highgui.hpp" -#include "opencv2/ocl/ocl.hpp" -#include -#include -#include - -using namespace cv; -using namespace std; - -#define ACCURACY_CHECK - -#ifdef ACCURACY_CHECK -// check if two vectors of vector of points are near or not -// prior assumption is that they are in correct order -static bool checkPoints( - vector< vector > set1, - vector< vector > set2, - int maxDiff = 5) -{ - if(set1.size() != set2.size()) - { - return false; - } - - for(vector< vector >::iterator it1 = set1.begin(), it2 = set2.begin(); - it1 < set1.end() && it2 < set2.end(); it1 ++, it2 ++) - { - vector pts1 = *it1; - vector pts2 = *it2; - - - if(pts1.size() != pts2.size()) - { - return false; - } - for(size_t i = 0; i < pts1.size(); i ++) - { - Point pt1 = pts1[i], pt2 = pts2[i]; - if(std::abs(pt1.x - pt2.x) > maxDiff || - std::abs(pt1.y - pt2.y) > maxDiff) - { - return false; - } - } - } - return true; -} -#endif - -int thresh = 50, N = 11; -const char* wndname = "OpenCL Square Detection Demo"; - - -// helper function: -// finds a cosine of angle between vectors -// from pt0->pt1 and from pt0->pt2 -static double angle( Point pt1, Point pt2, Point pt0 ) -{ - double dx1 = pt1.x - pt0.x; - double dy1 = pt1.y - pt0.y; - double dx2 = pt2.x - pt0.x; - double dy2 = pt2.y - pt0.y; - return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); -} - - -// returns sequence of squares detected on the image. -// the sequence is stored in the specified memory storage -static void findSquares( const Mat& image, vector >& squares ) -{ - squares.clear(); - Mat pyr, timg, gray0(image.size(), CV_8U), gray; - - // down-scale and upscale the image to filter out the noise - pyrDown(image, pyr, Size(image.cols/2, image.rows/2)); - pyrUp(pyr, timg, image.size()); - vector > contours; - - // find squares in every color plane of the image - for( int c = 0; c < 3; c++ ) - { - int ch[] = {c, 0}; - mixChannels(&timg, 1, &gray0, 1, ch, 1); - - // try several threshold levels - for( int l = 0; l < N; l++ ) - { - // hack: use Canny instead of zero threshold level. - // Canny helps to catch squares with gradient shading - if( l == 0 ) - { - // apply Canny. Take the upper threshold from slider - // and set the lower to 0 (which forces edges merging) - Canny(gray0, gray, 0, thresh, 5); - // dilate canny output to remove potential - // holes between edge segments - dilate(gray, gray, Mat(), Point(-1,-1)); - } - else - { - // apply threshold if l!=0: - // tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0 - cv::threshold(gray0, gray, (l+1)*255/N, 255, THRESH_BINARY); - } - - // find contours and store them all as a list - findContours(gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE); - - vector approx; - - // test each contour - for( size_t i = 0; i < contours.size(); i++ ) - { - // approximate contour with accuracy proportional - // to the contour perimeter - approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true); - - // square contours should have 4 vertices after approximation - // relatively large area (to filter out noisy contours) - // and be convex. - // Note: absolute value of an area is used because - // area may be positive or negative - in accordance with the - // contour orientation - if( approx.size() == 4 && - fabs(contourArea(Mat(approx))) > 1000 && - isContourConvex(Mat(approx)) ) - { - double maxCosine = 0; - - for( int j = 2; j < 5; j++ ) - { - // find the maximum cosine of the angle between joint edges - double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1])); - maxCosine = MAX(maxCosine, cosine); - } - - // if cosines of all angles are small - // (all angles are ~90 degree) then write quandrange - // vertices to resultant sequence - if( maxCosine < 0.3 ) - squares.push_back(approx); - } - } - } - } -} - - -// returns sequence of squares detected on the image. -// the sequence is stored in the specified memory storage -static void findSquares_ocl( const Mat& image, vector >& squares ) -{ - squares.clear(); - - Mat gray; - cv::ocl::oclMat pyr_ocl, timg_ocl, gray0_ocl, gray_ocl; - - // down-scale and upscale the image to filter out the noise - ocl::pyrDown(ocl::oclMat(image), pyr_ocl); - ocl::pyrUp(pyr_ocl, timg_ocl); - - vector > contours; - vector gray0s; - ocl::split(timg_ocl, gray0s); // split 3 channels into a vector of oclMat - // find squares in every color plane of the image - for( int c = 0; c < 3; c++ ) - { - gray0_ocl = gray0s[c]; - // try several threshold levels - for( int l = 0; l < N; l++ ) - { - // hack: use Canny instead of zero threshold level. - // Canny helps to catch squares with gradient shading - if( l == 0 ) - { - // do canny on OpenCL device - // apply Canny. Take the upper threshold from slider - // and set the lower to 0 (which forces edges merging) - cv::ocl::Canny(gray0_ocl, gray_ocl, 0, thresh, 5); - // dilate canny output to remove potential - // holes between edge segments - ocl::dilate(gray_ocl, gray_ocl, Mat(), Point(-1,-1)); - gray = Mat(gray_ocl); - } - else - { - // apply threshold if l!=0: - // tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0 - cv::ocl::threshold(gray0_ocl, gray_ocl, (l+1)*255/N, 255, THRESH_BINARY); - gray = gray_ocl; - } - - // find contours and store them all as a list - findContours(gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE); - - vector approx; - // test each contour - for( size_t i = 0; i < contours.size(); i++ ) - { - // approximate contour with accuracy proportional - // to the contour perimeter - approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true); - - // square contours should have 4 vertices after approximation - // relatively large area (to filter out noisy contours) - // and be convex. - // Note: absolute value of an area is used because - // area may be positive or negative - in accordance with the - // contour orientation - if( approx.size() == 4 && - fabs(contourArea(Mat(approx))) > 1000 && - isContourConvex(Mat(approx)) ) - { - double maxCosine = 0; - for( int j = 2; j < 5; j++ ) - { - // find the maximum cosine of the angle between joint edges - double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1])); - maxCosine = MAX(maxCosine, cosine); - } - - // if cosines of all angles are small - // (all angles are ~90 degree) then write quandrange - // vertices to resultant sequence - if( maxCosine < 0.3 ) - squares.push_back(approx); - } - } - } - } -} - - -// the function draws all the squares in the image -static void drawSquares( Mat& image, const vector >& squares ) -{ - for( size_t i = 0; i < squares.size(); i++ ) - { - const Point* p = &squares[i][0]; - int n = (int)squares[i].size(); - polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, LINE_AA); - } -} - - -// draw both pure-C++ and ocl square results onto a single image -static Mat drawSquaresBoth( const Mat& image, - const vector >& sqsCPP, - const vector >& sqsOCL -) -{ - Mat imgToShow(Size(image.cols * 2, image.rows), image.type()); - Mat lImg = imgToShow(Rect(Point(0, 0), image.size())); - Mat rImg = imgToShow(Rect(Point(image.cols, 0), image.size())); - image.copyTo(lImg); - image.copyTo(rImg); - drawSquares(lImg, sqsCPP); - drawSquares(rImg, sqsOCL); - float fontScale = 0.8f; - Scalar white = Scalar::all(255), black = Scalar::all(0); - - putText(lImg, "C++", Point(10, 20), FONT_HERSHEY_COMPLEX_SMALL, fontScale, black, 2); - putText(rImg, "OCL", Point(10, 20), FONT_HERSHEY_COMPLEX_SMALL, fontScale, black, 2); - putText(lImg, "C++", Point(10, 20), FONT_HERSHEY_COMPLEX_SMALL, fontScale, white, 1); - putText(rImg, "OCL", Point(10, 20), FONT_HERSHEY_COMPLEX_SMALL, fontScale, white, 1); - - return imgToShow; -} - - -int main(int argc, char** argv) -{ - const char* keys = - "{ i | input | | specify input image }" - "{ o | output | squares_output.jpg | specify output save path}" - "{ h | help | false | print help message }"; - CommandLineParser cmd(argc, argv, keys); - string inputName = cmd.get("i"); - string outfile = cmd.get("o"); - - if(cmd.get("help")) - { - cout << "Usage : squares [options]" << endl; - cout << "Available options:" << endl; - cmd.printMessage(); - return EXIT_SUCCESS; - } - - int iterations = 10; - namedWindow( wndname, WINDOW_AUTOSIZE ); - vector > squares_cpu, squares_ocl; - - Mat image = imread(inputName, 1); - if( image.empty() ) - { - cout << "Couldn't load " << inputName << endl; - return EXIT_FAILURE; - } - - int j = iterations; - int64 t_ocl = 0, t_cpp = 0; - //warm-ups - cout << "warming up ..." << endl; - findSquares(image, squares_cpu); - findSquares_ocl(image, squares_ocl); - - -#ifdef ACCURACY_CHECK - cout << "Checking ocl accuracy ... " << endl; - cout << (checkPoints(squares_cpu, squares_ocl) ? "Pass" : "Failed") << endl; -#endif - do - { - int64 t_start = cv::getTickCount(); - findSquares(image, squares_cpu); - t_cpp += cv::getTickCount() - t_start; - - - t_start = cv::getTickCount(); - findSquares_ocl(image, squares_ocl); - t_ocl += cv::getTickCount() - t_start; - cout << "run loop: " << j << endl; - } - while(--j); - cout << "cpp average time: " << 1000.0f * (double)t_cpp / getTickFrequency() / iterations << "ms" << endl; - cout << "ocl average time: " << 1000.0f * (double)t_ocl / getTickFrequency() / iterations << "ms" << endl; - - Mat result = drawSquaresBoth(image, squares_cpu, squares_ocl); - imshow(wndname, result); - imwrite(outfile, result); - waitKey(0); - - return EXIT_SUCCESS; -} diff --git a/samples/ocl/stereo_match.cpp b/samples/ocl/stereo_match.cpp deleted file mode 100644 index 880ad51c0..000000000 --- a/samples/ocl/stereo_match.cpp +++ /dev/null @@ -1,384 +0,0 @@ -#include -#include -#include -#include -#include - -#include "opencv2/core/utility.hpp" -#include "opencv2/ocl/ocl.hpp" -#include "opencv2/highgui/highgui.hpp" - -using namespace cv; -using namespace std; -using namespace ocl; - - -struct App -{ - App(CommandLineParser& cmd); - void run(); - void handleKey(char key); - void printParams() const; - - void workBegin() - { - work_begin = getTickCount(); - } - void workEnd() - { - int64 d = getTickCount() - work_begin; - double f = getTickFrequency(); - work_fps = f / d; - } - string method_str() const - { - switch (method) - { - case BM: - return "BM"; - case BP: - return "BP"; - case CSBP: - return "CSBP"; - } - return ""; - } - string text() const - { - stringstream ss; - ss << "(" << method_str() << ") FPS: " << setiosflags(ios::left) - << setprecision(4) << work_fps; - return ss.str(); - } -private: - bool running, write_once; - - Mat left_src, right_src; - Mat left, right; - oclMat d_left, d_right; - - StereoBM_OCL bm; - StereoBeliefPropagation bp; - StereoConstantSpaceBP csbp; - - int64 work_begin; - double work_fps; - - string l_img, r_img; - string out_img; - enum {BM, BP, CSBP} method; - int ndisp; // Max disparity + 1 - enum {GPU, CPU} type; -}; - -int main(int argc, char** argv) -{ - const char* keys = - "{ h | help | false | print help message }" - "{ l | left | | specify left image }" - "{ r | right | | specify right image }" - "{ m | method | BM | specify match method(BM/BP/CSBP) }" - "{ n | ndisp | 64 | specify number of disparity levels }" - "{ o | output | stereo_match_output.jpg | specify output path when input is images}"; - - CommandLineParser cmd(argc, argv, keys); - if (cmd.get("help")) - { - cout << "Available options:" << endl; - cmd.printMessage(); - return 0; - } - - try - { - App app(cmd); - cout << "Device name:" << cv::ocl::Context::getContext()->getDeviceInfo().deviceName << endl; - - app.run(); - } - catch (const exception& e) - { - cout << "error: " << e.what() << endl; - } - - return EXIT_SUCCESS; -} - -App::App(CommandLineParser& cmd) - : running(false),method(BM) -{ - cout << "stereo_match_ocl sample\n"; - cout << "\nControls:\n" - << "\tesc - exit\n" - << "\to - save output image once\n" - << "\tp - print current parameters\n" - << "\tg - convert source images into gray\n" - << "\tm - change stereo match method\n" - << "\ts - change Sobel prefiltering flag (for BM only)\n" - << "\t1/q - increase/decrease maximum disparity\n" - << "\t2/w - increase/decrease window size (for BM only)\n" - << "\t3/e - increase/decrease iteration count (for BP and CSBP only)\n" - << "\t4/r - increase/decrease level count (for BP and CSBP only)\n"; - - l_img = cmd.get("l"); - r_img = cmd.get("r"); - string mstr = cmd.get("m"); - if(mstr == "BM") method = BM; - else if(mstr == "BP") method = BP; - else if(mstr == "CSBP") method = CSBP; - else cout << "unknown method!\n"; - ndisp = cmd.get("n"); - out_img = cmd.get("o"); - write_once = false; -} - - -void App::run() -{ - // Load images - left_src = imread(l_img); - right_src = imread(r_img); - if (left_src.empty()) throw runtime_error("can't open file \"" + l_img + "\""); - if (right_src.empty()) throw runtime_error("can't open file \"" + r_img + "\""); - - cvtColor(left_src, left, COLOR_BGR2GRAY); - cvtColor(right_src, right, COLOR_BGR2GRAY); - - d_left.upload(left); - d_right.upload(right); - - imshow("left", left); - imshow("right", right); - - // Set common parameters - bm.ndisp = ndisp; - bp.ndisp = ndisp; - csbp.ndisp = ndisp; - - cout << endl; - printParams(); - - running = true; - while (running) - { - // Prepare disparity map of specified type - Mat disp; - oclMat d_disp; - workBegin(); - switch (method) - { - case BM: - if (d_left.channels() > 1 || d_right.channels() > 1) - { - cout << "BM doesn't support color images\n"; - cvtColor(left_src, left, COLOR_BGR2GRAY); - cvtColor(right_src, right, COLOR_BGR2GRAY); - cout << "image_channels: " << left.channels() << endl; - d_left.upload(left); - d_right.upload(right); - imshow("left", left); - imshow("right", right); - } - bm(d_left, d_right, d_disp); - break; - case BP: - bp(d_left, d_right, d_disp); - break; - case CSBP: - csbp(d_left, d_right, d_disp); - break; - } - - // Show results - d_disp.download(disp); - workEnd(); - - if (method != BM) - { - disp.convertTo(disp, 0); - } - putText(disp, text(), Point(5, 25), FONT_HERSHEY_SIMPLEX, 1.0, Scalar::all(255)); - imshow("disparity", disp); - if(write_once) - { - imwrite(out_img, disp); - write_once = false; - } - handleKey((char)waitKey(3)); - } -} - - -void App::printParams() const -{ - cout << "--- Parameters ---\n"; - cout << "image_size: (" << left.cols << ", " << left.rows << ")\n"; - cout << "image_channels: " << left.channels() << endl; - cout << "method: " << method_str() << endl - << "ndisp: " << ndisp << endl; - switch (method) - { - case BM: - cout << "win_size: " << bm.winSize << endl; - cout << "prefilter_sobel: " << bm.preset << endl; - break; - case BP: - cout << "iter_count: " << bp.iters << endl; - cout << "level_count: " << bp.levels << endl; - break; - case CSBP: - cout << "iter_count: " << csbp.iters << endl; - cout << "level_count: " << csbp.levels << endl; - break; - } - cout << endl; -} - - -void App::handleKey(char key) -{ - switch (key) - { - case 27: - running = false; - break; - case 'p': - case 'P': - printParams(); - break; - case 'g': - case 'G': - if (left.channels() == 1 && method != BM) - { - left = left_src; - right = right_src; - } - else - { - cvtColor(left_src, left, COLOR_BGR2GRAY); - cvtColor(right_src, right, COLOR_BGR2GRAY); - } - d_left.upload(left); - d_right.upload(right); - cout << "image_channels: " << left.channels() << endl; - imshow("left", left); - imshow("right", right); - break; - case 'm': - case 'M': - switch (method) - { - case BM: - method = BP; - break; - case BP: - method = CSBP; - break; - case CSBP: - method = BM; - break; - } - cout << "method: " << method_str() << endl; - break; - case 's': - case 'S': - if (method == BM) - { - switch (bm.preset) - { - case StereoBM_OCL::BASIC_PRESET: - bm.preset = StereoBM_OCL::PREFILTER_XSOBEL; - break; - case StereoBM_OCL::PREFILTER_XSOBEL: - bm.preset = StereoBM_OCL::BASIC_PRESET; - break; - } - cout << "prefilter_sobel: " << bm.preset << endl; - } - break; - case '1': - ndisp == 1 ? ndisp = 8 : ndisp += 8; - cout << "ndisp: " << ndisp << endl; - bm.ndisp = ndisp; - bp.ndisp = ndisp; - csbp.ndisp = ndisp; - break; - case 'q': - case 'Q': - ndisp = max(ndisp - 8, 1); - cout << "ndisp: " << ndisp << endl; - bm.ndisp = ndisp; - bp.ndisp = ndisp; - csbp.ndisp = ndisp; - break; - case '2': - if (method == BM) - { - bm.winSize = min(bm.winSize + 1, 51); - cout << "win_size: " << bm.winSize << endl; - } - break; - case 'w': - case 'W': - if (method == BM) - { - bm.winSize = max(bm.winSize - 1, 2); - cout << "win_size: " << bm.winSize << endl; - } - break; - case '3': - if (method == BP) - { - bp.iters += 1; - cout << "iter_count: " << bp.iters << endl; - } - else if (method == CSBP) - { - csbp.iters += 1; - cout << "iter_count: " << csbp.iters << endl; - } - break; - case 'e': - case 'E': - if (method == BP) - { - bp.iters = max(bp.iters - 1, 1); - cout << "iter_count: " << bp.iters << endl; - } - else if (method == CSBP) - { - csbp.iters = max(csbp.iters - 1, 1); - cout << "iter_count: " << csbp.iters << endl; - } - break; - case '4': - if (method == BP) - { - bp.levels += 1; - cout << "level_count: " << bp.levels << endl; - } - else if (method == CSBP) - { - csbp.levels += 1; - cout << "level_count: " << csbp.levels << endl; - } - break; - case 'r': - case 'R': - if (method == BP) - { - bp.levels = max(bp.levels - 1, 1); - cout << "level_count: " << bp.levels << endl; - } - else if (method == CSBP) - { - csbp.levels = max(csbp.levels - 1, 1); - cout << "level_count: " << csbp.levels << endl; - } - break; - case 'o': - case 'O': - write_once = true; - break; - } -} diff --git a/samples/ocl/surf_matcher.cpp b/samples/ocl/surf_matcher.cpp deleted file mode 100644 index f88678b7b..000000000 --- a/samples/ocl/surf_matcher.cpp +++ /dev/null @@ -1,329 +0,0 @@ -#include -#include -#include "opencv2/core/core.hpp" -#include "opencv2/core/utility.hpp" -#include "opencv2/highgui/highgui.hpp" -#include "opencv2/ocl/ocl.hpp" -#include "opencv2/nonfree/ocl.hpp" -#include "opencv2/calib3d/calib3d.hpp" -#include "opencv2/nonfree/nonfree.hpp" - -using namespace cv; -using namespace cv::ocl; - -const int LOOP_NUM = 10; -const int GOOD_PTS_MAX = 50; -const float GOOD_PORTION = 0.15f; - -int64 work_begin = 0; -int64 work_end = 0; - -static void workBegin() -{ - work_begin = getTickCount(); -} - -static void workEnd() -{ - work_end = getTickCount() - work_begin; -} - -static double getTime() -{ - return work_end /((double)getTickFrequency() * 1000.); -} - -template -struct SURFDetector -{ - KPDetector surf; - SURFDetector(double hessian = 800.0) - :surf(hessian) - { - } - template - void operator()(const T& in, const T& mask, std::vector& pts, T& descriptors, bool useProvided = false) - { - surf(in, mask, pts, descriptors, useProvided); - } -}; - -template -struct SURFMatcher -{ - KPMatcher matcher; - template - void match(const T& in1, const T& in2, std::vector& matches) - { - matcher.match(in1, in2, matches); - } -}; - -static Mat drawGoodMatches( - const Mat& cpu_img1, - const Mat& cpu_img2, - const std::vector& keypoints1, - const std::vector& keypoints2, - std::vector& matches, - std::vector& scene_corners_ - ) -{ - //-- Sort matches and preserve top 10% matches - std::sort(matches.begin(), matches.end()); - std::vector< DMatch > good_matches; - double minDist = matches.front().distance, - maxDist = matches.back().distance; - - const int ptsPairs = std::min(GOOD_PTS_MAX, (int)(matches.size() * GOOD_PORTION)); - for( int i = 0; i < ptsPairs; i++ ) - { - good_matches.push_back( matches[i] ); - } - std::cout << "\nMax distance: " << maxDist << std::endl; - std::cout << "Min distance: " << minDist << std::endl; - - std::cout << "Calculating homography using " << ptsPairs << " point pairs." << std::endl; - - // drawing the results - Mat img_matches; - drawMatches( cpu_img1, keypoints1, cpu_img2, keypoints2, - good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), - std::vector(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); - - //-- Localize the object - std::vector obj; - std::vector scene; - - for( size_t i = 0; i < good_matches.size(); i++ ) - { - //-- Get the keypoints from the good matches - obj.push_back( keypoints1[ good_matches[i].queryIdx ].pt ); - scene.push_back( keypoints2[ good_matches[i].trainIdx ].pt ); - } - //-- Get the corners from the image_1 ( the object to be "detected" ) - std::vector obj_corners(4); - obj_corners[0] = Point(0,0); - obj_corners[1] = Point( cpu_img1.cols, 0 ); - obj_corners[2] = Point( cpu_img1.cols, cpu_img1.rows ); - obj_corners[3] = Point( 0, cpu_img1.rows ); - std::vector scene_corners(4); - - Mat H = findHomography( obj, scene, RANSAC ); - perspectiveTransform( obj_corners, scene_corners, H); - - scene_corners_ = scene_corners; - - //-- Draw lines between the corners (the mapped object in the scene - image_2 ) - line( img_matches, - scene_corners[0] + Point2f( (float)cpu_img1.cols, 0), scene_corners[1] + Point2f( (float)cpu_img1.cols, 0), - Scalar( 0, 255, 0), 2, LINE_AA ); - line( img_matches, - scene_corners[1] + Point2f( (float)cpu_img1.cols, 0), scene_corners[2] + Point2f( (float)cpu_img1.cols, 0), - Scalar( 0, 255, 0), 2, LINE_AA ); - line( img_matches, - scene_corners[2] + Point2f( (float)cpu_img1.cols, 0), scene_corners[3] + Point2f( (float)cpu_img1.cols, 0), - Scalar( 0, 255, 0), 2, LINE_AA ); - line( img_matches, - scene_corners[3] + Point2f( (float)cpu_img1.cols, 0), scene_corners[0] + Point2f( (float)cpu_img1.cols, 0), - Scalar( 0, 255, 0), 2, LINE_AA ); - return img_matches; -} - -//////////////////////////////////////////////////// -// This program demonstrates the usage of SURF_OCL. -// use cpu findHomography interface to calculate the transformation matrix -int main(int argc, char* argv[]) -{ - const char* keys = - "{ help h | false | print help message }" - "{ left l | | specify left image }" - "{ right r | | specify right image }" - "{ output o | SURF_output.jpg | specify output save path (only works in CPU or GPU only mode) }" - "{ use_cpu c | false | use CPU algorithms }" - "{ use_all a | false | use both CPU and GPU algorithms}"; - - CommandLineParser cmd(argc, argv, keys); - if (cmd.get("help")) - { - std::cout << "Usage: surf_matcher [options]" << std::endl; - std::cout << "Available options:" << std::endl; - cmd.printMessage(); - return EXIT_SUCCESS; - } - - Mat cpu_img1, cpu_img2, cpu_img1_grey, cpu_img2_grey; - oclMat img1, img2; - bool useCPU = cmd.get("c"); - bool useGPU = false; - bool useALL = cmd.get("a"); - - std::string outpath = cmd.get("o"); - - cpu_img1 = imread(cmd.get("l")); - CV_Assert(!cpu_img1.empty()); - cvtColor(cpu_img1, cpu_img1_grey, COLOR_BGR2GRAY); - img1 = cpu_img1_grey; - - cpu_img2 = imread(cmd.get("r")); - CV_Assert(!cpu_img2.empty()); - cvtColor(cpu_img2, cpu_img2_grey, COLOR_BGR2GRAY); - img2 = cpu_img2_grey; - - if (useALL) - useCPU = useGPU = false; - else if(!useCPU && !useALL) - useGPU = true; - - if(!useCPU) - std::cout - << "Device name:" - << cv::ocl::Context::getContext()->getDeviceInfo().deviceName - << std::endl; - - double surf_time = 0.; - - //declare input/output - std::vector keypoints1, keypoints2; - std::vector matches; - - std::vector gpu_keypoints1; - std::vector gpu_keypoints2; - std::vector gpu_matches; - - Mat descriptors1CPU, descriptors2CPU; - - oclMat keypoints1GPU, keypoints2GPU; - oclMat descriptors1GPU, descriptors2GPU; - - //instantiate detectors/matchers - SURFDetector cpp_surf; - SURFDetector ocl_surf; - - SURFMatcher cpp_matcher; - SURFMatcher ocl_matcher; - - //-- start of timing section - if (useCPU) - { - for (int i = 0; i <= LOOP_NUM; i++) - { - if(i == 1) workBegin(); - cpp_surf(cpu_img1_grey, Mat(), keypoints1, descriptors1CPU); - cpp_surf(cpu_img2_grey, Mat(), keypoints2, descriptors2CPU); - cpp_matcher.match(descriptors1CPU, descriptors2CPU, matches); - } - workEnd(); - std::cout << "CPP: FOUND " << keypoints1.size() << " keypoints on first image" << std::endl; - std::cout << "CPP: FOUND " << keypoints2.size() << " keypoints on second image" << std::endl; - - surf_time = getTime(); - std::cout << "SURF run time: " << surf_time / LOOP_NUM << " ms" << std::endl<<"\n"; - } - else if(useGPU) - { - for (int i = 0; i <= LOOP_NUM; i++) - { - if(i == 1) workBegin(); - ocl_surf(img1, oclMat(), keypoints1, descriptors1GPU); - ocl_surf(img2, oclMat(), keypoints2, descriptors2GPU); - ocl_matcher.match(descriptors1GPU, descriptors2GPU, matches); - } - workEnd(); - std::cout << "OCL: FOUND " << keypoints1.size() << " keypoints on first image" << std::endl; - std::cout << "OCL: FOUND " << keypoints2.size() << " keypoints on second image" << std::endl; - - surf_time = getTime(); - std::cout << "SURF run time: " << surf_time / LOOP_NUM << " ms" << std::endl<<"\n"; - } - else - { - //cpu runs - for (int i = 0; i <= LOOP_NUM; i++) - { - if(i == 1) workBegin(); - cpp_surf(cpu_img1_grey, Mat(), keypoints1, descriptors1CPU); - cpp_surf(cpu_img2_grey, Mat(), keypoints2, descriptors2CPU); - cpp_matcher.match(descriptors1CPU, descriptors2CPU, matches); - } - workEnd(); - std::cout << "\nCPP: FOUND " << keypoints1.size() << " keypoints on first image" << std::endl; - std::cout << "CPP: FOUND " << keypoints2.size() << " keypoints on second image" << std::endl; - - surf_time = getTime(); - std::cout << "(CPP)SURF run time: " << surf_time / LOOP_NUM << " ms" << std::endl; - - //gpu runs - for (int i = 0; i <= LOOP_NUM; i++) - { - if(i == 1) workBegin(); - ocl_surf(img1, oclMat(), gpu_keypoints1, descriptors1GPU); - ocl_surf(img2, oclMat(), gpu_keypoints2, descriptors2GPU); - ocl_matcher.match(descriptors1GPU, descriptors2GPU, gpu_matches); - } - workEnd(); - std::cout << "\nOCL: FOUND " << keypoints1.size() << " keypoints on first image" << std::endl; - std::cout << "OCL: FOUND " << keypoints2.size() << " keypoints on second image" << std::endl; - - surf_time = getTime(); - std::cout << "(OCL)SURF run time: " << surf_time / LOOP_NUM << " ms" << std::endl<<"\n"; - - } - - //-------------------------------------------------------------------------- - std::vector cpu_corner; - Mat img_matches = drawGoodMatches(cpu_img1, cpu_img2, keypoints1, keypoints2, matches, cpu_corner); - - std::vector gpu_corner; - Mat ocl_img_matches; - if(useALL || (!useCPU&&!useGPU)) - { - ocl_img_matches = drawGoodMatches(cpu_img1, cpu_img2, gpu_keypoints1, gpu_keypoints2, gpu_matches, gpu_corner); - - //check accuracy - std::cout<<"\nCheck accuracy:\n"; - - if(cpu_corner.size()!=gpu_corner.size()) - std::cout<<"Failed\n"; - else - { - bool result = false; - for(size_t i = 0; i < cpu_corner.size(); i++) - { - if((std::abs(cpu_corner[i].x - gpu_corner[i].x) > 10) - ||(std::abs(cpu_corner[i].y - gpu_corner[i].y) > 10)) - { - std::cout<<"Failed\n"; - result = false; - break; - } - result = true; - } - if(result) - std::cout<<"Passed\n"; - } - } - - //-- Show detected matches - if (useCPU) - { - namedWindow("cpu surf matches", 0); - imshow("cpu surf matches", img_matches); - imwrite(outpath, img_matches); - } - else if(useGPU) - { - namedWindow("ocl surf matches", 0); - imshow("ocl surf matches", img_matches); - imwrite(outpath, img_matches); - } - else - { - namedWindow("cpu surf matches", 0); - imshow("cpu surf matches", img_matches); - - namedWindow("ocl surf matches", 0); - imshow("ocl surf matches", ocl_img_matches); - } - waitKey(0); - return EXIT_SUCCESS; -} diff --git a/samples/ocl/tvl1_optical_flow.cpp b/samples/ocl/tvl1_optical_flow.cpp deleted file mode 100644 index f678dd6fd..000000000 --- a/samples/ocl/tvl1_optical_flow.cpp +++ /dev/null @@ -1,237 +0,0 @@ -#include -#include -#include - -#include "opencv2/core/utility.hpp" -#include "opencv2/highgui/highgui.hpp" -#include "opencv2/ocl/ocl.hpp" -#include "opencv2/video/video.hpp" - -using namespace std; -using namespace cv; -using namespace cv::ocl; - -typedef unsigned char uchar; -#define LOOP_NUM 10 -int64 work_begin = 0; -int64 work_end = 0; - -static void workBegin() -{ - work_begin = getTickCount(); -} -static void workEnd() -{ - work_end += (getTickCount() - work_begin); -} -static double getTime() -{ - return work_end * 1000. / getTickFrequency(); -} - -template inline T clamp (T x, T a, T b) -{ - return ((x) > (a) ? ((x) < (b) ? (x) : (b)) : (a)); -} - -template inline T mapValue(T x, T a, T b, T c, T d) -{ - x = clamp(x, a, b); - return c + (d - c) * (x - a) / (b - a); -} - -static void getFlowField(const Mat& u, const Mat& v, Mat& flowField) -{ - float maxDisplacement = 1.0f; - - for (int i = 0; i < u.rows; ++i) - { - const float* ptr_u = u.ptr(i); - const float* ptr_v = v.ptr(i); - - for (int j = 0; j < u.cols; ++j) - { - float d = max(fabsf(ptr_u[j]), fabsf(ptr_v[j])); - - if (d > maxDisplacement) - maxDisplacement = d; - } - } - - flowField.create(u.size(), CV_8UC4); - - for (int i = 0; i < flowField.rows; ++i) - { - const float* ptr_u = u.ptr(i); - const float* ptr_v = v.ptr(i); - - - Vec4b* row = flowField.ptr(i); - - for (int j = 0; j < flowField.cols; ++j) - { - row[j][0] = 0; - row[j][1] = static_cast (mapValue (-ptr_v[j], -maxDisplacement, maxDisplacement, 0.0f, 255.0f)); - row[j][2] = static_cast (mapValue ( ptr_u[j], -maxDisplacement, maxDisplacement, 0.0f, 255.0f)); - row[j][3] = 255; - } - } -} - - -int main(int argc, const char* argv[]) -{ - const char* keys = - "{ h | help | false | print help message }" - "{ l | left | | specify left image }" - "{ r | right | | specify right image }" - "{ o | output | tvl1_output.jpg | specify output save path }" - "{ c | camera | 0 | enable camera capturing }" - "{ s | use_cpu | false | use cpu or gpu to process the image }" - "{ v | video | | use video as input }"; - - CommandLineParser cmd(argc, argv, keys); - - if (cmd.get("help")) - { - cout << "Usage: pyrlk_optical_flow [options]" << endl; - cout << "Available options:" << endl; - cmd.printMessage(); - return EXIT_SUCCESS; - } - - string fname0 = cmd.get("l"); - string fname1 = cmd.get("r"); - string vdofile = cmd.get("v"); - string outpath = cmd.get("o"); - bool useCPU = cmd.get("s"); - bool useCamera = cmd.get("c"); - int inputName = cmd.get("c"); - - Mat frame0 = imread(fname0, cv::IMREAD_GRAYSCALE); - Mat frame1 = imread(fname1, cv::IMREAD_GRAYSCALE); - cv::Ptr alg = cv::createOptFlow_DualTVL1(); - cv::ocl::OpticalFlowDual_TVL1_OCL d_alg; - - Mat flow, show_flow; - Mat flow_vec[2]; - if (frame0.empty() || frame1.empty()) - useCamera = true; - - if (useCamera) - { - VideoCapture capture; - Mat frame, frameCopy; - Mat frame0Gray, frame1Gray; - Mat ptr0, ptr1; - - if(vdofile.empty()) - capture.open( inputName ); - else - capture.open(vdofile.c_str()); - - if(!capture.isOpened()) - { - if(vdofile.empty()) - cout << "Capture from CAM " << inputName << " didn't work" << endl; - else - cout << "Capture from file " << vdofile << " failed" <calc(ptr0, ptr1, flow); - split(flow, flow_vec); - } - else - { - oclMat d_flowx, d_flowy; - d_alg(oclMat(ptr0), oclMat(ptr1), d_flowx, d_flowy); - d_flowx.download(flow_vec[0]); - d_flowy.download(flow_vec[1]); - } - if (i%2 == 1) - frame1.copyTo(frameCopy); - else - frame0.copyTo(frameCopy); - getFlowField(flow_vec[0], flow_vec[1], show_flow); - imshow("tvl1 optical flow field", show_flow); - } - - if( waitKey( 10 ) >= 0 ) - break; - } - - capture.release(); - } - else - { -nocamera: - oclMat d_flowx, d_flowy; - for(int i = 0; i <= LOOP_NUM; i ++) - { - cout << "loop" << i << endl; - - if (i > 0) workBegin(); - if (useCPU) - { - alg->calc(frame0, frame1, flow); - split(flow, flow_vec); - } - else - { - d_alg(oclMat(frame0), oclMat(frame1), d_flowx, d_flowy); - d_flowx.download(flow_vec[0]); - d_flowy.download(flow_vec[1]); - } - if (i > 0 && i <= LOOP_NUM) - workEnd(); - - if (i == LOOP_NUM) - { - if (useCPU) - cout << "average CPU time (noCamera) : "; - else - cout << "average GPU time (noCamera) : "; - cout << getTime() / LOOP_NUM << " ms" << endl; - - getFlowField(flow_vec[0], flow_vec[1], show_flow); - imshow("PyrLK [Sparse]", show_flow); - imwrite(outpath, show_flow); - } - } - } - - waitKey(); - - return EXIT_SUCCESS; -} From 50cf152977041c5705de25d7787aa0a553040beb Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 31 Jan 2014 14:00:05 +0400 Subject: [PATCH 291/295] cached commonly used device properties --- modules/core/src/ocl.cpp | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 7201fca71..9959b54ea 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -1626,6 +1626,16 @@ struct Device::Impl { handle = (cl_device_id)d; refcount = 1; + + name_ = getStrProp(CL_DEVICE_NAME); + version_ = getStrProp(CL_DEVICE_VERSION); + doubleFPConfig_ = getProp(CL_DEVICE_DOUBLE_FP_CONFIG); + hostUnifiedMemory_ = getBoolProp(CL_DEVICE_HOST_UNIFIED_MEMORY); + maxComputeUnits_ = getProp(CL_DEVICE_MAX_COMPUTE_UNITS); + maxWorkGroupSize_ = getProp(CL_DEVICE_MAX_WORK_GROUP_SIZE); + type_ = getProp(CL_DEVICE_TYPE); + deviceVersion_ = getStrProp(CL_DEVICE_VERSION); + driverVersion_ = getStrProp(CL_DRIVER_VERSION); } template @@ -1657,6 +1667,16 @@ struct Device::Impl IMPLEMENT_REFCOUNTABLE(); cl_device_id handle; + + String name_; + String version_; + int doubleFPConfig_; + bool hostUnifiedMemory_; + int maxComputeUnits_; + size_t maxWorkGroupSize_; + int type_; + String deviceVersion_; + String driverVersion_; }; @@ -1708,13 +1728,13 @@ void* Device::ptr() const } String Device::name() const -{ return p ? p->getStrProp(CL_DEVICE_NAME) : String(); } +{ return p ? p->name_ : String(); } String Device::extensions() const { return p ? p->getStrProp(CL_DEVICE_EXTENSIONS) : String(); } String Device::version() const -{ return p ? p->getStrProp(CL_DEVICE_VERSION) : String(); } +{ return p ? p->version_ : String(); } String Device::vendor() const { return p ? p->getStrProp(CL_DEVICE_VENDOR) : String(); } @@ -1726,13 +1746,13 @@ String Device::OpenCLVersion() const { return p ? p->getStrProp(CL_DEVICE_EXTENSIONS) : String(); } String Device::deviceVersion() const -{ return p ? p->getStrProp(CL_DEVICE_VERSION) : String(); } +{ return p ? p->deviceVersion_ : String(); } String Device::driverVersion() const -{ return p ? p->getStrProp(CL_DRIVER_VERSION) : String(); } +{ return p ? p->driverVersion_ : String(); } int Device::type() const -{ return p ? p->getProp(CL_DEVICE_TYPE) : 0; } +{ return p ? p->type_ : 0; } int Device::addressBits() const { return p ? p->getProp(CL_DEVICE_ADDRESS_BITS) : 0; } @@ -1751,7 +1771,7 @@ bool Device::linkerAvailable() const #endif int Device::doubleFPConfig() const -{ return p ? p->getProp(CL_DEVICE_DOUBLE_FP_CONFIG) : 0; } +{ return p ? p->doubleFPConfig_ : 0; } int Device::singleFPConfig() const { return p ? p->getProp(CL_DEVICE_SINGLE_FP_CONFIG) : 0; } @@ -1791,7 +1811,7 @@ int Device::localMemType() const { return p ? p->getProp(CL_DEVICE_LOCAL_MEM_TYPE) : 0; } bool Device::hostUnifiedMemory() const -{ return p ? p->getBoolProp(CL_DEVICE_HOST_UNIFIED_MEMORY) : false; } +{ return p ? p->hostUnifiedMemory_ : false; } bool Device::imageSupport() const { return p ? p->getBoolProp(CL_DEVICE_IMAGE_SUPPORT) : false; } @@ -1829,7 +1849,7 @@ int Device::maxClockFrequency() const { return p ? p->getProp(CL_DEVICE_MAX_CLOCK_FREQUENCY) : 0; } int Device::maxComputeUnits() const -{ return p ? p->getProp(CL_DEVICE_MAX_COMPUTE_UNITS) : 0; } +{ return p ? p->maxComputeUnits_ : 0; } int Device::maxConstantArgs() const { return p ? p->getProp(CL_DEVICE_MAX_CONSTANT_ARGS) : 0; } @@ -1853,7 +1873,7 @@ int Device::maxSamplers() const { return p ? p->getProp(CL_DEVICE_MAX_SAMPLERS) : 0; } size_t Device::maxWorkGroupSize() const -{ return p ? p->getProp(CL_DEVICE_MAX_WORK_GROUP_SIZE) : 0; } +{ return p ? p->maxWorkGroupSize_ : 0; } int Device::maxWorkItemDims() const { return p ? p->getProp(CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS) : 0; } From d15bf6261a7ab918850800cffaac3e766d6829bd Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 31 Jan 2014 14:39:03 +0400 Subject: [PATCH 292/295] redundant clFinish in upload since clEnqueueWriteBuffer above is already blocked --- modules/core/src/ocl.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 7201fca71..02053ddb4 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3582,8 +3582,6 @@ public: u->markHostCopyObsolete(true); u->markDeviceCopyObsolete(false); - - clFinish(q); } void copy(UMatData* src, UMatData* dst, int dims, const size_t sz[], From 9300af90cd8067f8a9f62adb1afd63b3e9aa395b Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 31 Jan 2014 14:42:38 +0400 Subject: [PATCH 293/295] imgproc/intersection: fix loop index --- modules/imgproc/src/intersection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/intersection.cpp b/modules/imgproc/src/intersection.cpp index cdee36663..dfebd260e 100644 --- a/modules/imgproc/src/intersection.cpp +++ b/modules/imgproc/src/intersection.cpp @@ -231,7 +231,7 @@ int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& r // Found a dupe, remove it std::swap(intersection[j], intersection.back()); intersection.pop_back(); - i--; // restart check + j--; // restart check } } } From c01e8e936182250f0bdda6c9d97b7b97be3906d8 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 30 Jan 2014 13:13:33 +0400 Subject: [PATCH 294/295] removed ABF --- modules/imgproc/doc/filtering.rst | 23 -- modules/imgproc/include/opencv2/imgproc.hpp | 5 - modules/imgproc/src/smooth.cpp | 279 -------------------- 3 files changed, 307 deletions(-) diff --git a/modules/imgproc/doc/filtering.rst b/modules/imgproc/doc/filtering.rst index 166e83e9f..a055b129f 100755 --- a/modules/imgproc/doc/filtering.rst +++ b/modules/imgproc/doc/filtering.rst @@ -412,29 +412,6 @@ http://www.dai.ed.ac.uk/CVonline/LOCAL\_COPIES/MANDUCHI1/Bilateral\_Filtering.ht This filter does not work inplace. -adaptiveBilateralFilter ------------------------ -Applies the adaptive bilateral filter to an image. - -.. ocv:function:: void adaptiveBilateralFilter( InputArray src, OutputArray dst, Size ksize, double sigmaSpace, double maxSigmaColor = 20.0, Point anchor=Point(-1, -1), int borderType=BORDER_DEFAULT ) - -.. ocv:pyfunction:: cv2.adaptiveBilateralFilter(src, ksize, sigmaSpace[, dst[, anchor[, borderType]]]) -> dst - - :param src: The source image - - :param dst: The destination image; will have the same size and the same type as src - - :param ksize: The kernel size. This is the neighborhood where the local variance will be calculated, and where pixels will contribute (in a weighted manner). - - :param sigmaSpace: Filter sigma in the coordinate space. Larger value of the parameter means that farther pixels will influence each other (as long as their colors are close enough; see sigmaColor). Then d>0, it specifies the neighborhood size regardless of sigmaSpace, otherwise d is proportional to sigmaSpace. - - :param maxSigmaColor: Maximum allowed sigma color (will clamp the value calculated in the ksize neighborhood. Larger value of the parameter means that more dissimilar pixels will influence each other (as long as their colors are close enough; see sigmaColor). Then d>0, it specifies the neighborhood size regardless of sigmaSpace, otherwise d is proportional to sigmaSpace. - - :param borderType: Pixel extrapolation method. - -A main part of our strategy will be to load each raw pixel once, and reuse it to calculate all pixels in the output (filtered) image that need this pixel value. The math of the filter is that of the usual bilateral filter, except that the sigma color is calculated in the neighborhood, and clamped by the optional input value. - - blur ---- Blurs an image using the normalized box filter. diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 84de283c0..1c566b70b 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -1066,11 +1066,6 @@ CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT ); -//! smooths the image using adaptive bilateral filter -CV_EXPORTS_W void adaptiveBilateralFilter( InputArray src, OutputArray dst, Size ksize, - double sigmaSpace, double maxSigmaColor = 20.0, Point anchor=Point(-1, -1), - int borderType=BORDER_DEFAULT ); - //! smooths the image using the box filter. Each pixel is processed in O(1) time CV_EXPORTS_W void boxFilter( InputArray src, OutputArray dst, int ddepth, Size ksize, Point anchor = Point(-1,-1), diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 9eb959901..dde9920df 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -2624,285 +2624,6 @@ void cv::bilateralFilter( InputArray _src, OutputArray _dst, int d, "Bilateral filtering is only implemented for 8u and 32f images" ); } - -/****************************************************************************************\ - Adaptive Bilateral Filtering -\****************************************************************************************/ - -namespace cv -{ -#ifndef ABF_CALCVAR -#define ABF_CALCVAR 1 -#endif - -#ifndef ABF_FIXED_WEIGHT -#define ABF_FIXED_WEIGHT 0 -#endif - -#ifndef ABF_GAUSSIAN -#define ABF_GAUSSIAN 1 -#endif - -class adaptiveBilateralFilter_8u_Invoker : - public ParallelLoopBody -{ -public: - adaptiveBilateralFilter_8u_Invoker(Mat& _dest, const Mat& _temp, Size _ksize, double _sigma_space, double _maxSigmaColor, Point _anchor) : - temp(&_temp), dest(&_dest), ksize(_ksize), sigma_space(_sigma_space), maxSigma_Color(_maxSigmaColor), anchor(_anchor) - { - if( sigma_space <= 0 ) - sigma_space = 1; - CV_Assert((ksize.width & 1) && (ksize.height & 1)); - space_weight.resize(ksize.width * ksize.height); - double sigma2 = sigma_space * sigma_space; - int idx = 0; - int w = ksize.width / 2; - int h = ksize.height / 2; - for(int y=-h; y<=h; y++) - for(int x=-w; x<=w; x++) - { -#if ABF_GAUSSIAN - space_weight[idx++] = (float)exp ( -0.5*(x * x + y * y)/sigma2); -#else - space_weight[idx++] = (float)(sigma2 / (sigma2 + x * x + y * y)); -#endif - } - } - virtual void operator()(const Range& range) const - { - int cn = dest->channels(); - int anX = anchor.x; - - const uchar *tptr; - - for(int i = range.start;i < range.end; i++) - { - int startY = i; - if(cn == 1) - { - float var; - int currVal; - int sumVal = 0; - int sumValSqr = 0; - int currValCenter; - int currWRTCenter; - float weight; - float totalWeight = 0.; - float tmpSum = 0.; - - for(int j = 0;j < dest->cols *cn; j+=cn) - { - sumVal = 0; - sumValSqr= 0; - totalWeight = 0.; - tmpSum = 0.; - - // Top row: don't sum the very last element - int startLMJ = 0; - int endLMJ = ksize.width - 1; - int howManyAll = (anX *2 +1)*(ksize.width ); -#if ABF_CALCVAR - for(int x = startLMJ; x< endLMJ; x++) - { - tptr = temp->ptr(startY + x) +j; - for(int y=-anX; y<=anX; y++) - { - currVal = tptr[cn*(y+anX)]; - sumVal += currVal; - sumValSqr += (currVal *currVal); - } - } - var = ( (sumValSqr * howManyAll)- sumVal * sumVal ) / ( (float)(howManyAll*howManyAll)); - - if(var < 0.01) - var = 0.01f; - else if(var > (float)(maxSigma_Color*maxSigma_Color) ) - var = (float)(maxSigma_Color*maxSigma_Color) ; - -#else - var = maxSigmaColor*maxSigmaColor; -#endif - startLMJ = 0; - endLMJ = ksize.width; - tptr = temp->ptr(startY + (startLMJ+ endLMJ)/2); - currValCenter =tptr[j+cn*anX]; - for(int x = startLMJ; x< endLMJ; x++) - { - tptr = temp->ptr(startY + x) +j; - for(int y=-anX; y<=anX; y++) - { -#if ABF_FIXED_WEIGHT - weight = 1.0; -#else - currVal = tptr[cn*(y+anX)]; - currWRTCenter = currVal - currValCenter; - -#if ABF_GAUSSIAN - weight = exp ( -0.5f * currWRTCenter * currWRTCenter/var ) * space_weight[x*ksize.width+y+anX]; -#else - weight = var / ( var + (currWRTCenter * currWRTCenter) ) * space_weight[x*ksize.width+y+anX]; -#endif - -#endif - tmpSum += ((float)tptr[cn*(y+anX)] * weight); - totalWeight += weight; - } - } - tmpSum /= totalWeight; - - dest->at(startY ,j)= static_cast(tmpSum); - } - } - else - { - assert(cn == 3); - float var_b, var_g, var_r; - int currVal_b, currVal_g, currVal_r; - int sumVal_b= 0, sumVal_g= 0, sumVal_r= 0; - int sumValSqr_b= 0, sumValSqr_g= 0, sumValSqr_r= 0; - int currValCenter_b= 0, currValCenter_g= 0, currValCenter_r= 0; - int currWRTCenter_b, currWRTCenter_g, currWRTCenter_r; - float weight_b, weight_g, weight_r; - float totalWeight_b= 0., totalWeight_g= 0., totalWeight_r= 0.; - float tmpSum_b = 0., tmpSum_g= 0., tmpSum_r = 0.; - - for(int j = 0;j < dest->cols *cn; j+=cn) - { - sumVal_b= 0, sumVal_g= 0, sumVal_r= 0; - sumValSqr_b= 0, sumValSqr_g= 0, sumValSqr_r= 0; - totalWeight_b= 0., totalWeight_g= 0., totalWeight_r= 0.; - tmpSum_b = 0., tmpSum_g= 0., tmpSum_r = 0.; - - // Top row: don't sum the very last element - int startLMJ = 0; - int endLMJ = ksize.width - 1; - int howManyAll = (anX *2 +1)*(ksize.width); -#if ABF_CALCVAR - float max_var = (float)( maxSigma_Color*maxSigma_Color); - for(int x = startLMJ; x< endLMJ; x++) - { - tptr = temp->ptr(startY + x) +j; - for(int y=-anX; y<=anX; y++) - { - currVal_b = tptr[cn*(y+anX)], currVal_g = tptr[cn*(y+anX)+1], currVal_r =tptr[cn*(y+anX)+2]; - sumVal_b += currVal_b; - sumVal_g += currVal_g; - sumVal_r += currVal_r; - sumValSqr_b += (currVal_b *currVal_b); - sumValSqr_g += (currVal_g *currVal_g); - sumValSqr_r += (currVal_r *currVal_r); - } - } - var_b = ( (sumValSqr_b * howManyAll)- sumVal_b * sumVal_b ) / ( (float)(howManyAll*howManyAll)); - var_g = ( (sumValSqr_g * howManyAll)- sumVal_g * sumVal_g ) / ( (float)(howManyAll*howManyAll)); - var_r = ( (sumValSqr_r * howManyAll)- sumVal_r * sumVal_r ) / ( (float)(howManyAll*howManyAll)); - - if(var_b < 0.01) - var_b = 0.01f; - else if(var_b > max_var ) - var_b = (float)(max_var) ; - - if(var_g < 0.01) - var_g = 0.01f; - else if(var_g > max_var ) - var_g = (float)(max_var) ; - - if(var_r < 0.01) - var_r = 0.01f; - else if(var_r > max_var ) - var_r = (float)(max_var) ; - -#else - var_b = maxSigma_Color*maxSigma_Color; var_g = maxSigma_Color*maxSigma_Color; var_r = maxSigma_Color*maxSigma_Color; -#endif - startLMJ = 0; - endLMJ = ksize.width; - tptr = temp->ptr(startY + (startLMJ+ endLMJ)/2) + j; - currValCenter_b =tptr[cn*anX], currValCenter_g =tptr[cn*anX+1], currValCenter_r =tptr[cn*anX+2]; - for(int x = startLMJ; x< endLMJ; x++) - { - tptr = temp->ptr(startY + x) +j; - for(int y=-anX; y<=anX; y++) - { -#if ABF_FIXED_WEIGHT - weight_b = 1.0; - weight_g = 1.0; - weight_r = 1.0; -#else - currVal_b = tptr[cn*(y+anX)];currVal_g=tptr[cn*(y+anX)+1];currVal_r=tptr[cn*(y+anX)+2]; - currWRTCenter_b = currVal_b - currValCenter_b; - currWRTCenter_g = currVal_g - currValCenter_g; - currWRTCenter_r = currVal_r - currValCenter_r; - - float cur_spw = space_weight[x*ksize.width+y+anX]; - -#if ABF_GAUSSIAN - weight_b = exp( -0.5f * currWRTCenter_b * currWRTCenter_b/ var_b ) * cur_spw; - weight_g = exp( -0.5f * currWRTCenter_g * currWRTCenter_g/ var_g ) * cur_spw; - weight_r = exp( -0.5f * currWRTCenter_r * currWRTCenter_r/ var_r ) * cur_spw; -#else - weight_b = var_b / ( var_b + (currWRTCenter_b * currWRTCenter_b) ) * cur_spw; - weight_g = var_g / ( var_g + (currWRTCenter_g * currWRTCenter_g) ) * cur_spw; - weight_r = var_r / ( var_r + (currWRTCenter_r * currWRTCenter_r) ) * cur_spw; -#endif -#endif - tmpSum_b += ((float)tptr[cn*(y+anX)] * weight_b); - tmpSum_g += ((float)tptr[cn*(y+anX)+1] * weight_g); - tmpSum_r += ((float)tptr[cn*(y+anX)+2] * weight_r); - totalWeight_b += weight_b, totalWeight_g += weight_g, totalWeight_r += weight_r; - } - } - tmpSum_b /= totalWeight_b; - tmpSum_g /= totalWeight_g; - tmpSum_r /= totalWeight_r; - - dest->at(startY,j )= static_cast(tmpSum_b); - dest->at(startY,j+1)= static_cast(tmpSum_g); - dest->at(startY,j+2)= static_cast(tmpSum_r); - } - } - } - } -private: - const Mat *temp; - Mat *dest; - Size ksize; - double sigma_space; - double maxSigma_Color; - Point anchor; - std::vector space_weight; -}; -static void adaptiveBilateralFilter_8u( const Mat& src, Mat& dst, Size ksize, double sigmaSpace, double maxSigmaColor, Point anchor, int borderType ) -{ - Size size = src.size(); - - CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_8UC3) && - src.type() == dst.type() && src.size() == dst.size() && - src.data != dst.data ); - Mat temp; - copyMakeBorder(src, temp, anchor.x, anchor.y, anchor.x, anchor.y, borderType); - - adaptiveBilateralFilter_8u_Invoker body(dst, temp, ksize, sigmaSpace, maxSigmaColor, anchor); - parallel_for_(Range(0, size.height), body, dst.total()/(double)(1<<16)); -} -} -void cv::adaptiveBilateralFilter( InputArray _src, OutputArray _dst, Size ksize, - double sigmaSpace, double maxSigmaColor, Point anchor, int borderType ) -{ - Mat src = _src.getMat(); - _dst.create(src.size(), src.type()); - Mat dst = _dst.getMat(); - - CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3); - - anchor = normalizeAnchor(anchor,ksize); - if( src.depth() == CV_8U ) - adaptiveBilateralFilter_8u( src, dst, ksize, sigmaSpace, maxSigmaColor, anchor, borderType ); - else - CV_Error( CV_StsUnsupportedFormat, - "Adaptive Bilateral filtering is only implemented for 8u images" ); -} - ////////////////////////////////////////////////////////////////////////////////////////// CV_IMPL void From 0ebb3ab0ea65b8565e5a84d609258d7a573b787a Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 28 Jan 2014 23:10:43 +0400 Subject: [PATCH 295/295] optimized createHanningWindow --- modules/imgproc/perf/perf_phasecorr.cpp | 22 ++++++++++++++++++++++ modules/imgproc/src/phasecorr.cpp | 24 ++++++++++++------------ 2 files changed, 34 insertions(+), 12 deletions(-) create mode 100644 modules/imgproc/perf/perf_phasecorr.cpp diff --git a/modules/imgproc/perf/perf_phasecorr.cpp b/modules/imgproc/perf/perf_phasecorr.cpp new file mode 100644 index 000000000..ee9d94e31 --- /dev/null +++ b/modules/imgproc/perf/perf_phasecorr.cpp @@ -0,0 +1,22 @@ +#include "perf_precomp.hpp" + +using namespace std; +using namespace cv; +using namespace perf; +using namespace testing; +using std::tr1::make_tuple; +using std::tr1::get; + +typedef TestBaseWithParam CreateHanningWindowFixture; + +PERF_TEST_P( CreateHanningWindowFixture, CreateHanningWindow, Values(szVGA, sz1080p)) +{ + const Size size = GetParam(); + Mat dst(size, CV_32FC1); + + declare.in(dst, WARMUP_RNG).out(dst); + + TEST_CYCLE() cv::createHanningWindow(dst, size, CV_32FC1); + + SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); +} diff --git a/modules/imgproc/src/phasecorr.cpp b/modules/imgproc/src/phasecorr.cpp index d21a4938f..f513e84e2 100644 --- a/modules/imgproc/src/phasecorr.cpp +++ b/modules/imgproc/src/phasecorr.cpp @@ -576,20 +576,23 @@ void cv::createHanningWindow(OutputArray _dst, cv::Size winSize, int type) _dst.create(winSize, type); Mat dst = _dst.getMat(); - int rows = dst.rows; - int cols = dst.cols; + int rows = dst.rows, cols = dst.cols; + + AutoBuffer _wc(cols); + double * const wc = (double *)_wc; + + double coeff0 = 2.0 * CV_PI / (double)(cols - 1), coeff1 = 2.0f * CV_PI / (double)(rows - 1); + for(int j = 0; j < cols; j++) + wc[j] = 0.5 * (1.0 - cos(coeff0 * j)); if(dst.depth() == CV_32F) { for(int i = 0; i < rows; i++) { float* dstData = dst.ptr(i); - double wr = 0.5 * (1.0f - cos(2.0f * CV_PI * (double)i / (double)(rows - 1))); + double wr = 0.5 * (1.0 - cos(coeff1 * i)); for(int j = 0; j < cols; j++) - { - double wc = 0.5 * (1.0f - cos(2.0f * CV_PI * (double)j / (double)(cols - 1))); - dstData[j] = (float)(wr * wc); - } + dstData[j] = (float)(wr * wc[j]); } } else @@ -597,12 +600,9 @@ void cv::createHanningWindow(OutputArray _dst, cv::Size winSize, int type) for(int i = 0; i < rows; i++) { double* dstData = dst.ptr(i); - double wr = 0.5 * (1.0 - cos(2.0 * CV_PI * (double)i / (double)(rows - 1))); + double wr = 0.5 * (1.0 - cos(coeff1 * i)); for(int j = 0; j < cols; j++) - { - double wc = 0.5 * (1.0 - cos(2.0 * CV_PI * (double)j / (double)(cols - 1))); - dstData[j] = wr * wc; - } + dstData[j] = wr * wc[j]; } }