PicturesToPicture/main.py

131 lines
4.3 KiB
Python
Raw Normal View History

2024-07-19 16:59:43 +00:00
import os
import pickle
from typing import List
from PIL import Image, ImageFile
import numpy as np
ImageFile.LOAD_TRUNCATED_IMAGES = True
target_path = input('Input relative path for target image: ')
Image.open(target_path)
user_input = input('Input segment width count (Higher=more pictures used. Default = 40): ')
global width_segments_count
try:
width_segments_count = int(user_input)
except:
width_segments_count = 40
user_input = input('Input segment height count (Higher=more pictures used. Default = 40): ')
global height_segments_count
try:
height_segments_count = int(user_input)
except:
height_segments_count = 40
user_input = input('Input quality for filling pictures (1=default, 2=double the size): ')
global FILLING_QUALITY
try:
FILLING_QUALITY = int(user_input)
except:
FILLING_QUALITY = 1
class PictureInfos:
def __init__(self, image_path, color, used):
self.image_path = image_path
self.color = color
self.used = used
def get_average_color(image_path):
with Image.open(image_path) as img:
img = img.convert('RGB')
np_image = np.array(img)
avg_color = np.mean(np_image, axis=(0,1))
return avg_color
def get_color_space_array(target_image_path):
with Image.open(target_image_path) as img:
global PIXELS_TO_FILL_WIDTH
global PIXELS_TO_FILL_HEIGHT
PIXELS_TO_FILL_WIDTH = int(np.floor(img.size[0]/width_segments_count))
PIXELS_TO_FILL_HEIGHT = int(np.floor(img.size[1]/height_segments_count))
img = img.convert('RGB')
matrix = np.zeros((height_segments_count, width_segments_count, 3))
for y in range(height_segments_count):
for x in range(width_segments_count):
pixels = []
for i in range(PIXELS_TO_FILL_HEIGHT):
for j in range(PIXELS_TO_FILL_WIDTH):
r,g,b = (img.getpixel((x*PIXELS_TO_FILL_WIDTH + j,y*PIXELS_TO_FILL_HEIGHT + i)))
pixels.append([r,g,b])
matrix[y][x]= np.mean(pixels, axis=0)
return matrix
def get_picture_names(file_path):
return os.listdir(file_path)
def get_closest(target):
image: PictureInfos
closest = np.inf
closest_path = ''
for image in allPictures:
if not image.used:
color = image.color
delta = np.sqrt(((target[0]-color[0])**2)+((target[2]-color[1])**2)+((target[2]-color[2])**2))
if(delta == 0):
# image.used = True
return image.image_path
if (delta<closest and delta>0) or (delta>closest and delta<0):
closest = delta
closest_path = image.image_path
return closest_path
source_categories = os.listdir('./101_ObjectCategories')
if 'allPictures.pkl' not in os.listdir():
allPictures = list()
print('Getting all pictures')
for category in source_categories:
imgs_path = './101_ObjectCategories/'+category
category_images = get_picture_names(imgs_path)
for img in category_images:
img_path = imgs_path +'/'+img
allPictures.append(PictureInfos(img_path, get_average_color(img_path), False))
print(category,'done')
with open('allPictures.pkl', 'wb') as file:
pickle.dump(allPictures, file)
print('done')
else:
with open('allPictures.pkl', 'rb') as file:
allPictures = pickle.load(file)
print('Segmenting target')
target = get_color_space_array(target_path)
print('Segmenting done')
# print((int(width_segments_count*PIXELS_TO_FILL_WIDTH*FILLING_QUALITY), int(height_segments_count*PIXELS_TO_FILL_HEIGHT*FILLING_QUALITY)))
new_im = Image.new('RGB', (int(width_segments_count*PIXELS_TO_FILL_WIDTH*FILLING_QUALITY), int(height_segments_count*PIXELS_TO_FILL_HEIGHT*FILLING_QUALITY)))
layer_offset = 0
for layer in target:
segment_offset = 0
for segment in layer:
closest = get_closest(segment)
closest_img = Image.open(closest)
closest_img = closest_img.resize((PIXELS_TO_FILL_WIDTH*FILLING_QUALITY, PIXELS_TO_FILL_HEIGHT*FILLING_QUALITY))
new_im.paste(closest_img, (segment_offset*PIXELS_TO_FILL_WIDTH*FILLING_QUALITY, layer_offset*PIXELS_TO_FILL_HEIGHT*FILLING_QUALITY))
segment_offset +=1
layer_offset += 1
print(layer_offset,'Layer done')
new_im.show()
new_im.save('final.jpg')