From 9bb26f131052da8be27b61d472812702f18122b9 Mon Sep 17 00:00:00 2001 From: lalami Date: Thu, 20 Jan 2022 12:36:13 +0100 Subject: [PATCH] This is the last version of card manager --- card_manager/main.py | 245 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 card_manager/main.py diff --git a/card_manager/main.py b/card_manager/main.py new file mode 100644 index 0000000..9fa9843 --- /dev/null +++ b/card_manager/main.py @@ -0,0 +1,245 @@ +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)