NetVLAD与MobileNetVLAD 极简打开方式

1、NetVLAD与MobileNetVLAD

        VLAD(vector of locally aggregated descriptors)建议直接移步Aggregating local image descriptors into compact codes 看几种方法的联系与异同,与BoW和FV为主要的常用整体描述的三种方法。作用指在我们拥有单个图像、语音、文本整体的很多局部描述后,如何使用一个向量表达这个单体。

        BoW方法的核心思想是提取出关键点描述子后利用聚类的方法训练一个码本,随后每幅图片中各描述子向量在码本中各中心向量出现的次数来表示该图片,该方法的缺点是需要码本较大;FV方法的核心思想是利用高斯混合模型(GMM),通过计算高斯混合模型中的均值、协方差等参数来表示每张图像。该方法的优点是准确度高,但缺点是计算、量较大。VLAD算法可以看做是一种简化的FV,其主要方法是通过聚类方法训练一个小的码本,对于每幅图像中的特征找到最近的码本聚类中心,随后所有特征与聚类中心的差值做累加,得到一个k*d的vlad矩阵,其中k是聚类中心个数,d是特征维数(如sift是128维),随后将该矩阵扩展为一个(k*d)维的向量,并对其L2归一化,所得到的向量即为VLAD。VLAD的优点在于比BoW使用更少的码本而比FV使用更少的计算量,是一个兼顾精度与效率的算法。(这段文章一大抄。。附参考来源)

       在深度学习开始盛行后,NetVALD: CNN architecture for weakly supervised place recognition  通过将VLAD的聚合残差统计函数微分化,创建了一个VLAD层,通过常用的CNN输出结果作为局部特征,最后利用谷歌街景数据训练完成了一个VGG+VLAD的模型,用以生成图像的描述子,两张图像的差值用以表达相似度。因为VGG模型对算力消耗很大,朋友建议训练一个resnet大模型,然后在用其蒸馏小模型。随后经金戈大王得知了MobileNetVLAD~

        下面介绍极简主义的打开方式

2.1、NetVLAD 测试代码与结果

         现有NetVLAD与MobileNetVLAD的模型测试资源,NetVLAD由(NetVLAD: CNN architecture for weakly supervised place recognition) 提出,其开放的源码作者NetVLAD 为matlab版本的代码,随后VLAD层被先后使用PyTorch与TensorFlow复现,相对完整的代码是UZH复现的 UZH版本 ,完成了与作者代码的接口,经过作者代码训练的模型可以转成TensorFlow可使用的模型,测试结果如下 

 

Error of final vector is 1.106167

 

Error of final vector is 0.845138

import cv2
import numpy as np
import tensorflow as tf

import netvlad_tf.net_from_mat as nfm
import netvlad_tf.nets as nets


tf.reset_default_graph()

image_batch = tf.placeholder(
        dtype=tf.float32, shape=[None, None, None, 3])

net_out = nets.vgg16NetvladPca(image_batch)
saver = tf.train.Saver()

sess = tf.Session()
saver.restore(sess, '/home/zzx/git/netvlad_ws/src/aibee_netvlad/netvlad/checkpoints/vd16_pitts30k_conv5_3_vlad_preL2_intra_white')

