IplImage和char*相互转换

      在OpenCV里边,widthStep必须是4的倍数,从而实现字节对齐,有利于提高运算速度。如果8U单通道图像宽度为3,那么widthStep是 4,加一个字节补齐。这个图像的一行需要4个字节,只使用前3个,最后一个空着。也就是一个宽3高3的图像的imageData数据大小为4*3=12字 节。

     空着的那个像素并不是无效的,它仍然可以被操作:

IplImage* image = cvCreateImage(cvSize(15, 15), 8, 1);
memcpy(image->imageData, data, 15*15);


      在cvCreateImage的时候,OpenCV为实现字节对齐,使得每行数据实际有16个字节(多出一个),在使用memcpy的过程 中,这些多出的字节就把对应的数据给“吃”了,因为这些数据在cvShowImage的时候并不会显示出来,这样,第二行就少一个字节,第三行少两个字 节,……,这样会造成整个图像偏向左下角!

      此时,应该这样Copy:

for(int i = 0; i<15; i++)...{
     memcpy(image->imageData + image->widthStep*i, data + 15*i, 15);
}


      IplImage和单字节char*之间相互转换的正确、简洁的方法:

      已知 IplImage* image 和 char* data

      从 IplImage 到 char* :

data = image->imageData //对齐的图像数据
或
data = image->imageDataOrigin //未对齐的原始图像数据


       从 char* 到 IplImage :

image = cvCreateImageHeader(cvSize(width,height), depth, channels);
cvSetData(image, data, step);

step指定IplImage图像每行占的字节数。需要注意是,在释放空间时不能直接使用cvReleaseImage,而需cvReleaseImageHeader,然后再delete data。

      cvSetData code from opencv2.3.1(now opencv2.4.3 is out . As usual, the packages are available at SourceForge (http://sourceforge.net/projects/opencvlibrary), or alternatively you can download the source code from https://github.com/Itseez/opencv/tree/2.4):

// Assigns external data to array
CV_IMPL void
cvSetData( CvArr* arr, void* data, int step )
{
    int pix_size, min_step;

    if( CV_IS_MAT_HDR(arr) || CV_IS_MATND_HDR(arr) )
        cvReleaseData( arr );

    if( CV_IS_MAT_HDR( arr ))
    {
        CvMat* mat = (CvMat*)arr;
    
        int type = CV_MAT_TYPE(mat->type);
        pix_size = CV_ELEM_SIZE(type);
        min_step = mat->cols*pix_size;

        if( step != CV_AUTOSTEP && step != 0 )
        {
            if( step < min_step && data != 0 )
                CV_Error( CV_BadStep, "" );
            mat->step = step;
        }
        else
            mat->step = min_step;

        mat->data.ptr = (uchar*)data;
        mat->type = CV_MAT_MAGIC_VAL | type |
                    (mat->rows == 1 || mat->step == min_step ? CV_MAT_CONT_FLAG : 0);
        icvCheckHuge( mat );
    }
    else if( CV_IS_IMAGE_HDR( arr ))
    {
        IplImage* img = (IplImage*)arr;
    
        pix_size = ((img->depth & 255) >> 3)*img->nChannels;
        min_step = img->width*pix_size;

        if( step != CV_AUTOSTEP && img->height > 1 )
        {
            if( step < min_step && data != 0 )
                CV_Error( CV_BadStep, "" );
            img->widthStep = step;
        }
        else
        {
            img->widthStep = min_step;
        }

        img->imageSize = img->widthStep * img->height;
        img->imageData = img->imageDataOrigin = (char*)data;

        if( (((int)(size_t)data | step) & 7) == 0 &&
            cvAlign(img->width * pix_size, 8) == step )
            img->align = 8;
        else
            img->align = 4;
    }
    else if( CV_IS_MATND_HDR( arr ))
    {
        CvMatND* mat = (CvMatND*)arr;
        int i;
        int64 cur_step;
    
        if( step != CV_AUTOSTEP )
            CV_Error( CV_BadStep,
            "For multidimensional array only CV_AUTOSTEP is allowed here" );

        mat->data.ptr = (uchar*)data;
        cur_step = CV_ELEM_SIZE(mat->type);

        for( i = mat->dims - 1; i >= 0; i-- )
        {
            if( cur_step > INT_MAX )
                CV_Error( CV_StsOutOfRange, "The array is too big" );
            mat->dim[i].step = (int)cur_step;
            cur_step *= mat->dim[i].size;
        }
    }
    else
        CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值