使用Java开发OpenCV3程序-3.OpenCV的组件结构以及java版本的数据结构

OpenCV组件结构java

  关于OpenCV的组件结构“浅墨”大神给出了详细的解释,详细的参照:一览众山小:OpenCV 2.4.8 or OpenCV 2.4.9组件结构全解析 但在OpenCV3.1中仍是有些变化的,在opencv/build/include/opencv2目录下有OpenCV的全部模块,安全

                                        

一共有这么多模块,在浅墨的文章中也作了详细的介绍,有些模块已经没有了。而后再看看java中所包含的模块,能够从opencv.jar中看到所实现的模块:ui

                                         

明显看到跟C++版本的少了不少模块,可是基本的功能模块都已经有了,官方应该也在不断晚上java版本的接口,不久的未来也应该会拥有跟C++版本如出一辙的功能吧。能够到各个模块中查看所实现的方法,通常的方法中都有注释,并且方法的名字都是跟C++中是同样的。spa

  咱们知道一幅图片都是有不一样的像素点组成的,每一个像素点的值表明了一个颜色,好比一副灰度图像,从0(黑色)到255(白色)来表明颜色的深浅。而一般一幅彩色图像又是由红绿蓝三种颜色组成,俗称RGB图像。更多关于图像与颜色能够参考数字图像处理方面的书籍,这是介绍OpenCV是如何来表示不一样的图像的。在core->CvType中定义了不少关于图像类型的常量,基本结构是:.net

  CV_<位数>{U|S|F}C(<通道数>)     位数=8|16|32|64   通道数=1|2|3|4  最多只有四通道。  下面以一通道的来作详细的说明。对象

  • CV_8UC1 8位无符号整数从0到255
  • CV_8SC1 8位有符号整数从-128到127
  • CV_16UC1 16位无符号整数从0到65536
  • CV_16SC1 16位有符号整数从-32768到32767
  • CV_32SC1 32位有符号整数从-2^(32-1)到2^(32-1)-1
  • CV_32FC1 32位有符号小数
  • CV_64FC1 64位有符号小数
你能够使用这样的方式来建立一幅图片:

Mat image = new Mat(new Size(3,4), CvType.CV_8UC3, new Scalar(new double[]{128,3,4})); blog

  Mat有不少中构造方法,这里只是其中一种,这样构造的mat对象含义是宽度为3个像素,高度为4个像素,8位无符号三通道图像,第一通道也就是Red全为128,第二通道Green全为3,第三通道Blue全是4,咱们能够使用以下的代码打印出这个对象的信息以及每一个像素点的数据。接口

        Mat image = new Mat(new Size(3, 4), CvType.CV_8UC3, new Scalar(new double[]{128, 3, 4}));
        System.out.println(image + " width=" + image.width() + " height=" + image.height());
        System.out.println(image.dump());

直接使用Mat对象的toString()方法,将会打印出mat对象的基本信息,dump()返回每一个像素点的值,注意当像素宽高太大时,可能耗时比较长。输出结果:图片

Mat [ 4*3*CV_8UC3, isCont=true, isSubmat=false, nativeObj=0x50aaf0, dataAddr=0x4dce00 ] width=3 height=4
[128,   3,   4, 128,   3,   4, 128,   3,   4;
 128,   3,   4, 128,   3,   4, 128,   3,   4;
 128,   3,   4, 128,   3,   4, 128,   3,   4;
 128,   3,   4, 128,   3,   4, 128,   3,   4]

因为图像过小,显示出来也是特别小,基本看不出来,能够把宽高设置大一些而后显示,就是一片深蓝色,也就是red=128,green=3,blue=4的颜色。内存

一些须要注意的点:

  java中没有无符号这个说法,全部的基本数据类型都是有符号的,好比对于CV_8UC1来讲,须要表示的像素是从0到255,在C++中只须要一个byte就够了,可是java中确不能用一个字节来表示0到255,因此是只能向上类型转换了。咱们先来看一段代码:

        Mat image = new Mat(new Size(3, 4), CvType.CV_8UC1, new Scalar(new double[]{234}));
        image.put(1, 2, new byte[]{123});
        System.out.println(image);
        System.out.println(image.dump());

        image.put(1, 2, new byte[]{200 - 256});
        System.out.println(image.dump());

  这段代码先建立了一个3*4的8位单通道无符号的图像,每一个像素点都是234,而后将[1,2]这个位置(注意从[0,0]坐标点开始计数)值置为123,而后打印出来像素,没问题,123<127因此能够put成功,可是若是咱们想改一个大于127的值呢,byte数据会直接报错,编译都没法经过,那是否是就没法建立一个大于127的值呢,固然不是,将大于127的值减去一个256,好比如今我想设置成200,怎么作呢,直接用200-256,也就是存一个-56,而后再打印出来看看是否是能够。结果固然是能够的,200已经设置成功了。那若是是一个CV_8SC1的图像呢,该是多少直接设置成多少就能够了。为何能打印出200呢,不是byte值得吗?不妨看看image.get(1,2)这个方法,这个方法返回了一个double[]类型,当时能保存200了,而dump返回的是String,在内部已经将-56转成了200的字符串.

  因此对于得到一幅图像的像素点的时候不用考虑太多,可是若是你要设置某个像素点,而且这个像素点的数据类型或是位宽小于你要设置的值得位宽时,就得注意了,不过也有更安全的作法,那就是全都使用double设置,在内部会自动转换。后面会看到在java版本的OpenCV的方法中不少地方都是使用的是double,这个确实是浪费了不少内存,不少时候咱们处理的都是8位无符号的3通道彩色图像,映射到java程序中,若是要把这个图像的数据dump过来,那就得8倍的内存来保存(C++中一个字节就够但java就须要用double表示,double占了8位)。

  下一遍开始就正式要开始介绍使用OpenCV来处理图像了。

相关文章
相关标签/搜索