622 lines
19 KiB
Python
622 lines
19 KiB
Python
import pygame
|
|
import random
|
|
import time
|
|
import queue
|
|
import math
|
|
import joblib
|
|
from keras.models import load_model, Sequential
|
|
from keras.preprocessing.image import img_to_array, load_img
|
|
from keras.layers import Conv2D, MaxPooling2D
|
|
from keras.layers import Activation, Dropout, Flatten, Dense
|
|
from keras import backend as K
|
|
from tkinter import messagebox
|
|
import tkinter as tk
|
|
from PIL import Image
|
|
root = tk.Tk()
|
|
root.withdraw() #ukrycie okna tworzonego przez tkinter
|
|
|
|
pygame.init()
|
|
|
|
|
|
def heuristic(current, goal):
|
|
dx = abs(current[0] - goal[0])
|
|
dy = abs(current[1] - goal[1])
|
|
return math.sqrt(dx * dx + dy * dy)
|
|
|
|
|
|
class Node():
|
|
def __init__(self, parent = None, position = None):
|
|
self.parent = parent
|
|
self.position = position
|
|
|
|
self.g = 0
|
|
self.h = 0
|
|
self.f = 0
|
|
|
|
def __eq__(self, other):
|
|
return self.position == other.position
|
|
|
|
|
|
def aStar(start, end):
|
|
if end in cantwalk:
|
|
print("Wybrano nieodpowiednie pole!")
|
|
return []
|
|
|
|
start_node = Node(None, start)
|
|
start_node.g = start_node.h = start_node.f = 0
|
|
end_node = Node(None, end)
|
|
end_node.g = end_node.h = end_node.f = 0
|
|
|
|
open_list = []
|
|
closed_list = []
|
|
open_list.append(start_node)
|
|
|
|
while len(open_list) > 0:
|
|
current_node = open_list[0]
|
|
current_index = 0
|
|
for index, item in enumerate(open_list):
|
|
if item.f < current_node.f:
|
|
current_node = item
|
|
current_index = index
|
|
|
|
open_list.pop(current_index)
|
|
closed_list.append(current_node)
|
|
|
|
if current_node == end_node:
|
|
path = []
|
|
current = current_node
|
|
while current is not None:
|
|
path.append(current.position)
|
|
current = current.parent
|
|
return list(map(lambda t: (t[0], t[1]), path[::-1])) #zwraca odwróconą ściezkę
|
|
|
|
children = []
|
|
# można dodać (-1, -1), (-1, 1), (1, -1), (1, 1) dla poruszania się po przekątnej
|
|
for new_position in [(0, -1), (0, 1), (-1, 0), (1, 0)]:
|
|
node_position = (current_node.position[0] + new_position[0], current_node.position[1]
|
|
+ new_position[1])
|
|
|
|
if node_position[0] >= (rows - 1) or node_position[0] <= 0 or node_position[1] >= (rows - 1) \
|
|
or node_position[1] <= 0: #spr. czy w kracie
|
|
continue
|
|
|
|
if node_position in cantwalk: #spr. czy można przejść
|
|
continue
|
|
|
|
new_node = Node(current_node, node_position)
|
|
children.append(new_node)
|
|
|
|
didBreak = False
|
|
for child in children:
|
|
didBreak = False
|
|
for closed_child in closed_list:
|
|
if child == closed_child:
|
|
didBreak = True
|
|
break
|
|
|
|
if didBreak:
|
|
continue
|
|
|
|
if child.position in cantwalk:
|
|
child.g = current_node.g + 99999
|
|
elif child.position in puddles:
|
|
child.g = current_node.g + 3
|
|
else:
|
|
child.g = current_node.g + 1
|
|
|
|
child.h = heuristic(child.position, end_node.position)
|
|
child.f = child.g + child.h
|
|
|
|
for open_node in open_list:
|
|
if child == open_node and child.g > open_node.g:
|
|
didBreak = True
|
|
break
|
|
|
|
if didBreak:
|
|
continue
|
|
|
|
open_list.append(child)
|
|
|
|
|
|
class Dish(object):
|
|
def __init__(self, dishName, prepTime, eatTime, price):
|
|
self.dishName = dishName
|
|
self.preparationTime = prepTime
|
|
self.eatingTime = eatTime
|
|
self.price = price
|
|
self.fatContent = random.randint(0, 16)
|
|
self.fiberContent = random.randint(0, 16)
|
|
self.spicy = random.randint(0, 1)
|
|
|
|
|
|
class Plate(object):
|
|
def __init__(self, dish, img):
|
|
self.dishName = dish.dishName
|
|
self.isEmpty = False
|
|
self.preparationTime = dish.preparationTime
|
|
self.eatingTime = dish.eatingTime
|
|
self.price = dish.price
|
|
self.img = img
|
|
|
|
def eat(self):
|
|
#time.sleep(self.eatingTime) psuje program - nie używajcie
|
|
self.isEmpty = True #zjadanie dania jest oznaczeniem talerza jako pusty (metoda będzie wywoływana przez klienta)
|
|
|
|
def draw(self):
|
|
load = Image.open(self.img)
|
|
load.show()
|
|
|
|
|
|
class Kitchen(object):
|
|
def __init__(self, pos):
|
|
self.readyDishes = queue.Queue(32) #kolejka o maksymalnej długości 32
|
|
self.orders = queue.Queue(32) #wyskakiwał mi tu błąd - poprawiłam na dużą literę i jest ok
|
|
self.pos = pos
|
|
|
|
def makeDish(self):
|
|
if not self.orders.empty():
|
|
plate = self.orders.get()
|
|
time.sleep(plate.preparationTime) #kuchnia przygotowuje danie przez określony czas
|
|
self.readyDishes.put(plate)
|
|
|
|
def giveDish(self):
|
|
if not self.readyDishes.empty():
|
|
plate = self.readyDishes.get()
|
|
return plate
|
|
else:
|
|
return None
|
|
|
|
def draw(self, surface):
|
|
image1 = pygame.image.load(r'kitchen1.png')
|
|
image1 = pygame.transform.scale(image1, (sizeBetween - 1, sizeBetween - 1))
|
|
surface.blit(image1, (13*sizeBetween+1, 0*sizeBetween+1))
|
|
|
|
image2 = pygame.image.load(r'kitchen2.png')
|
|
image2 = pygame.transform.scale(image2, (sizeBetween - 1, sizeBetween - 1))
|
|
surface.blit(image2, (14*sizeBetween+1, 0*sizeBetween+1))
|
|
|
|
image3 = pygame.image.load(r'kitchen3.png')
|
|
image3 = pygame.transform.scale(image3, (sizeBetween - 1, sizeBetween - 1))
|
|
surface.blit(image3, (13*sizeBetween+1, 1*sizeBetween+1))
|
|
|
|
image4 = pygame.image.load(r'kitchen4.png')
|
|
image4 = pygame.transform.scale(image4, (sizeBetween - 1, sizeBetween - 1))
|
|
surface.blit(image4, (14*sizeBetween+1, 1*sizeBetween+1))
|
|
|
|
|
|
class Client(object):
|
|
def __init__(self, age, sex, budget, table):
|
|
self.age = age
|
|
self.sex = sex
|
|
self.myPlate = None
|
|
self.budget = budget
|
|
self.myTable = table #domyślnie klient nie siedzi przy żadnym stole
|
|
|
|
def takePlateAndEat(self, plate):
|
|
self.myPlate = plate
|
|
plate.eat()
|
|
|
|
def takeASeat(self, table):
|
|
self.myTable = table
|
|
|
|
def returnPlate(self):
|
|
plate = self.myPlate
|
|
self.myPlate = None
|
|
return plate
|
|
|
|
|
|
class Table(object):
|
|
def __init__(self, pos, capacity):
|
|
self.pos = pos
|
|
self.capacity = capacity
|
|
|
|
def move(self, newx, newy): #metoda do ustawiania stołów poprzez podanie nowych współrzędnych
|
|
self.pos[0] = newx
|
|
self.pos[1] = newy
|
|
|
|
def draw(self, surface):
|
|
image = pygame.image.load(r'Table-croped.png')
|
|
image = pygame.transform.scale(image, (sizeBetween - 1, sizeBetween - 1))
|
|
|
|
i = self.pos[0]
|
|
j = self.pos[1]
|
|
|
|
surface.blit(image, (i*sizeBetween+1, j*sizeBetween+1))
|
|
|
|
|
|
class Waiter(object):
|
|
def __init__(self, color, pos, direction):
|
|
self.color = color
|
|
self.pos = pos #pozycja agenta, zapisana w formie dwuelementowej listy
|
|
self.posx = pos[0]
|
|
self.posy = pos[1]
|
|
self.dirnx = 0 #zmienne dirnx i dirny używane są do ruchu bota i ustalania, w którą stronę jest zwrócony
|
|
self.dirny = 1
|
|
self.plates = [] #lista niesionych przez agenta talerzy, planowo lista par: (talerz, klient)
|
|
self.direction = direction #kierunek, w ktory jest skierowany bot
|
|
self.currentRotation = 0
|
|
self.rotate = "forward"
|
|
self.rotationNumber = 0
|
|
|
|
def resetPosition(self, pos):
|
|
self.pos = pos
|
|
|
|
def takePlates(self, kitchen):
|
|
for i in range(2):
|
|
plate = kitchen.giveDish()
|
|
if plate == None:
|
|
break
|
|
else:
|
|
self.plates.append(plate)
|
|
|
|
def giveClientPlate(self, client):
|
|
plate = self.plates.pop(0)
|
|
client.takePlateAndEat(plate)
|
|
|
|
def rotateRight(self):
|
|
self.currentRotation += 90
|
|
|
|
def rotateLeft(self):
|
|
self.currentRotation -= 90
|
|
|
|
def goForward(self, movex, movey):
|
|
self.posx += movex
|
|
self.posy += movey
|
|
self.pos = (self.posx, self.posy)
|
|
|
|
def draw(self, surface):
|
|
image = pygame.image.load(r'waiter_right.png')
|
|
image = pygame.transform.scale(image, (sizeBetween - 1, sizeBetween - 1))
|
|
|
|
if self.rotate == "right":
|
|
self.rotateRight()
|
|
elif self.rotate == "left":
|
|
self.rotateLeft()
|
|
elif self.direction == "forward":
|
|
pass
|
|
|
|
image = pygame.transform.rotate(image, self.currentRotation)
|
|
|
|
i = self.pos[0]
|
|
j = self.pos[1]
|
|
surface.blit(image, (i * sizeBetween + 1, j * sizeBetween + 1))
|
|
|
|
def goByAStar(self, end):
|
|
positionList = aStar(self.pos, end)
|
|
print(positionList)
|
|
if len(positionList) == 0:
|
|
messagebox.showerror("BŁĄD!", "Wybrano nieosiągalne pole!")
|
|
pygame.quit()
|
|
exit()
|
|
else:
|
|
lenght = len(positionList) - 1
|
|
for i in range(lenght):
|
|
movex = positionList[i + 1][0] - positionList[i][0]
|
|
movey = positionList[i + 1][1] - positionList[i][1]
|
|
|
|
prevDirection = self.direction
|
|
if movex == -1 and movey == 0:
|
|
self.direction = 1 #"left"
|
|
elif movex == 1 and movey == 0:
|
|
self.direction = 3 #"right"
|
|
elif movey == 1 and movex == 0:
|
|
self.direction = 4 #"down"
|
|
else:
|
|
self.direction = 2 #"up"
|
|
|
|
howToRotate = prevDirection - self.direction #działa!
|
|
|
|
if howToRotate < 0:
|
|
self.rotate = "left"
|
|
self.rotationNumber = abs(howToRotate)
|
|
elif howToRotate > 0:
|
|
self.rotate = "right"
|
|
self.rotationNumber = abs(howToRotate)
|
|
elif howToRotate == 0:
|
|
self.rotate = "forward"
|
|
self.rotationNumber = 0
|
|
|
|
#print(self.rotate)
|
|
|
|
for i in range(self.rotationNumber):
|
|
redrawWindow(window)
|
|
time.sleep(0.2)
|
|
self.rotate = "forward"
|
|
self.rotationNumber = 0
|
|
|
|
self.goForward(movex, movey)
|
|
redrawWindow(window)
|
|
time.sleep(0.2)
|
|
|
|
|
|
def drawGrid(width, rows, surface):
|
|
x = 0
|
|
y = 0
|
|
|
|
for i in range(rows):
|
|
x = x + sizeBetween
|
|
y = y + sizeBetween
|
|
|
|
pygame.draw.line(surface, (255, 255, 255), (x, 0), (x, width))
|
|
pygame.draw.line(surface, (255, 255, 255), (0, y), (width, y))
|
|
|
|
|
|
def predictAndShowImg(plate):
|
|
img_width, img_height = 256, 256
|
|
|
|
plate.draw()
|
|
test_image = load_img(plate.img, target_size=(img_width, img_height))
|
|
test_image = img_to_array(test_image)
|
|
test_image = test_image.reshape((1,) + test_image.shape)
|
|
|
|
result = img_classify.predict(test_image)
|
|
print(result)
|
|
if (result == [1.]):
|
|
messagebox.showinfo("Rozpoznanie", "Talerz pełny.")
|
|
return 1
|
|
else:
|
|
messagebox.showinfo("Rozpoznanie", "Talerz pusty.")
|
|
return 0
|
|
|
|
|
|
def checkIfEmpty(fullOrEmpty, client):
|
|
if fullOrEmpty == 1:
|
|
pass
|
|
elif fullOrEmpty == 0:
|
|
client.returnPlate()
|
|
bot.goByAStar((kitchen.pos[0] - 1, kitchen.pos[1]))
|
|
|
|
|
|
def classify(a):
|
|
if a == 1:
|
|
dish_1 = Dish("obiad", 40, 20, 15)
|
|
dish_2 = Dish("deser", 25, 10, 10)
|
|
dish_3 = Dish("obiad 2", 55, 25, 28)
|
|
|
|
plate_1 = Plate(dish_1, "Sara/data/validation/food/food004.png")
|
|
plate_2 = Plate(dish_2, "Sara/data/validation/food/food002.png")
|
|
plate_3 = Plate(dish_1, "Sara/data/validation/dirty/dirty001.png")
|
|
plate_4 = Plate(dish_3, "Sara/data/validation/dirty/dirty009.png")
|
|
|
|
client_1 = Client(21, 1, 45, 1)
|
|
client_2 = Client(44, 0, 22, 4)
|
|
client_3 = Client(27, 1, 15, 5)
|
|
client_4 = Client(19, 0, 32, 8)
|
|
|
|
client_1.takePlateAndEat(plate_1)
|
|
client_2.takePlateAndEat(plate_2)
|
|
client_3.takePlateAndEat(plate_3)
|
|
client_4.takePlateAndEat(plate_4)
|
|
|
|
'''
|
|
TRASA + ROZPOZNAWANIE TALERZY
|
|
'''
|
|
|
|
bot.goByAStar((tables[1].pos[0] + 1, tables[1].pos[1]))
|
|
fullOrEmpty = predictAndShowImg(plate_1)
|
|
checkIfEmpty(fullOrEmpty, client_1)
|
|
|
|
bot.goByAStar((tables[4].pos[0] + 1, tables[4].pos[1]))
|
|
fullOrEmpty = predictAndShowImg(plate_2)
|
|
checkIfEmpty(fullOrEmpty, client_2)
|
|
|
|
bot.goByAStar((tables[5].pos[0] + 1, tables[5].pos[1]))
|
|
fullOrEmpty = predictAndShowImg(plate_3)
|
|
checkIfEmpty(fullOrEmpty, client_3)
|
|
|
|
bot.goByAStar((tables[8].pos[0] + 1, tables[8].pos[1]))
|
|
fullOrEmpty = predictAndShowImg(plate_4)
|
|
checkIfEmpty(fullOrEmpty, client_4)
|
|
|
|
messagebox.showinfo("Informacja końcowa", "Zakończono trasę.")
|
|
|
|
pygame.quit()
|
|
exit()
|
|
else:
|
|
pass
|
|
|
|
|
|
def predictDigest(dish, client, model):
|
|
|
|
data = []
|
|
data.append(client.age)
|
|
data.append(dish.fatContent)
|
|
data.append(dish.fiberContent)
|
|
data.append(client.sex)
|
|
data.append(dish.spicy)
|
|
|
|
prediction = model.predict([data])
|
|
|
|
if prediction == 1:
|
|
messagebox.showinfo("opinia", "Z tym może być ciężko. " + str(data))
|
|
return prediction
|
|
else:
|
|
messagebox.showinfo("opinia", "Z tym nie będzie tak źle! " + str(data))
|
|
return prediction
|
|
|
|
|
|
|
|
def evaluate(b):
|
|
if b == 1:
|
|
loaded_model = joblib.load('Marta/finalized_model.sav')
|
|
# load = Image.open('Marta/digest_entropy.png')
|
|
# load.show()
|
|
messagebox.showinfo("zaczynamy", "Zaczynamy!")
|
|
|
|
dish_1 = Dish("obiad", 40, 20, 15)
|
|
dish_2 = Dish("deser", 25, 10, 10)
|
|
dish_3 = Dish("obiad 2", 55, 25, 28)
|
|
|
|
plate_1 = Plate(dish_1, "Sara/data/validation/food/food004.png")
|
|
plate_2 = Plate(dish_2, "Sara/data/validation/food/food002.png")
|
|
plate_4 = Plate(dish_3, "Sara/data/validation/dirty/dirty009.png")
|
|
|
|
client_1 = Client(27, 1, 45, 1)
|
|
client_2 = Client(44, 0, 22, 4)
|
|
client_4 = Client(16, 0, 32, 8)
|
|
|
|
client_1.takePlateAndEat(plate_1)
|
|
client_2.takePlateAndEat(plate_2)
|
|
client_4.takePlateAndEat(plate_4)
|
|
|
|
bot.goByAStar((tables[1].pos[0] + 1, tables[1].pos[1]))
|
|
opinion = predictDigest(dish_1, client_1, loaded_model)
|
|
|
|
bot.goByAStar((tables[3].pos[0] + 1, tables[3].pos[1]))
|
|
opinion = predictDigest(dish_2, client_2, loaded_model)
|
|
|
|
bot.goByAStar((tables[5].pos[0] + 1, tables[5].pos[1]))
|
|
opinion = predictDigest(dish_3, client_4, loaded_model)
|
|
|
|
messagebox.showinfo("Informacja końcowa", "Zakończono trasę.")
|
|
|
|
pygame.quit()
|
|
exit()
|
|
else:
|
|
pass
|
|
|
|
|
|
def text_objects(text, font):
|
|
textSurface = font.render(text, True, black)
|
|
return textSurface, textSurface.get_rect()
|
|
|
|
|
|
def button(msg, x, y, w, h, ic, ac, action=None):
|
|
mouse = pygame.mouse.get_pos()
|
|
click = pygame.mouse.get_pressed()
|
|
|
|
if x+w > mouse[0] > x and y+h > mouse[1] > y:
|
|
pygame.draw.rect(window, ac, (x, y, w, h))
|
|
if click[0] == 1 and action != None:
|
|
print("pressed")
|
|
action(1)
|
|
else:
|
|
pygame.draw.rect(window, ic, (x, y, w, h))
|
|
|
|
smallText = pygame.font.Font("freesansbold.ttf", 15)
|
|
textSurf, textRect = text_objects(msg, smallText)
|
|
textRect.center = ((x+(w/2)), (y+(h/2)))
|
|
window.blit(textSurf, textRect)
|
|
|
|
|
|
def redrawWindow(surface):
|
|
surface.fill(beige)
|
|
bot.draw(surface)
|
|
kitchen.draw(surface)
|
|
for i in range(len(tables)):
|
|
tables[i].draw(surface)
|
|
for i in range(len(puddles)):
|
|
image = pygame.image.load(r'puddle.png')
|
|
image = pygame.transform.scale(image, (sizeBetween - 1, sizeBetween - 1))
|
|
surface.blit(image, (puddles[i][0] * sizeBetween + 1, puddles[i][1] * sizeBetween + 1))
|
|
|
|
drawGrid(width, rows, surface)
|
|
button("Rozpoznawanie talerzy", 0, width + 1, 198, 48, light_beige, white)
|
|
button("Ciężkostrawność dań", 200, width + 1, 198, 48, light_beige, white)
|
|
|
|
pygame.display.update()
|
|
|
|
|
|
def noWalkable(tables, kitchen):
|
|
list = []
|
|
for i in range(len(tables)):
|
|
list.append(tables[i].pos)
|
|
list.append(kitchen.pos)
|
|
return list
|
|
|
|
|
|
def makeImgClassificator(model):
|
|
img_width, img_height = 256, 256
|
|
if K.image_data_format() == 'channels_first':
|
|
input_shape = (3, img_width, img_height)
|
|
else:
|
|
input_shape = (img_width, img_height, 3)
|
|
|
|
model.add(Conv2D(32, (2, 2), input_shape=input_shape))
|
|
model.add(Activation('relu'))
|
|
model.add(MaxPooling2D(pool_size=(2, 2)))
|
|
|
|
model.add(Conv2D(32, (2, 2)))
|
|
model.add(Activation('relu'))
|
|
model.add(MaxPooling2D(pool_size=(2, 2)))
|
|
|
|
model.add(Conv2D(64, (2, 2)))
|
|
model.add(Activation('relu'))
|
|
model.add(MaxPooling2D(pool_size=(2, 2)))
|
|
|
|
model.add(Flatten())
|
|
model.add(Dense(64))
|
|
model.add(Activation('relu'))
|
|
model.add(Dropout(0.5))
|
|
model.add(Dense(1))
|
|
model.add(Activation('sigmoid'))
|
|
|
|
model.compile(loss='binary_crossentropy',
|
|
optimizer='rmsprop',
|
|
metrics=['accuracy'])
|
|
|
|
|
|
|
|
def main():
|
|
global width, rows, bot, light_beige, beige, white, black, sizeBetween, tables, kitchen, cantwalk, puddles, window, clock, \
|
|
img_classify
|
|
# skróty do kolorów
|
|
light_beige = (255, 240, 205)
|
|
beige = (255, 205, 178)
|
|
white = (255, 255, 255)
|
|
black = (0, 0, 0)
|
|
|
|
img_classify = Sequential()
|
|
makeImgClassificator(img_classify)
|
|
img_classify.load_weights('Sara/model_food_dirty.h5')
|
|
|
|
width = 600
|
|
rows = 15
|
|
sizeBetween = width // rows #wielkość pojedynczej kratki
|
|
window = pygame.display.set_mode((width, width + 50))
|
|
|
|
bot = Waiter((255, 0, 0), (12, 8), 2)
|
|
|
|
tables = []
|
|
tables.append(Table((0, 3), 1))
|
|
tables.append(Table((0, 6), 1))
|
|
tables.append(Table((0, 9), 2))
|
|
tables.append(Table((0, 12), 2))
|
|
tables.append(Table((4, 4), 2))
|
|
tables.append(Table((4, 7), 2))
|
|
tables.append(Table((4, 10), 2))
|
|
tables.append(Table((4, 13), 2))
|
|
tables.append(Table((8, 3), 1))
|
|
tables.append(Table((8, 6), 1))
|
|
tables.append(Table((8, 9), 2))
|
|
tables.append(Table((8, 12), 2))
|
|
|
|
kitchen = Kitchen((13, 1))
|
|
|
|
cantwalk = noWalkable(tables, kitchen) # lista pozycji, na ktore bot nie moze wejsc
|
|
puddles = []
|
|
puddles.append((7, 10))
|
|
puddles.append((2, 5))
|
|
puddles.append((3, 12))
|
|
puddles.append((10, 3))
|
|
puddles.append((6, 2))
|
|
puddles.append((12, 10))
|
|
puddles.append((1, 4))
|
|
|
|
flag = True
|
|
clock = pygame.time.Clock()
|
|
while flag:
|
|
for event in pygame.event.get():
|
|
if event.type == pygame.QUIT:
|
|
pygame.quit()
|
|
quit()
|
|
button("Rozpoznawanie talerzy", 0, width + 1, 198, 48, light_beige, white, classify)
|
|
button("Ciężkostrawność dań", 200, width + 1, 198, 48, light_beige, white, evaluate)
|
|
redrawWindow(window)
|
|
|
|
pygame.quit()
|
|
exit()
|
|
|
|
|
|
main()
|