OpenCV学习笔记.docx
- 文档编号:3274569
- 上传时间:2022-11-21
- 格式:DOCX
- 页数:13
- 大小:36.44KB
OpenCV学习笔记.docx
《OpenCV学习笔记.docx》由会员分享,可在线阅读,更多相关《OpenCV学习笔记.docx(13页珍藏版)》请在冰豆网上搜索。
OpenCV学习笔记
基础概念:
图像(Image):
图像函数是一个随空间和时间改变的连续函数f(x,y,t),如果不随t改变,也可以简化为f(x,y),这就是所谓的静态图像。
通常把图像当作一个矩阵来表达。
灰度(gray):
在单色图像中,最低值对应黑,最高对应白,之间的亮度值就是灰度。
离散化:
将图像采样(采样定理:
采样间隔要比感兴趣的最小尺寸的一半要小),连续图像在采样点处被数字化,这些采样点之间的集合关系就是栅格(grid),而光栅(raster)是指在点之间定义了相邻关系的栅格。
栅格中一个无限小的采样点对应于一个像元(像素pixel),也称为"点"
量化(quantization):
将图像的亮度转为等价数字量的方法称为量化,亮度阶
,b是用来表示亮度的bit位数,通常取b=8,如果量化的级别不够(<100)会出现伪轮廓。
距离(distance):
如果只允许横向和纵向的移动,
,这就是所谓的城市街区距离;如果允许对角线移动
,这就是"棋盘距离"。
邻接性(adjacency):
4-邻接即像素上下左右四个方向的相接像素
,8-邻接也可顾名思义。
区域(region):
由一些彼此邻接的像素构成的集合。
区域具有连通性,指的是区域的任意两个像素之间都存在属于该区域的路径。
我们将图像中的一些区域称为物体(object)。
边界(border):
边界指的是区域的界限上的点的集合。
边缘(edge):
边缘是一个像素与其邻域像素的局部性质,是一个有大小和方向的矢量,计算方式是图像函数的梯度。
直方图(histogram):
直方图是一个统计图,其横轴是灰度,纵轴是出现的频率。
对比度(contrast):
对比度是物体亮度的均值与背景亮度的比较。
噪声(noise):
图像因为受到某些影响而退化,这个退化称为噪声。
白噪声(whitenoise)是理想的噪声,其功率谱不变。
信噪比(SNR):
噪声的功率与观察到的所有功率之比。
数据结构:
对图像理解的分层表示,最底层是图标图像,由含有原始数据(灰度矩阵)的图像组成;然后依次是分割图象(一个图像的分割)、几何表示(2D或者3D的形状知识)、关系模型(最高层的抽象)。
矩阵:
对应于矩形或六边形栅格(偶数行要右移半个像素)的图像,矩阵中含有大量数据,一般先进行全局信息的处理然后再具体到矩阵。
链表:
链主要用于描述边界。
图:
图用来对图像进行整体描述,主要包括区域邻接图:
节点对应于区域,相邻的区域用弧连接起来。
关系结构:
都图整体进行抽象描述时使用,对应于数据库索引。
分层数据结构:
主要是为了解决分布式计算应用于图像处理中遇到的一些问题,这里从略。
图像预处理:
预处理主要是图像增强和复原。
预处理主要利用了图像信息的冗余性,所有的操作都不会增加图像的信息量。
亮度变换:
亮度矫正主要用于实际采集图像时出现亮度不均匀的情况;灰度变换则是纯理论上考虑的问题。
后者本质上就是对直方图某一段进行一些灰度函数的调整。
最常见的包括反转、对数(压缩灰度的动态范围),幂次(伽马矫正,灵活),分段线性变换,位图切割,直方图均衡化(用于提高对比度)和直方图匹配。
几何变换:
像素坐标(纯粹空间域像素的移动),亮度插值(主要用于过采样)
图像平滑:
用于抑制噪声,可能会模糊图像边缘。
主要包括平均、中值滤波等方法。
边缘检测:
edge的概念前面已经说过,是图像亮度发生急剧变化的位置。
图象锐化就是让边缘更陡峭。
边缘检测的算子大致分为三类,分别是差分近似图像函数导数算子(Roberts,Laplace,Sobel等,缺点是依赖物体的大小并对噪声敏感),二阶导数过零点算子(Gaussian,Canny等,缺点是可能平滑过渡了,边缘可能会环行化)。
Canny检测方法对受白噪声影响的阶跃型边缘是最优的。
自适应邻域性预处理:
所谓自适应邻域,指的是所有与种子像素的8-邻域相邻的满足某个相似特性的像素集合。
图像复原:
抑制退化,大多是全局的去卷积的方法。
图像分割:
图像分割也是比较常见的操作,这里也记录一下。
涉及具体的物体识别,图像理解、3D视觉部分统统略过。
分割方法主要分为三组:
全局知识、边缘分割、区域分割。
阈值化:
最古老的分割方法,根据某个阈值,将物体与背景分割。
又分为单阈值、多阈值、自适应阈值(范围阈值)和半阈值各种方法。
阈值检测方法是一个很成熟的方向,现在已经有很多现成的方法可供使用了。
基于边缘的分割:
边缘图像阈值化,使用p率阈值化来定义的简单检测子可能会使边缘变粗,可以通过某种形式的抑制来校正边缘数据;边缘上下文评价是用来使边缘更加精确的例子。
边界跟踪:
由区域定边界,边界包括内边界(区域的一个子集)和外边界(非…)。
霍夫(Hough)变换:
在已经物体的精确形状的情况下,使用霍夫变换可以获得较为精确的分割。
形状描述:
形状描述是查找物体的基础,区域标识是使用方法在图像中标记处区域的方法,数学形态学也是这可以用于区域标识。
下面直接记录形态学这块的东西,项目中主要用了这一块。
正常的学习顺序应该是形状描诉—物体识别—图像理解—3D,然后才学习这部分。
形态学主要就是膨胀和腐蚀操作,膨胀是向量加、腐蚀是向量减。
先腐蚀再膨胀,称为开运算,反之称为闭运算。
顶帽变换(top-hat)是用原始图像减去开运算后的图像,常用来分割物体。
分水岭分割是顶帽变换的加强版。
OpenCV基础:
下面还是回归到OpenCV这里。
基本数据类型:
CvPoint(点,由坐标x和y构成,整数),CvPoint2D32f(32位浮点数,二维),CvPoint3D32f(三维)
CvSize(尺度,width和height,整数),CVSize2D32f(浮点数)
CvRect(派生于CvPoint和CvSize,含有上述两个的所有数据成员)
CvScalar,含有4个double成员,tuple容器,可以存放1-4个双精度浮点数。
有3个构造函数。
这些数据结构的构造函数与之同名,只是首字母不大写(openCV1是C兼容的,所谓的构造函数并非面向对象意义上的,而是用内联实现的)
矩阵和图像:
CvArrCvMatIplImage
CvArr可以看作抽象基类,后面两个依次派生。
CvMat的成员如下:
typedefstructCvMat{ //使用CvCreateMat或CVCreateMatHeader+CvCreateData创建,使用CvCloneMat复制,使用CvReleaseMat释放
inttype; //类型,可以取值为CV_8UC1或CV_64FC4等,
intstep; //行的长度,字节
int*refcount; //内部使用
union{
uchar*ptr;
short*s;
int*I;
float*fi;
double*db;
}data; //指向数据的指针
union{
introws; //高度或行数
intheight;
};
union{
intcols; //宽度或列数
intwidth;
};
}CvMat;
对矩阵数据的操作:
cvGetSize,cvGetElemType,cvGetDims,cvGetDimSize等
存取:
CV_MAT_ELEM或CV_MAT_ELEM_PTR宏,前者一般用于提取,后者用于存放(取得指针后赋值),注意类型转换。
这种方法只限于一维或二维
另外还有一堆cvPtr*D和cvGetReal*D以及cvGet*D(CvScalar型)用来取值(或指针),Ptr系的可以与step(行字节偏移)结合来求连续的值,将Get变为Set是对应的存放函数。
一般情况下使用自己的指针而不是这些函数(这样会提高访问效率),因为struct所有元素的访问权限是public,所以不需要使用函数也可以直接访问(偏移量通过step估算)。
点的数组:
如CV32FC1和CV32FC3,其中的1和3代表的是存放对象的维数,显然3维对象可以完全展开成扁平的放在一维数组里面,但是要注意一维和三维在某些情况下内存布局并不相同。
IplImage结构:
前面已经说过图像是继承CvMat的,因此拥有CvMat的所有元素(但是某些联合只有其中一种数据),定义如下:
typedefstruct_IplImage{
intnsize;
intID;
intnChannels; //通道数,1-4,即图像中点的维数
intalphaChannel;
intdepth; //图像深度,IPL_DEPTH_XX,各类图像类型
charcolorModel[4];
charchannelSeq[4];
intdataOrder; //标明数据排序方式是交错排列还是通道平面(见"点的数组"部分的分析)
intorigin; //原点,可以是IPL_ORIGIN_TL或IPL_ORIGIN_BL,表示在左上角或左下角
intalign;
intwidth; //宽度
intheight; //高度
struct_IplROI*roi; //感兴趣的区域,struct_IplROI{intxOffset,intyOffset,intheight,intwidth,intCOL};其中COL是感兴趣的通道(很多函数忽略COL)
struct_IplImage*maskROI;
void*imageId;
struct_IplTileInfo*tileInfo;
intimagesize;
char*imageData; //指向图像数据的指针,如果dataOrder是IPL_DATA_ORDER_PLANE,行数是height*nChannels,否则就是depth
intwidthStep; //同CvMat中的Step,标明相邻行之间的字节数
intBorderMode[4];
intBorderConst[4];
char*imageDataOrigin;
}IplImage;
访问图像数据:
类似矩阵,虽然有一堆函数可以用,但是通常还是程序员直接访问结构中的元素,典型遍历代码如下:
voidsaturate_sv(IplImage*img){
for(inty=0;y
uchar*ptr=(uchar*)( //计算行首指针
img->imagedata+y*img->widthStep);
for(intx=0;x
ptr[3*x]=…
ptr[3*x+1]=…
}
}
}
注意IplImage中指向数据的指针是一个字符指针,但是CvMat中却是一个联合,因此后者需要自己计算偏移量(与step结合)。
roi可以使用cvSetImageROI设置,使用cvResetImageROI取消设置。
一旦设置ROI,所有的OpenCV函数都只对ROI区域有效,有效使用该方法可以提高程序的效率。
遗憾的是ROI不是线程安全的,只能用于串行处理,所以必要的时候我们还是要自己直接操作局部区域,即imageData+y*widthStep+x*nChannels为原点的一个矩形。
图像操作函数:
一大堆,分类记录如下。
cvAbs,cvAbsDiff和cvAbsDiffS
求绝对值或差的绝对值,注意以S结尾的函数的操作变量其中一个是标量。
cvAdd,cvAdds,cvAddWeighted和alpha融合
参数中有个mask值,可以指定一个dst,屏蔽它的变化。
最后一个是加权和,指定权重和最后的,最后
.这个函数可以用来实现alpha融合,注意两个图像的ROI必须属性一致,两个图像则必须类型一致。
cvSub,cvSubS,和cvSubRS
元素级减法,
cvDiv:
元素级除法,src设置为NULL相当于全一(用来求倒数)
cvMul:
元素级乘法
cvAnd,cvAndS;cvOr,cvOrS;cvNot,cvXor,cvXorS
位关系计算,分别是与或非,异或
cvAvg,cvAvgSdv:
计算平均值,后者还能计算标准差
cvCalcCovarMatrix:
计算均值和协方差,有一个参数flags可以改变函数的用处
cvCmp和cvCmpS:
比较图像或图像和标量,比较操作符可以通过参数cmp_op指定
cvConvertScale,cvConverScalAbs,cvScale
功能很多,包括:
转变图像类型,线性变换图像数据。
注意先变换,后转变。
宏cvConvert有类似的功能,相当于尺度和偏移都是不变的情况。
注意src和dst必须通道数一致。
cvCopy:
复制图像
cvCountNonZero:
计算非0
cvCrossProduct,cvDotProduct:
向量叉积,点积
cvCvtColor:
从一个颜色空间转为另外一个,换言之可以改变通道数,把彩色图像转为灰度图像等等,转变类型由code指定
cvDet:
行列式计算,必须是单通道矩阵
cvEigenVV:
求特征值和对应的特征向量
cvFlip:
反转图像
cvGEMM:
广义矩阵乘法
cvGetCol(cvGetRow)和cvGetCols(cvGetRows):
提取列(行)
cvGetSubRect:
提取子矩阵,以上这几个函数都不涉及到内存分配和数据复制,只是简单的返回指针
cvGetDims和cvGetDimSize:
返回维数和某一维的大小
cvGetSize:
专为2维设计,返回一个CvSize类型的数据
cvInRange和cvInRangeS:
检查图像中的像素灰度是否在某一指定范围。
图像必须是灰度图像,通道数必须一致。
cvInvert:
求逆,可以指定使用的算法
cvMahalonobis:
计算某点和高斯分布中心之间的向量距离
cvMax(cvMin)和cvMaxS(cvMinS):
成对比较,返回较大的一个组成的矩阵
cvMerge和cvSplit:
矩阵的合并和分解,常用来合并单通道图像或拆分多通道图像
cvMinMaxLoc:
找出arr中的最大值和最小值,返回或存储在指定位置。
cvNorm:
计算各种范数
cvNomalize:
规范化图像
cvReduce:
约简图像,按某种规则将矩阵简化
cvRepeat:
平铺复制
cvSet,cvsetZero:
设置值,后者等价于cvSet(0.0),另外cvZero不能设置mask,直接全部清零
cvSetIdentity:
将矩阵单位化,即将主对角线上的元素设为1,其余设为0
cvSolve:
解线性方程组
cvSum:
各个通道的所有像素之和(按通道计算)
cvSVD:
奇异值分解
cvTrace:
求迹
cvTranspose和cvT:
转置矩阵,后者是缩写,不支持多通道矩阵。
绘图函数:
虽然GDI或者OpenGL都有绘图的函数,不过OpenCV还是提供了简单的跨平台GUI支持。
直线:
cvLine;矩形:
cvRectangle;圆:
cvCircle;椭圆:
cvEllipse(Box);多边形:
cvFillPoly,cvFillConvexPoly,cvPolyLine
这些函数一般有如下参数:
一个图像的指针用来存放结果,点,颜色,粗细,填充项,连通性(默认8连通);多边形那三个函数,第一个全能但是速度慢,第二个每次只能画一个单调多边形但是速度更快,最后一个不用考虑相交的情况,速度最快。
字体和文字:
这块一般是系统提供的,比如CFont。
所以和绘图类似,OpenCV提供了简单的跨平台解决方案。
cvPutText()用于输出文本,CvFont就是指向字体的指针,cvInitFont用于初始化该指针。
数据存储:
也就是串行化,这个也是平台相关的。
OpenCV的串行化支持XML或者YAML格式,跨平台性能良好。
矩阵:
cvSave和cvLoad。
存储过程:
先创建一个CvFileStorage结构,读取使用cvOpenFileStorage(参数用CV_STORAGE_READ),写则用CV_STORAGE_WRITE,注意保存的后缀名用.xml或.yaml,释放文件用cvReleaseFileStorage.
写入函数:
cvWriteInt,cvWriteReal,cvWriteString,cvWriteComment,cvStartWriteStruct,cvEndWriteStruct,cvWrite,cvWriteRawData,cvWriteFileNode,注意灵活使用这些函数可以写出合理的配置文件。
读取函数:
cvGetRootFileNode,cvGetFileNodeByName,cvGetHashedKey,cvGetFileNode(ByName),cvReadInt(ByName),cvReadReal(ByName),cvReadString(ByName),cvRead(ByName),cvReadRowData,cvStartReadRawData,cvReadRawDataSlice.
HignGUI主要分为三个部分,硬件相关部分、文件部分以及图形用户界面部分,在实际使用过程中,这些部分可能被相机SDK(GeniCam)和系统相关的API(或各种GUI库,甚至boost:
:
filesystem)取代。
硬件相关的部分主要是操作摄像机,文件则是save和load图片、视频文件,GUI提供了简单的打开和显示窗口的功能。
openCV内部通过名称来引用窗口,但是也可以使用cvGetWindowHandle和cvGetWindowName来实现句柄和名称的转换。
cvResizeWindow用来调整窗口大小。
载入图像:
cvLoadImage,这个函数不是通过分析扩展名来鉴别图像文件,而是通过直接分析文件前几个字节来确定文件的编码格式,flag选项可以指定读入图像是否转换通道和深度(位数)。
如果读入失败,会返回一个空指针。
保存图像:
cvSaveImage,注意这个函数只能存放8位单通道或者8位3通道格式的图像,成功返回1,失败0。
显示图像:
cvShowImage。
移动窗口:
cvMoveWindow。
关闭窗口:
cvDestroyWindow和cvDestroyAllWindows;
单独的窗口处理线程:
cvStartWindowThread
等待按键:
cvWaitKey,参数是等待时间,返回是按键的ASCII码(如果是复合键,有点麻烦)。
鼠标事件:
采用回调函数处理,cvSetMouseCallback(constchar*window_name,CvMouseCallbackon_mouse,void*param),回调函数的固定原型为:
CvMouseCallback(intevent,intx,inty,intflags,void*param),类似win32的消息机制。
Sliders:
滑动条,cvCreateTrackBar也有一个回调函数参数用来制定拖动滑动条时的动作(回调函数名为cvTrackbarCallback),有两个函数用来取得/设定滑动条的当前位置,即:
cvGetTrackbarPos和cvSetTrackbarPos。
无按钮:
木有按钮,通常用一个只能由两个值的滑动条来代替按钮(也可以用图像或键盘快捷键代替)。
视频:
一帧CvCapture,创建用cvCreateFileCapture或cvCreateCameraCapture;读:
cvGrabFrame(获取一帧)然后cvRetrieveFrame(处理帧数据),或者直接用cvQueryFrame(封装了上述两个函数),由于cvGrabFrame会导致视频帧自动前进一步,所以cvRetrieveFrame也有这个副作用。
最后是用cvReleaseCapture释放。
对CvCapture结构,可以用cvGetCaptureProperty和cvSetCaptureProperty来获取和设置属性。
写:
把视频写入硬盘,cvCreateVideoWriter、cvWriteFrame和cvReleaseVideoWriter这几个配合。
最后一个是因为历史原因存在于highgui中的cvConvertImage,用来转换图像格式,原图像和目标图像之间不要求通道或深度一致。
图像处理部分:
平滑:
cvSmooth,参数smoothtype可选CV_BLUR(简单模糊),CV_BLUR_NO_SCALE(简单无缩放),CV_MEDIAN(中值),CV_GAUSSIAN(高斯),CV_BILATERAL(双边),前两者是用领域的平均值代替当前值,不同的是一个需要缩放,另一个不需要(但是不支持inplace);中值滤波是用周围领域的中间值来替换当前值(不能inplace);高斯滤波用卷积核与输入图像的每个点进行卷积,将结果之和替换当前值;由于高斯滤波会磨平边缘,所以引入双边滤波保留边缘。
形态学:
膨胀是求局部最大值的操作,用于填补凹洞,腐蚀则相反。
对应的函数分别是cvErode和cvDilate。
参数中限定局部范围的一个模版称为"核"(默认3*3),可以通过cvCreateStructuringElementEx()来创建,形态核和上面提到的卷积核不同,只是有个范围限定,不需要填充数值。
因此参数只有核的形状和大小以及参考点在形状中的相对位置。
形态学+:
cvMorphologyEx提供了更多功能,参数operation提供了更多操作,包括开运算(CV_MOP_OPEN),闭运算(CLOSE),形态梯度(GRADIENT),顶帽(TOPHAT)和黑帽(BLACKHAT),其中后三者可能需要temp图像(与原图像大小一致)。
开运算会消除高于领域的孤立点(孤白),闭运算相反。
两者类似腐蚀和膨胀,但是能更好地保存源图像连接的区域。
增加迭代次数会导致孤立点群消失。
形态学梯度:
gradient(src)=dilate(src)-erode(src),用膨胀后的图像减去腐蚀后的图像,用来突出团块的边缘(高亮边缘),和梯度不同的是后者不能获得物体的外围边缘。
TopHat和BlackHat用于分离比邻近点亮或暗的块,TopHat(src)=src-open(src),BlackHat(src)=close(src)-src,前者用于突出比周围区域更明亮的区域,后者相反。
漫水填充算法:
最通用的填充算法,从种子点开始,每个点如果在判定范围内,就用一个参数染色。
这个判定范围可以是和种子点开始也可以是其领域的染色点。
flags参数控制算法的连通性。
尺寸调整:
使用cvResize来放大或缩小图像。
参数interpolation用来选择插值算法。
图像
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- OpenCV 学习 笔记
![提示](https://static.bdocx.com/images/bang_tan.gif)