Производительность Python absdiff на подматрицах

#python #performance #image-processing

#python #Производительность #обработка изображений

Вопрос:

Я вычисляю сумму абсолютной разности двух матриц (представляющих два изображения в RGBA с типом uint8), чтобы увидеть, насколько они похожи друг на друга. Я наткнулся на странную проблему эффективности, когда вычисление расстояния на подматрицах (в частности, я рассматриваю только каналы RGB) занимает примерно в 5 раз больше, чем выполнение этого для целых матриц. Вот мой код:

Во-первых, я загружаю два изображения с помощью OpenCV и конвертирую их в RGBA (поскольку при загрузке они являются BGR) следующим образом (пути указаны ранее):

 template_image = cv2.cvtColor(cv2.imread(template_path, flags=cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGBA)
big_image = cv2.cvtColor(cv2.imread(big_image_path, flags=cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGBA)
 

Затем я вычисляю сходство таким образом (1000 циклов предназначены только для увеличения времени, которое требуется. Я делаю 1000 циклов во всех тестах, поэтому это не должно иметь значения):

 first = template_image[:,:,0:3]
second = big_image[0:200, 0:400,0:3]
t = time.time()
for i in range(1000):
    numpy.sum(cv2.absdiff(first, second))
print(f'elapsed time: {(time.time() - t):.3f} s')
 

Выполняя это несколько раз, оно дает время, которое колеблется между 1 с и 1,2 с

Это меня удивило, потому что до ограничения его каналами RGB он занимал намного меньше. Фактически, с помощью этого кода:

 first = template_image[:,:]
second = big_image[0:200, 0:400]
t = time.time()
for i in range(1000):
    numpy.sum(cv2.absdiff(first, second))
print(f'elapsed time: {(time.time() - t):.3f} s')
 

среднее затраченное время составляет примерно 0,25 с.

Этого самого по себе достаточно, чтобы вывести меня из себя, так как почему для выполнения технически меньших вычислений требуется в 5 раз больше?


Я также попробовал другой фрагмент кода, чтобы проверить сходство только на RGBA, и это меня еще больше пугает:

 first = numpy.zeros((200, 400, 3), dtype=numpy.uint8)
first[:,:,:] = template_image[:,:,0:3]
second = numpy.zeros((200, 400, 3), dtype=numpy.uint8)
second[:,:,:] = big_image[0:200, 0:400,0:3]
t = time.time()
for i in range(1000):
    numpy.sum(cv2.absdiff(first, second))
print(f'elapsed time: {(time.time() - t):.3f} s')
 

Теперь этот код занимает в среднем 0,19 секунды. Имеет смысл, что он занимает меньше времени, чем тот, который вычисляется на RGBA, поскольку это меньше вычислений, но почему он должен занимать намного меньше, чем другой, выполняемый только на каналах RGB?
Я указал dtype=numpy.uint8 , потому что это тип изображений, когда я читаю их с помощью OpenCV, и в противном случае это создало бы матрицы в типе float64, что (понятно) занимает гораздо больше времени.

В чем причина такого странного поведения? Спасибо!

Комментарии:

1. В медленном примере попробуйте first = template_image[:,:,0:3].copy(); second = big_image[0:200, 0:400,0:3].copy() . Это должно устранить любые изменения.

2. О, так успехи — это то, что вызывает проблему с производительностью? Спасибо! Не знал, что