本文翻译自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
分享到:
相关推荐
### OpenCV概述与基本操作 #### 一、OpenCV简介 OpenCV(Open Source Computer Vision Library)是一款免费且开源的计算机视觉库,适用于C/C++程序员。它由英特尔公司在1999年首次发布,并随着时间的发展不断更新...
【知识点详解】 这份广东省汕头市潮南区黄冈实验学校2015-2016学年七年级英语上学期单词竞赛...通过这样的练习,学生可以更好地掌握英语词汇的分类、拼写、翻译以及变化规则,为日常交流和后续的学习打下坚实的基础。
1. 英语词汇: - camping:露营 - catch:接住 - widely:张大地 - hide:藏 - search:搜寻 - build:建造 - care about:在乎 - fight:打架 - around:在…周围 - centre:中央 - trouble:麻烦,困难...
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 ...
1. 不定式(to do): - 作主语:通常表示具体的动作,如"To learn a new language takes time." - 作表语:表示未来或特定的动作,如"The goal is to pass the exam." - 作宾语:许多动词如“want”、“decide”...
- 不定式作宾语:to know (选A),如"I need to know today’s homework." - 所有格与倒装结构:So is your car (选C),如"My car is made in Shanghai. So is your car." - 查阅词典:look up (固定搭配,代词放...
- 题目1: "well" 在这里表示身体健康,选B。 - 题目2: "prefer to do rather than do" 表示宁愿做...而不愿做...,选C。 - 题目3: 定语从句,先行词是人,用"who"引导,选D。 - 题目4: "set aside" 意为预留,...
We're looking forward to seeing you soon. - 我明天八点在学校等你。I'll meet you at school at 8 a.m. tomorrow. - 它距离宾馆多远?乘地铁要花我们40分钟。How far is it from the hotel? It takes us 40 ...
- 额外奉献:Please feel free to ... 句型。 2. **短元音[i]** - 发音要领:舌尖抵下齿,前舌尽量抬高,口形扁平。 - 疯狂外号:“经典收小腹减肥短衣音”。 - 例子:visit、English、busy、pretty。 - 实用...
1. 词汇知识: - (n.)生涯,事业:career - (adj)太阳的:solar - (adv.)无疑地:certainly - (adj.)身体的:physical - (vi.)毕业:graduate - explosion:爆炸 - escape:逃脱 - weapon:武器 - ...
"look forward to" 表示期待,后面通常跟动名词,如 "looking forward to seeing you"。 - 能读懂关于描述过去的文章,从中获取细节信息。这是阅读理解能力的体现,学生应练习从文本中提取关键信息。 学法指导: ...
视而不见:用于AP最大化的对象检测的上下文记录 [ ] [ ] 介绍 “不看就看”是一种旨在通过使用从同一图像中其他对象推断出的上下文信息对对象检测进行记录来提高平均精度的方法。... 196.1 //重新记录
- be familiar with: 对...熟悉 - be familiar to: 为...所熟悉 3. 题目应用: - 1. My uncle cycles to work every day, even if he can afford a car. (题目中提到的是每天骑行上班,即使能负担得起汽车。) -...
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...
- 例1:“你和我们耍花招没用。”翻译为:“It’s no use you trying your tricks on us.” 主句是"It's no use",动词“trying”属于从句。 - 例2:“下次会议讨论我们是否承受他的建议。”翻译为:“It will be ...
- 语境与介词搭配:第1题考察的是固定搭配"get along with",意为“进展;相处”。 - 定语从句关系词:第2题涉及到最高级和定语从句,先行词为story,关系词需用that,因为先行词被最高级修饰。 - 时间表达:第3...
信息安全_数据安全_hum-r1-2-seeing-is-believing-mak 网络犯罪 安全攻击 安全人才 信息安全研究 内外威胁
1. 英汉互译: - 在早上:in the morning - 今天早上:this morning - 一场鹦鹉展览:a parrot show - 放风筝:fly a kite - 吃我们的午餐:have our lunch - black clouds:黑云 - some drinks:一些饮料 -...
1. **定义**: 现在进行时表示的是说话时刻正在进行的动作,或者现阶段持续的动作,也包括已经计划好但尚未发生的将来活动。 2. **用法**: - A 类:表示说话时刻正在发生的事情,如"We are waiting for you." -...