Resizing an image in PIL - python

I have the following function which takes an image and then returns it in three sizes. Another function then uploads those images to Amazon S3. It seems to me like there is some redundancy in how the file is being saved -
def resize_image(image, size_as_tuple):
"""
Example usage: resize_image(image, (100,200))
"""
image_as_string=""
for c in image.chunks():
image_as_string += c
imagefile = cStringIO.StringIO(image_as_string)
image = Image.open(imagefile)
if image.mode not in ("L", "RBG"):
image = image.convert("RGB")
filename = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(14)) + ".jpg"
height, width = size_as_tuple[0], size_as_tuple[1]
image.thumbnail((height, width), Image.ANTIALIAS)
imagefile = open(os.path.join('/tmp', filename), 'w')
image.save(imagefile, 'JPEG')
imagefile = open(os.path.join('/tmp', filename), 'r')
content = File(imagefile)
return (filename, content)
Is there a way to improve this?

You could replace:
height, width = size_as_tuple[0], size_as_tuple[1]
image.thumbnail((height, width), Image.ANTIALIAS)
with
image.thumbnail(size_as_tuple, Image.ANTIALIAS)
(especially since width and height are swapped; it should be width, height = size_as_tuple)
And you don't need the open(). image.save(os.path.join('/tmp', filename)) is enough.

Related

Why only the first image is added to my dataframe in this loop?

I am trying to read images from one directory and read their correspondant txt files containing the label and bounding box coordinates from another directory, then create a mask and store all these mask for each image in another dataframe.
The problem is only the first loop is executed in my code. (i.e in the mask_images dataset only the first image is stored)
here is my code:
mask_images = [] # DATASET FOR GRAYSCALE IMAGES
RGB_images = [] # DATASET FOR RGB IMAGES
for root, dirnames, filenames in os.walk("dataset/test/images"):
for imgname in filenames:
if re.search("\.(jpg|jpeg|JPEG|png|bmp|tiff)$", imgname):
imgpath = os.path.join(root, imgname)
name = os.path.splitext(imgname)
name = name[0] + ".txt"
img = cv2.imread(imgpath)
rgb_image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
RGB_images.append(rgb_image)
mask = np.zeros((img.shape[0], img.shape[1]), dtype = np.uint8)
#plt.imshow(mask, cmap = 'gray')
#print(imgname)
#print(imgpath)
for root, dirnames, filenames in os.walk("dataset/test/detection_labels"):
for txtname in filenames:
if name == txtname:
#print(txtname)
txtpath = os.path.join(root, txtname)
#print(txtpath)
with open(txtpath,'r') as f:
lines = f.readlines()
print(lines)
for line in lines:
#print(line)
coords = [float(coords) for coords in re.findall(r'-?\d+\.?\d*', line)]
coords[1] = np.int_(coords[1] * 2000)
coords[2] = np.int_(coords[2] * 2000)
coords[3] = np.int_(coords[3] * 2000)
coords[4] = np.int_(coords[4] * 2000)
print(coords)
mask = cv2.rectangle(mask, pt1 = (coords[1], coords[2]), pt2 = (coords[1] + coords[3], coords[2] + coords[4]), color = (255,255,255), thickness = -1)
f.close()
mask_images.append(mask)

Join extracted/splitted patches to reconstruct an image

