⚠️ 这是一个非官方翻译网站,与 ImageMagick Studio LLC 无关。准确信息请参阅原文(https://usage.imagemagick.org/blur/index.html)

ImageMagick 使用示例 -- 图像的模糊与锐化

ImageMagick 使用示例 前言与索引
图像模糊

图像模糊

将图像模糊使其变得朦胧,乍看之下似乎没什么用,但实际上它在生成背景效果和阴影方面非常有用。它对于通过平滑"锯齿"效果来实现图像边缘的抗锯齿、以及通过圆化特征来产生高光效果也非常有用。模糊非常重要,以至于它是图像缩放不可或缺的一部分,不过那里使用的是另一种模糊方法,其效果被限制在原始图像单个像素的边界之内。ImageMagick 中有两个通用的图像模糊运算符:"[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)" 的扩散和 "[-blur](https://imagemagick.org/command-line-options/#blur)"。两者的结果非常接近,但由于 "[-blur](https://imagemagick.org/command-line-options/#blur)" 算法更快,因此即便后者在数学上更为精确,一般也更倾向于使用前者。(参见模糊运算符 vs 高斯模糊运算符。)

模糊/高斯参数

"[-blur](https://imagemagick.org/command-line-options/#blur)" 和 "[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)" 的参数相同,但对于初次接触图像处理的人来说,这些参数值可能会令人困惑。

**-blur  {_radius_}x{_sigma_} **

上面设置中重要的是第二个 sigma(西格玛)值。可以把它理解为你希望图像"扩散"或模糊的程度的近似值,以像素为单位。可以把它想象成用来模糊图像的画笔大小。这些数值都是浮点数,因此可以使用像 '0.5' 这样非常小的值。第一个值 radius(半径)也很重要,它控制着运算符在扩散像素时应该查看多大的区域。这个值通常应设为 '0',或者至少是 sigma 的两倍。为了展示这些选项的效果,我们用这张四周留有大量空白的简单图像(模糊运算符需要大量空间来运作)来生成一个表格,列出各种运算符设置下的结果。我还特意使用了一种同时包含粗线和细线的字体,以便观察小的线条细节和大面积色块的模糊效果。 |

  magick -font Gecko -pointsize 48  label:A \
          -bordercolor white -border 20x10  blur_source.png

[IM Output]

[IM Output]

radius 会将模糊的效果限制在与被模糊像素相距该像素数以内的范围内(正方形半径)。因此,使用像 '1' 这样非常小的 radius,实际上会把模糊限制在每个像素紧邻的邻居范围内。请注意,虽然 sigma 是浮点数,但 radius 不是。如果给出(或内部计算出)一个浮点值,它会被向上取整为最接近的整数,以确定模糊的"邻域"。而每个邻居对最终结果的贡献程度,仍然由 sigma 控制。非常小的 sigma(小于 '1')会将其贡献限制在很小的量,而较大的 sigma 则会让所有邻居贡献更为均等的量。最大的 sigma 值 '65355' 会对正方形邻域内的所有像素进行简单的平均化。另外还要注意,当 radius 较小而 sigma 较大时,模糊结果中会出现伪影。这在 "-blur 5x8" 的输出中尤为明显。这是因为较小的正方形邻域"截断"了被模糊的区域,导致模糊的平滑高斯曲线突然中止,从而沿着锐利边缘产生振铃伪影。所以……

模糊时 radius 切勿小于 sigma

理想的解决方案是像上表最后一行所示,简单地将 radius 设为 '0x'。在这种情况下,运算符会尝试自动为给定的 sigma 确定最佳的 radius。IM 使用的最小半径是 3,对于 Q16 版本的 IM 通常是 sigma 的 3 倍(IM Q8 精度较低,因此使用的半径更小)。我唯一会使用非零 radius 的情况,是针对非常小的 sigma 或特殊的模糊需求。所以……

尽可能在模糊操作中将 radius 设为零

sigma 的小数值通常只用于模糊那些未经抗锯齿处理的图像的线条并柔化边缘(更多信息参见抗锯齿)。在这种情况下,我发现 '1x0.3' 的模糊是一个很有用的数值,可以去除图像中的大部分"锯齿"。而较大的值则有助于生成朦胧的图像,用于背景或阴影效果(参见复合字体),甚至是图像高光效果(如高级示例页面通篇所示)。由于 IM 处理 'x' 风格参数的方式,上面的 sigma 是可选的。然而它才是更重要的值,所以理应是 radius 可选,因为 radius 可以被自动确定。因此,对这类卷积运算符只给出单个数值参数是没有意义的。这种情况长期以来一直如此,不太可能改变,因为改变会破坏太多东西。模糊使用通道设置 为了演示模糊效果,让我们先从在浅蓝色背景上生成一个朦胧的黑色圆开始…… |

  magick -size 70x70 xc:lightblue \
          -fill black -draw 'circle 35,35 20,25'  circle_on_blue.png
  magick circle_on_blue.png    -blur 0x8         circle_on_blue_blur.png

[IM Output] [IM Output]
如你所见,模糊这样一张普通图像没有任何问题,效果完全符合预期。但如果我们对一张带有透明背景的图像再次尝试…… |

  magick -size 70x70 xc:none \
          -fill black -draw 'circle 35,35 20,25'  black_circle.png
  magick black_circle.png       -blur 0x8        black_blurred.png

[IM Output] [IM Output]
等等,发生了什么!图像根本没有变化!其实运算符确实起作用了。但 "[-blur](https://imagemagick.org/command-line-options/#blur)" 作为一个灰度通道运算符,会受到 "[-channel](https://imagemagick.org/command-line-options/#channel)" 设置的限制,只作用于三个颜色通道。也就是说,只有图像的三个颜色通道被模糊了,而图像的透明度即 alpha 通道保持原样。而在上面的例子中,图像其实是在颜色为 'none' 的背景画布上的一个完全不透明的圆,IM 将 'none' 定义为完全透明的黑色!这意味着我们得到的是透明黑色背景上的黑色圆。换句话说,这是一张所有颜色都是黑色、部分不透明、部分透明的图像。因此,当我们对图像进行模糊处理时,实际上只是把黑色和黑色互相模糊,结果可想而知——还是黑色!所以结果的颜色没有任何变化。同时我们也完全没有触及图像的 alpha 即透明度通道,所以图像的透明度保持不变。也就是说,仍然是一个黑色的圆!我们真正想做的,是模糊图像的全部四个通道,尤其是 alpha 通道。要做到这一点,需要把 "[-channel](https://imagemagick.org/command-line-options/#channel)" 设置为图像的全部四个通道(例如使用 'RGBA' 值)。 |

  magick black_circle.png  -channel RGBA  -blur 0x8  black_blurred_RGBA.png

[IM Output]
总结一下……

对带有透明度的图像进行模糊处理时,请始终使用 "-channel RGBA" 设置。

| IM 5.5.7 版本会自动模糊全部四个颜色通道,但该运算符对带有透明度的图像还有其他有问题(bug)的效果。详情参见带透明度的模糊 Bug
---|---
| 某些图像格式(例如 GIF 和 JPEG)无法处理半透明像素。因此,对于带有某种半透明颜色的图像,如果可能的话,建议使用 PNG 格式。
---|---
从上面可以看出,"[-channel](https://imagemagick.org/command-line-options/#channel)" 设置对于像 "[-blur](https://imagemagick.org/command-line-options/#blur)" 这样的灰度运算符来说非常重要。但在使用这类运算符时,这并不是唯一需要注意的重要事项。举例来说,让我们再次尝试上一个"忘记设置 "[-channel](https://imagemagick.org/command-line-options/#channel)"" 的例子,这次换成黄色的圆。 |

  magick -size 70x70 xc:none \
          -fill yellow   -draw 'circle 35,35 20,25'   yellow_circle.png
  magick yellow_circle.png       -blur 0x8           yellow_blurred.png

[IM Output] [IM Output]
请注意,和黑色圆的情况不同(那时图像没有变化),这次我们得到的是一个看起来很糟糕的黄色圆,边缘还渗入了黑色。真难看!这个问题是由一个大多数 IM 新用户都没意识到的事实引起的。

透明像素也是有颜色的,即使你看不见它。

在上面的例子中,那个透明的颜色是黑色,它渗入了黄色的圆中。当然,只要为透明图像正确设置 "[-channel](https://imagemagick.org/command-line-options/#channel)",就能修正这个问题,效果也会符合预期。 |

  magick yellow_circle.png  -channel RGBA  -blur 0x8  yellow_blurred_RGBA.png

[IM Output]

模糊的内部机制

让我们更进一步,用一个更复杂的例子,来准确探究 "[-blur](https://imagemagick.org/command-line-options/#blur)" 内部到底做了什么。这里我们创建一张非常特别的图像:在完全透明的红色背景上绘制一个黄色的圆。这样我们就能看到透明颜色在模糊图像时所产生的效果。 |

  magick -size 70x70 xc:'#F000' \
          -fill yellow   -draw 'circle 35,35 20,25'   yellow_on_red.png

[IM Output]
请注意,颜色 "#F000" 是完全透明的红色。也就是说,图像背景区域实际上是一种看不见的红色,而不是更常见的完全透明的黑色。这一点在后面的测试中很重要。我们可以使用 "[-alpha off](https://imagemagick.org/command-line-options/#alpha)" 运算符,实际上删除图像的 alpha 通道,从而看到图像透明部分的颜色。 |

  magick yellow_on_red.png   -alpha off  yellow_on_red_matte.png

[IM Output]
现在让我们再次尝试使用默认的 'RGB' "[-channel](https://imagemagick.org/command-line-options/#channel)" 设置,只模糊图像的颜色。 |

  magick yellow_on_red.png   -blur 0x8   yellow_on_red_RGB.png

[IM Output]
如你所见,图像完全透明的红色背景已经渗入了可见的黄色圆中,像之前一样给它添加了一圈有趣的橙色边缘。你可能会喜欢这种效果,但要生成它,有比依赖看不见的完全透明颜色更好的方法。为了证明可以正确地模糊这张图像,我们来正确地做一遍…… |

  magick yellow_on_red.png  -channel RGBA  -blur 0x8  yellow_on_red_RGBA.png

[IM Output]
之所以连同 alpha 通道一起模糊不会像之前那样产生橙色,是因为当 "[-blur](https://imagemagick.org/command-line-options/#blur)" 运算符发现(根据当前的 "[-channel](https://imagemagick.org/command-line-options/#channel)" 设置)alpha 通道也参与其中时,它只会使用根据该 alpha 通道判断为 可见 的像素来进行模糊。如果 alpha 通道不参与,它就会完全忽略该通道,于是完全透明的红色就会和黄色混合模糊,产生各种色调的橙色。基本上,模糊算法已经被修改为忽略图像中所有完全透明的像素,无论它们是什么颜色。半透明像素仍然会参与运算,但它们对结果的影响也会根据其可见程度而被调节。结果就是这个圆变成了一个朦胧的半透明黄色斑点——这正是用户很可能想要达到的效果。如果你真的愿意,也可以将颜色通道和 alpha 通道分别进行模糊,从而有效地切断算法对颜色通道的"可见性调整"。这样得到的结果更像是阳光透过一层脏兮兮的褐色雾霭照射进来。 |

  magick yellow_on_red.png  -channel  A  -blur 0x8 \
                             -channel RGB -blur 0x8  yellow_on_red_GS.png

[IM Output]
这最后一个例子所产生的效果,正是一个纯粹的灰度运算符在 alpha 通道与图像中的颜色(无论透明与否)之间完全没有交互时会产生的结果。也就是说,红、绿、蓝、alpha 各个通道彼此完全独立地被模糊,就好像它们各自是一张单独的灰度图像。请记住,由于默认的 "[-channel](https://imagemagick.org/command-line-options/#channel)" 设置是 'RGB',默认行为是不模糊 alpha 通道,并且 会把图像中不可见的颜色和可见的颜色一起模糊。你是不是很高兴 "[-blur](https://imagemagick.org/command-line-options/#blur)" 不再永远是一个纯粹的灰度运算符了?不过如果你真的想要,仍然可以那样使用它。只是你以前并不总是有这个选择…… | _在 IM 6.2.4-4 版本之前,"[-blur](https://imagemagick.org/command-line-options/#blur)" 和 "[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)" 运算符是作为纯粹的灰度操作来应用的,因此不会根据 alpha 通道的"可见性"来调整颜色权重。结果是,任何形式的带透明度的模糊,几乎总是会产生可怕的"黑色光晕"效果,就像前面例子中特意生成的那样。

这曾被列为 IM 发行版中一个长期存在的重大 Bug,也是一个非常难以绕过的问题。有关此问题的更多详情,请参见带透明度的模糊 Bug页面。_
---|---

FUTURE: Blur and Trimming Images.

模糊运算符 vs 高斯模糊运算符

关于 "[-blur](https://imagemagick.org/command-line-options/#blur)" 和 "[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)" 哪个更适合用来模糊图像,一直存在一些疑惑。首先,"[-blur](https://imagemagick.org/command-line-options/#blur)" 更快,但它是通过两阶段技术实现的:先在一个轴向上模糊,然后在另一个轴向上模糊。而另一方面,"[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)" 运算符会同时向所有方向进行模糊,因此在数学上更为精确。两者之间的速度差距可能非常巨大,视所涉及的模糊量而定,可达 10 倍甚至更多。从更技术性的角度来说,"[-blur](https://imagemagick.org/command-line-options/#blur)" 是一个两遍(2 pass)的一维正交卷积滤镜,而 "[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)" 是一个二维圆柱形卷积滤镜。详情参见卷积。与其他使用"滤镜化"的卷积操作不同,这两种方法的结果应当是相同的。然而两遍处理意味着存在一个中间阶段,在该阶段可能出现舍入或量化效应。Cristy 也证实了这一点,他曾这样报告……你应该始终使用 "[-blur](https://imagemagick.org/command-line-options/#blur)" 而不是 "[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)",因为它更快。由于舍入的原因,内部的一些像素可能会有所不同,而边缘像素也可能因为中间阶段虚拟像素边缘效应的损失而有所不同。总而言之,这两个运算符略有不同,但差异极小。由于 "[-blur](https://imagemagick.org/command-line-options/#blur)" 快得多,请使用它。在几乎所有涉及模糊的示例中,我都是这样做的。

使用 Resize 实现大范围模糊

对图像模糊使用较大的 sigma 值会非常慢。不过有一种技巧可以用来加快这个过程。不过这只是一种粗略的方法,若要改善结果,可能还需要一些数学上的严谨性。从本质上说,大范围模糊之所以慢,是因为对图像中的每一个像素,都需要一个较大的窗口即"核"来合并大量像素。然而 resize(缩小图像)也是做同样的事情,只是在过程中生成的像素更少。这个技巧基本上就是先缩小图像,然后再放大,从而生成强烈模糊的结果。高斯滤镜对此特别有用,因为你可以直接指定一个高斯 Sigma 定义。例如,这里我用两种方法都以 sigma 值 5 来模糊这张小玫瑰图像。

  magick rose: -blur 0x5   rose_blur_5.png
  magick rose: -filter Gaussian -resize 50% \
          -define filter:sigma=2.5 -resize 200%  rose_resize_5.png

[IM Output] [IM Output] [IM Output]

请注意,这里的 sigma 设置(仅用于放大步骤)只是实际期望值的一半,因为你同时也把图像尺寸放大了一倍。通过同时调整缩小比例和给定的 sigma 值,可以让最终得到的整体模糊效果更强。缩小步骤才是带来加速效果的部分,但为了质量控制,放大步骤中也应该保留至少一些模糊。这只是这个技巧的一个示例,它其实是用于对非常非常大的图像使用非常非常大的 sigma 值的场合。例如对现代数码照片使用 10 或更大的 sigma 进行模糊。这个技巧也被用于为单张图像生成多层级的模糊,参见稀疏颜色 Shepards 替代方案


图像锐化

建设中

锐化是一种在电视节目和电影中最常见的计算机图形算法。想象一下警方"清理"一张银行劫匪汽车牌照的"放大"照片,或是模糊的商店监控摄像头视频中一名男子的脸部特写,你就明白我的意思了。基本上他们所做的,是试图恢复因相机镜头的自然模糊或低分辨率图像而丢失的图像细节。锐化的参数是什么?(展开)

最重要的因素是 sigma(西格玛)。因为它才是真正
控制锐化操作的参数。它之所以在上面的写法中
排在第二位,纯粹是历史遗留的偶然结果。
该值可以是任意浮点数,从几乎不做任何锐化的
.1,到进行强烈锐化的 3 或更大。0.5 到 1.0 相当不错。

半径(radius)只是效果范围的限制,阈值也是如此。

半径只能取整数,因为算法本身就是这样设计的,
半径越大速度越慢。但它至少应为 sigma 的 1 倍,
最好是 2 倍。
首先忘掉第一个数字,直接用 0,这样系统就会为你给出的 "sigma" 系数使用最合适的数值。sigma 越大,锐化效果就越强。 -sharpen 0x.4 非常小
-sharpen 0x1.0 大约相当于 1 像素大小的锐化
-sharpen 0x3.0 可能已经过大
"[-sharpen](https://imagemagick.org/command-line-options/#sharpen)" 运算符可以说是一种反向的模糊。事实上,它的工作方式几乎完全一样。关于这与模糊之间的关系的示例,请参见通过插值与外推进行图像处理。举个例子,让我们先模糊一张简单的图像,然后再尝试锐化以去除模糊。
  magick -font Gecko -pointsize 72 label:A  A_original.jpg
  magick A_original.jpg     -blur    0x3    A_blur.jpg
  magick A_blur.jpg         -sharpen 0x3    A_blur_sharp.jpg
  magick A_blur_sharp.jpg   -sharpen 0x3    A_blur_sharp_x2.jpg

[IM Output] [IM Output] [IM Output] [IM Output]

如你所见,结果并不完美,因为把像素扩散开来会让图像的锐利转角变得不那么清晰。特别请注意图像最顶部两条线交汇处产生的额外增粗,以及细线几乎消失的现象。即便重复该操作或增大锐化区域的大小,也无法让图像恢复到与原图完全一致,因为图像的模糊已经从根本上丢失了更细的细节。不过宏观的细节还是可以恢复得相当不错。正是这种能够从模糊或大幅放大的图像中恢复更细细节的锐化算法,在警方、天文学家和政府情报机构所使用的软件包中创造了大量的商业价值。

反锐化(Unsharp)图像

建设中

"[-sharpen](https://imagemagick.org/command-line-options/#sharpen)" 和 "[-unsharp](https://imagemagick.org/command-line-options/#unsharp)" 这两个运算符,都是使用完全相同的技术:从原图中减去一个模糊版本。关于 "[-sharpen](https://imagemagick.org/command-line-options/#sharpen)" 和 "[-unsharp](https://imagemagick.org/command-line-options/#sharpen)" 实际内部工作原理的细节,请参见反锐化卷积

  magick A_blur.jpg       -unsharp 0x5        A_blur_unsharp.jpg

[IM Output] [IM Output]

来自 Alex Beels 对 [使用 ImageMagick 锐化](http://redskiesatnight.com/2005/04/06/sharpening-using-image-magick/) 一文的评论

  匹配 GIMP 的反锐化
    gimp 的半径加 1  => IM 的 sigma
    阈值除以 255     => IM 的阈值

  所以 GIMP 中 radius=2  amount=1.5  threshold=5  对应于
    -unsharp 0×3+1.5+0.0196

  另有人提出 im_sigma = sqrt(gimp_radius)

**Fred Weinhaus 的原始笔记**

用于测试的模糊图像。

A_original.jpg

magick A_original.jpg -blur 0x3 A_original_blur3.jpg

锐化其实就是用一张高斯型的模糊图像减去原图,
得到一张边缘图像(高通滤波),然后再将其与原图
等量混合,从而得到一张高通增强的图像。

magick A_original_blur3.jpg -sharpen 0x3 A_original_blur3_sharp3.jpg

反锐化更复杂一些,但原理类似。它同样取上述的
差值(边缘结果),也就是和锐化一样,但只将其中
一部分或某个倍数与原图混合,而且只有当差值超过
某个阈值时才会混合。因此 unsharp 0x3+1+0 基本上等同于 sharpen 0x3。

magick A_original_blur3.jpg -unsharp 0x3+1+0
A_original_blur3_unsharp3_1_0.jpg

compare -metric rmse A_original_blur3_sharp3.jpg
A_original_blur3_unsharp3_1_0.jpg null:
164.661 (0.00251256)

这个差异可能源于其中一种方法使用了可分离
(高斯型)模糊滤镜而另一种没有使用,两者只用了
其中一种。也可能只是 IM 实现中其他地方的一些细微差异。

如果与原图混合得更少,锐化效果就会更弱。

magick A_original_blur3.jpg -unsharp 0x3+0.5+0
A_original_blur3_unsharp3_0p5_0.jpg

如果与原图混合得更多,锐化效果就会更强。

magick A_original_blur3.jpg -unsharp 0x3+2+0
A_original_blur3_unsharp3_2_0.jpg

如果提高阈值,锐化效果又会变弱。

magick A_original_blur3.jpg -unsharp 0x3+2+0.2
A_original_blur3_unsharp3_2_0p2.jpg

我(Fred)的几个脚本 binomialedge、gaussianedge、sharpedge
都用到了这种混合概念(在高通滤波结果与原图之间),
脚本中附有相应说明。我的脚本中的阈值处理方式不同,
用途也不一样。

**使用反卷积进行锐化**

还有一种使用反卷积(在图像的快速傅里叶变换生成的
频域形式中进行除法运算)的技术。当原图所应用的
确切"模糊"是已知的,或可以通过某种方式计算出来时,这种方法效果最好。

目前 IM 中只提供了原始的 "DIY" 方法,其中一些方法
在子章节 [傅里叶乘法/除法](https://usage.imagemagick.org/fourier/fft_math/)
中进行了演示(试验)。

生成阴影

"[-shadow](https://imagemagick.org/command-line-options/#shadow)" 运算符是一个随 IM 示例页面一同开发出来的高级运算符。基本上,它代表了对给定图像的透明度形状进行的一次非常复杂的模糊与重新着色。这是 IM 用户一直在进行的操作,但要弄清楚如何正确实现它,需要相当多的知识。该运算符会取一张图像(通常是克隆出来的,可能已经带有一些透明度),并将其变成一张阴影图像,随后可以将其以给定的偏移量放置在原图下方(一般会使用特殊的图层合并运算符)。举例来说,这里展示了一种标准做法,使用与本网页相配的藏青色阴影为现有图像添加阴影。 |

  magick rose: \( +clone  -background navy  -shadow 80x3+5+5 \) +swap \
          -background none   -layers merge  +repage   shadow.png

[IM Output]
请注意阴影图像相对于原图的偏移是正确的。你甚至可以把模糊的 'sigma' 值设为零,从而生成一个坚硬但半透明的阴影。 |

  magick rose: \( +clone  -background navy  -shadow 60x0+4+4 \) +swap \
          -background none   -layers merge +repage  shadow_hard.png

[IM Output]
使用 "[-layers](https://imagemagick.org/command-line-options/#layers) merge" 将阴影图像与原图叠加在一起,可以轻松生成来自任意方向光源的阴影,而不仅限于左上方。 |

  magick rose: \( +clone -background navy -shadow 80x3-5+5 \) +swap \
          -background none  -layers merge +repage  shadow_other.png

[IM Output]
虽然直接使用图层合并是最简单的方法,但它往往会使结果图像的整体偏移发生变化。不过这种偏移并非由图层化方法本身造成,而是因为 "[+repage](https://imagemagick.org/command-line-options/#repage)" 会去除结果"图层"图像中可能存在的负或正偏移。有关替代技巧,请参见阴影与偏移问题。 | 图层合并方法是在 IM v6.3.6-2 中加入的。在此之前,你需要改用类似的图层扁平化运算符 "[-mosaic](https://imagemagick.org/command-line-options/#mosaic)"。不过该运算符存在一些问题(见下文)。
---|---

有形状的阴影

现在,"[-shadow](https://imagemagick.org/command-line-options/#shadow)" 是专为带形状的图像设计的(这也是它如此复杂的原因)。例如,这里是一个典型的带阴影字体。 |

  magick -background none -stroke black -fill white \
          -font Candice -pointsize 48 label:A -trim \
          \( +clone   -background navy   -shadow 80x3+3+3 \) +swap \
          -background none   -layers merge +repage  shadow_a.png

[IM Output]
如果原图中有足够的空间来容纳阴影而不被裁切,你可以使用这条命令。它使用一种特殊的 '[DstOver](compose.html#dst_over)' 合成方法,从而无需交换两张图像的顺序。 |

  magick -background none -stroke black -fill white \
          -font Candice -pointsize 48 label:'A ' \
          \( +clone -background navy -shadow 80x3+3+3 \) \
          -background none -compose DstOver -flatten  shadow_a_size.png

[IM Output]
你大概能在这里看到一点点裁切,因为原图没有为所需的阴影预留足够的额外空间。

阴影与偏移问题

阴影的问题在于,模糊的阴影会向各个方向扩展。为了补偿这一点,"[-shadow](https://imagemagick.org/command-line-options/#shadow)" 运算符会通过添加一个相当于给定模糊 'sigma' 值两倍大小的边框,来放大实际的原图。也就是说,如果你用 'x3' 来模糊阴影,它会把图像放大 12 像素(每边各放大 sigma 的两倍,即 3 像素的两倍)。为了补偿这种放大,阴影图像还会被赋予一个适当的负虚拟画布偏移,以便相对于被加上阴影的图像正确定位。对于普通图像来说,这意味着生成的阴影图像会带有一个负偏移。然而,当你的 IM 没有 "[-layers](https://imagemagick.org/command-line-options/#layers)" 的 'merge' 方法可用时,这就会产生问题。例如,这里我们尝试在图像左侧添加阴影,就好像光是从右上方照过来一样。 |

  magick rose: \( +clone  -background navy  -shadow 60x3-5+5 \) +swap \
          -background none   -mosaic   shadow_left_clipped.png

[IM Output]
如你所见,由于负偏移,阴影被 "[-mosaic](https://imagemagick.org/command-line-options/#mosaic)" 运算符裁切掉了。不太好!一种解决办法是给原图添加一个初始偏移,使生成的阴影图像的偏移不再为负。 |

  magick rose: -repage +11+0\
          \( +clone   -background navy   -shadow 80x3-5+5 \) +swap \
          -background none   -mosaic   shadow_left.png

[IM Output]
另一种方法是在生成阴影之后,将两张图像都偏移适当的量。这样可以在使用 "[-mosaic](https://imagemagick.org/command-line-options/#mosaic)" 合成之前,先消除任何负偏移。请注意这里在 "[-repage](https://imagemagick.org/command-line-options/#repage)" 中使用了 '!' 标志,将给定的偏移同时加到两张图像上。 |

  magick rose: \( +clone -background navy -shadow 80x3-5-5 \) +swap \
          -repage +11+11\! -background none  -mosaic  shadow_tl.png

[IM Output]
所需的空间量至少应为 2×'sigma'-'offset',在本例中即 2×3--5 ⇒ 11 像素,否则就有裁切阴影的风险。不过大约 'sigma'-'offset' 的空间通常就能产生可接受程度的裁切。另一种替代方案是扩展原图,以便为最终的阴影腾出足够空间。这是处理阴影的最佳方式,同时还能保留图像在虚拟画布上的原始位置。例如,这里我为原图填充了一些额外空间以容纳阴影,然后直接将阴影图像铺在下方。我在显示的图像结果中加了一个边框,这样你就能看到最终图像仍然位于"填充后"图像的中央。 |

  magick rose: -bordercolor None -border 11x11 \
          \( +clone -background navy -shadow 80x3+5+5 \) \
          -background none -compose DstOver -flatten \
          -compose Over  shadow_space.png

[IM Output]
所需的填充量应至少为 'sigma'+abs('offset'),最好是 2×'sigma'+abs('offset'),以确保阴影不会被裁切。填充可以是非对称的以节省空间,但为了方便起见,通常会像上面那样使用对称填充。 | 请注意,虽然上面的 "-compose Over" 设置实际上并非必需,但仍建议加上。否则,之后的操作(即便是在其他 "magick" 命令中)也可能受到影响,产生意料之外的结果。也就是说,非标准的合成设置可能影响其他操作,包括:图像分层、添加边框或画框,或者仅仅是其他合成操作。
---|---

阴影与 Composite

论坛上很多人会生成一张阴影图像,然后尝试使用更底层的 "[-composite](https://imagemagick.org/command-line-options/#composite)" 来合并图像。例如直接将原图叠加到生成的(更大的)阴影图像上。 |

  magick rose: \( +clone  -background navy  -shadow 60x3 \) \
          +swap -composite  +repage shadow_composite.png

[IM Output]
首先要记住的一点是,合成运算符是非常底层的,它不会读取原图或阴影运算符可能带有的任何图层或虚拟画布偏移。事实上,我们仍然需要使用 Repage 设置来去除或调整阴影所添加的、可能为负(不利)的偏移。这意味着,你在上面示例中看到的偏移,仅仅是因为阴影为了给自己留出空间而放大了输入图像的方式所产生的。阴影之所以出现在那个位置,完全是因为阴影图像被放大了 sigma 的两倍。此外,如果你使用"坚硬阴影"(sigma 为零),最终阴影根本不会有偏移,因此除了可能出现的暗色光晕边缘效果外,阴影会被原图完全遮住。你实际上等于放弃了阴影运算符所提供的内置偏移计算。当然,你也可以自行计算并设置合适的合成 Geometry/Gravity 设置,最简单的方法是使用 "[-gravity](https://imagemagick.org/command-line-options/#gravity) Center" 设置,因为放大后的阴影图像在各边都是等量扩展的。 |

  magick rose: \( +clone  -background navy  -shadow 60x3 \) +repage \
          +swap -gravity center -geometry -3-5 -composite shadow_geometry.png

[IM Output]
请注意,由于图像顺序被交换了,居中的 geometry 偏移是负值。

阴影轮廓

你还可以使用 "[-shadow](https://imagemagick.org/command-line-options/#shadow)" 来为形状(比如文字)生成模糊的轮廓。通过使用图层合并,IM 会自动为半透明的模糊添加所需的额外空间。 |

  magick -background none -fill white \
              -font Candice -pointsize 48 label:A -trim \
          \( +clone -background black  -shadow 100x3+0+0 \) +swap \
          -background none   -layers merge +repage  shadow_outline.png

[IM Output]
在这里你可以看到使用模糊形状来做轮廓的一个问题:由于模糊的工作原理本身,形状的边缘总是至少有 50% 是透明的。为了弥补这一点,你可以放大将被加上阴影的形状(示例参见更浓的柔和轮廓字体),或者更好的做法是,使用Level 调整来调整阴影图像的透明度,使形状边缘的 50% 透明变为完全不透明。 |

  magick -background none -fill white \
          -font Candice -pointsize 48  label:A -trim \
          \( +clone -background black  -shadow 100x3+0+0 \
             -channel A -level 0,50% +channel \) +swap \
          +repage -gravity center -composite   shadow_outline_darker.png

[IM Output]
另一种处理阴影定位和偏移的方法,是干脆把 "[-shadow](https://imagemagick.org/command-line-options/#shadow)" 生成的所有偏移都丢弃(使用 "[+repage](https://imagemagick.org/command-line-options/#repage)"),然后把原图居中叠加在更大的阴影图像上。通过添加一个 "[-geometry](https://imagemagick.org/command-line-options/#geometry)" 合成偏移,你就可以把阴影的偏移作为一个单独的操作来处理。 |

  magick -background none -fill white -stroke black \
          -font Candice -pointsize 48  label:A -trim \
          \( +clone -background navy  -shadow 80x3 \) +swap \
          +repage -gravity center -geometry -3-3 -composite \
          shadow_geometry_offset.png

[IM Output]
不过请注意,这里的偏移方向与通常用于定位阴影的方向相反。这是因为你实际上偏移的是文字形状而不是阴影本身,所以方向相反。这种方法在偏移量大于模糊 'sigma' 的两倍时,会裁切原始源图像而不是阴影图像。因此它不能用于"坚硬阴影"(使用 'x0' 的模糊 'sigma'),除非你在阴影图像中加入一些填充空间,以便叠加原图。不过对于柔和朦胧的阴影来说,这种情况很少成为问题。有关阴影处理的一些实用示例,请参见缩略图阴影更好的 3D Logo 生成

Montage 命令中的阴影

从 IM v6.3.1 开始,"magick montage" 的 "[-shadow](https://imagemagick.org/command-line-options/#shadow)" 设置开始使用该运算符提供的柔和"有形状"阴影。 |

  montage -label Rose  rose: \
          -background none -geometry +5+5 -shadow  shadow_montage.png

[IM Output]
不过并未提供设置该阴影颜色、模糊程度和偏移量的控制手段,因为 "magick montage" 除了简单的开/关选项之外,从来没有提供过这类控制。

阴影的内部机制

在内部,"[-shadow](https://imagemagick.org/command-line-options/#shadow)" 极其复杂。基本上,它不仅需要放大图像以容纳"柔和朦胧的阴影",还需要模糊图像现有的形状、适当设置其颜色,最后还要调整虚拟页面/画布的偏移;这一切都要按照用户的具体要求来完成。举例来说,给定下面这条 "[-shadow](https://imagemagick.org/command-line-options/#shadow)" 命令……

    magick image_clone.png -shadow 60x4+5+5   image_shadow.png

与之等效的 IM 操作大致如下……

  magick image_clone.png -alpha set \
          -bordercolor none  -border 8  -repage -8-8\!  \
          -channel A -virtual-pixel transparent \
               -blur 8x4 -evaluate multiply .60 +channel
          -fill {background_color} -colorize 100% \
          -repage +5+5\!     image_shadow.png

请注意,上面的数值 8 是模糊 sigma 的两倍,这是为了给模糊的阴影提供足够的空间。不过这也意味着最终图像会大出 sigma 的 4 倍像素。为了补偿这一点,还会加上等量的负偏移。既然会给生成的图像加上 sigma 两倍的负偏移,就要注意避免阴影被裁切,或相对于原图被错误定位。可以通过给原图一个初始的正偏移(比如 8-5 或 +3+3 像素)来做到这一点,也可以使用能够理解负偏移而不裁切最终图像的图层合并。基本上,请使用前面介绍的技巧,来正确处理阴影图像可能涉及的负偏移。 据我所知,PNG 和 MIFF 是仅有的既能处理负偏移、又能处理半透明像素的图像格式。如果要保存阴影图像以备将来使用,我建议使用 PNG。
正如我所说,"[-shadow](https://imagemagick.org/command-line-options/#shadow)" 是一个非常复杂的操作。当然,虽然上面的示例已经很接近 "[-shadow](https://imagemagick.org/command-line-options/#shadow)" 内部的实际做法,但并不完全相同。实际的 "[-shadow](https://imagemagick.org/command-line-options/#shadow)" 运算符不会改变任何全局设置,比如边框/背景/填充颜色,或当前的虚拟像素设置。此外,如果模糊 sigma 被设为 0,它还会跳过 "[-blur](https://imagemagick.org/command-line-options/#blur)" 运算符的调用,以避免模糊函数针对 sigma 或 radius 为零而发出警告。
FUTURE: overlaying multiple shadows

Overlaying two images with shadows, produces an unrealistic darkening of the
shadow where the shadow overlaps.  This darkening would be correct if each
object was lit by separate light sources, but more commonly the objects are
lit by the same light source.

The solution is to overlay the one image over the other, applying the shadow
effects to the opaque parts of each layer image in turn. That is, the
background shadow should be generated separately into each layer.  Remember
the shadow cast by the top most layer should become fuzzier than the shadow
contribution of the bottom most layer.

This complexity gets worse when you have three objects shadowing each other.
Also the offset and blurring from the shadow of each object should technically
be separate.  To generate that level of complexity, probably a 3-d ray-tracing
program should be used instead (sigh).

特殊模糊

IM 版本 6 中新增了几种其他类型的模糊,它们有着非常特殊的用途。这些模糊以特定的方式运作,而不像大多数其他"卷积"类操作那样在所有方向上起作用。它们也可能不如其他生成特殊模糊效果的方法好用,例如在进行更常规的模糊前后对图像进行扭曲。相关示例参见极坐标循环技巧椭圆(映射)模糊

警告:以下这些模糊都是实验性的,语法可能会发生变化!

径向模糊

你可以使用 "[-radial-blur](https://imagemagick.org/command-line-options/#radial-blur)" 让图像围绕一个圆心进行模糊,就像图像在不停旋转一样。不过严格来说,这其实是一种旋转或角度模糊,而不是真正意义上的径向模糊。注意: 使用Depolar-Polar - 旋转模糊技巧可以获得质量高得多的结果(不过速度也慢得多)。另外请注意,和普通的 "[-blur](https://imagemagick.org/command-line-options/#blur)" 运算符一样,"[-radial-blur](https://imagemagick.org/command-line-options/#radial-blur)" 也会受到 "[-channel](https://imagemagick.org/command-line-options/#channel)" 设置的影响。 |

  magick -size 70x70 xc:none \
          -stroke red    -strokewidth 15 -draw 'line 35,5 35,65' \
          -stroke yellow -strokewidth  9 -draw 'line 35,5 35,65' \
          -channel RGBA  -radial-blur 30   radial_blur.png

[IM Output]
你可以把对象放在偏离中心的位置(通过给图像添加一些空间),从而得到更有趣的 "[-radial-blur](https://imagemagick.org/command-line-options/#radial-blur)" 效果。 |

  magick -size 70x70 xc:none \
          -stroke red    -strokewidth 15 -draw 'line 5,50 65,50' \
          -stroke yellow -strokewidth  9 -draw 'line 5,50 65,50' \
          -channel RGBA  -radial-blur 90   radial_blur_90.png

[IM Output]
模糊的参数是径向模糊所覆盖的角度,也就是说,从原图出发,向每个方向各覆盖该角度的一半。所以角度为 180 时覆盖半个圆,而 360 度则会把图像模糊成一个完整的圆。 |

  magick -size 70x70 xc:none \
          -stroke red    -strokewidth 15 -draw 'line 5,50 65,50' \
          -stroke yellow -strokewidth  9 -draw 'line 5,50 65,50' \
          -channel RGBA  -radial-blur 180   radial_blur_180.png

[IM Output]
|

  magick -size 70x70 xc:none \
          -stroke red    -strokewidth 15 -draw 'line 5,50 65,50' \
          -stroke yellow -strokewidth  9 -draw 'line 5,50 65,50' \
          -channel RGBA  -radial-blur 360   radial_blur_360.png

[IM Output]
你甚至可以加入一点图像扭曲,让效果更有趣…… |

  magick -size 70x70 xc:none \
          -stroke red    -strokewidth 15 -draw 'line 5,50 65,50' \
          -stroke yellow -strokewidth  9 -draw 'line 5,50 65,50' \
          -channel RGBA  -radial-blur 180 -swirl 180 radial_swirl.png

[IM Output]
全圆径向模糊可以用来生成粗略的圆形渐变。不过要构造出能产生正确渐变的正确形状极其困难,可能并不值得为此付出努力。不过我还是试了试…… |

  magick -size 80x80 xc:lightblue -fill red \
          -draw "path 'M 40,40   C 43,43 47,47 50,40 \
                  S 52,23 40,20   S 14,22 10,40   S 15,75 40,79 Z'" \
          radial_gradient_pre.gif
  magick radial_gradient_pre.gif  -radial-blur 360  radial_gradient.gif

[IM Output] [IM Output]

运动模糊

通过使用 "[-motion-blur](https://imagemagick.org/command-line-options/#motion-blur)"(给出半径和 sigma,再加上模糊应发生的角度),你可以给图像添加一种仅沿单一方向线性衰减的模糊。这会让你的图像看起来就像它(或摄像机)在高速移动一样。 |

  magick -size 70x70 xc:none  -channel RGBA \
          -fill yellow  -stroke red  -strokewidth 3 \
          -draw 'circle 45,45 35,35'  -motion-blur 0x12+45  motion_blur.png

[IM Output]
请注意,对象不仅会拖出一条轨迹,其运动方向上的边缘也会把背景模糊进去。可以通过重新绘制或叠加原图,并多次重新施加一个较小的 "[-motion-blur](https://imagemagick.org/command-line-options/#motion-blur)",来改善这种前缘模糊。 |

  magick -size 70x70 xc:none -channel RGBA \
          -fill yellow  -stroke red -strokewidth 3 \
          -draw 'circle 45,45 35,35'  -motion-blur 0x8+45 \
          -draw 'circle 45,45 35,35'  -motion-blur 0x6+45 \
          -draw 'circle 45,45 35,35'  -motion-blur 0x2+45 \
          motion_blur_redraw.png

[IM Output]
多次运动模糊可以让移动物体拖尾的展开效果更明显,有点像正在消散的烟雾或火焰。 |

  magick -size 70x70 xc:none -channel RGBA \
          -fill yellow  -stroke red -strokewidth 3 \
          -draw 'circle 45,45 35,35'  -motion-blur 0x12+25 \
          -draw 'circle 45,45 35,35'  -motion-blur 0x12+55 \
          -draw 'circle 45,45 35,35'  -motion-blur 0x12+40 \
          motion_blur_spread.png

[IM Output]
这种技巧可以用来在地面上生成扩散开的阴影。另外你也可以先生成一个运动模糊,然后再对它稍微做一点径向模糊,不过这需要一些图像位移才能让中心对齐。你还可以再加一些图像扭曲,让效果更有意思…… |

  magick -size 70x100 xc:none -channel RGBA \
          -fill yellow  -stroke red -strokewidth 3 \
          -draw 'circle 35,80 45,70'  -motion-blur 0x20+90 \
          -background none  -rotate 50  -wave 5x25  -rotate -50 \
          -gravity center   -crop 70x100+0+0  +repage \
          -draw 'circle 35,80 45,70'  -blur 0x2 \
          motion_wave.png

[IM Output]

请注意,虽然 "[-radial-blur](https://imagemagick.org/command-line-options/#radial-blur)" 会向两个方向模糊,但 "[-motion-blur](https://imagemagick.org/command-line-options/#motion-blur)" 只会向一个方向模糊。在这两种情况下,我都建议你在图像边缘周围填充一些额外空间(通常使用 "[-border](https://imagemagick.org/command-line-options/#border)"),因为这两种特殊模糊都存在较强的边缘效应,最好加以避免。如果你发现了上述内容更实用或更有趣的示例或用法,请给我发一份邮件(地址见页脚)。


使用模糊实现形状羽化

建设中

警告: 本节内容目前已经过时,想要正确对图像进行羽化处理的用户应该参考使用距离实现形状羽化。这里展示的是所谓的"模糊羽化",正如后面部分所示,这是一种"伪羽化技巧"。尽管如此,它仍然是一种有用的方法,但仅限于"凸"形状的图像。 当你从图像中裁切出某个形状时,通常会希望对该形状的边缘做一点羽化或模糊处理,让外观更柔和,并淡化那些可能被意外包含进来的形状之外的部分,或者让图像更好地融入背景,而不至于让人一眼看出这是复制粘贴的痕迹。基本上,与其让某个形状带有"坚硬"的边缘,不如把它柔化,"伪造"出抗锯齿或镜头模糊的效果,使拼贴看起来更加天衣无缝。举个例子,这里有一张 GIF 图像,我把它叠加在一个浅色背景上。 |

  magick shape.gif -background wheat -flatten  overlaid.png

[IM Output]
然而,由于我叠加的是一张具有布尔透明度的 GIF 图像,边缘高度锯齿化,呈台阶状,所以图像在背景上显得非常突兀。如果处理的是真实照片,上面的结果看起来会显得非常人工。不过,只要把图像的透明度稍微模糊一下,就能让叠加效果更平滑地融入背景。 |

  magick figure.gif -alpha set -virtual-pixel transparent \
          -channel A -blur 0x0.7  -level 50,100% +channel \
          -background wheat -flatten  edge_blured.png

[IM Output]
顺便一提,这正是用于给缩略图生成柔和边缘的同一种技巧。关于这方面更多的示例,可以看看 Fred Weinhaus 的 "feather" 遮罩脚本的效果。如你所见,在叠加图像与背景之间对比度较高的简单情况下,这种方法效果非常好。但如果你想使用更大的羽化模糊系数,或者两张图像的颜色都非常浅,就会出现严重的问题。
请注意,由于模糊会同时向形状区域的内外扩展,因此必须调整 alpha 通道,使形状边缘处为零(完全透明),但随着远离边缘会很快变为完全不透明。这类 alpha 通道调整的一个示例,见于带透明度处理的 CLUT。这种调整至关重要,否则你非但不能淡化形状外部区域,反而会给形状外部区域添加一层半透明的阴影或光晕。基本上,就是某种此前被图像透明度隐藏起来的半透明"未定义颜色"。然而,模糊还有一个特别棘手的问题,那就是它也会把形状的轮廓一并柔化。例如…… |

  magick -size 100x60 xc: -draw 'polygon 5,5 50,30 5,55 95,30' \
          sharp_angles.gif

[IM Output]
如果你对这个特定形状进行模糊处理,会得到…… |

  magick sharp_angles.gif -blur 0x5  feather_blurred.gif

[IM Output]
请注意,遮罩的尖角比边缘被淡化得更严重。另外还要注意内角是如何被"填平"的,这在带有透明度的情况下,可能导致完全透明的像素变成半透明。也就是说,原本颜色未定义的像素实际上可能变得可见!如果对图像做阈值处理,就能更清楚地看到这一点。 |

  magick feather_blurred.gif  -threshold 50%  feather_blur_thres.gif

[IM Output]
这就是把"模糊"用作图像羽化手段所存在的问题。在处理手指、耳朵,以及双腿之间的区域这类东西时,这一点尤其值得关注。也就是说,它会影响附属物本身的形状,以及它们之间的空隙。如果图像带有卡通式的边界轮廓,那么对于"1 像素"的羽化来说,这个问题不算太大。但对于没有明确边界的真实照片来说,这就是一个真正的问题。一个恰当的解决方案,应该是找到某种度量,来衡量某一点距离形状边缘有多远,但要确保两条相邻很近的边缘不会把它们的效果叠加在一起。这种距离测量操作现已加入 IM,称为距离形态学。关于如何将其用于羽化处理的详情,请参见使用距离实现形状羽化


相关运算符

Basic image modifications
  -despeckle -enhance
  -noise  -spread -displace

  -median
    Set each channel color of the pixel to the median value of all all pixels
    within a given radius. (median = center most value of all values found,
    half on one side, half on the other).  This is a way of "de-speckling" an
    image  (such a dust in a scan).  But could distort edges, cause some color
    channel aburation, and remove thin lines.

    This filter is the best technique to use for removing Salt & Pepper
    noise, especially on gray scale images.

    It is suggested that a trim for a scan use a median filtered image for
    attempting to find the appropriate bounding box.

  -adaptive-sharpen  radius x sigma
    Adjust sharpening so that it is restricted to close to image edges
    as defined by edge detection.

    See forum discussion
      https://magick.imagemagick.org/viewtopic.php?f=1&t=10266

  -adaptive-blur   radius x sigma
    Blur images, except close to the edges as defined by an edge detection
    on the image.  Eg make the colors smoother, but don't destroy any
    sharp edges the image may have.

  -adaptive-resize
    Resize but attempt not to blur across sharp color changes