diff --git a/modules/line_descriptor/include/opencv2/line_descriptor/descriptor.hpp b/modules/line_descriptor/include/opencv2/line_descriptor/descriptor.hpp index ca3532d46..3f82c212f 100644 --- a/modules/line_descriptor/include/opencv2/line_descriptor/descriptor.hpp +++ b/modules/line_descriptor/include/opencv2/line_descriptor/descriptor.hpp @@ -133,6 +133,14 @@ namespace cv std::vector >& keypoints, const std::vector& masks=std::vector() ) const; + CV_WRAP void compute( const Mat& image, + CV_OUT CV_IN_OUT std::vector& keypoints, + CV_OUT Mat& descriptors ) const; + + void compute( const std::vector& images, + std::vector >& keypoints, + std::vector& descriptors ) const; + /*return descriptor size */ int descriptorSize() const; @@ -145,12 +153,22 @@ namespace cv /* check whether Gaussian pyramids were created */ bool empty() const; + CV_WRAP_AS(detectAndCompute) virtual void operator()( InputArray image, + InputArray mask, + CV_OUT std::vector& keypoints, + OutputArray descriptors, + bool useProvidedKeypoints=false ) const = 0; + protected: virtual void detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask=Mat() ) const = 0; + virtual void computeImpl( const Mat& image, + std::vector& keypoints, + Mat& descriptors ) const = 0; + AlgorithmInfo* info() const; private: @@ -158,7 +176,10 @@ namespace cv unsigned char binaryTest(float* f1, float* f2); /* compute LBD descriptors */ - int ComputeLBD_(ScaleLines &keyLines); + int computeLBD_(ScaleLines &keyLines); + + /* compute Gaussian pyramid of input image */ + void computeGaussianPyramid(const Mat& image); /* gather lines in groups. Each group contains the same line, detected in different octaves */ diff --git a/modules/line_descriptor/src/BinaryDescriptor.cpp b/modules/line_descriptor/src/BinaryDescriptor.cpp index 9bd2918ce..9fd01eeef 100644 --- a/modules/line_descriptor/src/BinaryDescriptor.cpp +++ b/modules/line_descriptor/src/BinaryDescriptor.cpp @@ -41,7 +41,6 @@ #define _USE_MATH_DEFINES #include "precomp.hpp" -#include using namespace cv; @@ -153,7 +152,33 @@ int BinaryDescriptor::descriptorSize() const /* check whether Gaussian pyramids were created */ bool BinaryDescriptor::empty() const { - return true; + return false; +} + +/* power function with error management */ +static inline int get2Pow(int i) { + if(i>=0 && i<=7) + return pow(2,i); + + else + { + CV_Assert(false); + return -1; + } +} + +/* conversion of an LBD descriptor to the decimal equivalent of its binary representation */ +unsigned char BinaryDescriptor::binaryTest(float* f1, float* f2) +{ + uchar result = 0; + for(int i = 0; i<8; i++) + { + if(f1[i]>f2[i]) + result+=get2Pow(i); + } + + return result; + } /* get coefficients of line passing by two points in (line_extremes) */ @@ -213,6 +238,30 @@ float BinaryDescriptor::getLineDirection(cv::Vec3i &lineParams) } } +/* compute Gaussian pyramid of input image */ +void BinaryDescriptor::computeGaussianPyramid(const Mat& image) +{ + /* clear class fields */ + images_sizes.clear(); + octaveImages.clear(); + + /* insert input image into pyramid */ + cv::Mat currentMat = image.clone(); + octaveImages.push_back(currentMat); + images_sizes.push_back(currentMat.size()); + + /* fill Gaussian pyramid */ + for(int pyrCounter = 1; pyrCounter& keypoints, @@ -243,24 +292,9 @@ void BinaryDescriptor::detectImpl( const Mat& image, std::vector& keyp BinaryDescriptor *bn = const_cast(this); bn->dxImg_vector.clear(); bn->dyImg_vector.clear(); - bn->images_sizes.clear(); - bn->octaveImages.clear(); - /* insert input image into pyramid */ - cv::Mat currentMat = image.clone(); - bn->octaveImages.push_back(currentMat); - bn->images_sizes.push_back(currentMat.size()); - - /* fill Gaussian pyramid */ - for(int pyrCounter = 0; pyrCounteroctaveImages.push_back(currentMat); - bn->images_sizes.push_back(currentMat.size()); - } + /* compute Gaussian pyramid */ + bn->computeGaussianPyramid(image); /* detect and arrange lines across octaves */ ScaleLines sl; @@ -287,6 +321,7 @@ void BinaryDescriptor::detectImpl( const Mat& image, std::vector& keyp kl.ePointInOctaveX = osl.ePointInOctaveX; kl.ePointInOctaveY = osl.ePointInOctaveY; kl.lineLength = osl.lineLength; + kl.numOfPixels = osl.numOfPixels; kl.angle = osl.direction; kl.class_id = i; @@ -294,7 +329,8 @@ void BinaryDescriptor::detectImpl( const Mat& image, std::vector& keyp kl.size = (osl.endPointX - osl.startPointX)*(osl.endPointY - osl.startPointY); kl.response = osl.lineLength/max(images_sizes[osl.octaveCount].width, images_sizes[osl.octaveCount].height); - kl.pt = Point((osl.endPointX + osl.startPointX)/2, (osl.endPointY + osl.startPointY)/2); + kl.pt = Point((osl.endPointX + osl.startPointX)/2, + (osl.endPointY + osl.startPointY)/2); /* store KeyLine */ keypoints.push_back(kl); @@ -302,95 +338,98 @@ void BinaryDescriptor::detectImpl( const Mat& image, std::vector& keyp } } -///* extract lines from an image and compute their descriptors */ -//inline void getLineBinaryDescriptors(cv::Mat &oct_binaryDescMat) -//{ -// /* start function that actually implements descriptors' computation */ -// getLineBinaryDescriptorsImpl(oct_binaryDescMat); - -//} - -///* compute descriptors */ -//inline void getLineBinaryDescriptorsImpl(cv::Mat &oct_binaryDescMat) -//{ -// /* prepare a matrix to store Gaussian pyramid of input matrix */ -// std::vector matVec(params.numOfOctave_); - -// /* reinitialize structures for hosting images' derivatives and sizes -// (they may have been used in the past) */ -// dxImg_vector.clear(); -// dyImg_vector.clear(); -// images_sizes.clear(); - -// dxImg_vector.resize(params.numOfOctave_); -// dyImg_vector.resize(params.numOfOctave_); -// images_sizes.resize(params.numOfOctave_); - -// /* insert input image into pyramid */ -// cv::Mat currentMat = oct_binaryDescMat.clone(); -// matVec.push_back(currentMat); -// images_sizes.push_back(currentMat.size()); - -// /* compute and store derivatives of input image */ -// cv:Mat currentDx, currentDy; -// cv::Sobel( currentMat, currentDx, CV_16SC1, 1, 0, 3); -// cv::Sobel( currentMat, currentDy, CV_16SC1, 0, 1, 3); - -// dxImg_vector.push_back(currentDx); -// dyImg_vector.push_back(currentDy); +void BinaryDescriptor::computeImpl( const Mat& image, + std::vector& keypoints, + Mat& descriptors ) const +{ + /* keypoints list can't be empty */ + if(keypoints.size() == 0) + { + std::cout << "Error: keypoint list is empty" << std::endl; + return; + } -// /* fill Gaussian pyramid */ -// for(int i = 1; i numLines) + numLines = keypoints[l].class_id; + } -// /* compute and store derivatives of new image */ -// cv::Sobel( currentMat, currentDx, CV_16SC1, 1, 0, 3); -// cv::Sobel( currentMat, currentDy, CV_16SC1, 0, 1, 3); + /* create a ScaleLines object */ + OctaveSingleLine fictiousOSL; + fictiousOSL.octaveCount = -1; + LinesVec lv(params.numOfOctave_, fictiousOSL); + ScaleLines sl(numLines, lv); -// dxImg_vector.push_back(currentDx); -// dyImg_vector.push_back(currentDy); -// } + /* create a map to record association between KeyLines and their position + in ScaleLines vector */ + std::map, int> correspondences; -// /* prepare a structure for hosting and organizing extracted lines */ -// ScaleLines keyLines; + /*fill ScaleLines object */ + for(size_t slCounter = 0; slCounter(kp); + OctaveSingleLine osl; + + osl.startPointX = (*kl).startPointX; + osl.startPointY = (*kl).startPointY; + osl.endPointX = (*kl).endPointX; + osl.endPointY = (*kl).endPointY; + osl.sPointInOctaveX = (*kl).sPointInOctaveX; + osl.sPointInOctaveY = (*kl).sPointInOctaveY; + osl.ePointInOctaveX = (*kl).ePointInOctaveX; + osl.ePointInOctaveY = (*kl).ePointInOctaveY; + osl.lineLength = (*kl).lineLength; + osl.numOfPixels = (*kl).numOfPixels; + + osl.direction = (*kl).angle; + osl.octaveCount = (*kl).octave; + + sl[(*kl).class_id][(*kl).octave] = osl; + + /* update map */ + int id = (*kl).class_id; + int oct = (*kl).octave; + correspondences.insert(std::pair, int>(std::pair(id, oct), slCounter)); + } -// /* extract and arrange lines */ -// OctaveKeyLines(matVec, keyLines); + /* delete useless OctaveSingleLines */ + for(size_t i = 0; i(this); + if(octaveImages.size() == 0 || cv::countNonZero(image != octaveImages[0]) != 0) + bn->computeGaussianPyramid(image); -//} + /* compute Sobel's derivatives */ + bn->dxImg_vector.clear(); + bn->dyImg_vector.clear(); -/* power function with error management */ -static inline int get2Pow(int i) { - if(i>=0 && i<=7) - return pow(2,i); + bn->dxImg_vector.resize(params.numOfOctave_); + bn->dyImg_vector.resize(params.numOfOctave_); - else + for(size_t sobelCnt = 0; sobelCntdxImg_vector[sobelCnt], CV_16SC1, 1, 0, 3); + cv::Sobel( octaveImages[sobelCnt], bn->dyImg_vector[sobelCnt], CV_16SC1, 0, 1, 3); } -} -/* conversion of an LBD descriptor to the decimal equivalent of its binary representation */ -unsigned char BinaryDescriptor::binaryTest(float* f1, float* f2) -{ - uchar result = 0; - for(int i = 0; i<8; i++) - { - if(f1[i]>f2[i]) - result+=get2Pow(i); - } + /* compute LBD descriptors */ + bn->computeLBD_(sl); +} - return result; -} /* gather lines in groups. Each group contains the same line, detected in different octaves */ int BinaryDescriptor::OctaveKeyLines(ScaleLines &keyLines) @@ -710,7 +749,7 @@ int BinaryDescriptor::OctaveKeyLines(ScaleLines &keyLines) } /* compute LBD descriptors */ -int BinaryDescriptor::ComputeLBD_(ScaleLines &keyLines) +int BinaryDescriptor::computeLBD_(ScaleLines &keyLines) { //the default length of the band is the line length. short numOfFinalLine = keyLines.size(); diff --git a/modules/line_descriptor/src/precomp.hpp b/modules/line_descriptor/src/precomp.hpp index caf9b6000..2a140a60b 100644 --- a/modules/line_descriptor/src/precomp.hpp +++ b/modules/line_descriptor/src/precomp.hpp @@ -43,16 +43,17 @@ #define __OPENCV_PRECOMP_H__ #include - #include "opencv2/core/utility.hpp" #include "opencv2/core/private.hpp" - #include #include #include #include "opencv2/line_descriptor.hpp" - +#include +#include +#include +#include #endif