mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 09:25:45 +08:00
added OpponentColorDescriptorExtractor
This commit is contained in:
parent
1a2fee0d56
commit
9e9d4b9e49
@ -1394,7 +1394,6 @@ protected:
|
||||
virtual void detectImpl( const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints ) const;
|
||||
};
|
||||
|
||||
|
||||
CV_EXPORTS Mat windowedMatchingMask( const vector<KeyPoint>& keypoints1, const vector<KeyPoint>& keypoints2,
|
||||
float maxDeltaX, float maxDeltaY );
|
||||
|
||||
@ -1429,6 +1428,9 @@ public:
|
||||
virtual void read( const FileNode& ) {};
|
||||
virtual void write( FileStorage& ) const {};
|
||||
|
||||
virtual int descriptorSize() const = 0;
|
||||
virtual int descriptorType() const = 0;
|
||||
|
||||
protected:
|
||||
/*
|
||||
* Remove keypoints within border_pixels of an image edge.
|
||||
@ -1451,6 +1453,9 @@ public:
|
||||
virtual void read( const FileNode &fn );
|
||||
virtual void write( FileStorage &fs ) const;
|
||||
|
||||
virtual int descriptorSize() const { return sift.descriptorSize(); }
|
||||
virtual int descriptorType() const { return CV_32FC1; }
|
||||
|
||||
protected:
|
||||
SIFT sift;
|
||||
};
|
||||
@ -1465,6 +1470,9 @@ public:
|
||||
virtual void read( const FileNode &fn );
|
||||
virtual void write( FileStorage &fs ) const;
|
||||
|
||||
virtual int descriptorSize() const { return surf.descriptorSize(); }
|
||||
virtual int descriptorType() const { return CV_32FC1; }
|
||||
|
||||
protected:
|
||||
SURF surf;
|
||||
};
|
||||
@ -1479,6 +1487,9 @@ public:
|
||||
virtual void read( const FileNode &fn );
|
||||
virtual void write( FileStorage &fs ) const;
|
||||
|
||||
virtual int descriptorSize() const { return classifier_.classes(); }
|
||||
virtual int descriptorType() const { return DataType<T>::type; }
|
||||
|
||||
protected:
|
||||
RTreeClassifier classifier_;
|
||||
static const int BORDER_SIZE = 16;
|
||||
@ -1518,6 +1529,30 @@ template<typename T>
|
||||
void CalonderDescriptorExtractor<T>::write( FileStorage& ) const
|
||||
{}
|
||||
|
||||
/*
|
||||
* Adapts a descriptor extractor to compute descripors in Opponent Color Space
|
||||
* (refer to van de Sande et al., CGIV 2008 "Color Descriptors for Object Category Recognition").
|
||||
* Input RGB image is transformed in Opponent Color Space. Then unadapted descriptor extractor
|
||||
* (set in constructor) computes descriptors on each of the three channel and concatenate
|
||||
* them into a single color descriptor.
|
||||
*/
|
||||
class OpponentColorDescriptorExtractor : public DescriptorExtractor
|
||||
{
|
||||
public:
|
||||
OpponentColorDescriptorExtractor( const Ptr<DescriptorExtractor>& dextractor );
|
||||
|
||||
virtual void compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const;
|
||||
|
||||
virtual void read( const FileNode& );
|
||||
virtual void write( FileStorage& ) const;
|
||||
|
||||
virtual int descriptorSize() const { return 3*dextractor->descriptorSize(); }
|
||||
virtual int descriptorType() const { return dextractor->descriptorType(); }
|
||||
|
||||
protected:
|
||||
Ptr<DescriptorExtractor> dextractor;
|
||||
};
|
||||
|
||||
CV_EXPORTS Ptr<DescriptorExtractor> createDescriptorExtractor( const string& descriptorExtractorType );
|
||||
|
||||
/****************************************************************************************\
|
||||
|
@ -147,8 +147,16 @@ static void _prepareImgAndDrawKeypoints( const Mat& img1, const vector<KeyPoint>
|
||||
outImg.create( size, CV_MAKETYPE(img1.depth(), 3) );
|
||||
outImg1 = outImg( Rect(0, 0, img1.cols, img1.rows) );
|
||||
outImg2 = outImg( Rect(img1.cols, 0, img2.cols, img2.rows) );
|
||||
cvtColor( img1, outImg1, CV_GRAY2RGB );
|
||||
cvtColor( img2, outImg2, CV_GRAY2RGB );
|
||||
|
||||
if( img1.type() == CV_8U )
|
||||
cvtColor( img1, outImg1, CV_GRAY2BGR );
|
||||
else
|
||||
img1.copyTo( outImg1 );
|
||||
|
||||
if( img2.type() == CV_8U )
|
||||
cvtColor( img2, outImg2, CV_GRAY2BGR );
|
||||
else
|
||||
img2.copyTo( outImg2 );
|
||||
}
|
||||
|
||||
// draw keypoints
|
||||
@ -308,7 +316,10 @@ void SiftDescriptorExtractor::compute( const Mat& image,
|
||||
Mat& descriptors) const
|
||||
{
|
||||
bool useProvidedKeypoints = true;
|
||||
sift(image, Mat(), keypoints, descriptors, useProvidedKeypoints);
|
||||
Mat grayImage = image;
|
||||
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
||||
|
||||
sift(grayImage, Mat(), keypoints, descriptors, useProvidedKeypoints);
|
||||
}
|
||||
|
||||
void SiftDescriptorExtractor::read (const FileNode &fn)
|
||||
@ -355,7 +366,10 @@ void SurfDescriptorExtractor::compute( const Mat& image,
|
||||
vector<float> _descriptors;
|
||||
Mat mask;
|
||||
bool useProvidedKeypoints = true;
|
||||
surf(image, mask, keypoints, _descriptors, useProvidedKeypoints);
|
||||
Mat grayImage = image;
|
||||
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
||||
|
||||
surf(grayImage, mask, keypoints, _descriptors, useProvidedKeypoints);
|
||||
|
||||
descriptors.create((int)keypoints.size(), (int)surf.descriptorSize(), CV_32FC1);
|
||||
assert( (int)_descriptors.size() == descriptors.rows * descriptors.cols );
|
||||
@ -380,6 +394,104 @@ void SurfDescriptorExtractor::write( FileStorage &fs ) const
|
||||
fs << "extended" << surf.extended;
|
||||
}
|
||||
|
||||
/****************************************************************************************\
|
||||
* OpponentColorDescriptorExtractor *
|
||||
\****************************************************************************************/
|
||||
OpponentColorDescriptorExtractor::OpponentColorDescriptorExtractor( const Ptr<DescriptorExtractor>& _dextractor ) :
|
||||
dextractor(_dextractor)
|
||||
{}
|
||||
|
||||
void convertBGRImageToOpponentColorSpace( const Mat& bgrImage, vector<Mat>& opponentChannels )
|
||||
{
|
||||
if( bgrImage.type() != CV_8UC3 )
|
||||
CV_Error( CV_StsBadArg, "input image must be an BGR image of type CV_8UC3" );
|
||||
|
||||
// Split image into RGB to allow conversion to Opponent Color Space.
|
||||
vector<Mat> bgrChannels(3);
|
||||
split( bgrImage, bgrChannels );
|
||||
|
||||
// Prepare opponent color space storage matrices.
|
||||
opponentChannels.resize( 3 );
|
||||
opponentChannels[0] = cv::Mat(bgrImage.size(), CV_8UC1); // R-G RED-GREEN
|
||||
opponentChannels[1] = cv::Mat(bgrImage.size(), CV_8UC1); // R+G-2B YELLOW-BLUE
|
||||
opponentChannels[2] = cv::Mat(bgrImage.size(), CV_8UC1); // R+G+B
|
||||
|
||||
// Calculate the channels of the opponent color space
|
||||
{
|
||||
// (R - G) / sqrt(2)
|
||||
MatConstIterator_<char> rIt = bgrChannels[2].begin<char>();
|
||||
MatConstIterator_<char> gIt = bgrChannels[1].begin<char>();
|
||||
MatIterator_<char> dstIt = opponentChannels[0].begin<char>();
|
||||
float factor = 1.f / sqrt(2.0);
|
||||
for( ; dstIt != opponentChannels[0].end<char>(); ++rIt, ++gIt, ++dstIt )
|
||||
{
|
||||
int value = static_cast<int>( static_cast<float>(static_cast<int>(*gIt)-static_cast<int>(*rIt)) * factor );
|
||||
if( value < 0 ) value = 0;
|
||||
if( value > 255 ) value = 255;
|
||||
(*dstIt) = static_cast<unsigned char>(value);
|
||||
}
|
||||
}
|
||||
{
|
||||
// (R + G - 2B)/sqrt(6)
|
||||
MatConstIterator_<char> rIt = bgrChannels[2].begin<char>();
|
||||
MatConstIterator_<char> gIt = bgrChannels[1].begin<char>();
|
||||
MatConstIterator_<char> bIt = bgrChannels[0].begin<char>();
|
||||
MatIterator_<char> dstIt = opponentChannels[1].begin<char>();
|
||||
float factor = 1.f / sqrt(6.0);
|
||||
for( ; dstIt != opponentChannels[1].end<char>(); ++rIt, ++gIt, ++bIt, ++dstIt )
|
||||
{
|
||||
int value = static_cast<int>( static_cast<float>(static_cast<int>(*rIt) + static_cast<int>(*gIt) - 2*static_cast<int>(*bIt)) *
|
||||
factor );
|
||||
if( value < 0 ) value = 0;
|
||||
if( value > 255 ) value = 255;
|
||||
(*dstIt) = static_cast<unsigned char>(value);
|
||||
}
|
||||
}
|
||||
{
|
||||
// (R + G + B)/sqrt(3)
|
||||
MatConstIterator_<char> rIt = bgrChannels[2].begin<char>();
|
||||
MatConstIterator_<char> gIt = bgrChannels[1].begin<char>();
|
||||
MatConstIterator_<char> bIt = bgrChannels[0].begin<char>();
|
||||
MatIterator_<char> dstIt = opponentChannels[2].begin<char>();
|
||||
float factor = 1.f / sqrt(3.0);
|
||||
for( ; dstIt != opponentChannels[2].end<char>(); ++rIt, ++gIt, ++bIt, ++dstIt )
|
||||
{
|
||||
int value = static_cast<int>( static_cast<float>(static_cast<int>(*rIt) + static_cast<int>(*gIt) + static_cast<int>(*bIt)) *
|
||||
factor );
|
||||
if( value < 0 ) value = 0;
|
||||
if( value > 255 ) value = 255;
|
||||
(*dstIt) = static_cast<unsigned char>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpponentColorDescriptorExtractor::compute( const Mat& bgrImage, vector<KeyPoint>& keypoints, Mat& descriptors ) const
|
||||
{
|
||||
vector<Mat> opponentChannels;
|
||||
convertBGRImageToOpponentColorSpace( bgrImage, opponentChannels );
|
||||
|
||||
// Compute descriptors three times, once for each Opponent channel
|
||||
// and concatenate into a single color surf descriptor
|
||||
int descriptorSize = dextractor->descriptorSize();
|
||||
descriptors.create( static_cast<int>(keypoints.size()), 3*descriptorSize, CV_32FC1 );
|
||||
for( int i = 0; i < 3/*channel count*/; i++ )
|
||||
{
|
||||
CV_Assert( opponentChannels[i].type() == CV_8UC1 );
|
||||
Mat opponentDescriptors = descriptors.colRange( i*descriptorSize, (i+1)*descriptorSize );
|
||||
dextractor->compute( opponentChannels[i], keypoints, opponentDescriptors );
|
||||
}
|
||||
}
|
||||
|
||||
void OpponentColorDescriptorExtractor::read( const FileNode& fn )
|
||||
{
|
||||
dextractor->read( fn );
|
||||
}
|
||||
|
||||
void OpponentColorDescriptorExtractor::write( FileStorage& fs ) const
|
||||
{
|
||||
dextractor->write( fs );
|
||||
}
|
||||
|
||||
/****************************************************************************************\
|
||||
* Factory functions for descriptor extractor and matcher creating *
|
||||
\****************************************************************************************/
|
||||
@ -389,20 +501,19 @@ Ptr<DescriptorExtractor> createDescriptorExtractor( const string& descriptorExtr
|
||||
DescriptorExtractor* de = 0;
|
||||
if( !descriptorExtractorType.compare( "SIFT" ) )
|
||||
{
|
||||
de = new SiftDescriptorExtractor/*( double magnification=SIFT::DescriptorParams::GET_DEFAULT_MAGNIFICATION(),
|
||||
bool isNormalize=true, bool recalculateAngles=true,
|
||||
int nOctaves=SIFT::CommonParams::DEFAULT_NOCTAVES,
|
||||
int nOctaveLayers=SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS,
|
||||
int firstOctave=SIFT::CommonParams::DEFAULT_FIRST_OCTAVE,
|
||||
int angleMode=SIFT::CommonParams::FIRST_ANGLE )*/;
|
||||
de = new SiftDescriptorExtractor();
|
||||
}
|
||||
else if( !descriptorExtractorType.compare( "SURF" ) )
|
||||
{
|
||||
de = new SurfDescriptorExtractor/*( int nOctaves=4, int nOctaveLayers=2, bool extended=false )*/;
|
||||
de = new SurfDescriptorExtractor();
|
||||
}
|
||||
else
|
||||
else if( !descriptorExtractorType.compare( "OpponentSIFT" ) )
|
||||
{
|
||||
//CV_Error( CV_StsBadArg, "unsupported descriptor extractor type");
|
||||
de = new OpponentColorDescriptorExtractor( new SiftDescriptorExtractor );
|
||||
}
|
||||
else if( !descriptorExtractorType.compare( "OpponentSURF" ) )
|
||||
{
|
||||
de = new OpponentColorDescriptorExtractor( new SurfDescriptorExtractor );
|
||||
}
|
||||
return de;
|
||||
}
|
||||
@ -414,14 +525,10 @@ Ptr<DescriptorMatcher> createDescriptorMatcher( const string& descriptorMatcherT
|
||||
{
|
||||
dm = new BruteForceMatcher<L2<float> >();
|
||||
}
|
||||
else if ( !descriptorMatcherType.compare( "BruteForce-L1" ) )
|
||||
else if( !descriptorMatcherType.compare( "BruteForce-L1" ) )
|
||||
{
|
||||
dm = new BruteForceMatcher<L1<float> >();
|
||||
}
|
||||
else
|
||||
{
|
||||
//CV_Error( CV_StsBadArg, "unsupported descriptor matcher type");
|
||||
}
|
||||
|
||||
return dm;
|
||||
}
|
||||
|
@ -90,7 +90,9 @@ void FastFeatureDetector::write (FileStorage& fs) const
|
||||
|
||||
void FastFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints) const
|
||||
{
|
||||
FAST( image, keypoints, threshold, nonmaxSuppression );
|
||||
Mat grayImage = image;
|
||||
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
||||
FAST( grayImage, keypoints, threshold, nonmaxSuppression );
|
||||
removeInvalidPoints( mask, keypoints );
|
||||
}
|
||||
|
||||
@ -127,8 +129,11 @@ void GoodFeaturesToTrackDetector::write (FileStorage& fs) const
|
||||
void GoodFeaturesToTrackDetector::detectImpl( const Mat& image, const Mat& mask,
|
||||
vector<KeyPoint>& keypoints ) const
|
||||
{
|
||||
Mat grayImage = image;
|
||||
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
||||
|
||||
vector<Point2f> corners;
|
||||
goodFeaturesToTrack( image, corners, maxCorners, qualityLevel, minDistance, mask,
|
||||
goodFeaturesToTrack( grayImage, corners, maxCorners, qualityLevel, minDistance, mask,
|
||||
blockSize, useHarrisDetector, k );
|
||||
keypoints.resize(corners.size());
|
||||
vector<Point2f>::const_iterator corner_it = corners.begin();
|
||||
@ -190,7 +195,11 @@ void MserFeatureDetector::write (FileStorage& fs) const
|
||||
void MserFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints ) const
|
||||
{
|
||||
vector<vector<Point> > msers;
|
||||
mser(image, msers, mask);
|
||||
|
||||
Mat grayImage = image;
|
||||
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
||||
|
||||
mser(grayImage, msers, mask);
|
||||
|
||||
keypoints.resize( msers.size() );
|
||||
vector<vector<Point> >::const_iterator contour_it = msers.begin();
|
||||
@ -239,7 +248,10 @@ void StarFeatureDetector::write (FileStorage& fs) const
|
||||
|
||||
void StarFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints) const
|
||||
{
|
||||
star(image, keypoints);
|
||||
Mat grayImage = image;
|
||||
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
||||
|
||||
star(grayImage, keypoints);
|
||||
removeInvalidPoints(mask, keypoints);
|
||||
}
|
||||
|
||||
@ -282,7 +294,10 @@ void SiftFeatureDetector::write (FileStorage& fs) const
|
||||
void SiftFeatureDetector::detectImpl( const Mat& image, const Mat& mask,
|
||||
vector<KeyPoint>& keypoints) const
|
||||
{
|
||||
sift(image, mask, keypoints);
|
||||
Mat grayImage = image;
|
||||
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
||||
|
||||
sift(grayImage, mask, keypoints);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -313,7 +328,10 @@ void SurfFeatureDetector::write (FileStorage& fs) const
|
||||
void SurfFeatureDetector::detectImpl( const Mat& image, const Mat& mask,
|
||||
vector<KeyPoint>& keypoints) const
|
||||
{
|
||||
surf(image, mask, keypoints);
|
||||
Mat grayImage = image;
|
||||
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
||||
|
||||
surf(grayImage, mask, keypoints);
|
||||
}
|
||||
|
||||
Ptr<FeatureDetector> createFeatureDetector( const string& detectorType )
|
||||
@ -353,10 +371,6 @@ Ptr<FeatureDetector> createFeatureDetector( const string& detectorType )
|
||||
fd = new GoodFeaturesToTrackDetector( 1000/*maxCorners*/, 0.01/*qualityLevel*/, 1./*minDistance*/,
|
||||
3/*int _blockSize*/, true/*useHarrisDetector*/, 0.04/*k*/ );
|
||||
}
|
||||
else
|
||||
{
|
||||
//CV_Error( CV_StsBadArg, "unsupported feature detector type");
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
@ -154,9 +154,9 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
cout << "< Reading the images..." << endl;
|
||||
Mat img1 = imread( argv[3], CV_LOAD_IMAGE_GRAYSCALE), img2;
|
||||
Mat img1 = imread( argv[3] ), img2;
|
||||
if( !isWarpPerspective )
|
||||
img2 = imread( argv[4], CV_LOAD_IMAGE_GRAYSCALE);
|
||||
img2 = imread( argv[4] );
|
||||
cout << ">" << endl;
|
||||
if( img1.empty() || (!isWarpPerspective && img2.empty()) )
|
||||
{
|
||||
|
@ -321,9 +321,14 @@ public:
|
||||
};
|
||||
|
||||
//CV_DescriptorExtractorTest siftDescriptorTest( "descriptor_sift", 0.001f,
|
||||
// createDescriptorExtractor("SIFT"), 8.06652f );
|
||||
// createDescriptorExtractor("SIFT"), 8.06652f );
|
||||
//CV_DescriptorExtractorTest surfDescriptorTest( "descriptor_surf", 0.004f,
|
||||
// createDescriptorExtractor("SURF"), 0.147372f );
|
||||
// createDescriptorExtractor("SURF"), 0.147372f );
|
||||
//CV_DescriptorExtractorTest siftDescriptorTest( "descriptor_opponent_sift", 0.001f,
|
||||
// createDescriptorExtractor("OpponentSIFT"), 8.06652f );
|
||||
//CV_DescriptorExtractorTest surfDescriptorTest( "descriptor_opponent_surf", 0.004f,
|
||||
// createDescriptorExtractor("OpponentSURF"), 0.147372f );
|
||||
|
||||
#if CV_SSE2
|
||||
CV_CalonderDescriptorExtractorTest<uchar> ucharCalonderTest( "descriptor_calonder_uchar",
|
||||
std::numeric_limits<float>::epsilon() + 1,
|
||||
|
Loading…
Reference in New Issue
Block a user