ViSP  2.9.0
Tutorial: Keypoint matching

Introduction

This tutorial focuses on SURF key points manipulation. You will learn how to detect SURF key points on a reference image considered here as the first image of an mpeg video. Then in the next images of the video, key points that match those detected in the reference image using SURF descriptor are displayed.

Note
We assume that you are familiar with video framegrabbing described in Tutorial: Image frame grabbing and with the way to display an image in a window described in Tutorial: Getting started.

SURF key points detection and matching

Let us consider the following source code also available in tutorial-matching-surf.cpp.

#include <visp/vpKeyPointSurf.h>
#include <visp/vpDisplayOpenCV.h>
#include <visp/vpVideoReader.h>
int main()
{
#if defined(VISP_HAVE_OPENCV_NONFREE) && defined(VISP_HAVE_FFMPEG)
vpVideoReader reader;
reader.setFileName("video-postcard.mpeg");
reader.acquire(I);
surf.buildReference(I);
Idisp.resize(I.getHeight(), 2*I.getWidth());
Idisp.insert(I, vpImagePoint(0, 0));
Idisp.insert(I, vpImagePoint(0, I.getWidth()));
vpDisplayOpenCV d(Idisp, 0, 0, "Matching surf keypoints") ;
while ( ! reader.end() )
{
reader.acquire(I);
Idisp.insert(I, vpImagePoint(0, I.getWidth()));
int nbMatch = surf.matchPoint(I);
vpImagePoint iPref, iPcur;
for (int i = 0; i < nbMatch; i++)
{
surf.getMatchedPoints(i, iPref, iPcur);
}
if (vpDisplay::getClick(Idisp, false))
break;
}
#endif
return 0;
}

Here after is the resulting video. The left image represents the reference image. The right images correspond to the successive images of the input video. All the green lines extremities represent the points that are matched.

Now, let us explain the lines dedicated to the SURF keypoint usage.

First we have to include the header of the vpKeyPointSurf class that is a wrapper over OpenCV classes.

#include <visp/vpKeyPointSurf.h>

Note that this class is only available if ViSP was build with OpenCV non free module. This is ensured by the check of VISP_HAVE_OPENCV_NONFREE macro. To grab the images from the mpeg video stream we need also that ViSP was build with ffmpeg 3rd party. That's why we check VISP_HAVE_FFMPEG macro definition:

#if defined(VISP_HAVE_OPENCV_NONFREE) && defined(VISP_HAVE_FFMPEG)

Then we open the mpeg video stream and grab the first image of the video that is stored in I container. A Surf keypoint class is instantiated and keypoints are detected on the first image which is considered as the reference image:

The next lines are used to create image Idisp to render the matching results; left image for the reference image, right image for the current image that is processed:

Idisp.resize(I.getHeight(), 2*I.getWidth());
Idisp.insert(I, vpImagePoint(0, 0));
Idisp.insert(I, vpImagePoint(0, I.getWidth()));

Then a display using OpenCV is created and image Idisp is rendered:

vpDisplayOpenCV d(Idisp, 0, 0, "Matching surf keypoints") ;

We enter then in the while() loop where a new image is acquired from the video stream and inserted in the right part of image Idisp dedicated to rendering of the matching results.

reader.acquire(I);
Idisp.insert(I, vpImagePoint(0, I.getWidth()));

We start the rendering by displaying the rendered image and by drawing a white vertical line to separate the reference image from the current one:

Keypoint matches between the reference image and the current image I are detected using:

int nbMatch = surf.matchPoint(I);

Then we parse all the matches to retrieve the coordinates of the points in the reference image (in iPref variable) and in the current image (in iPcur variable):

vpImagePoint iPref, iPcur;
for (int i = 0; i < nbMatch; i++)
{
surf.getMatchedPoints(i, iPref, iPcur);

Next we draw green lines between the matched points:

At the end of the iteration, we flush all the previous display to the render window:

You can now follow Tutorial: Homography estimation from points to see how to exploit couple of matched points in order to estimate an homography that allows to track the position of an object.