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

[prototype] Minor improvements on functional #6832

Merged
merged 5 commits into from
Oct 25, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
12 changes: 1 addition & 11 deletions torchvision/prototype/transforms/functional/_color.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ def _hsv_to_rgb(img: torch.Tensor) -> torch.Tensor:
h, s, v = img.unbind(dim=-3)
h6 = h * 6
i = torch.floor(h6)
f = (h6) - i
f = h6 - i
i = i.to(dtype=torch.int32)

p = (v * (1.0 - s)).clamp_(0.0, 1.0)
Expand All @@ -210,9 +210,6 @@ def adjust_hue_image_tensor(image: torch.Tensor, hue_factor: float) -> torch.Ten
if not (-0.5 <= hue_factor <= 0.5):
raise ValueError(f"hue_factor ({hue_factor}) is not in [-0.5, 0.5].")

if not (isinstance(image, torch.Tensor)):
raise TypeError("Input img should be Tensor image")
Comment on lines -213 to -214
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As decided previously, removing the final tensor checks on tensor kernels.


c = get_num_channels_image_tensor(image)

if c not in [1, 3]:
Expand Down Expand Up @@ -258,9 +255,6 @@ def adjust_hue(inpt: features.InputTypeJIT, hue_factor: float) -> features.Input


def adjust_gamma_image_tensor(image: torch.Tensor, gamma: float, gain: float = 1.0) -> torch.Tensor:
if not (isinstance(image, torch.Tensor)):
raise TypeError("Input img should be Tensor image")

if gamma < 0:
raise ValueError("Gamma should be a non-negative real number")

Expand Down Expand Up @@ -337,10 +331,6 @@ def solarize(inpt: features.InputTypeJIT, threshold: float) -> features.InputTyp


def autocontrast_image_tensor(image: torch.Tensor) -> torch.Tensor:

if not (isinstance(image, torch.Tensor)):
raise TypeError("Input img should be Tensor image")

c = get_num_channels_image_tensor(image)

