ImageMagick: Как получить пиксель от каждой области маски? - PullRequest
0 голосов
/ 24 января 2019

Как получить пиксель из каждой области маски с помощью ImageMagick ?

В настоящее время я могу получить центроид различных областей следующим образом:

enter image description here

convert circles.jpg -define connected-components:area-threshold=800 -define connected-components:verbose=true -connected-components 8 null: | sed '1,2d;$d' | awk '{print $1 $3}' > 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

enter image description here

Можно ли таким же образом получить список координат с одним пикселем для каждой области вместо центроида? Если да, то как?

=== РЕДАКТИРОВАТЬ ===

Моя цель на самом деле получить изображение маски для каждого компонента изображения ниже, так как координаты пикселя для каждой области позволят мне использовать опцию filltoborder , чтобы изолировать каждую область и получить маску для каждого компонента. enter image description here

Я также попробовал «другой подход к уровню серого» * ​​1039 * здесь , но ниже я получаю неожиданный результат, где у меня может быть разный серый для одного компонента. enter image description here

Ответы [ 2 ]

0 голосов
/ 25 января 2019

У вас есть пара проблем, которые вам нужно исправить, чтобы использовать подключенные компоненты в Imagemagick.

Во-первых, ваше изображение в формате JPG и, возможно, сглажено и, следовательно, в оттенках серого. (JPG - сжатие с потерями и изменяет значения). Таким образом, его нужно сделать двоичным, иначе вы получите слишком много регионов для того, что вы хотите сделать.

Во-вторых, вам нужно использовать -define connected-components: mean-color = true, чтобы выходное изображение выглядело как входное изображение и не имело шкалы яркости, соответствующие номерам идентификаторов регионов.

Например, если я сделаю следующее для вашего входного изображения, я получу много областей в оттенках серого.

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. Затем я бы зациклился на пороговом изображении, залил области заливки (предполагая, что они закрыты). ) после извлечения центроида и затем обрезки после извлечения ограничительной рамки.

Входной сигнал: enter image description here

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 $2,$3}'`)
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


Пороговое изображение: enter image description here

Три извлеченные заполненные области:

enter image description here

enter image description here

enter image description here

Что касается вашего второго изображения:

enter image description here

В этом случае вам не нужно их заполнять, поэтому просто используйте ограничивающий прямоугольник. Но вам нужно увеличить порог области, чтобы удалить небольшие пятна рядом с областью третьей строки / второго столбца. Поэтому здесь я бы сделал следующее:

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 $2}'`)
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:

enter image description here

enter image description here

enter image description here

0 голосов
/ 24 января 2019

Обновленный ответ

Ах, я вижу, проблема несколько сложнее, чем в первоначальном примере!Я экспериментировал с multicrop сценарием Фреда Вайнхауса, и, похоже, он неплохо справляется с этой задачей.

Я бы посоветовал вам связаться с Фредом (@ fmw42 на StackOverflow) или лично через еговеб-сайт для обсуждения пригодности для вашей проблемы и лицензирования.

Я запустил:

./multicrop blobs.png result.png

, а затем отобразил результаты на красном фоне:

magick montage -background red -geometry +10+10 result-*png montage.png

enter image description here

Положение и размеры различных полей обрезки показаны в результатах отладки скрипта:

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, вы будететакже получите маску результатов:

enter image description here

Оригинальный ответ

Если вы рисуете в найденных клетках, вы сразу увидите проблему!

enter image description here

Одним из решений может быть поиск gray(255), чтобы получить только белые области, поэтому вы должны сделать:

convert .. -connected-components ... | awk '/gray\(255\)/{print $1,$3}' > circles.txt
...