前几天听了刘立老师的图像处理一门课后,感觉图像处理很有意思,正好最近也在学习js,于是花了点时间做了一个简易处理程序,功能很简单,就是去除脸上的黑头和痘痘,哈哈。

效果图:(处理前,图片来源于网络)

处理后:

可以看到效果确实挺明显的哈,这也是html5的强大之处。

下面来说明这个程序的原理。

黑头和痘痘的恼人之处在于与自己的皮肤格格不入,每次自拍看到自己白白的脸上有那么几颗黑点显得格外的突兀,那么我们要想到,如何去除这些显眼的地方呢?

因为图片都是一个个像素点组成的,每个像素点的颜色不同才构成了一个绚丽多彩的图片,比较通用的一种描述颜色的方式是用RGB色彩模式描述,通过红(R)、绿(G)、蓝(B)三种颜色的变化以及它们之间的叠加来得到各种各样的颜色,其中每种颜色由浅到深用数字表示为0~255,假设有一个3* 3 像素的图片,其中每个像素的颜色都是(255, 0, 0),那么这个图片表现出来的就是一个3* 3的红色正方形,即:

(255, 0, 0) (255, 0, 0) (255, 0, 0)

(255, 0, 0) (255, 0, 0) (255, 0, 0)

(255, 0, 0) (255, 0, 0) (255, 0, 0)

那假设中间有个点颜色变为(0, 0, 0),如下:

(255, 0, 0) (255, 0, 0) (255, 0, 0)

(255, 0, 0)    (0, 0, 0) (255, 0, 0)

(255, 0, 0) (255, 0, 0) (255, 0, 0)

可以看到中间的颜色变为了黑色,格外显眼,就好像白皙的皮肤上多了一颗显眼的黑头!

那么如何去掉这个恼人的黑点呢? 很容易想到,将其与周边颜色同化即可,也就是说,我们可以扫描整个图片,然后找出那些与周围颜色不同的点,将其颜色改为与周围环境相似即可。

是不是很简单,下面演示代码。

首先是写出页面的主要结构:

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><style>#img_1 {margin: 10px;}canvas {border: 1px #c1c1c1 solid;}</style>
</head>
<body><img id="img_1" src="data:image/aa.jpg" style="display: inline-block"/><canvas id="canvas_1"></canvas>
</body>
</html>

img存放原图,方便处理后进行对比。canvas是html5中的标签,也是这个程序的关键所在,我们对图像的处理都在canvas中进行。

接下来写js代码:

首先,初始化canvas

