OpenCV常用的图像和矩阵操作总结

OpenCV常用的图像和矩阵操作总结
OpenCV常用的图像和矩阵操作总结

OpenCv常用图像和矩阵操作

目录

学习资料 (2)

书籍 (2)

网站: (2)

本地安装目录 (2)

图像IplImage (3)

Structure IplImage (3)

图像的常用操作 (4)

图像载入函数 (4)

窗口定义函数 (5)

图像显示函数 (5)

图像保存函数 (5)

图像销毁函数 (6)

存取图像像素 (6)

矩阵CvMat (10)

Struct CvMat (10)

矩阵的创建和初始化 (11)

释放矩阵 (11)

复制矩阵: (12)

存取矩阵元素 (12)

简单的方法 (12)

麻烦的方法 (13)

恰当的方法 (16)

cvmGet()和cvmSet()的局限 (17)

矩阵/向量数学操作 (18)

矩阵-矩阵操作: (18)

按元素的矩阵操作: (19)

向量乘积: (19)

单矩阵操作: (19)

非齐次线性系统求解: (19)

特征值分析(针对对称矩阵): (20)

奇异值分解SVD: (20)

其他 (21)

Shell函数显示图片 (21)

IplImage 到cvMat的转换 (21)

学习资料

书籍

Learning OpenCV(影印版)

作者:Gary Bradski, Adrian Kaehler

出版社:东南大学出版社

学习OpenCV(中文版)

作者:Gary Bradski, Adrian Kaehler

译者:于仕琪刘瑞祯

出版社:清华大学出版社

OpenCV中文教程

作者:刘瑞祯于仕琪

网站:

https://www.360docs.net/doc/8010323528.html,/index.php/%E9%A6%96%E9%A1%B5

https://www.360docs.net/doc/8010323528.html,/art/200912/172349.htm

本地安装目录

在安装目录OpenCV1.0\docs 下有各种学习资料

只用在本地安装目录下面就可以查询到大部分需要的信息,当然也可以直接百度,google

图像IplImage

Structure IplImage

OpenCv中图像的结构体为IplImage,位于头文件cxcore.h中,IplImage 结构体的定义如下:

/////////////////////////////////////////////////////////////////////////////

typedef struct _IplImage

{

int nSize; /* IplImage大小*/

int ID; /* 版本(=0)*/

int nChannels; /* 大多数OPENCV函数支持1,2,3 或4 个通道*/

int alphaChannel; /* 被OpenCV忽略*/

int depth; /* 像素的位深度,主要有以下支持格式:IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,IPL_DEPTH_16S, IPL_DEPTH_32S,

IPL_DEPTH_32F 和IPL_DEPTH_64F */

char colorModel[4]; /* 被OpenCV忽略*/

char channelSeq[4]; /* 同上*/

int dataOrder; /* 0 - 交叉存取颜色通道, 1 - 分开的颜色通道.

只有cvCreateImage可以创建交叉存取图像*/

int origin; /*图像原点位置:0表示顶-左结构,1表示底-左结构*/

int align; /* 图像行排列方式(4 or 8),在OpenCV 被忽略,使用widthStep 代替*/ int width; /* 图像宽像素数*/

int height; /* 图像高像素数*/

struct _IplROI *roi; /* 图像感兴趣区域,当该值非空时,

只对该区域进行处理*/

struct _IplImage *maskROI; /* 在OpenCV中必须为NULL */

void *imageId; /* 同上*/

struct _IplTileInfo *tileInfo; /*同上*/

int imageSize; /* 图像数据大小(在交叉存取格式下

ImageSize=image->height*image->widthStep),单位字节*/

char *imageData; /* 指向排列的图像数据*/

int widthStep; /* 排列的图像行大小,以字节为单位*/

int BorderMode[4]; /* 边际结束模式, 在OpenCV 被忽略*/

int BorderConst[4]; /* 同上*/

char *imageDataOrigin; /* 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的*/

} IplImage;}

IplImage;

/////////////////////////////////////////////////////////////////////////////

主要的成员变量有

nChannels : 图像的通道数目,即灰度图像:nChannels = 1; RGB图像nChannels = 3 depth: 每个像素值的数据类型和所占的存储空间

origin变量可以有两种取值:IPL_ORIGIN_TL 或者IPL_ORIGIN_BL,分别设置坐标原点的位置于图像的左上角或者左下角。在计算机视觉领域,一个重要的错误来源就是原点位置的定义不统一。具体而言,图像的来源、操作系统、编解码器和存储格式等因素都可以影响图像坐标原点的选取。举例来说,你或许认为自己正在从图像上面的脸部附近取样,但实际上却在图像下方的裙子附近取样。避免此类现象发生的最好办法是在最开始的时候检查一下系统,在所操作的图像块的地方画点东西试试。

dataOrder: 多通道的数据存储方式,dataOrder=0是交叉通道存储方式,即BGRBGRBGRBGR的方式存储;dataOrder=1是采用独立通道方式存储,即RRRRRRR。。。,GGGGGGG…,BBBBBB…,一般都是BGRBGRBGR的这种交叉存储方式,cvCreateImage生成的图像也是这种存储方式。

width: 图像的宽度

height: 图像的高度

imageData: 图像的像素矩阵

widthStep: 每一行像素所占的字节数目.参数widthStep包括相邻行的同列点之间的字节数。仅凭变量width是不能计算这个值的,因为为了处理过程更高效每行都会用固定的字节数来对齐;因此在第i行末和第i+1行开始处可能会有些冗于字节。参数imageData包含一个指向第一行图像数据的指针。如果图像中有些独立的平面(如当dataOrder = IPL_DATA_ORDER_PLANE)那么把它们作为单独的图像连续摆放,总行数为height和nChannels的乘积。但通常情况下,它们是交错的,使得行数等于高度,而且每一行都有序地包含交错的通道。

ROI-- 感兴趣的区域(ROI),实际上它是另一个IPL/IPP 结构IplROI的实例。IplROI 包含xOffset,yOffset,height,width和coi成员变量,其中COI代表channel of interest(感兴趣的通道)。ROI的思想是:一旦设定ROI,通常作用于整幅图像的函数便会只对ROI 所表示的子图像进行操作。如果IplImage变量中设置了ROI,则所有的OpenCV函数就会使用该ROI变量。如果COI被设置成非0值,则对该图像的操作就只作用于被指定的通道上了。不幸的是,许多OpenCV函数都忽略参数COI。

图像的常用操作

图像载入函数

函数cvLoadImage载入指定图像文件,并返回指向该文件的IplImage指针。函数支持bmp、jpg、png、tiff等格式的图像。其函数原型如下:

IplImage* cvLoadImage( const char* filename, int iscolor);

其中,filename 是待载入图像的名称,包括图像的扩展名;iscolor是一个辅助参数项,可选正数、零和负数三种值,正数表示作为三通道图像载入,零表示该图像作为单通道图像,负数表示载入图像的通道数由图像文件自身决定。

窗口定义函数

函数cvNamedWindow定义一个窗口,用于显示图像。其函数原型如下:

int cvNamedWindow( const char* name, unsigned long flags );

其中,name是窗口名,flags是窗口属性指标值,可以选择CV_WINDOW_AUTOSIZE 和0两种值。CV_WINDOW_AUTOSIZE表示窗口尺寸与图像原始尺寸相同,0表示以固定的窗口尺寸显示图像。

图像显示函数

函数cvShowImage是在指定的窗口中显示图像,其函数原型如下:

void cvShowImage( const char* name, const CvArr* image );

其中,name是窗口名称,image是图像类型指针,一般是IplImage指针。

图像保存函数

函数cvSaveImage以指定的文件名保存IplImage类型的指针变量,其函数原型如下:int cvSaveImage( const char* filename, const CvArr* image );

其中,filename是图像保存路径和名称,image是IplImage指针变量。

Trick:

