freak.diff

Seth Price, 2013-10-16 07:46 am

Download (16.1 kB)

 
freak.cpp 2013-10-15 22:38:17.000000000 -0700
214 214
             descriptionPairs[i] = allPairs[FREAK_DEF_PAIRS[i]];
215 215
    }
216 216
}
217

  
217
    
218 218
void FREAK::computeImpl( const Mat& image, std::vector<KeyPoint>& keypoints, Mat& descriptors ) const {
219

  
219
    
220 220
    if( image.empty() )
221 221
        return;
222 222
    if( keypoints.empty() )
223 223
        return;
224

  
224
    
225 225
    ((FREAK*)this)->buildPattern();
226
    
227
    // Use 32-bit integers if we won't overflow in the integral image
228
    if ((image.type() == CV_8U || image.type() == CV_8S) &&
229
        (image.rows * image.cols) < 8388608 ) // 8388608 = 2 ^ (32 - 8(bit depth) - 1(sign bit))
230
    {
231
        // Create the integral image appropriate for our type & usage
232
        if (image.type() == CV_8U)
233
            computeDescriptors<uchar, int>(image, keypoints, descriptors);
234
        else if (image.type() == CV_8S)
235
            computeDescriptors<char, int>(image, keypoints, descriptors);
236
        else
237
            CV_Error( CV_StsUnsupportedFormat, "" );
238
    } else {
239
        // Create the integral image appropriate for our type & usage
240
        if ( image.type() == CV_8U )
241
            computeDescriptors<uchar, double>(image, keypoints, descriptors);
242
        else if ( image.type() == CV_8S )
243
            computeDescriptors<char, double>(image, keypoints, descriptors);
244
        else if ( image.type() == CV_16U )
245
            computeDescriptors<ushort, double>(image, keypoints, descriptors);
246
        else if ( image.type() == CV_16S )
247
            computeDescriptors<short, double>(image, keypoints, descriptors);
248
        else
249
            CV_Error( CV_StsUnsupportedFormat, "" );
250
    }
251
}
226 252

  
253
template <typename srcMatType, typename iiMatType>
254
void FREAK::computeDescriptors( const Mat& image, std::vector<KeyPoint>& keypoints, Mat& descriptors ) const {
255
    
227 256
    Mat imgIntegral;
228
    integral(image, imgIntegral);
257
    if (sizeof(iiMatType) == sizeof(double))
258
        integral(image, imgIntegral, CV_64F);
259
    else
260
        integral(image, imgIntegral, CV_32S);
261
    
229 262
    std::vector<int> kpScaleIdx(keypoints.size()); // used to save pattern scale index corresponding to each keypoints
230 263
    const std::vector<int>::iterator ScaleIdxBegin = kpScaleIdx.begin(); // used in std::vector erase function
231 264
    const std::vector<cv::KeyPoint>::iterator kpBegin = keypoints.begin(); // used in std::vector erase function
232 265
    const float sizeCst = static_cast<float>(FREAK_NB_SCALES/(FREAK_LOG2* nOctaves));
233
    uchar pointsValue[FREAK_NB_POINTS];
266
    srcMatType pointsValue[FREAK_NB_POINTS];
234 267
    int thetaIdx = 0;
235 268
    int direction0;
236 269
    int direction1;
......
276 309
        // extract the best comparisons only
277 310
        descriptors = cv::Mat::zeros((int)keypoints.size(), FREAK_NB_PAIRS/8, CV_8U);
278 311
#if CV_SSE2
279
        __m128i* ptr= (__m128i*) (descriptors.data+(keypoints.size()-1)*descriptors.step[0]);
280
#else
281
        std::bitset<FREAK_NB_PAIRS>* ptr = (std::bitset<FREAK_NB_PAIRS>*) (descriptors.data+(keypoints.size()-1)*descriptors.step[0]);
312
        __m128i* ptrSSE = (__m128i*) (descriptors.data+(keypoints.size()-1)*descriptors.step[0]);
282 313
#endif
314
        std::bitset<FREAK_NB_PAIRS>* ptrScalar = (std::bitset<FREAK_NB_PAIRS>*) (descriptors.data+(keypoints.size()-1)*descriptors.step[0]);
315
        
283 316
        for( size_t k = keypoints.size(); k--; ) {
284 317
            // estimate orientation (gradient)
285 318
            if( !orientationNormalized ) {
......
289 322
            else {
290 323
                // get the points intensity value in the un-rotated pattern
291 324
                for( int i = FREAK_NB_POINTS; i--; ) {
292
                    pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,keypoints[k].pt.y, kpScaleIdx[k], 0, i);
325
                    pointsValue[i] = meanIntensity<srcMatType, iiMatType>(image, imgIntegral,
326
                                                                          keypoints[k].pt.x, keypoints[k].pt.y,
327
                                                                          kpScaleIdx[k], 0, i);
293 328
                }
294 329
                direction0 = 0;
295 330
                direction1 = 0;
......
310 345
            }
311 346
            // extract descriptor at the computed orientation
312 347
            for( int i = FREAK_NB_POINTS; i--; ) {
313
                pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,keypoints[k].pt.y, kpScaleIdx[k], thetaIdx, i);
348
                pointsValue[i] = meanIntensity<srcMatType, iiMatType>(image, imgIntegral,
349
                                                                      keypoints[k].pt.x, keypoints[k].pt.y,
350
                                                                      kpScaleIdx[k], thetaIdx, i);
314 351
            }
315 352
#if CV_SSE2
316
            // note that comparisons order is modified in each block (but first 128 comparisons remain globally the same-->does not affect the 128,384 bits segmanted matching strategy)
317
            int cnt = 0;
318
            for( int n = FREAK_NB_PAIRS/128; n-- ; )
319
            {
320
                __m128i result128 = _mm_setzero_si128();
321
                for( int m = 128/16; m--; cnt += 16 )
353
            if (sizeof(srcMatType) == sizeof(char)) {
354
                // note that comparisons order is modified in each block (but first 128 comparisons remain globally the same-->does not affect the 128,384 bits segmanted matching strategy)
355
                int cnt = 0;
356
                for( int n = FREAK_NB_PAIRS/128; n-- ; )
322 357
                {
323
                    __m128i operand1 = _mm_set_epi8(
324
                        pointsValue[descriptionPairs[cnt+0].i],
325
                        pointsValue[descriptionPairs[cnt+1].i],
326
                        pointsValue[descriptionPairs[cnt+2].i],
327
                        pointsValue[descriptionPairs[cnt+3].i],
328
                        pointsValue[descriptionPairs[cnt+4].i],
329
                        pointsValue[descriptionPairs[cnt+5].i],
330
                        pointsValue[descriptionPairs[cnt+6].i],
331
                        pointsValue[descriptionPairs[cnt+7].i],
332
                        pointsValue[descriptionPairs[cnt+8].i],
333
                        pointsValue[descriptionPairs[cnt+9].i],
334
                        pointsValue[descriptionPairs[cnt+10].i],
335
                        pointsValue[descriptionPairs[cnt+11].i],
336
                        pointsValue[descriptionPairs[cnt+12].i],
337
                        pointsValue[descriptionPairs[cnt+13].i],
338
                        pointsValue[descriptionPairs[cnt+14].i],
339
                        pointsValue[descriptionPairs[cnt+15].i]);
340

  
341
                    __m128i operand2 = _mm_set_epi8(
342
                        pointsValue[descriptionPairs[cnt+0].j],
343
                        pointsValue[descriptionPairs[cnt+1].j],
344
                        pointsValue[descriptionPairs[cnt+2].j],
345
                        pointsValue[descriptionPairs[cnt+3].j],
346
                        pointsValue[descriptionPairs[cnt+4].j],
347
                        pointsValue[descriptionPairs[cnt+5].j],
348
                        pointsValue[descriptionPairs[cnt+6].j],
349
                        pointsValue[descriptionPairs[cnt+7].j],
350
                        pointsValue[descriptionPairs[cnt+8].j],
351
                        pointsValue[descriptionPairs[cnt+9].j],
352
                        pointsValue[descriptionPairs[cnt+10].j],
353
                        pointsValue[descriptionPairs[cnt+11].j],
354
                        pointsValue[descriptionPairs[cnt+12].j],
355
                        pointsValue[descriptionPairs[cnt+13].j],
356
                        pointsValue[descriptionPairs[cnt+14].j],
357
                        pointsValue[descriptionPairs[cnt+15].j]);
358
                    __m128i result128 = _mm_setzero_si128();
359
                    for( int m = 128/16; m--; cnt += 16 )
360
                    {
361
                        __m128i operand1 = _mm_set_epi8(
362
                            pointsValue[descriptionPairs[cnt+0].i],
363
                            pointsValue[descriptionPairs[cnt+1].i],
364
                            pointsValue[descriptionPairs[cnt+2].i],
365
                            pointsValue[descriptionPairs[cnt+3].i],
366
                            pointsValue[descriptionPairs[cnt+4].i],
367
                            pointsValue[descriptionPairs[cnt+5].i],
368
                            pointsValue[descriptionPairs[cnt+6].i],
369
                            pointsValue[descriptionPairs[cnt+7].i],
370
                            pointsValue[descriptionPairs[cnt+8].i],
371
                            pointsValue[descriptionPairs[cnt+9].i],
372
                            pointsValue[descriptionPairs[cnt+10].i],
373
                            pointsValue[descriptionPairs[cnt+11].i],
374
                            pointsValue[descriptionPairs[cnt+12].i],
375
                            pointsValue[descriptionPairs[cnt+13].i],
376
                            pointsValue[descriptionPairs[cnt+14].i],
377
                            pointsValue[descriptionPairs[cnt+15].i]);
378

  
379
                        __m128i operand2 = _mm_set_epi8(
380
                            pointsValue[descriptionPairs[cnt+0].j],
381
                            pointsValue[descriptionPairs[cnt+1].j],
382
                            pointsValue[descriptionPairs[cnt+2].j],
383
                            pointsValue[descriptionPairs[cnt+3].j],
384
                            pointsValue[descriptionPairs[cnt+4].j],
385
                            pointsValue[descriptionPairs[cnt+5].j],
386
                            pointsValue[descriptionPairs[cnt+6].j],
387
                            pointsValue[descriptionPairs[cnt+7].j],
388
                            pointsValue[descriptionPairs[cnt+8].j],
389
                            pointsValue[descriptionPairs[cnt+9].j],
390
                            pointsValue[descriptionPairs[cnt+10].j],
391
                            pointsValue[descriptionPairs[cnt+11].j],
392
                            pointsValue[descriptionPairs[cnt+12].j],
393
                            pointsValue[descriptionPairs[cnt+13].j],
394
                            pointsValue[descriptionPairs[cnt+14].j],
395
                            pointsValue[descriptionPairs[cnt+15].j]);
358 396

  
359
                    __m128i workReg = _mm_min_epu8(operand1, operand2); // emulated "not less than" for 8-bit UNSIGNED integers
360
                    workReg = _mm_cmpeq_epi8(workReg, operand2);        // emulated "not less than" for 8-bit UNSIGNED integers
397
                        __m128i workReg = _mm_min_epu8(operand1, operand2); // emulated "not less than" for 8-bit UNSIGNED integers
398
                        workReg = _mm_cmpeq_epi8(workReg, operand2);        // emulated "not less than" for 8-bit UNSIGNED integers
361 399

  
362
                    workReg = _mm_and_si128(_mm_set1_epi16(short(0x8080 >> m)), workReg); // merge the last 16 bits with the 128bits std::vector until full
363
                    result128 = _mm_or_si128(result128, workReg);
400
                        workReg = _mm_and_si128(_mm_set1_epi16(short(0x8080 >> m)), workReg); // merge the last 16 bits with the 128bits std::vector until full
401
                        result128 = _mm_or_si128(result128, workReg);
402
                    }
403
                    (*ptrSSE) = result128;
404
                    ++ptrSSE;
364 405
                }
365
                (*ptr) = result128;
366
                ++ptr;
367
            }
368
            ptr -= 8;
369
#else
370
            // extracting descriptor preserving the order of SSE version
371
            int cnt = 0;
372
            for( int n = 7; n < FREAK_NB_PAIRS; n += 128)
406
                ptrSSE -= 8;
407
            } else
408
#endif
373 409
            {
374
                for( int m = 8; m--; )
410
                // extracting descriptor preserving the order of SSE version
411
                int cnt = 0;
412
                for( int n = 7; n < FREAK_NB_PAIRS; n += 128)
375 413
                {
376
                    int nm = n-m;
377
                    for(int kk = nm+15*8; kk >= nm; kk-=8, ++cnt)
414
                    for( int m = 8; m--; )
378 415
                    {
379
                        ptr->set(kk, pointsValue[descriptionPairs[cnt].i] >= pointsValue[descriptionPairs[cnt].j]);
416
                        int nm = n-m;
417
                        for(int kk = nm+15*8; kk >= nm; kk-=8, ++cnt)
418
                        {
419
                            ptrScalar->set(kk, pointsValue[descriptionPairs[cnt].i] >= pointsValue[descriptionPairs[cnt].j]);
420
                        }
380 421
                    }
381 422
                }
423
                --ptrScalar;
382 424
            }
383
            --ptr;
384
#endif
385 425
        }
