经常在网上看到这种 由很多图片拼接的效果,偶然间看到有人问了下js如何实现,于是引起了我的思考,今天尝试了下从前端的角度去实现
效果如图,经常见到这种效果,但是不知道叫什么名字,今天搜了很多,看到”照片马赛克效果“这个词,暂且就叫 ”照片马赛克效果“吧。
实现思路
基础素材:主图 + n张素材图
- 绘制主图在最底层
- 把主图的区域分割成m 行 n列的 小方格,并获取该区域的像素信息
- 所有素材图绘制到canvas上,获取该图的像素信息,并获取该图与每个区域的相似度
- 每个小方格 绘制上 与之 对应的 相似度最大的图,绘制在canvas第二层
实现细节
由于时间有限,本篇文章仅介绍 相关的算法实现,
《使用canvas实现照片马赛克效果上-基础算法实现》, 后续有时间会再出一篇文章 介绍实现细节《使用canvas实现照片马赛克效果下-功能实现》
准备素材
为了防止 canvas渲染的时候 拿不到图片,这里为了方便,先预加载所有图片资源:
加载完素材图后,计算与主图的相似度
根据相似度进行排序
由于后期实现会加透明度,且对颜色计算无需特别精确,为了方便计算,这里统一把图片绘制到 1px x 1px的画布上并获取颜色,这里就能拿到 整张图片的 平均颜色。
利用余弦定理计算 颜色差异度
利用CIELAB 颜色空间 计算 颜色差异度
CIELAB 颜色空间
由于发现 余弦值 计算出的不太符合预期,也可能是我使用的问题,比如 (1,1,1) 和 (255,255,255) 计算出来是1,相似度最高,这样计算出来的有问题,有同学如果有啥处理的思路,还请不吝赐教 因此查询并了解了另一种计算方式:
CIELAB色彩空间(英语:CIELAB color space)又写为Lab*,是国际照明委员会(缩写为CIE)在1976年定义的色彩空间。它将颜色用三个值表达示:“L*”代表感知的亮度、“a*”和“b*”代表人类视觉的四种独特颜色:红色、绿色、蓝色和黄色。CIELAB旨在作为一个感知上统一的空间,其中给定的数字变化对应于相似的感知颜色变化;虽然并不是真正的感知均匀,但在工业上仍可用于检测颜色的细微差异。
可以看下他们的对比:
使用余弦相似度排序结果
利用CIELAB色彩空间计算排序结果
结论
相比之下,在当前素材列表里,余弦相似度误差较大,而 CIELAB色彩空间 的方式完全符合预期,因此本次将继续采用 CIELAB色彩空间 的方式 来计算rgb颜色相似度。
由于时间有限,文章内容”一镜到底“,如有纰漏 欢迎指正,如果有感兴趣的同学也欢迎一起讨论