We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Use more pythonic expressions in rgb to hls
Make improvements in the `kornia/color/hls.py` module to use more pythonic expressions. Ex:
```diff
-    r = torch.select(im, -3, 0)
+   r = im[…, 0, :,:]
```


_Originally posted by @edgarriba in https://github.com/kornia/kornia/pull/2030#discussion_r1032065189_
      

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kornia/color/hls.py`
Content:
```
1 import math
2 from typing import Tuple
3 
4 import torch
5 
6 from kornia.core import Module, Tensor, stack, tensor, where
7 
8 
9 def rgb_to_hls(image: Tensor, eps: float = 1e-8) -> Tensor:
10     r"""Convert a RGB image to HLS.
11 
12     .. image:: _static/img/rgb_to_hls.png
13 
14     The image data is assumed to be in the range of (0, 1).
15 
16     NOTE: this method cannot be compiled with JIT in pytohrch < 1.7.0
17 
18     Args:
19         image: RGB image to be converted to HLS with shape :math:`(*, 3, H, W)`.
20         eps: epsilon value to avoid div by zero.
21 
22     Returns:
23         HLS version of the image with shape :math:`(*, 3, H, W)`.
24 
25     Example:
26         >>> input = torch.rand(2, 3, 4, 5)
27         >>> output = rgb_to_hls(input)  # 2x3x4x5
28     """
29     if not isinstance(image, Tensor):
30         raise TypeError(f"Input type is not a Tensor. Got {type(image)}")
31 
32     if len(image.shape) < 3 or image.shape[-3] != 3:
33         raise ValueError(f"Input size must have a shape of (*, 3, H, W). Got {image.shape}")
34 
35     _RGB2HSL_IDX = tensor([[[0.0]], [[1.0]], [[2.0]]], device=image.device, dtype=image.dtype)  # 3x1x1
36 
37     _img_max: Tuple[Tensor, Tensor] = image.max(-3)
38     maxc = _img_max[0]
39     imax = _img_max[1]
40     minc: Tensor = image.min(-3)[0]
41 
42     if image.requires_grad:
43         l_ = maxc + minc
44         s = maxc - minc
45         # weird behaviour with undefined vars in JIT...
46         # scripting requires image_hls be defined even if it is not used :S
47         h = l_  # assign to any tensor...
48         image_hls = l_  # assign to any tensor...
49     else:
50         # define the resulting image to avoid the torch.stack([h, l, s])
51         # so, h, l and s require inplace operations
52         # NOTE: stack() increases in a 10% the cost in colab
53         image_hls = torch.empty_like(image)
54         h = torch.select(image_hls, -3, 0)
55         l_ = torch.select(image_hls, -3, 1)
56         s = torch.select(image_hls, -3, 2)
57         torch.add(maxc, minc, out=l_)  # l = max + min
58         torch.sub(maxc, minc, out=s)  # s = max - min
59 
60     # precompute image / (max - min)
61     im = image / (s + eps).unsqueeze(-3)
62 
63     # epsilon cannot be inside the torch.where to avoid precision issues
64     s /= where(l_ < 1.0, l_, 2.0 - l_) + eps  # saturation
65     l_ /= 2  # luminance
66 
67     # note that r,g and b were previously div by (max - min)
68     r = torch.select(im, -3, 0)
69     g = torch.select(im, -3, 1)
70     b = torch.select(im, -3, 2)
71     # h[imax == 0] = (((g - b) / (max - min)) % 6)[imax == 0]
72     # h[imax == 1] = (((b - r) / (max - min)) + 2)[imax == 1]
73     # h[imax == 2] = (((r - g) / (max - min)) + 4)[imax == 2]
74     cond = imax.unsqueeze(-3) == _RGB2HSL_IDX
75     if image.requires_grad:
76         h = torch.mul((g - b) % 6, torch.select(cond, -3, 0))
77     else:
78         torch.mul((g - b).remainder(6), torch.select(cond, -3, 0), out=h)
79     h += torch.add(b - r, 2) * torch.select(cond, -3, 1)
80     h += torch.add(r - g, 4) * torch.select(cond, -3, 2)
81     # h = 2.0 * math.pi * (60.0 * h) / 360.0
82     h *= math.pi / 3.0  # hue [0, 2*pi]
83 
84     if image.requires_grad:
85         return stack([h, l_, s], -3)
86     return image_hls
87 
88 
89 def hls_to_rgb(image: Tensor) -> Tensor:
90     r"""Convert a HLS image to RGB.
91 
92     The image data is assumed to be in the range of (0, 1).
93 
94     Args:
95         image: HLS image to be converted to RGB with shape :math:`(*, 3, H, W)`.
96 
97     Returns:
98         RGB version of the image with shape :math:`(*, 3, H, W)`.
99 
100     Example:
101         >>> input = torch.rand(2, 3, 4, 5)
102         >>> output = hls_to_rgb(input)  # 2x3x4x5
103     """
104     if not isinstance(image, Tensor):
105         raise TypeError(f"Input type is not a Tensor. Got {type(image)}")
106 
107     if len(image.shape) < 3 or image.shape[-3] != 3:
108         raise ValueError(f"Input size must have a shape of (*, 3, H, W). Got {image.shape}")
109 
110     _HLS2RGB = tensor([[[0.0]], [[8.0]], [[4.0]]], device=image.device, dtype=image.dtype)  # 3x1x1
111 
112     im: Tensor = image.unsqueeze(-4)
113     h: Tensor = torch.select(im, -3, 0)
114     l: Tensor = torch.select(im, -3, 1)
115     s: Tensor = torch.select(im, -3, 2)
116     h = h * (6 / math.pi)  # h * 360 / (2 * math.pi) / 30
117     a = s * torch.min(l, 1.0 - l)
118 
119     # kr = (0 + h) % 12
120     # kg = (8 + h) % 12
121     # kb = (4 + h) % 12
122     k: Tensor = (h + _HLS2RGB) % 12
123 
124     # l - a * max(min(min(k - 3.0, 9.0 - k), 1), -1)
125     mink = torch.min(k - 3.0, 9.0 - k)
126     return torch.addcmul(l, a, mink.clamp_(min=-1.0, max=1.0), value=-1)
127 
128 
129 class RgbToHls(Module):
130     r"""Convert an image from RGB to HLS.
131 
132     The image data is assumed to be in the range of (0, 1).
133 
134     Returns:
135         HLS version of the image.
136 
137     Shape:
138         - image: :math:`(*, 3, H, W)`
139         - output: :math:`(*, 3, H, W)`
140 
141     Examples:
142         >>> input = torch.rand(2, 3, 4, 5)
143         >>> hls = RgbToHls()
144         >>> output = hls(input)  # 2x3x4x5
145     """
146 
147     def forward(self, image: Tensor) -> Tensor:
148         return rgb_to_hls(image)
149 
150 
151 class HlsToRgb(Module):
152     r"""Convert an image from HLS to RGB.
153 
154     The image data is assumed to be in the range of (0, 1).
155 
156     Returns:
157         RGB version of the image.
158 
159     Shape:
160         - input: :math:`(*, 3, H, W)`
161         - output: :math:`(*, 3, H, W)`
162 
163     Reference:
164         https://en.wikipedia.org/wiki/HSL_and_HSV
165 
166     Examples:
167         >>> input = torch.rand(2, 3, 4, 5)
168         >>> rgb = HlsToRgb()
169         >>> output = rgb(input)  # 2x3x4x5
170     """
171 
172     def forward(self, image: Tensor) -> Tensor:
173         return hls_to_rgb(image)
174
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kornia/color/hls.py b/kornia/color/hls.py
--- a/kornia/color/hls.py
+++ b/kornia/color/hls.py
@@ -7,7 +7,7 @@
 
 
 def rgb_to_hls(image: Tensor, eps: float = 1e-8) -> Tensor:
