def detect_building(self): # Get the x_click,y coordinates of the click x_click, y_click = geolocation.deg_to_tilexy_matrix(self.lat, self.long, self.zoom) # find xtile, ytile xtile, ytile = geolocation.deg_to_tile(self.lat, self.long, self.zoom) if self.first: # writes the pre_image before any changes cv2.imwrite('detectors/runtime_images/pre_image.png', self.image) print("running flood fill on existing image") flood_fill = FloodFill(self.image, x_click, y_click, self.THRESHOLD) flood_fill_image, message = flood_fill.flood_fill() cv2.imwrite('detectors/runtime_images/flood_fill_multi_click.png', flood_fill_image) print("ran flood fill") cropped_image = flood_fill.crop_image() cv2.imwrite('detectors/runtime_images/flood_fill_display.png', cropped_image) print('cropped image') edge_image, total_edge_list = flood_fill.find_edges() cv2.imwrite('detectors/runtime_images/flood_fill_edges.png', edge_image) print('found edges') polygon = Polygonify(total_edge_list) rect_points = polygon.find_polygon(rectangle=True) vertex_list = [] # gets polygon's points into lat/long for corner in rect_points: next_vertex = geolocation.tilexy_to_deg_matrix(xtile, ytile, self.zoom, corner[0], corner[1]) vertex_list.append(list(next_vertex)) return vertex_list, message
def get_rectangle_from_image_lat_long(gray_scale_image, lat_deg, long_deg, zoom): global image, width, height image = gray_scale_image.copy() height = image.shape[0] width = image.shape[1] # TODO check if this converts lat/long to x/y x, y = geolocation.deg_to_tilexy_matrix(lat_deg, long_deg, zoom) top_y = draw_up(x, y, threshold, timeout) bot_y = draw_down(x, y, threshold, timeout) right_x = draw_right(x, y, threshold, timeout) left_x = draw_left(x, y, threshold, timeout) # TODO check if this converts x/y to lat/long # How to deal with this: 9 slippy tiles in one pic slippy_tiles_tuple = geolocation.deg_to_tile(lat_deg, long_deg, zoom) x_tile = slippy_tiles_tuple[0] y_tile = slippy_tiles_tuple[1] top_right_lat_long = list( geolocation.tilexy_to_deg_matrix(x_tile, y_tile, zoom, right_x, top_y)) top_left_lat_long = list( geolocation.tilexy_to_deg_matrix(x_tile, y_tile, zoom, left_x, top_y)) bot_left_lat_long = list( geolocation.tilexy_to_deg_matrix(x_tile, y_tile, zoom, left_x, bot_y)) bot_right_lat_long = list( geolocation.tilexy_to_deg_matrix(x_tile, y_tile, zoom, right_x, bot_y)) Rectangle([ top_right_lat_long, top_left_lat_long, bot_left_lat_long, bot_right_lat_long ]) return Rectangle.get_added_rectangles(), Rectangle.arr_rect_to_id( Rectangle.get_removed_rectangles())
def detect_rectangle(pil_image, xtile, ytile, lat, long, zoom, threshold=None): """ Tries to detect the rectangle at a given point on an image. """ # Get the x,y coordinates of the click x, y = geolocation.deg_to_tilexy_matrix(lat, long, zoom) pil_image = np.array(pil_image) building_points = run_all(pil_image, x, y, threshold) vertex_list = [] # corners are already structured for corner in building_points: next_vertex = geolocation.tilexy_to_deg_matrix(xtile, ytile, zoom, corner[0], corner[1]) vertex_list.append(list(next_vertex)) Rectangle(vertex_list) retangles_to_add = Rectangle.get_added_rectangles() # return the rectangle's id added from the click/merge, the rectangle's points, and the ids of all rectangles to remove (from merging) return (retangles_to_add[0].get_id(), retangles_to_add[0].get_points(), Rectangle.arr_rect_to_id(Rectangle.get_removed_rectangles()))
def detect_building(self, image, lat=None, long=None, zoom=None, rectanglify=True, to_fill=False): assert(image.shape[-1] == 3) # must be size hxwx3 # to return masks = self._detect_single(image, rectanglify, to_fill) # just a regular image, not part of Flask setup if lat is None or long is None or zoom is None: masks = resize(masks, (image.shape[0], image.shape[1]), preserve_range=True) # masks can be reshaped, corners can't masks = masks != 0 # converts to bool mask return masks # list of lat/long points to plot to_return = {} # find xtile, ytile xtile, ytile = geolocation.deg_to_tile(lat, long, zoom) if (xtile+1, ytile+1) not in self.geo_to_point: self.geo_to_point[(xtile+1,ytile+1)] = {} relevant = self.geo_to_point[(xtile+1,ytile+1)] print(lat) print(long) print(xtile) print(ytile) if rectanglify: # finds corners building_ids = np.unique(masks) building_ids = building_ids[building_ids != 0].astype(int).tolist() for i, ids in enumerate(building_ids): points = np.argwhere(masks == ids).tolist() # gets as coordinates if len(points) != 4: print("NOT 4 INSTANCE, SKIPPING BY DEFAULT") continue for j in range(len(points)): x = points[j][1] y = points[j][0] x = int((image.shape[1] / masks.shape[1]) * x) # scales x to what it would be in the original image y = int((image.shape[1] / masks.shape[1]) * y) # scales y to what it would be in the original image geopoint = list(geolocation.tilexy_to_deg_matrix(xtile+1, ytile+1, zoom, x, y)) points[j] = geopoint tmp = points[2] # needs to be swapped to be in the right order when plotted points[2] = points[3] points[3] = tmp to_return[self.building_id] = points relevant[self.building_id] = points # all the points are stored in class memory self.id_to_geo[self.building_id] = (xtile+1, ytile+1) # if the building id is given, we can backtrace the geotile self.building_id += 1 # the full mask is being plotted else: # will turn all True x,y points to lat/long for r in range(masks.shape[1]): # horizontal (x) for c in range(masks.shape[0]): # vertical (y) if masks[c, r] != 0: geo_point = list(geolocation.tilexy_to_deg_matrix(xtile+1, ytile+1, zoom, r, c)) spot_id = masks[c, r] if spot_id not in to_return: to_return[spot_id] = [geo_point] # storing all these points in memory will suck, need to "rectanglify" relevant[spot_id] = [geo_point] else: to_return[spot_id].append(geo_point) relevant[spot_id].append(geo_point) self.image_id += 1 return to_return
def detect_rectangle(pil_image, xtile, ytile, lat, long, zoom, grayscale=True): """ Tries to detect the rectangle at a given point on an image. """ # chooses right get_intensity or get_RGB function def point_finder(im, x, y, step_x, step_y, grayscale): if grayscale: return get_next_intensity_change(im, x, y, step_x, step_y) else: return get_next_RGB_change(im, x, y, step_x, step_y) # to choose the right scoring function def scorer(im, building_list, click_x, click_y, grayscale): if grayscale: return mapping_scorer(im, building_list, click_x, click_y) else: return mapping_scorer_RGB(im, building_list, click_x, click_y) # used to find the corners given the results of the get_next functions # info is formatted as ((point_x, point_y), slope_n) def point_slope_intersect(info1, info2): x_1 = info1[0][0] y_1 = info1[0][1] m_1 = info1[1] x_2 = info2[0][0] y_2 = info2[0][1] m_2 = info2[1] x = (y_2 - y_1 + m_1 * x_1 - x_2 * m_2) / (m_1 - m_2) y = y_1 + m_1 * (x - x_1) return x, y if grayscale: pil_image = PIL.ImageOps.grayscale(pil_image) im = np.array(pil_image) # Get the x,y coordinates of the click x, y = geolocation.deg_to_tilexy_matrix(lat, long, zoom) # default is to search for every 15 degrees angles = [15 * x * math.pi / 180 for x in range(0, 6)] building_list = [] for angle in angles: # Get the boundaries of the rectangle quad_one = point_finder(im, x, y, math.cos(angle), math.sin(angle), grayscale) quad_four = point_finder(im, x, y, math.sin(angle), -math.cos(angle), grayscale) quad_two = point_finder(im, x, y, -math.sin(angle), math.cos(angle), grayscale) quad_three = point_finder(im, x, y, -math.cos(angle), -math.sin(angle), grayscale) slope2 = math.tan(angle) if slope2 == 0: # hard coded because slope_point_intersect doesn't work when slope is 0 building_list.append([(quad_one[0], quad_two[1]), (quad_one[0], quad_four[1]), (quad_three[0], quad_four[1]), (quad_three[0], quad_two[1])]) else: slope1 = -1 / slope2 # top right corner1 = point_slope_intersect((quad_one, slope1), (quad_two, slope2)) # bottom right corner2 = point_slope_intersect((quad_one, slope1), (quad_four, slope2)) # bottom left corner3 = point_slope_intersect((quad_three, slope1), (quad_four, slope2)) # top left corner4 = point_slope_intersect((quad_three, slope1), (quad_two, slope2)) building_list.append([corner1, corner2, corner3, corner4]) best_map = scorer(im, building_list, x, y, grayscale) corner1 = best_map[0] corner2 = best_map[1] corner3 = best_map[2] corner4 = best_map[3] # Calculate the geocoordinates of the rectangle topright = geolocation.tilexy_to_deg_matrix(xtile, ytile, zoom, corner1[0], corner1[1]) bottomright = geolocation.tilexy_to_deg_matrix(xtile, ytile, zoom, corner2[0], corner2[1]) bottomleft = geolocation.tilexy_to_deg_matrix(xtile, ytile, zoom, corner3[0], corner3[1]) topleft = geolocation.tilexy_to_deg_matrix(xtile, ytile, zoom, corner4[0], corner4[1]) topleft = list(topleft) topright = list(topright) bottomright = list(bottomright) bottomleft = list(bottomleft) Rectangle([topleft, topright, bottomright, bottomleft]) retangles_to_add = Rectangle.get_added_rectangles() # return the rectangle's id added from the click/merge, the rectangle's points, and the ids of all rectangles to remove (from merging) return (retangles_to_add[0].get_id(), retangles_to_add[0].get_points(), Rectangle.arr_rect_to_id(Rectangle.get_removed_rectangles()))
def detect_rectangle(pil_image, xtile, ytile, lat, long, zoom, complex, threshold=None): """ Tries to detect the rectangle at a given point on an image. """ if not complex: pil_image = PIL.ImageOps.grayscale(pil_image) im = np.array(pil_image) # Get the x,y coordinates of the click x, y = geolocation.deg_to_tilexy_matrix(lat, long, zoom) quad_one = get_next_intensity_change(im, x, y, 1, 0) quad_four = get_next_intensity_change(im, x, y, 0, -1) quad_two = get_next_intensity_change(im, x, y, 0, 1) quad_three = get_next_intensity_change(im, x, y, -1, 0) corner1 = quad_one[0], quad_two[1] corner2 = quad_one[0], quad_four[1] corner3 = quad_three[0], quad_four[1] corner4 = quad_three[0], quad_two[1] # Calculate the geocoordinates of the rectangle topright = geolocation.tilexy_to_deg_matrix(xtile, ytile, zoom, corner1[0], corner1[1]) bottomright = geolocation.tilexy_to_deg_matrix(xtile, ytile, zoom, corner2[0], corner2[1]) bottomleft = geolocation.tilexy_to_deg_matrix(xtile, ytile, zoom, corner3[0], corner3[1]) topleft = geolocation.tilexy_to_deg_matrix(xtile, ytile, zoom, corner4[0], corner4[1]) topleft = list(topleft) topright = list(topright) bottomright = list(bottomright) bottomleft = list(bottomleft) Rectangle([topleft, topright, bottomright, bottomleft]) retangles_to_add = Rectangle.get_added_rectangles() # return the rectangle's id added from the click/merge, the rectangle's points, and the ids of all rectangles to remove (from merging) return (retangles_to_add[0].get_id(), retangles_to_add[0].get_points(), Rectangle.arr_rect_to_id(Rectangle.get_removed_rectangles())) else: """COMPLEX MODE: Tries to detect the rectangle at a given point on an image. """ if threshold == None: threshold = 25 # Get the x,y coordinates of the click x, y = geolocation.deg_to_tilexy_matrix(lat, long, zoom) pil_image = np.array(pil_image) building_points = run_all(pil_image, x, y, threshold) vertex_list = [] # corners are already structured for corner in building_points: next_vertex = geolocation.tilexy_to_deg_matrix( xtile, ytile, zoom, corner[0], corner[1]) vertex_list.append(list(next_vertex)) Rectangle(vertex_list) retangles_to_add = Rectangle.get_added_rectangles() # return the rectangle's id added from the click/merge, the rectangle's points, and the ids of all rectangles to remove (from merging) return (retangles_to_add[0].get_id(), retangles_to_add[0].get_points(), Rectangle.arr_rect_to_id(Rectangle.get_removed_rectangles()))