[英]How can I efficently pad an RGB numpy array with the median of the image?
我有已經重新縮放的 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])
編輯(附加信息):
您可以通過以下方式輕松完成:
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")
輸出:
我也在努力解決這個問題,並找到了一個優雅的答案:
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)
派對遲到了,但這里有另一個建議:
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
使用示例:
img = np.zeros((11,21, 3), dtype=np.uint8) # create simple black image
img = pad_image(img, (128,0,0), .25)
plt.imshow(img)
哪個輸出:
對於這種特殊情況,正如其他人所說,您需要在填充之前計算中值顏色:
color = np.median(img, axis=(0,1))
我相信這可以使用單個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.