zl程序教程

您现在的位置是:首页 >  前端

当前栏目

Javascript图像处理思路及实现代码

2023-06-13 09:14:43 时间
思路
HTML5的canvas提供了getImageData接口来获取canvas中的数据,所以我们能够先用drawImage接口将图片画在canvas上然后再通过getImageData得到图片数据矩阵。

需要注意,虽然IE9开始支持了canvas接口,但是其getImageData获取的数据并不是以标准的TypedArray方式存储的,或者说IE9没有提供对WebGLNativebinarydata的支持,所以如果需要对IE9支持,下面的矩阵需要用Array的方式保存。虽然IE9以下版本(例如IE8)有开源项目explorercanvas提供canvas支持,但很可惜G_vmlCanvasManager并没有提供位图数据获取接口。TypedArray的相关内容可以参考HTML5的新数组

基本矩阵
在图像处理中,矩阵计算是非常重要的内容,所以我们首先来建立一个矩阵模型。
通过getImageData接口获取的ImageData虽然具有类似矩阵的结构,但是他的结构是不可变的,不适合扩展,所以我们选择在Javascript中自建一个矩阵。
复制代码代码如下:

functionMat(__row,__col,__data,__buffer){
this.row=__row||0;
this.col=__col||0;
this.channel=4;
this.buffer=__buffer||newArrayBuffer(__row*__col*4);
this.data=newUint8ClampedArray(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。
图片数据转成矩阵的方法
复制代码代码如下:

functionimread(__image){
varwidth=__image.width,
height=__image.height;
iResize(width,height);
iCtx.drawImage(__image,0,0);
varimageData=iCtx.getImageData(0,0,width,height),
tempMat=newMat(height,width,imageData.data);
imageData=null;
iCtx.clearRect(0,0,width,height);
returntempMat;
}

注意:这里的__image指的是Image对象,不是字符串URL。因为浏览器中Image的读取是一个异步过程,并不能立刻返回相应的Mat对象,所以这个函数应当这样使用:
复制代码代码如下:
varimg=newImage();
img.onload=function(){
varmyMat=cv.imread(img);
};
img.src="1.jpg";

iCtx和iResize方法是一个全局变量,允许给其它函数公用:
复制代码代码如下:
variCanvas=document.createElement("canvas"),
iCtx=iCanvas.getContext("2d");
functioniResize(__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上绘制经过处理的图像了。
复制代码代码如下:
functionRGBA2ImageData(__imgMat){
varwidth=__imgMat.col,
height=__imgMat.row,
imageData=iCtx.createImageData(width,height);
imageData.data.set(__imgMat.data);
returnimageData;
}

我们来看一下putImageData方法
用途
通过图像数据,在canvas上绘制图像。
语法
context.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);
将彩色图转换成灰度图
最后我们进行一个简单的色彩空间变换,将图像从RGBA转成GRAY。
复制代码代码如下:
functioncvtColor(__src){
if(__src.type&&__src.type==="CV_RGBA"){
varrow=__src.row,
col=__src.col;
vardst=newMat(row,col);
data=dst.data,
data2=__src.data;
varpix1,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{
returnsrc;
}
returndst;
}

参考OpenCV文档中的转换公式
RGBAtoGray:Y<-0.299*R+0.587*G+0.114*B
GraytoRGBA:R<-Y,G<-Y,B<-Y,A<-255
我们可以得出RGBAtoGRAY(指的是拥有4个通道)对应映射关系应该为:
RGBAtoRGBA(GRAY):R1=G1=B1<-0.299*R+0.587*G+0.114*B,A1<-A