Ask Your Question
0

How improve object detection robustness (it gives me false positives)

asked 2013-09-17 14:40:41 -0600

Tomas gravatar image

updated 2013-09-18 16:00:04 -0600

Moster gravatar image

Hi all, I have to improve the robustness of the object detection (I need a very very strong detection, no problem of constrains time), because how you can see in the image, he calculates false positives and give wrong results. Do you have any idea, how I can increase robustness? I use bruteforce matcher because I think he find the best matching but it isn't.

Here is the code:

#include <stdio.h>
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"

 #include <opencv2/objdetect/objdetect.hpp>
    #include <opencv2/features2d/features2d.hpp>
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/legacy/legacy.hpp>
    #include <opencv2/legacy/compat.hpp>
    #include <opencv2/flann/flann.hpp>
    #include <opencv2/calib3d/calib3d.hpp>
    #include <opencv2/nonfree/features2d.hpp>
    #include <opencv2/nonfree/nonfree.hpp>

using namespace cv;

void readme();

/** @function main */
int main( int argc, char** argv )
{
  if( argc != 3 )
  { readme(); return -1; }

  Mat img_object = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
  Mat img_scene = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );

  if( !img_object.data || !img_scene.data )
  { std::cout<< " --(!) Error reading images " << std::endl; return -1; }

  //-- Step 1: Detect the keypoints using SURF Detector
  int minHessian = 400;//20000

  SurfFeatureDetector detector( minHessian );

  std::vector<KeyPoint> keypoints_object, keypoints_scene;

  detector.detect( img_object, keypoints_object );
  detector.detect( img_scene, keypoints_scene );

  //-- Step 2: Calculate descriptors (feature vectors)
  SurfDescriptorExtractor extractor;

  Mat descriptors_object, descriptors_scene;

  extractor.compute( img_object, keypoints_object, descriptors_object );
  extractor.compute( img_scene, keypoints_scene, descriptors_scene );

  //-- Step 3: Matching descriptor vectors using FLANN matcher
  //FlannBasedMatcher matcher;
  BFMatcher matcher(NORM_L2,true);

  std::vector< DMatch > matches;
  matcher.match( descriptors_object, descriptors_scene, matches );

  double max_dist = 0; double min_dist = 100;

  //-- Quick calculation of max and min distances between keypoints
  for( unsigned int i = 0; i < descriptors_object.rows; i++ )
  { 
      if(i==matches.size()) break;

      double dist = matches[i].distance;
    if( dist < min_dist ) min_dist = dist;
    if( dist > max_dist ) max_dist = dist;
  }

  printf("-- Max dist : %f \n", max_dist );
  printf("-- Min dist : %f \n", min_dist );

  //-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )
  std::vector< DMatch > good_matches;

  for( unsigned int i = 0; i < descriptors_object.rows; i++ )
  { 
      if(i==matches.size()) break;

      if( matches[i].distance < 3*min_dist )
     { good_matches.push_back( matches[i]); }
  }

  Mat img_matches;
  drawMatches( img_object, keypoints_object, img_scene, keypoints_scene,
               good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
               vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

  //-- Localize the object
  std::vector<Point2f> obj;
  std::vector<Point2f> scene;

  for( unsigned int i = 0; i < good_matches.size(); i++ )
  {
    //-- Get the keypoints from the good matches
    obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
    scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt );
  }

  Mat H = findHomography( obj, scene, CV_RANSAC );

  //-- Get the corners from the image_1 ( the object to be "detected" )
  std::vector<Point2f> obj_corners(4);
  obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( img_object.cols, 0 );
  obj_corners[2] = cvPoint( img_object.cols, img_object.rows ); obj_corners[3] = cvPoint( 0, img_object.rows );
  std::vector<Point2f> scene_corners(4);

  perspectiveTransform( obj_corners, scene_corners, H);

  //-- Draw lines between the corners (the mapped object in the scene - image_2 )
  line( img_matches, scene_corners[0] + Point2f( img_object.cols, 0), scene_corners ...
(more)
edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
2

answered 2013-09-17 14:49:16 -0600

Moster gravatar image

You could try the ratio test that was initially introduced with SIFT I think.

http://answers.opencv.org/question/19163/ratio-check-function-with-findhomography/

edit flag offensive delete link more

Comments

thanks! tomorrow i'll try.

Tomas gravatar imageTomas ( 2013-09-17 15:17:06 -0600 )edit

I've modified the code, and I post the changes editing the question. I hope is right!

Tomas gravatar imageTomas ( 2013-09-18 09:14:59 -0600 )edit
2

Btw, just because I said it was introduced with SIFT, that doesnt mean you cant use SURF :) For example SIFT doesnt have a hessian threshold. Also, play around with the ratio for the ratio test. Maybe higher or lower values are better

Moster gravatar imageMoster ( 2013-09-18 16:05:10 -0600 )edit

Question Tools

Stats

Asked: 2013-09-17 14:40:41 -0600

Seen: 2,048 times

Last updated: Sep 18 '13