SLAM知识点——汉明距离两种计算方法

参考:
1)https://zhuanlan.zhihu.com/p/84900782
2)https://blog.csdn.net/weixin_37747104/article/details/82949194

汉明距离——两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数。两个向量之间做异或得到一个值(值越大距离越远),计算该值的二进制1的个数,比如1101,二进制1的个数是3。
这里介绍两种方法:

方法1:

int bitcount(uint32_t v) {
    int c = 0;
    while (v) {
        v &= v - 1;
        ++c;
    }
    return c;
}

下面话为引用参考1)第一个例子,“核心代码是v &= v - 1,它的作用是将最低位的那个1清0如何做到呢?

用二进制的方式来思考,假设v不为0,我们只关心v中最低位的那个1,其他位不管它,那么v的二进制可以这样表示:xx..x 1 0..0,1前面的x表示任意值(0或1),1后面肯定是0(因为都说了关注最低位的1);v-1就可以表示成:xx..x 0 1..1,现在v & (v - 1) :xx..x 1 0..0xx..x 0 1..1得到xx..x 0 0..0,这样就把这个1给消除掉了,如此循环,直到v为0,循环多少次,就表明v有多少个二进制1。

这个算法的消耗与1的个数有关,如果v的二进制全是1,那就要循环32次,如果是64位的数字,就要循环64次。

方法2

unsigned  int v = *pa ^ *pb;   
v = v - ((v >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
dist += (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;

ORBSLAM2算描述子之间的距离时用的方法。下面这段话引用参考2),与参考1)中第三个例子异曲同工。
"pa和pb分别是两个描述子,进行异或操作得到一个32位int值,里面包含多个1,1的个数和即为两个描述子之间的距离。

0x55555555=01010101 01010101 01010101 01010101,我们把32位分成16个2位来看,即XX(X未知,可0可1),我们会发现int a=XX-(XX>>1)&01的结果即为XX中1的数量。XX>>1=0X,然后会发现int a=XX-(XX>>1)&01后得到的int值即为XX中1的个数。即XX=00时,a=0,XX=01时,a=1,XX=10时,a=1,XX=11时,a=2。
那么同理,v=v-((v>>1)&0x55555555)得到了32位int值v,将此时的v每两位表示的int值相加即为原v中1的个数

v = (v & 0x33333333) + ((v >> 2) & 0x33333333);,0x33333333=00110011 00110011 00110011 00110011,很明显,这一步操作是v拆成8个4位,每个4位代表的int值之和即为原v中1的个数,每个4位是由上式中的结果v的相邻2位拼接得到的。

同理可得(v + (v >> 4)) & 0xF0F0F0F是把之前的相邻4位拼接成8位,则此时32位int值四个八位代表的int值之和即为1的个数。

之后乘0x1010101的目的是把每个8位的数加到25-32位上,(注意由于声明的是uint型为4个字节,所以最高32位;另外,可以手动算一下,确实是累加每个8位数)然后右移24位移到末8位,即可得到四个八位的int值之和,即1的个数。"

例子:

#include<stdio.h>
int main(int argc, char** argv)
{
	//int v = 0x12311231;  // 0001 0010 0011 0001 0001 0010 0011 0001 
	int v = 0xffffffff;  // 0001 0010 0011 0001 0001 0010 0011 0001 
	printf("%x\n", v);  // 不要写成&v

	v = v - ((v >> 1) & 0x55555555); // 0x55555555 = 0101 0101 0101 0101 0101 0101 0101 0101 
	printf("%x\n", v);  // 0001 0010 0011 0001 0001 0010 0011 0001 
	v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
	printf("%x\n", v);

	//v = (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
	v = (v + (v >> 4)) & 0xF0F0F0F;
	printf("x: %x\n", v);
	v = v * 0x1010101;  //变相累加
	int dist = ((v)) >> 24;  // int(0x20) = 32
	printf("y: %d\n", dist);
	
	return 0;
}

注意:方法1的程序效率与1的个数相关,方法2与1的个数无关:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SLAM精度评估中的EVO是指使用EVO工具来评估SLAM系统的轨迹误差。EVO是一个开源的工具,用于评估SLAM系统的性能。它提供了一系列命令和功能,可以计算和可视化SLAM系统的轨迹误差。 在EVO中,有几个常用的命令可以用来评估SLAM系统的轨迹误差。其中,evo_traj命令用于评估轨迹误差,可以使用手写的ATE(绝对位姿误差)和RPE(相对位姿误差)来比较SLAM系统的性能。\[1\] 相对位姿误差主要用于比较运动(姿态增量),而不是进行绝对位姿的比较。相对位姿误差可以给出局部精度,例如SLAM系统每米的平移或旋转漂移量。可以使用evo_rpe命令来计算相对位姿误差,并通过设置参数来进行可视化和保存结果。\[2\] 另外,evo_ape命令可以用于计算ATE(绝对位姿误差),并提供了可视化和保存结果的功能。可以使用该命令来评估SLAM系统在KITTI数据集上的性能。\[3\] 总之,EVO是一个用于评估SLAM系统性能的工具,可以通过计算和可视化轨迹误差来评估SLAM系统的精度。可以使用evo_traj、evo_rpe和evo_ape等命令来进行评估和分析。 #### 引用[.reference_title] - *1* *2* [SLAM精度测评——EVO进阶](https://blog.csdn.net/Darlingqiang/article/details/123534388)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [ros中SLAM的EVO、APE测评——SLAM精度测评(一)](https://blog.csdn.net/Yangy_Jiaojiao/article/details/124419966)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值