IplImage简介

IplImage简介

结构定义:

typedef struct _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 */
}
IplImage;


typedef struct _IplImage
    {
        int  nSize;         /* IplImage大小 */
        int  ID;            /* 版本 (=0)*/
        int  nChannels;     /* 大多数OPENCV函数支持1,2,3 或 4 个通道 */
        int  alphaChannel;  /* 被OpenCV忽略 */
        int  depth;         /* 像素的位深度: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,
                               IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F 可支持 */
        char colorModel[4]; /* 被OpenCV忽略 */
        char channelSeq[4]; /* 同上 */
        int  dataOrder;     /* 0 - 交叉存取颜色通道, 1 - 分开的颜色通道.
                               cvCreateImage只能创建交叉存取图像 */
        int  origin;        /* 0 - 顶—左结构,
                               1 - 底—左结构 (Windows bitmaps 风格) */
        int  align;         /* 图像行排列 (4 or 8). OpenCV 忽略它,使用 widthStep 代替 */
        int  width;         /* 图像宽像素数 */
        int  height;        /* 图像高像素数*/
        struct _IplROI *roi;/* 图像感兴趣区域. 当该值非空只对该区域进行处理 */
        struct _IplImage *maskROI; /* 在 OpenCV中必须置NULL */
        void  *imageId;     /* 同上*/
        struct _IplTileInfo *tileInfo; /*同上*/
        int  imageSize;     /* 图像数据大小(在交叉存取格式下imageSize=image->height*image->widthStep),单位字节*/
        char *imageData;  /* 指向排列的图像数据 */
        int  widthStep;   /* 排列的图像行大小,以字节为单位 */
        int  BorderMode[4]; /* 边际结束模式, 被OpenCV忽略 */
        int  BorderConst[4]; /* 同上 */
        char *imageDataOrigin; /* 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的 */
    }
    IplImage;


The IplImage is taken from the Intel Image Processing Library, in which the format is native. OpenCV only supports a subset of possibleIplImage formats, as outlined in the parameter list above.

In addition to the above restrictions, OpenCV handles ROIs differently. OpenCV functions require that the image size or ROI size of all source and destination images match exactly. On the other hand, the Intel Image Processing Library processes the area of intersection between the source and destination images (or ROIs), allowing them to vary independently.

Member Function Documentation

IplImage::_IplImage (   )  
inline
IplImage::_IplImage ( const cv::Mat m )  

Member Data Documentation

int IplImage::align

Alignment of image rows (4 or 8). OpenCV ignores it and uses widthStep instead.

int IplImage::alphaChannel

Ignored by OpenCV

int IplImage::BorderConst[4]

Ditto.

int IplImage::BorderMode[4]

Ignored by OpenCV.

char IplImage::channelSeq[4]

ditto

char IplImage::colorModel[4]

Ignored by OpenCV

int IplImage::dataOrder

0 - interleaved color channels, 1 - separate color channels. cvCreateImage can only create interleaved images

int IplImage::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.

int IplImage::height

Image height in pixels.

int IplImage::ID

version (=0)

char* IplImage::imageData

Pointer to aligned image data.

char* IplImage::imageDataOrigin

Pointer to very origin of image data (not necessarily aligned) - needed for correct deallocation

void* IplImage::imageId

" "

int IplImage::imageSize

Image data size in bytes (==image->height*image->widthStep in case of interleaved data)

struct _IplImage* IplImage::maskROI

Must be NULL.

int IplImage::nChannels

Most of OpenCV functions support 1,2,3 or 4 channels

int IplImage::nSize

sizeof(IplImage)

int IplImage::origin

0 - top-left origin, 1 - bottom-left origin (Windows bitmaps style).

struct _IplROI* IplImage::roi

Image ROI. If NULL, the whole image is selected.

struct _IplTileInfo* IplImage::tileInfo

" "

int IplImage::width

Image width in pixels.

int IplImage::widthStep

Size of aligned image row in bytes.


数据的访问存取

下面看一个图像数据存取的例子

例子转自:http://blog.csdn.net/to_utopia/article/details/4856171

