简介
fbow 是图像的特征点字典库,有以下功能:
- 可以把多个图像中的特征点存放在一起形成数据库,并以文件的方式保存
- 可以把新图像的特征点放到数据库里匹配,得到特征向量
- 可以计算特征向量之间的相似度
详见fbow的github。
安装
- 下载
git clone https://github.com/rmsalinas/fbow.git
#或 wget https://github.com/rmsalinas/fbow/archive/master.zip
- 编译安装
mkdir build
cd build
cmake ..
make
sudo make install
使用
注:代码来自这里。
- cmake
set( FBOW_INCLUDE_DIRS "/usr/local/include" )
set( FBOW_LIBS "/usr/local/lib/libfbow.so" )
#add_executable( app app.cpp )
#target_link_libraries( app ${OpenCV_LIBS} ${FBOW_LIBS} )
- 训练词典
//训练词典的参数
fbow::VocabularyCreator::Params params;
//叶子节点的个数
params.k = 10;
//树的高度
params.L = 5;
//使用的线程数量
params.nthreads=1;
//最大迭代次数
params.maxIters=0;
//词典创建工具
fbow::VocabularyCreator vocabCat;
//词典
fbow::Vocabulary vocabulary;
//创建词典,descriptors是一个vector<cv::Mat>,把要聚类的词典读进来就行
vocabCat.create(vocabulary,descriptors,"hf-net",params);
//保存词典
vocabulary.saveToFile("filename");
- 载入词典
//先创建一个词典
fbow::Vocabulary vocab;
//然后调用下面方法
vocab.readFromFile("filename");
- 获取评分
//这个是带权值的节点向量
fbow::fBow bowvector1;
//通过词典获取,descriptor是一个cv::Mat
bowvector1 = vocab.transform(descriptor1);
fbow::fBow bowvector2;
bowvector2 = vocab.transform(descriptor2);
//两个向量评分,调用静态方法
double score = fbow::fBow::score(bowvector1,bowvector2);
- 获取指定层数的节点向量
fbow::fBow bowvector;
//这个是描述子属于指定层的节点向量
fbow::fBow2 bowvector1;
//层数从0开始,descriptor是一个次cv:: Mat
vocab.transform(descriptor,4,bowvector,bowvector1)
- 增量的训练方法
void filterDes(vector<vector<Mat>> & descriptorss ,vector<vector<vector<KeyPoint>>> & keyPointss, vector<Mat> &optiDescriptors){
vector<leafNode> allLeaf;
Mat allDes = descriptorss[0][0].clone();
vector<int> globalDesToLeaf;
globalDesToLeaf.resize(1000);
for(int i = 0 ; i < allDes.rows ; i++){
leafNode temp;
Mat descriptor = allDes.rowRange(i , i+ 1);
temp.points.push_back(descriptor);
allLeaf.push_back(temp);
globalDesToLeaf[i] = i;
}
cout << "dataset number is:"<<descriptorss.size()<< endl;
for(int l = 0 ; l < descriptorss.size() ; l++){
vector<Mat> descriptors = descriptorss[l];
vector<vector<KeyPoint>> keyPoints = keyPointss[l];
/*进行分类*/
//先初始化
Mat lastDes = descriptors[0].clone();
vector<int> DesToLeaf;
DesToLeaf.resize(lastDes.rows);
vector<KeyPoint> lastKeyPoint = keyPoints[0];
//开始比较全局的描述子本,初始此数据的节点
//flann进行匹配
vector<DMatch> matchesGlobal;
FlannBasedMatcher matcher;
matcher.match(lastDes,allDes , matchesGlobal);
cout << "force match is " <<matchesGlobal.size() << endl;
for(int i = 0 ; i < matchesGlobal.size() ; i++){
DesToLeaf[matchesGlobal[i].queryIdx] = globalDesToLeaf[matchesGlobal[i].trainIdx];
}
//开始分类 descriptors.size()
for(int i = 1 ; i < descriptors.size(); i++){
//flann进行匹配
vector<DMatch> matches;
FlannBasedMatcher matcher;
matcher.match(descriptors[i], lastDes , matches);
//对匹配的点进行重新排位
vector<KeyPoint> leftpoints,rightpoints;
for(int j = 0 ; j < matches.size() ; j++){
leftpoints.push_back(keyPoints[i][matches[j].queryIdx]);
rightpoints.push_back(lastKeyPoint[matches[j].trainIdx]);
}
//生成2d点
vector<Point2f> ps1,ps2;
for (unsigned j = 0; j < leftpoints.size(); j++)
ps1.push_back(leftpoints[j].pt);
for (unsigned j = 0; j < rightpoints.size(); j++)
ps2.push_back(rightpoints[j].pt);
//使用ransac方法筛选
Mat status;
findFundamentalMat(ps1,ps2,FM_RANSAC,0.99,1,status);
//匹配成功的加入已经存在的节点
int index = 0;
int statuss[1000] = {0};
vector<int> tempDesToLeaf;
tempDesToLeaf.resize(descriptors[i].rows);
for (int j = 0; j < matches.size(); j++) {
if (status.at<uchar>(0,j) != 0 && statuss[matches[j].queryIdx] != 1){
allLeaf[DesToLeaf[matches[j].trainIdx]].points.push_back(descriptors[i].rowRange(matches[j].queryIdx , matches[j].queryIdx + 1));
tempDesToLeaf[matches[j].queryIdx] = DesToLeaf[matches[j].trainIdx];
statuss[matches[j].queryIdx] = 1;
index++;
}
}
//增加新的节点
for(int j = 0 ; j < descriptors[i].rows ; j++){
if(statuss[j]) continue;
leafNode temp;
Mat newDes = descriptors[i].rowRange(j , j + 1);
temp.points.push_back(newDes);
allLeaf.push_back(temp);
tempDesToLeaf[j] = allLeaf.size() - 1;
allDes.push_back(newDes);
globalDesToLeaf.push_back(tempDesToLeaf[j]);
}
lastDes = descriptors[i];
lastKeyPoint = keyPoints[i];
DesToLeaf = tempDesToLeaf;
}
cout << "finally all the cluster leaf node is:" << allLeaf.size() << endl;
}
// 开始构建聚类的mat
Mat allLeafMat;
for(int i = 0 ; i < allLeaf.size() ; i++){
Mat clusterDes = cv::Mat::zeros(1, 256, CV_32F);
int number = allLeaf[i].points.size();
for(int j = 0 ; j < allLeaf[i].points[0].cols ; j++){
float temp = 0 ;
for(int k = 0 ; k < number ; k++){
temp += allLeaf[i].points[k].at<float>(0, j);
}
clusterDes.at<float>(0,j) = temp / number;
}
allLeafMat.push_back(clusterDes);
}
optiDescriptors.push_back(allLeafMat);
cout << "all Leaf node is:" <<allLeafMat.rows << endl;