Ускоренная условная замена

Я пытаюсь ускорить внутренний цикл:

import cv2
import datetime
gt = cv2.imread("image.png",0)

start = datetime.datetime.now()
for i in range(gt.shape[0]):
 for j in range(gt.shape[1]):
 if(gt[i,j] == 0): continue
 limit = min(60,((gt.shape[1]-j)))
 for d in range(limit): # <------- this one
 if(gt[i,j] < gt[i,j+d] - d):
 gt[i,j] = 0
 break
print(datetime.datetime.now() - start)

Есть ли способ использовать встроенные операторы numpy для его перезаписи? на данный момент он очень медленный, как 46 секунд для каждого изображения. Я уже пробовал что-то вроде:

gt[ gt[i,j+range(d)] - range(d)]=0

но, конечно, это не сработает, поскольку вы не можете суммировать int со списком.

2 ответа

Ds может быть представлен с помощью постоянного np.arange(60) и gt[i,j+d] с gt[i, j:j+d].

import numpy as np
ds = np.arange(60)
for i in range(gt.shape[0]):
 for j in range(gt.shape[1]):
 if(gt[i, j] == 0):
 continue
 limit = min(60, ((gt.shape[1]-j)))
 if np.any(gt[i, j] < (gt[i, j:j+limit]-ds[:limit])):
 gt[i, j] = 0

Если у вас нет проблем с памятью, это возможно, скорее всего, будет векторизованным. Например:

mask = np.zeros(gt.shape, dtype="bool")
for dist in range(1, 60):
 diffs = gt[:, :-dist] < (gt[:, dist:] - dist)
 mask[:, :-dist] |= diffs
gt[mask] = 0

При работе с беззнаковыми целыми числами diffs должны быть рассчитаны с:

diffs = (gt2[:, :-dist] < (gt2[:, dist:] - dist)) & (gt2[:, dist:]>dist)

для предотвращения проблем с переполнением.

Который дает прибл. 200x ускорение на изображении 200x200pix.


gt = np.array([[1, 1, 1], [1.5, 2.5, 2.5], [2, 3.5, 4]])
limit = 2

m = np.zeros_like(gt, dtype=bool)
for d in range(1, limit + 1):
 if d >= gt.shape[0]:
 break
 shifted = np.roll(gt, shift=-d, axis=0)
 shifted[-d:] = np.nan
 m = m | (gt < shifted - d)
gt[m] = 0

print(gt)

выходы

array([[1. , 0. , 0. ],
 [1.5, 2.5, 0. ],
 [2. , 3.5, 4. ]])

licensed under cc by-sa 3.0 with attribution.