如果要保存一组图像到result文件夹,图像个数为n,保存名称按照一定的序号递增,假设为imgTmp0.jpg,imgTmp1.jpg,imgTmp2.jpg,imgTmp3.jpg,…, imgTmpn.jpg,则操作为:

char * f[30];

for(int i=0; i

{

sprintf(f,”result/imgTmp%d.jpg”,i);

cvSaveImage(f,img);

}

借用sprintf函数即可以完成依次命名的功能。

图像销毁函数

函数cvReleaseImage销毁已定义的IplImage指针变量,释放占用内存空间。其函数原型如下:

void cvReleaseImage( IplImage** image );

其中,image为已定义的IplImage指针。

存取图像像素

包括获取像素值和对像素值赋值

直接获取

假设图像为IplImage * img,图像的depth= IPL_DEPTH_8U(每个像素用8 bits表示),获取像素坐标(x,y)的操作为

1. 灰度图像(单通道img->nChannels = 1)

对像素赋值:

((char*)(img->imageData + y*imge->widthStep))[x] = 255;

获取像素值:

int grayValue = ((char*)(img->imageData + y*imge->widthStep))[x];

2.彩色图像(单通道img->nChannels = 1)

对像素赋值:

((char*)(img->imageData + y*imge->widthStep))[3*x] = 255;

((char*)(img->imageData + y*imge->widthStep))[3*x+1] = 255;

((char*)(img->imageData + y*imge->widthStep))[3*x+2] = 255;

获取像素值:

uchar b = ((char*)(img->imageData + y*imge->widthStep))[x];

uchar g = ((char*)(img->imageData + y*imge->widthStep))[x];

uchar r = ((char*)(img->imageData + y*imge->widthStep))[x];

注意:

注意(char*)这个指针的强制转换是针对img->imageData + y*imge->widthStep的,也就是针对图像的行指针进行的转换,注意括弧的范围。

当image->depth为其他值时,则可能每个像素的数据类型需要进行(int*),(float*),(double*)等转换。

参数widthStep是相邻行的同列点之间的字节数。仅凭变量width是不能计算这个值的,因为为了处理过程更高效每行都会用固定的字节数来对齐;因此在第i行末和第i+1行开始处可能会有些冗于字节。一次在进行行切换时,一定要widthStep来进行内存的偏移,而不是用depth*width.

一般的情况下,假设有N-通道,类型为T 的图像:

I(x,y)c ~ ((T*)(img->imageData + img->widthStep*y))[x*N + c] //注意x.,y的位置例子:

void saturate_sv( IplImage* img )

{

for( int y=0; y < img->height; y++ )

{

uchar* ptr = (uchar*) ( Img->imageData + y * img->widthStep );

for( int x=0; x < img->width; x++ )

{

ptr[3*x] = 255;

ptr[3*x+1] = 255;

ptr[3*x+2] = 255;

}

}

}

在以上程序中,我们用指针ptr指向第y行的起始位置。接着,我们从指针中析出饱和度和高度在x维的值。因为这是一个三通道图像,所以C通道在x行的位置是3*x+c。

该使用方法是受限的

uchar b,g,r;

b = img->imageData[img->widthStep * row + col * 3]

g = img->imageData[img->widthStep * row + col * 3 + 1];

r = img->imageData[img->widthStep * row + col * 3 + 2];

由于imageData指针始终是char*类型的,因此该方法只适用于8 bits/pixel的图像表示,其他的图像类型则需要进行指针转换。

●宏

可以使用宏CV_IMAGE_ELEM( image_header, elemtype, y, x_Nc )

I(x,y)c ~ CV_IMAGE_ELEM( img, T, y, x*N + c ),其中c为通道的序号,如彩色图像c=0,1,2

不过使用该宏是也要小心数据类型elemtype的问题。

也有针对各种图像(包括4 通道图像)和矩阵的函数(cvGet2D, cvSet2D),但是它们非常慢。

注:

该宏在每次调用时,都会重新计算指针的位置。这意味着,先查找数据区中第0个元素的位置,然后,根据参数中的行和列,计算所需要的元素的地址偏移量,然后将地址偏移量与第0个元素的地址相加,获得所需要的元素的地址。

所以,以上的方式虽然很容易使用,但是却不是获得元素的最好方式。特别是当你要顺序遍历整个图像中所有元素时,这种每次对地址的重复计算就更加显得不合理。

●cvGet2D()和cvSet2D()

可以通过cvGet2D()和cvSet2D()两个函数加上一个CvScalar结构体做到获取图像的像素点。

OpenCV中,CvScalar结构为:

typedef struct CvScalar

{

double val[4];

}

CvScalar;

4个double型变量,算法处理时不至于被强制类型转换而降低精度了。

再来看读写函数的定义:

cvGet2D 获得某个点的值, idx0=hight 行值, idx1=width 列值。

CVAPI(CvScalar) cvGet2D( const CvArr* arr, int idx0, int idx1 );

cvSet2D 给某个点赋值。

CVAPI(void) cvSet2D( CvArr* arr, int idx0, int idx1, CvScalar value );

有上可见,cvGet2D的返回类型和cvSet2D中value的类型都是CvScalar,这样定义一个CvScalar变量再调用函数就OK了。

OpenCV中像素点读写例子:

矩阵CvMat

Struct CvMat

CvMat的结构体定义为:

typedef struct CvMat

{

int type; /* CvMat signature (CV_MAT_MAGIC_VAL), element type and flags */

int step; /* full row length in bytes */

int* refcount; /* underlying data reference counter */

union

{

uchar* ptr;

short* s;

int* i;

float* fl;

double* db;

} data; /* data pointers */

#ifdef __cplusplus

union

{

int rows;

int height;

};

union

{

int cols;

int width;

};

#else

int rows; /* number of rows */

int cols; /* number of columns */

#endif

} CvMat;

step 是每一行数据的长度,以字节来表示

data 是存放矩阵数据的联合体,如果矩阵pMat是float类型的,那么获取矩阵数据指

针的方式为pMat->data.fl,如果是整型的pMat->data.i

行数和列数在c和c++中定义略有不同,但是rows和cols是通用的两个变量。

矩阵的创建和初始化

矩阵有多种创建方法。最常见的方法是用cvCreateMat(),它由多个原函数组成,如cvCreateMatHeader()和cvCreateData()。cvCreateMatHeader()函数创建CvMat结构,不为数据分配内存,而cvCreateData()函数只负责数据的内存分配。有时,只需要函数cvCreateMatHeader(),因为已因其他理由分配了存储空间,或因为还不准备分配存储空间。第三种方法是用函数cvCloneMat (CvMat*) ,它依据一个现有矩阵创建一个新的矩阵。当这个矩阵不再需要时,可以调用函数cvReleaseMat(CvMat*)释放它。

●分配矩阵空间

CvMat* cvCreateMat(int rows, int cols, int type);

type: 矩阵元素类型. 格式为CV_(S|U|F)C.

例如: CV_8UC1 表示8位无符号单通道矩阵, CV_32SC2表示32位有符号双通道矩阵.

例: CvMat* M = cvCreateMat(4,4,CV_32FC1);

●逐点赋值式初始化

CvMat* mat = cvCreateMat( 2, 2, CV_64FC1 );

cvZero( mat );

cvmSet( mat, 0, 0, 1 );

cvmSet( mat, 0, 1, 2 );

cvmSet( mat, 1, 0, 3 );

cvmSet( mat, 2, 2, 4 );

cvReleaseMat( &mat );

●使用现有数组初始化

double a[] = { 1, 2, 3, 4,

5, 6, 7, 8,

9, 10, 11, 12 };

CvMat mat = cvMat( 3, 4, CV_64FC1, a ); // 64FC1 for double

// 不需要cvReleaseMat,因为数据内存分配是由double定义的数组进行的。

释放矩阵

CvMat* M = cvCreateMat(4,4,CV_32FC1);

cvReleaseMat(&M);

复制矩阵:

CvMat* M1 = cvCreateMat(4,4,CV_32FC1);

CvMat* M2;

M2=cvCloneMat(M1);

存取矩阵元素

假设需要存取一个2维浮点矩阵的第(i,j)个元素.

简单的方法

从矩阵中得到一个元素的最简单的方法是利用宏CV_MAT_ELEM()。这个宏(参见例3-4)传入矩阵、待提取的元素的类型、行和列数4个参数,返回提取出的元素的值。

例3-4:利用CV_MAT_ELEM()宏存取矩阵

1.CvMat* mat = cvCreateMat( 5, 5, CV_32FC1 );

2.float element_3_2 = CV_MAT_ELEM( *mat, float, 3, 2 );

更进一步,还有一个与此宏类似的宏,叫CV_MAT_ELEM_PTR()。CV_MAT_ELEM_ PTR()(参见例3-5)传入矩阵、待返回元素的行和列号这3个参数,返回指向这个元素的指针。该宏和CV_MAT_ELEM()宏的最重要的区别是后者在指针解引用之前将其转化成指定的类型。如果需要同时读取数据和设置数据,可以直接调用CV_MAT_ELEM_PTR()。但在这种情况下,必须自己将指针转化成恰当的类型。

例3-5:利用宏CV_MAT_ELEM_PTR()为矩阵设置一个数值

1.CvMat* mat = cvCreateMat( 5, 5, CV_32FC1 );

2.float element_3_2 = 7.7;

3.*( (float*)CV_MAT_ELEM_PTR( *mat, 3, 2 ) ) = element_3_2;

遗撼的是,这些宏在每次调用的时候都重新计算指针。这意味着要查找指向矩阵基本元素数据区的指针、计算目标数据在矩阵中的相对地址,然后将相对位置与基本位置相加。所以,即使这些宏容易使用,但也不是存取矩阵的最佳方法。在计划顺序访问矩阵中的所有元素时,这种方法的缺点尤为突出。

麻烦的方法

在"简单的方法"中讨论的两个宏仅仅适用于访问1维或2维的数组(回忆一下,1维的数组,或者称为"向量"实际只是一个n×1维矩阵)。OpenCV提供了处理多维数组的机制。事实上,OpenCV可以支持普通的N维的数组,这个N值可以取值为任意大的数。

为了访问普通矩阵中的数据,我们可以利用在例3-6和例3-7中列举的cvPtr*D和cvGet*D…等函数族。cvPtr*D家族包括cvPtr1D(), cvPtr2D(), cvPtr3D()和cvPtrND()…。这三个函数都可接收CvArr*类型的矩阵指针参数,紧随其后的参数是表示索引的整数值,最后是一个可选的参数,它表示输出值的类型。函数返回一个指向所需元素的指针。对于cvPtrND()来说,第二个参数是一个指向一个整型数组的指针,这个数组中包含索引的合适数字。后文会再次介绍此函数(在这之后的原型中,也会看到一些可选参数,必要时会有讲解)。

例3-6:指针访问矩阵结构

1.uchar* cvPtr1D(

2. const CvArr* arr,

3. int idx0,

4. int* type = NULL

5.);

6.

7.uchar* cvPtr2D(

8. const CvArr* arr,

9. int idx0,

10.

11.

12.

13. int idx1,

14. int* type = NULL

15.);

16.

17.uchar* cvPtr3D(

18. const CvArr* arr,

19. int idx0,

20. int idx1,

21. int idx2,

22. int* type = NULL

23.);

24.uchar* cvPtrND(

25. const CvArr* arr,

26. int* idx,

27. int* type = NULL,

28. int create_node = 1,

29. unsigned* precalc_hashval = NULL

30.);

如果仅仅是读取数据,可用另一个函数族cvGet*D。如例3-7所示,该例与例3-6类似,但是返回矩阵元素的实际值。

例3-7:CvMat和IPlImage元素函数

1.double cvGetReal1D( const CvArr* arr, int idx0 );

2.double cvGetReal2D( const CvArr* arr, int idx0, int idx1 );

3.double cvGetReal3D( const CvArr* arr, int idx0, int idx1, int idx2 )

;

4.double cvGetRealND( const CvArr* arr, int* idx );

5.

6.CvScalar cvGet1D( const CvArr* arr, int idx0 );

7.CvScalar cvGet2D( const CvArr* arr, int idx0, int idx1 );

8.CvScalar cvGet3D( const CvArr* arr, int idx0, int idx1, int idx2 );

9.CvScalar cvGetND( const CvArr* arr, int* idx );

cvGet*D中有四个函数返回的是整型的,另外四个的返回值是CvScalar类型的。这意味着在使用这些函数的时候,会有很大的空间浪费。所以,只是在你认为用这些函数比较方便和高效率的时候才用它们,否则,最好用cvPtr*D。

用cvPtr*D()函数族还有另外一个原因,即可以用这些指针函数访问矩阵中的特定的点,然后由这个点出发,用指针的算术运算得到指向矩阵中的其他数据的指针。在多通道的矩阵中,务必记住一点:通道是连续的,例如,在一个3通道2维的表示红、绿、蓝(RGB)矩阵中。矩阵数据如下存储rgbrgbrgb . . .。所以,要将指向该数据类型的指针移动到下一通道,我们只需要将其增加1。如果想访问下一个"像素"或者元素集,我们只需要增加一定的偏移量,使其与通道数相等。

另一个需要知道的技巧是矩阵数组的step元素(参见例3-1和例3-3),step是矩阵中行的长度,单位为字节。在那些结构中,仅靠cols或width是无法在矩阵的不同行之间移动指针的,出于效率的考虑,矩阵或图像的内存分配都是4字节的整数倍。所以,三个字节宽度的矩阵将被分配4个字节,最后一个字节被忽略。因此,如果我们得到一个字节指针,

该指针指向数据元素,那么我们可以用step和这个指针相加以使指针指向正好在我们的点的下一行元素。如果我们有一个整型或者浮点型的矩阵,对应的有整型和浮点型的指针指向数据区域,我们将让step/4与指针相加来移到下一行,对双精度型的,我们让step/8与指针相加(这里仅仅考虑了C将自动地将差值与我们添加的数据类型的字节数相

乘)。

例3-8中的cvSet*D和cvGet*D多少有些相似,它通过一次函数调用为一个矩阵或图像中的元素设置值,函数cvSetReal*D()和函数cvSet*D()可以用来设置矩阵或者图像中元素的数值。

例3-8:为CvMat或者IplImage元素设定值的函数

1.void cvSetReal1D( CvArr* arr, int idx0, double value );

2.void cvSetReal2D( CvArr* arr, int idx0, int idx1, double value );

3.void cvSetReal3D(

4. CvArr* arr,

5. int idx0,

6. int idx1,

7. int idx2,

8. double value

9.);

10.void cvSetRealND( CvArr* arr, int* idx, double value );

11.

12.void cvSet1D( CvArr* arr, int idx0, CvScalar value );

13.void cvSet2D( CvArr* arr, int idx0, int idx1, CvScalar value );

14.void cvSet3D(

15. CvArr* arr,

16. int idx0,

17.

18. int idx1,

19. int idx2,

20. CvScalar value

21.);

22.void cvSetND( CvArr* arr, int* idx, CvScalar value );

为了方便,我们也可以使用cvmSet()和cvmGet(),这两个函数用于处理浮点型单通道矩阵,非常简单。

1.double cvmGet( const CvMat* mat, int row, int col )

2.void cvmSet( CvMat* mat, int row, int col, double value )

以下函数调用cvmSet():

1.cvmSet( mat, 2, 2, 0.5000 );

等同于cvSetReal2D函数调用:

1.cvSetReal2D( mat, 2, 2, 0.5000 );

恰当的方法

从以上所有那些访问函数来看,你可能会想,没有必要再介绍了。实际上,这些set

和get函数很少派上用场。大多数时侯,计算机视觉是一种运算密集型的任务,因而你想尽量利用最有效的方法做事。毋庸置疑,通过这些函数接口是不可能做到十分高效的。相反地,应该定义自己的指针计算并且在矩阵中利用自己的方法。如果打算对数组中的每一个元素执行一些操作,使用自己的指针是尤为重要的(假设没有可以为你执行任务的OpenCV函数)。

要想直接访问矩阵,其实只需要知道一点,即数据是按光栅扫描顺序存储的,列("x")是变化最快的变量。通道是互相交错的,这意味着,对于一个多通道矩阵来说,它们变化的速度仍然比较快。例3-9显示了这一过程。

例3-9:累加一个三通道矩阵中的所有元素

1.float sum( const CvMat* mat ) {

2.

3. float s = 0.0f;

4. for(int row=0; rowrows; row++ ) {

5. const float* ptr=(const float*)(mat->data.ptr + row * mat->step)

;

6. for( col=0; colcols; col++ ) {

7. s += *ptr++;

8.

9. }

10. }

11. return( s );

12.}

计算指向矩阵的指针时,记住一点:矩阵的元素data是一个联合体。所以,对这个指针解引用的时候,必须指明结构体中的正确的元素以便得到正确的指针类型。然后,为了使指针产生正确的偏移,必须用矩阵的行数据长度(step)元素。我们以前曾提过,行数据元素的是用字节来计算的。为了安全,指针最好用字节计算,然后分配恰当的类

型,如浮点型。CvMat结构中为了兼容IplImage结构,有宽度和高度的概念,这个概念已经被最新的行和列取代。最后要注意,我们为每行都重新计算了ptr,而不是简单地从开头开始,尔后每次读的时候累加指针。这看起来好像很繁琐,但是因为CvMat 数据指针可以指向一个大型数组中的ROI,所以无法保证数据会逐行连续存取。

●间接存取矩阵元素

cvmSet(M,i,j,2.0); // Set M(i,j)

t = cvmGet(M,i,j); // Get M(i,j)

注意:cvmGet()和cvmSet()函数只支持CV_32FC1(float)和CV_64FC1(double)的类型

●直接存取,假设使用4-字节校正

CvMat* M = cvCreateMat(4,4,CV_32FC1);

int n = M->cols;

float *data = M->data.fl;

data[i*n+j] = 3.0;

●直接存取,校正字节任意

CvMat* M = cvCreateMat(4,4,CV_32FC1);

int step = M->step/sizeof(float);

float *data = M->data.fl;

(data+i*step)[j] = 3.0;

●直接存取一个初始化的矩阵元素

double a[16];

CvMat Ma = cvMat(3, 4, CV_64FC1, a);

a[i*4+j] = 2.0; // Ma(i,j)=2.0;

cvmGet()和cvmSet()的局限

cvmGet()和cvmSet()函数只支持CV_32FC1(float)和CV_64FC1(double)的类型

// 源码如下。也就是说只支持CV_32FC1(float)和CV_64FC1(double)的类型

// 对于U类型的数据,可以使用cvSet2D进行读写

CV_INLINE double cvmGet( const CvMat* mat, int row, int col )

{

int type;

type = CV_MAT_TYPE(mat->type);

assert( (unsigned)row < (unsigned)mat->rows &&

(unsigned)col < (unsigned)mat->cols );

if( type == CV_32FC1 )

return ((float*)(mat->data.ptr + (size_t)mat->step*row))[col];

else

{

assert( type == CV_64FC1 );

return ((double*)(mat->data.ptr + (size_t)mat->step*row))[col];

}

}

CV_INLINE void cvmSet( CvMat* mat, int row, int col, double value )

{

int type;

type = CV_MAT_TYPE(mat->type);

assert( (unsigned)row < (unsigned)mat->rows &&

(unsigned)col < (unsigned)mat->cols );

if( type == CV_32FC1 )

((float*)(mat->data.ptr + (size_t)mat->step*row))[col] = (float)value;

else

{

assert( type == CV_64FC1 );

((double*)(mat->data.ptr + (size_t)mat->step*row))[col] = (double)value;

}

}

矩阵/向量数学操作

矩阵-矩阵操作:

CvMat *Ma, *Mb, *Mc;

cvAdd(Ma, Mb, Mc); // Ma+Mb -> Mc

cvSub(Ma, Mb, Mc); // Ma-Mb -> Mc

cvMatMul(Ma, Mb, Mc); // Ma*Mb -> Mc

按元素的矩阵操作:

CvMat *Ma, *Mb, *Mc;

cvMul(Ma, Mb, Mc); // Ma.*Mb -> Mc

cvDiv(Ma, Mb, Mc); // Ma./Mb -> Mc

cvAddS(Ma, cvScalar(-10.0), Mc); // Ma.-10 -> Mc

向量乘积:

double va[] = {1, 2, 3};

double vb[] = {0, 0, 1};

double vc[3];

CvMat Va=cvMat(3, 1, CV_64FC1, va);

CvMat Vb=cvMat(3, 1, CV_64FC1, vb);

CvMat Vc=cvMat(3, 1, CV_64FC1, vc);

double res=cvDotProduct(&Va,&Vb); // 点乘: Va . Vb -> res

cvCrossProduct(&Va, &Vb, &Vc); // 向量积: Va x Vb -> Vc

注意Va, Vb, Vc 在向量积中向量元素个数须相同.

单矩阵操作:

CvMat *Ma, *Mb;

cvTranspose(Ma, Mb); // transpose(Ma) -> Mb (不能对自身进行转置) CvScalar t = cvTrace(Ma); // trace(Ma) -> t.val[0]

double d = cvDet(Ma); // det(Ma) -> d

cvInvert(Ma, Mb); // inv(Ma) -> Mb

非齐次线性系统求解:

CvMat* A = cvCreateMat(3,3,CV_32FC1);

CvMat* x = cvCreateMat(3,1,CV_32FC1);

CvMat* b = cvCreateMat(3,1,CV_32FC1);

cvSolve(&A, &b, &x); // solve (Ax=b) for x

特征值分析(针对对称矩阵):

CvMat* A = cvCreateMat(3,3,CV_32FC1);

CvMat* E = cvCreateMat(3,3,CV_32FC1);

CvMat* l = cvCreateMat(3,1,CV_32FC1);

cvEigenVV(&A, &E, &l); // l = A的特征值(降序排列)

// E = 对应的特征向量(每行)

奇异值分解SVD:

CvMat* A = cvCreateMat(3,3,CV_32FC1);

CvMat* U = cvCreateMat(3,3,CV_32FC1);

CvMat* D = cvCreateMat(3,3,CV_32FC1);

CvMat* V = cvCreateMat(3,3,CV_32FC1);

cvSVD(A, D, U, V, CV_SVD_U_T|CV_SVD_V_T); // A = U D V^T

标号使得U 和V 返回时被转置(若没有转置标号,则有问题不成功!!!).

OpenCV 2.4.4安装与配置

OpenCV 2.4.4 安装与配置 步骤一:安装OpenCV https://www.360docs.net/doc/8010323528.html,/projects/opencvlibrary/files/opencv-win/2.4.4/ 1.从以上地址下载OpenCV 2.4.4,执行exe文件,将文件安装到所需目录。 2.建立环境变量并添加到系统路径(以将文件安装在D:\opencv为例): i) 右键点击桌面的计算机图标,选择“属性”,跳出如下窗口:

ii) 点击“高级系统设置”,跳出如下窗口:

