Angel Eyes基于SIFT特征点的图像搜索系统的开发
2012-02-06 11:39
267 查看
过年回来以后,Angel Eyes的团队成员又开始了紧张忙碌的工作。为了争取在这个月向外界开放API和SDK,我们又对图像特征点搜索系统开发做了进一步的研究和实验,以力求搜索,匹配的精准。以下是我们基于SIFT特征点的图像搜索系统开发日志,也算是一些心得,与各位CV的同行们分享。
一、C#验证实验阶段
1、实验框架搭建工作:配置EmguCV、编写界面。
写界面是C#的长项,不过需要怎样一个界面来做实验,倒是一开始没想清楚,折腾了几下,要是用MFC来写,就伤不起了。
2、特征点提取与XML存储
以前学习的C#的XML序列化派上用场了,几行代码轻松解决图像库的特征点存储问题,存储的XML格式片段如下:
<Objects>
<StandardObject>
<Name>U盾</Name>
<Images>
<FeaturableImage>
<Name>IMG_0819.jpg</Name>
<Featrues>
<ImageFeature>
<Descriptor>
<float>0.000823393755</float>
<float>0.0008284497</float>
…………………………………………………….
</StandardObject>
</Objects>
3、简单图像搜索,两幅图像对比时,仅考虑两幅图像中有多少比例的特征点配对
4、高级筛选:随机样本一致算法
4.1 仿射变换模型封装(6参数线性变换模型,支持旋转、平移、缩放、错切等变换的组合,不含尺度空间的尺度参数)
4.2仿射变换模型的最小二乘拟合
4.2.1 公式推导:相当于多元线性回归的最小二乘拟合
4.2.2 求解3元一次方程组,我们用的最基本的行列式和代数余子式的求法,看了一下网上的,其他人是用了列主元素消元法,没有Angel Eyes的方法精度高,最终筛选效果不行,到底是他们实现的列主元素消元法不太正确,还是方法本身的差异,Angel Eyes也没深究,因为3元一次的方程组用什么方法速度都差不多,精度够就行。
怕求余子式展开时不小心写错,试用MatLab的符号计算功能,还不错
syms a11 a12 a13
syms a21 a22 a23
syms a31 a32 a33
A=[a11,a12,a13;a21,a22,a23;a31,a32,a33];
syms y1 y2 y3;
Y=[y1;y2;y3];
linsolve(A,Y)
4.3 实现随机样本一致
按照维基百科关于随机抽样的共识(RANdom SAmple Consensus,RANSAC)的词条介绍的框架,带入仿射变换模型来实现的。
其中有一点想法,就是RANSAC每次随机选三点建立仿射变换模型,有可能重复,导致要做随机选择的次数比较多,才有充分的代表性,倒是可以设计一个每次选三点绝不重复的伪随机函数,不知道性能能否提升一丁点,不过这块不是算法的性能瓶颈,可以控制在1ms以内筛选好两幅有较多相似特征点的匹配,没功夫纠缠了。
维基百科英文RANSAC:http://en.wikipedia.org/wiki/Ransac 信息更全面
筛选后的结果如下,比没筛选的效果好太多。
5 如何利用筛选后的结果
在筛选之前,我们只考虑匹配上了多少对点,筛选之后,我们还可以利用这些点的一致性(回归的残差越小,说明拟合得越好,一致性越好),这里我们粗略建了一个评价函数,还需进一步查资料了解经典的做法是怎样。
6 特征点的搜索
如果用C#组个对比特征点(128位向量),整个搜索匹配过程会非常慢,如下图所示,差不多一幅图要耗1秒钟。
二、C++移植阶段
做C++移植主要是两个目的:一个是在算法复杂度一样的情况下,利用C的高效,尽量提高搜索效率,通过特征点的全遍历搜索来看,做这种纯数值计算,C++还是可以比C#快2-3倍;第二个目的是C++的兼容性好,可以把服务器架架设在Linux、Windows,也可以把搜索匹配做在iOS、安卓上。
1.用KDTREE实现特征点的高效搜索
提到高效检索,我们应该想到的就是HASH表和二叉平衡树了, KD树就是多关键字的二叉树,如果不考虑对结点的增删改,我们可以把这颗二叉树建得非常平衡,这样相对于顺序查找,查找效率是非常高的。
1.1 调用or自己写?
KDTree的基本原理和实验数据仍然是从博客园的博文http://archive.cnblogs.com/a/2241247/参考的。在网上找了几个KdTree的实现代码,感觉实现得比较好的是OpenCV的_kdtree.hpp,不过OpenCV的那段代码太多C的技巧和特殊优化的处理,没看太懂怎么用起来就放弃了,我们自己实现一遍吧,有什么特殊需求也好修改。从OpenCV哪里倒是借鉴了一次性全部申请树的所有结点的方法,不然按数据结构教科书的套路,差点弄成每个结点单独动态申请了,效率降很多还不好存储到磁盘文件。另外可能有一小点创新的是,在生成KDTree做排序划分的时候,没有去移动特征向量,而是做了一个小标集map,排序的是map中的下标,这样排序的移动代价小了128倍,最后查找使用时,也没增加复杂度,唯一的坏处是得自己写排序算法,c语言标准的qsort不好支持这样的排序需求。
1.2 几个经典的bug(缺陷)调试
第一个缺陷是:建立的KDTree数据量小的时候没问题,数据量大就报告栈溢出,一查看原来是qsort递归次数太多,再一看怎么会这么递归多呢?原来是qsort遇到了最坏情况,数据是有序的,每次只能把数据分成1和n-1个,这个n很大时,递归次数当然很多。为什么运气会这么差呢?再以分析,应该在建立KDTree时,有些作过划分维的维度,已经有序了。我们自己心里当然明白,按说有三个方法解决,一个是舍伍德算法也就是乱序再来,感觉费劲还效果不一定好,一个是每次取中位数做划分依据,实现太麻烦,最后选择实现了一个非递归的MergeSort,轻松实现又不依赖于人品,什么样顺序的数据都可以稳定的表现。
第二个缺陷是:用C#做顺序搜索,然后筛选,查找,结果很好。同样搜索参数,用KDTree做下来很差,反复分析分析分析之后,发现我们在C#中用标准图中的每个点在未知图中找最相似的匹配点,因为标准图没有多余的特征点,这样匹配下来的有效率很高。而对于KDTree,我们只能用未知图的特征点在KDTree中搜索在每幅标准图中的最相似点,而未知图的背景比较复杂,对于最终正确的匹配,无效特征点很多,这样做就会出很多无效匹配点,挤占了有效匹配点的比例,导致RANSAC算法的一个前提条件不成立:就是内点要达到一定比例才能用RANSAC。发现了就有办法解决,具体不说了。
第三个缺陷是:居然KDTree没有顺序搜索速度快,不管是5000个特征点的标准库(都是5秒),还是22000个特征点的标准库(都是18秒),居然和顺序搜索一样,毫无点,严重的打击了我们团队的斗志,岂不是白忙活一阵子,完全不能用?然后深入调节参数,在保证搜索准确率不降低的情况下,把KDTree的搜索效率大幅度提高。同时
在5017个特征点中搜索火机图,需要171ms,29.3个特征点/ms
在22228个特征点中搜索火机图,需要578ms,38.5个特征点/ms
在32643个特征点中搜索火机图,需要812ms,40.2个特征点/ms
以上数据初步说明当特征点越多的时候,检索效率越高,KDTree有一定效果,按这个升高趋势,在10幅图中检索要超过100ms,在100幅图中检索在1000ms以内,在1000幅图钟检索应该在6000ms左右。
三、性能深度优化阶段
1、考虑多线程,预计8核提高5倍
2、考虑分布式计算,预计提高10-100倍,视资源多少而定
3、考虑SSE等CPU多媒体指令级别的优化,预计提高10-50倍
4、考虑设计KDTree以外的更高效的多关键字检索算法,有一定想法,希望提高10-200倍
5、显卡计算,CUDA不是很通用,暂时不考虑
6、考虑服务端被大量用户并发访问,性能降低1000倍。
我们的产品Angel Eyes预计将会在这个月向开发者开放API和SDK,希望对计算机视觉(CV)和Angel Eyes感兴趣的朋友能够时刻关注我们的信息,并申请内测。
我们的网址:www.angeleyes.it
我们的微博:http://weibo.com/u/2597388234
我们的电邮:angeleyes.tech@gmail.com
一、C#验证实验阶段
1、实验框架搭建工作:配置EmguCV、编写界面。
写界面是C#的长项,不过需要怎样一个界面来做实验,倒是一开始没想清楚,折腾了几下,要是用MFC来写,就伤不起了。
2、特征点提取与XML存储
以前学习的C#的XML序列化派上用场了,几行代码轻松解决图像库的特征点存储问题,存储的XML格式片段如下:
<Objects>
<StandardObject>
<Name>U盾</Name>
<Images>
<FeaturableImage>
<Name>IMG_0819.jpg</Name>
<Featrues>
<ImageFeature>
<Descriptor>
<float>0.000823393755</float>
<float>0.0008284497</float>
…………………………………………………….
</StandardObject>
</Objects>
3、简单图像搜索,两幅图像对比时,仅考虑两幅图像中有多少比例的特征点配对
4、高级筛选:随机样本一致算法
4.1 仿射变换模型封装(6参数线性变换模型,支持旋转、平移、缩放、错切等变换的组合,不含尺度空间的尺度参数)
4.2仿射变换模型的最小二乘拟合
4.2.1 公式推导:相当于多元线性回归的最小二乘拟合
4.2.2 求解3元一次方程组,我们用的最基本的行列式和代数余子式的求法,看了一下网上的,其他人是用了列主元素消元法,没有Angel Eyes的方法精度高,最终筛选效果不行,到底是他们实现的列主元素消元法不太正确,还是方法本身的差异,Angel Eyes也没深究,因为3元一次的方程组用什么方法速度都差不多,精度够就行。
怕求余子式展开时不小心写错,试用MatLab的符号计算功能,还不错
syms a11 a12 a13
syms a21 a22 a23
syms a31 a32 a33
A=[a11,a12,a13;a21,a22,a23;a31,a32,a33];
syms y1 y2 y3;
Y=[y1;y2;y3];
linsolve(A,Y)
4.3 实现随机样本一致
按照维基百科关于随机抽样的共识(RANdom SAmple Consensus,RANSAC)的词条介绍的框架,带入仿射变换模型来实现的。
其中有一点想法,就是RANSAC每次随机选三点建立仿射变换模型,有可能重复,导致要做随机选择的次数比较多,才有充分的代表性,倒是可以设计一个每次选三点绝不重复的伪随机函数,不知道性能能否提升一丁点,不过这块不是算法的性能瓶颈,可以控制在1ms以内筛选好两幅有较多相似特征点的匹配,没功夫纠缠了。
维基百科英文RANSAC:http://en.wikipedia.org/wiki/Ransac 信息更全面
筛选后的结果如下,比没筛选的效果好太多。
5 如何利用筛选后的结果
在筛选之前,我们只考虑匹配上了多少对点,筛选之后,我们还可以利用这些点的一致性(回归的残差越小,说明拟合得越好,一致性越好),这里我们粗略建了一个评价函数,还需进一步查资料了解经典的做法是怎样。
6 特征点的搜索
如果用C#组个对比特征点(128位向量),整个搜索匹配过程会非常慢,如下图所示,差不多一幅图要耗1秒钟。
二、C++移植阶段
做C++移植主要是两个目的:一个是在算法复杂度一样的情况下,利用C的高效,尽量提高搜索效率,通过特征点的全遍历搜索来看,做这种纯数值计算,C++还是可以比C#快2-3倍;第二个目的是C++的兼容性好,可以把服务器架架设在Linux、Windows,也可以把搜索匹配做在iOS、安卓上。
1.用KDTREE实现特征点的高效搜索
提到高效检索,我们应该想到的就是HASH表和二叉平衡树了, KD树就是多关键字的二叉树,如果不考虑对结点的增删改,我们可以把这颗二叉树建得非常平衡,这样相对于顺序查找,查找效率是非常高的。
1.1 调用or自己写?
KDTree的基本原理和实验数据仍然是从博客园的博文http://archive.cnblogs.com/a/2241247/参考的。在网上找了几个KdTree的实现代码,感觉实现得比较好的是OpenCV的_kdtree.hpp,不过OpenCV的那段代码太多C的技巧和特殊优化的处理,没看太懂怎么用起来就放弃了,我们自己实现一遍吧,有什么特殊需求也好修改。从OpenCV哪里倒是借鉴了一次性全部申请树的所有结点的方法,不然按数据结构教科书的套路,差点弄成每个结点单独动态申请了,效率降很多还不好存储到磁盘文件。另外可能有一小点创新的是,在生成KDTree做排序划分的时候,没有去移动特征向量,而是做了一个小标集map,排序的是map中的下标,这样排序的移动代价小了128倍,最后查找使用时,也没增加复杂度,唯一的坏处是得自己写排序算法,c语言标准的qsort不好支持这样的排序需求。
1.2 几个经典的bug(缺陷)调试
第一个缺陷是:建立的KDTree数据量小的时候没问题,数据量大就报告栈溢出,一查看原来是qsort递归次数太多,再一看怎么会这么递归多呢?原来是qsort遇到了最坏情况,数据是有序的,每次只能把数据分成1和n-1个,这个n很大时,递归次数当然很多。为什么运气会这么差呢?再以分析,应该在建立KDTree时,有些作过划分维的维度,已经有序了。我们自己心里当然明白,按说有三个方法解决,一个是舍伍德算法也就是乱序再来,感觉费劲还效果不一定好,一个是每次取中位数做划分依据,实现太麻烦,最后选择实现了一个非递归的MergeSort,轻松实现又不依赖于人品,什么样顺序的数据都可以稳定的表现。
第二个缺陷是:用C#做顺序搜索,然后筛选,查找,结果很好。同样搜索参数,用KDTree做下来很差,反复分析分析分析之后,发现我们在C#中用标准图中的每个点在未知图中找最相似的匹配点,因为标准图没有多余的特征点,这样匹配下来的有效率很高。而对于KDTree,我们只能用未知图的特征点在KDTree中搜索在每幅标准图中的最相似点,而未知图的背景比较复杂,对于最终正确的匹配,无效特征点很多,这样做就会出很多无效匹配点,挤占了有效匹配点的比例,导致RANSAC算法的一个前提条件不成立:就是内点要达到一定比例才能用RANSAC。发现了就有办法解决,具体不说了。
第三个缺陷是:居然KDTree没有顺序搜索速度快,不管是5000个特征点的标准库(都是5秒),还是22000个特征点的标准库(都是18秒),居然和顺序搜索一样,毫无点,严重的打击了我们团队的斗志,岂不是白忙活一阵子,完全不能用?然后深入调节参数,在保证搜索准确率不降低的情况下,把KDTree的搜索效率大幅度提高。同时
在5017个特征点中搜索火机图,需要171ms,29.3个特征点/ms
在22228个特征点中搜索火机图,需要578ms,38.5个特征点/ms
在32643个特征点中搜索火机图,需要812ms,40.2个特征点/ms
以上数据初步说明当特征点越多的时候,检索效率越高,KDTree有一定效果,按这个升高趋势,在10幅图中检索要超过100ms,在100幅图中检索在1000ms以内,在1000幅图钟检索应该在6000ms左右。
三、性能深度优化阶段
1、考虑多线程,预计8核提高5倍
2、考虑分布式计算,预计提高10-100倍,视资源多少而定
3、考虑SSE等CPU多媒体指令级别的优化,预计提高10-50倍
4、考虑设计KDTree以外的更高效的多关键字检索算法,有一定想法,希望提高10-200倍
5、显卡计算,CUDA不是很通用,暂时不考虑
6、考虑服务端被大量用户并发访问,性能降低1000倍。
我们的产品Angel Eyes预计将会在这个月向开发者开放API和SDK,希望对计算机视觉(CV)和Angel Eyes感兴趣的朋友能够时刻关注我们的信息,并申请内测。
我们的网址:www.angeleyes.it
我们的微博:http://weibo.com/u/2597388234
我们的电邮:angeleyes.tech@gmail.com
相关文章推荐
- 基于Google的嵌入式系统android开发语音技术(语音搜索,语音朗读文章,语音控制)
- 基于DSP的实时图像目标搜索与跟踪系统设计方案
- RDIFramework.NET — 系列目录 — 基于.NET的快速信息化系统开发框架
- KoaHub平台基于Node.js开发的Koa的模板系统handlebars插件代码详情
- 【备忘】全网最新基于ElasticSearch的找房网实战开发企业级房屋搜索网视频教程
- 基于Curl的RIA系统开发入门
- 在基于RedHat与Debian的系统上安装Wine 最新的开发版本
- 学校公文办公处理系统_基于ASP.NET和Swfupload、FlashPaper2.2、校讯通短信发送的开发
- 基于.Net开发的WEB图像制作工具XPaint (3)
- 基于图像的室内装修风格分类系统(一)---项目介绍
- 基于tm-extractor的Word文档内容搜索软件开发
- 基于图像的室内装修风格分类系统(四)---分类器
- 基于ARM 的嵌入式系统程序开发要点-(二)系统的初始化过程
- 在Windows系统中搭建基于.NET的iPhone应用程序虚机开发环境
- 【转】谈基于SOA的应用系统设计和开发
- 开发体系结构-基于bboss 框架开发BS系统的体系结构
- 基于arm+uClinux的嵌入式系统的开发
- 基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - 报表系统介绍
- DeskViewer基于Silverlight 2.0开发的个性相册展示系统
- [系统开发] 一个基于Django和PureCSS的内容管理系统