Commit 9e9d4b9e authored by Maria Dimashova's avatar Maria Dimashova

added OpponentColorDescriptorExtractor

parent 1a2fee0d
......@@ -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,
......
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