Some problems at using python for making thumbnails - python

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)

Related

Read all images from subfolder, detect text them and save them with their original name and folder in Python?

I have a train folder and it contains 20 classes and each class contains different images in .png and .jpg format. I have tested on one image and it works fine and now I want to apply this process on all images by maintaining folder and class structure. After the detected text, we have a folder with a "final" name and it contains 20 classes and inside each class contains a detected text image. The detected text code already works fine
Code
my_path = "Path"
files = glob.glob(my_path + '/**/*.jpg', recursive=True)
images = []
each_image = ''
for root, dirs, files in os.walk(my_path, topdown=False):
for file in files:
each_image = file
print(root)
print(dirs)
for file in files:
image_path = file
with open(image_path, 'rb') as image_file:
content = image_file.read()
image = vision.Image(content=content)
response = client.text_detection(image=image)
texts = response.text_annotations
img_openCV = cv2.imread(image_path)
h, w = img_openCV.shape[:2]
print(h, w)
for text in texts:
box_w = abs(text.bounding_poly.vertices[2].x - text.bounding_poly.vertices[0].x)
box_h = abs(text.bounding_poly.vertices[2].y - text.bounding_poly.vertices[0].y)
if box_h * box_w > thres * h * w:
continue
if (text.bounding_poly.vertices[2].x - text.bounding_poly.vertices[0].x) > (w / 2):
print('ebug width ')
print(text.bounding_poly.vertices[2].x - text.bounding_poly.vertices[0].x)
else:
imagee = cv2.rectangle(img_openCV, (text.bounding_poly.vertices[0].x, text.bounding_poly.vertices[0].y),
(text.bounding_poly.vertices[2].x, text.bounding_poly.vertices[2].y), (0, 255, 0),
-1)
print('height, width, color:', text.bounding_poly)
cv2.imwrite(
os.path.join("Path", each_image + str(total_images) + '.png'),
imagee)
total_images += 1
import os, io
import random
from turtle import color
from google.cloud import vision
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import cv2
from text import draw_borders
import glob
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "GoogleVisionAPI.json"
client = vision.ImageAnnotatorClient()
# file_name = '3017.jpg'
# image_folder = './img/'
total_images = 1
thres = 0.5
# Location with subdirectories
my_path = "/Path of whole folder which contains subclasses/"
files = glob.glob(my_path + '/**/*.jpg', recursive=True)
images = []
each_image = ''
# for root, dirs, files in os.walk(my_path, topdown=False):
# for file in files:
# each_image = file
# print(root)
# print(dirs)
for root, dirs, files in os.walk(my_path, topdown=False):
for file in files:
image_path = file
with open(root + "/" + image_path, 'rb') as image_file:
content = image_file.read()
image = vision.Image(content=content)
response = client.text_detection(image=image)
texts = response.text_annotations
img_openCV = cv2.imread(root + "/" + image_path)
h, w = img_openCV.shape[:2]
print(h, w)
for text in texts:
box_w = abs(text.bounding_poly.vertices[2].x - text.bounding_poly.vertices[0].x)
box_h = abs(text.bounding_poly.vertices[2].y - text.bounding_poly.vertices[0].y)
if box_h * box_w > thres * h * w:
continue
if (text.bounding_poly.vertices[2].x - text.bounding_poly.vertices[0].x) > (w / 2):
print('ebug width ')
print(text.bounding_poly.vertices[2].x - text.bounding_poly.vertices[0].x)
else:
imagee = cv2.rectangle(img_openCV,
(text.bounding_poly.vertices[0].x, text.bounding_poly.vertices[0].y),
(text.bounding_poly.vertices[2].x, text.bounding_poly.vertices[2].y),
(0, 255, 0),
-1)
print('height, width, color:', text.bounding_poly)
if root.__contains__("BC"):
cv2.imwrite(os.path.join("/Specific_class", file), imagee)
elif root.__contains__("BK"):
cv2.imwrite(os.path.join("/Specific_class", file), imagee)
elif root.__contains__("CC"):
cv2.imwrite(os.path.join("/Specific_class", file), imagee)
total_images += 1
# cv2.imshow('window_name', imagee)
# cv2.waitKey(0)
# closing all open windows
# cv2.destroyAllWindows()

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!