386 426
    }
387 427
    else { // extract all possible comparisons for selection
......
397 437
            else {
398 438
                //get the points intensity value in the un-rotated pattern
399 439
                for( int i = FREAK_NB_POINTS;i--; )
400
                    pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,keypoints[k].pt.y, kpScaleIdx[k], 0, i);
440
                    pointsValue[i] = meanIntensity<srcMatType, iiMatType>(image, imgIntegral,
441
                                                                          keypoints[k].pt.x,keypoints[k].pt.y,
442
                                                                          kpScaleIdx[k], 0, i);
401 443

  
402 444
                direction0 = 0;
403 445
                direction1 = 0;
......
419 461
            }
420 462
            // get the points intensity value in the rotated pattern
421 463
            for( int i = FREAK_NB_POINTS; i--; ) {
422
                pointsValue[i] = meanIntensity(image, imgIntegral, keypoints[k].pt.x,
423
                                             keypoints[k].pt.y, kpScaleIdx[k], thetaIdx, i);
464
                pointsValue[i] = meanIntensity<srcMatType, iiMatType>(image, imgIntegral,
465
                                                                      keypoints[k].pt.x, keypoints[k].pt.y,
466
                                                                      kpScaleIdx[k], thetaIdx, i);
424 467
            }
425 468

  
426 469
            int cnt(0);
