opencv学习笔记(八)-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;

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
depth变量:像素的深度。深度值有:

#define IPL_DEPTH_1U     1
#define IPL_DEPTH_8U     8
#define IPL_DEPTH_16U   16
#define IPL_DEPTH_32F   32

#define IPL_DEPTH_8S  (IPL_DEPTH_SIGN| 8)
#define IPL_DEPTH_16S (IPL_DEPTH_SIGN|16)
#define IPL_DEPTH_32S (IPL_DEPTH_SIGN|32)

通俗一点讲就是像素的取值大小,例如:IPL_DEPTH_8U 即代表有8位数据,最大值256,即一个像素的颜色等级分为256种。从0到256不断加深。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

nChannels变量:图像通道(通道的概念之前有介绍)。
彩色图像的排列方式:
彩色图像一般是由3通道表示。3通道表示一个像素点有三个值,分别对应R,G,B.RGB决定该像素点的颜色。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
一下其他的重要参数:
imageData 包含一个指向第一行图像数据的指针。
widthStep是指一个排列图像行的大小,以字节为单位。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

访问图像数据

实例:分别打印一个彩色图像和R,G,B三个单通道的图像

int main()
{
    IplImage* img;
    img = cvLoadImage("F:\\Opencv\\素材\\楪析.jpg");
    IplImage* b_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
    IplImage* g_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
    IplImage* r_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
    int x, y;
    for (y = 0; y < img->height; y++)
    {
        unsigned char* prow = (unsigned char*)(img->imageData + y*img->widthStep);
        unsigned char* brow = (unsigned char*)(b_img->imageData + y*b_img->widthStep);
        unsigned char* grow = (unsigned char*)(g_img->imageData + y*g_img->widthStep);
        unsigned char* rrow = (unsigned char*)(r_img->imageData + y*r_img->widthStep);

        for (x = 0; x < img->width; x++)
        {
            brow[x] = prow[3 * x + 0];
            grow[x] = prow[3 * x + 1];
            rrow[x] = prow[3 * x + 2];
        }
    }

    cvNamedWindow("1");
    cvShowImage("1", img);

    cvNamedWindow("b");
    cvShowImage("b", b_img);

    cvNamedWindow("r");
    cvShowImage("r", r_img);

    cvNamedWindow("g");
    cvShowImage("g", g_img);

    cvWaitKey(0);
    return 0;


}

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

对ROI和widthStep的补充

ROI全称:region of interest,即:感兴趣的区域。使用ROI可以对图像的部分区域进行操作而不是对图像额整个区域进行运算,可以提高计算机视觉代码的执行速度。
例:用imageROI来增加某范围的像素。

int main()
{
    IplImage* img;
    img = cvLoadImage("F:\\Opencv\\素材\\楪析.jpg");
    CvRect rect;
    rect.x = 350;
    rect.y = 102;
    rect.width = 166;
    rect.height = 141;
    cvSetImageROI(img, rect);

    cvAddS(img, cvScalar(150), img);

    cvResetImageROI(img);
    cvNamedWindow("1");
    cvShowImage("1", img);

    cvWaitKey(0);

    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

介绍几个主要函数:
cvSetImageROI()和cvResetImageROI()这两个函数用来设置和取消ROI,
void cvSetImageROI(IplImage* image,CvRect rect);
需要传递一个图像指针和矩阵,这个矩阵

typedef struct CvRect
{
    int x;
    int y;
    int width;
    int height;
}
CvRect;

x,y是ROI图像起始点的坐标,width和height是ROI图像的宽度和高度。
图像指针是指我们选取ROI区域的母图像。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

我们可以使用widthStep达到同样的效果,
首先我们要创建一个CvRect结构体,设置图像起点和大小。
然后创建一个图像头,让它的width和height和之前创建CvRect结构体的width和height相同,并且让它的通道和像素深度与母图像的相同。
在使图像头的origin(起点)和widthStep(步长)和母图像相同,
可以理解为创建一个大小与母图像相等CvRect结构体指定的图像区域有颜色,其他地方是透明的图像覆盖在母图像上面。例程如下:

int main()
{
    IplImage* interest_img = cvLoadImage("F:\\Opencv\\素材\\楪析.jpg");
    CvRect interest_rect = cvRect(350, 102, 166, 141);
    IplImage* sub_img = cvCreateImageHeader
        (
        cvSize(interest_rect.width, interest_rect.height),
        interest_img->depth,
        interest_img->nChannels
        );
    sub_img->origin = interest_img->origin;
    sub_img->widthStep = interest_img->widthStep;
    sub_img->imageData = interest_img->imageData + 
        interest_img->widthStep*interest_rect.y +
        interest_img->nChannels*interest_rect.x;
    cvAddS(sub_img, cvScalar(150), sub_img);

    cvNamedWindow("interest_img");
    cvNamedWindow("sub_img");
    cvShowImage("interest_img", interest_img);
    cvShowImage("sub_img", sub_img);
    cvResetImageROI(sub_img);
    cvWaitKey(0);
    cvDestroyWindow("interest_img");
    cvDestroyWindow("sub_img");
    interest_img = NULL;
    sub_img = NULL;

    return 0;
}

看起来设置和重置ROI更方便一些,为什么还要使用widthStep?原因在于有些时候在处理的过程中,想在操作过程中设置和保持一幅图像的多个子区域处于活动状态,但是ROI只能串行处理并且必须不断地设置和重置。

发布了57 篇原创文章 · 获赞 25 · 访问量 16万+
展开阅读全文

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

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览