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

事情是这样的,前几天闲来无事,手机上下载了个图片找茬游戏,本以为是小孩子玩玩的很简单,没想到开头几关就把我难住了,有些细节真是藏的很深呀,不仔细看真的找不到。于是乎我想,肉眼很难辨别的东西是不是可以通过代码帮我快速找到?前端有 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 库,大家可以按需使用,当然也可以自研,原理其实并不难。希望本篇文章对大家有帮助~

相关推荐
DFT计算杂谈4 分钟前
AMSET 设置多核并行计算
java·前端·css·html·css3
花椒技术7 分钟前
AI 协同开发落地复盘:1 小时生成首版后,为什么 Review 和修正又花了 2-3 天
前端·人工智能·架构
万少41 分钟前
万少用9个AI工具,帮朋友完成了一个"不可能"的项目
前端
小小小小宇43 分钟前
Vue `import` 为什么可以异步加载
前端
WMYeah1 小时前
【无标题】
前端·rust·抽奖程序·跨平台抽奖程序
Unbelievabletobe1 小时前
免费外汇api的响应时间在不同时段下的波动分析
大数据·开发语言·前端·python
大哥,带带弟弟1 小时前
Grafana 前端嵌入与 JWT 鉴权实战
前端·grafana
小小小小宇1 小时前
前端 V8 引擎垃圾回收机制与内存问题排查
前端
前端老石人1 小时前
CSS 值定义语法
前端·css
sheeta19981 小时前
Vue 前端基础笔记
前端·vue.js·笔记