Draw rectangle around detected object only when it is detected
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?
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.
Please check the edited question.
please define : "only when it is detected" . would that be
if (good_matches.size() >= 4)
?i mean, the answer would be obvious, then.
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.
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?
@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?
Just clear the vector and inside your loop you check if there are exactly 4 values or not!