Commit 1c246d47 authored by biagio montesano's avatar biagio montesano

Detection test, smoothed removal, setter modified, samples corrected

parent 97854e2b
...@@ -190,14 +190,12 @@ class CV_EXPORTS_W BinaryDescriptor : public Algorithm ...@@ -190,14 +190,12 @@ class CV_EXPORTS_W BinaryDescriptor : public Algorithm
/* requires descriptors computation (only one image) */ /* requires descriptors computation (only one image) */
CV_WRAP CV_WRAP
void compute( const Mat& image, CV_OUT CV_IN_OUT std::vector<KeyLine>& keylines, CV_OUT Mat& descriptors, bool returnFloatDescr = false, void compute( const Mat& image, CV_OUT CV_IN_OUT std::vector<KeyLine>& keylines, CV_OUT Mat& descriptors, bool returnFloatDescr = false ) const;
bool useDetectionData = false ) const;
/* requires descriptors computation (more than one image) */ /* requires descriptors computation (more than one image) */
CV_WRAP CV_WRAP
void compute( const std::vector<Mat>& images, std::vector<std::vector<KeyLine> >& keylines, std::vector<Mat>& descriptors, bool returnFloatDescr = void compute( const std::vector<Mat>& images, std::vector<std::vector<KeyLine> >& keylines, std::vector<Mat>& descriptors, bool returnFloatDescr =
false, false ) const;
bool useDetectionData = false ) const;
/* returns descriptor size */ /* returns descriptor size */
CV_WRAP CV_WRAP
......
...@@ -106,21 +106,19 @@ class EDLineDetector ...@@ -106,21 +106,19 @@ class EDLineDetector
/*extract edges from image /*extract edges from image
*image: In, gray image; *image: In, gray image;
*edges: Out, store the edges, each edge is a pixel chain *edges: Out, store the edges, each edge is a pixel chain
*smoothed: In, flag to mark whether the image has already been smoothed by Gaussian filter.
*return -1: error happen *return -1: error happen
*/ */
int EdgeDrawing( cv::Mat &image, EdgeChains &edgeChains, bool smoothed ); int EdgeDrawing( cv::Mat &image, EdgeChains &edgeChains );
/*extract lines from image /*extract lines from image
*image: In, gray image; *image: In, gray image;
*lines: Out, store the extracted lines, *lines: Out, store the extracted lines,
*smoothed: In, flag to mark whether the image has already been smoothed by Gaussian filter.
*return -1: error happen *return -1: error happen
*/ */
int EDline( cv::Mat &image, LineChains &lines, bool smoothed ); int EDline( cv::Mat &image, LineChains &lines );
/* extract line from image, and store them */ /* extract line from image, and store them */
int EDline( cv::Mat &image, bool smoothed ); int EDline( cv::Mat &image );
cv::Mat dxImg_; //store the dxImg; cv::Mat dxImg_; //store the dxImg;
......
...@@ -61,19 +61,6 @@ static void help() ...@@ -61,19 +61,6 @@ static void help()
<< std::endl; << std::endl;
} }
inline void writeMat( cv::Mat m, std::string name, int n )
{
std::stringstream ss;
std::string s;
ss << n;
ss >> s;
std::string fileNameConf = name + s;
cv::FileStorage fsConf( fileNameConf, cv::FileStorage::WRITE );
fsConf << "m" << m;
fsConf.release();
}
int main( int argc, char** argv ) int main( int argc, char** argv )
{ {
/* get parameters from command line */ /* get parameters from command line */
...@@ -103,18 +90,9 @@ int main( int argc, char** argv ) ...@@ -103,18 +90,9 @@ int main( int argc, char** argv )
std::vector<KeyLine> keylines; std::vector<KeyLine> keylines;
bd->detect( imageMat, keylines, mask ); bd->detect( imageMat, keylines, mask );
/* select only lines from first octave */
/*std::vector<KeyLine> octave0;
for ( size_t i = 0; i < keylines.size(); i++ )
{
if( keylines[i].octave == 0 )
octave0.push_back( keylines[i] );
}*/
/* compute descriptors */ /* compute descriptors */
cv::Mat descriptors; cv::Mat descriptors;
bd->compute( imageMat, keylines, descriptors); bd->compute( imageMat, keylines, descriptors);
writeMat( descriptors, "bd_descriptors", 1 );
} }
...@@ -192,5 +192,8 @@ int main( int argc, char** argv ) ...@@ -192,5 +192,8 @@ int main( int argc, char** argv )
/* require knn match */ /* require knn match */
bdm->knnMatch( descr1, descr2, matches, 6 ); bdm->knnMatch( descr1, descr2, matches, 6 );
} }
...@@ -92,7 +92,7 @@ int main( int argc, char** argv ) ...@@ -92,7 +92,7 @@ int main( int argc, char** argv )
cv::Mat mask2 = Mat::ones( imageMat2.size(), CV_8UC1 ); cv::Mat mask2 = Mat::ones( imageMat2.size(), CV_8UC1 );
/* create a pointer to a BinaryDescriptor object with default parameters */ /* create a pointer to a BinaryDescriptor object with default parameters */
Ptr<BinaryDescriptor> bd = BinaryDescriptor::createBinaryDescriptor(); Ptr<BinaryDescriptor> bd = BinaryDescriptor::createBinaryDescriptor( );
/* compute lines and descriptors */ /* compute lines and descriptors */
std::vector<KeyLine> keylines1, keylines2; std::vector<KeyLine> keylines1, keylines2;
...@@ -101,27 +101,48 @@ int main( int argc, char** argv ) ...@@ -101,27 +101,48 @@ int main( int argc, char** argv )
( *bd )( imageMat1, mask1, keylines1, descr1, false, false ); ( *bd )( imageMat1, mask1, keylines1, descr1, false, false );
( *bd )( imageMat2, mask2, keylines2, descr2, false, false ); ( *bd )( imageMat2, mask2, keylines2, descr2, false, false );
/* select keylines from first octave and their descriptors */
std::vector<KeyLine> lbd_octave1, lbd_octave2;
Mat left_lbd, right_lbd;
for ( int i = 0; i < (int) keylines1.size(); i++ )
{
if( keylines1[i].octave == 0 )
{
lbd_octave1.push_back( keylines1[i] );
left_lbd.push_back( descr1.row( i ) );
}
}
for ( int j = 0; j < (int) keylines2.size(); j++ )
{
if( keylines2[j].octave == 0 )
{
lbd_octave2.push_back( keylines2[j] );
right_lbd.push_back( descr2.row( j ) );
}
}
/* create a BinaryDescriptorMatcher object */ /* create a BinaryDescriptorMatcher object */
Ptr<BinaryDescriptorMatcher> bdm = BinaryDescriptorMatcher::createBinaryDescriptorMatcher(); Ptr<BinaryDescriptorMatcher> bdm = BinaryDescriptorMatcher::createBinaryDescriptorMatcher();
/* require match */ /* require match */
std::vector<DMatch> matches; std::vector<DMatch> matches;
bdm->match( descr1, descr2, matches ); bdm->match( left_lbd, right_lbd, matches );
/* select best matches */ /* select best matches */
std::vector<DMatch> good_matches; std::vector<DMatch> good_matches;
for(int i = 0; i<(int)matches.size(); i++) for ( int i = 0; i < (int) matches.size(); i++ )
{ {
if(matches[i].distance < MATCHES_DIST_THRESHOLD) if( matches[i].distance < MATCHES_DIST_THRESHOLD )
good_matches.push_back(matches[i]); good_matches.push_back( matches[i] );
} }
/* plot matches */ /* plot matches */
cv::Mat outImg; cv::Mat outImg;
cv::Mat scaled1, scaled2;
std::vector<char> mask( matches.size(), 1 ); std::vector<char> mask( matches.size(), 1 );
drawLineMatches( imageMat1, keylines1, imageMat2, keylines2, good_matches , outImg, Scalar::all( -1 ), Scalar::all( -1 ), mask, drawLineMatches( imageMat1, lbd_octave1, imageMat2, lbd_octave2, good_matches, outImg, Scalar::all( -1 ), Scalar::all( -1 ), mask,
DrawLinesMatchesFlags::DEFAULT ); DrawLinesMatchesFlags::DEFAULT );
imshow( "Matches", outImg ); imshow( "Matches", outImg );
waitKey(); waitKey();
...@@ -132,48 +153,55 @@ int main( int argc, char** argv ) ...@@ -132,48 +153,55 @@ int main( int argc, char** argv )
/* detect lines */ /* detect lines */
std::vector<KeyLine> klsd1, klsd2; std::vector<KeyLine> klsd1, klsd2;
Mat lsd_descr1, lsd_descr2; Mat lsd_descr1, lsd_descr2;
lsd->detect(imageMat1, klsd1, 2, 2, mask1); lsd->detect( imageMat1, klsd1, 2, 2, mask1 );
lsd->detect(imageMat2, klsd2, 2, 2, mask2); lsd->detect( imageMat2, klsd2, 2, 2, mask2 );
/* compute descriptors for lines from first octave */
bd->compute( imageMat1, klsd1, lsd_descr1 );
bd->compute( imageMat2, klsd2, lsd_descr2 );
/* select lines from first octave */ /* select lines and descriptors from first octave */
std::vector<KeyLine> octave0_1, octave0_2; std::vector<KeyLine> octave0_1, octave0_2;
for(int i = 0; i<(int)klsd1.size(); i++) Mat leftDEscr, rightDescr;
for ( int i = 0; i < (int) klsd1.size(); i++ )
{ {
if(klsd1[i].octave == 0) if( klsd1[i].octave == 1 )
octave0_1.push_back(klsd1[i]); {
octave0_1.push_back( klsd1[i] );
leftDEscr.push_back( lsd_descr1.row( i ) );
}
} }
for(int j = 0; j<(int)klsd1.size(); j++) for ( int j = 0; j < (int) klsd2.size(); j++ )
{
if( klsd2[j].octave == 1 )
{ {
if(klsd2[j].octave == 0) octave0_2.push_back( klsd2[j] );
octave0_2.push_back(klsd2[j]); rightDescr.push_back( lsd_descr2.row( j ) );
} }
}
/* compute descriptors for lines from first octave */
bd->compute( imageMat1, octave0_1, lsd_descr1 );
bd->compute( imageMat2, octave0_2, lsd_descr2 );
/* compute matches */ /* compute matches */
std::vector<DMatch> lsd_matches; std::vector<DMatch> lsd_matches;
bdm->match( lsd_descr1, lsd_descr2, lsd_matches); bdm->match( leftDEscr, rightDescr, lsd_matches );
/* select best matches */ /* select best matches */
good_matches.clear(); good_matches.clear();
for(int i = 0; i<(int)lsd_matches.size(); i++) for ( int i = 0; i < (int) lsd_matches.size(); i++ )
{ {
if(lsd_matches[i].distance < MATCHES_DIST_THRESHOLD) if( lsd_matches[i].distance < MATCHES_DIST_THRESHOLD )
good_matches.push_back(lsd_matches[i]); good_matches.push_back( lsd_matches[i] );
} }
/* plot matches */ /* plot matches */
cv::Mat lsd_outImg; cv::Mat lsd_outImg;
resize( imageMat1, imageMat1, Size( imageMat1.cols / 2, imageMat1.rows / 2 ) );
resize( imageMat2, imageMat2, Size( imageMat2.cols / 2, imageMat2.rows / 2 ) );
std::vector<char> lsd_mask( matches.size(), 1 ); std::vector<char> lsd_mask( matches.size(), 1 );
drawLineMatches( imageMat1, octave0_1, imageMat2, octave0_2, good_matches , lsd_outImg, Scalar::all( -1 ), Scalar::all( -1 ), lsd_mask, drawLineMatches( imageMat1, octave0_1, imageMat2, octave0_2, good_matches, lsd_outImg, Scalar::all( -1 ), Scalar::all( -1 ), lsd_mask,
DrawLinesMatchesFlags::DEFAULT ); DrawLinesMatchesFlags::DEFAULT );
imshow("LSD matches", lsd_outImg); imshow( "LSD matches", lsd_outImg );
waitKey(); waitKey();
} }
...@@ -56,7 +56,7 @@ void LSDDetector::computeGaussianPyramid( const Mat& image, int numOctaves, int ...@@ -56,7 +56,7 @@ void LSDDetector::computeGaussianPyramid( const Mat& image, int numOctaves, int
/* insert input image into pyramid */ /* insert input image into pyramid */
cv::Mat currentMat = image.clone(); cv::Mat currentMat = image.clone();
cv::GaussianBlur( currentMat, currentMat, cv::Size( 5, 5 ), 1 ); //cv::GaussianBlur( currentMat, currentMat, cv::Size( 5, 5 ), 1 );
gaussianPyrs.push_back( currentMat ); gaussianPyrs.push_back( currentMat );
/* fill Gaussian pyramid */ /* fill Gaussian pyramid */
......
...@@ -111,6 +111,46 @@ int BinaryDescriptor::getWidthOfBand() ...@@ -111,6 +111,46 @@ int BinaryDescriptor::getWidthOfBand()
void BinaryDescriptor::setWidthOfBand( int width ) void BinaryDescriptor::setWidthOfBand( int width )
{ {
params.widthOfBand_ = width; params.widthOfBand_ = width;
/* reserve enough space for EDLine objects and images in Gaussian pyramid */
edLineVec_.resize( params.numOfOctave_ );
images_sizes.resize( params.numOfOctave_ );
for ( int i = 0; i < params.numOfOctave_; i++ )
edLineVec_[i] = Ptr<EDLineDetector>( new EDLineDetector() );
/* prepare a vector to host local weights F_l*/
gaussCoefL_.resize( params.widthOfBand_ * 3 );
/* compute center of central band (every computation involves 2-3 bands) */
double u = ( params.widthOfBand_ * 3 - 1 ) / 2;
/* compute exponential part of F_l */
double sigma = ( params.widthOfBand_ * 2 + 1 ) / 2; // (widthOfBand_*2+1)/2;
double invsigma2 = -1 / ( 2 * sigma * sigma );
/* compute all local weights */
double dis;
for ( int i = 0; i < params.widthOfBand_ * 3; i++ )
{
dis = i - u;
gaussCoefL_[i] = exp( dis * dis * invsigma2 );
}
/* prepare a vector for global weights F_g*/
gaussCoefG_.resize( NUM_OF_BANDS * params.widthOfBand_ );
/* compute center of LSR */
u = ( NUM_OF_BANDS * params.widthOfBand_ - 1 ) / 2;
/* compute exponential part of F_g */
sigma = u;
invsigma2 = -1 / ( 2 * sigma * sigma );
for ( int i = 0; i < NUM_OF_BANDS * params.widthOfBand_; i++ )
{
dis = i - u;
gaussCoefG_[i] = exp( dis * dis * invsigma2 );
}
} }
int BinaryDescriptor::getReductionRatio() int BinaryDescriptor::getReductionRatio()
...@@ -351,6 +391,12 @@ unsigned char BinaryDescriptor::binaryConversion( float* f1, float* f2 ) ...@@ -351,6 +391,12 @@ unsigned char BinaryDescriptor::binaryConversion( float* f1, float* f2 )
/* requires line detection (only one image) */ /* requires line detection (only one image) */
void BinaryDescriptor::detect( const Mat& image, CV_OUT std::vector<KeyLine>& keylines, const Mat& mask ) void BinaryDescriptor::detect( const Mat& image, CV_OUT std::vector<KeyLine>& keylines, const Mat& mask )
{ {
if( image.data == NULL )
{
std::cout << "Error: input image for detection is empty" << std::endl;
return;
}
if( mask.data != NULL && ( mask.size() != image.size() || mask.type() != CV_8UC1 ) ) if( mask.data != NULL && ( mask.size() != image.size() || mask.type() != CV_8UC1 ) )
throw std::runtime_error( "Mask error while detecting lines: please check its dimensions and that data type is CV_8UC1" ); throw std::runtime_error( "Mask error while detecting lines: please check its dimensions and that data type is CV_8UC1" );
...@@ -361,6 +407,13 @@ void BinaryDescriptor::detect( const Mat& image, CV_OUT std::vector<KeyLine>& ke ...@@ -361,6 +407,13 @@ void BinaryDescriptor::detect( const Mat& image, CV_OUT std::vector<KeyLine>& ke
/* requires line detection (more than one image) */ /* requires line detection (more than one image) */
void BinaryDescriptor::detect( const std::vector<Mat>& images, std::vector<std::vector<KeyLine> >& keylines, const std::vector<Mat>& masks ) const void BinaryDescriptor::detect( const std::vector<Mat>& images, std::vector<std::vector<KeyLine> >& keylines, const std::vector<Mat>& masks ) const
{ {
if( images.size() == 0 )
{
std::cout << "Error: input image for detection is empty" << std::endl;
return;
}
/* detect lines from each image */ /* detect lines from each image */
for ( size_t counter = 0; counter < images.size(); counter++ ) for ( size_t counter = 0; counter < images.size(); counter++ )
{ {
...@@ -444,18 +497,18 @@ void BinaryDescriptor::detectImpl( const Mat& imageSrc, std::vector<KeyLine>& ke ...@@ -444,18 +497,18 @@ void BinaryDescriptor::detectImpl( const Mat& imageSrc, std::vector<KeyLine>& ke
} }
/* requires descriptors computation (only one image) */ /* requires descriptors computation (only one image) */
void BinaryDescriptor::compute( const Mat& image, CV_OUT CV_IN_OUT std::vector<KeyLine>& keylines, CV_OUT Mat& descriptors, bool returnFloatDescr, void BinaryDescriptor::compute( const Mat& image, CV_OUT CV_IN_OUT std::vector<KeyLine>& keylines, CV_OUT Mat& descriptors,
bool useDetectionData ) const bool returnFloatDescr ) const
{ {
computeImpl( image, keylines, descriptors, returnFloatDescr, useDetectionData ); computeImpl( image, keylines, descriptors, returnFloatDescr, false );
} }
/* requires descriptors computation (more than one image) */ /* requires descriptors computation (more than one image) */
void BinaryDescriptor::compute( const std::vector<Mat>& images, std::vector<std::vector<KeyLine> >& keylines, std::vector<Mat>& descriptors, void BinaryDescriptor::compute( const std::vector<Mat>& images, std::vector<std::vector<KeyLine> >& keylines, std::vector<Mat>& descriptors,
bool returnFloatDescr, bool useDetectionData ) const bool returnFloatDescr ) const
{ {
for ( size_t i = 0; i < images.size(); i++ ) for ( size_t i = 0; i < images.size(); i++ )
computeImpl( images[i], keylines[i], descriptors[i], returnFloatDescr, useDetectionData ); computeImpl( images[i], keylines[i], descriptors[i], returnFloatDescr, false );
} }
/* implementation of descriptors computation */ /* implementation of descriptors computation */
...@@ -621,7 +674,6 @@ int BinaryDescriptor::OctaveKeyLines( cv::Mat& image, ScaleLines &keyLines ) ...@@ -621,7 +674,6 @@ int BinaryDescriptor::OctaveKeyLines( cv::Mat& image, ScaleLines &keyLines )
/* loop over number of octaves */ /* loop over number of octaves */
for ( int octaveCount = 0; octaveCount < params.numOfOctave_; octaveCount++ ) for ( int octaveCount = 0; octaveCount < params.numOfOctave_; octaveCount++ )
{ {
/* matrix storing results from blurring processes */ /* matrix storing results from blurring processes */
cv::Mat blur; cv::Mat blur;
...@@ -631,7 +683,7 @@ int BinaryDescriptor::OctaveKeyLines( cv::Mat& image, ScaleLines &keyLines ) ...@@ -631,7 +683,7 @@ int BinaryDescriptor::OctaveKeyLines( cv::Mat& image, ScaleLines &keyLines )
images_sizes[octaveCount] = blur.size(); images_sizes[octaveCount] = blur.size();
/* for current octave, extract lines */ /* for current octave, extract lines */
if( ( edLineVec_[octaveCount]->EDline( blur, true ) ) != 1 ) if( ( edLineVec_[octaveCount]->EDline( blur ) ) != 1 )
{ {
return -1; return -1;
} }
......
...@@ -97,13 +97,15 @@ void drawLineMatches( const Mat& img1, const std::vector<KeyLine>& keylines1, co ...@@ -97,13 +97,15 @@ void drawLineMatches( const Mat& img1, const std::vector<KeyLine>& keylines1, co
for ( size_t i = 0; i < keylines1.size(); i++ ) for ( size_t i = 0; i < keylines1.size(); i++ )
{ {
KeyLine k1 = keylines1[i]; KeyLine k1 = keylines1[i];
line( outImg, Point2f( k1.startPointX, k1.startPointY ), Point2f( k1.endPointX, k1.endPointY ), singleLineColorRGB, 2 ); //line( outImg, Point2f( k1.startPointX, k1.startPointY ), Point2f( k1.endPointX, k1.endPointY ), singleLineColorRGB, 2 );
line( outImg, Point2f( k1.sPointInOctaveX, k1.sPointInOctaveY ), Point2f( k1.ePointInOctaveX, k1.ePointInOctaveY ), singleLineColorRGB, 2 );
} }
for ( size_t j = 0; j < keylines2.size(); j++ ) for ( size_t j = 0; j < keylines2.size(); j++ )
{ {
KeyLine k2 = keylines2[j]; KeyLine k2 = keylines2[j];
line( outImg, Point2f( k2.startPointX + offset, k2.startPointY ), Point2f( k2.endPointX + offset, k2.endPointY ), singleLineColorRGB, 2 ); line( outImg, Point2f( k2.sPointInOctaveX + offset, k2.sPointInOctaveY ), Point2f( k2.ePointInOctaveX + offset, k2.ePointInOctaveY ), singleLineColorRGB, 2 );
} }
} }
...@@ -133,13 +135,21 @@ void drawLineMatches( const Mat& img1, const std::vector<KeyLine>& keylines1, co ...@@ -133,13 +135,21 @@ void drawLineMatches( const Mat& img1, const std::vector<KeyLine>& keylines1, co
matchColorRGB = matchColor; matchColorRGB = matchColor;
/* draw lines if necessary */ /* draw lines if necessary */
line( outImg, Point2f( left.startPointX, left.startPointY ), Point2f( left.endPointX, left.endPointY ), singleLineColorRGB, 2 ); // line( outImg, Point2f( left.startPointX, left.startPointY ), Point2f( left.endPointX, left.endPointY ), singleLineColorRGB, 2 );
//
// line( outImg, Point2f( right.startPointX + offset, right.startPointY ), Point2f( right.endPointX + offset, right.endPointY ), singleLineColorRGB,
// 2 );
//
// /* link correspondent lines */
// line( outImg, Point2f( left.startPointX, left.startPointY ), Point2f( right.startPointX + offset, right.startPointY ), matchColorRGB, 1 );
line( outImg, Point2f( left.sPointInOctaveX, left.sPointInOctaveY ), Point2f( left.ePointInOctaveX, left.ePointInOctaveY ), singleLineColorRGB, 2 );
line( outImg, Point2f( right.startPointX + offset, right.startPointY ), Point2f( right.endPointX + offset, right.endPointY ), singleLineColorRGB, line( outImg, Point2f( right.sPointInOctaveX + offset, right.sPointInOctaveY ), Point2f( right.ePointInOctaveX + offset, right.ePointInOctaveY ), singleLineColorRGB,
2 ); 2 );
/* link correspondent lines */ /* link correspondent lines */
line( outImg, Point2f( left.startPointX, left.startPointY ), Point2f( right.startPointX + offset, right.startPointY ), matchColorRGB, 1 ); line( outImg, Point2f( left.sPointInOctaveX, left.sPointInOctaveY ), Point2f( right.sPointInOctaveX + offset, right.sPointInOctaveY ), matchColorRGB, 1 );
} }
} }
} }
......
...@@ -117,18 +117,12 @@ EDLineDetector::~EDLineDetector() ...@@ -117,18 +117,12 @@ EDLineDetector::~EDLineDetector()
} }
} }
int EDLineDetector::EdgeDrawing( cv::Mat &image, EdgeChains &edgeChains, bool smoothed ) int EDLineDetector::EdgeDrawing( cv::Mat &image, EdgeChains &edgeChains )
{ {
imageWidth = image.cols; imageWidth = image.cols;
imageHeight = image.rows; imageHeight = image.rows;
unsigned int pixelNum = imageWidth * imageHeight; unsigned int pixelNum = imageWidth * imageHeight;
/*if( !smoothed )
{ //input image hasn't been smoothed.
cv::Mat InImage = image.clone();
cv::GaussianBlur( InImage, image, cv::Size( ksize_, ksize_ ), sigma_ );
}*/
unsigned int edgePixelArraySize = pixelNum / 5; unsigned int edgePixelArraySize = pixelNum / 5;
unsigned int maxNumOfEdge = edgePixelArraySize / 20; unsigned int maxNumOfEdge = edgePixelArraySize / 20;
//compute dx, dy images //compute dx, dy images
...@@ -925,12 +919,12 @@ int EDLineDetector::EdgeDrawing( cv::Mat &image, EdgeChains &edgeChains, bool sm ...@@ -925,12 +919,12 @@ int EDLineDetector::EdgeDrawing( cv::Mat &image, EdgeChains &edgeChains, bool sm
return 1; return 1;
} }
int EDLineDetector::EDline( cv::Mat &image, LineChains &lines, bool smoothed ) int EDLineDetector::EDline( cv::Mat &image, LineChains &lines )
{ {
//first, call EdgeDrawing function to extract edges //first, call EdgeDrawing function to extract edges
EdgeChains edges; EdgeChains edges;
if( ( EdgeDrawing( image, edges, smoothed ) ) != 1 ) if( ( EdgeDrawing( image, edges ) ) != 1 )
{ {
cout << "Line Detection not finished" << endl; cout << "Line Detection not finished" << endl;
return -1; return -1;
...@@ -1411,9 +1405,9 @@ bool EDLineDetector::LineValidation_( unsigned int *xCors, unsigned int *yCors, ...@@ -1411,9 +1405,9 @@ bool EDLineDetector::LineValidation_( unsigned int *xCors, unsigned int *yCors,
} }
} }
int EDLineDetector::EDline( cv::Mat &image, bool smoothed ) int EDLineDetector::EDline( cv::Mat &image )
{ {
if( ( EDline( image, lines_, smoothed ) ) != 1 ) if( ( EDline( image, lines_/*, smoothed*/ ) ) != 1 )
{ {
return -1; return -1;
} }
......
/*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) 2014, Biagio Montesano, 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;
/****************************************************************************************\
* Regression tests for line detector comparing keylines. *
\****************************************************************************************/
const std::string LINE_DESCRIPTOR_DIR = "line_descriptor";
const std::string IMAGE_FILENAME = "cameraman.jpg";
const std::string DETECTOR_DIR = LINE_DESCRIPTOR_DIR + "/detectors";
class CV_BinaryDescriptorDetectorTest : public cvtest::BaseTest
{
public:
CV_BinaryDescriptorDetectorTest( std::string fs )
{
bd = BinaryDescriptor::createBinaryDescriptor();
fs_name = fs;
}
protected:
bool isSimilarKeylines( const KeyLine& k1, const KeyLine& k2 );
void compareKeylineSets( const std::vector<KeyLine>& validKeylines, const std::vector<KeyLine>& calcKeylines );
void createMatFromVec( const std::vector<KeyLine>& linesVec, Mat& output );
void createVecFromMat( Mat& inputMat, std::vector<KeyLine>& output );
void emptyDataTest();
void regressionTest();
virtual void run( int );
Ptr<BinaryDescriptor> bd;
std::string fs_name;
};
void CV_BinaryDescriptorDetectorTest::emptyDataTest()
{
/* one image */
Mat image;
std::vector<KeyLine> keylines;
try
{
bd->detect( image, keylines );
}
catch ( ... )
{
ts->printf( cvtest::TS::LOG, "detect() on empty image must return empty keylines vector (1).\n" );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
}
if( !keylines.empty() )
{
ts->printf( cvtest::TS::LOG, "detect() on empty image must return empty keylines vector (1).\n" );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
/* more than one image */
std::vector<Mat> images;
std::vector<std::vector<KeyLine> > keylineCollection;
try
{
bd->detect( images, keylineCollection );
}
catch ( ... )
{
ts->printf( cvtest::TS::LOG, "detect() on empty image vector must not generate exception (2).\n" );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
}
}
void CV_BinaryDescriptorDetectorTest::createMatFromVec( const std::vector<KeyLine>& linesVec, Mat& output )
{
output = Mat( (int) linesVec.size(), 17, CV_32FC1 );
for ( int i = 0; i < (int) linesVec.size(); i++ )
{
std::vector<float> klData;
KeyLine kl = linesVec[i];
klData.push_back( kl.angle );
klData.push_back( kl.class_id );
klData.push_back( kl.ePointInOctaveX );
klData.push_back( kl.ePointInOctaveY );
klData.push_back( kl.endPointX );
klData.push_back( kl.endPointY );
klData.push_back( kl.lineLength );
klData.push_back( kl.numOfPixels );
klData.push_back( kl.octave );
klData.push_back( kl.pt.x );
klData.push_back( kl.pt.y );
klData.push_back( kl.response );
klData.push_back( kl.sPointInOctaveX );
klData.push_back( kl.sPointInOctaveY );
klData.push_back( kl.size );
klData.push_back( kl.startPointX );
klData.push_back( kl.startPointY );
float* pointerToRow = output.ptr<float>( i );
for ( int j = 0; j < 17; j++ )
{
*pointerToRow = klData[j];
pointerToRow++;
}
}
}
void CV_BinaryDescriptorDetectorTest::createVecFromMat( Mat& inputMat, std::vector<KeyLine>& output )
{
for ( int i = 0; i < inputMat.rows; i++ )
{
std::vector<float> tempFloat;
KeyLine kl;
float* pointerToRow = inputMat.ptr<float>( i );
for ( int j = 0; j < 17; j++ )
{
tempFloat.push_back( *pointerToRow );
pointerToRow++;
}
kl.angle = tempFloat[0];
kl.class_id = tempFloat[1];
kl.ePointInOctaveX = tempFloat[2];
kl.ePointInOctaveY = tempFloat[3];
kl.endPointX = tempFloat[4];
kl.endPointY = tempFloat[5];
kl.lineLength = tempFloat[6];
kl.numOfPixels = tempFloat[7];
kl.octave = tempFloat[8];
kl.pt.x = tempFloat[9];
kl.pt.y = tempFloat[10];
kl.response = tempFloat[11];
kl.sPointInOctaveX = tempFloat[12];
kl.sPointInOctaveY = tempFloat[13];
kl.size = tempFloat[14];
kl.startPointX = tempFloat[15];
kl.startPointY = tempFloat[16];
output.push_back( kl );
}
}
bool CV_BinaryDescriptorDetectorTest::isSimilarKeylines( const KeyLine& k1, const KeyLine& k2 )
{
const float maxPtDif = 1.f;
const float maxSizeDif = 1.f;
const float maxAngleDif = 2.f;
const float maxResponseDif = 0.1f;
float dist = (float) norm( k1.pt - k2.pt );
return ( dist < maxPtDif && fabs( k1.size - k2.size ) < maxSizeDif && abs( k1.angle - k2.angle ) < maxAngleDif
&& abs( k1.response - k2.response ) < maxResponseDif && k1.octave == k2.octave && k1.class_id == k2.class_id );
}
void CV_BinaryDescriptorDetectorTest::compareKeylineSets( const std::vector<KeyLine>& validKeylines, const std::vector<KeyLine>& calcKeylines )
{
const float maxCountRatioDif = 0.01f;
// Compare counts of validation and calculated keylines.
float countRatio = (float) validKeylines.size() / (float) calcKeylines.size();
if( countRatio < 1 - maxCountRatioDif || countRatio > 1.f + maxCountRatioDif )
{
ts->printf( cvtest::TS::LOG, "Bad keylines count ratio (validCount = %d, calcCount = %d).\n", validKeylines.size(), calcKeylines.size() );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
int progress = 0;
int progressCount = (int) ( validKeylines.size() * calcKeylines.size() );
int badLineCount = 0;
int commonLineCount = max( (int) validKeylines.size(), (int) calcKeylines.size() );
for ( size_t v = 0; v < validKeylines.size(); v++ )
{
int nearestIdx = -1;
float minDist = std::numeric_limits<float>::max();
for ( size_t c = 0; c < calcKeylines.size(); c++ )
{
progress = update_progress( progress, (int) ( v * calcKeylines.size() + c ), progressCount, 0 );
float curDist = (float) norm( calcKeylines[c].pt - validKeylines[v].pt );
if( curDist < minDist )
{
minDist = curDist;
nearestIdx = (int) c;
}
}
assert( minDist >= 0 );
if( !isSimilarKeylines( validKeylines[v], calcKeylines[nearestIdx] ) )
badLineCount++;
}
ts->printf( cvtest::TS::LOG, "badLineCount = %d; validLineCount = %d; calcLineCount = %d\n", badLineCount, validKeylines.size(),
calcKeylines.size() );
if( badLineCount > 0.9 * commonLineCount )
{
ts->printf( cvtest::TS::LOG, " - Bad accuracy!\n" );
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
return;
}
ts->printf( cvtest::TS::LOG, " - OK\n" );
}
void CV_BinaryDescriptorDetectorTest::regressionTest()
{
assert( bd );
std::string imgFilename = std::string( ts->get_data_path() ) + LINE_DESCRIPTOR_DIR + "/" + IMAGE_FILENAME;
std::string resFilename = std::string( ts->get_data_path() ) + DETECTOR_DIR + "/" + fs_name + ".yaml";
std::cout << "PATH " << std::string( ts->get_data_path() ) << std::endl;
// Read the test image.
Mat image = imread( imgFilename );
if( image.empty() )
{
ts->printf( cvtest::TS::LOG, "Image %s can not be read.\n", imgFilename.c_str() );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
return;
}
// open a storage for reading
FileStorage fs( resFilename, FileStorage::READ );
// Compute keylines.
std::vector<KeyLine> calcKeylines;
bd->detect( image, calcKeylines );
if( fs.isOpened() ) // Compare computed and valid keylines.
{
// Read validation keylines set.
std::vector<KeyLine> validKeylines;
Mat storedKeylines;
fs["keylines"] >> storedKeylines;
createVecFromMat( storedKeylines, validKeylines );
if( validKeylines.empty() )
{
ts->printf( cvtest::TS::LOG, "keylines can not be read.\n" );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
return;
}
compareKeylineSets( validKeylines, calcKeylines );
}
else // Write detector parameters and computed keylines as validation data.
{
fs.open( resFilename, FileStorage::WRITE );
if( !fs.isOpened() )
{
ts->printf( cvtest::TS::LOG, "File %s can not be opened to write.\n", resFilename.c_str() );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
return;
}
else
{
fs << "detector_params" << "{";
bd->write( fs );
fs << "}";
Mat lines;
createMatFromVec( calcKeylines, lines );
fs << "keylines" << lines;
}
}
}
void CV_BinaryDescriptorDetectorTest::run( int )
{
if( !bd )
{
ts->printf( cvtest::TS::LOG, "Feature detector is empty.\n" );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
return;
}
emptyDataTest();
regressionTest();
ts->set_failed_test_info( cvtest::TS::OK );
}
/****************************************************************************************\
* Tests registrations *
\****************************************************************************************/
TEST( BinaryDescriptor_Detector, regression )
{
CV_BinaryDescriptorDetectorTest test( std::string( "edl_detector_keylines_cameraman" ) );
test.safe_run();
}
#include "test_precomp.hpp"
CV_TEST_MAIN("cv")
#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/opencv.hpp"
#include "opencv2/ts.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/line_descriptor.hpp"
#include <opencv2/core.hpp>
#include <iostream>
#include <string.h>
#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