-    r"""Convert a RGB image to HLS.
+    r"""Convert an RGB image to HLS.
 
     .. image:: _static/img/rgb_to_hls.png
 
@@ -51,9 +51,7 @@
         # so, h, l and s require inplace operations
         # NOTE: stack() increases in a 10% the cost in colab
         image_hls = torch.empty_like(image)
-        h = torch.select(image_hls, -3, 0)
-        l_ = torch.select(image_hls, -3, 1)
-        s = torch.select(image_hls, -3, 2)
+        h, l_, s = image_hls[..., 0, :, :], image_hls[..., 1, :, :], image_hls[..., 2, :, :]
         torch.add(maxc, minc, out=l_)  # l = max + min
         torch.sub(maxc, minc, out=s)  # s = max - min
 
@@ -65,19 +63,18 @@
     l_ /= 2  # luminance
 
     # note that r,g and b were previously div by (max - min)
-    r = torch.select(im, -3, 0)
-    g = torch.select(im, -3, 1)
-    b = torch.select(im, -3, 2)
+    r, g, b = im[..., 0, :, :], im[..., 1, :, :], im[..., 2, :, :]
     # h[imax == 0] = (((g - b) / (max - min)) % 6)[imax == 0]
     # h[imax == 1] = (((b - r) / (max - min)) + 2)[imax == 1]
     # h[imax == 2] = (((r - g) / (max - min)) + 4)[imax == 2]
