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面向对象编程 for Cookie
Sep 19 Javascript
javascript同步服务器时间和同步倒计时小技巧
Sep 24 Javascript
jquery html5 视频播放控制代码
Nov 06 Javascript
Bootstrap警告框(Alert)插件使用方法
Mar 21 Javascript
详解vue数据渲染出现闪烁问题
Jun 29 Javascript
Thinkjs3新手入门之添加一个新的页面
Dec 06 Javascript
判断jQuery是否加载完成,没完成继续判断的解决方法
Dec 06 jQuery
Vue服务器渲染Nuxt学习笔记
Jan 31 Javascript
Vue中的无限加载vue-infinite-loading的方法
Apr 08 Javascript
js实现动态增加文件域表单功能
Oct 22 Javascript
JQuery事件冒泡和默认行为代码实例
May 13 jQuery
解决Vue大括号字符换行踩的坑
Nov 09 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
中英文字符串翻转函数
2008/12/09 PHP
php中的观察者模式
2010/03/24 PHP
php使用sql数据库 获取字段问题介绍
2013/08/12 PHP
PHP实现模仿socket请求返回页面的方法
2014/11/04 PHP
php将HTML表格每行每列转为数组实现采集表格数据的方法
2015/04/03 PHP
Apache服务器下防止图片盗链的办法
2015/07/06 PHP
一个高效的JavaScript压缩工具下载集合
2007/03/06 Javascript
jQuery EasyUI datagrid实现本地分页的方法
2015/02/13 Javascript
js操作table元素实现表格行列新增、删除技巧总结
2015/11/18 Javascript
JSON遍历方式实例总结
2015/12/07 Javascript
理解jquery事件冒泡
2016/01/03 Javascript
在JavaScript中call()与apply()区别
2016/01/22 Javascript
jQuery 获取跨域XML(RSS)数据的相关总结分析
2016/05/18 Javascript
Javascript之Math对象详解
2016/06/07 Javascript
jQuery基于ID调用指定iframe页面内的方法
2016/07/06 Javascript
微信小程序 flex实现导航实例详解
2017/04/26 Javascript
Angular 4依赖注入学习教程之InjectToken的使用(八)
2017/06/04 Javascript
Mobile Web开发基础之四--处理手机设备的横竖屏问题
2017/08/11 Javascript
JS实现评价的星星功能
2017/08/20 Javascript
vue 实现走马灯效果
2019/10/28 Javascript
Python将list中的string批量转化成int/float的方法
2018/06/26 Python
Pyqt5自适应布局实例
2019/12/13 Python
python3.8.1+selenium实现登录滑块验证功能
2020/05/22 Python
Python如何生成xml文件
2020/06/04 Python
Python调用Redis的示例代码
2020/11/24 Python
Nike德国官网:Nike.com (DE)
2018/11/13 全球购物
艺术应用与设计个人的自我评价
2013/11/23 职场文书
物流管理专业自荐信
2014/06/23 职场文书
初中生旷课检讨书范文
2014/10/06 职场文书
教师批评与自我批评范文
2014/10/15 职场文书
离婚协议书范文
2015/01/26 职场文书
关于拾金不昧的感谢信(五篇)
2019/10/18 职场文书
Redis持久化与主从复制的实践
2021/04/27 Redis
tensorflow+k-means聚类简单实现猫狗图像分类的方法
2021/04/28 Python
Python序列化与反序列化相关知识总结
2021/06/08 Python
Java面试题冲刺第十七天--基础篇3
2021/08/07 面试题