OpenCV提取前景

opencv提取前景

#include <SDKDDKVer.h>
#include <stdio.h>
#include <tchar.h>
#include<opencv2\highgui.hpp>
#include<opencv2\imgproc.hpp>
#include<iostream>

//用Canny算子计算输入图像的边缘
void canny(cv::Mat& img, cv::Mat& out) {
	//如是彩色图像,则转换成灰度图像
	if (img.channels() == 3)
	{
		cv::cvtColor(img, out, cv::COLOR_BGR2GRAY);
		//计算Canny边缘
		cv::Canny(out, out, 100, 200);
	}
	else
	{
		cv::Canny(img, out, 100, 200);
	}
	cv::threshold(out, out, 128, 255, cv::THRESH_BINARY_INV);
}

//处理帧的接口
class FrameProcessor {
public:
	//处理方法
	virtual void process(cv::Mat& input, cv::Mat& output) = 0; //纯虚函数
};

class VideoProcessor {
private:
	//OpenCV视频捕获类对象
	cv::VideoCapture capture;
	//处理每一帧时都会调用的函数指针
	void(*process)(cv::Mat&, cv::Mat&);
	//布尔型变量,表示该处理函数是否会被调用
	bool callIt;
	//输入窗口的显示名称
	std::string windowNameInput;
	//输出窗口的显示名称
	std::string windowNameOutput;
	//帧之间的延时
	int delay;
	//已经处理的帧数
	long fnumber;
	//达到这个帧数时结束
	long frameToStop;
	//结束处理标志
	bool stop;

	FrameProcessor* frameProcessor;//帧处理器对象指针

public:
	//构造函数,设置默认值
	VideoProcessor() : callIt(false), delay(-1), fnumber(0), stop(false), frameToStop(-1), process(NULL), frameProcessor(NULL) {}

	//设置视频文件的名称并打开
	bool setInput(std::string filename) {
		fnumber = 0;
		//防止已经有资源与VideoCapture实例关联
		capture.release();
		//打开视频文件
		return capture.open(filename);
	}

	//打开摄像设备
	bool setInput(int device) {
		fnumber = 0;
		//防止已经有资源与VideoCapture实例关联
		capture.release();
		//打开视频捕捉设备
		return capture.open(device);
	}

	//创建用于显示输入帧的窗口
	void displayInput(std::string wn) {
		windowNameInput = wn;
		cv::namedWindow(windowNameInput);
	}

	//创建用于显示输出帧的窗口
	void displayOutput(std::string wn) {
		windowNameOutput = wn;
		cv::namedWindow(windowNameOutput);
	}

	//设置帧之间的延时(单位为毫秒)
	//0表示每一帧都等待
	//负数表示不延时
	void setDelay(int d) {
		delay = d;
	}

	//设置为需要调用回调函数process
	void callProcess() {
		callIt = true;
	}

	//设置为不需要调用回调函数
	void dontCallProcess() {
		callIt = false;
	}

	//设置针对每一帧调用的处理函数
	void setFrameProcessor(void(*frameProcessingCallback)(cv::Mat&, cv::Mat&)) {
		process = frameProcessingCallback;
		frameProcessor = NULL;	//使帧处理器失效
		callProcess();
	}

	//设置在处理完指定数量的帧后结束
	void stopAtFrameNo(long frameNo) {
		frameToStop = frameNo;
	}

	//结束处理
	void stopIt() {
		stop = true;
	}

	//处理过程是否已经停止?
	bool isStopped() {
		return stop;
	}

	//捕获设备是否已经打开?
	bool isOpened() {
		return capture.isOpened();
	}

	//返回下一帧的编号
	long getFrameNumber() {
		//从捕获设备获取信息
		long fnumber = static_cast<long>(capture.get(CV_CAP_PROP_POS_FRAMES));
		return fnumber;
	}

	//获取视频的帧速率
	double getFrameRate() {
		if (isOpened())
		{
			double rate = capture.get(CV_CAP_PROP_FPS);
			if (!rate)
			{
				//std::cout<<"视频源已打开,但帧率无法获取!"<<std::endl;
				std::cout << "视频源已打开,但帧率无法获取" << std::endl;
			}
			return rate;
		}
		else
		{
			return 0;
		}
	}

