how to simulate a mouse click using opencv (c/c++)

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • katiezhu

    how to simulate a mouse click using opencv (c/c++)

    I'm working a project. It's about screen control. I write the program using c/c++ in visual studio 2008. I just use my hand to replace mouse to control screen. The code is given below:
    Code:
    //Must have the following line for console mode
    #include "stdafx.h"
    #include <stdlib.h>
    #include <stdio.h>
    #include <math.h>
    #include <conio.h>
    
    #include <cv.h>
    #include <cxcore.h>
    #include <highgui.h>
    
    
    CvPoint2D32f srcpoints[4];
    CvPoint temppoints[4];
    CvPoint2D32f dstpoints[4];
    
    int n = 0;
    IplImage* src=0;
    CvScalar color = CV_RGB(0,0,255);
    CvScalar color1 = CV_RGB(255,255,255);
    
    bool PointsCaptured = false;
    
    //4-times mouse click
    void on_mouse( int event, int x, int y, int flags,void* param )
    {
        switch( event )
        {
        case CV_EVENT_LBUTTONDOWN:
    
    		if (n<4) 
    		{
    			temppoints[n] =cvPoint(x,y);
    
    			srcpoints[n] =cvPointTo32f(temppoints[n]);
    
    			n++;
    			printf("Mouse Clicked, n = %d, (x,y) = (%d,%d) \n",n,x,y);
    			
    			if (n == 4)  
    			{ 
    				PointsCaptured = true;
    				printf("n is now equal to 4\n");
    			}
    
    
    		}
    	}
    }
    
    //Find the centroid of the maxpoint
    void FindCentroid(const IplImage *src, const IplImage *mask, double maxpt_Threshold, CvPoint2D32f *ptMaxLoc )
    {
    	int height = src->height;
    	int width = src->width;
    	if(height == 0 || width == 0) return;
    
    	unsigned char *srcdata,*maskdata;
    
    	srcdata = (unsigned char*)src->imageData ;
    	maskdata = (unsigned char*)mask->imageData ;
    	unsigned int srcindex = 0;
    	unsigned int maskindex = 0;
    	unsigned int maskindexrange = height * width;
    	unsigned int val = 0;
    	unsigned int max_srcindex = 0;
    	unsigned int max_maskindex = 0;
    	double sumVal = 0;
    	double sumxVal = 0;
    	double sumyVal = 0;
    
    	int Threshold = (int) maxpt_Threshold  ;
    
    	for(maskindex=0; maskindex < maskindexrange;  maskindex++)
    	{   
    		//val = (0.1140*srcdata[srcindex++] + 0.5870*srcdata[srcindex++] + 0.2989*srcdata[srcindex++]); 
    		//val = (srcdata[srcindex++] + srcdata[srcindex++] + srcdata[srcindex++]); 
    		val = (float)srcdata[srcindex++] ; // for grayscale image
    		if( ( val >= Threshold) && maskdata[maskindex] )
    		{	
    			// find the centroid of the lightspot - assuming there is only one spot!!
    			sumVal += (float)val;
    			sumxVal += (float)val*(float)fmod((double)maskindex,(double)width);
    			sumyVal += (float)val*(float)floor((double)maskindex/(double)width);
    		}
    	}
    
    	if (sumVal >= Threshold) // i.e. true even if there is only one single pixel brighter than the threshold
    	{
    		ptMaxLoc->x = sumxVal / sumVal ;	
    		ptMaxLoc->y = sumyVal / sumVal ;      
    		printf("findcentroid: %f %f %f\n", sumVal, ptMaxLoc->x,ptMaxLoc->y);
    		SetCursorPos(ptMaxLoc->x,ptMaxLoc->y);
    	} else
    	{
    		ptMaxLoc->x = -1.0 ;	// i.e. no centroid found
    		ptMaxLoc->y = -1.0 ;
    		printf("findcentroid: %f %f %f\n", sumVal, ptMaxLoc->x,ptMaxLoc->y);
    	}
    }
    
    //Find the maxpoint
    void FindMaxPoint(const IplImage *img, double *maxValR, double *maxXR, double *maxYR  )
    {
    		CvScalar p;
    
    		// Process the image pixel by pixel!
    		double maxVal, maxX, maxY, Y;
    		int A, B;
    		
    		int height = img->height;
    		int width = img->width;
    
    		maxVal=0; maxX=0; maxY=0;
    		for(int j=0;j<height;j++) 
    		{
    			for(int i=0;i<width;i++) 
    			{
    				p = cvGet2D(img,j,i);	// get pixel values from input image
                    Y =( p.val[2]+p.val[1]+p.val[0])/3;
    
    				if(Y>maxVal)
    				{	
    					maxVal=Y; maxX=i; maxY=j;
    				}
    			}
    		}
    
    		*maxXR = maxX; 
    		*maxYR = maxY;
    		*maxValR = maxVal;
    }
    
    int main(int argc, char *argv[])
    {
      /////////////////////////
      // 0. Initialization      
      /////////////////////////
    
      // Variables for holding the images or frames
      IplImage* ImageIn = 0;
      IplImage* ImageOut = 0;
      IplImage* ImageGray = 0;
      IplImage* ImageMask = 0;
    
      // For Input Image Information
      int height, width, size, channels;
      // width
       int cx = GetSystemMetrics(SM_CXSCREEN);
       // height
       int cy = GetSystemMetrics(SM_CYSCREEN);
    
      
    
      CvPoint2D32f ptMaxLoc;
      double  ThresholdLevel;
    
    
      ///////////////////////////////////////////////////////
      // 1. Initialize and Setup the Camera
      ///////////////////////////////////////////////////////
    
      CvCapture* capture = 0;
      capture = cvCaptureFromCAM( 0 ); // capture the first camera found
      if( !capture )
      {
          fprintf(stderr,"Could not initialize capturing...\n");
          return -1;
      }
    
      //Set the camera input width and height 
      cvQueryFrame(capture); // this call is necessary to get correct 
                             // capture properties
      cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 320);
      cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 240);
      // Read the camera width and height - note: it may not always end up what we wanted.
      height    = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
      width    = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
    
    
      /////////////////////////////////////////////////////
      // 2. SETTING UP THE DISPLAY WINDOWS AND IMAGE FRAMES 
      /////////////////////////////////////////////////////
    
      printf("\nProcessing %dx%d video images\n", width, height ); 
      printf("\nPress ESC key to exit program\n"); 
    
      // Initialize Input and Output Frames 
      ImageIn = cvCreateImage( cvSize(width, height), IPL_DEPTH_8U, 3 ); // 3 channels = color
      ImageOut = cvCreateImage( cvSize(width, height), IPL_DEPTH_8U, 3 ); // 3 channels = color
      ImageGray = cvCreateImage( cvSize(width, height), IPL_DEPTH_8U, 1 ); // 3 channels = color
      ImageMask = cvCreateImage( cvSize(width, height), IPL_DEPTH_8U, 1 );
      
      cvSet(ImageMask,cvScalar(255)); //  Set Mask to Entire Frame for now (reserved)
    
      // Create two windows to display the images (input and output)
      cvNamedWindow("Input Image", CV_WINDOW_AUTOSIZE); 
      cvNamedWindow("Output Image", CV_WINDOW_AUTOSIZE); 
      
      cvSetMouseCallback( "Input Image", on_mouse );
    
      ////////////////////////////////////////
      // 2.5 Calibration Loop ...
      ////////////////////////////////////////
      char key = 0;
      while( (key != 27) &&  !PointsCaptured  ) // 27 = 'ESC' 
      {
    	// The following lines monitor to see if any key has been pressed 
        key = (char) cvWaitKey(1);  // get key from OpenCV Image Windows
        if (key==-1) if (_kbhit()) key = _getch(); // no key entered, so check the console window also
        //if (key=='c' || key=='C') {VI.showSettingsWindow(device1); }  // key="C" => Show Camera Control 
    
    
        // GRAB THE NEW VIDEO FRAME
     	ImageIn = cvQueryFrame( capture );
    
        // show the images before and after processing
        cvShowImage("Input Image", ImageIn );
      }
    	
        printf("Points Captured\n The Points Are: \n");
        for (int i = 0; i<4;i++)
    	{
    	printf("point %d = (%4.1f,%4.1f)\n", i, srcpoints[i].x,srcpoints[i].y);
    	}
    
    	CvMat mat;
    	double data[] = {0,0,0,0,0,0,0,0,0};
    
    	cvInitMatHeader(&mat,3,3,CV_64FC1,data );
    
    	float mxx = 320;
    	float mxy = 240;
    
    	dstpoints[0].x=0;
    	dstpoints[0].y=0;
    	dstpoints[1].x=mxx;
    	dstpoints[1].y=0;
    	dstpoints[2].x=mxx;
    	dstpoints[2].y=mxy;
    	dstpoints[3].x=0;
    	dstpoints[3].y=mxy;
    
    	cvGetPerspectiveTransform(srcpoints,dstpoints,&mat );    //Calculates the perspective transform from 4 corresponding points
    
    	printf("H Matrix Obtained: \n");
    	
    	printf("%13.8f, %13.8f, %13.8f \n", cvmGet(&mat,0,0), cvmGet(&mat,1,0), cvmGet(&mat,2,0));
    	printf("%13.8f, %13.8f, %13.8f \n", cvmGet(&mat,0,1), cvmGet(&mat,1,1), cvmGet(&mat,2,1));
    	printf("%13.8f, %13.8f, %13.8f \n", cvmGet(&mat,0,2), cvmGet(&mat,1,2), cvmGet(&mat,2,2));
    	
    	printf("\n");
    
    
      /////////////////////////////////////////////////////
      // 3. THE MAIN LOOP - Continues forever until the ESC key (ASCII = 27) is pressed
      /////////////////////////////////////////////////////
      key = 0;
      while( key != 27 ) // 27 = 'ESC' 
      {
        // The following lines monitor to see if any key has been pressed 
        key = (char) cvWaitKey(1);  // get key from OpenCV Image Windows
        if (key==-1) if (_kbhit()) key = _getch(); // no key entered, so check the console window also
        //if (key=='c' || key=='C') {VI.showSettingsWindow(device1); }  // key="C" => Show Camera Control 
    
    	///////////////////////////////////////////////////////////////////
    	// Check if a new video frame is available, if yes then process it. 
    	///////////////////////////////////////////////////////////////////
    
          // GRAB THE NEW VIDEO FRAME
     	ImageIn = cvQueryFrame( capture );
    
    	//cvFlip(ImageIn, NULL, 1);
    
        if( ImageIn )
        {
    	  // Process the Video Input (ImageIn) and Save Result in ImageOut
    	  // In this case we just make a copy, i.e. ImageOut = ImageIn;
          //cvCopy(ImageIn, ImageOut, 0);
    
    		CvScalar p, q, r; //s;
    
    		double maxval, maxX, maxY;
    		maxval = 0;
    		maxX = -1;
    		maxY = -1;
    
    		// Find Centroid in Image Input
    		ThresholdLevel = 100;
    		cvCvtColor(ImageIn, ImageGray,CV_BGR2GRAY);
    		FindMaxPoint(ImageIn,&maxval,&maxX,&maxY);
    		FindCentroid(ImageGray, ImageMask, ThresholdLevel, &ptMaxLoc);
    		cvLine(ImageIn,cvPoint(maxX,maxY),cvPoint(maxX,maxY),cvScalar(0,0,255),4,8,0);
    	    cvRectangle(ImageIn, cvPoint(maxX-5,maxY-5), cvPoint(maxX+5,maxY+5), cvScalar(0,0,255), 1, 8, 0);
    
    
    		if ((maxX >= 0) && (maxX < 320) && (maxY >= 0) && (maxY < 240))
    		{
    
    			p = cvGet2D(ImageGray,maxY,maxX);
    			maxval = p.val[0]; 
    			printf("maxval = %f\n",maxval);
    
    			double ti =   maxX * cvmGet(&mat,2,0) + maxY * cvmGet(&mat,2,1) + 1*cvmGet(&mat,2,2) ;
    			double xp = ( maxX * cvmGet(&mat,0,0) + maxY * cvmGet(&mat,0,1) + 1*cvmGet(&mat,0,2) ) / ti;
    			double yp = ( maxX * cvmGet(&mat,1,0) + maxY * cvmGet(&mat,1,1) + 1*cvmGet(&mat,1,2) ) / ti;
    
    			maxX = xp;
    			maxY = yp;
    		
    			if (maxval > 200) 
    			{
    				//SetCursorPos(maxX*1440.0/320.0,maxY*800.0/240.0);
    				//SetCursorPos((int)(maxX * 1280/320.0),(int)(maxY * 800/240.0));
    				SetCursorPos((int)(maxX * (double)(cx)/320.0),(int)(maxY * (double)(cy)/240.0));		
    			}
    		}
    		cvWarpPerspective(ImageIn,ImageOut,&mat,CV_INTER_LINEAR,cvScalarAll(0));//applies a perspective transformation to an image
    
    		// show the images before and after processing
    		cvShowImage("Input Image", ImageIn );
    		cvShowImage("Output Image", ImageOut );
    
    	} // end if(VI.isFrameNew(device1))
      }   // end while( key != 27 ) // 27 = 'ESC' 
    
      ////////////////////////////////////////////
      // 4. EXIT: clean up before you go ...
      ////////////////////////////////////////////
      
      cvReleaseCapture( &capture );
      // release the image - can't use these - program crashes! weird.
      // Appearantly, wou can't release a image that pointer to a buffer. 
      // Msg from .h file: !!!DO NOT RELEASE or MODIFY the retrieved frame!!! 
    
      // close all windows
      cvDestroyWindow("Input Image"); 
      cvDestroyWindow("Output Image");
    
      return 0;
    }
    for the program, I just can control the mouse already. But I don't know how to simulate a mouse click. Can anybody help me now? thank you
Working...