Javascript影像處理思路及實現代碼

來源:互聯網
上載者:User

思路
HTML5的canvas提供了getImageData介面來擷取canvas中的資料,所以我們能夠先用drawImage介面將圖片畫在canvas上然後再通過getImageData得到圖片資料矩陣。

需要注意,雖然IE9開始支援了canvas介面,但是其getImageData擷取的資料並不是以標準的TypedArray方式儲存的,或者說IE9沒有提供對WebGL Native binary data的支援,所以如果需要對IE9支援,下面的矩陣需要用Array的方式儲存。雖然IE9以下版本(例如IE8)有開源項目explorercanvas提供canvas支援,但很可惜G_vmlCanvasManager並沒有提供位元影像資料擷取介面。TypedArray的相關內容可以參考HTML5的新數組

基本矩陣
在影像處理中,矩陣計算是非常重要的內容,所以我們首先來建立一個矩陣模型。
通過getImageData介面擷取的ImageData雖然具有類似矩陣的結構,但是他的結構是不可變的,不適合擴充,所以我們選擇在Javascript中自建一個矩陣。 複製代碼 代碼如下:function Mat(__row, __col, __data, __buffer){
this.row = __row || 0;
this.col = __col || 0;
this.channel = 4;
this.buffer = __buffer || new ArrayBuffer(__row * __col * 4);
this.data = new Uint8ClampedArray(this.buffer);
__data && this.data.set(__data);
this.bytes = 1;
this.type = "CV_RGBA";
}

row - 代表矩陣的行數
col - 代表矩陣的列數
channel - 代表通道數量,因為通過getImageData擷取的圖片資料是以RGBA色彩空間進行描述的,即有Red(紅)、Green(綠)、Blue(藍)和Alpha(不透明度)四個通道。
buffer - 資料所用的ArrayBuffer引用。
data - 圖片的Uint8ClampedArray數組資料。
bytes - 每個資料單位佔用位元組,因為是uint8資料類型,所以佔用位元組數為1。
type - 資料類型是CV_RGBA。
圖片資料轉成矩陣的方法 複製代碼 代碼如下:function imread(__image){
var width = __image.width,
height = __image.height;
iResize(width, height);
iCtx.drawImage(__image, 0, 0);
var imageData = iCtx.getImageData(0, 0, width, height),
tempMat = new Mat(height, width, imageData.data);
imageData = null;
iCtx.clearRect(0, 0, width, height);
return tempMat;
}

注意:這裡的__image指的是Image對象,不是字串URL。因為瀏覽器中Image的讀取是一個非同步過程,並不能立刻返回相應的Mat對象,所以這個函數應當這樣使用: 複製代碼 代碼如下:var img = new Image();
img.onload = function(){
var myMat = cv.imread(img);
};
img.src = "1.jpg";

iCtx和iResize方法是一個全域變數,允許給其它函數公用: 複製代碼 代碼如下:var iCanvas = document.createElement("canvas"),
iCtx = iCanvas.getContext("2d");
function iResize(__width, __height){
iCanvas.width = __width;
iCanvas.height = __height;
}

我們來看一下drawImage方法
用途
在canvas上繪製一個圖片。
文法
context.drawImage(img,x,y);
context.drawImage(img,x,y,width,height);
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
例子
還有getImageData方法:
用途
擷取canvas中的映像資料。
資料是以RGBA色彩空間返回的,即:
R - 紅色通道大小
G - 綠色通道大小
B - 藍色通道大小
A - 不透明程度大小
文法
context.getImageData(x,y,width,height);
例子 複製代碼 代碼如下:red = imgData.data[0];
green = imgData.data[1];
blue = imgData.data[2];
alpha = imgData.data[3];

矩陣轉成映像資料的方法
經過處理後的矩陣,需要一個方法變成ImageData,然後我們就可以通過putImageData方法,在canvas上繪製經過處理的映像了。 複製代碼 代碼如下:function RGBA2ImageData(__imgMat){
var width = __imgMat.col,
height = __imgMat.row,
imageData = iCtx.createImageData(width, height);
imageData.data.set(__imgMat.data);
return imageData;
}

我們來看一下putImageData方法
用途
通過映像資料,在canvas上繪製映像。
文法
context.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);
將彩色圖轉換成灰階圖
最後我們進行一個簡單的色彩空間變換,將映像從RGBA轉成GRAY。 複製代碼 代碼如下:function cvtColor(__src){
if(__src.type && __src.type === "CV_RGBA"){
var row = __src.row,
col = __src.col;
var dst = new Mat(row, col);
data = dst.data,
data2 = __src.data;
var pix1, pix2, pix = __src.row * __src.col * 4;
while (pix){
data[pix -= 4] = data[pix1 = pix + 1] = data[pix2 = pix + 2] = (data2[pix] * 299 + data2[pix1] * 587 + data2[pix2] * 114) / 1000;
data[pix + 3] = data2[pix + 3];
}
}else{
return src;
}
return dst;
}

參考OpenCV文檔中的轉換公式
RGBA to Gray: Y <- 0.299 * R + 0.587 * G + 0.114 * B
Gray to RGBA: R <- Y, G <- Y, B <- Y, A <- 255
我們可以得出RGBA to GRAY(指的是擁有4個通道)對應映射關係應該為:
RGBA to RGBA(GRAY): R1 = G1 = B1 <- 0.299 * R + 0.587 * G + 0.114 * B , A1 <- A

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.