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]点出统计器
Oct 11 Javascript
给超链接添加特效鼠标移动展示提示信息且随鼠标移动
Oct 17 Javascript
JS获取表格内指定单元格html内容的方法
Mar 31 Javascript
jQuery的end()方法使用详解
Jul 15 Javascript
js关于getImageData跨域问题的解决方法
Oct 14 Javascript
vue2.0 与 bootstrap datetimepicker的结合使用实例
May 22 Javascript
jQuery 中msgTips 顶部弹窗效果实现代码
Aug 14 jQuery
用vue构建多页面应用的示例代码
Sep 20 Javascript
解决bootstrap模态框数据缓存的问题方法
Aug 10 Javascript
react 项目中引入图片的几种方式
Jun 02 Javascript
Vue elementUI表单嵌套表格并对每行进行校验详解
Feb 18 Vue.js
详解JSON.parse和JSON.stringify用法
Feb 18 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静态新闻列表自动生成代码
2007/06/14 PHP
php 应用程序安全防范技术研究
2009/09/25 PHP
php 中的4种标记风格介绍
2012/05/10 PHP
php修改文件上传限制方法汇总
2015/04/07 PHP
简单谈谈PHP中的Reload操作
2016/12/12 PHP
php实现与python进行socket通信的方法示例
2017/08/30 PHP
CodeIgniter框架实现的整合Smarty引擎DEMO示例
2019/03/28 PHP
浅析js中2个等号与3个等号的区别
2013/08/06 Javascript
javascript页面上使用动态时间具体实现
2014/03/18 Javascript
node.js超时timeout详解
2014/11/26 Javascript
JS绘制生成花瓣效果的方法
2015/08/05 Javascript
jfinal与bootstrap的登录跳转实战演习
2015/09/22 Javascript
详解Backbone.js框架中的模型Model与其集合collection
2016/05/05 Javascript
jQuery插件Echarts实现的双轴图效果示例【附demo源码下载】
2017/03/04 Javascript
微信小程序搜索组件wxSearch实例详解
2017/06/08 Javascript
vue 使用ref 让父组件调用子组件的方法
2018/02/08 Javascript
vue-cli中的babel配置文件.babelrc实例详解
2018/02/22 Javascript
当vue路由变化时,改变导航栏的样式方法
2018/08/22 Javascript
JavaScript判断对象和数组的两种方法
2019/05/31 Javascript
javascript实现滚动条效果
2020/03/24 Javascript
Python import自定义模块方法
2015/02/12 Python
Python异常处理知识点总结
2019/02/18 Python
Python3之手动创建迭代器的实例代码
2019/05/22 Python
python plotly绘制直方图实例详解
2019/07/22 Python
python实现几种归一化方法(Normalization Method)
2019/07/31 Python
通过Python实现Payload分离免杀过程详解
2020/07/13 Python
python爬虫请求头设置代码
2020/07/28 Python
python实现经典排序算法的示例代码
2021/02/07 Python
CSS3教程:新增加的结构伪类
2009/04/02 HTML / CSS
CSS3 box-sizing属性详解
2016/11/15 HTML / CSS
基于CSS3 animation动画属性实现轮播图效果
2017/09/12 HTML / CSS
更夫岗位责任制
2014/02/11 职场文书
函授本科个人自我鉴定
2014/03/25 职场文书
军训决心书范文
2015/09/22 职场文书
2016年教师节贺卡寄语
2015/12/04 职场文书
详解MySQL中的主键与事务
2021/05/27 MySQL