zoukankan      html  css  js  c++  java
  • Opencv step by step


    CvArr,CvMat,IplImage这三者是继承的关系。

    打开opencv 3.0的源码:


    cvArr


    /* CvArr* is used to pass arbitrary
     * array-like data structures
     * into functions where the particular
     * array type is recognized at runtime:
     */
    typedef void CvArr;

    oh god,它是可变类型的数据


    cvMat

    再看一下cvMat。



    typedef struct CvMat
    {
        int type;
        int step;
    
        /* for internal use only */
        int* refcount;
        int hdr_refcount;
    
        union
        {
            uchar* ptr;
            short* s;
            int* i;
            float* fl;
            double* db;
        } data;
    
    #ifdef __cplusplus
        union
        {
            int rows;
            int height;
        };
    
        union
        {
            int cols;
            int width;
        };
    #else
        int rows;
        int cols;
    #endif
    
    
    #ifdef __cplusplus
        CvMat() {}
        CvMat(const CvMat& m) { memcpy(this, &m, sizeof(CvMat));}
        CvMat(const cv::Mat& m);
    #endif
    
    }
    CvMat;
    
    

    这里先不管C++了,纯c的做法是:


    typedef struct CvMat
    {
        int type;
        int step;
    
        /* for internal use only */
        int* refcount;
        int hdr_refcount;
    
        union
        {
            uchar* ptr;
            short* s;
            int* i;
            float* fl;
            double* db;
        } data;
    
    
        int rows;
        int cols;
    
    }
    CvMat;

    这里,cvMat有几个属性,到底是干什么的呢?

    可以看看它的初始化函数:


    CV_INLINE CvMat cvMat( int rows, int cols, int type, void* data CV_DEFAULT(NULL))
    {
        CvMat m;
    
        assert( (unsigned)CV_MAT_DEPTH(type) <= CV_64F );
        type = CV_MAT_TYPE(type);
        m.type = CV_MAT_MAGIC_VAL | CV_MAT_CONT_FLAG | type;
        m.cols = cols;
        m.rows = rows;
        m.step = m.cols*CV_ELEM_SIZE(type);
        m.data.ptr = (uchar*)data;
        m.refcount = NULL;
        m.hdr_refcount = 0;
    
        return m;
    }
    

    微笑看了之后恍然大悟:


    type是矩阵中每一个数据点的类型。

    cols是矩阵的列数。

    rows当然是行数。

    step是每一行的数据大小(应该是byte数吧)。

    data是一个union的类型,里面是不同类型的指针,这样做的目的应该是可以接收 不同的数据类型吧。

    比如你传了一个float*的指针进去,他就是float*了,反正这个联合体的大小就是sizeof(pointer) = 4了


    internal use的先不管了。


    在其他版本中把rows和height写在union里面的做法应该是做变量的兼容性吧。


    IplImage

    下面来重点看一下这个结构体:


    typedef struct
    #ifdef __cplusplus
      CV_EXPORTS
    #endif
    _IplImage
    {
        int  nSize;             /* sizeof(IplImage) */
        int  ID;                /* version (=0)*/
        int  nChannels;         /* Most of OpenCV functions support 1,2,3 or 4 channels */
        int  alphaChannel;      /* Ignored by OpenCV */
        int  depth;             /* Pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S,
                                   IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported.  */
        char colorModel[4];     /* Ignored by OpenCV */
        char channelSeq[4];     /* ditto */
        int  dataOrder;         /* 0 - interleaved color channels, 1 - separate color channels.
                                   cvCreateImage can only create interleaved images */
        int  origin;            /* 0 - top-left origin,
                                   1 - bottom-left origin (Windows bitmaps style).  */
        int  align;             /* Alignment of image rows (4 or 8).
                                   OpenCV ignores it and uses widthStep instead.    */
        int  width;             /* Image width in pixels.                           */
        int  height;            /* Image height in pixels.                          */
        struct _IplROI *roi;    /* Image ROI. If NULL, the whole image is selected. */
        struct _IplImage *maskROI;      /* Must be NULL. */
        void  *imageId;                 /* "           " */
        struct _IplTileInfo *tileInfo;  /* "           " */
        int  imageSize;         /* Image data size in bytes
                                   (==image->height*image->widthStep
                                   in case of interleaved data)*/
        char *imageData;        /* Pointer to aligned image data.         */
        int  widthStep;         /* Size of aligned image row in bytes.    */
        int  BorderMode[4];     /* Ignored by OpenCV.                     */
        int  BorderConst[4];    /* Ditto.                                 */
        char *imageDataOrigin;  /* Pointer to very origin of image data
                                   (not necessarily aligned) -
                                   needed for correct deallocation */
    
    #ifdef __cplusplus
        _IplImage() {}
        _IplImage(const cv::Mat& m);
    #endif
    }
    IplImage;
    

    可以看出来,这个结构体和cvMat很像。

    下面通过实际操作来understand一下这个结构体:

    #include <cv.h>
    #include <highgui.h>
    
    #define u8 unsigned char
    
    
    void image_operation(IplImage *image)
    {
    	printf("nchannels:%d
    ",image->nChannels);
    	printf("depth:%d
    ",image->depth);
    	/* ./modules/core/include/opencv2/core/types_c.h:
    	 *		#define IPL_DATA_ORDER_PIXEL  0 
    	 */
    	printf("dataOrder:%d
    ",image->dataOrder);
    	printf("%d
    ",image->width);
    	printf("height:%d
    ",image->height);
    	printf("origin:%d
    ",image->origin);
    	printf("widthStep:%d
    ",image->widthStep);
    
    
    	for (int y = 0; y<image->height ; y++) {
    		u8* row = (u8*)(image->imageData + y*image->widthStep);
    		for(int x = 0; x<image->width; x++) {
    			row[3*x + 1] = 0;
    			row[3*x + 2] = 0;
    		}
    	}
    }
    
    int main(int argc,char **argv)
    {
    
    
    	printf("this is image transforming plus
    ");
            IplImage *image;  
            image = cvLoadImage(argv[1]);  
            if(argc != 2)  
            {  
                std::cout << "No image data
    ";  
                return -1;  
            }
    
    	cvNamedWindow("image input");
    	cvNamedWindow("image output");
    	cvShowImage("image input", image);	
    	image_operation(image);
    	cvShowImage("image output", image);	
    	cvReleaseImage(&image);
    	cvWaitKey(0);
    	cvDestroyWindow("image input");
    	cvDestroyWindow("image output");
    
    
    
    
    
    	return 0;
    }
    


    这里读取一个图像,并且将两个通道变成0,结果如下:

    tan@ubuntu:~/cv$ ./TransformImage image/1.jpg 
    this is image transforming plus
    nchannels:3
    depth:8
    dataOrder:0
    400
    height:300
    origin:0
    widthStep:1200




    从结果来看,这里把蓝色通道提取了,再次验证一下就可以发现opencv的存储是 BGR 顺序存储的。

    重要的一个变量是image->widthStep,因为opencv会把图像数据4字节对齐,每过一行需要加上这个值而不是自己进行处理。



  • 相关阅读:
    用Sql添加删除字段,判断字段是否存在的方法
    [转]SQL Server中获得EXEC后面的sql语句或者存储过程的返回值的方法
    sql日记(相关子查询,动态交叉表篇)
    一种迅速从datatable生成excel文件的方法
    系统设计说明书(架构、概要、详细)目录结构
    针对Web系统常用的功能测试方法浅析
    单元测试(UnitTest)入门
    文件操作概览
    C#仿QQ面板的简单实现
    用MD5和SHA1加密字符串
  • 原文地址:https://www.cnblogs.com/tanhangbo/p/4282613.html
Copyright © 2011-2022 走看看