教你如何成为图片找茬高手

事情是这样的,前几天闲来无事,手机上下载了个图片找茬游戏,本以为是小孩子玩玩的很简单,没想到开头几关就把我难住了,有些细节真是藏的很深呀,不仔细看真的找不到。于是乎我想,肉眼很难辨别的东西是不是可以通过代码帮我快速找到?前端有 canvas 可以用来处理图像,查了下 API 也可以读取像素点,感觉可行,说干就干!

canvas 读取像素点

我们知道,canvas 是可以拷贝图像的,通过 ctx.drawImage,我们可以方便的将图片绘制在 canvas 里面,下面是例子

tsx 复制代码
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  const image = new Image();
  image.src = 'xxx';
  image.onload = ()=> {
   canvas.width = image.width;
   canvas.height = image.height;
   ctx.drawImage(image, 0, 0);
  }

但应该没多少童鞋知道,canvas 其实也可以读取像素点,通过 ctx.getImageData 我们可以方便的读取当前绘制图片的像素点数组。

tsx 复制代码
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;

然后我们会得到如下数组

tsx 复制代码
  // [255,254,255,255,...]

这里每4个值一组就代表了一个像素点,聪明的童鞋已经看出来了,没错,这4个值分别对应了 RGBA,如下图所示 我们可以通过对比每一个像素点,来实现图片的差异化对比。

绘制差异化像素点

既然能读取,我们能不能修改里面的像素点呢?答案是可以的,通过ctx.putImageData,我们可以方便的对现有图像的像素进行随意改造,比较常用的就是 滤镜,通过不同的滤镜算法,我们可以在网页上实现类似美图秀秀的功能,当然在我们这个需求里,也可以用来标记差异化的像素点。具体流程如下:

  1. 绘制需要对比的两张图片到 canvas
  2. 获取原图的像素点数组作为对照
  3. 遍历对比图的像素点,将和原图不同的部分用蓝色重新赋值
  4. 通过ctx.putImageData,重新生成新的图像信息
  5. 最后通过 canvastoDataURL api 生成 base64 图像

简单写了个 demo,效果类似这样

我们可以很快发现,diff 图 里蓝色明显的地方即为差异点

源代码我放在 github 上了,有兴趣的童鞋自取~ 👉 image-diff-demo

抛砖引玉

经过这个小 demo 的实战,深入理解了 ctx.getImageDatactx.putImageData 的用法,虽然原理差不多是这样子,但是还是有很多可以优化的地方,比如对比原图发现,很多没改动的地方也染上了一些蓝色,这个原因是因为两张图的相同部分的像素点也是不一致的,受限于图片压缩问题,很多颜色也是会有些许出入,虽然肉眼看不出来,但实际上从像素角度出发是不一样的,大家也可以想想怎么优化 diff 算法 可以让误差尽量减小😁

总结

image-diff 也不是新东西了,市面上也有不少成熟的产品了,开源社区耳熟能详的就是大名鼎鼎的 argos-ci,还有开源产品,比如 Resemble.js,都是比较好的 image-diff 库,大家可以按需使用,当然也可以自研,原理其实并不难。希望本篇文章对大家有帮助~

相关推荐
九筠几秒前
python网络爬虫开发实战之Ajax数据提取
前端·爬虫·ajax·网络爬虫
excel13 分钟前
webpack 核心编译器 十七 节
前端
斯普信专业组29 分钟前
ceph数据迁移数据迁移与bacula配置调整优化实战
前端·ceph·github
好_快34 分钟前
Lodash源码阅读-baseMatches
前端·javascript·源码阅读
好_快36 分钟前
Lodash源码阅读-baseHasIn
前端·javascript·源码阅读
好_快36 分钟前
Lodash源码阅读-baseIsEqual
前端·javascript·源码阅读
好_快40 分钟前
Lodash源码阅读-getMatchData
前端·javascript·源码阅读
吴永琦(桂林电子科技大学)2 小时前
HTML5
前端·html·html5
爱因斯坦乐2 小时前
【HTML】纯前端网页小游戏-戳破彩泡
前端·javascript·html
恋猫de小郭2 小时前
注意,暂时不要升级 MacOS ,Flutter/RN 等构建 ipa 可能会因 「ITMS-90048」This bundle is invalid 被拒绝
android·前端·flutter