printing out recognized orders, bug with table thread

This commit is contained in:
= 2020-05-16 12:08:02 +02:00
parent 87483f5838
commit 723568cf31
13 changed files with 335 additions and 51 deletions

View File

@ -9,6 +9,9 @@ from kelner.src.managers.TableManager import TableManager
from kelner.src.managers.WaiterManager import WaiterManager from kelner.src.managers.WaiterManager import WaiterManager
from kelner.src.algorithms.DecisionTree import Tree_Builder from kelner.src.algorithms.DecisionTree import Tree_Builder
from kelner.src.managers.KitchenManager import KitchenManager from kelner.src.managers.KitchenManager import KitchenManager
from kelner.src.algorithms.CNN.PrepareData import LoadModelThread
import kelner.src.settings as settings
import time
# create screen consts # create screen consts
Scale = 2 # scale for all images used within project Scale = 2 # scale for all images used within project
@ -18,10 +21,20 @@ GridCountX = 15 # number of columns in grid
GridCountY = 9 # number of rows in grid GridCountY = 9 # number of rows in grid
ScreenWidth = CellSize * GridCountX + 2 * PaintOffset # screen width in pixels ScreenWidth = CellSize * GridCountX + 2 * PaintOffset # screen width in pixels
ScreenHeight = CellSize * GridCountY + 2 * PaintOffset # screen height in pixels ScreenHeight = CellSize * GridCountY + 2 * PaintOffset # screen height in pixels
running_tasks = {'table': [], 'waiter': []}
# initialize background # initialize background
gridBoard = GridBoard(ScreenWidth, ScreenHeight) gridBoard = GridBoard(ScreenWidth, ScreenHeight)
# start loading prediction model
settings.init()
load_model_thread = LoadModelThread()
load_model_thread.start()
# joining this thread to main thread. Man thread will be started after this finish
load_model_thread.join()
# initialize drawable objects manager # initialize drawable objects manager
drawableManager = DrawableCollection() drawableManager = DrawableCollection()
@ -76,12 +89,10 @@ drawableManager.add(waiter1)
# drawableManager.add(waiter4) # drawableManager.add(waiter4)
# TODO: create kitchen
kitchen = Kitchen(5, GridCountX - 5, 5, GridCountY - 5, CellSize, PaintOffset) kitchen = Kitchen(5, GridCountX - 5, 5, GridCountY - 5, CellSize, PaintOffset)
drawableManager.add(kitchen) drawableManager.add(kitchen)
kitchenManager = KitchenManager(drawableManager, gridBoard) kitchenManager = KitchenManager(drawableManager, gridBoard)
# My comment # My comment
# initialize a number of tables given in range # initialize a number of tables given in range
for i in range(0, 40): for i in range(0, 40):
@ -92,10 +103,12 @@ for i in range(0, 40):
# new thread controlling tables # new thread controlling tables
tableTask = TableManager(drawableManager, menuManager) tableTask = TableManager(drawableManager, menuManager)
tableTask.start() tableTask.start()
running_tasks['table'].append(tableTask)
# new thread controlling waiter # new thread controlling waiter
waiter1Task = WaiterManager(drawableManager, [waiter1], kitchenManager) waiter1Task = WaiterManager(drawableManager, [waiter1], kitchenManager, menuManager, tableTask)
waiter1Task.start() waiter1Task.start()
running_tasks['waiter'].append(tableTask)
# waiter2Task = WaiterManager(drawableManager, [waiter2]) # waiter2Task = WaiterManager(drawableManager, [waiter2])
# waiter2Task.start() # waiter2Task.start()

View File

@ -0,0 +1,40 @@
from tensorflow.keras.preprocessing import image
import tensorflow as tf
from tensorflow.keras.models import load_model
import numpy as np
import kelner.src.settings as settings
class Predictor:
def __init__(self, food_list):
self._food_list = food_list
self._model = settings.tensorflowModel
def predict_classes(self, images):
for img in images:
img = image.load_img(img, target_size=(224, 224))
img = image.img_to_array(img)
img = np.expand_dims(img, axis=0)
img /= 255.
pred = self._model.predict(img)
index = np.argmax(pred)
self._food_list.sort()
pred_value = self._food_list[index]
print("Pred: {}, index: {}, pred_value:{}".format(pred, index, pred_value))
print("THIS IS A:{}".format(pred_value))
def predict_class(self, img):
img = image.load_img(img, target_size=(224, 224))
img = image.img_to_array(img)
img = np.expand_dims(img, axis=0)
img /= 255.
pred = self._model.predict(img)
index = np.argmax(pred)
self._food_list.sort()
pred_value = self._food_list[index]
# print("Pred: {}, index: {}, pred_value:{}".format(pred, index, pred_value))
print("THIS IS A:{}".format(pred_value))

