Compare commits

..

No commits in common. "master" and "kacperB" have entirely different histories.

92 changed files with 74 additions and 559 deletions

3
.gitignore vendored
View File

@ -2,5 +2,4 @@ venv/
.vscode/
.ideagit
.idea
__pycache__/
/resources/smieci w kontenerach
__pycache__/

View File

@ -8,13 +8,13 @@
## 1. Ogólne działanie:
![gif](../screenShots/gifProjektu.gif)
![gif](resources/screenShots/gifProjektu.gif)
---
## 2. Struktura katalogów:
![katalogi](../screenShots/strukturaKatalogu.png)
![katalogi](resources/screenShots/strukturaKatalogu.png)
**Resources**:
@ -24,18 +24,18 @@
**Pliki**:
**[game.py](../../src/game.py)** - plik zawierający całą funkcjonalność projektu:
**[game.py](game.py)** - plik zawierający całą funkcjonalność projektu:
- główna pętla programu,
- tworzenie planszy,
- tworzenie i usytuowanie obiektów z katalogu [modeli](../../src/modele.py),
- tworzenie i usytuowanie obiektów z katalogu [modeli](modele.py),
- generowanie tekstowej interpretacji zebranej wiedzy
**[main.py](../../src/main.py)** - klasa odpowiedzialna za uruchomienie programu
**[main.py](main.py)** - klasa odpowiedzialna za uruchomienie programu
**[modele.py](../../src/modele.py)** - zawiera klasy aplikacji
**[modele.py](modele.py)** - zawiera klasy aplikacji
**[requirements.txt](../../requirements.txt)** - posiada biblioteki niezbędne do uruchomienia programu, które instalujemy za pomocą poniższego polecenia:
**[requirements.txt](requirements.txt)** - posiada biblioteki niezbędne do uruchomienia programu, które instalujemy za pomocą poniższego polecenia:
```
pip install -r requirements.txt
@ -46,23 +46,23 @@ pip install -r requirements.txt
## 3. Opis funkcjonalności programu:
* śmieciarka porusza się w losowy sposób po planszy 15 x 15 (koloruje na niebiesko przebytą trasę)
![ruch śmieciarki](../screenShots/randMove.png)
![ruch śmieciarki](resources/screenShots/randMove.png)
* domy generowane są losowo na mapie z pominięciem kolizji z innymi obiektami
![generowanie_domów](../screenShots/wspolrzedneDomow.png)
![generowanie_domów](resources/screenShots/wspolrzedneDomow.png)
* pozycja wysypiska, przeszkody (jeziorko) i kontenerów jest statyczna
![statyczna_pozycja](../screenShots/statycznaPozycja.png)
![statyczna_pozycja](resources/screenShots/statycznaPozycja.png)
* w kontenerach przechowywane będą posegregowane, odpowiednio według kategorii, zdjęcia śmieci
* zdjęcia śmieci będą przydzielane w sposób losowy do każdego z domów na planszy
![losowanie_śmieci](../screenShots/wyborSmieci.png)
![losowanie_śmieci](resources/screenShots/wyborSmieci.png)
* śmieciarka zbiera śmieci po najechaniu na pozycję danego domu
* po każdym uruchomieniu programu tworzona jest struktura katalogów dla posegregowanych śmieci
![tworzenie_struktury](../screenShots/tworzenieStrukturyKatalogow.png)
![tworzenie_struktury](resources/screenShots/tworzenieStrukturyKatalogow.png)
* śmieciarka sprawdza w każdym ruchu czy nie dojdzie do kolizji z innym obiektem lub nie wyjedzie poza planszę
![sprawdzanie_kolizcji](../screenShots/sprawdzanieKolizji.png)
![sprawdzanie_kolizcji](resources/screenShots/sprawdzanieKolizji.png)
* po prawej stronie wypisywane są aktualne, najważniejsze informacje
![wiedza](../screenShots/wiedzaPoPrawejStronie.png)
![wiedza](resources/screenShots/wiedzaPoPrawejStronie.png)
* każdy obiekt na planszy posiada atrybuty odpowiedzalne za
przechowywanie wiedzy o danym obiekcie np.: obiekt śmieciarka przechowuje informacje o odwiedzonych domach
![atrybuty](../screenShots/atrybutySmieciarki.png)
![atrybuty](resources/screenShots/atrybutySmieciarki.png)

View File

@ -3,25 +3,25 @@ import modele
import numpy as np
import random
import os
import shutil
import astar
import uczenie_kacper as kacper
import uczenie_adamO as adamO
import uczenie_adamB as adamB
smieci_path = ''
smieci_w_kontenerach = "..\\resources\\smieci w kontenerach"
smieci_w_kontenerach = "resources\\smieci w kontenerach"
# PODAJ OSOBE PRZED URUCHOMIENIEM (kacper/adamB/adamO)
osoba = 'kacper'
rfc = None
if osoba == 'kacper':
smieci_path = '..\\resources\\smieci'
smieci_path = 'resources/smieci'
elif osoba == 'adamB':
smieci_path = '..\\resources\\smieci'
smieci_path = 'resources/smieci_stare'
else:
smieci_path = '..\\resources\\smieci_stare'
smieci_path = 'resources/smieci_stare'
rfc = adamO.rozpocznijUczenie()
pygame.init()
@ -53,10 +53,8 @@ def game():
obiekty = utworzObiekty()
nieodwiedzone_domy = obiekty["wspolrzedne_domow"]
nieodwiedzone_kontenery = [(obiekty["kontener_szklo"].x, obiekty["kontener_szklo"].y),
(obiekty["kontener_papier"].x,
obiekty["kontener_papier"].y),
(obiekty["kontener_metal"].x,
obiekty["kontener_metal"].y),
(obiekty["kontener_papier"].x, obiekty["kontener_papier"].y),
(obiekty["kontener_metal"].x, obiekty["kontener_metal"].y),
(obiekty["kontener_plastik"].x, obiekty["kontener_plastik"].y), ]
# Petla az uzytkownik zamknie program
done = False
@ -94,8 +92,7 @@ def game():
nieodwiedzone_domy.sort(
key=lambda x: astar.heurystyka((obiekty["smieciarka"].x, obiekty["smieciarka"].y), x))
cel = nieodwiedzone_domy.pop(0)
obiekty["smieciarka"].astar_move(
obiekty, (obiekty["smieciarka"].x, obiekty["smieciarka"].y), cel)
obiekty["smieciarka"].astar_move(obiekty, (obiekty["smieciarka"].x, obiekty["smieciarka"].y), cel)
pozX = cel[0]
pozY = cel[1]
for dom in obiekty["domy"]:
@ -107,7 +104,7 @@ def game():
if osoba == 'kacper':
rodzaj = kacper.przewidz(smiec)
elif osoba == 'adamB':
rodzaj = adamB.predict(smiec)
pass
else:
rodzaj = adamO.przewidz(smiec, rfc)
@ -124,8 +121,7 @@ def game():
nieodwiedzone_kontenery.sort(
key=lambda x: astar.heurystyka((obiekty["smieciarka"].x, obiekty["smieciarka"].y), x))
cel = nieodwiedzone_kontenery.pop(0)
obiekty["smieciarka"].astar_move(
obiekty, (obiekty["smieciarka"].x, obiekty["smieciarka"].y), cel)
obiekty["smieciarka"].astar_move(obiekty, (obiekty["smieciarka"].x, obiekty["smieciarka"].y), cel)
pozX = cel[0]
pozY = cel[1]
@ -165,9 +161,9 @@ def rysowaniePlanszy(obiekty):
HEIGHT])
obiekty["obraz"].blit(pygame.image.load(
"../resources/plansza/wysypisko.jpg"), (5, 5))
"resources/plansza/wysypisko.jpg"), (5, 5))
obiekty["obraz"].blit(pygame.image.load(
"../resources/plansza/jezioro.png"), (395, 655))
"resources/plansza/jezioro.png"), (395, 655))
obiekty["plansza"][6, 10].setJestPrzeszkoda(True)
obiekty["plansza"][6, 11].setJestPrzeszkoda(True)
obiekty["plansza"][7, 10].setJestPrzeszkoda(True)
@ -208,40 +204,38 @@ def utworzObiekty():
os.makedirs(smieci_w_kontenerach)
else:
for dir in os.listdir(os.getcwd() + "\\" + smieci_w_kontenerach):
files = os.listdir(os.getcwd() + "\\" +
smieci_w_kontenerach + "\\" + dir)
files = os.listdir(os.getcwd() + "\\" + smieci_w_kontenerach + "\\" + dir)
for file in files:
os.remove(os.getcwd() + "\\" +
smieci_w_kontenerach + "\\" + dir + "\\" + file)
os.remove(os.getcwd() + "\\" + smieci_w_kontenerach + "\\" + dir + "\\" + file)
kontener_szklo = modele.Kontener(4, 4, "glass")
kontener_szklo.setImage(pygame.image.load(
"../resources/plansza/pojemnik_szklo.png"))
"resources/plansza/pojemnik_szklo.png"))
plansza[4, 4].setJestKontenerem(True)
plansza[4, 4].setObiekt(kontener_szklo)
kontener_metal = modele.Kontener(0, 4, "metal")
kontener_metal.setImage(pygame.image.load(
"../resources/plansza/pojemnik_metal.png"))
"resources/plansza/pojemnik_metal.png"))
plansza[0, 4].setJestKontenerem(True)
plansza[0, 4].setObiekt(kontener_metal)
kontener_papier = modele.Kontener(4, 0, "paper")
kontener_papier.setImage(pygame.image.load(
"../resources/plansza/pojemnik_papier.png"))
"resources/plansza/pojemnik_papier.png"))
plansza[4, 0].setJestKontenerem(True)
plansza[4, 0].setObiekt(kontener_papier)
kontener_plastik = modele.Kontener(0, 0, "plastic")
kontener_plastik.setImage(pygame.image.load(
"../resources/plansza/pojemnik_plastik.png"))
"resources/plansza/pojemnik_plastik.png"))
plansza[0, 0].setJestKontenerem(True)
plansza[0, 0].setObiekt(kontener_plastik)
# domy
doms_array = ['../resources/plansza/domy/dom1.png', '../resources/plansza/domy/dom2.png',
'../resources/plansza/domy/dom3.png', '../resources/plansza/domy/dom4.png',
'../resources/plansza/domy/dom5.png']
doms_array = ['resources/plansza/domy/dom1.png', 'resources/plansza/domy/dom2.png',
'resources/plansza/domy/dom3.png', 'resources/plansza/domy/dom4.png',
'resources/plansza/domy/dom5.png']
domy_lista = pygame.sprite.Group()
@ -259,8 +253,7 @@ def utworzObiekty():
dom.setImage(pygame.image.load(random.choice(doms_array)))
plansza[wspolrzedne_domow[i][0],
wspolrzedne_domow[i][1]].setJestDomem(True)
plansza[wspolrzedne_domow[i][0],
wspolrzedne_domow[i][1]].setObiekt(dom)
plansza[wspolrzedne_domow[i][0], wspolrzedne_domow[i][1]].setObiekt(dom)
domy_lista.add(dom)
all_sprites_list.add(dom)
@ -315,14 +308,10 @@ def liczSmieci(domy, obiekty):
elif "glass" in s:
ile_szkla += 1
text_metal = obiekty["font"].render(
"Metal: " + str(ile_metalu), True, WHITE)
text_papier = obiekty["font"].render(
"Papier: " + str(ile_papieru), True, WHITE)
text_plastik = obiekty["font"].render(
"Plastik: " + str(ile_plastiku), True, WHITE)
text_szklo = obiekty["font"].render(
"Szkło: " + str(ile_szkla), True, WHITE)
text_metal = obiekty["font"].render("Metal: " + str(ile_metalu), True, WHITE)
text_papier = obiekty["font"].render("Papier: " + str(ile_papieru), True, WHITE)
text_plastik = obiekty["font"].render("Plastik: " + str(ile_plastiku), True, WHITE)
text_szklo = obiekty["font"].render("Szkło: " + str(ile_szkla), True, WHITE)
text_pozostale = obiekty["font"].render(
"Pozostałe: " + str(ile_pozostalych), True, WHITE)
text_odwiedzone_domy = obiekty["font"].render(

View File

@ -10,7 +10,7 @@
## 1. Model:
![model](../screenShots/kacper1.png)
![model](resources/screenShots/kacper1.png)
- Powyższa funkcja tworzy sekwencyjny model sieci neuronowej
- Składa się on z warstw
@ -25,7 +25,7 @@
## 2. Uczenie modelu:
![uczenie](../screenShots/kacper2.png)
![uczenie](resources/screenShots/kacper2.png)
- Model uczy się na 1599 zdjęciach śmieci podzielonych na 4 kategorie
- Wszystkie zdjęcia mają rozmiar 299x299 pikseli
@ -36,7 +36,7 @@
## 2. Przewidywanie:
![przewidywanie](../screenShots/kacper3.png)
![przewidywanie](resources/screenShots/kacper3.png)
- Obrazki są zamieniane na macierze
- Prediction zawiera rozkład prawdopodobieństwa obrazka na kategorie
@ -46,7 +46,7 @@
## 2. Integracja w projekcie:
![integracja](../screenShots/kacper4.png)
![integracja](resources/screenShots/kacper4.png)
- Podczas wizyty śmieciarki w domu wykonywana jest funkcja przewidzenia kategorii na każdym ze śmieci w danym domu
- Zależnie od wyniku przewidywania śmieć jest umieszczany na odpowiedniej liście śmieci w śmieciarce

View File

@ -25,7 +25,7 @@ class Smieciarka(pygame.sprite.Sprite):
def __init__(self, x, y):
self.x = x
self.y = y
self.image = pygame.image.load('../resources/plansza/smieciarka.png')
self.image = pygame.image.load('resources/plansza/smieciarka.png')
self.obraz = None
self.ruch = 1
self.plastik = []
@ -79,7 +79,7 @@ class Smieciarka(pygame.sprite.Sprite):
self.zwiekszIloscOdwiedzonychDomow()
if self.ruch == 2:
self.image = pygame.image.load(
'../resources/plansza/smieciarka.png')
'resources/plansza/smieciarka.png')
self.ruch = 1
self.plansza[self.x - 1, self.y].setKolor(BLUE)

View File

@ -1,58 +1,2 @@
absl-py==0.9.0
astunparse==1.6.3
autopep8==1.5
cachetools==4.1.0
certifi==2020.4.5.1
chardet==3.0.4
cycler==0.10.0
future==0.18.2
gast==0.3.3
google-auth==1.14.3
google-auth-oauthlib==0.4.1
google-pasta==0.2.0
grpcio==1.29.0
h5py==2.10.0
idna==2.9
importlib-metadata==1.6.0
joblib==0.15.0
Keras==2.3.1
Keras-Applications==1.0.8
Keras-Preprocessing==1.1.2
kiwisolver==1.2.0
mahotas==1.4.9
Markdown==3.2.2
matplotlib==3.2.1
numpy==1.18.0
oauthlib==3.1.0
opencv-python==4.2.0.34
opt-einsum==3.2.1
Pillow==7.1.2
protobuf==3.11.3
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycodestyle==2.5.0
pydotplus==2.0.2
pygame==1.9.6
pyparsing==2.4.7
PyQt5==5.14.2
python-dateutil==2.8.1
PyYAML==5.3.1
requests==2.23.0
requests-oauthlib==1.3.0
rsa==4.0
scikit-learn==0.23.0
scipy==1.4.1
sip==5.3.0
six==1.14.0
tensorboard==2.2.1
tensorboard-plugin-wit==1.6.0.post3
tensorflow==2.2.0
tensorflow-estimator==2.2.0
termcolor==1.1.0
threadpoolctl==2.0.0
torch==1.5.0
torchvision==0.6.0
urllib3==1.25.9
Werkzeug==1.0.1
wrapt==1.12.1
zipp==3.1.0
numpy==1.18

Binary file not shown.

View File

@ -1,118 +0,0 @@
# Sztuczna Inteligencja
**Temat projektu:** Inteligenta Śmieciarka
**Zespół:** Kacper Borkowski, Adam Borowski, Adam Osiowy
**Podprojekt:** Adam Osiowy - *segregator śmieci*
---
## Opis podprojektu:
- w projekcie wykorzystane zostały drzewa decyzyjne jako metoda uczenia
- projekt podzielony jest na 4 pliki
- plik tworzenie_danych_AO.py jest odpowiedzialny za wydobycie z każdego zdjęcia własności i zapis ich do pliku
![4](../screenShots/adamo4.png)
- w pliku uczenie_adamO.py znajdują się funkcje odpowiedzialne za uczenie i testowanie modelu
![5](../screenShots/adamo5.png)
- plik parametry_zdjec.h5 zawiera własności wszystkich zdjęć wykorzystanych w projekcie
- plik etykiety.h5 zawiera odpowiedni typ każdego ze zdjęć (glass,paper,plastic,metal)
---
## Ogólne działanie:
- na początku zbierane są informacje o każdym zdjęciu
```
momenty = wyznaczHuMomenty(zdj)
haralick = wyznaczHaralick(zdj)
histogram = wyznaczHistogram(zdj)
```
- wybrane własności to:
1. Histogram kolorów okreslający rozkład jasności pixeli w każdej komórce na zdjęciu w skali szarości
![6](../screenShots/adamo6.png)
zdjęcie jest przekształcane do przestrzeni barw hsv
po czym wyliczany jest histogram podając do funkcji zdjęcie, kanały (hsv), maskę, podział zdjęcia na 512 przedziałów (8x8x8), zakres każdego kanału
2. Momenty obrazu (Hu Moments) określające kształt obiektu na zdjęciu
![8](../screenShots/adamo8.png)
są średnią ważoną intensywności pikseli obrazu.
Są liczone ze wzoru:
![10](../screenShots/adamo10.png)
gdzie I(x,y) to intensywność pixela w danym punkcie
*Momenty surowe* - informują o intensywności pikseli i ich położeniu na obrazie
*Momenty centralne* - otrzymujemy po odjęciu od momentów surowych środka ciężkości danego kształtu
![11](../screenShots/adamo11.png)
momenty te są niezmienne w wyliczaniu to znaczy że jeśli kształt jest ten sam to nie ważne jest jego położenie na zdjęciu
*Momenty Hu* - to zbiór 7 liczb obliczonych na podstawie momentów centralnych.
Pierwsze 6 momentów są niezmienne dla translacji, skali i rotacji.
Podczas gdy znak siódmej liczby zmienia się wraz z odbiciem kształu (względem osi).
![12](../screenShots/adamo12.png)
3. Tekstura Haralicka określająca nasycenie ilości pixeli w skali szarości
![7](../screenShots/adamo7.png)
"Haralick zasugerował zastosowanie macierzy współwystępowania poziomu szarości (GLCM).
Ta metoda opiera się na połączonych rozkładach prawdopodobieństwa par pikseli.
GLCM pokazuje, jak często każdy poziom szarości występuje w pikselach umieszczonych w ustalonym położeniu
geometrycznym względem siebie, w zależności od poziomu szarości."
![13](../screenShots/adamo13.png)
- własności sa zapisywane jako macierze, ustawiane w szereg jako wiersz i zapisywane do pliku z danymi .h5
```
wiersz = np.hstack([momenty, histogram, haralick])
```
- dane dzielone są losowo na 2 pary, jedna testowa druga treningowa
```
(uczenieDane, testowanieDane, uczenieEtykiety, testowanieEtykiety) =
train_test_split(np.array(dane), np.array(etykiety), test_size=rozmiar_zbioru_testowego)
```
gdzie rozmiar zbioru testowego określony wcześniej na 20%
- tworzony jest estymator
```
rfc = RandomForestClassifier(max_depth=15, n_jobs=4, random_state=1)
```
gdzie n_jobs to ilość wątków, random_state pilnuje aby zbiór był zawsze dzielony tak samo,
a max_depth to maksymalna głebokość każdego drzewa
estymator domyślnie korzysta ze strategii opierającej się o indeks Giniego
```
'indeks Giniego jest to miara która określa jak często losowo wybrany element zostanie błędnie zidentyfikowany'
```
indeks jest obliczany ze wzoru:
![9](../screenShots/adamo9.png)
[przykład](https://www.geeksforgeeks.org/decision-tree-introduction-example/)
- estymator rozpoczyna uczenie korzystając ze zbiorów treningowych
```
rfc.fit(uczenieDane, uczenieEtykiety)
```
- następnie wyliczana jest skuteczność na zbiorach testowych
```
rfc.score(testowanieDane, testowanieEtykiety)
```
---
## Integracja z projektem zespołowym:
- Przy starcie programu estymator rozpoczyna nauke
```
rfc = adamO.rozpocznijUczenie()
```
- Śmieciarka porusza się po domach zbierając z nich śmieci
- Po zebraniu wszystkich śmieci kieruje się na wysypisko
- Każde zdjęcie śmieci jest segregowane z wykorzystaniem funkcji przewidującej typ
```
rodzaj = adamO.przewidz(smiec, rfc)
```
![3](../screenShots/adamo3.png)
- Zdjęcia posegregowanych śmieci umieszczane są w odpowiednich folderach:
![1](../screenShots/adamo1.png)
- Na koniec wyświetlane są losowo wybrane zdjęcia śmieci z kontenerów wraz z informacją o typie ustalonym przez estymator
![2](../screenShots/adamo2.png)
1. górny napis to typ zwrócony przez estymator
2. drugi napis to wartości prawpopodobieństwa z jakim estymator ocenił typ
3. trzeci napis to nazwa zdjęcia
---
## Efekt działania programu w postaci drzewa decyzyjnego:
![10](graph.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 MiB

View File

@ -1,129 +0,0 @@
# Sztuczna Inteligencja
**Temat projektu:** Inteligenta Śmieciarka
**Zespół:** Kacper Borkowski, Adam Borowski, Adam Osiowy
**Podprojekt:** Adam Borowski
---
## 1. Temat podprojektu:
Celem projektu było utworzenie klasyfikatora rodzajów danych wejściowych(śmieci) na podstawie zdjęć. Do tego celu wykorzystano bibliotekę [PyTorch](https://pytorch.org/docs/stable/index.html). Cały podprojekt opiera się na utworzeniu sieci neuronowej i przetworzeniu inputu przez kolejne jej warstwy.
## 2. Model sieci:
```
class Net(nn.Module): # klasa Net dziedziczaca po klasie bazowej nn.Module
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 71 * 71, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 4)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(x.size(0), 16 * 71 * 71)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
```
- conv1, conv2 warstwy konwolucyjna, rozmiar filtra 5×5, posiadające 3 kanały wejściowe (RGB) i kanały wyjściowe dla następnych warstw
- pool - operacja `max-poolingu` - wyciaganie najwazniejszej informacji z zadanego obszaru obrazu
![model](../screenShots/maxpool.png)
- fc1, fc2, fc3 - warstwy liniowe - `full connection layers` - w odróznieniu od warstw konwolucyjnych, każdy neuron dostaje input o neuronie z poprzedniej warstwy. W warstwie konwolucyjnej neurony wiedzą tylko o określonych neuronach z poprzedniego layera
![model](../screenShots/fc.png)
- metoda `forward` - metoda forward określa cały przepływ(flow) inputu przez warstwy aż do outputu. W pierwszej części tensor danej wejściowej(tensor zdjęcia) przepuszczany jest przez dwie warstwy konwolucyjne i wykonywana jest na nim wcześniej wspomniana operacja `max-poolingu`. W następnej części wypłaszczamy x, wszystkie wymiary przechowujace dane obrazu 16 kanalow o rozmiarach 71×71 rozciągamy jako jeden długi wektor. Na koniec przepuszczamy tensor przez warstwy liniowe i zwracamy output.
## 3. Trening:
```
def train():
net = Net()
trainset = torchvision.datasets.ImageFolder(
root='./resources/zbior_uczacy', transform=transform)
trainloader = torch.utils.data.DataLoader(
trainset, batch_size=1, shuffle=True, num_workers=2)
classes = ('glass', 'metal', 'paper', 'plastic')
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
for epoch in range(10):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i:
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss))
running_loss = 0.0
print('Finished Training')
PATH = './wytrenowaned.pth'
torch.save(net.state_dict(), PATH)
```
- na początku zainicjowano sieć, pobrano zbiór uczący i znormalizowano jego wnętrze, aby każde zdjęcie było pod postacią Tensora(tego wymaga model sieci)
- następnie zdefiniowano kryterium do wyznaczania jakości klasyfikacji zdjęć do klas i wyznaczono optymalizator
- potem wchodzimy do pętli i iterujemy po data secie, pobieramy inputy, czyścimy gradienty z poprzedniej iteracji, za pomocą algorytmu propagacji wstecznej liczymy pochodne z utraconej wartości, wyswietlamy w konsoli loss z danej iteracji,
- następnie zapisujemy wytrenowany model
## 4. Przewidywanie:
```
def predict(img_path):
net = Net()
PATH = './wytrenowaned.pth'
img = Image.open(img_path)
pil_to_tensor = transforms.ToTensor()(img).unsqueeze_(0)
classes = ('glass', 'metal', 'paper', 'plastic')
net.load_state_dict(torch.load(PATH))
net.eval()
outputs = net(pil_to_tensor)
return classes[torch.max(outputs, 1)[1]]
```
- zainicjowano sieć, wczytano ścieżke, przetransformowano argument funkcji(zdjecie) do porządanego formatu
- następnie przekazano tensor jako argument do instancji klasy sieci
- w ostatnim kroku za pomocą funkcji `max` wyciągnięto największą wagę i na jej podstawie rozpoznano klasę
## 5. Integracja w projekcie:
```
for dom in obiekty["domy"]:
if dom.x == pozX and dom.y == pozY:
while dom.smieci:
smiec = dom.smieci.pop(0)
rodzaj = ""
if osoba == 'kacper':
rodzaj = kacper.przewidz(smiec)
elif osoba == 'adamB':
rodzaj = adamB.predict(smiec)
else:
rodzaj = adamO.przewidz(smiec, rfc)
if rodzaj == "paper":
obiekty["smieciarka"].dodajPapier(smiec)
elif rodzaj == "glass":
obiekty["smieciarka"].dodajSzklo(smiec)
elif rodzaj == "metal":
obiekty["smieciarka"].dodajMetal(smiec)
elif rodzaj == "plastic":
obiekty["smieciarka"].dodajPlastik(smiec)
```
- zgodnie z wybraną osobą na starcie wykonywana jest odpowiednia funkcja przewidywania na śmieciach w poszczególnych domach
- finalnie zdjęcia posortowanych śmieci znajdują się w kontenerach(folder `smieci w kontenerach`)

View File

@ -1,50 +0,0 @@
# Raport końcowy
**Temat projektu:** Inteligenta Śmieciarka
**Zespół:** Kacper Borkowski, Adam Borowski, Adam Osiowy
---
## Krótkie wyjaśnienie integracji podprojektów:
Celem projektu było utworzenie inteligentnej śmieciarki. Jej zadaniem było zbieranie śmieci ze wszystkich domów na planszy korzystając z algorytmu _A*_. Docelowo, wybierając jeden z trzech zaimplementowanych przez nas klasyfikatorów, śmieciarka segreguje odpady w kontenerach. Ich zdjęcia trafiają następnie do posortowanego folderu _smieci w kontenerach_.
```
for dom in obiekty["domy"]:
if dom.x == pozX and dom.y == pozY:
while dom.smieci:
smiec = dom.smieci.pop(0)
rodzaj = ""
if osoba == 'kacper':
rodzaj = kacper.przewidz(smiec)
elif osoba == 'adamB':
rodzaj = adamB.predict(smiec)
else:
rodzaj = adamO.przewidz(smiec, rfc)
if rodzaj == "paper":
obiekty["smieciarka"].dodajPapier(smiec)
elif rodzaj == "glass":
obiekty["smieciarka"].dodajSzklo(smiec)
elif rodzaj == "metal":
obiekty["smieciarka"].dodajMetal(smiec)
elif rodzaj == "plastic":
obiekty["smieciarka"].dodajPlastik(smiec)
```
Tworzenie katalogu:
```
# kontenery
if not os.path.exists(smieci_w_kontenerach):
os.makedirs(smieci_w_kontenerach)
else:
for dir in os.listdir(os.getcwd() + "\\" + smieci_w_kontenerach):
files = os.listdir(os.getcwd() + "\\" +
smieci_w_kontenerach + "\\" + dir)
for file in files:
os.remove(os.getcwd() + "\\" +
smieci_w_kontenerach + "\\" + dir + "\\" + file)
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -8,7 +8,7 @@
## 1. Ogólne działanie:
![gif](../screenShots/route-planning.gif)
![gif](resources/screenShots/route-planning.gif)
- Śmieciarka zaczyna ruch z pozycji (10, 10), po czym odwiedza wszystkie domy,
których współrzędne zostały wylosowane, następnie jedzie na wysypisko do najbliższego kontenera,
@ -20,7 +20,7 @@ po czym wybiera następny najbliższy nieodwiedzony kontener.
## 2. Pętla główna strategii przeszukiwania:
![petla](../screenShots/petlaGlowna.png)
![petla](resources/screenShots/petlaGlowna.png)
- w pętli głównej wykorzystujemy przeszukiwanie grafu (graphsearch)
- tworzymy kolejkę priorytetową, po czym dodajemy do niej bieżący węzeł
@ -36,7 +36,7 @@ po czym wybiera następny najbliższy nieodwiedzony kontener.
## 3. Funkcja następnika:
![succ](../screenShots/funkcjaNastepnika.png)
![succ](resources/screenShots/funkcjaNastepnika.png)
gdzie sąsiedzi to:
```
@ -51,7 +51,7 @@ sasiedzi = [(0, 1), (0, -1), (1, 0), (-1, 0)]
## 4. Przyjęta heurystyka:
![heurystyka](../screenShots/heurystyka.png)
![heurystyka](resources/screenShots/heurystyka.png)
- Heurystyka to suma odległości Manhattan
@ -59,7 +59,7 @@ sasiedzi = [(0, 1), (0, -1), (1, 0), (-1, 0)]
## 5. Koszt wjechania na pole
![stepcost](../screenShots/stepcost.png)
![stepcost](resources/screenShots/stepcost.png)
- Koszt wjechania na pole, na którym jest dom wynosi 3
- Koszt wjechania na pole, które jest wysypiskiem wynosi 2

View File

@ -1,19 +0,0 @@
import torch
import cv2
import torchvision
import torch.nn as nn
import torch.nn.functional as F
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
import torch.optim as optim
from PIL import Image
import os
for filename in os.listdir('../resources/smieci/plastic'):
img = Image.open('../resources/smieci/plastic/'+filename)
pil_to_tensor = transforms.ToTensor()(img).unsqueeze_(0)
if(str(pil_to_tensor.shape[1]) == '1'):
print(filename)

View File

@ -1,79 +0,0 @@
import torch
import cv2
import torchvision
import torch.nn as nn
import torch.nn.functional as F
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
import torch.optim as optim
from PIL import Image
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 71 * 71, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 4)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(x.size(0), 16 * 71 * 71)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
def train():
net = Net()
trainset = torchvision.datasets.ImageFolder(
root='./resources/zbior_uczacy', transform=transform)
trainloader = torch.utils.data.DataLoader(
trainset, batch_size=2, shuffle=True, num_workers=2)
classes = ('glass', 'metal', 'paper', 'plastic')
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
for epoch in range(10):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i:
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss))
running_loss = 0.0
print('Finished Training')
PATH = '../resources/dane/wytrenowaned.pth'
torch.save(net.state_dict(), PATH)
def predict(img_path):
net = Net()
PATH = '../resources/dane/wytrenowaned.pth'
img = Image.open(img_path)
pil_to_tensor = transforms.ToTensor()(img).unsqueeze_(0)
classes = ('glass', 'metal', 'paper', 'plastic')
net.load_state_dict(torch.load(PATH))
net.eval()
outputs = net(pil_to_tensor)
return classes[torch.max(outputs, 1)[1]]

View File

@ -6,9 +6,9 @@ import os
import h5py
rozmiar_zdj = tuple((500, 500))
sciezka_do_zdj = "../resources/dane/smieci_stare"
h5_dane = '../resources/dane/parametry_zdjec.h5'
h5_etykiety = '../resources/dane/etykiety.h5'
sciezka_do_zdj = "resources/smieci_stare"
h5_dane = 'parametry_zdjec.h5'
h5_etykiety = 'etykiety.h5'
def wyznaczHuMomenty(zdj):

View File

@ -10,17 +10,14 @@ import matplotlib.pyplot as plt
import mahotas
import random
from math import ceil
from io import StringIO
from sklearn.tree import export_graphviz
import pydotplus
warnings.filterwarnings('ignore')
rozmiar_zbioru_testowego = 0.20
katalog_uczacy = "..\\resources\\smieci_stare"
katalog_testujacy = "..\\resources\\smieci w kontenerach"
h5_parametry = '..\\resources\\dane\\parametry_zdjec.h5'
h5_etykiety = '..\\resources\\dane\\etykiety.h5'
katalog_uczacy = "resources\\smieci_stare"
katalog_testujacy = "resources\\smieci w kontenerach"
h5_parametry = 'parametry_zdjec.h5'
h5_etykiety = 'etykiety.h5'
rozmiar_zdj = tuple((500, 500))
@ -32,8 +29,7 @@ def wyznaczHuMomenty(zdj):
def wyznaczHistogram(zdj, mask=None):
zdj = cv2.cvtColor(zdj, cv2.COLOR_BGR2HSV)
hist = cv2.calcHist([zdj], [0, 1, 2], mask, [8, 8, 8],
[0, 256, 0, 256, 0, 256])
hist = cv2.calcHist([zdj], [0, 1, 2], mask, [8, 8, 8], [0, 256, 0, 256, 0, 256])
cv2.normalize(hist, hist)
return hist.flatten()
@ -61,25 +57,12 @@ def rozpocznijUczenie():
h5f_etykiety.close()
(uczenieDane, testowanieDane, uczenieEtykiety, testowanieEtykiety) = train_test_split(np.array(dane),
np.array(
etykiety),
np.array(etykiety),
test_size=rozmiar_zbioru_testowego)
rfc = RandomForestClassifier(max_depth=15, n_jobs=4, random_state=1)
rfc.fit(uczenieDane, uczenieEtykiety)
print("uzyskana skutecznosc: ", rfc.score(
testowanieDane, testowanieEtykiety))
# tworzenie grafu
# dot_data = StringIO()
# print(rfc.estimators_)
# estimator = rfc.estimators_[5]
# export_graphviz(estimator, out_file=dot_data,
# feature_names=dane[1],
# rounded=True, proportion=False,
# precision=2, filled=True,
# special_characters=True, class_names=['glass', 'metal', 'paper', 'plastic'])
# graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
# graph.write_png('graph.png')
print("uzyskana skutecznosc: ", rfc.score(testowanieDane, testowanieEtykiety))
return rfc
@ -94,8 +77,7 @@ def przewidz(zdjecie, rfc):
haralick = wyznaczHaralick(zdj)
histogram = wyznaczHistogram(zdj)
# ustaw poziomo, jeden za drugim
wiersz = np.hstack([momenty, histogram, haralick])
wiersz = np.hstack([momenty, histogram, haralick]) # ustaw poziomo, jeden za drugim
wiersz = wiersz.reshape(1, -1) # zmniejsz wymiar z 2 do 1
przewidywany_typ = rfc.predict(wiersz)[0] # zwraca wartosc 0,1,2,3
return klasy[przewidywany_typ] # zwraca glass,metal,paper,plastic
@ -122,7 +104,7 @@ def wyswietlZdjecia(rfc):
wszystkie_pliki = sum(wszystkie_pliki, [])
rozmiar = ceil(0.25 * len(wszystkie_pliki))
wybrane_zdjecia = random.sample(wszystkie_pliki, k=rozmiar)
print("ilosc wybranych zdjec: ", len(wybrane_zdjecia))
print("ilosc wybranych zdjec: ",len(wybrane_zdjecia))
for i in wybrane_zdjecia:
zdjecie = cv2.imread(path + "\\" + katalog_testujacy + "\\" + i)
@ -133,19 +115,15 @@ def wyswietlZdjecia(rfc):
haralick = wyznaczHaralick(zdjecie)
histogram = wyznaczHistogram(zdjecie)
# ustaw poziomo, jeden za drugim
wiersz = np.hstack([momenty, histogram, haralick])
wiersz = np.hstack([momenty, histogram, haralick]) # ustaw poziomo, jeden za drugim
wiersz = wiersz.reshape(1, -1) # zmniejsz wymiar z 2 do 1
przewidywany = rfc.predict(wiersz)[0]
prawdopodobienstwo = rfc.predict_proba(wiersz)
cv2.putText(zdjecie, klasy[przewidywany], (3, 30),
cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), thickness=3)
cv2.putText(zdjecie, str(prawdopodobienstwo), (3, 60),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), thickness=1)
cv2.putText(zdjecie, i, (3, 460), cv2.FONT_HERSHEY_SIMPLEX,
1, (255, 0, 0), thickness=2)
cv2.putText(zdjecie, klasy[przewidywany], (3, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), thickness=3)
cv2.putText(zdjecie, str(prawdopodobienstwo), (3, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), thickness=1)
cv2.putText(zdjecie, i, (3, 460), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), thickness=2)
plt.imshow(cv2.cvtColor(zdjecie, cv2.COLOR_BGR2RGB))
plt.show()

View File

@ -9,8 +9,8 @@ from keras import backend as K
img_width, img_height = 299, 299
train_data_dir = '../resources/zbior_uczacy'
validation_data_dir = '../resources/smieci'
train_data_dir = 'resources/zbior_uczacy'
validation_data_dir = 'resources/smieci'
nb_train_samples = 1599
nb_validation_samples = 395
epochs = 1
@ -79,12 +79,12 @@ def trainModel():
validation_data=validation_generator,
validation_steps=nb_validation_samples // batch_size,
shuffle=True)
model.save_weights('../resources/dane/nowy_wytrenowany.h5')
model.save_weights('nowy_wytrenowany.h5')
def przewidz(path):
model = stworzModel()
model.load_weights('../resources/dane/wytrenowany.h5')
model.load_weights('wytrenowany.h5')
img = load_img(path, target_size=(299, 299))
img_array = img_to_array(img)
img_array = np.expand_dims(img_array, axis=0)