We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Bug] save pointcloud not updates num_points when inf
## 🐛 Bug

The function `K.utils.save_pointcloud_ply` doesn't update the final number of points to be serialized when one of the values contain an infinite value.

How to  fix:

update this line https://github.com/kornia/kornia/blob/master/kornia/utils/pointcloud_io.py#L34

```python
            if not bool(torch.isfinite(xyz).any()):
                continue
```
by

```python
            if not bool(torch.isfinite(xyz).any()):
                num_points -= 1
                continue
```

--- 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/utils/pointcloud_io.py`
Content:
```
1 import os
2 from typing import Optional
3 
4 import torch
5 
6 
7 def save_pointcloud_ply(filename: str, pointcloud: torch.Tensor) -> None:
8     r"""Utility function to save to disk a pointcloud in PLY format.
9 
10     Args:
11         filename: the path to save the pointcloud.
12         pointcloud: tensor containing the pointcloud to save.
13           The tensor must be in the shape of :math:`(*, 3)` where the last
14           component is assumed to be a 3d point coordinate :math:`(X, Y, Z)`.
15     """
16     if not isinstance(filename, str) and filename[-3:] == '.ply':
17         raise TypeError("Input filename must be a string in with the .ply  " "extension. Got {}".format(filename))
18 
19     if not torch.is_tensor(pointcloud):
20         raise TypeError(f"Input pointcloud type is not a torch.Tensor. Got {type(pointcloud)}")
21 
22     if not len(pointcloud.shape) == 3 and pointcloud.shape[-1] == 3:
23         raise TypeError("Input pointcloud must be in the following shape " "HxWx3. Got {}.".format(pointcloud.shape))
24 
25     # flatten the input pointcloud in a vector to iterate points
26     xyz_vec: torch.Tensor = pointcloud.reshape(-1, 3)
27 
28     with open(filename, 'w') as f:
29         data_str: str = ''
30         num_points: int = xyz_vec.shape[0]
31         for idx in range(num_points):
32             xyz = xyz_vec[idx]
33             if not bool(torch.isfinite(xyz).any()):
34                 continue
35             x: float = xyz[0].item()
36             y: float = xyz[1].item()
37             z: float = xyz[2].item()
38             data_str += f'{x} {y} {z}\n'
39 
40         f.write("ply\n")
41         f.write("format ascii 1.0\n")
42         f.write("comment arraiy generated\n")
43         f.write("element vertex %d\n" % num_points)
44         f.write("property double x\n")
45         f.write("property double y\n")
46         f.write("property double z\n")
47         f.write("end_header\n")
48         f.write(data_str)
49 
50 
51 def load_pointcloud_ply(filename: str, header_size: int = 8) -> torch.Tensor:
52     r"""Utility function to load from disk a pointcloud in PLY format.
53 
54     Args:
55         filename: the path to the pointcloud.
56         header_size: the size of the ply file header that will
57           be skipped during loading.
58 
59     Return:
60         tensor containing the loaded point with shape :math:`(*, 3)` where
61         :math:`*` represents the number of points.
62     """
63     if not isinstance(filename, str) and filename[-3:] == '.ply':
64         raise TypeError("Input filename must be a string in with the .ply  " "extension. Got {}".format(filename))
65     if not os.path.isfile(filename):
66         raise ValueError("Input filename is not an existing file.")
67     if not (isinstance(header_size, int) and header_size > 0):
68         raise TypeError(f"Input header_size must be a positive integer. Got {header_size}.")
69     # open the file and populate tensor
70     with open(filename) as f:
71         points = []
72 
73         # skip header
74         lines = f.readlines()[header_size:]
75 
76         # iterate over the points
77         for line in lines:
78             x_str, y_str, z_str = line.split()
79             points.append((torch.tensor(float(x_str)), torch.tensor(float(y_str)), torch.tensor(float(z_str))))
80 
81         # create tensor from list
82         pointcloud: torch.Tensor = torch.tensor(points)
83         return pointcloud
84
```
--- 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/utils/pointcloud_io.py b/kornia/utils/pointcloud_io.py
--- a/kornia/utils/pointcloud_io.py
+++ b/kornia/utils/pointcloud_io.py
@@ -31,6 +31,7 @@
         for idx in range(num_points):
             xyz = xyz_vec[idx]
             if not bool(torch.isfinite(xyz).any()):
+                num_points -= 1
                 continue
             x: float = xyz[0].item()
             y: float = xyz[1].item()

{"golden_diff": "diff --git a/kornia/utils/pointcloud_io.py b/kornia/utils/pointcloud_io.py\n--- a/kornia/utils/pointcloud_io.py\n+++ b/kornia/utils/pointcloud_io.py\n@@ -31,6 +31,7 @@\n         for idx in range(num_points):\n             xyz = xyz_vec[idx]\n             if not bool(torch.isfinite(xyz).any()):\n+                num_points -= 1\n                 continue\n             x: float = xyz[0].item()\n             y: float = xyz[1].item()\n", "issue": "[Bug] save pointcloud not updates num_points when inf\n## \ud83d\udc1b Bug\r\n\r\nThe function `K.utils.save_pointcloud_ply` doesn't update the final number of points to be serialized when one of the values contain an infinite value.\r\n\r\nHow to  fix:\r\n\r\nupdate this line https://github.com/kornia/kornia/blob/master/kornia/utils/pointcloud_io.py#L34\r\n\r\n```python\r\n            if not bool(torch.isfinite(xyz).any()):\r\n                continue\r\n```\r\nby\r\n\r\n```python\r\n            if not bool(torch.isfinite(xyz).any()):\r\n                num_points -= 1\r\n                continue\r\n```\n", "before_files": [{"content": "import os\nfrom typing import Optional\n\nimport torch\n\n\ndef save_pointcloud_ply(filename: str, pointcloud: torch.Tensor) -> None:\n    r\"\"\"Utility function to save to disk a pointcloud in PLY format.\n\n    Args:\n        filename: the path to save the pointcloud.\n        pointcloud: tensor containing the pointcloud to save.\n          The tensor must be in the shape of :math:`(*, 3)` where the last\n          component is assumed to be a 3d point coordinate :math:`(X, Y, Z)`.\n    \"\"\"\n    if not isinstance(filename, str) and filename[-3:] == '.ply':\n        raise TypeError(\"Input filename must be a string in with the .ply  \" \"extension. Got {}\".format(filename))\n\n    if not torch.is_tensor(pointcloud):\n        raise TypeError(f\"Input pointcloud type is not a torch.Tensor. Got {type(pointcloud)}\")\n\n    if not len(pointcloud.shape) == 3 and pointcloud.shape[-1] == 3:\n        raise TypeError(\"Input pointcloud must be in the following shape \" \"HxWx3. Got {}.\".format(pointcloud.shape))\n\n    # flatten the input pointcloud in a vector to iterate points\n    xyz_vec: torch.Tensor = pointcloud.reshape(-1, 3)\n\n    with open(filename, 'w') as f:\n        data_str: str = ''\n        num_points: int = xyz_vec.shape[0]\n        for idx in range(num_points):\n            xyz = xyz_vec[idx]\n            if not bool(torch.isfinite(xyz).any()):\n                continue\n            x: float = xyz[0].item()\n            y: float = xyz[1].item()\n            z: float = xyz[2].item()\n            data_str += f'{x} {y} {z}\\n'\n\n        f.write(\"ply\\n\")\n        f.write(\"format ascii 1.0\\n\")\n        f.write(\"comment arraiy generated\\n\")\n        f.write(\"element vertex %d\\n\" % num_points)\n        f.write(\"property double x\\n\")\n        f.write(\"property double y\\n\")\n        f.write(\"property double z\\n\")\n        f.write(\"end_header\\n\")\n        f.write(data_str)\n\n\ndef load_pointcloud_ply(filename: str, header_size: int = 8) -> torch.Tensor:\n    r\"\"\"Utility function to load from disk a pointcloud in PLY format.\n\n    Args:\n        filename: the path to the pointcloud.\n        header_size: the size of the ply file header that will\n          be skipped during loading.\n\n    Return:\n        tensor containing the loaded point with shape :math:`(*, 3)` where\n        :math:`*` represents the number of points.\n    \"\"\"\n    if not isinstance(filename, str) and filename[-3:] == '.ply':\n        raise TypeError(\"Input filename must be a string in with the .ply  \" \"extension. Got {}\".format(filename))\n    if not os.path.isfile(filename):\n        raise ValueError(\"Input filename is not an existing file.\")\n    if not (isinstance(header_size, int) and header_size > 0):\n        raise TypeError(f\"Input header_size must be a positive integer. Got {header_size}.\")\n    # open the file and populate tensor\n    with open(filename) as f:\n        points = []\n\n        # skip header\n        lines = f.readlines()[header_size:]\n\n        # iterate over the points\n        for line in lines:\n            x_str, y_str, z_str = line.split()\n            points.append((torch.tensor(float(x_str)), torch.tensor(float(y_str)), torch.tensor(float(z_str))))\n\n        # create tensor from list\n        pointcloud: torch.Tensor = torch.tensor(points)\n        return pointcloud\n", "path": "kornia/utils/pointcloud_io.py"}], "after_files": [{"content": "import os\nfrom typing import Optional\n\nimport torch\n\n\ndef save_pointcloud_ply(filename: str, pointcloud: torch.Tensor) -> None:\n    r\"\"\"Utility function to save to disk a pointcloud in PLY format.\n\n    Args:\n        filename: the path to save the pointcloud.\n        pointcloud: tensor containing the pointcloud to save.\n          The tensor must be in the shape of :math:`(*, 3)` where the last\n          component is assumed to be a 3d point coordinate :math:`(X, Y, Z)`.\n    \"\"\"\n    if not isinstance(filename, str) and filename[-3:] == '.ply':\n        raise TypeError(\"Input filename must be a string in with the .ply  \" \"extension. Got {}\".format(filename))\n\n    if not torch.is_tensor(pointcloud):\n        raise TypeError(f\"Input pointcloud type is not a torch.Tensor. Got {type(pointcloud)}\")\n\n    if not len(pointcloud.shape) == 3 and pointcloud.shape[-1] == 3:\n        raise TypeError(\"Input pointcloud must be in the following shape \" \"HxWx3. Got {}.\".format(pointcloud.shape))\n\n    # flatten the input pointcloud in a vector to iterate points\n    xyz_vec: torch.Tensor = pointcloud.reshape(-1, 3)\n\n    with open(filename, 'w') as f:\n        data_str: str = ''\n        num_points: int = xyz_vec.shape[0]\n        for idx in range(num_points):\n            xyz = xyz_vec[idx]\n            if not bool(torch.isfinite(xyz).any()):\n                num_points -= 1\n                continue\n            x: float = xyz[0].item()\n            y: float = xyz[1].item()\n            z: float = xyz[2].item()\n            data_str += f'{x} {y} {z}\\n'\n\n        f.write(\"ply\\n\")\n        f.write(\"format ascii 1.0\\n\")\n        f.write(\"comment arraiy generated\\n\")\n        f.write(\"element vertex %d\\n\" % num_points)\n        f.write(\"property double x\\n\")\n        f.write(\"property double y\\n\")\n        f.write(\"property double z\\n\")\n        f.write(\"end_header\\n\")\n        f.write(data_str)\n\n\ndef load_pointcloud_ply(filename: str, header_size: int = 8) -> torch.Tensor:\n    r\"\"\"Utility function to load from disk a pointcloud in PLY format.\n\n    Args:\n        filename: the path to the pointcloud.\n        header_size: the size of the ply file header that will\n          be skipped during loading.\n\n    Return:\n        tensor containing the loaded point with shape :math:`(*, 3)` where\n        :math:`*` represents the number of points.\n    \"\"\"\n    if not isinstance(filename, str) and filename[-3:] == '.ply':\n        raise TypeError(\"Input filename must be a string in with the .ply  \" \"extension. Got {}\".format(filename))\n    if not os.path.isfile(filename):\n        raise ValueError(\"Input filename is not an existing file.\")\n    if not (isinstance(header_size, int) and header_size > 0):\n        raise TypeError(f\"Input header_size must be a positive integer. Got {header_size}.\")\n    # open the file and populate tensor\n    with open(filename) as f:\n        points = []\n\n        # skip header\n        lines = f.readlines()[header_size:]\n\n        # iterate over the points\n        for line in lines:\n            x_str, y_str, z_str = line.split()\n            points.append((torch.tensor(float(x_str)), torch.tensor(float(y_str)), torch.tensor(float(z_str))))\n\n        # create tensor from list\n        pointcloud: torch.Tensor = torch.tensor(points)\n        return pointcloud\n", "path": "kornia/utils/pointcloud_io.py"}]}