Python:用numpy改进图像处理

时间:2017-08-16 12:57:30

标签: python-2.7 numpy image-processing

让两个大的(2000x2000或更高).tiff图像只包含numpy float32值(没有rgb)。我把它们称为图像A和B.我想以一种特殊的方式将它们相乘:

  • 在B中找到最大值并将其滚动(使用numpy.roll)到 左上角。
  • 乘以A和B
  • 将B的总和加到A的索引中,其中B的最大值被滚动
  • 进一步滚动B个元素的最大值
  • 重复A
  • 的所有元素
  • 保存生成的图片

两个图像总是相同的形状。 我提出了这个想法:

#A,B are loaded with PIL as numpy images and are flattend
B = np.roll(B, len(mult_img)-distance_to_max) #roll max to the first element

sum_arr = np.sum(B) #sum of B

for i in range(len(A)):
    A = np.multiply(A,  np.roll(B, i)) #roll B with i-increment and multiply
    A[i] += sum_arr #add sum to A at index

在重新整形数组并保存之后,看起来它会完成这项工作。但是对于一个2000x2000的图像需要大约40秒,并且它们将有处理的内容。 问题是:如何改进?或者是否有更好的numpy解决方案来完成这项任务以加快速度?

提前致谢

1 个答案:

答案 0 :(得分:2)

预期方法

考虑一下:

In [154]: B = np.arange(5)

In [155]: B
Out[155]: array([0, 1, 2, 3, 4])

使用B的滚动版本:

In [156]: for i in range(len(B)):
     ...:     print np.roll(B, i)
     ...:     
[0 1 2 3 4]
[4 0 1 2 3]
[3 4 0 1 2]
[2 3 4 0 1]
[1 2 3 4 0]

因此,我们需要采用的技巧是创建一个可以切片以获得滚动版本的扩展数组。在NumPy切片的想法基本上是免费的。因此,扩展数组将是 -

In [157]: B_ext = np.concatenate((B[1:], B))

In [158]: B_ext
Out[158]: array([1, 2, 3, 4, 0, 1, 2, 3, 4])

因此,切片步骤将是 -

[1, 2, 3, 4, 0, 1, 2, 3, 4]
             [            ]
          [            ]
       [            ]
    [            ]
[            ]

使用

然后,可以像这样使用扩展数组 -

n = len(A)
for i in range(n-1,-1,-1):
    Ac *= B_ext[i:i+n] #roll B with i-increment and multiply
    Ac[n-1-i] += sum_arr #add sum to A at index

<强>结束写入

最终确定,方法是 -

def org_app(A, B, sum_arr): # Original approach
    for i in range(len(A)):
        A = np.multiply(A,  np.roll(B, i)) #roll B with i-increment and multiply
        A[i] += sum_arr #add sum to A at index
    return A

def app1(A, B, sum_arr): # Proposed approach
    B_ext = np.concatenate((B[1:], B))
    n = len(A)
    for i in range(n-1,-1,-1):
        A *= B_ext[i:i+n] #roll B with i-increment and multiply
        A[n-1-i] += sum_arr #add sum to A at index
    return A

<强>基准

1)验证 -

In [144]: # Setup inputs
     ...: np.random.seed(1234)
     ...: N = 10000
     ...: A = np.random.randint(0,255,(N))
     ...: B = np.random.randint(0,255,(N))
     ...: A_copy = A.copy()
     ...: sum_arr = np.sum(B) #sum of B
     ...: 

In [145]: out1 = org_app(A, B, sum_arr)
     ...: out2 = app1(A_copy, B, sum_arr)
     ...: print "Abs. Max. Error : " + str(np.abs(out1-out2).max())
     ...: 
Abs. Max. Error : 0

2)运行时测试 -

In [146]: # Setup inputs
     ...: np.random.seed(1234)
     ...: N = 10000
     ...: A = np.random.randint(0,255,(N))
     ...: B = np.random.randint(0,255,(N))
     ...: A_copy = A.copy()
     ...: sum_arr = np.sum(B) #sum of B
     ...: 

In [147]: %timeit org_app(A, B, sum_arr)
1 loop, best of 3: 196 ms per loop

In [148]: %timeit app1(A_copy, B, sum_arr)
10 loops, best of 3: 51.9 ms per loop