Python implementace - Sliding window

Vydáno:

Jiří Kupka

Častou úlohou ve zpracování a analýze obrazu je detekce zájmových objektů na fotografii (snažíme se najít místo, kde leží obličej, zjistit, zda se na fotografii nachází motorka atd.), což je většinou obtížné zařídit tak, že detektoru předložíme celý obraz najednou. Často si volíme nějaké okénko, výřez aktuální fotografie, a zkoumáme, jestli se hledaný objekt nenachází právě v tomto okénku. Při inicializaci si zvolíme minimální velikost okénka a to posouváme s definovaným krokem od levého horního rohu fotografie až k pravému dolnímu. Až okénko dorazí na konec fotografie, mírně ho zvětšíme a celý proces opakujeme dokud výřez nenabyde maximální možné velikosti, která ještě dává smysl.

Celá implementace níže je vcelku jednoduchá. Instance třídy SlidingWindow funguje jako iterátor a každý průchod cyklem vrací jeden výřez. Jako dodatečné informace vrací aktuální stav okénka. Ve slovníku self.window je jeho základní nastavení, které je možné přepsat klíčovými parametry při vzniku objektu. Třídu níže je možné si podle libosti upravit - například nastavit pevný krok oproti vypočtenému apod.

import cv2
 
class SlidingWindow:
 
	def __init__(self, img, **kwargs):
		self.img = img
 
		self.window = {
			'x': 0,
			'y': 0,
			'width': 64,
			'height': 64,
			'scale_factor': 1.1,
			'stride_factor': 0.1,
			'max_width': 256,
			'max_height': 256
		}
 
		self.window.update(kwargs)
 
 
	def scale(self):
		self.window['width'] = int(self.window['scale_factor']*self.window['width'])
		self.window['height'] = int(self.window['scale_factor']*self.window['height'])
 
 
	def move(self):
		self.window['x'] += int(self.window['width']*self.window['stride_factor'])
 
		if self.window['x'] > self.img.shape[1]-self.window['x']:
			self.window['x'] = 0
			self.window['y'] += int(self.window['height']*self.window['stride_factor'])
 
		if self.window['y'] > self.img.shape[0]-self.window['y']:
			self.window['y'] = 0
			self.window['x'] = 0
 
			self.scale()
 
		if self.window['width'] >= self.window['max_width'] or self.window['height'] >= self.window['max_height']:
			return False
 
		return True
 
 
	def __iter__(self):
		return self
 
 
	def next(self):
		window = self.window
		piece = self.img[window['y']:window['y']+window['height'],window['x']:window['x']+window['width']]
 
		if self.move():
			return (piece, window)
		else:
			raise StopIteration()
 
 
img = cv2.imread("landscape.jpg")
parts = SlidingWindow(img, width=48, height=48)
 
for part, window_data in parts:
	cv2.imshow("window", part)
	cv2.waitKey(0)