在这一篇我们要来讲一些比较进阶的内容。
那就是图像模糊演算法
~
大部分有Debug过IE的人应该都知道,IE是不支援css的filter属性的。
但是很多时候设计师交上来的稿子里面又常常会含有很多的模糊特效。
不得不吐槽一下设计师几乎都只爱那种会吃爆效能的Feature,而且还都屡屡讲不听= =
通常这种时候大部分的工程师都会自己取舍要不要实现这样的Feature,
本文的主旨就是提供各位一个备选方案~ 也就是用canvas来实作模糊特效。
这篇文一共会分成两篇来讲解,第一篇我们会进行理论
面的讲解,而第二篇才会进入实作
。
不知道大家还对小时候的考试成绩
结算的方法有没有印象~
例如小时候老师在月考前会说:『这次月考的成绩统计会采加权制度
,数学的加权权重
会是3, 国/英文是2,社会/自然是1』
老师这样讲的意思就是说~最後平均成绩的计算方式会是:
『(数学分数*3+国文分数*2+英文分数*2+社会分数*1+自然分数*1) / (3+2+2+1+1)』
像这样的分数计算,就是一种加权运算
。
而我们在这边要提到的模糊
说穿了其实也就是一种加权运算
。
为什麽这样说呢? 我们先来看看最简单的图形模糊演算法
: 方框模糊(Box Blur)
的做法~
这张照片右半部就是图像透过方框模糊运算之後产生的结果
熟悉Photoshop
操作的人一定知道,模糊
其实有分成很多种类,除了我们现在提到的方框模糊(Box Blur)
以外,还有动态模糊(Motion Blur)
, 高斯模糊(Gaussian Blur)
...,etc.
这几种模糊的差别其实就在於背後实现它们的加权运算
的权重
不太一样。
以 方框模糊(Box Blur)
来讲, 它的加权运算
是取每颗像素(这边先把它叫做像素i)
的n宫格(九宫格是3*3, 那n宫格就是√n *√n)范围内的邻近像素(包括自己),每颗像素的权重都定为1,最後把这些像素加起来取平均(也就是把他们的r/g/b/a
值统统个别的加起来,然後不做任何权重加成来取平均), 最後把这个平均赋予给像素i
,像这样的动作去把每个像素
都处理一遍,就会变成我们上面看到的图样。
如果光看文字还是不懂意思,可以看下面这张图
在上面这张图我们可以看到n宫格
范围内的r/g/b值
都分别被取了平均,然後赋予到n宫格
中间的像素上面。
这个就是方框模糊(Box Blur)
的做法。
我们刚刚提到的『n宫格,而且每一格的权重都只有1』,像这样的一个Pattern,我们先姑且把它称为像素加权模型
,我们可以用一个阵列来表示之:
[
1,1,1
1,1,1
1,1,1
]
像这样的像素加权模型
其实有一个正式的名称,那就是Convolution kernel(卷积核)
。
模糊
之所以会有不同的类型,主要原因就是卷积核
的不同。
例如以高斯模糊
为例,高斯模糊的卷积核
,以大小3*3/5*5/7*7的情况来看,大致上个别是这样:
我们这边把这样子的卷积核
做成3D模型来看,就看起来会像钟型分布
而我们在做高斯模糊的时候,其实就是把一张图像
的 每个像素
的 卷积核范围
内 的 像素
,按照这些像素在卷积核
上的权重,来取加权平均,最後把这个加权平均赋予到卷积核
中间那颗像素上面。
这个就是图像模糊运算的经典理论
。
我们刚刚提到了图像模糊运算的经典理论
,BUT 实际上我们在前端
如果要实现如同理论
中描述的运算的话,我们来看看会发生什麽事~
先假设今天我们的卷积核
大小是5*5, 然後图像是一张500*500
的png;
for (图像中的每一颗像素 i ){
let 总和 = 0
let 权重总计 = 0
for (i 的 二十五宫格范围内所有像素中的某一个颗 j ){
总和 += j* 二十五宫格上面 j位置 的权重
权重总计 += 二十五宫格上面 j位置 的权重
}
let 平均= 总和/权重总计
}
这样去计算起来,我们做这个运算至少需要跑500
*500
*5
*5
= 6250000
次回圈才做得完一张图片
的图像模糊运算。
吓到了吧~,可以试着想像一下我们亲爱的使用者打开你那放了100张
图片的网页的状况XD。
上述的这个状况意味着如果我们照着书上的理论去实作大尺度的模糊滤镜,肯定是会GG
的。
那麽应该怎麽办呢?
我们需要做的事情简单来说就是简化理论
,例如最常见的解法就是把n宫格
简化成n十字
,也就是先做一次横向
范围√n格内的的加权平均
,然後再做一次纵向
范围√n格内的的加权平均
,这麽一来运算的状况就会变成
for (图像中的每一颗像素 i ){
let 总和 = 0
let 权重总计 = 0
for (i 的 横向范围五格内所有像素中的某一颗 j ){
总和 += j* n宫格上面 j位置 的权重
权重总计 += n宫格上面 j位置 的权重
}
let 平均= 总和/权重总计
// 然後把平均值先赋予给该颗像素
}
for (图像中的每一颗像素 i ){
let 总和 = 0
let 权重总计 = 0
for (i 的 纵向范围√n格内所有像素中的某一颗 j ){
总和 += j* n宫格上面 j位置 的权重
权重总计 += n宫格上面 j位置 的权重
}
let 平均= 总和/权重总计
}
用刚刚的情况来看(卷积核
大小是5*5, 然後图像是一张500*500
的png), 回圈次数就变成了2
*500
*500
*(3
+3
) = 3000000
直接减少了3250000
次~(超过一半)
By This Way 我们就成功削减了一大票需运行回圈次数
~ 而这样我们就可以在前端实现近似的效果,但是实际与理论细节不同
的方框模糊
。
我们今天的介绍大概就先到这边,相信各位已经对模糊的理论
与简化理论的办法
有基本的认识~
明天我们将会继续来到实作
的部分~ 敬请各位期待 :D
P.S 本文後半段在2021/10/11号晚上
有调整过,主要是修正效能改良计算
的部分,有因应後来实作
的方法调整过,如果造成各位不便,还请见谅 >< !
>>: 用 Python 畅玩 Line bot - 06:Image Message
font-family属性设定HTML元素的文字字型 以下例子为将文字字型设定为标楷体 font-s...
本节将进行完整的虚拟订单请求发送 def get_order(shop_no, need_pay, ...
感谢支持! ...
好久没有更新了,最近比较忙,不过今天遇到一个很有意思的问题,就过来记录一下。 通过正则表达式匹配文本...
Odoo模组开发实战 目录 VIEW-Form View 第一章 VIEW-Form View 1....