def __init__(self, stitcher_controller): self.algorithm_scheduler = algorithm_scheduler.AlgorithmScheduler() self.running_algorithms = set() self.algo_lock = threading.RLock() self.extract_output_list = vs.ExtractOutputPtrVector() self.extract_output_managed = [] for i in range(stitcher_controller.getPano().numInputs()): input = stitcher_controller.getPano().getInput(i) if not input.getIsVideoEnabled(): continue surf = vs.OffscreenAllocator_createSourceSurface( input.width, input.height, "Algorithm") if not surf.ok(): raise errors.AlgorithmError( 'Cannot run algorithm:' + str(surf.status().getErrorMessage())) dontmemleak = vs.sourceSurfaceSharedPtr(surf.release()) # SWIG create a proxy object with an empty deleter # when passing directly the pointer to the vector object :( # DON'T TRY TO FACTORIZE THE PREVIOUS LINE OR MEMLEAK extract_output = stitcher_controller.createBlockingExtractOutput( i, dontmemleak, None, None) if not extract_output.status().ok(): raise errors.AlgorithmError("Cannot create AsyncExtractOutput") # To preserve ownership over outputs self.extract_output_managed.append(extract_output) self.extract_output_list.push_back(extract_output.object()) self._connect_signals()
def stretch_so_it_looks_like(self, other): if self.facing in [DIR_UP, DIR_DOWN]: u = self.x_to_range().union_if_match(other.x_to_range()) if not u: raise errors.AlgorithmError('This shouldn\'t be possible') return Edge(self.facing, self.y0, u.p0, self.y0, u.p1) else: u = self.y_to_range().union_if_match(other.y_to_range()) if not u: raise errors.AlgorithmError('This shouldn\'t be possible') return Edge(self.facing, u.p0, self.x0, u.p1, self.x1)
def different_endpoint(self, point): if self.facing in [DIR_UP, DIR_DOWN]: assert self.y0 == self.y1 == point.y if self.x0 == point.x: return Point(self.y0, self.x1) elif self.x1 == point.x: return Point(self.y0, self.x0) else: raise errors.AlgorithmError('Not one of my endpoints') else: assert self.x0 == self.x1 == point.x if self.y0 == point.y: return Point(self.y1, self.x0) elif self.y1 == point.y: return Point(self.y0, self.x0) else: raise errors.AlgorithmError('Not one of my endpoints')
def get_move(self, dir, y, x): m = self.turn_left(dir, y, x) if m: return m[0], m[1], m[2] m = self.go_forward(dir, y, x) if m: return m[0], m[1], m[2] m = self.turn_right(dir, y, x) if m: return m[0], m[1], m[2] raise errors.AlgorithmError('Stuck, cannot move at %sy, %sx' % (y, x))
def distance_from(self, other): if isinstance(other, Edge): if self.facing in [other.facing, opposite_dir(other.facing)]: other = other.get_endpoints()[0] else: raise errors.AlgorithmError('Cannot get distance from misaligned edges') if self.facing == DIR_UP: return self.y0 - other.y elif self.facing == DIR_RIGHT: return other.x - self.x0 elif self.facing == DIR_DOWN: return other.y - self.y0 elif self.facing == DIR_LEFT: return self.x0 - other.x
def side_between(self, first, second, rotate_clockwise): if first.facing != opposite_dir(second.facing): raise errors.AlgorithmError('Side direction mismatch!') if rotate_clockwise: dir = rotate_dir_cw(first.facing) else: dir = rotate_dir_counter_cw(first.facing) if first.facing in DIR_UP: # +---+ # cc | | rc # | | # | | y0, y1 = first.y0, second.y0 if rotate_clockwise: # right-hand side from the top and bottom x0 = x1 = first.x1 else: # left-hand side from the top and bottom x0 = x1 = first.x0 elif first.facing == DIR_RIGHT: x0, x1 = second.x0, first.x0 if rotate_clockwise: # bottom side from the right and left y0 = y1 = first.y1 else: # top side from the right and left y0 = y1 = first.y0 elif first.facing == DIR_DOWN: # | | # | | # rc | | cc # +---+ y0, y1 = second.y0, first.y0 if rotate_clockwise: # left-hand side from the bottom and top x0 = x1 = first.x0 else: # right-hand side from the bottom and top x0 = x1 = first.x1 elif first.facing == DIR_LEFT: x0, x1 = first.x0, second.x0 if rotate_clockwise: # bottom side from the right and left y0 = y1 = first.y0 else: # top side from the right and left y0 = y1 = first.y1 return geometry.Edge(dir, y0, x0, y1, x1)
def get_algo_output(self, panorama): # Todo: investigate OnlineAlgorithm opaque pointer (shared calibration context? / last parameter) # Clone a panorama and acquire ownership. self.panorama = panorama.clone() self.panorama.thisown = 1 self._update_config(panorama) self.online_algorithm = vs.OnlineAlgorithm_create(self.config_name, self.config.to_config()) if not self.online_algorithm.status().ok(): CLIENT_MESSENGER.send_error( errors.AlgorithmError("Online algorithm \"{}\" creation failed".format(self.config_name))) return None self.listener_wrapper = vs.AlgorithmListenerGIL(self.this) self.algorithm_output = vs.AlgorithmOutput(self.online_algorithm.release(), panorama, vs.toListener(self.listener_wrapper.this), None) return self.algorithm_output
def add(self, dir, point_y, point_x, next_dir): self.count += 1 if self.count >= 128: raise errors.AlgorithmError('loop detected at y=%s, x=%s' % (point_y, point_x)) # Adjust if dir == DIR_DOWN: point_x += 1 if dir == DIR_LEFT: point_y += 1 if next_dir == DIR_DOWN: point_x += 1 elif next_dir == DIR_LEFT: point_y += 1 # Edge edge = geometry.Edge(rotate_dir_cw(dir), self.curr_y, self.curr_x, point_y, point_x) self.edges.append(edge) # Vertex kind = 'convex' if next_dir == rotate_dir_cw(dir) else 'reflex' self.vertices.append( geometry.Vertex(kind, point_y, point_x, len(self.vertices))) # Border if point_y < self.min_y: self.min_y = point_y if point_y > self.max_y: self.max_y = point_y if point_x < self.min_x: self.min_x = point_x if point_x > self.max_x: self.max_x = point_x # Done? self.curr_y = point_y self.curr_x = point_x if point_y == self.start_y and point_x == self.start_x: first = self.vertices[-1] self.vertices = [first] + self.vertices[:-1] return True
def common_endpoint(self, other): ys = set([self.y0, self.y1]).intersection([other.y0, other.y1]) xs = set([self.x0, self.x1]).intersection([other.x0, other.x1]) if len(ys) == 1 and len(xs) == 1: return Point(list(ys)[0], list(xs)[0]) raise errors.AlgorithmError('No common endpoint found')