我正在实施自定义面板模糊效果。我想模拟玻璃效果。 我在搜索中找到了the following code:
function blur(source:TBitmap):TBitmap;
var
x, y, x3:integer;
tline, mline, bline:PByteArray;
begin
for y := 1 to source.Height - 2 do
begin
tline := source.ScanLine[y-1];
mline := source.ScanLine[y];
bline := source.ScanLine[y+1];
for x := 1 to source.Width - 2 do
begin
x3 := x*3;
mline^[x3] :=
(mline^[x3 - 3] + mline^[x3 + 3] +
tline^[x3 - 3] + tline^[x3 + 3] + tline^[x3] +
mline^[x3 - 3] + mline^[x3 + 3] + mline^[x3]) div 8;
mline^[x3 + 1] :=
(mline^[x3 - 2] + mline^[x*3 + 4] +
tline^[x3 - 2] + tline^[x*3 + 4] + tline^[x3+1] +
mline^[x3 - 2] + mline^[x*3 + 4] + mline^[x3+1]) div 8;
mline^[x3 + 2] :=
(mline^[x3 - 1] + mline^[x3 + 5] +
tline^[x3 - 1] + tline^[x3 + 5] + tline^[x3+2] +
mline^[x3 - 1] + mline^[x3 + 5] + mline^[x3+2]) div 8;
end;
end;
result := source;
end;
上述功能运行正常,但由于我不是作者,对图像处理一无所知,我会在此功能中添加设置模糊等级的可能性。
我还发现了following code,它可以配置,但是,应用起来很慢。
我发现“配置”模糊的临时解决方案是根据您想要的模糊程度调整函数以递归方式运行。请参阅下面的代码段:
function blur(source:TBitmap; nTimes: Integer = 1): TBitmap;
var
x, y, x3, I : integer;
tline, mline, bline: PByteArray;
begin
if nTimes = 0 then Exit(source);
for I := 0 to nTimes do...
问题是:如何制作可配置且有效的模糊效果,还是有人可以帮我改进上述功能?
答案 0 :(得分:3)
此功能无法正常工作,可能是由于复制粘贴中的错误。
Blur是一种卷积。要获得模糊图像中像素的值,您必须计算某些附近的源像素的加权和。
Dest[y,x] = Sum(dy=-size/2..size/2, dx=-size/2..size/2) (Src[y+dy, x+dx] * Weight[dy, dx])
在你的情况下,系数(权重)是
1/8 1/8 1/8
1/8 0 1/8 or 1/8 * (1,1,1,1,0,1,1,1,1)
1/8 1/8 1/8
这不是高斯模糊 - 3x3内核的系数是1/16 * (1, 2, 1, 2, 4, 2, 1, 2, 1)
。请注意,中心像素涉及最大系数。
此外,代码不利用较低的扫描线 - 每个总和中的第三行应使用bline
。
一般情况下,您可以计算和使用任何大小的高斯内核(公式取决于sigma
随处可见),但直接使用大型过滤器的速度很慢。将小高斯滤波器多次应用于同一图像相当于应用一些较大的滤波器。
对于大内核大小,有快速(但更复杂)的方法 - 通过FFT(快速傅立叶变换)进行快速卷积。