Implemented read/write methods for FlannBasedMatcher; fixed features2d wrappers for java
This commit is contained in:
parent
16b0fcf083
commit
874196e384
modules
features2d
flann
java
android_test/src/org/opencv/test/features2d
src/cpp
@ -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 (...)
|
||||
catch (...) {}
|
||||
|
||||
strValues.push_back(it->second.type().name());
|
||||
|
||||
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);
|
||||
}
|
||||
double val = it->second.cast<double>();
|
||||
types.push_back( CV_64F );
|
||||
numValues.push_back(val);
|
||||
continue;
|
||||
}
|
||||
catch (...) {}
|
||||
try
|
||||
{
|
||||
float val = it->second.cast<float>();
|
||||
types.push_back( CV_32F );
|
||||
numValues.push_back(val);
|
||||
continue;
|
||||
}
|
||||
catch (...) {}
|
||||
try
|
||||
{
|
||||
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),
|
||||
|
Loading…
x
Reference in New Issue
Block a user