一、图片近似度对比
开门见山,不绕弯路。
用的是这个Github项目:https://github.com/obartra/ssim
之所以选这个,是我看这个项目提交次数比较多,文件版本也比较高。
案例先行
不管怎样,先看对比效果。
您可以狠狠地点击这里:JS实现图片对比差异参数demo
首先,选两个近似的图,例如选择我的CSS书籍的书封,点击对比,则会有下图所示的结果:
相似度在0.51左右,这两个图结构类似,尺寸有些许差别,颜色也有些不同,文案也有所不同,50%左右的差异符合预期。
然后,选择两个长得完全大相径庭的图片,例如使用我的帅照 ?:
可以看到对比的结果接近于0,也就是差别巨大,完全没有可比性。
最后,演示页面还支持选择本地图片进行相似度对比,大家可以选择本地的图片素材,看看结果如何。
例如,我选择了如下图所示的两张图,得到了相似值挺高的对比结果:
高达0.83,这是一个比较高的对比值了。
使用总结
根据我的使用感受,对比值小于0.4的,就可以认为有明显差异,数值越小,自然差异就越大了。
二、使用说明
官方示意的代码是npm包引入,如下:
npm install ssim.js
import ssim from "ssim.js";
const img1 = loadImage("./img1.jpg");
const img2 = loadImage("./img2.jpg");
const { mssim, performance } = ssim(img1, img2);
console.log(`SSIM: ${mssim} (${performance}ms)`);
而上面出现的loadImage方法,其实是不存在的,我搜索了ssim的JS源码,根本就没有loadImage这个关键字。
而这里的img1和img2并非图片元素,而是ImageData对象,可以通过canvas元素获取,context.getImageData()
方法。
代码示意:
// 图片转imageData需要的canvas
// 为了节省开销,就在外面定义,只用这一个玩耍了
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', {
willReadFrequently: true
});
// image 转 imagedata的方法
const image2data = (img, flag) => {
const { width, height } = canvas;
ctx.clearRect(0, 0, width, height);
ctx.drawImage(img, 0, 0, width, height);
return ctx.getImageData(0, 0, width, height);
};
在使用image2data方法之前,需要先给canvas元素设置高宽属性。
如果是Web直连引用
直连引用的话,使用下面示意的代码:
<script src="./ssim.web.js"></script>
<script>
const { mssim, performance } = ssim.ssim(imgData1, imgData2);
console.log(`相似度: ${mssim} (${performance}ms)`);
</script>
前面提供的演示页面就是使用直连引用的方式实现的。
更具体的使用细节直接参阅demo演示页面的源码即可。
三、应用场景,结束语
图片相似度的应用通常都与图片序列相关。
例如,GIF动图需要进行压缩,则可以删除相似度极为类似的图片序列帧,只保留第一个,同时增加这一帧的延时时间。
目前的Web技术对此需求的实现已经非常成熟,尤其是有个WebCodecs API,可以轻松对GIF图片进行解码。
又例如对识别视频素材的转场画面等。
另外,素材的大小并不会影响识别的准确性,但是会影响识别的性能。
也就是1024*1024的图片对比结果,和128*128的图片对比结果相差不大,但是性能差异那就非常明显了。
所以,这里有个小tips,在获取图片数据的时候,记得绘制在合适大小的Canvas上,没有必要基于原图尺寸绘制,除非你这个相似度对比就是一锤子买卖,而不是批量化的操作。
OK,就说这么多吧,一个小小的技术积累,说不定什么时候就会用到呢。
感谢阅读,欢迎分享,以及圣诞节快乐!
☃️⛄️??❤️
(本篇完)