如何在类似于Matlab的blkproc(blockproc)函数的块中有效地处理numpy数组 [英] How can I efficiently process a numpy array in blocks similar to Matlab's blkproc (blockproc) function

查看:752
本文介绍了如何在类似于Matlab的blkproc(blockproc)函数的块中有效地处理numpy数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种有效的方法来有效地将图像分成小区域,分别处理每个区域,然后将每个过程的结果重新组合成单​​个处理过的图像。 Matlab有一个名为 blkproc 的工具(替换为 blockproc 在较新版本的Matlab中)。

I'm looking for a good approach for efficiently dividing an image into small regions, processing each region separately, and then re-assembling the results from each process into a single processed image. Matlab had a tool for this called blkproc (replaced by blockproc in newer versions of Matlab).

在理想情况下,函数或类也支持输入矩阵中的分区之间的重叠。在Matlab帮助中,blkproc定义为:

In an ideal world, the function or class would support overlap between the divisions in the input matrix too. In the Matlab help, blkproc is defined as:


B = blkproc(A,[mn],[mborder nborder],有趣,。 ..)

B = blkproc(A,[m n],[mborder nborder],fun,...)




  • A是您的输入矩阵,

  • [mn]是块大小

  • [mborder,nborder]是边框区域的大小(可选)

  • fun是一个要应用的函数每个街区

    • A is your input matrix,
    • [m n] is the block size
    • [mborder, nborder] is the size of your border region (optional)
    • fun is a function to apply to each block
    • 我已经采取了一种方法,但它让我觉得笨拙,我敢打赌,这是一个更好的方法。冒着我自己的尴尬,这是我的代码:

      I have kluged together an approach, but it strikes me as clumsy and I bet there's a much better way. At the risk of my own embarrassment, here's my code:

      
      import numpy as np
      
      def segmented_process(M, blk_size=(16,16), overlap=(0,0), fun=None):
          rows = []
          for i in range(0, M.shape[0], blk_size[0]):
              cols = []
              for j in range(0, M.shape[1], blk_size[1]):
                  cols.append(fun(M[i:i+blk_size[0], j:j+blk_size[1]]))
              rows.append(np.concatenate(cols, axis=1))
          return np.concatenate(rows, axis=0)
      
      R = np.random.rand(128,128)
      passthrough = lambda(x):x
      Rprime = segmented_process(R, blk_size=(16,16), 
                                 overlap=(0,0), 
                                 fun=passthrough)
      
      np.all(R==Rprime)
      


      推荐答案

      以下是一些使用块的不同(无循环)方式的示例: / p>

      Here are some examples of a different (loop free) way to work with blocks:

      import numpy as np
      from numpy.lib.stride_tricks import as_strided as ast
      
      A= np.arange(36).reshape(6, 6)
      print A
      #[[ 0  1  2  3  4  5]
      # [ 6  7  8  9 10 11]
      # ...
      # [30 31 32 33 34 35]]
      
      # 2x2 block view
      B= ast(A, shape= (3, 3, 2, 2), strides= (48, 8, 24, 4))
      print B[1, 1]
      #[[14 15]
      # [20 21]]
      
      # for preserving original shape
      B[:, :]= np.dot(B[:, :], np.array([[0, 1], [1, 0]]))
      print A
      #[[ 1  0  3  2  5  4]
      # [ 7  6  9  8 11 10]
      # ...
      # [31 30 33 32 35 34]]
      print B[1, 1]
      #[[15 14]
      # [21 20]]
      
      # for reducing shape, processing in 3D is enough
      C= B.reshape(3, 3, -1)
      print C.sum(-1)
      #[[ 14  22  30]
      # [ 62  70  78]
      # [110 118 126]]
      

      所以只是试图简单地将 matlab 功能复制到 numpy 并不是所有方式都是最好的方式继续。有时候需要一个脱帽的想法。

      So just trying to simply copy the matlab functionality to numpy is not all ways the best way to proceed. Sometimes a 'off the hat' thinking is needed.

      警告

      一般来说,基于步幅技巧的实现可能(但不一定需要)遭受一些性能损失。所以要准备好衡量你的表现的各种方法。在任何情况下,首先检查所需的功能(或类似的,以便轻松适应)是否已经准备好在 numpy scipy 。

      Caveat:
      In general, implementations based on stride tricks may (but does not necessary need to) suffer some performance penalties. So be prepared to all ways measure your performance. In any case it's wise to first check if the needed functionality (or similar enough, in order to easily adapt for) has all ready been implemented in numpy or scipy.

      更新

      请注意,没有真正的 magic 这里涉及 strides ,所以我将提供一个简单的函数来获取 block_view 任何合适的2D numpy -array。所以我们走了:

      Update:
      Please note that there is no real magic involved here with the strides, so I'll provide a simple function to get a block_view of any suitable 2D numpy-array. So here we go:

      from numpy.lib.stride_tricks import as_strided as ast
      
      def block_view(A, block= (3, 3)):
          """Provide a 2D block view to 2D array. No error checking made.
          Therefore meaningful (as implemented) only for blocks strictly
          compatible with the shape of A."""
          # simple shape and strides computations may seem at first strange
          # unless one is able to recognize the 'tuple additions' involved ;-)
          shape= (A.shape[0]/ block[0], A.shape[1]/ block[1])+ block
          strides= (block[0]* A.strides[0], block[1]* A.strides[1])+ A.strides
          return ast(A, shape= shape, strides= strides)
      
      if __name__ == '__main__':
          from numpy import arange
          A= arange(144).reshape(12, 12)
          print block_view(A)[0, 0]
          #[[ 0  1  2]
          # [12 13 14]
          # [24 25 26]]
          print block_view(A, (2, 6))[0, 0]
          #[[ 0  1  2  3  4  5]
          # [12 13 14 15 16 17]]
          print block_view(A, (3, 12))[0, 0]
          #[[ 0  1  2  3  4  5  6  7  8  9 10 11]
          # [12 13 14 15 16 17 18 19 20 21 22 23]
          # [24 25 26 27 28 29 30 31 32 33 34 35]]
      

      这篇关于如何在类似于Matlab的blkproc(blockproc)函数的块中有效地处理numpy数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