<script>window.onload = function () {var canvas = document.getElementById("canvas_1");var img = document.getElementById("img_1");canvas.width = img.width + 20;canvas.height = img.height + 20;var context = canvas.getContext("2d");//画出图像context.drawImage(img, 10, 10);};
</script>

因为我想通过鼠标拖拽来处理相应位置的图片,所以接下来给画布添加鼠标监听,另外鼠标拖拽时需要有一个影响范围,用radius表示。

    var isDrag = false;var radius = 20;window.onload = function () {var canvas = document.getElementById("canvas_1");var img = document.getElementById("img_1");canvas.width = img.width + 20;canvas.height = img.height + 20;var context = canvas.getContext("2d");//画出图像context.drawImage(img, 10, 10);//添加鼠标监听canvas.onmousedown = function(e){isDrag = true;};canvas.onmouseup = function(){isDrag = false;this.style.cursor = "default";};canvas.onmousemove = function(e){if(isDrag){this.style.cursor = "pointer";// 获取鼠标相对于父元素的坐标var x = e.clientX + document.body.scrollLeft - document.body.clientLeft;var y = e.clientY + document.body.scrollTop - document.body.clientTop - canvas.offsetTop;handleArea(context, x - radius - 10, y - radius, radius * 2, radius * 2);}};};

那么在handleArea里面就是改变图像的代码了,其中参数分别为canvas的上下文、处理部分的左上角横坐标、纵坐标、处理部分的宽、处理部分的高,因为在css里面对img设置了margin,为了好看,我们也在canvas里的10,10处开始绘画。

修改图片部分像素的颜色是通过改变其RGB值实现的,为了方便保存和修改完之后合成RGB值,我创建了三个数组来分别保存每个像素点的RGB值:

var red2 = [], green2 = [], blue2 = [];

因为js不能直接创建二维数组,所以对其初始化

function initArr2(arr, size) {for (var i = 0; i < size; i++) {arr[i] = [];}
}

接下来就是第一个重点了,取出每个像素点的RGB值并保存

            //获取像素信息var imageData = context.getImageData(start_x, start_y, width, height);//取出像素信息var col = 0, row = 0;for (var i = 0; i < imageData.data.length; i += 4) {red2[row][col] = imageData.data[i];<span style="white-space:pre">  </span>//获取红色值green2[row][col] = imageData.data[i + 1];<span style="white-space:pre">  </span>//获取绿色值blue2[row][col] = imageData.data[i + 2];<span style="white-space:pre">   </span>//获取蓝色值col++;if (col == width) {col = 0;row++;}}

getImageData可以复制画布上指定矩形的像素数据,对于imageData中的每个像素,都存在四方面的信息,即RGBA值,分别是RGB加Alpha(透明度),这些数据以数组的形式按顺序存放于imageData中的data属性里。可以按如上方式依次取出,这里我们暂时不需要透明度,所以只取前3个。

取完RGB颜色之后即是处理的时候了,既然我们现在已经将每个点的RGB值都拿到了,当然好比较每个像素点和周围像素的区别了,遍历查找即可:

function handleArray(arr) {for (var i = 0; i < arr.length; i++) {for (var j = 0; j < arr[i].length; j++) {if (i > 0 && i < arr.length - 1 && j > 0 && j < arr[i].length - 1) {var temp = [arr[i - 1][j - 1], arr[i][j - 1], arr[i + 1][j - 1], arr[i - 1][j], arr[i + 1][j], arr[i - 1][j + 1], arr[i][j + 1], arr[i + 1][j + 1]];var avg = temp.getAvg();if (Math.abs(arr[i][j] - avg) > 0) {arr[i][j] = avg;}}}}}

这里用到数组取平均值,为了重复使用,在原型中加入了方法:

/*** 获取数组平均数* @returns {number}*/
Array.prototype.getAvg = function(){var sum = 0;for(var i = 0; i < this.length; i++){sum += this[i];}return sum / this.length;
};

那么至此已经将指定位置的像素信息改变了,但是原图不会发生任何变化,因为我们并未将改变后的信息放入到图像中,放入图像用到context的 putImageData方法:

var rows = 0, cols = 0;for (var i = 0; i < imageData.data.length; i += 4) {imageData.data[i] = red2[rows][cols];imageData.data[i + 1] = green2[rows][cols];imageData.data[i + 2] = blue2[rows][cols];cols++;if (cols == width) {cols = 0;rows++;}}context.putImageData(imageData, start_x, start_y);

那么,一个简单的图像处理就做好了,全部代码如下,当然这固定了影响的范围,大家也可以根据自己需要加入<input type="range">标签,动态改变radius值,手动调整范围

index.html

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><style>#img_1 {margin: 10px;
        }canvas {border: 1px #c1c1c1 solid;
        }</style>
</head>
<body><img id="img_1" src="image/aa.jpg" style="display: inline-block"/><canvas id="canvas_1"></canvas><script src="js/arrayUtil.js"></script><script>var red2 = [], green2 = [], blue2 = [];
        var isDrag = false;
        var radius = 10;
        window.onload = function () {var canvas = document.getElementById("canvas_1");
            var img = document.getElementById("img_1");

            canvas.width = img.width + 20;
            canvas.height = img.height + 20;
            var context = canvas.getContext("2d");

            //画出图像
            context.drawImage(img, 10, 10);

            canvas.onmousedown = function(e){isDrag = true;
                console.log(e.clientY + document.body.scrollTop - document.body.clientTop - canvas.offsetTop);
            };

            canvas.onmouseup = function(){isDrag = false;
                this.style.cursor = "default";
            };

            canvas.onmousemove = function(e){if(isDrag){this.style.cursor = "pointer";
                    // 获取鼠标相对于父元素的坐标
                    var x = e.clientX + document.body.scrollLeft - document.body.clientLeft;
                    var y = e.clientY + document.body.scrollTop - document.body.clientTop - canvas.offsetTop;
                    handleArea(context, x - radius - 10, y - radius, radius * 2, radius * 2);
                }};
        };

        function handleArray(arr) {for (var i = 0; i < arr.length; i++) {for (var j = 0; j < arr[i].length; j++) {if (i > 0 && i < arr.length - 1 && j > 0 && j < arr[i].length - 1) {var temp = [arr[i - 1][j - 1], arr[i][j - 1], arr[i + 1][j - 1], arr[i - 1][j], arr[i + 1][j], arr[i - 1][j + 1], arr[i][j + 1], arr[i + 1][j + 1]];
                        var avg = temp.getAvg();
                        if (Math.abs(arr[i][j] - avg) > 0) {arr[i][j] = avg;
                        }}}}}function initArr2(arr, size) {for (var i = 0; i < size; i++) {arr[i] = [];
            }}/**
         *
         * @param context
         * @param start_x 此x 为相对于canvas右下10px的坐标
         * @param start_y
         * @param width
         * @param height
         */
        function handleArea(context, start_x, start_y, width, height){initArr2(red2, height);
            initArr2(green2, height);
            initArr2(blue2, height);

            //获取像素信息
            var imageData = context.getImageData(start_x, start_y, width, height);

            //取出二维数组
            var col = 0, row = 0;
            for (var i = 0; i < imageData.data.length; i += 4) {red2[row][col] = imageData.data[i];
                green2[row][col] = imageData.data[i + 1];
                blue2[row][col] = imageData.data[i + 2];

                col++;
                if (col == width) {col = 0;
                    row++;
                }}handleArray(red2);
            handleArray(green2);
            handleArray(blue2);

            var rows = 0, cols = 0;
            for (var i = 0; i < imageData.data.length; i += 4) {imageData.data[i] = red2[rows][cols];
                imageData.data[i + 1] = green2[rows][cols];
                imageData.data[i + 2] = blue2[rows][cols];
                cols++;
                if (cols == width) {cols = 0;
                    rows++;
                }}context.putImageData(imageData, start_x, start_y);
        }</script>
</body></html>

arrayUtil.js

/**
 * 获取数组平均数
 * @returns {number}
 */
Array.prototype.getAvg = function(){var sum = 0;
    for(var i = 0; i < this.length; i++){sum += this[i];
    }return sum / this.length;
};

博主也在学习js当中,文章难免有不足之处,还望大家指正!

HTML5 模糊图片相关推荐

  1. HTML5 Canvas图片马赛克模糊动画

    经常可以在网上或者电视上看到被马赛克模糊的图片或者视频,今天我们要利用HTML5 Canvas技术来实现图片的马赛克模糊效果.在演示中我们可以拖动滑竿来设置马赛克模糊的程度,你可以在不同的值下观察图片 ...

  2. 简单的字幕效果html,7种HTML5 Figure图片字幕标题特效

    这是一款效果非常酷的HTML5 Figure图片字幕标题特效jQuery插件.该插件可以将任何图片元素转换为带标题的HTML figure元素.它内置了7种不同的图片标题效果.当标题文字高于图片时,还 ...

  3. Google 超分辨率技术 RAISR:模糊图片瞬间变清晰,运算速度快十倍

    Google 超分辨率技术 RAISR:模糊图片瞬间变清晰,运算速度快十倍 Everyday the web is used to share and store millions of pictur ...

  4. 如何把HTML转换成动图,html5实现图片转圈的动画效果——让页面动起来

    1.先瞧瞧效果: 2.代码是这样的: @mixin ani-btnRotate{ @keyframes btnRotate{ from{transform: rotateZ(0);} to{trans ...

  5. html5内容切换特效,html5+jQuery图片和文字内容同时左右切换特效

    html5+jQuery图片和文字内容同时左右切换特效,点击图片或者点击左右按钮进行切换,图片转动以及文字内容动画效果切换. 查看演示 下载资源: 22 次 下载资源 下载积分: 20 积分 js代码 ...

  6. [html] 如何使用html5进行图片压缩上传?

    [html] 如何使用html5进行图片压缩上传? 1.获取到图片的base64格式: 2.图片加载完成后,把图片转化为canvas: 3.使用canvas的toDataURL按照自己的需要进行压缩: ...

  7. HTML5 多图片上传(前端+后台详解)

    HTML5 多图片上传(前端+后台详解) 1.参考jquery插件库 2.修改代码 3.添加的后台代码 4.删除的后台代码 1.参考jquery插件库 手机端实现多图片上传 2.修改代码 我发现他这里 ...

  8. 基于html5背景图片自适应代码

    基于html5背景图片自适应代码是一款背景不随滚动条滚动,会根据分辨率不同自动匹配对应的背景图片.效果图如下: 在线预览    源码下载 实现的代码. css代码: .jawbone-hero .ja ...

  9. 照片转换为动画 html5,如何使用html5让图片转圈的动画效果

    如何使用html5让图片转圈的动画效果 发布时间:2020-10-26 09:33:22 来源:亿速云 阅读:78 作者:小新 如何使用html5让图片转圈的动画效果?这个问题可能是我们日常学习或工作 ...

最新文章

  1. MySQL · 捉虫动态 · show binary logs 灵异事件
  2. 微信系小程序 StorageSync
  3. 如何理解矩阵特征值?
  4. python生成柱状图 不显示_python – Matplotlib图表不显示在PyCharm中
  5. C++ 对象内存布局 (4)
  6. background-position—CSS设置背景图片的位置
  7. mysql 主备及时_MySQL高可用(二)主备延时如何解决?
  8. 文本多标签分类python_Scikitlearn多标签分类
  9. go语言载入json的一个坑
  10. urllib库的使用
  11. 做一款仿映客的直播App?看我就够了
  12. mac vscode 背景半透明_武装Mac|常用MacBook软件分类汇总
  13. 正则表达式实现中文的大写字符
  14. 2021年高考成绩查询永春一中,今天2018福建高考成绩出炉!泉州第一名是他们,永春一中、四中取得优异成绩!...
  15. curl_multi异步高并发服务实现
  16. HTML5期末大作业:电影网站设计——电影资讯博客(5页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 web学生网页设计作业源码
  17. SpringSecurity+jwt安全框架
  18. 牛顿法与牛顿下山法(切线法)
  19. 金海佳学C++primer9.45/9.46
  20. 要做研发高手,就是必须能看英文、写英文

热门文章

  1. mysql数据库物理结构设计_MySQL之数据库结构设计
  2. 渗透测试-WEB安全梳理-中间件(apache、IIS、tomcat、weblogic、websphere、jboos、nginx)
  3. Python3.8.2安装教程
  4. pom.xml上显示删除线
  5. 怎样在豆瓣上为公众号引流?如何利用豆瓣推广微信公众号?
  6. 关于大学新青年织梦后台的操作
  7. WPF绘制三维坐标系
  8. 小程序1v1视频通话多种实现方法
  9. 扫二维码+阶梯流式布局+自定义画圆+组合view
  10. 金鹰节智能机器人_Dobi机器人与秦岚曾合作过这部科技电影,金鹰节可否颁给Dobi机器人一...