mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-19 02:09:23 +08:00
Detection test, smoothed removal, setter modified, samples corrected
This commit is contained in:
@@ -190,14 +190,12 @@ class CV_EXPORTS_W BinaryDescriptor : public Algorithm
|
||||
|
||||
/* requires descriptors computation (only one image) */
|
||||
CV_WRAP
|
||||
void compute( const Mat& image, CV_OUT CV_IN_OUT std::vector<KeyLine>& keylines, CV_OUT Mat& descriptors, bool returnFloatDescr = false,
|
||||
bool useDetectionData = false ) const;
|
||||
void compute( const Mat& image, CV_OUT CV_IN_OUT std::vector<KeyLine>& keylines, CV_OUT Mat& descriptors, bool returnFloatDescr = false ) const;
|
||||
|
||||
/* requires descriptors computation (more than one image) */
|
||||
CV_WRAP
|
||||
void compute( const std::vector<Mat>& images, std::vector<std::vector<KeyLine> >& keylines, std::vector<Mat>& descriptors, bool returnFloatDescr =
|
||||
false,
|
||||
bool useDetectionData = false ) const;
|
||||
false ) const;
|
||||
|
||||
/* returns descriptor size */
|
||||
CV_WRAP
|
||||
|
@@ -106,21 +106,19 @@ class EDLineDetector
|
||||
/*extract edges from image
|
||||
*image: In, gray image;
|
||||
*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
|
||||
*/
|
||||
int EdgeDrawing( cv::Mat &image, EdgeChains &edgeChains, bool smoothed );
|
||||
int EdgeDrawing( cv::Mat &image, EdgeChains &edgeChains );
|
||||
|
||||
/*extract lines from image
|
||||
*image: In, gray image;
|
||||
*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
|
||||
*/
|
||||
int EDline( cv::Mat &image, LineChains &lines, bool smoothed );
|
||||
int EDline( cv::Mat &image, LineChains &lines );
|
||||
|
||||
/* 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;
|
||||
|
||||
|
@@ -61,19 +61,6 @@ static void help()
|
||||
<< 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 )
|
||||
{
|
||||
/* get parameters from command line */
|
||||
@@ -103,18 +90,9 @@ int main( int argc, char** argv )
|
||||
std::vector<KeyLine> keylines;
|
||||
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 */
|
||||
cv::Mat descriptors;
|
||||
|
||||
bd->compute( imageMat, keylines, descriptors);
|
||||
writeMat( descriptors, "bd_descriptors", 1 );
|
||||
|
||||
}
|
||||
|
@@ -192,5 +192,8 @@ int main( int argc, char** argv )
|
||||
/* require knn match */
|
||||
bdm->knnMatch( descr1, descr2, matches, 6 );
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@@ -101,13 +101,33 @@ int main( int argc, char** argv )
|
||||
( *bd )( imageMat1, mask1, keylines1, descr1, 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 */
|
||||
Ptr<BinaryDescriptorMatcher> bdm = BinaryDescriptorMatcher::createBinaryDescriptorMatcher();
|
||||
|
||||
/* require match */
|
||||
std::vector<DMatch> matches;
|
||||
bdm->match( descr1, descr2, matches );
|
||||
bdm->match( left_lbd, right_lbd, matches );
|
||||
|
||||
/* select best matches */
|
||||
std::vector<DMatch> good_matches;
|
||||
@@ -119,8 +139,9 @@ int main( int argc, char** argv )
|
||||
|
||||
/* plot matches */
|
||||
cv::Mat outImg;
|
||||
cv::Mat scaled1, scaled2;
|
||||
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 );
|
||||
|
||||
imshow( "Matches", outImg );
|
||||
@@ -135,28 +156,34 @@ int main( int argc, char** argv )
|
||||
lsd->detect( imageMat1, klsd1, 2, 2, mask1 );
|
||||
lsd->detect( imageMat2, klsd2, 2, 2, mask2 );
|
||||
|
||||
/* select lines from first octave */
|
||||
/* compute descriptors for lines from first octave */
|
||||
bd->compute( imageMat1, klsd1, lsd_descr1 );
|
||||
bd->compute( imageMat2, klsd2, lsd_descr2 );
|
||||
|
||||
/* select lines and descriptors from first octave */
|
||||
std::vector<KeyLine> octave0_1, octave0_2;
|
||||
Mat leftDEscr, rightDescr;
|
||||
for ( int i = 0; i < (int) klsd1.size(); i++ )
|
||||
{
|
||||
if(klsd1[i].octave == 0)
|
||||
octave0_1.push_back(klsd1[i]);
|
||||
}
|
||||
|
||||
for(int j = 0; j<(int)klsd1.size(); j++)
|
||||
if( klsd1[i].octave == 1 )
|
||||
{
|
||||
if(klsd2[j].octave == 0)
|
||||
octave0_2.push_back(klsd2[j]);
|
||||
octave0_1.push_back( klsd1[i] );
|
||||
leftDEscr.push_back( lsd_descr1.row( i ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* compute descriptors for lines from first octave */
|
||||
bd->compute( imageMat1, octave0_1, lsd_descr1 );
|
||||
bd->compute( imageMat2, octave0_2, lsd_descr2 );
|
||||
for ( int j = 0; j < (int) klsd2.size(); j++ )
|
||||
{
|
||||
if( klsd2[j].octave == 1 )
|
||||
{
|
||||
octave0_2.push_back( klsd2[j] );
|
||||
rightDescr.push_back( lsd_descr2.row( j ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* compute matches */
|
||||
std::vector<DMatch> lsd_matches;
|
||||
bdm->match( lsd_descr1, lsd_descr2, lsd_matches);
|
||||
bdm->match( leftDEscr, rightDescr, lsd_matches );
|
||||
|
||||
/* select best matches */
|
||||
good_matches.clear();
|
||||
@@ -166,9 +193,10 @@ int main( int argc, char** argv )
|
||||
good_matches.push_back( lsd_matches[i] );
|
||||
}
|
||||
|
||||
|
||||
/* plot matches */
|
||||
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 );
|
||||
drawLineMatches( imageMat1, octave0_1, imageMat2, octave0_2, good_matches, lsd_outImg, Scalar::all( -1 ), Scalar::all( -1 ), lsd_mask,
|
||||
DrawLinesMatchesFlags::DEFAULT );
|
||||
|
@@ -56,7 +56,7 @@ void LSDDetector::computeGaussianPyramid( const Mat& image, int numOctaves, int
|
||||
|
||||
/* insert input image into pyramid */
|
||||
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 );
|
||||
|
||||
/* fill Gaussian pyramid */
|
||||
|
@@ -111,6 +111,46 @@ int BinaryDescriptor::getWidthOfBand()
|
||||
void BinaryDescriptor::setWidthOfBand( int 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()
|
||||
@@ -351,6 +391,12 @@ unsigned char BinaryDescriptor::binaryConversion( float* f1, float* f2 )
|
||||
/* requires line detection (only one image) */
|
||||
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 ) )
|
||||
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
|
||||
/* 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
|
||||
{
|
||||
|
||||
if( images.size() == 0 )
|
||||
{
|
||||
std::cout << "Error: input image for detection is empty" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/* detect lines from each image */
|
||||
for ( size_t counter = 0; counter < images.size(); counter++ )
|
||||
{
|
||||
@@ -444,18 +497,18 @@ void BinaryDescriptor::detectImpl( const Mat& imageSrc, std::vector<KeyLine>& ke
|
||||
}
|
||||
|
||||
/* 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,
|
||||
bool useDetectionData ) const
|
||||
void BinaryDescriptor::compute( const Mat& image, CV_OUT CV_IN_OUT std::vector<KeyLine>& keylines, CV_OUT Mat& descriptors,
|
||||
bool returnFloatDescr ) const
|
||||
{
|
||||
computeImpl( image, keylines, descriptors, returnFloatDescr, useDetectionData );
|
||||
computeImpl( image, keylines, descriptors, returnFloatDescr, false );
|
||||
}
|
||||
|
||||
/* 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,
|
||||
bool returnFloatDescr, bool useDetectionData ) const
|
||||
bool returnFloatDescr ) const
|
||||
{
|
||||
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 */
|
||||
@@ -621,7 +674,6 @@ int BinaryDescriptor::OctaveKeyLines( cv::Mat& image, ScaleLines &keyLines )
|
||||
/* loop over number of octaves */
|
||||
for ( int octaveCount = 0; octaveCount < params.numOfOctave_; octaveCount++ )
|
||||
{
|
||||
|
||||
/* matrix storing results from blurring processes */
|
||||
cv::Mat blur;
|
||||
|
||||
@@ -631,7 +683,7 @@ int BinaryDescriptor::OctaveKeyLines( cv::Mat& image, ScaleLines &keyLines )
|
||||
images_sizes[octaveCount] = blur.size();
|
||||
|
||||
/* for current octave, extract lines */
|
||||
if( ( edLineVec_[octaveCount]->EDline( blur, true ) ) != 1 )
|
||||
if( ( edLineVec_[octaveCount]->EDline( blur ) ) != 1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
@@ -97,13 +97,15 @@ void drawLineMatches( const Mat& img1, const std::vector<KeyLine>& keylines1, co
|
||||
for ( size_t i = 0; i < keylines1.size(); 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++ )
|
||||
{
|
||||
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
|
||||
matchColorRGB = matchColor;
|
||||
|
||||
/* 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( right.startPointX + offset, right.startPointY ), Point2f( right.endPointX + offset, right.endPointY ), singleLineColorRGB,
|
||||
line( outImg, Point2f( left.sPointInOctaveX, left.sPointInOctaveY ), Point2f( left.ePointInOctaveX, left.ePointInOctaveY ), singleLineColorRGB, 2 );
|
||||
|
||||
line( outImg, Point2f( right.sPointInOctaveX + offset, right.sPointInOctaveY ), Point2f( right.ePointInOctaveX + offset, right.ePointInOctaveY ), 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( right.sPointInOctaveX + offset, right.sPointInOctaveY ), matchColorRGB, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
imageHeight = image.rows;
|
||||
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 maxNumOfEdge = edgePixelArraySize / 20;
|
||||
//compute dx, dy images
|
||||
@@ -925,12 +919,12 @@ int EDLineDetector::EdgeDrawing( cv::Mat &image, EdgeChains &edgeChains, bool sm
|
||||
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
|
||||
EdgeChains edges;
|
||||
if( ( EdgeDrawing( image, edges, smoothed ) ) != 1 )
|
||||
if( ( EdgeDrawing( image, edges ) ) != 1 )
|
||||
{
|
||||
cout << "Line Detection not finished" << endl;
|
||||
return -1;
|
||||
@@ -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;
|
||||
}
|
||||
|
341
modules/line_descriptor/test/test_detector_regression.cpp
Normal file
341
modules/line_descriptor/test/test_detector_regression.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
/*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();
|
||||
}
|
3
modules/line_descriptor/test/test_main.cpp
Normal file
3
modules/line_descriptor/test/test_main.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
CV_TEST_MAIN("cv")
|
24
modules/line_descriptor/test/test_precomp.hpp
Normal file
24
modules/line_descriptor/test/test_precomp.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#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
|
Reference in New Issue
Block a user