iii) 点击“高级”选项卡下的“环境变量”,跳出如下窗口:

iv) 点击“系统变量”下的“新建”,“变量名”输入OPENCV_BUILD,“变量值”输入D:\opencv\build(如果OpenCV解压在别的目录,请输入该目录路径。比如,如果在C盘ProgramFiles文件夹建立了名为OpenCV的文件夹,并在其中解压,那么输入的目录就为 C:\ProgramFiles\OpenCV\opencv\build,总之目录一直到build文件夹),点击“确定”。 v) 双击“用户变量”中的PATH,在跳出的窗口中输入变量值为%OPENCV_BUILD%\x86\vc10\bin (如果电脑是64位系统的,请把“x86”改为“x64”;并请确保使用的是VS 2010,因为vc10 文件夹针对的是VS 2010)。

步骤二:在VS2010中配置OpenCV 1. 打开VS 2010,新建一个项目(Win32控制台或MFC 都可以)。 2. 建立Debug 属性表。 i) 点击“视图”菜单中的“属性管理器”。

图像处理opencv代码

#include "stdafx.h" #include "mymfc.h" #include "mymfcDlg.h" #include "afxdialogex.h" #include #ifdef _DEBUG #define new DEBUG_NEW #endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialogEx { public: CAboutDlg(); // 对话框数据 enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP() // CmymfcDlg 对话框

CmymfcDlg::CmymfcDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CmymfcDlg::IDD, pParent) , TheImage(NULL) , rePath(_T("")) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CmymfcDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CmymfcDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_ReadImg, &CmymfcDlg::OnBnClickedReadimg) ON_BN_CLICKED(IDC_EdgeDetect, &CmymfcDlg::OnBnClickedEdgedetect) ON_BN_CLICKED(IDC_Refresh, &CmymfcDlg::OnBnClickedRefresh) ON_BN_CLICKED(IDC_GrayProcess, &CmymfcDlg::OnBnClickedGrayprocess) ON_BN_CLICKED(IDC_Sobel, &CmymfcDlg::OnBnClickedSobel) ON_BN_CLICKED(IDC_Laplace, &CmymfcDlg::OnBnClickedLaplace) ON_BN_CLICKED(IDC_FFT2, &CmymfcDlg::OnBnClickedFft2) ON_BN_CLICKED(IDC_CImage, &CmymfcDlg::OnBnClickedCimage) ON_BN_CLICKED(IDC_Mirror, &CmymfcDlg::OnBnClickedMirror) ON_BN_CLICKED(IDC_CColor, &CmymfcDlg::OnBnClickedCcolor) ON_BN_CLICKED(IDC_MedianBlur, &CmymfcDlg::OnBnClickedMedianblur) ON_BN_CLICKED(IDC_Gaussian, &CmymfcDlg::OnBnClickedGaussian) ON_BN_CLICKED(IDC_BothSide, &CmymfcDlg::OnBnClickedBothside) ON_BN_CLICKED(IDC_Equally, &CmymfcDlg::OnBnClickedEqually) ON_BN_CLICKED(IDC_Corrosion, &CmymfcDlg::OnBnClickedCorrosion) ON_BN_CLICKED(IDC_Dilate, &CmymfcDlg::OnBnClickedDilate) END_MESSAGE_MAP() // CmymfcDlg 消息处理程序 BOOL CmymfcDlg::OnInitDialog() { CDialogEx::OnInitDialog();

