CV编程常用的获取鼠标圈定区域的方法

2024-02-24 09:20

本文主要是介绍CV编程常用的获取鼠标圈定区域的方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  在CV里面,很多时候需要自己手动截出一块区域,然后针对这块区域进行处理,OpenCV并没有提供直接可调用的函数,如果每次都要自己写的话,估计写获取鼠标圈定区域就需要花很有一段时间~

  近来是在做视频跟踪这一块,有的跟踪是基于检测的跟踪,则不需要手动圈定,但很多时候,为了能直接看到跟踪的效果,则采取手动圈定的方式,如下图所示:

  我在看粒子滤波源码的时候发现了其鼠标圈定函数写的已经比较好调用,后来再看到meanshift跟踪,发现所用获取鼠标圈定函数一样的,所以我将其收集下来,以备后用,唔,接下来就是贴代码,这上面有部分我自己的代码……

  若能看懂其鼠标圈定函数,则对自己以后写此函数很有裨益,注释就不写那么多了,整体也比较容易吧:

  1 #include <cv.h>
  2 #include <highgui.h>
  3 
//-------------- 控制获取区域个数 4 const int MAX_OBJECTS = 1; 5
  //-------- 对参数封装 cvSetMouseCallback 所需参数
  6 typedef struct params {
  7   CvPoint loc1[MAX_OBJECTS];
  8   CvPoint loc2[MAX_OBJECTS];
  9   IplImage* objects[MAX_OBJECTS];
 10   char* win_name;
 11   IplImage* orig_img;
 12   IplImage* cur_img;
 13   int n;
 14 } params;
 15 
 16 int GetRegions( IplImage*, CvRect** );
 17 void mouse( int, int, int, int, void* );
 18 
 19 int main(void)
 20 {
 21     IplImage *frame, *frame_copy;
 22     CvCapture *video;
 23     CvScalar color;
 24     CvRect* regions;
 25 
 26     char *video_file = "E:\\Coding\\acivs\\1.AVI";
 27 
 28     video = cvCaptureFromFile( video_file );
 29     if(!video)
 30     {
 31         printf("Cannot open the video file!!!");
 32         return -1;
 33     }
 34 
 35     int frmNo = 0, nObjects = 0;
 36     while( frame = cvQueryFrame( video ) )
 37     {
 38         frame_copy = cvCloneImage( frame );
 39         if(frmNo == 0)
 40         {
 41             printf("Please select a region to track !");
 42             while( nObjects == 0 )
 43             {
 44                 nObjects = GetRegions( frame, &regions );
 45                 if( nObjects == 0 )
 46                     printf( "Please select a object\n" );
 47             }
 48         }
 49         else
 50         {
 51             printf("This is the %d st frame\n", frmNo);
 52 
 53         }
 54         frmNo++;
 55         cvReleaseImage(&frame_copy);
 56     }
 57 
 58     cvReleaseCapture( &video );
 59     return 0;
 60 }
 61 //-------- 获取的区域 regions
 62 int GetRegions( IplImage* frame, CvRect** regions )
 63 {
 64   char* win_name = "First frame";
 65   params p;
 66   CvRect* r;
 67   int i, x1, y1, x2, y2, w, h;
 68   
 69   /* use mouse callback to allow user to define object regions */
 70   p.win_name = win_name;
 71   p.orig_img = cvCloneImage( frame );
 72   p.cur_img = NULL;
 73   p.n = 0;
 74   cvNamedWindow( win_name, 1 );
 75   cvShowImage( win_name, frame );
 76   cvSetMouseCallback( win_name, &mouse, &p );
 77   cvWaitKey( 0 );
 78   cvDestroyWindow( win_name );
 79   cvReleaseImage( &(p.orig_img) );
 80   if( p.cur_img )
 81     cvReleaseImage( &(p.cur_img) );
 82 
 83   /* extract regions defined by user; store as an array of rectangles */
 84   if( p.n == 0 )
 85     {
 86       *regions = NULL;
 87       return 0;
 88     }
 89   r = (CvRect *)malloc( p.n * sizeof( CvRect ) );
 90   for( i = 0; i < p.n; i++ )
 91     {
 92       x1 = MIN( p.loc1[i].x, p.loc2[i].x );
 93       x2 = MAX( p.loc1[i].x, p.loc2[i].x );
 94       y1 = MIN( p.loc1[i].y, p.loc2[i].y );
 95       y2 = MAX( p.loc1[i].y, p.loc2[i].y );
 96       w = x2 - x1;
 97       h = y2 - y1;
 98 
 99       /* ensure odd width and height */
100       w = ( w % 2 )? w : w+1;
101       h = ( h % 2 )? h : h+1;
102       r[i] = cvRect( x1, y1, w, h );
103     }
104   *regions = r;
105   return p.n;
106 }
107 
108 void mouse( int event, int x, int y, int flags, void* param )
109 {
110   params* p = (params*)param;
111   CvPoint* loc;
112   int n;
113   IplImage* tmp;
114   static int pressed = FALSE;
115   
116   /* on left button press, remember first corner of rectangle around object */
117   if( event == CV_EVENT_LBUTTONDOWN )
118     {
119       n = p->n;
120       if( n == MAX_OBJECTS )
121     return;
122       loc = p->loc1;
123       loc[n].x = x;
124       loc[n].y = y;
125       pressed = TRUE;
126     }
127 
128   /* on left button up, finalize the rectangle and draw it in black */
129   else if( event == CV_EVENT_LBUTTONUP )
130     {
131       n = p->n;
132       if( n == MAX_OBJECTS )
133     return;
134       loc = p->loc2;
135       loc[n].x = x;
136       loc[n].y = y;
137       cvReleaseImage( &(p->cur_img) );
138       p->cur_img = NULL;
139       cvRectangle( p->orig_img, p->loc1[n], loc[n], CV_RGB(0,0,0), 1, 8, 0 );
140       cvShowImage( p->win_name, p->orig_img );
141       pressed = FALSE;
142       p->n++;
143     }
144 
145   /* on mouse move with left button down, draw rectangle as defined in white */
146   else if( event == CV_EVENT_MOUSEMOVE  &&  flags & CV_EVENT_FLAG_LBUTTON )
147     {
148       n = p->n;
149       if( n == MAX_OBJECTS )
150     return;
151       tmp = cvCloneImage( p->orig_img );
152       loc = p->loc1;
153       cvRectangle( tmp, loc[n], cvPoint(x, y), CV_RGB(255,255,255), 1, 8, 0 );
154       cvShowImage( p->win_name, tmp );
155       if( p->cur_img )
156     cvReleaseImage( &(p->cur_img) );
157       p->cur_img = tmp;
158     }
159 }

