事情是这样的,我想把IplImage转换到Mat,然后使用Mat做相关的处理,我是这么干的:
IplImage *tmpCutImg=cvCreateImage(cutSize,srcImage->depth,srcImage->nChannels);
GetImageRect(srcImage,iRect,tmpCutImg);
Mat cutMat(tmpCutImg);
cvReleaseImage(&tmpCutImg);//释放IplImage的内存
//显示Mat图像
imshow("cutMat",cutMat);
waitKey(1);
然后就发现跪掉了,显示的图像根本是一张乱码图片,后来发现是因为使用
Mat cutMat(tmpCutImg);
将IplImage转换为Mat时,Mat和IplImage共用数据区,在显示Mat之前就将tmpCutImg释放掉,Mat中的数据就变成随机的了,显示就成乱码了。所以正确的做法应该是在使用完毕Mat后再释放tmpCutImg。
同样的,使用Mat的构造函数进行Mat的构造也会是这种情况,产生的新的Mat会与原来的Mat公用相同的数据区。如下所示:
Mat A=imread("test.jpg");
Mat A(B);
上面的操作构造出来的B会和A共用数据区,如果对B的数据区进行了操作,A的内容也会变化,因此如果想要复制全新的独立的Mat,要使用如下方式:
Mat B=A.clone();
还有一个函数是
void Mat::copyTo(OutputArray m, InputArray mask) const
这个函数的用法跟clone()的关系看了下面的代码就明白了:
inline Mat Mat::clone() const
{
Mat m;
copyTo(m);
return m;
}
所以如果不提供mask,那么clone()与copyTo()的功能是一样的,而不同的是copyTo()拷贝Mat时只拷贝mask不为零的位置,且mask的类型必须为CV_8U