C++ 实现运动目标的追踪
一、介绍
本次实验将使用利用 OpenCV 来实现对视频中动态物体的追踪。
涉及的知识点
- C++ 语言基础
- g++ 的使用
- 图像基础
- OpenCV 在图像及视频中的应用
- Meanshift 和 Camshift 算法
实验效果
本次实验要实现的效果是追踪太阳系中运动的行星(图中选择了浅绿颜色轨道上的土星,可以看到追踪的目标被红色的椭圆圈住):
二、环境搭建
进行本节的实验时,您需要先完成 C++实现太阳系行星运行系统 的相关实验,才能进行下面的相关学习。
2.1 创建视频文件
在实验楼环境中暂时还不支持连接用户计算机的摄像头进行实时取景,我们首先需要创建实验前的视频文件。
首先安装屏幕录制工具:
sudo apt-get update && sudo apt-get install gtk-recordmydesktop
安装完成后,我们能够在应用程序菜单中找到:
运行之前完成的太阳系行星系统程序 ./solarsystem
并使用 RecordMyDesktop
录制程序运行画面(10~30s 即可),并保存到 ~/Code/camshift
路径下,命名为 video
:
时间足够后停止录制便能得到一个.ogv
结尾的视频文件video.ogv
:
2.2 图像基础
OpenCV 是一个开源的跨平台计算机视觉库,与 OpenGL 所提供的图像绘制不同,OpenCV 实现了图像处理和计算机视觉方面的很多通用的算法。在学习 OpenCV 之前,我们需要先了解一下图像、视频在计算机中的一些基本概念。
首先,我们要理解图片在计算机中的表示方式:图像在显示过程中以连续变化的形式而存在,但在计算机中,有两种常见的存储图片的方式:一种是矢量图,一种则是像素图。
矢量图,也称为面向对象的图像或绘图图像,在数学上定义为一系列由线连接的点。矢量文件中的图形元素称为对象。每个对象都是一个自成一体的实体,它具有颜色、形状、轮廓、大小和屏幕位置等属性。
而更常见的则是像素图,比如常说的一张图片的尺寸为1024*768,这就意味着这张图片水平方向上有1024个像素,垂直方向上有768个像素。
像素就是表示像素图的基本单位,通常情况下一个像素由三原色(红绿蓝)混合而成。由于计算机的本质是对数字的识别,一般情况下我们把一种原色按亮度的不同从 0~255 进行表示,换句话说,对于原色红来说,0表示最暗,呈现黑色,255表示最亮,呈现纯红色。
这样,一个像素就可以表示为一个三元组(B,G,R)
,比如白色可以表示为(255,255,255)
,黑色则为(0,0,0)
,这时我们也称这幅图像是 RGB 颜色空间中的一副图像,R、G、B 分别成为这幅图像的三个通道,除了 RGB 颜色空间外,还有很多其他的颜色空间,如 HSV、YCrCb 等等。
像素是表示像素图的基本单位,而图像则是表示视频的基本单位。一个视频由一系列图像组成,在视频中我们称其中的图像为帧。而通常我们所说的视频帧率,意味着这个视频每秒钟包含多少帧图像。比如帧率为 25,那么这个视频每秒钟就会播放25帧图像。
1秒钟共有1000毫秒,因此如果帧率为 rate
那么每一帧图像之间的时间间隔为 1000/rate
。
2.3 图像颜色直方图
颜色直方图是描述图像的一种工具,它和普通的直方图类似,只是颜色直方图需是根据某一幅图片计算而来。
如果一副图片是 RGB 颜色空间,那么我们可以统计 R 通道中,颜色值为 0~255 这 256 种颜色出现的次数,这边能获得一个长度为 256 的数组(颜色概率查找表),我们再将所有的值同时除以这幅图像中像素的总数,将这之后所得的数列转化为直方图,其结果就是颜色直方图。
2.4 直方图反向投影
人们已经证明,在 RGB 颜色空间中,对光照亮度变化较为敏感,为了减少此变化对跟踪效果的影响,就需要对直方图进行反向投影。这一共分为三个步骤:
- 首先将图像从RGB空间转换到HSV空间。
- 然后获取其中的 H 颜色通道的直方图。
- 将图像中每个像素的值用颜色概率查找表中对应的概率进行替换,就得到了颜色概率分布图。
这个过程就叫反向投影,