View File

@ -0,0 +1,110 @@
from collections import defaultdict
from shutil import copytree, rmtree, copy
import matplotlib.pyplot as plt
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
import threading
from tensorflow.keras.models import load_model
import kelner.src.settings as settings
# currently all images are not stored in repo because of big weight (5 GB)
data_dir = 'D:\\Nauka\\Studia\\4_sem\\SztucznaInteligencja\\A_star\\CNN\\foodRecognitionCNN\\food-101\\images'
folder_dir = 'D:\\Nauka\\Studia\\4_sem\\SztucznaInteligencja\\A_star\\CNN\\foodRecognitionCNN\\food-101'
foods_sorted = sorted(os.listdir(data_dir))
food_id = 0
# VISUALIZE DATA #
####################################################################
# rows = 17
# cols = 6
# fig, ax = plt.subplots(rows, cols, figsize=(50, 50))
# fig.suptitle("Showing one random image from each class", y=1.05, fontsize=24)
# for i in range(rows):
# for j in range(cols):
# try:
# food_selected = foods_sorted[food_id]
# food_id += 1
# except:
# break
# if food_selected == '.DS_Store':
# continue
#
# food_selected_images = os.listdir(os.path.join(data_dir, food_selected))
# food_selected_random = np.random.choice(food_selected_images)
# img = plt.imread(os.path.join(data_dir, food_selected, food_selected_random))
# ax[i][j].imshow(img)
# ax[i][j].set_title(food_selected, pad=10)
#
# plt.setp(ax, xticks=[], yticks=[])
# plt.tight_layout()
def prepare_data(filepath, source, dest):
print('Creating test data...')
print("filepath{} source{} dest{}".format(filepath, source, dest))
class_images = defaultdict(list)
with open(filepath, 'r') as txt:
paths = [read.strip() for read in txt.readlines()]
for p in paths:
food = p.split('/')
class_images[food[0]].append(food[1] + '.jpg')
for food in class_images.keys():
print("\nCopying images into ", food)
if not os.path.exists(os.path.join(dest, food)):
os.makedirs(os.path.join(dest, food))
for i in class_images[food]:
copy(os.path.join(source, food, i), os.path.join(dest, food, i))
print('Done copying')
def count_files(dir):
files_len = 0
for base, dirs, files in os.walk(dir):
for file in files:
files_len += 1
return files_len
# create train_mini and test_mini dataset
def dataset_mini(food_list, src, dest):
if os.path.exists(dest):
rmtree(dest)
os.makedirs(dest)
for food_item in food_list:
# recursive copying all subdirectories
copytree(os.path.join(src, food_item), os.path.join(dest, food_item))
food_list = ['pizza', 'apple_pie', 'donuts', 'sushi', 'omelette', 'nachos', 'tiramisu', 'pho', 'carrot_cake', 'mussels',
'waffles', 'hot_dog', 'hamburger']
src_train = os.path.abspath('train')
dest_train = os.path.abspath('train_mini')
src_test = os.path.abspath('test')
dest_test = os.path.abspath('test_mini')
# # create minisets
# print(os.path.join(src_train))
# print('Creating train_mini folder')
# dataset_mini(food_list, src_train, dest_train)
# print('Creating test_mini folder')
# dataset_mini(food_list, src_test, dest_test)
#
# # count minisets
# print("Total data in mini_train folder")
# print(count_files(dest_train))
# print("Total data in mini_test folder")
# print(count_files(dest_test))
class LoadModelThread(threading.Thread):
def __init__(self):
super().__init__()
self.__runThread = True
def run(self):
model_path = 'D:\\Nauka\\Studia\\4_sem\\SztucznaInteligencja\\ProjektAI\\kelner\\src\\algorithms\\CNN\\trainedModels\\big_model_trained_3class.hdf5'
model = load_model(model_path)
settings.tensorflowModel = model
print("---MODEL LOADED---")

