Как (быстро) извлечь билинейно-интерполированные участки из двумерного изображения в определенных точках? - PullRequest
0 голосов
/ 29 января 2019

Обновление: Первоначальная формулировка вопроса была немного неясной.Я не просто обрезаю изображение, но применяю билинейную интерполяцию в процессе извлечения патчей.(См. Справочный документ ниже).Вот почему алгоритм немного сложнее, чем просто взятие ломтиков.


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

enter image description here

Функция должна генерировать N=15 «патчей», по одному патчу на ориентир:

enter image description here

У меня есть следующая наивная реализация, построенная поверх torch тензоров:

def generate_patch(x, y, w, h, image):
    c = image.size(0)
    patch = torch.zeros((c, h, w), dtype=image.dtype)
    for q in range(h):
        for p in range(w):
            yq = y + q - (h - 1)/2
            xp = x + p - (w - 1)/2
            xd = 1 - (xp - math.floor(xp))
            xu = 1 - (math.ceil(xp) - xp)
            yd = 1 - (yq - math.floor(yq))
            yu = 1 - (math.ceil(yq) - yq)
            for idx in range(c):
                patch[idx, q, p] = (
                    image[idx, math.floor(yq), math.floor(xp)]*yd*xd + 
                    image[idx, math.floor(yq),  math.ceil(xp)]*yd*xu +
                    image[idx,  math.ceil(yq), math.floor(xp)]*yu*xd +
                    image[idx,  math.ceil(yq),  math.ceil(xp)]*yu*xu
                ).item()
    return patch


def generate_patches(image, points, n=None, sz=31):
    if n is None:
        n = len(points)//2
    patches = []
    for i in range(n):
        x_val, y_val = points[i], points[i + n]
        patch = generate_patch(x_val, y_val, sz, sz, image)
        patches.append(patch)
    return patches

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

Я знаю, что есть функция extract_patches_2d из пакета sklearn, которая помогает выбирать случайные патчи из изображения.Однако я бы хотел выбрать патчи из определенных точек , а не делать это случайно.Я предполагаю, что я могу каким-то образом адаптировать вышеупомянутую функцию или преобразовать показанную выше реализацию в код Cython / C, но, возможно, кто-то уже делал что-то подобное раньше.

Не могли бы вы порекомендовать альтернативу коду, показанному выше, или, может быть, предложение о том, как сделать его быстрее?(За исключением использования нескольких параллельных рабочих).

1 Ответ

0 голосов
/ 29 января 2019

1) использовать numpy

2) выбирать патчи с извлечением индекса.Пример:

Patch=img[0:100,0:100]

3) создать 3-мерное тело, где в 3-м измерении - патчи.[15x15x количество патчей]

4) сделайте свой билинейный int.С NumPy для всех патчей в одно и то же время (один пиксель вычисляется со всеми пикселями в 3-м измерении).

Это увеличит вашу обработку за гранью вашего воображения

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

...