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获取元素相对窗口位置的实现代码
Sep 28 Javascript
node.js中的require使用详解
Dec 15 Javascript
深入理解JavaScript系列(40):设计模式之组合模式详解
Mar 04 Javascript
jQuery插件Tooltipster实现漂亮的工具提示
Apr 12 Javascript
JavaScript将字符串转换为整数的方法
Apr 14 Javascript
轻松学习jQuery插件EasyUI EasyUI创建RSS Feed阅读器
Nov 30 Javascript
javascript正则表达式定义(语法)总结
Jan 08 Javascript
jQuery模拟下拉框选择对应菜单的内容
Mar 07 Javascript
vue+vant实现商品列表批量倒计时功能
Jan 13 Javascript
Vue中的this.$options.data()和this.$data用法说明
Jul 26 Javascript
JavaScript中ES6规范中let和const的用法和区别
Aug 06 Javascript
PHP 502bad gateway原因及解决方案
Nov 13 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_Flame(Version:Progress)的原代码
2006/10/09 PHP
PHP运行出现Notice : Use of undefined constant 的完美解决方案分享
2012/03/05 PHP
php实现的返回数据格式化类实例
2014/09/22 PHP
PHP中使用curl伪造IP的简单方法
2015/08/07 PHP
微信支付开发动态链接Native支付
2016/07/12 PHP
php实现购物车功能(以大苹果购物网为例)
2017/03/09 PHP
php实现往pdf中加数字签名操作示例【附源码下载】
2018/08/07 PHP
javascript:文字不间断向左移动的实例代码
2013/08/08 Javascript
Javascript中arguments对象详解
2014/10/22 Javascript
node.js中的url.parse方法使用说明
2014/12/10 Javascript
完美解决jQuery符号$与其他javascript 库、框架冲突的问题
2016/08/09 Javascript
webpack+vue.js快速入门教程
2016/10/12 Javascript
JS实现HTML标签转义及反转义
2020/04/14 Javascript
jQuery上传多张图片带进度条样式(DEMO)
2017/03/02 Javascript
Vue组件tree实现树形菜单
2017/04/13 Javascript
Angular模板表单校验方法详解
2017/08/11 Javascript
vue源码解析之事件机制原理
2018/04/21 Javascript
element-ui组件中input等的change事件中传递自定义参数
2019/05/22 Javascript
解决layui追加或者动态修改的表单元素“没效果”的问题
2019/09/18 Javascript
基于JavaScript实现留言板功能
2020/03/16 Javascript
浅析JavaScript中的事件委托机制跟深浅拷贝
2021/01/20 Javascript
浅谈django model的get和filter方法的区别(必看篇)
2017/05/23 Python
Pyqt5自适应布局实例
2019/12/13 Python
Python selenium环境搭建实现过程解析
2020/09/08 Python
python 实现的IP 存活扫描脚本
2020/12/10 Python
关于CSS Tooltips(鼠标经过时显示)的效果
2013/04/10 HTML / CSS
CSS3实现伪类hover离开时平滑过渡效果示例
2017/08/10 HTML / CSS
HTML5 LocalStorage 本地存储详细概括(多图)
2017/08/18 HTML / CSS
加拿大国民体育购物网站:National Sports
2018/11/04 全球购物
会计系中文个人求职信
2013/12/24 职场文书
百度吧主申请感言
2014/01/12 职场文书
个人对照检查材料思想汇报
2014/09/26 职场文书
2014年学校党建工作总结
2014/11/11 职场文书
小学教师个人总结
2015/02/05 职场文书
确保减税降费落地生根,用实实在在措施
2019/07/19 职场文书
yyds什么意思?90后已经听不懂00后讲话了……
2022/02/03 杂记