i used this code below to extract patches from a image.
extract code:
import os
import glob
from PIL import Image
Image.MAX_IMAGE_PIXELS = None # to avoid image size warning
imgdir = "/path/to/image/folder"
filelist = [f for f in glob.glob(imgdir + "**/*.png", recursive=True)]
savedir = "/path/to/image/folder/output"
start_pos = start_x, start_y = (0, 0)
cropped_image_size = w, h = (256, 256)
for file in filelist:
img = Image.open(file)
width, height = img.size
frame_num = 1
for col_i in range(0, width, w):
for row_i in range(0, height, h):
crop = img.crop((col_i, row_i, col_i + w, row_i + h))
name = os.path.basename(file)
name = os.path.splitext(name)[0]
save_to= os.path.join(savedir, name+"_{:03}.png")
crop.save(save_to.format(frame_num))
frame_num += 1
Now i want to reconstruct this imagem from all those patches extracted before, i've tried 2 diffenret codes
so my DB is 120x256x256x3 extracted patches, theres 120 patches to fit in 3840x2048 shape..:
patches = []
for directory_path in glob.glob('D:\join_exemplo'):
for img_path in glob.glob(os.path.join(directory_path, "*.png")):
img = cv2.imread(img_path,1)
patches.append(img)
input_patches = np.array(patches)
first i've tried sklearn.feature_extraction.image importing reconstruct_from_patches_2d, but got a black image:
reconstruct = reconstruct_from_patches_2d(input_patches, input_image)
reconstruct = reconstruct.astype(np.uint8)
Image.fromarray(reconstruct, 'RGB').save(r'D:\join_exemplo\re\re3.png')
also tried, this below but got a grayscale tone pattern image
input_image = (3840,2048,3)
reconstructed_arr = np.zeros(shape=(3840,2048,3))
#%%
>>> step = 256
>>> for x in range(img.shape[0]):
for y in range(img.shape[1]):
x_pos, y_pos = x * step, y * step
reconstructed_arr[x_pos:x_pos + 512, y_pos:y_pos + 512] = img[x, y, 0, ...]
>>> (input_image == reconstructed_arr).all()
True
cv2.imwrite(r'D:\join_exemplo\re\re.png',reconstructed_arr)
Can someone see whats wrong? sorry about my bad english

How to resize the images in order to have the same dimension in the end?

I need to resize the the images within a folder in Python. By using the code below, how can I have the same dimension of them in the end?
from PIL import Image
import os
path = "E:/Jupyter-Project/images/test/car/"
resize_ratio = 0.5
def resize_aspect_fit():
dirs = os.listdir(path)
for item in dirs:
if item == '.jpg':
continue
if os.path.isfile(path+item):
image = Image.open(path+item)
file_path, extension = os.path.splitext(path+item)
new_image_height = int(image.size[0] / (1/resize_ratio))
new_image_length = int(image.size[1] / (1/resize_ratio))
image = image.resize((new_image_height, new_image_length), Image.ANTIALIAS)
image.save(file_path + "_small" + extension, 'JPEG', quality=90)
resize_aspect_fit()
The code works perfect, but some images are 3 K, others are 4... and I do not really know how to modify it in order to achieve the same dimension.

Can't paste image in square with a loop

