Python PIL - Resizing Images Without Keeping Aspect Ratio - python

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.

Related

How do you save the images that are embedded in the placeholders of a pptx file using python?

I can extract all the images from the shapes of a slide, as shown in the code below. The problem comes when an image is embedded in a placeholder. I have no idea how to get the images from those placeholders, and the documentation to me isn't clear.
Note also that I have a minimum width limit for the kind of images I want, hence I have "shape.width > 250000" in the code
import os
import pptx
from pptx.enum.shapes import MSO_SHAPE_TYPE
ppFileName = "Test.pptx"
directory = os.path.dirname(__file__)
imageDirectory = directory + "\\Images " + ppFileName.replace(".pptx","")
if not os.path.exists(imageDirectory):
os.makedirs(imageDirectory)
def saveImage(shape,slideNumber,imageNumber):
image = shape.image
imageBytes = image.blob
imageFileName = f"Slide {slideNumber} Image {imageNumber}.{image.ext}"
imagePath = imageDirectory + "\\" + imageFileName
with open(imagePath, 'wb') as file:
file.write(imageBytes)
imageNumber += 1
prs = pptx.Presentation(directory + "\\" + ppFileName)
slides = prs.slides
slideNumber = 0
for slide in slides:
imageNumber = 0
for shape in slide.shapes:
if shape.shape_type == MSO_SHAPE_TYPE.PICTURE and shape.width > 250000:
saveImage(shape,slideNumber,imageNumber)
elif shape.shape_type == MSO_SHAPE_TYPE.GROUP and shape.width > 250000:
for s in shape.shapes:
saveImage(s,slideNumber,imageNumber)
slideNumber += 1
Alright, I figured it out.
Just added these three lines of code:
for shape in slide.placeholders:
if hasattr(shape, "image") and shape.width > 250000:
saveImage(shape,slideNumber,imageNumber)

Return multiple values to script

In the script below I import some pictures that I want to segmentate. The segmentation is done withe the line:
mask = cv.inRange(blur0, low_yellow, high_yellow)
As you can see, normally the low_yellow and high_yellow is given. But depending the color of the pictures, I need a different segmentation. So, I created a listbox in Tkinter with the different colors. When I select some item in the listbox, I want to make a return value who fills in the low_yellow and the high_yellow. So 2 different return values. I did already some trail and error, but couldn't find the solution. My question is, is it possible to make 2 different renturn values and hwo?
from tkinter import *
from tkinter import filedialog
import tkinter as tk
import datetime
import cv2 as cv
import glob
import numpy as np
import pandas as pd
from colormath.color_objects import sRGBColor, xyYColor, LabColor, XYZColor
from colormath.color_conversions import convert_color
import os
# create folder for subfolders
Foldername = 'Kleurmeting_output'
mainfolder = os.getcwd() + '\\' + Foldername
if not os.path.exists(mainfolder):
os.makedirs(mainfolder)
def Innovator(ImagePath, SavePath, LowY, HighY):
dfs = []
for file in glob.glob(ImagePath):
print(file)
img = cv.imread(file)
scale_percent = 60
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
dim = (width, height)
imgr = cv.resize(img, dim, interpolation=cv.INTER_AREA)
hsv = cv.cvtColor(imgr, cv.COLOR_BGR2HSV)
blur0 = cv.medianBlur(hsv, 11)
#low_yellow = np.array([10, 42, 210])
#high_yellow = np.array([30, 255, 255])
low_yellow = LowY
high_yellow = HighY
print(low_yellow)
print(high_yellow)
mask = cv.inRange(blur0, low_yellow, high_yellow)
res = cv.bitwise_and(imgr, imgr, mask=mask)
fname = os.path.splitext(os.path.basename(file))[0]
# print(fname)
Imagefolder = str(SavePath) + '\\' + 'Gesegmenteerde afbeelding'
if not os.path.exists(Imagefolder):
os.makedirs(Imagefolder)
cv.imwrite(str(SavePath) + f'/Gesegmenteerde afbeelding/{fname}.jpg', res)
result_df = pd.DataFrame()
#FileNames = ['Mean']
def run_command():
if Most_Recent == 0: # Geen selectie
print("Select a folder")
elif Most_Recent == 'Image': # Afbeelding
if Listb.get(ANCHOR) == '':
print("Select the potato type")
else:
# Creates subfolder
d = datetime.datetime.now()
SaveFolder = os.getcwd() + '\\' + Foldername + '\\' + str(d.date()) + '_Change_name_later1'
else:
# Folder
if Listb.get(ANCHOR) == '':
print("Select the potato type")
else:
# Creates subfolder
d = datetime.datetime.now()
SaveFolder = os.getcwd() + '\\' + Foldername + '\\' + str(d.date()) + '_Change_name_later'
if not os.path.exists(SaveFolder):
os.makedirs(SaveFolder)
#SavedImage = SaveFolder + '\\' + 'Gesegmenteerde afbeelding' + '*.jpg'
ScriptPath = New_Method_Script_Parser((Listb.get(ANCHOR)))
print(ScriptPath)
Innovator(ImagePath= FolderPath, SavePath= SaveFolder, LowY=ScriptPath, HighY=ScriptPath)
def New_Method_Script_Parser(ListValue):
if ListValue == 'Wit':
return LowY(10, 40, 220), High(30, 255, 255)
elif ListValue == 'Licht geel':
return "--LowY 10 42 210 --HighY 30 255 255"
elif ListValue == 'Geel':
return "--LowY 10 42 200 --HighY 30 255 255"
elif ListValue == 'Donker geel':
return "--LowY 10 42 190 --HighY 30 255 255"
Listb = Listbox(root)
Listb.insert(0, "Wit")
Listb.insert(1, "Licht geel")
Listb.insert(2, "Geel")
Listb.insert(3, "Donker geel")
Listb.place(x=100, y=100)

