OPENCV_Mat类存取方法(元素访问)
- 格式:doc
- 大小:540.50 KB
- 文档页数:13
opencv mat 用法OpenCV是一个广泛使用的计算机视觉库,它提供了许多功能和工具,用于图像处理、视频处理、特征提取等任务。
在OpenCV中,Mat 是一个非常重要的数据结构,用于存储和操作图像数据。
在本篇文章中,我们将介绍Mat的基本用法,包括创建、读取、写入和操作图像数据。
一、Mat的创建在使用Mat之前,需要先创建它。
OpenCV提供了多种方法来创建Mat对象,可以根据需要选择合适的方法。
常用的创建Mat的方法包括:1.使用zeros()或ones()函数创建指定尺寸的零矩阵或全矩阵。
2.使用imread()函数从文件中加载图像,并将其存储为Mat对象。
3.使用随机数生成器创建具有一定分布的图像数据。
下面是一个简单的示例代码,演示如何使用imread()函数创建Mat对象:```pythonimportcv2#读取图像并创建Mat对象img=cv2.imread('image.jpg')#显示图像cv2.imshow('Image',img)cv2.waitKey(0)```二、Mat的读取和写入使用imread()函数可以从文件中加载图像数据并将其存储为Mat 对象。
同样地,使用imwrite()函数可以将Mat对象中的数据写入文件。
下面是一个简单的示例代码,演示如何使用imwrite()函数将Mat 对象中的数据写入文件:```pythonimportcv2importnumpyasnp#创建一个随机图像数据data=np.random.randint(0,256,(500,500,3),dtype=np.uint8) #创建Mat对象并设置数据mat=cv2.Mat(500,500,CV_8UC3,data)#显示Mat对象的内容cv2.imshow('Mat',mat)cv2.waitKey(0)#将Mat对象写入文件cv2.imwrite('output.jpg',mat)```三、Mat的数据类型和尺寸Mat对象可以存储不同类型的数据,包括单通道和多通道数据。
OpenCV:Mat元素访问方法、性能、代码复杂度以及安全性分析欢迎转载,尊重原创,所以转载请注明出处:/bendanban/article/details/30527785本文讲述了OpenCV中几种访问矩阵元素的方法,在指定平台上给出性能比较,分析每种矩阵元素访问方法的代码复杂度,易用性。
一、预备设置本文假设你已经正确配置了OpenCV的环境,为方便大家实验,在文中也给出了编译源程序的Makefile,其内容如代码段1所示。
采用如代码段2所示的计时函数,这段代码你可以在我之前的博文中找到,abtic() 可以返回微秒(10^-6秒)级,而且兼容Windows和Linux系统。
本文使用彩色图像做实验,所以矩阵是2维的3通道的。
[plain]view plaincopy = g++2.CPPFLAGS = -O3 `pkg-config --cflags opencv`3.CPPLIB = `pkg-config --libs opencv`4.5.OBJS = test.o6.7.main.exe : $(OBJS)8. $(CC) $(CPPFLAGS) $^ -o $@ $(CPPLIB)9.10.test.o: test.cpp11. $(CC) -c $(CPPFLAGS) $^ -o $@12.13.clean:14. rm -rf *.out main.exe *.o15.16.run:17. ./main.exe文件的内容[cpp]view plaincopy1.#if defined(_WIN32) && defined(_MSC_VER)2.#include <windows.h>3.double abtic() {4.__int64 freq;5.__int64 clock;6. QueryPerformanceFrequency( (LARGE_INTEGER *)&freq );7. QueryPerformanceCounter( (LARGE_INTEGER *)&clock );8.return (double)clock/freq*1000*1000;9.}10.#else11.#include <time.h>12.#include <sys/time.h>13.double abtic() {14.double result = 0.0;15.struct timeval tv;16. gettimeofday( &tv, NULL );17. result = _sec*1000*1000 + _usec;18.return result;19.}20.#endif /* _WIN32 */abtic()的定义二、测试算法文中用于测试的算法:将矩阵中每个元素乘以一个标量,写入一个新的矩阵,每个通道操作独立。
opencv中Mat格式的数据访问.atopencv3中图形存储基本为Mat格式,如果我们想获取像素点的灰度值或者RGB值,可以通过image.at<uchar>(i,j)的⽅式轻松获取。
Mat类中的at⽅法对于获取图像矩阵某点的RGB值或者改变某点的值很⽅便,对于单通道的图像,则可以使⽤:image.at<uchar>(i, j)其中有⼀个要注意的地⽅是i对应的是点的y坐标,j对应的是点的x坐标,⽽不是我们习惯的(x,y)来获取或改变该点的值,⽽RGB通道的则可以使⽤:image.at<Vec3b>(i, j)[0]image.at<Vec3b>(i, j)[1]image.at<Vec3b>(i, j)[2]来分别获取B、G、R三个通道的对应的值。
下边的代码实现对图像加椒盐噪声:// created by ning zhang 2018/4/25// The function of this program is to add noise to the image#include <opencv2/opencv.hpp>#include <iostream>using namespace std;using namespace cv;void salt_noise( Mat image, int time );int main ( int argc, char** argv ){Mat image = imread("../lena.jpg",0); //input the gray imageif ( image.empty() ){cout << "Load image error" << endl;return -1;}salt_noise(image, 3000);namedWindow("image", 1);imshow("image", image);waitKey();return 0;}void salt_noise ( Mat image, int time ){for (int k = 0; k < time; k++ ) //time is the number of noise you add{int i = rand() % image.rows;int j = rand() % image.cols;if (image.channels() == 1) //single channel{image.at<uchar>(i,j) = rand() % 255;}else if (image.channels() == 3) //RGB channel{image.at<Vec3b>(i, j)[0] = rand() % 255;image.at<Vec3b>(i, j)[1] = rand() % 255;image.at<Vec3b>(i, j)[2] = rand() % 255;}}}效果图如下所⽰,可以为图⽚增加噪点还有⽐较省时的⽅法使⽤Mat的模板⼦类Mat_<T>,,对于单通道的具体使⽤:Mat_<uchar> img = image;img(i, j) = rand() % 255;对于RGB通道的使⽤:Mat_<Vec3b> img = image;img(i, j)[0] = rand() % 255;img(i, j)[1] = rand() % 255;mg(i, j)[2] = rand() % 255;还可以⽤指针的⽅法遍历每⼀像素:(耗时较⼩)void colorReduce(Mat image, int div = 64){int nrow = image.rows;int ncol = image.cols*image.channels();for (int i = 0; i < nrow; i++){uchar* data = image.ptr<uchar>(i);//get the address of row i;for (int j = 0; j < ncol; j++){data[i] = (data[i] / div)*div ;}}}我们要尤其注意OpenCV坐标系与row&col的关系 (Mat::at(x,y)和Mat::at(Point(x, y))的区别)直接给出对应关系吧row == heigh == Point.ycol == width == Point.xMat::at(Point(x, y)) == Mat::at(y,x)因为还有点的坐标,所以建议在访问时都⽤Mat::at(Point(x, y))这种形式吧,免去了点坐标和⾏列的转换详细说明:1. 坐标体系中的零点坐标为图⽚的左上⾓,X轴为图像矩形的上⾯那条⽔平线;Y轴为图像矩形左边的那条垂直线。
OPENCV对于Mat的理解和操作1,Mat 是⽤来存储图⽚的数据他会把图⽚变成矩阵Mat src;int main(int argc, char** argv){src = imread("F:\\视觉\\opencv\\pic\\MatTest.png");//读图⽚cout << "灰度化后" << endl;cout << src << endl;}矩阵的格式如下图⽚时这样的:⽤dos显⽰是这样的灰度化之后是这样的怎么样是不是看上去有点熟悉没错,灰度化后直接把每个位置的像素的值,组成⼀个矩阵,⽽没有灰度化时是如图⼀所⽰。
2,Mat获取某⼀点坐标的值cout << (int)src.ptr<uchar>(1)[1] << endl;锐化的案例:int cols = (src.cols-1)*src.channels();int rows = src.rows;int channels = src.channels();int offsetx = src.channels();Mat dst1 = Mat::zeros(src.size(), src.type());for (int row = 1; row < (rows - 1); row++){const uchar* previous = src.ptr<uchar>(row - 1);const uchar* current = src.ptr<uchar>(row);const uchar* next = src.ptr<uchar>(row + 1);uchar* output = dst1.ptr<uchar>(row);for (int col = offsetx; col < cols; col++) {output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col])); }}imshow("锐化转化后", dst1);src.ptr<uchar>(row);是获取第⼏⾏的指针src.ptr<uchar>(1)[1];默认是char类型,所以要转成int类型输出才能看得到,不然会输出Hex码表对于的字符信息。
opencv-访问Mat中每个像素的值参考:膜拜⼤佬以下例⼦代码均针对8位单通道灰度图。
1 .ptr和[]操作符Mat最直接的访问⽅法是通过.ptr<>函数得到⼀⾏的指针,并⽤[]操作符访问某⼀列的像素值。
Mat image(rows,cols,CV_8UC1);for (int j=0; j<image.rows; j++){uchar* pdata= image.ptr<uchar>(j);for (int i=0; i<image.cols; i++){uchar data=pdata[i];}}2 .ptr和指针操作除了[]操作符,我们可以使⽤移动指针*++的组合⽅法访问某⼀⾏中所有像素的值。
Mat image(rows,cols,CV_8UC1);for (int j=0; j<image.rows; j++){uchar* pdata= image.ptr<uchar>(j);for (int i=0; i<image.cols; i++){uchar data=*pdata++;}}3 Mat _iterator⽤Mat提供的迭代器代替前⾯的[]操作符或指针,⾎统纯正的官⽅⽅法~1 Mat image(rows,cols,CV_8UC1);23 Mat_<uchar>::iterator it=image.begin<uchar>();4 Mat_<uchar>::iterator itend=image.end<uchar>();56for (;it != itend;++it)7 {8 uchar data=*it;9 }4 图像坐标 atMat image(rows,cols,CV_8UC1);for (int j=0; j<image.rows; j++){for (int i=0; i<image.cols; i++){uchar data=image.at<uchar>(j,i);}}其中,指针*++访问是最快的⽅法;另外迭代器访问虽然安全,但性能远低于指针运算;通过图像坐标(j,i)访问是最慢的。
OpenCV中对Mat的遍历访问与赋值⼀、访问对于Mat的访问有两种⽅式第⼀种,利⽤Mat::at进⾏访问//读取3通道彩⾊图像Mat img = imread("图⽚地址");int px;//读取图像中第⼀⾏第⼀列,Blue通道数据int px = img.at<Vec3b>(0, 0)[0];第⼆种,利⽤Mat的成员ptr指针进⾏访问//读取3通道彩⾊图像Mat img = imread("图⽚地址");//将Mat中的第⼀⾏地址赋予pxVecuchar* pxVec=img.ptr<uchar>(0);//遍历访问Mat中各个像素值int i, j;int px;for (i = 0; i < img.rows; i++){pxvec = img.ptr<uchar>(i);//三通道数据都在第⼀⾏依次排列,按照BGR顺序//依次赋值为1for (j = 0; j < img.cols*img.channels(); j++){px=pxvec[j];//do anything}}⼆、赋值不能⽤Mat::at进⾏赋值,只能⽤ptr对Mat中的像素点进⾏赋值⼀个完整的例⼦如下:#include "stdafx.h"#include <opencv2\core\core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2\imgproc\imgproc.hpp>#include <vector>int main(){//对Mat进⾏遍历赋值//初始化Mat数据结构,256*256,三通道8位(256⾊)图像Mat myimg(256,256,CV_8UC3);//取像素数据⾸地址uchar* pxvec = myimg.ptr<uchar>(0);int i, j;for (i = 0; i < myimg.rows; i++){pxvec = myimg.ptr<uchar>(i);//三通道数据都在第⼀⾏依次排列,按照BGR顺序//依次赋值为1for (j = 0; j < myimg.cols*myimg.channels(); j++){pxvec[j] = 1;}}//展⽰图像imshow("abc", myimg); waitKey(10000);}结果如下:。
opencv中Mat使用,很好,顶!(一)Mat矩阵中数据指针Mat.data是uchar类型指针,CV_8U 系列可以通过计算指针位置快速地定位矩阵中的任意元素。
二维单通道元素可以用Mat::at(i, j)访问,i是行序号,j是列序号。
但对于多通道的非unsigned char类型矩阵来说,以上方法都不好(注:后来知道可以通过类型转换,用指针访问data数据,见后文)。
可以用Mat::ptr()来获得指向某行元素的指针,在通过行数与通道数计算相应点的指针。
参照OpenCV的Mat::at()函数,写了一个访问二维Mat矩阵的两个简单的小函数,没有边界检查。
1#include <opencv2/core/core.hpp>23template<typename ItemType>4ItemType* getMatPointPtr(cv::Mat & src, int i , int j , int c = 0)5{6ItemType* curRow = src.ptr<ItemType>(i); 7return curRow + j * src.channels() + c; 8}9template<typename ItemType>10ItemType getMatPoint(cv::Mat & src, int i , int j , int c = 0)11{12ItemType* curRow = src.ptr<ItemType>(i);13return *(curRow + j * src.channels() + c);14}OpenCV中的Mat::at()代码有严格的边界检测,Mat::ptr()也有边界检测,但代码中没有检测j是否越界。
以上为推荐使用的情况,下边的不推荐使用。
可以通过转换指针类型,访问非uchar类型的Mat元素。
OpenCV使用FileStorage保存Mat数据/************************************************************转自:/mmjwung/article/details/6913540 ************************************************************/在OpenCV2.0以后的版本中,加入了对C++的支持,大大减少了程序代码量,方便了程序编写,也更符合现代编程思想。
在视觉处理过程中,往往需要保存中间数据。
这些数据的数据类型往往并不是整数。
OpenCV的C++接口中,用于保存图像的imwrite只能保存整数数据,且需作为图像格式。
当需要保存浮点数据或XML/YML文件时,OpenCV的C语言接口提供了cvSave函数,但这一函数在C++接口中已经被删除。
取而代之的是FileStorage类。
具体使用方法参照这个例子:矩阵存储[cpp] view plain copy1.Mat mat = Mat::eye(Size(12,12), CV_8UC1);2.FileStorage fs(".\\vocabulary.xml", FileStorage::WRITE);3.fs<<"vocabulary"<<mat;4.fs.release();在另一处,需要加载这个矩阵数据。
代码如下:[cpp] view plain copy1.FileStorage fs(".\\vocabulary.xml", FileStorage::READ);2.Mat mat_vocabulary;3.fs["vocabulary"] >> mat_vocabulary;在存储数据时,fs<<"vocabulary"<<mat将mat矩阵保存在了声明fs对象时制定的xml文件的vocabulary标签下,也可换成其它标签。
Opencv----Mat类∙cv::Mat∙depth/dims/channels/step/data/elemSizeMat矩阵中数据元素的地址计算公式: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(step / elemSize1),M.step[m-1] 总是等于elemSize,M.step1(i)返回的是第i 维的步长,因此M.step1(m-1)总是等于channels,m是M的维度;这里是解释步长step[k]的,步长也可以看作是与第k维的存储单位,在2维的矩阵中,因为存储是按照行的顺序存储的,整个矩阵存储为一个平面,所以第k=0维的步长也就是单位肯定就是一行所占的字节数;如果是3维的话,第0维是按照面为单位来存储的,第1维是按照行为单位来存储的,第2维是按照元素类型为单位存储的,每个元素类型是基本类型(即uchar,float,short等等)与通道数的乘积...;也就是基本数据类型与通道数组成元素,多个元素组成了行,多行组成了面,多个面组成了3维体,多个3维体组成4维超体。
以此类推,如此看来某一维的步长应该等于高一维的步长step*低一维的大小size 。
vii.elemSize : 矩阵中每一个元素的数据大小,如果是n通道,就是(n*数据类型)。
如果Mat中的数据的数据类型是CV_8U 那么elemSize = 1,CV_8UC3 那么elemSize = 3,CV_16UC2 那么elemSize = 4;记住另外有个elemSize1 表示的是矩阵中数据类型的大小,即elemSize / channels 的大小。
图片分析1:考虑二维情况(stored row by row)按行存储上面是一个3 X 4 的矩阵,假设其数据类型为CV_8U,也就是单通道的uchar 类型∙这是一个二维矩阵,那么维度为2 (M.dims == 2);∙M.rows == 3; M.cols == 4;∙sizeof(uchar) = 1,那么每一个数据元素大小为1 (M.elemSize() == 1, M.elemSize1() == 1);∙CV_8U 得到M.depth() == 0, M.channels() == 1;∙因为是二维矩阵,那么step 数组只有两个值,step[0] 和step[1] 分别代表一行的数据大小和一个元素的数据大小,则M.step[0] == 4, M.step[1] == 1;∙M.step1(0) == M.cols = 4; M.step1(1) == 1;假设上面的矩阵数据类型是CV_8UC3,也就是三通道∙M.dims == 2;M.channels() == 3;M.depth() == 0;∙M.elemSize() == 3 (每一个元素包含3个uchar值)M.elemSize1() == 1 (elemSize / channels)∙M.step[0] == M.cols * M.elemSize() == 12, M.step[1] == M.channels() *M.elemSize1() == M.elemSize() == 3;∙M.step(0) == M.cols * M.channels() == 12 ; M.step(1) == M.channels() == 3;图片分析2:考虑三维情况(stored plane by plane)按面存储上面是一个3 X 4 X 6 的矩阵,假设其数据类型为CV_16SC4,也就是short 类型∙M.dims == 3 ; M.channels() == 4 ; M.elemSize1() == sizeof(short) == 2 ;∙M.rows == M.cols == –1;∙M.elemSize() == M.elemSize1() * M.channels() == M.step[M.dims-1] == M.step[2] == 2 * 4 == 8;∙M.step[0] == 4 * 6 * M.elemSize() == 192;∙M.step[1] == 6 * M.elemSize() == 48;∙M.step[2] == M.elemSize() == 8;∙M.step1(0) == M.step[0] / M.elemSize() == 48 / 2 == 96 (第一维度(即面的元素个数) * 通道数);∙M.step1(1) == M.step[1] / M.elemSize() == 12 / 2 == 24(第二维度(即行的元素个数/列宽) * 通道数);∙M.step1(2) == M.step[2] / M.elemSize() == M.channels() == 4(第三维度(即元素) * 通道数);End以上为Mat的存放形式以下为Mat的一些操作方法具体使用方法Fn 1 :利用step。
Code 1:int main(){//新建一个uchar类型的单通道矩阵(grayscale image 灰度图)Mat m(400, 400, CV_8U, Scalar(0));for (int col = 0; col < 400; col++){for (int row = 195; row < 205; row++){//获取第[row,col]个像素点的地址并用 * 符号解析*(m.data + m.step[0] * row + m.step[1] * col) = 255;}}imshow("canvas", m);cvWaitKey();return 0;}Output 1 :Code1只是演示了单通道的情况,对于多通道的例子,请看Code2 然后再看Code3。
Fn 2 :使用Mat::at 函数∙原型template<typename _Tp> inline _Tp& Mat::at(…) //其中参数有多个,也就是说at 函数有多个重载∙返回值为Mat 类型, Mat 有个索引的重载,也就是[] 符号的重载,用这个重载可以定位多通道数据,具体示例可以看下面代码。
下面的代码把红色通道值大于128的颜色的置为白色,左边为原图,右边为处理过后的图。
Code 2 :int main(){Mat img = imread("lena.jpg");imshow("Lena Original", img);for (int row = 0; row < img.rows; row++){for (int col = 0; col < img.cols; col++){/* 注意 Mat::at 函数是个模板函数, 需要指明参数类型, 因为这张图是具有红蓝绿三通道的图,所以它的参数类型可以传递一个 Vec3b, 这是一个存放 3 个 uchar 数据的Vec(向量). 这里提供了索引重载, [2]表示的是返回第三个通道, 在这里是 Red 通道, 第一个通道(Blue)用[0]返回 */if(img.at<Vec3b>(row, col)[2] > 128)img.at<Vec3b>(row, col) = Vec3b(255, 255, 255);}}imshow("Lena Modified", img);cvWaitKey();return 0;}Output 2 :Code 3 :这段代码用的是Fn1 的方式,效果和Code 2 等价,不过是处理三通道数据而已:int main(){Mat img = imread("lena.jpg");imshow("Lena Original", img);for (int row = 0; row < img.rows; row++){for (int col = 0; col < img.cols; col++){//主要是这里的代码if(*(img.data + img.step[0] * row + img.step[1] * col + img.elemSize1() * 2) > 128){//[row, col]像素的第 1 通道地址被 * 解析(blue通道)*(img.data + img.step[0] * row + img.step[1] * col) = 255;//[row, col]像素的第 2 通道地址被 * 解析(green通道), 关于elemSize1函数的更多描述请见 Fn1 里所列的博文链接*(img.data + img.step[0] * row + img.step[1] * col +img.elemSize1()) = 255;//[row, col]像素的第 3 通道地址被 * 解析(red通道)*(img.data + img.step[0] * row + img.step[1] * col +img.elemSize1() * 2) = 255;}}}imshow("Lena Modified", img);cvWaitKey();return 0;}Output 3 = Output 2Fn 3 :使用Mat 的一个模板子类Mat_<typename _Tp> 的( ) 符号重载定位一个像素Code 4 :int main(){Mat m(400, 400, CV_8UC3, Scalar(255, 255, 255));// m2 是 Mat_<Vec3b> 类型的, 因为 m 中元素的类型是 CV_8UC3, 可以用 Vec3b 存储 3 个通道的值// 注意 Mat_<CV_8UC3> 这种写法是错误的, 因为 CV_8UC3 只是一个宏定义// #define CV_8UC3 CV_MAKETYPE(CV_8U, 3)Mat_<Vec3b> m2 = m;// for 循环画一个红色的实心圆for (int y = 0; y < m.rows; y++){for (int x = 0; x < m.rows; x++){if (pow(double(x-200), 2) + pow(double(y-200), 2) - 10000.0 < 0.00000000001){// Mat_ 模板类实现了对()的重载, 可以定位到一个像素m2(x, y) = Vec3b(0, 0, 255);}}}imshow("Image", m);cvWaitKey();return 0;}Output 4 :[ 看上去怎么有点不爽]Fn 4 :使用Mat::ptr 模板函数Code 5 :int main(){Mat m(400, 400, CV_8UC3, Scalar(226, 46, 166)); imshow("Before", m);for (int row = 0; row < m.rows; row++){if (row % 5 == 0){// data 是 uchar* 类型的, m.ptr<uchar>(row) 返回第 row 行数据的首地址// 需要注意的是该行数据是按顺序存放的,也就是对于一个 3 通道的 Mat, 一个像素有// 有 3 个通道值, [B,G,R][B,G,R][B,G,R]... 所以一行长度为:// sizeof(uchar) * m.cols * m.channels() 个字节uchar* data = m.ptr<uchar>(row);for (int col = 0; col < m.cols; col++){data[col * 3] = 102; //第row行的第col个像素点的第一个通道值 Blue data[col * 3 + 1] = 217; // Greendata[col * 3 + 2] = 239; // Red}}}imshow("After", m);cout << (int)m.at<Vec3b>(0, 0)[0] << ','; //利用 Fn 1 介绍的方法输出一下像素值到控制台cout << (int)m.at<Vec3b>(0, 0)[1] << ',';cout << (int)m.at<Vec3b>(0, 0)[2] << endl;cvWaitKey();return 0;}Output 5 :End :Author : Ggicci谢谢阅读,有误希望指正!--OpenCV初学者。