Commit 874196e3 authored by Andrey Kamaev's avatar Andrey Kamaev

Implemented read/write methods for FlannBasedMatcher; fixed features2d wrappers for java

parent 16b0fcf0
......@@ -2540,6 +2540,11 @@ public:
virtual void add( const vector<Mat>& descriptors );
virtual void clear();
// Reads matcher object from a file node
virtual void read( const FileNode& );
// Writes matcher object to a file storage
virtual void write( FileStorage& ) const;
virtual void train();
virtual bool isMaskSupported() const;
......
......@@ -542,6 +542,195 @@ void FlannBasedMatcher::train()
}
}
void FlannBasedMatcher::read( const FileNode& fn)
{
if (indexParams == 0)
indexParams = new flann::IndexParams();
FileNode ip = fn["indexParams"];
CV_Assert(ip.type() == FileNode::SEQ);
for(size_t i = 0; i < ip.size(); ++i)
{
CV_Assert(ip[i].type() == FileNode::MAP);
std::string name = (std::string)ip[i]["name"];
int type = (int)ip[i]["type"];
switch(type)
{
case CV_8U:
case CV_8S:
case CV_16U:
case CV_16S:
case CV_32S:
indexParams->setInt(name, (int) ip[i]["value"]);
break;
case CV_32F:
indexParams->setFloat(name, (float) ip[i]["value"]);
break;
case CV_64F:
indexParams->setDouble(name, (double) ip[i]["value"]);
break;
case CV_USRTYPE1:
indexParams->setString(name, (std::string) ip[i]["value"]);
break;
case CV_MAKETYPE(CV_USRTYPE1,2):
indexParams->setBool(name, (int) ip[i]["value"]);
break;
case CV_MAKETYPE(CV_USRTYPE1,3):
indexParams->setAlgorithm(name, (int) ip[i]["value"]);
break;
};
}
if (searchParams == 0)
searchParams = new flann::SearchParams();
FileNode sp = fn["searchParams"];
CV_Assert(sp.type() == FileNode::SEQ);
for(size_t i = 0; i < sp.size(); ++i)
{
CV_Assert(sp[i].type() == FileNode::MAP);
std::string name = (std::string)sp[i]["name"];
int type = (int)sp[i]["type"];
switch(type)
{
case CV_8U:
case CV_8S:
case CV_16U:
case CV_16S:
case CV_32S:
searchParams->setInt(name, (int) sp[i]["value"]);
break;
case CV_32F:
searchParams->setFloat(name, (float) ip[i]["value"]);
break;
case CV_64F:
searchParams->setDouble(name, (double) ip[i]["value"]);
break;
case CV_USRTYPE1:
searchParams->setString(name, (std::string) ip[i]["value"]);
break;
case CV_MAKETYPE(CV_USRTYPE1,2):
searchParams->setBool(name, (int) ip[i]["value"]);
break;
case CV_MAKETYPE(CV_USRTYPE1,3):
searchParams->setAlgorithm(name, (int) ip[i]["value"]);
break;
};
}
flannIndex.release();
}
void FlannBasedMatcher::write( FileStorage& fs) const
{
fs << "indexParams" << "[";
if (indexParams != 0)
{
std::vector<std::string> names;
std::vector<int> types;
std::vector<std::string> strValues;
std::vector<double> numValues;
indexParams->getAll(names, types, strValues, numValues);
for(size_t i = 0; i < names.size(); ++i)
{
fs << "{" << "name" << names[i] << "type" << types[i] << "value";
switch(types[i])
{
case CV_8U:
fs << (uchar)numValues[i];
break;
case CV_8S:
fs << (char)numValues[i];
break;
case CV_16U:
fs << (ushort)numValues[i];
break;
case CV_16S:
fs << (short)numValues[i];
break;
case CV_32S:
case CV_MAKETYPE(CV_USRTYPE1,2):
case CV_MAKETYPE(CV_USRTYPE1,3):
fs << (int)numValues[i];
break;
case CV_32F:
fs << (float)numValues[i];
break;
case CV_64F:
fs << (double)numValues[i];
break;
case CV_USRTYPE1:
fs << strValues[i];
break;
default:
fs << (double)numValues[i];
fs << "typename" << strValues[i];
break;
}
fs << "}";
}
}
fs << "]" << "searchParams" << "[";
if (searchParams != 0)
{
std::vector<std::string> names;
std::vector<int> types;
std::vector<std::string> strValues;
std::vector<double> numValues;
searchParams->getAll(names, types, strValues, numValues);
for(size_t i = 0; i < names.size(); ++i)
{
fs << "{" << "name" << names[i] << "type" << types[i] << "value";
switch(types[i])
{
case CV_8U:
fs << (uchar)numValues[i];
break;
case CV_8S:
fs << (char)numValues[i];
break;
case CV_16U:
fs << (ushort)numValues[i];
break;
case CV_16S:
fs << (short)numValues[i];
break;
case CV_32S:
case CV_MAKETYPE(CV_USRTYPE1,2):
case CV_MAKETYPE(CV_USRTYPE1,3):
fs << (int)numValues[i];
break;
case CV_32F:
fs << (float)numValues[i];
break;
case CV_64F:
fs << (double)numValues[i];
break;
case CV_USRTYPE1:
fs << strValues[i];
break;
default:
fs << (double)numValues[i];
fs << "typename" << strValues[i];
break;
}
fs << "}";
}
}
fs << "]";
}
bool FlannBasedMatcher::isMaskSupported() const
{
return false;
......
......@@ -68,6 +68,9 @@ struct CV_EXPORTS IndexParams
void setString(const std::string& key, const std::string& value);
void setInt(const std::string& key, int value);
void setDouble(const std::string& key, double value);
void setFloat(const std::string& key, float value);
void setBool(const std::string& key, bool value);
void setAlgorithm(const std::string& key, int value);
void getAll(std::vector<std::string>& names,
std::vector<int>& types,
......
......@@ -70,7 +70,21 @@ void IndexParams::setDouble(const std::string& key, double value)
{
setParam(*this, key, value);
}
void IndexParams::setFloat(const std::string& key, float value)
{
setParam(*this, key, value);
}
void IndexParams::setBool(const std::string& key, bool value)
{
setParam(*this, key, value);
}
void IndexParams::setAlgorithm(const std::string& key, int value)
{
setParam(*this, key, (cvflann::flann_algorithm_t)value);
}
void IndexParams::getAll(std::vector<std::string>& names,
std::vector<int>& types,
......@@ -94,23 +108,88 @@ void IndexParams::getAll(std::vector<std::string>& names,
types.push_back(CV_USRTYPE1);
strValues.push_back(val);
numValues.push_back(-1);
continue;
}
catch (...) {}
strValues.push_back(it->second.type().name());
try
{
double val = it->second.cast<double>();
types.push_back( CV_64F );
numValues.push_back(val);
continue;
}
catch (...)
catch (...) {}
try
{
float val = it->second.cast<float>();
types.push_back( CV_32F );
numValues.push_back(val);
continue;
}
catch (...) {}
try
{
try
{
double val = it->second.cast<double>();
strValues.push_back(std::string());
types.push_back( val == saturate_cast<int>(val) ? CV_32S : CV_64F );
numValues.push_back(val);
}
catch( ... )
{
types.push_back(-1); // unknown type
strValues.push_back(std::string());
numValues.push_back(-1);
}
int val = it->second.cast<int>();
types.push_back( CV_32S );
numValues.push_back(val);
continue;
}
catch (...) {}
try
{
short val = it->second.cast<short>();
types.push_back( CV_16S );
numValues.push_back(val);
continue;
}
catch (...) {}
try
{
ushort val = it->second.cast<ushort>();
types.push_back( CV_16U );
numValues.push_back(val);
continue;
}
catch (...) {}
try
{
char val = it->second.cast<char>();
types.push_back( CV_8S );
numValues.push_back(val);
continue;
}
catch (...) {}
try
{
uchar val = it->second.cast<uchar>();
types.push_back( CV_8U );
numValues.push_back(val);
continue;
}
catch (...) {}
try
{
bool val = it->second.cast<bool>();
types.push_back( CV_MAKETYPE(CV_USRTYPE1,2) );
numValues.push_back(val);
continue;
}
catch (...) {}
try
{
cvflann::flann_algorithm_t val = it->second.cast<cvflann::flann_algorithm_t>();
types.push_back( CV_MAKETYPE(CV_USRTYPE1,3) );
numValues.push_back(val);
continue;
}
catch (...) {}
types.push_back(-1); // unknown type
numValues.push_back(-1);
}
}
......
......@@ -23,7 +23,80 @@ public class FlannBasedDescriptorMatcherTest extends OpenCVTestCase {
DescriptorMatcher matcher;
int matSize;
DMatch[] truth;
static final String ymlParamsDefault = "%YAML:1.0\n"
+ "indexParams:\n"
+ " -\n"
+ " name: algorithm\n"
+ " type: 23\n"
+ " value: 1\n"
+ " -\n"
+ " name: trees\n"
+ " type: 4\n"
+ " value: 4\n"
+ "searchParams:\n"
+ " -\n"
+ " name: checks\n"
+ " type: 4\n"
+ " value: 32\n"
+ " -\n"
+ " name: eps\n"
+ " type: 5\n"
+ " value: 0.\n"
+ " -\n"
+ " name: sorted\n"
+ " type: 15\n"
+ " value: 1\n";
static final String xmlParamsDefault = "<?xml version=\"1.0\"?>\n"
+ "<opencv_storage>\n"
+ "<indexParams>\n"
+ " <_>\n"
+ " <name>algorithm</name>\n"
+ " <type>23</type>\n"
+ " <value>1</value></_>\n"
+ " <_>\n"
+ " <name>trees</name>\n"
+ " <type>4</type>\n"
+ " <value>4</value></_></indexParams>\n"
+ "<searchParams>\n"
+ " <_>\n"
+ " <name>checks</name>\n"
+ " <type>4</type>\n"
+ " <value>32</value></_>\n"
+ " <_>\n"
+ " <name>eps</name>\n"
+ " <type>5</type>\n"
+ " <value>0.</value></_>\n"
+ " <_>\n"
+ " <name>sorted</name>\n"
+ " <type>15</type>\n"
+ " <value>1</value></_></searchParams>\n"
+ "</opencv_storage>\n";
static final String ymlParamsModified = "%YAML:1.0\n"
+ "indexParams:\n"
+ " -\n"
+ " name: algorithm\n"
+ " type: 23\n"
+ " value: 6\n"//this line is changed
+ " -\n"
+ " name: trees\n"
+ " type: 4\n"
+ " value: 4\n"
+ "searchParams:\n"
+ " -\n"
+ " name: checks\n"
+ " type: 4\n"
+ " value: 32\n"
+ " -\n"
+ " name: eps\n"
+ " type: 5\n"
+ " value: 0.\n"
+ " -\n"
+ " name: sorted\n"
+ " type: 15\n"
+ " value: 1\n";
protected void setUp() throws Exception {
matcher = DescriptorMatcher.create(DescriptorMatcher.FLANNBASED);
matSize = 100;
......@@ -91,6 +164,39 @@ public class FlannBasedDescriptorMatcherTest extends OpenCVTestCase {
}
};
}
private Mat getBriefTrainImg() {
Mat img = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(255));
Core.line(img, new Point(40, 40), new Point(matSize - 40, matSize - 40), new Scalar(0), 8);
return img;
}
private Mat getBriefQueryImg() {
Mat img = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(255));
Core.line(img, new Point(40, matSize - 40), new Point(matSize - 50, 50), new Scalar(0), 8);
return img;
}
private Mat getBriefTestDescriptors(Mat img) {
List<KeyPoint> keypoints = new ArrayList<KeyPoint>();
Mat descriptors = new Mat();
FeatureDetector detector = FeatureDetector.create(FeatureDetector.FAST);
DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.BRIEF);
detector.detect(img, keypoints);
extractor.compute(img, keypoints, descriptors);
return descriptors;
}
private Mat getBriefQueryDescriptors() {
return getBriefTestDescriptors(getBriefQueryImg());
}
private Mat getBriefTrainDescriptors() {
return getBriefTestDescriptors(getBriefTrainImg());
}
public void testAdd() {
matcher.add(Arrays.asList(new Mat()));
......@@ -200,12 +306,21 @@ public class FlannBasedDescriptorMatcherTest extends OpenCVTestCase {
}
public void testRead() {
fail("https://code.ros.org/trac/opencv/ticket/1253");
String filename = OpenCVTestRunner.getTempFileName("yml");
writeFile(filename, "%YAML:1.0\n");
writeFile(filename, ymlParamsModified);
matcher.read(filename);
assertTrue(true);
Mat train = getBriefTrainDescriptors();
Mat query = getBriefQueryDescriptors();
List<DMatch> matches = new ArrayList<DMatch>();
matcher.match(query, train, matches);
assertListDMatchEquals(Arrays.asList(new DMatch (0, 0, 0, 0),
new DMatch (1, 2, 0, 0),
new DMatch (2, 1, 0, 0),
new DMatch (3, 3, 0, 0)), matches, EPS);
}
public void testTrain() {
......@@ -224,13 +339,19 @@ public class FlannBasedDescriptorMatcherTest extends OpenCVTestCase {
}
public void testWrite() {
fail("https://code.ros.org/trac/opencv/ticket/1253");
String filename = OpenCVTestRunner.getTempFileName("xml");
matcher.write(filename);
assertEquals(xmlParamsDefault, readFile(filename));
}
public void testWriteYml() {
String filename = OpenCVTestRunner.getTempFileName("yml");
matcher.write(filename);
String truth = "%YAML:1.0\n!!!!!";
assertEquals(truth, readFile(filename));
assertEquals(ymlParamsDefault, readFile(filename));
}
}
......@@ -245,6 +245,7 @@ public:
OPPONENTEXTRACTOR = 1000,
OPPONENT_SIFT = OPPONENTEXTRACTOR + SIFT,
OPPONENT_SURF = OPPONENTEXTRACTOR + SURF,
OPPONENT_ORB = OPPONENTEXTRACTOR + ORB,
......@@ -313,27 +314,27 @@ public:
CV_WRAP virtual void clear();
CV_WRAP virtual bool isMaskSupported();
CV_WRAP virtual void train();
CV_WRAP void classify( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
CV_WRAP void classify( const Mat& queryImage, CV_IN_OUT vector<KeyPoint>& queryKeypoints,
const Mat& trainImage, vector<KeyPoint>& trainKeypoints ) const;
CV_WRAP void classify( const Mat& queryImage, vector<KeyPoint>& queryKeypoints );
CV_WRAP void classify( const Mat& queryImage, CV_IN_OUT vector<KeyPoint>& queryKeypoints );
CV_WRAP void match( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
const Mat& trainImage, vector<KeyPoint>& trainKeypoints,
vector<DMatch>& matches, const Mat& mask=Mat() ) const;
CV_OUT vector<DMatch>& matches, const Mat& mask=Mat() ) const;
CV_WRAP void knnMatch( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
const Mat& trainImage, vector<KeyPoint>& trainKeypoints,
vector<vector<DMatch> >& matches, int k,
CV_OUT vector<vector<DMatch> >& matches, int k,
const Mat& mask=Mat(), bool compactResult=false ) const;
CV_WRAP void radiusMatch( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
const Mat& trainImage, vector<KeyPoint>& trainKeypoints,
vector<vector<DMatch> >& matches, float maxDistance,
CV_OUT vector<vector<DMatch> >& matches, float maxDistance,
const Mat& mask=Mat(), bool compactResult=false ) const;
CV_WRAP void match( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
vector<DMatch>& matches, const vector<Mat>& masks=vector<Mat>() );
CV_OUT vector<DMatch>& matches, const vector<Mat>& masks=vector<Mat>() );
CV_WRAP void knnMatch( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
vector<vector<DMatch> >& matches, int k,
CV_OUT vector<vector<DMatch> >& matches, int k,
const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
CV_WRAP void radiusMatch( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
vector<vector<DMatch> >& matches, float maxDistance,
CV_OUT vector<vector<DMatch> >& matches, float maxDistance,
const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
CV_WRAP virtual bool empty() const;
#endif
......@@ -411,7 +412,7 @@ CV_EXPORTS_W void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoint
const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1),
const vector<char>& matchesMask=vector<char>(), int flags=0 );
CV_EXPORTS_W void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
CV_EXPORTS_AS(drawMatches2) void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
const Mat& img2, const vector<KeyPoint>& keypoints2,
const vector<vector<DMatch> >& matches1to2, Mat& outImg,
const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-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