1.直接存取: (效率高, 但容易出错)

  • 对单通道字节图像:
    IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
    ((uchar *)(img->imageData + i*img->widthStep))[j]=111;
  • 对多通道字节图像:
    IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
    ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
    ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
    ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R
  • 对多通道浮点图像:
    IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
    ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
    ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
    ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R


2.用指针直接存取 : (在某些情况下简单高效)


  • 对单通道字节图像:
IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
int height     = img->height;
int width      = img->width;
int step       = img->widthStep/sizeof(uchar);
uchar* data    = (uchar *)img->imageData;
data[i*step+j] = 111;
  • 对多通道字节图像:
IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
int height     = img->height;
int width      = img->width;
int step       = img->widthStep/sizeof(uchar);
int channels   = img->nChannels;
uchar* data    = (uchar *)img->imageData;
data[i*step+j*channels+k] = 111;
  • 对多通道浮点图像(假设用4字节调整):
IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
int height     = img->height;
int width      = img->width;
int step       = img->widthStep/sizeof(float);
int channels   = img->nChannels;
float * data    = (float *)img->imageData;
data[i*step+j*channels+k] = 111;


3.使用 c++ wrapper 进行直接存取: (简单高效)

 

  • 对单/多通道字节图像,多通道浮点图像定义一个 c++ wrapper:
    template<class T> class Image
    {
      private:
      IplImage* imgp;
      public:
      Image(IplImage* img=0) {imgp=img;}
      ~Image(){imgp=0;}
      void operator=(IplImage* img) {imgp=img;}
      inline T* operator[](const int rowIndx) {
        return ((T *)(imgp->imageData + rowIndx*imgp->widthStep));}
    };
    
    typedef struct{
      unsigned char b,g,r;
    } RgbPixel;
    
    typedef struct{
      float b,g,r;
    } RgbPixelFloat;
    
    typedef Image<RgbPixel>       RgbImage;
    typedef Image<RgbPixelFloat>  RgbImageFloat;
    typedef Image<unsigned char>  BwImage;
    typedef Image<float>          BwImageFloat;
    

     

  • 单通道字节图像:
    IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
    BwImage imgA(img);
    imgA[i][j] = 111;
    

     

  • 多通道字节图像:
    IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
    RgbImage  imgA(img);
    imgA[i][j].b = 111;
    imgA[i][j].g = 111;
    imgA[i][j].r = 111;
    

     

  • 多通道浮点图像:
    IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
    RgbImageFloat imgA(img);
    imgA[i][j].b = 111;
    imgA[i][j].g = 111;imgA[i][j].r = 111;

其他示例:

直接访问:

对我们来说比较重要的两个元素是:char *imageData以及widthStep。imageData存放图像像素数据,而widStep类似CvMat中的step,表示以字节为单位的行数据长度。

一个m*n的单通道字节型图像,其imageData排列如下:


如果我们要遍历图像中的元素,只需:

  1. IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);  
  2. uchar* tmp;  
  3. for(int i=0;i<img->height;i++)  
  4.     for(int j=0;j<img->width;j++)  
  5.         *tmp=((uchar *)(img->imageData + i*img->widthStep))[j];  

这种直接访问的方法速度快,但容易出错,我们可以通过定义指针来访问。即:

  1. IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);  
  2. ucha* data=(uchar *)img->imageData;  
  3. int step = img->widthStep/sizeof(uchar);  
  4. uchar* tmp;  
  5. for(int i=0;i<img->height;i++)  
  6.     for(int j=0;j<img->width;j++)  
  7.         *tmp=data[i*step+j];  

而多通道(三通道)字节图像中,imageData排列如下:

其中(Bi,Bj)(Gi,Gj)(Ri,Rj)表示图像(i,j)处BGR分量的值。使用指针的遍历方法如下:

  1. IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);  
  2. IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);  
  3. uchar* data=(uchar *)img->imageData;  
  4. int step = img->widthStep/sizeof(uchar);  
  5. int channels = img->nChannels;  
  6. uchar *b,*g,*r;  
  7. for(int i=0;i<img->height;i++)  
  8.      for(int j=0;j<img->width;j++){  
  9.            *b=data[i*step+j*chanels+0];  
  10.            *g=data[i*step+j*chanels+1];  
  11.            *r=data[i*step+j*chanels+2];  
  12.       }  

