<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Programming/Opencv on 风中飞舞</title><link>https://blog.perillaroc.wang/categories/programming/opencv/</link><description>Recent content in Programming/Opencv on 风中飞舞</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sun, 30 Aug 2026 20:06:22 +0800</lastBuildDate><atom:link href="https://blog.perillaroc.wang/categories/programming/opencv/index.xml" rel="self" type="application/rss+xml"/><item><title>VideoCapture：OpenCV的读视频类</title><link>https://blog.perillaroc.wang/post/2012/2012-08-23-videocaptureefbc9aopencve79a84e8afbbe8a786e9a291e7b1bb/</link><pubDate>Thu, 23 Aug 2012 21:38:58 +0000</pubDate><guid>https://blog.perillaroc.wang/post/2012/2012-08-23-videocaptureefbc9aopencve79a84e8afbbe8a786e9a291e7b1bb/</guid><description>&lt;p&gt;VideoCapture可以从文件或设备中读取视频。有两种构造方式：&lt;/p&gt;
&lt;p&gt;[cpp]&lt;br&gt;
VideoCapture::VideoCapture(const string&amp;amp; filename);&lt;br&gt;
VideoCapture::VideoCapture(int device);&lt;br&gt;
[/cpp]&lt;br&gt;
第一种是文件名，第二种是设备编号。&lt;br&gt;
VideoCapture::read方法可获取一帧图像&lt;br&gt;
[cpp]&lt;br&gt;
VideoCapture&amp;amp; VideoCapture::operator&amp;raquo;(Mat&amp;amp; image);&lt;br&gt;
bool VideoCapture::read(Mat&amp;amp; image);&lt;br&gt;
[/cpp]&lt;br&gt;
注意，read方法中的Mat是引用，实则是VideoCapture内部解析出来的帧图像的引用，而OpenCV中Mat的复制构造函数和赋值操作符共享数据，仅构造矩阵头，所以读取下一帧后，image中的数据就变化了。如果同时获取多帧图像，应用Mat::clone()方法复制image中的数据，这样就不会丢失了。例如&lt;br&gt;
[cpp]&lt;br&gt;
video_capture.read(frame1);&lt;br&gt;
video_capture.read(frame2);&lt;br&gt;
[/cpp]&lt;br&gt;
此时，frame1和frame2均为后面的一帧，不是想要的那样。我们应该这样&lt;br&gt;
[cpp]&lt;br&gt;
video_capture.read(frame);&lt;br&gt;
frame.clone(frame1);&lt;br&gt;
video_capture.read(frame);&lt;br&gt;
frame.clone(frame2);&lt;br&gt;
[/cpp]&lt;br&gt;
这样，frame1和frame2就存储相邻两帧了。&lt;/p&gt;</description></item><item><title>OpenCV坐标方向</title><link>https://blog.perillaroc.wang/post/2012/2012-08-02-opencve59d90e6a087e696b9e59091/</link><pubDate>Thu, 02 Aug 2012 23:07:08 +0000</pubDate><guid>https://blog.perillaroc.wang/post/2012/2012-08-02-opencve59d90e6a087e696b9e59091/</guid><description>&lt;p&gt;OpenCV坐标方向和Matlab不同，x轴沿水平方向，y轴沿竖直方向。因为Matlab中数据按列存储，而OpenCV中数据按行存储。&lt;/p&gt;
&lt;p&gt;OpenCV函数变量中涉及位置信息的有以下几类：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;x y&lt;br&gt;
点的坐标用(x,y)表示，x在前，y在后，例如&lt;br&gt;
[cpp]CvPoint cvPoint(int x, int y)[/cpp]&lt;br&gt;
cv::Point_与CvPoint类似。&lt;/li&gt;
&lt;li&gt;width height&lt;br&gt;
区域尺寸的宽和高，宽在前，高在后，例如&lt;br&gt;
[cpp]CvSize cvSize(int width, int height)[/cpp]&lt;br&gt;
cv::Size_与CvSize类似。&lt;br&gt;
[cpp]&lt;br&gt;
template&amp;lt;typename _Tp&amp;gt; class Size_&lt;br&gt;
{&lt;br&gt;
public:&lt;br&gt;
typedef _Tp value_type;&lt;br&gt;
…&lt;br&gt;
Size_(_Tp _width, _Tp _height);&lt;br&gt;
…&lt;br&gt;
}&lt;br&gt;
[/cpp]&lt;br&gt;
矩形则综合以上两种类型：&lt;br&gt;
[cpp]CvRect cvRect(int x, int y, int width, int height)[/cpp]&lt;/li&gt;
&lt;li&gt;row column&lt;br&gt;
主要矩阵类型cv::Mat，注意row相当于height，column相当于width，但两者在函数中的位置不同，row和col用于矩阵，width和height用于区域和尺寸。&lt;br&gt;
[cpp]CvMat* cvCreateMatHeader(int rows, int cols, int type)[/cpp]&lt;br&gt;
cv::Mat类型也有用row和column的构造函数&lt;br&gt;
Mat::Mat(int rows, int cols, int type)&lt;br&gt;
但若用cv::Size作为参数，则要注意size中的参数顺序。&lt;br&gt;
最易混淆的就是矩阵Mat函数at中的坐标(i,j)与(x,y)正好相反，i代表行坐标，j代表列坐标。与Matlab中矩阵坐标是相同了，但与Point坐标就相反了，很费劲。下面是Mat::at的原型。&lt;br&gt;
[cpp]&lt;br&gt;
template&lt;typename T&gt; T&amp;amp; Mat::at(int i) const&lt;br&gt;
template&lt;typename T&gt; const T&amp;amp; Mat::at(int i) const&lt;br&gt;
template&lt;typename T&gt; T&amp;amp; Mat::at(int i, int j)&lt;br&gt;
template&lt;typename T&gt; const T&amp;amp; Mat::at(int i, int j) const&lt;br&gt;
template&lt;typename T&gt; T&amp;amp; Mat::at(Point pt)&lt;br&gt;
template&lt;typename T&gt; const T&amp;amp; Mat::at(Point pt) const&lt;br&gt;
template&lt;typename T&gt; T&amp;amp; Mat::at(int i, int j, int k)&lt;br&gt;
template&lt;typename T&gt; const T&amp;amp; Mat::at(int i, int j, int k) const&lt;br&gt;
template&lt;typename T&gt; T&amp;amp; Mat::at(const int* idx)&lt;br&gt;
template&lt;typename T&gt; const T&amp;amp; Mat::at(const int* idx) const&lt;br&gt;
[/cpp]&lt;br&gt;
参数含义如下：&lt;br&gt;
i – Index along the dimension 0&lt;br&gt;
j – Index along the dimension 1&lt;br&gt;
k – Index along the dimension 2&lt;br&gt;
pt – Element position specified as Point(j,i) .&lt;br&gt;
idx – Array of Mat::dims indices.&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>OpenCV中构造Mat矩阵赋值和复制的花销</title><link>https://blog.perillaroc.wang/post/2012/2012-02-27-opencve4b8ade69e84e980a0mate79fa9e998b5e8b58be580bce5928ce5a48de588b6e79a84e88ab1e99480/</link><pubDate>Mon, 27 Feb 2012 20:49:16 +0000</pubDate><guid>https://blog.perillaroc.wang/post/2012/2012-02-27-opencve4b8ade69e84e980a0mate79fa9e998b5e8b58be580bce5928ce5a48de588b6e79a84e88ab1e99480/</guid><description>&lt;p&gt;对OpenCV中的Mat矩阵的用法一直不太清晰，不了解各种操作的花销，尤其是Mat矩阵结构有智能指针的性质，传递参数时不知道是传对象还是传引用，返回结构不知道是直接返回对象还是要用类似指针的结构。这些问题我还搞不懂，也许没有太大的难度，仔细看一下文档就能明白，就因为我懒，所以看不下去，记性不好，看了也忘。&lt;/p&gt;
&lt;p&gt;Mat构造函数种类太多，简单写了一段程序，看看常用的生成Mat矩阵方法的花销有多大。&lt;br&gt;
代码如下：&lt;br&gt;
[cpp] clock_t t1,t2;&lt;br&gt;
t1 = clock();&lt;br&gt;
Mat mat1(10000,5000,CV_64FC1,Scalar::all(0.0));&lt;br&gt;
t2 = clock();&lt;br&gt;
cout&amp;laquo;&amp;ldquo;Mat mat1(10000,5000,CV_64FC1,Scalar::all(0.0))\t&amp;rdquo;&amp;laquo;t2-t1&amp;laquo;endl; { t1 = clock(); Mat mat2(mat1); t2 = clock(); cout&amp;laquo;&amp;ldquo;Mat mat2(mat1)\t&amp;rdquo;&amp;laquo;t2-t1&amp;laquo;endl; } { Mat mat3(500,500,CV_64FC1,Scalar::all(0.0)); t1 = clock(); mat3 = mat1; t2 = clock(); cout&amp;laquo;&amp;ldquo;mat3 = mat1;\t&amp;rdquo;&amp;laquo;t2-t1&amp;laquo;endl; } { Mat mat4; t1 = clock(); mat1.copyTo(mat4); t2 = clock(); cout&amp;laquo;&amp;ldquo;mat1.copyTo(mat4);\t&amp;rdquo;&amp;laquo;t2-t1&amp;laquo;endl; } { Mat mat4; t1 = clock(); mat4 = mat1.clone(); t2 = clock(); cout&amp;laquo;&amp;ldquo;mat4 = mat1.clone();\t&amp;rdquo;&amp;laquo;t2-t1&amp;laquo;endl; } { Mat mat5(10000,5000,CV_32FC1,Scalar::all(0.0)); t1 = clock(); mat1.convertTo(mat5,CV_32FC1); t2 = clock(); cout&amp;laquo;&amp;ldquo;mat1.convertTo(mat5,CV_32FC1);\t&amp;rdquo;&amp;laquo;t2-t1&amp;laquo;endl; }[/cpp] 一个典型的输出。 [cpp]Mat mat1(10000,5000,CV_64FC1,Scalar::all(0.0)) 540 Mat mat2(mat1) 0 mat3 = mat1; 1 mat1.copyTo(mat4); 515 mat4 = mat1.clone(); 465 mat1.convertTo(mat5,CV_32FC1); 488[/cpp] 另一个运行的输出。 [cpp]Mat mat1(10000,5000,CV_64FC1,Scalar::all(0.0)) 391 Mat mat2(mat1) 0 mat3 = mat1; 0 mat1.copyTo(mat4); 433 mat4 = mat1.clone(); 453 mat1.convertTo(mat5,CV_32FC1); 495[/cpp] 从结果中可以看到，拷贝构造函数和赋值的时间可以忽略不计，但Mat::copyTo、Mat::clone、Mat::convertTo等需要申请空间或复制数据的操作就需要大量的时间。 应该研究下OpenCV的源代码，加深对Mat类型的认识。&lt;/p&gt;</description></item></channel></rss>