Opencv文件操作与数据存储

数据存储 OpenCV提供了一种机制来序列化(serialize)和去序列化(de-serialize)其各种数据类型,可以从磁盘中按YAML或XML格式读/写。在第4章中,我们将专门介绍存储和调用常见的对象IplImages的函数(cvSaveImage()和cvLoadImage())。此外,第4章将讨论读/写视频的特有函数:可以从文件或者摄影机中读取数据的函数cvGrabFrame()以及写操作函数cvCreateVideoWriter()和cvWriteFrame()。本小节将侧重于一般对象的永久存储:读/写矩阵、OpenCV结构、配置与日志文件。 首先,我们从有效且简便的OpenCV矩阵的保存和读取功能函数开始。函数是cvSave()和cvLoad()。例3-15展示了如何保存和读取一个5×5的单位矩阵(对角线上是1,其余地方都是0)。 例3-15:存储和读取CvMat 1.CvMat A= cvMat( 5, 5, CV_32F, the_matrix_data ); 2. 3.cvSave( "my_matrix.xml", &A ); 4.. . . 5.// to load it then in some other program use … 6.CvMat* A1= (CvMat*) cvLoad( "my_matrix.xml" ); CxCore参考手册中有整节内容都在讨论数据存储。首先要知道,在OpenCV中,一般的数据存储要先创建一个CvFileStorage结构(如例3-16)所示,该结构将内存对象存储在一个树形结构中。然后通过使用 CV_STORAGE_READ参数的cvOpenFileStorage()从磁盘读取数据,创建填充该结构,也可以通过使用 CV_STORAGE_WRITE的cvOpenFileStorage()创建并打开CvFileStorage写数据,而后使用适当的数据存储函数来填充它。在磁盘上,数据的存储格式为XML或者YAML。 例3-16:CvFileStorage结构,数据通过CxCore数据存储函数访问 1.typedef struct CvFileStorage 2.{ 3.... // hidden fields 4.} CvFileStorage; CvFileStorage树内部的数据是一个层次化的数据集合,包括标量、CxCore对象(矩阵、序列和图)以及用户定义的对象。 假如有一个配置文件或日志文件。配置文件告诉我们视频有多少帧(10),画面大小(320×240)并且将应用一个3×3的色彩转换矩阵。例3-17展示了如何从磁盘中调出cfg.xml文件。 例3-17:往磁盘上写一个配置文件cfg.xml 1.CvFileStorage* fs= cvOpenFileStorage( 2."cfg.xml", 3.0, 4.CV_STORAGE_WRITE 5.); 6.cvWriteInt( fs, "frame_count", 10 ); 7.cvStartWriteStruct( fs, "frame_size", CV_NODE_SEQ ); 8.cvWriteInt( fs, 0, 320 ); 9.cvWriteInt( fs, 0, 200 ); 10.cvEndWriteStruct(fs); 11.cvWrite( fs, "color_cvt_matrix", cmatrix );

OPENCV 2.4.10安装

一、VS2020安装opencv2.4.10 1.1首先安装vs2010 安装这个就不用多谈了 1.2下载opencv- 2.4.10.exe,并解压到 最后会在 1.3添加系统变量 在系统变量path后添加:C:\opencv\opencv\build\x86\vc10\bin 1.4新建vc++控制台工程项目,配置 1.4.1项目属性->配置属性->VC++目录->包含目录 添加 C:\opencv\opencv\build\include C:\opencv\opencv\build\include\opencv C:\opencv\opencv\build\include\opencv2

1.4.2项目属性->配置属性->VC++目录->引用目录 添加 C:\opencv\opencv\build\x86\vc10\lib 1.4.3项目属性->链接器->输入->附加依赖项 在debug模式下添加 配置方案为Debug的配置,添加:(2410代表我的opencv版本是2.4.10,需要对应更改) opencv_calib3d2410d.lib opencv_contrib2410d.lib opencv_core2410d.lib opencv_features2d2410d.lib

opencv_flann2410d.lib opencv_gpu2410d.lib opencv_highgui2410d.lib opencv_imgproc2410d.lib opencv_legacy2410d.lib opencv_ml2410d.lib opencv_nonfree2410d.lib opencv_objdetect2410d.lib opencv_ocl2410d.lib opencv_photo2410d.lib opencv_stitching2410d.lib opencv_superres2410d.lib opencv_ts2410d.lib opencv_video2410d.lib opencv_videostab2410d.lib 配置方案为Release的配置,添加: opencv_calib3d2410.lib opencv_contrib2410.lib opencv_core2410.lib opencv_features2d2410.lib opencv_flann2410.lib opencv_gpu2410.lib opencv_highgui2410.lib opencv_imgproc2410.lib opencv_legacy2410.lib opencv_ml2410.lib opencv_nonfree2410.lib opencv_objdetect2410.lib opencv_ocl2410.lib opencv_photo2410.lib opencv_stitching2410.lib opencv_superres2410.lib opencv_ts2410.lib opencv_video2410.lib opencv_videostab2410.lib

opencv函数目录-Cv图像处理

