1. 程式人生 > >OpenCV中Mat與Android中Bitmap簡介

OpenCV中Mat與Android中Bitmap簡介

        因為在介紹這部分系列的內容時,預設是對Android開發有一點基礎的,所以這樣的話,Bitmap可能就相對很熟悉了,相較陌生的是Mat,那我們就首先來看看Mat是什麼。

1,Mat

1.1 Mat基本介紹

Mat是OpenCV中用於儲存影象資訊的類,它在OpenCV中作為一個很重要的資訊載體,下面看一下文件中的介紹的關於其方法的部分:

構造方法:

Mat() 
Mat(int rows, int cols, int type) 
Mat(int rows, int cols, int type, java.nio.ByteBuffer data) 
Mat(int rows, int cols, int type, Scalar s) 
Mat(long addr) 
Mat(Mat m, Range rowRange) 
Mat
(Mat m, Range rowRange, Range colRange)
 
Mat(Mat m, Rect roi) 
Mat(Size size, int type) 
Mat(Size size, int type, Scalar s) 

成員方法:

Mat adjustROI
(int dtop, int dbottom, int dleft, int dright)
 
void assignTo(Mat m) 
void assignTo(Mat m, int type) 
int channels() 
int checkVector(int elemChannels) 
int checkVector(int elemChannels, int depth) 
int checkVector(int elemChannels, int depth, boolean requireContinuous) 
Mat clone() 
Mat col(int x) 
Mat colRange(int startcol, int endcol) 
Mat colRange(Range r) 
int cols() 
void convertTo(Mat m, int rtype) 
void convertTo(Mat m, int rtype, double alpha) 
void convertTo(Mat m, int rtype, double alpha, double beta) 
void copyTo(Mat m) 
void copyTo(Mat m, Mat mask) 
void create(int rows, int cols, int type) 
void create(Size size, int type) 
Mat cross(Mat m) 
long dataAddr() 
int depth() 
Mat diag() 
Mat diag(int d) 
static Mat diag(Mat d) 
int dims() 
double dot(Mat m) 
java.lang.String dump() 
long elemSize() 
long elemSize1() 
boolean empty() 
static Mat eye(int rows, int cols, int type) 
static Mat eye(Size size, int type) 
double[] get(int row, int col) 
int get(int row, int col, byte[] data) 
int get(int row, int col, double[] data) 
int get(int row, int col, float[] data) 
int get(int row, int col, int[] data) 
int get(int row, int col, short[] data) 
long getNativeObjAddr() 
int height() 
Mat inv() 
Mat inv(int method) 
boolean isContinuous() 
boolean isSubmatrix() 
void locateROI(Size wholeSize, Point ofs) 
Mat mul(Mat m) 
Mat mul(Mat m, double scale) 
static Mat ones(int rows, int cols, int type) 
static Mat ones(Size size, int type) 
void push_back(Mat m) 
int put(int row, int col, byte[] data) 
int put(int row, int col, byte[] data, int offset, int length) 
int put(int row, int col, double... data) 
int put(int row, int col, float[] data) 
int put(int row, int col, int[] data) 
int put(int row, int col, short[] data) 
void release() 
Mat reshape(int cn) 
Mat reshape(int cn, int rows) 
Mat reshape(int cn, int[] newshape) 
Mat row(int y) 
Mat rowRange(int startrow, int endrow) 
Mat rowRange(Range r) 
int rows() 
Mat setTo(Mat value) 
Mat setTo(Mat value, Mat mask) 
Mat setTo(Scalar s) 
Mat setTo(Scalar value, Mat mask) 
Size size() 
int size(int i) 
long step1() 
long step1(int i) 
Mat submat(int rowStart, int rowEnd, int colStart, int colEnd) 
Mat submat(Range rowRange, Range colRange) 
Mat submat(Rect roi) 
Mat t() 
java.lang.String toString() 
long total() 
int type() 
int width() 
static Mat zeros(int rows, int cols, int type) 
static Mat zeros(Size size, int type) 

這裡也只是列舉一下這個類的方法而已,看著非常之多,但是不難看出其實主要就是幾類,一類是建立Mat或者修改已有Mat到指定屬性值Mat物件的方法,一類是以獲取Mat物件屬性值的方法;其實就這兩類,比我們常常用於儲存資訊的Bean物件多了一些第一類的方法而已,至少概念上可以這麼理解。

 

1.2 Mat建立方式

        我對於上面關於Mat的API沒有過多介紹,因為本身沒有什麼難度,下面就結合建立Mat物件簡單說明一下,關於建立一個Mat物件有兩大類,一個是從無到有,一個是從有到有,從有到有又分為兩類,一個是複製,一個修改已有Mat物件的屬性,可以簡單用下圖表示一下:

package com.hfut.operationopencvmain.Mat_Test;

import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.core.Size;

/**
 * author:why
 * created on: 2018/11/27 19:30
 * description:
 */
public class MatUtils {

    /**
     * create a Mat Object by it's create() method;the parameters can be different ,both
     * by Size and cows number and rows number
     *
     * @return
     */
    public static Mat method1() {
        Mat mat = new Mat();
        mat.create(new Size(10, 10), CvType.CV_16UC3);
        //mat.create(10,10,CvType.CV_16UC3);
        return mat;
    }


    /**
     * create a Mat object by it's static methods like eye(),ones() and zeros()
     * it's just like the usage of Matlab
     *
     * @return
     */
    public static Mat method2() {
        Mat mat = new Mat();
        mat = Mat.eye(new Size(10, 10), CvType.CV_16UC3);
        // mat=Mat.ones(new Size(10,10),CvType.CV_16UC3);
        // mat=Mat.zeros(new Size(10,10),CvType.CV_16UC3);
        return mat;
    }


    /**
     * create a Mat object by it's setTo() method ,this is similar to the first method
     *
     * @return
     */
    public static Mat method3() {
        Mat mat = new Mat(new Size(10, 10), CvType.CV_16UC3);
        mat = mat.setTo(new Scalar(0, 0, 0));
        return mat;
    }

    /**
     * create a Mat object by it's clone()  and copyTo() method,this is similar to the Object's clone()
     * actually,if you want a self define Object can be clone,you must implement the Cloneable interface
     * @return
     */
    public static Mat method4() {
        Mat mat = new Mat(new Size(10, 10), CvType.CV_16UC3);
        Mat mat1 = mat.clone();
        //Mat mat2=new Mat();
        // mat.copyTo(mat2);
        return mat1;
    }
}

 

1.3 幾個概念

1.3.1 影象深度和影象通道數

這裡借用《OpenCV Android開發實戰》書中的表格釋義一下:

影象深度
影象深度 Java中對應的資料型別
CV_8U=0 8位byte
CV_8S=1 8位byte
CV_16U=2 16位char
CV_16S=3 16位char
CV_32S=4 32位整形 -int
CV_32F=5 32位-float
CV_64F=6 64位-double

 

其中U表示無符號,S表示符號整形,F表示浮點型;還有就是一個影象通道的概念,在Android當中,我們在使用Bitmap時,Bitmap.Config API中有幾個型別常量:

ALPHA_8
           
ARGB_4444
           
ARGB_8888
           
RGB_565

其中RGB_565就表示RGB三通道16位的含義,其他類似,所以在OpenCV中把圖片載入成Mat物件時也有通道的概念,也是對應的1,3,4通道。這樣通道和影象深度組合在一起就構成了Mat物件的載入型別,這個主要可在CvType中能檢視,下面就是CvType中所有的型別了:

static int CV_16S 
static int CV_16SC1 
static int CV_16SC2 
static int CV_16SC3 
static int CV_16SC4 
static int CV_16U 
static int CV_16UC1 
static int CV_16UC2 
static int CV_16UC3 
static int CV_16UC4 
static int CV_32F 
static int CV_32FC1 
static int CV_32FC2 
static int CV_32FC3 
static int CV_32FC4 
static int CV_32S 
static int CV_32SC1 
static int CV_32SC2 
static int CV_32SC3 
static int CV_32SC4 
static int CV_64F 
static int CV_64FC1 
static int CV_64FC2 
static int CV_64FC3 
static int CV_64FC4 
static int CV_8S 
static int CV_8SC1 
static int CV_8SC2 
static int CV_8SC3 
static int CV_8SC4 
static int CV_8U 
static int CV_8UC1 
static int CV_8UC2 
static int CV_8UC3 
static int CV_8UC4 
static int CV_USRTYPE1

其實它們的組成也很簡單,就拿後面經常使用的一種型別來說CV_8UC3(inread方法預設使用型別),其中CV表示計算機視覺,8UC表示8位無符號char,3表示3通道(在OpenCv中3通道的順序是GBR);其他類似。

 

2,Android中的Bitmap

關於這部分的類容我不想多做介紹,因為在Android開發過程中,我們對其使用應該是比較熟悉了的。

2.1 建立方式

其建立的方式主要有兩類,一類是通過Bitmap工廠,一個是自身的靜態方法;但更一層的可以知道,它也是儲存影象資訊的物件,建立其物件一個是根據已有的影象資源或者Bitmap物件建立,一個是構建資訊填充到將要建立的Bitmap物件中,分別舉例如下:

(1)根據已有的影象資源或者Bitmap物件建立

BitmapFactory靜態方法

decodeFile(String pathName)

Bitmap靜態方法

createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)

(2)構建資訊填充到將要建立的Bitmap物件中

Bitmap靜態方法

createBitmap(int[] colors, int width, int height, Bitmap.Config config)


2.2 Bitmap畫素儲存型別

這個在上面其實已經介紹過了,就是我們的Bitmap.Config中的列舉常量:

ALPHA_8
           
ARGB_4444
           
ARGB_8888
           
RGB_565

拿其中一個舉例,ARGB_4444表示4通道,每一個通道4位,共兩個位元組,表示一個畫素。

 

3 兩者資源管理

(1)Mat物件在確定後續不使用時,需主動呼叫release()方法釋放資源

(2)Bitmap在現有裝置使用的OS版本里面是不需要主動釋放資源(也可以保證資源的及時釋放主動呼叫recycle()方法),已經被加入了垃圾回收(gc)機制裡面

好了,本篇關於Mat和Bitmap的介紹到這裡結束了。作為影象資訊的載體,它們API本身邏輯非常之簡單,總結好就行了。更多類容請往下看:

上一篇:OpenCV之處理影象前的基本準備工作

下一篇:OpenCV之Mat與Bitmap之間的轉換