Алгоритм минимального расстояния с использованием GDAL и Python

Я пытаюсь реализовать Алгоритм минимального расстояния для классификации изображений с помощью GDAL и Python. После вычисления среднего значения пикселя областей выборки и сохранения их в списке массивов («sample_array») я считываю изображение в массив, называемый «значения». Со следующим кодом я перебираю этот массив:

values = valBD.ReadAsArray()

# loop through pixel columns
for X in range(0,XSize):

    # loop thorugh pixel lines
    for Y in range (0, YSize):

        # initialize variables
        minDist = 9999
        # get minimum distance
        for iSample in range (0, sample_count):
            # dist = calc_distance(values[jPixel, iPixel], sample_array[iSample])

            # computing minimum distance
            iPixelVal = values[Y, X]
            mean = sample_array[iSample]
            dist = math.sqrt((iPixelVal - mean) * (iPixelVal - mean)) # only for testing

            if dist < minDist:
                minDist = dist
                values[Y, X] = iSample

classBD.WriteArray(values, xoff=0, yoff=0)

Эта процедура занимает очень много времени для больших изображений. Вот почему я хочу спросить, знает ли кто-нибудь более быстрый метод. Я мало знаю о скорости доступа к различным переменным в python. Или, может быть, кто-то знает библиотеку, которую я мог бы использовать. Заранее спасибо, Марио


person Mario Härtwig    schedule 05.05.2011    source источник
comment
Выполнение чего-либо попиксельно в чистом Python, скорее всего, будет медленным. Вы можете взглянуть на PIL, библиотеку изображений Python, чтобы узнать, полезны ли для этого ее функции.   -  person Thomas K    schedule 06.05.2011


Ответы (2)


Вы обязательно должны использовать NumPy. Я работаю с довольно большими наборами растровых данных, и NumPy прожигает их. На моей машине с приведенным ниже кодом нет заметной задержки для массива 1000 x 1000. Объяснение того, как это работает, следует за кодом.

import numpy as np
from scipy.spatial.distance import cdist

# some starter data
dim = (1000,1000)
values = np.random.randint(0, 10, dim)

# cdist will want 'samples' as a 2-d array
samples = np.array([1, 2, 3]).reshape(-1, 1)

# this could be a one-liner
# 'values' must have the same number of columns as 'samples'
mins = cdist(values.reshape(-1, 1), samples)
outvalues = mins.argmin(axis=1).reshape(dim)

cdist() вычисляет «расстояние» от каждого элемента в values до каждого из элементов в samples. Это создает массив 1 000 000 x 3, где каждая строка n имеет расстояние от пикселя n в исходном массиве до каждого из выборочных значений [1, 2, 3]. argmin(axis=1) дает вам индекс минимального значения в каждой строке, что вам и нужно. Быстрое изменение формы дает вам прямоугольный формат, который вы ожидаете от изображения.

person Robin Kraft    schedule 15.08.2011

Согласитесь с Томасом К.: используйте PIL или напишите C-функцию. и оберните его, например. ctypes или, по крайней мере, использовать некоторые операции с матрицами numPy. Или же используйте pypy для вашего существующего кода (код, скомпилированный JIT, может быть в 100 раз быстрее для кода изображения). Попробуйте pypy и расскажите нам, какое ускорение вы получили.

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

person smci    schedule 30.06.2011