zoukankan      html  css  js  c++  java
  • Opencv(3):基本数据类型

    1.比较简单的原子类型

    结构 成员 意义
    CvPoint int x,y 图像中的点
    CvPoint2D32f float x,y 二维空间中的点
    CvPoint3D32f float x,y,z 三维空间中的点
    CvSize int width,height 图像的尺寸
    CvRect intx,y,width,height 图像的部分区域
    CvScalar double val[4] GBA值

    其中cvScalar是一个特殊例子,它有3个构造函数。第一个是cvScalar(),它需要一个,两个,三个或四个参数并将这些参数传递给数组val[]中的相应元素。

    第二个函数是cvRealScalar(),它需要一个参数,它被传递给val[0],其他值被赋为0,第三个是cvScalarAll(),它需要一个参数并且val[ ]中的4个元素都会设置为这个参数。

    2.矩阵和图像类型

    CvArr->CvMat->IplImage

    CvMat矩阵结构

    在OpenCV中没有向量结构,任何时候需要向量,都只需要一个列矩阵。

    CvMat结构:矩阵头

    typedef struct CvMat {
        int type;
        int step;
        int* fefount;
        union {
            uchar* ptr;
            short* s;
            int* i;
            float* fl;
            double* db;
        }data;
        union {
            int rows;
            int height;
        };
        union {
            int cols;
            int width;
        };
    }CvMat;

    矩阵创建方法:

    1).cvCreateMat(),它由多个原数组组成,如cvCreateMatHeader()何cvCreateData()。cvCreateMatHeader()函数常见CvMat结构,不为数据分配内存,

    而cvCreateData()函数只负责分配数据的内存分配。

    2).只需函数cvCreateMatHeader(),因为已因其他理由分配了内存空间,或因为还不准备分配存储空间。

    3).使用函数cvCloneMat(CvMat*),它依据一个现有矩阵创建一个新的矩阵。当这个矩阵不再需要时,可以调用函数cvReleaseMat(CvMat*)释放它。

    矩阵的创建和释放

    //Create a new rows by cols matrix of type 'type'
    CvMat* cvCreateMat(int rows, int cols, int type);
    //Create only matirx header without allocating data
    CvMat* cvCreateMatHeader(int rows, int cols, int type);
    //Initialize header on existing CvMat structure
    CvMat* cvInitMatHeader(
        CvMat* mat,
        int rows,
        int cols,
        int type,
        void *data = NULL,
        int step = CV_AUTOSTEP
    )
    
    //Like cvInitMatHeader() but allocates CvMat as well
    CvMat cvMat(
        int rows,
        int cole,
        int type,
        void *data = NULL
    );
    
    //Allocate a new matrix just like the matrix 'mat'
    
    CvMat* cvCloneMat(const cvMat* mat);
    void cvReleaseMat(CvMat** mat);

    用固定数据创建一个OpenCV矩阵

    float vals[] = { 0.8,0,5,0.4,0,3 };
    	CvMat rotmat;
    	cvInitMatHeader(
    		&rotmat,
    		2,
    		2,
    		CV_32FC1,
    		vals
    	);
    	
    

      

      一旦创建一个矩阵,便可用它来完成很多事情。最简单的操作就睡查询数组定义和数据访问等。

    查询:

    cvGetElemType(const CvArr* arr) :返回一个整型常数,表示存储在数组里的元素类型

    cvGetDims(const CvArr* arr,int* size=NULL):取出数组以及一个可选择的整型指针,返回维数

    cvGetDimSize(const CvArr* arr,int index):通过一个指示维数的整型简单地返回矩阵在那个维数上矩阵的大小。

    3.矩阵数据的存取

    1)简单的方法

    从矩阵中得到一个元素的最简单的方法是利用宏CV_MAT_ELEM()。这个宏传入矩阵,待提取的元素的类型,行和列数这四个参数,

    返回提取出的元素的值。

    #include<iostream>
    #include<opencv2/core/core.hpp>
    #include<opencv2/highgui/highgui.hpp>
    #include<windows.h>
    using namespace cv;
    using namespace std;
    int main() {
        CvMat* cmat = cvCreateMat(5, 5, CV_32FC1);
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                float element = CV_MAT_ELEM(*cmat, float, i, j);
                cout << element << " ";
            }
            cout << endl;
        }
        system("pause");
        return 0;
    }

    还有一个于此类似的宏CV_MAT_ELEM_PTR(),传入矩阵,待返回元素的行和列号这3个参数,返回指向这个元素的指针。

    该宏和CV_MAT_ELEM()宏的最重要的区别是后者在指针解引用之前将其转化成指定的类型。如果需要同时读取数据和设置数据

    可以直接调用CV_MAT_ELEM_PTR()。但在这种情况先,必须自己将指针转化为恰当的类型。

    利用CV_MAT_ELEM_PTR()为矩阵设置一个数值

      

    CvMat* mat = cvCreateMat(5, 5, CV_32FC1);
    	float element_3_2 = 7.7;
    	*((float*)CV_MAT_ELEM_PTR(*mat, 3, 2)) = element_3_2;
    

      

    但是,这些宏在每次调用的时候都重新计算指针。这意味着要查找指向矩阵基本元素数据区的指针,计算目标数据在矩阵中的相对地址,

    然后将相对位置与基本位置相加。

    2)麻烦的方法

    为了访问普通矩阵中的数据,可以利用cvPtr*D和cvGet*D等函数族,cvPtr*D家族cvPtr1D(),cvPtr2D(),cvPtr3D()...cvPtrND()。前三个函数

    都可接收CvArr*类型的矩阵指针参数,紧随其后的参数是表示索引的整数值,最后一个是可选参数,表示输出值的类型。函数返回一个指

    向所需元素的指针。对于cvPtrND()来说,第二个参数是一个指向一个整数数组的指针,这个数组中包含索引的合适数字。

    cvGet*D

    double cvGEtReal1D(const CvArr* arr,int idx0);
    double cvGetReal2D(const CvArr* arr,int idx0,int idx1);
    double cvGetReal3D(const CvArr* arr,int idx0,int idx1,int idx2);
    double cvGetRealND(const CvArr* arr,int* idx);
    CvScalar cvGet1D(const CvArr* arr,int idx0);
    CvScalar cvGet2D(const CvArr* arr,int idx0,int idx1)
    CvScalar cvGet3D(const CvArr* arr,int idx0,int idx1,int idx2)
    CvScalar cvGetND(const CvArr* arr,int *idx);

    cvGet*D中有四个函数返回的是整数的,另外四个的返回值是CvScalar类型的。这意味着在使用这些函数的时候,会有很大的空间浪费。

    所以,在使用这些函数的时候,会有很大的空间浪费。所以,只是在你认为用这些函数比较方便和高效率的时候才用它们,否则,最好

    用cvPtr*D。

    用cvPtr*D()函数族还有另外一个原因,即可以用这些指针函数访问矩阵中的特定的点,然后由这个点触发,用指针的算术运算得到指向

    矩阵中其他数据的指针。

    4.ImlIage数据结构

    从本质上讲,它是一个CvMat对象,但它还有一些成员变量将矩阵解释为图像。

    typedef struct _IplImage {
    	int nSize;
    	int ID;
    	int nChannels;
    	int alphaChannel;
    	int depth;
    	char colorModel[4];
    	char channelSeq[4];
    	int dataOrder;
    	int origin;
    	int align;
    	int width;
    	int height;
    	struct _IplROI* roi;
    	struct _IplImage* maskROI;
    	void* imageId;
    	struct _IplTileInfo* titleInfo;
    	int imageSize;
    	char* imageData;
    	int widthStep;
    	int BorderMode[4];
    	char* imageDataOrigin;
    }IplImage;
    

      width和height这两个变量很重要,其次是depth和nchannals。depth变量的值取自ipl.h中定义的一组数据,但与在矩阵中看到的对应变量不同。

    因为在图像中,我们往往将深度和通道数分开处理,而在矩阵中,我们往往同时表示它们。可用的深度值如下表所示

    t图像像素类型
    IPL_DEPTH_8U w无符号8位整数(8s)
    IPL_DEPTH_8S y有符号8位整数(8s)
    IPL_DEPTH_16S y有符号16位整数(16s)
    IPL_DEPTH_32s y有符号32位整数(32s)
    IPL_DEPTH_32f 32位浮点数单精度(32f)
    IPL_DEPTH_64f 64位浮点数双精度(64f)

    通道数nChannels可取得值是1,2,3,4

    随后两个重要成员是origin和dataOrder。origin变量可以有两种取值:IPL_ORIGIN_TL或者IPL_ORIGIN_BL,分别设置坐标原点的位置于图像的右上角

    或者左下角。在计算机视觉领域,一个重要的错误来源就是原点位置的定义不同意。具体而言,图像的来源,操作系统,编解码器和存储格式等因素

    都可以影响图像坐标原点的选取。举例来说,你或许认为自己正在从图像上面的脸部附近取样,但实际上却在图像下方的裙子附近取样。避免此类现象

    反正的最好办法是在最开始的时候检查一下系统,在所操作的图像块的地方画点东西试试。

    dataOrder的取值可以是IPL_DATA_ORDER_PIXEL或IPL_DATA_ORDER_PLANE,前者指明数据是将像素点不同通道的值交错排在一起,后者是把所有

    像素通道值排在一起,形成通道平面,再把平面排列起来。

  • 相关阅读:
    压测 swoole_websocket_server 性能
    Laravel本地环境搭建:Homestead开发环境的部署
    laravel5.5框架中视图间如何共享数据?视图间共享数据的两种方法
    laravel框架模型model的创建与使用方法
    laravel学习:主从读写分离配置的实现
    《梦断代码》阅读笔记一
    数组结对开发
    对搜狗输入法的评价
    几个一
    对于大家的评审提出改进方案
  • 原文地址:https://www.cnblogs.com/zuoyou151/p/9374937.html
Copyright © 2011-2022 走看看