@@ -48,24 +48,6 @@ namespace aruco {
48
48
49
49
using namespace std ;
50
50
51
-
52
-
53
- /* *
54
- * Hamming weight look up table from 0 to 255
55
- */
56
- const unsigned char hammingWeightLUT[] = {
57
- 0 , 1 , 1 , 2 , 1 , 2 , 2 , 3 , 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 ,
58
- 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 ,
59
- 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 ,
60
- 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 ,
61
- 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 ,
62
- 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 ,
63
- 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 ,
64
- 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 , 5 , 6 , 6 , 7 , 6 , 7 , 7 , 8
65
- };
66
-
67
-
68
-
69
51
/* *
70
52
*/
71
53
Dictionary::Dictionary (const unsigned char *bytes, int _markerSize, int dictsize, int _maxcorr) {
@@ -75,14 +57,9 @@ Dictionary::Dictionary(const unsigned char *bytes, int _markerSize, int dictsize
75
57
if ((markerSize * markerSize) % 8 != 0 ) nbytes++;
76
58
77
59
// save bytes in internal format
78
- // bytesList.at<Vec4b>(i, j )[k] is j-th byte of i-th marker, in its k-th rotation
60
+ // bytesList.ptr(i )[k*nbytes + j ] is j-th byte of i-th marker, in its k-th rotation
79
61
bytesList = Mat (dictsize, nbytes, CV_8UC4);
80
- for (int i = 0 ; i < dictsize; i++) {
81
- for (int j = 0 ; j < nbytes; j++) {
82
- for (int k = 0 ; k < 4 ; k++)
83
- bytesList.at < Vec4b >(i, j)[k] = bytes[i * (4 * nbytes) + k * nbytes + j];
84
- }
85
- }
62
+ memcpy (bytesList.data , bytes, dictsize*nbytes*4 );
86
63
}
87
64
88
65
@@ -106,13 +83,10 @@ bool Dictionary::identify(const Mat &onlyBits, int &idx, int &rotation,
106
83
int currentMinDistance = markerSize * markerSize + 1 ;
107
84
int currentRotation = -1 ;
108
85
for (unsigned int r = 0 ; r < 4 ; r++) {
109
- int currentHamming = 0 ;
110
- // for each byte, calculate XOR result and then sum the Hamming weight from the LUT
111
- for (unsigned int b = 0 ; b < candidateBytes.total (); b++) {
112
- unsigned char xorRes =
113
- bytesList.ptr < Vec4b >(m)[b][r] ^ candidateBytes.ptr < Vec4b >(0 )[b][0 ];
114
- currentHamming += hammingWeightLUT[xorRes];
115
- }
86
+ int currentHamming = hal::normHamming (
87
+ bytesList.ptr (m)+r*candidateBytes.cols ,
88
+ candidateBytes.ptr (),
89
+ candidateBytes.cols );
116
90
117
91
if (currentHamming < currentMinDistance) {
118
92
currentMinDistance = currentHamming;
@@ -147,12 +121,10 @@ int Dictionary::getDistanceToId(InputArray bits, int id, bool allRotations) cons
147
121
Mat candidateBytes = getByteListFromBits (bits.getMat ());
148
122
int currentMinDistance = int (bits.total () * bits.total ());
149
123
for (unsigned int r = 0 ; r < nRotations; r++) {
150
- int currentHamming = 0 ;
151
- for (unsigned int b = 0 ; b < candidateBytes.total (); b++) {
152
- unsigned char xorRes =
153
- bytesList.ptr < Vec4b >(id)[b][r] ^ candidateBytes.ptr < Vec4b >(0 )[b][0 ];
154
- currentHamming += hammingWeightLUT[xorRes];
155
- }
124
+ int currentHamming = hal::normHamming (
125
+ bytesList.ptr (id) + r*candidateBytes.cols ,
126
+ candidateBytes.ptr (),
127
+ candidateBytes.cols );
156
128
157
129
if (currentHamming < currentMinDistance) {
158
130
currentMinDistance = currentHamming;
@@ -202,26 +174,25 @@ Mat Dictionary::getByteListFromBits(const Mat &bits) {
202
174
Mat candidateByteList (1 , nbytes, CV_8UC4, Scalar::all (0 ));
203
175
unsigned char currentBit = 0 ;
204
176
int currentByte = 0 ;
177
+
178
+ // the 4 rotations
179
+ uchar* rot0 = candidateByteList.ptr ();
180
+ uchar* rot1 = candidateByteList.ptr () + 1 *nbytes;
181
+ uchar* rot2 = candidateByteList.ptr () + 2 *nbytes;
182
+ uchar* rot3 = candidateByteList.ptr () + 3 *nbytes;
183
+
205
184
for (int row = 0 ; row < bits.rows ; row++) {
206
185
for (int col = 0 ; col < bits.cols ; col++) {
207
186
// circular shift
208
- candidateByteList.ptr < Vec4b >(0 )[currentByte][0 ] =
209
- candidateByteList.ptr < Vec4b >(0 )[currentByte][0 ] << 1 ;
210
- candidateByteList.ptr < Vec4b >(0 )[currentByte][1 ] =
211
- candidateByteList.ptr < Vec4b >(0 )[currentByte][1 ] << 1 ;
212
- candidateByteList.ptr < Vec4b >(0 )[currentByte][2 ] =
213
- candidateByteList.ptr < Vec4b >(0 )[currentByte][2 ] << 1 ;
214
- candidateByteList.ptr < Vec4b >(0 )[currentByte][3 ] =
215
- candidateByteList.ptr < Vec4b >(0 )[currentByte][3 ] << 1 ;
216
- // increment if bit is 1
217
- if (bits.at < unsigned char >(row, col))
218
- candidateByteList.ptr < Vec4b >(0 )[currentByte][0 ]++;
219
- if (bits.at < unsigned char >(col, bits.cols - 1 - row))
220
- candidateByteList.ptr < Vec4b >(0 )[currentByte][1 ]++;
221
- if (bits.at < unsigned char >(bits.rows - 1 - row, bits.cols - 1 - col))
222
- candidateByteList.ptr < Vec4b >(0 )[currentByte][2 ]++;
223
- if (bits.at < unsigned char >(bits.rows - 1 - col, row))
224
- candidateByteList.ptr < Vec4b >(0 )[currentByte][3 ]++;
187
+ rot0[currentByte] <<= 1 ;
188
+ rot1[currentByte] <<= 1 ;
189
+ rot2[currentByte] <<= 1 ;
190
+ rot3[currentByte] <<= 1 ;
191
+ // set bit
192
+ rot0[currentByte] |= bits.at <uchar>(row, col);
193
+ rot1[currentByte] |= bits.at <uchar>(col, bits.cols - 1 - row);
194
+ rot2[currentByte] |= bits.at <uchar>(bits.rows - 1 - row, bits.cols - 1 - col);
195
+ rot3[currentByte] |= bits.at <uchar>(bits.rows - 1 - col, row);
225
196
currentBit++;
226
197
if (currentBit == 8 ) {
227
198
// next byte
@@ -247,7 +218,7 @@ Mat Dictionary::getBitsFromByteList(const Mat &byteList, int markerSize) {
247
218
unsigned char base2List[] = { 128 , 64 , 32 , 16 , 8 , 4 , 2 , 1 };
248
219
int currentByteIdx = 0 ;
249
220
// we only need the bytes in normal rotation
250
- unsigned char currentByte = byteList.ptr < Vec4b >( 0 )[ 0 ] [0 ];
221
+ unsigned char currentByte = byteList.ptr () [0 ];
251
222
int currentBit = 0 ;
252
223
for (int row = 0 ; row < bits.rows ; row++) {
253
224
for (int col = 0 ; col < bits.cols ; col++) {
@@ -258,7 +229,7 @@ Mat Dictionary::getBitsFromByteList(const Mat &byteList, int markerSize) {
258
229
currentBit++;
259
230
if (currentBit == 8 ) {
260
231
currentByteIdx++;
261
- currentByte = byteList.ptr < Vec4b >( 0 )[currentByteIdx][ 0 ];
232
+ currentByte = byteList.ptr ( )[currentByteIdx];
262
233
// if not enough bits for one more byte, we are in the end
263
234
// update bit position accordingly
264
235
if (8 * (currentByteIdx + 1 ) > (int )bits.total ())
@@ -369,12 +340,8 @@ static Mat _generateRandomMarker(int markerSize) {
369
340
static int _getSelfDistance (const Mat &marker) {
370
341
Mat bytes = Dictionary::getByteListFromBits (marker);
371
342
int minHamming = (int )marker.total () + 1 ;
372
- for (int i = 1 ; i < 4 ; i++) {
373
- int currentHamming = 0 ;
374
- for (int j = 0 ; j < bytes.cols ; j++) {
375
- unsigned char xorRes = bytes.ptr < Vec4b >()[j][0 ] ^ bytes.ptr < Vec4b >()[j][i];
376
- currentHamming += hammingWeightLUT[xorRes];
377
- }
343
+ for (int r = 1 ; r < 4 ; r++) {
344
+ int currentHamming = hal::normHamming (bytes.ptr (), bytes.ptr () + bytes.cols *r, bytes.cols );
378
345
if (currentHamming < minHamming) minHamming = currentHamming;
379
346
}
380
347
return minHamming;
0 commit comments