【问题标题】:Creating image tiles (m*n) of original image using Python and Numpy使用 Python 和 Numpy 创建原始图像的图像块 (m*n)
【发布时间】:2018-02-07 13:27:20
【问题描述】:

我正在使用 numpy 从我的 16 位 tiff 图像 (13777*16004) 创建 (224*224) 的图块。我能够沿行和列裁剪/切片为 224*224 的相等图块。我在尝试创建移动一半瓷砖大小的新瓷砖时遇到了问题......例如:我想要实现的粗略算法

(1:224, 1:224)

(1:224, 112:336)

(, 224:448)

目标是保持平铺尺寸(224*224),同时移动平铺尺寸的一半以获得更多图像平铺...

为执行任务而编写的代码片段

row_x =  img.shape[0]
column_y = img.shape[1]

tile_size_x = 224
tile_size_y = 224


range_x = mpz(ceil(row_x/tile_size_x))
range_y = mpz(ceil(column_y/tile_size_y))

for x in range(range_x, row_x):

    for y in range(range_y, column_y): 

        x0 = x * tile_size_x 

        x1 = int(x0/2) + tile_size_x

        y0 = y * tile_size_y 

        y1 = int(y0/2) + tile_size_y



        z = img[x0:x1, y0:y1]
        print (z.shape,z.dtype)

我总是得到错误的结果,谁能帮忙???

【问题讨论】:

  • 我本可以发誓这是一个骗子(使用as_strided 有一个很好的答案),但我一辈子都找不到它。 @Divakar,你通常是as_strided 巫师,也许你还记得?

标签: python image opencv numpy


【解决方案1】:

如果您不介意使用 ImageMagick,那么使用 -crop 命令很简单。见https://imagemagick.org/Usage/crop/#crop_tile

您可以使用 Python 子进程调用来调用 imagemagick。

输入:

为了简单起见,假设您需要 4 个 256x256 的图块。

convert lena512.png -crop 256x256 lena512_%d.png

或百分比

convert lena512.png -crop 50x50% lena512_%d.png

【讨论】:

    【解决方案2】:

    我觉得你可以用这个

    def TileImage(image,rows,cols):
    imagename = image
    im = Image.open(imagename) 
    width, height = im.size
    indexrow = 0
    indexcolum = 0
    left = 0
    top = 0
    right = width/col
    buttom = 0
    while(right<=width):    
        buttom = height/rows
        top = 0
        indexrow=0  
    
        while(top<height):
            print(f"h : {height}, w : {width}, left : {left},top : {top},right : {right}, buttom   :  {buttom}")
            cropimg= im.crop((left, top, right, buttom)) 
            cropimg.save(imagename + str(indexrow) + str(indexcolum) +".jpg")
            top = buttom
            indexrow += 1
            buttom += height/rows   
    
        indexcolum+=1
        left = right
        right += width/col 
    

    【讨论】:

    • 工作就像一个魅力
    【解决方案3】:

    我更喜欢预先计算瓷砖的数量,然后使用简单的重塑。例如

    tile = 512
    img_height = img.shape[1]
    img_width = img.shape[0]
    number_of_vertical_tiles = img_height // tile
    number_of_horizontal_tiles = img_width // tile
    cropped_img = img[:tile*number_of_vertical_tiles, :tile*number_of_horizontal_tiles,:]
    tiled_img = img.reshape(-1, tile, tile, 3)
    

    【讨论】:

      【解决方案4】:

      我认为您可以使用as_strided 非常有效地完成此操作。

      def window_nd(a, window, steps = None):
          ashp = np.array(a.shape)
          wshp = np.array(window).reshape(-1)
          if steps:
              stp = np.array(steps).reshape(-1)
          else:
              stp = np.ones_like(ashp)
          astr = np.array(a.strides)
          assert np.all(np.r_[ashp.size == wshp.size, wshp.size == stp.size, wshp <= ashp])
          shape = tuple((ashp - wshp) // stp + 1) + tuple(wshp)
          strides = tuple(astr * stp) + tuple(astr)
          as_strided = np.lib.stride_tricks.as_strided
          aview = as_strided(a, shape = shape, strides = strides)
          return aview
      

      编辑:尽可能概括跨步方法。

      针对您的具体问题:

      aview = window_nd(a, (288, 288), (144, 144))
      z = aview.copy().reshape(-1, wx, wy) #to match expected output
      print(z.shape, z.dtype) # z.shape should be (num_patches, 288, 288)
      

      【讨论】:

        【解决方案5】:

        您在计算 for 循环的范围时有点偏离。要制作的切片数量必须使用两个切片之间的偏移量来计算,在您的情况下为x0/2,我已经简化了您的代码并定义了一些有意义的变量,您可以配置这些变量以从给定图像中获取所需的切片:

        import cv2
        import math
        
        img = cv2.imread("/path/to/lena.png") # 512x512
        
        img_shape = img.shape
        tile_size = (256, 256)
        offset = (256, 256)
        
        for i in xrange(int(math.ceil(img_shape[0]/(offset[1] * 1.0)))):
            for j in xrange(int(math.ceil(img_shape[1]/(offset[0] * 1.0)))):
                cropped_img = img[offset[1]*i:min(offset[1]*i+tile_size[1], img_shape[0]), offset[0]*j:min(offset[0]*j+tile_size[0], img_shape[1])]
                # Debugging the tiles
                cv2.imwrite("debug_" + str(i) + "_" + str(j) + ".png", cropped_img)
        

        如果是图像尺寸的整数倍,即 512x512,则作为当前偏移量,因此我们将获得 4 个相同大小的图块:

        更改偏移量的值会得到不规则大小的图块,如果偏移量不是图像尺寸的精确倍数,您可以稍后通过将math.ceil 更改为math.floor 来过滤这些图块for 循环。

        【讨论】:

        • 我能够根据我的情况进行配置,效果很好。感谢您的解释。没有为循环定义偏移量,因此结果错误。谢谢
        猜你喜欢
        • 1970-01-01
        • 2021-07-24
        • 2015-09-11
        • 2012-02-16
        • 1970-01-01
        • 2016-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多