How do you add a black background to text in Python PIL?

I'm looking to put black backgrounds on text using PIL in Python that automatically adjust to the width and height of the text.
Currently, I have code that constructs the text at equal distances from each other. How would I now put a black background on each line?
font_fname = r'user\arial.ttf'
font_size = 50
font = ImageFont.truetype(font_fname, font_size)
text = 'This is a picture of a dolphin having fun'
text_items = wrap(text, 25)
for i in range(4):
try:
number = str(i)
item = text_items[i]
exec(str("line" + number + ' = ''"""' + item + '"""'))
except:
pass
spacing = spacing + 30
par_spacing = 40
for i in range(len(opening_par_items) + 1):
line_number = str(i)
try:
exec("draw.text((130, " + str(spacing) + "), line_" + line_number + ", font=font , fill='rgb(255, 255, 255)')")
spacing = spacing + par_spacing
except:
pass

saving random images in separate folder in python

I am facing a little problem,
actually I have a function which generates so many frames from a video that I provided to my code which then saves in a specific folder , then I access some frames from that folder by using RND (random ) command , now what I want is that those random frames which my code pick randomly should also save in some other folder, for example, if there are 300 frames and my code pick 15 frames randomly from those 300 frames then these 15 frames must also save in some other separate folder .
This is my code,
def video_frames(nameof_video,frame_savelocation,cropimages_save):
vidcap = cv2.VideoCapture(nameof_video)
success, image = vidcap.read()
print(success)
count = 1
success = True
while success:
success, image = vidcap.read()
cv2.imwrite(frame_savelocation+"/%d.jpg" % count, image)
# save frame as JPEG file
# if cv2.waitKey(10) == 27: # exit if Escape is hit
# break
if count == 0:
break
count += 1
print("frames saved in the desired location!!!!!")
##### crop faces from frame and save them----###
for r in range(1, 15):
random_imagecrop(frame_savelocation, cropimages_save) #-----> function called
return
def random_imagecrop(frame_savelocation,cropimages_save):
#b=1
crop_faces_path = frame_savelocation
list_frames = os.listdir(crop_faces_path) # dir is your directory path
number_files = len(list_frames)
rnd = random.randint(1, number_files)
print("random:", rnd)
image = face_recognition.load_image_file(frame_savelocation + "/" + str(rnd) + ".jpg")
#pil_image.save("Datasets/randomimg" + "/" + str(b) + ".jpg")
#b=b+1
# Find all the faces in the image
face_locations = face_recognition.face_locations(image)
check = os.listdir(cropimages_save) # dir is your directory path
already_prsntimg = len(check)
a = 1+already_prsntimg
for face_location in face_locations:
# Print the location of each face in this image
top, right, bottom, left = face_location
# print("A face is located at pixel location Top: {}, Left: {}, Bottom: {}, Right: {}".format(top, left, bottom, right))
# You can access the actual face itself like this:
face_image = image[top:bottom, left:right]
pil_image = Image.fromarray(face_image)
# pil_image.show()
pil_image.save(cropimages_save + "/" + str(a) + ".jpg")
a = a + 1
print("--> Images saved successfully...!!!")
# a=a+len(face_locations)
return
You can use os.chdir('output') to change the working directory to the output directory and then write the image. Then to return to the original directory to pick your random images use os.chdir('../').

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