I can't achieve to paste images in a square form (if I choose 9 for n_album, I should have a 3x3 collage). It only works for 1x1, if it's more it will paste the same image where another image is supposed to be.
Here is my code:
def make_montage(n_album, path):
x_offset = width #Constant resized image width
y_offset = height #Constant resized image height
c = []
x = 0
img = Image.new('RGB', (n_album*height + y_offset*2, n_album*width + x_offset*2), color = (0, 0, 0))
for file_name in os.listdir(path):
print(f"Processing {file_name}")
c.append(file_name)
print(f"root of n_album = {int(math.sqrt(n_album))}")
#Loop in square
for i in range(int(math.sqrt(n_album))):
for j in range(int(math.sqrt(n_album))):
try:
cover = Image.open(os.path.join(path, c[i + j]))
print(f"Pasting {str(c[i + j])}")
img.paste(cover, (int(i * height + y_offset), int(j * width + x_offset)))
except:
print("Je code mal mdr")
img.save(f'{path}\\{n_album}x{n_album}_musical.png')
#Clean
for file_name in os.listdir(path):
if file_name != f'{n_album}x{n_album}_musical.png':
print(f"Deleting {file_name}")
os.remove(os.path.join(path, file_name))
And here's a result for a 2x2 with images of (the order it was supposed to be pasted): Link, Mario, Princess Zelda, Peach.
I see several issues in your code:
In your method declaration, you should also pass the (desired) width and height of each image. (As is, your method assumes, that width and height are properly set outside.) This has also the advantage, that you can resize your images on-the-fly within your loop.
You don't pay attention, when to use n_album and when int(math.sqrt(n_album)). (See your 2x2 montage: You obviously initialized a 4x4 montage.) For the latter, create a variable like n_per_axis, so you don't have this math.sqrt term all the time.
In your nested loop, you have i = 1, 2, 3, and j = 1, 2, 3. Using c[i + j] then isn't the correct way to access the proper images from c. (In your 2x2 montage, you get (0 + 1) = 1 and (1 + 0) = 1, so Mario two times.) Set up a (global) image counter (let's say k), and increment it with each entering of the inner loop.
Don't post code including deleting of files, if that's not the main point of your question.
Here's your code with some modifications:
def make_montage(n_album, path, width, height): # <-- Width, height!?
x_offset = width
y_offset = height
c = []
n_per_axis = int(math.sqrt(n_album))
img = Image.new('RGB',
(n_per_axis*height + y_offset*2, # <-- n per axis!?
n_per_axis*width + x_offset*2), # <-- n per axis!?
color=(0, 0, 0))
for file_name in os.listdir(path):
print(f"Processing {file_name}")
c.append(file_name)
print(f"root of n_album = {n_per_axis}")
# Loop in square
k = -1 # <-- Image counter
for i in range(n_per_axis):
for j in range(n_per_axis):
k += 1
try:
cover = Image.open(os.path.join(path, c[k]))\
.resize((width, height)) # <-- Might be omitted here
print(f"Pasting {str(c[k])}")
img.paste(cover,
(int(i * height + y_offset),
int(j * width + x_offset)))
except:
print("Je code mal mdr")
img.save(f'{path}\\{n_per_axis}x{n_per_axis}_musical.png') # <-- n per axis!?
for file_name in os.listdir(path):
if file_name != f'{n_per_axis}x{n_per_axis}_musical.png':
print(f"Deleting {file_name}")
#os.remove(os.path.join(path, file_name))
Using
make_montage(9, 'path_with_nine_images/', 100, 100)
I get the following output:
Hope that helps!

Some problems at using python for making thumbnails

I'm studying image classification with python and tensorflow. Before classify image dataset, I have to do reform my images to thumbnails. When I changed my images to thumbnails, thumbnails created all red color. Just like this.
enter image description here
It is chest x-ray images downloaded from here (https://ceb.nlm.nih.gov/repositories/tuberculosis-chest-x-ray-image-data-sets/). Montgomery County X-ray Set. Why is it happend? Whats the problem?
My image to thumbnail python code is here. python 3.5 used.
def _image_to_thumbnail(self):
size = (200, 200)
for file in [filename for filename in os.listdir(ImageToCSV.__IMAGE_PATH) if
re.search('[0-9]+\.(jpg|jpeg|png)', filename) is not None]:
try:
# print(file)
filename, ext = os.path.splitext(file)
new_img = Image.new("RGB", (200, 200), "black")
im = Image.open(ImageToCSV.__IMAGE_PATH + str(file))
im.thumbnail(size, Image.ANTIALIAS)
load_img = im.load()
load_newimg = new_img.load()
i_offset = (200 - im.size[0]) / 2
j_offset = (200 - im.size[1]) / 2
for i in range(0, im.size[0]):
for j in range(0, im.size[1]):
load_newimg[i + i_offset, j + j_offset] = load_img[i, j]
if ext.lower() in ('.jpeg', '.jpg'):
new_img.save(ImageToCSV.__IMAGE_PATH + 'resized\\' + str(filename) + '.jpeg')
elif ext.lower() == '.png':
new_img.save(ImageToCSV.__IMAGE_PATH + 'resized\\' + str(filename) + '.png')
except Exception as e:
print(str(file), e)

Categories

Resources