diff --git a/Makefile b/Makefile index 6d55d78..2edf7f2 100644 --- a/Makefile +++ b/Makefile @@ -77,6 +77,11 @@ maximize_test: cp $(PROJECT_DIR)/data/raw/collections/20180211-130001.jpg $(PROJECT_DIR)/data/isr/input/sample/ docker run -v "$(PROJECT_DIR)/data/isr:/home/isr/data" -v "$(PROJECT_DIR)/../image-super-resolution/weights:/home/isr/weights" -v "$(PROJECT_DIR)/config/config_isr.yml:/home/isr/config.yml" -it isr -d -p -c config.yml +maximize_version_3: + cp $(PROJECT_DIR)/data/raw/collections/20170815-130001.jpg $(PROJECT_DIR)/data/isr/input/version_3/ + cp $(PROJECT_DIR)/data/raw/collections/20180902-100001.jpg $(PROJECT_DIR)/data/isr/input/version_3/ + docker run -v "$(PROJECT_DIR)/data/isr:/home/isr/data" -v "$(PROJECT_DIR)/../image-super-resolution/weights:/home/isr/weights" -v "$(PROJECT_DIR)/config/config_isr.yml:/home/isr/config.yml" -it isr -d -p -c config.yml + ################################################################################# # FLOYDHUB # diff --git a/README.md b/README.md index 9dd8747..db1993e 100644 --- a/README.md +++ b/README.md @@ -57,3 +57,23 @@ Project Organization --------

Project based on the cookiecutter data science project template. #cookiecutterdatascience

