<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Numpy on Benedykt Huszcza | Blog</title><link>https://blog.huszcza.dev/pl/tags/numpy/</link><description>Recent content in Numpy on Benedykt Huszcza | Blog</description><generator>Hugo -- gohugo.io</generator><language>pl</language><lastBuildDate>Sun, 23 Feb 2025 18:00:00 +0000</lastBuildDate><atom:link href="https://blog.huszcza.dev/pl/tags/numpy/index.xml" rel="self" type="application/rss+xml"/><item><title>Vessel Extraction – Przetwarzanie Obrazów z Wykorzystaniem Pythona i OpenCV</title><link>https://blog.huszcza.dev/pl/p/vessel-extraction/</link><pubDate>Sun, 23 Feb 2025 18:00:00 +0000</pubDate><guid>https://blog.huszcza.dev/pl/p/vessel-extraction/</guid><description>&lt;img src="https://blog.huszcza.dev/p/vessel-extraction/cover.jpg" alt="Featured image of post Vessel Extraction – Przetwarzanie Obrazów z Wykorzystaniem Pythona i OpenCV" />&lt;h2 id="słowem-wstępu">Słowem wstępu
&lt;/h2>&lt;p>Projekt został stworzony jako ocena cząstkowa z przedmiotu &lt;strong>informatyka w medycynie&lt;/strong>. Nie licząc hackathonu (swoją drogą, polecam wpis &lt;a class="link" href="https://kaszkowiak.org/blog/ensemble-ai/" target="_blank" rel="noopener"
>Macieja&lt;/a> na temat tego wydarzenia), było to moje &lt;strong>pierwsze poważniejsze zetknięcie z bibliotekami&lt;/strong> takimi jak &lt;strong>PyTorch&lt;/strong> czy &lt;strong>OpenCV&lt;/strong>.&lt;/p>
&lt;p>Ponieważ zadanie okazało się dość wymagające, zmusiło mnie to do &lt;strong>szerokiego researchu&lt;/strong> na temat różnych metod przetwarzania obrazów. Sprawdzałem dosłownie wszystko – od najprostszych filtrów po bardziej zaawansowane techniki &lt;strong>computer vision&lt;/strong>. Dzięki temu poznałem podstawowe metody używane w tej dziedzinie, co znacznie poszerzyło moje horyzonty.&lt;/p>
&lt;p>Nie będę ukrywał – momentami bywało ciężko, zwłaszcza gdy szumy na obrazach niweczyły godziny pracy nad kodem. Mimo to, &lt;strong>wizja wykorzystania technologii do analizy obrazów medycznych&lt;/strong> była dla mnie ogromną inspiracją i napędzała mnie do działania. Czasami frustrowałem się, gdy coś nie działało zgodnie z oczekiwaniami, ale &lt;strong>satysfakcja z działającego rozwiązania&lt;/strong> zdecydowanie wynagrodziła wszystkie trudy.&lt;/p>
&lt;h2 id="k-nearest-neighbors-knn--klasyfikacja-naczyń-krwionośnych">K-Nearest Neighbors (KNN) – Klasyfikacja naczyń krwionośnych
&lt;/h2>&lt;h3 id="czym-jest-k-nearest-neighbors">Czym jest K-Nearest Neighbors?
&lt;/h3>&lt;p>&lt;strong>K-Nearest Neighbors (KNN)&lt;/strong> to jeden z najprostszych i najbardziej intuicyjnych algorytmów &lt;strong>uczenia maszynowego&lt;/strong>. Jego działanie opiera się na założeniu, że &lt;strong>podobne dane są blisko siebie w przestrzeni cech&lt;/strong>. W skrócie – jeśli chcesz wiedzieć, do jakiej klasy należy nowy punkt, sprawdź, do jakiej klasy należą jego najbliżsi sąsiedzi.&lt;/p>
&lt;p>W przypadku projektu &lt;strong>Vessel Extraction&lt;/strong> KNN został użyty do:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Klasyfikacji pikseli&lt;/strong> jako „naczynia krwionośne” lub „tło”,&lt;/li>
&lt;li>&lt;strong>Analizy sąsiedztwa pikseli&lt;/strong>, co pozwalało na bardziej precyzyjne rozróżnienie naczyń od szumów.&lt;/li>
&lt;/ul>
&lt;h3 id="undersampling--jak-poradziłem-sobie-z-niezbalansowanymi-danymi">Undersampling – Jak poradziłem sobie z niezbalansowanymi danymi?
&lt;/h3>&lt;h3 id="jakie-były-wyzwania">Jakie były wyzwania?
&lt;/h3>&lt;ul>
&lt;li>
&lt;p>&lt;strong>Nadmiar danych tła&lt;/strong> – Obszary bez naczyń krwionośnych (tło) dominowały na obrazach, co powodowało, że model uczył się głównie rozpoznawać tło, a nie naczynia.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Niedobór danych naczyń krwionośnych&lt;/strong> – Piksele należące do naczyń krwionośnych stanowiły &lt;strong>mniej niż 10%&lt;/strong> wszystkich danych, co powodowało, że model bardzo szybko przeuczał się.&lt;/p>
&lt;p>&lt;img src="https://blog.huszcza.dev/p/vessel-extraction/mask.png"
width="512"
height="512"
srcset="https://blog.huszcza.dev/p/vessel-extraction/mask_hub25e895537f1a182441b7f28296fe610_37737_480x0_resize_box_3.png 480w, https://blog.huszcza.dev/p/vessel-extraction/mask_hub25e895537f1a182441b7f28296fe610_37737_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="Przykładowa maska, na której widać, że naczynia stanowią małą część całego obrazu"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="240px"
>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="jak-sobie-z-tym-poradziłem">Jak sobie z tym poradziłem?
&lt;/h3>&lt;p>Postanowiłem zastosować &lt;strong>undersampling&lt;/strong> – czyli &lt;strong>celowe ograniczenie liczby danych tła&lt;/strong>, aby liczba pikseli naczyniowych i tła była bardziej zrównoważona. Brzmi prosto, ale wymagało to kilku przemyślanych kroków:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Wybór próbek tła&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Nie wyrzucałem danych tła losowo, bo mogło to prowadzić do utraty ważnych informacji o kontekście obrazu.&lt;/li>
&lt;li>Skupiłem się na &lt;strong>reprezentatywnych próbkach&lt;/strong>, czyli takich, które znajdowały się blisko naczyń krwionośnych. Dzięki temu model miał lepszy kontekst do nauki.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Redukcja liczby próbek tła&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Ostatecznie &lt;strong>zredukowałem liczbę próbek tła o około 70%&lt;/strong>, co sprawiło, że stosunek danych naczyniowych do tła był &lt;strong>bardziej zrównoważony&lt;/strong>.&lt;/li>
&lt;li>Ważne było, żeby nie przesadzić – musiałem zostawić wystarczająco dużo tła, żeby model nie zaczął go mylić z naczyniami.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Zachowanie lokalnych wzorców&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Dzięki zastosowaniu &lt;strong>wycinków 3x3 pikseli&lt;/strong> model nie stracił lokalnych wzorców, co poprawiło &lt;strong>dokładność (accuracy)&lt;/strong>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h3 id="jak-działało-knn-w-tym-projekcie">Jak działało KNN w tym projekcie?
&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>Ekstrakcja cech&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Każdy piksel został opisany za pomocą wartości jasności oraz wartości sąsiednich pikseli.&lt;/li>
&lt;li>Dzięki temu model miał więcej informacji o lokalnym kontekście.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Wybór liczby sąsiadów (k)&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Najważniejszym parametrem w KNN jest &lt;strong>k&lt;/strong> – liczba najbliższych sąsiadów, których klasa będzie brana pod uwagę przy klasyfikacji.&lt;/li>
&lt;li>W projekcie przeprowadziłem &lt;strong>walidację krzyżową&lt;/strong>, żeby znaleźć optymalną wartość &lt;strong>k&lt;/strong>.&lt;/li>
&lt;li>Najlepsze wyniki osiągnąłem dla &lt;strong>k = 5&lt;/strong>, co zapewniło &lt;strong>równowagę między dokładnością a czułością&lt;/strong>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Klasyfikacja&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Dla każdego pikselu sprawdzane było, jakie klasy mają jego &lt;strong>k najbliżsi sąsiedzi&lt;/strong>.&lt;/li>
&lt;li>Piksel zostawał przypisany do tej klasy, która miała najwięcej reprezentantów w sąsiedztwie.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h3 id="wyniki-i-efekty">Wyniki i efekty
&lt;/h3>&lt;ul>
&lt;li>&lt;strong>Dokładność (accuracy)&lt;/strong>: &lt;strong>89%&lt;/strong> – całkiem nieźle jak na prosty model bez głębokiego uczenia!&lt;/li>
&lt;li>&lt;strong>Czułość (recall)&lt;/strong>: &lt;strong>85%&lt;/strong> – dobrze wykrywał naczynia krwionośne, ale czasami mylił je z cienkimi liniami tła.&lt;/li>
&lt;li>&lt;strong>Precyzja (precision)&lt;/strong>: &lt;strong>91%&lt;/strong> – model dość skutecznie unikał fałszywych alarmów (błędnego oznaczania tła jako naczyń).&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://blog.huszcza.dev/p/vessel-extraction/knn_results.png"
width="877"
height="231"
srcset="https://blog.huszcza.dev/p/vessel-extraction/knn_results_huab335b82c4c70e0ad9aa232b7bc3a084_116236_480x0_resize_box_3.png 480w, https://blog.huszcza.dev/p/vessel-extraction/knn_results_huab335b82c4c70e0ad9aa232b7bc3a084_116236_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="Od lewej: oryginalne zdjęcie, maska, odtworzona maska oparta na klasyfikacji"
class="gallery-image"
data-flex-grow="379"
data-flex-basis="911px"
>
Wiem, że &lt;strong>efekt na pierwszy rzut oka nie powala&lt;/strong> i można się zastanawiać, jakim cudem udało się uzyskać tak dobre &lt;strong>&amp;ldquo;cyferki&amp;rdquo;&lt;/strong> (czyli dokładność). Ale tu właśnie tkwi mały szkopuł, czyli narzucone wymaganie.&lt;/p>
&lt;p>Chciałbym zaznaczyć, że do uczenia modelu wykorzystałem &lt;strong>wycinki o rozmiarze 3x3 pikseli&lt;/strong>, ponieważ na tak małych fragmentach model łatwiej wykrywa lokalne wzorce charakterystyczne dla naczyń krwionośnych.&lt;/p>
&lt;p>Całkowity rozmiar obrazu to &lt;strong>512x512 pikseli&lt;/strong>, więc jeśli klasyfikator stwierdził, że &lt;strong>dany wycinek to naczynie krwionośne&lt;/strong>, to te &lt;strong>9 pikseli&lt;/strong> (3x3) w rezultacie zostało &lt;strong>w całości wypełnione na biało&lt;/strong>.&lt;/p>
&lt;h3 id="zalety-i-wady-knn">Zalety i wady KNN
&lt;/h3>&lt;p>&lt;strong>Zalety:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Prostota implementacji&lt;/strong> – KNN jest bardzo intuicyjny i łatwy do zrozumienia.&lt;/li>
&lt;li>&lt;strong>Brak trenowania modelu&lt;/strong> – Cała „nauka” odbywa się w momencie klasyfikacji.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Wady:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Wolne działanie dla dużych zbiorów danych&lt;/strong> – Każda klasyfikacja wymaga obliczenia odległości do wszystkich punktów treningowych.&lt;/li>
&lt;li>&lt;strong>Czułość na nieistotne cechy&lt;/strong> – Wszystkie cechy mają taką samą wagę, co czasami może prowadzić do błędnych klasyfikacji.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="fastai--głębokie-uczenie-dla-klasyfikacji-naczyń-krwionośnych">FastAi – Głębokie uczenie dla klasyfikacji naczyń krwionośnych
&lt;/h2>&lt;h3 id="dlaczego-fastai">Dlaczego FastAi?
&lt;/h3>&lt;p>Po przetestowaniu klasycznego KNN postanowiłem pójść krok dalej i zastosować &lt;strong>FastAi&lt;/strong> – framework oparty na &lt;strong>PyTorch&lt;/strong>, który jest świetny do szybkiego prototypowania modeli głębokiego uczenia. FastAi oferuje:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Łatwą integrację z gotowymi modelami&lt;/strong> (np. ResNet),&lt;/li>
&lt;li>&lt;strong>Prosty w użyciu interfejs API&lt;/strong>, który przyspiesza przygotowanie danych i trenowanie modeli,&lt;/li>
&lt;li>&lt;strong>Zaawansowane techniki optymalizacji&lt;/strong> (np. learning rate finder).&lt;/li>
&lt;/ul>
&lt;h3 id="jak-działało-fastai-w-projekcie">Jak działało FastAi w projekcie?
&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>Przygotowanie danych&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Obrazy zostały podzielone na &lt;strong>mniejsze fragmenty&lt;/strong> (patches), aby modele mogły łatwiej nauczyć się wzorców.&lt;/li>
&lt;li>Użyłem &lt;strong>FastAi DataBlock API&lt;/strong> do zarządzania danymi i ich etykietowania.&lt;/li>
&lt;li>Klasyfikacja odbywała się na dwóch poziomach:
&lt;ul>
&lt;li>&lt;strong>Naczynia krwionośne&lt;/strong>,&lt;/li>
&lt;li>&lt;strong>Tło&lt;/strong>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Model głębokiego uczenia&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Wybrałem &lt;strong>ResNet34&lt;/strong> – lekki, ale wystarczająco mocny model do rozpoznawania naczyń.&lt;/li>
&lt;li>Skorzystałem z &lt;strong>transfer learningu&lt;/strong>, żeby model uczył się na podstawie gotowych wag (ImageNet), co przyspieszyło trening.&lt;/li>
&lt;li>&lt;strong>Fine-tuning&lt;/strong> na ostatnich warstwach pozwolił dostosować model do specyficznego zadania rozpoznawania naczyń krwionośnych.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Trenowanie i optymalizacja&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Trenowałem model przy użyciu &lt;strong>learning rate finder&lt;/strong> FastAi, co pomogło dobrać optymalny współczynnik uczenia.&lt;/li>
&lt;li>&lt;strong>Augmentacja danych&lt;/strong> (rotacje, odbicia, zmiana jasności) pomogła zwiększyć różnorodność danych treningowych i poprawiła ogólną wydajność modelu.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>&lt;img src="https://blog.huszcza.dev/p/vessel-extraction/fast_ai_results.png"
width="884"
height="278"
srcset="https://blog.huszcza.dev/p/vessel-extraction/fast_ai_results_hu4eebe31602d40791196e041ac3b07fee_162820_480x0_resize_box_3.png 480w, https://blog.huszcza.dev/p/vessel-extraction/fast_ai_results_hu4eebe31602d40791196e041ac3b07fee_162820_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="Wyniki FastAi"
class="gallery-image"
data-flex-grow="317"
data-flex-basis="763px"
>&lt;/p>
&lt;h3 id="wyniki-i-efekty-1">Wyniki i efekty
&lt;/h3>&lt;ul>
&lt;li>&lt;strong>Dokładność (accuracy)&lt;/strong>: &lt;strong>92%&lt;/strong> – co jest wyraźną poprawą w porównaniu do KNN.&lt;/li>
&lt;li>&lt;strong>Czułość (recall)&lt;/strong>: &lt;strong>90%&lt;/strong> – model świetnie radził sobie z rozpoznawaniem naczyń nawet w trudniejszych przypadkach.&lt;/li>
&lt;li>&lt;strong>Precyzja (precision)&lt;/strong>: &lt;strong>94%&lt;/strong> – minimalna liczba fałszywych alarmów i bardzo precyzyjne wykrywanie naczyń.&lt;/li>
&lt;/ul>
&lt;h3 id="zalety-i-wady-fastai">Zalety i wady FastAi
&lt;/h3>&lt;p>&lt;strong>Zalety:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Wysoka dokładność&lt;/strong> – Model głębokiego uczenia znacznie przewyższał KNN pod względem dokładności.&lt;/li>
&lt;li>&lt;strong>Możliwość fine-tuningu&lt;/strong> – Dzięki transfer learningowi i fine-tuningowi model szybko dostosował się do specyfiki obrazów medycznych.&lt;/li>
&lt;li>&lt;strong>Proste API&lt;/strong> – FastAi pozwala na szybkie eksperymentowanie z różnymi modelami i parametrami.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Wady:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Wysokie wymagania sprzętowe&lt;/strong> – Modele głębokiego uczenia wymagają mocnego GPU do efektywnego treningu, sam korzsytałem z Kaggle do fine tuningu.&lt;/li>
&lt;/ul>
&lt;h2 id="pierwszy-krok-w-świecie-uczenia-maszynowego">Pierwszy krok w świecie uczenia maszynowego
&lt;/h2>&lt;p>Muszę przyznać, że to mój &lt;strong>pierwszy indywidualny projekt&lt;/strong> związany z &lt;strong>uczeniem maszynowym&lt;/strong> i &lt;strong>computer vision&lt;/strong>. Poznałem w praktyce działanie &lt;strong>KNN&lt;/strong> oraz &lt;strong>FastAi&lt;/strong>, zrozumiałem, jak potężne są techniki przetwarzania obrazu i jak radzić sobie z problemem niezbalansowanych danych za pomocą &lt;strong>undersamplingu&lt;/strong>. Satysfakcja z wyniku przetwarzania była ogromna, jednakże sam projekt uświadomił mi również, że &lt;strong>jestem dopiero na początku drogi&lt;/strong>.&lt;/p>
&lt;p>Pomimo wielu błędów i frustracji, poczułem prawdziwą &lt;strong>zajawkę na uczenie maszynowe&lt;/strong>. Kombinowanie z danymi, testowanie modeli i optymalizacja algorytmów okazały się czymś, co naprawdę mnie kręci. Wiem, że przede mną jeszcze mnóstwo nauki – zaawansowane architektury sieci neuronowych, optymalizacja hiperparametrów, wydajność na GPU – ale jestem na to gotowy.&lt;/p>
&lt;p>Jeśli chcesz zobaczyć kod źródłowy albo dowiedzieć się więcej, zajrzyj do &lt;strong>repozytorium na &lt;a class="link" href="https://github.com/benhus8/vessel-recognition/tree/main" target="_blank" rel="noopener"
>GitHubie&lt;/a>&lt;/strong>. Może ten projekt zainspiruje Cię do rozpoczęcia własnej przygody z AI?&lt;/p></description></item></channel></rss>