ImageMagick:如何从蒙版的每个区域获取像素?
ImageMagick: How to get a pixel from each area of a mask?
如何使用 ImageMagick 从蒙版的每个区域获取像素?
我目前可以通过这种方式获得不同区域的质心:
convert circles.jpg -define connected-components:area-threshold=800 -define connected-components:verbose=true -connected-components 8 null: | sed '1,2d;$d' | awk '{print }' > circles_centroids.txt
这给了我这些坐标:
3994:668.1,373.8
660:145.2,161.5
7301:278.1,547.5
2973:666.8,372.6
49:143.6,156.0
对了,为什么我只有三个圆,却得到五个坐标?
然后,我在每个坐标上画了一个红点:
while IFS=: read -r n xy ; do
mogrify -stroke red -strokewidth 3 -draw "stroke-linecap round line ${xy%,*},${xy#*,} ${xy%,*},$(bc<<<${xy#*,}+0.0001)" circles.jpg;
done < circles_centroids.txt
是否有可能以同样的方式获得每个区域只有一个像素的坐标列表,而不是质心?如果是,如何?
=== 编辑 ===
我的目标实际上是为下图的每个组件获取蒙版图像,每个区域的像素坐标将允许我使用 filltoborder 选项为了隔离每个区域并为每个组件获取掩码。
我也尝试了“不同的灰度级方法here,但我得到了下面意想不到的结果,其中我可以为一个组件设置不同的灰度。
更新答案
啊,我看这个问题比最初的例子要复杂一些!我用 Fred Weinhaus 的 multicrop
script 进行了试验,它似乎做得很好。
我建议您与 Fred(Whosebug 上的@fmw42)联系或通过他的网站私下讨论您的问题和许可的适用性。
我运行:
./multicrop blobs.png result.png
然后将结果合成到红色背景上:
magick montage -background red -geometry +10+10 result-*png montage.png
各种裁剪框的位置和大小显示在脚本的调试输出中:
width=2990; height=4440; wg=299; hg=444; num=8
299 444 0 none
598 444 0 none
897 444 0 none
1196 444 0 none
1495 444 0 none
1794 444 0 none
2093 444 0 none
2392 444 0 none
2691 444 0 none
299 888 1 red
Processing Image 0
Initial Crop Box: 339x639+221+509
598 888 0 none
897 888 1 red
Processing Image 1
Initial Crop Box: 381x577+742+511
1196 888 0 none
1495 888 1 red
Processing Image 2
Initial Crop Box: 461x624+1314+437
1794 888 0 none
2093 888 0 none
2392 888 0 none
2691 888 1 red
Processing Image 3
Initial Crop Box: 326x939+2468+428
299 1332 0 none
598 1332 0 none
897 1332 0 none
1196 1332 0 none
1495 1332 0 none
1794 1332 0 none
2093 1332 0 none
2392 1332 0 none
2691 1332 0 none
299 1776 0 none
598 1776 0 none
897 1776 0 none
1196 1776 1 red
Processing Image 4
Initial Crop Box: 483x648+896+1374
1495 1776 0 none
1794 1776 1 red
Processing Image 5
Initial Crop Box: 536x837+1685+1218
2093 1776 0 none
2392 1776 0 none
2691 1776 0 none
299 2220 0 none
598 2220 0 none
897 2220 0 none
1196 2220 0 none
1495 2220 0 none
1794 2220 1 red
Processing Image 6
Initial Crop Box: 422x523+1578+2161
2093 2220 0 none
2392 2220 0 none
2691 2220 1 red
Processing Image 7
Initial Crop Box: 342x568+2432+2105
299 2664 0 none
598 2664 0 none
897 2664 0 none
1196 2664 0 none
1495 2664 0 none
1794 2664 0 none
2093 2664 0 none
2392 2664 0 none
2691 2664 0 none
299 3108 0 none
598 3108 0 none
897 3108 0 none
1196 3108 1 red
Processing Image 8
Initial Crop Box: 325x555+931+2784
1495 3108 0 none
1794 3108 1 red
Processing Image 9
Initial Crop Box: 426x528+1621+2820
2093 3108 0 none
2392 3108 0 none
2691 3108 1 red
Processing Image 10
Initial Crop Box: 305x549+2432+2781
299 3552 1 red
Processing Image 11
Initial Crop Box: 336x623+256+3413
598 3552 0 none
897 3552 0 none
1196 3552 1 red
Processing Image 12
Initial Crop Box: 381x617+934+3410
1495 3552 0 none
1794 3552 0 none
2093 3552 0 none
2392 3552 0 none
2691 3552 0 none
299 3996 0 none
598 3996 0 none
897 3996 0 none
1196 3996 0 none
1495 3996 0 none
1794 3996 0 none
2093 3996 0 none
2392 3996 0 none
2691 3996 0 none
如果您 运行 使用 -m
选项,您还将获得结果掩码:
原答案
如果你把它找到的方框画进去,你马上就会发现问题!
一种解决方案可能是寻找 gray(255)
以仅获得白色区域,因此您可以这样做:
convert .. -connected-components ... | awk '/gray\(255\)/{print ,}' > circles.txt
您有几个问题需要解决才能在 Imagemagick 中使用连接组件。
首先,您的图像是 JPG 图像,可能经过抗锯齿处理,因此是灰度图像。 (JPG 是有损压缩并更改值)。因此需要将其制成二进制文件,否则您将获得太多的区域来执行您想要执行的操作。
其次,您需要使用 -define connected-components:mean-color=true 以使输出图像看起来像输入图像,而不是灰度对应于区域 ID 号。
例如,如果我对您的输入图像执行以下操作,我会得到很多灰度区域。
convert image.jpg \
-define connected-components:verbose=true \
-define connected-components:area-threshold=0 \
-define connected-components:mean-color=true \
-connected-components 4 \
null:
0: 818x687+0+0 420.4,339.2 393850 gray(255)
6405: 213x232+560+260 667.8,373.2 38867 gray(255)
1066: 212x197+46+61 145.7,161.0 32689 gray(255)
11470: 197x189+180+453 278.4,547.6 27921 gray(255)
4764: 259x279+536+236 667.8,372.1 14056 gray(0)
86: 258x261+22+21 144.0,156.7 13604 gray(0)
10418: 241x236+159+430 278.8,546.4 12060 gray(0)
8450: 4x40+538+304 539.5,323.5 160 gray(2)
14378: 2x57+158+496 158.5,523.8 113 gray(3)
10247: 31x6+260+425 278.7,427.6 98 gray(255)
5996: 32x5+106+257 121.2,259.2 89 gray(255)
15035: 43x3+656+514 676.8,515.5 85 gray(0)
14031: 41x4+659+490 678.3,492.3 81 gray(255)
9942: 2x41+795+407 795.5,427.2 81 gray(4)
3152: 2x32+22+144 22.5,159.5 64 gray(3)
11234: 29x6+264+449 279.1,451.8 64 gray(0)
15824: 4x16+378+568 379.5,575.5 64 gray(2)
284: 28x5+127+33 140.6,35.3 61 gray(255)
14375: 3x58+153+496 154.9,525.4 60 gray(254)
14374: 1x56+154+496 154.0,523.5 56 gray(252)
14377: 1x56+157+496 157.0,523.5 56 gray(0)
14376: 1x56+156+496 156.0,523.5 56 gray(252)
7795: 28x3+101+282 114.5,283.5 54 gray(0)
...
在上面的完整列表中,有超过3个黑色区域。
但是如果我将阈值设置为 50% 以使图像成为纯黑白图像并另存为 PNG,那么我会得到
convert image.jpg -threshold 50% -type bilevel \
-define connected-components:verbose=true \
-define connected-components:area-threshold=0 \
-define connected-components:mean-color=true \
-connected-components 4 \
null:
Objects (id: bounding-box centroid area mean-color):
0: 818x687+0+0 419.2,339.3 401926 gray(255)
4: 215x236+560+258 668.0,373.6 41506 gray(255)
2: 215x202+44+60 145.1,161.4 34718 gray(255)
6: 197x192+180+452 278.1,547.3 29700 gray(255)
3: 262x283+536+234 666.8,372.5 19261 gray(0)
1: 262x265+20+20 143.2,155.8 18388 gray(0)
5: 243x239+157+428 277.3,546.1 16467 gray(0)
请注意,现在只有 3 个灰色 (0),即黑色区域。如果有一些小黑点,你可以增加面积阈值来去除它们。
现在要提取您的区域,我将执行以下操作。我会提取边界框和质心,它们之间有一个下划线,然后放入一个数组中。我会将阈值图像保存为连接组件的输出(这可以通过使用 -define connected-components:mean-color=true 来完成。然后我将遍历阈值图像,洪水填充区域(假设它们是封闭的) 提取质心后提取边界框再裁剪
输入:
box_cent_Arr=(`convert image.jpg -threshold 50% -type bilevel \
-define connected-components:verbose=true \
-define connected-components:mean-color=true \
-connected-components 4 \
image_t50.png | grep "gray(0)" | awk 'BEGIN {OFS="_"} {print ,}'`)
num=${#box_cent_Arr[*]}
for ((i=0; i<num; i++)); do
bbox=`echo "${box_cent_Arr[$i]}" | cut -d\_ -f1`
centroid=`echo "${box_cent_Arr[$i]}" | cut -d\_ -f2`
convert image_t50.png -fill black -draw "color $centroid floodfill" -alpha off -crop $bbox +repage image_$i.png
done
阈值图像:
三个提取的填充区域:
关于你的第二张图片:
在这种情况下,您不需要填充它们,因此只需使用边界框即可。但是您需要增加 area-threshold 以删除第三个 row/second 列区域旁边的小点。所以在这里我会做以下事情:
bboxArr=(`convert image.png -threshold 50% -type bilevel \
-define connected-components:verbose=true \
-define connected-components:area-threshold=1000 \
-define connected-components:mean-color=true \
-connected-components 4 \
image_t50.png | grep "gray(0)" | awk '{print }'`)
num=${#bboxArr[*]}
for ((i=0; i<num; i++)); do
bbox=`echo "${bboxArr[$i]}" | cut -d\_ -f1`
convert image_t50.png -crop $bbox +repage image_$i.png
done
结果是提取了22个区域(我编号为0到21)。例如,这里是前 3 个:
如何使用 ImageMagick 从蒙版的每个区域获取像素?
我目前可以通过这种方式获得不同区域的质心:
convert circles.jpg -define connected-components:area-threshold=800 -define connected-components:verbose=true -connected-components 8 null: | sed '1,2d;$d' | awk '{print }' > circles_centroids.txt
这给了我这些坐标:
3994:668.1,373.8
660:145.2,161.5
7301:278.1,547.5
2973:666.8,372.6
49:143.6,156.0
对了,为什么我只有三个圆,却得到五个坐标?
然后,我在每个坐标上画了一个红点:
while IFS=: read -r n xy ; do
mogrify -stroke red -strokewidth 3 -draw "stroke-linecap round line ${xy%,*},${xy#*,} ${xy%,*},$(bc<<<${xy#*,}+0.0001)" circles.jpg;
done < circles_centroids.txt
是否有可能以同样的方式获得每个区域只有一个像素的坐标列表,而不是质心?如果是,如何?
=== 编辑 ===
我的目标实际上是为下图的每个组件获取蒙版图像,每个区域的像素坐标将允许我使用 filltoborder 选项为了隔离每个区域并为每个组件获取掩码。
我也尝试了“不同的灰度级方法here,但我得到了下面意想不到的结果,其中我可以为一个组件设置不同的灰度。
更新答案
啊,我看这个问题比最初的例子要复杂一些!我用 Fred Weinhaus 的 multicrop
script 进行了试验,它似乎做得很好。
我建议您与 Fred(Whosebug 上的@fmw42)联系或通过他的网站私下讨论您的问题和许可的适用性。
我运行:
./multicrop blobs.png result.png
然后将结果合成到红色背景上:
magick montage -background red -geometry +10+10 result-*png montage.png
各种裁剪框的位置和大小显示在脚本的调试输出中:
width=2990; height=4440; wg=299; hg=444; num=8
299 444 0 none
598 444 0 none
897 444 0 none
1196 444 0 none
1495 444 0 none
1794 444 0 none
2093 444 0 none
2392 444 0 none
2691 444 0 none
299 888 1 red
Processing Image 0
Initial Crop Box: 339x639+221+509
598 888 0 none
897 888 1 red
Processing Image 1
Initial Crop Box: 381x577+742+511
1196 888 0 none
1495 888 1 red
Processing Image 2
Initial Crop Box: 461x624+1314+437
1794 888 0 none
2093 888 0 none
2392 888 0 none
2691 888 1 red
Processing Image 3
Initial Crop Box: 326x939+2468+428
299 1332 0 none
598 1332 0 none
897 1332 0 none
1196 1332 0 none
1495 1332 0 none
1794 1332 0 none
2093 1332 0 none
2392 1332 0 none
2691 1332 0 none
299 1776 0 none
598 1776 0 none
897 1776 0 none
1196 1776 1 red
Processing Image 4
Initial Crop Box: 483x648+896+1374
1495 1776 0 none
1794 1776 1 red
Processing Image 5
Initial Crop Box: 536x837+1685+1218
2093 1776 0 none
2392 1776 0 none
2691 1776 0 none
299 2220 0 none
598 2220 0 none
897 2220 0 none
1196 2220 0 none
1495 2220 0 none
1794 2220 1 red
Processing Image 6
Initial Crop Box: 422x523+1578+2161
2093 2220 0 none
2392 2220 0 none
2691 2220 1 red
Processing Image 7
Initial Crop Box: 342x568+2432+2105
299 2664 0 none
598 2664 0 none
897 2664 0 none
1196 2664 0 none
1495 2664 0 none
1794 2664 0 none
2093 2664 0 none
2392 2664 0 none
2691 2664 0 none
299 3108 0 none
598 3108 0 none
897 3108 0 none
1196 3108 1 red
Processing Image 8
Initial Crop Box: 325x555+931+2784
1495 3108 0 none
1794 3108 1 red
Processing Image 9
Initial Crop Box: 426x528+1621+2820
2093 3108 0 none
2392 3108 0 none
2691 3108 1 red
Processing Image 10
Initial Crop Box: 305x549+2432+2781
299 3552 1 red
Processing Image 11
Initial Crop Box: 336x623+256+3413
598 3552 0 none
897 3552 0 none
1196 3552 1 red
Processing Image 12
Initial Crop Box: 381x617+934+3410
1495 3552 0 none
1794 3552 0 none
2093 3552 0 none
2392 3552 0 none
2691 3552 0 none
299 3996 0 none
598 3996 0 none
897 3996 0 none
1196 3996 0 none
1495 3996 0 none
1794 3996 0 none
2093 3996 0 none
2392 3996 0 none
2691 3996 0 none
如果您 运行 使用 -m
选项,您还将获得结果掩码:
原答案
如果你把它找到的方框画进去,你马上就会发现问题!
一种解决方案可能是寻找 gray(255)
以仅获得白色区域,因此您可以这样做:
convert .. -connected-components ... | awk '/gray\(255\)/{print ,}' > circles.txt
您有几个问题需要解决才能在 Imagemagick 中使用连接组件。
首先,您的图像是 JPG 图像,可能经过抗锯齿处理,因此是灰度图像。 (JPG 是有损压缩并更改值)。因此需要将其制成二进制文件,否则您将获得太多的区域来执行您想要执行的操作。
其次,您需要使用 -define connected-components:mean-color=true 以使输出图像看起来像输入图像,而不是灰度对应于区域 ID 号。
例如,如果我对您的输入图像执行以下操作,我会得到很多灰度区域。
convert image.jpg \
-define connected-components:verbose=true \
-define connected-components:area-threshold=0 \
-define connected-components:mean-color=true \
-connected-components 4 \
null:
0: 818x687+0+0 420.4,339.2 393850 gray(255)
6405: 213x232+560+260 667.8,373.2 38867 gray(255)
1066: 212x197+46+61 145.7,161.0 32689 gray(255)
11470: 197x189+180+453 278.4,547.6 27921 gray(255)
4764: 259x279+536+236 667.8,372.1 14056 gray(0)
86: 258x261+22+21 144.0,156.7 13604 gray(0)
10418: 241x236+159+430 278.8,546.4 12060 gray(0)
8450: 4x40+538+304 539.5,323.5 160 gray(2)
14378: 2x57+158+496 158.5,523.8 113 gray(3)
10247: 31x6+260+425 278.7,427.6 98 gray(255)
5996: 32x5+106+257 121.2,259.2 89 gray(255)
15035: 43x3+656+514 676.8,515.5 85 gray(0)
14031: 41x4+659+490 678.3,492.3 81 gray(255)
9942: 2x41+795+407 795.5,427.2 81 gray(4)
3152: 2x32+22+144 22.5,159.5 64 gray(3)
11234: 29x6+264+449 279.1,451.8 64 gray(0)
15824: 4x16+378+568 379.5,575.5 64 gray(2)
284: 28x5+127+33 140.6,35.3 61 gray(255)
14375: 3x58+153+496 154.9,525.4 60 gray(254)
14374: 1x56+154+496 154.0,523.5 56 gray(252)
14377: 1x56+157+496 157.0,523.5 56 gray(0)
14376: 1x56+156+496 156.0,523.5 56 gray(252)
7795: 28x3+101+282 114.5,283.5 54 gray(0)
...
在上面的完整列表中,有超过3个黑色区域。
但是如果我将阈值设置为 50% 以使图像成为纯黑白图像并另存为 PNG,那么我会得到
convert image.jpg -threshold 50% -type bilevel \
-define connected-components:verbose=true \
-define connected-components:area-threshold=0 \
-define connected-components:mean-color=true \
-connected-components 4 \
null:
Objects (id: bounding-box centroid area mean-color):
0: 818x687+0+0 419.2,339.3 401926 gray(255)
4: 215x236+560+258 668.0,373.6 41506 gray(255)
2: 215x202+44+60 145.1,161.4 34718 gray(255)
6: 197x192+180+452 278.1,547.3 29700 gray(255)
3: 262x283+536+234 666.8,372.5 19261 gray(0)
1: 262x265+20+20 143.2,155.8 18388 gray(0)
5: 243x239+157+428 277.3,546.1 16467 gray(0)
请注意,现在只有 3 个灰色 (0),即黑色区域。如果有一些小黑点,你可以增加面积阈值来去除它们。
现在要提取您的区域,我将执行以下操作。我会提取边界框和质心,它们之间有一个下划线,然后放入一个数组中。我会将阈值图像保存为连接组件的输出(这可以通过使用 -define connected-components:mean-color=true 来完成。然后我将遍历阈值图像,洪水填充区域(假设它们是封闭的) 提取质心后提取边界框再裁剪
输入:
box_cent_Arr=(`convert image.jpg -threshold 50% -type bilevel \
-define connected-components:verbose=true \
-define connected-components:mean-color=true \
-connected-components 4 \
image_t50.png | grep "gray(0)" | awk 'BEGIN {OFS="_"} {print ,}'`)
num=${#box_cent_Arr[*]}
for ((i=0; i<num; i++)); do
bbox=`echo "${box_cent_Arr[$i]}" | cut -d\_ -f1`
centroid=`echo "${box_cent_Arr[$i]}" | cut -d\_ -f2`
convert image_t50.png -fill black -draw "color $centroid floodfill" -alpha off -crop $bbox +repage image_$i.png
done
阈值图像:
三个提取的填充区域:
关于你的第二张图片:
在这种情况下,您不需要填充它们,因此只需使用边界框即可。但是您需要增加 area-threshold 以删除第三个 row/second 列区域旁边的小点。所以在这里我会做以下事情:
bboxArr=(`convert image.png -threshold 50% -type bilevel \
-define connected-components:verbose=true \
-define connected-components:area-threshold=1000 \
-define connected-components:mean-color=true \
-connected-components 4 \
image_t50.png | grep "gray(0)" | awk '{print }'`)
num=${#bboxArr[*]}
for ((i=0; i<num; i++)); do
bbox=`echo "${bboxArr[$i]}" | cut -d\_ -f1`
convert image_t50.png -crop $bbox +repage image_$i.png
done
结果是提取了22个区域(我编号为0到21)。例如,这里是前 3 个: