【Open CV基础】使用Open CV操作图像的像素通道值

Open CV最本职的工作时计算机视觉处理,所以在它的函数库中,最重要的结构体是IplImage,里面有丰富的图像数据。下面是百度百科里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 和IPL_DEPTH_64F */
    char colorModel[4]; /* 被OpenCV忽略 */
    char channelSeq[4]; /* 同上 */
    int dataOrder; /* 0 - 交叉存取颜色通道, 1 - 分开的颜色通道. 只有cvCreateImage可以创建交叉存取图像 */
    int origin; /*图像原点位置: 0表示顶-左结构,1表示底-左结构 */
    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;

我们可以通过操纵图像的像素数据对图像进行处理。下面介绍两种方法:

使用img->imageData和img->widthStep获取图像像素地址,直接操作

示例如下:


#include "cv.h"
#include "highgui.h"

//处理图像的函数
void saturate_sv(IplImage* img){

    for (int y = 0; y < img->height; y++){
        uchar* ptr = (uchar*)(
            img->imageData + y * img->widthStep);

        for (int x = 0; x < img->width; x++){   
            //将颜色通道的四个通道值分别作如下变换
            ptr[3 * x    ] = (ptr[3 * x    ] + 30) % 256;
            ptr[3 * x + 1] = (ptr[3 * x + 1] + 30) % 256;
            ptr[3 * x + 2] = (ptr[3 * x + 2] + 30) % 256;
            ptr[3 * x + 3] = (ptr[3 * x + 3] + 30) % 256;

        }
    }
}

void main()
{
    IplImage* img = cvLoadImage("fruits.jpg");

    char* _1 = "处理前图像";
    char* _2 = "处理后图像";

    //处理前图像
    cvNamedWindow(_1, CV_WINDOW_AUTOSIZE);
    cvShowImage(_1, img);
    //处理图像
    saturate_sv(img);
    //处理后图像
    cvNamedWindow(_2, CV_WINDOW_AUTOSIZE);
    cvShowImage(_2, img);

    cvWaitKey(0);
    cvReleaseImage(&img);
    cvDestroyWindow(_1);
    cvDestroyWindow(_2);
}

IplImage是继承自CvMat,所以图像成了一种矩阵结构,在上述代码中,我们通过imageData获取了图像的首地址,然后通过widthStep获得了以字节记的行宽(用width则以像素记),然后将可以直接在内存里对图像的颜色通道赋值。

处理fruits.jpg前后的图像对比:
【Open CV基础】使用Open CV操作图像的像素通道值_第1张图片

使用cvSetImageROI圈定图像的像素范围,批量操作

示例如下:


#include "cv.h"
#include "highgui.h"

int _imageROI(){
    IplImage* src;
    src = cvLoadImage("fruits.jpg");
    if (src == 0)
        return 0;
    int x = 100;
    int y = 100;
    int width = 100;
    int height = 100;
    int add = 150;

    char* _1 = "处理前图像";
    char* _2 = "处理后图像";

    //处理前图像
    cvNamedWindow(_1, CV_WINDOW_AUTOSIZE);
    cvShowImage(_1, src);

    //处理图像
    cvSetImageROI(src, cvRect(x, y, width, height));
    cvAddS(src, cvScalar(add,100,100,100), src);
    cvResetImageROI(src);


    //处理后图像
    cvNamedWindow(_2, CV_WINDOW_AUTOSIZE);
    cvShowImage(_2, src);

    cvWaitKey(0);
    cvReleaseImage(&src);
    cvDestroyWindow(_1);
    cvDestroyWindow(_2);
    return 0;
}

处理图像前后对比:

【Open CV基础】使用Open CV操作图像的像素通道值_第2张图片

你可能感兴趣的:(opencv,图像处理)