*如果要修改某像素值,则直接赋值。

使用cvGet2D()函数访问:

cvGet*D系列函数可以用来返回特定位置的数组元素(一般使用cvGet2D),原型如下:
  1. CvScalar cvGet1D( const CvArr* arr, int idx0 );  
  2. CvScalar cvGet2D( const CvArr* arr, int idx0, int idx1 );  
  3. CvScalar cvGet3D( const CvArr* arr, int idx0, int idx1, int idx2 );  
  4. CvScalar cvGetND( const CvArr* arr, int* idx );  
idx0,idx1,idx2分别用来指示元素数组下标,即cvGet2D返回(idx0,idx1)处元素的值。
因此,单通道图像像素访问方式如下:
  1. IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);  
  2. double tmp;  
  3. for(int i=0;i<img->height;i++)  
  4.     for(int j=0;j<img->width;j++)  
  5.         tmp=cvGet2D(img,i,j).val[0];  
多通道字节型/浮点型图像:
  1. IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);  
  2. double tmpb,tmpg,bmpr;  
  3. for(int i=0;i<img->height;i++)  
  4.     for(int j=0;j<img->width;j++){  
  5.         tmpb=cvGet2D(img,i,j).val[0];  
  6.         tmpg=cvGet2D(img,i,j).val[1];  
  7.         tmpr=cvGet2D(img,i,j).val[2];  
  8.     }  
如果是修改元素的值,可用cvSet*D(一般是cvSet2D)函数:
  1. void cvSet1D( CvArr* arr, int idx0, CvScalar value );  
  2. void cvSet2D( CvArr* arr, int idx0, int idx1, CvScalar value );  
  3. void cvSet3D( CvArr* arr, int idx0, int idx1, int idx2, CvScalar value );  
  4. void cvSetND( CvArr* arr, int* idx, CvScalar value );  
这种方法对于任何图像的访问方式是一样的,比较简单,但效率较低,不推荐使用。

参考文档
http://blog.csdn.net/xiaowei_cqu/article/details/7557063#


发布了110 篇原创文章 · 获赞 584 · 访问量 363万+
展开阅读全文

python使用ctypes调用c++函数时怎样传入IPlImage型的数据?

09-28

python 代码 ``` import ctypes import numpy as np import cv2 from Face_Alignment import warp_im, coord5point, resizeimage import time from numpy.ctypeslib import ndpointer start = time.time() so = ctypes.cdll.LoadLibrary lib = so("./build/liblandmark.so") class StructPointer(ctypes.Structure): _fields_ = [("x",ctypes.c_double), ("y",ctypes.c_double)] lib.test.argtypes = [ctypes.c_int,ndpointer(ctypes.c_uint8)] path = "/Huang/images/3.jpeg" img = cv2.imread(path) imge_1 = cv2.cv.LoadImage(path, cv2.cv.CV_LOAD_IMAGE_COLOR) point = lib.landmark(1,imge_1) ``` c++代码: ``` extern "C" { seeta::StructPointer landmark(int argc, IplImage* imge) { seeta::FaceDetection detector("./build/seeta_fd_frontal_v1.0.bin"); detector.SetMinFaceSize(40); detector.SetScoreThresh(2.f); detector.SetImagePyramidScaleFactor(0.8f); detector.SetWindowStep(4, 4); seeta::FaceAlignment point_detector((MODEL_DIR + "seeta_fa_v1.1.bin").c_str()); IplImage *img_grayscale = NULL; cvCvtColor(imge, img_grayscale, CV_BGR2GRAY);//把从python中获得的iplimage参数灰度化传给img_grayscale IplImage *img_color = imge; ``` 运行结果:Traceback (most recent call last): File "test.py", line 27, in <module> point = lib.landmark(1,imge_1) ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: Don't know how to convert parameter 2 这里python中的Iplimage 参数应该如何通过ctypes传入c++中。我的实际问题是怎样把在python中获得的np.array传入c++函数中并赋值给Iplimage型的参数 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览