【问题标题】:How can I efficently pad an RGB numpy array with the median of the image?如何有效地用图像的中值填充 RGB numpy 数组?
【发布时间】:2015-07-26 10:31:41
【问题描述】:

我的 RGB 图像已经过重新缩放,长边变为 256 像素,现在我想用该图像的 RGB 中值填充边框,使生成的图像始终为 256x256 像素。

这段代码已经可以工作了,但我相信还有更简单更优雅的方法来做到这一点:

img = loadAndFitImage(filePath, maxSideLength=256, upscale=True)
shp = img.shape
#the shp in this case is typically (256,123,3) or (99,256,3)

leftPad = (256 - shp[0]) / 2
rightPad = 256 - shp[0] - leftPad
topPad = (256 - shp[1]) / 2
bottomPad = 256 - shp[1] - topPad

# this part looks like there might be a way to do it with one median call instead of 3:
median = (np.median(img[:, :, 0]),np.median(img[:, :, 1]),np.median(img[:, :, 2]))

img = np.lib.pad(img, ((leftPad,rightPad),(topPad,bottomPad),(0,0)),
 'constant',constant_values=0)

if leftPad > 0:
    img[:leftPad,:,0].fill(median[0])
    img[:leftPad,:,1].fill(median[1])
    img[:leftPad,:,2].fill(median[2])
if rightPad > 0:
    img[-rightPad:,:,0].fill(median[0])
    img[-rightPad:,:,1].fill(median[1])
    img[-rightPad:,:,2].fill(median[2])
if topPad > 0:
    img[:,:topPad,0].fill(median[0])
    img[:,:topPad,1].fill(median[1])
    img[:,:topPad,2].fill(median[2])
if bottomPad > 0:
    img[:,-bottomPad:,0].fill(median[0])
    img[:,-bottomPad:,1].fill(median[1])
    img[:,-bottomPad:,2].fill(median[2])

编辑(附加信息):

  • 这是最终结果的样子:

  • 这不应该是这样的(每列的中位数):

【问题讨论】:

    标签: python numpy image-processing


    【解决方案1】:

    您可以通过以下方式轻松完成:

    import numpy as np
    
    a = np.asarray([[1,2,3,4,5,6],
         [8,4,5,6,7,7],
         [1,2,3,4,5,6],
         [1,2,3,4,5,6],
         [1,2,3,4,5,6],
         [1,2,3,4,5,6]])
    
    b = a * 3
    c = a * 4
    d = (a,b,c)
    
    im = np.asarray([np.pad(x, (2,), 'constant', constant_values=(np.median(x) ,)) for x in d])
    print im
    

    输出:

    [[[ 4  4  4  4  4  4  4  4  4  4]
      [ 4  4  4  4  4  4  4  4  4  4]
      [ 4  4  1  2  3  4  5  6  4  4]
      [ 4  4  8  4  5  6  7  7  4  4]
      [ 4  4  1  2  3  4  5  6  4  4]
      [ 4  4  1  2  3  4  5  6  4  4]
      [ 4  4  1  2  3  4  5  6  4  4]
      [ 4  4  1  2  3  4  5  6  4  4]
      [ 4  4  4  4  4  4  4  4  4  4]
      [ 4  4  4  4  4  4  4  4  4  4]]
    
     [[12 12 12 12 12 12 12 12 12 12]
      [12 12 12 12 12 12 12 12 12 12]
      [12 12  3  6  9 12 15 18 12 12]
      [12 12 24 12 15 18 21 21 12 12]
      [12 12  3  6  9 12 15 18 12 12]
      [12 12  3  6  9 12 15 18 12 12]
      [12 12  3  6  9 12 15 18 12 12]
      [12 12  3  6  9 12 15 18 12 12]
      [12 12 12 12 12 12 12 12 12 12]
      [12 12 12 12 12 12 12 12 12 12]]
    
     [[16 16 16 16 16 16 16 16 16 16]
      [16 16 16 16 16 16 16 16 16 16]
      [16 16  4  8 12 16 20 24 16 16]
      [16 16 32 16 20 24 28 28 16 16]
      [16 16  4  8 12 16 20 24 16 16]
      [16 16  4  8 12 16 20 24 16 16]
      [16 16  4  8 12 16 20 24 16 16]
      [16 16  4  8 12 16 20 24 16 16]
      [16 16 16 16 16 16 16 16 16 16]
      [16 16 16 16 16 16 16 16 16 16]]]
    

    或者在你的特殊情况下:

    import numpy as np
    from PIL import Image
    
    filePath = '/home/george/Desktop/img.jpg'
    
    Img = Image.open(filePath)
    img = np.asarray(Img, np.int)
    shp = np.shape(img)
    img = img.transpose(2,0,1).reshape(3,215,215)
    
    leftPad = round(float((255 - shp[0])) / 2)
    rightPad = round(float(255 - shp[0]) - leftPad)
    topPad = round(float((255 - shp[1])) / 2)
    bottomPad = round(float(255 - shp[1]) - topPad)
    pads = ((leftPad,rightPad),(topPad,bottomPad))
    
    img_arr = np.ndarray((3,255,255),np.int)
    for i,x in enumerate(img):
        cons = np.int(np.median(x))
        x_p = np.pad(x,pads,
                    'constant', 
                     constant_values=cons)
        img_arr[i,:,:] = x_p
    
    im_shp = np.shape(img_arr)
    ii = np.uint8(img_arr).transpose(1,2,0)
    
    im = Image.fromarray(np.array( (ii) ))
    im.show()
    im.save((filePath), "JPEG")
    

    输出:

    【讨论】:

    • 谢谢!但是看看你的例子,中位数似乎是按行或每列计算的。我正在寻找的是整个填充区域被整个图像的中值填充。另外,我的特别困难是理解正确的语法来为步骤中的所有 3 个通道执行此操作。
    • 感谢您的更新!问题是这适用于 1 通道灰度图像,但我特别在寻找处理 3 通道 RGB 阵列的解决方案。
    • 不幸的是,这仍然不起作用。上例中数组的形状是 (3,6,6),而在使用的图像格式中,它是 (6,6,3) - 我已经尝试过改变它以使其工作,但我的 Python 知识是那部分还很初级,所以到目前为止我失败了。
    • @Quasimondo 这是一项艰巨的工作,但我不能让你自己解决这个问题。 :)
    • 我的快乐伙伴!无论如何,一些 Kaggle 工作或其他工作? :)
    【解决方案2】:

    我也在为此苦苦挣扎,并想出了一个优雅的答案:

    color = np.median(img, axis=(0,1)) img = np.stack([np.pad(img[:,:,c], pad, mode='constant', constant_values=color[c]) for c in range(3)], axis=2)

    【讨论】:

    • pad 的论据是什么?
    • 如果要填充 2 行 2 列,则为 (2,)
    【解决方案3】:

    可以使用median = np.median(img.reshape(-1, 3), axis=0) 或类似的方法计算中位数,请参阅this answer

    填充可以用每边一行来完成,比如img[:leftPad,:,:] = median。看看broadcasting rules

    【讨论】:

      猜你喜欢
      • 2021-06-24
      • 1970-01-01
      • 2020-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-26
      • 2014-09-21
      • 2020-07-30
      相关资源
      最近更新 更多