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


Posted in Javascript onDecember 25, 2012

思路
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
Javascript 相关文章推荐
用js一次改变多个input的readonly属性值的方法
Jun 11 Javascript
ff chrome和ie下全局动态定位的异同及全局高度的取法
Jun 30 Javascript
完美解决jQuery fancybox ie 无法显示关闭按钮的问题
Nov 29 Javascript
JS实现点击表头表格自动排序(含数字、字符串、日期)
Jan 22 Javascript
jquery仿京东侧边栏导航效果
Mar 02 Javascript
轻松理解JavaScript闭包
Mar 14 Javascript
微信小程序登录态控制深入分析
Apr 12 Javascript
JS正则验证多个邮箱完整实例【邮箱用分号隔开】
Apr 19 Javascript
Agularjs妙用双向数据绑定实现手风琴效果
May 26 Javascript
Vue2.0 从零开始_环境搭建操作步骤
Jun 14 Javascript
jQuery Collapse1.1.0折叠插件简单使用
Aug 28 jQuery
微信小程序网络封装(简单高效)
Aug 06 Javascript
javascript的offset、client、scroll使用方法详解
Dec 25 #Javascript
JS解析json数据并将json字符串转化为数组的实现方法
Dec 25 #Javascript
jquery 事件冒泡的介绍以及如何阻止事件冒泡
Dec 25 #Javascript
js优化针对IE6.0起作用(详细整理)
Dec 25 #Javascript
js 取时间差去掉周六周日实现代码
Dec 25 #Javascript
纯js网页画板(Graphics)类简介及实现代码
Dec 24 #Javascript
Knockoutjs快速入门(经典)
Dec 24 #Javascript
You might like
PHP迭代器的内部执行过程详解
2013/11/12 PHP
php curl上传、下载、https登陆实现代码
2017/07/23 PHP
图片自动缩小的js代码,用以防止图片撑破页面
2007/03/12 Javascript
数组方法解决JS字符串连接性能问题有争议
2011/01/12 Javascript
javascript学习笔记(四) Number 数字类型
2012/06/19 Javascript
jQuery实现用方向键控制层的上下左右移动
2013/01/13 Javascript
js中的前绑定和后绑定详解
2013/08/01 Javascript
莱鸟介绍javascript onclick事件
2016/01/06 Javascript
js简单实现图片延迟加载的方法
2016/07/19 Javascript
js实现非常棒的弹出div
2016/10/06 Javascript
浅析上传头像示例及其注意事项
2016/12/14 Javascript
微信小程序开发之map地图实现教程
2017/06/08 Javascript
Angular中的$watch、$watchGroup、$watchCollection
2017/06/25 Javascript
基于ES6 Array.of的用法(实例讲解)
2017/09/05 Javascript
使用vs code开发Nodejs程序的使用方法
2017/09/21 NodeJs
使用vue如何构建一个自动建站项目
2018/02/05 Javascript
layui实现table加载的示例代码
2018/08/14 Javascript
vue中如何自定义右键菜单详解
2020/12/08 Vue.js
Pycharm代码无法复制,无法选中删除,无法编辑的解决方法
2018/10/22 Python
Python使用random模块生成随机数操作实例详解
2019/09/17 Python
django框架中ajax的使用及避开CSRF 验证的方式详解
2019/12/11 Python
解决python web项目意外关闭,但占用端口的问题
2019/12/17 Python
使用卷积神经网络(CNN)做人脸识别的示例代码
2020/03/27 Python
Alpine安装Python3依赖出现的问题及解决方法
2020/12/25 Python
国际旅客访问北美最大的汽车租赁提供商:Alamo Rent A Car
2018/06/13 全球购物
荣耀商城:HIHONOR
2020/11/03 全球购物
保安自我鉴定范文
2013/12/08 职场文书
护理专科学生自荐书
2014/07/05 职场文书
群众路线剖析材料范文
2014/10/09 职场文书
2014年人力资源部工作总结
2014/11/19 职场文书
小班教师个人总结
2015/02/05 职场文书
入党转正介绍人意见
2015/06/03 职场文书
工商行政处罚决定书
2015/06/24 职场文书
重阳节简报
2015/07/20 职场文书
基于JavaScript实现省市联动效果
2021/06/22 Javascript
js作用域及作用域链工作引擎
2022/07/07 Javascript