This is the last version of card manager

This commit is contained in:
Driss Lalami 2022-01-20 12:36:13 +01:00
parent c6f997d2ed
commit 9bb26f1310

245
card_manager/main.py Normal file
View file

@ -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/<mode>/<nb>', 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)