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 相关文章推荐
javascript+css 网页每次加载不同样式的实现方法
Dec 27 Javascript
JavaScript 开发规范要求(图文并茂)
Jun 11 Javascript
jQuery大于号(&gt;)选择器的作用解释
Jan 13 Javascript
jQuery插件kinMaxShow扩展效果用法实例
May 04 Javascript
JavaScript框架是什么?怎样才能叫做框架?
Jul 01 Javascript
详解JavaScript中localStorage使用要点
Jan 13 Javascript
JS模拟的Map类实现方法
Jun 17 Javascript
Javascript动画效果(2)
Oct 11 Javascript
IE8兼容Jquery.validate.js的问题
Dec 01 Javascript
原生JS实现图片翻书效果
Feb 16 Javascript
解决Vue中mounted钩子函数获取节点高度出错问题
May 18 Javascript
vue日历/日程提醒/html5本地缓存功能
Sep 02 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获取谷歌PR值算法,附上php查询PR值代码示例
2011/12/25 PHP
CodeIgniter生成网站sitemap地图的方法
2013/11/13 PHP
php自定义加密与解密程序实例
2014/12/31 PHP
php获取系统变量方法小结
2015/05/29 PHP
PHP使用xpath解析XML的方法详解
2017/05/20 PHP
yii2 上传图片的示例代码
2018/11/02 PHP
PHP的图像处理实例小结【文字水印、图片水印、压缩图像等】
2019/12/20 PHP
关于js注册事件的常用方法
2013/04/03 Javascript
探讨JQUERY JSON的反序列化类 using问题的解决方法
2013/12/19 Javascript
jQuery中insertBefore()方法用法实例
2015/01/08 Javascript
JS中Array数组学习总结
2017/01/18 Javascript
走进javascript——不起眼的基础,值和分号
2017/02/24 Javascript
VUE axios上传图片到七牛的实例代码
2017/07/28 Javascript
vue实现侧边栏导航效果
2019/10/21 Javascript
详解vue beforeEach 死循环问题解决方法
2020/02/25 Javascript
JavaScript适配器模式原理与用法实例详解
2020/03/09 Javascript
Python FTP操作类代码分享
2014/05/13 Python
Python函数式编程指南(二):从函数开始
2015/06/24 Python
Python将阿拉伯数字转换为罗马数字的方法
2015/07/10 Python
spark: RDD与DataFrame之间的相互转换方法
2018/06/07 Python
浅谈关于Python3中venv虚拟环境
2018/08/01 Python
Python Selenium参数配置方法解析
2020/01/19 Python
python 实现Harris角点检测算法
2020/12/11 Python
canvas实现圆绘制的示例代码
2019/09/11 HTML / CSS
举例详解HTML5中使用JSON格式提交表单
2015/06/16 HTML / CSS
英国翻新电子产品购物网站:Tech Trade
2017/12/25 全球购物
户外拓展活动方案
2014/02/11 职场文书
考核工作实施方案
2014/03/30 职场文书
群众路线教育实践活动个人对照检查材料思想汇报(社区班子)
2014/10/06 职场文书
建筑横幅标语
2014/10/09 职场文书
工程竣工验收申请报告
2015/05/15 职场文书
2015年会计人员工作总结
2015/05/22 职场文书
MySQL 重写查询语句的三种策略
2021/05/10 MySQL
mysql备份策略的实现(全量备份+增量备份)
2021/07/07 MySQL
golang实现浏览器导出excel文件功能
2022/03/25 Golang
vue elementUI表格控制对应列
2022/04/13 Vue.js