opencv 矩阵块的复制问题

opencv中有函数可以实现,图像指点块的复制,或者复制到图像指定块:

void cvSetImageROI(IplImage* image,  CvRect rect)

这个函数对于控制图像的局部块进行处理非常方便,但是它的输入只能是图像指针 ,对于CvMat* 或者CvArray*这些类型的数据都稍稍麻烦了点。

1.             将他们相互转化

  • IplImage转Cvmat
1
2
3
Ptr image; //input
Ptr mat = cvCreateMatHeader(image->height, image->width, CV_32SC1);
cvConvert(image, mat);

或者:

1
2
CvMat matObj;
*mat = cvGetMat(image, &matObj); // cvGetImage和cvGetMat都要慎用
  • Cvmat 转IplImage
1
2
Ptr image = cvCreateImageHeader(cvGetSize(mat), 8,1);
cvGetImage(mat, image); //cvGetImage和cvGetMat都要慎用

2.            使用其他的函数

cvMat* cvGetSubRect(const CvArr* arr, cvMat* submat, CvRect rect);

该函数实现,将arr中rect区域数据copy到submat中。

注:没有实现将数据copy到arr中的某rect区域,需要自己实现

实现时,一定要注意:Submat一定不能分配内存空间

如:

1
2
3
//如上的实现会出先内存泄漏
Ptr
cvGetSubRect(src, submat, rect);
1
2
3
//这样子的实现就是ok的
Ptr submat = cvCreateMatHeader(rect.width , rect.height,CV_32F);
cvGetSubRect(src, submat, rect);

出现内存错误的原因:我们看看cvGetSubRect的源代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
CV_IMPL  CvMat* cvGetSubRect(  const  CvArr* arr, CvMat* submat, CvRect rect )
{
      CvMat* res = 0;
      CV_FUNCNAME(  "cvGetRect"  );
      __BEGIN__;
      CvMat stub, *mat = (CvMat*)arr;
      if ( !CV_IS_MAT( mat ))
          CV_CALL( mat = cvGetMat( mat, &stub ));
      if ( !submat )
          CV_ERROR( CV_StsNullPtr,  ""  );
      if ( (rect.x|rect.y|rect.width|rect.height) < 0 )
          CV_ERROR( CV_StsBadSize,  ""  );
      if ( rect.x + rect.width> mat->cols || rect.y + rect.height>mat->rows )
          CV_ERROR( CV_StsBadSize,  ""  );
  { //从此处可以看出,如果submat已经分配有内存空间,那么,此处将产生内存泄漏,切记传递submat时,一定要穿一个没有分配内存的指针。
      submat -> data.ptr = mat->data.ptr + ( size_t )rect.y*mat->step + rect.x*CV_ELEM_SIZE(mat->type);
      submat->step = mat->step & (rect.height > 1 ? -1 : 0);
      submat->type = (mat->type & (rect.width <  mat->cols ? ~CV_MAT_CONT_FLAG : -1)) |
      (submat->step == 0 ? CV_MAT_CONT_FLAG : 0);
      submat->rows = rect.height;
      submat->cols = rect.width;
      submat->refcount = 0;
      res = submat;
  }
      __END__;
      return  res;
  }

总之,这个函数和opencv中的其他函数使用习惯不太一样,使用时,一定要注意。

你可能感兴趣的:(opencv 矩阵块的复制问题)