akt
This commit is contained in:
BIN
dzien_05/przyklady/adam.jpg
Normal file
BIN
dzien_05/przyklady/adam.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
BIN
dzien_05/przyklady/boat.jpg
Normal file
BIN
dzien_05/przyklady/boat.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 293 KiB |
94
dzien_05/przyklady/obraz.py
Normal file
94
dzien_05/przyklady/obraz.py
Normal file
@@ -0,0 +1,94 @@
|
||||
import os
|
||||
|
||||
import cv2
|
||||
import cv2 as cv
|
||||
import os
|
||||
|
||||
class Obraz:
|
||||
def __init__(self, filename:str, mode:int = cv.IMREAD_COLOR_BGR):
|
||||
self.filename = filename
|
||||
self.mode = mode
|
||||
self.loaded = False
|
||||
self.img = None
|
||||
self.img_other = None
|
||||
self.transform_name = "NOTHING"
|
||||
|
||||
def load_image(self):
|
||||
if self.loaded:
|
||||
return True
|
||||
if not os.path.exists(self.filename):
|
||||
return False
|
||||
# raise FileNotFoundError(self.filename)
|
||||
try:
|
||||
self.img = cv.imread(self.filename, flags=self.mode)
|
||||
self.loaded = True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
return True
|
||||
|
||||
def show_image(self, window_name:str="Window"):
|
||||
if not self.loaded:
|
||||
return False
|
||||
window_name += f" - {self.filename}"
|
||||
cv.imshow(window_name, self.img)
|
||||
cv.waitKey(0)
|
||||
cv.destroyAllWindows()
|
||||
return None
|
||||
|
||||
def show_image_other(self, window_name:str="Window after "):
|
||||
if not self.loaded:
|
||||
return False
|
||||
if self.img_other is None:
|
||||
return False
|
||||
window_name += f" - {self.filename} - {self.transform_name}"
|
||||
combined = cv.hconcat([self.img, self.img_other])
|
||||
cv.imshow(window_name, combined)
|
||||
cv.waitKey(0)
|
||||
cv.destroyAllWindows()
|
||||
return None
|
||||
|
||||
def transform_equalize_histogram(self):
|
||||
if not self.loaded:
|
||||
return False
|
||||
if self.mode == cv.IMREAD_COLOR or self.mode == cv.IMREAD_COLOR_BGR:
|
||||
gray_image = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)
|
||||
self.img_other = cv.equalizeHist(gray_image)
|
||||
self.transform_name = "Equalize Histogram"
|
||||
return True
|
||||
|
||||
def transform_smoothing(self, smoothing_type="GaussianBlur"):
|
||||
"""
|
||||
|
||||
:param smoothing_type: GaussianBlur (default) or medianBlur
|
||||
:return: True or False
|
||||
"""
|
||||
if not self.loaded:
|
||||
return False
|
||||
try:
|
||||
if smoothing_type == "GaussianBlur":
|
||||
self.img_other = cv.GaussianBlur(self.img, (5, 5), 0)
|
||||
else:
|
||||
self.img_other = cv.medianBlur(self.img, 5)
|
||||
self.transform_name = smoothing_type
|
||||
return True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
def return_image_stream(self, type:str="other"):
|
||||
"""
|
||||
|
||||
:param type: other | original
|
||||
:return:
|
||||
"""
|
||||
if not self.loaded:
|
||||
return None
|
||||
if type == "original":
|
||||
return self.img
|
||||
elif type == "other":
|
||||
if self.img_other is None:
|
||||
return None
|
||||
return self.img_other
|
||||
else:
|
||||
return None
|
||||
15
dzien_05/przyklady/ocv_01.py
Normal file
15
dzien_05/przyklady/ocv_01.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import os
|
||||
from exif import Image
|
||||
|
||||
file_name = "adam.jpg"
|
||||
|
||||
if not os.path.exists(file_name):
|
||||
print(f"Brak pliku: {file_name}")
|
||||
# kod błedu na podstawie https://questdb.com/docs/troubleshooting/os-error-codes/
|
||||
exit(5)
|
||||
|
||||
with open(file_name, 'rb') as image_file:
|
||||
image = Image(image_file)
|
||||
|
||||
print(image.list_all())
|
||||
|
||||
28
dzien_05/przyklady/ocv_02.py
Normal file
28
dzien_05/przyklady/ocv_02.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import os
|
||||
import cv2
|
||||
from exif import Image
|
||||
|
||||
file_name = "adam.jpg"
|
||||
|
||||
if not os.path.exists(file_name):
|
||||
print(f"Brak pliku: {file_name}")
|
||||
# kod błedu na podstawie https://questdb.com/docs/troubleshooting/os-error-codes/
|
||||
exit(5)
|
||||
|
||||
with open(file_name, 'rb') as image_file:
|
||||
image = Image(image_file)
|
||||
|
||||
print(image.list_all())
|
||||
|
||||
# czytamy plik
|
||||
flags = cv2.IMREAD_COLOR
|
||||
img = cv2.imread(file_name, flags)
|
||||
print(f"Rozmiary obrazka to: {img.shape=}")
|
||||
rozmiary_exif = f"""
|
||||
Wymiary to {image.x_resolution} x {image.y_resolution}
|
||||
Unit {image.resolution_unit=}
|
||||
"""
|
||||
print(rozmiary_exif)
|
||||
cv2.imshow("nazwa okienka", img)
|
||||
cv2.waitKey(0)
|
||||
cv2.destroyAllWindows()
|
||||
BIN
dzien_05/przyklady/pies.jpg
Normal file
BIN
dzien_05/przyklady/pies.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 MiB |
3
dzien_05/przyklady/requirements.txt
Normal file
3
dzien_05/przyklady/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
matplotlib
|
||||
opencv-python
|
||||
exif
|
||||
5
dzien_05/przyklady/skrypt_01.py
Normal file
5
dzien_05/przyklady/skrypt_01.py
Normal file
@@ -0,0 +1,5 @@
|
||||
import cv2
|
||||
|
||||
print(cv2.__version__)
|
||||
print(f"To jest to {cv2.__version__}")
|
||||
print(f"To też {cv2.__version__=}")
|
||||
11
dzien_05/przyklady/test_klasy_01.py
Normal file
11
dzien_05/przyklady/test_klasy_01.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from funkcje.obraz import Obraz
|
||||
|
||||
obrazek = Obraz("/home/adasiek/Documents/03_foto/00_adam_amerigo_small.png")
|
||||
if obrazek.load_image():
|
||||
obrazek.show_image()
|
||||
# obrazek.transform_equalize_histogram()
|
||||
# obrazek.show_image_other()
|
||||
obrazek.transform_smoothing()
|
||||
obrazek.show_image_other()
|
||||
else:
|
||||
print("Some error")
|
||||
466
dzien_05/przyklady/yolo_test/INSTRUKCJA_OBSLUGI.md
Normal file
466
dzien_05/przyklady/yolo_test/INSTRUKCJA_OBSLUGI.md
Normal file
@@ -0,0 +1,466 @@
|
||||
# Instrukcja Obsługi - Program Transformacji i Detekcji Obrazów
|
||||
|
||||
## Spis treści
|
||||
1. [Uruchomienie programu](#uruchomienie-programu)
|
||||
2. [Wybór źródła obrazu](#wybór-źródła-obrazu)
|
||||
3. [Menu główne](#menu-główne)
|
||||
4. [Opis transformacji](#opis-transformacji)
|
||||
5. [Detekcja obiektów YOLO](#detekcja-obiektów-yolo)
|
||||
6. [Skróty klawiszowe](#skróty-klawiszowe)
|
||||
7. [Rozwiązywanie problemów](#rozwiązywanie-problemów)
|
||||
|
||||
---
|
||||
|
||||
## Uruchomienie programu
|
||||
|
||||
### Krok 1: Instalacja zależności (jednorazowo)
|
||||
```bash
|
||||
cd C:\Praca\ProjektyPython\2025_11_elektryk\dzien_02
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Krok 2: Uruchomienie
|
||||
```bash
|
||||
python test_transform.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Wybór źródła obrazu
|
||||
|
||||
Po uruchomieniu programu zobaczysz menu wyboru źródła obrazu:
|
||||
|
||||
```
|
||||
WYBÓR ŹRÓDŁA OBRAZU
|
||||
============================================================
|
||||
1. Wybierz plik z dysku (okno dialogowe)
|
||||
2. Podaj URL do obrazu w internecie
|
||||
3. Użyj domyślnego obrazu z katalogu dzien_01
|
||||
0. Anuluj
|
||||
============================================================
|
||||
```
|
||||
|
||||
### Opcja 1: Plik z dysku
|
||||
- Otwiera okno dialogowe do wyboru pliku
|
||||
- Obsługuje formaty: JPG, JPEG, PNG, BMP, GIF, TIFF
|
||||
- Możesz wybrać dowolny obraz z komputera
|
||||
|
||||
### Opcja 2: URL z internetu
|
||||
- Wpisz adres URL obrazu (np. z Unsplash, Pixabay)
|
||||
- Przykład: `https://picsum.photos/800/600`
|
||||
- Obraz zostanie pobrany i zapisany tymczasowo
|
||||
|
||||
### Opcja 3: Domyślny obraz
|
||||
- Używa pierwszego obrazu z katalogu `dzien_01`
|
||||
- Szybka opcja do testowania
|
||||
|
||||
---
|
||||
|
||||
## Menu główne
|
||||
|
||||
Po wyborze obrazu zobaczysz menu z 18 dostępnymi transformacjami:
|
||||
|
||||
```
|
||||
DOSTĘPNE TRANSFORMACJE OBRAZU
|
||||
============================================================
|
||||
1. GRAY
|
||||
2. BLUR_GAUSSIAN
|
||||
3. BLUR_MEDIAN
|
||||
4. BLUR_BILATERAL
|
||||
5. CANNY
|
||||
6. EDGE_DETECTION
|
||||
7. THRESHOLD
|
||||
8. ADAPTIVE
|
||||
9. SOBEL
|
||||
10. LAPLACIAN
|
||||
11. CONTOURS
|
||||
12. FACE_DETECTION
|
||||
13. SHARPEN
|
||||
14. EMBOSS
|
||||
15. YOLO_DETECT
|
||||
16. YOLO_DETECT_MEDIUM
|
||||
17. YOLO_DETECT_LARGE
|
||||
18. YOLO_SEGMENT
|
||||
------------------------------------------------------------
|
||||
C. Zmień obraz (wybierz inny plik)
|
||||
0. Wyjście z programu
|
||||
============================================================
|
||||
```
|
||||
|
||||
### Jak używać:
|
||||
1. Wpisz numer transformacji (1-18)
|
||||
2. Naciśnij ENTER
|
||||
3. Poczekaj na przetworzenie obrazu
|
||||
4. Zobaczysz okno z porównaniem: **Oryginalny obraz | Przetworzony obraz**
|
||||
5. Naciśnij dowolny klawisz w oknie obrazu, aby zamknąć
|
||||
6. Naciśnij ENTER w konsoli, aby wrócić do menu
|
||||
7. Wybierz kolejną transformację lub '0' aby zakończyć
|
||||
|
||||
---
|
||||
|
||||
## Opis transformacji
|
||||
|
||||
### 1. GRAY - Skala szarości
|
||||
**Co robi:** Konwertuje kolorowy obraz do skali szarości (czarno-biały).
|
||||
|
||||
**Zastosowanie:**
|
||||
- Uproszczenie obrazu
|
||||
- Przygotowanie do dalszego przetwarzania
|
||||
- Redukcja ilości danych
|
||||
|
||||
**Przykład użycia:** Analiza tekstur, detekcja krawędzi
|
||||
|
||||
---
|
||||
|
||||
### 2. BLUR_GAUSSIAN - Rozmycie Gaussa
|
||||
**Co robi:** Rozmywa obraz używając filtru Gaussa (jądro 15x15).
|
||||
|
||||
**Zastosowanie:**
|
||||
- Redukcja szumu
|
||||
- Wygładzenie obrazu
|
||||
- Usunięcie drobnych szczegółów
|
||||
|
||||
**Parametry:** Rozmiar jądra 15x15 pikseli
|
||||
|
||||
**Przykład użycia:** Przygotowanie obrazu przed detekcją krawędzi
|
||||
|
||||
---
|
||||
|
||||
### 3. BLUR_MEDIAN - Rozmycie medianowe
|
||||
**Co robi:** Rozmywa obraz używając filtru medianowego.
|
||||
|
||||
**Zastosowanie:**
|
||||
- Usuwanie szumu typu "sól i pieprz"
|
||||
- Zachowanie krawędzi lepiej niż Gaussian
|
||||
- Wygładzenie obrazu
|
||||
|
||||
**Przykład użycia:** Czyszczenie zaszumionych zdjęć
|
||||
|
||||
---
|
||||
|
||||
### 4. BLUR_BILATERAL - Rozmycie bilateralne
|
||||
**Co robi:** Rozmywa obraz zachowując ostre krawędzie.
|
||||
|
||||
**Zastosowanie:**
|
||||
- Redukcja szumu z zachowaniem szczegółów
|
||||
- Efekt "wygładzenia skóry" w fotografii
|
||||
- Przygotowanie do segmentacji
|
||||
|
||||
**Zaleta:** Nie rozmywa krawędzi obiektów
|
||||
|
||||
---
|
||||
|
||||
### 5. CANNY - Detekcja krawędzi Canny
|
||||
**Co robi:** Wykrywa krawędzie w obrazie metodą Canny'ego.
|
||||
|
||||
**Zastosowanie:**
|
||||
- Detekcja konturów obiektów
|
||||
- Analiza kształtów
|
||||
- Segmentacja obrazu
|
||||
|
||||
**Parametry:** Progi 100 i 200
|
||||
|
||||
**Wynik:** Biały obraz z czarnymi krawędziami
|
||||
|
||||
---
|
||||
|
||||
### 6. EDGE_DETECTION - Zaawansowana detekcja krawędzi
|
||||
**Co robi:** Wykrywa krawędzie z wcześniejszym rozmyciem Gaussa.
|
||||
|
||||
**Zastosowanie:**
|
||||
- Detekcja krawędzi z redukcją szumu
|
||||
- Lepsza jakość niż zwykły Canny
|
||||
- Analiza struktury obrazu
|
||||
|
||||
**Parametry:** Gaussian blur (5x5), Canny (50, 150)
|
||||
|
||||
---
|
||||
|
||||
### 7. THRESHOLD - Progowanie binarne
|
||||
**Co robi:** Konwertuje obraz do czarno-białego (0 lub 255).
|
||||
|
||||
**Zastosowanie:**
|
||||
- Segmentacja obiektów
|
||||
- Wykrywanie tekstu
|
||||
- Analiza binarna
|
||||
|
||||
**Parametry:** Próg 127
|
||||
|
||||
**Wynik:** Piksele poniżej progu = czarne, powyżej = białe
|
||||
|
||||
---
|
||||
|
||||
### 8. ADAPTIVE - Progowanie adaptacyjne
|
||||
**Co robi:** Progowanie z lokalnie dostosowanym progiem.
|
||||
|
||||
**Zastosowanie:**
|
||||
- Segmentacja przy nierównym oświetleniu
|
||||
- Wykrywanie tekstu w trudnych warunkach
|
||||
- Lepsza jakość niż zwykłe progowanie
|
||||
|
||||
**Zaleta:** Działa dobrze przy zmiennym oświetleniu
|
||||
|
||||
---
|
||||
|
||||
### 9. SOBEL - Detekcja krawędzi Sobel
|
||||
**Co robi:** Wykrywa krawędzie używając operatora Sobela (gradient).
|
||||
|
||||
**Zastosowanie:**
|
||||
- Detekcja krawędzi poziomych i pionowych
|
||||
- Analiza gradientu obrazu
|
||||
- Wykrywanie zmian intensywności
|
||||
|
||||
**Wynik:** Obraz gradientu (jasne = silne krawędzie)
|
||||
|
||||
---
|
||||
|
||||
### 10. LAPLACIAN - Detekcja krawędzi Laplacian
|
||||
**Co robi:** Wykrywa krawędzie używając operatora Laplace'a.
|
||||
|
||||
**Zastosowanie:**
|
||||
- Detekcja krawędzi we wszystkich kierunkach
|
||||
- Wykrywanie ostrości obrazu
|
||||
- Analiza drugiej pochodnej
|
||||
|
||||
**Wynik:** Podkreślone krawędzie
|
||||
|
||||
---
|
||||
|
||||
### 11. CONTOURS - Detekcja konturów
|
||||
**Co robi:** Znajduje i rysuje kontury obiektów na obrazie.
|
||||
|
||||
**Zastosowanie:**
|
||||
- Wykrywanie kształtów obiektów
|
||||
- Liczenie obiektów
|
||||
- Analiza geometrii
|
||||
|
||||
**Wynik:** Zielone kontury narysowane na oryginalnym obrazie
|
||||
|
||||
---
|
||||
|
||||
### 12. FACE_DETECTION - Detekcja twarzy
|
||||
**Co robi:** Wykrywa twarze używając klasyfikatora Haar Cascade.
|
||||
|
||||
**Zastosowanie:**
|
||||
- Wykrywanie twarzy na zdjęciach
|
||||
- Rozpoznawanie ludzi
|
||||
- Analiza portretów
|
||||
|
||||
**Wynik:** Zielone prostokąty wokół wykrytych twarzy z etykietą "Face"
|
||||
|
||||
**Uwaga:** Działa najlepiej z twarzami en face (z przodu)
|
||||
|
||||
---
|
||||
|
||||
### 13. SHARPEN - Wyostrzenie
|
||||
**Co robi:** Wyostrza obraz podkreślając szczegóły.
|
||||
|
||||
**Zastosowanie:**
|
||||
- Poprawa ostrości rozmytych zdjęć
|
||||
- Podkreślenie detali
|
||||
- Poprawa jakości obrazu
|
||||
|
||||
**Efekt:** Obraz staje się bardziej wyrazisty
|
||||
|
||||
---
|
||||
|
||||
### 14. EMBOSS - Efekt wytłoczenia
|
||||
**Co robi:** Tworzy efekt 3D wytłoczenia/rzeźby.
|
||||
|
||||
**Zastosowanie:**
|
||||
- Efekty artystyczne
|
||||
- Podkreślenie struktury
|
||||
- Wizualizacja głębi
|
||||
|
||||
**Wynik:** Obraz wygląda jak wytłoczony w metalu
|
||||
|
||||
---
|
||||
|
||||
## Detekcja obiektów YOLO
|
||||
|
||||
### 15. YOLO_DETECT - Detekcja obiektów (szybka)
|
||||
**Model:** YOLOv8n (nano)
|
||||
|
||||
**Co robi:** Wykrywa i klasyfikuje 80 klas obiektów (ludzie, zwierzęta, pojazdy, przedmioty).
|
||||
|
||||
**Zastosowanie:**
|
||||
- Szybka detekcja obiektów w czasie rzeczywistym
|
||||
- Analiza zawartości obrazu
|
||||
- Liczenie obiektów
|
||||
|
||||
**Wynik:**
|
||||
- Kolorowe prostokąty wokół obiektów
|
||||
- Etykiety z nazwą klasy i pewnością (np. "person: 0.95")
|
||||
- Lista wykrytych obiektów w konsoli
|
||||
|
||||
**Czas:** ~50-100ms
|
||||
|
||||
**Wykrywane klasy:** person, car, dog, cat, bicycle, motorcycle, airplane, bus, train, truck, boat, chair, table, laptop, phone, book, bottle, cup, fork, knife, spoon, bowl, banana, apple, sandwich, orange, pizza, donut, cake i wiele innych (80 klas COCO)
|
||||
|
||||
---
|
||||
|
||||
### 16. YOLO_DETECT_MEDIUM - Detekcja obiektów (średnia)
|
||||
**Model:** YOLOv8s (small)
|
||||
|
||||
**Co robi:** Dokładniejsza detekcja obiektów niż wersja szybka.
|
||||
|
||||
**Zastosowanie:**
|
||||
- Balans między szybkością a dokładnością
|
||||
- Detekcja mniejszych obiektów
|
||||
- Lepsza klasyfikacja
|
||||
|
||||
**Czas:** ~100-200ms
|
||||
|
||||
**Zaleta:** Wykrywa więcej obiektów i z większą pewnością
|
||||
|
||||
---
|
||||
|
||||
### 17. YOLO_DETECT_LARGE - Detekcja obiektów (dokładna)
|
||||
**Model:** YOLOv8m (medium)
|
||||
|
||||
**Co robi:** Najdokładniejsza detekcja obiektów.
|
||||
|
||||
**Zastosowanie:**
|
||||
- Profesjonalna analiza obrazu
|
||||
- Wykrywanie małych i trudnych obiektów
|
||||
- Maksymalna dokładność
|
||||
|
||||
**Czas:** ~200-400ms
|
||||
|
||||
**Zaleta:** Najwyższa dokładność i najmniej fałszywych detekcji
|
||||
|
||||
---
|
||||
|
||||
### 18. YOLO_SEGMENT - Segmentacja obiektów
|
||||
**Model:** YOLOv8n-seg
|
||||
|
||||
**Co robi:** Wykrywa obiekty i tworzy precyzyjne maski segmentacji.
|
||||
|
||||
**Zastosowanie:**
|
||||
- Precyzyjna segmentacja obiektów
|
||||
- Wydzielanie tła
|
||||
- Analiza kształtów
|
||||
|
||||
**Wynik:**
|
||||
- Kolorowe, półprzezroczyste maski na obiektach
|
||||
- Kontury obiektów
|
||||
- Etykiety z nazwą i pewnością
|
||||
|
||||
**Czas:** ~100-200ms
|
||||
|
||||
**Zaleta:** Dokładne wyznaczenie granic obiektów (nie tylko prostokąty)
|
||||
|
||||
---
|
||||
|
||||
## Skróty klawiszowe
|
||||
|
||||
### W konsoli:
|
||||
- **0** - Wyjście z programu
|
||||
- **1-18** - Wybór transformacji
|
||||
- **C** - Zmiana obrazu
|
||||
- **ENTER** - Potwierdzenie/powrót do menu
|
||||
- **Ctrl+C** - Awaryjne przerwanie programu
|
||||
|
||||
### W oknie obrazu:
|
||||
- **Dowolny klawisz** - Zamknięcie okna i powrót do menu
|
||||
- **ESC** - Zamknięcie okna
|
||||
|
||||
---
|
||||
|
||||
## Rozwiązywanie problemów
|
||||
|
||||
### Problem: "YOLO nie jest dostępne"
|
||||
**Rozwiązanie:**
|
||||
```bash
|
||||
pip install ultralytics
|
||||
```
|
||||
|
||||
### Problem: Okno obrazu nie pojawia się
|
||||
**Rozwiązanie:**
|
||||
1. Sprawdź czy obraz został poprawnie wczytany
|
||||
2. Upewnij się, że ścieżka do obrazu jest prawidłowa
|
||||
3. Spróbuj innego obrazu
|
||||
|
||||
### Problem: Detekcja twarzy nie działa
|
||||
**Rozwiązanie:**
|
||||
- Upewnij się, że twarze są widoczne z przodu
|
||||
- Użyj obrazu o dobrej jakości
|
||||
- Twarze powinny być wyraźne i dobrze oświetlone
|
||||
|
||||
### Problem: YOLO nie wykrywa obiektów
|
||||
**Rozwiązanie:**
|
||||
1. Spróbuj użyć YOLO_DETECT_LARGE (opcja 17) dla lepszej dokładności
|
||||
2. Upewnij się, że obiekty należą do 80 klas COCO
|
||||
3. Sprawdź jakość i rozdzielczość obrazu
|
||||
|
||||
### Problem: Program działa wolno
|
||||
**Rozwiązanie:**
|
||||
1. Użyj YOLO_DETECT (opcja 15) zamiast LARGE
|
||||
2. Zmniejsz rozmiar obrazu
|
||||
3. Użyj prostszych transformacji (1-14)
|
||||
|
||||
### Problem: Błąd przy pobieraniu obrazu z URL
|
||||
**Rozwiązanie:**
|
||||
1. Sprawdź połączenie internetowe
|
||||
2. Upewnij się, że URL prowadzi bezpośrednio do pliku obrazu
|
||||
3. Spróbuj innego URL
|
||||
|
||||
---
|
||||
|
||||
## Przykładowe scenariusze użycia
|
||||
|
||||
### Scenariusz 1: Analiza zdjęcia z wakacji
|
||||
1. Wybierz opcję **1** (plik z dysku)
|
||||
2. Wybierz zdjęcie z wakacji
|
||||
3. Użyj **YOLO_DETECT** (opcja 15) aby zobaczyć co jest na zdjęciu
|
||||
4. Użyj **FACE_DETECTION** (opcja 12) aby wykryć twarze
|
||||
|
||||
### Scenariusz 2: Poprawa jakości starego zdjęcia
|
||||
1. Wczytaj stare, rozmyte zdjęcie
|
||||
2. Użyj **SHARPEN** (opcja 13) aby wyostrzyć
|
||||
3. Porównaj z oryginałem
|
||||
|
||||
### Scenariusz 3: Analiza obrazu z internetu
|
||||
1. Wybierz opcję **2** (URL)
|
||||
2. Wklej link do obrazu (np. z Unsplash)
|
||||
3. Użyj **YOLO_SEGMENT** (opcja 18) aby zobaczyć segmentację
|
||||
|
||||
### Scenariusz 4: Detekcja krawędzi
|
||||
1. Wczytaj dowolny obraz
|
||||
2. Użyj **CANNY** (opcja 5) dla podstawowej detekcji
|
||||
3. Porównaj z **EDGE_DETECTION** (opcja 6)
|
||||
4. Porównaj z **SOBEL** (opcja 9)
|
||||
|
||||
---
|
||||
|
||||
## Wskazówki
|
||||
|
||||
✅ **Najlepsze praktyki:**
|
||||
- Używaj obrazów o dobrej jakości (min. 640x480)
|
||||
- Dla detekcji YOLO używaj obrazów z wyraźnymi obiektami
|
||||
- Eksperymentuj z różnymi transformacjami na tym samym obrazie
|
||||
- Zapisuj ciekawe wyniki (zrzut ekranu)
|
||||
|
||||
⚠️ **Uwagi:**
|
||||
- Pierwsze uruchomienie YOLO pobierze modele (~6-50 MB)
|
||||
- YOLO działa najlepiej na obrazach z dobrym oświetleniem
|
||||
- Niektóre transformacje wymagają obrazu w skali szarości (automatyczna konwersja)
|
||||
|
||||
📝 **Zalecane formaty obrazów:**
|
||||
- JPG/JPEG - najczęstszy, dobra kompresja
|
||||
- PNG - bez strat, przezroczystość
|
||||
- BMP - bez kompresji, duże pliki
|
||||
|
||||
---
|
||||
|
||||
## Kontakt i wsparcie
|
||||
|
||||
W razie problemów sprawdź:
|
||||
- `README_YOLO.md` - szczegółowe informacje o YOLO
|
||||
- `requirements.txt` - lista wymaganych bibliotek
|
||||
|
||||
---
|
||||
|
||||
**Wersja:** 1.0
|
||||
**Data:** 2025-11-04
|
||||
**Autor:** Program transformacji i detekcji obrazów
|
||||
BIN
dzien_05/przyklady/yolo_test/INSTRUKCJA_OBSLUGI.pdf
Normal file
BIN
dzien_05/przyklady/yolo_test/INSTRUKCJA_OBSLUGI.pdf
Normal file
Binary file not shown.
137
dzien_05/przyklady/yolo_test/README_YOLO.md
Normal file
137
dzien_05/przyklady/yolo_test/README_YOLO.md
Normal file
@@ -0,0 +1,137 @@
|
||||
https://www.ultralytics.com/
|
||||
|
||||
# Instrukcja instalacji YOLO dla projektu transformacji obrazów
|
||||
|
||||
## Wymagania
|
||||
|
||||
Aby używać funkcji detekcji i segmentacji obiektów YOLO, musisz zainstalować bibliotekę `ultralytics`.
|
||||
|
||||
## Instalacja
|
||||
|
||||
### Krok 1: Zainstaluj bibliotekę ultralytics
|
||||
|
||||
```bash
|
||||
pip install ultralytics
|
||||
```
|
||||
|
||||
### Krok 2: Zainstaluj dodatkowe zależności (opcjonalnie)
|
||||
|
||||
Jeśli chcesz używać GPU (NVIDIA CUDA):
|
||||
|
||||
```bash
|
||||
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
|
||||
```
|
||||
|
||||
Dla CPU (wystarczy podstawowa instalacja):
|
||||
|
||||
```bash
|
||||
pip install torch torchvision torchaudio
|
||||
```
|
||||
|
||||
## Dostępne modele YOLO w programie
|
||||
|
||||
### 1. YOLO_DETECT (Opcja 15)
|
||||
- **Model**: YOLOv8n (nano - najszybszy)
|
||||
- **Zastosowanie**: Szybka detekcja obiektów
|
||||
- **Czas**: ~50-100ms na obraz
|
||||
- **Dokładność**: Dobra
|
||||
- **Klasy**: 80 klas obiektów (COCO dataset)
|
||||
|
||||
### 2. YOLO_DETECT_MEDIUM (Opcja 16)
|
||||
- **Model**: YOLOv8s (small - średni)
|
||||
- **Zastosowanie**: Balans między szybkością a dokładnością
|
||||
- **Czas**: ~100-200ms na obraz
|
||||
- **Dokładność**: Bardzo dobra
|
||||
|
||||
### 3. YOLO_DETECT_LARGE (Opcja 17)
|
||||
- **Model**: YOLOv8m (medium - duży)
|
||||
- **Zastosowanie**: Wysoka dokładność detekcji
|
||||
- **Czas**: ~200-400ms na obraz
|
||||
- **Dokładność**: Doskonała
|
||||
|
||||
### 4. YOLO_SEGMENT (Opcja 18)
|
||||
- **Model**: YOLOv8n-seg (segmentacja)
|
||||
- **Zastosowanie**: Segmentacja obiektów (dokładne kontury)
|
||||
- **Czas**: ~100-200ms na obraz
|
||||
- **Wizualizacja**: Kolorowe maski na obiektach
|
||||
|
||||
## Wykrywane klasy obiektów (COCO dataset)
|
||||
|
||||
YOLO wykrywa 80 klas obiektów, w tym:
|
||||
|
||||
**Osoby i zwierzęta:**
|
||||
- person, cat, dog, horse, sheep, cow, elephant, bear, zebra, giraffe
|
||||
|
||||
**Pojazdy:**
|
||||
- bicycle, car, motorcycle, airplane, bus, train, truck, boat
|
||||
|
||||
**Przedmioty codziennego użytku:**
|
||||
- bottle, wine glass, cup, fork, knife, spoon, bowl
|
||||
- chair, couch, bed, dining table, toilet
|
||||
- tv, laptop, mouse, remote, keyboard, cell phone
|
||||
|
||||
**Sport i rekreacja:**
|
||||
- frisbee, skis, snowboard, sports ball, kite, baseball bat
|
||||
- skateboard, surfboard, tennis racket
|
||||
|
||||
**Jedzenie:**
|
||||
- banana, apple, sandwich, orange, broccoli, carrot, hot dog, pizza, donut, cake
|
||||
|
||||
I wiele innych...
|
||||
|
||||
## Jak działa wizualizacja
|
||||
|
||||
### Detekcja obiektów (YOLO_DETECT*)
|
||||
- Prostokąty wokół wykrytych obiektów
|
||||
- Różne kolory dla różnych klas
|
||||
- Etykiety z nazwą klasy i pewnością detekcji (np. "person: 0.95")
|
||||
- Wyświetlenie listy wykrytych obiektów w konsoli
|
||||
|
||||
### Segmentacja obiektów (YOLO_SEGMENT)
|
||||
- Kolorowe maski nakładane na obiekty (40% przezroczystości)
|
||||
- Kontury obiektów
|
||||
- Etykiety z nazwą klasy i pewnością
|
||||
- Precyzyjne wyznaczenie granic obiektów
|
||||
|
||||
## Pierwsze uruchomienie
|
||||
|
||||
Przy pierwszym uruchomieniu każdej opcji YOLO:
|
||||
1. Model zostanie automatycznie pobrany z internetu (~6-50 MB w zależności od modelu)
|
||||
2. Model zostanie zapisany lokalnie w katalogu użytkownika
|
||||
3. Kolejne uruchomienia będą używały zapisanego modelu (szybsze)
|
||||
|
||||
## Przykład użycia
|
||||
|
||||
1. Uruchom program: `python test_transform.py`
|
||||
2. Wybierz źródło obrazu (plik, URL lub domyślny)
|
||||
3. Wybierz opcję 15-18 (YOLO)
|
||||
4. Poczekaj na przetworzenie (pierwsze uruchomienie może potrwać dłużej)
|
||||
5. Zobacz wyniki w oknie porównawczym i w konsoli
|
||||
|
||||
## Rozwiązywanie problemów
|
||||
|
||||
### Błąd: "YOLO nie jest dostępne"
|
||||
```bash
|
||||
pip install ultralytics
|
||||
```
|
||||
|
||||
### Błąd: "No module named 'torch'"
|
||||
```bash
|
||||
pip install torch torchvision
|
||||
```
|
||||
|
||||
### Wolne działanie
|
||||
- Użyj YOLO_DETECT (opcja 15) zamiast YOLO_DETECT_LARGE
|
||||
- Zmniejsz rozmiar obrazu przed przetwarzaniem
|
||||
- Rozważ użycie GPU (wymaga NVIDIA CUDA)
|
||||
|
||||
### Brak wykrytych obiektów
|
||||
- Upewnij się, że obraz zawiera obiekty z listy COCO
|
||||
- Spróbuj użyć modelu YOLO_DETECT_LARGE (opcja 17) dla lepszej dokładności
|
||||
- Sprawdź jakość i rozdzielczość obrazu
|
||||
|
||||
## Więcej informacji
|
||||
|
||||
- Dokumentacja Ultralytics: https://docs.ultralytics.com/
|
||||
- YOLOv8 GitHub: https://github.com/ultralytics/ultralytics
|
||||
- COCO Dataset: https://cocodataset.org/
|
||||
BIN
dzien_05/przyklady/yolo_test/README_YOLO.pdf
Normal file
BIN
dzien_05/przyklady/yolo_test/README_YOLO.pdf
Normal file
Binary file not shown.
0
dzien_05/przyklady/yolo_test/funkcje/__init__.py
Normal file
0
dzien_05/przyklady/yolo_test/funkcje/__init__.py
Normal file
470
dzien_05/przyklady/yolo_test/funkcje/obraz.py
Normal file
470
dzien_05/przyklady/yolo_test/funkcje/obraz.py
Normal file
@@ -0,0 +1,470 @@
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
import os
|
||||
try:
|
||||
from ultralytics import YOLO
|
||||
YOLO_AVAILABLE = True
|
||||
except ImportError:
|
||||
YOLO_AVAILABLE = False
|
||||
print("Uwaga: Biblioteka ultralytics (YOLO) nie jest zainstalowana.")
|
||||
print("Aby używać detekcji YOLO, zainstaluj: pip install ultralytics")
|
||||
|
||||
class Obraz:
|
||||
def __init__(self, filename: str, mode: int = cv.IMREAD_COLOR_BGR):
|
||||
self.filename = os.path.abspath(filename)
|
||||
self.mode = mode
|
||||
self.loaded = False
|
||||
self.img = None
|
||||
self.img_other = None
|
||||
self.transform_name = "NOTHING"
|
||||
|
||||
def load_image(self):
|
||||
if self.loaded:
|
||||
return True
|
||||
if not os.path.exists(self.filename):
|
||||
raise FileNotFoundError(f"Nie udało się wczytać pliku: {self.filename}")
|
||||
try:
|
||||
self.img = cv.imread(self.filename, flags=self.mode)
|
||||
self.loaded = True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
return self.img
|
||||
|
||||
def show_image(self, window_name = "Window"):
|
||||
if not self.loaded:
|
||||
raise ValueError("Obraz nie został wczytany")
|
||||
window_name += f"-{os.path.basename(self.filename)} ({self.filename})"
|
||||
cv.imshow(window_name, self.img)
|
||||
cv.waitKey(0)
|
||||
cv.destroyAllWindows()
|
||||
return None
|
||||
|
||||
def show_side_by_side(self, window_name="Original vs Transformed"):
|
||||
"""
|
||||
Wyświetla oryginalny i przetworzony obraz obok siebie w jednym oknie.
|
||||
|
||||
Args:
|
||||
window_name (str): Nazwa okna
|
||||
"""
|
||||
if not self.loaded:
|
||||
raise ValueError("Obraz nie został wczytany")
|
||||
if self.img_other is None:
|
||||
raise ValueError("Nie wykonano jeszcze żadnej transformacji")
|
||||
|
||||
try:
|
||||
# Przygotuj obrazy do wyświetlenia
|
||||
if len(self.img.shape) == 2: # Jeśli obraz jest w skali szarości
|
||||
img_display = cv.cvtColor(self.img, cv.COLOR_GRAY2BGR)
|
||||
else:
|
||||
img_display = self.img.copy()
|
||||
|
||||
if len(self.img_other.shape) == 2: # Jeśli obraz przetworzony jest w skali szarości
|
||||
img_other_display = cv.cvtColor(self.img_other, cv.COLOR_GRAY2BGR)
|
||||
else:
|
||||
img_other_display = self.img_other.copy()
|
||||
|
||||
# Upewnij się, że oba obrazy mają ten sam rozmiar
|
||||
if img_display.shape != img_other_display.shape:
|
||||
# Jeśli rozmiary są różne, przeskaluj drugi obraz do rozmiaru pierwszego
|
||||
img_other_display = cv.resize(img_other_display, (img_display.shape[1], img_display.shape[0]))
|
||||
|
||||
# Dodaj etykiety
|
||||
cv.putText(img_display, "Original", (10, 30), cv.FONT_HERSHEY_SIMPLEX,
|
||||
1, (0, 255, 0), 2, cv.LINE_AA)
|
||||
cv.putText(img_other_display, f"{self.transform_name}", (10, 30),
|
||||
cv.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv.LINE_AA)
|
||||
|
||||
# Połącz obrazy obok siebie
|
||||
combined = cv.hconcat([img_display, img_other_display])
|
||||
|
||||
# Domyślne rozmiary ekranu
|
||||
screen_width = 1920
|
||||
screen_height = 1080
|
||||
|
||||
# Dostosuj rozmiar obrazu do ekranu (80% rozmiaru ekranu)
|
||||
max_width = int(screen_width * 0.8)
|
||||
max_height = int(screen_height * 0.8)
|
||||
|
||||
h, w = combined.shape[:2]
|
||||
|
||||
# Oblicz skalę, jeśli obraz jest większy niż maksymalne wymiary
|
||||
if w > max_width or h > max_height:
|
||||
scale = min(max_width / w, max_height / h)
|
||||
new_width = int(w * scale)
|
||||
new_height = int(h * scale)
|
||||
combined = cv.resize(combined, (new_width, new_height))
|
||||
|
||||
# Wyświetl połączony obraz
|
||||
cv.namedWindow(window_name, cv.WINDOW_AUTOSIZE)
|
||||
cv.imshow(window_name, combined)
|
||||
|
||||
# Poczekaj chwilę, aby okno się wyrenderowało
|
||||
cv.waitKey(1)
|
||||
|
||||
# Poczekaj na naciśnięcie klawisza
|
||||
print(f"Wyświetlono obraz. Naciśnij dowolny klawisz w oknie obrazu, aby zamknąć...")
|
||||
cv.waitKey(0)
|
||||
cv.destroyAllWindows()
|
||||
|
||||
except Exception as e:
|
||||
print(f"Błąd podczas wyświetlania obrazów: {str(e)}")
|
||||
raise
|
||||
|
||||
return None
|
||||
|
||||
def transform(self, transform_name: str, show_side_by_side=True):
|
||||
"""
|
||||
Metoda transformuje obrazek na podstawie przekazanej nazwy transformacji.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
transform_name : str
|
||||
Nazwa transformacji, która ma być zastosowana do obrazka.
|
||||
show_side_by_side : bool
|
||||
Czy wyświetlić obrazy obok siebie po transformacji.
|
||||
|
||||
Returns
|
||||
-------
|
||||
numpy.ndarray
|
||||
Przetworzony obraz.
|
||||
|
||||
Raises
|
||||
-------
|
||||
ValueError
|
||||
Jeśli obrazek nie został wczytany lub transformacja nie jest obsługiwana.
|
||||
"""
|
||||
if not self.loaded:
|
||||
raise ValueError("Obraz nie został wczytany")
|
||||
|
||||
# Zresetuj poprzedni wynik transformacji
|
||||
self.img_other = None
|
||||
self.transform_name = transform_name
|
||||
|
||||
if transform_name == "NOTHING":
|
||||
self.img_other = self.img.copy()
|
||||
|
||||
elif transform_name == "GRAY":
|
||||
self.img_other = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY)
|
||||
|
||||
elif transform_name == "BLUR_GAUSSIAN":
|
||||
# Rozmycie Gaussa
|
||||
self.img_other = cv.GaussianBlur(self.img, (15, 15), 0)
|
||||
|
||||
elif transform_name == "BLUR_MEDIAN":
|
||||
# Rozmycie medianowe
|
||||
self.img_other = cv.medianBlur(self.img, 5)
|
||||
|
||||
elif transform_name == "BLUR_BILATERAL":
|
||||
# Rozmycie bilateralne (zachowuje krawędzie)
|
||||
self.img_other = cv.bilateralFilter(self.img, 9, 75, 75)
|
||||
|
||||
elif transform_name == "CANNY":
|
||||
# Detekcja krawędzi Canny
|
||||
gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY) if len(self.img.shape) == 3 else self.img
|
||||
self.img_other = cv.Canny(gray, 100, 200)
|
||||
|
||||
elif transform_name == "THRESHOLD":
|
||||
# Threshold wymaga obrazu w skali szarości
|
||||
gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY) if len(self.img.shape) == 3 else self.img
|
||||
self.img_other = cv.threshold(gray, 127, 255, cv.THRESH_BINARY)[1]
|
||||
|
||||
elif transform_name == "ADAPTIVE":
|
||||
# Adaptive threshold wymaga obrazu w skali szarości
|
||||
gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY) if len(self.img.shape) == 3 else self.img
|
||||
self.img_other = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 11, 2)
|
||||
|
||||
elif transform_name == "SOBEL":
|
||||
# Detekcja krawędzi Sobel
|
||||
gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY) if len(self.img.shape) == 3 else self.img
|
||||
sobelx = cv.Sobel(gray, cv.CV_64F, 1, 0, ksize=5)
|
||||
sobely = cv.Sobel(gray, cv.CV_64F, 0, 1, ksize=5)
|
||||
self.img_other = cv.magnitude(sobelx, sobely)
|
||||
self.img_other = np.uint8(self.img_other)
|
||||
|
||||
elif transform_name == "LAPLACIAN":
|
||||
# Detekcja krawędzi Laplacian
|
||||
gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY) if len(self.img.shape) == 3 else self.img
|
||||
self.img_other = cv.Laplacian(gray, cv.CV_64F)
|
||||
self.img_other = np.uint8(np.absolute(self.img_other))
|
||||
|
||||
elif transform_name == "FACE_DETECTION":
|
||||
# Detekcja twarzy używając Haar Cascade
|
||||
self.img_other = self.img.copy()
|
||||
gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY)
|
||||
|
||||
# Ścieżka do klasyfikatora Haar Cascade
|
||||
cascade_path = cv.data.haarcascades + 'haarcascade_frontalface_default.xml'
|
||||
face_cascade = cv.CascadeClassifier(cascade_path)
|
||||
|
||||
# Wykryj twarze
|
||||
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
|
||||
|
||||
# Narysuj prostokąty wokół wykrytych twarzy
|
||||
for (x, y, w, h) in faces:
|
||||
cv.rectangle(self.img_other, (x, y), (x+w, y+h), (0, 255, 0), 2)
|
||||
cv.putText(self.img_other, "Face", (x, y-10), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
|
||||
|
||||
elif transform_name == "EDGE_DETECTION":
|
||||
# Zaawansowana detekcja krawędzi
|
||||
gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY)
|
||||
blurred = cv.GaussianBlur(gray, (5, 5), 0)
|
||||
self.img_other = cv.Canny(blurred, 50, 150)
|
||||
|
||||
elif transform_name == "CONTOURS":
|
||||
# Detekcja konturów
|
||||
self.img_other = self.img.copy()
|
||||
gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY)
|
||||
blurred = cv.GaussianBlur(gray, (5, 5), 0)
|
||||
edges = cv.Canny(blurred, 50, 150)
|
||||
contours, _ = cv.findContours(edges, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
|
||||
cv.drawContours(self.img_other, contours, -1, (0, 255, 0), 2)
|
||||
|
||||
elif transform_name == "SHARPEN":
|
||||
# Wyostrzenie obrazu
|
||||
kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
|
||||
self.img_other = cv.filter2D(self.img, -1, kernel)
|
||||
|
||||
elif transform_name == "EMBOSS":
|
||||
# Efekt emboss (wytłoczenie)
|
||||
kernel = np.array([[-2,-1,0], [-1,1,1], [0,1,2]])
|
||||
self.img_other = cv.filter2D(self.img, -1, kernel)
|
||||
|
||||
elif transform_name == "YOLO_DETECT":
|
||||
# Detekcja obiektów używając YOLO
|
||||
if not YOLO_AVAILABLE:
|
||||
raise ValueError("YOLO nie jest dostępne. Zainstaluj: pip install ultralytics")
|
||||
|
||||
self.img_other = self._yolo_detection(model_size='n')
|
||||
|
||||
elif transform_name == "YOLO_DETECT_MEDIUM":
|
||||
# Detekcja obiektów używając YOLO (model średni - dokładniejszy)
|
||||
if not YOLO_AVAILABLE:
|
||||
raise ValueError("YOLO nie jest dostępne. Zainstaluj: pip install ultralytics")
|
||||
|
||||
self.img_other = self._yolo_detection(model_size='s')
|
||||
|
||||
elif transform_name == "YOLO_DETECT_LARGE":
|
||||
# Detekcja obiektów używając YOLO (model duży - najdokładniejszy)
|
||||
if not YOLO_AVAILABLE:
|
||||
raise ValueError("YOLO nie jest dostępne. Zainstaluj: pip install ultralytics")
|
||||
|
||||
self.img_other = self._yolo_detection(model_size='m')
|
||||
|
||||
elif transform_name == "YOLO_SEGMENT":
|
||||
# Segmentacja obiektów używając YOLO
|
||||
if not YOLO_AVAILABLE:
|
||||
raise ValueError("YOLO nie jest dostępne. Zainstaluj: pip install ultralytics")
|
||||
|
||||
self.img_other = self._yolo_segmentation()
|
||||
|
||||
else:
|
||||
raise ValueError(f"Brak obsługiwanej metody transformacji: {transform_name}")
|
||||
|
||||
# Po wykonaniu transformacji wyświetl obrazy obok siebie, jeśli wymagane
|
||||
if show_side_by_side and self.img_other is not None:
|
||||
self.show_side_by_side()
|
||||
|
||||
return self.img_other
|
||||
|
||||
def _yolo_detection(self, model_size='n', conf_threshold=0.25):
|
||||
"""
|
||||
Wykonuje detekcję obiektów używając YOLO.
|
||||
|
||||
Args:
|
||||
model_size (str): Rozmiar modelu ('n', 's', 'm', 'l', 'x')
|
||||
conf_threshold (float): Próg pewności detekcji (0.0-1.0)
|
||||
|
||||
Returns:
|
||||
numpy.ndarray: Obraz z naniesionymi detekcjami
|
||||
"""
|
||||
print(f"\nŁadowanie modelu YOLO (yolov8{model_size})...")
|
||||
|
||||
# Załaduj model YOLO
|
||||
model = YOLO(f'yolov8{model_size}.pt')
|
||||
|
||||
print("Wykonywanie detekcji obiektów...")
|
||||
|
||||
# Wykonaj detekcję
|
||||
results = model(self.img, conf=conf_threshold, verbose=False)
|
||||
|
||||
# Skopiuj obraz
|
||||
img_result = self.img.copy()
|
||||
|
||||
# Pobierz wyniki
|
||||
if len(results) > 0:
|
||||
result = results[0]
|
||||
boxes = result.boxes
|
||||
|
||||
detected_objects = []
|
||||
|
||||
# Rysuj prostokąty i etykiety dla każdego wykrytego obiektu
|
||||
for box in boxes:
|
||||
# Pobierz współrzędne
|
||||
x1, y1, x2, y2 = map(int, box.xyxy[0])
|
||||
|
||||
# Pobierz klasę i pewność
|
||||
conf = float(box.conf[0])
|
||||
cls = int(box.cls[0])
|
||||
class_name = model.names[cls]
|
||||
|
||||
detected_objects.append((class_name, conf))
|
||||
|
||||
# Wybierz kolor dla prostokąta (różne kolory dla różnych klas)
|
||||
color = self._get_color_for_class(cls)
|
||||
|
||||
# Narysuj prostokąt
|
||||
cv.rectangle(img_result, (x1, y1), (x2, y2), color, 2)
|
||||
|
||||
# Przygotuj etykietę
|
||||
label = f"{class_name}: {conf:.2f}"
|
||||
|
||||
# Oblicz rozmiar tekstu
|
||||
(text_width, text_height), baseline = cv.getTextSize(
|
||||
label, cv.FONT_HERSHEY_SIMPLEX, 0.6, 2
|
||||
)
|
||||
|
||||
# Narysuj tło dla tekstu
|
||||
cv.rectangle(
|
||||
img_result,
|
||||
(x1, y1 - text_height - baseline - 5),
|
||||
(x1 + text_width, y1),
|
||||
color,
|
||||
-1
|
||||
)
|
||||
|
||||
# Narysuj tekst
|
||||
cv.putText(
|
||||
img_result,
|
||||
label,
|
||||
(x1, y1 - baseline - 5),
|
||||
cv.FONT_HERSHEY_SIMPLEX,
|
||||
0.6,
|
||||
(255, 255, 255),
|
||||
2
|
||||
)
|
||||
|
||||
# Wyświetl podsumowanie w konsoli
|
||||
print(f"\n✓ Wykryto {len(detected_objects)} obiektów:")
|
||||
for obj_name, obj_conf in detected_objects:
|
||||
print(f" - {obj_name}: {obj_conf:.2%}")
|
||||
else:
|
||||
print("\n✗ Nie wykryto żadnych obiektów.")
|
||||
|
||||
return img_result
|
||||
|
||||
def _yolo_segmentation(self, model_size='n', conf_threshold=0.25):
|
||||
"""
|
||||
Wykonuje segmentację obiektów używając YOLO.
|
||||
|
||||
Args:
|
||||
model_size (str): Rozmiar modelu ('n', 's', 'm', 'l', 'x')
|
||||
conf_threshold (float): Próg pewności detekcji (0.0-1.0)
|
||||
|
||||
Returns:
|
||||
numpy.ndarray: Obraz z naniesioną segmentacją
|
||||
"""
|
||||
print(f"\nŁadowanie modelu YOLO Segmentation (yolov8{model_size}-seg)...")
|
||||
|
||||
# Załaduj model segmentacji
|
||||
model = YOLO(f'yolov8{model_size}-seg.pt')
|
||||
|
||||
print("Wykonywanie segmentacji obiektów...")
|
||||
|
||||
# Wykonaj segmentację
|
||||
results = model(self.img, conf=conf_threshold, verbose=False)
|
||||
|
||||
# Skopiuj obraz
|
||||
img_result = self.img.copy()
|
||||
|
||||
# Pobierz wyniki
|
||||
if len(results) > 0:
|
||||
result = results[0]
|
||||
|
||||
if result.masks is not None:
|
||||
masks = result.masks.data.cpu().numpy()
|
||||
boxes = result.boxes
|
||||
|
||||
detected_objects = []
|
||||
|
||||
# Dla każdej maski
|
||||
for i, (mask, box) in enumerate(zip(masks, boxes)):
|
||||
# Pobierz klasę i pewność
|
||||
conf = float(box.conf[0])
|
||||
cls = int(box.cls[0])
|
||||
class_name = model.names[cls]
|
||||
|
||||
detected_objects.append((class_name, conf))
|
||||
|
||||
# Wybierz kolor dla maski
|
||||
color = self._get_color_for_class(cls)
|
||||
|
||||
# Przeskaluj maskę do rozmiaru obrazu
|
||||
mask_resized = cv.resize(mask, (img_result.shape[1], img_result.shape[0]))
|
||||
mask_bool = mask_resized > 0.5
|
||||
|
||||
# Nałóż kolorową maskę na obraz
|
||||
colored_mask = np.zeros_like(img_result)
|
||||
colored_mask[mask_bool] = color
|
||||
|
||||
# Zmieszaj z oryginalnym obrazem (przezroczystość 40%)
|
||||
img_result = cv.addWeighted(img_result, 1.0, colored_mask, 0.4, 0)
|
||||
|
||||
# Narysuj kontur
|
||||
contours, _ = cv.findContours(
|
||||
mask_bool.astype(np.uint8),
|
||||
cv.RETR_EXTERNAL,
|
||||
cv.CHAIN_APPROX_SIMPLE
|
||||
)
|
||||
cv.drawContours(img_result, contours, -1, color, 2)
|
||||
|
||||
# Dodaj etykietę
|
||||
x1, y1, x2, y2 = map(int, box.xyxy[0])
|
||||
label = f"{class_name}: {conf:.2f}"
|
||||
cv.putText(
|
||||
img_result,
|
||||
label,
|
||||
(x1, y1 - 10),
|
||||
cv.FONT_HERSHEY_SIMPLEX,
|
||||
0.6,
|
||||
color,
|
||||
2
|
||||
)
|
||||
|
||||
# Wyświetl podsumowanie w konsoli
|
||||
print(f"\n✓ Zsegmentowano {len(detected_objects)} obiektów:")
|
||||
for obj_name, obj_conf in detected_objects:
|
||||
print(f" - {obj_name}: {obj_conf:.2%}")
|
||||
else:
|
||||
print("\n✗ Nie wykryto żadnych obiektów do segmentacji.")
|
||||
else:
|
||||
print("\n✗ Nie wykryto żadnych obiektów.")
|
||||
|
||||
return img_result
|
||||
|
||||
def _get_color_for_class(self, class_id):
|
||||
"""
|
||||
Generuje unikalny kolor dla danej klasy obiektów.
|
||||
|
||||
Args:
|
||||
class_id (int): ID klasy
|
||||
|
||||
Returns:
|
||||
tuple: Kolor w formacie BGR
|
||||
"""
|
||||
# Predefiniowane kolory dla lepszej wizualizacji
|
||||
colors = [
|
||||
(255, 0, 0), # Niebieski
|
||||
(0, 255, 0), # Zielony
|
||||
(0, 0, 255), # Czerwony
|
||||
(255, 255, 0), # Cyjan
|
||||
(255, 0, 255), # Magenta
|
||||
(0, 255, 255), # Żółty
|
||||
(128, 0, 128), # Fioletowy
|
||||
(255, 128, 0), # Pomarańczowy
|
||||
(0, 128, 255), # Jasnoniebieski
|
||||
(128, 255, 0), # Limonkowy
|
||||
]
|
||||
|
||||
return colors[class_id % len(colors)]
|
||||
|
||||
5
dzien_05/przyklady/yolo_test/requirements.txt
Normal file
5
dzien_05/przyklady/yolo_test/requirements.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
opencv-python>=4.8.0
|
||||
numpy>=1.24.0
|
||||
ultralytics>=8.0.0
|
||||
torch>=2.0.0
|
||||
torchvision>=0.15.0
|
||||
7
dzien_05/przyklady/yolo_test/test_klasy_01.py
Normal file
7
dzien_05/przyklady/yolo_test/test_klasy_01.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from funkcje.obraz import Obraz
|
||||
|
||||
obraz = Obraz("../dzien_01/plane.jpg")
|
||||
obraz.load_image()
|
||||
obraz.show_image("Obraz")
|
||||
|
||||
|
||||
245
dzien_05/przyklady/yolo_test/test_transform.py
Normal file
245
dzien_05/przyklady/yolo_test/test_transform.py
Normal file
@@ -0,0 +1,245 @@
|
||||
from funkcje.obraz import Obraz
|
||||
import os
|
||||
import sys
|
||||
import cv2
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
from tkinter import Tk, filedialog
|
||||
import urllib.request
|
||||
import tempfile
|
||||
|
||||
def test_transform(image_path, transform_name):
|
||||
"""
|
||||
Testuje wybraną transformację na podanym obrazie.
|
||||
|
||||
Args:
|
||||
image_path (str): Ścieżka do obrazu
|
||||
transform_name (str): Nazwa transformacji do przetestowania
|
||||
"""
|
||||
try:
|
||||
# Wczytanie obrazu
|
||||
img = Obraz(image_path)
|
||||
img.load_image()
|
||||
|
||||
print(f"\n--- Testowanie transformacji: {transform_name} ---")
|
||||
|
||||
# Wykonanie transformacji
|
||||
result = img.transform(transform_name, show_side_by_side=True)
|
||||
|
||||
# Zamknięcie wszystkich okien przed zakończeniem
|
||||
cv2.destroyAllWindows()
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"Błąd podczas wykonywania transformacji {transform_name}: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
cv2.destroyAllWindows()
|
||||
return False
|
||||
|
||||
def select_image_from_disk():
|
||||
"""Otwiera okno dialogowe do wyboru pliku obrazu z dysku."""
|
||||
print("\nOtwieranie okna dialogowego wyboru pliku...")
|
||||
|
||||
# Ukryj główne okno Tkinter
|
||||
root = Tk()
|
||||
root.withdraw()
|
||||
root.attributes('-topmost', True)
|
||||
|
||||
# Otwórz dialog wyboru pliku
|
||||
file_path = filedialog.askopenfilename(
|
||||
title="Wybierz plik obrazu",
|
||||
filetypes=[
|
||||
("Pliki obrazów", "*.jpg *.jpeg *.png *.bmp *.gif *.tiff"),
|
||||
("JPEG", "*.jpg *.jpeg"),
|
||||
("PNG", "*.png"),
|
||||
("BMP", "*.bmp"),
|
||||
("Wszystkie pliki", "*.*")
|
||||
]
|
||||
)
|
||||
|
||||
root.destroy()
|
||||
|
||||
if file_path:
|
||||
print(f"✓ Wybrano plik: {file_path}")
|
||||
return file_path
|
||||
else:
|
||||
print("✗ Nie wybrano pliku.")
|
||||
return None
|
||||
|
||||
def download_image_from_url(url):
|
||||
"""Pobiera obraz z URL i zapisuje go w pliku tymczasowym."""
|
||||
try:
|
||||
print(f"\nPobieranie obrazu z URL: {url}")
|
||||
|
||||
# Pobierz obraz
|
||||
with urllib.request.urlopen(url, timeout=10) as response:
|
||||
image_data = response.read()
|
||||
|
||||
# Zapisz do pliku tymczasowego
|
||||
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.jpg')
|
||||
temp_file.write(image_data)
|
||||
temp_file.close()
|
||||
|
||||
print(f"✓ Obraz pobrany i zapisany jako: {temp_file.name}")
|
||||
return temp_file.name
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ Błąd podczas pobierania obrazu: {str(e)}")
|
||||
return None
|
||||
|
||||
def select_image_source():
|
||||
"""Pozwala użytkownikowi wybrać źródło obrazu."""
|
||||
print("\n" + "="*60)
|
||||
print("WYBÓR ŹRÓDŁA OBRAZU")
|
||||
print("="*60)
|
||||
print("1. Wybierz plik z dysku (okno dialogowe)")
|
||||
print("2. Podaj URL do obrazu w internecie")
|
||||
print("3. Użyj domyślnego obrazu z katalogu dzien_01")
|
||||
print("0. Anuluj")
|
||||
print("="*60)
|
||||
|
||||
while True:
|
||||
choice = input("\nWybierz opcję (0-3): ").strip()
|
||||
|
||||
if choice == '0':
|
||||
return None
|
||||
elif choice == '1':
|
||||
return select_image_from_disk()
|
||||
elif choice == '2':
|
||||
url = input("\nPodaj URL obrazu: ").strip()
|
||||
if url:
|
||||
return download_image_from_url(url)
|
||||
else:
|
||||
print("✗ Nie podano URL.")
|
||||
return None
|
||||
elif choice == '3':
|
||||
# Użyj domyślnego obrazu
|
||||
base_dir = Path(__file__).parent.parent
|
||||
images_dir = base_dir / 'dzien_01'
|
||||
image_extensions = ('.jpg', '.jpeg', '.png', '.bmp')
|
||||
available_images = [f for f in os.listdir(images_dir)
|
||||
if f.lower().endswith(image_extensions)]
|
||||
|
||||
if available_images:
|
||||
default_path = str(images_dir / available_images[0])
|
||||
print(f"✓ Używam domyślnego obrazu: {default_path}")
|
||||
return default_path
|
||||
else:
|
||||
print("✗ Nie znaleziono obrazów w katalogu dzien_01")
|
||||
return None
|
||||
else:
|
||||
print("✗ Nieprawidłowy wybór. Wybierz 0-3.")
|
||||
|
||||
def print_menu(transformations):
|
||||
"""Wyświetla menu z dostępnymi transformacjami."""
|
||||
print("\n" + "="*60)
|
||||
print("DOSTĘPNE TRANSFORMACJE OBRAZU")
|
||||
print("="*60)
|
||||
for i, transform in enumerate(transformations, 1):
|
||||
print(f"{i:2d}. {transform}")
|
||||
print("-"*60)
|
||||
print(" C. Zmień obraz (wybierz inny plik)")
|
||||
print(" 0. Wyjście z programu")
|
||||
print("="*60)
|
||||
|
||||
def main():
|
||||
print(f"\n{'='*60}")
|
||||
print(f"PROGRAM TESTOWANIA TRANSFORMACJI OBRAZÓW")
|
||||
print(f"{'='*60}")
|
||||
|
||||
# Wybór początkowego obrazu
|
||||
image_path = select_image_source()
|
||||
|
||||
if not image_path:
|
||||
print("\n✗ Nie wybrano obrazu. Program zakończony.")
|
||||
return
|
||||
|
||||
print(f"\nObecnie używany obraz:")
|
||||
print(f" Nazwa: {os.path.basename(image_path)}")
|
||||
print(f" Ścieżka: {image_path}")
|
||||
|
||||
# Lista dostępnych transformacji do przetestowania
|
||||
transformations = [
|
||||
"GRAY", # Skala szarości
|
||||
"BLUR_GAUSSIAN", # Rozmycie Gaussa
|
||||
"BLUR_MEDIAN", # Rozmycie medianowe
|
||||
"BLUR_BILATERAL", # Rozmycie bilateralne
|
||||
"CANNY", # Detekcja krawędzi Canny
|
||||
"EDGE_DETECTION", # Zaawansowana detekcja krawędzi
|
||||
"THRESHOLD", # Progowanie binarne
|
||||
"ADAPTIVE", # Progowanie adaptacyjne
|
||||
"SOBEL", # Detekcja krawędzi Sobel
|
||||
"LAPLACIAN", # Detekcja krawędzi Laplacian
|
||||
"CONTOURS", # Detekcja konturów
|
||||
"FACE_DETECTION", # Detekcja twarzy
|
||||
"SHARPEN", # Wyostrzenie
|
||||
"EMBOSS", # Efekt wytłoczenia
|
||||
"YOLO_DETECT", # YOLO - Detekcja obiektów (szybki)
|
||||
"YOLO_DETECT_MEDIUM", # YOLO - Detekcja obiektów (średni)
|
||||
"YOLO_DETECT_LARGE", # YOLO - Detekcja obiektów (dokładny)
|
||||
"YOLO_SEGMENT" # YOLO - Segmentacja obiektów
|
||||
]
|
||||
|
||||
# Pętla główna programu
|
||||
while True:
|
||||
print_menu(transformations)
|
||||
|
||||
try:
|
||||
choice = input(f"\nWybierz opcję (0-{len(transformations)}, C aby zmienić obraz): ").strip().upper()
|
||||
|
||||
# Sprawdź czy użytkownik chce zakończyć
|
||||
if choice == '0':
|
||||
print("\nZakończono program. Do widzenia!")
|
||||
break
|
||||
|
||||
# Sprawdź czy użytkownik chce zmienić obraz
|
||||
elif choice == 'C':
|
||||
new_image_path = select_image_source()
|
||||
if new_image_path:
|
||||
image_path = new_image_path
|
||||
print(f"\n✓ Zmieniono obraz na:")
|
||||
print(f" Nazwa: {os.path.basename(image_path)}")
|
||||
print(f" Ścieżka: {image_path}")
|
||||
else:
|
||||
print("\n✗ Nie wybrano nowego obrazu. Pozostawiono poprzedni.")
|
||||
input("\nNaciśnij ENTER, aby kontynuować...")
|
||||
continue
|
||||
|
||||
# Konwersja na liczbę
|
||||
try:
|
||||
choice_idx = int(choice) - 1
|
||||
except ValueError:
|
||||
print("\n✗ Proszę wprowadzić poprawną liczbę lub 'C'.")
|
||||
continue
|
||||
|
||||
# Sprawdź poprawność wyboru
|
||||
if 0 <= choice_idx < len(transformations):
|
||||
transform_name = transformations[choice_idx]
|
||||
print(f"\n{'='*60}")
|
||||
print(f"Wybrano transformację: {transform_name}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
# Wykonaj transformację
|
||||
success = test_transform(image_path, transform_name)
|
||||
|
||||
if success:
|
||||
print(f"\n✓ Transformacja '{transform_name}' zakończona pomyślnie.")
|
||||
else:
|
||||
print(f"\n✗ Transformacja '{transform_name}' zakończona z błędem.")
|
||||
|
||||
# Poczekaj na potwierdzenie przed powrotem do menu
|
||||
input("\nNaciśnij ENTER, aby wrócić do menu...")
|
||||
else:
|
||||
print(f"\n✗ Nieprawidłowy wybór. Wybierz numer od 0 do {len(transformations)}.")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\nPrzerwano przez użytkownika. Do widzenia!")
|
||||
break
|
||||
except Exception as e:
|
||||
print(f"\n✗ Wystąpił nieoczekiwany błąd: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user