I have developed a semantic segmentation method to map certain objects in aerial imagery. Throughout this project I download pictures (4800x4800 pxs) where I know the min_x, min_y, max_x and max_y in world coordinates, e.g. (6.212454957892032, 51.58908266914109, 6.219403242107967, 51.59339941284951). Resolution is 10 cm per pixel.
To then segment the pictures I crop the large picture (4800x4800) into multiple pictures with a resolution of 320x320. To identify each of those cropped pictures I calculated its center coordinate as follows (from upper left to right then to south):
dlat = (side * 360) / (2 * np.pi * r) #dlat for 32m in degrees side = 32 r = 6371000 #avg earth radius minx = float(minx) miny = float(miny) maxx = float(maxx) maxy = float(maxy) identifier = (minx, miny, maxx, maxy) # Takes a 4800x4800 image tile and returns a list of 320x320 pixel images tile = np.array(tile) images =  coords =  N = 0 S = 4800 W = 0 E = 4800 # y coordinate is dlat/2 degrees, i.e. 16 meters, south of the maximum y coordinate. y_coord = maxy - dlat/2 while N < S: W = 0 x_coord = minx + (((side * 360) / (2 * np.pi * r * np.cos(np.deg2rad(y_coord))))/2) #16 m to the middle while W < E: # The first image is taken from the upper left corner, we then slide from left # to right and from top to bottom images.append(tile[N:N + 320, W:W + 320]) coords.append((x_coord, y_coord)) x_coord += (((side * 360) / (2 * np.pi * r * np.cos(np.deg2rad(y_coord))))) W = W + 320 N = N + 320 y_coord = y_coord - dlat
As I also use this approach to then convert the identified pixel polygons to real world coordinates I run into minor differences between the underlying map and the identified objects (10-20m difference) sometimes minor. So I ask myself what is wrong with my approach and where could I make it more efficient by using proper packages.
I actually did some research but it is rather confusing to me because I do not use GeoTIFF files or similar. I get a numpy array as output which I then rasterize with rasterio to retrieve the polygons in pixel coordinates. I convert these using the following function to real world coordinates (using the middle point of each picture as an identifier and fix point to calculate the other coordinates):
def centroid_coord(center_coord, distance_vector, size = 320): ''' returns lat, lon of array centroid :param center_coord: tuple of center coords, identifier of picture tile :param distance_vector: tuple of distance vector, measured from center point in px :param size: scaling factor for distance from center point in pixels (half the size of the segmented output (320) :return: lat,lon array centroid ''' dist_px_x, dist_px_y = distance_vector x_center, y_center = center_coord x_min = x_center - (((32 * 360) / (2 * np.pi * r * np.cos(np.deg2rad(y_center))))/2) y_new = y_center + (side/size) * dist_px_y * (dlat/side) x_new = x_min + (side/size) * ((size/2) + dist_px_x) * 360 * (1/(2 * np.pi * r * np.cos(np.deg2rad(y_new)))) return (x_new, y_new)
I think that this approach is not optimal and that there is a much more correct and efficient way using proper packages.
How can I do this?
Array: Binary array with a size (320,320) indicating where a certain object is or not. Using rasterio finding polygons of the objects in pixel coordinates. Output: Convert polygons in pixel coordinates to world coordinates using the identifier of the input image (center point) My problems:
- Is the center point calculation (world-coordinatewise) correct like this?
- Should I take the upper left corner point of the image to ease the process?
- How can I convert the polygons with pixel coordinates correctly to world coordinate polygons?