转载于:https://www.cnblogs.com/moondark/archive/2012/07/08/2582013.html

这篇关于CV编程常用的获取鼠标圈定区域的方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/741649

相关文章

检查 Nginx 是否启动的几种方法

《检查Nginx是否启动的几种方法》本文主要介绍了检查Nginx是否启动的几种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录1. 使用 systemctl 命令(推荐)2. 使用 service 命令3. 检查进程是否存在4

Java方法重载与重写之同名方法的双面魔法(最新整理)

《Java方法重载与重写之同名方法的双面魔法(最新整理)》文章介绍了Java中的方法重载Overloading和方法重写Overriding的区别联系,方法重载是指在同一个类中,允许存在多个方法名相同... 目录Java方法重载与重写:同名方法的双面魔法方法重载(Overloading):同门师兄弟的不同绝

MySQL字符串转数值的方法全解析

《MySQL字符串转数值的方法全解析》在MySQL开发中,字符串与数值的转换是高频操作,本文从隐式转换原理、显式转换方法、典型场景案例、风险防控四个维度系统梳理,助您精准掌握这一核心技能,需要的朋友可... 目录一、隐式转换:自动但需警惕的&ld编程quo;双刃剑”二、显式转换:三大核心方法详解三、典型场景

MySQL快速复制一张表的四种核心方法(包括表结构和数据)

《MySQL快速复制一张表的四种核心方法(包括表结构和数据)》本文详细介绍了四种复制MySQL表(结构+数据)的方法,并对每种方法进行了对比分析,适用于不同场景和数据量的复制需求,特别是针对超大表(1... 目录一、mysql 复制表(结构+数据)的 4 种核心方法(面试结构化回答)方法 1:CREATE

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

springboot的controller中如何获取applicatim.yml的配置值

《springboot的controller中如何获取applicatim.yml的配置值》本文介绍了在SpringBoot的Controller中获取application.yml配置值的四种方式,... 目录1. 使用@Value注解(最常用)application.yml 配置Controller 中

springboot中配置logback-spring.xml的方法

《springboot中配置logback-spring.xml的方法》文章介绍了如何在SpringBoot项目中配置logback-spring.xml文件来进行日志管理,包括如何定义日志输出方式、... 目录一、在src/main/resources目录下,也就是在classpath路径下创建logba

SQL Server中行转列方法详细讲解

《SQLServer中行转列方法详细讲解》SQL行转列、列转行可以帮助我们更方便地处理数据,生成需要的报表和结果集,:本文主要介绍SQLServer中行转列方法的相关资料,需要的朋友可以参考下... 目录前言一、为什么需要行转列二、行转列的基本概念三、使用PIVOT运算符进行行转列1.创建示例数据表并插入数

MyBatis配置文件中最常用的设置

《MyBatis配置文件中最常用的设置》文章主要介绍了MyBatis配置的优化方法,包括引用外部的properties配置文件、配置外置以实现环境解耦、配置文件中最常用的6个核心设置以及三种常用的Ma... 目录MyBATis配置优化mybatis的配置中引用外部的propertis配置文件⚠️ 注意事项X

C++打印 vector的几种方法小结

《C++打印vector的几种方法小结》本文介绍了C++中遍历vector的几种方法,包括使用迭代器、auto关键字、typedef、计数器以及C++11引入的范围基础循环,具有一定的参考价值,感兴... 目录1. 使用迭代器2. 使用 auto (C++11) / typedef / type alias