公开图像识别匹配技术之二 Vlad向量方法

2016-04-09 13:47:05来源:oschina作者:zhuyuping人点击

提取特征点并抽样



System.setProperty("hadoop.home.dir","C://spark//hadoop-2.6.0");
SparkConfconf=newSparkConf().setAppName("vladindeximage").setMaster("local");
//conf.set("spark.hadoop.fs.oss.impl","com.aliyun.fs.oss.nat.NativeOssFileSystem");
JavaSparkContextcontext=newJavaSparkContext(conf);
Listfiles=AliyunOSSUtils.listalldirImages("imagenet_downloader/n01440764/",Lists.newArrayList());
JavaRDD>imagefeatures=context.parallelize(files,10).map(newFunction>(){
@Override
publicListcall(Stringpath)throwsException{
Listvectors=Lists.newArrayList();
try{

vectors=readFeature(AliyunOSSUtils.getObject(path));
returnvectors;
}catch(Throwablee){
returnvectors;
}
}
});
//imagefeatures.persist(StorageLevel.MEMORY_AND_DISK_SER());
JavaRDDvectors=imagefeatures.flatMap(newFlatMapFunction,Vector>(){
@Override
publicIterablecall(Listvectors)throwsException{
Listsamples=Lists.newArrayList();
try{

finalint[]indices=RandomData.getUniqueRandomInts((int)(vectors.size()*0.1f),0,
vectors.size());
for(inti:indices){
samples.add(vectors.get(i));
}
returnsamples;
}catch(Exceptione){
returnsamples;
}
}
});

第二步使用Kmean聚类 或者 使用 Autoencoder 或者 其他 DBscan 或者 深度学习



intnumClusters=64;
intnumIterations=500;
longstartTime=System.nanoTime();
KMeansModelclusters=KMeans.train(vectors.rdd(),numClusters,numIterations);
Vector[]vs=clusters.clusterCenters();
double[][]dd=newdouble[vs.length][];//64
inti=0;
for(Vectorvector:vs){
dd[i++]=vector.toArray();
}
//保存dd数组用于计算vlad向量
ByteArrayDataOutputoutput=ByteStreams.newDataOutput();
BinIO.storeDoubles(dd,output);
byte[]ddatas=output.toByteArray();
AliyunOSSUtils.upload(newByteArrayInputStream(ddatas),ddatas.length,"vladaggrate.datas");

3.第三步使用VLAD 聚合 ,求得vlad向量 ,这个可以百度一搜一大堆



JavaRDDvlads=imagefeatures.map(newFunction,Vector>(){
@Override
publicVectorcall(Listv1)
throwsException{
VladAggratevlad=newVladAggrate(dd,true);
Vectorfeature=vlad.aggregateVectors(newExactDoubleAssigner(dd,null),v1);
returnfeature;
}
});

4.第四步 奇异值分解SVD ===============》PCA降维 从二维数组降维一位数字 MXN =MXM MXN NXN




RowMatrixmat1=newRowMatrix(vlads.rdd());
Vectormean=mat1.computeColumnSummaryStatistics().mean();
RowMatrixmat=newRowMatrix(newNormalizer(1).transform(vlads.rdd()));
SingularValueDecompositionsvd=mat.computeSVD(32,true,1.0E-9d);
RowMatrixU=svd.U();//矩阵U
Vectors=svd.s();////奇异值
MatrixV=svd.V();////矩阵V
DenseMatrixbasis=(DenseMatrix)V;//basic
double[]eigenvalues=s.toArray();//eigenvalues
FeatureVectorPCApca=newFeatureVectorPCA(basis,dmean,eigenvalues);
finalJama.Matrixwhitening=createRandomWhitening(32);
pca.setBasisMatrix(0,32-1,0,32-1,whitening);
List>>maps=vlads.map(newFunction(){
@Override
publicdouble[]call(Vectorv1)throwsException{
returnnewDoubleFV(pca.project(v1.toArray())).normaliseFV(2).asDoubleVector();
}
}).flatMapToPair(newPairFlatMapFunction(){
@Override
publicIterable>call(double[]t)
throwsException{
List>tuples=Lists.newArrayList();
for(inti=0;i<16;i++){
double[]tmp=newdouble[2];
System.arraycopy(t,i*2,tmp,0,2);
tuples.add(newTuple2(i,Vectors.dense(tmp)));
}
returntuples;
}
}).combineByKey(newFunction>(){
@Override
publicListcall(Vectorv1)throwsException{

returnLists.newArrayList(v1);
}

},newFunction2,Vector,List>(){
@Override
publicListcall(Listv1,Vectorv2)
throwsException{
v1.add(v2);
returnv1;
}
},newFunction2,List,List>(){
@Override
publicListcall(Listv1,Listv2)
throwsException{
v1.addAll(v2);
returnv1;
}
}).collect();

5 第五步 ANN 最近邻近算法 求得距离KNN数组 用来判断后面的向量的距离



