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字节对齐,每过一行需要加上这个值而不是自己进行处理。



  • 相关阅读:
    Vsftpd 3.0.2 正式版发布
    Putdb WebBuilder 6.5 正式版本发布
    SoaBox 1.1.6 GA 发布,SOA 模拟环境
    pynag 0.4.6 发布,Nagios配置和插件管理
    Percona Playback 0.4,MySQL 负荷回放工具
    xombrero 1.3.1 发布,微型 Web 浏览器
    Hypertable 0.9.6.4 发布,分布式数据库
    libmemcached 1.0.11 发布
    CryptoHeaven 3.7 发布,安全邮件解决方案
    Android Activity生命周期
  • 原文地址:https://www.cnblogs.com/tanhangbo/p/4282613.html
Copyright © 2011-2022 走看看