Javascript圖像處理


思路

HTML5的canvas提供了getImageData接口來獲取canvas中的數據,所以我們能夠先用drawImage接口將圖片畫在canvas上然后再通過getImageData得到圖片數據矩陣。

canvas的瀏覽器支持情況,請參見:

http://html5test.com/compare/feature/canvas-context.html

需要注意,雖然IE9開始支持了canvas接口,但是其getImageData獲取的數據並不是以標准的TypedArray方式存儲的,或者說IE9沒有提供對WebGL Native binary data的支持,所以如果需要對IE9支持,下面的矩陣需要用Array的方式保存。雖然IE9以下版本(例如IE8)有開源項目explorercanvas提供canvas支持,但很可惜G_vmlCanvasManager並沒有提供位圖數據獲取接口。TypedArray的相關內容可以參考HTML5的新數組,TypedArray的相關支持情況可以參見:

http://html5test.com/compare/feature/webgl-datatypes-ArrayBuffer.html

 

基本矩陣

在圖像處理中,矩陣計算是非常重要的內容,所以我們首先來建立一個矩陣模型。

通過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 = 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);

例子

http://www.w3schools.com/tags/playcanvas.asp?filename=playcanvas_drawimagedy&preval=img,90,130,50,60,10,10,50,60

還有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];

http://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_canvas_getimagedata_firstpx

 

矩陣轉成圖像數據的方法

經過處理后的矩陣,需要一個方法變成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

 

系列目錄

Javascript圖像處理系列

 

參考資料

HTML Canvas Reference

Miscellaneous Image Transformations


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM