Обновление: Первоначальная формулировка вопроса была немного неясной.Я не просто обрезаю изображение, но применяю билинейную интерполяцию в процессе извлечения патчей.(См. Справочный документ ниже).Вот почему алгоритм немного сложнее, чем просто взятие ломтиков.
Я пытаюсь обучить модели глубокого обучения прогнозированию ориентиров лица после этой статьи .Мне нужно обрезать части изображения, которое содержит лицо, в меньшие участки вокруг лицевых ориентиров.Например, если у нас есть изображение, показанное ниже:
Функция должна генерировать N=15
«патчей», по одному патчу на ориентир:
У меня есть следующая наивная реализация, построенная поверх 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, но, возможно, кто-то уже делал что-то подобное раньше.
Не могли бы вы порекомендовать альтернативу коду, показанному выше, или, может быть, предложение о том, как сделать его быстрее?(За исключением использования нескольких параллельных рабочих).