关于深拷贝和浅拷贝:
深拷贝和浅拷贝是根据拷贝的变量是否重新分配内存来区分的,当要重新分配内存来存放拷贝的变量时,就是深拷贝,反之如果拷贝不复制数据只创建矩阵头则为浅拷贝。 举个栗子:加如路人甲有一份文件放在储物柜A中,某时刻路人乙想阅览这份文件或者文件中的一部分(ROI),此时路人乙有两种选择:
1 从甲那获知储物柜A的地址并记住(创建矩阵头),根据这个信息去储物柜A阅览(查询数据)以及修改(处理数据),之后再放 回原位置。这样两者同时共享这份文件;
2 从储物柜A中拿出文件,在复印机中复印一份,源文件依旧在储物柜A中,新复印出来的文件则放在储物柜B中,这样路人乙以后再操作文件就在自己的文件中进行。
在openCV感兴趣区域ROI中,Mat roi = src(rect(x,y,width,height));可以取目标图像的一块作为感兴趣区域,当正常显示时候没问题,但当需要对图像进行处理时则容易出现问题。
uchar* p = roi.ptr<ucahr>(0);通过指针指向roi的起始地址,
for(int i=0;i<roi.rows;++i){
for(int j=0;j<roi.cols;++j){
//cout<<int(*(p+i*roi.cols+j));//针对普通Mat
int(*(p+i*roi.cols+j))==0?printf("0"):printf("1");//方便显示用一张二值化图片
}
cout<<endl;
}
通过这两张图可以看到,roi输出尺寸和预想一样,输出显示也正常,当时通过指针打印出来后发现数据不对。
这是因为,在程序中 = 赋值是浅拷贝的形式,也就是说roi在生成时只生成了相关的矩阵头,获取了对应图像的地址,其自身并没有对应的数据。在显示中可以正常显示,但当用指针操作时,指针实际指向的是原图像src的roi部分的最开始的那个地址。所以指针操作实际上是在src上操作,ij对应的roi行和列在这里并没有意义,因为这里指针寻迹为src的行和列。也就是说当用指针操作roi时他操作的范围并不是roi而是src在当前地址以后的范围。解决这个问题只需要将roi区域进行clone()或者copyto()深拷贝即可解决。