diff --git a/deepforest/utilities.py b/deepforest/utilities.py index 91ca9285..60532c68 100644 --- a/deepforest/utilities.py +++ b/deepforest/utilities.py @@ -382,13 +382,13 @@ def check_image(image): "found image with shape {}".format(image.shape)) -def boxes_to_shapefile(df, root_dir, projected=True, flip_y_axis=False): +def boxes_to_shapefile(df, rgb, projected=True, flip_y_axis=False): """ Convert from image coordinates to geographic coordinates Note that this assumes df is just a single plot being passed to this function Args: df: a pandas type dataframe with columns: name, xmin, ymin, xmax, ymax. Name is the relative path to the root_dir arg. - root_dir: directory of images to lookup image_path column + rgb: path for the image file projected: If True, convert from image to geographic coordinates, if False, keep in image coordinate system flip_y_axis: If True, reflect predictions over y axis to align with raster data in QGIS, which uses a negative y origin compared to numpy. See https://gis.stackexchange.com/questions/306684/why-does-qgis-use-negative-y-spacing-in-the-default-raster-geotransform Returns: @@ -401,15 +401,7 @@ def boxes_to_shapefile(df, root_dir, projected=True, flip_y_axis=False): .format(flip_y_axis, projected), UserWarning) projected = False - plot_names = df.image_path.unique() - if len(plot_names) > 1: - raise ValueError("This function projects a single plots worth of data. " - "Multiple plot names found {}".format(plot_names)) - else: - plot_name = plot_names[0] - - rgb_path = "{}/{}".format(root_dir, plot_name) - with rasterio.open(rgb_path) as dataset: + with rasterio.open(rgb) as dataset: bounds = dataset.bounds pixelSizeX, pixelSizeY = dataset.res crs = dataset.crs diff --git a/docs/annotation.md b/docs/annotation.md index eaa922c1..8d0dbeab 100644 --- a/docs/annotation.md +++ b/docs/annotation.md @@ -83,7 +83,7 @@ for path in files: plt.imshow(fig) #Create a shapefile, in this case img data was unprojected - shp = boxes_to_shapefile(boxes, root_dir=PATH_TO_DIR, projected=False) + shp = boxes_to_shapefile(boxes, rgb=path, projected=False) #Get name of image and save a .shp in the same folder basename = os.path.splitext(os.path.basename(path))[0] diff --git a/tests/test_utilities.py b/tests/test_utilities.py index b5a9ea49..10e52017 100644 --- a/tests/test_utilities.py +++ b/tests/test_utilities.py @@ -88,28 +88,28 @@ def test_boxes_to_shapefile_projected(m): img = get_data("OSBS_029.tif") r = rio.open(img) df = m.predict_image(path=img) - gdf = utilities.boxes_to_shapefile(df, root_dir=os.path.dirname(img), projected=True) + gdf = utilities.boxes_to_shapefile(df, rgb=img, projected=True) #Confirm that each boxes within image bounds geom = geometry.box(*r.bounds) assert all(gdf.geometry.apply(lambda x: geom.intersects(geom)).values) #Edge case, only one row in predictions - gdf = utilities.boxes_to_shapefile(df.iloc[:1,], root_dir=os.path.dirname(img), projected=True) + gdf = utilities.boxes_to_shapefile(df.iloc[:1,], rgb=img, projected=True) assert gdf.shape[0] == 1 def test_boxes_to_shapefile_projected_from_predict_tile(m): img = get_data("OSBS_029.tif") r = rio.open(img) df = m.predict_tile(raster_path=img) - gdf = utilities.boxes_to_shapefile(df, root_dir=os.path.dirname(img), projected=True) + gdf = utilities.boxes_to_shapefile(df, rgb=img, projected=True) #Confirm that each boxes within image bounds geom = geometry.box(*r.bounds) assert all(gdf.geometry.apply(lambda x: geom.intersects(geom)).values) #Edge case, only one row in predictions - gdf = utilities.boxes_to_shapefile(df.iloc[:1,], root_dir=os.path.dirname(img), projected=True) + gdf = utilities.boxes_to_shapefile(df.iloc[:1,], rgb=img, projected=True) assert gdf.shape[0] == 1 # Test unprojected data, including warning if flip_y_axis is set to True, but projected is False @@ -123,7 +123,7 @@ def test_boxes_to_shapefile_unprojected(m, flip_y_axis, projected): with pytest.warns(UserWarning): gdf = utilities.boxes_to_shapefile( df, - root_dir=os.path.dirname(img), + rgb=img, projected=projected, flip_y_axis=flip_y_axis)