#include<iostream>
#include <opencv2/opencv.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include <iomanip>
using namespace std;
using namespace cv;
//帧处理基类
class FrameProcessor{
public:
virtual void process(Mat &input, Mat &ouput) = 0;
};
class VideoProcessor{
private:
//Opencv视频捕捉对象
VideoCapture capture;
//每帧调用的回调函数
void(*process)(Mat&, Mat&);
//确定是否调用回调函数的bool变量
bool callIt;
//输入窗口的名称
string windowNameInput;
string windowNameOutput;
//延迟
int delay;
//已处理的帧数
long fnumber;
//在该帧数停止
long frameToStop;
//是否停止处理
bool stop;
//opencv的写视频对象
VideoWriter writer;
//输出文件名称
string outputFile;
//输出图像的当前索引
int currentIndex;
//输出图像名称中的数字位数
int digits;
//输出图像的扩展名
string extension;
FrameProcessor *frameprocessor;
//图像序列作为输入视频流
vector<string> images;
public:
VideoProcessor() :callIt(true), delay(0), fnumber(0), stop(false), frameToStop(-1){}
//设置回调函数
void setFrameProcessor(
void(*frameProcessingCallback)(Mat&, Mat&)){
process = frameProcessingCallback;
}
//设置视频文件的名称
bool setInput(string filename){
fnumber = 0;
//释放之前打开过的资源
capture.release();
//打开视频文件
return capture.open(filename);
}
//创建输入窗口
void displayInput(string wn){
windowNameInput = wn;
namedWindow(windowNameInput);
}
//创建输出窗口
void displayOutput(string wn){
windowNameOutput = wn;
namedWindow(windowNameOutput);
}
//不再显示处理后的帧
void dontDisplay(){
destroyWindow(windowNameInput);
destroyWindow(windowNameOutput);
windowNameInput.clear();
windowNameOutput.clear();
}
//获取并处理序列帧
void run(){
//当前帧
Mat frame;
//输出帧
Mat output;
//打开失败时
if (!isOpened())return;
stop = false;
while (!isStopped())
{
//读取下一帧
if (!readNextFrame(frame))break;
//显示输出帧
if (windowNameInput.length() != 0)
imshow(windowNameInput, frame);
//调用处理函数
if (callIt){
//处理当前帧
if (process)
process(frame, output);
else if (frameprocessor)
frameprocessor->process(frame, output);
//增加帧数
fnumber++;
}
else
{
output = frame;
}
//输出图像序列
if (outputFile.length() != 0)
writeNextFrame(output);
//显示输出帧
if (windowNameOutput.length() != 0)
imshow(windowNameOutput, output);
//引入延迟
if (delay >= 0 && waitKey(delay) >= 0)
stopIt();
//检查是否需要停止运行
if (frameToStop >= 0 && getFrameNumber() == frameToStop)
stopIt();
}
}
//停止运行
void stopIt(){
stop = true;
}
//是否已停止
bool isStopped(){
return stop;
}
//是否开始了捕获设备
bool isOpened(){
return capture.isOpened();
}
//设置帧间的延迟 0意味着在每帧都等待用户按键 负数意味着没有延迟
void setDelay(int d){
delay = d;
}
//得到下一帧 可能是视频文件或摄像头
bool readNextFrame(Mat &frame){
return capture.read(frame);
}
//需要调用回调函数
void callProcess(){
callIt = true;
}
//不需要调用回调函数
void dontCallProcess(){
callIt = false;
}
void stopAtFrameNo(long frame){
frameToStop = frame;
}
//返回下一帧的帧数
long getFrameNumber(){
//得到捕获设备的信息
long fnumber = static_cast<long>(capture.get(CV_CAP_PROP_POS_FRAMES));
return fnumber;
}
int getFrameRate(){
return capture.get(CV_CAP_PROP_FPS);
}
//获得编码类型
int getCodec(char codec[4]) {
if (images.size() != 0)
return -1;
union { // 数据结构4-char
int value;
char code[4];
} returned;
//获得编码值
returned.value = static_cast<int>(
capture.get(CV_CAP_PROP_FOURCC));
// get the 4 characters
codec[0] = returned.code[0];
codec[1] = returned.code[1];
codec[2] = returned.code[2];
codec[3] = returned.code[3];
return returned.value;
}
//获得帧大小
Size getFrameSize() {
if (images.size() == 0) {
// 从视频流获得帧大小
int w = static_cast<int>(capture.get(CV_CAP_PROP_FRAME_WIDTH));
int h = static_cast<int>(capture.get(CV_CAP_PROP_FRAME_HEIGHT));
return Size(w, h);
}
else {
//从图像获得帧大小
cv::Mat tmp = cv::imread(images[0]);
return (tmp.data) ? (tmp.size()) : (Size(0, 0));
}
}
//设置输出视频文件
//默认使用于输入视频相同的参数
bool setOutput(const string &filename, int codec = 0, double framerate = 0.0, bool isColor = true){
outputFile = filename;
extension.clear();
if (framerate == 0.0)
framerate = getFrameRate();//与输入相同
char c[4];
//使用相同的编码格式
if (codec == 0)
{
codec = getCodec(c);
}
//打开输出视频
return writer.open(outputFile, //文件名
codec, //将使用的编码格式
framerate, //帧率
getFrameSize(), //尺寸
isColor); //是否是彩色视频?
}
//输出帧 可能是视频文件或图像文件
void writeNextFrame(Mat &frame){
if (extension.length())//我们输出到图像文件
{
stringstream ss;
//组成输出文件名称
ss << outputFile << setfill('0')
<< setw(digits)
<< currentIndex++ << extension;
imwrite(ss.str(), frame);
}
else
{//我们输出到视频文件
writer.write(frame);
}
}
//设置输出为独立的图像文件 扩展名必须是".jpg" ".bmp"
bool setOutput(const string &filename,//前缀
const string&ext,//后缀
int numberofDigits = 3,//数字位数
int startIndex = 0){ //开始索引
//数字位数必须是正的
if (numberofDigits < 0)return false;
//文件名及其后缀
outputFile = filename;
extension = ext;
//文件名中的数字位数
digits = numberofDigits;
//开始索引
currentIndex = startIndex;
return true;
}
void setFrameProcessor(FrameProcessor *frameprocessor){
process = 0;
this->frameprocessor = frameprocessor;
callProcess();
}
};
class FeatureTracker :public FrameProcessor{
Mat gray; //当前灰度图像
Mat gray_prev; //之前灰度图像
//两幅图像间跟踪的特征点 0->1
vector<Point2f>points[2];
//跟踪的点初始位置
vector<Point2f> initial;
vector<Point2f>features; //检测到的特征
int max_count; //需要跟踪的最大特征数目
double qlevel; //特征检测中的质量等级
double minDist; //两点之间的最小距离
vector<uchar> status; //检测到的特征的状态
vector<float>err; //跟踪过程中的错误
public:
FeatureTracker() :max_count(500), qlevel(0.01), minDist(10.){};
void process(Mat&frame, Mat&output){
//转换为灰度图像
cvtColor(frame, gray, CV_BGR2GRAY);
frame.copyTo(output);
//1.如果需要添加新的特征点
if (addNewPoints()){
//进行检测
detectFeaturePoints();
//添加检测到的特征到当前跟踪的特征中
points[0].insert(points[0].end(), features.begin(), features.end());
initial.insert(initial.end(), features.begin(), features.end());
}
//对于序列中的第一幅图像
if (gray_prev.empty()){
gray.copyTo(gray_prev);
}
//2.跟踪特征点
calcOpticalFlowPyrLK(
gray_prev, gray, //两幅连续图
points[0], //图1中的输入点坐标
points[1], //图2中的输出点坐标
status, //跟踪成功
err //跟踪错误
);
//3.遍历所有跟踪的点进行筛选
int k = 0;
for (int i = 0; i < points[1].size(); i++)
{
//是否需要保留该点
if (acceptTrackedPoint(i)){
//进行保留
initial[k] = initial[i];
points[1][k++] = points[1][i];
}
}
//去除不成功的点
points[1].resize(k);
initial.resize(k);
//4.处理接受的跟踪点
handleTrackedPoints(frame, output);
//5.当前帧的点和图像变为前一帧的点和图像
swap(points[1], points[0]);
swap(gray_prev, gray);
}
//检测特征点
void detectFeaturePoints(){
//检测特征
goodF
没有合适的资源?快使用搜索试试~ 我知道了~
【OpenCV学习笔记 013】处理视频序列
共14个文件
cpp:5个
log:2个
mov:2个
需积分: 13 20 下载量 133 浏览量
2016-10-01
23:02:53
上传
评论
收藏 4.92MB RAR 举报
温馨提示
爱分享、爱极客的编程怪兽--DaveBobo 博文 《【OpenCV学习笔记 013】处理视频序列》 博文链接: http://blog.csdn.net/davebobo/article/details/52677657 OpenCV版本:2.4.9
资源推荐
资源详情
资源评论
收起资源包目录
【OpenCV学习笔记 013】处理视频序列.rar (14个子文件)
【OpenCV学习笔记 013】处理视频序列
【OpenCV学习笔记 013】处理视频序列.sln 1KB
【OpenCV学习笔记 013】处理视频序列.sdf 13MB
【OpenCV学习笔记 013】处理视频序列.v12.suo 23KB
Debug
【OpenCV学习笔记 013】处理视频序列
walkMan.mov 661KB
【OpenCV学习笔记 013】处理视频序列.vcxproj.filters 1KB
【OpenCV学习笔记 013】处理视频序列.vcxproj 5KB
10.3处理视频帧.cpp 4KB
10.2读取视频序列.cpp 839B
10.6提取视频中的前景物休.cpp 7KB
10.4写入视频序列.cpp 6KB
屌丝男士.mov 1.73MB
Debug
【OpenCV学习笔记 013】处理视频序列.log 95B
【OpenCV学习笔记 013】处理视频序列.Build.CppClean.log 3KB
【OpenCV学.48509C68.tlog
10.5跟踪视频中的特征点.cpp 9KB
共 14 条
- 1
资源评论
DaveBobo
- 粉丝: 743
- 资源: 52
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功