zoukankan      html  css  js  c++  java
  • Opencv在视频中静态、动态方式绘制矩形框ROI

    Opencv视频处理中的目标跟踪经常用到要在视频上画一个矩形框ROI,标注出要跟踪的物体,这里介绍两种在视频中绘制矩形框的方法,一种是“静态的”,一种是“动态的”。

    静态的是指在绘制过程中,视频暂停播放,画面定格在鼠标左键单击上去时候播放的画面,这时候按着鼠标左键并拖动出一个感兴趣的区域,鼠标左键抬起完成矩形框的绘制。在整个绘制过程中,矩形是连续显示出来的,跟随鼠标位置变化而变化。

    过程和实现都很简单,以下是具体代码实现,主要用到了鼠标响应事件:


    #include "core/core.hpp"  
    #include "highgui/highgui.hpp"  
    #include "imgproc/imgproc.hpp"  
    #include<iostream>  
    
    using namespace cv;  
    using namespace std;  
    
    Mat image;
    Mat imageCopy; //绘制矩形框时用来拷贝原图的图像
    bool leftButtonDownFlag=false; //左键单击后视频暂停播放的标志位
    Point originalPoint; //矩形框起点
    Point processPoint; //矩形框终点
    
    void onMouse(int event,int x,int y,int flags ,void* ustc); //鼠标回调函数
    
    int main(int argc,char*argv[])  
    {  
    	VideoCapture video(argv[1]);
    	double fps=video.get(CV_CAP_PROP_FPS); //获取视频帧率
    	double pauseTime=1000/fps; //两幅画面中间间隔
    	namedWindow("Friends");
    	setMouseCallback("Friends",onMouse);
    	while(true)
    	{
    		if(!leftButtonDownFlag) //判定鼠标左键没有按下,采取播放视频,否则暂停
    		{
    			video>>image;
    		}
    		if(!image.data||waitKey(pauseTime)==27)  //图像为空或Esc键按下退出播放
    		{
    			break;
    		}
    		//两种情况下不在原始视频图像上刷新矩形
    		//1. 起点等于终点
    		//2. 左键按下且未抬起
    		if(originalPoint!=processPoint&&!leftButtonDownFlag)
    		{
    			rectangle(image,originalPoint,processPoint,Scalar(255,0,0),2);
    		}
    		imshow("Friends",image);		
    	}
    	return 0;
    }  
    
    //*******************************************************************//  
    //鼠标回调函数  
    void onMouse(int event,int x,int y,int flags,void *ustc)  
    {     
    
    	if(event==CV_EVENT_LBUTTONDOWN)  
    	{  
    		leftButtonDownFlag=true; //标志位
    		originalPoint=Point(x,y);  //设置左键按下点的矩形起点
    		processPoint=originalPoint;
    	}  
    	if(event==CV_EVENT_MOUSEMOVE&&leftButtonDownFlag)  
    	{  
    		imageCopy=image.clone();
    		processPoint=Point(x,y);
    		if(originalPoint!=processPoint)
    		{
    			//在复制的图像上绘制矩形
    			rectangle(imageCopy,originalPoint,processPoint,Scalar(255,0,0),2);
    		}
    		imshow("Friends",imageCopy);
    	}  
    	if(event==CV_EVENT_LBUTTONUP)  
    	{  
    		leftButtonDownFlag=false;
    		Mat rectImage=image(Rect(originalPoint,processPoint)); //子图像显示
    		imshow("Sub Image",rectImage);		 
    	}	 
    } 


    鼠标左键按下,此时视频画面暂停,拖动左键,绘制出需要的矩形:


    截取出来单独显示的子画面:



    对应的,动态的是说在绘制矩形框的过程中,视频还是在正常播放的,截取的子画面是鼠标抬起时当前视频帧的画面。动态绘制不需要在鼠标事件中处理矩形框的绘制,相比静态的还更为简单一点:


    #include "core/core.hpp"  
    #include "highgui/highgui.hpp"  
    #include "imgproc/imgproc.hpp"  
    #include<iostream>  
    
    using namespace cv;  
    using namespace std;  
    
    Mat image;
    Mat imageCopy; //绘制矩形框时用来拷贝原图的图像
    bool leftButtonDownFlag=false; //左键单击后视频暂停播放的标志位
    Point originalPoint; //矩形框起点
    Point processPoint; //矩形框终点
    
    void onMouse(int event,int x,int y,int flags ,void* ustc); //鼠标回调函数
    
    int main(int argc,char*argv[])  
    {  
    	VideoCapture video(argv[1]);
    	double fps=video.get(CV_CAP_PROP_FPS); //获取视频帧率
    	double pauseTime=1000/fps; //两幅画面中间间隔
    	namedWindow("Friends");
    	setMouseCallback("Friends",onMouse);
    	while(true)
    	{		
    		video>>image;		
    		if(!image.data||waitKey(pauseTime)==27)  //图像为空或Esc键按下退出播放
    		{
    			break;
    		}
    		//两种情况下不在原始视频图像上刷新矩形
    		//1. 起点等于终点
    		//2. 左键按下且未抬起
    		if(originalPoint!=processPoint)
    		{
    			rectangle(image,originalPoint,processPoint,Scalar(255,0,0),2);
    		}
    		imshow("Friends",image);		
    	}
    	return 0;
    }  
    
    //*******************************************************************//  
    //鼠标回调函数  
    void onMouse(int event,int x,int y,int flags,void *ustc)  
    {     
    
    	if(event==CV_EVENT_LBUTTONDOWN)  
    	{  
    		leftButtonDownFlag=true; //标志位
    		originalPoint=Point(x,y);  //设置左键按下点的矩形起点
    		processPoint=originalPoint;
    	}  
    	if(event==CV_EVENT_MOUSEMOVE&&leftButtonDownFlag)  
    	{  		
    		processPoint=Point(x,y);		
    	}  
    	if(event==CV_EVENT_LBUTTONUP)  
    	{  
    		leftButtonDownFlag=false;
    		Mat rectImage=image(Rect(originalPoint,processPoint)); //子图像显示
    		imshow("Sub Image",rectImage);		 
    	}	 
    }  


    鼠标左键按下,视频仍会继续播放,拖动鼠标,画出矩形框:



    截取出来单独显示的子画面:



  • 相关阅读:
    Maidsafe-去中心化互联网白皮书
    The Top 20 Cybersecurity Startups To Watch In 2021 Based On Crunchbase
    Top 10 Blockchain Security and Smart Contract Audit Companies
    The 20 Best Cybersecurity Startups To Watch In 2020
    Blockchain In Cybersecurity: 11 Startups To Watch In 2019
    004-STM32+BC26丨260Y基本控制篇(阿里云物联网平台)-在阿里云物联网平台上一型一密动态注册设备(Android)
    涂鸦开发-单片机+涂鸦模组开发+OTA
    000-ESP32学习开发-ESP32烧录板使用说明
    03-STM32+Air724UG远程升级篇OTA(阿里云物联网平台)-STM32+Air724UG使用阿里云物联网平台OTA远程更新STM32程序
    03-STM32+Air724UG远程升级篇OTA(自建物联网平台)-STM32+Air724UG实现利用http/https远程更新STM32程序(TCP指令,单片机程序检查更新)
  • 原文地址:https://www.cnblogs.com/mtcnn/p/9411966.html
Copyright © 2011-2022 走看看