canvas 基础之图像处理的使用_html5教程技巧

来源:脚本之家  责任编辑:小易  

Canvas在我的理解中就好像在一张画布上绘制图像,它只能看到却“摸”不到,那要如何进行操作呢。我不知道网上是怎么做的,这里用自己的想法做了个DEMO分享给大家。思路:虽然Canvas不能拖拽,但div可以拖拽,那怎么把二者结合起来呢www.zgxue.com防采集请勿采集本网。

前些日子,前辈推荐了一个有趣的项目 —— Real-Time-Person-Removal ,这个项目使用了 TensorFlow.js ,以及 canvas 中的图像处理实现视频中的人物消失。借此机会,复习下 canvas 基础中的图像处理。

package zhidao;import java.awt.Canvas;import java.awt.Graphics;import java.awt.Image;import java.io.File;import java.io.IOException;import javax.imageio.ImageIO;public class

基础 API

给你一个旋转的demo: canvas id=\"myCanvas所以没在基础上整改。补充一个参考网站(英文的):http://tutorials.jenkov.com/html5-canvas/transformation.html (如果有帮助,望采纳,谢谢)

canvas 的图像处理能力通过 ImageData 对象来处理像素数据。主要的 API 如下: createImageData():创建一个空白的 ImageData 对象 getImageData():获取画布像素数据,每一个像素点有 4 个值 —— rgba putImageData():将像素数据写入画布

首先,通过对个旧矿区约900km2范围内原始ETM数据图像的几何校正、地理配准等预处理,得到具有统一地理坐标和校正控制点的各波段图像数据,然后根据各个波段特征值的统计分析,以及几种合成方案的

 

图像处理的各个内容是互相有联系的。一个实用的图像处理系统往往结合应用几种图像处理技术才能得到所需要的结果。图像编码技术可用以传输和存储图像。图像增强和复原可以是图像处理的最后目的,也可以是为

imageData = { width: Number, height: Number, data: Uint8ClampedArray}

编辑修改,处理修改。都是差不多的意思。说是基础这个要看你自己觉得编辑东西是不是比处理东西从字面上看来低级一些。但在我看来,两个都代表着一个意思,但是编辑代表的范围小了点,处理代表的

width 是 canvas 画布的宽或者说 x 轴的像素数量;height 是画布的高或者说 y 轴的像素数量;data 是画布的像素数据数组,总长度 w * h * 4,每 4 个值(rgba)代表一个像素。

对图片的处理

下面,我们通过几个例子来看下 canvas 基础的图片处理能力。

原图效果:

const cvs = document.getElementById("canvas");const ctx = cvs.getContext("2d");const img = new Image();img.src="图片 URL";img.onload = function () { ctx.drawImage(img, 0, 0, w, h);}

底片/负片效果

算法:将 255 与像素点的 rgb 的差,作为当前值。

function negative(x) { let y = 255 - x; return y;}

效果图:

const imageData = ctx.getImageData(0, 0, w, h);const { data } = imageData;let l = data.length;for(let i = 0; i < l; i+=4) { const r = data[i]; const g = data[i + 1]; const b = data[i + 2]; data[i] = negative(r); data[i + 1] = negative(g); data[i + 2] = negative(b);}ctx.putImageData(imageData, 0, 0);

单色效果

单色效果就是保留当前像素的 rgb 3个值中的一个,去除其他色值。

