简体   繁体   English

如何用图像的中值有效填充 RGB numpy 数组?

[英]How can I efficently pad an RGB numpy array with the median of the image?

I have RGB images which have already been rescaled so that the longer edge becomes 256 pixels, now I want to pad the border with the median RGB values of that image so the resulting image is always 256x256 pixels.我有已经重新缩放的 RGB 图像,因此较长的边缘变为 256 像素,现在我想用该图像的中值 RGB 值填充边框,因此生成的图像始终为 256x256 像素。

This code already works, but I am sure there could be a simpler more elegant way to do this:这段代码已经可以工作了,但我相信可以有一种更简单、更优雅的方法来做到这一点:

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])

Edit (Additional Info):编辑(附加信息):

  • This is how the final result should look like:这是最终结果的样子:

  • 期望:

  • This is how it should not look like (median per column):这是它不应该的样子(每列的中位数):

  • 不受欢迎的:

You can do it easily with: 您可以通过以下方式轻松完成:

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

Output: 输出:

[[[ 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]]]

Or in you particular case: 或者在你的特殊情况下:

原始图像

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")

Output: 输出:

中位填充图像

我也在努力解决这个问题,并找到了一个优雅的答案:

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)

Calculating the median can be done with median = np.median(img.reshape(-1, 3), axis=0) or something similar, see this answer . 计算中位数可以使用median = np.median(img.reshape(-1, 3), axis=0)或类似的东西来完成,请参阅此答案

The padding can probably be done with a single line per side, something like img[:leftPad,:,:] = median . 填充可能可以通过每边一行完成,类似于img[:leftPad,:,:] = median Have a look at the broadcasting rules . 看看广播规则

Late to the party but here goes another suggestion:派对迟到了,但这里有另一个建议:

def pad_image(img, color, border_width=.1):
    """
    pads image img with given color. 
    Color must be in same color space as image (usually, RGB). 
    border_width is expected to be the fraction of padding you want to add,
    with respect to the shorter dimension of the image.
    """
    h, w, c = img.shape

    # compute the number of pixels you'll pad
    border = int(float(min(h, w) * border_width))  

    # compute the "new background"
    result = np.full((h+2*border, w+2*border, c), color, dtype=img.dtype)
    
    # now fill this "new background" with your original image in the center
    result[border:-border, border:-border] = img

    return result

Usage example:使用示例:

img = np.zeros((11,21, 3), dtype=np.uint8)  # create simple black image

img = pad_image(img, (128,0,0), .25)

plt.imshow(img)

Which outputs this:哪个输出:

输出图像:被深红色边框包围的黑色图像

For this particular case, as other said, you need to compute the median color before padding:对于这种特殊情况,正如其他人所说,您需要在填充之前计算中值颜色:

color = np.median(img, axis=(0,1))

I believe that this can be done more simply using a single np.pad() call:我相信这可以使用单个np.pad()调用更简单地完成:

  value = np.median(image, axis=(0, 1))
  pad = 2
  cval = np.array([[value, value], [value, value], [0, 0]], dtype=object)  # Ragged.
  image2 = np.pad(image, ((pad, pad), (pad, pad), (0, 0)), constant_values=cval)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM