我目前正在使用OpenCV的ORB功能提取器,我确实注意到存储ORB描述符的奇怪方式(至少对我来说)(它基本上是一个带有修改的Brief-32)与我的问题无关)。正如你们中的一些人所知,ORB使用修改后的FAST-9(圆半径= 9像素;也存储关键点的方向)提取的关键点,并使用具有修改的BRIEF-32描述符的关键点来存储关键点所代表的特征。 / p>
Brief(ORB版)的工作原理如下:我们采用31x31像素的补丁(代表一个特征)并创建一堆随机的5x5像素测试点。然后我们采用这些点的对并评估它们的强度,从而基于该对中的第一点的强度是大于还是小于第二点的强度来产生二元决策(0或1)。然后我们取所有这些位并使用基本求和公式来构建长度为n的二进制字符串(对于BRIEF-32,我们有32个字节* 8 = 256位长的二进制字符串):
SUM(2 第(i-1) * bit_pair_test)
其中bit_pair_test是我们从一对测试点的测试中计算出的位值。最终的结果是(对于一组二进制测试(...,0,1,0,1,1)):
(2 0 * 1)+(2 1 * 1)+(2 2 * 0)+(2 3 * 1)+(2 4 * 0)+ ...
现在,OpenCV的ORB存储这些位串的方式对我来说是个谜。如果我们查看包含整个图像的描述符的矩阵,其中每一行是单个关键点的单个描述符,我们可以看到每个描述符有32个8位数,这总共产生了Brief-32使用的那些256位存储信息。 我不明白为什么我们将这些256位分成32个字节。官方文档(http://docs.opencv.org/trunk/doc/py_tutorials/py_feature2d/py_brief/py_brief.html)只说OpenCV以字节为单位存储这样的描述符,但是它没有解释为什么会这样做。我已经考虑了三种可能性,但没有排除这些可能性的一些组合的可能性:
答案 0 :(得分:16)
选择8位和32位模式是由于存储和效率问题。
Brief,ORB和BRISK中的位顺序无关(与FREAK不同)。 因此,这些描述符的所有位都具有相同的意义,您只能比较比特流的第一部分等。
另一方面,FREAK的设计考虑了这样一个匹配过程(在FREAK论文中称为 cascade )。
好吧,计算机不存储单独的位。因此,您不会看到任何人在位数组中存储Brief等。
可从存储器读取的最小组件是一个字节(通常对应于8位,尽管有些DSP无法读取小于16位的块,但这是另一个故事)。
因此,你可以看到人们将他们的描述符存储在 byte 数组中(在C / C ++中输入unsigned char
,这是底层的OpenCV实现语言)。
另外,当CPU字边界上的变量对齐时,内存访问通常会更好(更快)。 现在大多数CPU都有32或64位的字,32位字是更好的选择,因为64位架构是在设计时考虑到传统的32位处理器。
通过XOR运算计算汉明距离。 碰巧许多处理器都有专用指令集,可以用32位字有效地计算XOR(在64位CPU变得更常见之前,整数的通用大小)。 更进一步,它们还可以支持在多个32位字并行上计算多个XOR值,这是一种称为SIMD(单输入多数据)的并行技术。例如,可以利用SSE扩展来进一步加速大小为32位倍数的BRIEF / ORB / ...描述符的汉明距离计算。