Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jb/tiling2 #100

Merged
merged 2 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 25 additions & 34 deletions detectree2/preprocessing/tiling.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import random
import shutil
import warnings
from math import ceil
from pathlib import Path

import cv2
Expand Down Expand Up @@ -206,23 +207,31 @@ def tile_data_train( # noqa: C901
tilename = Path(data.name).stem
crs = data.crs.data["init"].split(":")[1]
# out_img, out_transform = mask(data, shapes=crowns.buffer(buffer), crop=True)
for minx in np.arange(data.bounds[0], data.bounds[2] - tile_width, tile_width, int):
for miny in np.arange(data.bounds[1], data.bounds[3] - tile_height, tile_height, int):
# Should start from data.bounds[0] + buffer, data.bounds[1] + buffer to avoid later complications
for minx in np.arange(ceil(data.bounds[0]) + buffer, data.bounds[2] - tile_width - buffer, tile_width, int):
for miny in np.arange(ceil(data.bounds[1]) + buffer, data.bounds[3] - tile_height - buffer, tile_height, int):

out_path_root = out_path / f"{tilename}_{minx}_{miny}_{tile_width}_{buffer}_{crs}"
# new tiling bbox including the buffer
bbox = box(
minx - buffer,
miny - buffer,
minx + tile_width + buffer,
miny + tile_height + buffer,
)

# turn the bounding boxes into geopandas DataFrames
geo = gpd.GeoDataFrame({"geometry": bbox},
index=[0],
crs=data.crs)
# Calculate the buffered tile dimensions
#tile_width_buffered = tile_width + 2 * buffer
#tile_height_buffered = tile_height + 2 * buffer

# Calculate the bounding box coordinates with buffer
minx_buffered = minx - buffer
miny_buffered = miny - buffer
maxx_buffered = minx + tile_width + buffer
maxy_buffered = miny + tile_height + buffer

# Create the affine transformation matrix for the tile
# transform = from_bounds(minx_buffered, miny_buffered, maxx_buffered,
# maxy_buffered, tile_width_buffered, tile_height_buffered)

bbox = box(minx_buffered, miny_buffered, maxx_buffered, maxy_buffered)
geo = gpd.GeoDataFrame({"geometry": bbox}, index=[0], crs=data.crs)
coords = get_features(geo)

# Skip if insufficient coverage of crowns - good to have early on to save on unnecessary processing
with warnings.catch_warnings():
warnings.simplefilter("ignore")
# Warning:
Expand All @@ -237,9 +246,6 @@ def tile_data_train( # noqa: C901
if (overlapping_crowns.dissolve().area[0] / geo.area[0]) < threshold:
continue

# here we are cropping the tiff to the bounding box of the tile we want
coords = get_features(geo)

# define the tile as a mask of the whole tiff with just the bounding box
out_img, out_transform = mask(data, shapes=coords, crop=True)

Expand All @@ -255,8 +261,6 @@ def tile_data_train( # noqa: C901
elif sumnan > nan_threshold * totalpix: # reject tiles with many NaN cells
continue

# copy the metadata then update it, the "nodata" and "dtype" where important as made larger
# tifs have outputted tiles which were not just black
out_meta = data.meta.copy()
out_meta.update({
"driver": "GTiff",
Expand All @@ -265,8 +269,7 @@ def tile_data_train( # noqa: C901
"transform": out_transform,
"nodata": None,
})

# dtype needs to be unchanged for some data and set to uint8 for others
# dtype needs to be unchanged for some data and set to uint8 for others to deal with black tiles
if dtype_bool:
out_meta.update({"dtype": "uint8"})

Expand Down Expand Up @@ -314,20 +317,8 @@ def tile_data_train( # noqa: C901

overlapping_crowns = overlapping_crowns.explode(index_parts=True)

# translate to 0,0 to overlay on png
# this now works as a universal approach.
if minx == data.bounds[0] and miny == data.bounds[1]:
# print("We are in the bottom left!")
moved = overlapping_crowns.translate(-minx, -miny)
elif miny == data.bounds[1]:
# print("We are on the bottom, but not bottom left")
moved = overlapping_crowns.translate(-minx + buffer, -miny)
elif minx == data.bounds[0]:
# print("We are along the left hand side, but not bottom left!")
moved = overlapping_crowns.translate(-minx, -miny + buffer)
else:
# print("We are in the middle!")
moved = overlapping_crowns.translate(-minx + buffer, -miny + buffer)
# Translate to 0,0 to overlay on png
moved = overlapping_crowns.translate(-minx + buffer, -miny + buffer)

# scale to deal with the resolution
scalingx = 1 / (data.transform[0])
Expand Down
36 changes: 36 additions & 0 deletions docs/source/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,42 @@ The data has now been tiled and partitioned for model training, tuning and evalu
└── test (test data folder)


It is advisable to do a visual inspection on the tiles to ensure that the tiling has worked as expected and that crowns
and images align. This can be done quickly with the inbuilt ``detectron2`` visualisation tools.

.. code-block:: python

from detectron2.data import DatasetCatalog, MetadataCatalog
from detectron2.utils.visualizer import Visualizer
from detectree2.models.train import combine_dicts, register_train_data
import random
import cv2
from PIL import Image

name = "Danum"
train_location = "/content/drive/Shareddrives/detectree2/data/" + name + "/tiles_" + appends + "/train"
dataset_dicts = combine_dicts(train_location, 1) # The number gives the fold to visualise
trees_metadata = MetadataCatalog.get(name + "_train")

for d in dataset_dicts:
img = cv2.imread(d["file_name"])
visualizer = Visualizer(img[:, :, ::-1], metadata=trees_metadata, scale=0.3)
out = visualizer.draw_dataset_dict(d)
image = cv2.cvtColor(out.get_image()[:, :, ::-1], cv2.COLOR_BGR2RGB)
display(Image.fromarray(image))


.. image:: ../../report/figures/trees_train1.jpg
:width: 400
:alt: Prediction
:align: left

.. image:: ../../report/figures/trees_train2.jpg
:width: 400
:alt: Prediction
:align: left


Training a model
----------------

Expand Down
Binary file added report/figures/trees_train1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added report/figures/trees_train2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.