ByteArrayOutputStreamoutputStream=newByteArrayOutputStream();
BinIO.storeObject(pca,outputStream);
byte[]pcadatas=outputStream.toByteArray();
AliyunOSSUtils.upload(newByteArrayInputStream(pcadatas),pcadatas.length,"pcaobject.bin");
ExecutorServicepool=Executors.newFixedThreadPool(5);
List>>tasks=Lists.newArrayList();
for(finalTuple2>tuple2:maps){
tasks.add(newCallable>(){
@Override
publicPaircall()throwsException{

Integerkey=tuple2._1;
KMeansModeltemp=KMeans.train(context.parallelize(tuple2._2).rdd(),256,500);
Vector[]vstemp=temp.clusterCenters();
double[][]dd=newdouble[vstemp.length][];
inti=0;
for(Vectorvector:vstemp){
dd[i++]=vector.toArray();
}
returnnewPair(key,dd);
}

});
}
//http://my.oschina.net/lovesesun/blog/76823
List>>futures=pool.invokeAll(tasks);
//double[][][]ddds=newdouble[futures.size()][][];
//Listdds=Lists.newArrayList();
ByteArrayOutputStreambos=newByteArrayOutputStream();
ZipOutputStreamzos=newZipOutputStream(bos);
for(Future>future:futures){
Pairpair=future.get();
//ddds[pair.getKey()]=pair.getVal();
Integerkey=pair.getKey();
ByteArrayDataOutputout=ByteStreams.newDataOutput();
BinIO.storeDoubles(pair.getVal(),out);
ZipEntryentry=newZipEntry(key+".bin");
zos.putNextEntry(entry);
zos.write(out.toByteArray());
//dds.add(pair.getVal());
zos.closeEntry();
}
zos.flush();
zos.close();
byte[]datas=bos.toByteArray();
AliyunOSSUtils.upload(newByteArrayInputStream(datas),datas.length,"knndatas.zip");
//System.out.println("==================="+dds.size());
//获取到了List保存起来
context.stop();

5.搜索 进行 ANN搜索 其实就是 通过PCA降维project 得到的double[] 进行ANN搜索



JavaPairRDDrdds=context.parallelizePairs(knnTuples,knnTuples.size()).mapToPair(newPairFunction,Integer,double[]>(){
@Override
publicTuple2call(
Tuple2t)throwsException{
Integerkey=t._1;
double[][]nn=t._2;
intk=nn.length;
intsplitsize=qu.length/knnTuples.size();
double[]qus=Arrays.copyOfRange(qu,key*splitsize,splitsize*(key+1));
finalBoundedPriorityQueuequeue=
newBoundedPriorityQueue(k,IntDoublePair.SECOND_ITEM_ASCENDING_COMPARATOR);
for(intj=0;j doublescore=DoubleFVComparison.SUM_SQUARE.compare(qus,nn[j]);
intindex=key;
IntDoublePairwp=newIntDoublePair(index,score);
wp=queue.offerItem(wp);
}
Listpair=queue.toOrderedListDestructive();
double[]dis=newdouble[pair.size()];
for(intj=0;j doublesecond=pair.get(j).second;
dis[j]=second;
}
returnnewTuple2(key,dis);
}
});
// .mapToPair(newPairFunction>,Integer,double[]>(){
//
// @Override
// publicTuple2call(
// Tuple2>t)throwsException{
// Integerkey=t._1;
// Listpairs=t._2;
// double[]dis=newdouble[pairs.size()];
// for(intj=0;j// IntDoublePairpair=pairs.get(j);
// doublesecond=pair.second;
// dis[j]=second;
// }
// returnnewTuple2(key,dis);
// }
// });
Mapmap=rdds.collectAsMap();
JavaPairRDDindexids=context.newAPIHadoopRDD(mongodbConfig,MongoInputFormat.class,
Object.class,BSONObject.class);
ByteArrayOutputStreamdataouts=newByteArrayOutputStream();
IOUtils.copy(AliyunOSSUtils.getObject(imagepath),dataouts);
byte[]imagedatas=dataouts.toByteArray();
JavaRDD>indexrdd=indexids.values().map(newFunction>(){
@Override
publicThreePaircall(BSONObjectobject)throwsException{
Stringid=(String)object.get("id");
Stringpath=(String)object.get("path");
Doublesecond=newDouble(0);
Rowrow=TableStoreUtils.getRow("imagesearch",uid,id,Lists.newArrayList("vladindex"));
byte[]data=row.getColumns().get("vladindex").asBinary();
for(intj=0;j finalintcentroid=data[j]+128;
second+=map.get(j)[centroid];
}
returnnewThreePair(id,second,path);

}
}).sortBy(newFunction,Double>(){
@Override
publicDoublecall(ThreePairv1)
throwsException{
returnv1.getVal();
}
},true,5);//ascending默认是true,也就是升序;



6. 由于项目依赖 太多,好多深度学习 方面的 东西,我不便公开,所以 最近有空再整理文件,整理出一个VLAD BOW的图像匹配搜索的源码 项目,不久将会然后开源 托管到github上去。


可以用他实现 咔嚓购物 百度识图 亮风台AR bliperAR 图像匹配 ,高通vofori 图像搜索匹配技术。图像搜索技术

微信扫一扫

第七城市微信公众平台