【问题标题】:crop center portion of a numpy image裁剪 numpy 图像的中心部分
【发布时间】:2017-01-15 21:11:49
【问题描述】:

假设我有一个宽度为 x 和高度为 y 的 numpy 图像。 我必须将图像的中心部分裁剪为宽度cropx和高度cropy。假设cropx 和cropy 是正非零整数并且小于各自的图像大小。对输出图像应用切片的最佳方法是什么?

【问题讨论】:

    标签: python image numpy image-processing crop


    【解决方案1】:

    我遇到了一个问题,我需要从 2D 和 3D 阵列中裁剪中心。这意味着从img.shape 中解包不同数量的项目。

    把这个放在这里,以防有人遇到同样的问题。 Divkar 解决方案的这种修改允许裁剪 2D 或 3D 数组

    def crop_center(img, cropx, cropy):
        y, x, *_ = img.shape
        startx = x // 2 - (cropx // 2)
        starty = y // 2 - (cropy // 2)    
        return img[starty:starty + cropy, startx:startx + cropx, ...]
    

    【讨论】:

      【解决方案2】:

      @Divakar 回答的另一个简单修改是保留颜色通道:

      def crop_center(img,cropx,cropy):
          y,x,_ = img.shape
          startx = x//2-(cropx//2)
          starty = y//2-(cropy//2)
          return img[starty:starty+cropy,startx:startx+cropx,:]
      

      【讨论】:

        【解决方案3】:

        对@Divakar 的回答进行简单修改,保留图像通道:

            def crop_center(self, img, cropx, cropy):
               _, y, x = img.shape
               startx = x // 2 - (cropx // 2)
               starty = y // 2 - (cropy // 2)
               return img[:, starty:starty + cropy, startx:startx + cropx]
        

        【讨论】:

          【解决方案4】:

          谢谢,迪瓦卡。

          你的回答让我朝着正确的方向前进。我想出了这个使用负切片偏移量“从头开始”:

          def cropimread(crop, xcrop, ycrop, fn):
              "Function to crop center of an image file"
              img_pre= msc.imread(fn)
              if crop:
                  ysize, xsize, chan = img_pre.shape
                  xoff = (xsize - xcrop) // 2
                  yoff = (ysize - ycrop) // 2
                  img= img_pre[yoff:-yoff,xoff:-xoff]
              else:
                  img= img_pre
              return img
          

          【讨论】:

          • 您可能希望使用// 而不是/ 以避免使它们成为浮动pt 数字,因为它们可能不适用于索引,至少我猜Python 3.x 版本。
          • 我会从这个“答案”中删除问题
          • 这不适用于奇数。例如。将 101 宽的图像裁剪为 50 将产生 51 宽的图像!
          【解决方案5】:

          基于@Divakar 的回答的更通用的解决方案:

          def cropND(img, bounding):
              start = tuple(map(lambda a, da: a//2-da//2, img.shape, bounding))
              end = tuple(map(operator.add, start, bounding))
              slices = tuple(map(slice, start, end))
              return img[slices]
          

          如果我们有一个数组a

          >>> a = np.arange(100).reshape((10,10))
          
          array([[ 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, 36, 37, 38, 39],
                 [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
                 [50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
                 [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
                 [70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
                 [80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
                 [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])
          

          我们可以用cropND(a, (5,5))剪辑它,你会得到:

          >>> cropND(a, (5,5))
          
          array([[33, 34, 35, 36, 37],
                 [43, 44, 45, 46, 47],
                 [53, 54, 55, 56, 57],
                 [63, 64, 65, 66, 67],
                 [73, 74, 75, 76, 77]])
          

          它不仅适用于 2D 图像,还适用于 3D 图像。

          祝你有美好的一天。

          【讨论】:

          • 为什么没有更多的支持?图像通常可以有多个通道 (3D)
          • 嗨,我有一个形状为 (WxHxD) (281, 389, 104) 的 3D 图像,但是一旦我尝试运行 cropND,我收到一个错误:Traceback (most recent call last): File "<pyshell#42>", line 1, in <module> cropND(img,(256,256)) File "<pyshell#27>", line 2, in cropND start = tuple(map(lambda a, da: a//2-da//2, img.shape, bounding)) File "<pyshell#27>", line 2, in <lambda> start = tuple(map(lambda a, da: a//2-da//2, img.shape, bounding)) TypeError: unsupported operand type(s) for //: 'NoneType' and 'int'跨度>
          • @S.EB 试试cropND(img, (256, 256, 104))
          【解决方案6】:

          类似的东西-

          def crop_center(img,cropx,cropy):
              y,x = img.shape
              startx = x//2-(cropx//2)
              starty = y//2-(cropy//2)    
              return img[starty:starty+cropy,startx:startx+cropx]
          

          示例运行 -

          In [45]: img
          Out[45]: 
          array([[88, 93, 42, 25, 36, 14, 59, 46, 77, 13, 52, 58],
                 [43, 47, 40, 48, 23, 74, 12, 33, 58, 93, 87, 87],
                 [54, 75, 79, 21, 15, 44, 51, 68, 28, 94, 78, 48],
                 [57, 46, 14, 98, 43, 76, 86, 56, 86, 88, 96, 49],
                 [52, 83, 13, 18, 40, 33, 11, 87, 38, 74, 23, 88],
                 [81, 28, 86, 89, 16, 28, 66, 67, 80, 23, 95, 98],
                 [46, 30, 18, 31, 73, 15, 90, 77, 71, 57, 61, 78],
                 [33, 58, 20, 11, 80, 25, 96, 80, 27, 40, 66, 92],
                 [13, 59, 77, 53, 91, 16, 47, 79, 33, 78, 25, 66],
                 [22, 80, 40, 24, 17, 85, 20, 70, 81, 68, 50, 80]])
          
          In [46]: crop_center(img,4,6)
          Out[46]: 
          array([[15, 44, 51, 68],
                 [43, 76, 86, 56],
                 [40, 33, 11, 87],
                 [16, 28, 66, 67],
                 [73, 15, 90, 77],
                 [80, 25, 96, 80]])
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-04-12
            • 2015-01-15
            • 1970-01-01
            • 2014-05-26
            • 2019-05-13
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多