前言 上一篇文章,我們
定義了矩陣,這篇文章我們來為矩陣增加一些常用方法。
toString方法 toString方法通常用作將物件轉成字串描述,所以我們將此方法定義為輸出矩陣元素。
Mat.prototype.toString = function(){
>var tempData = this.data,
text = "Mat(" this.type ") = {n",
num = this.col * this.channel;
for(var i = 0; i text = "["
for(var j = 0; j text = (tempData[i * num j] "," );
}
text = "]n";
}
text = "}";
return text;
};
這樣,我們就可以用:
console.log(mat) ;
來輸出矩陣了。
clone方法 實際上,我們可以透過建構函式進行複製操作,不過依然提供一個方法來方便記憶、使用。
Mat.prototype.clone = function(){
>return new Mat(this.row, this.col, this.data);
};
取得指定元素 我們有兩種方法獲取矩陣元素。
陣列方法 由於實際上Mat是以陣列形式保存資料的,而資料看起來是這樣的:
R00 G00 B00 A00 R01 G01 B01 A01 … R0n G0n B0n A0n
R10 G10 B10 A10 R11 G11 B11 A11 …… R1n G1n B1n A1n
……
Rm0 Gm0 Bm0 Am0 Rm1 Gm1 Bm111, Nmn G、B、A分別代表各通道的數值,而下標第一個表示行號,第二個表示列號。即第k行,第j列的G通道數值就是Gkj。
我們很容易得到對於一個Mat類型的mat來說,第k行,第j列像素的每個元素分別是:
Rkj = mat.data[(k * mat.col j) * 4 0]
Gkj = mat.data[(k * mat.col j) * 4 1]
Bkj = mat.data[(k * mat.col j) * 4 2]
Akj = mat .data[(k * mat.col j) * 4 3]
Buffer部分引用方法
透過Buffer的部分引用,我們可以得到矩陣的部分引用,例如我們可以利用這個來取得一個像素點的資料數組,而改變這個數組中的值,對應的矩陣資料也會改變;再例如我們可以以其他資料類型的方式讀取資料。而這些對於普通Array是不能實現的。下面我們來看看at方法的實作:
Mat. prototype.at = function(__type, __x, __y){
var type = __type,
x = __x || 0,
y = __y || 0,
rowLen = this.col * this.channel * this.bytes,
len = 1;
if(type.indexOf("Vec") > -1){
var temp = __type.match(/Vec(d )([ a-z])/);
len = parseInt(temp[1]);
switch(temp[2]){
case "b":
type = "uchar";
break;
case "s":
type = "short";
break;
case "i":
type = "int";
break;
case "f":
type = "float";
break;
case "d":
type = "double";
break;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
switch(type){
case "uchar":
return new Uint8Array(this.buffer, (y * rowLen x), len);
break;
case "short":
return new Int16Array(this.buffer, (y * rowLen x * 2), len);
break;
case "int":
return new Int32Array(this.buffer, (y * rowLen x * 4), len);
break; case "float": return new Float32Array(this.buffer, (y * rowLen x * 4), len); break; case "doulble": return new Float64Array(this.buffer, (y * rowLen x * 8), len); break; default: console.error("不支援資料型態"); } };
如果你對ArrayBuffer和TypedArray還不太清楚,可以參考:HTML5 中的新陣列。
String type - 需要傳回的資料類型。支援:
uchar 無符號8位元整數
short 有符號16位元整數
int 有符號32位元整數
float 有符號32位元浮點數
double 有符號64位元浮點數
Vec 向量形式 向量形式字串拼字是:Vec (型) (個數),例如Vecb4就是4個無符號8位元整數,這是常見的得到一個像素點資料的方法,例如為了得到mat第j行,第k列的像素數據,可以使用:
mat.at("Vecb4", j, k);
int x - 要取得的元素在矩陣的行數。
int y - 要取得的元素在矩陣的列數。
getRow方法和getCol方法 類似at的實作方法,我們可以輕易寫出取得某一行或某一列的方法:
Mat.prototype.getRow = function(__i){
var len = this.col * this.channel,
rowLen = len * this.bytes,
i = __i || 0;
return new this.data.constructor(this.buffer, i * rowLen, len);
};
程式碼如下:
.getCol = function(__i){
var len = this.col * this.channel,
rowLen = len * this.bytes,
array = [],
i = __i || 0 ;
function getAllElement(__constructor){
var row = this.row,
channel = this.channel;
for(var j = 0; j array .push(new __constructor(this.buffer, j * rowLen i, 1 * channel));
}
}
getAllElement(this.data.constructor);
return array;
};
複製程式碼
程式碼如下:
Mat.prototype.rowRange = function(__i, __j){
var len = this.col * this.channel,
rowLen = len * this.bytes,
array = [],
i = __i || 0,
j = __j || this.row;
function getAllElement (__constructor){
var row = this.row;
for(var k = i; k array.push(new __constructor(this.buffer, k * rowLen, len));
}
}
getAllElement(this.data.constructor);
複製程式碼
程式碼如下:
Mat.prototype.colRange = function(__i, __j){
var len = this. col * this.channel,
rowLen = len * this.bytes,
array = [],
i = __i || 0,
j = __j || this.col;
function getAllElement(__constructor){
var row = this.row
channel = this.channel;
for(var k = 0; k array.push(new __constructor (this.buffer, k * rowLen __i, (__j - __i 1) * channel));
} } getAllElement(Float64Array); return array; > 這四種方法回傳的都是一種Array
的陣列。如果要取得這個陣列rect第j行,第k列的元素,則可用: rect[j][k]