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, Rect roi) |
Mat(Size size, int type) |
Mat(Size size, int type, Scalar s) |
成員方法:
Mat |
adjustROI |
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本身邏輯非常之簡單,總結好就行了。更多類容請往下看: