def add_edges2pixel(self, frame_num, x, y): # bounds centered window around pixel lower = int(-math.floor(self.window / 2)) upper = int(math.floor(self.window / 2)) # iterated through the neighbours in next frame and add edges # provided neighbour does exist, if not create dummy neighbour and edge for j in range(lower, upper + 1, 1): for i in range(lower, upper + 1, 1): if x + i >= 0 and x + i < self.shape_frame[ 0] and y + j >= 0 and y + j < self.shape_frame[1]: # add from earlier to later pixel # self.g.add_edge(self.g.vertex(pixel2id(self.shape_frame, frame_num, x , y)), self.g.vertex(pixel2id(self.shape_frame, frame_num+1, x +i, y + j))) # add from later to earlier pixel self.g.add_edge( self.g.vertex( pixel2id(self.shape_frame, frame_num + 1, x, y)), self.g.vertex( pixel2id(self.shape_frame, frame_num, x + i, y + j))) else: # add dummy node to graph and connect it to pixel, so that there are always window**2 many edges from every 'real' pixel # the dummy pixels will have and index higher than the one of the sink # the resulting graph with have more nodes and more edges than expected. self.g.add_edge( self.g.vertex( pixel2id(self.shape_frame, frame_num + 1, x, y)), self.g.add_vertex())
def build(self): # instanciate a graph with all but the last node self.g = Graph() self.vertices = self.g.add_vertex(self.num_real_pixels - 1) # insert sink with edges to it self.t = self.g.add_vertex() for x in range(self.shape_frame[0]): for y in range(self.shape_frame[1]): # add to sink #e = self.g.add_edge(self.g.vertex(pixel2id(self.shape_frame, self.num_frames -1, x, y)), self.t) # add edges from sink e = self.g.add_edge( self.t, self.g.vertex( pixel2id(self.shape_frame, self.num_frames - 1, x, y))) # add edges from all vertices to the ones in the next frame for v in self.g.vertices(): # is vertext not on last frame if int(v) + self.shape_frame[0] * self.shape_frame[ 1] < self.num_real_pixels - 1: frame_num, x, y = id2pixel(int(v), self.shape_frame) self.add_edges2pixel(frame_num, x, y) # print status, once a frame is connected if int(v) % (self.shape_frame[0] * self.shape_frame[1]) == 0 and int(v) > 0: print('Frame ' + str(int(v) // (self.pixel_per_frame)) + ' connected.')
def add_edges2pixel(graph, shape_frame, frame_num, x, y, window): # window size must be odd assert window % 2 == 1 lower = int(-math.floor(window / 2)) upper = int(math.floor(window / 2)) for i in range(lower, upper + 1, 1): for j in range(lower, upper + 1, 1): if x + i >= 0 and x + i < shape_frame[0]: if y + j >= 0 and y + j < shape_frame[1]: # add from earlier to later pixel # graph.add_edge(graph.vertex(pixel2id(shape_frame, frame_num, x , y)), graph.vertex(pixel2id(shape_frame, frame_num+1, x +i, y + j))) # add from later to earlier pixel graph.add_edge( graph.vertex(pixel2id(shape_frame, frame_num + 1, x, y)), graph.vertex( pixel2id(shape_frame, frame_num, x + i, y + j)))
def all_paths_generator(self): # iterate over entire frame for x in range(len(mask_f)): for y in range(len(mask_f[0, :])): # vertex that iterates along the path v = self.g.vertex(pixel2id(self.shape_frame, 0, x, y)) # while we have not reached the first node (t), go to # predecessor and remember the edges we passed path = [] while self.pred_map[v] != self.num_real_pixels - 1: path.append(self.g.edge(self.pred_map[v], v)) v = self.pred_map[v] # obatin coodinates to pixel on last frame _, v_x, v_y = id2pixel(int(v), self.shape_frame) yield path, v_x, v_y
def update_costs(g, pred_map, frame_0, frame_l): loss = 0 hit = 0 not_hit = 0 # iterate over entire frame for x in range(len(frame_0)): for y in range(len(frame_0[0, :])): # only paths from pixels in BB matter if np.all(frame_0[x, y] == 1): # vertex that iterates along the path v = g.vertex(pixel2id(frame_0.shape, 0, x, y)) # while we have not reached the first node (t), go to # predecessor and remember the edges we passed path = [] while pred_map[v] != g.num_vertices() - 1: path.append(g.edge(pred_map[v], v)) v = pred_map[v] # obatin coodinates to pixel on last frame _, v_x, v_y = id2pixel(int(v), frame_l.shape) # depedning on whether path lands in BB or not, # update edge costs on path and loss length = len(path) if np.all(frame_l[v_x, v_y] == 1): f = 0 hit += 1 loss -= 1 for e in path: f += 1 factor = f / length g.ep.cost[e] -= 2 * f / length else: f = 0 not_hit += 1 loss += 1 for e in path: f += 1 g.ep.cost[e] += 2 * f / length return loss, hit, not_hit
#graph_draw(g) # print out neighbours for a test pixel #for v in g.vertex(pixel2id(frames.dims,1, 1,2)).out_neighbors(): #< print(id2pixel(int(v), frames.dims)) # create edge property for edge costs eprop = g.new_edge_property("double") g.ep.cost = eprop # equivalent to g.vertex_properties["foo"] = vprop # randomly set edge costs g.ep.cost.a = 2 * np.random.random(g.num_edges()) - 1 # print some edge costs as test #for e in g.vertex(pixel2id(frames.dims,1, 1,2)).out_edges(): # print(g.ep.cost[e]) # insert sink with edges to it and add set edge costs to 0 t = g.add_vertex() for x in range(frames.dims[0]): for y in range(frames.dims[1]): # add to sink #e = g.add_edge(g.vertex(pixel2id(frames.dims, frames.n_frames-1, x, y)), t) # add edges from sink e = g.add_edge( t, g.vertex(pixel2id(frames.dims, frames.n_frames - 1, x, y))) g.ep.cost[e] = 0 learn_costs(g, frames.frames[0], frames.frames[frames.n_frames - 1], 100)