-    cond = imax.unsqueeze(-3) == _RGB2HSL_IDX
+    cond = imax[..., None, :, :] == _RGB2HSL_IDX
     if image.requires_grad:
-        h = torch.mul((g - b) % 6, torch.select(cond, -3, 0))
+        h = ((g - b) % 6) * cond[..., 0, :, :]
     else:
-        torch.mul((g - b).remainder(6), torch.select(cond, -3, 0), out=h)
-    h += torch.add(b - r, 2) * torch.select(cond, -3, 1)
-    h += torch.add(r - g, 4) * torch.select(cond, -3, 2)
+        # replacing `torch.mul` with `out=h` with python * operator gives wrong results
+        torch.mul((g - b) % 6, cond[..., 0, :, :], out=h)
+    h += (b - r + 2) * cond[..., 1, :, :]
+    h += (r - g + 4) * cond[..., 2, :, :]
     # h = 2.0 * math.pi * (60.0 * h) / 360.0
     h *= math.pi / 3.0  # hue [0, 2*pi]
 
@@ -110,9 +107,9 @@
     _HLS2RGB = tensor([[[0.0]], [[8.0]], [[4.0]]], device=image.device, dtype=image.dtype)  # 3x1x1
 
     im: Tensor = image.unsqueeze(-4)
-    h: Tensor = torch.select(im, -3, 0)
-    l: Tensor = torch.select(im, -3, 1)
-    s: Tensor = torch.select(im, -3, 2)
+    h: Tensor = im[..., 0, :, :]
+    l: Tensor = im[..., 1, :, :]
+    s: Tensor = im[..., 2, :, :]
     h = h * (6 / math.pi)  # h * 360 / (2 * math.pi) / 30
     a = s * torch.min(l, 1.0 - l)

