继续做测试,这次要测试的是OpenCV for Android API 中的submat方法,该方法可以看做是Android中ROI的一种实现,因其返回的mat对象比较特殊,因此也对其常见操作进行了简单的测试。为方便叙述,原图对象称为原图mat,submat提取的mat对象称为子图mat。
测试代码如下:(关于屏幕输出用的是System.out.println而不是Log.i,这只是我个人抽抽而已)
private void Test_SubMatrix()
{
//构建位图原图
Mat mat=Highgui.imread(mImagePath);
//创建子区域(左上角坐标与原图一致)
Mat subMat=mat.submat(0, 20, 0, 20);
//打印两个mat的详细信息
System.out.println("mat info: "+mat.toString());
System.out.println("submat info: "+subMat.toString());
//访问原图像素值
double[] matpixel=mat.get(1, 1);
System.out.print("mat pixel in (1,1)");
for (double d : matpixel)
{
System.out.print("("+d+" )");
}
System.out.println();
//访问子区域图像素值
double[] submatpixel=subMat.get(1, 1);
System.out.println("submat pixel in (1,1)");
for (double d : submatpixel)
{
System.out.print("("+d+" )");
}
System.out.println();
//修改子区域像素值
double[] updataPixe=new double[]{12,33,55};
subMat.put(1, 1, updataPixe);
//访问原图像素值
matpixel=mat.get(1, 1);
System.out.println("mat pixel in (1,1)");
for (double d : matpixel)
{
System.out.print("("+d+" )");
}
System.out.println();
//访问子区域图像素值
submatpixel=subMat.get(1, 1);
System.out.println("submat pixel in (1,1)");
for (double d : submatpixel)
{
System.out.print("("+d+" )");
}
System.out.println();
//释放子区域
subMat.release();
//打印两个mat的详细信息
System.out.println("submat is empty is "+(subMat.empty()));
System.out.println("mat is empty is "+(mat.empty()));
//访问原图详细
System.out.println("mat pixel in (1,1)");
for (double d : matpixel)
{
System.out.print("("+d+" )");
}
System.out.println();
}
测试结果:
分析:
1.由第一次原图mat与子图mat的打印结果可以看出来。两者虽然有着不同的本地地址(nativeref)但两者的数据地址(dataAdd)是一直的。按照OpenCV的观点来说就是submat创建的子图mat只有“头结构”,(或者元数据metadata).而子图mat的图像数据和原图mat的图像数据共享一片内存。因此,在第一次对两个mat的(1,1)元素进行访问时,实际是对同一个内存访问了两次。
2.共享内存,就导致了子图mat与原图mat之间的修改会相互影响。测试中,我们对子图mat中(1,1)位置的元素修改了像素值,结果表明原图mat也进行了相应修改。因此,当后期我们操作子图mat时,也要注意避免数据修改对原图的影像。
3.修改中最特殊的应当算是释放内存操作,而由Mat对象的打印信息来看,OpenCV专门为Mat对象添加了IsSubmat标示符,用于防止因release()方法的调用者是子图mat而导致的对原图mat的内存释放修改。不过,用于子图mat只有“头结构”因此,也不会出现因没有调用release()而出现的内存泄露问题。
当然,听说在OpenCV android API 也提供了locateROI的方法,只是目前还没有测试与应用。还望各位看官包含。