我的编程空间,编程开发者的网络收藏夹
学习永远不晚

html5如何利用canvas实现颜色容差抠图功能

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

html5如何利用canvas实现颜色容差抠图功能

这篇文章主要介绍了html5如何利用canvas实现颜色容差抠图功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

利用canvas的getImageData,我们可以获取到一张图片每一个像素的信息,而通过对每一个像素信息的对比,我们就可以找到需要消去的像素点。比如下面这一张图片,如果我们想要扣去白色部分(粉色是body的背景颜色)。

html5如何利用canvas实现颜色容差抠图功能 

let canvas = document.querySelector('#canvas');let context = canvas.getContext('2d');let img = document.createElement('img');img.class="lazy" data-src = './head2.png';img.onload = function () {    canvas.height = img.height;    canvas.width = img.width;    context.drawImage(img, 0, 0);    cutout(canvas, [255, 255, 255], 0.2); // 对白色进行抠除,容差为0.2}function cutout(canvas, color, range = 0) {    let context = canvas.getContext('2d');    let imageInfo = context.getImageData(0, 0, canvas.width, canvas.height);    // pixiArr是一个数组,每四个数组元素代表一个像素点,这四个数组元素分别对应一个像素的r,g,b,a值。    let pixiArr = imageInfo.data;    for (let i = 0; i < pixiArr.length; i += 4) {    // 匹配到目标像素就将目标像素的alpha设为0        if (testColor([pixiArr[i], pixiArr[i + 1], pixiArr[i + 2]], color, range)) pixiArr[i + 3] = 0;    }    context.putImageData(imageInfo, 0, 0);}function testColor(current, target, range) {    for (let i = 0; i < 3; i++) {        if (!((1 - range) * target[i] <= current[i] && (1 + range) * target[i] >= current[i])) return false;    }    return true;}

testColor(current, target, range) 方法三个参数分别为 待检测像素点的rgb数组 、 目标像素点的rgb数组 和 容差范围 ,这里的容差只是简单用r、g、b的值分别乘以(1 + range)和(1 - range)来计算并对比,不同的容差参数会得到不同的效果&darr;

range = 0.095

html5如何利用canvas实现颜色容差抠图功能 

range = 0.1

html5如何利用canvas实现颜色容差抠图功能 

range = 0.2

html5如何利用canvas实现颜色容差抠图功能 

当然对于底色是标准的纯色的图片就不需要容差了。

边界处理

但是有时候我们希望有一个边界,让抠图操作不对边界内部的像素造成影响。比如上面的图片,我们希望不会对人物头像内部的像素造成影响。 如果我们一行一行来看,是不是只要在碰到不是边界像素的时候停止操作,就可以达到效果了呢?

我们对每一行分别进行扫描,定义一个左指针 left 指向这一行的第一个像素,定义一个右指针 right 指向这一行的最后一个像素,并用一个 leftF 标识左边是否碰到边界,一个 rightF 标识右边是否碰到边界,当没碰到边界时指针就一直向内收缩,直到两个指针都碰到边界或者左右指针重合就跳到下一行,直到所有行都扫描完毕。

function cutout(canvas, color, range = 0) {    let context = canvas.getContext('2d');    let imageInfo = context.getImageData(0, 0, canvas.width, canvas.height);    let pixiArr = imageInfo.data;    for (let row = 0; row < canvas.height; row++) {        let left = row * 4 * canvas.width; // 指向行首像素        let right = left + 4 * canvas.width - 1 - 3; // 指向行尾像素        let leftF = false; // 左指针是否碰到边界的标识        let rightF = false; // 右指针是否碰到边界的标识        while (!leftF || !rightF) { // 当左右指针都为true,即都碰到边界时结束            if (!leftF) {                if (testColor([pixiArr[left], pixiArr[left + 1], pixiArr[left + 2]], color, range)) {                    pixiArr[left + 3] = 0; // 此像素的alpha设为0                    left += 4; // 移到下一个像素                } else leftF = true; // 碰到边界            }            if (!rightF) {                if (testColor([pixiArr[right], pixiArr[right + 1], pixiArr[right + 2]], color, range)) {                    pixiArr[right + 3] = 0;                    right -= 4;                } else rightF = true;            }            if (left == right) { // 左右指针重合                leftF = true;                rightF = true;            };        }    }    context.putImageData(imageInfo, 0, 0);}

html5如何利用canvas实现颜色容差抠图功能 

虽然大概完成了我们的需求,但是看一下上面头发那为啥会多了一块白色

html5如何利用canvas实现颜色容差抠图功能 

因为我们仅仅只进行了行扫描,当左指针碰到头发时就会停止扫描,但是头发弧度里面的就无法被扫描到了,我们还需要进行列扫描,改造一下上面的方法:

function cutout(canvas, color, range = 0) {    let context = canvas.getContext('2d');    let imageInfo = context.getImageData(0, 0, canvas.width, canvas.height);    let pixiArr = imageInfo.data;    for (let row = 0; row < canvas.height; row++) {        let left = row * 4 * canvas.width;        let right = left + 4 * canvas.width - 1 - 3;        let leftF = false;        let rightF = false;        while (!leftF || !rightF) {            if (!leftF) {                if (testColor([pixiArr[left], pixiArr[left + 1], pixiArr[left + 2]], color, range)) {                    pixiArr[left + 3] = 0;                    left += 4;                } else leftF = true;            }            if (!rightF) {                if (testColor([pixiArr[right], pixiArr[right + 1], pixiArr[right + 2]], color, range)) {                    pixiArr[right + 3] = 0;                    right -= 4;                } else rightF = true;            }            if (left == right) {                leftF = true;                rightF = true;            };        }    }    // 同理进行列扫描    for (let col = 0; col < canvas.width; col++) {        let top = col * 4; // 指向列头        let bottom = top + (canvas.height - 2) * canvas.width * 4 + canvas.width * 4; // 指向列尾        let topF = false;        let bottomF = false;        while (!topF || !bottomF) {            if (!topF) {                if (testColor([pixiArr[top], pixiArr[top + 1], pixiArr[top + 2]], color, range)) {                    pixiArr[top + 3] = 0;                    top += canvas.width * 4;                } else topF = true;            }            if (!bottomF) {                if (testColor([pixiArr[bottom], pixiArr[bottom + 1], pixiArr[bottom + 2]], color, range)) {                    pixiArr[bottom + 3] = 0;                    bottom -= canvas.width * 4;                } else bottomF = true;            }            if (top == bottom) {                topF = true;                bottomF = true;            };        }    }    context.putImageData(imageInfo, 0, 0);}

至于top和bottom为啥是那样计算画个矩阵图大概就知道了。

html5如何利用canvas实现颜色容差抠图功能 

处理后&darr;

html5如何利用canvas实现颜色容差抠图功能 

其实还可以先将 pixiArr 包装为以一个像素点为单位的矩阵

[    [{r: 255, g: 255, b: 255, a: 1}, {r: 255, g: 255, b: 255, a: 1}, {r: 255, g: 255, b: 255, a: 1}],    [{r: 255, g: 255, b: 255, a: 1}, {r: 255, g: 255, b: 255, a: 1}, {r: 255, g: 255, b: 255, a: 1}]    [{r: 255, g: 255, b: 255, a: 1}, {r: 255, g: 255, b: 255, a: 1}, {r: 255, g: 255, b: 255, a: 1}]]

处理后计算像素下标也就会更简单,列扫描时直接先将这个矩阵旋转,再用行扫描处理一遍就行了。这样处理pixiArr也有利于进一步对算法进行优化。

上述方法虽然大概完成了抠图效果,但是这种简单处理还会有许多情况没有考虑到。

比如右边头发这里是行扫描和列扫描都无法触碰到的区域&darr;

html5如何利用canvas实现颜色容差抠图功能 

下面的衣服也因为颜色和底色一样且没有边界在列扫描中被直接抹去了&darr;

html5如何利用canvas实现颜色容差抠图功能 

最后

对于主体和底色区分度很大的图片来说,最开始的那种方法就已经够用了。这篇中我采用的容差和边界处理算法的优化空间还很大,但是它们是非常容易实现与理解的,这篇权当做一个引子,各位完全可以根据自己的能力继续去实现边界与容差算法。

感谢你能够认真阅读完这篇文章,希望小编分享的“html5如何利用canvas实现颜色容差抠图功能”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网行业资讯频道,更多相关知识等着你来学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

html5如何利用canvas实现颜色容差抠图功能

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

html5如何利用canvas实现颜色容差抠图功能

这篇文章主要介绍了html5如何利用canvas实现颜色容差抠图功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。利用canvas的getImageData,我们可以获取到一
2023-06-09

如何利用canvas实现图片压缩功能

小编给大家分享一下如何利用canvas实现图片压缩功能,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!项目中做身份证识别时,需要传送图片的 base64 格式编码,
2023-06-09

OpenCV如何使用GrabCut实现抠图功能

这篇文章主要介绍“OpenCV如何使用GrabCut实现抠图功能”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“OpenCV如何使用GrabCut实现抠图功能”文章能帮助大家解决问题。1、概述案例:使
2023-07-05

如何利用canvas实现图片下载功能来实现浏览器兼容问题

小编给大家分享一下如何利用canvas实现图片下载功能来实现浏览器兼容问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前言:项目中需要实现图片下载功能,第一个想
2023-06-09

基于Html5 canvas如何实现裁剪图片和马赛克功能

这篇文章主要介绍了基于Html5 canvas如何实现裁剪图片和马赛克功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1.核心功能  此组件功能包含:    图片裁剪(裁剪
2023-06-09

如何在python中使用opencv实现一个颜色检测功能

本文章向大家介绍如何在python中使用opencv实现一个颜色检测功能的基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。Python主要用来做什么Python主要应用于:1、Web开发;2、数据科学研究;3、网络
2023-06-06

Html5 Canvas如何实现图片标记、缩放、移动和保存历史状态功能

这篇文章主要介绍Html5 Canvas如何实现图片标记、缩放、移动和保存历史状态功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!效果预览动图是放cdn的,如果访问不了,可以登录在线尝试尝试: test.algbb
2023-06-09

如何利用springMVC容器实现一个源码加载功能

如何利用springMVC容器实现一个源码加载功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。springmvc是一个基于servlet容器的轻量灵活的mvc框架,在它整个请
2023-05-31

如何利用ChatGPT和Python实现用户意图识别功能

如何利用ChatGPT和Python实现用户意图识别功能引言:在当今的数字化时代,人工智能技术逐渐成为各个领域中不可或缺的一部分。其中,自然语言处理(Natural Language Processing,NLP)技术的发展使得机器能够理解
2023-10-27

如何利用HTML5+css3+jquery+weui实现仿微信聊天界面功能

这篇文章主要介绍如何利用HTML5+css3+jquery+weui实现仿微信聊天界面功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!最新因项目需要,就利用HTML5+css3+jquery+weui做了一个仿微信
2023-06-09

如何利用ChatGPT和Python实现内容生成与推荐功能

如何利用ChatGPT和Python实现内容生成与推荐功能引言:随着人工智能技术的快速发展,ChatGPT(聊天型生成对抗网络)成为了一种强大的模型,能够理解并生成人类语言。在Python编程语言的支持下,我们可以利用ChatGPT实现各种
2023-10-24

如何在Android应用中利用SDK实现一个地图功能

这期内容当中小编将会给大家带来有关如何在Android应用中利用SDK实现一个地图功能,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1.找到控制台创建一个应用2.添加key名称,注意命名规范,还有就是下面
2023-05-31

如何在Android中利用Glide实现一个图片圆角功能

如何在Android中利用Glide实现一个图片圆角功能?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。一、简介:介绍两种使用 BitmapTransformation 来实
2023-05-31

如何在Android中利用imageview实现一个图片缩放功能

如何在Android中利用imageview实现一个图片缩放功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Android 自定义imageview实现图片缩放实例详解 觉得
2023-05-31

如何在Android中利用OkHttp实现一个图片上传功能

本篇文章给大家分享的是有关如何在Android中利用OkHttp实现一个图片上传功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。实现方法如下:object UploadFil
2023-05-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录