目录 1 梯度、边缘和角点 1.1 Sobel 1.2 Laplace 1.3 Canny 1.4 PreCornerDetect 1.5 CornerEigenValsAndVecs 1.6 CornerMinEigenVal 1.7 CornerHarris 1.8 FindCornerSubPix 1.9 GoodFeaturesToTrack 2 采样、插值和几何变换 2.1 InitLineIterator 2.2 SampleLine 2.3 GetRectSubPix 2.4 GetQuadrangleSubPix 2.5 Resize 2.6 WarpAffine 2.7 GetAffineTransform 2.8 2DRotationMatrix 2.9 WarpPerspective 2.10 WarpPerspectiveQMatrix 2.11 GetPerspectiveTransform 2.12 Remap 2.13 LogPolar 3 形态学操作 3.1 CreateStructuringElementEx 3.2 ReleaseStructuringElement 3.3 Erode 3.4 Dilate 3.5 MorphologyEx 4 滤波器与色彩空间变换 4.1 Smooth 4.2 Filter2D 4.3 CopyMakeBorder 4.4 Integral 4.5 CvtColor 4.6 Threshold 4.7 AdaptiveThreshold 5 金字塔及其应用 5.1 PyrDown 5.2 PyrUp 6 连接部件 6.1 CvConnectedComp

OpenCV主要函数介绍

4.1 OpenCV主要函数介绍 1) cvLoadImage 从文件中读取图像 IplImage* cvLoadImage(const char* filename,int flags=CV_LOAD_IMAGE_COLOR ); 函数cvLoadImage从指定文件读入图像,返回读入图像的指针。其中filename是要被读入的文件的文件名;flags指定读入图像的颜色和深度。 2)cvSaveImage 保存图像到文件 int cvSaveImage( const char* filename, const CvArr* image ); 函数cvSaveImage保存图像到指定文件。其中filename保存文件名。image 要保存的图像。图像格式的的选择依赖于filename的扩展名,只有8位单通道或者3通道(通道顺序为'BGR' )可以使用这个函数保存。 3)cvQueryFrame从摄像头或者文件中抓取并返回一帧 IplImage* cvQueryFrame( CvCapture* capture ); 函数cvQueryFrame从摄像头或者文件中抓取一帧,然后解压并返回这一帧。这个函数仅仅是函数cvGrabFrame和函数cvRetrieveFrame在一起调用的组合。返回的图像不可以被用户释放或者修改。其中capture视频获取结构。。 4)cvCaptureFromCAM 初始化摄像头 CvCapture* cvCaptureFromCAM( int index ); 函数cvCaptureFromCAM给从摄像头的视频流分配和初始化CvCapture结构。 其中index要使用的摄像头索引。如果只有一个摄像头或者用哪个摄像头也无所谓,那使用参数-1应该便可以。 5)cvHaarDetectObjects 用来检测图像中的人脸区域 CV API(CvSeq*) cvHaarDetectObjects( const CvArr* image, CvHaarClassifierCascade* cascade, CvMemStorage* storage, double scale_factor CV_DEFAULT(1.1), int min_neighbors CV_DEFAULT(3), int flags CV_DEFAULT(0), CvSize min_size CV_DEFAULT(cvSize(0,0)), CvSize max_size CV_DEFAULT(cvSize(0,0))); 用于快速检测人脸区域,便于提取得到人脸数据。其中image 为被检图像,cascade为 haar分类器级联的内部标识形式,storage 为用来存储检测到的一

vs2010下配置OpenCV

以下配置方法仅属于个人见解;若有什么不对的地方请指教啊。 在完成每一步骤后,记住点击?确定?,以确保你的设置成功。 在某些步骤中注意要在Debug 和Release 分别进行配置。 1.首先是下载VS2010并安装,这里不作赘述;(安装目录: D:\\Program Files\Microsoft Visual Studio 10.0) 2.下载并安装OpenCV,我的版本是2.1(安装目录为D:\Program Files\OpenCV2.1)注意将路径添加至Path中 3.下载并安装CMake,下载版本为Windows(Win32 Installer),安装目录为D:\Program Files\CMake 2.8 4.运行cmake-gui(D:\Program Files\CMake 2.8\bin),设置路径为OpenCV安装路径(本文档假定安装位置为:D:\Program Files\OpenCV2.1),并创建子目录D:\Program Files\OpenCV2.1\vs2010,用于存放编译结果。将数据填入指定文本框中

5.点击?Configure?,在弹出对话框中选中Visual Studio 10.0;单选框中选项选择程序默认的;然后点击Fnish;程序会自动完成 ?Configure Done?; 6.然后点击?configure?,接着点击?Generate?。程序完成?Generate Done?。 7.完成以上步骤后,将在D:\Program Files\OpenCV2.1|vs2010目录下生成OpenCV.sln的VC Solution File,接着请用vs2010打开OpenCV.sln,完成以下操作:

图像管理方案计划opencv代码

/. #include "stdafx.h" #include "mymfc.h" #include "mymfcDlg.h" #include "afxdialogex.h" #include #ifdef _DEBUG #define new DEBUG_NEW #endif // 用于应用程序“关于”菜单项的CAboutDlg 对话框 class CAboutDlg : public CDialogEx { public: CAboutDlg(); // 对话框数据 enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP() // CmymfcDlg 对话框

CmymfcDlg::CmymfcDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CmymfcDlg::IDD, pParent) , TheImage(NULL) , rePath(_T("")) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CmymfcDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CmymfcDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_ReadImg, &CmymfcDlg::OnBnClickedReadimg) ON_BN_CLICKED(IDC_EdgeDetect, &CmymfcDlg::OnBnClickedEdgedetect) ON_BN_CLICKED(IDC_Refresh, &CmymfcDlg::OnBnClickedRefresh) ON_BN_CLICKED(IDC_GrayProcess, &CmymfcDlg::OnBnClickedGrayprocess) ON_BN_CLICKED(IDC_Sobel, &CmymfcDlg::OnBnClickedSobel) ON_BN_CLICKED(IDC_Laplace, &CmymfcDlg::OnBnClickedLaplace) ON_BN_CLICKED(IDC_FFT2, &CmymfcDlg::OnBnClickedFft2) ON_BN_CLICKED(IDC_CImage, &CmymfcDlg::OnBnClickedCimage) ON_BN_CLICKED(IDC_Mirror, &CmymfcDlg::OnBnClickedMirror) ON_BN_CLICKED(IDC_CColor, &CmymfcDlg::OnBnClickedCcolor) ON_BN_CLICKED(IDC_MedianBlur, &CmymfcDlg::OnBnClickedMedianblur) ON_BN_CLICKED(IDC_Gaussian, &CmymfcDlg::OnBnClickedGaussian) ON_BN_CLICKED(IDC_BothSide, &CmymfcDlg::OnBnClickedBothside) ON_BN_CLICKED(IDC_Equally, &CmymfcDlg::OnBnClickedEqually) ON_BN_CLICKED(IDC_Corrosion, &CmymfcDlg::OnBnClickedCorrosion) ON_BN_CLICKED(IDC_Dilate, &CmymfcDlg::OnBnClickedDilate) END_MESSAGE_MAP() // CmymfcDlg 消息处理程序 BOOL CmymfcDlg::OnInitDialog() { CDialogEx::OnInitDialog();

基于opencv对图像的预处理

基于opencv 对图像的预处理 1.问题描述 本次设计是基于opencv 结合c++语言实现的对图像的预处理,opencv 是用于开发实时的图像处理、计算机视觉及模式识别程序;其中图像的预处理也就是利用opencv 对图像进行简单的编辑操作;例如对图像的对比度、亮度、饱和度进行调节,同时还可以对图像进行缩放和旋转,这些都是图像预处理简单的处理方法;首先通过opencv 加载一幅原型图像,显示出来;设置五个滑动控制按钮,当拖动按钮时,对比度、亮度、饱和度的大小也会随之改变,也可以通过同样的方式调节缩放的比例和旋转的角度,来控制图像,对图像进行处理,显示出符合调节要求的图像,进行对比观察他们的之间的变化。 2.模块划分 此次设计的模块分为五个模块,滑动控制模块、对比度和亮度调节模块、饱和度调节模块、缩放调节模块、旋转调节模块,他们之间的关系如下所示: 图一、各个模块关系图 调用 调用 调用 调用 滑动控制模块 对比度和亮度调节模块 饱和度调节模块 缩放调节模块 旋转调节模块

