How can I efficiently place an RGB numpy array with an image environment?
I have RGB images that have already been rescaled so that the longer edge becomes 256 pixels, now I want to place a border with the average RGB values โโof this image so that the resulting image is always 256x256 pixels.
This code is already working, but I'm sure there might be an easier and more elegant way to do it:
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 (More information):
source to share
You can do it easily:
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 your specific 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:
source to share
Calculating the median can be done with median = np.median(img.reshape(-1, 3), axis=0)
or something similar, see this answer .
Subscription can be done with one line per side, something like img[:leftPad,:,:] = median
. Check out the broadcasting rules .
source to share