1. 程式人生 > >opencv的滑鼠以及鍵值使用

opencv的滑鼠以及鍵值使用

簡介

  本章是學習opencv上鍵盤和滑鼠相應的操縱與例項。


鍵盤響應

#include <math.h>                                                                                                                    
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv/cv.h>
 
int main(int agrc, char* argv[]){  
    int c;
    int exit = 0;
    cv::Mat src=cv::imread(argv[1],1);
 
    cv::imshow("22", src);
    while(!exit){
        c = cv::waitKey(0);
        switch(c){
            case 'w':
                printf("w \n");
                break;
            case 'a':
                printf("a \n");
                break;
            case 's':
                printf("s \n");
                break;  
            case 'd':
                printf("d \n");
                break;
            case 'q':
                printf("exit\n");
                exit = 1;
                break;
            default:
                printf("c:%d\n", c);
        }
    }
    return 0;                                                                                                                        
}

  如程式碼所示,主要就是waitKey中的引數,小於等於0表示一直等待鍵值,大於0的表示等待多少毫秒,超時就返回-1,否則就返回對應的鍵值。


滑鼠響應

#include <math.h>                                                                                                                    
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv/cv.h>
 
void on_mouse( int event, int x, int y, int flags, void* ustc)  
{  
    char *temp = (char *) ustc;  
 
    printf("temp:%s, event:%d, flags:%d\n", temp, event, flags);
}  
 
int main(int agrc, char* argv[]){
    char str[4] = "tao";
 
    cv::Mat src=cv::imread(argv[1],1);  
    cv::imshow("src",src);
 
    cvSetMouseCallback( "src", on_mouse, str);
    cv::waitKey(0);
    cv::waitKey(0);                                                                                                                  
    cvDestroyAllWindows();  
 
    return 0; 
} 

  對應程式碼如上所示,通過函式cvSetMouseCallback,綁定了滑鼠事件的相應視窗為:"src",響應函式為:on_mouse,以及可以往該響應函式傳入的引數指標:str。
如果沒有引數需要傳入,可以直接置為0或者NULL。
  接著看下它的響應函式on_mouse,先看下該函式的幾個引數,首先是:event用來描述滑鼠的點選事件。
  highgui/highgui_c.h中有定義如下變數:
enum
{
    CV_EVENT_MOUSEMOVE      =0,        //滑鼠移動
    CV_EVENT_LBUTTONDOWN    =1,        //滑鼠左鍵按下
    CV_EVENT_RBUTTONDOWN    =2,        //滑鼠右鍵按下
    CV_EVENT_MBUTTONDOWN    =3,        //滑鼠中鍵按下
    CV_EVENT_LBUTTONUP      =4,        //滑鼠左鍵彈起
    CV_EVENT_RBUTTONUP      =5,        //滑鼠右鍵彈起
    CV_EVENT_MBUTTONUP      =6,        //滑鼠中鍵彈起
    CV_EVENT_LBUTTONDBLCLK  =7,        //滑鼠左鍵雙擊
    CV_EVENT_RBUTTONDBLCLK  =8,        //滑鼠右鍵雙擊
    CV_EVENT_MBUTTONDBLCLK  =9         //滑鼠中鍵雙擊
};
  這些變數就是觸發滑鼠事件後,對應的event根據滑鼠不同操作返回的對應的值,每個值的對應意義如上述。
  然後:x,y對應的為滑鼠當前座標。
  接著:flag描述滑鼠的拖拽事件。
  highgui/highgui_c.h中有定義如下變數:
enum
{
    CV_EVENT_FLAG_LBUTTON   =1,     //滑鼠左鍵拖拽(按下滑鼠左鍵,然後在視窗中拖動滑鼠)
    CV_EVENT_FLAG_RBUTTON   =2,     //滑鼠右鍵拖拽
    CV_EVENT_FLAG_MBUTTON   =4,     //滑鼠中鍵拖拽
    CV_EVENT_FLAG_CTRLKEY   =8,     //按下鍵值CTRL不放
    CV_EVENT_FLAG_SHIFTKEY  =16,    //按下鍵值SHIFT不放
    CV_EVENT_FLAG_ALTKEY    =32     //按下鍵值ALT不放
};
  flag對應返回響應引數如上述,需要注意一些組合:比如按下鍵值CTRL的同時按下滑鼠左鍵拖拽,flag就變成了:9=1+8。如果是按下CTRL+滑鼠右鍵則變成:10=8+2。
  最後的void* 型別ustc,就是對應之前傳入的str,我傳入的str型別為char*,則直接將ustc轉回char*即可;如果是傳入為0或者NULL,則無需處理;如果是
其他型別指標,則轉化為對應的型別。


使用例項

  這裡做一個程式的例項:在影象上畫一個根據滑鼠拖拽而變化的矩形,然後按下鍵值‘C’之後,將對應被畫了矩形的位置複製為新圖片顯示;按下'q'鍵,退出程式。
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv/cv.h>
 
using namespace cv;
 
cv::Mat src;
char pic_name[20];
int pic_info[4];
 
void on_mouse( int event, int x, int y, int flags, void* ustc)  
{  
	if(event == CV_EVENT_LBUTTONDOWN){
		pic_info[0] = x;   /*width1*/
		pic_info[1] = y;   /*height1*/
		pic_info[2] = 0;   /*width2*/
		pic_info[3] = 0;   /*height2*/
	}else if(event == CV_EVENT_LBUTTONUP){
		pic_info[2] = x;
		pic_info[3] = y;
		src=cv::imread(pic_name,1);  
		cv::rectangle(src,cvPoint(pic_info[0], pic_info[1]),cvPoint(pic_info[2], pic_info[3]),cvScalar(255,0,0),2);	
		cv::imshow("src",src);
	}
	if(flags == CV_EVENT_FLAG_LBUTTON){
		pic_info[2] = x;
		pic_info[3] = y;
		src=cv::imread(pic_name,1);  
		cv::rectangle(src,cvPoint(pic_info[0], pic_info[1]),cvPoint(pic_info[2], pic_info[3]),cvScalar(255,0,0),2);	
		cv::imshow("src",src);
	}
	printf("%d %d %d %d\n", pic_info[0], pic_info[1], pic_info[2], pic_info[3]);
}  
 
int main(int agrc, char* argv[]){
	bool exit = false;
	char c;
	cv::Mat imageROI;
 
	memcpy(pic_name,argv[1],sizeof(argv[1]));
 
	src=cv::imread(pic_name,1);  
	cv::imshow("src",src);
 
	cvSetMouseCallback( "src", on_mouse, NULL);
	while(!exit){
		c = cv::waitKey(0);
		if(c == 'c'){
			if((pic_info[0] != 0) && (pic_info[1] != 0) && (pic_info[2] != 0) && (pic_info[3] != 0)){
				imageROI = src(cv::Rect(pic_info[0], pic_info[1], pic_info[2]-pic_info[0], pic_info[3]-pic_info[1]));
				cv::imshow("ROI", imageROI);
			}
		}else if(c == 'q'){
			exit = true;	
		}
	}
	cvDestroyAllWindows();  
 
	return 0;  
}  


效果演示

  對應的效果演示如下: