Извлечение окон/подмассивов вдоль бинарной круговой линии/пути с помощью view_as_windows из skimage

У меня есть 8-битное бинарное изображение, которое показывает контур круга. Контур имеет ширину всего 1 пиксель. Использование функции view_as_windows позволяет мне генерировать меньшие массивы или окна входного массива, как это изображение, с соседними перекрывающимися окнами. Размер этого изображения 250250.

from skimage.io import imread
from skimage.util import view_as_windows

fname = "C:\\Users\\Username\\Desktop\\Circle.tif"

array = imread(fname)
window_shape = (50, 50)
step = 20

new_array = view_as_windows(array, window_shape, step=step)

Это дает мне 1111 перекрывающихся окон. Однако я хочу извлечь только окна вдоль линии круга, чтобы потом снова собрать этот объект. Строка каждого окна должна располагаться по центру или таким образом, чтобы у меня был доступ к информации прямо под кругом.

Это то, что я пробовал до сих пор:

Сначала я заменил значения (0) и (255) на (1) и (0) соответственно. Таким образом, математика немного упрощается.

array[array==0] = 1
array[array==255] = 0

Затем я перебрал окна в new_array. В данном случае по первым двум измерениям. new_array.shape это (11, 11, 50, 50)

for j in range(new_array.shape[0]):
    for i in range(new_array.shape[1]):
        Window = new_array[j, i]
        SliceOfWindow = Slice[20:30, 20:30]
        sumAxis0 = np.sum(Slice, axis=0)
        sumSlice = np.sum(sumAxis0)
        if sumSlice >= SliceOfWindow.shape[0]
            imsave(...) 

Я создал меньший фрагмент формы = (10, 10) внутри каждого окна, поместив его в центр. Если сумма каждого среза >= длина среза, я сохранил этот массив как изображение.

Можно ли это сделать более точным способом? Есть ли способ добиться лучших результатов (лучшие окна!)?


person Johannes Schmidt    schedule 20.03.2018    source источник
comment
Если у вас есть бинарная маска, вы можете использовать numpy.where, чтобы найти координаты для этих пикселей, и вручную извлечь окна посредством нарезки. Кроме того, вы можете подогнать параметры к кругу (центр + радиус), а затем использовать skimage.draw.circle_perimeter для создания координат координат для вас.   -  person Stefan van der Walt    schedule 20.03.2018
comment
Что вы хотите, чтобы произошло, если круг находится близко к краю изображения, где окно выходит за край?   -  person Eric    schedule 20.03.2018
comment
Я должен был упомянуть, что получить координаты этих пикселей не проблема. И да, тогда я мог бы легко извлечь окна каждого пикселя этой строки. Тем не менее, я хочу иметь, например. для каждого 10-го пикселя строки окно вокруг этого пикселя. Однако для этого потребуется список координат в правильном порядке, начальная и конечная точки. На самом деле это была моя первоначальная идея, но я не мог найти способ составить список с координатами, описывающий ход линии. Круг — это только пример. Позже формы будут больше похожи на эллипсы.   -  person Johannes Schmidt    schedule 20.03.2018
comment
Эта функция из skimage не создает окна, выходящие за край, но, кажется, я понимаю, что вы имеете в виду. Моя идея заключалась в том, чтобы обрабатывать края по-разному. Для окон на краю я бы только проверил, есть ли в них какая-либо информация о круге (без центрального среза). Если да, то я бы их взял. Вероятно, есть лучшие решения. Я надеюсь, что кто-то может помочь.   -  person Johannes Schmidt    schedule 20.03.2018


Ответы (1)


Для выпуклой кривой вы можете использовать полярные координаты и отсортировать краевые пиксели по их углу через numpy.argsort и numpy.arctan2.

Демо

from skimage import io
import matplotlib.pyplot as plt
import numpy as np

img = io.imread('https://i.stack.imgur.com/r3D6I.png')

# Arbitrary point inside the curve
row_cen, col_cen = 125, 125

# Coordinates of the edge pixels
row, col = np.nonzero(img == 0)

# Put the origin on the lower left corner
x = col - col_cen
y = -(row - row_cen)

# Indices of the centers of the windows
step = 60
idx = np.argsort(np.arctan2(y, x))[::step]

windows = np.zeros_like(img)
size = 15
for _, n in enumerate(idx):
    windows[row[n] - size:row[n] + size, col[n] - size:col[n] + size] = 255

plt.imshow(windows, cmap='gray')
for i, n in enumerate(idx):
    plt.text(col[n], row[n], i, fontsize='14',
             horizontalalignment='center', 
             verticalalignment='center')
plt.show()

Край и набор окон на краю

person Tonechas    schedule 21.03.2018
comment
Мне удалось найти решение самостоятельно, и завтра я предоставлю код. Я также внимательно рассмотрю ваш подход. Большое спасибо за подробный ответ. - person Johannes Schmidt; 21.03.2018