2012-06-21 12:19:55 -04:00
|
|
|
/*
|
|
|
|
* =====================================================================================
|
|
|
|
*
|
|
|
|
* Filename: libcvautomation-opencv.c
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
*
|
|
|
|
* Created: 06/21/2012 08:34:21 AM
|
|
|
|
* Revision: none
|
|
|
|
* Compiler: gcc
|
|
|
|
*
|
|
|
|
* Author: Bradlee Speice, bspeice@uncc.edu
|
|
|
|
* Organization: MOSAIC at University of North Carolina at Charlotte
|
|
|
|
*
|
|
|
|
* =====================================================================================
|
|
|
|
*/
|
|
|
|
|
2012-06-22 13:22:16 -04:00
|
|
|
#include <libcvautomation/libcvautomation-opencv.h>
|
2012-06-21 12:19:55 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* === FUNCTION ======================================================================
|
|
|
|
* Name: matchSubImage
|
|
|
|
* Returns: CvPoint if a match is found, null if not
|
|
|
|
* =====================================================================================
|
|
|
|
*/
|
|
|
|
|
2012-06-22 09:16:44 -04:00
|
|
|
CvPoint matchSubImage ( IplImage *rootImage, IplImage *subImage, int searchMethod, double tolerance )
|
2012-06-21 12:19:55 -04:00
|
|
|
{
|
|
|
|
/* We have the two OpenCV images we want, go ahead and find if there are any matches */
|
|
|
|
IplImage *result;
|
|
|
|
CvPoint minloc, maxloc; /* Location for the match - depending on search algorithm,
|
|
|
|
the result may be in either minloc or maxloc */
|
|
|
|
CvPoint badpoint; /* (-1, -1), used to indicate an error */
|
|
|
|
double minval, maxval;
|
|
|
|
int rootImage_width, rootImage_height;
|
|
|
|
int subImage_width, subImage_height;
|
|
|
|
int result_width, result_height;
|
|
|
|
|
|
|
|
badpoint.x = badpoint.y = -1;
|
|
|
|
|
|
|
|
/* Make sure we have valid images */
|
|
|
|
if ( rootImage == 0 || subImage == 0) {
|
|
|
|
/* Otherwise return invalid */
|
|
|
|
minloc.x = minloc.y = -1;
|
|
|
|
return minloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set up the parameters for our result image */
|
|
|
|
rootImage_width = rootImage->width;
|
|
|
|
rootImage_height = rootImage->height;
|
|
|
|
subImage_width = subImage->width;
|
|
|
|
subImage_height = subImage->height;
|
|
|
|
result_width = rootImage_width - subImage_width + 1;
|
|
|
|
result_height = rootImage_height - subImage_height + 1;
|
|
|
|
|
|
|
|
/* Initialize our result image */
|
|
|
|
result = cvCreateImage( cvSize( result_width, result_height ), IPL_DEPTH_32F, 1 );
|
|
|
|
|
|
|
|
/* Compute the result image */
|
|
|
|
cvMatchTemplate( rootImage, subImage, result, searchMethod );
|
|
|
|
cvMinMaxLoc( result, &minval, &maxval, &minloc, &maxloc, 0 );
|
|
|
|
|
|
|
|
/* Free memory for the result image
|
|
|
|
* Note that we don't control the root or sub image,
|
|
|
|
* so don't mess with those */
|
|
|
|
cvReleaseImage( &result );
|
|
|
|
|
|
|
|
/* Make sure that we have enough correlation to return a result,
|
|
|
|
* and then return the match location*/
|
|
|
|
/* Return the match location */
|
|
|
|
if ( searchMethod == CV_TM_SQDIFF || searchMethod == CV_TM_SQDIFF_NORMED )
|
|
|
|
{
|
2012-06-22 09:16:44 -04:00
|
|
|
if ( minval < tolerance )
|
2012-06-21 12:19:55 -04:00
|
|
|
return minloc;
|
|
|
|
else
|
|
|
|
return badpoint;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-22 09:16:44 -04:00
|
|
|
if ( maxval > tolerance )
|
2012-06-21 12:19:55 -04:00
|
|
|
return maxloc;
|
|
|
|
else
|
|
|
|
return badpoint;
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* ----- end of function matchSubImage ----- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* === FUNCTION ======================================================================
|
|
|
|
* Name: matchSubImage_location
|
|
|
|
* Description: Match a root image and sub image from filename
|
|
|
|
* =====================================================================================
|
|
|
|
*/
|
2012-06-22 13:22:16 -04:00
|
|
|
CvPoint matchSubImage_location ( const char *rootImage_location, const char *subImage_location, int searchMethod, double tolerance )
|
2012-06-21 12:19:55 -04:00
|
|
|
{
|
|
|
|
/* This is basically a wrapper for matchSubImage( IplImage, IplImage )
|
|
|
|
* All we do is load the images from the given filenames, and then
|
|
|
|
* pass off the result to the above-named function */
|
|
|
|
IplImage *rootImage;
|
|
|
|
rootImage = cvLoadImage( rootImage_location, CV_LOAD_IMAGE_COLOR );
|
|
|
|
|
|
|
|
IplImage *subImage;
|
|
|
|
subImage = cvLoadImage( subImage_location, CV_LOAD_IMAGE_COLOR );
|
|
|
|
|
|
|
|
CvPoint return_point;
|
|
|
|
return_point.x = return_point.y = -1;
|
|
|
|
|
|
|
|
/* Make sure we have good images */
|
|
|
|
if ( rootImage == 0 || subImage == 0 )
|
|
|
|
{
|
|
|
|
/* Return error */
|
|
|
|
return return_point;
|
|
|
|
}
|
|
|
|
|
2012-06-22 09:16:44 -04:00
|
|
|
return_point = matchSubImage( rootImage, subImage, searchMethod, tolerance );
|
2012-06-21 12:19:55 -04:00
|
|
|
|
|
|
|
/* Free up the memory we created */
|
|
|
|
cvReleaseImage( &rootImage );
|
|
|
|
cvReleaseImage( &subImage );
|
|
|
|
|
|
|
|
/* Our return_point will already be NULL if there's no match */
|
|
|
|
return return_point;
|
|
|
|
|
|
|
|
} /* ----- end of function matchSubImage ----- */
|
2012-06-22 09:16:44 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* === FUNCTION ======================================================================
|
2012-06-22 09:38:02 -04:00
|
|
|
* Name: matchSubImage_a
|
|
|
|
* Description: Match a root image and sub image from an array of sub-images.
|
2012-06-22 09:16:44 -04:00
|
|
|
* The list contains an element for each sub-image to specify its own
|
|
|
|
* searchMethod and threshold value.
|
|
|
|
* =====================================================================================
|
|
|
|
*/
|
2012-06-22 09:38:02 -04:00
|
|
|
void matchSubImage_a ( IplImage *rootImage, cvautomationList *subImageArray, int listSize )
|
2012-06-22 09:16:44 -04:00
|
|
|
{
|
|
|
|
/* This is also a higher-end wrapper for matchSubImage, but is mostly aimed
|
|
|
|
* at making python support for multiple images very easy. */
|
|
|
|
|
|
|
|
CvPoint resultPoint;
|
|
|
|
cvautomationList curr;
|
|
|
|
|
|
|
|
int x = 0;
|
|
|
|
for ( x = 0; x < listSize; x++ )
|
|
|
|
{
|
2012-06-22 09:38:02 -04:00
|
|
|
curr = subImageArray[x];
|
|
|
|
if ( subImageArray[x].cvaImage != 0 )
|
2012-06-22 09:16:44 -04:00
|
|
|
resultPoint = matchSubImage ( rootImage, curr.cvaImage, curr.searchMethod, curr.tolerance );
|
|
|
|
else
|
2012-06-22 09:38:02 -04:00
|
|
|
{
|
|
|
|
/* We have a sub-image filename, go ahead and create the actual image. */
|
|
|
|
IplImage *subImage;
|
|
|
|
subImage = cvLoadImage( curr.fileName, CV_LOAD_IMAGE_COLOR );
|
|
|
|
|
|
|
|
resultPoint = matchSubImage ( rootImage, subImage, curr.searchMethod, curr.tolerance );
|
|
|
|
|
|
|
|
cvReleaseImage( &subImage );
|
|
|
|
}
|
2012-06-22 09:16:44 -04:00
|
|
|
|
|
|
|
curr.resultPoint = resultPoint;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* === FUNCTION ======================================================================
|
2012-06-22 15:38:41 -04:00
|
|
|
* Name: matchSubImage_a_location
|
2012-06-22 09:16:44 -04:00
|
|
|
* Description: Match a root image from location, and sub image from
|
2012-06-22 09:38:02 -04:00
|
|
|
* an array of sub-images.
|
2012-06-22 09:16:44 -04:00
|
|
|
* The list contains an element for each sub-image to specify its own
|
|
|
|
* searchMethod and threshold value.
|
|
|
|
* =====================================================================================
|
|
|
|
*/
|
2012-07-10 16:32:42 -04:00
|
|
|
void matchSubImage_a_location ( const char *rootImage_location, cvautomationList *subImageArray, int listSize )
|
2012-06-22 09:16:44 -04:00
|
|
|
{
|
|
|
|
/* This is also a higher-end wrapper for matchSubImage, but is mostly aimed
|
|
|
|
* at making python support for multiple images very easy. */
|
|
|
|
|
|
|
|
CvPoint resultPoint;
|
|
|
|
cvautomationList curr;
|
|
|
|
|
|
|
|
IplImage *rootImage;
|
2012-07-10 16:32:42 -04:00
|
|
|
rootImage = cvLoadImage( rootImage_location, CV_LOAD_IMAGE_COLOR );
|
2012-06-22 09:16:44 -04:00
|
|
|
|
|
|
|
int x = 0;
|
|
|
|
for ( x = 0; x < listSize; x++ )
|
|
|
|
{
|
2012-06-22 09:38:02 -04:00
|
|
|
curr = subImageArray[x];
|
|
|
|
if ( subImageArray[x].cvaImage != 0 )
|
2012-06-22 09:16:44 -04:00
|
|
|
resultPoint = matchSubImage ( rootImage, curr.cvaImage, curr.searchMethod, curr.tolerance );
|
|
|
|
else
|
2012-06-22 09:38:02 -04:00
|
|
|
{
|
|
|
|
/* We have a sub-image filename, go ahead and create the actual image. */
|
|
|
|
IplImage *subImage;
|
|
|
|
subImage = cvLoadImage( curr.fileName, CV_LOAD_IMAGE_COLOR );
|
|
|
|
|
|
|
|
resultPoint = matchSubImage ( rootImage, subImage, curr.searchMethod, curr.tolerance );
|
|
|
|
|
|
|
|
cvReleaseImage( &subImage );
|
|
|
|
}
|
2012-06-22 09:16:44 -04:00
|
|
|
|
|
|
|
curr.resultPoint = resultPoint;
|
|
|
|
}
|
2012-06-22 09:38:02 -04:00
|
|
|
|
|
|
|
cvReleaseImage( &rootImage );
|
2012-06-22 09:16:44 -04:00
|
|
|
}
|
|
|
|
|
2012-06-22 15:38:41 -04:00
|
|
|
/*
|
|
|
|
* === FUNCTION ======================================================================
|
|
|
|
* Name: matchSubImage_center
|
|
|
|
* Returns: CvPoint if a match is found, null if not
|
|
|
|
* The code is mostly the same as matchSubImage, but the difference
|
|
|
|
* here is that it returns the center of the sub-image, rather than
|
|
|
|
* the top-left corner.
|
|
|
|
* =====================================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
CvPoint matchSubImage_center ( IplImage *rootImage, IplImage *subImage, int searchMethod, double tolerance )
|
|
|
|
{
|
|
|
|
/* We have the two OpenCV images we want, go ahead and find if there are any matches */
|
|
|
|
IplImage *result;
|
|
|
|
CvPoint minloc, maxloc; /* Location for the match - depending on search algorithm,
|
|
|
|
the result may be in either minloc or maxloc */
|
|
|
|
CvPoint badpoint; /* (-1, -1), used to indicate an error */
|
|
|
|
double minval, maxval;
|
|
|
|
int rootImage_width, rootImage_height;
|
|
|
|
int subImage_width, subImage_height;
|
|
|
|
int result_width, result_height;
|
|
|
|
|
|
|
|
badpoint.x = badpoint.y = -1;
|
|
|
|
|
|
|
|
/* Make sure we have valid images */
|
|
|
|
if ( rootImage == 0 || subImage == 0) {
|
|
|
|
/* Otherwise return invalid */
|
|
|
|
minloc.x = minloc.y = -1;
|
|
|
|
return minloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set up the parameters for our result image */
|
|
|
|
rootImage_width = rootImage->width;
|
|
|
|
rootImage_height = rootImage->height;
|
|
|
|
subImage_width = subImage->width;
|
|
|
|
subImage_height = subImage->height;
|
|
|
|
result_width = rootImage_width - subImage_width + 1;
|
|
|
|
result_height = rootImage_height - subImage_height + 1;
|
|
|
|
|
|
|
|
/* Initialize our result image */
|
|
|
|
result = cvCreateImage( cvSize( result_width, result_height ), IPL_DEPTH_32F, 1 );
|
|
|
|
|
|
|
|
/* Compute the result image */
|
|
|
|
cvMatchTemplate( rootImage, subImage, result, searchMethod );
|
|
|
|
cvMinMaxLoc( result, &minval, &maxval, &minloc, &maxloc, 0 );
|
|
|
|
|
|
|
|
/* Free memory for the result image
|
|
|
|
* Note that we don't control the root or sub image,
|
|
|
|
* so don't mess with those */
|
|
|
|
cvReleaseImage( &result );
|
|
|
|
|
|
|
|
/* Make sure that we have enough correlation to return a result,
|
|
|
|
* and then return the match location*/
|
|
|
|
/* Return the match location */
|
|
|
|
if ( searchMethod == CV_TM_SQDIFF || searchMethod == CV_TM_SQDIFF_NORMED )
|
|
|
|
{
|
|
|
|
if ( minval < tolerance )
|
|
|
|
{
|
|
|
|
CvPoint resultPoint = minloc;
|
|
|
|
/* Center the image before returning */
|
|
|
|
resultPoint.x += (subImage->width) / 2;
|
|
|
|
resultPoint.y += (subImage->height) / 2;
|
|
|
|
|
|
|
|
return resultPoint;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return badpoint;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( maxval > tolerance )
|
|
|
|
{
|
|
|
|
CvPoint resultPoint;
|
|
|
|
resultPoint = maxloc;
|
|
|
|
/* Center the image before returning */
|
|
|
|
resultPoint.x += (subImage->width) / 2;
|
|
|
|
resultPoint.y += (subImage->height) / 2;
|
|
|
|
|
|
|
|
return resultPoint;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return badpoint;
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* ----- end of function matchSubImage ----- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* === FUNCTION ======================================================================
|
|
|
|
* Name: matchSubImage_location_center
|
|
|
|
* Description: Match a root image and sub image from filename
|
|
|
|
* Most of the code is the same as matchSubImage_location, but use
|
|
|
|
* matchSubImage_center as the lower-level call to make sure that
|
|
|
|
* we get the center of the sub-image.
|
|
|
|
* =====================================================================================
|
|
|
|
*/
|
|
|
|
CvPoint matchSubImage_location_center ( const char *rootImage_location, const char *subImage_location, int searchMethod, double tolerance )
|
|
|
|
{
|
|
|
|
/* This is basically a wrapper for matchSubImage( IplImage, IplImage )
|
|
|
|
* All we do is load the images from the given filenames, and then
|
|
|
|
* pass off the result to the above-named function */
|
|
|
|
IplImage *rootImage;
|
|
|
|
rootImage = cvLoadImage( rootImage_location, CV_LOAD_IMAGE_COLOR );
|
|
|
|
|
|
|
|
IplImage *subImage;
|
|
|
|
subImage = cvLoadImage( subImage_location, CV_LOAD_IMAGE_COLOR );
|
|
|
|
|
|
|
|
CvPoint return_point;
|
|
|
|
return_point.x = return_point.y = -1;
|
|
|
|
|
|
|
|
/* Make sure we have good images */
|
|
|
|
if ( rootImage == 0 || subImage == 0 )
|
|
|
|
{
|
|
|
|
/* Return error */
|
|
|
|
return return_point;
|
|
|
|
}
|
|
|
|
|
|
|
|
return_point = matchSubImage_center( rootImage, subImage, searchMethod, tolerance );
|
|
|
|
|
|
|
|
/* Free up the memory we created */
|
|
|
|
cvReleaseImage( &rootImage );
|
|
|
|
cvReleaseImage( &subImage );
|
|
|
|
|
|
|
|
/* Our return_point will already be NULL if there's no match */
|
|
|
|
return return_point;
|
|
|
|
|
|
|
|
} /* ----- end of function matchSubImage ----- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* === FUNCTION ======================================================================
|
|
|
|
* Name: matchSubImage_a_center
|
|
|
|
* Description: Match a root image and sub image from an array of sub-images.
|
|
|
|
* The list contains an element for each sub-image to specify its own
|
|
|
|
* searchMethod and threshold value.
|
|
|
|
* Most of the code is the same as matchSubImage_a, but we use
|
|
|
|
* matchSubImage_center as the underlying function to make sure we
|
|
|
|
* get the center of the sub-image, rather than the top-left corner
|
|
|
|
* =====================================================================================
|
|
|
|
*/
|
|
|
|
void matchSubImage_a_center ( IplImage *rootImage, cvautomationList *subImageArray, int listSize )
|
|
|
|
{
|
|
|
|
/* This is also a higher-end wrapper for matchSubImage, but is mostly aimed
|
|
|
|
* at making python support for multiple images very easy. */
|
|
|
|
|
|
|
|
CvPoint resultPoint;
|
|
|
|
cvautomationList curr;
|
|
|
|
|
|
|
|
int x = 0;
|
|
|
|
for ( x = 0; x < listSize; x++ )
|
|
|
|
{
|
|
|
|
curr = subImageArray[x];
|
|
|
|
if ( subImageArray[x].cvaImage != 0 )
|
|
|
|
resultPoint = matchSubImage ( rootImage, curr.cvaImage, curr.searchMethod, curr.tolerance );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* We have a sub-image filename, go ahead and create the actual image. */
|
|
|
|
IplImage *subImage;
|
|
|
|
subImage = cvLoadImage( curr.fileName, CV_LOAD_IMAGE_COLOR );
|
|
|
|
|
|
|
|
resultPoint = matchSubImage_center ( rootImage, subImage, curr.searchMethod, curr.tolerance );
|
|
|
|
|
|
|
|
cvReleaseImage( &subImage );
|
|
|
|
}
|
|
|
|
|
|
|
|
curr.resultPoint = resultPoint;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* === FUNCTION ======================================================================
|
|
|
|
* Name: matchSubImage_a_location_center
|
|
|
|
* Description: Match a root image from location, and sub image from
|
|
|
|
* an array of sub-images.
|
|
|
|
* The list contains an element for each sub-image to specify its own
|
|
|
|
* searchMethod and threshold value.
|
|
|
|
* Most of the code is the same as matchSubImage_a_location, but we
|
|
|
|
* use matchSubImage_center in order to return the center of the sub-
|
|
|
|
* image, rather than the top-left corner.
|
|
|
|
* =====================================================================================
|
|
|
|
*/
|
2012-07-10 16:32:42 -04:00
|
|
|
void matchSubImage_a_location_center ( const char *rootImage_location, cvautomationList *subImageArray, int listSize )
|
2012-06-22 15:38:41 -04:00
|
|
|
{
|
|
|
|
/* This is also a higher-end wrapper for matchSubImage, but is mostly aimed
|
|
|
|
* at making python support for multiple images very easy. */
|
|
|
|
|
|
|
|
CvPoint resultPoint;
|
|
|
|
cvautomationList curr;
|
|
|
|
|
|
|
|
IplImage *rootImage;
|
2012-07-10 16:32:42 -04:00
|
|
|
rootImage = cvLoadImage( rootImage_location, CV_LOAD_IMAGE_COLOR );
|
2012-06-22 15:38:41 -04:00
|
|
|
|
|
|
|
int x = 0;
|
|
|
|
for ( x = 0; x < listSize; x++ )
|
|
|
|
{
|
|
|
|
curr = subImageArray[x];
|
|
|
|
if ( subImageArray[x].cvaImage != 0 )
|
|
|
|
resultPoint = matchSubImage ( rootImage, curr.cvaImage, curr.searchMethod, curr.tolerance );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* We have a sub-image filename, go ahead and create the actual image. */
|
|
|
|
IplImage *subImage;
|
|
|
|
subImage = cvLoadImage( curr.fileName, CV_LOAD_IMAGE_COLOR );
|
|
|
|
|
|
|
|
resultPoint = matchSubImage_center ( rootImage, subImage, curr.searchMethod, curr.tolerance );
|
|
|
|
|
|
|
|
cvReleaseImage( &subImage );
|
|
|
|
}
|
|
|
|
|
|
|
|
curr.resultPoint = resultPoint;
|
|
|
|
}
|
|
|
|
|
|
|
|
cvReleaseImage( &rootImage );
|
|
|
|
}
|
|
|
|
|