SIFT匹配算法FPGA实现

       这是一种实时的SIFT匹配算法实现方法,全由FPGA编写构成。通过MATLAB将RGB图片转换成8位灰度图片,再生成txt数据文件,这里设定成image1.txt和image2.txt。
       构想是通过USB传输数据给FPGA,FPGA处理好后再将匹配到的位置传回PC端,让MATLAB读取这些位置,显示在图片上。不过USB传输我还没做,现在只做完了仿真。
        工程分为构建高斯金字塔、生成特征点、生成描述子和匹配四个部分。高斯金字塔我用的一组四层,因为简单。就是用不同的高斯核滤出来四张图片,两两相减构建DOG金字塔,四层出三张DOG图。特征点需要最“突出”的点--极值点,如果一个DOG像素点比上下左右26个点都大,它就是特征点。当然,介于数字的不连贯性,它还应该有个更正的过程,去除边缘效应,但是太麻烦了我没做。
       选好特征点,就要开始做描述子,保证它的旋转不变性和尺度不变性。尺度不变就是高斯金字塔,我金字塔做的简单,如果做更多组、更多层,就能得到更多的特征点、更多的匹配点。旋转不变性就要确定特征点的主方向了,得到主方向再把特征点附近的邻域旋转到主方向,这样图片旋转了也能匹配到。按照一般的SIFT方法,需要一个大的方形区域算主方向,再在里面划个圆旋转,然后在圆里面划一个方形区域,割成16个子域分别算直方图,这个直方图是每个像素点按8个方向
分布的数值和。选用的数值是离DOG最近的那张高斯图,过一遍Sobel求梯度,这样就能得到128维的描述子。
       这样的方法用Verilog写,超出了我的知识范围。我查阅文献,用了化圆的方法求描述子。就是将16个方形子域换成4个同心圆,圆的直径按高斯核的sigma选。8个方向换成16个,得到64维描述子,也能用。因为我代码全用Verilog写的,所以为更一步简化代码,我把同心圆换成了八边形,旋转到主方向一样只需要换位置,比如90°的主方向只用将原方向0的值换到方向3。四个八边形的边长为2倍的9、8、5、2。
       匹配图和模板图的描述子求出来后只需要计算它们之间的欧氏距离,最近的比次近的一半都小,说明它就是匹配点。也有用深度学习KD树匹配的,但特征点少于1500的用遍历就行。
       我最先是用MATLAB硬写了SIFT算法,在移植到FPGA上面,FPGA不用浮点,小数我都乘256变成整数,节省资源。
       MATLAB部分,SIFT_wr是将RGB图像转成灰度数据输出去,SIFT_rd是读位置,将两幅图匹配到的位置连线,SIFT是我最先在MATLAB写的SIFT算法,可移植到FPGA上面。
       FPGA里面,有Creat_Describe生成描述子和Get_Feature得到特征点两部分。Get_Feature里面Guass和Cordic就是高斯滤波和求模求像素点方向,sobel算法求梯度,compare比较当前点和周围26个数值大小,选特征点。Creat_Describe里面最麻烦的是seed_addr,选八边形子域,这选出来的4个八边形、16个方向的直方图,直接构成64维描述子。Histogram求直方图,子域内16个方向的模值之和,最大的那个就是主方向。Sort是比较大小,选主方向用的。rotate旋转到主方向。Get_describe算顶层文件,生成描述子。最后有个归一化过程,这也是资源消耗最严重的部分,有四个除法器。Match就是匹配了,选出最近邻和次近邻,得到匹配位置。
       仿真测得,100MHZ下,用时13.5ms;WNS 0.225ns,LUT为28778,FF为30377,BRAM为60。两幅图分别为388和374个特征点,检测到77个匹配点。
       最后,程序是没有注释的,因为我最讨厌的两件事就是:写注释和别人不写注释。不过这玩意应该没人看,也就无所谓啦。

        我把代码放在GitHub里面,只有算法部分,包含verilog和matlab。

       https://github.com/caifangfei/SIFT.git
       Bye~

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值