检测 mini_magick 中的透明像素

Detecting Transparent Pixels in mini_magick

我有一张尺寸已知的图像,比方说 8x8。我需要使用 MiniMagick 明确知道图像外边缘像素周围是否有 any 非透明像素。我也很想知道如何在 ImageMagick 中执行此操作,如果可能的话(为了我自己的理解),但我现在真的只需要在 MiniMagick 中执行此操作。

如果有人甚至有一半的答案,请随时在这个问题上发表意见。我也愿意玩弄概念。谢谢!

我会这样处理。用完全透明的虚无填充内部 non-edge 像素 - 一个洞,如果你愿意的话。那么图像中残留的任何不透明度都必须是边缘像素中某些不透明度的结果。因此,如果我们在任何背景上覆盖带有孔的 newly-created 图像并导致背景发生变化,我们可以推断出新图像中必须有 non-transparent 像素,因此在新图像的边缘,因为我们已经确保中间没有 non-transparent 像素。听起来比实际更难!

#!/bin/bash
# First get dimensions of inner "hole", it's the width minus 2 and height minus 2
# so for a 16x16 image, it will be 14x14
inner=$(convert input.png -format "%[fx:w-2]x%[fx:h-2]" info:)

# Now punch a fully transparent hole in the input image
convert input.png                                      \ 
        -size $inner xc:none -alpha set -geometry +1+1 \
        -compose copy -composite tmp.png

input.png

tmp.png

所以,现在我们在白色背景上叠加一个有洞的图像,然后将结果与纯白色图像进行比较,并计算有多少像素不同。

convert -size 16x16 xc:white tmp.png -composite \
        xc:white -metric AE -compare -format "%[distortion]" info:
60

顶部有 60 => 16 个,底部有 16 个,每个垂直边缘有 14 个。如果我们用完全透明的原始图像重复练习,答案将为零。所以你需要的测试是错误度量(不同像素的数量)是否是 non-zero.

实际上,在 shell 中,由于您的图像很小,您可能只需将图像转换为文本,然后让 awk 找到边缘像素,如下所示:

# Create opaque image
convert -size 16x16 xc:red PNG32:input.png

# Find pixels in row 0, row 15, col 0, col 15 where transparency (last digit before closing paren) is non-zero
convert input.png txt: | awk '/,0:|,15:|^0,|^15,/ && !/,0)/'
0,0: (255,0,0,1)  #FF0000  red
1,0: (255,0,0,1)  #FF0000  red
2,0: (255,0,0,1)  #FF0000  red
3,0: (255,0,0,1)  #FF0000  red
4,0: (255,0,0,1)  #FF0000  red
5,0: (255,0,0,1)  #FF0000  red
6,0: (255,0,0,1)  #FF0000  red
7,0: (255,0,0,1)  #FF0000  red
8,0: (255,0,0,1)  #FF0000  red
9,0: (255,0,0,1)  #FF0000  red
10,0: (255,0,0,1)  #FF0000  red
11,0: (255,0,0,1)  #FF0000  red
12,0: (255,0,0,1)  #FF0000  red
13,0: (255,0,0,1)  #FF0000  red
14,0: (255,0,0,1)  #FF0000  red
15,0: (255,0,0,1)  #FF0000  red
0,1: (255,0,0,1)  #FF0000  red
15,1: (255,0,0,1)  #FF0000  red
0,2: (255,0,0,1)  #FF0000  red
15,2: (255,0,0,1)  #FF0000  red
0,3: (255,0,0,1)  #FF0000  red
15,3: (255,0,0,1)  #FF0000  red
0,4: (255,0,0,1)  #FF0000  red
15,4: (255,0,0,1)  #FF0000  red
0,5: (255,0,0,1)  #FF0000  red
15,5: (255,0,0,1)  #FF0000  red
0,6: (255,0,0,1)  #FF0000  red
15,6: (255,0,0,1)  #FF0000  red
0,7: (255,0,0,1)  #FF0000  red
15,7: (255,0,0,1)  #FF0000  red
0,8: (255,0,0,1)  #FF0000  red
15,8: (255,0,0,1)  #FF0000  red
0,9: (255,0,0,1)  #FF0000  red
15,9: (255,0,0,1)  #FF0000  red
0,10: (255,0,0,1)  #FF0000  red
15,10: (255,0,0,1)  #FF0000  red
0,11: (255,0,0,1)  #FF0000  red
15,11: (255,0,0,1)  #FF0000  red
0,12: (255,0,0,1)  #FF0000  red
15,12: (255,0,0,1)  #FF0000  red
0,13: (255,0,0,1)  #FF0000  red
15,13: (255,0,0,1)  #FF0000  red
0,14: (255,0,0,1)  #FF0000  red
15,14: (255,0,0,1)  #FF0000  red
0,15: (255,0,0,1)  #FF0000  red
1,15: (255,0,0,1)  #FF0000  red
2,15: (255,0,0,1)  #FF0000  red
3,15: (255,0,0,1)  #FF0000  red
4,15: (255,0,0,1)  #FF0000  red
5,15: (255,0,0,1)  #FF0000  red
6,15: (255,0,0,1)  #FF0000  red
7,15: (255,0,0,1)  #FF0000  red
8,15: (255,0,0,1)  #FF0000  red
9,15: (255,0,0,1)  #FF0000  red
10,15: (255,0,0,1)  #FF0000  red
11,15: (255,0,0,1)  #FF0000  red
12,15: (255,0,0,1)  #FF0000  red
13,15: (255,0,0,1)  #FF0000  red
14,15: (255,0,0,1)  #FF0000  red
15,15: (255,0,0,1)  #FF0000  red

# Now create fully transparent image
convert -size 16x16 xc:none PNG32:input.png

# Find any non-opaque pixels
convert input.png txt: | awk '/,0:|,15:|^0,|^15,/ && !/,0)/'

# None

如果你不喜欢 hard-coding 把 15 变成 awk 就像我做的那样,你当然可以从convert 的输出如下所示:

# ImageMagick pixel enumeration: 16,16,255,srgba

并使用最后一个 row/col 沿着这些行创建搜索模式 - 如果您不知道该怎么做,请询问:

awk 'NR==1                  {... pattern="0,|,0:..." }   # First line, get dimensions, make pattern
     [=14=] ~ pattern && !/,0)/ {print "..."; exit}'         # Find non-transparent edge pixels