首先cvGetSubRect的定义如下:
cvGetSubRect( const CvArr* arr, CvMat* submat, CvRect rect );
第一个参数是输入图像,第二个参数是裁切后的输出图像,第三个参数是裁切的范围
主要注意一下第三个参数的设置:
cvRect(offset, offset, W, H)
首先是宽和高的偏移量,接下来要注意先设置“宽”,再设置“高”
容易发生的错误:很多人将第二个参数预先初始化并分配内存:
CvMat *src = cvCreate(H, W , CV_64FC1);
CvMat *srcPlus = cvCreateMat(H + offset * 2, W + offset * 2, CV_64FC1);
cvGetSubRect(srcPlus, src, cvRect(offset, offset, W, H));
上面这种写法是不对的,因为cvGetSubRect的裁切并不是真正的裁切出一个新的图像,生成的目标src图像对应指针指向的源数据其实是srcPlus,并没有分配新的内存;所以预先分配了src的内存会造成内存泄漏
因此以上情况中,如果释放了srcPlus的内存(cvRelease(void **)&srcPlus),src也会失效
正确的使用方式如下:
CvMat *src = cvCreateMatHeader(H, W, CV_64FC1);
CvMat *srcPlus = cvCreateMat(H + offset * 2, W + offset * 2, CV_64FC1);
CvMat *dst = cvCreateMat(H, W, CV_64FC1);
cvGetSubRect(srcPlus, src, cvRect(offset, offset, W, H));
cvCopy(src, dst, NULL);
cvRelease((void **)&src);
cvRelease((void **)&srcPlus);
cvRelease((void **)&dst);
cvCreateMatHeader() 函数创建CvMat结构,不为数据分配内存,所以不会造成内存泄漏,如果想“单独”存取裁切后的数据,创建一个新的变量dst,并使用cvCopy实现数据的复制