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 相关文章推荐
jquery 插件 人性化的消息显示
Jan 21 Javascript
javascript 禁止复制网页
Jun 11 Javascript
JavaScript浏览器选项卡效果
Aug 25 Javascript
Node.js插件的正确编写方式
Aug 03 Javascript
Bootstrap按钮下拉菜单组件详解
May 10 Javascript
angularjs中回车键触发某一事件的方法
Apr 24 Javascript
简单实现js轮播图效果
Jul 14 Javascript
用vue2.0实现点击选中active其他选项互斥的效果
Apr 12 Javascript
Vue.js最佳实践(五招助你成为vuejs大师)
May 04 Javascript
傻瓜式vuex语法糖kiss-vuex整理
Dec 21 Javascript
4 种滚动吸顶实现方式的比较
Apr 09 Javascript
微信小程序云开发如何实现数据库自动备份实现
Aug 16 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函数utf8转gb2312编码
2006/12/21 PHP
PHP比你想象的好得多
2014/11/27 PHP
php的sso单点登录实现方法
2015/01/08 PHP
PHP session 会话处理函数
2016/06/06 PHP
Laravel框架实现文件上传的方法分析
2019/09/29 PHP
javascript一点特殊用法
2008/05/28 Javascript
jsTree树控件(基于jQuery, 超强悍)[推荐]
2009/09/01 Javascript
表头固定(利用jquery实现原理介绍)
2012/11/08 Javascript
JavaScript prototype属性深入介绍
2012/11/27 Javascript
JavaScript等比例缩放图片控制超出范围的图片
2013/08/06 Javascript
window resize和scroll事件的基本优化思路
2014/04/29 Javascript
javascript返回顶部的按钮实现方法
2016/01/09 Javascript
javascript每日必学之多态
2016/02/23 Javascript
JavaScript常用正则验证函数实例小结【年龄,数字,Email,手机,URL,日期等】
2017/01/23 Javascript
深入理解ES7的async/await的用法
2017/09/09 Javascript
详解用async/await来处理异步
2019/08/28 Javascript
vue 兄弟组件的信息传递的方法实例详解
2019/08/30 Javascript
微信小程序tab左右滑动切换功能的实现代码
2021/02/08 Javascript
[03:11]DOTA2上海特锦赛小组赛第一日recap精彩回顾
2016/02/28 DOTA
python requests包的request()函数中的参数-params和data的区别介绍
2020/05/05 Python
Python3如何实现Win10桌面自动切换
2020/08/11 Python
阿迪达斯中国官网:Adidas中国
2020/12/14 全球购物
颇特女士香港官网:NET-A-PORTER香港
2021/03/08 全球购物
房地产销售大学生自我评价分享
2013/11/11 职场文书
历史学专业求职信
2014/06/19 职场文书
泸县召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
大学生求职自荐信范文
2015/03/04 职场文书
2015年大学教师工作总结
2015/05/20 职场文书
2015法院个人工作总结范文
2015/05/25 职场文书
2016教师学习教育法心得体会
2016/01/19 职场文书
学长教您写论文:经验总结
2019/07/09 职场文书
Ajax是什么?Ajax高级用法之Axios技术
2021/04/21 Javascript
CSS预处理框架——Stylus
2021/04/21 HTML / CSS
Java SSH 秘钥连接mysql数据库的方法
2021/06/28 Java/Android
Javascript之datagrid查询详解
2021/09/15 Javascript
MyBatis核心源码深度剖析SQL语句执行过程
2022/05/20 Java/Android