inim = cv2.imread("test/3.jpg")
inim = cv2.cvtColor(inim, cv2.COLOR_BGR2RGB)
inim = cv2.resize(inim, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
cv2.imshow('frame',inim)
batch = np.expand_dims(inim, axis=0)
result = sess.run(net_out, feed_dict={image_batch: batch})

inim2 = cv2.imread("test/4.jpg")
inim2 = cv2.cvtColor(inim2, cv2.COLOR_BGR2RGB)
inim2 = cv2.resize(inim2, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
cv2.imshow('frame2',inim2)
batch2 = np.expand_dims(inim2, axis=0)
result2 = sess.run(net_out, feed_dict={image_batch: batch2})
out_diff = np.abs(result2- result)
print('Error of final vector is %f' % np.linalg.norm(out_diff))


       可以看到针对不同的相似度的图片结果可以表现相似程度,在随后的测试中,现有的依赖街景得到的模型,可以在我们常见的办公区,室外环境使用,阈值建议在0.9~1,当两张图片的结果差<阈值时,则可以认为来到了同一地点。NetVLAD输入是彩色图像,模型大小在1G左右,480×960 1050ti 运行时间在 0.67s。 

 

2.2、MobileNetVLAD 测试代码与结果

 

         MobileNetVLAD被ethz在Leveraging Deep Visual Descriptors for Hierarchical Efficient Localization提出,随之开源的代码包含了retrievalnet 网络的训练过程,而作者的对其的使用则是使用tensorflow c++的版本,国内装maplab与编译tensorflow全家桶难度比较大,retrievalnet中有将中间参数输出模型的脚本,笔者利用它得到模型,做了一个纯使用的test。代码链接~  安装tensorflow即可使用。

import tensorflow as tf  
import cv2
import numpy as np
import time
import array
export_path = '/home/zzx/retrievalnet/data/weights/mobilenetvlad_depth-0.35'
# We start a session using a temporary fresh Graph
with tf.Session(graph=tf.Graph()) as sess:
    '''
    You can provide 'tags' when saving a model,
    in my case I provided, 'serve' tag 
    '''
    tf.saved_model.loader.load(sess, ['serve'], export_path)
    graph = tf.get_default_graph()
    y = sess.graph.get_tensor_by_name('descriptor:0')
    x = sess.graph.get_tensor_by_name('image:0')
    print(y)
    print(x)
    inim =  cv2.imread("/home/zzx/retrievalnet/data/images/a.jpg")
    inim = cv2.cvtColor(inim, cv2.COLOR_BGR2GRAY)
    inim =  cv2.resize(inim, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
    batch = np.expand_dims(inim, axis=0)
    batch = np.expand_dims(batch, axis=3)
    print(batch.shape)
    start=time.time()
    pred = sess.run(y, feed_dict={x: batch})
    end = time.time()
    print(start-end)
    inim = cv2.imread("/home/zzx/retrievalnet/data/images/e.jpg")
    inim = cv2.cvtColor(inim, cv2.COLOR_BGR2GRAY)
    inim = cv2.resize(inim, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
    batch = np.expand_dims(inim, axis=0)
    batch = np.expand_dims(batch, axis=3)
    start=time.time()
    pred2 = sess.run(y, feed_dict={x: batch})
    end = time.time()
    print(start-end)
    out_diff = abs(pred2 - pred)
    print(np.linalg.norm(out_diff))

同样的图片误差分别是0.64682966与0.436366

        可以看到针对不同的相似度的图片结果可以表现相似程度,在随后的测试中,现有的依赖街景得到的模型,可以在我们常见的办公区,室外环境使用,阈值建议在0.6,当两张图片的结果差<阈值时,则可以认为来到了同一地点。MobileNetVLAD输入是灰色图像,模型大小在60M左右,480×960 1050ti 运行时间在 0.027s。

3、使用问题与脑洞

       常见的使用即针对每一张得到的图片保存向量,在已有向量中搜索与其差值最小的图片,笔者并非专业炼丹手,主要是菜?SLAM选手,主要使用其进行回环操作。在使用过程中出现了几个问题,大家集思广益!!!

Q1、60hz的相机,如何做图片是否进行向量化保存的选择,因为可能出现长时间主要是如何利用现有信息得到地图代表性的判断,来确定是否进行向量化。类似于ORB中关键帧的生成与merge策略。

笔者的答案:借鉴了cartographer的一个思路,利用定位信息,时间信息与前后两帧差值来完成这个判断,位置变化超过一定值,等待过长时间或者前后两帧变化量超过一定阈值时,进行保存。关于merge,笔者还没有太多想法。在获取信息越多的情况下,策略也就更复杂,如何利用最少的向量完成最大面积的覆盖,如何利用定位和评分消除冗余,是个很好玩的问题

Q2、误回环,单帧视觉容易在,两个相似区域产生误回环,如何利用现有信息,进行误回环的消除,类似于时域上的多重判断。

笔者的脑洞:时序与位置(如果有)的多重确认,其实即使有了也不能保证做好,毕竟如果遇到了两个一摸一样的房间。。。呆久了也会有问题。再就是利用其他传感器的消除了,蓝牙或者Wi-Fi,大家集思广益,如果只有向量信息,如何消除误回环

Q3、低纹理,在低纹理特征时,向量不具备代表性,比如家徒四壁玩回环,

笔者朋友的建议:小伙伴AR出身,说苹果有一个轻量级的网络判断低纹理。小伙伴还说或者将常见低纹理图片或者不具备代表性的图片向量做个数据集,如果当前图片向量与这些距离较近,就剔除认为其不具备代表性。个人想着可以利用特征点的规模来做一些事

集思广益、集思广益。

 

参考:

金戈大王

技术刘

https://blog.csdn.net/o3279/article/details/81221881

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值