OpenCV for Android (3)——Mat

1. Mat - 基本图像容器

从真实世界中获取数字图像有很多方法,比如数码相机、扫描仪、CT或者磁共振成像。无论哪种方法,我们(人类)看到的是图像,而让数字设备来“看“的时候,则是在记录图像中的每一个点的数值。

关于 Mat ,首先要知道的是你不必再手动地:

  • 为其开辟空间
  • 在不需要时立即将空间释放

但手动地做还是可以的:大多数OpenCV函数仍会手动地为输出数据开辟空间。当传递一个已经存在的 Mat 对象时,开辟好的矩阵空间会被重用。也就是说,我们每次都使用大小正好的内存来完成任务。

  • OpenCV函数中输出图像的内存分配是自动完成的(如果不特别指定的话)。
  • 使用OpenCV的C++接口时不需要考虑内存释放问题。
  • 赋值运算符和拷贝构造函数( ctor )只拷贝信息头。
  • 使用函数 clone() 或者 copyTo() 来拷贝一副图像的矩阵。

2. 存储方法

这里讲述如何存储像素值。需要指定颜色空间和数据类型。颜色空间是指对一个给定的颜色,如何组合颜色元素以对其编码。最简单的颜色空间要属灰度级空间,只处理黑色和白色,对它们进行组合可以产生不同程度的灰色。

对于彩色方式则有更多种类的颜色空间,但不论哪种方式都是把颜色分成三个或者四个基元素,通过组合基元素可以产生所有的颜色。

RGB颜色空间是最常用的一种颜色空间,这归功于它也是人眼内部构成颜色的方式。它的基色是红色、绿色和蓝色,有时为了表示透明颜色也会加入第四个元素 alpha (A),ARGB。

有很多的颜色系统,各有自身优势:

  • RGB是最常见的,这是因为人眼采用相似的工作机制,它也被显示设备所采用。
  • HSV和HLS把颜色分解成色调、饱和度和亮度/明度。这是描述颜色更自然的方式,比如可以通过抛弃最后一个元素,使算法对输入图像的光照条件不敏感。
  • YCrCb在JPEG图像格式中广泛使用。
  • CIE L*a*b* 是一种在感知上均匀的颜色空间,它适合用来度量两个颜色之间的距离 。

每个组成元素都有其自己的定义域,取决于其数据类型。如何存储一个元素决定了我们在其定义域上能够控制的精度。

最小的数据类型是 char ,占一个字节或者8位,可以是有符号型(0到255之间)或无符号型(-127到+127之间)。尽管使用三个 char 型元素已经可以表示1600万种可能的颜色(使用RGB颜色空间),但若使用float(4字节,32位)或double(8字节,64位)则能给出更加精细的颜色分辨能力。但同时也要切记增加元素的尺寸也会增加了图像所占的内存空间。

3. CV_(S|U|F)C

CV_(S|U|F)C

  • bit_depth:比特数,有8bite,16bites,32bites,64bites
  • S|U|F
    S:代表signed int,有符号整形
    U:代表unsigned int,无符号整形
    F:代表float,单精度浮点型
  • C:代表一张图片的通道数,
    比如:
//【1】CV_8UC1---则可以创建----8位无符号的单通道---灰度图片------grayImg
#define CV_8UC1 CV_MAKETYPE(CV_8U,1)
#define CV_8UC2 CV_MAKETYPE(CV_8U,2)
//【2】CV_8UC3---则可以创建----8位无符号的三通道---RGB彩色图像---colorImg 
#define CV_8UC3 CV_MAKETYPE(CV_8U,3)
//【3】CV_8UC4--则可以创建-----8位无符号的四通道---带透明色的RGB图像 
#define CV_8UC4 CV_MAKETYPE(CV_8U,4)

一般的图像文件格式使用的是Unsigned,对应的是8bits,CvMat矩阵对应的参数类型就是CV_8UC1,CV_8UC2,CV_8UC3,CV_8UC4;
float 是32位的,对应CvMat数据结构参数就是:CV_32FC1,CV_32FC2,CV_32FC3...
double是64bits,对应CvMat数据结构参数:CV_64FC1,CV_64FC2,CV_64FC3等。


原始图像

4. 在图像中截取子图并显示

这里将子图截取后转换为灰度图像:

public static Bitmap getRoi(Bitmap bitmap) {
        Rect roi = new Rect(200, 150, 200, 300);//create a sub image with (x,y,width,height)
        Bitmap roiMap = Bitmap.createBitmap(roi.width, roi.height, Bitmap.Config.ARGB_8888);
        org.opencv.android.Utils.bitmapToMat(bitmap, sSrc);
        Mat roiMat = sSrc.submat(roi);
        Mat roiDstMat = new Mat();
        Imgproc.cvtColor(roiMat, roiDstMat, Imgproc.COLOR_BGRA2GRAY);
        org.opencv.android.Utils.matToBitmap(roiDstMat, roiMap);
        //Don't forget to release all of this. Or it may cause OOM.
        roiDstMat.release();
        roiMat.release();
        sSrc.release();
        return roiMap;
    }

5. 调整图像亮度与对比度

public static void contrast_ratio_adjust(Bitmap bitmap) {
        org.opencv.android.Utils.bitmapToMat(bitmap, sSrc);
        //This operation enables you to adjust CM in a float number.
        sSrc.convertTo(sSrc, CvType.CV_32F);
        Mat whiteImage = new Mat(sSrc.size(), sSrc.type(), Scalar.all(1.25));//Contrast Ratio
        Mat bwImage = new Mat(sSrc.size(), sSrc.type(), Scalar.all(30));//Brightness+30
        Core.multiply(whiteImage, sSrc, sSrc);
        Core.add(bwImage, sSrc, sSrc);
        sSrc.convertTo(sSrc, CvType.CV_8U);
        org.opencv.android.Utils.matToBitmap(sSrc, bitmap);
        //Don't forget to release.
        bwImage.release();
        whiteImage.release();
        sSrc.release();
    }

Demo On GitHub

参考并感谢

  1. CV_8UC1,CV_8UC2,CV_8UC3
  2. OpenCv学习笔记(二)--Mat矩阵(图像容器)的创建及CV_8UC1,CV_8UC2等参数详解
  3. Mat - 基本图像容器

你可能感兴趣的:(OpenCV for Android (3)——Mat)