Main Body

Akwizycja i przechowywanie obrazu

Akwizycja obrazu to proces zmiany energii świetlnej pochodzącej od punktów obserwowanej sceny na sygnał elektryczny. Urządzenia do elektrycznej rejestracji obrazów to między innymi: kamera wideo, aparat fotograficzny czy skaner. Obraz to sygnał dwuwymiarowy, rzadziej trójwymiarowy. W tym ujęciu, obraz jest formalnym opisem tego, co rozumiemy intuicyjnie pod tym pojęciem (np. obraz telewizyjny, obraz fotograficzny czy obraz powstały na siatkówce oka). Jednocześnie, należy zaznaczyć, że z wykorzystaniem zaawansowanych narzędzi jesteśmy w stanie stworzyć obraz dwu lub trójwymiarowy, który przedstawia nam pewne elementy lub struktury składowe niedostrzegalne ludzkim okiem. Najczęściej chodzi tu o obrazy powstałe z wykorzystaniem technik obrazowania medycznego (rezonans magnetyczny, tomografia komputerowa, zdjęcie rentgenowskie) czy z wykorzystaniem kamery termowizyjnej lub obrazowania mikrofalowego.

Do rejestracji obrazu najczęściej wykorzystujemy kamerę lub aparat cyfrowy. Aparat i kamera przypomina działaniem i budową oko ludzkie. System optyczny składa się z zespołu soczewek oraz czujnika obrazu. Zadaniem zespołu soczewek jest wychwycenie części światła emitowanego przez obiekt i zogniskowanie go na czujniku obrazu. W kolejnym kroku czujnik obrazu przekształca strumień świetlny na sygnał elektryczny. System soczewek ma za zadanie regulować ogniskową i średnicę przesłony. Ważnym elementem systemu optycznego jest przesłona. Umożliwia ona regulację ilości dostarczanego światła a więc jaskrawości obrazu rzutowanego na czujnik. W oku ludzkim do tego celu służy źrenica. W aparacie ogniskowanie wykonuje się poprzez przesuwanie soczewki bliżej lub dalej czujnika.

Rysunek 1. Schemat działania aparatu cyfrowego

Czujnik obrazu cyfrowego to matryca, która zamienia energię świetlną na energię elektryczną. Wyróżnić możemy dwa rodzaje matryc: CCD (Charge-coupled device) nazwa pochodzi od sposobu działania matrycy oraz CMOS (complimentary metal-oxide semiconductor) nazwa wywodzi się od zastosowanych do produkcji matryc tranzystorów MOS. Matryca to to krzemowa płytka zbudowana z elementów światłoczułych, która jest detektorem wyłapującym i rejestrującym światło, padające na nią w postaci fotonów. Matryca jest podzielona na wiele elementów zwanych pikselami. W matrycy CCD na skutek zjawiska fotoelektrycznego, wytrącany jest elektron, następnie wybity elektron podąża w kierunku dodatnio naładowanej studni potencjału i tam zostaje przechowany (kondensator). Im dłużej trwa ekspozycja, tym więcej elektronów gromadzimy. Stosując samą matrycę nie otrzymujemy informacji o kolorze.

Rysunek 2. Zasada działania matrycy CCD i CMOS

 

Zgromadzony ładunek należy odczytać i przesłać do mikrokontrolera a następnie zapisać lub przetworzyć w pamięci urządzenia. To co jest charakterystyczne dla matryc CCD, to sposób odczytu ładunku z poszczególnych pikseli. Zawartość pikseli w matrycy CCD odczytuje się sekwencyjnie rząd po rzędzie. Ładunki w tym procesie są przesuwane w kierunku szyny odczytującej i kierują je do dalszej obróbki. To co otrzymujemy po zakończeniu opisanego tu procesu odczytu to tzw. obraz surowy, ogólnie nazywany RAW.