View File

@ -0,0 +1,88 @@
import tensorflow as tf
import numpy as np
from collections import defaultdict
import collections
import tensorflow.keras.backend as K
import os
import random
import tensorflow as tf
import tensorflow.keras.backend as K
from tensorflow.keras import regularizers
from tensorflow.keras.applications.inception_v3 import InceptionV3
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten
from tensorflow.keras.layers import Convolution2D, MaxPooling2D, ZeroPadding2D, GlobalAveragePooling2D, AveragePooling2D
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import ModelCheckpoint, CSVLogger
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.regularizers import l2
from tensorflow import keras
from tensorflow.keras import models
import cv2
from PIL import Image
### NOT TESTED IN PYCHARM ###
### CHECK JUPYTER NOTEBOOK FILE ###
# using model pretrainded on datasets like ImageNet
n_classes = 13
IMGSIZE = 224
training_data_dir = os.path.abspath('train_mini')
validation_data_dir = os.path.abspath('test_mini')
number_train_files = 9750 # 75750
number_test_files = 3250 # 25250
batch_size = 16
# Normalize images to avoid repeatability of some marks on images
train_datagen = ImageDataGenerator(
# rescale all pixels from image
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True
)
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
training_data_dir,
target_size=(IMGSIZE, IMGSIZE),
batch_size=batch_size,
class_mode='categorical'
)
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(IMGSIZE, IMGSIZE),
batch_size=batch_size,
class_mode='categorical'
)
inception = InceptionV3(weights='imagenet', include_top=False)
x = inception.output
x = GlobalAveragePooling2D()(x) # reduce spatial dimensions of layer, prevent overfitting
x = Dense(128, activation='relu')(x) # dense layer with relu activation function
x = Dropout(0.2)(x) # prevent overfitting
predictions = Dense(13, kernel_regularizer=regularizers.l2(0.005), activation='softmax')(x)
model = Model(inputs=inception.input, outputs=predictions)
# same as model.fit
# takes 2 arguments - optimizer and loss
model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), loss='categorical_crossentropy', metrics=['accuracy'])
# save best prediction
checkpointer = ModelCheckpoint(filepath=os.path.abspath('pycharm_trained_model.hdf5'), verbose=1, save_best_only=True)
# log history
csv_logger = CSVLogger('history_3class.log')
history = model.fit_generator(train_generator,
steps_per_epoch=number_train_files // batch_size,
validation_data=validation_generator,
validation_steps=number_test_files // batch_size,
epochs=30,
verbose=1,
callbacks=[csv_logger, checkpointer])
model.save("big_model_trained_3class.hdf5")

View File

@ -31,9 +31,5 @@ class GridBoard:
def udpdate(self): def udpdate(self):
pygame.display.update() pygame.display.update()
def update_and_sleep(self, sec):
pygame.display.update()
time.sleep(sec)
def get_screen(self): def get_screen(self):
return self.__screen return self.__screen

View File

@ -22,7 +22,7 @@ class Kitchen(Drawable):
self._preparing_orders = [] self._preparing_orders = []
for order in orders.items(): for order in orders.items():
self._preparing_orders.append(order) self._preparing_orders.append(order)
print("Added {} to kitchen".format(order)) # print("Added {} to kitchen".format(order))
def get_ready_orders(self): def get_ready_orders(self):
print("Ready orders on kitchen: {}".format(self._ready_orders)) print("Ready orders on kitchen: {}".format(self._ready_orders))
@ -80,18 +80,17 @@ class Kitchen(Drawable):
def draw_order(self, dishes, screen): def draw_order(self, dishes, screen):
draw_screen = screen.get_screen() draw_screen = screen.get_screen()
img_paths = []
for i, dish in enumerate(dishes): for i, dish in enumerate(dishes):
img_path = str(dish) + '/' + str(random.randint(0, 4)) + '.jpg' img_path = os.path.join(str(dish), str(random.randint(0, 4)) + '.jpg')
print("Image drawing: {}".format(img_path)) img_path = os.path.join(os.getcwd(), 'images', 'testDishes', img_path)
image = self.getImage(Images.Dishes, img_path)
size = int(self.getCellSize()) size = int(self.getCellSize())
print(os.getcwd()) image = pygame.transform.scale((pygame.image.load(img_path)), (size, size))
image = pygame.transform.scale((pygame.image.load(os.path.join(os.getcwd(), 'images', 'testDishes', img_path))), (size, size)) draw_screen.blit(image, ((12 - i) * self.getCellSize(), 1 * self.getCellSize()))
print((13 - i) * self.getCellSize(), 1 * self.getCellSize())
draw_screen.blit(image, ((13 - i) * self.getCellSize(), 1 * self.getCellSize()))
screen.udpdate() screen.udpdate()
img_paths.append(str(img_path))
# screen.update_and_sleep(5) # print("Image drawing: {}".format(img_path))
return img_paths

