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

1
.gitignore vendored
View File

@@ -11,6 +11,7 @@ __pycache__/
.Python .Python
build/ build/
virtual/ virtual/
wirtualka/
develop-eggs/ develop-eggs/
dist/ dist/
downloads/ downloads/

60
dane_aj.csv Normal file
View File

@@ -0,0 +1,60 @@
"pan Tymoteusz Fornalik","3579454591527662","PPUH Opioła-Franków i syn s.c.","plac Jaśminowa 42/38 ~ 82-249 Zambrów"
"Anastazja Kobza","4597865459252406","Oleksak-Nicewicz Sp.j.","pl. Rzeczna 028 ~ 78-208 Piotrków Trybunalski"
"pan Igor Madzia","213174349909859","Fundacja Kulis Sp. z o.o.","pl. Lelewela 03/08 ~ 93-852 Mielec"
"Miłosz Lenarcik","213113678367743","Dybaś Sp.k.","al. Szewska 90/80 ~ 78-042 Oświęcim"
"Cyprian Troć","213179982678067","Ruszczak-Ruszczak S.A.","aleja Źródlana 13 ~ 95-829 Sochaczew"
"pan Mariusz Rycerz","180061535819365","Cyrulik-Kuświk S.A.","plac Glówna 55 ~ 18-830 Ostrów Wielkopolski"
"Eliza Wikło","213142435307718","Fundacja Flaga","ulica Kochanowskiego 36 ~ 95-595 Sopot"
"Radosław Burza","6011363834691624","Fundacja Hrabia Sp. z o.o. Sp.k.","al. Targowa 08/52 ~ 21-002 Wągrowiec"
"Natan Janowiak","3593567621055321","Żuchowicz i syn s.c.","plac Ogrodowa 61/02 ~ 23-192 Malbork"
"Maksymilian Kieca","377417377811550","PPUH Bilewicz","plac Kopernika 36/61 ~ 48-407 Legionowo"
"pani Dorota Wieczerzak","6596262282704702","PPUH Plona-Lenc Sp.k.","ul. Wieniawskiego 773 ~ 45-722 Nowa Ruda"
"Dagmara Haponiuk","30572635788401","Czajor-Kozłowicz i syn s.c.","plac Czereśniowa 42/85 ~ 64-701 Ruda Śląska"
"Ksawery Michalkiewicz","2720067801981675","Gabinety Mikiciuk-Jędrzejek S.A.","pl. Porzeczkowa 656 ~ 78-965 Grudziądz"
"Dagmara Mikus","4926843824626","Sendor-Pianka s.c.","ulica Bociania 865 ~ 14-918 Pruszków"
"Lidia Czosnyka","4654299725117636938","Kuryłowicz-Brodawka Sp.k.","al. Kołłątaja 93/97 ~ 53-732 Brzeg"
"pan Bruno Startek","6011844466007999","Roch S.A.","ul. Partyzantów 721 ~ 47-570 Żory"
"Radosław Troć","676319474810","FPUH Łukasz Sp. z o.o. Sp.k.","ul. Porzeczkowa 56 ~ 28-009 Bielawa"
"Blanka Tadla","341704652423174","FPUH Cyman-Białach i syn s.c.","al. Nowa 526 ~ 21-033 Piła"
"Konrad Toma","3519664242836923","Gryga Sp. z o.o. Sp.k.","ul. Partyzantów 698 ~ 33-849 Suwałki"
"pan Mikołaj Lepak","2246616556310947","Fundacja Suszko","ulica Azaliowa 384 ~ 03-897 Bielsk Podlaski"
"Paweł Salach","180059547928299","Fundacja Małysiak-Dyja i syn s.c.","ul. Lwowska 55/66 ~ 22-570 Siemianowice Śląskie"
"pani Gaja Czuj","4389757006142895","Grupa Łabaj","plac Kraszewskiego 09 ~ 06-308 Swarzędz"
"Marianna Chorążewicz","4174174208112086622","Jarosik Sp. z o.o.","ul. Częstochowska 53/98 ~ 23-231 Luboń"
"Alex Nałęcz","4143163965298694","Szajner Sp.k.","aleja Poniatowskiego 97 ~ 12-132 Goleniów"
"pan Jacek Piegza","4474623156971045315","Stowarzyszenie Śmieszek-Kunert s.c.","pl. Kamienna 59/75 ~ 15-194 Kraśnik"
"Andrzej Wieja","2238009374691336","PPUH Pyś","ul. Boczna 79/53 ~ 69-572 Jarocin"
"Kacper Lew","2463778200660725","Gabinety Drywa Sp.j.","plac Lotnicza 167 ~ 62-855 Bartoszyce"
"pani Kornelia Smykla","6011299674289634","Grupa Makoś","pl. Jana 19/69 ~ 59-451 Włocławek"
"Monika Grądziel","4748102815949568","Drewniok Sp.j.","pl. Szpitalna 24/46 ~ 62-902 Ełk"
"Sebastian Wąsiewicz","2372377796167979","Brodawka-Kruzel i syn s.c.","al. Pogodna 26/32 ~ 98-571 Bielawa"
"Artur Sobisz","502092509400","Spółdzielnia Dziurla-Sprawka i syn s.c.","al. Konarskiego 89 ~ 70-206 Gniezno"
"Aleks Klama","378734565638473","Spółdzielnia Juśkiewicz-Kosz i syn s.c.","pl. Kościuszki 120 ~ 93-546 Świdnik"
"Jacek Lenarcik","376258200817229","FPUH Bors Sp.k.","pl. Urocza 88/84 ~ 09-291 Nowy Targ"
"Marcin Pyda","4669896962095423","Stowarzyszenie Gradek-Samoraj Sp. z o.o. Sp.k.","ul. Konwaliowa 555 ~ 07-657 Nowa Ruda"
"Dorota Matejczyk","6539652147472497","Spółdzielnia Roda","al. Zamkowa 831 ~ 57-579 Zgorzelec"
"Ewa Jeżyna","4097364985845102","Nowotnik-Welc Sp. z o.o. Sp.k.","al. Dąbrowskiej 13/41 ~ 76-645 Żagań"
"Mieszko Prokopiak","2263482666892193","Wójs Sp.j.","plac Okrzei 83/70 ~ 70-345 Szczecinek"
"Róża Dziób","4855572717299","Nieradzik-Trzcionka Sp. z o.o.","plac Nadrzeczna 934 ~ 61-453 Swarzędz"
"pan Jan Lamch","4502391994143798","Fundacja Florian","aleja Zwycięstwa 694 ~ 34-759 Łaziska Górne"
"Jan Murach","3593771038771088","Kyc Sp. z o.o. Sp.k.","pl. Sowia 465 ~ 13-673 Szczecin"
"Elżbieta Towarek","4667302067260428","FPUH Paliga","aleja Wiatraczna 54/94 ~ 67-755 Zgierz"
"pani Dorota Pasiut","378563891230360","Stowarzyszenie Starzak-Częścik S.A.","aleja Orla 72 ~ 20-575 Ząbki"
"pani Blanka Ptok","370541417282287","Fundacja Hadam i syn s.c.","pl. Maczka 59/48 ~ 24-166 Łaziska Górne"
"pan Julian Hnat","3579541640930739","Kajdan-Szmajda S.A.","plac Agrestowa 98/92 ~ 13-643 Ostrów Wielkopolski"
"pan Ignacy Znojek","6542009648451071","Gramza-Szatko Sp.k.","ul. Szmaragdowa 36/71 ~ 65-328 Sopot"
"Olaf Zamora","6011860315859596","Stowarzyszenie Styn i syn s.c.","ulica Zbożowa 01/42 ~ 02-874 Ostrowiec Świętokrzyski"
"Gustaw Kapka","180038930766375","Spółdzielnia Ostapczuk-Cieciora Sp.j.","aleja Porzeczkowa 741 ~ 48-066 Radom"
"Błażej Broszkiewicz","213127797448648","Frycz i syn s.c.","pl. Zdrojowa 89 ~ 70-635 Turek"
"Anna Maria Gendera","5298861480970198","PPUH Karpik Sp. z o.o. Sp.k.","ul. Wojska Polskiego 699 ~ 56-951 Koło"
"Natasza Litwinowicz","375165883159673","Gabinety Mikita-Podsiadła S.A.","aleja Konarskiego 796 ~ 08-952 Piaseczno"
"pan Daniel Ficner","377979875476186","FPUH Szyma Sp. z o.o.","ul. Szeroka 08 ~ 80-356 Kutno"
"Justyna Małyszka","4355469743417","Grupa Lizoń","al. Dąbrowskiego 57/35 ~ 90-380 Swarzędz"
"Iwo Mirgos","4997687699233202","Friedrich-Sieczko i syn s.c.","ulica Zdrojowa 31/55 ~ 43-995 Bochnia"
"Julian Kozdrój","30434364978861","Bela-Kanarek Sp. z o.o. Sp.k.","plac Szarych Szeregów 89/77 ~ 07-575 Lębork"
"Aleksander Miecznik","3521088600665714","Stowarzyszenie Owsiany","ulica Daszyńskiego 62 ~ 92-483 Malbork"
"Michał Balcewicz","675968012087","Saczuk-Matla Sp.j.","al. Szczęśliwa 05/00 ~ 09-246 Świecie"
"Aleksander Kościk","581893943703","Rudolf Sp. z o.o.","plac Klonowa 92/99 ~ 08-621 Lubin"
"Julian Sapała","6544987846408225","Spółdzielnia Aleksiejuk","aleja Słowackiego 49 ~ 18-405 Katowice"
"Antoni Kość","3582058987733167","Spółdzielnia Puto","ul. Władysława Łokietka 93 ~ 30-757 Gdańsk"
"Jan Majorek","3535423261750899","Stowarzyszenie Gumieniak s.c.","pl. Harcerska 46/67 ~ 11-093 Stalowa Wola"
1 pan Tymoteusz Fornalik 3579454591527662 PPUH Opioła-Franków i syn s.c. plac Jaśminowa 42/38 ~ 82-249 Zambrów
2 Anastazja Kobza 4597865459252406 Oleksak-Nicewicz Sp.j. pl. Rzeczna 028 ~ 78-208 Piotrków Trybunalski
3 pan Igor Madzia 213174349909859 Fundacja Kulis Sp. z o.o. pl. Lelewela 03/08 ~ 93-852 Mielec
4 Miłosz Lenarcik 213113678367743 Dybaś Sp.k. al. Szewska 90/80 ~ 78-042 Oświęcim
5 Cyprian Troć 213179982678067 Ruszczak-Ruszczak S.A. aleja Źródlana 13 ~ 95-829 Sochaczew
6 pan Mariusz Rycerz 180061535819365 Cyrulik-Kuświk S.A. plac Glówna 55 ~ 18-830 Ostrów Wielkopolski
7 Eliza Wikło 213142435307718 Fundacja Flaga ulica Kochanowskiego 36 ~ 95-595 Sopot
8 Radosław Burza 6011363834691624 Fundacja Hrabia Sp. z o.o. Sp.k. al. Targowa 08/52 ~ 21-002 Wągrowiec
9 Natan Janowiak 3593567621055321 Żuchowicz i syn s.c. plac Ogrodowa 61/02 ~ 23-192 Malbork
10 Maksymilian Kieca 377417377811550 PPUH Bilewicz plac Kopernika 36/61 ~ 48-407 Legionowo
11 pani Dorota Wieczerzak 6596262282704702 PPUH Plona-Lenc Sp.k. ul. Wieniawskiego 773 ~ 45-722 Nowa Ruda
12 Dagmara Haponiuk 30572635788401 Czajor-Kozłowicz i syn s.c. plac Czereśniowa 42/85 ~ 64-701 Ruda Śląska
13 Ksawery Michalkiewicz 2720067801981675 Gabinety Mikiciuk-Jędrzejek S.A. pl. Porzeczkowa 656 ~ 78-965 Grudziądz
14 Dagmara Mikus 4926843824626 Sendor-Pianka s.c. ulica Bociania 865 ~ 14-918 Pruszków
15 Lidia Czosnyka 4654299725117636938 Kuryłowicz-Brodawka Sp.k. al. Kołłątaja 93/97 ~ 53-732 Brzeg
16 pan Bruno Startek 6011844466007999 Roch S.A. ul. Partyzantów 721 ~ 47-570 Żory
17 Radosław Troć 676319474810 FPUH Łukasz Sp. z o.o. Sp.k. ul. Porzeczkowa 56 ~ 28-009 Bielawa
18 Blanka Tadla 341704652423174 FPUH Cyman-Białach i syn s.c. al. Nowa 526 ~ 21-033 Piła
19 Konrad Toma 3519664242836923 Gryga Sp. z o.o. Sp.k. ul. Partyzantów 698 ~ 33-849 Suwałki
20 pan Mikołaj Lepak 2246616556310947 Fundacja Suszko ulica Azaliowa 384 ~ 03-897 Bielsk Podlaski
21 Paweł Salach 180059547928299 Fundacja Małysiak-Dyja i syn s.c. ul. Lwowska 55/66 ~ 22-570 Siemianowice Śląskie
22 pani Gaja Czuj 4389757006142895 Grupa Łabaj plac Kraszewskiego 09 ~ 06-308 Swarzędz
23 Marianna Chorążewicz 4174174208112086622 Jarosik Sp. z o.o. ul. Częstochowska 53/98 ~ 23-231 Luboń
24 Alex Nałęcz 4143163965298694 Szajner Sp.k. aleja Poniatowskiego 97 ~ 12-132 Goleniów
25 pan Jacek Piegza 4474623156971045315 Stowarzyszenie Śmieszek-Kunert s.c. pl. Kamienna 59/75 ~ 15-194 Kraśnik
26 Andrzej Wieja 2238009374691336 PPUH Pyś ul. Boczna 79/53 ~ 69-572 Jarocin
27 Kacper Lew 2463778200660725 Gabinety Drywa Sp.j. plac Lotnicza 167 ~ 62-855 Bartoszyce
28 pani Kornelia Smykla 6011299674289634 Grupa Makoś pl. Jana 19/69 ~ 59-451 Włocławek
29 Monika Grądziel 4748102815949568 Drewniok Sp.j. pl. Szpitalna 24/46 ~ 62-902 Ełk
30 Sebastian Wąsiewicz 2372377796167979 Brodawka-Kruzel i syn s.c. al. Pogodna 26/32 ~ 98-571 Bielawa
31 Artur Sobisz 502092509400 Spółdzielnia Dziurla-Sprawka i syn s.c. al. Konarskiego 89 ~ 70-206 Gniezno
32 Aleks Klama 378734565638473 Spółdzielnia Juśkiewicz-Kosz i syn s.c. pl. Kościuszki 120 ~ 93-546 Świdnik
33 Jacek Lenarcik 376258200817229 FPUH Bors Sp.k. pl. Urocza 88/84 ~ 09-291 Nowy Targ
34 Marcin Pyda 4669896962095423 Stowarzyszenie Gradek-Samoraj Sp. z o.o. Sp.k. ul. Konwaliowa 555 ~ 07-657 Nowa Ruda
35 Dorota Matejczyk 6539652147472497 Spółdzielnia Roda al. Zamkowa 831 ~ 57-579 Zgorzelec
36 Ewa Jeżyna 4097364985845102 Nowotnik-Welc Sp. z o.o. Sp.k. al. Dąbrowskiej 13/41 ~ 76-645 Żagań
37 Mieszko Prokopiak 2263482666892193 Wójs Sp.j. plac Okrzei 83/70 ~ 70-345 Szczecinek
38 Róża Dziób 4855572717299 Nieradzik-Trzcionka Sp. z o.o. plac Nadrzeczna 934 ~ 61-453 Swarzędz
39 pan Jan Lamch 4502391994143798 Fundacja Florian aleja Zwycięstwa 694 ~ 34-759 Łaziska Górne
40 Jan Murach 3593771038771088 Kyc Sp. z o.o. Sp.k. pl. Sowia 465 ~ 13-673 Szczecin
41 Elżbieta Towarek 4667302067260428 FPUH Paliga aleja Wiatraczna 54/94 ~ 67-755 Zgierz
42 pani Dorota Pasiut 378563891230360 Stowarzyszenie Starzak-Częścik S.A. aleja Orla 72 ~ 20-575 Ząbki
43 pani Blanka Ptok 370541417282287 Fundacja Hadam i syn s.c. pl. Maczka 59/48 ~ 24-166 Łaziska Górne
44 pan Julian Hnat 3579541640930739 Kajdan-Szmajda S.A. plac Agrestowa 98/92 ~ 13-643 Ostrów Wielkopolski
45 pan Ignacy Znojek 6542009648451071 Gramza-Szatko Sp.k. ul. Szmaragdowa 36/71 ~ 65-328 Sopot
46 Olaf Zamora 6011860315859596 Stowarzyszenie Styn i syn s.c. ulica Zbożowa 01/42 ~ 02-874 Ostrowiec Świętokrzyski
47 Gustaw Kapka 180038930766375 Spółdzielnia Ostapczuk-Cieciora Sp.j. aleja Porzeczkowa 741 ~ 48-066 Radom
48 Błażej Broszkiewicz 213127797448648 Frycz i syn s.c. pl. Zdrojowa 89 ~ 70-635 Turek
49 Anna Maria Gendera 5298861480970198 PPUH Karpik Sp. z o.o. Sp.k. ul. Wojska Polskiego 699 ~ 56-951 Koło
50 Natasza Litwinowicz 375165883159673 Gabinety Mikita-Podsiadła S.A. aleja Konarskiego 796 ~ 08-952 Piaseczno
51 pan Daniel Ficner 377979875476186 FPUH Szyma Sp. z o.o. ul. Szeroka 08 ~ 80-356 Kutno
52 Justyna Małyszka 4355469743417 Grupa Lizoń al. Dąbrowskiego 57/35 ~ 90-380 Swarzędz
53 Iwo Mirgos 4997687699233202 Friedrich-Sieczko i syn s.c. ulica Zdrojowa 31/55 ~ 43-995 Bochnia
54 Julian Kozdrój 30434364978861 Bela-Kanarek Sp. z o.o. Sp.k. plac Szarych Szeregów 89/77 ~ 07-575 Lębork
55 Aleksander Miecznik 3521088600665714 Stowarzyszenie Owsiany ulica Daszyńskiego 62 ~ 92-483 Malbork
56 Michał Balcewicz 675968012087 Saczuk-Matla Sp.j. al. Szczęśliwa 05/00 ~ 09-246 Świecie
57 Aleksander Kościk 581893943703 Rudolf Sp. z o.o. plac Klonowa 92/99 ~ 08-621 Lubin
58 Julian Sapała 6544987846408225 Spółdzielnia Aleksiejuk aleja Słowackiego 49 ~ 18-405 Katowice
59 Antoni Kość 3582058987733167 Spółdzielnia Puto ul. Władysława Łokietka 93 ~ 30-757 Gdańsk
60 Jan Majorek 3535423261750899 Stowarzyszenie Gumieniak s.c. pl. Harcerska 46/67 ~ 11-093 Stalowa Wola

22
dzien_04/fake_data.py Normal file
View File

@@ -0,0 +1,22 @@
from faker import Faker
from random import randint
import csv
fake_data = Faker("pl_PL")
tabela = []
for _ in range(60):
wiersz = []
wiersz.append(fake_data.name())
wiersz.append(randint(10,6000))
wiersz.append(fake_data.credit_card_number())
wiersz.append(fake_data.company())
wiersz.append(fake_data.address().replace('\n',' ~ '))
tabela.append(wiersz)
print(tabela)
with open("dane_aj.csv", "w", newline="") as plik_csv:
dane_writer = csv.writer(plik_csv, delimiter=",", \
quotechar='"', quoting=csv.QUOTE_NONNUMERIC)
dane_writer.writerows(tabela)

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

View 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

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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

View File

@@ -0,0 +1,3 @@
matplotlib
opencv-python
exif

View File

@@ -0,0 +1,5 @@
import cv2
print(cv2.__version__)
print(f"To jest to {cv2.__version__}")
print(f"To też {cv2.__version__=}")

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

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