美文网首页
canvas实现抠图和颜色替换

canvas实现抠图和颜色替换

作者: 阿明先森 | 来源:发表于2021-08-26 14:20 被阅读0次
效果图

演示地址
代码仓库

关键技术

canvas apielement-ui (el-color-picker、el-upload)

原理解析

1. 用户从本地上传一张图片

我们拿到图片数据并在页面渲染出来,这一步用到了elementui的el-upload

el-upload.avatar-uploader(
  ref="logoUpload",
  accept="image/*",
  action="#",
  :auto-upload="false",
  :on-change="handleStatusChange"
)
  el-button(size="small", type="primary") 点击上传

这里实际上不需要真正上传到服务器,只需要获取到图片的在内存中的url

handleStatusChange(file) {
  // console.log(file);
  this.originImg = URL.createObjectURL(file.raw);
},

拿到url之后可以先把图片用img标签渲染在页面上,这样做的目的是为了获取图片的实际尺寸,方面我们等比例缩放在我们的canvas上。

// 图片加载完成
    loadImg(e) {
      const img = e.target;
      const width = img.offsetWidth;
      const height = img.offsetHeight;
      this.imgWidth = width;
      this.imgHeight = height;
      this.canHeight = (height / width) * this.canWidth;
    }

canvas的width可以根据外层容器来获取

this.$nextTick(() => {
      const contentWidth = document.querySelector(".origin-box").offsetWidth;
      this.canWidth = Math.min(contentWidth - 12, this.canWidth);
});

2. 绘制canvas

绘制图片到canvas,这一步比较简单,

//这里需要缩放一下,因为我们的画布已经被缩放了
this.originCtx.scale(this.canWidth / width, this.canWidth / width);
this.originCtx.drawImage(img, 0, 0);

3. 选中颜色

点击canvas,我们可以拿到该点上的颜色值,获取方式

ctx.getImageData(targetX,targetY,1,1)

拿到的是imagedate对象,{data, width, height},data即为我们要的颜色值。

4. 遍历原图片的颜色值,匹配到选中颜色之后,做对应颜色的替换即可

核心api: getImageData putImageData

//获取data
const data = this.imageData.data || [];
//遍历并替换
for (let i = 0; i < data.length; i += 4) {
        const similar = this.isSimilar(_fromColor, data.slice(i, i + 4));
        if (similar) {
          data[i] = _toColor[0];
          data[i + 1] = _toColor[1];
          data[i + 2] = _toColor[2];
          data[i + 3] = _toColor[3] * 255;
        }
 }
 //绘制到目标容器上
 this.transCtx.putImageData(this.imageData, 0, 0);

isSimilar方法用来判断两个颜色是否相似或相等,这个可以通过参数调整(类似于ps的容差概念),容差值越小,匹配越精准。

颜色值是rgba格式的,即4个数组为一组,数值都在[0,255]之间,由于el-picker返回的rgba,透明度用的是【0,1】表示的,所以要转换到0-255区间

5. undo&redo

撤销、前进、后退功能还是很有必要的,重复替换操作,可返回历史操作步骤。
创建一个队列(这里用数组代替),每次有新的数据变化添加到队列里,用unshift表示入列pop从队列后面删除。可以设置上限10,队列过大会占用较大内存,不建议设置过大。
维护一个index,理解成指针,表示当前回退的数据在队列中的位置。

undo() {
  this.index++;
  this.redrawImg();
},
redo() {
  this.index--;
  this.redrawImg();
},
redrawImg() {
  const preImageData = JSON.parse(this.imgStock[this.index]).data;
  this.imageData = this.transCtx.createImageData(
    this.canWidth,
    this.canHeight
  );
  for (let i = 0; i < this.imageData.data.length; i++) {
    this.imageData.data[i] = preImageData[i];
  }
  this.transCtx.putImageData(this.imageData, 0, 0);
},

需要注意的细节:当回退到某一条历史记录,比如index=5,这时候再执行手动操作替换,此时就“穿越”了,需要把index = 5之前的历史都移除。(可能描述有点绕~)

至此,就完成了核心功能了~

TODO LIST

  1. 增加边缘识别,去除毛边
  2. 增加容差选项
  3. 尝试视频抠图和替换
  4. 。。。

演示地址
代码仓库

欢迎提意见&star!

相关文章

  • canvas实现抠图和颜色替换

    演示地址[http://49.235.109.180/]代码仓库[https://github.com/aMiin...

  • Swift图片处理

    本文源码在Github: *** 简单图片背景替换(实现抠图效果) 参考:http://blog.csdn.net...

  • iOS 图片处理

    iOS开发-简单图片背景替换(实现抠图效果) iOS8 Core Image In Swift:自动改善图像以及内...

  • 懒人抠图

    1,可选颜色 当我们要抠的图片是这种颜色单一,常见于淘宝抠图 最快速的抠图方法是:在图层上方建立可选颜色图层-颜色...

  • PS零基础入门课程——通道抠图、滤镜使用

    1. 通道抠图 在PS中,通道是用来存放颜色信息的,使用通道抠图主要是可以通过颜色对比快速便捷地抠图。 操作:打开...

  • Android OpenGL ES(八) - 简单实现绿幕抠图

    实现绿幕抠图,其实想法很简单。这里简单粗暴的使用着色器替换。 OES Filter 直接实现在相机预览上的Shad...

  • Python:批量抠图,填充背景

    抠图 参考:知乎,3行Python代码,实现批量抠图和换底色的方法,作者林泽风 获取API 利用了Remove I...

  • 稿定设计

    稿定设计 主要提供在线抠图技术支持,在线平面海报设计支持功能,提供可替换素材模板进行编辑。 抠图 模板 视频 ht...

  • photo shop零基础12

    抠图四 通道抠图 先说说通道的概念通道是一个用于存储颜色信息和选区信息的功能,photo shop有三种类型的通道...

  • 哪里有PhotoScissors 6 for Mac(mac抠图

    PhotoScissors 6 for Mac是一款简单易用的Mac抠图软件,可以自动删除和替换图像背景!想去除头...

网友评论

      本文标题:canvas实现抠图和颜色替换

      本文链接:https://www.haomeiwen.com/subject/dfhuiltx.html