Podobnie wygląda sposób akumulacji ładunku w matrycy CMOS. Jednak, występują pewne różnice związane z odczytaniem i przechowywaniem ładunku elektrycznego. W matrycy CMOS, każdy piksel ma swój przetwornik ładunku na napięcie. To powoduje, że, każdy piksel ma swój indywidualny adres i jego zawartość może być odczytana w dowolnej kolejności. Obwody elektryczne zintegrowane z każdym pikselem zajmują miejsce na matrycy i dlatego w ogólności powierzchnia wszystkich pikseli do powierzchni całej matrycy jest mniejszy dla matryc typu CMOS.

Niewątpliwie, każdego rodzaju matryca ma swoje wady i zalety. Matryca CCD cechuje się: stosunkowo wolnym działaniem spowodowane tym, że układ odczytuje dane z pikseli rząd po rzędzie z całej matrycy; układ posiada jeden przetwornik ładunku na napięcie, oraz jeden przetwornik A/D – napięcia na liczbę; dużym zużyciem prądu; powoduje to nagrzewanie matrycy; większy współczynnik stosunek powierzchni pikseli do powierzchni całej matrycy; mniejsze szumy. Jeśli chodzi o matryce CMOS to cechują się: szybszym działaniem spowodowane tym, że układ ma możliwość odczytu danych z dowolnej liczby pikseli; każdy piksel matrycy posiada swój przetwornik na napięcie, oraz przetwornik A/D; małym zużyciem prądu; mniejszym współczynnikiem wypełnienia przetworników na powierzchni; większe szumy.

 

Rysunek 3. Matryca CCD

 

Rysunek 4. Matryca CMOS

 

Matryca jest detektorem wyłapującym i rejestrującym światło, natomiast bezpośrednio nie przetwarza informacji o kolorze. Aby rozwiązać, ten problem stosuje się specjalne filtry, które przepuszczają wybrany kolor światła do pewnych komórek matrycy. Jednym z najpopularniejszych filtrów odpowiedzialnych za rejestrację barw jest filtr Bayera. Po napyleniu detektora specjalnymi filtrami matryca CCD/CMOS wygląda jak trójkolorowa szachownica złożona z czerwonych, zielonych i niebieskich pól. W ten sposób piksele matrycy są czułe na światło w trzech podstawowych kolorach: czerwonym (R), zielonym (G) i niebieskim (B). Oprócz siatki Bayera istnieje jeszcze kilka rodzajów matryc filtrów, używanych w aparatach cyfrowych. Matryca filtrów Cyan Magenda Yellow, używa zamiast kolorów pochodnych: Cyjanu (jasno niebieski), Magenty (różowy) i Żółtego. Dlatego sensory z matryca CMY zbierają więcej fotonów, ponadto mają większą czułość oraz lepszy stosunek sygnału do szumu. Matryca filtrów Cyan Yellow Green Magenda składa się z czterech różnych kolorów. Układ ten powoli zdobywa popularność wśród aparatów kompaktowych i dSLR. Matryca filtrów Red Green Blue Emerald to siatka z czterech różnych kolorów filtrów, gdzie oprócz standardowych barw RGB stosuje się filtr szmaragdowy.

Odczytane i przetworzone napięcie z matrycy możemy interpretować, jako natężenie pewnego koloru. Istotnym parametrem zarejestrowanego obrazu jest rozdzielczość (liczba wierszy i kolumn pikseli) związana z zastosowaną matrycą. Ważnym elementem akwizycji jest sposób zapisu i przechowywania informacji o obrazie lub sekwencji obrazów (wideo). Wspomniany format RAW reprezentuje dane surowe, w którym obrazy lub filmy nie są w ogóle skompresowane, bądź też są skompresowane bez strat, aby umożliwić najbardziej elastyczną obróbkę obrazu. Nie zawsze potrzebna jest nam tak dokładna informacja o zarejestrowanych pikselach. Dlatego, w wielu zastosowaniach stosuje się kompresję obrazu. Najważniejszą zaletą kompresji jest zmniejszenie ilości miejsca potrzebnego do przechowywania użytecznej informacji. W wielu stosowanych formatach możemy wybrać stopień kompresji i zredukować rozdzielczość.

Plik typu JPG (JPEG) to jedna z metod kompresji danych stosowana w obrazach cyfrowych w szczególności w fotografii. Format JPEG jest najczęściej stosowanym standardem kompresji obrazu na świecie. Plik typu JPG jest plikiem obrobionym przez procesor w aparacie. W pliku JPG zapisywane są wszystkie zmiany, które nałożyliśmy z poziomu aparatu. Algorytm kompresji używany przez JPEG jest algorytmem stratnym, tzn. w czasie jego wykonywania tracona jest bezpowrotnie część pierwotnej informacji. W algorytmie JPG obraz jest konwertowany z kanałów czerwony-zielony-niebieski (model RGB) na jeden kanał jasności/luminancji i 2 kanały barwy/chrominancji (model YCbCr). Ponieważ ludzkie oko znacznie dokładniej postrzega różnice jasności od różnic barwy, a więc użyteczne jest tutaj rozbicie obrazu na te kanały, żeby użyć na nich różnych parametrów kompresji. Następnie, zmniejszana jest rozdzielczość pikseli kanałów barwy. Każdy kanał jest dzielony na bloki 8 na 8 pikseli. Na blokach wykonywana jest dyskretna transformata kosinusowa (DCT). Kolejny etap to kwantyzacja, czyli zastąpienie danych zmiennoprzecinkowych przez liczby całkowite. Powstało wiele formatów plików dedykowanych pewnego rodzaju grafik.

Format GIF umożliwia zapis grafiki w kolorze indeksowanym. Każdy piksel obrazu reprezentowany jest przez jeden z 256 kolorów palety. Zapis danych w pliku jest kompresją bezstratną metodą. Format ten zachowuje przezroczystość obrazów (przezroczystość lub jej brak). Format pozwala na utworzenie animacji poklatkowej. Format PNG to alternatywa dla formatu GIF obsługuje obrazy 24-bitowe oraz stopniowaną przezroczystość. Format PNG zalecany jest do zapisu grafiki umieszczanej na stronach WWW. Istnieje cała gama formatów graficznych obrazów i wideo. Należy zdawać sobie sprawę, że sposób kompresji, może wpływać na pewne detale, które mogą mieć znaczenie w dalszych etapach przetwarzania i analizy obrazu. Ważnym elementem w trakcie projektowania i analizy jest poprawny odczyt i interpretacja obrazów. Obecnie, załadowanie i konwersję do formy graficznej wykonują biblioteki. Pozwalają na odczyt większości formatów graficznych. W przypadku trudności z interpretacją formatów graficznych obrazów lub wideo może być konieczne doinstalowanie kodeków.

 

Do odczytu plików w bibliotece OpenCV służy funkcja imread(). Funkcja jako argumenty wejściowe przyjmuje łańcuch nazwy pliku, który chcemy odczytać oraz identyfikator parametru deklarujący sposób odczytu/ładowania danych do wyjściowej tablicy. Przykład ładowania tego samego pliku zaprezentowano na listingu 1. Parametrem zmieniającym się jest sposób ładowania do tablicy. Parametr IMREAD_COLOR oznacza, że obrazy ładowane są jako trzykanałowe grafiki, 8 bitów na kanał. Natomiast opcja IMREAD_GRAYSCALE ładuje obraz w skali szarości. Ładując z wykorzystaniem parametru IMREAD_ANYCOLOR funkcja ładuje plik jako jedno kanałowy w przypadku obrazu o odcieniach szarości natomiast jako  trzykanałowy w przypadku obrazu kolorowego. Opcja IMREAD_ANYDEPTH ładuje obraz bez żadnej konwersji, jeśli kanały obrazu mają więcej niż 8 bitów. Opcja IMREAD_UNCHANGED pozwala na załadowanie kanału apha, który oznacza przezroczystości grafiki.

Listing 1. Odczyt plików

import cv2
img1 = cv2.imread('swan_1.jpg',cv2.IMREAD_COLOR)

cv2.imshow('obraz pierwszy',img1)

cv2.waitKey(0)
cv2.destroyAllWindows()

Załadowany plik, w postaci macierzy kolorów, możemy przetwarzać, modyfikować. Natomiast w końcowym efekcie możemy zapisać wynik do pliku. Do zapisu posłużymy się funkcją imwirte(). Funkcja  wymaga podana nazwy pod jaką zapiszemy nasz plik, nazwy tablicy wielowymiarowej która jest obrazem. Ostatnim opcjonalnym parametrem, jest opcja sposobu danego formatu pliku. Pliki możemy zapisywać w formatach:

  • .jpg lub .jpeg – podstawowy JEPEG, 8 bitów na jeden kanał lub trzy kanały,
  • .jp2 – JEPEG 2000, 8 lub 16 bitów, jeden lub trzy kanały,
  • .tif lub fiff – TIFF, 8 lub 16 bitów, jeden, trzy lub trzy cztery,
  • .png – PNG, 8 lub 16 bitów, jeden, trzy lub cztery kanały,
  • .bmp – BMP, 8 bitów, jeden trzy lub cztery kanały,
  • .ppm lub .pgm – NetPBM, 8 bitów na jeden kanał (PGM) lub trzy kanały (PPM).

W tabeli 1 opisano parametry przyjmowane przez funkcję imwrite(). Wpisując identyfikator parametru możemy ustawić wartość, na przykład jakość kompresji.

Tabela 1. Parametry funkcji imwrite().

Identyfiaktor parametru Opis Zakres Domyślna wartość
IMWRITE_JPG_QUALITY Jakość obrazu JPEG 0-100 95
IMWRITE_JPG_COMPRESSION Kompresja PNG (wyższa wartość oznacza mniejszą kompresję) 0-9 3
IMWRITE_PXM_BINARY Format binarny dla plików PPM, PGM lub PGM 0 lub 1 1

Na listingu 2 zaprezentowano program, który odczytuje plik a następnie z pewnym poziomem kompresji zapisuje obraz JPG. Jakość kompresji i wizualne efekty zależą od struktury obrazu. Na kolejnych obrazach zaprezentowano obraz oryginalny (Rysunek 5), oraz zapisany z kompresją ustawioną na 10 (Rysunek 6) i 30 (Rysunek 7). Wielkość obrazu bez kompresji wynosi 118KB, dla kompresji 30 wynosi 59,7KB a dla kompresji 10 wynosi 26,9KB.

Listing 2. Odczyt, kompresja i zapis pliku jpg.

import cv2
img1 = cv2.imread('swan_1.jpg',cv2.IMREAD_COLOR)
cv2.imshow('obraz pierwszy',img1)

cv2.imwrite('swan_1_80.jpg',img1,[cv2.IMWRITE_JPEG_QUALITY, 80])

cv2.waitKey(0)
cv2.destroyAllWindows()
Rysunek 5. Obraz oryginalny JPEG.
Rysunek 6. Obraz zapisany z kompresją 10.

 

Rysunek 7. Obraz zapisany z kompresją 30.

Określony odczytany i przetworzony obraz o określonym rozmiarze (rozdzielczości) możemy zmniejszyć lub powiększyć. W tym celu możemy zastosować funkcję resize(). Funkcja działa w taki sposób, że musimy podać obraz oraz określić rozmiar docelowy. Funkcja wygeneruje nowy obraz o określonym rozmiarze. Na listingu 3 zaprezentowano program, który przeskalowuje wczytany plik a następnie zapisuje pod określoną nazwą pliku. Funkcja resize() umożliwia interpolację pikseli z określonymi parametrami. Zestawienie parametrów interpolacji przedstawiono w tabeli 2. Na rynkach 8, 9, 10 zaprezentowano plik dla kolejnych skalowań.

Tabela 2. Opcje interpolacji dla funkcji resize().

Interpolacja Opis
INTER_NEAREST Interpolacja najbliższego sąsiada
INTER_LINEAR Interpolacja liniowa
INTER_AREA Przepróbkowywanie obszaru pikseli
INTER_CUBIC Interpolacja wielomianem trzeciego stopnia
INTER_LANCZOS4 Interpolacja algorytmem Lanczos 8×8

Listing 3. Program zmieniający rozdzielczość pliku.


import cv2

img = cv2.imread('4.png', cv2.IMREAD_UNCHANGED)

print('Rozmiar oryginalnego obrazu : ',img.shape)

scale_percent = 500
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
dim = (width, height)

resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)

print('Rozmiar przeskalowanego obrazu : ',resized.shape)

cv2.imshow('obraz', resized)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

Rysunek 8. Obraz oryginalny.
Rysunek 9. Obraz powiększony 2 razy.
Rysunek 10. Obraz powiększony 5 razy.

 

Zadanie 1.

Na podstawie ogólnodostępnych materiałów w internecie, proszę sprawdzić jakiego typu matryce (CCD czy CMOS) dominują w aparatach fotograficznych oraz kamerach wideo. Jakie są typowe parametry dla matryc CCD i CMOS.

Odpowiedź 1.

Korzystając z wyszukiwarki jednego ze sklepów internetowych i ustawiając poszczególne filtry możemy zaobserwować, że dla aparatów cyfrowych dominują metryce CMOS 74 produkty. Dla matryc CCD znaleziono 35 produktów. Dla aparatów bezlusterkowych dominują matryce CMOS, 46 produktów. Dla kamer cyfrowych większość kamer wyposażonych jest w matryce typu CMOS. Jeden z produktów zawierający matrycę CMOS, lepszej klasy: Rozdzielczość przetwornika 12.7 [Mpx],  Rozmiar matrycy 1/2.3 [cal], Maksymalna rozdzielczość nagrywania filmów 3840 x 2160, Maksymalna rozdzielczość zdjęć 4000 x 3000.

Zadanie 2.

Proszę napisać program, który załaduje pliki w różnych formatach: .jpg, .tiff, .bmp, .png. Proszę sprawdzić jakiego, rozmiaru są tablice otrzymane po załadowaniu każdego pliku. Proszę sprawdzić różne opcje ładowania pliku i zweryfikować poprawność otrzymanych tablic.

Odpowiedź 2.

Na listingu 4 zaprezentowano fragment programu umożliwiający odczytanie plików z różnymi parametrami: IMREAD_COLOR, IMREAD_GRAYSCALE, IMREAD_ANYCOLOR, IMREAD_ANYDEPTH, IMREAD_UNCHANGED. Do weryfikacji rozmiaru tablicy obrazu możemy wykorzystać funkcję shape: img.shape

 

Listing 4. Odczyt plików z różnymi opcjami.

import cv2
img1 = cv2.imread('swan_1.jpg',cv2.IMREAD_COLOR)
img2 = cv2.imread('swan_1.jpg',cv2.IMREAD_GRAYSCALE)
img3 = cv2.imread('swan_1.jpg',cv2.IMREAD_ANYCOLOR)
img4 = cv2.imread('swan_1.jpg',cv2.IMREAD_ANYDEPTH)
img5 = cv2.imread('swan_1.jpg',cv2.IMREAD_UNCHANGED)

cv2.imshow('obraz pierwszy',img1)

cv2.waitKey(0)
cv2.destroyAllWindows()
Zadanie 3.

Proszę napisać program, który załaduje plik jpg dobrej jakości. Następnie proszę sprawdzić, jak wpływa jakość kompresji na wielkość pliku wyrażoną w KB oraz na jakość skompresowanego obrazu. Proszę ocenić próg kompresji, dla którego plik jest akceptowalny wizualnie. Proszę wykonać eksperymenty dla plików jpg zawierających krajobrazy, zdjęcia miasta, chmur, twarzy.

Odpowiedź 3.

Na listingu 5 zaprezentowano fragment programu umożliwiający odczytanie plików oraz kompresję pliku z wykorzystaniem opcji IMWRITE_JPEG_QUALITY. Program umożliwia stworzenie plików wynikowych w pętli. Dla pliku wejściowego o rozmiarze 337 KB, otrzymano 161KB dla kompresji ustawionej na 40. Jeśli chodzi o efekty wizualne, to są one różne dla plików o innej rozdzielczości oraz strukturze zdjęcia.

 

Listing 5. Odczyt plików i kompresja z różnymi parametrami.

import cv2

for x in range(1, 100, 10):
   img1 = cv2.imread('gory.jpg',cv2.IMREAD_COLOR)
   cv2.imwrite('gory' + str(x)+ '.jpg',img1,[cv2.IMWRITE_JPEG_QUALITY, x])
Zadanie 4.

Proszę napisać program, który załaduje plik graficzny. Z wykorzystaniem funkcji OpenCV proszę narysować linię, elipsę, okrąg, oraz napisać dowolny tekst. Następnie proszę sprawdzić, jak wpływa jakość kompresji na wielkość pliku wyrażoną w KB oraz na jakość skompresowanego obrazu.

Odpowiedź 4.

Na listingu 5 zaprezentowano fragment programu umożliwiający wczytanie obrazu, następnie z wykorzystaniem funkcji line, ellipse oraz putText dokonuje odpowiednich modyfikacji obrazu. Na rysunku 11 zaprezentowano przykład stworzonej grafiki.

 

Rysunek 11. Przykład stworzonego obrazu

Listing 5. Wczytanie pliku oraz narysowanie, linii, elipsy oraz wpisanie tekstu.

import cv2

img = cv2.imread('obraz.jpg',1)

cv2.line(img,(50,100),(511,511),(255,250,0),5)
cv2.ellipse(img,(256,256),(100,50),0,0,280,255,-1)

font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,'Projektowanie Systemow Wizyjnych',(50,500), font, 1,(0,0,255),2,cv2.LINE_AA)

cv2.imshow('obraz pierwszy',img)
cv2.imwrite('obraz_stworzony.png',img)

cv2.waitKey(0)
cv2.destroyAllWindows()
Zadanie 5.

Proszę napisać program, który załaduje plik graficzny, a następnie w sposób bezpośredni zmodyfikować wartości wczytanej tablicy, tak aby otrzymać: linię, poziomą, pionową. Proszę zmodyfikować dowolny piksel. W jaki sposób możemy interpretować wczytaną tablicę. Proszę przeprowadzić badania dla pliku kolorowego oraz pliku o odcieniach szarości.

Odpowiedź 5.

Na listingu 6 zaprezentowano program umożliwiający wczytanie obrazu, następnie modyfikację pikseli. Proszę zwrócić uwagę na funkcje split oraz merge oraz kolejność indeksów odpowiedzialnych z kolory B, G, R.


import cv2
img = cv2.imread('krajobraz.jpg')

#wartosc jednego piksela
px = img[100,100]
print(px)

# wartosc skladowej dla 0=b, 1=g, 2=r
blue = img[100,100,0]

#zapis konkretnego piksela
img[100:150,100] = [255,255,255];
img[100:150,300] = [0,0,255];

# wymiary obrazu
print(img.shape)

#wyodrebienie skladowych
b,g,r = cv2.split(img);

#polaczenie skladowych
img = cv2.merge((b,g,r));

cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

License

Projektowanie systemów wizyjnych Copyright © by Marcin Kołodziej. All Rights Reserved.

Share This Book