关于深拷贝和浅拷贝:

深拷贝和浅拷贝是根据拷贝的变量是否重新分配内存来区分的,当要重新分配内存来存放拷贝的变量时,就是深拷贝,反之如果拷贝不复制数据只创建矩阵头则为浅拷贝。   举个栗子:加如路人甲有一份文件放在储物柜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;
}

opencv mat rgb顺序 opencv mat roi_指针操作

opencv mat rgb顺序 opencv mat roi_指针操作_02

通过这两张图可以看到,roi输出尺寸和预想一样,输出显示也正常,当时通过指针打印出来后发现数据不对。

这是因为,在程序中 = 赋值是浅拷贝的形式,也就是说roi在生成时只生成了相关的矩阵头,获取了对应图像的地址,其自身并没有对应的数据。在显示中可以正常显示,但当用指针操作时,指针实际指向的是原图像src的roi部分的最开始的那个地址。所以指针操作实际上是在src上操作,ij对应的roi行和列在这里并没有意义,因为这里指针寻迹为src的行和列。也就是说当用指针操作roi时他操作的范围并不是roi而是src在当前地址以后的范围。解决这个问题只需要将roi区域进行clone()或者copyto()深拷贝即可解决。

opencv mat rgb顺序 opencv mat roi_数据_03