Commit 8f9bcb77 authored by biagio montesano's avatar biagio montesano

Derivation from Feature2D completed. Warnings corrected.

parent a0237c31
...@@ -74,11 +74,9 @@ namespace cv ...@@ -74,11 +74,9 @@ namespace cv
/* number of pixels covered by the line */ /* number of pixels covered by the line */
unsigned int numOfPixels; unsigned int numOfPixels;
}; };
class CV_EXPORTS_W BinaryDescriptor : public FeatureDetector class CV_EXPORTS_W BinaryDescriptor : public Feature2D
{ {
public: public:
...@@ -114,9 +112,14 @@ namespace cv ...@@ -114,9 +112,14 @@ namespace cv
}; };
/* constructor */
CV_WRAP BinaryDescriptor(const BinaryDescriptor::Params &parameters = CV_WRAP BinaryDescriptor(const BinaryDescriptor::Params &parameters =
BinaryDescriptor::Params()); BinaryDescriptor::Params());
/* constructors with smart pointers */
CV_EXPORTS Ptr<BinaryDescriptor> createBinaryDescriptor();
CV_EXPORTS Ptr<BinaryDescriptor> createBinaryDescriptor(Params parameters);
/* read parameters from a FileNode object and store them (class function ) */ /* read parameters from a FileNode object and store them (class function ) */
virtual void read( const cv::FileNode& fn ); virtual void read( const cv::FileNode& fn );
...@@ -133,10 +136,12 @@ namespace cv ...@@ -133,10 +136,12 @@ namespace cv
std::vector<std::vector<KeyPoint> >& keypoints, std::vector<std::vector<KeyPoint> >& keypoints,
const std::vector<Mat>& masks=std::vector<Mat>() ) const; const std::vector<Mat>& masks=std::vector<Mat>() ) const;
/* requires descriptors computation (only one image) */
CV_WRAP void compute( const Mat& image, CV_WRAP void compute( const Mat& image,
CV_OUT CV_IN_OUT std::vector<KeyPoint>& keypoints, CV_OUT CV_IN_OUT std::vector<KeyPoint>& keypoints,
CV_OUT Mat& descriptors ) const; CV_OUT Mat& descriptors ) const;
/* requires descriptors computation (more than one image) */
void compute( const std::vector<Mat>& images, void compute( const std::vector<Mat>& images,
std::vector<std::vector<KeyPoint> >& keypoints, std::vector<std::vector<KeyPoint> >& keypoints,
std::vector<Mat>& descriptors ) const; std::vector<Mat>& descriptors ) const;
...@@ -157,26 +162,26 @@ namespace cv ...@@ -157,26 +162,26 @@ namespace cv
InputArray mask, InputArray mask,
CV_OUT std::vector<KeyPoint>& keypoints, CV_OUT std::vector<KeyPoint>& keypoints,
OutputArray descriptors, OutputArray descriptors,
bool useProvidedKeypoints=false ) const = 0; bool useProvidedKeypoints=false ) const;
protected: protected:
virtual void detectImpl( const Mat& image, virtual void detectImpl( const Mat& image,
std::vector<KeyPoint>& keypoints, std::vector<KeyPoint>& keypoints,
const Mat& mask=Mat() ) const = 0; const Mat& mask=Mat() ) const;
virtual void computeImpl( const Mat& image, virtual void computeImpl( const Mat& image,
std::vector<KeyPoint>& keypoints, std::vector<KeyPoint>& keypoints,
Mat& descriptors ) const = 0; Mat& descriptors ) const;
AlgorithmInfo* info() const; AlgorithmInfo* info() const;
private: private:
/* conversion of an LBD descriptor to the decimal equivalent of its binary representation */ /* conversion of an LBD descriptor to its binary representation */
unsigned char binaryTest(float* f1, float* f2); unsigned char binaryConversion(float* f1, float* f2);
/* compute LBD descriptors */ /* compute LBD descriptors */
int computeLBD_(ScaleLines &keyLines); int computeLBD(ScaleLines &keyLines);
/* compute Gaussian pyramid of input image */ /* compute Gaussian pyramid of input image */
void computeGaussianPyramid(const Mat& image); void computeGaussianPyramid(const Mat& image);
......
...@@ -38,12 +38,20 @@ ...@@ -38,12 +38,20 @@
// the use of this software, even if advised of the possibility of such damage. // the use of this software, even if advised of the possibility of such damage.
// //
//M*/ //M*/
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#include "precomp.hpp" #include "precomp.hpp"
using namespace cv; using namespace cv;
/* combinations of internal indeces for binary descriptor extractor */
static const int combinations [32][2] = {{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{1,2},{1,3},
{1,4},{1,5},{1,6},{2,3},{2,4},{2,5},{2,6},{2,7},
{2,8},{3,4},{3,5},{3,6},{3,7},{3,8},{4,5},{4,6},
{4,7},{4,8},{5,6},{5,7},{5,8},{6,7},{6,8},{7,8}};
/* return default parameters */ /* return default parameters */
BinaryDescriptor::Params::Params() BinaryDescriptor::Params::Params()
{ {
...@@ -81,6 +89,16 @@ void BinaryDescriptor::Params::write(cv::FileStorage& fs) const ...@@ -81,6 +89,16 @@ void BinaryDescriptor::Params::write(cv::FileStorage& fs) const
fs << "reductionRatio" << reductionRatio; fs << "reductionRatio" << reductionRatio;
} }
Ptr<BinaryDescriptor> BinaryDescriptor::createBinaryDescriptor()
{
return Ptr<BinaryDescriptor>(new BinaryDescriptor());
}
Ptr<BinaryDescriptor> BinaryDescriptor::createBinaryDescriptor(Params parameters)
{
return Ptr<BinaryDescriptor>(new BinaryDescriptor(parameters));
}
/* construct a BinaryDescrptor object and compute external private parameters */ /* construct a BinaryDescrptor object and compute external private parameters */
BinaryDescriptor::BinaryDescriptor(const BinaryDescriptor::Params &parameters) : params(parameters) BinaryDescriptor::BinaryDescriptor(const BinaryDescriptor::Params &parameters) : params(parameters)
{ {
...@@ -119,6 +137,36 @@ BinaryDescriptor::BinaryDescriptor(const BinaryDescriptor::Params &parameters) : ...@@ -119,6 +137,36 @@ BinaryDescriptor::BinaryDescriptor(const BinaryDescriptor::Params &parameters) :
} }
} }
/* definition of operator () inherited from Feature2D class */
void BinaryDescriptor::operator()( InputArray image,
InputArray mask,
CV_OUT std::vector<KeyPoint>& keypoints,
OutputArray descriptors,
bool useProvidedKeypoints) const
{
/* create some matrix objects */
cv::Mat imageMat, maskMat, descrMat;
/* store reference to input matrices */
imageMat = image.getMat();
maskMat = mask.getMat();
/* initialize output matrix */
descriptors.create(Size(32, keypoints.size()), CV_8UC1);
/* store reference to output matrix */
descrMat = descriptors.getMat();
/* require KeyLines detection if demanded */
if(!useProvidedKeypoints)
detectImpl(imageMat, keypoints, maskMat);
/* compute descriptors */
computeImpl(imageMat, keypoints, descrMat);
}
/* read parameters from a FileNode object and store them (class function ) */ /* read parameters from a FileNode object and store them (class function ) */
void BinaryDescriptor::read( const cv::FileNode& fn ) void BinaryDescriptor::read( const cv::FileNode& fn )
{ {
...@@ -146,13 +194,13 @@ int BinaryDescriptor::descriptorType() const ...@@ -146,13 +194,13 @@ int BinaryDescriptor::descriptorType() const
/*return descriptor size */ /*return descriptor size */
int BinaryDescriptor::descriptorSize() const int BinaryDescriptor::descriptorSize() const
{ {
return 1; return 32*8;
} }
/* check whether Gaussian pyramids were created */ /* check whether Gaussian pyramids were created */
bool BinaryDescriptor::empty() const bool BinaryDescriptor::empty() const
{ {
return false; return octaveImages.empty();
} }
/* power function with error management */ /* power function with error management */
...@@ -167,8 +215,8 @@ static inline int get2Pow(int i) { ...@@ -167,8 +215,8 @@ static inline int get2Pow(int i) {
} }
} }
/* conversion of an LBD descriptor to the decimal equivalent of its binary representation */ /* conversion of an LBD descriptor to its binary representation */
unsigned char BinaryDescriptor::binaryTest(float* f1, float* f2) unsigned char BinaryDescriptor::binaryConversion(float* f1, float* f2)
{ {
uchar result = 0; uchar result = 0;
for(int i = 0; i<8; i++) for(int i = 0; i<8; i++)
...@@ -182,7 +230,7 @@ unsigned char BinaryDescriptor::binaryTest(float* f1, float* f2) ...@@ -182,7 +230,7 @@ unsigned char BinaryDescriptor::binaryTest(float* f1, float* f2)
} }
/* get coefficients of line passing by two points in (line_extremes) */ /* get coefficients of line passing by two points in (line_extremes) */
void BinaryDescriptor::getLineParameters(cv::Vec4i &line_extremes, cv::Vec3i &lineParams) void BinaryDescriptor::getLineParameters(cv::Vec4i& line_extremes, cv::Vec3i& lineParams)
{ {
int x1 = line_extremes[0]; int x1 = line_extremes[0];
int x2 = line_extremes[2]; int x2 = line_extremes[2];
...@@ -287,11 +335,17 @@ void BinaryDescriptor::detect( const std::vector<Mat>& images, ...@@ -287,11 +335,17 @@ void BinaryDescriptor::detect( const std::vector<Mat>& images,
void BinaryDescriptor::detectImpl( const Mat& image, std::vector<KeyPoint>& keypoints, void BinaryDescriptor::detectImpl( const Mat& image, std::vector<KeyPoint>& keypoints,
const Mat& mask) const const Mat& mask) const
{ {
/* reinitialize structures for hosting images, images' derivatives and sizes
(they may have been used in the past) */ /*check whether image depth is different from 0 */
if(image.depth() != 0)
{
std::cout << "Warning, depth image!= 0" << std::endl;
CV_Assert(false);
}
/* create a pointer to self */
BinaryDescriptor *bn = const_cast<BinaryDescriptor*>(this); BinaryDescriptor *bn = const_cast<BinaryDescriptor*>(this);
bn->dxImg_vector.clear();
bn->dyImg_vector.clear();
/* compute Gaussian pyramid */ /* compute Gaussian pyramid */
bn->computeGaussianPyramid(image); bn->computeGaussianPyramid(image);
...@@ -336,12 +390,49 @@ void BinaryDescriptor::detectImpl( const Mat& image, std::vector<KeyPoint>& keyp ...@@ -336,12 +390,49 @@ void BinaryDescriptor::detectImpl( const Mat& image, std::vector<KeyPoint>& keyp
keypoints.push_back(kl); keypoints.push_back(kl);
} }
} }
/* delete undesired KeyLines, according to input mask */
for(size_t keyCounter = 0; keyCounter<keypoints.size(); keyCounter++)
{
KeyLine *kl = static_cast<KeyLine*>(&keypoints[keyCounter]);
if(mask.at<int>(kl->startPointX, kl->startPointY) == 0 &&
mask.at<int>(kl->endPointX, kl->endPointY) == 0)
keypoints.erase(keypoints.begin() + keyCounter);
}
}
/* requires descriptors computation (only one image) */
void BinaryDescriptor::compute( const Mat& image,
CV_OUT CV_IN_OUT std::vector<KeyPoint>& keypoints,
CV_OUT Mat& descriptors ) const
{
computeImpl(image, keypoints, descriptors);
} }
/* requires descriptors computation (more than one image) */
void BinaryDescriptor::compute( const std::vector<Mat>& images,
std::vector<std::vector<KeyPoint> >& keypoints,
std::vector<Mat>& descriptors ) const
{
for(size_t i = 0; i<images.size(); i++)
computeImpl(images[i], keypoints[i], descriptors[i]);
}
/* implementation of descriptors computation */
void BinaryDescriptor::computeImpl( const Mat& image, void BinaryDescriptor::computeImpl( const Mat& image,
std::vector<KeyPoint>& keypoints, std::vector<KeyPoint>& keypoints,
Mat& descriptors ) const Mat& descriptors ) const
{ {
/*check whether image depth is different from 0 */
if(image.depth() != 0)
{
std::cout << "Warning, depth image!= 0" << std::endl;
CV_Assert(false);
}
/* keypoints list can't be empty */ /* keypoints list can't be empty */
if(keypoints.size() == 0) if(keypoints.size() == 0)
{ {
...@@ -349,7 +440,7 @@ void BinaryDescriptor::computeImpl( const Mat& image, ...@@ -349,7 +440,7 @@ void BinaryDescriptor::computeImpl( const Mat& image,
return; return;
} }
/* get number of lines */ /* get maximum class_id */
int numLines = 0; int numLines = 0;
for(size_t l = 0; l<keypoints.size(); l++) for(size_t l = 0; l<keypoints.size(); l++)
{ {
...@@ -361,19 +452,29 @@ void BinaryDescriptor::computeImpl( const Mat& image, ...@@ -361,19 +452,29 @@ void BinaryDescriptor::computeImpl( const Mat& image,
OctaveSingleLine fictiousOSL; OctaveSingleLine fictiousOSL;
fictiousOSL.octaveCount = -1; fictiousOSL.octaveCount = -1;
LinesVec lv(params.numOfOctave_, fictiousOSL); LinesVec lv(params.numOfOctave_, fictiousOSL);
ScaleLines sl(numLines, lv); ScaleLines sl(numLines+1, lv);
/* create a map to record association between KeyLines and their position /* create a map to record association between KeyLines and their position
in ScaleLines vector */ in ScaleLines vector */
std::map<std::pair<int, int>, int> correspondences; std::map<std::pair<int, int>, int> correspondences;
/*fill ScaleLines object */ /* fill ScaleLines object */
for(size_t slCounter = 0; slCounter<keypoints.size(); slCounter++) for(size_t slCounter = 0; slCounter<keypoints.size(); slCounter++)
{ {
std::string classType = typeid(keypoints[slCounter]).name();
if(classType.compare("KeyLine") != 0)
{
std::cout << "Error: one or more element in KeyPoint input vector " <<
"don't belong to KeyLine class" << std::endl;
return;
}
/* get a pointer to a KeyLine object and create a new line */
KeyPoint *kp = &(keypoints[slCounter]); KeyPoint *kp = &(keypoints[slCounter]);
KeyLine *kl = static_cast<KeyLine*>(kp); KeyLine *kl = static_cast<KeyLine*>(kp);
OctaveSingleLine osl; OctaveSingleLine osl;
/* insert data in newly created line */
osl.startPointX = (*kl).startPointX; osl.startPointX = (*kl).startPointX;
osl.startPointY = (*kl).startPointY; osl.startPointY = (*kl).startPointY;
osl.endPointX = (*kl).endPointX; osl.endPointX = (*kl).endPointX;
...@@ -388,12 +489,14 @@ void BinaryDescriptor::computeImpl( const Mat& image, ...@@ -388,12 +489,14 @@ void BinaryDescriptor::computeImpl( const Mat& image,
osl.direction = (*kl).angle; osl.direction = (*kl).angle;
osl.octaveCount = (*kl).octave; osl.octaveCount = (*kl).octave;
/* store new line */
sl[(*kl).class_id][(*kl).octave] = osl; sl[(*kl).class_id][(*kl).octave] = osl;
/* update map */ /* update map */
int id = (*kl).class_id; int id = (*kl).class_id;
int oct = (*kl).octave; int oct = (*kl).octave;
correspondences.insert(std::pair<std::pair<int,int>, int>(std::pair<int,int>(id, oct), slCounter)); correspondences.insert(std::pair<std::pair<int,int>, int>(std::pair<int,int>(id, oct),
slCounter));
} }
/* delete useless OctaveSingleLines */ /* delete useless OctaveSingleLines */
...@@ -401,7 +504,7 @@ void BinaryDescriptor::computeImpl( const Mat& image, ...@@ -401,7 +504,7 @@ void BinaryDescriptor::computeImpl( const Mat& image,
{ {
for(size_t j = 0; j<sl[i].size(); j++) for(size_t j = 0; j<sl[i].size(); j++)
{ {
if((sl[i][j]).octaveCount == -1) if((int)(sl[i][j]).octaveCount == -1)
(sl[i]).erase((sl[i]).begin() + j); (sl[i]).erase((sl[i]).begin() + j);
} }
} }
...@@ -426,9 +529,38 @@ void BinaryDescriptor::computeImpl( const Mat& image, ...@@ -426,9 +529,38 @@ void BinaryDescriptor::computeImpl( const Mat& image,
} }
/* compute LBD descriptors */ /* compute LBD descriptors */
bn->computeLBD_(sl); bn->computeLBD(sl);
}
/* resize output matrix */
descriptors = cv::Mat(keypoints.size(), 32, CV_8UC1);
/* fill output matrix with descriptors */
for(size_t k = 0; k<sl.size(); k++)
{
for(size_t lineC = 0; lineC<sl[k].size(); lineC++){
/* get original index of keypoint */
int lineOctave = (sl[k][lineC]).octaveCount;
int originalIndex = correspondences.find(std::pair<int,int>(k, lineOctave))->second;
/* get a pointer to correspondent row in output matrix */
uchar* pointerToRow = descriptors.ptr(originalIndex);
/* get LBD data */
float* desVec = sl[k][lineC].descriptor.data();
/* fill current row with binary descriptor */
for(int comb = 0; comb<32; comb++)
{
*pointerToRow = bn->binaryConversion(&desVec[8*combinations[comb][0]],
&desVec[8*combinations[comb][1]]);
pointerToRow++;
}
}
}
}
/* gather lines in groups. Each group contains the same line, detected in different octaves */ /* gather lines in groups. Each group contains the same line, detected in different octaves */
...@@ -678,15 +810,9 @@ int BinaryDescriptor::OctaveKeyLines(ScaleLines &keyLines) ...@@ -678,15 +810,9 @@ int BinaryDescriptor::OctaveKeyLines(ScaleLines &keyLines)
cv::Vec3i tempParams; cv::Vec3i tempParams;
getLineParameters(extractedLines[octaveID][lineIDInOctave], tempParams); getLineParameters(extractedLines[octaveID][lineIDInOctave], tempParams);
direction = getLineDirection(tempParams); direction = getLineDirection(tempParams);
// direction = edLineVec_[octaveID]->lineDirection_[lineIDInOctave];
singleLine.octaveCount = octaveID; singleLine.octaveCount = octaveID;
singleLine.direction = direction; singleLine.direction = direction;
singleLine.lineLength = octaveLines[lineID].lineLength; singleLine.lineLength = octaveLines[lineID].lineLength;
//singleLine.salience = singleLine.lineLength/max(images_sizes[octaveID].width,
// images_sizes[octaveID].height);
//singleLine.salience = edLineVec_[octaveID]->lineSalience_[lineIDInOctave];
//singleLine.numOfPixels = edLineVec_[octaveID]->lines_.sId[lineIDInOctave+1]-
//edLineVec_[octaveID]->lines_.sId[lineIDInOctave];
//decide the start point and end point //decide the start point and end point
shouldChange = false; shouldChange = false;
...@@ -739,7 +865,20 @@ int BinaryDescriptor::OctaveKeyLines(ScaleLines &keyLines) ...@@ -739,7 +865,20 @@ int BinaryDescriptor::OctaveKeyLines(ScaleLines &keyLines)
} }
tempID = octaveLines[lineID].lineIDInScaleLineVec; tempID = octaveLines[lineID].lineIDInScaleLineVec;
/* compute number of pixels covered by line */
LineIterator li(octaveImages[octaveID],
Point(singleLine.startPointX, singleLine.startPointY),
Point(singleLine.endPointX, singleLine.endPointY));
singleLine.numOfPixels = li.count;
/* store line */
keyLines[tempID].push_back(singleLine); keyLines[tempID].push_back(singleLine);
} }
delete [] scale; delete [] scale;
...@@ -749,14 +888,14 @@ int BinaryDescriptor::OctaveKeyLines(ScaleLines &keyLines) ...@@ -749,14 +888,14 @@ int BinaryDescriptor::OctaveKeyLines(ScaleLines &keyLines)
} }
/* compute LBD descriptors */ /* compute LBD descriptors */
int BinaryDescriptor::computeLBD_(ScaleLines &keyLines) int BinaryDescriptor::computeLBD(ScaleLines &keyLines)
{ {
//the default length of the band is the line length. //the default length of the band is the line length.
short numOfFinalLine = keyLines.size(); short numOfFinalLine = keyLines.size();
float *dL = new float[2];//line direction cos(dir), sin(dir) float *dL = new float[2];//line direction cos(dir), sin(dir)
float *dO = new float[2];//the clockwise orthogonal vector of line direction. float *dO = new float[2];//the clockwise orthogonal vector of line direction.
short heightOfLSP = params.widthOfBand_*params.numOfBand_;//the height of line support region; short heightOfLSP = params.widthOfBand_*params.numOfBand_;//the height of line support region;
short descriptorSize = params.numOfBand_ * 8;//each band, we compute the m( pgdL, ngdL, pgdO, ngdO) and std( pgdL, ngdL, pgdO, ngdO); short descriptor_size = params.numOfBand_ * 8;//each band, we compute the m( pgdL, ngdL, pgdO, ngdO) and std( pgdL, ngdL, pgdO, ngdO);
float pgdLRowSum;//the summation of {g_dL |g_dL>0 } for each row of the region; float pgdLRowSum;//the summation of {g_dL |g_dL>0 } for each row of the region;
float ngdLRowSum;//the summation of {g_dL |g_dL<0 } for each row of the region; float ngdLRowSum;//the summation of {g_dL |g_dL<0 } for each row of the region;
float pgdL2RowSum;//the summation of {g_dL^2 |g_dL>0 } for each row of the region; float pgdL2RowSum;//the summation of {g_dL^2 |g_dL>0 } for each row of the region;
...@@ -949,7 +1088,7 @@ int BinaryDescriptor::computeLBD_(ScaleLines &keyLines) ...@@ -949,7 +1088,7 @@ int BinaryDescriptor::computeLBD_(ScaleLines &keyLines)
return 0; */ return 0; */
/* construct line descriptor */ /* construct line descriptor */
pSingleLine->descriptor.resize(descriptorSize); pSingleLine->descriptor.resize(descriptor_size);
desVec = pSingleLine->descriptor.data(); desVec = pSingleLine->descriptor.data();
short desID; short desID;
...@@ -1016,7 +1155,7 @@ int BinaryDescriptor::computeLBD_(ScaleLines &keyLines) ...@@ -1016,7 +1155,7 @@ int BinaryDescriptor::computeLBD_(ScaleLines &keyLines)
* vector no larger than this threshold. In Z.Wang's work, a value of 0.4 is found * vector no larger than this threshold. In Z.Wang's work, a value of 0.4 is found
* empirically to be a proper threshold.*/ * empirically to be a proper threshold.*/
desVec = pSingleLine->descriptor.data(); desVec = pSingleLine->descriptor.data();
for(short i=0; i<descriptorSize; i++ ){ for(short i=0; i<descriptor_size; i++ ){
if(desVec[i]>0.4){ if(desVec[i]>0.4){
desVec[i]=0.4; desVec[i]=0.4;
} }
...@@ -1024,12 +1163,12 @@ int BinaryDescriptor::computeLBD_(ScaleLines &keyLines) ...@@ -1024,12 +1163,12 @@ int BinaryDescriptor::computeLBD_(ScaleLines &keyLines)
//re-normalize desVec; //re-normalize desVec;
temp = 0; temp = 0;
for(short i=0; i<descriptorSize; i++){ for(short i=0; i<descriptor_size; i++){
temp += desVec[i] * desVec[i]; temp += desVec[i] * desVec[i];
} }
temp = 1/sqrt(temp); temp = 1/sqrt(temp);
for(short i=0; i<descriptorSize; i++){ for(short i=0; i<descriptor_size; i++){
desVec[i] = desVec[i] * temp; desVec[i] = desVec[i] * temp;
} }
}/* end for(short lineIDInSameLine = 0; lineIDInSameLine<sameLineSize; }/* end for(short lineIDInSameLine = 0; lineIDInSameLine<sameLineSize;
......
...@@ -55,5 +55,7 @@ ...@@ -55,5 +55,7 @@
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <utility> #include <utility>
#include <string>
#include <typeinfo>
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment