Na początku zajmijmy się opracowaniem prostej metody, która będzie miała na celu zalezienie w podanej przez nas palecie koloru najbliższego dla wartości piksela, który aktualnie analizujemy. Naszą funkcję będziemy wstępnie opracowywać dla danych testowych, zakładamy, że nasze dane są dostarczane w formacie float
\(<0,1>\). Na początek zadeklarujmy sobie naszą wstępną paletę zawierającą \(N\) wartości:
= np.linspace(0,1,N).reshape(N,1)
paleta print(paleta) #można usunać
Po wywołaniu tego fragmentu kodu mamy dostępny kolumnowy wektor N-elementowy, zawierający wartości z zakresu naszego koloru. Jeżeli chcecie zmienić zakres na uint8
to trzeba przesunąć górną granicę zmiennej oraz zrzutować całość na uint8
. Na początek ustawmy sobie \(N=3\). Jakie mamy wartości w naszej palecie?
Zacznijmy od zadeklarowania naszej funkcji:
def colorFit(pixel,Pallet):
pass
Nasza funkcja nie będzie potrzebowała do działania żadnych pętli i będzie działała niezależnie od ilości kolorów (tak długo, jak ilość kolorów pikseli i palety będzie taka sama). Zacznijmy od omówienia podejścia:
Zakładamy, że traktujemy nasze kolory jako punkty w przestrzeni. Żeby policzyć, który z tych punktów z palety jest najbliżej naszego piksela, potrzebujemy odległości między nimi. Odległość ta jest długością wektora pomiędzy nimi. Z matematyki powinniście wiedzieć, że aby stworzyć wektor pomiędzy dwoma punktami i od razu przesunąć jego początek do centrum osi współrzędnych, to należy odjąć jeden punkt od drugiego. Nasze środowisko NumPy daje nam możliwość wykonania tej operacji od razu dla całej tablicy. Co dostajemy poniżej:
print(Pallet-pixel)
Dla przypadku jednowymiarowego, czyli palety dla obrazu w skali odcieni szarości mamy już dostateczną ilość informacji, ale nasza funkcja ma działać w sposób kompleksowy, czyli dla wszystkich ilości kolorów. Dlatego potrzebujemy wyliczyć odległość pomiędzy naszymi kolorami do tego celu najlepiej wykorzystać funkcję liczącą odległość euklidesową dla naszego wektora:
=1) np.linalg.norm(?,axis
Na tej podstawie bez względu ile mamy kolorów (skala odcieni szarości, RGB, CMYK itd.) na tym etapie będziemy dysponować wektorem wartości. Teraz musimy znaleźć najmniejszą wartość w naszym wektorze. Do tego celu sugeruję wykorzystać poniższą funkcję.
np.argmin()
Jeżeli wykorzystacie powyższe funkcje, to cała funkcja może składać się z 1 linii (maksymalnie 3) i działać dla dowolnej ilości kolorów (o ile ilość kolumn będzie równa ilości warstw). Poniżej kilka przykładów działania:
= np.linspace(0,1,3).reshape(3,1)
paleta print(colorFit(0.43,paleta)) # 0.5
print(colorFit(0.66,paleta)) # ?
print(colorFit(0.8,paleta)) # ?
Przedefiniowane palety kolorów
Paleta 8 kolorów ([R, G, B]):
= np.array([
pallet8 0.0, 0.0, 0.0,],
[0.0, 0.0, 1.0,],
[0.0, 1.0, 0.0,],
[0.0, 1.0, 1.0,],
[1.0, 0.0, 0.0,],
[1.0, 0.0, 1.0,],
[1.0, 1.0, 0.0,],
[1.0, 1.0, 1.0,],
[ ])
Paleta 16 kolorów [web safe] ([R, G, B]):
= np.array([
pallet16 0.0, 0.0, 0.0,],
[0.0, 1.0, 1.0,],
[0.0, 0.0, 1.0,],
[1.0, 0.0, 1.0,],
[0.0, 0.5, 0.0,],
[0.5, 0.5, 0.5,],
[0.0, 1.0, 0.0,],
[0.5, 0.0, 0.0,],
[0.0, 0.0, 0.5,],
[0.5, 0.5, 0.0,],
[0.5, 0.0, 0.5,],
[1.0, 0.0, 0.0,],
[0.75, 0.75, 0.75,],
[0.0, 0.5, 0.5,],
[1.0, 1.0, 1.0,],
[1.0, 1.0, 0.0,]
[ ])
Co tu powinno się zwrócić?
print(colorFit(np.array([0.25,0.25,0.5]),pallet8))
print(colorFit(np.array([0.25,0.25,0.5]),pallet16))
Wykorzystanie funkcji colorFit
do kwantyzacji obrazu
Do wykorzystania funkcji colorFit
do kwantyzacji obrazu potrzebujemy dwie pętle po wierszach i po kolumnach. Dzięki właściwościom Python i NumPy nie potrzeba dodawać 3 pętli po warstwach, gdyż domyślnie zostaną one przekazane jako tablica.
def kwant_colorFit(img,Pallet):
= img.copy()
out_img for w in range():
for k in range():
=colorFit(img[w,k],Pallet)
out_img[w,k]return out_img