本文翻译自Robin Hewitt的《Seeing With OpenCV - A Five-Part Series》。
正如标题所表达的那样,通过连载的五篇文章,我们将通过step by step的方式,实现一个人脸识别的程序,即从原始图片中检测脸部,并通过某种算法从样本库中筛选近似的肖像加以匹配,这是相当有用&有趣的应用。
这是本系列的第一章,主要介绍OpenCV及其一些简单用法。
1、OpenCV简介
OpenCV是一款免费、开源、使用C&C++编写的计算机视觉库,可以从
http://sourceforge.net/projects/opencvlibrary
下载获得。
Intel在1999年发布了OpenCV的第一个版本,当时它需要Intel的图形处理包。现在,这个限制已经被去除,你可以像使用任何一个标准库一样使用OpenCV。
OpenCV被设计为跨平台,同时支持Windows、Linux以及MacOSX。有一个例外,CVCAM(负责摄像头处理)被设计为平台相关,这点后面会讨论到。
2、特点
OpenCV具有强大的图形处理功能,庞大的API可能会让初学者产生畏惧感。因此,作为初学者,你只需要了解其中最常用的部分。
通用计算机视觉以及图形处理算法(中、低层API)
使用这些接口,无需复杂的编写图像算法就可以实现一些常用的图像处理功能,包括边缘&直线&角的检测、椭圆拟合、多分辨率的图形金字塔算法、模板匹配,各种变换(傅里叶、离散余弦、距离)等等。
高层计算机视觉模块
OpenCV包含了许多高层的功能,例如脸部检测&识别&跟踪等
人工智能与机器学习方法
计算机视觉的问题往往会涉及到一些机器学习以及人工智能的方法,这些都被包装在OpenCV的机器学习包里面
图像采样与视角变换
OpenCV提供了图像子区域提取、随机采样、图形缩放、包装、旋转以及透视变换等功能
二值化图像的创建和处理
OpenCV提供的二值化图像的创建和分析功能,在监控、形状检测以及物件计数等领域往往很有用
3D计算与处理
这些方法可以用于3D建模和定位,以及摄像机的多视角处理
用于图像处理、计算机视觉的数学库
OpenCV提供了大量常用的数学运算库,包括线性代数、统计学以及几何运算等等
作图
这些接口可以使你很方便地再图片上写字或者作画。可以通过它实现一些简单的水印功能,或者辅助其它更高阶的功能,例如在进行物体识别的同时,可以使用该接口标记检测出来的位置和区域。
GUI
OpenCV封装了许多跨平台的GUI接口作为API,你可以实现自己的应用,操作键盘、鼠标、滑块等控件。
数据结构与算法
使用这些接口,你可以有效地存储、查询、保存和操作一些常用的数据结构,比如链表、几何、树、图等
数据持久化
这些接口提供了将数据保存到本地以便日后读取的功能
下图展示了OpenCV的一些应用场景,包括脸部识别、轮廓检测以及边缘检测。
3、模块结构
OpenCV包含以下几个模块:
CXCORE包含了一些基本的数据类型的定义。例如,一些常见的图、点、矩形等数据结构定义在cxtypes.h中。CXCORE同时也包含含线性代数和统计等模块,以及持久化函数、错误句柄处理、以及画图等功能。
CV包含了图像处理以及摄像机校正、几何计算等方法。
CVAUX包含了一些实验型的方法,比如脸部识别等
ML主要是一些机器学习的方法
HighGUI包含了一些基本的IO操作以及一些跨平台的界面调用接口
CVCAM包含了一些视频处理的接口,使得你不必亲自去使用DirectX
4、OpenCV编程基础
关于头文件与库文件的引用
本文所介绍的大部分程序都需要引用cv.h和highgui.h。脸部识别的程序还需要添加cvaux.h。这些头文件自身引用了其余的大多数其它头文件。
你的连接器也需要添加cxcore.lib、cv.lib以及highgui.lib。对于脸部识别的程序,还需要添加cvaux.lib,它们都在OpenCV的lib目录下。
图片的读写
下面的实例代码说明了如何读取图片文件,并采用不同的压缩格式(jpg -> png)保存为另一个文件。
#include <stdio.h>
int main(int argc, char** argv)
{
IplImage * pInpImg = 0;
// Load an image from file
pInpImg = cvLoadImage("my_image.jpg", CV_LOAD_IMAGE_UNCHANGED);
if(!pInpImg)
{
fprintf(stderr, "failed to load input image\n");
return -1;
}
// Write the image to a file with a different name,
// using a different image format -- .png instead of .jpg
if( !cvSaveImage("my_image_copy.png", pInpImg) )
{
fprintf(stderr, "failed to write image file\n");
}
// Remember to free image memory after using it!
cvReleaseImage(&pInpImg);
return 0;
}
当读取图片时,仅需要调用cvLoadImage方法,并且传递给他文件名作为参数即可(如第十四行所述)。OpenCV支持常见的大多数的图片格式,包括JPEG、PNG和BMP(目前还不支持GIF)。你无须关心图片具体是按照何种格式压缩保存的,cvLoadImage会在读取图片头文件信息的时候决定采用哪一种格式的解码器。
可以通过cvSaveImage方法将内存中的图片保存为文件。保存文件时,采用何种压缩格式,是由传入的文件的扩展名决定的。比如,传入参数为"XXX.png",就以PNG的格式来存储。
在调用cvLoadImage之后,使用完图片资源之后务必记得调用cvReleaseImage来释放内存。
cvLoadImage与cvSaveImage都被封装在HighGUI模块中。
色彩空间的转换
下面的例子说明了如何将一幅图片转化为灰度图。OpenCV内置了许多色彩空间模型方便自由地转换,包括RGB、HSV、YCrCb已经CIELAB等等。如果你对色彩模型感兴趣,推荐看SERVO Magazine的《The World of Color》。
// ConvertToGray.c
// Example showing how to convert an image from color
// to grayscale
#include "stdio.h"
#include "string.h"
#include "cv.h"
#include "highgui.h"
int main(int argc, char** argv)
{
IplImage * pRGBImg = 0;
IplImage * pGrayImg = 0;
// Load the RGB image from file
pRGBImg = cvLoadImage("my_image.jpg", CV_LOAD_IMAGE_UNCHANGED);
if(!pRGBImg)
{
fprintf(stderr, "failed to load input image\n");
return -1;
}
// Allocate the grayscale image
pGrayImg = cvCreateImage
( cvSize(pRGBImg->width, pRGBImg->height), pRGBImg->depth, 1 );
// Convert it to grayscale
cvCvtColor(pRGBImg, pGrayImg, CV_RGB2GRAY);
// Write the grayscale image to a file
if( !cvSaveImage("my_image_gray.jpg", pGrayImg) )
{
fprintf(stderr, "failed to write image file\n");
}
// Free image memory
cvReleaseImage(&pRGBImg);
cvReleaseImage(&pGrayImg);
return 0;
}
注意,具体执行色彩转换的函数——cvCvtColor,其参数列表包含两个图片指针类型,第一个参数,pRGBImg,代表源图像。第二个参数,pGrayImg,代表目标图像。
注意25行,我们使用cvCreateImage创建了一个与原始图像相同尺寸,但为初始化像素的数据结构,这类操作在今后的OpenCV编程中会很常见。
OpenCV图片的数据结构
OpenCV使用标准的C语言结构体来。其中,IPL是Image Processing Library的缩写。IplImage是在CXCOR中定义的,除了原始的像素数据之外,它还定义了一些元数据(描述字段),统一称为图片的“头文件”。它包括:
- width —— 图片宽度,以像素为单位
- height —— 图片高度,以像素为单位
- depth —— 图片位深,即每通道每像素所包含的位的数目。比如,depth为IPL_DEPTH_8U,则表示单个通道的每个像素为8位无符号类型,即0-255
- nChannels —— 通道数量,一般为1-4. 每个通道包含一种像素数据类型。比如RGB图像包含三个通道,因为每个像素都存储了红、绿、蓝三种颜色信息;而灰度图像只包含一个通道,即像素的亮度。
操作像素值
事实上,使用OpenCV的大部分应用,都不需要去直接操作原始的像素数据,比如脸部检测、追踪、识别等;它们只需要使用图像指针以及其它的一些高层的数据结构。OpenCV的许多函数封装了像素级别的计算。尽管如此,你还是会有直接操作原始像素数据的场景,比如当你需要自己写一些图形算法的时候。下面介绍两种操作像素的方法:
1、简单的像素操作
最简单的读取单个像素的方法时采用cvGet2D方法:
该函数具有三个参数:一个指向数据容器的指针(CVArr*)以及代表了位置坐标(第几行第几列)的数组。数据容器可以使IplImage结构体。最顶上一行的像素的row=0,最低部一行的row=height-1。
cvGet2D返回一个C结构体,CvScalar,其定义如下:
typedef struct CvScalar
{
double val[4];
}
CvScalar;
每个通道的像素值被保存在val[i]中。对于灰度图像,val[0]代表了像素的亮度值,而其它三个值则被设为0,。对于三通道的BGR图片,blue=val[0],green=val[1],red=val[2]。
另一个函数,cvSet2D方法允许你修改像素值,它的定义如下:
void cvSet2D(CvArr*, int row, int col, CvScalar);
2、快速的像素操作
尽管vGet2D()以及cvSet2D()十分方便使用,但是对于批量存取大量像素点来说,它们的性能很糟糕。此种情况下,你需要直接从原生的数据缓存,即IplImage.imageData中读取像素值。
缓存中的图像数据以一维数组的形式存放,以行优先的顺序,即:先顺序存放第一行的所有数据,再存放第二行的所有数据,以此类推。
出于性能考虑,所有的像素数据都经过对齐,并且在需要的时候补0。IplImage的第二个字段,IplImage.widthStep,代表相邻两行数据之间的bit数,也就是说,第i行的数据指针指向
IplImage.imageData + i*IplImage.widthStep处。
IplImage.imageData被定义为char*类型,因此必要时你需要转换数据类型,比如,通常来说,你的图像数据是unsigned bytes,你在使用它时往往需要将其转化为unsigned char*。
如果你在操作的是位深等于8的灰度图像,可以通过如下方式操作pixel[row][col]:
pixel[row][col] =
(uchar*)(pImg->imageData + row*pImg->widthStep + col);
最后,如果遇到图片的位深大于8bit的情况(比如,IPL_DEPTH_32S),你需要将其转化为多字节的数据类型,并且将其width step乘以字节数作为其实际的位深(比如,对于IPL_DEPTH_32S来说,你需要将buffer转化为int*,并且将使用4倍的width step。)。尽管如此,实际情况下,很少会遇到需要直接操作多字节像素值的场景。
5、下一章预告
在Part 2,我将会介绍如何使用OpenCV来实现脸部检测,并且详细讲解其背后的算法,感谢你的阅读。
- 大小: 165.9 KB
分享到:
相关推荐
This document will help you learn how to read and write image file, capture video.
If your team is struggling with any of these symptoms, these four case studies will guide you to project success. See how Kanban was used to significantly improve time to market and to create a ...
视而不见:用于AP最大化的对象检测的上下文记录 [ ] [ ] 介绍 “不看就看”是一种旨在通过使用从同一图像中其他对象推断出的上下文信息对对象检测进行记录来提高平均精度的方法。... 196.1 //重新记录
This book presents an introduction to programming interactive computer graphics, with an emphasis on game development, using real-time shaders with DirectX 9.0c. It teaches the fundamentals of Direct...
信息安全_数据安全_hum-r1-2-seeing-is-believing-mak 网络犯罪 安全攻击 安全人才 信息安全研究 内外威胁
This book presents an introduction to programming interactive computer graphics, with an emphasis on game development, using Direct3D 10. It teaches the fundamentals of Direct3D and shader programming...
眼见为实将seeing_is_believing集成到Sublime Text 2和3。先决条件您需要安装 2.0或更高版本: gem install seeing_is_believing安装您可以通过两种方式安装SeeingIsBelieving插件:使用Git或直接下载它。 然后,您...
○ seeing-red https://github.com/ssloxford/seeing-red 包含15份原始手指视频数据集(论文是针对心跳监测)(Each video is a 30 seconds long recording which was taken as the participant kept his index ...
For physics students interested in the mathematics they use, and for math students interested in seeing how some of the ideas of their discipline find realization in an applied setting. The ...
Seeing eye pi 负责提供键盘反馈并读取应用程序产生的输出。 ##Affordable 这个项目的最终目标是生产一种负担得起的便携式设备(低于 50 美元),能够执行各种基本任务,如访问在线信息、收听有声读物和编写电子...
猫头鹰看到家的助手 “ Owl Seeing”品牌的应用程序设计。 所有内容和图像都纯粹用于教育目的,因为这是6级Web和UX设计的汇总作业。
This book presents an introduction to programming interactive computer graphics, with an emphasis on game development, using real-time shaders with DirectX 9.0c. It teaches the fundamentals of Direct...
This book presents an introduction to programming interactive computer graphics, with an emphasis on game development, using real-time shaders with DirectX 9.0c. It teaches the fundamentals of Direct...
Step 1: Thinking in Layers and Aspects Step 2: Seeing the Big Picture Step 3: Recognizing the Potential Stage II: Why the Blockchain Is Needed Step 4: Discovering the Core Problem Step 5: ...
The latter include: • A new chapter on singular values and singular vectors, including ways to analyze a matrix of data • A revised chapter on computing in linear algebra, with professional-level ...
3.Seeing 01d Friends in New Ways 4.Double Your Fun 5.Members Ornly 6.The Fun Never Ends… 7.A Bit Too Much 8.Just a Bit More 9.Thin Ice 10.Under the Hood A.Connecting the Wires B.Welcome to the Club ...
6 Advanced SELECT: Seeing your data with new eyes 235 7 Multi-table Database Design: Outgrowing your table 281 8 Joins and Multi-table Operations: Can’t we all just get along? 343 9 Subqueries: ...
word源码java springboot2.0 springboot2.0、Mybatis-Plus、encache...... ...seeing this as a fallback. Thu Aug 09 11:16:51 CST 2018 There was an unexpected error (type=Not Found,\nstatus=
6.859 A4:看音乐团队成员蕾切尔·福克斯(rfuchs) AlizéeSchoen(阿姆舒恩) 克莱尔·尹(音)数据集我们使用了,其中包含可追溯到1920年的首歌曲。设计决策设计决策的基本原理。 您如何选择特定的视觉编码,交互...