def find_start_end_points(self): self.temp_img = self.topo_map.image.copy() self.temp_img = cv2.resize(self.temp_img, None, fx=2 / 5, fy=2 / 5, interpolation=cv2.INTER_LINEAR) self.start = Point(-1, -1) self.end = Point(-1, -1) cv2.namedWindow("image") cv2.setMouseCallback("image", self.__click_image) cv2.imshow("image", self.temp_img) while (self.start.x < 0 or self.end.x < 0): k = cv2.waitKey(1000) & 0xFF cv2.imshow("image", self.temp_img) if k == ord('q') or k == ord(' '): break cv2.imshow("image", self.temp_img) self.start *= 5 / 2 self.end *= 5 / 2 self.find_cropped_image()
def __init__(self, cv_image): self.cv_image = cv_image self._image_masks = None self._contours = None self.start = Point(-1, -1) self.end = Point(-1, -1)
def find_cropped_image(start, end, topo_map, padding=500): # calculate padding needed for each point yPad = padding xPad = padding # crop image around start and end points with padding minY = max(min(start.y, end.y) - yPad, 0) maxY = min(max(start.y, end.y) + yPad, topo_map.height) minX = max(min(start.x, end.x) - xPad, 0) maxX = min(max(start.x, end.x) + xPad, topo_map.width) img = topo_map.image[minY:maxY, minX:maxX] # calculate start/end points for cropped image # width/height of cropped image width = maxX - minX height = maxY - minY # ratio of start/end points to cropped image size sxFactor = ((start.x - minX) / width) syFactor = ((start.y - minY) / height) exFactor = ((end.x - minX) / width) eyFactor = ((end.y - minY) / height) # init cropped_img for extracting contours, etc. cropped_img = CroppedImage(img) # use ratios to find scaled start/end points cropped_img.start = Point(int(sxFactor * width), int(syFactor * height)) cropped_img.end = Point(int(exFactor * width), int(eyFactor * height)) return cropped_img
def find_start_end_points(self, option=None): if option is None or len(option) == 0: self.user_settings.find_start_end_points() else: vals = option.split(',') # self.user_settings.start = Point(int(vals[0])+500, int(vals[1])+500) # self.user_settings.end = Point(int(vals[2])+500, int(vals[3])+500) self.user_settings.start = Point(int(vals[0]), int(vals[1])) self.user_settings.end = Point(int(vals[2]), int(vals[3])) self.user_settings.find_cropped_image()
def __get_direction_vector_to_point(self, from_point, to_point): direction = Point(to_point.x - from_point.x, to_point.y - from_point.y) if (abs(direction.x) >= 2 and abs(direction.y) >= 2) or abs( direction.x) > 2 or abs(direction.y) > 2: factor = max(min(abs(direction.x), abs(direction.y)), 1) direction.x = int(direction.x / factor) direction.y = int(direction.y / factor) return direction
def __get_nearest_density_point(self, start_point, direction): cur_point = start_point next_point = Point(cur_point.x + direction.x, cur_point.y + direction.y) while self.__density_between_points(cur_point, direction) == False: if self.__point_in_grid(next_point): cur_point = next_point next_point = Point(cur_point.x + direction.x, cur_point.y + direction.y) else: break return next_point
def __generate_successor_nodes_original(self, cur_node): point = cur_node.coord successors = [] # successors to the left x = point.x - 1 if x >= 0: lm = Node(Point(x, point.y), parent=cur_node) successors.append(lm) y = point.y - 1 if y >= 0: lt = Node(Point(x, y), parent=cur_node) successors.append(lt) y = point.y + 1 if y < self.grid.resolution_y: lb = Node(Point(x, y), parent=cur_node) successors.append(lb) # successors to the right x = point.x + 1 if x < self.grid.resolution_x: rm = Node(Point(x, point.y), parent=cur_node) successors.append(rm) y = point.y - 1 if y >= 0: rt = Node(Point(x, y), parent=cur_node) successors.append(rt) y = point.y + 1 if y < self.grid.resolution_y: rb = Node(Point(x, y), parent=cur_node) successors.append(rb) # top middle y = point.y + 1 if y < self.grid.resolution_y: mb = Node(Point(point.x, y), parent=cur_node) successors.append(mb) # bottom middle y = point.y - 1 if y > 0: mt = Node(Point(point.x, y), parent=cur_node) successors.append(mt) successors = self.__remove_invalid_nodes(successors) return successors
def __click_image(self, event, x, y, flags, param): if event == cv2.EVENT_LBUTTONUP: if self.cur_start_point is None: self.cur_start_point = Point(x, y) self.points.append(self.cur_start_point) cv2.circle(self.temp_img, (x, y), 5, (255, 0, 0), 2) else: self.cur_end_point = Point(x, y) self.points.append(self.cur_end_point) cv2.line(self.temp_img,\ (self.cur_start_point.x, self.cur_start_point.y),\ (self.cur_end_point.x, self.cur_end_point.y),\ (255,0,0),2) self.cur_start_point = self.cur_end_point cv2.circle(self.temp_img, (x, y), 5, (0, 0, 255), 2)
def __add_neighbor_points(self, point, distance, points): for x in range(point.x - distance, point.x + distance + 1): for y in range(point.y - distance, point.y + distance + 1): cur_point = Point(x, y) if self.__point_in_grid(cur_point): points[cur_point] = True
def find_path(self): points = self.__convert_pixel_points([ self.user_settings.cropped_img.start, self.user_settings.cropped_img.end ]) self.grid_start = Point(points[0].x, points[0].y) self.grid_end = Point(points[1].x, points[1].y) # print(self.grid_start) # print(self.grid_end) # print(self.__point_in_grid(self.grid_start)) # print(self.__point_in_grid(self.grid_end)) # print(self.grid.resolution_x) # print(self.grid.resolution_y) # print(self.grid.cell_width) return self.__calculate_path()
def __get_nearest_contour_point(self, start_point, direction): cur_point = start_point next_point = Point(cur_point.x + direction.x, cur_point.y + direction.y) # while self.__point_in_image(next_point): while self.__point_in_grid( self.grid.convert_pixel_to_grid_point(next_point)): if self.__contour_at_point( next_point) or self.__contour_in_between( cur_point, direction): return next_point cur_point = next_point next_point = Point(cur_point.x + direction.x, cur_point.y + direction.y) return None
def __init__(self): self.topo_map = None self.save_image = False # self.start = Point(350, 220) # self.end = Point(850, 700) # self.end = Point(1377, 772) self.start = Point(550, 435) self.end = Point(1873, 1081) self.cropped_img = None self.avoid_water = False self.avoid_forest = False self.max_grade = 30 self.cell_width = 30 self.node_method = NodeMethod.single_step
def __get_points_in_direction(self, cur_point, direction): points = [] if abs(direction.x) > 1: points.append( Point(cur_point.x + int(direction.x / 2), cur_point.y + direction.y)) points.append( Point(cur_point.x + int(direction.x / 2), cur_point.y + int(direction.y / 2))) elif abs(direction.y) > 1: points.append( Point(cur_point.x + int(direction.x / 2), cur_point.y + int(direction.y / 2))) points.append( Point(cur_point.x + direction.x, cur_point.y + int(direction.y / 2))) return points
def find_cropped_image(self, padding=700): # get max of width and height of points dist = max(abs(self.start.x - self.end.x), abs(self.start.y - self.end.y)) # calculate padding needed for each point yPad = padding #int((dist - abs(self.start.y - self.end.y)) / 2) + padding xPad = padding #int((dist - abs(self.start.x - self.end.x)) / 2) + padding # crop image around start and end points with padding minY = max(min(self.start.y, self.end.y) - yPad, 0) maxY = min(max(self.start.y, self.end.y) + yPad, self.topo_map.height) minX = max(min(self.start.x, self.end.x) - xPad, 0) maxX = min(max(self.start.x, self.end.x) + xPad, self.topo_map.width) img = self.topo_map.image[minY:maxY, minX:maxX] # calculate start/end points for cropped image # width/height of cropped image width = maxX - minX height = maxY - minY # ratio of start/end points to cropped image size sxFactor = ((self.start.x - minX) / width) syFactor = ((self.start.y - minY) / height) exFactor = ((self.end.x - minX) / width) eyFactor = ((self.end.y - minY) / height) # width/height of cropped and rescaled image width *= Helper.resize_factor height *= Helper.resize_factor # init cropped_img for extracting contours, etc. self.cropped_img = CroppedImage(img) # use ratios to find scaled start/end points self.cropped_img.start = Point(int(sxFactor * width), int(syFactor * height)) self.cropped_img.end = Point(int(exFactor * width), int(eyFactor * height))
def __get_next_point(self, cur_point, direction): points = self.__get_points_in_direction(cur_point, direction) if len(points) > 0: for p in points: if not self.__point_valid(p): return None next_point = Point(cur_point.x + direction.x, cur_point.y + direction.y) return next_point
def draw_route_in_pieces(self): h = self.image.shape[0] w = self.image.shape[1] max_h = 750 num = int(h / max_h) temp_image = self.image.copy() points = [] for i in range(num - 1): start = i * max_h end = start + max_h img, ps = self.draw_route(temp_image[start:end, :]) for p in ps: points.append(Point(p.x, p.y + start)) start = (num - 1) * max_h img, ps = self.draw_route(temp_image[start:, :]) for p in ps: points.append(Point(p.x, p.y + start)) first = True prev = None for p in points: cv2.circle(temp_image, (p.x, p.y), 5, (255, 0, 0), 2) if first: first = False else: cv2.line(temp_image, (prev.x, prev.y), (p.x, p.y), (255, 0, 0), 2) prev = p return temp_image, points
def set_boundary_points(self, node, distance): points = {} cur_point = node.coord cur_parent = node.parent while cur_parent is not None: next_point = cur_parent.coord direction = self.__get_direction_vector_to_point( cur_point, cur_parent.coord) temp_point = Point(cur_point.x, cur_point.y) while not temp_point == cur_parent.coord: self.__add_neighbor_points(temp_point, distance, points) temp_point.x += direction.x temp_point.y += direction.y cur_point = next_point cur_parent = cur_parent.parent self.__add_neighbor_points(cur_point, distance, points) self.boundary_points = points
def __generate_successor_nodes(self, cur_node): # variable names indicate top, middle, bottom -> left, middle, right -> (optional) left, middle, right, top, bottom # ie: the locations around cur_node upto two cells away, roughly every 22 degrees tl = Point(-1, -1) tlr = Point(-1, -2) tm = Point(0, -1) tr = Point(1, -1) trl = Point(1, -2) ml = Point(-1, 0) mlt = Point(-2, -1) mlb = Point(-2, 1) mr = Point(1, 0) mrt = Point(2, -1) mrb = Point(2, 1) bl = Point(-1, 1) blr = Point(-1, 2) bm = Point(0, 1) br = Point(1, 1) brl = Point(1, 2) #all_directions = [tl, tlr, tm, tr, trl, ml, mlt, mlb, mr, mrt, mrb, bl, blr, bm, br, brl] directions = [tl, tm, tr, ml, mr, bl, bm, br] successors = [] # for direction in all_directions: for direction in directions: successors.append(self.__get_node(cur_node, direction)) # successors = list(map(lambda x: self.__get_node(cur_node, x), all_directions)) # successors = list(map(lambda x: self.__get_node(cur_node, x), directions)) return list( filter(lambda x: x is not None and self.__point_within_boundary(x), successors))
route_image, points = get_drawn_route(start, end, topo_map) path = "images/" + topo_map.filename[5:-4] + "/" + points_to_path_string( start, end) + "/drawn" if not os.path.exists(path): os.makedirs(path) num = len([x for x in os.listdir(path)]) + 1 cv2.imwrite(path + '/drawn' + str(int(num / 2)) + '.png', route_image) out = open(path + "/data" + str(int(num / 2)) + '.csv', 'w') t = input("enter completion time:") m = input("enter mile length:") n = input("enter initial:") out.write("x,y," + str(t) + ',' + str(m) + ',' + str(n) + "\n") for p in points: out.write(str(p.x) + "," + str(p.y) + "\n") out.close() if __name__ == "__main__": topo_map = TopographicMap("maps/SanLuisObispo.jpg") start = Point(550, 435) end = Point(1873, 1081) get_drawn_route(start, end, topo_map)