Szükséges importálások. A time csomag az időméréshez kell.
import cv2
import time
Kép, maszk és maszk körvonal beolvasása.
img = cv2.imread('car_numberplate_rs.jpg', cv2.IMREAD_COLOR)
mask = cv2.imread('car_numberplate_rs_mask.png', cv2.IMREAD_COLOR)
edge = cv2.imread('car_numberplate_rs_mask_edge.png', cv2.IMREAD_GRAYSCALE)
Képmátrix méretek ellenőrzése. Az assert után egy feltételt adhatunk meg. Ha az nem teljesül, akkor a program futása hibaüzenttel megszakad. A shape attribútum első két elemét nézzük, ami a sorok és oszlopok számát veszi csak figyelembe.
assert img.shape[0:2] == mask.shape[0:2]
assert img.shape[0:2] == edge.shape[0:2]
Kép és maszk megjelenítése.
cv2.imshow('img', img)
cv2.imshow('mask', mask)
Színes képen a maszkon kívüli terület kinullázása és megjelenítése. Mivel a feltételezzük, hogy a maszk kép csak 0 és 255 értékeket tartalmaz, a logikai ÉS művelet a maszkon belüli, vagyis a 255 értékkel fedésbe kerülőket tartja meg, a többit nullázza. Megjegyezzök, hogy Numpy feltételes indexeléssel is megoldhattuk volna, gyakorlásként választottuk most a logikai bitműveletet.
masked = cv2.bitwise_and(img, mask)
cv2.imshow('masked', masked)
cv2.waitKey(0)
Eredeti színes képen a maszkon belüli rész fehér színűre változtatása Numpy feltételes indexeléssel.
img_roi = img.copy()
img_roi[mask > 0] = 255
cv2.imshow('img_roi', img_roi)
cv2.waitKey(0)
Vörös színű maszk körvonal elhelyezése az eredeti képen. Először Numpy feltéletes indexelést használunk. Vegyük észre, hogy nem elegendő a vörös csatornára értéket írni, a másik kettő kinullázása is szükséges a korrket vörös szín előállításához! A megoldást időméréssel látjuk el.
img_np_edge = img.copy()
start_time = time.perf_counter()
img_np_edge[edge > 0] = [0, 0, 255]
end_time = time.perf_counter()
print('Numpy élrajzolás:', (end_time - start_time) * 1000.0, "ezredmásodperc.")
cv2.imshow('img_np_edge', img_np_edge)
cv2.waitKey(0)
Második megközelítésként kettős for ciklussal bejárjuk a maszkot, a 255 értékek helyén az eredeti képmátrixban vörös színt állítunk be. A ciklust időméréssel látjuk el.
img_edge = img.copy()
start_time = time.perf_counter()
for y in range(0, img.shape[0]):
for x in range(0, img.shape[1]):
if edge[y, x] > 0:
img_edge[y, x] = [0, 0, 255]
end_time = time.perf_counter()
print((end_time - start_time) * 1000.0, "ezredmásodperc.")
cv2.imshow('img_edge', img_edge)
cv2.waitKey(0)
Vörös színű körvonal rávetítés OpenCV logikai függvényekkel, időméréssel. A működésének a lényege, hogy az eredeti BGR képet csatornákra bontjuk, a vörös csatornába a VAGY művelettel beégetjük a vörös körvonalat (ahol a maszk körvonal kép 255 értékű, ott a vörös csatorna is ezt az értéket veszi fel, ahol a körvonal 0 értékű, ott megmarad az eredetileg ott szereplő érték), a másik két csatornán nullázzuk ugyanezen helyeket (a ~ operátor a bitenkénti negálás, vagyis ellentettre fordítás, ezzel ÉS-elve kapjuk a körvonal pontokban a nulla eredményt).
img_ocv_edge = img.copy()
start_time = time.perf_counter()
b, g, r = cv2.split(img_ocv_edge)
r = cv2.bitwise_or(r, edge)
g = cv2.bitwise_and(g, ~edge)
b = cv2.bitwise_and(b, ~edge)
img_ocv_edge = cv2.merge((b, g, r))
end_time = time.perf_counter()
print((end_time - start_time) * 1000.0, "ezredmásodperc.")
cv2.imshow('img_ocv_edge', img_ocv_edge)
cv2.waitKey(0)
Program szabályos lezárása.
cv2.destroyAllWindows()
A program a laptopon futtatva az alábbi időmérési eredményeket adta. A Numpy és az OpenCV megoldás nagyjából 4 és 9 ezredmásodperc alatt lefutott. Az egymásba ágyazott for ciklusokkal bejárt kép esetén ez 1,2 másodperc (a Numpy 283-szor gyorsabb!), és használat közben érezhetően várni kell az eredményre. Pedig nem is nagy a bemeneti kép mérete.
Numpy élrajzolás: 4.24610000000003 ezredmásodperc.
Élrajzolás for ciklusokkal: 1202.1564000000003 ezredmásodperc.
OpenCV élrajzolás: 8.807400000000243 ezredmásodperc.