Python 两个uint8阵列的快速绝对差分

Python 两个uint8阵列的快速绝对差分,python,numpy,Python,Numpy,我有两个numpy数组,其dtype=np.uint8-如下所示: img1=np.uint8(np.random.randint(0, 255, (480, 640))) img2=np.uint8(np.random.randint(0, 255, (480, 640))) 我想建立这些数组的正差异 以下是我的前两种方法(第三种方法供参考): 有没有办法像V2那样更快地得到正确的结果?这里有一种方法比V2快得多:取img1-img2,然后根据img1>img2乘以1或-1。以下是它的实现方

我有两个numpy数组,其
dtype=np.uint8
-如下所示:

img1=np.uint8(np.random.randint(0, 255, (480, 640)))
img2=np.uint8(np.random.randint(0, 255, (480, 640)))
我想建立这些数组的正差异

以下是我的前两种方法(第三种方法供参考):


有没有办法像V2那样更快地得到正确的结果?

这里有一种方法比
V2
快得多:取
img1-img2
,然后根据
img1>img2
乘以1或-1。以下是它的实现方式:

def differenceImageV6(img1, img2):
  a = img1-img2
  b = np.uint8(img1<img2) * 254 + 1
  return a * b
differenceImageV6
比不正确的
differenceImageV3
慢约6倍,但仍比以前最好的
differenceImageV2
快约6倍
differenceImageV1
未经测试,因为它很容易比其他图像慢几个数量级


注:我包括了一个
np.where
比较方法;我认为它可能有很好的表现,但结果是相当差。似乎通过布尔数组执行切片在NumPy中相当慢。

如果您有可用的
opencv
,您还可以使用:

def differenceImageV4(img1, img2):
  return cv2.absdiff(img1, img2)

它的速度几乎与
differenceImageV3

相同,不确定它是否真的有那么大的帮助,但您可能不需要
differenceImageV2
中的
np.int16(img2)
,只需要使用
img2
。另外,您是否使用库来获得精确的计时结果?我知道溢出(下溢是指两个浮点数之间的差值太小而无法区分)。我的意思是完整的语句应该是
返回(np.uint8(np.absolute(np.int16(img1)-img2))
img1
仍被强制转换为
int16
,因此结果将是
int16
,并且可以允许与预先执行强制转换相同的负数
np.sum
给出相同的结果。它只是不首先获取整个阵列的副本。我剃掉了大约70毫秒1000圈。你说得对。如果我做一个
np.int16(img1)-img2
,我会得到同样的结果。对于1000个循环,执行时间下降到400.39毫秒。不,我在这里使用
time.process\u time()
,因为我不在乎一毫秒或十毫秒。@dede:看我的答案。由于我在测试中得到了V2和V3之间40倍的差距(远大于您的15倍差距),我想看看我的解决方案在您的测试设置中的性能。@nneonneo:我得到了以下值:V1(10x:1897.16毫秒)、V2(1000x:412.73毫秒)、V3(1000x:28.60毫秒)、V4(1000x:1369.41毫秒)、V5(1000x:253.97毫秒)、V6(1000x:183.48毫秒)。这是您要求的数据吗?我得到的
differenceImageV2
数据约为895µs,而
differenceImageV6
数据约为645µs。不管实际的加速效果如何,我仍然为numpy魔法喝彩。我喜欢你的V6:-)…但仍在努力理解;-)我认为如果你按照
a=img1-img2的方式来做,V6会更快;a[img1
@dede最基本的位是用8位数学乘以
255
相当于乘以
-1并使其溢出
a
是基本区别,
b
1
255
的数组,基于
img1
的元素是否小于
img2
的元素@Jaime,虽然巧妙,但它甚至比我机器上的
differenceImageV2
还要慢。
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
def differenceImageV4(img1, img2):
  return cv2.absdiff(img1, img2)