Python PIL - Resizing Images Without Keeping Aspect Ratio

So I've got a Python script that takes a bunch of images in a folder, and puts them together into arrays (like this). I also have another script that takes the frames of a video and puts them together in arrays. The problem is, the one that takes the frames from a video creates black bars between the images.
Here is the correct image made using the first script, which uses JPEGS:
Here is the wrong image made using the second script, which uses video frames:
Here is the script that makes the correct first image:
import Image
import glob
import os
name = raw_input('What is the file name (excluding the extension) of your video that was converted using FreeVideoToJPGConverter?\n')
x_res = int(raw_input('What do you want the width of your image to be (in pixels)?\n'))
y_res = int(raw_input('What do you want the height of your image to be (in pixels)?\n'))
rows = int(raw_input('How many rows do you want?\n'))
columns = int(raw_input('How many columns do you want?\n'))
images = glob.glob('./' + name + ' (*)/' + name + '*.jpg')
new_im = Image.new('RGB', (x_res,y_res))
x_cntr = 0
y_cntr = 0
if not os.path.exists('./' + name + ' Output/'):
os.makedirs('./' + name + ' Output/')
for x in xrange(0,len(images),1):
if x%(rows*columns) == 0:
new_im.save('./' + name + ' Output/' + str(x) + '.jpg')
new_im = Image.new('RGB', (x_res,y_res))
y_cntr = 0
x_cntr = 0
print str(round(100*(float(x)/len(images)), 1)) + "% Complete"
elif x%rows == 0:
x_cntr = 0
y_cntr = y_cntr + y_res/columns
elif x%1 == 0:
x_cntr = x_cntr + x_res/rows
im = Image.open(images[x])
im = im.resize((x_res/rows + x_res%rows, y_res/columns + y_res%columns), Image.ANTIALIAS)
new_im.paste(im, (x_cntr, y_cntr))
Here is the script that makes the incorrect second image:
import cv2, Image, os
name = raw_input('Video File (With Extension): ')
x_res = int(raw_input('Image Width (Pixels): '))
y_res = int(raw_input('Image Height (Pixels): '))
rows = int(raw_input('Number of Rows: '))
columns = int(raw_input('Number of Columns: '))
vidcap = cv2.VideoCapture(name)
success,im = vidcap.read()
frames = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
new_im = Image.new('RGB', (x_res, y_res))
x_cntr = 0
y_cntr = 0
print str(frames) + " Frames to Join"
if not os.path.exists('./' + name + ' Output/'):
os.makedirs('./' + name + ' Output/')
for x in xrange(0,frames,1):
if x%(rows*columns) == 0:
new_im.save('./' + name + ' Output/' + str(x) + '.jpg')
new_im = Image.new('RGB', (x_res,y_res))
y_cntr = 0
x_cntr = 0
print str(round(100*(float(x)/frames), 1)) + "% Complete"
elif x%rows == 0:
x_cntr = 0
y_cntr = y_cntr + y_res/columns
elif x%1 == 0:
x_cntr = x_cntr + x_res/rows
success,cv2_im = vidcap.read()
if success == True:
cv2_im = cv2.cvtColor(cv2_im,cv2.COLOR_BGR2RGB)
im = Image.fromarray(cv2_im)
im = im.resize((x_res/rows + x_res%rows, y_res/columns + y_res%columns), Image.ANTIALIAS)
new_im.paste(im, (x_cntr, y_cntr))
elif success == False:
new_im.save('./' + name + ' Output/' + str(x) + '.jpg')
print str(round(100*(float(x)/frames), 1)) + "% Complete" #Why isn't this 100%, fix
As you can see, this specific line for resizing the image (to fit the new array of images) is exactly the same in both scripts:
im = im.resize((x_res/rows + x_res%rows, y_res/columns + y_res%columns), Image.ANTIALIAS)
...Except in the first script, the image is opened from a JPEG, and in the second script, the image is taken from a video frame using OpenCV2. If I try this with a different video, the same thing happens. It resizes as if I were using .thumbnail instead of .resize.
So why is there a different output even though they are the same script?
PS: I also don't know why there are more output images on the jpeg script than the video script, but that may be the fault of FreeVideoToJPGConverter (a software); I'm not sure though.

Resizing an image in PIL

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.

Categories

Resources