+ + +## Size + +original size : 1280x720 +cut size : 48x27 + +inch = 2.54cm +150dpi +300dpi +http://www.altelia.fr/actualites/calculateur-resolution-definition-format.htm +https://fr.wikipedia.org/wiki/Point_par_pouce + + +2880px X 4320px +donne : (en 150 dpi) + +48.77cm x 73.15cm + +bordure de 60px pour 1 cm en 150dpi \ No newline at end of file diff --git a/iss/data/DataBaseManager.py b/iss/data/DataBaseManager.py index c62e818..e993eea 100644 --- a/iss/data/DataBaseManager.py +++ b/iss/data/DataBaseManager.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import numpy as np +import pandas as pd class MysqlDataBaseManager: @@ -84,3 +85,32 @@ CREATE TABLE IF NOT EXISTS `iss`.`pictures_embedding` ( return self.cursor.fetchall() + def select_df(self, req, args): + self.cursor.execute(req, args) + res = self.cursor.fetchall() + df_res = pd.DataFrame(res, columns=self.cursor.column_names) + + return df_res + + def create_posters_table(self, force = False): + if force: + self.cursor.execute("DROP TABLE IF EXISTS `iss`.`posters`;") + + self.cursor.execute(""" +CREATE TABLE IF NOT EXISTS `iss`.`posters` ( + `poster_id` VARCHAR(32), + `version` VARCHAR(5), + `position` VARCHAR(5), + `pictures_id` VARCHAR(15), + UNIQUE KEY `unique_key` (`poster_id`, `version`,`position`, `pictures_id`), + UNIQUE KEY `unique_key_2` (`poster_id`, `version`,`position`) +) ENGINE = MYISAM ; + """) + + def insert_row_poster(self, array): + sql_insert_template = "INSERT INTO `iss`.`posters` (poster_id, version, position, pictures_id) VALUES (%s, %s, %s, %s);" + + self.cursor.executemany(sql_insert_template, array) + self.conn.commit() + + return self.cursor.rowcount diff --git a/iss/exec/posters.py b/iss/exec/posters.py new file mode 100644 index 0000000..0b9f807 --- /dev/null +++ b/iss/exec/posters.py @@ -0,0 +1,241 @@ +import os +import numpy as np +import random +import uuid +import PIL +from PIL import ImageDraw, ImageFont +from iss.init_config import CONFIG +from iss.tools import Tools + + +## +## +## + +## +## Variables globales +## + + +BORDER_SIZE = 30 +O_WIDTH = 1080 +O_HEIGHT = 720 +N_GENERATE = 1 +POSTER_ID = 'secret_santa_lincoln' +CLUSTERS = { + 'horizon_only': [2, 6, 20, 23, 27, 44, 47], + 'horizon_iss': [4, 5, 12, 17, 32, 37, 40], + 'vertical': [1, 22, 34, 38, 45] +} + +COLORS = { + 'x': {'hex': '#f7f9f9', 'rgb': [247, 249, 249]}, + '2x': {'hex': '#bed8d4', 'rgb': [190, 216,212]}, + 'x.2': {'hex': '#78d5d7', 'rgb': [120, 213, 215]}, + 'x.rect': {'hex': '#63d2ff', 'rgb': [99, 210, 255]}, + '2x.bis': {'hex': '#2081c3', 'rgb': [32, 129, 195]} +} + +POSTERS_CONFIG = [{ + "version": 1, + "size": { + 'width': O_WIDTH*4 + BORDER_SIZE*3, + 'height': O_HEIGHT*4 + BORDER_SIZE*3, + 'channel': 3 + }, + "ARGS_SQL": (1, 'simple_conv', 'model_colab'), + "DECOUPAGE": [ + {'origin': [0+BORDER_SIZE, 0+BORDER_SIZE], 'size': [1080*2, 720*2], 'cluster': [6, 23, 27, 44, 47], 'color': '2x', 'position': '1'}, + {'origin': [1080*2+BORDER_SIZE*2, 0+BORDER_SIZE], 'size': [1080-30, 720-30], 'cluster': [4, 12], 'color': 'x', 'position': '2'}, + {'origin': [1080*3+BORDER_SIZE*3-30, 0+BORDER_SIZE], 'size': [1080-30, 720-30], 'cluster': [32, 5, 17], 'color': 'x', 'position': '3'}, + {'origin': [1080*2+BORDER_SIZE*2, 720-30+2*BORDER_SIZE], 'size': [1080-30, 720-30], 'cluster': [1, 22, 34, 38, 45], 'color': 'x', 'position': '4'}, + {'origin': [1080*3+BORDER_SIZE*3-30, 720-30+2*BORDER_SIZE], 'size': [1080-30, 720-30], 'cluster': [6, 23, 27, 44, 47], 'color': 'x', 'position': '5'}, + + {'origin': [0+BORDER_SIZE, 720*2+BORDER_SIZE*2], 'size': [1080-30, 720-30], 'cluster': [39], 'color': 'x', 'position': '6'}, + {'origin': [1080+BORDER_SIZE*2-30, 720*2+BORDER_SIZE*2], 'size': [1080-30, 720-30], 'cluster': [7], 'color': 'x', 'position': '7'}, + {'origin': [0+BORDER_SIZE, 720*3-30+BORDER_SIZE*3], 'size': [1080-30, 720-30], 'cluster': [1, 22, 34, 38, 45], 'color': 'x', 'position': '8'}, + {'origin': [1080+BORDER_SIZE*2-30, 720*3-30+BORDER_SIZE*3], 'size': [1080-30, 720-30], 'cluster': [46], 'color': 'x', 'position': '9'}, + {'origin': [1080*2+BORDER_SIZE*3-30*2, 720*2-30*2+BORDER_SIZE*3], 'size': [1080*2, 720*2], 'cluster': [6, 23, 27, 44, 47], 'color': '2x', 'position': '10'} + ] +}, +{ + "version": 2, + "size": { + 'width': O_WIDTH*4 + BORDER_SIZE*3, + 'height': O_HEIGHT*4 + BORDER_SIZE*3, + 'channel': 3 + }, + "ARGS_SQL": (1, 'simple_conv', 'model_colab'), + "DECOUPAGE": [ + {'origin': [0+BORDER_SIZE, 0+BORDER_SIZE], 'size': [1080*2, 720*2], 'cluster': CLUSTERS['horizon_only'][:4], 'color': '2x', 'position': '1'}, + {'origin': [1080*2+BORDER_SIZE*2, 0+BORDER_SIZE], 'size': [1080-15, 720-15], 'cluster': CLUSTERS['horizon_iss'], 'color': 'x', 'position': '2'}, + {'origin': [1080*3+BORDER_SIZE*3-15, 0+BORDER_SIZE], 'size': [1080-15, 720-15], 'cluster': None, 'picture_ids': ['20170726-004001', '20170723-231002'], 'color': 'x', 'position': '3'}, + {'origin': [1080*2+BORDER_SIZE*2, 720-15+2*BORDER_SIZE], 'size': [1080-15, 720-15], 'cluster': None, 'picture_ids': ['20190101-220001', '20180625-140001', '20180617-112001'], 'color': 'x', 'position': '4'}, + {'origin': [1080*3+BORDER_SIZE*3-15, 720-15+2*BORDER_SIZE], 'size': [1080-15, 720-15], 'cluster': CLUSTERS['horizon_only'], 'color': 'x', 'position': '5'}, + + {'origin': [0+BORDER_SIZE, 720*2+BORDER_SIZE*2], 'size': [1080-15, 720-15], 'cluster': CLUSTERS['vertical'], 'color': 'x', 'position': '6'}, + {'origin': [1080+BORDER_SIZE*2-15, 720*2+BORDER_SIZE*2], 'size': [1080-15, 720-15], 'cluster': CLUSTERS['vertical'], 'color': 'x', 'position': '7'}, + {'origin': [0+BORDER_SIZE, 720*3-15+BORDER_SIZE*3], 'size': [1080-15, 720-15], 'cluster': CLUSTERS['vertical'], 'color': 'x', 'position': '8'}, + {'origin': [1080+BORDER_SIZE*2-15, 720*3-15+BORDER_SIZE*3], 'size': [1080-15, 720-15], 'cluster': CLUSTERS['vertical'], 'color': 'x', 'position': '9'}, + {'origin': [1080*2+BORDER_SIZE*3-15*2, 720*2-15*2+BORDER_SIZE*3], 'size': [1080*2, 720*2], 'cluster': CLUSTERS['horizon_only'][4:], 'color': '2x', 'position': '10'} + ] +}, +{ + "version": "3", + "size": { + 'width': O_WIDTH*4 + BORDER_SIZE*3, + 'height': O_HEIGHT*4 + BORDER_SIZE*3, + 'channel': 3 + }, + "ARGS_SQL": (1, 'simple_conv', 'model_colab'), + "DECOUPAGE": [ + {'origin': [0+BORDER_SIZE, 0+BORDER_SIZE], 'size': [1080*2, 720*2], 'cluster': None, 'picture_ids' : ['20170815-130001'], 'directory': 'data/isr/output/version_3/rrdn-C4-D3-G32-G032-T10-x4/2019-12-16_2245', 'color': '2x', 'position': '1'}, + {'origin': [1080*2+BORDER_SIZE*2, 0+BORDER_SIZE], 'size': [1080-15, 720-15], 'cluster': None, 'picture_ids': ['20170424-133001'], 'color': 'x', 'position': '2'}, + {'origin': [1080*3+BORDER_SIZE*3-15, 0+BORDER_SIZE], 'size': [1080-15, 720-15], 'cluster': None, 'picture_ids': ['20170726-004001'], 'color': 'x', 'position': '3'}, + {'origin': [1080*2+BORDER_SIZE*2, 720-15+2*BORDER_SIZE], 'size': [1080-15, 720-15], 'cluster': None, 'picture_ids': ['20180625-140001', '20180617-112001'], 'color': 'x', 'position': '4'}, + {'origin': [1080*3+BORDER_SIZE*3-15, 720-15+2*BORDER_SIZE], 'size': [1080-15, 720-15], 'cluster': None, 'picture_ids': ['20180731-000001'], 'color': 'x', 'position': '5'}, + + {'origin': [0+BORDER_SIZE, 720*2+BORDER_SIZE*2], 'size': [1080-15, 720-15], 'cluster': None, 'picture_ids': ['20180902-100001'], 'directory': 'data/isr/output/version_3/rrdn-C4-D3-G32-G032-T10-x4/2019-12-16_2245', 'color': 'x', 'position': '6'}, + {'origin': [1080+BORDER_SIZE*2-15, 720*2+BORDER_SIZE*2], 'size': [1080-15, 720-15], 'cluster': None, 'picture_ids': ['20181129-080002'], 'color': 'x', 'position': '7'}, + {'origin': [0+BORDER_SIZE, 720*3-15+BORDER_SIZE*3], 'size': [1080-15, 720-15], 'cluster': None, 'picture_ids': ['20170420-195001'], 'color': 'x', 'position': '8'}, + {'origin': [1080+BORDER_SIZE*2-15, 720*3-15+BORDER_SIZE*3], 'size': [1080-15, 720-15], 'cluster': None, 'picture_ids': ['20180118-032001'], 'color': 'x', 'position': '9'}, + {'origin': [1080*2+BORDER_SIZE*3-15*2, 720*2-15*2+BORDER_SIZE*3], 'size': [1080*2, 720*2], 'cluster': None, 'picture_ids': ['20180613-102001'], 'color': '2x', 'position': '10'} + ] +}] + + +## +## Fonctions +## + +def pictures_df(config, db_manager, config_poster): + + + req_sql = "SELECT * FROM iss.pictures_embedding WHERE clustering_version = %s AND clustering_model_type = %s AND clustering_model_name = %s" + + pictures_df = db_manager.select_df(req_sql, poster_config['ARGS_SQL']) + + return pictures_df + + +def create_empty_poster(config, poster_config): + poster = np.zeros(( + poster_config['size']['height'], + poster_config['size']['width'], + poster_config['size']['channel'] + )) + + return poster + + +def create_poster_template_picture(config, poster_config, poster): + + font = ImageFont.truetype("LiberationMono-Regular.ttf", 70) + + for part in poster_config['DECOUPAGE']: + rgb_values = COLORS[part['color']]['rgb'] + for c, v in enumerate(rgb_values): + poster[part['origin'][1]:(part['origin'][1]+part['size'][1]), part['origin'][0]:(part['origin'][0]+part['size'][0]), c] = v + poster = poster.astype('uint8') + img = PIL.Image.fromarray(poster, 'RGB') + d = ImageDraw.Draw(img) + + for part in poster_config['DECOUPAGE']: + d.text((part['origin'][0],part['origin'][1]), "position %s" % (part['position']), fill=(0,0,0), font=font) + + return np.array(img) + + +def create_poster_picture(config, poster_config, poster, pictures_df): + + pictures_id_positions = [] + for part in poster_config['DECOUPAGE']: + + picture_id = None + directory = config.get('directory')['collections'] + if 'directory' in part.keys() and part['directory']: + directory = os.path.join(config.get('directory')['project_dir'], part['directory']) + + if part['cluster']: + selection = pictures_df.loc[pictures_df.label.isin(part['cluster'])].sample(1) + pictures_df = pictures_df.drop(selection.index) + + picture_id = selection.pictures_id.values[0] + else: + picture_id = random.choice(part['picture_ids']) + + pictures_id_positions.append({'pictures_id': picture_id, 'position': part['position']}) + + if part['size'][0] < O_WIDTH or part['size'][1] < O_HEIGHT: + part_array = Tools.read_np_picture(os.path.join(directory, "%s.jpg" % picture_id ), target_size = (O_HEIGHT, O_WIDTH)) + index_col = np.floor((O_WIDTH - part['size'][0])/2).astype(int) + index_row = np.floor((O_HEIGHT - part['size'][1])/2).astype(int) + part_array = part_array[index_col:(index_col+part['size'][1]), index_row:(index_row+part['size'][0]), :].copy() + else: + part_array = Tools.read_np_picture(os.path.join(directory, "%s.jpg" % picture_id ), target_size = (part['size'][1], part['size'][0])) + + poster[part['origin'][1]:(part['origin'][1]+part['size'][1]), part['origin'][0]:(part['origin'][0]+part['size'][0]), :] = part_array + + return poster, pictures_id_positions + + +def save_poster_picture(config, poster_config, pictures_id_positions, db_manager, poster_id = None): + poster_id = poster_id if poster_id else uuid.uuid1().hex + array = [] + for p_pos in pictures_id_positions: + array.append(( + poster_id, + poster_config['version'], + p_pos['position'], + p_pos['pictures_id'] + )) + + db_manager.insert_row_poster(array) + + return poster_id + + +def write_poster_picture(config, poster_config, poster, poster_id = None): + + poster_id = poster_id if poster_id else uuid.uuid1() + img = Tools.display_one_picture(poster) + img.save(os.path.join(CONFIG.get('directory')['data_dir'], 'posters', "version_%s_%s.jpg" % (poster_config['version'], poster_id)), "JPEG") + + return poster_id + + +## +## Main +## + +if __name__ == '__main__': + db_manager = Tools.create_db_manager(CONFIG) + + ## creation de la base + db_manager.create_posters_table() + + ## + poster_config = POSTERS_CONFIG[2] + + ## + pictures_df = pictures_df(CONFIG, db_manager, poster_config) + + ## + poster = create_empty_poster(CONFIG, poster_config) + + ## + poster = create_poster_template_picture(CONFIG, poster_config, poster) + + ## + write_poster_picture(CONFIG, poster_config, poster, poster_id = "template") + + for i in range(N_GENERATE): + print("%s / %s" % (i+1, N_GENERATE)) + ## + poster, p_pos = create_poster_picture(CONFIG, poster_config, poster, pictures_df) + + ## + poster_id = save_poster_picture(CONFIG, poster_config, p_pos, db_manager, POSTER_ID) + + ## + write_poster_picture(CONFIG, poster_config, poster, poster_id)