This commit is contained in:
2025-12-18 10:40:08 +01:00
parent f2754cba35
commit 321a7e5b39
21 changed files with 1569 additions and 0 deletions

View 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

Binary file not shown.

View 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/

Binary file not shown.

View 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)]

View 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

View File

@@ -0,0 +1,7 @@
from funkcje.obraz import Obraz
obraz = Obraz("../dzien_01/plane.jpg")
obraz.load_image()
obraz.show_image("Obraz")

View 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()