Jak widzieliśmy razem w materiale, http://analityk.edu.pl/czym-jest-obraz-dla-komputera/ pokazany był obraz człowieka z czerwoną różą na czarno-białym tle.

 

.

 

 

.

 

W tym materiale przedstawiony będzie proces doprowadzający do powyższego efektu.

 

Jeśli nie masz jeszcze zainstalowanej biblioteki OpenCV bardzo łatwo to zrobić, wystarczy w Terminalu, bądź Anaconda prompt (jeśli korzystasz z Anacondy):

 

 

Wpisać komendę:

 

pip install opencv-python

 

Co tak naprawdę widać na obrazku?

 

Wczytajmy bibliotekę OpenCV oraz pomocniczo numpy:

 

import cv2
import numpy as np

 

Wczytajmy zdjęcie i zmieńmy reprezentacje na HSV:

 

img = cv2.imread('D:\Biznes\Analityk.edu.pl\kolory\Red-rose.jpg')

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

 

metoda cv2.cvtColor pozwala na zmianę reprezentacji koloru z RGB ( dla przypomnienia jest to mix czerwonego, zielonego oraz niebieskiego, polecam szczegóły w artykule poprzedzającym) na reprezentacje HSV ( odcień, nasycenie, jasność)

 

Aby zobaczyć, jak wygląda każdy z kanałów należy skorzystać z funkcji cv2.split:

 

h,s,v = cv2.split(hsv)

cv2.imshow('odcień', h)
cv2.imshow('nasycenie', s)
cv2.imshow('jasność', v)

cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

Aby oddzielić kolorową różę od obrazka należy stworzyć MASKę, czyli swoiste sitko przez które przelejemy kolorowy obrazek i zostanie nam tylko czerwona róża.

 

.

 

 

.

 

Najbardziej oczywistym sposobem patrząc na obrazek oryginalny byłoby wydzielenie odcienia czerwonego czyli w tej reprezentacji koloru czerwonego 170-179 w odcieniu, pozostawiając saturacje i jasność od 0 do 255.

 

# mask
lower_red = np.array([170,0,0])
upper_red = np.array([179,255,255])
mask0 = cv2.inRange(hsv, lower_red, upper_red)

cv2.imshow('mask', mask0)

cv2.waitKey(0)
cv2.destroyAllWindows()

 

Robiąc maskę korzystając z tego podejścia otrzymujemy poniższy obrazek.

 

maska odcienia koloru czerwonego

 

Widzieliśmy natomiast, że w kanale saturacji mamy dużą szanse na jednoznaczne wydzielenie róży od reszty obiektów z obrazka gdyż ma dużo większą saturacje (kolor biały).

 

W tym celu możemy stworzyć MASKę przez określenie wartości saturacji od 165 do 255 (wartość maksymalna, biel na obrazie), oraz ustawienie odcienia i jasności na pełen zakres – odcień 0-179, jasność 0-255.

 

# mask
lower_red = np.array([0,165,0])
upper_red = np.array([179,255,255])
mask0 = cv2.inRange(hsv, lower_red, upper_red)

 

Aby wyświetlić maskę korzystamy z funkcji cv2.imshow:

 

cv2.imshow('mask', mask)

cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

Jak widać nie wystarczyło to na jednoznaczne wydzielenie róży, gdyż podobne nasycenie jest też częścią liści oraz tło. Natomiast wiemy, że zarówno liście jak i tło nie posiada czerwonego koloru nasycenia.

 

Żadne z tych pojedynczych rozwiązań nie daje nam oczekiwanego efektu, natomiast moglibyśmy je połączyć.

 

# mask
lower_red = np.array([170,165,0])
upper_red = np.array([179,255,255])
mask0 = cv2.inRange(hsv, lower_red, upper_red)

cv2.imshow('mask', mask0)

cv2.waitKey(0)
cv2.destroyAllWindows()

 

Otrzymamy wtedy poniższy efekt:

 

 

Ostatecznym krokiem jest rozszerzenie zakresu i odcięcie niepotrzebnych resztek, najlepszym sposobem jest metoda prób i błędów przez połączenie dwóch takich masek :

 

# lower mask (0-10)
lower_red = np.array([0,165,50])
upper_red = np.array([10,255,255])
mask0 = cv2.inRange(hsv, lower_red, upper_red)

# upper mask (170-180)
lower_red = np.array([170,165,50])
upper_red = np.array([179,255,255])
mask1 = cv2.inRange(hsv, lower_red, upper_red)

# join my masks
mask = mask0+mask1

 

.

 

 

.

 

Przygotowujemy obrazek czarno biały:

 

im_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

#musimy przetłumaczyć obrazek czarno-biały na 3 kanały ale #już w kolorach szarości

im_gray3=cv2.cvtColor(im_gray, cv2.COLOR_GRAY2BGR)

 

 

Następnie odwracamy maskę oraz obrazek szarości

 

mask=cv2.bitwise_not(mask)
im_gray3=cv2.bitwise_not(im_gray3)

 

 

Ostatnim krokiem jest połączenie obrazka czarno-białego z obrazkiem kolorowym oraz maską:

 

im_red = cv2.bitwise_not(im_gray3, img,  mask=mask)

 

Na końcu otrzymujemy taki oto efekt:

 

cv2.imshow('output', im_red)

 

.

 

 

.

 

Aby zapisać obrazek korzystamy z metody cv2.imwrite

 

cv2.imwrite('D:\Biznes\Analityk.edu.pl\kolory\only_rose.png', im_red)