Есть ли что-нибудь в приложении imagemagick или gimp или другом совместимом с Linux, что может автоматически обнаруживать отдельные объекты на изображении и возвращать какое-либо местоположение объекта или хранить каждый объект в виде отдельного изображения?
Для других изображений, где объекты расположены на сетке, я успешно использовал оператор crop
в imagemagick, например. для сетки 3x3:
Ответ 1
Это можно сделать с помощью ImageMagick несколькими шагами. Изображение orignal называется meat.jpg:
convert meat.jpg -threshold 98% -morphology Dilate Octagon meat_0.png
![meat_0.png]()
convert meat_0.png text: | grep -m 1 black
Это дает вам расположение пикселей в области первой части мяса:
131,11: ( 0, 0, 0) #000000 black
Мы будем использовать это, чтобы покрасить первую часть в красный цвет, отделить красный канал, а затем создать и применить маску для первой части:
convert meat_0.png -fill red -bordercolor white \
-draw 'color 131,11 filltoborder' meat_1_red.png
convert meat_1_red.png -channel R -separate meat_1.png
convert meat_1_red.png meat_1.png -compose subtract \
-threshold 50% -composite -morphology Dilate Octagon \
-negate meat_1_mask.png
convert meat_1_mask.png meat.jpg -compose Screen -composite \
-trim meat_1.jpg
Полученный результат meat_1.jpg уже обрезается. Затем вы можете продолжить то же самое с meat_1.png вместо meat_0.png, генерируя meat_2.png в качестве основы для последовательных итераций "на лету". Возможно, это можно упростить и обернуть в оболочку script.
![meat_1.jpg]()
Ответ 2
Я бы занялся этим с помощью подхода "Connected Components Analysis" или "Image Segmentation", такого как...
Сначала разделите входное изображение на компоненты, указав минимальный размер (чтобы удалить меньшие куски) и разрешив 8-соединение (т.е. 8 соседних пикселей N, NE, E, SE, S, SW, W, NW считаются соседями), а не 4-связность, которая учитывает только N, E, S и W пикселей.
convert http://i.stack.imgur.com/T2VEJ.jpg -threshold 98% \
-morphology dilate octagon \
-define connected-components:area-threshold=800 \
-define connected-components:verbose=true \
-connected-components 8 -auto-level PNG8:lumps.png
который дает этот результат:
Objects (id: bounding-box centroid area mean-color):
0: 450x450+0+0 219.2,222.0 93240 srgb(255,255,255)
14: 127x98+111+158 173.0,209.4 9295 srgb(0,0,0)
29: 105x91+331+303 384.1,346.9 6205 srgb(0,0,0)
8: 99x75+340+85 388.9,124.6 5817 srgb(1,1,1)
15: 110x69+330+168 385.4,204.9 5640 srgb(1,1,1)
3: 114x62+212+12 270.0,42.4 5021 srgb(0,0,0)
4: 103x63+335+12 388.9,44.9 4783 srgb(0,0,0)
11: 99x61+13+134 61.5,159.1 4181 srgb(0,0,0)
37: 128x52+313+388 375.1,418.4 4058 srgb(0,0,0)
24: 95x62+24+256 69.6,285.7 4017 srgb(0,0,0)
2: 91x68+15+12 62.0,44.4 3965 srgb(0,0,0)
38: 91x50+10+391 55.1,417.0 3884 srgb(0,0,0)
12: 83x64+249+134 288.3,168.4 3761 srgb(0,0,0)
19: 119x62+320+240 385.4,268.4 3695 srgb(9,9,9)
25: 93x63+128+268 176.1,302.1 3612 srgb(0,0,0)
39: 96x49+111+391 158.1,416.0 3610 srgb(0,0,0)
31: 104x59+117+333 172.9,360.1 3493 srgb(0,0,0)
33: 88x55+238+335 279.3,364.5 3440 srgb(0,0,0)
26: 121x54+230+271 287.6,294.0 3431 srgb(8,8,8)
1: 98x61+109+11 159.7,40.0 3355 srgb(0,0,0)
40: 88x42+218+399 262.3,419.7 3321 srgb(0,0,0)
6: 87x61+115+70 157.9,100.1 3263 srgb(0,0,0)
30: 97x57+14+327 57.3,357.2 3237 srgb(55,55,55)
17: 84x57+13+207 53.1,232.2 2995 srgb(0,0,0)
5: 107x58+10+68 58.9,97.5 2988 srgb(0,0,0)
18: 77x60+237+212 273.0,243.0 2862 srgb(0,0,0)
7: 87x49+249+78 291.8,99.3 2703 srgb(9,9,9)
10: 82x51+178+109 222.8,133.9 2628 srgb(0,0,0)
Каждая строка соответствует отдельному компоненту или сегменту и показывает ширину и высоту ограничивающих полей для каждого компонента и их смещения в верхнем левом углу. Вы можете легко проанализировать это с помощью awk
и нарисовать указанные красные квадратики на изображении, чтобы это сделать:
![enter image description here]()
Выходное изображение называется lumps.png
, и оно выглядит так:
![enter image description here]()
и вы можете видеть, что каждый компонент (кусок мяса) имеет другой серый уровень, связанный с ним. Вы также можете проанализировать lumps.png
и извлечь отдельную маску для каждого куска мяса, например:
#!/bin/bash
# Extract every grey level, and montage together all that are not entirely black
rm mask_*png 2> /dev/null
mask=0
for v in {1..255}; do
((l=v*255))
((h=l+255))
mean=$(convert lumps.png -black-threshold "$l" -white-threshold "$h" -fill black -opaque white -threshold 1 -verbose info: | grep -c "mean: 0 ")
if [ "$mean" -eq 0 ]; then
convert lumps.png -black-threshold "$l" -white-threshold "$h" -fill black -opaque white -threshold 1 mask_$mask.png
((mask++))
fi
done
Это дает нам такие маски:
![enter image description here]()
и этот
![enter image description here]()
мы можем увидеть их все вместе, если мы сделаем это
montage -tile 4x mask_* montage_masks.png
![enter image description here]()
Если мы применим каждую из масок к входному изображению как непрозрачность и обрезаем результирующее изображение, мы останемся с отдельными кусками мяса
seg=0
rm segment_*png 2> /dev/null
for f in mask_*png; do
convert http://i.stack.imgur.com/T2VEJ.jpg $f -compose copy-opacity -composite -trim +repage segment_$seg.png
((seg++))
done
И они будут выглядеть так:
![enter image description here]()
и этот
![enter image description here]()
Или, мы можем собрать их все так:
montage -background white -tile 4x segment_* montage_results.png
![enter image description here]()
Холодный вопрос: -)