📄 c+m+b mmvi opencv 编程入门.htm
字号:
<P> </P></LI></UL>
<P></P>
<P></P>
<H1><A>矩阵操作</A> </H1>
<P></P>
<H2><A>分配释放矩阵空间</A> </H2>
<P></P>
<UL>
<LI>综述:
<UL>
<LI>OpenCV有针对矩阵操作的C语言函数. 许多其他方法提供了更加方便的C++接口,其效率与OpenCV一样.
<LI>OpenCV将向量作为1维矩阵处理.
<LI>矩阵按行存储,每行有4字节的校整. </LI></UL>
<P></P>
<LI>分配矩阵空间: <PRE>CvMat* cvCreateMat(int rows, int cols, int type);<BR><BR> type: 矩阵元素类型. 格式为CV_<bit_depth>(S|U|F)C<number_of_channels>. <BR> 例如: CV_8UC1 表示8位无符号单通道矩阵, CV_32SC2表示32位有符号双通道矩阵.<BR><BR> 例程:<BR> CvMat* M = cvCreateMat(4,4,CV_32FC1);<BR></PRE>
<P></P>
<LI>释放矩阵空间: <PRE>CvMat* M = cvCreateMat(4,4,CV_32FC1);<BR>cvReleaseMat(&M);<BR></PRE>
<P></P>
<LI>复制矩阵: <PRE>CvMat* M1 = cvCreateMat(4,4,CV_32FC1);<BR>CvMat* M2;<BR>M2=cvCloneMat(M1);<BR></PRE>
<P></P>
<LI>初始化矩阵: <PRE>double a[] = { 1, 2, 3, 4,<BR> 5, 6, 7, 8,<BR> 9, 10, 11, 12 };<BR><BR>CvMat Ma=cvMat(3, 4, CV_64FC1, a);<BR></PRE>
<P>另一种方法: </P><PRE>CvMat Ma;<BR>cvInitMatHeader(&Ma, 3, 4, CV_64FC1, a);<BR></PRE>
<P></P>
<LI>初始化矩阵为单位阵: <PRE>CvMat* M = cvCreateMat(4,4,CV_32FC1);<BR>cvSetIdentity(M); // 这里似乎有问题,不成功<BR></PRE>
<P></P></LI></UL>
<P></P>
<H2><A>存取矩阵元素</A> </H2>
<P></P>
<UL>
<LI>假设需要存取一个2维浮点矩阵的第(i,j)个元素.
<P></P>
<LI>间接存取矩阵元素: <PRE>cvmSet(M,i,j,2.0); // Set M(i,j)<BR>t = cvmGet(M,i,j); // Get M(i,j)<BR></PRE>
<P></P>
<LI>直接存取,假设使用4-字节校正: <PRE>CvMat* M = cvCreateMat(4,4,CV_32FC1);<BR>int n = M->cols;<BR>float *data = M->data.fl;<BR><BR>data[i*n+j] = 3.0;<BR></PRE>
<P></P>
<LI>直接存取,校正字节任意: <PRE>CvMat* M = cvCreateMat(4,4,CV_32FC1);<BR>int step = M->step/sizeof(float);<BR>float *data = M->data.fl;<BR><BR>(data+i*step)[j] = 3.0;<BR></PRE>
<P></P>
<LI>直接存取一个初始化的矩阵元素: <PRE>double a[16];<BR>CvMat Ma = cvMat(3, 4, CV_64FC1, a);<BR>a[i*4+j] = 2.0; // Ma(i,j)=2.0;<BR></PRE>
<P></P></LI></UL>
<P></P>
<H2><A>矩阵/向量操作</A> </H2>
<P></P>
<UL>
<LI>矩阵-矩阵操作: <PRE>CvMat *Ma, *Mb, *Mc;<BR>cvAdd(Ma, Mb, Mc); // Ma+Mb -> Mc<BR>cvSub(Ma, Mb, Mc); // Ma-Mb -> Mc<BR>cvMatMul(Ma, Mb, Mc); // Ma*Mb -> Mc<BR></PRE>
<P></P>
<LI>按元素的矩阵操作: <PRE>CvMat *Ma, *Mb, *Mc;<BR>cvMul(Ma, Mb, Mc); // Ma.*Mb -> Mc<BR>cvDiv(Ma, Mb, Mc); // Ma./Mb -> Mc<BR>cvAddS(Ma, cvScalar(-10.0), Mc); // Ma.-10 -> Mc<BR></PRE>
<P></P>
<P></P>
<LI>向量乘积: <PRE>double va[] = {1, 2, 3};<BR>double vb[] = {0, 0, 1};<BR>double vc[3];<BR><BR>CvMat Va=cvMat(3, 1, CV_64FC1, va);<BR>CvMat Vb=cvMat(3, 1, CV_64FC1, vb);<BR>CvMat Vc=cvMat(3, 1, CV_64FC1, vc);<BR><BR>double res=cvDotProduct(&Va,&Vb); // 点乘: Va . Vb -> res<BR>cvCrossProduct(&Va, &Vb, &Vc); // 向量积: Va x Vb -> Vc<BR>end{verbatim}<BR></PRE>
<P>注意 Va, Vb, Vc 在向量积中向量元素个数须相同. </P>
<P><BR></P>
<P></P>
<LI>单矩阵操作: <PRE>CvMat *Ma, *Mb;<BR>cvTranspose(Ma, Mb); // transpose(Ma) -> Mb (不能对自身进行转置)<BR>CvScalar t = cvTrace(Ma); // trace(Ma) -> t.val[0] <BR>double d = cvDet(Ma); // det(Ma) -> d<BR>cvInvert(Ma, Mb); // inv(Ma) -> Mb<BR></PRE>
<P></P>
<LI>非齐次线性系统求解: <PRE>CvMat* A = cvCreateMat(3,3,CV_32FC1);<BR>CvMat* x = cvCreateMat(3,1,CV_32FC1);<BR>CvMat* b = cvCreateMat(3,1,CV_32FC1);<BR>cvSolve(&A, &b, &x); // solve (Ax=b) for x<BR></PRE>
<P></P>
<LI>特征值分析(针对对称矩阵): <PRE>CvMat* A = cvCreateMat(3,3,CV_32FC1);<BR>CvMat* E = cvCreateMat(3,3,CV_32FC1);<BR>CvMat* l = cvCreateMat(3,1,CV_32FC1);<BR>cvEigenVV(&A, &E, &l); // l = A的特征值 (降序排列)<BR> // E = 对应的特征向量 (每行)<BR></PRE>
<P></P>
<LI>奇异值分解SVD: <PRE>CvMat* A = cvCreateMat(3,3,CV_32FC1);<BR>CvMat* U = cvCreateMat(3,3,CV_32FC1);<BR>CvMat* D = cvCreateMat(3,3,CV_32FC1);<BR>CvMat* V = cvCreateMat(3,3,CV_32FC1);<BR>cvSVD(A, D, U, V, CV_SVD_U_T|CV_SVD_V_T); // A = U D V^T<BR></PRE>
<P>标号使得 U 和 V 返回时被转置(若没有转置标号,则有问题不成功!!!). </P>
<P></P></LI></UL>
<P></P>
<H1><A>视频序列操作</A> </H1>
<P></P>
<H2><A>从视频序列中抓取一帧</A> </H2>
<P></P>
<UL>
<LI>OpenCV支持从摄像头或视频文件(AVI)中抓取图像.
<P></P>
<LI>从摄像头获取初始化: <PRE>CvCapture* capture = cvCaptureFromCAM(0); // capture from video device #0<BR></PRE>
<P></P>
<LI>从视频文件获取初始化: <PRE>CvCapture* capture = cvCaptureFromAVI("infile.avi");<BR></PRE>
<P></P>
<LI>抓取帧: <PRE>IplImage* img = 0; <BR>if(!cvGrabFrame(capture)){ // 抓取一帧 <BR> printf("Could not grab a frame\n\7");<BR> exit(0);<BR>}<BR>img=cvRetrieveFrame(capture); // 恢复获取的帧图像<BR></PRE>
<P>要从多个摄像头同时获取图像, 首先从每个摄像头抓取一帧. 在抓取动作都结束后再恢复帧图像. </P>
<P></P>
<LI>释放抓取源: <PRE>cvReleaseCapture(&capture);<BR></PRE>
<P>注意由设备抓取的图像是由capture函数自动分配和释放的. 不要试图自己释放它. </P>
<P></P></LI></UL>
<P></P>
<H2><A>获取/设定帧信息</A> </H2>
<P></P>
<UL>
<LI>获取设备特性: <PRE>cvQueryFrame(capture); // this call is necessary to get correct <BR> // capture properties<BR>int frameH = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);<BR>int frameW = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);<BR>int fps = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);<BR>int numFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);<BR></PRE>
<P>所有帧数似乎只与视频文件有关. 用摄像头时不对,奇怪!!!. </P>
<P></P>
<P></P>
<LI>获取帧信息: <PRE>float posMsec = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_MSEC);<BR>int posFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES);<BR>float posRatio = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO);<BR></PRE>
<P>获取所抓取帧在视频序列中的位置, 从首帧开始按[毫秒]算. 或者从首帧开始从0标号, 获取所抓取帧的标号.
或者取相对位置,首帧为0,末帧为1, 只对视频文件有效. </P>
<P></P>
<LI>设定所抓取的第一帧标号: <PRE>// 从视频文件相对位置0.9处开始抓取<BR>cvSetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO, (double)0.9);<BR></PRE>
<P>只对从视频文件抓取有效. 不过似乎也不成功!!!</P>
<P></P></LI></UL>
<P></P>
<H2><A>存储视频文件</A> </H2>
<P></P>
<UL>
<LI>初始化视频存储器: <PRE>CvVideoWriter *writer = 0;<BR>int isColor = 1;<BR>int fps = 25; // or 30<BR>int frameW = 640; // 744 for firewire cameras<BR>int frameH = 480; // 480 for firewire cameras<BR>writer=cvCreateVideoWriter("out.avi",CV_FOURCC('P','I','M','1'),<BR> fps,cvSize(frameW,frameH),isColor);<BR></PRE>
<P>其他有效编码: </P><PRE>CV_FOURCC('P','I','M','1') = MPEG-1 codec<BR>CV_FOURCC('M','J','P','G') = motion-jpeg codec (does not work well)<BR>CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec<BR>CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec<BR>CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec<BR>CV_FOURCC('U', '2', '6', '3') = H263 codec<BR>CV_FOURCC('I', '2', '6', '3') = H263I codec<BR>CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec<BR></PRE>
<P>若把视频编码设为-1则将打开一个编码选择窗口(windows系统下). </P>
<P></P>
<P></P>
<LI>存储视频文件: <PRE>IplImage* img = 0; <BR>int nFrames = 50;<BR>for(i=0;i<nFrames;i++){<BR> cvGrabFrame(capture); // 抓取帧<BR> img=cvRetrieveFrame(capture); // 恢复图像<BR> cvWriteFrame(writer,img); // 将帧添加入视频文件<BR>}<BR></PRE>
<P>若想在抓取中查看抓取图像, 可在循环中加入下列代码: </P><PRE>cvShowImage("mainWin", img); <BR>key=cvWaitKey(20); // wait 20 ms<BR></PRE>
<P>若没有20[毫秒]延迟,将无法正确显示视频序列. </P>
<P></P>
<LI>释放视频存储器: <PRE>cvReleaseVideoWriter(&writer);<BR></PRE>
<P></P></LI></UL></DIV></DIV>
<TABLE cellSpacing=0 border=0>
<TBODY></TBODY></TABLE>
<DIV class=footerLinks>1:55 | <NOBR><A title=单击为此项添加评论。
href="http://yujian5.spaces.live.com/blog/cns!6CDC9EF6CBD6E27C!531.entry#post"
bvItemType="post">添加评论</A></NOBR> | <NOBR><A title=单击以显示此项的评论。
href="http://yujian5.spaces.live.com/blog/cns!6CDC9EF6CBD6E27C!531.entry#comment"
bvItemType="comment">阅读评论 (3)</A></NOBR> | <NOBR><A
title=单击以显示此项的引用通告。
href="http://yujian5.spaces.live.com/blog/cns!6CDC9EF6CBD6E27C!531.entry#trackback"
bvItemType="trackback">引用通告 (0)</A></NOBR> | <NOBR><A
title=在您的共享空间中记录关于此项的日志。
href="javascript:BlogIt('cns!6CDC9EF6CBD6E27C!531');"
bvItemType="">记录它</A></NOBR></DIV>
<DIV class=footer></DIV></DIV></SPAN>
<SCRIPT language=javascript>
var g_spLastMTime = "2006/11/23 10:09:49zh-CN2006-11-30_19.10";
</SCRIPT>
<DIV
class="bvSection ContainerBorder BlogCommentPane SubContainer bvEntryComments bvCommentsPane"
bv:cns="cns!6CDC9EF6CBD6E27C!531" bv:lastcns="cns!6CDC9EF6CBD6E27C!532"
bv:commentcount="3" bv:prevtooltip="单击以查看前 20 项评论"
bv:nexttooltip="单击以查看后 20 项评论">
<DIV class="ContainerPadding TitleBar">
<H5>评论</H5><SPAN class=ControlBox></SPAN></DIV>
<DIV class=Content
style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px"><SPAN
id=ctl02_ctl00_lblComments>
<UL>
<LI id=1cns!6CDC9EF6CBD6E27C!534>
<TABLE>
<TBODY>
<TR>
<TD>
<DIV class=bvContactControl>
<DIV class=ccui id="" align=left valign="top"
uicontact:contactsize="WLThumb1LineMedium"
uicontact:cid="-2095364124398994291"></DIV></DIV></TD>
<TD>
<DIV class="bvCommentText bvwordwrap"><SPAN
class=TextBold>h.qiu</SPAN>
<DIV>
<DIV>鼓励在贴一篇opev CV,directX,open GL的相关比较</DIV>
<DIV>这三个功能感觉差不多么</DIV>
<DIV>真的要去学我都不知道该学哪个了</DIV></DIV>11月23日 11:09<BR><A
href="http://piggy-qiu.spaces.live.com/" target=_blank
rel=nofollow>(http://Piggy-QIU.spaces.live.com/)</A></DIV></TD></TR></TBODY></TABLE>
<LI id=1cns!6CDC9EF6CBD6E27C!533>
<TABLE>
<TBODY>
<TR>
<TD>
<DIV class=bvContactControl>
<DIV class=ccui id="" align=left valign="top"
uicontact:contactsize="WLThumb1LineMedium"
uicontact:cid="4109777764847389594"></DIV></DIV></TD>
<TD>
<DIV class="bvCommentText bvwordwrap"><SPAN
class=TextBold>Linan</SPAN>
<DIV>
<DIV>实在是无语了。。。。只能向Mensch同学好好学习了!!!</D
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -