Kornia 0.2.1 release
Data augmentation framework, deep descriptors and more.
In this release we support compatibility between kornia.augmentation
and torchvision.transforms
.
We now support all the same existing operations with torch.Tensor in the GPU with extra features such as returning for each operator the transformation matrix generated to produce such transformation.
import kornia as K
import torchvision as T
# kornia
transform_fcn = torch.nn.Sequential(
K.augmentation.RandomAffine(
[-45., 45.], [0., 0.5], [0.5, 1.5], [0., 0.5], return_transform=True),
K.color.Normalize(0.1307, 0.3081),
)
# torchvision
transform_fcn = T.transforms.Compose([
T.transforms.RandomAffine(
[-45., 45.], [0., 0.5], [0.5, 1.5], [0., 0.5]),
T.transforms.ToTensor(),
T.transforms.Normalize((0.1307,), (0.3081,)),
])
Check the online documentations with the updated API [DOCS]
Check this Google Colab to see how to reproduce same results [Colab]
kornia.augmentation
as a framework
In addition, we have re-designed kornia.augmentation
such in a way that users can easily contribute with more operators, or just use it as a framework to create their custom operators.
Each of the kornia.augmentation
modules inherit from AugmentationBase
and one can easily define a new operator by creating a subclass and overriding a couple of methods.
Let’s take a look at a custom MyRandomRotation
. The class inherits from AugmentationBase
making it a nn.Module
so that can be stacked in a nn.Sequential
to compute chained transformations.
To implement a new functionality two things needed: override get_params and apply.
The get_params
receives the shape of the input tensor and returns a dictionary with the parameters to use in the apply
function.
The apply
function receives as input a tensor and the dictionary defined in get_params
and returns a tuple with the transformed input and the transformation applied to it.
class MyRandomRotation(AugmentationBase):
def __init__(self, angle: float, return_transform: bool = True) -> None:
super(MyRandomRotation, self).__init__(self.apply, return_transform)
self.angle = angle
def get_params(self, batch_shape: torch.Size) -> Dict[str, torch.Tensor]:
angles_rad torch.Tensor = torch.rand(batch_shape) * K.pi
angles_deg = kornia.rad2deg(angles_rad) * self.angle
return dict(angles=angles_deg)
def apply(self, input: torch.Tensor, params: Dict[str, torch.Tensor]):
# compute transformation
angles: torch.Tensor = params['angles'].type_as(input)
center = torch.tensor([[W / 2, H / 2]]).type_as(input)
transform = K.get_rotation_matrix2d(
center, angles, torch.ones_like(angles))
# apply transformation
output = K.warp_affine(input, transform, (H, W))
return (output, transform)
# how to use it
# load an image and cast to tensor
img1: torch.Tensor = imread(...) # BxDxHxW
# instantiate and apply the transform
aug = MyRandomRotation(45., return_transformation=True)
img2, transform = aug(img1) # BxDxHxW - Bx3x3
Please, do not hesitate to check the release notes on GitHub to learn about the new library features and get more details.
Have a happy coding day
The Kornia team