from flask import Flask # Pour créer le service from flask import request # Pour faire des jolis "POST" import requests # Pour "request" un server "autre" import sqlite3 import random as rd import os import cv2 from matplotlib import pyplot import numpy as np import json #return json : json.dumps(dico) import sqlite3 import random as rd import os data_folder = "/data" database_path = "file::memory:?cache=shared" conn = sqlite3.connect(database_path) cursor = conn.cursor() cursor.execute("DROP TABLE images") cmd = """CREATE TABLE images ( id INT PRIMARY KEY NOT NULL, label VARCHAR(256) NOT NULL, path VARCHAR(256) NOT NULL )""" cursor.execute(cmd) list_subfolders_with_paths = [f for f in os.scandir(data_folder) if f.is_dir()] idp = 0 cmdIns = """INSERT INTO images VALUES (?,?,?)""" for folder in list_subfolders_with_paths: gen = os.scandir(folder) for e in gen: cursor.execute(cmdIns, (idp,folder.name,e.path)) idp+=1 conn.commit() conn.close() #prend une liste d'images de même taille et retourne un json décrivant la carte def retourneJSON(Images, eps=5): if( len(Images) == 0 ): raise ValueError("Pas d'images reçues") d = len(Images[0]) n = len(Images) #TODO mieux if( n<= 2): card = {"dimX" : n*d + (n+1)*eps, "dimY" : d + 2*eps, "posX" : list(eps+(d/2) + np.array([i*(eps+(d)) for i in range(n)])), "posY" : list(np.array([eps+(d/2) for i in range(n)])), } elif( n<=4 ): card = {"dimX" : 2*d + 3*eps, "dimY" : 2*d + 3*eps, "posX" : list(eps+(d/2) + np.array([i*(eps+(d)) for i in range(2)]))*2, "posY" : list(np.array([eps+(d/2) for i in range(2)])) + list(np.array([eps+d+(d/2) for i in range(2)])), } else: card = {"dimX" : 3*d + 4*eps, "dimY" : 3*d + 4*eps, "posX" : list(eps+(d/2) + np.array([i*(eps+(d)) for i in range(3)]))*3, "posY" : list(np.array([eps+(d/2) for i in range(3)])) + list(np.array([2*eps+d+(d/2) for i in range(3)])) + list(np.array([3*eps+2*d+(d/2) for i in range(3)])), } return json.dumps(card) #store json into string ? #Generate a card from PIL import Image, ImageDraw import random def generateCard(Img): # Generate a Card with the images in the given order #TODO randomize ? n = len(Img) descJSON = retourneJSON(Img) desc = json.loads(descJSON) #Read the images Images = [] for img in Img: tmp = img# cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #todo plus tard quand on sera fixé Images.append(Image.fromarray(np.uint8(tmp)).convert('RGB')) #Resize image Size = [] image_size = Images[0].size for i in range(len(Images)): scale = random.uniform(0.5, 1) Images[i] = Images[i].resize(( int(Images[i].size[0]*scale), int(Images[i].size[1]*scale) )) Size.append(Images[i].size) #Rotation for i in range(len(Images)): alpha = random.randint(1, 360) Images[i] = Images[i].rotate(alpha, resample=0, expand=0, fillcolor='white') #Card Creation card = Image.new('RGB',(desc["dimX"], desc["dimY"]), (255,255,255)) #white canevas (code final = couleur de background (attention différent du backgroud des images collées dessus)) #Past images into the card for i in range(len(Images)): #même longueur/ordre : Images, posX, posY card.paste( Images[i], ( int( desc["posX"][i]-Size[i][0]/2 ), int( desc["posY"][i]-Size[i][1]/2 ) ) ) #x = int( desc["posX"][i]-Size[i][0]/2 ) #y = int( desc["posY"][i]-Size[i][1]/2 ) #xmilieu = (x + Images[i].size[0])/2 #ymilieu = (y + Images[i].size[1])/2 #imgDraw = ImageDraw.Draw(card) #imgDraw.point((xmilieu,ymilieu), fill=(255, 0, 255)) return card def decoupeDobble(nbIC): #nombre d'images par carte nbC = int(nbIC + 1) nbIT = int((nbIC)*(nbIC+1)/2) return [nbC, nbIT] def coord(M): for i in range(len(M)): for j in range(len(M[0])): if( M[i][j] == 0 ): return [i, j] return -1 def repartitionNum(nbC, nbTI, nb): #Récupérer nbTI images de classes différentes (2 par classe) dans la BDD et les répartir dans nbC cards de façon correcte repartition = np.zeros((nbC, nb)) #ligne = carte, colonne = class #class numéroté de 1 à nbTI for i in range(1, nbTI+1): # On met le nombre une 1ere fois c = coord(repartition) repartition[c[0]][c[1]] = i # On met la 2ème itération de ce même nombre p = 0 cont = c[1] != 0 while(cont): if(repartition[c[0]][c[1]-p] + p == i and repartition[c[0]][c[1]-p] != 0): p += 1 else: cont = False p -= 1 k = 0 while( repartition[c[0]+p+1][c[1]-k] != 0 ): k += 1 if( k > 2*nb): raise Exception('aucune colonne dispo sur cette ligne') repartition[c[0]+p+1][c[1]-k] = i return repartition #TODO avce la BDD : récupérer 2 images de n class déifférentes def recupImage(nbC, nbTI): #selectionner nbTI dossiers au hasard #pour chaque dossier, sélectionner 2 images res = [] list_subfolders_with_paths = [f.name for f in os.scandir(data_folder) if f.is_dir() and f.name != 'lost+found' and f.name != "yolo"] rd.shuffle(list_subfolders_with_paths) labels = list_subfolders_with_paths[:nbTI] for label in labels: conn = sqlite3.connect(database_path) cursor = conn.cursor() cursor.execute("SELECT * FROM images WHERE label = ?",(label,)) images = cursor.fetchall() path_img1, path_img2 = [img[-1] for img in rd.choices(images,k = 2)] img1,img2 = Image.open(path_img1), Image.open(path_img2) res.append(img1) res.append(img2) return [np.array(e.resize((256,256))) for e in res] # fait le lien entre la répartition et les images def placerImage(nb): nbC, nbTI = decoupeDobble(nb) #nbTI = nb de class donc 2 fois plus d'images car 2 images pour chaque class (nb Total (type) Images), nbC = nb Cartes repartition = repartitionNum(nbC, nbTI, nb) images = recupImage(nbC, nbTI) #TODO modifier celon la fct finale dico = dict([(i+1, [images[2*i], images[2*i + 1]]) for i in range((nbC))]) Deck = [] for i in range(len(repartition)): ligne = [] for j in range(len(repartition[i])): val = int(repartition[i][j]) cont = True cnt = 0 listDicoVal = list(dico.values()) listDicoKey = list(dico.keys()) while(cont): #print("val : " + str(val) + "\tcnt : " + str(cnt) + "\tkey : " + str(listDicoKey[cnt])) if(int(val) == int(listDicoKey[cnt])): cont = False myValNew = listDicoVal[cnt][-1] myVal = listDicoVal[cnt][0] ligne.append(myVal) dico[listDicoKey[cnt]] = [myValNew] else: cnt += 1 Deck.append(ligne) return Deck #MS app = Flask(__name__) #app.config.from_object('config') @app.route('/recupCarte//', methods=['GET']) def recupCarte(mode, nb): #nb = nb d'images par carte #Ensemble des cartes DeckInitial = placerImage(int(nb)) Deck = [] for Img in DeckInitial: Deck.append(generateCard(Img)) return json.dumps([np.array(e).tolist() for e in Deck]) if __name__ == "__main__": app.run(host="0.0.0.0",port=50000)