一.简介
OpenCV中提供了程序界面中的鼠标和键盘事件
二.鼠标事件
// 设置鼠标回调函数
void setMouseCallback
(
const string& winname,
MouseCallback onMouse,
void* userdata = 0
)
// 被调用的函数指针
void Fun
(
int event,
int x,
int y,
int flags,
void* param)
- event
#define CV_EVENT_MOUSEMOVE 0--滑动
#define CV_EVENT_LBUTTONDOWN 1--左键点击
#define CV_EVENT_RBUTTONDOWN 2--右键点击
#define CV_EVENT_MBUTTONDOWN 3--中键点击
#define CV_EVENT_LBUTTONUP 4--左键放开
#define CV_EVENT_RBUTTONUP 5--右键放开
#define CV_EVENT_MBUTTONUP 6--中键放开
#define CV_EVENT_LBUTTONDBLCLK 7--左键双击
#define CV_EVENT_RBUTTONDBLCLK 8--右键双击
#define CV_EVENT_MBUTTONDBLCLK 9--中键双击
- flags
#define CV_EVENT_FLAG_LBUTTON 1--左键拖曳
#define CV_EVENT_FLAG_RBUTTON 2--右键拖曳
#define CV_EVENT_FLAG_MBUTTON 4-中键拖曳
#define CV_EVENT_FLAG_CTRLKEY 8~15--按Ctrl键不放事件
#define CV_EVENT_FLAG_SHIFTKEY 16~31--按Shift键不放事件
#define CV_EVENT_FLAG_ALTKEY 32~39--按Alt键不放事件
(1)图片信息
//鼠标点击事件
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <stdio.h>
//全局变量
cv::Mat srcImage;
void MouseEvent(int event, int x, int y, int flags, void* data)
{
char charText[30];
cv::Mat tempImage, hsvImage;
tempImage = srcImage.clone();
//
// 左键按下移动显示RGB信息
//
if (event == CV_EVENT_LBUTTONDOWN)
{
cv::Vec3b p = tempImage.at<cv::Vec3b>(y,x);
sprintf(charText, "R = %d, G = %d, B = %d", p[2], p[1], p[0]);
// 写RGB信息文本到图像
cv::putText(tempImage, charText, cv::Point(8,20), cv::FONT_HERSHEY_COMPLEX, 2, CV_RGB(0,0,255));
imwrite("c.jpg",tempImage);
}
//
// 右键按下移动显示HSV信息
//
else if (event == CV_EVENT_RBUTTONDOWN)
{
// 转换成HSV图像
cv::cvtColor(tempImage, hsvImage, CV_BGR2HSV);
cv::Vec3b p = hsvImage.at<cv::Vec3b>(y,x);
// 获取相应的通道值
sprintf(charText, "H = %d, S = %d, V = %d", p[0], p[1], p[2]);
// 写HSV文本信息到图像
cv::putText(tempImage, charText, cv::Point(8,20), cv::FONT_HERSHEY_PLAIN, 2, CV_RGB(0,255,0));
imwrite("d.jpg",tempImage);
}
//
// 没有按下键显示对应坐标
//
else
{
// 移动鼠标显示坐标
sprintf(charText, "x = %d, y = %d", x, y);
// 写X Y坐标文本信息到图像
cv::putText(tempImage, charText, cv::Point(8,20), cv::FONT_HERSHEY_PLAIN, 2, CV_RGB(255,0,0));
imwrite("e.jpg",tempImage);
}
}
int main(int argc, char** argv)
{
// 读取图像及判断是否正确读入
srcImage = cv::imread("a.jpg");
if (srcImage.empty())
return -1;
// 回调事件响应
cv::namedWindow("srcImage");
cv::setMouseCallback("srcImage", MouseEvent, 0);
cv::imshow("srcImage", srcImage);
cv::waitKey(0);
return 0;
}
- (2)滑动条
OpenCV提供滑动条函数createTrackbar(),当拖动滑块移动鼠标时触发滑动事件
// 滑动条二值化
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
//createTrackbar的回调响应函数
void onChangeTrackBar(int pos, void* data)
{
// 强制类型转换
cv::Mat srcImage = *(cv::Mat*)(data);
cv::Mat dstImage;
// 根据滑动条的值进行二值化
cv::threshold(srcImage, dstImage, pos, 255, 0);
cv::imshow("dyn_threshold", dstImage);
}
int main()
{
// 源图像载入及判断
cv::Mat srcImage = cv::imread("a.jpg");
if (!srcImage.data)
return -1;
//转换为灰度图像
cv::Mat srcGray;
cv::cvtColor(srcImage, srcGray, CV_RGB2GRAY);
cv::namedWindow("dyn_threshold");
cv::imshow("dyn_threshold", srcGray);
//创建滑动条createTrackbar,调用回调函数
createTrackbar("pos", "dyn_threshold", 0, 255, onChangeTrackBar, &srcGray);
cv::waitKey(0);
return 0;
}
- (3)固定区域提取
从整个图像中提取出兴趣区域ROI,通过Rect设置相应的感兴趣矩形区域,再用copyTo进行图像赋值
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
// 全局变量源图像
cv::Mat srcImage;
// 方法1:利用Rect选择区域(100, 180, 150, 50)
void regionExtraction(int xRoi, int yRoi, int widthRoi, int heightRoi)
{
// 提取指定坐标区域
cv::Mat roiImage(srcImage.rows, srcImage.cols, CV_8UC3);
std::cout << srcImage.rows << " " << srcImage.cols << std::endl;
// 将兴趣区域复制到目标图像
srcImage(cv::Rect(xRoi, yRoi, widthRoi, heightRoi)).copyTo(roiImage);
cv::imshow("roiImage", roiImage);
cv::waitKey(0);
}
int main()
{
// 源图像载入及判断
srcImage = cv::imread("a.jpg");
if (!srcImage.data)
return -1;
cv::imshow("ROIing", srcImage);
// 方法1:利用Rect选择区域(100,180,150,50)
int xRoi = 100;
int yRoi = 180;
int widthRoi = 150;
int heightRoi = 50;
regionExtraction(xRoi, yRoi, widthRoi, heightRoi);
cv::waitKey(0);
return 0;
}
(4)鼠标提取区域
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
//全局变量
cv::Mat srcImage;
//所选矩形区域
cv::Rect roiRect;
//起始点
cv::Point startPoint;
//终止点
cv::Point endPoint;
//完成所选区域标志位
bool downFlag = false;
bool upFlag = false;
void MouseEvent(int event, int x, int y, int flags, void* data)
{
// 鼠标左键按下 获取起始点
if (event == EVENT_LBUTTONDOWN)
{
downFlag = true;
startPoint.x = x;
startPoint.y = y;
}
// 鼠标拖到松开 获取终止点
if (event == EVENT_LBUTTONUP)
{
upFlag = true;
endPoint.x = x;
endPoint.y = y;
}
// 显示拖到图像区域
if (downFlag == true && upFlag == false)
{
Point tempPoint;
tempPoint.x = x;
tempPoint.y = y;
// 用于显示图像生成
cv::Mat tempImage = srcImage.clone();
cv::rectangle(tempImage, startPoint, tempPoint, Scalar(255,0,0), 2, 3, 0);
cv::imshow("ROIing", tempImage);
}
// 选择区域生成
if (downFlag == true && upFlag == true)
{
// 获取选择区域的ROI
roiRect.width = abs(startPoint.x - endPoint.x);
roiRect.height = abs(startPoint.y - endPoint.y);
roiRect.x = min(startPoint.x, endPoint.x);
roiRect.y = min(startPoint.y, endPoint.y);
cv::Mat roiMat(srcImage, roiRect);
imshow("ROI", roiMat);
downFlag = false;
upFlag = false;
}
cv::waitKey(0);
}
int main(int argc, char** argv)
{
// 读取图像及判断是否正确读入
srcImage = cv::imread("a.jpg");
if (srcImage.empty())
return -1;
// 回调事件响应
cv::namedWindow("ROIing");
cv::imshow("ROIing", srcImage);
cv::setMouseCallback("ROIing", MouseEvent, 0);
cv::waitKey(0);
return 0;
}
三.键盘事件