一:整体思路
数据库建立:
1. 提取图像的SIFT特征
2. 将所有特征集合起来进行Kmeans聚类
3. 求出各个聚类的聚类中心并存入文件(高版本的opencv的Kmeans无需此步骤)
4. 记录下每个图片文件的聚类词频 ( FIle1 : class1: n1 class2: n2 class3.......)
5. 建立倒排索引表 ( class1: file1: n1 file2: n2 file3:.....)
查询:
1. 提取文件的SIFT特征
2. 对每一个特征与kmeans中心匹配,求出匹配的class ,并根据匹配程度做权值记录表。
3. 根据权值表和倒排索引表求出最佳匹配项
二:环境搭建
1. opencv1.0
2. gsl
下载连接:点击打开链接
具体配置问度娘,此处略过!
三: 部分代码实现
1. 提取sift特征向量
struct feature* featTemp;
featTemp->feat_num = sift_features( img, &featTemp ); export_features(fileName,featTemp,featTemp->feat_num);
2. Kmeans聚类
CvMat *samples=cvCreateMat(featNum, 128, CV_32FC1); //包含所有图片的所有feature信息的矩阵,featureNum个feature,每个feature为dims(128)维向量,每一维的元素类型为32位浮点数 CvMat *clusters=cvCreateMat(featNum, 1, CV_32SC1); //每个feature所在“质心”的指针(实际上本例程中没有用到该信息) //CvMat *centers=cvCreateMat(cluster_count, 128, CV_32FC1); //“质心”信息的数组,k个“质心”每个质心都是dims(128)维向量,每一维的元素类型为32位浮点数 cvSet(clusters,cvScalar(1,0,0,0),0); cvSet(centers,cvScalar(1,0,0,0),0); //获取sift特征文件列表 getFilePathArray("*.feature"); if (fileListHead == NULL) { printf("please makeLib first"); return 0; } filelist = fileListHead; do { n = import_features(filelist->name, FEATURE_LOWE, &featTemp); //导入feature文件,n为导入的 for(i = 0; i < n; i++) { for(j = 0; j < 128; j++) { samples->data.fl[temp++] = featTemp[i].descr[j]; } } }while( filelist->next != NULL && (filelist = filelist->next) ); cvKMeans2(samples, cluster_count, clusters,cvTermCriteria(CV_TERMCRIT_EPS,10,1.0) ); //Kmeans聚类
3. 建立倒排索引表
//最大图片数量 超出则需要修改数组大小 #define MAX_LIB_PIC 500 //聚类目标类种 #define MAX_MEANS 1024
//创建feature字典,并保存到文件中 //feature[]:数组中存储每一个文件的特征个数 int createKeyWordList(CvMat *samples,CvMat *clusters,const char* filename,int feature[],int featureNum) { int loop = 0, loop2 = 0,whichFile = 0,key; int keyWordList[MAX_LIB_PIC][MAX_MEANS] = {0} ; int dictionary[MAX_MEANS][MAX_LIB_PIC] = {0}; int ave[MAX_MEANS] = {0}; int avePic[MAX_LIB_PIC] = {0}; FILE* fp,*word; fp = fopen( filename , "w" ); if ( fp == NULL ) { printf("createKeyWordList file writr error "); } //求出每一个文件feature的词频 for ( loop = 0 ; loop < featureNum ; loop++) { if ( loop >= feature[whichFile] ) { whichFile ++; } keyWordList[whichFile][ clusters->data.i[loop] ]++; } // 将词频转化为百分率占比 for ( loop2 = 0 ; loop2 < MAX_LIB_PIC ; loop2++ ) { for ( loop = 0 ; loop < MAX_MEANS ; loop++ ) { avePic[loop2] += keyWordList[loop2][loop]; } } for ( loop = 0 ; loop < MAX_MEANS ; loop++ ) { for ( loop2 = 0 ; loop2 < MAX_LIB_PIC ; loop2++ ) { if (avePic[loop2] != 0) { dictionary[loop][loop2] = keyWordList[loop2][loop] * 10000 /avePic[loop2]; } } }
//建立倒排索引 for ( loop = 0 ; loop < MAX_MEANS ; loop++ ) { for ( loop2 = 0 ; loop2 < MAX_LIB_PIC ; loop2++ ) { ave[loop] += dictionary[loop][loop2]; } } for ( loop = 0 ; loop < MAX_MEANS ; loop++ ) { fprintf(fp,"%d ", loop + 1); for ( loop2 = 0 ; loop2 < MAX_LIB_PIC ; loop2++ ) { fprintf(fp," %d:%d ", loop2 + 1 , dictionary[loop][loop2]*10000/ave[loop] ); //fprintf(fp," %d:%d ", loop2 + 1 , dictionary[loop][loop2]); } fprintf(fp,"\n"); } fclose(fp); }
4. 查询图像特征
float macheImageFeat[MAX_MEANS] = {0};
int MakeMatch(const char* filename , struct kd_node* kd_root) { struct feature *match , *copy; struct feature** nbrs; int k , i , count = 0,num; double d0, d1; match = (struct feature*)malloc(sizeof(struct feature)); _getcwd(feature_Path,_MAX_PATH); num = import_features(filename,FEATURE_LOWE,&match); memset(macheImageFeat,0, MAX_MEANS * sizeof(float) ); for( i = 0; i < num ; i++ ) { copy = match + i ; k = kdtree_bbf_knn( kd_root, copy, 2, &nbrs, KDTREE_BBF_MAX_NN_CHKS ); if ( k == 2 ) { d0 = descr_dist_sq( copy, nbrs[0] ); d1 = descr_dist_sq( copy, nbrs[1] ); //printf("distens : d0 --- %f d1 --- %f d1 - d0 --- %f %f \n" , d0 , d1 , d1 * NN_SQ_DIST_RATIO_THR - d0); if( d0 < d1 * NN_SQ_DIST_RATIO_THR ) { count++; match[i].fwd_match = nbrs[0]; macheImageFeat[i] = 1 - ( d0 /d1 );// 求出特征权值 } } free( nbrs ); } printf("There are %d feature matchs with the picture %s\n",count,filename); return count; }
5. 求出最佳匹配图片
int getMaxMatch( float lable[] , int dictionary[MAX_MEANS][MAX_LIB_PIC]){ int loop,loop2,result,num = 1,temp; int target[3] = {0}; float ret[MAX_LIB_PIC] = {0} ; for ( loop2 = 0 ; loop2 < MAX_LIB_PIC ; loop2++ ) { for ( loop = 0 ; loop < MAX_MEANS ; loop++ ) { ret[loop2] += dictionary[ loop ][ loop2 ] * lable[loop] ;//lable就是求出的<span style="font-family: Arial, Helvetica, sans-serif;">macheImageFeat</span> } } result = 0; for ( loop2 = 0 ; loop2 < MAX_LIB_PIC ; loop2++ ) { if ( result < ret[loop2] ) { result = ret[loop2] ; num = loop2 + 1; } } printf("The match picture is %d : %f matchs\n",num,ret[num - 1]); return num;//图片的序列号 }
大功告成。
目前对学校建筑物图片就行测试,图片库大概20张左右,准确率为100%。
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