emgucv.坑01
ZC:∵ ROI的Mat使用的是原来的Mat的内存空间,∴内存访问的时候会造成困扰或麻烦,还是将ROI的Mat再clone一下比较保险。如果追求速度 不clone的话,使用时就要非常注意。
ZC: 举例:单通道的ROI使用 类似pb[r*cols+c]来访问内存的话,很可能就进到了非roi的内存区域
1、知识点:
1.1、Mat 的 raw数据的指针,是使用 Mat::DataPointer属性来获取的(这是 本Mat图片的 首个raw数据的地址)
1.2、Mat::Step 属性,参考 C#中 Bitmap的相应属性含义(与 C++/Delphi等中的含义不一样),应该就是指 每row元素的字节数(多通道的话 该值等于 Mat的列数*通道数)
1.3、坑:在下面的 调试截图中可以看到,mat2 & mat3 的step 和 mat1中的是一样的,也就是说 它们使用的是同一片内存空间。简单验证一下:mat1的 Datapointer为 0x0b240040,mat & mat3 的 Datapointer 为 0x0b28b298,0x0b28b298 - 0x0b240040 = 0x4B258(十进制:307800),mat2 的开始位置是 第100行200列处,3072 * 100(行) + 3(通道)* 200(列) 值正好等于 307800 。
(1)于是,基本可得结论:mat1 & mat2 & mat3 使用的是同一片内存空间,只是 DataPointer的指向不同而已。
(2)但是,我之前 以为 “Mat mat2 = new Mat(mat1, new System.Drawing.Rectangle(200, 100, 200, 200));”会是 另外开辟空间,于是导致 程序怎么调试 得到的结果图片画面 总是不对...
(3)使用 Mat:Clone() 之后,就是另外的地址空间了。原图 大小是:宽 1024像素,高 680像素 ,占用像素空间大小是 十进制3072*680=2088960(字节)(0x1FE000)
可以看到 mat1的地址空间范围是 0x0b240040 ~ 0x0b240040+0x1FE000 ==> 0x0b240040 ~ 0x0B43E040。
取的 小图的 大小是 200行*600(step)= 120000(0x1D4C0)小图的地址范围就是:0x08b8aac0 ~ 0x08BA7F80
两者 明显没有交集
2、代码:
private void Click_imshow(object sender, RoutedEventArgs e) { string str = @"C: \Users\Administrator\Desktop\AAA.jpg"; Mat mat1 = CvInvoke.Imread(str); CvInvoke.Imshow("1", mat1); Mat mat2 = new Mat(mat1, new System.Drawing.Rectangle(200, 100, 200, 200)); CvInvoke.Imshow("2", mat2); Mat mat3 = mat2; CvInvoke.Imshow("3", mat3); Mat mat4 = mat2.Clone(); CvInvoke.Imshow("4", mat4); }
2.1、emgucv:vs2017 的 “管理 NuGet 程序包”安装的:(选择安装了 Emgucv4.1.1 之后,它自动安装了下图中的 ZedGraph)
3、调试 截图:
4、代码执行效果图:
4.1、原图
5、