OPenCV /*=========================================================================*/ // 了解Opencv 数据类型 /*=========================================================================*/ 包含头文件: #include "opencv2/core/core.h" //C++数据结构和算术例程 #include "opencv2/flann/miniflann.hpp" //近似最近邻匹配函数 #include "opencv2/imgproc/imgproc.hpp" //特定于处理和恢复照片的算法 #include "opencv2/video/photo.hpp" //视频跟踪和背景分割例程 #include "opencv2/features2d/features2d.hpp" //二维功能跟踪支持 #include "opencv2/objdetect/objdetect/hpp" //级联人脸检测器;检测的SVM;系首长;平面斑块检测器 #include "opencv2/calib3d/calib3d.hpp" //校准和立体声 #include "opencv2/ml/ml.hpp" //机器学习:聚类和模式识别 #include "opencv2/highgui/highgui.hpp" //C++图像显示,滑块,按钮,鼠标,I/O #include "opencv2/contrib/contrib.hpp" //用户贡献的代码:肉体检测,模糊均值平移跟踪,自旋图像,自相似特征 DEMO1 - 显示图片 ———————————————————— #include <opencv2/opencv.hpp> //包含每个支持的Open函数的文件 int main() { //读取图像(支持图像格式:JPEG,PNG,BMP,DIB,JPE,PBM,PGM,PPM,SR) Mat img = imread("") ; //可处理单通道,多通道,整数值,浮点值 if (img.empty()) return -1 ; //建立窗口并指定名称 WINDOW_AUTOSIZE/0 设置窗口属性 namedWindow("img",WINDOW_AUTOSIZE) ; //要求程序停下来等待按键 waitKey(0) ; //关闭窗口并释放任何相关的内存使用情况 destroyWindow("img") ; } DEMO2 - 视频 用于从磁盘中播放视频 ———————————————————— #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" using namespace cv ; int main() { namedWindow("Video",WINDOW_AUTOSIZE) ; VideoCapture cap ; //实例化视频捕捉对象 cap.open(string("")) ; //捕获对象被赋予一个字符串,其中包含要打开的视频路径和文件名 Mat frame ; //实例化一个数据对象保存帧 for (;;){ //进入死循环 cap >> frame ; //不断从捕获对象流中逐帧读取视频文件 if (frame.empty()) break ; //检查数据是否实际从视频文件中读取 若没有 则退出视频 imshow("Video",frame) ; //如果是视频帧 成功读入,则显示通过imshow() if (waitKey(33) >= 0) break ; //如果在此期间按下某个键,退出读取循环。否则继续循环 } return ; } DEMO3 - 将轨迹栏滑块添加到基本查看器窗口,以便在视频文件中移动 ———————————————————— #include "opencv4/opencv2/opencv.hpp" //#include "opencv2/highgui/highgui.cpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <fstream> using namespace std ; using namespace cv ; int g_slider_position = 0 ; //[1]定义全局变量保持轨迹栏滑块的位置状态 //以单步模式开始 int g_run = 1; //实例化对象,只要它不等于1,就会显示新的帧 int g_dontset = 0 ; //允许在不触发单步模式情况下更新轨迹栏的位置 VideoCapture g_cap ; //[2]回调访问捕获对象,也定义为全局变量 void onTrackbarSlide(int pos, void*) { //传递pos为新的轨迹栏位置 g_cap.set(CAP_PROP_POS_FRAMES,pos) ; //使用新请求的位置来实际将视频回放推进到新位置 if (!g_dontset) g_run = 1 ; //将程序设置为在下一个新帧进入后进入单步模式 g_dontset = 0 ; } int main(int argc, char ** argv){ namedWindow("Video",WINDOW_AUTOSIZE) ; g_cap.open(string(argv[1])) ; //这些例程允许我们配置VideoCapture对象的各种属性 //用来确定视频中的帧数以及视频图像的宽度和高度 int frames = (int)g_cap.get(CAP_PROP_FRAME_COUNT) ; //传递CAP_PROP_FRAME表明以帧为单位设置读取位置 int tmpw = (int)g_cap.get(CAP_PROP_FRAME_WIDTH) ; //宽度 int tmph = (int)g_cap.get(CAP_PROP_FRAME_HEIGHT) ; //高度 cout << "视频:" << frames << "维度框架:(" << tmpw << "," << tmph << ")" << endl ; //创建轨迹栏 //指定标签和放置轨迹栏的窗口。将变量绑定到轨迹栏,轨迹蓝的最大值(视频中的帧数),移动滑块时的回调 createTrackbar("Position","Video",&g_slider_position,frames,onTrackbarSlide) ; Mat frame ; //实例化一个数据对象保存帧 for (;;){ if (g_run!=0){ g_cap >> frame ; if (frame.empty()) break ; int current_pos = (int)g_cap.get(CAP_PROP_POS_FRAMES) ; g_dontset = 1 ; //设置参数以便下一个轨迹栏回调不会进入单步模式 //调用轨迹栏回调来更新显示的滑块轨迹栏的位置 setTrackbarPos("Position","Video",current_pos) ; imshow("Video",frame) ; g_run -= 1 ; //保持单步模式或者让视频根据用户按键设置的先前状态运行 } char c = (char)cv::waitKey(10) ; if (c = 's') //如果按下S,计入单步模式,允许读取单帧 {g_run = 1; cout << "单步,运行=" << g_run << endl ;} if (c = 'r') //如果按下R,进入连续视频模式 {g_run = -1; cout << "运行模式,运行=" << g_run << endl ;} if (c == 27) break ; //如果按下ESC,程序终止 } return 0 ; } DEMO4 - 在图像显示在屏幕上之前加载并平滑图像 ———————————————————— #include <opencv2/opencv.hpp> void Smooth(const Mat&image){ namedWindow("in",WINDOW_AUTOSIZE) ; //创建输入窗口 namedWindow("out",WINDOW_AUTOSIZE) ; //创建输出窗口 imshow("in",image) ; //显示输入图像 Mat out ; //实例化输出图像矩阵 //图像平滑处理 /*GaussianBlur() blur() median() bilateralFilter()*/ GaussianBlur(image,out,Size(5,5),3,3) ; //输入图像被5*5高斯卷积滤波器模糊并写入out GaussianBlur(out,out,Size(5,5),3,3) ; //out用做输入输出,进行双重模糊 imshow("out",out) ; //显示生成模糊图像 waitKey(0) ; //等待按键 } DEMO5 - 使用pyrDown()创建一个新的图像,该图像是输入图像宽度和高度的一半 ———————————————————— #include <opencv2/opencv.hpp> int main(int argc, char ** argv) { Mat img1, img2 ; namedWindow("img1",WINDOW_AUTOSIZE) ; namedWindow("img2",WINDOW_AUTOSIZE) ; string path = "" ; img = imread(path) ; imshow("img1",img1) ; pyrDown(img1, img2) ; //下采样 imshow("img2",img2) ; waitKey(0) ; } DEMO6 - Canny边缘检测器将其输出写入单通道(灰度)图像 ———————————————————— #include <opencv2/opencv.hpp> int main(int argc, char ** argv) { Mat img_rgb, img_gry,img_cny ; namedWindow("Grey",WINDOW_AUTOSIZE) ; namedWindow("Canny",WINDOW_AUTOSIZE) ; string path = "" ; img_rgb = imread(path) ; cvtColor(img_rgb,img_gry,COLOR_BGR2GRAY) ; //转换颜色空间到 BGB到灰度 imshow("gray",img_gry) ; Canny(img_gry,img_cny,10,100,3,true) ; //边缘检测器生成的图像是输入图像的全尺寸 imshow("canny",img_cny) ; waitKey(0) ; return 0 ; } DEMO7 - 将金字塔向下运算符和canny子程序组合 ———————————————————— cvtColor(img_rgb,img_gry,COLOR_BGR2GRAY) pyrDown(img_gry,img_pyr) ; pyrDown(img_pyr,img_pyr2) ; Canny(img_pyr2, img_cny, 10,100,3,true) ; DEMO8 - 获取和设置像素 ———————————————————— int x = 16 , y = 32 ; Vec3b intensity = img_rgb.at<Vec3b>(y,x) ; uchar blue = intensity[0] ; uchar green = intensity[1] ; uchar red = intensity[2] ; cout << "At(x,y)=(" << x << "," << y << "):(blue,green,blue)=(" << (unsigned int)blue << "," << (unsigned int)green << "," << (unsigned int)red << ")" << endl ; cout << "Gray pixel there is:" << (unsigned int)img_gry.at<uchar>(y,x) << endl ; x /= 4; y /= 4 ; cout << "Pyramid2 pixel there is:" << << (unsigned int)img_pyr2.at<uchar>(y,x) << endl ; img_cny.at<uchar>(x,y) = 128 ; //将canny像素设置为128 DEMO9 - 相同的对象可以从相机或者文件加载视频 ———————————————————— #include <opencv2/opencv.hpp> #include <iostream> using namespace std ; using namespace cv ; int main(int argc,char ** argv) { namedWindow("Video",WINDOW_AUTOSIZE) ; VideoCapture cap ; string path = "" ; if (argc == 1) { cap.open(0) ; //打开第一台相机 } else { cap.open(path) ; } if (!cap.isOpened()){ //检查是否成功 cerr << "Coundn't open capture." << endl ; return -1 ; } } DEMO10 - 用于读取彩色视频并写出对数极化变换后的视频 ———————————————————— //从VideoReader对象中逐帧读取视频,转换帧以对象极坐标格式,并将对象坐标帧一次一个写入新的视频文件 #include <opencv2/opencv.hpp> #include <iostream> using namespace std ; using namespace cv ; int main(int argc,char ** argv){ namedWindow("Video",WINDOW_AUTOSIZE) ; namedWindow("Log_Polar",WINDOW_AUTOSIZE) ; VideoCapture capture(argv[]1) ; //注意:可以通过将摄像头ID作为int来从摄像机捕获 double fps = capture.get(CAP_PROP_FPS) ; Size size( (int)capture.get(CAP_PROP_FRAME_WIDTH) , (int)capture.get(CAP_PROP_FRAME_HEIGHT) ); VideoWriter writer ; /*参数说明 */ //argv[2] 新文件的文件名 //CV_FOURCC('M','J','P','G') 用于压缩视频流的视频编解码器 //fps 重放帧速率 //size 使用图像的大小 writer.open(argv[2],CV_FOURCC('M','J','P','G'),fps, size) ; Mat logpolar_frame,bgr_frame ; for (;;){ capture >> bgr_frame ; if (bgr_frame.empty()) break ; imshow("bgr_frame",bgr_frame) ; logPolar( bgr_frame, //输入颜色框 logpolar_frame, //输出对数极坐标框架 Point2f( //对数极坐标变换的中心点 bgr_frame.cols / 2, //x bgr_frame.rows / 2 //y ), 40, //幅度(比例参数) WARP_FILL_OUTLIERS //用“零”填充异常值 ); imshow("Log_Polar",logpolar_frame) ; writer << logpolar_frame ; if (c == 27) break ; } capture.release() ; } /*=========================================================================*/ // 了解Opencv 数据类型 /*=========================================================================*/ Opencv数据类型: 1.基本数据类型:int、float (包括简单的矢量和矩阵)(简单几何概念的表示:点、矩形、大小) 2.辅助对象:表示更抽de (例如垃圾收de切片的范围对象,以及终止条件等抽象) 3.大型数组的类型:(de基元组件,或者基本数据类型) 例:Mat clasde任何基本元素的任意维数组。 Mat,此类别de例如稀疏矩阵cv::SparseMat类,更自然地适用于非密集数据 4.C++标准模板库(STL)de OPenCV特别依赖于Vector类,许多opencv库函数在其参数列表中都有矢量模板对象。 固定向量类:class cv::Vec<> 基本的容器类,适用于尺寸在编译时已知的小向量。 这允许特别有效的代码来处理小的常见的错误。 大多数情况不适用这种形式,并且存在typedef用于cv::Vec<>模板的常见实例化的别名。 名称类似于: cv::Vec2i 两元素整数向量 cv::Vec3i 三元素整数向量 cv::Vec4d 四元素双精度浮点向量 一般情况下,形式的cv::Vec{2,3,4,6}{b,w,s,i,f,d}是有效的六个数据类型两到四个维度的任何组合和。 固定矩阵类:cv::Matx<> 不用于大型数组,而是设计用于处理某些特定的小矩阵运算。 在计算级视觉中,周围有许多2*2或3*3的小矩阵,并且有少数4*4矩阵用于各种变换。 cv::Matx<>旨在容纳这些类型的对象。 cv::Matx通常是通过以下形式的别名访问cv::Matx{1,2,3,4,6}{1,2,3,4,6}{f,d}。 重要的是注意使用固定矩阵类的维度必须在编译时知道,可以操作高效并消除许多动态内存分配操作。 点类:于固定向量类密切相关,是一种容器,用于其中一种基本类型的两个或者三个值。 点类是从它们自身的模板派生的,因此不是直接来自固定的矢量类,而可以在它们之间进行转换。 点类和固定向量类之间的主要区别: 在于访问的成员 由命名变量(mypoint.x,mypoint.y) 而不是由向量索引(myvec[0],myvec[1])等。 与此一样cv::Vec<>,通常通过别名调用点类来实例化适当的模板。 例如:cv::Point2i cv::Point2f cv::Point2d cv::Point3i cv::Point3f cv::Point3d 该class cv::Scalar本质上是一个四维点。与点类一样,cv::Scalar实际上与可以生成任意四个分量矢量 的模板相关联,但该关键字cv::Scalar具体别名为 具有双精度分量的四分量矢量。 与点类不同,cv::Scalar对象的元素使用整数索引访问,与cv::Vec<>。 这是因为cv::Scalar直接来自cv::Vec<double,4> 实例化的。 点类:用于二维点,用于三维点。 点类的最大优点是它们很简单并且开销很小。 在本地,它们没有定义很多操作,但是在需要时可以将它们转换为更通用的类型。 在大多数程序中,点类通过别名实例化采用像cv::Point2i或之类的形式cv::Point3f。 最后一个字母表示要从中构造点的所需基元。 (b是无符号数,s是短整型,i是一个32位整数,f是32位浮点数,d是一个64位浮点数) —————————————————————————————————————————————————————————————————— 点类 直接支持的操作 —————————————————————————————————————————————————————————————————— 默认构造函数 | cv::Point2i p ; | cv::Point3f p ; —————————————————————————————————————————————————————————————————— 复制构造函数 | Point3f p2(p1) ; —————————————————————————————————————————————————————————————————— 值构造函数 | Point2i p(x0,x1) ; Value constructors | Point3d p(x0,x1,x2) ; —————————————————————————————————————————————————————————————————— 转换为固定的矢量类 | (cv::Vec3f)p ; —————————————————————————————————————————————————————————————————— 成员访问 | PX; PY; //并且是三维的 //点类:pz —————————————————————————————————————————————————————————————————— 点Dot product | float x = p1.dot(p2) ; —————————————————————————————————————————————————————————————————— 双精度点积 | double x = p1.ddot(p2) ; —————————————————————————————————————————————————————————————————— 交叉Cross product| p1.cross(p2) ; —————————————————————————————————————————————————————————————————— 查询点p是否在矩形r内| p.inside(r) ; —————————————————————————————————————————————————————————————————— Scalar —————————————————————————————————————————————————————————————————— 默认构造函数 | cv::Scalar s ; —————————————————————————————————————————————————————————————————— 复制构造函数 | cv::Scalar s2(s1) ; —————————————————————————————————————————————————————————————————— 值构造函数 | Point2i p(x0,x1) ; Value constructors | Point3d p(x0,x1,x2) ; —————————————————————————————————————————————————————————————————— 元素乘法 | s1.mul(s2); —————————————————————————————————————————————————————————————————— (四元数)共轭 | s.conj(); //返回cv::Scalar(s0,-s1,s2,-s2) —————————————————————————————————————————————————————————————————— (四元素)real test | s.isReal(); //(如果s1 == s2 == s3 == 0则返回true) —————————————————————————————————————————————————————————————————— cv::Scalar 中没有出现“强制转换为固定向量类”的操作 这是因为,与点类不同,它 直接从固定向量类模板的实例化继承。 因此,它继承 了固定向量类中的所有向量代数运算,成员访问函数(即)和其他属性。 The size class 大小类:类似于点类。可以转换为它们。两者之间的主要区别在于点类数据成员的命名x和y, 而在尺寸等级对应的数据成员的命名width和heiht。这三个别名规模类cv::Size, cv::Size,cv::Size2i,cv::Size2f。前两个是等效的并且代表整数大小,最后一位是32位浮点数大小。 大小类支持的操作 —————————————————————————————————————————————————————————————————— 默认构造函数 | cv::Size sz ; cv::Sizezi sz ; cv::Size2f sz ; —————————————————————————————————————————————————————————————————— 复制构造函数 | cv::Size sz2(sz1) ; —————————————————————————————————————————————————————————————————— 值构造函数 | cv::Size2f sz(w,h) ; Value constructors| —————————————————————————————————————————————————————————————————— 成员访问 | sz.width ; sz.height ; —————————————————————————————————————————————————————————————————— 计算面积 | sz.area() —————————————————————————————————————————————————————————————————— cv::Rect 矩形类: 矩形类包括点类的成员x和y(表示矩形的左上角)和成员的宽度和高度类(表示矩形的大小)。 但是,矩形类不继承从点或大小类,因此通常它们不从继承运算符。 —————————————————————————————————————————————————————————————————— 默认构造函数 | cv::Rect r ; —————————————————————————————————————————————————————————————————— 复制构造函数 | cv::Rect r2(r1) ; —————————————————————————————————————————————————————————————————— 值构造函数 | cv::Rect(x,y,w,h) ; —————————————————————————————————————————————————————————————————— 从起点和大小构造 | cv::Rect(p,sz) ; —————————————————————————————————————————————————————————————————— 从两个角落构建 | cv::Rect (p1,p2) ; —————————————————————————————————————————————————————————————————— 成员访问 | RX; RY; r.width; r.height ; —————————————————————————————————————————————————————————————————— 计算面积 | r.area() ; —————————————————————————————————————————————————————————————————— 提取左上角 | r.tl() ; —————————————————————————————————————————————————————————————————— 提取右下角 | r.bl() ; —————————————————————————————————————————————————————————————————— 确定点p是否在矩形内 | r.contains(p) —————————————————————————————————————————————————————————————————— Rect还支持各种重载运算符,可以用于计算两个矩形或矩形和另一个对象的几何属性。 —————————————————————————————————————————————————————————————————— 矩形r1和r2的交点 | cv::Rect r3 = r1 & r2 ; r1 &= r2 —————————————————————————————————————————————————————————————————— 包含矩形r1和r2的最小区域矩形 | cv::Rect r3 = r1 | r2 ; r1 |= r2 ; —————————————————————————————————————————————————————————————————— 将矩形r转换为量x | cv::Rect rx = r + x ; r += x ; —————————————————————————————————————————————————————————————————— 按尺寸s给出的量放大矩形r | cv::Rect rs = r + s ; r += s ; —————————————————————————————————————————————————————————————————— 比较矩形r1和r2是否完全相等 | bool eq = (r1 == r2) ; —————————————————————————————————————————————————————————————————— 比较矩形r1和r2的不等式 | bool ne = (r1 != r2) ; —————————————————————————————————————————————————————————————————— cv::RotatedRect class类 otatedRect类是一个容器,它包含一个cv::Point2f 被调用的center , 一个cv::Size2f 被调用的size ,另一个float 被调用的angle,后者代表矩形的旋转center 。 cv::RotatedRect 和之间的一个非常重要的区别cv::Rect 是a cv::RotatedRect 相对于其中心位于“空间”中,而cv::Rect 相对于其左上角的位置。 —————————————————————————————————————————————————————————————————— 默认构造函数 | cv::RotatedRect rr() ; —————————————————————————————————————————————————————————————————— 复制构造函数 | cv::RotatedRect rr2(rr1) ; —————————————————————————————————————————————————————————————————— 从两个角点构建 | cv::RotatedRect (p1,p2) ; —————————————————————————————————————————————————————————————————— 值构造函数 | cv::RotatedRect rr(p,sz,theta) ; 取一个点,一个大小和一个角度 | —————————————————————————————————————————————————————————————————— 成员访问 | rr.center ; rr.size ; rr.angle ; —————————————————————————————————————————————————————————————————— 返回角点列表 | rr.points(pts[4]) ; —————————————————————————————————————————————————————————————————— The fixed matrix classes 固定矩阵类: 固定矩阵类 是给 矩阵的尺寸 在编译时已知(因此“固定”)。 因此,其数据的所有内存都在堆栈上分配,这意味着它们可以快速分配和清理。 对它们的操作很快,并且针对小矩阵(2×2,3×3等)有特别优化的实现。 一般来说,当你表示的东西实际上是你要用矩阵代数做的矩阵时,你应该使用固定矩阵类。 如果您的对象实际上是一个大数据数组,如图像或大量的点列表, 则固定矩阵类不是正确的解决方案; 你应该使用cv::Mat。 cv::Matx : —————————————————————————————————————————————————————————————————— 默认构造函数 | cv::Matx33f m33f ; cv::Matx43d m43d ; —————————————————————————————————————————————————————————————————— 复制构造函数 | cv::Matx22d m22d(n22d) ; —————————————————————————————————————————————————————————————————— 值构造函数 | cv::Matx21f m(x0,x1) ; | cv::Matx44d m(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10) ; —————————————————————————————————————————————————————————————————— 相同元素矩阵 | m33f = cv::Matx33f::all(x) ; —————————————————————————————————————————————————————————————————— 零矩阵 | m23d = cv::Matx23d::zeros() ; —————————————————————————————————————————————————————————————————— 一的矩阵 | m16f = cv::Matx16f::ones() ; —————————————————————————————————————————————————————————————————— 创建单位矩阵 | m33f = cv::Matx33f::eye() ; —————————————————————————————————————————————————————————————————— 创建一个保持另一个对角线的矩阵 | m31f = cv::Matx33f::diag() ; —————————————————————————————————————————————————————————————————— 创建具有正太分布条目的矩阵 | m33f = cv::Matx::nrandn(mean, variance) ; —————————————————————————————————————————————————————————————————— 成员访问 | m(i,j) , (i) ; //一个参数 //仅限一维矩阵 —————————————————————————————————————————————————————————————————— 矩阵代数 | m1 = m0; m0 * m1; m0 + m1; m0 - m1 ; —————————————————————————————————————————————————————————————————— 单子代数 | m * a; a * m; m / a ; —————————————————————————————————————————————————————————————————— 对照 | m1 == m2; m1 != m2 ; —————————————————————————————————————————————————————————————————— 点积 | m1.dot(m2) ; //元素之和 //乘法,m的精度 —————————————————————————————————————————————————————————————————— 点积 | m1.ddot(m2) ; //元素乘法的总和 //双精度 —————————————————————————————————————————————————————————————————— 重塑矩阵 | m91f = m33f.reshape<9,1>() ; —————————————————————————————————————————————————————————————————— 转型操作符 | m44f = (Matx44f)m44d ; —————————————————————————————————————————————————————————————————— 在(i,j)处提取2*2的子矩阵 | m44f.get_minor<2,2>(i,j) ; —————————————————————————————————————————————————————————————————— 提取行i | m14f = m44f.row(i) ; —————————————————————————————————————————————————————————————————— 提取列j | m41f = m44f.col(j) ; —————————————————————————————————————————————————————————————————— 提取矩阵对角线 | m41f = m44f.diag() ; —————————————————————————————————————————————————————————————————— 计算转置 | n44f = m44f.t() ; —————————————————————————————————————————————————————————————————— 反转矩阵 | n44f = m44f.inv(方法) ; //默认方法是:cv::DECOMP_LU —————————————————————————————————————————————————————————————————— 解决线性系统 | m31f = m33f.solve(rhs31f,方法) ; m32f = m33f.sovle<2>(rhs32f,方法) ; //模板形成一个 //默认方法是: DECOMP_LU —————————————————————————————————————————————————————————————————— 每元素乘法 | m1.mul(m2) ; —————————————————————————————————————————————————————————————————— 固定的矢量类 The fixed vector classes 导出固定的矢量类 来自固定矩阵类。 它们实际上只是便利功能cv::Matx<> 。 在适当的C ++继承意义上,说固定向量是正确的 template cv::Vec<> 是一个cv::Matx<> 列数为1的列表。 对于具体的实例的容易获得的别名cv::Vec<> 的形式为 cv::Vec { 2 ,3 ,4 ,6 } { b ,s ,w ,i ,f ,d }, 其中最后一个字符具有通常的含义(加入的w ,表示一个无符号短)。 cv::Vec —————————————————————————————————————————————————————————————————— 默认构造函数 | Vec2s v2s ; Vec6f v6f ; —————————————————————————————————————————————————————————————————— 复制构造函数 | Vec3f u3f(v3f) ; —————————————————————————————————————————————————————————————————— 值构造函数 | Vec2f v2f(x0,x1) ; Vec6d v6d(x0,x1,x2,x3,x4,x5) ; —————————————————————————————————————————————————————————————————— 成员访问 | v4f[i] ; v3w(j) ;//(operator()和operator []都工作) —————————————————————————————————————————————————————————————————— 矢量交叉积 | v3f.cross(u3f) ; —————————————————————————————————————————————————————————————————— 复数类The complex number classes 基本类型中还应包含一个类类型:复数类。 OpenCV复数类与它们不相同,但与相关的类兼容 - 并且可以与之相关 使用STL复数类模板complex<> 。 OpenCV和STL复数类之间最重要的区别在于成员访问。 在STL类,实部和虚部通过成员函数访问real() 和imag(), 而在OpenCV的类,它们是可直接访问(公共)成员变量re 和im 。 cv::Complexf —————————————————————————————————————————————————————————————————— 默认构造函数 | cv::Complexf z1; cv::Complexf z2 ; —————————————————————————————————————————————————————————————————— 复制构造函数 | cv::Complexf z2(z1) ; —————————————————————————————————————————————————————————————————— 值构造函数 | cv::Complexf z1(re0); cv::Complexf(re0,im1) ; —————————————————————————————————————————————————————————————————— 复制构造函数 | cv::Complexf u2f(v2f) ; —————————————————————————————————————————————————————————————————— 成员访问 | z1.re; z1.im ; —————————————————————————————————————————————————————————————————— 复共轭 | z2 = z1.conj() ; —————————————————————————————————————————————————————————————————— 辅助对象 Helper Objects 还有一个非常重要的对象,即“智能”指针对象cv::Ptr 。 展望一下cv::Ptr ,我们将研究垃圾收集系统,它是OpenCV的C ++接口的组成部分。 该系统使我们免于担心在早期基于C的OpenCV接口(即2.1版之前)中如此繁重的对象分配和释放的细节。 cv::TermCriteria class 这些cv::TermCriteria 对象封装了一个或两个停止标准,以便它们可以方便地传递给OpenCV算法函数。 他们有三名成员 变量- type ,maxCount 和epsilon -这 可以直接设置(它们是公共的), 或者更常见的是,只是由构造函数使用表单设置TermCriteria(int type, int maxCount, double epsilon ) 。 变量type 设置为cv::TermCriteria::COUNT 或TermCriteria::EPS 。 你也可以将“或”(即| )两者结合在一起。 该值cv::TermCriteria::COUNT 是其同义词cv::TermCriteria::MAX_ITER , 因此您可以根据需要使用该值。如果终止标准包括cv::TermCriteria::COUNT , 那么您告诉算法在maxCount 迭代后终止。如果终止标准包括cv::TermCriteria::EPS , 那么您告诉算法在与算法的收敛相关的某个度量下降之后终止epsilon 。 所述的 参数具有用于向进行相应的设置 或 使用。typemaxCountepsilon cv::Range class 在cv::Range 类用于指定 连续 序列 整数。cv::Range 对象有两个元素, start并且-通常使用构造函数设置end-类似于cv::TermCriteria- cv::Range( int start, int end ) 。范围均包括其初始值的,但不包括他们的最终价值, 所以cv::Range rng( 0, 4 ) 包括变量0 ,1 ,2 ,和3 ,但不会4 。 使用size() ,您可以找到范围内的元素数量。在前面的例子中,rng.size() 将等于4 。 还有一个成员,empty() 用于测试范围是否没有元素。 最后,cv::Range::all() 可以在需要范围的任何地方使用,以指示对象可用的范围。 cv::Ptr 模板和垃圾收集101 一个非常有用 C ++中的对象类型是“智能”指针。7 这个 指针 允许我们创建对某事物的引用,然后传递它。 您可以创建更多对该事物的引用,然后 将计算所有这些引用。 由于引用超出范围,智能指针的引用计数递减。 一旦所有引用(指针的实例)消失,“事物”将自动被清除(解除分配) [运行过程] 首先,为要“包装”的类对象定义指针模板的实例。 您可以使用cv::Ptr<Matx33f> p( new cv::Matx33f ) 或等调用来执行此操作cv::Ptr<Matx33f> p = makePtr<cv::Matx33f>() 。 模板对象的构造函数获取指向要指向的对象的指针。一旦你这样做,你就有了一个智能指针p , 它是一种类似指针的对象,你可以传递它并像普通指针一样使用(即它支持诸如operator*() 和 之类的运算符operator->() )。一旦拥有p ,您可以创建相同类型的其他对象, 而不向它们传递指向新对象的指针。例如,您可以创建Ptr<Mat33f> q ,并在分配值的p 时间q 在幕后的某个地方,智能指针的“智能”动作发挥作用。你看,就像通常的指针一样, 那里仍然只有一个实际的cv::Mat33f 对象,p 并且q 都指向。 所不同的是,这两个p并q 知道他们是两个指针中的每一个。 应该p 消失(例如通过超出范围),q 知道它是对原始矩阵的唯一剩余参考。 如果q 应该消失并且它的析构函数被调用(隐式),q 会知道这是剩下的最后一个,它应该释放原始矩阵。 您可以将此视为建筑物中最后一个负责关灯和锁门的人(在这种情况下,也将建筑物烧毁到地面)。 [注意]大师的提示: 一个严肃的程序员可能会担心引用计数的递增和递减可能不足以使Ptr<>模板在多线程应用程序中安全。 但是,情况并非如此,并且Ptr<> 是线程安全的。 类似地,OpenCV中的其他引用计数对象在同样的意义上都是线程安全的 cv::Exception类和异常处理 OpenCV使用异常来处理错误。 OpenCV定义 它自己的异常类型, cv::Exception 它是从STL异常类派生的std::exception 。 实际上,这个异常类型没有什么特别之处,除了在cv:: 命名空间中, 因此可以与其他也从中派生的对象区分开来std::exception 。 类型cv::Exception 有成员code ,err ,func ,file ,和line , 其中(分别)是一个数字错误代码,表明产生的例外,其中发生错误的函数的名称, 该文件的错误的性质的字符串,其中该错误发生了,并且整数表示该文件中发生错误的行。 err , func 和file 都是STL字符串。 cv::DataType<>模板 当OpenCV库运行时 需要 传达特定数据类型的概念,他们通过创建类型的对象来实现cv::DataType<> 。 cv::DataType<> 本身是一个模板,因此传递的实际对象是该模板的特化。 模板类定义 : DataType template<typename _Tp> class DataType { typedef _Tp value_type; typedef value_type work_type; typedef value_type channel_type; typedef value_type vec_type; enum { generic_type = 1, depth = -1, channels = 1, fmt = 0, type = CV_MAKETYPE(depth, channels) }; }; 首先,我们可以看到这cv::DataType<> 是一个模板,并期望专门用于一个名为的类_Tp 。 然后它有四个typedef 语句,允许 在编译时cv::DataType<> 从cv::DataType<>实例化对象中提取类型以及其他一些相关类型。 在模板定义中,这些都是相同的,但我们将在我们的模板专业化示例中看到它们不必(通常不应该)。 这些是,所述的数目,格式,和 generic_typedepthchannelsfmttype 。 要了解所有这些组件的含义,我们cv::DataType<> 将从core.hpp中查看两个示例特化 。 第一个是以下cv::DataType<> 定义float : template<typename _Tp> class DataType { typedef _Tp value_type; typedef value_type work_type; typedef value_type channel_type; typedef value_type vec_type; enum { generic_type = 1, depth = -1, channels = 1, fmt = 0, type = CV_MAKETYPE(depth, channels) }; }; 首先要注意的是,这是C ++内置类型的定义。 对内置类型进行此类定义很有用,但我们也可以将它们用于更复杂的对象。 在这种情况下,value_type 当然是float 和work_type ,channel_type 和vec_type 都是相同的。 cv::InputArray和cv::OutputArray类 许多OpenCV函数将数组作为参数并返回数组作为返回值,但在OpenCV中,有许多种类的数组。 OpenCV的支持一些小数组类型(cv::Scalar ,cv::Vec ,cv::Matx )和STL的std::vector<> (大数组类型cv::Mat 和cv::SparseMat)。为了防止界面变得过于复杂(和重复), OpenCV定义了类型cv::InputArray 和cv::OutputArray 。 实际上,这些类型对于库支持的许多数组形式而言意味着“上述任何一种”。 甚至有一个cv::InputOutputArray ,为就地计算指定一个数组。 cv::InputArray 和之间的主要区别在于cv::OutputArray 假设前者const (即,只读)。 您通常会在库例程的定义中看到这两种类型。 您不会自己使用它们,但是当您被介绍到库函数时,它们的存在意味着您可以使用任何数组类型, 包括单个数组,cv::Scalar 结果应该是您所期望的。 相关的cv::InputArray 是特殊的cv::noArray() 返回一个的 函数cv::InputArray 。 返回的对象可以传递给任何需要cv::InputArray 指示此输入未被使用的输入。 某些函数还具有可选的输出数组,您可以cv::noArray() 在不需要相应输出时传递。 效用函数 Utility Functions 除了提供专门的原始数据类型,OpenCV库也提供了 一些专门的功能, 可用于更有效地处理计算机视觉应用中常见的数学和其他操作。在库的上下文中,这些被称为实用函数 。 实用程序功能包括用于数学运算,测试,错误生成,内存和线程处理,优化等的工具。 【实用程序和系统功能】 功能 描述 —————————————————————————————————————————————————————————————————— cv::alignPtr() 将指针与指定的字节数对齐 —————————————————————————————————————————————————————————————————— cv::alignSize() 将缓冲区大小与给定的字节数对齐 —————————————————————————————————————————————————————————————————— cv::allocate() 分配C风格的对象数组 —————————————————————————————————————————————————————————————————— cvCeil() a 圆形浮点数x 到最小整数不小于x —————————————————————————————————————————————————————————————————— cv::cubeRoot() 计算数字的立方根 —————————————————————————————————————————————————————————————————— cv::CV_Assert() 如果给定条件不为真,则抛出异常 —————————————————————————————————————————————————————————————————— CV_Error() 用于构建cv::Exception (从固定字符串)并抛出它的宏 —————————————————————————————————————————————————————————————————— CV_Error_() 用于构建cv::Exception (从格式化的字符串)并抛出它的宏 —————————————————————————————————————————————————————————————————— cv::deallocate() 释放C风格的对象数组 —————————————————————————————————————————————————————————————————— cv::error() 指出错误并抛出异常 —————————————————————————————————————————————————————————————————— cv::fastAtan2() 以度为单位计算矢量的二维角度 —————————————————————————————————————————————————————————————————— cv::fastFree() 释放内存缓冲区 —————————————————————————————————————————————————————————————————— cv::fastMalloc() 分配对齐的内存缓冲区 —————————————————————————————————————————————————————————————————— cvFloor() 圆形浮点数x 到最接近的整数不大于x —————————————————————————————————————————————————————————————————— cv::format() 使用sprintf 类似格式创建STL字符串 —————————————————————————————————————————————————————————————————— cv::getCPUTickCount() 从内部CPU计时器获取计数 —————————————————————————————————————————————————————————————————— cv::getNumThreads() 计算OpenCV当前使用的线程数 —————————————————————————————————————————————————————————————————— cv::getOptimalDFTSize() 计算您计划传递到的数组的最佳大小 cv::DFT() —————————————————————————————————————————————————————————————————— cv::getThreadNum() 获取当前线程的索引 —————————————————————————————————————————————————————————————————— cv::getTickCount() 从系统获取滴答计数 —————————————————————————————————————————————————————————————————— cv::getTickFrequency() 每秒获得数字或刻度(请参阅cv::getTickCount() ) cvIsInf() 检查浮点数x 是否为无穷大 —————————————————————————————————————————————————————————————————— cvIsNaN() 检查浮点数x 是否为“非数字” —————————————————————————————————————————————————————————————————— cvRound() 将浮点数x舍 入为最接近的整数 —————————————————————————————————————————————————————————————————— cv::setNumThreads() 设置OpenCV使用的线程数 —————————————————————————————————————————————————————————————————— cv::setUseOptimized() 启用或禁用优化代码(SSE2等)的使用 —————————————————————————————————————————————————————————————————— cv::useOptimized() 指示优化代码启用的状态(请参阅cv::setUseOptimized() ) —————————————————————————————————————————————————————————————————— cv::alignPtr() template <T> T * cv :: alignPtr(//返回T *类型的对齐指针 T * ptr,//指针,未对齐 int n = sizeof(T)//与块大小对齐,幂为2 ); 给定任何类型的指针,此函数计算一个根据以下计算对齐相同类型的指针: (T *)(((size_t)ptr + n + 1)&-n) cv::alignSize() size_t cv :: alignSize(//最小尺寸> ='sz'可被'n'整除 size_t sz,//缓冲区的大小 int n = sizeof(T)//与块大小对齐,幂为2 ); 给定一个数字n (通常是一个回报 from sizeof() )和缓冲区 的大小sz , cv::alignSize()计算此缓冲区的大小,以便包含整数个大小的对象n - 即大于或等于可sz 被整除的最小数n。 使用以下公式: (sz + n-1)&-n cv::allocate() template <T> T * cv :: allocate(//返回指向已分配缓冲区的指针 size_t sz //缓冲区大小,sizeof(T)的倍数 ); 该功能cv::allocate() 功能相似 到的阵列形式new , 因为它 分配n 类型对象的C风格数组,T 为每个对象调用默认构造函数,并返回指向数组中第一个对象的指针。 cv::deallocate() template <T> void cv :: deallocate( T * ptr,//指向缓冲区释放的指针 size_t sz //缓冲区大小,sizeof(T)的倍数 ); 该功能cv::deallocate() 功能相似 到数组形式delete,因为它解除了C n 类型的对象数组T , 并为每个对象调用析构函数。cv::deallocate() 用于释放分配的对象cv::allocate() 。 n 传递给的元素数cv::deallocate() 必须与最初分配的对象数相同cv::allocate() 。 cv::astAtan2() float cv :: fastAtan2(//返回值是32位浮点数 float y,// y输入值(32位浮点数) float x // x输入值(32位浮点数) ); 这个函数计算 一x,y 对的反正切并返回 从原点到指示点的角度。结果报告在度从0.0 到360.0 ,包容0.0 但不包括的360.0 。 cvCeil() int cvCeil(//返回最小的int> = x float x //输入值(32位浮点数) ); 给定一个浮点数x ,cvCeil() 计算 不小于的最小整数x 。 如果输入值超出可由32位整数表示的范围,则结果是未定义的。 cv::cubeRoot() float cv :: cubeRoot(//返回值是32位浮点数 float x //输入值(32位浮点数) ); 这个函数计算争论的立方根x 。x 正确处理负值(即返回值为负)。 cv :: CV_Assert()和CV_DbgAssert() //示例 CV_Assert(x!= 0) CV_Assert() 是一个将测试表达式的宏 传递给它,如果该表达式求值为False (或0 ),它将抛出异常。 该CV_Assert() 宏始终测试。或者,您可以使用CV_DbgAssert(),仅在调试编译中进行测试。 cv :: CV_Error()和CV_Error_() //示例 CV_Error(ecode,estring) CV_Error_(ecode,fmt,...) 宏CV_Error() 允许您传入 一个错误 代码ecode 和固定的C风格字符串estring , 然后将其打包成一个cv::Exception 然后传递cv::error() 给要处理的字符串。CV_Error_() 如果需要动态构造消息字符串,则使用变量宏。CV_Error_() 接受相同ecode 的CV_Error() , 但随后期望一个sprintf() 风格格式字符串随后的参数个数可变,如将被预期sprintf() 。 cv::error() void cv::error( const cv::Exception& ex //抛出异常 ); 这个功能是主要是来自CV_Error() 和CV_Error_() 。 如果您的代码是在非调试版本中编译的,那么它将抛出异常ex 。 如果您的代码是在调试版本中编译的,那么它会故意引发内存访问冲突 ,以便执行堆栈和所有参数可用于您运行的任何调试器。 您可能不会cv::error() 直接调用,而是依赖宏CV_Error() 并CV_Error_() 为您抛出错误。 这些宏获取您希望在异常中显示的信息,为您打包,并将生成的异常传递给cv::error() 。 CV :: fastFree() void cv :: fastFree( void * ptr //指向要释放的缓冲区的指针 ); 此例程释放缓冲区 分配cv::fastMalloc() (覆盖下一个)。 CV :: fastMalloc() void * cv :: fastMalloc(//指向已分配缓冲区的指针 size_t size //要分配的缓冲区大小 ); cv::FastMalloc() 工作正常 就像malloc() 你熟悉的那样,除了它通常更快,它确实缓冲大小对齐。 这意味着如果传递的缓冲区大小超过16个字节,则返回的缓冲区将与16字节边界对齐。 cvFloor() int cvFloor(//返回最大的int <= x float x //输入值(32位浮点数) }; 给定一个浮点数x ,cv::Floor() 计算最大值 整数不大于x 。 如果输入值超出可由32位整数表示的范围,则结果是未定义的。 cv::format() string cv :: format(//返回STL-string const char * fmt,//格式化字符串,作为sprintf() ... // vargs,as sprintf() ); 这个功能是 sprintf() 与标准基本相同库, 但不是要求来自调用者的字符缓冲区,它构造一个STL字符串对象并返回它。 对于Exception()构造函数(在其参数中需要STL字符串)格式化错误消息特别方便。 cv::getCPUTickCount() int64 cv :: getCPUTickCount(void); // long int CPU用于滴答计数 此函数报告这些体系结构上的CPU滴答数 具有这样的构造(包括但不限于x86架构)。 然而,重要的是要知道,在许多体系结构中,此函数的返回值很难解释。 特别是,因为在多核系统上,一个线程可以在一个内核上休眠并在另一个内核上唤醒, 结果与两个后续调用之间的差异cv::getCPUTickCount() 可能会产生误导或完全无意义。 因此,除非您确定自己知道自己在做什么,否则最好使用cv::getTickCount() 定时测量。 此功能最适用于初始化随机数生成器等任务。 cv::getNumThreads() int cv :: getNumThreads(void); //分配给OpenCV的总线程数 返回当前使用的线程数 通过OpenCV。 cv::getOptimalDFTSize() int cv :: getOptimalDFTSize(int n); //用于dft的最佳大小数组,> = n 当你调用cv::dft()时 , OpenCV用来计算变换的算法对传递给的数组的大小非常敏感cv::dft() 。 优选的大小确实遵循它们生成的规则,但是该规则足够复杂, 以至于每次都计算正确的大小以填充阵列(最多)是烦恼。 该函数cv::getOptimalDFTSize() 将您传递给的数组的大小作为参数cv::dft(), 并返回应传递给的数组的大小cv::dft() 。 OpenCV使用此信息创建一个更大的数组,您可以在其中复制数据并用零填充其余数据。 cv::getThreadNum() int cv :: getThreadNum(void); // int,此特定线程的id 如果您的OpenCV库是使用OpenMP支持编译的,那么它将会 返回当前正在执行的线程的索引(从零开始)。 cv::GetTickCount的() int64 cv :: getTickCount(void); // long int CPU用于滴答计数 这个功能 返回相对于某些与体系结构相关的时间的滴答计数。 然而,刻度的速率也取决于架构和操作系统; 每个滴答的时间可以通过cv::getTickFrequency() 计算。此功能优于cv::getCPUTickCount() 大多数计时应用程序,因为它不受低级问题的影响, 例如运行您的线程的核心和CPU频率的自动限制(大多数现代处理器出于电源管理的原因)。 cv::getTickFrequency() double cv :: getTickFrequency(void); //以秒为单位记录频率为64位 何时cv::getTickCount() 用于时序分析, 一般来说,刻度的确切含义取决于架构。该函数cv::getTickFrequency() 计算时钟时间(即秒)和抽象“滴答”之间的转换。 [注意] 要计算某些特定事物发生所需的时间(例如要执行的函数),只需要cv::getTickCount() 在函数调用之前和之后调用,减去结果,然后除以值cv::getTickFrequency() 。 cvIsInf() int cvIsInf(double x); //如果x是IEEE754“infinity”,则返回1 返回值cvIsInf() 是1 if x 是加号还是减号 无穷大和0 其他。无穷大测试是IEEE754标准所暗示的测试。 cvIsNaN() int cvIsNan(double x); //如果x是IEEE754则返回1“不是数字” 该 返回值cvIsNaN() 是1 if x 是“不是数字”,0 否则。NaN测试是IEEE754标准所暗示的测试。 cvRound() int cvRound(double x); //返回最接近'x'的整数 给定一个浮点数x ,cvRound() 计算整数 最接近x 。如果输入值超出可由32位整数表示的范围, 则结果是未定义的。在OpenCV 3.0中有重载cvRound( float x)(以及cvFloor 和cvCeil),这在ARM上更快。 cv::setNumThreads() void cv :: setNumThreads(int nthreads); //设置OpenCV可以使用的线程数 使用OpenMP支持编译OpenCV时,此功能 设置OpenCV将在并行OpenMP区域中使用的线程数。线程数的默认值是CPU上的逻辑核心数(即,如果我们有四个核心,每个核心有两个超线程,默认情况下将有八个线程)。如果nthreads 设置为0 ,则线程数将返回到此默认值。 cv::setUseOptimized() void cv :: setUseOptimized(bool on_off); //如果为false,请关闭优化的例程 虽然早期版本的OpenCV依赖 用于访问高性能优化的外部库(例如IPP,Intel Performance Primitives库) 例如SSE2指令,后来的版本越来越多地转向在OpenCV本身中包含该代码。默认情况下,启用这些优化例程的使用,除非您在构建库安装时专门禁用它们。但是,您可以随时打开和关闭这些优化的使用cv::setUseOptimized() 。 [注意] 优化使用的全局标志的测试在OpenCV库函数内部以相对较高的级别完成。这意味着您不应该cv::setUseOptimized() 在任何其他例程运行时调用(在任何线程上)。只有当您确定自己知道什么是什么以及什么不运行时,您应确保调用此例程,最好是从应用程序的最顶层开始。 cv::useOptimized() bool cv :: useOptimized(void); //如果启用了优化,则返回true 在任何时候,你 可以检查全局标志的状态,cv::setUseOptimized() 通过调用可以使用高性能优化 (请参阅参考资料)cv::useOptimized() 。True 仅在当前启用了这些优化时才会返回; 否则,此功能将返回False 。 [模板结构] OpenCV提供了您可以使用的类型。您也可以使用STL复杂类型intintcv::Complexstd::complex, 这与OpenCV毫无关系。对于您自己的其他类型的建筑也是如此。 此相同的概念推广到其他类型的模板,如cv::Scalar_<> 和cv::Rect_<>,以及cv::Matx_<>和cv::Vec_<> 。 在自己实例化这些模板时,必须提供用于组成模板的单一类型,以及(在相关时)模板的尺寸。 常用的固定长度模板 功能 描述 —————————————————————————————————————————————————————————————————— cv::Point_<Type T> 由一对类型的对象组成的点T 。 —————————————————————————————————————————————————————————————————— cv::Rect_<Type T> 所有类型的位置,宽度和高度T 。 —————————————————————————————————————————————————————————————————— cv::Vec<Type T, int H> 一组H 类型的对象T 。 —————————————————————————————————————————————————————————————————— cv::Matx<Type T, int H, int W> 一组H * W 类型的对象T 。 —————————————————————————————————————————————————————————————————— cv::Scalar_<Type T> 一组四个类型的对象T (相同cv::Vec<T, 4> )。 ——————————————————————————————————————————————————————————————————
本文摘录自<<学习opencv>>