OpenCV example, and why does Google do so poorly?

Take searching for cvGetSpatialMoment:

All the top results are nearly useless, just code that doesn't help much if you don't know what cvGetSpatialMoment does.

The "CV Reference Manual" that comes with an install of OpenCV probably should come up first (the local html files of course aren't google searchable), or any real text explanation or tutorial of the function. So scrolling down further there are some odd but useful sites like http://www.ieeta.pt/~jmadeira/OpenCV/OpenCVdocs/ref/opencvref_cv.htm. I guess the official Willow Garage docs here haven't been linked to enough.

The official OpenCV book on Google is highly searchable, some pages are restricted but many are not.

Through all that frustration I did manage to learn a lot of basics to load an image and process a portion of the image to look for a certain color, and then find the center of the region that has that color.

IplImage* image = cvLoadImage( base_filename, CV_LOAD_IMAGE_COLOR );

split it into two halves for separate processing
IplImage* image_left = cvCreateImage( cvSize( image->width/2, image->height), IPL_DEPTH_8U, 3 );
cvSetImageROI( image, cvRect( 0, 0, image->width/2, image->height ) );
cvCopy( image, image_left );

convert it to hsv color space
IplImage* image_left_hsv = cvCreateImage( cvSize(image_left->width, image_left->height), IPL_DEPTH_8U, 3 );

get only the hue component using the COI '[color] Channel Of Interest' function
IplImage* image_left_hue = cvCreateImage( cvSize(image_left->width, image_left->height), IPL_DEPTH_8U, 1 );
cvSetImageCOI( image_left_hsv, 1);
cvCopy(image_left_hsv, image_left_hue);

find only the parts of an image within a certain hue range
cvInRangeS(image_left_hue, cvScalarAll(huemin), cvScalarAll(huemax), image_msk);

erode it down to get rid of noise
cvErode(image_msk,image_msk,NULL, 3);

and then find the centers of mass of the found regions
CvMoments moments;
cvMoments(image_msk, &moments, 1);
double m00, m10, m01;

m00 = cvGetSpatialMoment(&moments, 0,0);
m10 = cvGetSpatialMoment(&moments, 1,0);
m01 = cvGetSpatialMoment(&moments, 0,1);

// TBD check that m00 != 0
float center_x = m10/m00;
float center_y = m01/m00;

Copy the single channel mask back into a three channel rgb image

IplImage* image_rgb = cvCreateImage( cvSize(image_msk->width, image_msk->height), IPL_DEPTH_8U, 3 );
cvSetImageCOI( image_rgb, 2);
cvSetImageCOI( image_rgb, 0);

and draw circles on a temp image where the centers of mass are
cvCircle(image_rgb,cvPoint(int(center_x),int(center_y)), 10, CV_RGB(200,50,50),3);

All the work of setting channels of interest and regions of interest was new to me. I could have operated on images in place rather than creating many new ones, taking up more memory (and I would need to remember to free the memory created by all of them), but for debugging it's nice to keep around the intermediate steps.


JohnDel said...

"cvSplit" can be used to split an image into the different channels

Clau said...

Muchisimas gracias por la info, crei que no habia nada en la red sobre moments en opencv.

thanks for the info, i didnt found any web or paper which explain moments.

GaryB said...

See new, searchable, documentation links referenced by the main opencv page: