为了账号安全,请及时绑定邮箱和手机立即绑定

基于 Sift + Kmeans + 倒排索引 的图像匹配

标签:
人工智能

一:整体思路


数据库建立:

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 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消