Thursday, November 4, 2010

Finding a Laser Dot in An Image with OpenCV

Earlier today a friend of mine, who is working on an OpenCV project, asked me for a good way to locate a laser pointer in an image of a blank wall. I showed him two options:
  1. The function cvMatchTemplate() generates a likelyhood map for the position of a template within a larger image. See this tutorial for a sample program;
  2. Alternatively, since the searched object (the laser dot) distinguishes itself from the background by a primary color's (Red) concentration, it may be simpler to just isolate the image's Red channel with cvSetImageCOI(), then use cvMinMaxLoc() to return the position of the biggest-valued pixel:
/*
Returns the most likely position of a laser dot within the input image. This is
defined as the position of the pixel with the biggest value in the Red
channel.

Arguments:

image
Pointer to the input image, assumed 32-bit RGB.

dot
Pointer to the CvPoint instance to receive the output location.
*/
void cvSearchLaserDot(IplImage* image, CvPoint* dot) {
double minVal, maxVal;

// Select's the image's first channel. Assuming this is an RGB image, the
// Red channel will be selected.
cvSetImageCOI(image, 1);

// Looks for the biggest-valued pixel on the above selected channel.
cvMinMaxLoc(image, &minVal, &maxVal, NULL, dot, NULL);

// Resets the channel selection performed in the previous call to
// cvSetImageROI().
cvSetImageCOI(image, 0);
}
I did think of a third option – fitting a 2D gaussian function to the Red channel, then taking the gaussian's center as the location of the dot – but that would be a bit of an overkill, wouldn't it?