{"golden_diff": "diff --git a/kornia/color/hls.py b/kornia/color/hls.py\n--- a/kornia/color/hls.py\n+++ b/kornia/color/hls.py\n@@ -7,7 +7,7 @@\n \n \n def rgb_to_hls(image: Tensor, eps: float = 1e-8) -> Tensor:\n-    r\"\"\"Convert a RGB image to HLS.\n+    r\"\"\"Convert an RGB image to HLS.\n \n     .. image:: _static/img/rgb_to_hls.png\n \n@@ -51,9 +51,7 @@\n         # so, h, l and s require inplace operations\n         # NOTE: stack() increases in a 10% the cost in colab\n         image_hls = torch.empty_like(image)\n-        h = torch.select(image_hls, -3, 0)\n-        l_ = torch.select(image_hls, -3, 1)\n-        s = torch.select(image_hls, -3, 2)\n+        h, l_, s = image_hls[..., 0, :, :], image_hls[..., 1, :, :], image_hls[..., 2, :, :]\n         torch.add(maxc, minc, out=l_)  # l = max + min\n         torch.sub(maxc, minc, out=s)  # s = max - min\n \n@@ -65,19 +63,18 @@\n     l_ /= 2  # luminance\n \n     # note that r,g and b were previously div by (max - min)\n-    r = torch.select(im, -3, 0)\n-    g = torch.select(im, -3, 1)\n-    b = torch.select(im, -3, 2)\n+    r, g, b = im[..., 0, :, :], im[..., 1, :, :], im[..., 2, :, :]\n     # h[imax == 0] = (((g - b) / (max - min)) % 6)[imax == 0]\n     # h[imax == 1] = (((b - r) / (max - min)) + 2)[imax == 1]\n     # h[imax == 2] = (((r - g) / (max - min)) + 4)[imax == 2]\n-    cond = imax.unsqueeze(-3) == _RGB2HSL_IDX\n+    cond = imax[..., None, :, :] == _RGB2HSL_IDX\n     if image.requires_grad:\n-        h = torch.mul((g - b) % 6, torch.select(cond, -3, 0))\n+        h = ((g - b) % 6) * cond[..., 0, :, :]\n     else:\n-        torch.mul((g - b).remainder(6), torch.select(cond, -3, 0), out=h)\n-    h += torch.add(b - r, 2) * torch.select(cond, -3, 1)\n-    h += torch.add(r - g, 4) * torch.select(cond, -3, 2)\n+        # replacing `torch.mul` with `out=h` with python * operator gives wrong results\n+        torch.mul((g - b) % 6, cond[..., 0, :, :], out=h)\n+    h += (b - r + 2) * cond[..., 1, :, :]\n+    h += (r - g + 4) * cond[..., 2, :, :]\n     # h = 2.0 * math.pi * (60.0 * h) / 360.0\n     h *= math.pi / 3.0  # hue [0, 2*pi]\n \n@@ -110,9 +107,9 @@\n     _HLS2RGB = tensor([[[0.0]], [[8.0]], [[4.0]]], device=image.device, dtype=image.dtype)  # 3x1x1\n \n     im: Tensor = image.unsqueeze(-4)\n-    h: Tensor = torch.select(im, -3, 0)\n-    l: Tensor = torch.select(im, -3, 1)\n-    s: Tensor = torch.select(im, -3, 2)\n+    h: Tensor = im[..., 0, :, :]\n+    l: Tensor = im[..., 1, :, :]\n+    s: Tensor = im[..., 2, :, :]\n     h = h * (6 / math.pi)  # h * 360 / (2 * math.pi) / 30\n     a = s * torch.min(l, 1.0 - l)\n", "issue": "Use more pythonic expressions in rgb to hls\nMake improvements in the `kornia/color/hls.py` module to use more pythonic expressions. Ex:\r\n```diff\r\n-    r = torch.select(im, -3, 0)\r\n+   r = im[\u2026, 0, :,:]\r\n```\r\n\r\n\r\n_Originally posted by @edgarriba in https://github.com/kornia/kornia/pull/2030#discussion_r1032065189_\r\n      \n", "before_files": [{"content": "import math\nfrom typing import Tuple\n\nimport torch\n\nfrom kornia.core import Module, Tensor, stack, tensor, where\n\n\ndef rgb_to_hls(image: Tensor, eps: float = 1e-8) -> Tensor:\n    r\"\"\"Convert a RGB image to HLS.\n\n    .. image:: _static/img/rgb_to_hls.png\n\n    The image data is assumed to be in the range of (0, 1).\n\n    NOTE: this method cannot be compiled with JIT in pytohrch < 1.7.0\n\n    Args:\n        image: RGB image to be converted to HLS with shape :math:`(*, 3, H, W)`.\n        eps: epsilon value to avoid div by zero.\n\n    Returns:\n        HLS version of the image with shape :math:`(*, 3, H, W)`.\n\n    Example:\n        >>> input = torch.rand(2, 3, 4, 5)\n        >>> output = rgb_to_hls(input)  # 2x3x4x5\n    \"\"\"\n    if not isinstance(image, Tensor):\n        raise TypeError(f\"Input type is not a Tensor. Got {type(image)}\")\n\n    if len(image.shape) < 3 or image.shape[-3] != 3:\n        raise ValueError(f\"Input size must have a shape of (*, 3, H, W). Got {image.shape}\")\n\n    _RGB2HSL_IDX = tensor([[[0.0]], [[1.0]], [[2.0]]], device=image.device, dtype=image.dtype)  # 3x1x1\n\n    _img_max: Tuple[Tensor, Tensor] = image.max(-3)\n    maxc = _img_max[0]\n    imax = _img_max[1]\n    minc: Tensor = image.min(-3)[0]\n\n    if image.requires_grad:\n        l_ = maxc + minc\n        s = maxc - minc\n        # weird behaviour with undefined vars in JIT...\n        # scripting requires image_hls be defined even if it is not used :S\n        h = l_  # assign to any tensor...\n        image_hls = l_  # assign to any tensor...\n    else:\n        # define the resulting image to avoid the torch.stack([h, l, s])\n        # so, h, l and s require inplace operations\n        # NOTE: stack() increases in a 10% the cost in colab\n        image_hls = torch.empty_like(image)\n        h = torch.select(image_hls, -3, 0)\n        l_ = torch.select(image_hls, -3, 1)\n        s = torch.select(image_hls, -3, 2)\n        torch.add(maxc, minc, out=l_)  # l = max + min\n        torch.sub(maxc, minc, out=s)  # s = max - min\n\n    # precompute image / (max - min)\n    im = image / (s + eps).unsqueeze(-3)\n\n    # epsilon cannot be inside the torch.where to avoid precision issues\n    s /= where(l_ < 1.0, l_, 2.0 - l_) + eps  # saturation\n    l_ /= 2  # luminance\n\n    # note that r,g and b were previously div by (max - min)\n    r = torch.select(im, -3, 0)\n    g = torch.select(im, -3, 1)\n    b = torch.select(im, -3, 2)\n    # h[imax == 0] = (((g - b) / (max - min)) % 6)[imax == 0]\n    # h[imax == 1] = (((b - r) / (max - min)) + 2)[imax == 1]\n    # h[imax == 2] = (((r - g) / (max - min)) + 4)[imax == 2]\n    cond = imax.unsqueeze(-3) == _RGB2HSL_IDX\n    if image.requires_grad:\n        h = torch.mul((g - b) % 6, torch.select(cond, -3, 0))\n    else:\n        torch.mul((g - b).remainder(6), torch.select(cond, -3, 0), out=h)\n    h += torch.add(b - r, 2) * torch.select(cond, -3, 1)\n    h += torch.add(r - g, 4) * torch.select(cond, -3, 2)\n    # h = 2.0 * math.pi * (60.0 * h) / 360.0\n    h *= math.pi / 3.0  # hue [0, 2*pi]\n\n    if image.requires_grad:\n        return stack([h, l_, s], -3)\n    return image_hls\n\n\ndef hls_to_rgb(image: Tensor) -> Tensor:\n    r\"\"\"Convert a HLS image to RGB.\n\n    The image data is assumed to be in the range of (0, 1).\n\n    Args:\n        image: HLS image to be converted to RGB with shape :math:`(*, 3, H, W)`.\n\n    Returns:\n        RGB version of the image with shape :math:`(*, 3, H, W)`.\n\n    Example:\n        >>> input = torch.rand(2, 3, 4, 5)\n        >>> output = hls_to_rgb(input)  # 2x3x4x5\n    \"\"\"\n    if not isinstance(image, Tensor):\n        raise TypeError(f\"Input type is not a Tensor. Got {type(image)}\")\n\n    if len(image.shape) < 3 or image.shape[-3] != 3:\n        raise ValueError(f\"Input size must have a shape of (*, 3, H, W). Got {image.shape}\")\n\n    _HLS2RGB = tensor([[[0.0]], [[8.0]], [[4.0]]], device=image.device, dtype=image.dtype)  # 3x1x1\n\n    im: Tensor = image.unsqueeze(-4)\n    h: Tensor = torch.select(im, -3, 0)\n    l: Tensor = torch.select(im, -3, 1)\n    s: Tensor = torch.select(im, -3, 2)\n    h = h * (6 / math.pi)  # h * 360 / (2 * math.pi) / 30\n    a = s * torch.min(l, 1.0 - l)\n\n    # kr = (0 + h) % 12\n    # kg = (8 + h) % 12\n    # kb = (4 + h) % 12\n    k: Tensor = (h + _HLS2RGB) % 12\n\n    # l - a * max(min(min(k - 3.0, 9.0 - k), 1), -1)\n    mink = torch.min(k - 3.0, 9.0 - k)\n    return torch.addcmul(l, a, mink.clamp_(min=-1.0, max=1.0), value=-1)\n\n\nclass RgbToHls(Module):\n    r\"\"\"Convert an image from RGB to HLS.\n\n    The image data is assumed to be in the range of (0, 1).\n\n    Returns:\n        HLS version of the image.\n\n    Shape:\n        - image: :math:`(*, 3, H, W)`\n        - output: :math:`(*, 3, H, W)`\n\n    Examples:\n        >>> input = torch.rand(2, 3, 4, 5)\n        >>> hls = RgbToHls()\n        >>> output = hls(input)  # 2x3x4x5\n    \"\"\"\n\n    def forward(self, image: Tensor) -> Tensor:\n        return rgb_to_hls(image)\n\n\nclass HlsToRgb(Module):\n    r\"\"\"Convert an image from HLS to RGB.\n\n    The image data is assumed to be in the range of (0, 1).\n\n    Returns:\n        RGB version of the image.\n\n    Shape:\n        - input: :math:`(*, 3, H, W)`\n        - output: :math:`(*, 3, H, W)`\n\n    Reference:\n        https://en.wikipedia.org/wiki/HSL_and_HSV\n\n    Examples:\n        >>> input = torch.rand(2, 3, 4, 5)\n        >>> rgb = HlsToRgb()\n        >>> output = rgb(input)  # 2x3x4x5\n    \"\"\"\n\n    def forward(self, image: Tensor) -> Tensor:\n        return hls_to_rgb(image)\n", "path": "kornia/color/hls.py"}], "after_files": [{"content": "import math\nfrom typing import Tuple\n\nimport torch\n\nfrom kornia.core import Module, Tensor, stack, tensor, where\n\n\ndef rgb_to_hls(image: Tensor, eps: float = 1e-8) -> Tensor:\n    r\"\"\"Convert an RGB image to HLS.\n\n    .. image:: _static/img/rgb_to_hls.png\n\n    The image data is assumed to be in the range of (0, 1).\n\n    NOTE: this method cannot be compiled with JIT in pytohrch < 1.7.0\n\n    Args:\n        image: RGB image to be converted to HLS with shape :math:`(*, 3, H, W)`.\n        eps: epsilon value to avoid div by zero.\n\n    Returns:\n        HLS version of the image with shape :math:`(*, 3, H, W)`.\n\n    Example:\n        >>> input = torch.rand(2, 3, 4, 5)\n        >>> output = rgb_to_hls(input)  # 2x3x4x5\n    \"\"\"\n    if not isinstance(image, Tensor):\n        raise TypeError(f\"Input type is not a Tensor. Got {type(image)}\")\n\n    if len(image.shape) < 3 or image.shape[-3] != 3:\n        raise ValueError(f\"Input size must have a shape of (*, 3, H, W). Got {image.shape}\")\n\n    _RGB2HSL_IDX = tensor([[[0.0]], [[1.0]], [[2.0]]], device=image.device, dtype=image.dtype)  # 3x1x1\n\n    _img_max: Tuple[Tensor, Tensor] = image.max(-3)\n    maxc = _img_max[0]\n    imax = _img_max[1]\n    minc: Tensor = image.min(-3)[0]\n\n    if image.requires_grad:\n        l_ = maxc + minc\n        s = maxc - minc\n        # weird behaviour with undefined vars in JIT...\n        # scripting requires image_hls be defined even if it is not used :S\n        h = l_  # assign to any tensor...\n        image_hls = l_  # assign to any tensor...\n    else:\n        # define the resulting image to avoid the torch.stack([h, l, s])\n        # so, h, l and s require inplace operations\n        # NOTE: stack() increases in a 10% the cost in colab\n        image_hls = torch.empty_like(image)\n        h, l_, s = image_hls[..., 0, :, :], image_hls[..., 1, :, :], image_hls[..., 2, :, :]\n        torch.add(maxc, minc, out=l_)  # l = max + min\n        torch.sub(maxc, minc, out=s)  # s = max - min\n\n    # precompute image / (max - min)\n    im = image / (s + eps).unsqueeze(-3)\n\n    # epsilon cannot be inside the torch.where to avoid precision issues\n    s /= where(l_ < 1.0, l_, 2.0 - l_) + eps  # saturation\n    l_ /= 2  # luminance\n\n    # note that r,g and b were previously div by (max - min)\n    r, g, b = im[..., 0, :, :], im[..., 1, :, :], im[..., 2, :, :]\n    # h[imax == 0] = (((g - b) / (max - min)) % 6)[imax == 0]\n    # h[imax == 1] = (((b - r) / (max - min)) + 2)[imax == 1]\n    # h[imax == 2] = (((r - g) / (max - min)) + 4)[imax == 2]\n    cond = imax[..., None, :, :] == _RGB2HSL_IDX\n    if image.requires_grad:\n        h = ((g - b) % 6) * cond[..., 0, :, :]\n    else:\n        # replacing `torch.mul` with `out=h` with python * operator gives wrong results\n        torch.mul((g - b) % 6, cond[..., 0, :, :], out=h)\n    h += (b - r + 2) * cond[..., 1, :, :]\n    h += (r - g + 4) * cond[..., 2, :, :]\n    # h = 2.0 * math.pi * (60.0 * h) / 360.0\n    h *= math.pi / 3.0  # hue [0, 2*pi]\n\n    if image.requires_grad:\n        return stack([h, l_, s], -3)\n    return image_hls\n\n\ndef hls_to_rgb(image: Tensor) -> Tensor:\n    r\"\"\"Convert a HLS image to RGB.\n\n    The image data is assumed to be in the range of (0, 1).\n\n    Args:\n        image: HLS image to be converted to RGB with shape :math:`(*, 3, H, W)`.\n\n    Returns:\n        RGB version of the image with shape :math:`(*, 3, H, W)`.\n\n    Example:\n        >>> input = torch.rand(2, 3, 4, 5)\n        >>> output = hls_to_rgb(input)  # 2x3x4x5\n    \"\"\"\n    if not isinstance(image, Tensor):\n        raise TypeError(f\"Input type is not a Tensor. Got {type(image)}\")\n\n    if len(image.shape) < 3 or image.shape[-3] != 3:\n        raise ValueError(f\"Input size must have a shape of (*, 3, H, W). Got {image.shape}\")\n\n    _HLS2RGB = tensor([[[0.0]], [[8.0]], [[4.0]]], device=image.device, dtype=image.dtype)  # 3x1x1\n\n    im: Tensor = image.unsqueeze(-4)\n    h: Tensor = im[..., 0, :, :]\n    l: Tensor = im[..., 1, :, :]\n    s: Tensor = im[..., 2, :, :]\n    h = h * (6 / math.pi)  # h * 360 / (2 * math.pi) / 30\n    a = s * torch.min(l, 1.0 - l)\n\n    # kr = (0 + h) % 12\n    # kg = (8 + h) % 12\n    # kb = (4 + h) % 12\n    k: Tensor = (h + _HLS2RGB) % 12\n\n    # l - a * max(min(min(k - 3.0, 9.0 - k), 1), -1)\n    mink = torch.min(k - 3.0, 9.0 - k)\n    return torch.addcmul(l, a, mink.clamp_(min=-1.0, max=1.0), value=-1)\n\n\nclass RgbToHls(Module):\n    r\"\"\"Convert an image from RGB to HLS.\n\n    The image data is assumed to be in the range of (0, 1).\n\n    Returns:\n        HLS version of the image.\n\n    Shape:\n        - image: :math:`(*, 3, H, W)`\n        - output: :math:`(*, 3, H, W)`\n\n    Examples:\n        >>> input = torch.rand(2, 3, 4, 5)\n        >>> hls = RgbToHls()\n        >>> output = hls(input)  # 2x3x4x5\n    \"\"\"\n\n    def forward(self, image: Tensor) -> Tensor:\n        return rgb_to_hls(image)\n\n\nclass HlsToRgb(Module):\n    r\"\"\"Convert an image from HLS to RGB.\n\n    The image data is assumed to be in the range of (0, 1).\n\n    Returns:\n        RGB version of the image.\n\n    Shape:\n        - input: :math:`(*, 3, H, W)`\n        - output: :math:`(*, 3, H, W)`\n\n    Reference:\n        https://en.wikipedia.org/wiki/HSL_and_HSV\n\n    Examples:\n        >>> input = torch.rand(2, 3, 4, 5)\n        >>> rgb = HlsToRgb()\n        >>> output = rgb(input)  # 2x3x4x5\n    \"\"\"\n\n    def forward(self, image: Tensor) -> Tensor:\n        return hls_to_rgb(image)\n", "path": "kornia/color/hls.py"}]}