Merge remote-tracking branch 'origin/master'

This commit is contained in:
xkamikoo 2020-05-28 15:05:43 +02:00
commit ff6de2c7e4
4 changed files with 226 additions and 10 deletions

93
Marcin.md Normal file
View File

@ -0,0 +1,93 @@
# Podprojekt - sieć neuronowa"
**Twórca: Marcin Kwapisz**
**Klawisz F7 uruchamia program**
Program otrzymuje zdjęcie aktualnego pola i za
pomocą sieci neuronowej określa jakie to jest pole
i wybiera tryb w jakim ma pracować traktor
Sieć neuronowa została nauczona przy użyciu modułu darknet. Sieć została użyta po
20000 iteracjach treningowych
**Main**
```
def main(self):
self.pole = self.ui.field_images[self.field.get_value(self.traktor.get_poz())]
self.img = pygame.surfarray.array3d(self.pole)
self.img = self.img.transpose([1,0,2])
self.img = cv2.cvtColor(self.img, cv2.COLOR_RGB2BGR)
self.reco = self.mode(self.recognition(self.img))
if self.reco == 10:
print("Nic nie trzeba robić")
else:
self.traktor.set_mode(self.reco)
```
Wywołuje wszystkie pozostałe funkcje programu
**Get_output_layers**
```
def get_output_layers(self,net):
layer_names = net.getLayerNames()
output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
return output_layers
```
Zwraca nazwy kolejnych warstw, warstwa wyjściowa nie jest połączona z żadną następną warstwą
**Recognition**
```
def recognition(self,photo):
image = photo
Width = image.shape[1]
Height = image.shape[0]
scale = 0.00392
with open("si.names", 'r') as f:
classes = [line.strip() for line in f.readlines()]
COLORS = np.random.uniform(0, 255, size=(len(classes), 3))
net = cv2.dnn.readNet("si_20000.weights", "si.cfg")
blob = cv2.dnn.blobFromImage(image, scale, (416, 416), (0, 0, 0), True, crop=False)
net.setInput(blob)
outs = net.forward(self.get_output_layers(net))
class_ids = []
confidences = []
boxes = []
conf_threshold = 0.5
nms_threshold = 0.4
for out in outs:
for detection in out:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
if confidence > 0.5:
class_ids.append(class_id)
return class_ids[0]
```
Odpowiada za odebranie zdjęcia od funkcji głównej i
używa sieci neuronowej do rozpoznania zdjęcia
**Mode**
```
def mode(self,mode):
self.mode_value = mode
if self.mode_value in [0, 1, 2, 3]:
return 0
elif self.mode_value in [1, 3, 5, 7]:
return 1
elif self.mode_value in [0, 1, 4, 5]:
return 2
elif self.mode_value in [8]:
return 3
elif self.mode_value in [6]:
return 10
```
Na podstawie klasy otrzymanej przez funkcję **recognition** wybiera tryb
w jakim ma pracować traktor

View File

@ -9,6 +9,7 @@ class main():
self.field = field
self.ui = ui
self.path = path
self.mode_value = 0
def get_output_layers(self,net):
layer_names = net.getLayerNames()
@ -27,7 +28,7 @@ class main():
COLORS = np.random.uniform(0, 255, size=(len(classes), 3))
net = cv2.dnn.readNet("si_final.weights", "si.cfg")
net = cv2.dnn.readNet("si_20000.weights", "si.cfg")
blob = cv2.dnn.blobFromImage(image, scale, (416, 416), (0, 0, 0), True, crop=False)
@ -48,16 +49,18 @@ class main():
confidence = scores[class_id]
if confidence > 0.5:
class_ids.append(class_id)
print(class_id)
print(scores)
return class_id
return class_ids[0]
def main(self):
self.pole = self.ui.field_images[self.field.get_value(self.traktor.get_poz())]
self.img = pygame.surfarray.array3d(self.pole)
self.img = self.img.transpose([1,0,2])
self.img = cv2.cvtColor(self.img, cv2.COLOR_RGB2BGR)
self.traktor.set_mode(self.mode(self.recognition(self.img)))
self.reco = self.mode(self.recognition(self.img))
if self.reco == 10:
print("Nic nie trzeba robić")
else:
self.traktor.set_mode(self.reco)
def mode(self,mode):
self.mode_value = mode
@ -69,3 +72,5 @@ class main():
return 2
elif self.mode_value in [8]:
return 3
elif self.mode_value in [6]:
return 10

View File

