OpenCV2:幼儿园篇 第七章 界面事件

一.简介

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)图片信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//鼠标点击事件
  
#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(),当拖动滑块移动鼠标时触发滑动事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 滑动条二值化
  
#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进行图像赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#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)鼠标提取区域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#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;
}

 

三.键盘事件

 

posted @   言午丶  阅读(373)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示