View File

@ -67,6 +67,11 @@ class DrawableCollection:
kitchen = item kitchen = item
return kitchen return kitchen
def lock(self):
self.__waiterLock.acquire()
def unlock(self):
self.__waiterLock.release()
# gets all waiters from collection # gets all waiters from collection
def getWaiters(self): def getWaiters(self):

View File

@ -12,7 +12,6 @@ class KitchenManager(threading.Thread):
self._gridboard = gridboard self._gridboard = gridboard
self.__runThread = False self.__runThread = False
def prepare_dish(self): def prepare_dish(self):
pass pass
@ -24,34 +23,33 @@ class KitchenManager(threading.Thread):
kitchen.clear_orders() kitchen.clear_orders()
return out return out
def pass_and_return_order(self, orders, kitchen): def pass_and_return_order(self, orders, kitchen):
return kitchen.pass_and_return_order(orders) return kitchen.pass_and_return_order(orders)
def draw_orders(self, orders, kitchen): def draw_orders(self, orders, kitchen):
if orders: if orders:
for order in orders: for i, order in enumerate(orders):
dishes = order[1] dishes = order[1]
if dishes: if dishes:
kitchen.draw_order(dishes, self._gridboard) paths = kitchen.draw_order(dishes, self._gridboard)
print("Order nr{}: paths:"
"{}".format(i, paths))
return paths
def run(self, orders, kitchen): # TODO: recognize here
def draw_single_order(self, order, kitchen):
dishes = order[1]
if dishes:
paths = kitchen.draw_order(dishes, self._gridboard)
# print("Ordering table: {} Order paths: {}".format(order[0], paths))
return paths
def run(self):
self.__runThread = True self.__runThread = True
self.draw_orders(orders, kitchen)
time.sleep(10)
def stop(self): def stop(self):
self.__runThread = False self.__runThread = False
def is_running(self): def is_running(self):
return self.__runThread return self.__runThread
# def draw_orders(self, kitchen, orders, draw_manager):
# for order in orders:
# dishes = order[1]
# i = 0
# print("DISHES TO PRINT: {}".format(dishes))
# TODO: draw real images

View File

@ -19,3 +19,6 @@ class MenuManager:
order += [(self.__menuCard[random.randint(0, len(self.__menuCard) - 1)])] order += [(self.__menuCard[random.randint(0, len(self.__menuCard) - 1)])]
return order return order
def get_menu(self):
return self.__menuCard

View File

@ -27,3 +27,6 @@ class TableManager(threading.Thread):
def stop(self): def stop(self):
self.__runThread = False self.__runThread = False
def resume(self):
self.__runThread = True

View File