......
437 480
}
438 481

  
439 482
// simply take average on a square patch, not even gaussian approx
440
uchar FREAK::meanIntensity( const cv::Mat& image, const cv::Mat& integral,
483
template <typename imgType, typename iiType>
484
int FREAK::meanIntensity( const cv::Mat& image, const cv::Mat& integral,
441 485
                            const float kp_x,
442 486
                            const float kp_y,
443 487
                            const unsigned int scale,
......
461 505
        const int r_y = static_cast<int>((yf-y)*1024);
462 506
        const int r_x_1 = (1024-r_x);
463 507
        const int r_y_1 = (1024-r_y);
464
        uchar* ptr = image.data+x+y*imagecols;
465 508
        unsigned int ret_val;
466 509
        // linear interpolation:
467
        ret_val = (r_x_1*r_y_1*int(*ptr));
468
        ptr++;
469
        ret_val += (r_x*r_y_1*int(*ptr));
470
        ptr += imagecols;
471
        ret_val += (r_x*r_y*int(*ptr));
472
        ptr--;
473
        ret_val += (r_x_1*r_y*int(*ptr));
510
        ret_val = r_x_1*r_y_1*int(image.at<imgType>(y  , x  ))
511
                + r_x  *r_y_1*int(image.at<imgType>(y  , x+1))
512
                + r_x_1*r_y  *int(image.at<imgType>(y+1, x  ))
513
                + r_x  *r_y  *int(image.at<imgType>(y+1, x+1));
474 514
        //return the rounded mean
475 515
        ret_val += 2 * 1024 * 1024;
476
        return static_cast<uchar>(ret_val / (4 * 1024 * 1024));
516
        return static_cast<int>(ret_val / (4 * 1024 * 1024));
477 517
    }
478 518

  
479 519
    // expected case:
......
483 523
    const int y_top = int(yf-radius+0.5);
484 524
    const int x_right = int(xf+radius+1.5);//integral image is 1px wider
485 525
    const int y_bottom = int(yf+radius+1.5);//integral image is 1px higher
486
    int ret_val;
526
    iiType ret_val;
487 527

  
488
    ret_val = integral.at<int>(y_bottom,x_right);//bottom right corner
489
    ret_val -= integral.at<int>(y_bottom,x_left);
490
    ret_val += integral.at<int>(y_top,x_left);
491
    ret_val -= integral.at<int>(y_top,x_right);
528
    ret_val = integral.at<iiType>(y_bottom,x_right);//bottom right corner
529
    ret_val -= integral.at<iiType>(y_bottom,x_left);
530
    ret_val += integral.at<iiType>(y_top,x_left);
531
    ret_val -= integral.at<iiType>(y_top,x_right);
492 532
    ret_val = ret_val/( (x_right-x_left)* (y_bottom-y_top) );
493 533
    //~ std::cout<<integral.step[1]<<std::endl;
494
    return static_cast<uchar>(ret_val);
534
    return static_cast<int>(ret_val);
495 535
}
496 536

  
497 537
// pair selection algorithm from a set of training images and corresponding keypoints