if c not in [1, 3]:
Expand Down
10 changes: 3 additions & 7 deletions torchvision/prototype/transforms/functional/_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,8 @@ def clamp_bounding_box(
return convert_format_bounding_box(xyxy_boxes, BoundingBoxFormat.XYXY, format)


def _split_alpha(image: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:
return image[..., :-1, :, :], image[..., -1:, :, :]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tensor_split is marginally faster because it avoids the double indexing:

[------------------------------- Convert_color_space_image_tensor cpu torch.uint8 ------------------------------]
                     |  convert_color_space_image_tensor v2 before  |  convert_color_space_image_tensor_ v2 after
1 threads: ------------------------------------------------------------------------------------------------------
      (4, 400, 400)  |                     217                      |                     213                    
6 threads: ------------------------------------------------------------------------------------------------------
      (4, 400, 400)  |                     297                      |                     292                    

Times are in microseconds (us).

[------------------------------ Convert_color_space_image_tensor cuda torch.uint8 ------------------------------]
                     |  convert_color_space_image_tensor v2 before  |  convert_color_space_image_tensor_ v2 after
1 threads: ------------------------------------------------------------------------------------------------------
      (4, 400, 400)  |                     56.4                     |                      52                    
6 threads: ------------------------------------------------------------------------------------------------------
      (4, 400, 400)  |                     56.4                     |                      52                    

Times are in microseconds (us).

[------------------------------ Convert_color_space_image_tensor cpu torch.float32 -----------------------------]
                     |  convert_color_space_image_tensor v2 before  |  convert_color_space_image_tensor_ v2 after
1 threads: ------------------------------------------------------------------------------------------------------
      (4, 400, 400)  |                     236                      |                     232                    
6 threads: ------------------------------------------------------------------------------------------------------
      (4, 400, 400)  |                     325                      |                     321                    

Times are in microseconds (us).

[----------------------------- Convert_color_space_image_tensor cuda torch.float32 -----------------------------]
                     |  convert_color_space_image_tensor v2 before  |  convert_color_space_image_tensor_ v2 after
1 threads: ------------------------------------------------------------------------------------------------------
      (4, 400, 400)  |                     56.9                     |                     52.4                   
6 threads: ------------------------------------------------------------------------------------------------------
      (4, 400, 400)  |                     56.7                     |                     52.4                   

Times are in microseconds (us).



def _strip_alpha(image: torch.Tensor) -> torch.Tensor:
image, alpha = _split_alpha(image)
image, alpha = torch.tensor_split(image, indices=(-1,), dim=-3)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO we don't need a private one liner method for something Torch has a built in method.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: I would prefer it since it is a little more expressive. Plus, since we have a _add_alpha function it would be consistent to have the complementary _split_alpha as well. With this change we have three identical, non-trivial calls of torch.tensor_split. At a glance, it is harder to see that these three actually do exactly the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I'll restore `_split_alpha.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restoring this causes more harm than good. JIT is complaining that it's not longer a tuple, which means I would have to split into 2 lines and return as tuple to please it. I don't think it's worth this.

if not torch.all(alpha == _FT._max_value(alpha.dtype)):
raise RuntimeError(
"Stripping the alpha channel if it contains values other than the max value is not supported."
Expand Down Expand Up @@ -237,7 +233,7 @@ def convert_color_space_image_tensor(
elif old_color_space == ColorSpace.GRAY_ALPHA and new_color_space == ColorSpace.RGB:
return _gray_to_rgb(_strip_alpha(image))
elif old_color_space == ColorSpace.GRAY_ALPHA and new_color_space == ColorSpace.RGB_ALPHA:
image, alpha = _split_alpha(image)
image, alpha = torch.tensor_split(image, indices=(-1,), dim=-3)
return _add_alpha(_gray_to_rgb(image), alpha)
elif old_color_space == ColorSpace.RGB and new_color_space == ColorSpace.GRAY:
return _rgb_to_gray(image)
Expand All @@ -248,7 +244,7 @@ def convert_color_space_image_tensor(
elif old_color_space == ColorSpace.RGB_ALPHA and new_color_space == ColorSpace.GRAY:
return _rgb_to_gray(_strip_alpha(image))
elif old_color_space == ColorSpace.RGB_ALPHA and new_color_space == ColorSpace.GRAY_ALPHA:
image, alpha = _split_alpha(image)
image, alpha = torch.tensor_split(image, indices=(-1,), dim=-3)
return _add_alpha(_rgb_to_gray(image), alpha)
elif old_color_space == ColorSpace.RGB_ALPHA and new_color_space == ColorSpace.RGB:
return _strip_alpha(image)
Expand Down
8 changes: 4 additions & 4 deletions torchvision/prototype/transforms/functional/_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,18 +69,18 @@ def normalize(
return normalize_image_tensor(inpt, mean=mean, std=std, inplace=inplace)


def _get_gaussian_kernel1d(kernel_size: int, sigma: float) -> torch.Tensor:
def _get_gaussian_kernel1d(kernel_size: int, sigma: float, dtype: torch.dtype, device: torch.device) -> torch.Tensor:
lim = (kernel_size - 1) / (2 * math.sqrt(2) * sigma)
x = torch.linspace(-lim, lim, steps=kernel_size)
x = torch.linspace(-lim, lim, steps=kernel_size, dtype=dtype, device=device)
pmeier marked this conversation as resolved.
Show resolved Hide resolved
kernel1d = torch.softmax(-x.pow_(2), dim=0)
return kernel1d


def _get_gaussian_kernel2d(
kernel_size: List[int], sigma: List[float], dtype: torch.dtype, device: torch.device
) -> torch.Tensor:
kernel1d_x = _get_gaussian_kernel1d(kernel_size[0], sigma[0]).to(device, dtype=dtype)
kernel1d_y = _get_gaussian_kernel1d(kernel_size[1], sigma[1]).to(device, dtype=dtype)
kernel1d_x = _get_gaussian_kernel1d(kernel_size[0], sigma[0], dtype, device)
kernel1d_y = _get_gaussian_kernel1d(kernel_size[1], sigma[1], dtype, device)
kernel2d = kernel1d_y.unsqueeze(-1) * kernel1d_x
return kernel2d

Expand Down