def detect(self, image): """ Find the object's new position in image, using current model M """ # Convert to grayscale image = np.sum(image, 2) / 3 patch = crop_patch(image, self.region) P = fft2(MOSSETrackerGrayscale.normalize(patch)) response = ifft2( np.conjugate(self.M) * P ) r, c = np.unravel_index(np.argmax(response), response.shape) # Keep for visualisation self.last_response = response r_offset = np.mod(r + self.region_center[0], self.region.height) - self.region_center[0] c_offset = np.mod(c + self.region_center[1], self.region.width) - self.region_center[1] self.region.xpos += c_offset self.region.ypos += r_offset # Revert update if bbox is completely out of image if self.region.intersection_box(BoundingBox("tl-size", 0, 0, image.shape[1], image.shape[0])).area() == 0.0: self.region.ypos -= r_offset self.region.xpos -= c_offset return self.region
def test_crop_shape(): from cvl.image_io import crop_patch from cvl.dataset import BoundingBox import numpy as np img = np.random.uniform(size=(1200, 600)) region = BoundingBox('tl-size', 50, 60, 100, 200) crop = crop_patch(img, region) assert crop.shape == region.shape()
def test_crop_pad_value_negative(): from cvl.image_io import crop_patch from cvl.dataset import BoundingBox import numpy as np img = np.random.uniform(size=(1200, 600)) region = BoundingBox('tl-size', -1, 0, 100, 75) crop = crop_patch(img, region) assert crop[0, 0] == 0
def test_crop_region(): from cvl.image_io import crop_patch from cvl.dataset import BoundingBox import numpy as np img = np.random.uniform(size=(1200, 600)) region = BoundingBox('tl-size', 60, 50, 100, 200) crop = crop_patch(img, region) assert crop[0, 0] == img[region.ypos, region.xpos] assert crop[-1, -1] == img[region.ypos + region.height - 1, region.xpos + region.width - 1]
def update(self, image): """ Re-fit model M using new object position found in self.region (from detection step) """ # Convert to grayscale image = np.sum(image, 2) / 3 patch = crop_patch(image, self.region) normalized_patch = MOSSETrackerGrayscale.normalize(patch) C = MOSSETrackerGrayscale.get_fourier_transformed_gaussian(height=self.region.height, width=self.region.width, std=self.std, mean_x=0, mean_y=0) P = fft2(normalized_patch) self.A = self.A * (1-self.learning_rate) + np.conjugate(C) * P * self.learning_rate self.B = self.B * (1-self.learning_rate) + np.conjugate(P) * P * self.learning_rate self.M = self.A / self.B return normalized_patch
def start(self, image, region): """ Construct initial model (=filter) in fourier domain using provided region in image """ # Convert to grayscale image = np.sum(image, 2) / 3 # Where the gaussian should be centered self.region = region self.region_center = (region.height // 2, region.width // 2) C = MOSSETrackerGrayscale.get_fourier_transformed_gaussian(height=region.height, width=region.width, std=self.std, mean_x=0, mean_y=0) patch = crop_patch(image, region) P = fft2(MOSSETrackerGrayscale.normalize(patch)) self.A = np.conjugate(C) * P self.B = np.conjugate(P) * P self.M = self.A / self.B
def crop_patch(self, image): region = self.region return crop_patch(image, region)