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
Indices Transforms #127
Indices Transforms #127
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might need a bit more thought before we can safely integrate this with Kornia.
@adamjstewart @calebrob6 I'm curious if we should even utilize kornia to facilitate augmentations when these are instead simply transforms. We could use it along with kornia and the AugmentationSequential wrapper I created like below: import torch
import torch.nn as nn
import kornia.augmentation as K
from torchgeo.transforms import AugmentationSequential, AppendNDVI, AppendNDBI
sample = dict(
image=torch.randn(2, 9, 512, 512).to("cuda"),
mask=torch.randint(0, 10, size=(2, 1, 512, 512)).to(torch.float).to("cuda") # kornia requires mask to be float for some reason
)
transforms = nn.Sequential(
AppendNDVI(index_red=2, index_nir=3),
AppendNDBI(index_swir=4, index_nir=3),
AugmentationSequential(
K.RandomHorizontalFlip(),
K.RandomVerticalFlip(),
data_keys=["image", "mask"]
)
)
transforms = transforms.to("cuda")
outputs = transforms(sample)
# "image": (2, 11, 512, 512)
# "mask": (2, 1, 512, 512) The above actually works as of now and simply chains multiple non augmentation transforms (e.g. computing indices), along with an AugmentationSequential wrapper which then performs the transforms on the image and mask. |
The above seems fine to me! Thoughts:
The name of the game is to be as friendly to existing CV code as possible. |
That's a great point about sample vs batch. Apparently torchvision transforms on tensors work for both batch and sample data. Although, under the hood, I believe they just add a batch dim of 1 to sample data and then squeeze it off afterwards. A note on the AugmentationSequential wrapper. I'm actually hoping that a PR I'm working on for adding this to kornia will be accepted. Until then, using the wrapper should allow us to chain transforms and augs similarly to the above example. |
77992c6
to
4ca7bbf
Compare
I'm running into a very strange mypy error due to something in kornia. Tracking it down...
|
I'm getting this same error in the trainers PR |
spatial_soft_argmax.py needs to do |
Ok, I'll make an issue in the kornia repo. Edit: see kornia/kornia#1318 |
Sphinx seems to be failing due to warning that it doesn't allow cells with shell commands in them (e.g. |
That's odd, can you open an issue at https://github.com/spatialaudio/nbsphinx/issues? We definitely want/need this to be supported. This is a very common thing to have in a notebook and is a requirement for our code to work on Colab. P.S. We need to convert our other notebooks to |
542d540
to
9dffcd9
Compare
6da7361
to
d9ed746
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we get rid of torchgeo/transforms/transforms.py
? We're already planning on dropping the random flip transforms, and we could move Identity
to the tests themselves. I'm not sure where the best place to put AugmentationSequential
would be. It could be in __init__.py
itself or in torchgeo/transforms/containers.py
.
I still need to look at the tutorial. I still have a lot of questions remaining about how Kornia does things and how TorchGeo is compatible with Kornia, but I'll save those for later.
Great question, if kornia adds support for optionally taking a dict input and returning a dict output to AugmentationSequential where only the specified keys are modified, we could actually drop the AugmentationSequential wrapper entirely and transforms.py as well. Then kornia would only be used in our trainers and tutorials. They are also working on finishing up a "LambdaAugmentation" class which allows a user to add a general operation to images or masks or both which is simply a nn.Module without having to subclass their AugmentationBase classes and write your own. This would allows us to contain kornia usage only in the trainers but still have a transforms.py of general nn.Modules which modify images using torch ops. Edit: |
Just to circle back to this. I was able to get around this by using cell magic |
Edit: Scratch that. I fixed it. |
Didn't realize this already existed, perfect! |
Made the following changes to the notebooks:
Remaining TODOs which can happen in a follow-up PR:
The Indices tutorial has a suspiciously greater amount of comments than the Transforms tutorial. You didn't get the Indices tutorial from somewhere else did you? |
I added additional comments for clarity, so no, I didn't pull this tutorial from somewhere else. I would recommend opening the notebook in colab otherwise you can't see the visualization app that uses some of the Colab functionality. The image that's plotted might be dark because it's one of the images of a lake/sea. I'll refactor to use kornia's minmax normalize. Although, they don't have a stretch/percentile normalize so I'll have to hack something together. |
I'll make some of the changes in a bit and the rest can come in a separate PR I think. |
025eb63
to
904d89d
Compare
a6466df
to
bea4f53
Compare
Some updates:
|
The primary purpose of the tutorials is to serve as documentation, the fact that they can be ran on Colab is less important. If this shows up on Read the Docs and doesn't do anything outside of Colab I think we should just remove it. Aren't there Jupyter Notebook magic things to make this work everywhere? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to merge this as is. At some point before we release I plan on going back through the tutorials and touching them up and testing them, so if there's anything else needed I can work on them then.
* draft indices transform * import sort * added AugmentationSequential wrapper for dicts * updated indices * fix dim concat bugs * format * add kornia dependency * add augmentationsequenal unit tests * add augmentationsequential support for boxes and mask dtypes * add indices tests * Draft indices tutorial notebook * move notebook to tutorials folder * mypy fixes * fix bug when only image key used in AugmentationSequential * Created using Colaboratory * added tutorial to docs * format * added kornia master branch dependency' * refactor notebook to use % cell magic and python to download files * revert kornia version * install kornia master branch for mypy checks * update mypy github action install order * fix divide by zero error in indices * Created using Colaboratory * fix nbsphinx errors * add TODO to remove kornia in tests action * format setup.cfg * minor fixes to indices * remove unecessary variable * update mask to cast to original dtype * removed unused ignore comment * added gray/rgb/multispectral unit tests * added tests with boxes * Created using Colaboratory * Created using Colaboratory * fix mypy issues * updated notebooks in docs * Updates to tutorials * Created using Colaboratory * Created using Colaboratory Co-authored-by: Adam J. Stewart <ajstewart426@gmail.com>
This is simply a draft of a transform for computing NDVI and concatenating to thesample["image"]
channels. Open to suggestions/feedback.Note: I just realized that the requiring the index of the channels for computing the indices doesn't scale. See Enhanced Vegation Index which requires 4+ bands to computeEVI = G * ((NIR - R) / (NIR + C1 * R – C2 * B + L))
.Update:
This PR adds the following:
AugmentationSequential
wrapper aroundkornia.augmentation.AugmentationSequential
which supports our sample/batch dicts.ndbi
,ndsi
,ndvi
,ndwi
functionals which given specific multispectral band input will compute the associated index.AppendNDBI
,AppendNDSI
,AppendNDVI
,AppendNDWI
transform modules which take as input a batch dict, computes the desired index, and appends to the channel dimension.kornia>=0.5.4
as dependency which is the version whenkornia.augmentation.AugmentationSequential
was added. Additionally, kornia's only dependency is pytorch.TODO:
docs/tutorials
display the usage of indices transformsCloses #112