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

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

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

canvas 读取像素点

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

  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 我们可以方便的读取当前绘制图片的像素点数组。

  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;

然后我们会得到如下数组

  // [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 库,大家可以按需使用,当然也可以自研,原理其实并不难。希望本篇文章对大家有帮助~

原文链接:https://juejin.cn/post/7314365637308350490 作者:红果汁

(0)
上一篇 2023年12月20日 下午4:00
下一篇 2023年12月20日 下午4:10

相关推荐

发表回复

登录后才能评论