Enable using X11 root as root image

This commit is contained in:
Bradlee Speice 2012-06-21 14:50:24 -04:00
parent 792ef300cb
commit 7a7b87babb
4 changed files with 224 additions and 6 deletions

View File

@ -23,6 +23,8 @@
#include "libcvautomation.h" #include "libcvautomation.h"
void usage ();
int main( int argc, char** argv ) int main( int argc, char** argv )
{ {
CvPoint result_point; CvPoint result_point;
@ -34,6 +36,8 @@ int main( int argc, char** argv )
char *sub_location = "sub.png"; char *sub_location = "sub.png";
int threshold = INT_MAX; int threshold = INT_MAX;
int search_method = CV_TM_SQDIFF; int search_method = CV_TM_SQDIFF;
int useX = 0; /* bool useX = false; */
char *xDisplay;
/* Start getopt */ /* Start getopt */
while (1) while (1)
@ -47,13 +51,14 @@ int main( int argc, char** argv )
{"separator", required_argument, 0, 'p'}, {"separator", required_argument, 0, 'p'},
{"search-method",required_argument, 0, 'm'}, {"search-method",required_argument, 0, 'm'},
{"threshold", required_argument, 0, 't'}, {"threshold", required_argument, 0, 't'},
{"x-root", optional_argument, 0, 'x'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
int option_index = 0; int option_index = 0;
opterr = 0; opterr = 0;
int c = getopt_long (argc, argv, "hur:s:p:m:t:", int c = getopt_long (argc, argv, "hur:s:p:m:t:x:",
long_options, &option_index); long_options, &option_index);
/* We're done with parsing options */ /* We're done with parsing options */
@ -93,6 +98,19 @@ int main( int argc, char** argv )
threshold = atoi(optarg); threshold = atoi(optarg);
break; break;
case 'x':
if (optarg) {
useX = 1;
xDisplay = optarg;
printf ("Using display %s", xDisplay);
} else {
useX = 1;
xDisplay = "";
printf ("Using display %s", xDisplay);
}
break;
case '?': case '?':
/* Error routine */ /* Error routine */
break; break;
@ -103,8 +121,10 @@ int main( int argc, char** argv )
}; };
} }
/* Use INT_MAX for the threshold, due to the way CV_TM_SQDIFF is calculated */ if (useX)
result_point = matchSubImage_location( root_location, sub_location, search_method, threshold ); result_point = matchSubImage_X11_location( xDisplay, sub_location, search_method, threshold );
else
result_point = matchSubImage_location( root_location, sub_location, search_method, threshold );
if ( result_point.x != -1 && result_point.y != -1 ) if ( result_point.x != -1 && result_point.y != -1 )
/* Output the match location */ /* Output the match location */
@ -123,6 +143,7 @@ void usage ( )
{ {
fprintf( stderr, "\n\ fprintf( stderr, "\n\
cva-match -r <root_image> -s <sub_image> \n\ cva-match -r <root_image> -s <sub_image> \n\
cva-match -s <sub_image> -x \n\
\n\ \n\
This program uses OpenCV in order to recognize an image within an image.\n\ This program uses OpenCV in order to recognize an image within an image.\n\
The return code is how many matches were found - return 0 for no matches,\n\ The return code is how many matches were found - return 0 for no matches,\n\
@ -146,6 +167,11 @@ Usage: \n\
\t\t\t\t\tCV_TM_CCORR_NORMED = 3\n\ \t\t\t\t\tCV_TM_CCORR_NORMED = 3\n\
\t\t\t\t\tCV_TM_CCOEFF = 4\n\ \t\t\t\t\tCV_TM_CCOEFF = 4\n\
\t\t\t\t\tCV_TM_COEFF_NORMED = 5\n\ \t\t\t\t\tCV_TM_COEFF_NORMED = 5\n\
\t-x, --x-root[=DISPLAY]:\tSet the root image to come from X11\n\
\t\t\t\tThe DISPLAY variable is optional, not specifying it will cause X\n\
\t\t\t\tto use the default display (not specifically :0.0)\n\
\t\t\t\tPlease note also that the '-x' must come at the end\n\
\t\t\t\tsince it is an optional argument.\n\
\n\ \n\
If you have any questions, comments, concerns, email bspeice@uncc.edu\n" ); If you have any questions, comments, concerns, email bspeice@uncc.edu\n" );

View File

@ -15,5 +15,193 @@
* *
* ===================================================================================== * =====================================================================================
*/ */
#include <stdlib.h>
#include "libcvautomation-x11.h"
/*
* === FUNCTION ======================================================================
* Name: matchSubImage_X11
* Description: Match a sub image using the X11 root window as root
* =====================================================================================
*/
CvPoint matchSubImage_X11( char *displayLocation, IplImage *subImage, int searchMethod, int threshold )
{
/* First things first, grab the root X window and convert it to
* the IplImage format.
* Much of this code was ripped lovingly from:
* http://opencv.willowgarage.com/wiki/ximage2opencvimage */
IplImage *X_IPL;
CvSize imageSize;
CvPoint resultPoint;
XImage *rootImage;
XColor color;
Display *display;
Screen *screen;
unsigned long rmask, gmask, bmask;
unsigned long rshift, rbits,
gshift, gbits,
bshift, bbits;
unsigned char colorChannel[3];
int startX = 0, startY = 0;
unsigned int width, height;
/* Setting up the X screengrab is the first order of business */
display = XOpenDisplay(displayLocation);
screen = DefaultScreenOfDisplay(display);
width = screen->width;
height = screen->height;
rootImage = XGetImage( display, DefaultRootWindow(display),
startX, startY, width, height,
AllPlanes, ZPixmap );
/* Make sure that we're good to go before going any farther */
if ( rootImage == NULL || display == NULL || screen == NULL )
{
fprintf( stderr, "Couldn't grab the root window!" );
resultPoint.x = -1;
resultPoint.y = -1;
return resultPoint;
}
/* Set up the OpenCV Image */
imageSize.width = rootImage->width;
imageSize.height = rootImage->height;
X_IPL = cvCreateImage( imageSize, IPL_DEPTH_8U, 3 ); /* 3 channels - RGB */
/* This if block converts the X root window to an IPL image. See you on the other side! */
unsigned int x, y; /* To be used later */
if ( screen->depths->depth == 24 )
{
/* Actually convert the XImage to Ipl */
rmask = screen->root_visual->red_mask;
gmask = screen->root_visual->green_mask;
bmask = screen->root_visual->blue_mask;
/* I honestly have no clue how most of the below code works */
/* TODO: Figure out how this code works and document it */
rshift = 0; rbits = 0;
while ( !(rmask & 1) ){
rshift++;
rmask >>= 1; /* Right bitshift by 1 */
}
while (rmask & 1) {
rbits++;
rmask >>= 1; /* Right bitshift by 1 */
}
if (rbits > 8) {
rshift += rbits - 8;
rbits = 8;
}
gshift = 0; gbits = 0;
while ( !(gmask & 1) ){
gshift++;
gmask >>= 1; /* Right bitshift by 1 */
}
while (gmask & 1) {
gbits++;
gmask >>= 1; /* Right bitshift by 1 */
}
if (gbits > 8) {
gshift += gbits - 8;
gbits = 8;
}
bshift = 0; bbits = 0;
while ( !(bmask & 1) ){
bshift++;
bmask >>= 1; /* Right bitshift by 1 */
}
while (bmask & 1) {
bbits++;
bmask >>= 1; /* Right bitshift by 1 */
}
if (bbits > 8) {
bshift += bbits - 8;
bbits = 8;
}
for ( x = 0; x < rootImage->width; x++) {
for ( y = 0; y < rootImage->height; y++) {
color.pixel = XGetPixel ( rootImage, x, y );
colorChannel[0] = ((color.pixel >> bshift) & ((1 << bbits) - 1)) << (8 - bbits);
colorChannel[1] = ((color.pixel >> gshift) & ((1 << gbits) - 1)) << (8 - gbits);
colorChannel[2] = ((color.pixel >> rshift) & ((1 << rbits) - 1)) << (8 - rbits);
CV_IMAGE_ELEM(X_IPL, uchar, y, x * X_IPL->nChannels) = colorChannel[0];
CV_IMAGE_ELEM(X_IPL, uchar, y, x * X_IPL->nChannels + 1) = colorChannel[1];
CV_IMAGE_ELEM(X_IPL, uchar, y, x * X_IPL->nChannels + 2) = colorChannel[2];
}
}
}
else
{
/* Slow alternative for non-24-bit-depth images */
/* I don't know how this works either. */
/* TODO: Figure out how this code works and document it */
Colormap colormap = DefaultColormap( &display, DefaultScreen ( &display ));
for ( x = 0; x < rootImage->width; x++ ) {
for ( y = 0; y < rootImage->height; y++ ) {
color.pixel = XGetPixel ( rootImage, x, y );
XQueryColor( display, colormap, &color );
CV_IMAGE_ELEM(X_IPL, uchar, y, x * X_IPL->nChannels) = color.blue;
CV_IMAGE_ELEM(X_IPL, uchar, y, x * X_IPL->nChannels + 1) = color.green;
CV_IMAGE_ELEM(X_IPL, uchar, y, x * X_IPL->nChannels + 2) = color.red;
}
}
}
/* Now that we've got the image we want as X_IPL, time to actually do the comparison.
* However, we don't want to do any more work than we have to - send our images off
* to matchSubImage in libopencvautomation-opencv. */
resultPoint = matchSubImage ( X_IPL, subImage, searchMethod, threshold );
/* Clean up the CV image we created, as well as all X resources */
XDestroyImage( rootImage );
XCloseDisplay( display );
cvReleaseImage( &X_IPL );
/* Return and be done */
return resultPoint;
} /* ----- end of function matchSubImage_X11 ----- */
/*
* === FUNCTION ======================================================================
* Name: matchSubImage_X11
* Description: Match a sub image using the X11 root window as root, from filename
* =====================================================================================
*/
CvPoint matchSubImage_X11_location( char *displayLocation, char *subImage_location, int searchMethod, int threshold )
{
/* This is basically a wrapper for matchSubImage_X11( char *display, IplImage )
* All we do is load the sub-image from the given filename, and then
* pass off the result to the above-named function */
IplImage *subImage;
subImage = cvLoadImage( subImage_location, CV_LOAD_IMAGE_COLOR );
CvPoint return_point;
/* Make sure we have a good image */
if ( subImage == 0 )
{
/* Return error */
return return_point;
}
return_point = matchSubImage_X11( displayLocation, subImage, searchMethod, threshold );
/* Free up the memory we created */
cvReleaseImage( &subImage );
/* Our return_point will already be bad if there's no match,
* we don't need to worry about setting it. */
return return_point;
} /* ----- end of function matchSubImage_X11_location ----- */

View File

@ -23,6 +23,9 @@
#include <opencv/highgui.h> #include <opencv/highgui.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "libcvautomation.h"
/* It should be noted that the following are the macros for template matching: /* It should be noted that the following are the macros for template matching:
* CV_TM_SQDIFF (default) * CV_TM_SQDIFF (default)
@ -33,7 +36,7 @@
* CV_TM_CCOEFF_NORMED * CV_TM_CCOEFF_NORMED
*/ */
CvPoint matchSubImage_X11( IplImage *subImage, int searchMethod, int threshold ); /* Match a sub image using the X11 root window as root */ CvPoint matchSubImage_X11( char *displayLocation, IplImage *subImage, int searchMethod, int threshold ); /* Match a sub image using the X11 root window as root */
CvPoint matchSubImage_X11_location( char *rootImage_location, int search_method, int threshold ); /* Match a sub image using X11 as root, from filename */ CvPoint matchSubImage_X11_location( char *displayLocation, char *rootImage_location, int search_method, int threshold ); /* Match a sub image using X11 as root, from filename */
#endif /* LIBCVAUTOMATION_X11_H */ #endif /* LIBCVAUTOMATION_X11_H */

View File

@ -18,6 +18,7 @@
#ifndef LIBCVAUTOMATION_H #ifndef LIBCVAUTOMATION_H
#define LIBCVAUTOMATION_H #define LIBCVAUTOMATION_H
#include <stdio.h>
#include "libcvautomation-opencv.h" #include "libcvautomation-opencv.h"
#include "libcvautomation-x11.h" #include "libcvautomation-x11.h"