Как вернуть Scikit-изображение Сегментация в 3D массив? - PullRequest
1 голос
/ 12 июня 2019

У меня есть четырехполосные растровые изображения (которые представляют собой 3D-массив), и я хотел бы сегментировать изображение по полосам. Форма этого растра (после преобразования в трехмерный массив): (12200, 7200, 4).

Я пытался использовать scikit-image:

skimage.segmentation.slic(image[, …])

и

skimage.segmentation.quickshift(image[, …])

и в результате получается только двумерный массив (= 1 растр полосы), имеющий форму (12200, 7200).

Команда, казалось, выровняла изображение, и я не могу найти ничего в их документации по этому вопросу.

Вот что я пробовал:

from __future__ import print_function
from osgeo import gdal
import numpy as np
from skimage import io
from skimage.segmentation import felzenszwalb, slic, quickshift
from skimage.segmentation import mark_boundaries
from skimage.util import img_as_float

# The input 4-band TSX image
image = r'raw_img/09K0153_20140501T084638_TSX.tif'

#convert image to Np array
img = io.imread(image, as_gray=False, plugin="gdal")

# Run the quick shift segmentation
segments = quickshift(img, kernel_size=3, convert2lab=False, max_dist=6, ratio=0.5)

Как мне получить результат трехмерной сегментации (что означает: ввод: трехмерный массив, вывод: трехмерный массив), используя Scikit-изображение вместо 2D? Или есть другая библиотека, которую я могу использовать для этой цели?

Ответы [ 2 ]

0 голосов
/ 12 июня 2019

Как получить результат 3D-сегментации (что означает, ввод: 3D-массив, вывод: 3D-массив), используя Scikit-изображение вместо 2D?

Давайте посмотрим, что этона самом деле означает иметь результат 3D-сегментации в виде 3D-массива.Давайте рассмотрим трехканальное изображение, показанное ниже.Интересующая нас сегментация показана синей пунктирной линией.

enter image description here

Предположим сейчас, что существует некоторый алгоритм, который будет сегментировать сегмент с синей пунктирной линией.для нас.Но тогда как изобразить синий пунктирный сегмент?Если бы это был квадрат прямоугольной формы, мы могли бы представить сегмент в виде трехмерного массива (3D-среза исходного изображения).Но если изображение имеет произвольную форму, то как нам это сделать?Информация о сегментации фиксируется с помощью маски.Создается двумерный массив маски, соответствующий размеру изображения.Давайте предположим, что у нас есть только один сегмент в нашем изображении.В таком случае все пиксели внутри сегмента изображения отмечены как 1 в соответствующем изображении маски.Это логическая маска (1 сегмент).Если есть несколько сегментов, то пиксели в каждом сегменте как уникальное число.

По этой причине вы видите, что результатом quickshift является двумерный массив с таким же размером изображения.Результатом является маска, местоположения в маске, имеющие одинаковые значения, соответствуют сегменту, который будет представлять срез (который будет одинаковым для всех каналов).Тем не менее, вы не сможете представить фрагмент, используя массив NumPy, если он имеет произвольную форму.

Просто добавить, что это плохая идея - запускать quickshift одного канала за раз, потому что он использует 5D пространство, состоящее из информации о цвете и расположения изображения 2 для сегментации.Использование его на 1 канале за раз даст вам плохие результаты сегментации.

0 голосов
/ 12 июня 2019

добро пожаловать в StackOverflow.

Действительно, алгоритм quickshift возвращает только одну (x, y) маску. Вы можете найти реализацию здесь . Если вы дадите алгоритму более одного канала, он будет учитывать все каналы для вычисления маски сегментации.

Если вы хотите применить алгоритм независимо к каждому каналу, вы должны сделать это итеративно, например, с помощью следующего кода

from __future__ import print_function
from osgeo import gdal
import numpy as np
from skimage import io
from skimage.segmentation import felzenszwalb, slic, quickshift
from skimage.segmentation import mark_boundaries
from skimage.util import img_as_float

# The input 4-band TSX image
image = r'raw_img/09K0153_20140501T084638_TSX.tif'

#convert image to Np array
img = io.imread(image, as_gray=False, plugin="gdal")

# Instantiate a segments array of same shape than image
segments = np.zeros(img.shape)
Nc = img.shape[-1] # number of channels

# Run the quick shift segmentation for each channel
for c in range(Nc):
    segments[:,:,c] = quickshift(img[:,:,c], kernel_size=3, convert2lab=False, max_dist=6, ratio=0.5)
...