滑动控制模块处于主函数之中,是整个设计的核心部分,通过createTrackbar创建五个滑动控制按钮并且调用每个模块实现对图像相应的调节。 3.算法设计 (1)滑动控制: 滑动控制是整个设计的核心部分,通过创建滑动控制按钮调节大小来改变相应的数据,进行调用函数实现对图像的编辑,滑动控制是利用createTrackbar(),函数中包括了滑动控制的名称,滑动控制显示在什么窗口上,滑动变量的地址和它调节的最大围,以及每个控制按钮应该调用什么函数实现什么功能; (2)对比度和亮度的调节: 对比度和亮度的调节的原理是依照线性理论,它的公式如下所示:g(x)=a* f(x) +b,其中f(x)表示源图像的像素,g(x)表示输出图像的像素,参数a(需要满足a>0)被称为增益(gain),常常被用来控制图像的对比度,参数b通常被称为偏置(bias),常常被用来控制图像的亮度; (3)饱和度的调节: 饱和度调节利用cvCvtColor( src_image, dst_image, CV_BGR2HSV )将RGB 颜色空间转换为HSV颜色空间,其中“H=Hue”表示色调,“S=Saturation”表示饱和度,“V=Value ”表示纯度;所以饱和度的调节只需要调节S的大小,H 和V的值不需要做任何的改变; (4)旋转的调节: 旋转是以某参考点为圆心,将图像的个点(x,y)围绕圆心转动一个逆时针角度θ,变为新的坐标(x1,y1),x1=rcos(α+θ),y1=rsin(α+θ),其中r是图像的极径,α是图像与水平的坐标的角度的大小; (5)缩放的调节: 首先得到源图像的宽度x和高度y,变换后新的图像的宽度和高度分别为x1和y1,x1=x*f,y1=y*f,其中f是缩放因子; 4.函数功能描述 (1)主函数main()用来设置滑动控制按钮,当鼠标拖动按钮可以得到相应的数据大小,实现手动控制的功能,当鼠标拖动对比度和亮度调节是,主函数调用

opencv配置

VS2010 + OpenCV2.3配置 ; 在VS2010下安装配置OpenCV2.3 ; 全程截图,绝对能配置好,不能的留言! 操作系统:Windows 7 x86 中文旗舰版; 编译环境:Visual Studio 2010 中文旗舰版; OpenCV版本:OpenCV-2.3.0-win、OpenCV-2.3.1-win; 备注: a、不需要Cmake编译!! b、如果是最新的2.3.1版本,则将下面第5步中的(5)和(6)中的名为230的lib 修改成231即可,否则会出现找不到lib的情况。 c、不分x86和x64版本,一律按照这个方案配置就可以使用。 d、C#开发环境下的配置方法: https://www.360docs.net/doc/8010323528.html,/mvp_xuan/blog/item/7e6f6d8c4d34be09b31bb aa9.html?timeStamp=1316746687080 e、第5步属于“项目属性配置”,意思是:“每次新建或新打开一个项目,都需要重新配置”。1-4步是系统配置,一次性工程。 1、下载OpenCV(必须要superpack.exe) https://www.360docs.net/doc/8010323528.html,/download/OpenCV-2.3.0-win-superpack.exe 2、安装 解压到D盘根目录下。(位置随便,不过下面的path需要根据实际情况自行修改了。) 3、设置系统环境变量 在用户变量处,新建PATH和OPENCV两个项: ———————————————————— PATH (只需添加下面中的一行,根据系统情况自行选择) D:\OpenCV2.3\build\x86\vc10\bin ———————————————————— OPENCV D:\OpenCV2.3\build ————————————————————

OPENCV函数

Opencv函数 分配图像空间: IplImage*cvCreateImage(CvSize size,int depth,int channels); size:cvSize(width,height); depth:IPL_DEPTH_8U,IPL_DEPTH_8S,IPL_DEPTH_16U, IPL_DEPTH_16S,IPL_DEPTH_32S,IPL_DEPTH_32F, IPL_DEPTH_64F channels:1,2,3or4. 注意数据为交叉存取.彩色图像的数据编排为b0g0r0b1g1 r1... 举例: //分配一个单通道字节图像 IplImage*img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); //分配一个三通道浮点图像 IplImage*img2=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3); 释放图像空间: IplImage*img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); cvReleaseImage(&img); 复制图像: IplImage*img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); IplImage*img2; img2=cvCloneImage(img1); 设定/获取兴趣区域: void cvSetImageROI(IplImage*image,CvRect rect); void cvResetImageROI(IplImage*image); vRect cvGetImageROI(const IplImage*image); 大部分OpenCV函数都支持ROI. 设定/获取兴趣通道: void cvSetImageCOI(IplImage*image,int coi);//0=all int cvGetImageCOI(const IplImage*image); 大部分OpenCV函数暂不支持COI.

OpenCV最基础的图像处理的例子

?什么是OpenCV ?开源C/C++计算机视觉库. ?面向实时应用进行优化. ?跨操作系统/硬件/窗口管理器. ?通用图像/视频载入、存储和获取. ?由中、高层API构成. ?为Intel?公司的Integrated Performance Primitives (IPP) 提供了透明接口. ?特性: ?图像数据操作(分配,释放, 复制, 设定, 转换). ?图像与视频I/O (基于文件/摄像头输入, 图像/视频文件输出). ?矩阵与向量操作与线性代数计算(相乘, 求解, 特征值, 奇异值分解SVD). ?各种动态数据结构(列表, 队列, 集, 树, 图). ?基本图像处理(滤波, 边缘检测, 角点检测, 采样与插值, 色彩转换, 形态操作, 直方图, 图像金字塔). ?结构分析(连接成分, 轮廓处理, 距离转换, 模板匹配, Hough转换, 多边形近似, 线性拟合, 椭圆拟合, Delaunay三角化). ?摄像头标定 (寻找并跟踪标定模板, 标定, 基础矩阵估计, homography估计, 立体匹配). ?动作分析(光流, 动作分割, 跟踪). ?对象辨识 (特征方法, 隐马可夫链模型HMM). ?基本GUI(显示图像/视频, 键盘鼠标操作, 滚动条). ?图像标识 (直线, 圆锥, 多边形, 文本绘图) ?OpenCV 模块: ?cv - OpenCV 主要函数. ?cvaux - 辅助(实验性) OpenCV 函数. ?cxcore - 数据结构与线性代数算法. ?highgui - GUI函数. 资料链接 ?参考手册: ?/docs/index.htm ?网络资源: ?官方网页: https://www.360docs.net/doc/8010323528.html,/technology/computing/opencv/?软件下载: https://www.360docs.net/doc/8010323528.html,/projects/opencvlibrary/ ?书籍: ?Open Source Computer Vision Library by Gary R. Bradski, Vadim Pisarevsky, and Jean-Yves Bouguet, Springer, 1st ed. (June, 2006). ?视频处理例程(位于/samples/c/目录中): ?色彩跟踪: camshiftdemo ?点跟踪: lkdemo

Visual Studio2012环境下配置OpenCV_v2.4.10的步骤

