图像检索之乘积量化二

来源:互联网 发布:原油交易软件 编辑:程序博客网 时间:2024/05/29 17:26

pq_new.c


/*

实现productquantization

从一个学习数据集中构建ANN(aproximatenearest neighbor) pq codes.

使用pq*p=pq_new(int nsq,CvMat *v);

nsq:子向量的个数,论文中的m.

v:用于学习的数据集,指向一个CvMat的指针,每一行是一个训练数据。

*/

返回的数据结构

typedef struct pq{int nsq;//子向量的个数int ks;//子向量的聚类中心个数int ds;//子向量的维数 ds=d/nsq;CvMat **centroids;//子向量聚类中心的坐标,nsq个CvMat指针,centroid[i]是第i个子向量的中心,ksxds维,表示第i个子向量有ks个中心,中心的坐标是ds维。CvMat **assigns;//分配向量,nsq个CvMat指针,assign[i]是第i个子向量的分配id,nx1维,分别表示n个子向量分配到哪一个中心。}pq;
具体实现

pq* pq_new(int nsq,CvMat * v){int n=v->rows;int d=v->cols;int ds=d/nsq;//dimension of subvectors to quantizeint nsqbits=1;//default 8int ks=pow(2,nsqbits);int q;int i,j;pq *p=(pq*)malloc(sizeof(pq));p->nsq=nsq;p->ds=ds;p->ks=ks;p->centroids=(CvMat**)malloc(sizeof(CvMat*)*nsq);for(q=0;q<nsq;q++)p->centroids[q]=cvCreateMat(ks,ds,CV_32FC1);//assert(res!=NULL);CvMat **centers=(CvMat **)malloc(sizeof(CvMat *)*nsq);for(q=0;q<nsq;q++)centers[q]=cvCreateMat(n,1,CV_32S);CvMat *vs=cvCreateMat(n,ds,CV_32FC1);//p->centroids=res;assert((p->centroids)[0]!=NULL);p->assigns=centers;for(q=0;q<nsq;q++){//copy the sub vectorfor(i=0;i<n;i++){for(j=0;j<ds;j++){vs->data.fl[i*vs->cols+j]=v->data.fl[i*v->cols+q*ds+j];}}//vs:n*ds;ks,centers//printf("n rows:%d,%d,%d\n",vs->rows,centers[q]->cols,centers[q]->rows);cvKMeans2(vs,ks,centers[q],cvTermCriteria(CV_TERMCRIT_ITER,10,0.1),1,0,0,p->centroids[q],0);}//cvReleaseMat(&vs);return p;}//测试输出void pq_print(pq* p){printf("nsq:%d;ks:%d;ds:%d\n",p->nsq,p->ks,p->ds);printf("assign\n");int i,j,k;for(i=0;i<p->nsq;i++){printf("subvector:%d\n",i);for(j=0;j<p->assigns[i]->rows;j++){printf("row[%d]=%d,",j,p->assigns[i]->data.i[j]);}printf("\n");}printf("\n");printf("centers:\n");for(i=0;i<p->nsq;i++){printf("subvector:%d\n",i);for(j=0;j<p->ks;j++){printf("centers:%d\n",j);for(k=0;k<p->ds;k++){printf("dim[%d]=%f,",k,p->centroids[i]->data.fl[j*(p->centroids[i]->cols)+k]);}printf("\n");}}printf("\n");}
测试文件

#include"pq_new.h"int main(){float arr[]={1,2,5,6,1.2,2.2,5.3,6.1,0.9,1.8,4.9,6.1};CvMat v=cvMat(3,4,CV_32FC1,arr);//v是一个3x4的矩阵int nsq=2;//我们设定子向量的个数为2pq* p=pq_new(nsq,&v);pq_print(p);}

结果显示:

nsq:2;ks:2;ds:2assignsubvector:0row[0]=0,row[1]=1,row[2]=0,subvector:1row[0]=1,row[1]=0,row[2]=1,centers:subvector:0centers:0dim[0]=0.950000,dim[1]=1.900000,centers:1dim[0]=1.200000,dim[1]=2.200000,subvector:1centers:0dim[0]=5.300000,dim[1]=6.100000,centers:1dim[0]=4.950000,dim[1]=6.050000,
我们的测试数据:

v=

{

  1,  2,  5,  6,1.2,2.2,5.3,6.1,0.9,1.8,4.9,6.1
}

v按列被分成了两组子向量。第一组子向量的有两个聚类中心,一(1.2,2.2)和二(0.95,1.9),v的第一祖的第一个向量(1,2)分配到了第一个聚类中心,第二个向量(1.2,2.2)单独分配到第二个聚类中心,第三个向量(0.9,1.8)被分配到第一个聚类中心,依次类推。


原创粉丝点击