@ -2,10 +2,125 @@
**Członkowie zespołu:** Marcin Kwapisz, Kamila Matysiak, Piotr Rychlicki, Justyna Zarzycka
**Temat podprojektu:** Wybór trybu pracy traktora za pomocą drzewa decyzyjnego
**Autor podprojektu:** Kamila Matysiak
### Drzewo Decyzyjne
Projekt wykorzystuje drzewo decyzyjne do wybrania czynności dla każdego pola, a następnie wysłania traktora do pól zgodnych z obecnie wybranym trybem.
Projekt używa metody CART (Classification and Regression Tree). Tworzy on drzewo binarne, w którym rozpatruje wszystkie możliwe podziały zbioru wartości cech na dwa rozłączne i uzupełniające się podzbiory dla cech dyskretnych.
Uruchamia się go za pomocą klawisza **F6**.
#### Zbiór uczący:
Zbiorem uczącym jest zestaw danych informujących drzewo jak postępować z polem o danych parametrach.
Kolejne cyfry odpowiadają za: nawodnienie pola, obecność chwastów, czy pole jest puste, czy jest do zbioru.
```
training_data = [[0, 0, 1, 0, "Zasadzic"],
[0, 1, 1, 0, "Odchwascic"],
[0, 0, 0, 0, "Podlac"],
[0, 1, 0, 0, "Odchwascic"],
[1, 0, 1, 0, "Zasadzic"],
[1, 1, 1, 0, "Odchwascic"],
[1, 0, 0, 0, "Czekac"],
[1, 1, 0, 0, "Odchwascic"],
[0, 0, 0, 1, "Zebrac"]]
self.tree = build_tree(training_data)
print_tree(self.tree)
```
#### Algotytm tworzenia drzewa:
Budowanie drzewa zaczynamy od stworzenia klasy **Question**, w której będziemy tworzyć zapytanie, na podstawie którego będziemy dzielić nasze dane. Następnie tworzymy funkcję **partition**, która na podstawie zapytania dzieli nam dane na spełnione i niespełnione wiersze:
```
# podział danych na spełnione i niespełnione wiersze
def partition(rows, question):
true_rows, false_rows = [], []
for row in rows:
if question.match(row):
true_rows.append(row)
else:
false_rows.append(row)
return true_rows, false_rows
```
Następnie wyokrzystujemy **Index Gini**, który mierzy jak często losowo wybrany element będzie źle zindentyfikowany. Gdy jest równy 0, oznacza to, że element zostanie właściwie oznaczony.
```
# funkcja implementująca indeks gini
def gini(rows):
counts = class_counts(rows)
impurity = 1
for lbl in counts:
prob_of_lbl = counts[lbl] / float(len(rows))
impurity -= prob_of_lbl ** 2
return impurity
def info_gain(left, right, current_uncertainty):
p = float(len(left)) / (len(left) + len(right))
return current_uncertainty - p * gini(left) - (1 - p) * gini(right)
```
Następnie na podstawie uzykanych informacji, znajdujemy najlepsze miejsce na podział danych:
```
# znalezienie najlepszego "miejsca" na podział danych
def find_best_split(rows):
best_gain = 0
best_question = None
current_uncertainty = gini(rows)
n_features = len(rows[0]) - 1
for col in range(n_features):
values = set([row[col] for row in rows])
for val in values:
question = Question(col, val)
true_rows, false_rows = partition(rows, question)
if len(true_rows) == 0 or len(false_rows) == 0:
continue
gain = info_gain(true_rows, false_rows, current_uncertainty)
if gain >= best_gain:
best_gain, best_question = gain, question
return best_gain, best_question
```
Po stworzeniu klas definiujących liść i węzęł deycyzyjny przechodzimy do właściwej funkcji **build_tree*:
```
# funkcja budująca drzewo
def build_tree(rows):
gain, question = find_best_split(rows) # znalezienie najlepszego podziału
if gain == 0:
return Leaf(rows)
true_rows, false_rows = partition(rows, question) # podział danych
true_branch = build_tree(true_rows)
false_branch = build_tree(false_rows) #stworzenie gałęzi prawdy i fałszu
return DecisionNode(question, true_branch, false_branch)
```
#### Integracja:
Program sczytuje dane z głównego projektu, następnie interpretuje je za pomocą prostej funkcji **translate**, która zwraca informacje o stanie pola. Następnie za pomocą drzewa określamy czynność, jaka powinna zostać wykonana na tym polu. Wykonanie pracy zlecamy klasie **pathfinding**, która za pomocą algorytmu A* wysyła traktor na pola odpowiadające wybranemu trybowi.
```
def search_field(self):
matrix = self.field.get_matrix()
for i in range(len(matrix)):
for j in range(len(matrix[i])):
print("Pole (%d,%d) Przewidziania czynnosc: %s"
% (i, j, print_leaf(classify(translate(matrix[i][j]), self.tree))))
if work[self.traktor.get_mode()] in self.work_field(classify(translate(matrix[i][j]), self.tree)):
print("Zgodna z aktualnym trybem, czynnosc wykonywana")
self.path.find_path(self.traktor, self.field, self.ui, [j, i])
self.ui.update()
time.sleep(0.5)
```

9
ui.py
View File

@ -1,5 +1,5 @@
import pygame
import random
class game_ui():
def __init__(self,traktor,field):
@ -34,8 +34,11 @@ class game_ui():
self.pole1_surf_rect.y = self.POLE_POZ[1] - 75
self.traktor_img = ["traktor_d.png", "traktor_l.png", "traktor_u.png", "traktor_r.png"]
self.field_images = []
for i in ['gleba_pix.png','gleba_chwasty_pix.png','sadzonka_suchi_pix.png','sadzonka_chwasty_pix.png','gleba_mokra_pix.png','gleba_mokra_chwasty.png','sadzonka_mokra_pix.png','sadzonka_mokra_chwasty_pix.png','gotowy_burak_pix.png']:
self.field_images.append(pygame.image.load('images/'+i))
# self.field_images_path = []
# self.random = random.randint(0,99)
for i in ['gleba_pix','gleba_chwasty_pix','sadzonka_suchi_pix','sadzonka_chwasty_pix','gleba_mokra_pix','gleba_mokra_chwasty','sadzonka_mokra_pix','sadzonka_mokra_chwasty_pix','gotowy_burak_pix']:
# self.field_images_path.append("images/"+i+"/"+i+str(self.random)+".png")
self.field_images.append(pygame.image.load("images/"+i+".png"))
# Zezwalamy na przechwytywanie klawiszy
pygame.event.pump()