Visual Studio2012环境下配置OpenCV的步骤 2014/12/16 本文将针对Visual Studio2012环境下如何配置OpenCV做出说明,具体如下。 1.下载和安装OpenCV SDK 1.1资源下载 在OpenCV官网https://www.360docs.net/doc/8010323528.html, SDK安装包。对应自己的操作系统,可以下载Windows,Linux/Mac和ios版本。目前官网已经给出OpenCV v3.0bata版本。本文中以OpenCV v2.4.10版本为例进行安装。(各个版本安装过程大体相同,后面将针对不同之处给出说明) 1.2资源安装 下载的OpenCV SDK的后缀名为exe,是一个解压安装程序。双击后会提示设置解压路径,推荐路径D:\Program Files。(因为OpenCV项目文件打包的时候,根目录就是opencv,所以我们不需要额外的新建一个名为opencv的文件夹然后再解压,那是多此一举的事情)然后点击Extract按钮,进行安装。 2.环境变量和路径设置 打开计算机→属性→高级系统设置,在高级目录下单击环境变量按钮,打开环境变量设置对话框。

2.1用户变量设置 在用户变量(此处为lbs的用户变量中)添加两个变量。 新建opencv变量,变量值设置为D:\Program Files\opencv\build。 新建path变量,变量值设置为D:\Program Files\opencv\build\x86\vc11\bin。此处如果已存在path变量,仅需对其变量值修改就行,在后面加上上述路径,但需要用分号和前面的路径隔开(英文半角下的分号) 2.2系统变量设置 在原有的path变量中对变量值修改,在变量值的最后加上D:\Program Files\opencv\build\x86\vc11\bin路径,注意要使用英文半角下的分号和前面的路径隔开。 ※说明 (1)不论电脑是32位还是64位,上述路径中均以x86路径输入,因为创建的程序中默认是在使用win32编译器进行编译。 (2)路径修改后需要重启电脑才能生效。 3.工程项目属性设置 工程项目属性配置主要是指对Debug和Release环境下的工程属性进行修改(通过修改https://www.360docs.net/doc/8010323528.html,er文件进行)。查阅相关资料,发现Visual Studio 2012中已经不再区分Debug和Release的https://www.360docs.net/doc/8010323528.html,er文件,所以配置了Debug或Release中的任

OPenCV3.2中Mat对象常用函数属性总结

OPenCV3.2中Mat对象常用函数属性总结Mat对象是OpenCV2.0之后引进的图像数据结构,它能自动分配内存、不存在内存泄漏的问题,是面向对象的数据结构。分了两个部分,头部与数据部分。 在使用Mat对象时,有以下四个要点需要注意: 1、输出图像的内存是自动分配的 2、使用OpenCV的C++接口,不需要考虑内存分配问题 3、赋值操作和拷贝构造函数只会复制头部分 4、使用clone与copyTo两个函数实现数据完全复制 下面我们就具体介绍一下公共成员函数和公共属性。 公共成员函数: 1、cv::Mat::Mat ( int rows, int cols, int type ) 参数: rows2D数组中的行数 cols2D数组中的列数。 type数组类型。使用CV_8UC1,…,CV_64FC4创建1 - 4通道矩阵,或CV_8UC(n),…,CV_64FC(n)创建多通道(向上到CV_CN_MAX通道)矩阵。

2、cv::Mat::Mat ( Size size, int type ) 参数: size 2D数组大小:Size(cols, rows)。在Size()构造函数中,行数和列数以相反的顺序排列。 type 数组类型。使用CV_8UC1,…,CV_64FC4创建1 - 4通道矩阵,或CV_8UC(n),…,CV_64FC(n)创建多通道(向上到CV_CN_MAX通道)矩阵。 3、cv::Mat::Mat ( int rows, int cols, int type, const Scalar & s ) 参数: rows2D数组中的行数。 cols 2D数组中的列数。 type数组类型。使用CV_8UC1,…,CV_64FC4创建1 - 4通道矩阵,或CV_8UC(n),…,CV_64FC(n)创建多通道(向上到CV_CN_MAX通道)矩阵。s 初始化每个矩阵元素的可选值。在构建后将所有矩阵元素设置为特定值, 使用赋值运算符Mat::operator=(const Scalar& value) 。 4、cv::Mat::Mat ( Size size, int type,

opencv最基础的图像处理

openCV——几个实用函数 2010年12月20日星期一 09:18 1. cvSmooth:各种方法的图像平滑 void cvSmooth( const CvArr* src, CvArr* dst, int smoothtype=CV_GAUSSIAN, int param1=3, int param2=0, double param3=0 ); src 输入图像. dst 输出图像. smoothtype 平滑方法: . CV_BLUR_NO_SCALE (简单不带尺度变换的模糊) - 对每个象素的param1×param2 领域求和。如果邻域大小是变化的,可以事先利用函数cvIntegral 计算积分图像。 . CV_BLUR (simple blur) - 对每个象素param1×param2邻域求和并做尺度变换 1/(param1.param2). . CV_GAUSSIAN (gaussian blur) - 对图像进行核大小为 param1×param2 的高斯卷积 . CV_MEDIAN (median blur) - 对图像进行核大小为 param1×param1 的中值滤波 (i.e. 邻域是方的). . CV_BILATERAL (双向滤波) - 应用双向 3x3 滤波,彩色 sigma=param1,空间 sigma=param2. 平滑操作的第一个参数. param2 平滑操作的第二个参数. 对于简单/非尺度变换的高斯模糊的情况,如果 param2的值为零,则表示其被设定为param1。 param3

对应高斯参数的 Gaussian sigma (标准差). 如果为零,则标准差由下面的核尺寸计算: sigma = (n/2 - 1)*0.3 + 0.8, 其中 n=param1 对应水平核, n=param2 对应垂直核. 对小的卷积核 (3×3 to 7×7) 使用如上公式所示的标准 sigma 速度会快。如果 param3 不为零,而 param1 和 param2 为零,则核大小有sigma 计算 (以保证足够精确的操作). 函数 cvSmooth 可使用上面任何一种方法平滑图像。每一种方法都有自己的特点以及局限。 没有缩放的图像平滑仅支持单通道图像,并且支持8位到16位的转换(与cvSobel和cvaplace相似)和32位浮点数到32位浮点数的变换格式。 简单模糊和高斯模糊支持 1- 或 3-通道, 8-比特和 32-比特浮点图像。这两种方法可以(in-place)方式处理图像。 中值和双向滤波工作于 1- 或 3-通道, 8-位图像,但是不能以 in-place 方式处理图像. 2.IplImage结构 由于OpenCV主要针对的是计算机视觉方面的处理,因此在函数库中,最重要的结构体是IplImage结构。IplImage结构来源于Intel的另外一个函数库Intel Image Processing Library (IPL),该函数库主要是针对图像处理。IplImage结构具体定义如下: typedef struct _IplImage { int nSize; /* IplImage大小 */ int ID; /* 版本 (=0)*/

OPENCV_Mat类存取方法(元素访问)

Opencv ----Mat类 ?cv::Mat ?depth/dims/channels/step/data/elemSize Mat矩阵中数据元素的地址计算公式: addr(M i0,i1,…i m-1) = M.data + M.step[0] * i0 + M.step[1] * i1+ … + M.step[m-1] * i m-1。其中m = M.dims 是指M的维度 i.data:Mat对象中的一个指针,指向内存中存放矩阵数据的一块内存(uchar* data). ii.row: 行;col:列;rows:行数;cols:列数。 iii.dims :Mat所代表的矩阵的维度,如3 * 4 的矩阵为2 维,3 * 4 * 5 的为3维. iv.channels:通道,矩阵中的每一个矩阵元素拥有的值的个数,比如说3 * 4 矩阵中一共12 个元素,如果每个元素有三个值,那么就说这个矩阵是3 通道的,即channels = 3。常见的是一张彩色图片有红、绿、蓝三个通道。但是opencv用imread(opencv读图的函数)读进来的图像,三通道存放顺序为B、 G、R。 v.depth:深度,即每一个像素的位数(bits),在opencv的Mat.depth()中得到的是一个0 –6 的数字,分别代表不同的位数:enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 };可见0和1都代表8位,2和3都代表16位,4和5代表32位,6代表64位; vi.step:是一个数组,定义了矩阵的布局,具体见下面图片分析,另外注意step1

相关文档
最新文档