OpenCV学习 (二)  OpenCV基本操…

来源:互联网 发布:学会plc编程工资高吗 编辑:程序博客网 时间:2024/06/06 13:05


【矩阵处理】

1.      内存的分配与释放

因为OpenCV使用C语言来进行矩阵操作,但是用C++的替代方案可以更加高效地完成操作。

OpenCV中向量被当做是有一个维数为1N维矩阵。

矩阵按照行—行方式存储,每行4byte32bit)对齐。

2.      为新的矩阵分配内存

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

其中 Type是矩阵元素的类型:

          CV(S|U|F)C方式指定

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

3.      释放矩阵内存

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

cvReleaseMat(&M);

4.      复制矩阵

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

cvMat *M2;

M2=cvCloneMat(M1);

5.      初始化矩阵

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

                            5,6,7,8,

                            9,10,11,12}

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

等价于

CvMat Ma;

cvInitMatHeader(&Ma,3,4,CV_64FC1,a);

6.      初始化矩阵为单位矩阵

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

cvSetIdentity(M);

7.      访问矩阵元素

假设我们现在需要访问一个2D浮点型矩阵的第(i,j)个单元

1.      间接访问

cvmSet(M,I,j,2.0);//设置M的(I,j)位置的值为2.0

t=cvmGet(M,I,j)

2.      直接访问(假设矩阵按照4字节对齐)

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

Int    =M->cols;

Float *data=M->data.f1;

Data[i*n+j]=3.0;

3.      直接访问(当数据的对齐可能存在间隙的时候)

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

Int step=M->Setp/sizeof(float)

 

Float*data=M->data.f1;

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

4.      对于初始化后的矩阵进行直接访问

double a[16];

CvMatMa=cvMat(3,4,CV_64FC1,a);

a[i*4+j]=2.0 

【基本运算】

1.      矩阵之间的运算

CvMat *Ma,*Mb,*Mc;

cvAdd(Ma,Mb,Mc);

cvSub(Ma,Mb,Mc)

cvMatMul(Ma,Mb,Mc);

2.      矩阵之间的元素级运算

CvMat *Ma,*Mb,*Mc;

cvMulMaMb, Mc;

cvDiv(Ma,Mb,Mc);

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

3.      向量乘积

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

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

double vc[3];

CvMatVa=cvMat(3,1,CV_64FC1,va);

CvMatVb=cvMat(3,1,CV_64FC1,vb);

CvMatVc=cvMat(3,1,CV_64FC1,vc);

 

Doubleres=cvDotProduct(&Va&Vb)//向量点乘

cvCrossProduct&Va,&Vb,&vc;//向量叉乘

4.      单一矩阵的运算

CvMat * Ma* Mb

cvTranspos(Ma,Mb);//转置  transposeMa->Mb(转置不能返回给Ma本身

CvScalart=cvTraceMa);

cvInvertMa,Mb;//逆矩阵invMa->Mb

5.      非齐次线性方程求解

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); //solveAx=bfor  x

6.      特征值与特征向量(矩阵为方阵)

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

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

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

cvEigenVV(A,E,l);//l=A的特征值(递减顺序)  E=对应的特征向量(行向量)

7.      奇异值分解(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=UDV^T

标志位使得矩阵U或者V按照转置的形式返回(若不转置可能运算出错)

 

OpenCV视频处理】

1.      从视频流中捕捉一帧画面

(1)      OpenCV支持从摄像头或者视频文件(AVI格式)中捕捉帧画面;

(2)      初始化一个摄像头捕捉器:

CvCapture*capture=cvCaptureFromCAM(0);

(3)      初始化一个视频文件捕捉器:

CvCapture*capture=cvCaptureFromAVI(“infile.avi”;

(4)      捕捉一帧画面:

IplImage *img=0;

If(!cvGrabFrame(capture)){ 捕捉一帧

   Printf(“could not grav a frame\n\7”);

 Exit(0);

}

Img=cvRetrieveFrame(capture);  //检索捕捉到的这一帧给图像img

        若要从多个摄像头中同步捕捉画面,则必须先从每个摄像头中抓取一帧,紧接着要将被捕捉的帧画面恢复到一个IplImage *型图像中。(这个过程可以使用cvQueryFrame()函数一步完成;

(5)      释放视频流捕捉器:

cvReleaseCapture(&capture);

2.      获取/设置视频流信息

(1)      获取视频流设备信息:

CvQueryFrame(capture);//在读取视频流信息之前,要先执行此操作

int       frameH=(int)cvGetXaptureProperty(capture,CV_CAP_PROP_FRAME_HEIGHT);

int       frameW=(int)cvGetCaptureProperty(capture,CV_CAP_PROP_FRAME_WIDTH);

int       fps=(int)cvGetCaptureProperty(capture,CV_CAP_PROP_FPS);

int numFrames=(int)cvGetCaptureProperty(capture,CV_CAP_PROP_FRAME_COUNT);

fps仅仅对于视频文件有效,但是不太准确

(2)      获取帧图信息:

floatposMsec=cvGetCaptureProperty(capture,CV_CAP_PROP_POS_MSEC):

int posFrames=(int)cvGetCaptureProperty(capture,CV_CAP_PROP_POS_FRAMES):

floatposRatio=cvGetCaptureProperty(capture,CV_CAP_PROP_POS_AVI_RATIO);

(3)      设置从视频文件抓取第一帧画面的位置:

CvSetCapturePropertycapture,CV_CAP_PROP_POS_AVI_RATIO,(double)0.9;

3.      保存视频文件

(1)      初始化视频编写器:

CvVideoWriter*writer=0;

int isColor=1;

int fps=25;

int frameW =640;

int frameH=480;

write=cvCreateVideoWriter(“out.avi”,CV_FOURCC(‘P’,’I’,’M’,’1’),

                                                           fpscvSize(frameW,frameH),isColor)

其他的编码器代号包括:

其它的编码器代号包括: CV_FOURCC('P','I','M','1') = MPEG-1 codecCV_FOURCC('M','J','P','G') = motion-jpeg codec (does not work well)CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec CV_FOURCC('D', 'I','V', '3') = MPEG-4.3 codec CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4codec CV_FOURCC('U', '2', '6', '3') = H263 codec CV_FOURCC('I','2', '6', '3') = H263I codec CV_FOURCC('F', 'L', 'V', '1') = FLV1codec 若编码器代号为 -1,则运行时会弹出一个编码器选择框.

(2)      保持视频文件

IplImage *img=0;

Int nFrames=50;

for(i=0;i

{

   cvGrabFrame(capture);  //捕捉一帧

   img=cvRetrieveFrame(capture);//重新保存这帧图像在img

   //img=cvQueryFramecapture);

   cvWriteFrame(write,img);

                 

要查看所抓取到的帧画面,在循环中加入下列语句即可:

                   cvShowImage(“mainWin”img)

                   key=cvWaitKey(20);

注意显示的时候cvWaitkey不能小于20ms,否则画面的显示可能出错。

(3)      释放视频编写器

cvReleaseVideoWriter(&writer);