for(let i = 0; i < l; i+=4) { // 去除了 r 、g 的值 data[i] = 0; data[i + 1] = 0;}

效果图:

 

灰度图

灰度图:每个像素只有一个色值的图像。0 到 255 的色值,颜色由黑变白。

for(let i = 0; i < l; i+=4) { const r = data[i]; const g = data[i + 1]; const b = data[i + 2]; const gray = grayFn(r, g, b); data[i] = gray; data[i + 1] = gray; data[i + 2] = gray;}

算法1——平均法:

const gray = (r + g + b) / 3;

效果图:

 

算法2——人眼感知:根据人眼对红绿蓝三色的感知程度:绿 > 红 > 蓝,给定权重划分

const gray = r * 0.3 + g * 0.59 + b * 0.11

效果图:

除此以外,还有:

取最大值或最小值。

const grayMax = Math.max(r, g, b); // 值偏大,较亮const grayMin = Math.min(r, g, b); // 值偏小,较暗

取单一通道,即 rgb 3个值中的一个。

 二值图

算法:确定一个色值,比较当前的 rgb 值,大于这个值显示黑色,否则显示白色。

for(let i = 0; i < l; i+=4) { const r = data[i]; const g = data[i + 1]; const b = data[i + 2]; const gray = gray1(r, g, b); const binary = gray > 126 ? 255 : 0; data[i] = binary; data[i + 1] = binary; data[i + 2] = binary;}

效果图:

 

高斯模糊

高斯模糊是“模糊”算法中的一种,每个像素的值都是周围相邻像素值的加权平均。原始像素的值有最大的高斯分布值(有最大的权重),相邻像素随着距离原始像素越来越远,权重也越来越小。

一阶公式:

(使用一阶公式是因为一阶公式的算法比较简单)

const radius = 5; // 模糊半径const weightMatrix = generateWeightMatrix(radius); // 权重矩阵for(let y = 0; y < h; y++) { for(let x = 0; x < w; x++) { let [r, g, b] = [0, 0, 0]; let sum = 0; let k = (y * w + x) * 4; for(let i = -radius; i <= radius; i++) { let x1 = x + i; if(x1 >= 0 && x1 < w) { let j = (y * w + x1) * 4; r += data[j] * weightMatrix[i + radius]; g += data[j + 1] * weightMatrix[i + radius]; b += data[j + 2] * weightMatrix[i + radius]; sum += weightMatrix[i + radius]; } } data[k] = r / sum; data[k + 1] = g / sum; data[k + 2] = b / sum; }}for(let x = 0; x < w; x++) { for(let y = 0; y < h; y++) { let [r, g, b] = [0, 0, 0]; let sum = 0; let k = (y * w + x) * 4; for(let i = -radius; i <= radius; i++) { let y1 = y + i; if(y1 >= 0 && y1 < h) { let j = (y1 * w + x) * 4; r += data[j] * weightMatrix[i + radius]; g += data[j + 1] * weightMatrix[i + radius]; b += data[j + 2] * weightMatrix[i + radius]; sum += weightMatrix[i + radius]; } } data[k] = r / sum; data[k + 1] = g / sum; data[k + 2] = b / sum; }}function generateWeightMatrix(radius = 1, sigma) { // sigma 正态分布的标准偏差 const a = 1 / (Math.sqrt(2 * Math.PI) * sigma); const b = - 1 / (2 * Math.pow(sigma, 2)); let weight, weightSum = 0, weightMatrix = []; for (let i = -radius; i <= radius; i++){ weight = a * Math.exp(b * Math.pow(i, 2)); weightMatrix.push(weight); weightSum += weight; } return weightMatrix.map(item => item / weightSum); // 归一处理}

效果图:

 

其他效果

这里再简单介绍下其他的图像效果处理,因为例子简单重复,所以不再给出代码和效果图。 亮度调整:将 rgb 值,分别加上一个给定值。 透明化处理:改变 rgba 值中的 a 值。 对比度增强:将 rgb 值分别乘以 2,然后再减去一个给定值。

总结

好了,上面就是一些基础的图像处理算法。

参考资料

高斯模糊的算法

高斯模糊

到此这篇关于canvas 基础之图像处理的使用的文章就介绍到这了,更多相关canvas 图像处理内容请搜索真格学网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持真格学网!

HTML5 的标准已经出来好久了,但是似乎其中的 Canvas 现在并没有在太多的地方用到。一个很重要的原因是,Canvas 的标准还没有完全确定,不适合大规模用在生产环境。但是,Canvas 的优点也是很明显的,例如在绘制含有大量元素的图表的时候,SVG 往往因为性能问题而无法胜任,例如我见过的一次技术分享会的抽奖环节,虽然效果比较炫,但因为每个头像都是 DOM,利用 CSS3 控制的动画,导致了性能非常低下。此外,随着硬件性能的提高,视频截图、图像处理等功能也逐渐可以在网页上实现了,大多数网站用的是 Flash,但是 Flash 在 Mac 电脑上性能不高,还需要学一些额外的知识。Canvas 则是直接使用 JavaScript 来进行绘图,对 Mac 友好,所以不失为 Flash 的一个继承者。使用 Canvas说了这么多,Canvas 究竟是个啥?英文中 Canvas 的意思是“画布”,不过这里说的 Canvas 是HTML5 中新出的一个元素,开发者可以在上面绘制一系列图形。Canvas 在HTML 文件中的写法很简单:宽度"height="高度">其中 id 属性是所有HTML 元素都可以用的,Canvas 自带的属性只有后面两个(分别控制宽度、高度),没有其它的了。至于兼容性,CanIUse 上面写了,基础的功能目前用户使用的 90%的浏览器都支持,所以大部分情况下还是可以放心使用的。注意,一定要使用 Canvas 自带的 width 和 height 属性,不要使用 CSS 来控制,因为 CSS 控制会导致 Canvas 变形。可以试着与 PhptpShop 对比一下,后者是改变“图像大小”,前者才是正确的改变“画布大小”。例如下图是三张图片的横向拼接:最左边的黑框中是大小为 50px*50px 的原图;中间是改变了图像大小为 100px*100px 的效果,图像变得模糊,但是对于图像本身来说坐标范围并没有变大;最右边才是正确的 100px*100px 的 Canvas。Canvas 绝大部分的绘图方法都与标签无关,需要使用 JavaScript 对其进行操作,这就是所谓的 Canvas API。我们首先获取到这个元素:var canvas=document.getElementById('canvas');然后通过一个方法来获取可以调用一切 Canvas API 的入口:var ctx=canvas.getContext('2d');看到 2d 是不是很激动地联想到有没有 3d 呢?没有 3d 的写法,不过如果想要开启 3D 世界的大门,则可以写 canvas.getContext('webgl')。然而 WebGL 是基于 OpenGL ES 2.0 的一套标准,与本文是彻彻底底的两条路,因此这里就不讨论了。Canvas 中的基本概念坐标与数学上常见的笛卡尔坐标系不太相同,Canvas 的坐标系是计算机中常见的坐标系,它长这样:画布的最左上角是(0,0),往右 x 增大,往下 y 增大,而且 x 和 y 都是整数(就算在计算过程中不是整数,在绘制的时候也会当作整数处理),单位是像素。绘图带大家怀旧一下。不知道有多少同学小时候玩过 logo 语言,在里面你可以控制一只小海龟在一块板子上行走、画画、提笔、落笔。Canvas 中也一样,你需要控制一只画笔的移动和绘制。然而 Canvas 更高级一些,你可以直接利用一些函数来画图,不用去控制那只画笔的位置。Canvas 中的基本图形通过上文定义的 ctx 变量可以干许多有意思的事情,我们先看看如何绘制一些基本图形。线条我们指定画笔移动到某一点,然后告诉画笔需要从当前这一点画到另一点。我们可以让画笔多次移动、绘制,最后统一输出到屏幕上。例子如下:ctx.moveTo(10,10);ctx.lineTo(150,50);ctx.lineTo(10,50);ctx.moveTo(10,20);ctx.lineTo(40,70);ctx.stroke();上面的代码中,lineTo 是产生线条用的函数,执行完之后画笔就移到了线条的终点。需要注意的是,线条此时并没有显示在屏幕上,必须调用 stroke 才会显示。这样设计是有道理的,因为向屏幕上输出内容需要耗费大量的资源,我们完全可以先攒够一波 lineTo,最后用 stroke 放一个大的。路径绘制路径非常简单,只需要先告诉 ctx 一声“我要开始画路径了”,然后通过各种方法(例如 lineTo)绘制路径。如果需要画一个封闭路径,那就最后告诉 ctx一声:“我画完了,你把它封闭起来吧。当然,不要忘记利用 stroke 输出到屏幕上。一个简单的例子:ctx.beginPath();ctx.moveTo(10,10);ctx.lineTo(150,50);ctx.lineTo(10,50);ctx.closePath();ctx.stroke();如果我不想只描绘路径线条,而是想填充整个路径呢?可以将最后一行的 stroke 改成 fill,这样就跟使用了画图中的油漆桶一样,封闭路径里面的内容就都被填充上颜色了:ctx.fill();弧/圆形绘制弧的函数参数比较多:ctx.arc(圆心 x 坐标,圆心 y 坐标,半径,起始角度,终止角度,是否为逆时针);注意,在 Canvas 的坐标系中,角的一边是以圆心为中心的水平向右的直线。角度单位均为弧度。例如下图,确定了圆心、起始角度(图中标明的锐角)和终止角度(图中标明的钝角),方向为逆时针,于是就有了这么一个弧。如果方向为顺时针,那么就会是一个跟它互补的、非常非常大的弧…所以如果转了 2π 圈之后,弧就成了圆形,因此也可以使用绘制弧的方式来绘制圆形:ctx.beginPath();ctx.arc(圆心 x 坐标,圆心 y 坐标,半径,0,Math.PI*2,true);ctx.closePath();最后一个参数随便填(当然也可以不填),因为不管是顺时针还是逆时针,转了 2π 圈之后都是一个圆。矩形如果只是想绘制一个横平竖直的矩形,可以使用下面的两个方法:只描边ctx.strokeRect(左上角 x 坐标,左上角 y 坐标,宽度,高度);只填充ctx.fillRect(左上角 x 坐标,左上角 y 坐标,宽度,高度);线条样式/填充样式之前绘制的所有图形都是黑色的,但是 Canvas 肯定不止这么一种颜色(不然标准的制定者会被喷的很惨)。事实上,Canvas 可以单独设置线条样式和填充样式,分别使用的是 strokeStyle 和 fillStyle。可能的值有三种:纯色、渐变、图像。既然线条样式与填充样式的使用方法相同,那么下面统一以填充样式为例。如果想设置线条样式,直接将所有的 fillStyle改成 strokeStyle 即可,里面的参数都不变。纯色填充*/普通的颜色ctx.fillStyle='#0000ff';带有透明度的颜色ctx.fillStyle='rgba(64,0,127,0.5)';渐变填充*/设置渐变的尺寸(参数分别为起始点的 x 和 y、终止点的 x 和 y)var gradient=ctx.createLinearGradient(0,0,170,0);设置过渡色,第一个参数是渐变的位置,第二个参数是颜色gradient.addColorStop(0,'magenta');gradient.addColorStop(0.5,'blue');gradient.addColorStop(1.0,'red');设置填充样式ctx.fillStyle=gradient;图片填充*/创建图片var image=new Image;image.src='/path/to/image.png';创建图片笔触,可以指定图片的平铺方式,这里是横向平铺var pattern=ctx.createPattern(image,'repeat-x');设置笔触填充ctx.fillStyle=pattern;关于渐变,除了代码中提到的线性渐变以外,还有 createRadialGradient,也就是径向渐变。设置完填充样式之后,就可以使用 fill 来填充啦!如果设置的是线条样式,那么就可以使用 stroke 来描边。当然,对于线条样式,还有个额外的方法叫 lineWidth 可以用来控制线条的宽度。文字要想在画布上画文字,首先需要知道所使用的字体和字号:ctx.font='30px Verdana';然后就可以通过 strokeText 或者 fillText 来对字体描边或者填充字体。ctx.strokeText("Hello Coding!23,33);ctx.fillText("Hello Coding!23,66);图片在 Canvas 中绘制图片有三种方法:指定绘制位置ctx.drawImage(image,x,y);指定绘制位置和图像宽高ctx.drawImage(image,x,y,width,height);指定剪裁区域、绘制位置和图像宽高ctx.drawImage(image,sx,sy,swidth,sheight,x,y,width,height);参数的含义依次如下:image:要使用的 Image、Canvas 或 Videosx:可选,开始剪切的 x 坐标sy:可选,开始剪切的 y 坐标swidth:可选,被剪切图像的宽度sheight:可选,被剪切图像的高度x:在画布上放置图像的 x 坐标y:在画布上放置图像的 y 坐标width:可选,要使用的图像的宽度height:可选,要使用的图像的高度画布设置细心的同学可能会发现,刚才有些属性是直接对 ctx 变量做设置,例如 ctx.lineWidth,只要设置了它,那么后续画出来的线条全都是这么个宽度。其实,Canvas 的设置项还有许多,例如我们可以直接移动画布、旋转画布、设置全局的绘制透明度等等。这些设置还可以随时保存和恢复。要注意的一点是,所有已经画在画布上的东西,是已经定死了的,不管之后再次进行任何设置都不会再改变。这个很像 Windows 下的画图程序。废话不多说,直接上代码:移动画布,其实就是移动坐标系ctx.translate(往右移动的量,往下移动的量);旋转画布,旋转中心为坐标系原点ctx.rotate(顺时针旋转的角度);以坐标系原点为中心缩放画布ctx.scale(横向放大倍数,纵向放大倍数);设置绘制透明度,如果 fillStyle 等属性设置了透明度则会叠加ctx.globalAlpha(零到一的小数);设置全局组合操作ctx.globalCompositeOperation='lighter';保存当前设置ctx.save();恢复上次保存的设置ctx.restore();移动、旋转、缩放其实就是在控制绘图的坐标系,如果你在调用这三个方法的时候,脑子里时刻有一个带刻度的坐标系,效果会非常好。事实上,Canvas 的坐标变换遵循计算机图形学的知识:变换矩阵。简单来说,一个坐标可以看成是一个矩阵,坐标所对应的矩阵乘上变换矩阵就可以实现对坐标的变换。为了提升计算的效率,可以先计算出几种变换复合之后的变换矩阵,然后直接通过 transform 函数对当前坐标系进行变换,或者通过 setTransform 函数将坐标系重置为初始状态后再进行变换。至于变换矩阵的内容,对于本文来说就有些超纲了。全局组合操作有点像 PhotoShop 里面的“混合选项”,具体的实现方式还没有完全确定,目前常见浏览器都统一了的实现方式有:source-over、source-atop、destination-over、destination-out、lighter、xor。具体的行为可以看 Mozilla 官方文档,但是由于标准还未完全确定,因此其它浏览器不保证所有的行为都跟 Mozilla 的标准一致。一般来说,比较常见的是 source-over 和 lighter 两种,这两种的..内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • 在html5 canvas里用卷积核进行图像处理的方法
  • 如何用Canvas绘制多种图形
  • 如何实现Canvas图像的拖拽,点击等操作
  • canvas图片处理,求教ps像素级高手。美图秀秀,ps等软件都有一些图片风格特效,比如lomo,灰化,水下效果
  • 数字图像处理的一道基础题,大神只要教我如何求出滤波结果就行了
  • Java基础 canvas加载图片问题
  • javascript canvas 如何对图片进行绕中心点旋转
  • 遥感基础图像的处理
  • 研究生学习图像处理,需要哪些基础课程?
  • 为什么说图像编辑是图像处理的基础
  • 学习图像处理需要哪些基础知识?
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全主页网页制作html5canvas在html5 canvas里用卷积核进行图像处理的方法html/xhtmlhtml5cssxml/xsltdreamweaver教程frontpage教程心得技巧css 如何让背景图片拉伸填充避免重复显示html5 input placeholder 颜色修改示例基于第一个phonegap(cordova)的应用详解 html5配合css3实现带提示文字的输入框(摆脱js)html5定位获取当前位置并在百度地图上显示将html5 canvas的内容保存为图片借助todataurl实现html5中如何显示视频呢 html5视频播放demo让ie支持html5的方法微信浏览器取消缓存的方法html5的存储方式sessionstorage和localstorage详解基于html5+tracking.js实现刷脸支付功能html中meta标签及keywords详解移动端h5页面根据屏幕适配的四种方案html5移动端自适应布局的实现html里显示pdf、word、xls、ppt的方法示例html5 直播疯狂点赞动画实现代码 附源码html5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷canvas 基础之图像处理的使用用canvas显示验证码的实现html5给汉字加拼音收起展开组件的实现代码
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved