Як буферувати растрові пікселі за їх значеннями?


28

Пікселі ліворуч представляють місця дерева та пов’язані з ними радіуси крони (тобто значення пікселів у межах від 2 до 5). Я хотів би захистити ці растрові пікселі за значенням радіуса корони. Зображення праворуч - це те, що я сподіваюся досягти, використовуючи лише методи растрової обробки .

Я б спочатку думав використовувати кругову фокусну суму в ArcGIS, хоча настройка сусідства є фіксованим значенням, яке б не враховувало радіус корони змінної величини.

Який хороший метод "буферизації" пікселів за їх значеннями?

введіть тут опис зображення


2
Ви намагалися перетворити растр у точки, а потім буфер за полем, а потім перетворити назад у растр?

2
Це допомагає усвідомити, що це не локальна операція, оскільки ця нелокальність показує, що існують властиві обмеження щодо того, як можна здійснити розрахунок. Наприклад, ваш вихід радикально зміниться майже скрізь, якби лише один ізольований піксель на вході змінився на велике значення. Таким чином, якщо ви знаєте обмеження вхідних значень, то будь ласка, поділіться ними, оскільки це може призвести до вдосконалених рішень. Наприклад, чи всі вхідні значення завжди будуть в наборі {2,3,4}?
whuber

@Dan Patterson Саме тому я придумав зображення праворуч. Однак я намагаюся взагалі уникати векторних операцій і уникати цих кроків.
Аарон

2
@whuber Цей набір даних представляє дерева зі змінним діаметром крони. Враховуючи це, вимірювання радіусу крони дерева може реально змінюватись від 1-10. Я також повинен додати, що буферний вихід повинен бути лише 0 на відсутність корони та 1 на наявність крони.
Аарон

1
Добре, дякую. Схоже, ви створили приклад виведення, об'єднавши 3-буфери точок зі значенням 3, 4-буфери точок зі значенням 4 та 5-буфери точок зі значенням 5. (Ви, здається, забули обробити очки зі значенням 2.) Цей процес не тільки відповідає на ваше запитання, але (я вважаю) це найпростіше рішення з використанням інструментів, доступних у Spatial Analyst.
whuber

Відповіді:


14

Ось чисте растрове рішення щодо Python 2.7використання numpyта scipy:

import numpy as np
from scipy import ndimage
import matplotlib.pyplot as plt

#create tree location matrix with values indicating crown radius
A = np.zeros((120,320))
A[60,40] = 1
A[60,80] = 2
A[60,120] = 3
A[60,160] = 4
A[60,200] = 5
A[60,240] = 6
A[60,280] = 7

#plot tree locations
fig = plt.figure()
plt.imshow(A, interpolation='none')
plt.colorbar()

#find unique values
unique_vals = np.unique(A)
unique_vals = unique_vals[unique_vals > 0]

# create circular kernel
def createKernel(radius):
    kernel = np.zeros((2*radius+1, 2*radius+1))
    y,x = np.ogrid[-radius:radius+1, -radius:radius+1]
    mask = x**2 + y**2 <= radius**2
    kernel[mask] = 1
    return kernel

#apply binary dilation sequentially to each unique crown radius value 
C = np.zeros(A.shape).astype(bool)   
for k, radius in enumerate(unique_vals):  
    B = ndimage.morphology.binary_dilation(A == unique_vals[k], structure=createKernel(radius))
    C = C | B #combine masks

#plot resulting mask   
fig = plt.figure()
plt.imshow(C, interpolation='none')
plt.show()

Вхід: введіть тут опис зображення

Вихід: введіть тут опис зображення


1
+1 для розширення підходу! Він також працює з близькими точками.
Антоніо Фальчіано

Це чудовий приклад того, чому ця стара струменева кольорова схема була жахливою. Це набагато чіткіше виглядає з вірудіс.
naught101

8

Векторний підхід

Це завдання можна виконати в три етапи:

Примітка: використання поля буфера дозволяє уникнути обчислення буфера для кожного значення радіуса корони.


Підхід на основі растру

Уникаючи векторного рішення, ця проблема пропонує використовувати своєрідні стільникові автомати на основі найближчих сусідів. Якщо припустити, що всі чорні пікселі є нулями, пікселі мають квадрат, а їх розмір дорівнює 1 (або, як варіант, зручно масштабувати), правила прийняття дуже прості:

  1. Якщо значення пікселя ( VALUE) більше 1, його значення стає, VALUE-1а потім враховуйте його оточуючі пікселі. Якщо їх значення менше VALUE-1, ці пікселі народжуються або ростуть і їх значення стає VALUE-1. В іншому випадку ці пікселі виживають і залишаються незмінними.
  2. Якщо VALUE<=1нічого не робити (піксель мертвий!).

Ці правила потрібно застосовувати, поки всі пікселі не мертві, тобто їх значення дорівнюють 0 або 1. Тож N-1раз, де Nмаксимальне значення, яке ви маєте у вхідному растрі. Цей підхід може бути досить легко реалізований за допомогою трохи Python та numpy.


1
Дякую за відповідь afalciano. Цей метод полягає в тому, як я створив зображення праворуч і використовує векторний підхід - такого, якого я намагаюся уникати.
Аарон

1
Добре Аарон, ось растровий підхід зараз. Сподіваюсь, це допомагає.
Антоніо Фальчіано

7

Іншим варіантом було б створити окремі растри для кожного значення пікселя, у цьому випадку 4 растри, з умовою. Потім розгорніть растри на кількість пікселів, що відповідає значенню растру (можливо, повторившись над списком значень). Нарешті, приєднайтеся до растрових (алгебраїчних або просторових), щоб створити один бінарний растр для крони дерев.


1
Ця ідея правильна. Деталі можуть бути покращені: (1) відбір створює двійковий (0,1) індикатор дерев заданого радіуса крони. (2) Фокальну суму цього вибору - за допомогою кругового сусідства заданого радіуса - швидко обчислити за допомогою FFT. (3) Додавання фокусних сум (точково) та порівняння з 0 дає бажаний буфер.
whuber

7

Це складне питання зробити це в растрі, оскільки у вас немає можливості використовувати значення пікселя для визначення розміру буфера. Тому вам потрібно зробити фокусний фільтр для кожного значення, як ви вже говорили.

Ось можлива відповідь зробити це лише за допомогою трьох фільтрів (я не міг знайти менше), але не ідеально, як згадує Whuber: ваші буфери будуть усічені, коли дерева знаходяться близько один до одного.

1) EDIT: виділення Евкліда (це не вирішує повністю питання, оскільки воно скорочує буфери поблизу менших дерев, але це краще, ніж артефакти мого першого рішення).

2) евклідова відстань навколо кожного пікселя

3) растровий калькулятор (алгебра карти) із умовним твердженням

Con("allocation_result" > ("distance_result" / pixel_size) , 1 , 0)

Зауважте, що ви можете налаштувати умову залежно від ваших потреб з точки зору радіусу (з центральним пікселем або з ним)


+1 Це творчий підхід. Я спробую перевірити, чи можливо масштабувати цей підхід.
Аарон

2
Евклідовий дистанційний підхід не буде працювати, оскільки він обчислює лише відстань до найближчого дерева, що не обов'язково - відстань до дерева, крона якого покриває точку.
whuber

2

Цікаво, чому ви не використовуєте інструмент розширення ArcGIS ?

import arcpy
from arcpy.sa import *

raster_in  = r'c:\test.tif'
raster_out = r'c:\test_out.tif'

outExpand1 = Expand(raster_in, 2, 2)
outExpand2 = Expand(outExpand1, 3, 3)
outExpand3 = Expand(outExpand3, 4, 4)
outExpand4 = Expand(outExpand4, 5, 5)

outExpand4.save(raster_out)

У разі перекриття: остання expandкоманда охоплює попередні.


2

Якщо у вас є піксельна позиція, радіус та алгоритм кола середньої точки (варіант Алгена Брезена) дає вам підказку. ІМО легко створити багатокутник за цим підходом, і я думаю, що це легко реалізувати в Python. Об'єднання цього набору багатокутників дає вам покривну площу.


Я знаю, що це не питання, але чи хочете ви дізнатися більше про графічні примітиви та сканування заповнення полігону? Для кіл це дуже просто. Опукла комбінація - це
модна мова

Як це можна застосувати за допомогою основних растрових операцій?
whuber

Якщо ви спробуєте впоратися з цим у растровому просторі, визначте точки кола, сортуючи їх по у або х і заповніть простір прямою лінією (лінія сканування), на шляху заповнення кола. У трикутному підході, якщо ви будуєте коло за наближенням трикутних секторів і намагаєтесь заповнити трикутник, вам потрібен тест, якщо точка знаходиться всередині або зовні (опукла комбінація) і є іншим способом. А в підході "ГІС" побудова полігонів (тактових полігонів, орієнтованих на годинник) та складання об'єднання є третім (ІМО - найдорожчий дорогий).
huckfinn

Щоб було зрозуміло: А в підході "ГІС" ... зробіть алгебраричну операцію, як об'єднання, перехрестя, дотик .... третій ІМО - найдорожчий дорогий.
huckfinn
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.