Ответ 1
Здесь один подход, который значительно быстрее, чем V2
: возьмите img1-img2
и умножьте на 1 или -1 в зависимости от img1>img2
. Вот как это реализовано:
def differenceImageV6(img1, img2):
a = img1-img2
b = np.uint8(img1<img2) * 254 + 1
return a * b
Испытательный жгут для тестирования производительности:
import numpy as np
img1=np.uint8(np.random.randint(0, 255, (480, 640)))
img2=np.uint8(np.random.randint(0, 255, (480, 640)))
def differenceImageV1(img1, img2):
diff=np.empty_like(img1)
h, w=img1.shape
for y in range(h):
for x in range(w):
if img1[y, x]<img2[y, x]: diff[y, x]=img2[y, x]-img1[y, x]
else: diff[y, x]=img1[y, x]-img2[y, x]
return(diff)
def differenceImageV2(img1, img2):
return(np.uint8(np.abs(np.int16(img1)-img2)))
def differenceImageV3(img1, img2): # fast - but wrong result
return(img1-img2)
def differenceImageV4(img1, img2):
return np.where(img1>img2, img1-img2, img2-img1)
def differenceImageV5(img1, img2):
a = img1-img2
b = img2-img1
c = img1>img2
return a*c + b*(~c)
def differenceImageV6(img1, img2):
a = img1-img2
b = np.uint8(img1<img2) * 254 + 1
return a * b
import timeit
def testit():
for fn in [differenceImageV2, differenceImageV3, differenceImageV4, differenceImageV5, differenceImageV6]:
print fn.__name__, np.sum(fn(img1, img2).astype('int64')),
print timeit.timeit("%s(img1, img2)" % fn.__name__, "from test import img1, img2, %s" % fn.__name__, number=1000)
if __name__ == '__main__':
testit()
и итоговые номера производительности:
differenceImageV2 26071358 0.982538938522
differenceImageV3 39207702 0.0261280536652
differenceImageV4 26071358 1.36270809174
differenceImageV5 26071358 0.220561981201
differenceImageV6 26071358 0.154536962509
differenceImageV6
примерно на 6 раз медленнее, чем неправильный differenceImageV3
, но все же примерно на 6 раз быстрее предыдущего differenceImageV2
. differenceImageV1
не тестируется, потому что он легко на несколько порядков медленнее остальных.
Примечание. Я использовал метод np.where
для сравнения; Я думал, что это может иметь хорошую производительность, но оказалось, что она довольно бедна. Кажется, что выполнение разрезания булевым массивом в NumPy довольно медленное.