	//取得下一帧
	bool readNextFrame(cv::Mat& frame) {
		return capture.read(frame);
	}

	//抓取并处理序列中的帧
	void run() {
		cv::Mat frame;//用于储存当前帧
		cv::Mat output;//用于存储输出帧

		//如果没有打开视频文件或捕获设备
		if (!isOpened())
			return;

		stop = false;

		while (!isStopped()) {
			//读取下一帧(如果有)
			if (!readNextFrame(frame))
				break;

			//显示输入的帧
			if (windowNameInput.length() != 0)
				cv::imshow(windowNameInput, frame);

			//调用处理函数
			if (callIt) {
				//处理帧
				if (process)		//如果用的是处理函数
					process(frame, output);
				else if (frameProcessor)		//如果用的是帧处理类的接口
					frameProcessor->process(frame, output);
				else	//如果没有设置处理函数
					output = frame;		//输出帧直接等于输入帧
			}
			else {	//没有处理
				output = frame;		//输出帧直接等于输入帧
			}
			fnumber++;//递增帧数

			//显示输出的帧
			if (windowNameOutput.length() != 0)
				cv::imshow(windowNameOutput, output);

			//逐帧查看,按Esc键退出
			if (delay == 0 && 27 == cv::waitKey(0))
				stopIt();
			//等待指定毫秒数,按键则直接退出
			else if (delay > 0 && cv::waitKey(delay) >= 0)
				stopIt();

			//检查是否需要结束
			if (frameToStop >= 0 && fnumber == frameToStop)
				stopIt();
		}
	}

	//设置实现FrameProcessor接口的实例
	void setFrameProcessor(FrameProcessor* frameProcessorPtr) {
		//使处理函数失效
		process = NULL;
		//这个就是即将被调用的帧处理器接口
		frameProcessor = frameProcessorPtr;
		callProcess();
	}
};

class BGFGSegmentor : public FrameProcessor {
private:
	cv::Mat gray;		// 当前灰度图像
	cv::Mat background;	// 累积的背景
	cv::Mat backImage;	// 当前背景图像
	cv::Mat foreground;	// 前景图像
	// 累计背景时使用的学习速率
	double learningRate;
	int threshold;		// 提取前景的阈值
public:
	BGFGSegmentor() : threshold(10), learningRate(0.01) {}
	// 处理方法
	void process(cv::Mat& frame, cv::Mat& output) {
		// 转换成灰度图像
		cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
		// 采用第一帧初始化背景
		if (background.empty())
			gray.convertTo(background, CV_32F);
		// 背景转换成8U类型
		background.convertTo(backImage, CV_8U);
		// 计算图像与背景之间的差异
		cv::absdiff(backImage, gray, foreground);
		// 在前景图像上应用阈值
		cv::threshold(foreground, output, threshold, 255,
			cv::THRESH_BINARY_INV);
		// 累积背景
		// background(x,y) = learningRate * gray(x,y) + (1-			
		// learningRate)*background(x,y), if(output(x,y)≠0)
		cv::accumulateWeighted(gray, background,
			learningRate,	// 学习速率
			output);		// 掩码
	}
	// 设置前景阈值
	void setThreshold(int t) {
		threshold = t;
	}
};
int main()
{
	
	//滑动平均值法提取视频前景
	// 创建视频处理类的实例
	VideoProcessor processor;
	// 创建背景/前景的分割器
	BGFGSegmentor segmentor;
	segmentor.setThreshold(25
	);// 打开视频文件
	
	processor.setInput("bike.avi"
	);// 设置帧处理对象
	processor.setFrameProcessor(
		&segmentor);
	// 声明显示视频的窗口
	processor.displayInput("原始视频");

	processor.displayOutput("提取的前景\n"
	);// 用原始帧速率播放视频
	processor.setDelay(1000. / processor.getFrameRate());
	// 开始处理
	processor.run();

	return 0;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值