华章计算机 2017-05-02 4615浏览量
在本章中,你将了解计算机视觉系统的数据采集部分。相机和传感器的数据都会被处理。本章将讲授如何给视觉系统选择相机和传感器以及如何正确使用它们。因此,本章有两个主要部分:一个部分是关于用OpenCV进行图像和视频采集,另外一个部分是用Arduino进行传感器数据采集。
人们通过眼睛来获取周围环境的视觉信息。当涉及机器如何获取视觉数据时,各种各样的相机被用于这个目的。因为视觉数据会用数字来表示,有效的相机处理会得到一个更好的表示。这是你可以从本章中学到的知识。
在第2章中,你已经安装了OpenCV并且运行了一个典型的hello world应用。在此基础上,我们通过手头实际案例的讲解来学习OpenCV的数据采集功能。
OpenCV支持各种各样的相机,这样开发者有很大的选择范围。学习如何针对你的应用选择一个合适的相机也是本章的一个主题。你会在本章的相机选择部分找到答案。
选择相机之后,我们将研究如何使用OpenCV进行图像和视频的采集。在此过程中,我们将会学习如何读写图像、捕捉视频等。现在让我们开始吧!
3.1.1 相机选择
相机的选择是和需求紧密相关的。所以,在开始的时候多花点时间仔细考虑你需要的系统。这个简单的步骤会在后面的开发过程中帮你节省时间和金钱。除了需求以外,相机本身的性能也是需要考虑的。所以应该联系项目需求和相机性能来做出最佳选择。这正是本节要讲的内容!
3.1.1.1 分辨率
为了给应用程序选择合适的相机,分辨率和相关的相机传感器属性非常重要,先解释一下分辨率这个术语代表的意思。
当我们谈论一台200万像素相机的时候,这是什么意思?这是指图像(或者一个视频帧)上像素的数目。如果相机产生的图片有1200像素高、1800像素宽,那么图像包括1200×1800 = 2?160?000个像素大概是两百万像素。尽管这个属性被称为相机的分辨率,但是现实中的视觉应用程序往往需要不同的信息比如物体的分辨率,它与相机分辨率紧密相关但是需要更多的细节。
在实际使用中,分辨率意味着可用来区分两点的最小距离。因为照相的目的是获取一个物体或者事件的细节,能够获取的最小细节就显得非常重要。对于视频也是一样的,它不过是一系列连续的图像。
物体分辨率这个重要术语意味着可以通过相机察觉的物体最小粒度。因此物体和最小粒度都是非常重要的。下式展示了一个特定物体的大小和可以获取的最小粒度之间的关系:
3.1.1.2 颜色
从颜色的角度区分,相机有两种类型:单色或者彩色。选择单色相机还是彩色相机仅仅取决于应用的要求。如果应用需要彩色信息,那么必须用彩色相机。如果颜色不重要,重要的是形状,最好选择一个单色(灰度)相机。单色相机通常比彩色相机更敏感并能提供更清晰的图片。在某些情况下将这两种相机一起使用也是有可能并且是必要的。
大部分网络摄像头是彩色的。此外你可以用OpenCV从彩色相机里面捕获一个灰度图像。一般来说,考虑未来的扩展性,彩色相机是首选。通过这种方式,你可以同时获取颜色和形状信息。
3.1.1.3 帧率
帧率是用每秒的帧数(FPS)来衡量的。帧率这个术语描述了相机每秒能够捕获和传输的图像的数量。一般来说,网络摄像头最高可以达到30FPS。有一些相机允许你动态调整帧率。
帧率越高,传感器运行得更快。此外,更高的帧率也会导致更多数据的存储。需要注意的是,如果你的应用程序不够快,也许无法充分利用相机的最高FPS。如果要在工厂每分钟生产6000个产品的生产线上找到产品缺陷,你可能需要一个高FPS相机。每分钟6000个产品意味着每秒100个,假设你需要为每个产品花10帧来找到缺陷,那么在这个应用中你需要一个10×100 = 1000FPS的相机。
FPS越高的相机,价格也越高。针对工厂这个例子做一个启发性计算并用帧速率来定义平均速度。比如一个普通的网络摄像机的FPS可能是50,而上文讨论的工厂的例子至少需要一个1000FPS的相机来检测缺陷,如果做一个粗略估计,1000FPS相机的价格可能是普通相机的20倍。
3.1.1.4 2D还是3D
从原理上来说,相机获取的图像是对场景的2D投影。如果你熟悉网络摄像头,它们都是2D网络摄像头。
3D相机加了第三个维度——到数据的距离。3D相机这个词指的是广角相机或者立体相机。广角相机会生成一个每个像素带着到特定点距离信息的图像。立体相机是用2个平行相机模仿人类的视觉来捕获三维图像。通过两张图片对应点的偏移量,可以计算出图像中任意点的深度。
如果你的应用需要3D功能,那么你需要一个3D相机比如Kinect或者Asus Xtion Pro Live。当然,还有很多其他3D相机!
再次提醒,3D相机需要更多的存储空间。所以如果你不需要3D信息,请使用2D相机。
3.1.1.5 通信接口
通信接口影响相机系统的很多属性。流行的接口有USB、FireWire、GigE和CameraLink。有很多变量可以进行比较,见下表:
通信接口 最大距离 最大带宽 支持多相机 实时性 即插即用
USB 2.0 5m 40MB/s 中等 低 高
USB 3.0 8m 350MB/s 中等 高 高
FireWire 4.5m 65MB/s 中等 高 高
CameraLink 10m 850MB/s 低 高 低
GigE 100m 100MB/s 高 中等 中等
从表中可以看到,通信接口对控制器到相机的距离、带宽、FPS甚至可用性会产生巨大影响!所以,请评估你的需求并且给应用选择合适的接口。
网络摄像头有一个USB接口。所以它们有不错的控制器到相机距离、带宽、FPS和可用性。这使得绝大多数计算机视觉应用可以使用网络摄像头。
3.1.2 图像采集
到现在为止,我们已经对如何选择相机有了一个比较清楚的认识。现在是时候更进一步了,让我们从相机中读取数据。
大道至简,最好让一切事情保持简单并且易于使用。正因如此,我们的例子将使用一个标准的网络摄像头。这个例子将选用罗技C120作为网络摄像头。请注意安装网络摄像头的驱动以便可以与OpenCV一起工作。
我们使用了OpenCV C++ API来从相机中读取数据,此外,OpenCV提供了很棒的文档,可以用C、Python和Java API轻松实现这个例子。如果需要更多信息,可以访问opencv.org。
3.1.2.1 读取静态图片
在设计的概念验证阶段,使用静态图片进行工作是有好处的。例如,假设你想开发一个人脸识别的应用程序。首先,你应该在一组人脸图像的样本上工作,所以,从数据存储中读取静态数据将是这个过程的第一步。
OpenCV使计算机视觉系统的开发变得简单!让我们用OpenCV从存储中读取静态数据。现在编写代码来读取静态图片并将它展现在窗口中。请把下面的代码输入到OpenCV开发环境中并将其保存为read_static_image.cpp:
当你编译这段代码时,它将生成一个可执行文件。在Windows环境下,我们姑且认为它是read_static_image.exe。你可以把计算机视觉里面著名的lena.jpg图片作为输入。在Windows环境下,把这个图片复制到C:/cv_book/目录下。在cmd.exe窗口中,导航到包含read_static_image.exe的目录下。该指令如下:
现在让我们解释这段代码。引入头文件这样的基础部分已经在前面讲过。让我们从新的部分开始,如下代码片段所示:
首先检查参数的数目是否正确。在前面的命令行中看到应该有两个参数:第一个参数是程序本身,第二个参数是图片路径。如果参数的数量不是两个,那么程序将打印一行帮助信息然后报错退出。
下一步创建了一个Mat对象用来存储图像数据。图片数据以RGB格式读取,如下代码所示:
3.1.2.2 在网络摄像头里面做快照
有时候需要用相机做快照并且保存下来以便进一步分析。这个过程通常通过一个触发器启动。
回想一下基于人脸识别的门锁例子。当访客按门铃时,系统需要对脸部做一个快照并且对它进行人脸识别。这个应用是快照的一个很好的例子,我们还能找到其他需要做快照的相似情形。使用以下代码创建一个项目并且保存为take_snapshot.cpp。
这段代码和快照代码非常相似,除了帧数据的读取过程是在一个无限while循环中。有一个可选的ProcessFrame函数来把视频帧转成灰度帧。如果你想要一个彩色的帧,那么注释掉ProcessFrame函数。
在运行这段代码时,你能看到相机里面的实时视频流!
如果要改变视频流的FPS,你可以使用函数bool VideoCapture::set(int propId, double value),propId的值为CV_CAP_PROP_FPS。如果你要把FPS设为10,你可以输入:
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。