@ -4,17 +4,21 @@ import sys
from kelner.src.components.Table import Status from kelner.src.components.Table import Status
from kelner.src.algorithms.AStar.Finder import Finder from kelner.src.algorithms.AStar.Finder import Finder
from kelner.src.algorithms.BFS.BFS import BFS from kelner.src.algorithms.BFS.BFS import BFS
from kelner.src.components.Table import Status
from kelner.src.algorithms.CNN.ModelPrediction import Predictor
# creates new thread # creates new thread
class WaiterManager(threading.Thread): class WaiterManager(threading.Thread):
def __init__(self, drawableManager, waiters, kitchenManager): def __init__(self, drawableManager, waiters, kitchen_manager, menu_manager, table_manager):
super().__init__() super().__init__()
self.__drawableManager = drawableManager self.__drawableManager = drawableManager
self.__waiters = waiters self.__waiters = waiters
self.__runThread = True self.__runThread = True
self._kitchen_manager = kitchenManager self._kitchen_manager = kitchen_manager
self._menu_manager = menu_manager
self._table_manager = table_manager
def __getNearestTargetPath(self, waiter, target): def __getNearestTargetPath(self, waiter, target):
distance = sys.maxsize distance = sys.maxsize
@ -72,7 +76,6 @@ class WaiterManager(threading.Thread):
turns = result turns = result
lessTurnsTable = table lessTurnsTable = table
if lessTurnsTable is not None: if lessTurnsTable is not None:
tables.remove(lessTurnsTable) tables.remove(lessTurnsTable)
self.__changeWaiterDirection(waiter, lessTurnsTable.getX(), lessTurnsTable.getY()) self.__changeWaiterDirection(waiter, lessTurnsTable.getX(), lessTurnsTable.getY())
@ -104,7 +107,8 @@ class WaiterManager(threading.Thread):
print("Ready to go") print("Ready to go")
return ready_orders return ready_orders
def predict_orders(self, orders, waiter):
pass
# changes the status of a random table from NotReady to Ready # changes the status of a random table from NotReady to Ready
@ -126,36 +130,58 @@ class WaiterManager(threading.Thread):
self.__changeWaiterDirection(waiter, step[0], step[1]) self.__changeWaiterDirection(waiter, step[0], step[1])
self.__moveWaiter(waiter, step[0], step[1]) self.__moveWaiter(waiter, step[0], step[1])
# check if waiter is near kitchen
if (waiter.getX(), waiter.getY()) == (14, 1) or (waiter.getX(), waiter.getY()) == (13, 0): if (waiter.getX(), waiter.getY()) == (14, 1) or (waiter.getX(), waiter.getY()) == (13, 0):
if waiter.get_target() == 'kitchen': if waiter.get_target() == 'kitchen':
kitchen = self.__drawableManager.get_kitchen() kitchen = self.__drawableManager.get_kitchen()
waiter_orders = waiter.getAcceptedOrders() waiter_orders = waiter.getAcceptedOrders()
print(type(waiter_orders))
print("Waiter near kitchen. Collected orders: {}".format(waiter_orders)) print("Waiter near kitchen. Collected orders: {}".format(waiter_orders))
kitchen.add_orders(waiter_orders) kitchen.add_orders(waiter_orders)
received_orders = kitchen.get_ready_orders() received_orders = kitchen.get_ready_orders()
waiter.clear_accepted_orders() waiter.clear_accepted_orders()
if received_orders: if received_orders:
# self._kitchen_manager.draw_orders(received_orders) # self._kitchen_manager.draw_orders(received_orders)
KM = self._kitchen_manager # paths = self._kitchen_manager.draw_orders(received_orders, kitchen)
KM.run(received_orders, kitchen) food_list = self._menu_manager.get_menu()
KM.stop() ImagePredictor = Predictor(food_list)
for order in received_orders:
paths = self._kitchen_manager.draw_single_order(order, kitchen)
self._kitchen_manager.run()
self._table_manager.stop()
# print("Printed images paths: {}".format(paths))
if paths is not None:
for img_path in paths:
ImagePredictor.predict_class(img_path)
self.__drawableManager.forceRepaint()
self._kitchen_manager.stop()
self._table_manager.resume()
self._table_manager.join()
# TODO: recognize images # TODO: recognize images
# TODO: choose proper tableo
# TODO: set path to tables, another target
print('should blit')
kitchen.clear_orders() all_tables = self.__drawableManager.getTables(Status.Waiting)
waiter.make_ready() for table in all_tables:
waiter.set_target('table') # order = table.get_order()
# print("Table: {}\norder: {}".format(table, order))
pass
# TODO: choose proper tableo
# TODO: set path to tables, another target
time.sleep(5)
self._kitchen_manager.stop()
kitchen.clear_orders()
waiter.make_ready()
waiter.set_target('table')
else: else:
self.__collectOrder(waiter) self.__collectOrder(waiter)
def stop(self): def stop(self):
self.__runThread = False self.__runThread = False
def resume(self):
self.__runThread = True

3
kelner/src/settings.py Normal file
View File

@ -0,0 +1,3 @@
def init():
global tensorflowModel
tensorflowModel = None