学习OpenCV——初始化视频第一帧

在很多视频跟踪或分割中,总是需要初始化第一帧,即在第一帧上画一个框,或者标注前景与背景啊等等,今天就把初始化第一帧,在第一帧上画一个框的代码实现了一下,顺便复习一下OpenCV里面的鼠标召回事件,在此贴上代码,与大家分享,也方便以后查找。

#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <string>
#include <iostream>
#include <stdio.h>

using namespace cv;
using namespace std;

//最多对一个对象进行跟踪;
#define MAX_OBJECTS 1

//传递参数的class
class params
{
public:
 	
	Point loc1,loc2;
	string win_name;
	Mat src;
	Mat cur;
	int n;					//记录对象个数
	params() : n(0) {}
	// 	~params();
};

//鼠标事件
void mouseEvent(int event, int x, int y, int flags, void* param)  
{
	static bool check_line_state = FALSE;
	Mat tmp;
	params* p = (params*)param;
	//按下鼠标左键,存储初始位置;
	if( event == CV_EVENT_LBUTTONDOWN )
	{
		 if (p->n == MAX_OBJECTS)//判断是否已经有了跟踪对象;
		{
			cout<<"Fail! \n Only Can Tracking One Object!"<<endl;
			return ;
		}
		p->loc1.x = x;
		p->loc1.y = y;
		check_line_state = TRUE;
	}

	//按下鼠标左键且鼠标移动,画矩形框;
	else if (check_line_state && event == CV_EVENT_MOUSEMOVE)
	{
		if (p->n == MAX_OBJECTS)//判断是否已经有了跟踪对象;
		{
			cout<<"Fail! \n Only Can Tracking One Object!"<<endl;
			return ;
		}
		p->src.copyTo(tmp);
		rectangle(tmp, p->loc1, Point(x,y), CV_RGB(255,0,0), 2, 8 );
		imshow(p->win_name,tmp);
	}

	//左键弹起,画框结束;
	else if(event == CV_EVENT_LBUTTONUP)
	{
		if (p->n == MAX_OBJECTS)//判断是否已经有了跟踪对象;
		{
			cout<<"Fail! \n Only Can Tracking One Object!"<<endl;
			return ;
		}
		p->loc2.x = x;
		p->loc2.y = y;
		rectangle(p->src, p->loc1, Point(x,y), CV_RGB(255,0,0), 2, 8 );
		imshow(p->win_name,p->src);
		p->n++;
		check_line_state = FALSE;
	}
}

//初始化第一帧,画出要跟踪的对象
void InitialVideo(Mat& src, Rect& rect)
{
	params p;
	src.copyTo(p.src);
	p.win_name = "Initial Window";
	imshow(p.win_name, src);
	
	//鼠标召回事件
	setMouseCallback(p.win_name, &mouseEvent, &p); 
	cout<<"draw rect & press any key to end"<<endl;
	
	waitKey();

	//把得到的位置赋给rect
	rect.x = min(p.loc1.x, p.loc2.x);
	rect.y = min(p.loc1.y, p.loc2.y);
	rect.width = abs(p.loc1.x - p.loc2.x);
	rect.height = abs(p.loc1.y - p.loc2.y);

	destroyWindow("Initial Window");
}

int main()
{
	//从默认摄像头输入
	VideoCapture cap(0);
	//从视频输入
	//string filename = "D:/soccer.avi";
	//VideoCapture cap(filename); 

	if(!cap.isOpened())  // check if we succeeded
	{
		cout<<"couldn't open video file"<<endl;
		return -1;
	}

	Mat frame;
	bool isFirstFrame = TRUE;
	Rect rect;
        cap>>frame;//可能是因为电脑问题,导致第一帧显示不出来,所以就把第一帧先读一次
	for (;;)
	{
		cap>>frame;
		//初始化第一帧
		if ( isFirstFrame)
		{
			InitialVideo(frame,rect);
			 isFirstFrame = FALSE;
		}
		//其他操作
		rectangle(frame, rect, CV_RGB(255,0,0), 2, 8 );
		imshow("showSrc",frame);
		char key = (char)waitKey(5);
		switch (key)
		{
		case 27:
			return 0;
		case  ' ' :
			cout<<"save process"<<endl;
			break;
		default:
			break;
		}
	}
}


 

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
**大津法 (Otsu's Method) 是一种自动阈值分割技术,广泛应用于图像处理领域,特别是为了从灰度图或彩色图中提取出轮廓、背景等元素时需要进行的预处理步骤——即二值化操作。** ### **原理简述** 大津法的核心思想是寻找一个最佳阈值使得分割后的两部分图像内的像素分布差异最大。这个最优阈值通过计算两个类别的方差来确定。两个类别分别是图像中低于阈值的部分和高于阈值的部分。 #### 算法步骤 1. **统计直方图**: 计算输入图像灰度级的频率分布。 2. **寻找阈值**: 对于所有可能的阈值点,分别计算左右两边像素所占的比例及其相应的均值。然后基于这两个部分的方差计算目标函数的最大值。目标函数通常定义为两部分概率加权的平均方差。 3. **选择阈值**: 找到使得目标函数达到最大值的那个阈值作为最终的分割阈值。 ### **Python 实现** 在 OpenCV 中,可以轻松地应用大津法进行二值化。以下是一个简单的 Python 示例: ```python import cv2 import numpy as np # 加载灰度图像 image = cv2.imread('path_to_image.jpg', cv2.IMREAD_GRAYSCALE) # 应用 Otsu 的二值化算法 threshold_value, binary_image = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) print("Threshold Value:", threshold_value) cv2.imshow('Binary Image - Otsu Method', binary_image) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在这个例子中: - `cv2.imread` 用于加载图像,并将其转换成灰度模式。 - `cv2.threshold` 函数应用了 Otsu 的二值化算法。第一个参数是输入的灰度图像,第二个参数是初始阈值(这里设置为 0,由算法自动确定),第三个参数是结果图像的最大值(这里是 255)。第四个参数指定阈值类型,其中 `cv2.THRESH_BINARY` 表示将小于阈值的像素设为 0,大于等于阈值的像素设为 255;`cv2.THRESH_OTSU` 则是使用 Otsu 的方法自动选取阈值。 - 最终输出的是经过二值化处理的结果图像以及使用的最优阈值。 ### **相关问题** 1. **如何调整 Otsu 方法得到更好的效果?** 是否存在其他优化技巧或是参数调整策略? 2. **当图像包含多种光照条件或复杂背景时,如何改进大津法的性能?** 这些情况下的常见解决方案是什么? 3. **是否能讨论一些替代的大津法,如全局阈值法、局部阈值法或其他先进的自动阈值分割算法?** 每种方法的优缺点是什么? 通过理解并掌握大津法的应用,您将在图像处理任务中获得更强的灵活性和精确性。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值