<学习opencv>opencv数据类型

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.基本数据类型:intfloat (包括简单的矢量和矩阵)(简单几何概念的表示:点、矩形、大小)
    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 { 2346 } { 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 ,12 ,和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::Inpu⁠t​Array 指示此输入未被使用的输入。
某些函数还具有可选的输出数组,您可以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>>

猜你喜欢

转载自www.cnblogs.com/lx17746071609/p/11839688.html