ORBSLAM2計算描述子距離——C++ 位操作得到二進位制32位int值中有多少個1
阿新 • • 發佈:2018-11-10
看ORBSLAM2時算描述子之間的距離時看到的神奇的位操作,特此記錄一哈。
unsigned int v = *pa ^ *pb;
v = v - ((v >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
dist += (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
pa和pb分別是兩個描述子,進行異或操作得到一個32位int值,裡面包含多個1,1的個數和即為兩個描述子之間的距離。
然後通過三個語句12個操作即可得到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位上,然後右移24位移到末8位,即可得到四個八位的int值之和,即1的個數。