Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a rectangle around the target object using the features extracted by SIFT in OpenCV

I'm doing project in OpenCV on object detection which consists of matching the object in template image with the reference image. Using SIFT algorithm the features get acurately detected and matched but I want a rectagle around the matched features My algorithm uses the KD-Tree est ean First technique to get the matches

like image 378
Punit Avatar asked Feb 02 '23 09:02

Punit


2 Answers

If you want a rectangle around the detected object, here you have code example with exactly that. You just need to draw a rectangle around the homography H.

Hope it helps. Good luck.

like image 163
Jav_Rock Avatar answered Apr 27 '23 03:04

Jav_Rock


I use the following code, adapted from the SURF algoritm in OpenCV (modules/features2d/src/surf.cpp) to extract a surrounding of a keypoint.

Apart from other examples based on rectangles and ROI, this code returns the patch correctly oriented according to the orientation and scale determined by the feature detection algorithm (both available in the KeyPoint struct).

An example of the results of the detection on several different images:

SIFT keypoint patch extract example

const int PATCH_SZ = 20;
Mat extractKeyPoint(const Mat& image, KeyPoint kp)
{
    int x = (int)kp.pt.x;
    int y = (int)kp.pt.y;
    float size = kp.size;
    float angle = kp.angle;

    int win_size = (int)((PATCH_SZ+1)*size*1.2f/9.0);
    Mat win(win_size, win_size, CV_8UC3);

    float descriptor_dir = angle * (CV_PI/180);
    float sin_dir = sin(descriptor_dir);
    float cos_dir = cos(descriptor_dir);
    float win_offset = -(float)(win_size-1)/2;
    float start_x = x + win_offset*cos_dir + win_offset*sin_dir;
    float start_y = y - win_offset*sin_dir + win_offset*cos_dir;
    uchar* WIN = win.data;
    uchar* IMG = image.data;
    for( int i = 0; i < win_size; i++, start_x += sin_dir, start_y += cos_dir )
    {
        float pixel_x = start_x;
        float pixel_y = start_y;
        for( int j = 0; j < win_size; j++, pixel_x += cos_dir, pixel_y -= sin_dir )
        {
            int x = std::min(std::max(cvRound(pixel_x), 0), image.cols-1);
            int y = std::min(std::max(cvRound(pixel_y), 0), image.rows-1);
            for (int c=0; c<3; c++) {
                WIN[i*win_size*3 + j*3 + c] = IMG[y*image.step1() + x*3 + c];
            }
        }
    }
    return win;
}

I am not sure if the scale is entirely OK, but it is taken from the SURF source and the results look relevant to me.

like image 36
Michal Kottman Avatar answered Apr 27 '23 02:04

Michal Kottman