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+ajax实现顶一下,踩一下效果
Jul 17 Javascript
js获取UserControl内容为拼html时提供方便
Nov 02 Javascript
jquery仿百度百科底部浮动导航特效
Aug 08 Javascript
JavaScript编程中window的location与history对象详解
Oct 26 Javascript
浅谈js中的in-for循环
Jun 28 Javascript
JS实现批量上传文件并显示进度功能
Jun 27 Javascript
基于JavaScript实现无限加载瀑布流
Jul 21 Javascript
利用Three.js如何实现阴影效果实例代码
Sep 26 Javascript
详解Angular6.0使用路由步骤(共7步)
Jun 29 Javascript
vue router的基本使用和配置教程
Nov 05 Javascript
Vue开发环境中修改端口号的实现方法
Aug 15 Javascript
nuxt.js写项目时增加错误提示页面操作
Nov 05 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
德生H-501的评价与改造
2021/03/02 无线电
木翼下载系统中说明的PHP安全配置方法
2007/06/16 PHP
PHP rsa加密解密使用方法
2015/04/27 PHP
可兼容php5与php7的cURL文件上传功能实例分析
2018/05/11 PHP
Laravel框架实现超简单的分页效果示例
2019/02/08 PHP
Javascript操作URL函数修改版
2013/11/07 Javascript
Javascript中的String对象详谈
2014/03/03 Javascript
angularjs指令中的compile与link函数详解
2014/12/06 Javascript
JS组件Bootstrap导航条使用方法详解
2016/04/29 Javascript
深入浅出ES6新特性之函数默认参数和箭头函数
2016/08/01 Javascript
nodejs爬虫遇到的乱码问题汇总
2017/04/07 NodeJs
关于vue.js组件数据流的问题
2017/07/26 Javascript
vue中v-for通过动态绑定class实现触发效果
2018/12/06 Javascript
在Vue中使用icon 字体图标的方法
2019/06/14 Javascript
使用Vue实现调用接口加载页面初始数据
2019/10/28 Javascript
详解element-ui 表单校验 Rules 配置 常用黑科技
2020/07/11 Javascript
python原始套接字编程示例分享
2014/02/21 Python
Python中MySQL数据迁移到MongoDB脚本的方法
2016/04/28 Python
Python实现的多线程同步与互斥锁功能示例
2017/11/30 Python
利用python爬取斗鱼app中照片方法实例
2017/12/03 Python
对DataFrame数据中的重复行,利用groupby累加合并的方法详解
2019/01/30 Python
python tools实现视频的每一帧提取并保存
2020/03/20 Python
Python基于stuck实现scoket文件传输
2020/04/02 Python
Python包和模块的分发详细介绍
2020/06/19 Python
解决python中0x80072ee2错误的方法
2020/07/19 Python
python复合条件下的字典排序
2020/12/18 Python
EGO Shoes美国/加拿大:英国时髦鞋类品牌
2018/08/04 全球购物
华三通信H3C面试题
2015/05/15 面试题
Java中的异常处理机制的简单原理和应用
2013/04/27 面试题
迅雷Cued工作心得体会
2014/01/27 职场文书
工程建设实施方案
2014/03/14 职场文书
幼儿园毕业寄语
2014/04/03 职场文书
在教室放鞭炮的检讨书
2014/09/28 职场文书
工作失误检讨书
2015/01/26 职场文书
投资合作意向书范本
2015/05/08 职场文书
nginx 添加http_stub_status_module模块
2022/05/25 Servers