Javascript圖像處理—為矩陣添加常用方法
更新時(shí)間:2012年12月27日 09:32:25 作者:
上一篇文章,我們定義了矩陣,這篇文章我們來(lái)給矩陣添加一些常用方法比如:toString方法、clone方法等,需要了解的朋友可以詳細(xì)參考下
前言
上一篇文章,我們定義了矩陣,這篇文章我們來(lái)給矩陣添加一些常用方法。
toString方法
toString方法通常用作將對(duì)象轉(zhuǎn)成字符串描述,所以我們將這一方法定義為輸出矩陣元素。
Mat.prototype.toString = function(){
var tempData = this.data,
text = "Mat("+ this.type +") = {\n",
num = this.col * this.channel;
for(var i = 0; i < this.row; i++){
text += "["
for(var j = 0; j < num; j++){
text += (tempData[i * num + j] + ",");
}
text += "]\n";
}
text += "}";
return text;
};
這樣,我們就可以通過(guò):
console.log(mat);
來(lái)輸出矩陣了。
clone方法
實(shí)際上,我們可以通過(guò)構(gòu)造函數(shù)進(jìn)行克隆操作,不過(guò)依然提供一個(gè)方法來(lái)方便記憶、使用。
Mat.prototype.clone = function(){
return new Mat(this.row, this.col, this.data);
};
獲取指定元素
我們有兩種方法獲取矩陣元素。
數(shù)組方法
由于實(shí)際上Mat是以數(shù)組形式保存數(shù)據(jù)的,而數(shù)據(jù)看起來(lái)是這樣的:
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 Bm1 Am1 …… Rmn Gmn Bmn Amn
其中大寫(xiě)R、G、B、A分別代表各通道的數(shù)值,而下標(biāo)第一個(gè)表示行號(hào),第二個(gè)表示列號(hào)。即第k行,第j列的G通道數(shù)值就是Gkj。
我們很容易得到對(duì)于一個(gè)Mat類型的mat來(lái)說(shuō),第k行,第j列像素的每個(gè)元素分別是:
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部分引用方法
通過(guò)Buffer的部分引用,我們可以得到矩陣的部分引用,比如我們可以利用這個(gè)來(lái)獲取一個(gè)像素點(diǎn)的數(shù)據(jù)數(shù)組,而改變這個(gè)數(shù)組中的值,相應(yīng)的矩陣數(shù)據(jù)也會(huì)改變;再比如我們可以以其他數(shù)據(jù)類型的方式讀取數(shù)據(jù)。而這些對(duì)于普通Array是不能實(shí)現(xiàn)的。下面我們來(lái)看一下at方法的實(shí)現(xiàn):
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("不支持?jǐn)?shù)據(jù)類型");
}
};
如果你對(duì)ArrayBuffer和TypedArray還不太清楚,可以參考:HTML5 中的新數(shù)組。
String type - 需要返回的數(shù)據(jù)類型。支持:
uchar 無(wú)符號(hào)8位整數(shù)
short 有符號(hào)16位整數(shù)
int 有符號(hào)32位整數(shù)
float 有符號(hào)32位浮點(diǎn)數(shù)
double 有符號(hào)64位浮點(diǎn)數(shù)
Vec 向量形式
向量形式字符串拼寫(xiě)是:Vec + (類型)+ (個(gè)數(shù)),例如Vecb4就是4個(gè)無(wú)符號(hào)8位整數(shù),這是常見(jiàn)的得到一個(gè)像素點(diǎn)數(shù)據(jù)的方法,例如為了得到mat第j行,第k列的像素?cái)?shù)據(jù),可以使用:
mat.at("Vecb4", j, k);
int x - 要獲取的元素在矩陣的行數(shù)。
int y - 要獲取的元素在矩陣的列數(shù)。
getRow方法和getCol方法
類似于at的實(shí)現(xiàn)方法,我們可以很容易寫(xiě)出獲取某一行或者某一列的方法:
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);
};
Mat.prototype.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 < row; j++){
array.push(new __constructor(this.buffer, j * rowLen + i, 1 * channel));
}
}
getAllElement(this.data.constructor);
return array;
};
rowRange和colRange方法
類似的,我們也可以得到指定行和指定列的方法:
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 <= j; k++){
array.push(new __constructor(this.buffer, k * rowLen, len));
}
}
getAllElement(this.data.constructor);
return array;
};
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 < row; k++){
array.push(new __constructor(this.buffer, k * rowLen + __i, (__j - __i + 1) * channel));
}
}
getAllElement(Float64Array);
return array;
};
這四種方法返回的都是一種Array<TypedArray>的數(shù)組。如果要獲取這個(gè)數(shù)組rect第j行,第k列的元素,則可用:
rect[j][k]
上一篇文章,我們定義了矩陣,這篇文章我們來(lái)給矩陣添加一些常用方法。
toString方法
toString方法通常用作將對(duì)象轉(zhuǎn)成字符串描述,所以我們將這一方法定義為輸出矩陣元素。
復(fù)制代碼 代碼如下:
Mat.prototype.toString = function(){
var tempData = this.data,
text = "Mat("+ this.type +") = {\n",
num = this.col * this.channel;
for(var i = 0; i < this.row; i++){
text += "["
for(var j = 0; j < num; j++){
text += (tempData[i * num + j] + ",");
}
text += "]\n";
}
text += "}";
return text;
};
這樣,我們就可以通過(guò):
復(fù)制代碼 代碼如下:
console.log(mat);
來(lái)輸出矩陣了。
clone方法
實(shí)際上,我們可以通過(guò)構(gòu)造函數(shù)進(jìn)行克隆操作,不過(guò)依然提供一個(gè)方法來(lái)方便記憶、使用。
復(fù)制代碼 代碼如下:
Mat.prototype.clone = function(){
return new Mat(this.row, this.col, this.data);
};
獲取指定元素
我們有兩種方法獲取矩陣元素。
數(shù)組方法
由于實(shí)際上Mat是以數(shù)組形式保存數(shù)據(jù)的,而數(shù)據(jù)看起來(lái)是這樣的:
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 Bm1 Am1 …… Rmn Gmn Bmn Amn
其中大寫(xiě)R、G、B、A分別代表各通道的數(shù)值,而下標(biāo)第一個(gè)表示行號(hào),第二個(gè)表示列號(hào)。即第k行,第j列的G通道數(shù)值就是Gkj。
我們很容易得到對(duì)于一個(gè)Mat類型的mat來(lái)說(shuō),第k行,第j列像素的每個(gè)元素分別是:
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部分引用方法
通過(guò)Buffer的部分引用,我們可以得到矩陣的部分引用,比如我們可以利用這個(gè)來(lái)獲取一個(gè)像素點(diǎn)的數(shù)據(jù)數(shù)組,而改變這個(gè)數(shù)組中的值,相應(yīng)的矩陣數(shù)據(jù)也會(huì)改變;再比如我們可以以其他數(shù)據(jù)類型的方式讀取數(shù)據(jù)。而這些對(duì)于普通Array是不能實(shí)現(xiàn)的。下面我們來(lái)看一下at方法的實(shí)現(xiàn):
復(fù)制代碼 代碼如下:
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("不支持?jǐn)?shù)據(jù)類型");
}
};
如果你對(duì)ArrayBuffer和TypedArray還不太清楚,可以參考:HTML5 中的新數(shù)組。
String type - 需要返回的數(shù)據(jù)類型。支持:
uchar 無(wú)符號(hào)8位整數(shù)
short 有符號(hào)16位整數(shù)
int 有符號(hào)32位整數(shù)
float 有符號(hào)32位浮點(diǎn)數(shù)
double 有符號(hào)64位浮點(diǎn)數(shù)
Vec 向量形式
向量形式字符串拼寫(xiě)是:Vec + (類型)+ (個(gè)數(shù)),例如Vecb4就是4個(gè)無(wú)符號(hào)8位整數(shù),這是常見(jiàn)的得到一個(gè)像素點(diǎn)數(shù)據(jù)的方法,例如為了得到mat第j行,第k列的像素?cái)?shù)據(jù),可以使用:
復(fù)制代碼 代碼如下:
mat.at("Vecb4", j, k);
int x - 要獲取的元素在矩陣的行數(shù)。
int y - 要獲取的元素在矩陣的列數(shù)。
getRow方法和getCol方法
類似于at的實(shí)現(xiàn)方法,我們可以很容易寫(xiě)出獲取某一行或者某一列的方法:
復(fù)制代碼 代碼如下:
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);
};
復(fù)制代碼 代碼如下:
Mat.prototype.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 < row; j++){
array.push(new __constructor(this.buffer, j * rowLen + i, 1 * channel));
}
}
getAllElement(this.data.constructor);
return array;
};
rowRange和colRange方法
類似的,我們也可以得到指定行和指定列的方法:
復(fù)制代碼 代碼如下:
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 <= j; k++){
array.push(new __constructor(this.buffer, k * rowLen, len));
}
}
getAllElement(this.data.constructor);
return array;
};
復(fù)制代碼 代碼如下:
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 < row; k++){
array.push(new __constructor(this.buffer, k * rowLen + __i, (__j - __i + 1) * channel));
}
}
getAllElement(Float64Array);
return array;
};
這四種方法返回的都是一種Array<TypedArray>的數(shù)組。如果要獲取這個(gè)數(shù)組rect第j行,第k列的元素,則可用:
rect[j][k]
您可能感興趣的文章:
- JavaScript圖像放大鏡效果實(shí)現(xiàn)方法詳解
- JavaScript如何使用插值實(shí)現(xiàn)圖像漸變
- JavaScript實(shí)現(xiàn)圖像模糊化的方法實(shí)例
- Javascript基礎(chǔ)_嵌入圖像的簡(jiǎn)單實(shí)現(xiàn)
- JavaScript圖像延遲加載庫(kù)Echo.js
- javascript實(shí)現(xiàn)圖像循環(huán)明暗變化的方法
- JS預(yù)覽圖像將本地圖片顯示到瀏覽器上
- javascript圖像處理—仿射變換深度理解
- Javascript圖像處理—圖像形態(tài)學(xué)(膨脹與腐蝕)
- 10大Js圖像處理庫(kù)
相關(guān)文章
極致之美——百行代碼實(shí)現(xiàn)全新智能語(yǔ)言
極致之美——百行代碼實(shí)現(xiàn)全新智能語(yǔ)言...2007-03-03
js實(shí)現(xiàn)鼠標(biāo)切換圖片(無(wú)定時(shí)器)
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)鼠標(biāo)切換圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-01-01
微信小程序movable view移動(dòng)圖片和雙指縮放實(shí)例代碼
movable-area是微信小程序的新組件,可以用來(lái)移動(dòng)視圖區(qū)域movable-view。這篇文章主要介紹了微信小程序movable view移動(dòng)圖片和雙指縮放實(shí)例代碼,需要的朋友可以參考下2017-08-08
document節(jié)點(diǎn)對(duì)象的獲取方式示例介紹
如果要操作一個(gè)元素,首先要獲取到它,下面為大家介紹下document節(jié)點(diǎn)對(duì)象的獲取方式,感興趣的朋友不要錯(cuò)過(guò)2013-12-12
javascript html5 canvas實(shí)現(xiàn)可拖動(dòng)省份的中國(guó)地圖
這篇文章主要介紹了javascript html5 canvas實(shí)現(xiàn)可拖動(dòng)省份的中國(guó)地圖的相關(guān)資料,需要的朋友可以參考下2016-03-03

