Drawing rectangle around detected object using SURF
Asked Answered
I

1

5

I am trying to detect an object from the following code involving surf detector, I do not want to draw matches, I want to draw a rectangle around the detected object, but somehow I am unable to get correct Homography, please can anyone point out where I am going wrong.

#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"

using namespace cv;

int main()
{
    Mat object = imread( "sample.jpeg", CV_LOAD_IMAGE_GRAYSCALE );

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

    //Detect the keypoints using SURF Detector
    int minHessian = 500;

    SurfFeatureDetector detector( minHessian );
    std::vector<KeyPoint> kp_object;

    detector.detect( object, kp_object );

    //Calculate descriptors (feature vectors)
    SurfDescriptorExtractor extractor;
    Mat des_object;

    extractor.compute( object, kp_object, des_object );

    FlannBasedMatcher matcher;

    VideoCapture cap(0);

    namedWindow("Good Matches",0);
    cvResizeWindow("Good Matches",800,800);

    std::vector<Point2f> obj_corners(4);

    //Get the corners from the object
    obj_corners[0] = (cvPoint(0,0));
    obj_corners[1] = (cvPoint(object.cols,0));
    obj_corners[2] = (cvPoint(object.cols,object.rows));
    obj_corners[3] = (cvPoint(0, object.rows));

    char key = 'a';
    int framecount = 0;
    while (key != 27)
    {
        Mat frame;
        cap >> frame;

        if (framecount < 5)
        {
            framecount++;
            continue;
        }

        Mat des_image, img_matches;
        std::vector<KeyPoint> kp_image;
        std::vector<vector<DMatch > > matches;
        std::vector<DMatch > good_matches;
        std::vector<Point2f> obj;
        std::vector<Point2f> scene;
        std::vector<Point2f> scene_corners(4);
        Mat H;
        Mat image;

        cvtColor(frame, image, CV_RGB2GRAY);

        detector.detect( image, kp_image );
       extractor.compute( image, kp_image, des_image );

        matcher.knnMatch(des_object, des_image, matches, 2);

       for(int i = 0; i < min(des_image.rows-1,(int) matches.size()); i++) //THIS LOOP IS SENSITIVE TO SEGFAULTS
      {
            if((matches[i][0].distance < 0.6*(matches[i][1].distance)) && ((int) matches[i].size()<=2 && (int) matches[i].size()>0))
         {
              good_matches.push_back(matches[i][0]);
            }
       }

        //Draw only "good" matches
     //  drawMatches( object, kp_object, image, kp_image, good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(),DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);

        if (good_matches.size() >= 4)
        {
            for( int i = 0; i < good_matches.size(); i++ )
            {
                //Get the keypoints from the good matches
                obj.push_back( kp_object[ good_matches[i].queryIdx ].pt );
                scene.push_back( kp_image[ good_matches[i].trainIdx ].pt );
           }

            H = findHomography( obj, scene, CV_RANSAC );

            perspectiveTransform( obj_corners, scene_corners, H);

            //Draw lines between the corners (the mapped object in the scene image )
            line( image, scene_corners[0] + Point2f( object.cols, 0), scene_corners[1] + Point2f( object.cols, 0), Scalar(0, 255, 0), 4 );
            line( image, scene_corners[1] + Point2f( object.cols, 0), scene_corners[2] + Point2f( object.cols, 0), Scalar( 0, 255, 0), 4 );
            line( image, scene_corners[2] + Point2f( object.cols, 0), scene_corners[3] + Point2f( object.cols, 0), Scalar( 0, 255, 0), 4 );
            line( image, scene_corners[3] + Point2f( object.cols, 0), scene_corners[0] + Point2f( object.cols, 0), Scalar( 0, 255, 0), 4 );
        }

        //Show detected matches
        imshow( "Good Matches", image );

        key = waitKey(1);
    }
    return 0;
}
Intendment answered 15/6, 2012 at 10:36 Comment(2)
somehow unable in what way? are you not getting enough good matches, is the calculated homography just plain wrong? maybe you have some matches outside the objects?Bossism
@Bossism the matches are good enough, but the rectangle which is supposed to be around the object is not around it, so i guess i am calculating wrong coordinates.Intendment
R
4

If you want to see both images with a bounding rectangle to the second one around the detected object you need to use img_matches array and not image when you draw the lines.

If you want to see only the image with the marked object and not the pair of images (as you define by drawing lines into image), you just need to change your code to:

line( image, scene_corners[0], scene_corners[1], Scalar(0, 255, 0), 4 );

line( image, scene_corners[1], scene_corners[2], Scalar( 0, 255, 0), 4 );

line( image, scene_corners[2], scene_corners[3], Scalar( 0, 255, 0), 4 );

line( image, scene_corners[3], scene_corners[0], Scalar( 0, 255, 0), 4 );

and show the image in a new window

imshow( "Result", image);

Riccio answered 19/6, 2012 at 9:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.