Ask Your Question
0

Draw rectangle around detected object only when it is detected

asked 2016-03-30 14:04:08 -0600

MarKS9 gravatar image

updated 2016-03-31 04:10:12 -0600

I am using SURF for detecting specific objects. But the issue with my code is the rectangle is drawn even if the object is not present in the scene. Like if i remove the object from the scene the rectangle stays there. I have no issues with detection it works perfectly.

//Ptr<SIFT> detector = SIFT::create(0,5,0.03,18);
Ptr<SURF> detector = SURF::create(minHessian,4,2);
Ptr<DescriptorExtractor> extractor = SURF::create(minHessian,4,2);
//Ptr<DescriptorExtractor> extractor = SIFT::create(0,5,0.03,18);

cvtColor(dst, src, CV_BGR2GRAY);
cvtColor(frame, gray_image, CV_BGR2GRAY);


detector->detect(src, keypoints_1);
//printf("Object: %d keypoints detected\n", (int)keypoints_1.size());
detector->detect(gray_image, keypoints_2);
//printf("Object: %d keypoints detected\n", (int)keypoints_1.size());

extractor->compute(src, keypoints_1, img_extractor);
// printf("Object: %d descriptors extracted\n", img_extractor.rows);
extractor->compute(gray_image, keypoints_2, snap_extractor);

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

obj_corners[0] = (cvPoint(0, 0));
obj_corners[1] = (cvPoint(src.cols, 0));
obj_corners[2] = (cvPoint(src.cols, src.rows));
obj_corners[3] = (cvPoint(0, src.rows));

vector<DMatch> matches;
matcher.match(img_extractor, snap_extractor, matches);

double max_dist = 0; double min_dist = 100;

//-- Quick calculation of max and min distances between keypoints
for (int i = 0; i < img_extractor.rows; i++)
{
    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);

vector< DMatch > good_matches;

for (int i = 0; i < img_extractor.rows; i++)
{
    if (matches[i].distance <= max(2 * min_dist, 0.02))
    {
        good_matches.push_back(matches[i]);
    }
}

Mat img_matches;
vector< DMatch > emptyVec;
drawMatches(src, keypoints_1, gray_image, keypoints_2, emptyVec,
    img_matches, Scalar::all(-1), Scalar::all(-1),
    vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);

if (good_matches.size() >= 4){

    for (size_t i = 0; i<good_matches.size(); i++){

        //get the keypoints from good matches
        obj.push_back(keypoints_1[good_matches[i].queryIdx].pt);
        scene.push_back(keypoints_2[good_matches[i].trainIdx].pt);

    }
}

H = findHomography(obj, scene, CV_RANSAC);

perspectiveTransform(obj_corners, scene_corners, H);

line(img_matches, scene_corners[0] + Point2f(src.cols, 0), scene_corners[1] + Point2f(src.cols, 0), Scalar(0, 255, 0), 4);
line(img_matches, scene_corners[1] + Point2f(src.cols, 0), scene_corners[2] + Point2f(src.cols, 0), Scalar(0, 255, 0), 4);
line(img_matches, scene_corners[2] + Point2f(src.cols, 0), scene_corners[3] + Point2f(src.cols, 0), Scalar(0, 255, 0), 4);
line(img_matches, scene_corners[3] + Point2f(src.cols, 0), scene_corners[0] + Point2f(src.cols, 0), Scalar(0, 255, 0), 4);

I want to draw rectangle only when the object in the scene is detected. How do i do it?

edit retag flag offensive close merge delete

Comments

1

I'm afraid you didn't include the part that does the actual detection so I can't give specifics, but you need to add an if statement around the code you have here if the match is bad. In short, if you didn't find it don't execute any of the code you have included.

Tetragramm gravatar imageTetragramm ( 2016-03-30 19:32:08 -0600 )edit

Please check the edited question.

MarKS9 gravatar imageMarKS9 ( 2016-03-31 04:11:16 -0600 )edit
1

please define : "only when it is detected" . would that be if (good_matches.size() >= 4) ?

i mean, the answer would be obvious, then.

berak gravatar imageberak ( 2016-03-31 04:17:21 -0600 )edit

First guess, you are initializing your scene corners outside your capture loop, and you do not reinitialize it each time. This means that it will keep and remember the last found positions and thus it gets drawn each time. Simply said, initialize inside your loop OR at the beginning of your loop you reinitialize the scene_corners data structure.

StevenPuttemans gravatar imageStevenPuttemans ( 2016-03-31 04:18:40 -0600 )edit

Well sorry for this stupid question. Thank you @Tetragramm & @berak it worked. But it is so slow to find the object in the new position. I mean the rectangle doesn't follow the object in the scene in real time and it takes around 8-9 secs to draw new rectangle around the object. I want it like in this video https://www.youtube.com/watch?v=ZXn69.... Any idea how do i do that?

MarKS9 gravatar imageMarKS9 ( 2016-03-31 04:36:20 -0600 )edit

@StevenPuttemans i am calling surf detection using a function inside my capture loop. So yes, my scene_corners is outside my main(). How do i reinitialize scene_corners?

MarKS9 gravatar imageMarKS9 ( 2016-03-31 04:47:48 -0600 )edit
1

Just clear the vector and inside your loop you check if there are exactly 4 values or not!

StevenPuttemans gravatar imageStevenPuttemans ( 2016-03-31 06:25:20 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2016-04-02 18:05:57 -0600

MarKS9 gravatar image

thank you all for the response. I have finally solved it as per your suggestions

if (good_matches.size() >= 4){
line(img_matches, scene_corners[0] + Point2f(src.cols, 0), scene_corners[1] + Point2f(src.cols, 0), Scalar(0, 255, 0), 4);
line(img_matches, scene_corners[1] + Point2f(src.cols, 0), scene_corners[2] + Point2f(src.cols, 0), Scalar(0, 255, 0), 4);
line(img_matches, scene_corners[2] + Point2f(src.cols, 0), scene_corners[3] + Point2f(src.cols, 0), Scalar(0, 255, 0), 4);
line(img_matches, scene_corners[3] + Point2f(src.cols, 0), scene_corners[0] + Point2f(src.cols, 0), Scalar(0, 255, 0), 4);
}

as per @StevenPuttemans suggestion i managed to reinitialize scene_vector inside the capture loop. And its working perfectly fine.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2016-03-30 14:04:08 -0600

Seen: 2,700 times

Last updated: Apr 02 '16