【碎片知识(7)· 计算机视觉基础】基于光流估计的目标跟踪
2018-02-18 12:42
549 查看
1.1 问题需求及实现流程:
要求:使用光流法跟踪给定视频或摄像头中的运动特点。
检测流程:1)视频采集(取到视频中当前帧图像);2)图像预处理;3)提取特征点;4)使用光流法估计特征运动;5)相邻帧及特征点交换。
1.2 OpenCV实现:
OpenCV相关函数:
Ø void calcOpticalFlowPyrLK(InputArray prevImg, InputArray nextImg,InputArray prevPts, InputOutputArray nextPts, OutputArray status, OutputArray err, Size winSize = Size (21,21), int maxLevel = 3, TermCriteria criteria = TermCriteria (TermCriteria::COUNT +TermCriteria::EPS, 30, 0.01), int flags = 0, double minEigThreshold = 1e-4)
prevImg,第一帧图像。
nextImg,第二帧图像。
prevPts,第一帧图像中的所有特征向量。
nextPts,第二帧图像中的所有特征向量。
status,输出状态向量;如果相应点光流被发现,向量的每个单元被设置为1,否则,被置为0。
Ø void goodFeatureToTrack(InputArray _image, OutputArray _corners,int maxCorners, double qualityLevel,double minDistance, InputArray _mask,int blockSize, bool useHarrisDeterctor,double harrisK)
_image,8位或32位浮点型输入图像,单通道。
_corners,保存检测出的角点。
maxCorners,角点数目最大值,如果实际检测的角点超过此值,则只返回前maxCorners个强角点。
qualityLevel,角点的品质因子,决定角点可信度。
minDistance,此领域范围内如果存在更强角点,则删除此角点。
要求:使用光流法跟踪给定视频或摄像头中的运动特点。
检测流程:1)视频采集(取到视频中当前帧图像);2)图像预处理;3)提取特征点;4)使用光流法估计特征运动;5)相邻帧及特征点交换。
1.2 OpenCV实现:
OpenCV相关函数:
Ø void calcOpticalFlowPyrLK(InputArray prevImg, InputArray nextImg,InputArray prevPts, InputOutputArray nextPts, OutputArray status, OutputArray err, Size winSize = Size (21,21), int maxLevel = 3, TermCriteria criteria = TermCriteria (TermCriteria::COUNT +TermCriteria::EPS, 30, 0.01), int flags = 0, double minEigThreshold = 1e-4)
prevImg,第一帧图像。
nextImg,第二帧图像。
prevPts,第一帧图像中的所有特征向量。
nextPts,第二帧图像中的所有特征向量。
status,输出状态向量;如果相应点光流被发现,向量的每个单元被设置为1,否则,被置为0。
Ø void goodFeatureToTrack(InputArray _image, OutputArray _corners,int maxCorners, double qualityLevel,double minDistance, InputArray _mask,int blockSize, bool useHarrisDeterctor,double harrisK)
_image,8位或32位浮点型输入图像,单通道。
_corners,保存检测出的角点。
maxCorners,角点数目最大值,如果实际检测的角点超过此值,则只返回前maxCorners个强角点。
qualityLevel,角点的品质因子,决定角点可信度。
minDistance,此领域范围内如果存在更强角点,则删除此角点。
#include <opencv2/opencv.hpp> using namespace cv; using namespace std; const int MAX_POINT_COUNT = 500; // 全局变量限制单词循环中检测的特征点数量 bool needTolnit(); void main() { char *fn = "D:\\CommonSoftware\\OpenCV\\Workplace\\Example3_OpticalFlow\\vtest.avi"; VideoCapture cap; Mat source, result, gray, lastGray; // 原始图像、、上一帧灰度图像、本帧灰度图像 vector<Point2f> points[2]; // 定义一维向量数组points[2],分别存放上一帧和当前帧的特征点 // vector<Point2f> temp; vector<uchar> status; vector<float> err; cap.open(fn); // 打开视频 if (!cap.isOpened()) // 检测是否成功打开视频 { cout << "Cannot open the source, check camera or file." << endl; return; } for ( ; ; ) // 无条件循环 { cap >> source; // 将cap抓取的当前帧图像传递给原始图像 if (source.empty()) // 通过判断提取到的当前帧是否为空来判断是否到了视频结尾 { break; } cvtColor(source, gray, COLOR_BGR2GRAY); // 将当前帧原始图像转换为灰度图像 if (points[0].size() < 10) // 如果上一帧中的特征点数量小于10个认为不可信,则重新检测 { goodFeaturesToTrack(gray, points[0], MAX_POINT_COUNT, 0.01, 20); } // 从灰度图像gray中提取特征点放入points[0]中,角点品质因子为0.01,20的范围内仅保留最强角点 if (lastGray.empty()) { // 如果上一帧灰度图像为空,即视频开头,将当前帧灰度图像复制到上一帧灰度图像中 gray.copyTo(lastGray); } calcOpticalFlowPyrLK(lastGray, gray, points[0], points[1], status, err); // 从上一帧和当前帧灰度图像中的特征点计算光流,第i个特征点如光流发现则status[i]=1,否则为0 int counter = 0; for (int i = 0; i < points[1].size(); i++) // 当i小于当前帧特征点总数时,进行循环 { double dist = norm(points[1][i] - points[0][i]); // 计算当前帧第i个特征点与上一帧第i个特征点的距离 if (status[i] && dist >= 2.0 && dist <= 20.0) // 对所有得到的特征点光流进行一个筛选 { // 筛选依据是帧间光流被发现且帧间光流长度介于2到20之间 points[0][counter] = points[0][i]; points[1][counter++] = points[1][i]; } // 将points[0]和points[1]分别的前counter个元素用过滤合格的元素代替 } points[0].resize(counter); points[1].resize(counter); // 将前counter以后的元素去除 source.copyTo(result); // 将原始图像复制到result当中 for (int i = 0; i < points[1].size(); i++) // 当i小于滤除后当前帧中特征点总数 { line(result, points[0][i], points[1][i], Scalar(0, 0, 0xff)); // 在result图像中用红色线将当前帧和上一帧中分别的第i个特征点连起来 circle(result, points[1][i], 3, Scalar (0, 0xff, 0)); // 在result图像中将所有筛选出的特征点用半径为3的绿色圈标识出来 } swap(points[0], points[1]); swap(lastGray, gray); // 将当前帧和上一帧的特征点和图像数据交换,从而将当前帧放入上一帧中以进行后续循环 imshow("Source Image", source); imshow("Result Image", result); char key = waitKey(100); // 等待100好眠 if (key == 27) // Esc键退出 { break; } } } bool needTolnit() { return true; }
相关文章推荐
- 【碎片知识(6)· 计算机视觉基础】基于背景提取的目标跟踪算法
- 【碎片知识(1)· 计算机视觉基础】利用OpenCV实现图像的“Hello, world!”
- 【碎片知识(5)· 计算机视觉基础】自定义均值滤波器和OpenCV中blur平均滤波函数的对比
- [置顶] SLAM基础技术点之基于计算机视觉求解相机姿态变化的方法汇总
- [置顶] 基于DL的计算机视觉(1)-- Python基础介绍
- iOS开发基础知识--碎片12
- 计算机基础知识
- 计算机系统-电脑硬件基础知识
- 图像处理与计算机视觉:基础,经典以及最近发展(3)计算机视觉中的信号处理与模式识别
- Java笔记之计算机基础知识$java语言基础
- iOS开发基础知识--碎片16
- 以太网基础知识(二)-计算机网络
- iOS开发基础知识--碎片22
- 图像处理与计算机视觉:基础,经典以及最近发展
- 计算机视觉基础2——相机成像的几何描述
- 基于Linux的USB子系统学习 --- <基础知识与USB协议概述> ing
- IOS开发基础知识--碎片18
- 计算机视觉与机器人控制:基础概述
- UNIX环境高级编程——计算机体系结构基础知识