245 lines
7.1 KiB
Python
245 lines
7.1 KiB
Python
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)
|