• 【OpenCV】选择ROI区域 (转)


    问题描述:在测试目标跟踪算法时,需要选择不同区域作为目标,进行目标跟踪,测试目标跟踪的效果。

    解决思路:

    1.OpenCV中提供了鼠标交互控制,利用setMouseCallback()给固定的窗口设置鼠标回调函数。

    2.在鼠标回调函数中,选择感兴趣区域。

    代码实现如下,将感兴趣区域封装在MouseSelect类中,提供选择点和矩形框两种模式。

    复制代码

     1 #pragma once
     2 #ifndef __MOUSESELECT_H__
     3 #define __MOUSESELECT_H__
     4 
     5 #include <opencv2/opencv.hpp>
     6 #include <iostream>
     7 
     8 #define MAX_OBJECTS    10
     9 using namespace cv;
    10 using namespace std;
    11 typedef struct MouseSelectParams
    12 {
    13     vector<Point> pts;        //Points of selected
    14     char        *win_name;
    15     Mat            *image;        
    16     unsigned int mode;        //1 Point,2 Rect
    17     int             n;            // selected object number
    18 }MouseSelectParams;
    19 
    20 void on_mouse(int event,int x,int y,int flags,void *param);
    21 class MouseSelect
    22 {
    23 public:
    24     MouseSelect();
    25     ~MouseSelect();
    26 
    27     void select_rect(Mat &frame);
    28     void select_point(Mat &frame);
    29 
    30     vector<Point> vPoints;
    31     vector<Rect> vRects;
    32     unsigned int obj_selected;
    33 private:
    34     int get_rects(Mat &frame);
    35     int get_points(Mat &frame);
    36 
    37 };
    38 #endif

    复制代码

    复制代码

      1 #include "MouseSelect.h"
      2 
      3 MouseSelectParams *g_mousep;
      4 MouseSelect::MouseSelect() {}
      5 
      6 MouseSelect::~MouseSelect() {}
      7 
      8 void MouseSelect::select_rect(Mat &frame)
      9 {
     10     obj_selected = 0;
     11     while(0 == obj_selected)
     12     {
     13         obj_selected = get_rects(frame);
     14         if (obj_selected == 0)
     15         {
     16             cout<<"You haven't selected any rectangles. "<<endl;
     17         }
     18     }
     19 }
     20 
     21 void MouseSelect::select_point(Mat &frame)
     22 {
     23     obj_selected = 0;
     24     while(0 == obj_selected)
     25     {
     26         obj_selected = get_points(frame);
     27         if (obj_selected == 0)
     28         {
     29             cout<<"You haven't selected any points."<<endl;
     30         }
     31     }
     32 }
     33 
     34 int MouseSelect::get_rects(Mat &frame)
     35 {
     36     char *win_name = "Init Frame";
     37     MouseSelectParams params;
     38     params.win_name = win_name;
     39     params.image = &frame;
     40     params.n = 0;
     41     params.mode = 2;
     42     namedWindow(win_name,WINDOW_AUTOSIZE);
     43     imshow(win_name,frame);
     44     
     45     g_mousep = &params;
     46     setMouseCallback(win_name,on_mouse,0);
     47     waitKey(0);
     48     destroyWindow(win_name);
     49     
     50     int x1,x2,y1,y2,w,h;
     51     Rect rt;
     52     Point pt1,pt2;
     53     cout<<"Point Num: "<<params.pts.size()<<" Object Num: "<<params.n<<" Object Type: Rect."<<endl;
     54     for(int i = 0;i < params.pts.size();i += 2)
     55     {
     56         pt1 = params.pts[i];
     57         pt2 = params.pts[i + 1];
     58         x1 = min(pt1.x,pt2.x);
     59         x2 = max(pt1.x,pt2.x);
     60         y1 = min(pt1.y,pt2.y);
     61         y2 = max(pt1.y,pt2.y);
     62         w = x2 - x1;
     63         h = y2 - y1;
     64         w = (w % 2)? w:w+1;
     65         h = (h % 2)? h:h+1;
     66         rt.x = x1;
     67         rt.y = y1;
     68         rt.width = w;
     69         rt.height = h;
     70         vRects.push_back(rt);
     71     }
     72     return params.n;
     73 }
     74 
     75 int MouseSelect::get_points(Mat &frame)
     76 {
     77     char    *win_name = "Init Frame";
     78     MouseSelectParams params;
     79     params.win_name = win_name;
     80     params.image = &frame;
     81     params.n = 0;
     82     params.mode = 1;
     83 
     84     namedWindow(win_name,1);
     85     imshow(win_name,frame);
     86 
     87     g_mousep = &params;
     88     setMouseCallback(win_name,on_mouse,0);
     89     waitKey(0);
     90 
     91     destroyWindow(win_name);
     92     
     93     cout<<"Point Num: "<<params.pts.size()<<" Object Num: "<<params.n<<" Object Type: Point."<<endl;
     94     for (int i = 0;i < params.n;i++)
     95     {
     96         vPoints.push_back(params.pts[i]);
     97     }
     98     return params.n;
     99 }
    100 
    101 void on_mouse(int event,int x,int y,int flags,void *param)
    102 {
    103     int        n;
    104     static bool pressed = false;
    105     static Point cur_pt;
    106     static Point prev_pt;
    107     /* on left button press, remember first corner of rectangle around object */
    108     if (event == CV_EVENT_LBUTTONDOWN)
    109     {
    110         n = g_mousep->n;
    111         if (n == MAX_OBJECTS)
    112         {
    113             return;
    114         }
    115         prev_pt.x = x;
    116         prev_pt.y = y;
    117         //cout<<prev_pt.x <<","<<prev_pt.y<<" "<<cur_pt.x<<","<<cur_pt.y<<endl;
    118         pressed = true;
    119     }
    120     /* on left button up, finalise the rectangle and draw it in black */
    121     else if(event == CV_EVENT_LBUTTONUP && pressed)
    122     {
    123         /* 1 == mode for selecting points */
    124         if (1 == g_mousep->mode)
    125         {
    126             n = g_mousep->n;
    127             if (n == MAX_OBJECTS)
    128             {
    129                 return;
    130             }
    131             cur_pt.x = x;
    132             cur_pt.y = y;
    133             g_mousep->pts.push_back(cur_pt);
    134             int radius = 3;
    135             circle(*g_mousep->image,cur_pt,radius,CV_RGB(255,0,0));
    136             imshow(g_mousep->win_name,*g_mousep->image);
    137             pressed = false;
    138             g_mousep->n++;
    139         }
    140         /* 2 == mode for selecting rectangles */
    141         else if (2 == g_mousep->mode)
    142         {
    143             n = g_mousep->n;
    144             if (n == MAX_OBJECTS)
    145             {
    146                 return;
    147             }
    148             cur_pt.x = x;
    149             cur_pt.y = y;
    150             g_mousep->pts.push_back(prev_pt);
    151             g_mousep->pts.push_back(cur_pt);
    152         //    cout<<prev_pt.x <<","<<prev_pt.y<<" "<<cur_pt.x<<","<<cur_pt.y<<endl;
    153             rectangle(*g_mousep->image,prev_pt,cur_pt,CV_RGB(0,0,255));
    154             imshow(g_mousep->win_name,*g_mousep->image);
    155             pressed = false;
    156             g_mousep->n++;
    157         }
    158         else if (3 == g_mousep->mode)
    159         {
    160             n = g_mousep->n;
    161 
    162         }
    163     }
    164     else if (event == CV_EVENT_MOUSEMOVE && pressed && CV_EVENT_FLAG_LBUTTON)
    165     {
    166         if (2 == g_mousep->mode)
    167         {
    168             n = g_mousep->n;
    169             if (n == MAX_OBJECTS)
    170             {
    171                 return;
    172             }
    173             cur_pt.x = x;
    174             cur_pt.y = y;
    175             Mat tmp = (*g_mousep->image).clone();
    176             //cout<<prev_pt.x <<","<<prev_pt.y<<" "<<cur_pt.x<<","<<cur_pt.y<<endl;
    177             rectangle(tmp,prev_pt,cur_pt,CV_RGB(0,255,0));
    178             imshow(g_mousep->win_name,tmp);
    179         }
    180     }
    181 }

    复制代码

    代码分析:

    on_mouse()回调函数,对应于一个显示窗口。

    在回调函数处理鼠标事件,要理解一个鼠标点击过程,会产生多个事件。

    例如:鼠标左击,对应着CV_EVENT_LBUTTONDOWN和CV_EVENT_LBUTTONUP。 

    在选择矩形框区域时,CV_EVENT_LBUTTONDOWN记录一个对角点;CV_EVENT_MOUSEMOVE记录选对矩形框的中间过程,并显示出来,便于用户调整选择的区域;CV_EVENT_LBUTTONUP记录另一个对角点,CV_EVENT_LBUTTONUP响应后,完成一个矩形框的选择。

    在选择点时,只需记录CV_EVENT_LBUTTONUP事件响应的坐标。

  • 相关阅读:
    Spring Boot 7:配置文件信息读取
    Spring Boot 6:自定义filter
    Spring AOP:Java动态代理和CGlib
    Spring AOP:概念
    设计模式(二)---策略模式
    设计模式(一)--装饰模式
    java并发编程实战笔记
    剑指offer java -查找旋转数组的最小数字
    读书计划
    协议初学
  • 原文地址:https://www.cnblogs.com/xmphoenix/p/4508439.html
Copyright © 2020-2023  润新知