Metadata-Version: 2.4
Name: ncut_pytorch
Version: 2.3.2
Summary: Normalized Cut and Spectral Embedding
Author-email: Huzheng Yang <huze.yann@gmail.com>
License-Expression: MIT
Project-URL: Documentation, https://ncut-pytorch.readthedocs.io/
Project-URL: Github, https://github.com/huzeyann/ncut_pytorch/
Project-URL: PyPI, https://pypi.org/project/ncut_pytorch/
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Image Processing
Classifier: Topic :: Scientific/Engineering :: Mathematics
Requires-Python: >=3
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy<2.0
Requires-Dist: fpsample>=0.2.0
Requires-Dist: tqdm
Requires-Dist: pillow
Requires-Dist: opencv-python
Requires-Dist: matplotlib
Requires-Dist: umap-learn
Provides-Extra: torch
Requires-Dist: torch>=2.7.1; extra == "torch"
Requires-Dist: pytorch-lightning~=2.0; extra == "torch"
Requires-Dist: torchvision>=0.23.0; extra == "torch"
Provides-Extra: cmap
Requires-Dist: pycolormap_2d; extra == "cmap"
Requires-Dist: scikit-image; extra == "cmap"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
Requires-Dist: tabulate; extra == "dev"
Requires-Dist: pytest-benchmark>=5.1.0; extra == "dev"
Provides-Extra: all
Requires-Dist: ncut_pytorch[cmap,dev,torch]; extra == "all"
Dynamic: license-file


### [🌐Documentation (old version)](https://ncut-pytorch.readthedocs.io/) | [🤗HuggingFace Demo](https://huggingface.co/spaces/huzey/ncut-pytorch)


## Nyström Normalized Cut

Normalized Cut with Nyström approximation, handle large-scale graph with $O(n)$ time complexity, $O(1)$ space complexity. Solve million-scale graph in milliseconds.



https://github.com/user-attachments/assets/cdf53e33-bb34-4a84-b1f4-679b66da1d48




<div align="center">
  Video: Ncut spectral embedding eigenvectors, on SAM features.
</div>


---

## Installation

<div style="text-align:">
    <pre><code class="language-shell">pip install -U ncut-pytorch</code></pre>
</div>


## Quick Start: plain Ncut

### Default Workflow: Color Visualization

```py linenums="1"
import torch
from ncut_pytorch import Ncut
from ncut_pytorch.color import umap_color, tsne_color, mspace_color

features = torch.rand(1960, 768)
eigvecs = Ncut(n_eig=20).fit_transform(features)  # (1960, 20)

# Color visualizations (default workflow)
rgb_umap = umap_color(eigvecs)      # UMAP-based RGB
rgb_tsne = tsne_color(eigvecs)       # t-SNE-based RGB  
rgb_mspace = mspace_color(eigvecs)  # M-space RGB
```

### Alternative Workflow: Discrete Segmentation

```py linenums="1"
import torch
from ncut_pytorch import Ncut, kway_ncut

features = torch.rand(1960, 768)
eigvecs = Ncut(n_eig=20).fit_transform(features)  # (1960, 20)

# Discrete segmentation (alternative workflow)
kway_eigvecs = kway_ncut(eigvecs)
cluster_assignment = kway_eigvecs.argmax(1)
cluster_centroids = kway_eigvecs.argmax(0)
```

## Quick Start: Ncut DINOv3 Predictor

```py linenums="1"
from ncut_pytorch.predictor import NcutDinov3Predictor
from PIL import Image

predictor = NcutDinov3Predictor(model_cfg="dinov3_vitl16")
predictor = predictor.to('cuda')

images = [Image.open(f"images/view_{i}.jpg") for i in range(4)]
predictor.set_images(images)

image = predictor.summary(n_segments=[10, 25, 50, 100], draw_border=True)
display(image)

```

![summary](https://github.com/user-attachments/assets/a5d8a966-990b-4f6d-be10-abb00291bee2)



More examples and detailed usage can be found in the `examples` directory.

## Performance

- `ncut_pytorch.Ncut` is $O(n)$ time complexity

- `sklearn.SpectralEmbedding` is $O(n^2)$ time complexity.

#### Setup:

CPU: Intel(R) Core(TM) i9-13900K CPU

RAM: 128 GiB

GPU: RTX 4090 24 GiB

SYSTEM: Ubuntu 22.04.3 LTS

#### Run benchmark:


```shell
pytest unit_tests/bench_speed.py --benchmark-columns=mean,stddev --benchmark-sort=mean
```

#### Results:

```
------------- benchmark 'ncut-pytorch (CPU) vs sklearn': 8 tests ------------
Name (time in ms)                        Mean                StdDev          
-----------------------------------------------------------------------------
test_ncut_cpu_100_data_10_eig          2.5536 (1.0)          0.2782 (1.0)    
test_sklearn_100_data_10_eig           4.0913 (1.60)         1.6749 (6.02)   
test_ncut_cpu_300_data_10_eig          4.9034 (1.92)         1.6575 (5.96)   
test_sklearn_300_data_10_eig          10.1861 (3.99)         3.8870 (13.97)  
test_ncut_cpu_1000_data_10_eig        11.1968 (4.38)         1.7070 (6.13)   
test_ncut_cpu_3000_data_10_eig        38.6101 (15.12)        1.6379 (5.89)   
test_sklearn_1000_data_10_eig        193.5934 (75.81)        8.1933 (29.45)  
test_sklearn_3000_data_10_eig      1,246.4295 (488.11)   1,047.0191 (>1000.0)
-----------------------------------------------------------------------------
```
```
------------- benchmark 'ncut-pytorch (GPU) n_data': 5 tests -------------
Name (time in ms)                         Mean            StdDev          
--------------------------------------------------------------------------
test_ncut_gpu_100_data_10_eig           2.9564 (1.0)      0.1816 (1.0)    
test_ncut_gpu_1000_data_10_eig          4.6938 (1.59)     0.3933 (2.17)   
test_ncut_gpu_10000_data_10_eig        67.9607 (22.98)    4.0902 (22.52)  
test_ncut_gpu_100000_data_10_eig      396.9994 (134.29)   3.6202 (19.93)  
test_ncut_gpu_1000000_data_10_eig     798.4598 (270.08)   1.5704 (8.65)   
--------------------------------------------------------------------------
```
```
------------- benchmark 'ncut-pytorch (GPU) n_eig': 3 tests --------------
Name (time in ms)                         Mean            StdDev          
--------------------------------------------------------------------------
test_ncut_gpu_10000_data_10_eig        67.9607 (1.0)      4.0902 (10.76)  
test_ncut_gpu_10000_data_100_eig       74.0033 (1.09)     0.7856 (2.07)   
test_ncut_gpu_10000_data_1000_eig     179.8690 (2.65)     0.3801 (1.0)    
--------------------------------------------------------------------------
```


#### Run benchmark:

```shell
python unit_tests/bench_memory.py
```

#### Results:

`ncut-pytorch.Ncut` is $O(1)$ space complexity

```
+---------------+------------------------+
| Data Points   |   Peak GPU Memory (MB) |
+===============+========================+
| 1,000         |                   8.14 |
+---------------+------------------------+
| 10,000        |                   0.1  |
+---------------+------------------------+
| 100,000       |                   0.39 |
+---------------+------------------------+
| 1,000,000     |                   0.39 |
+---------------+------------------------+
```



## Citation

```
@misc{yang2024alignedcutvisualconceptsdiscovery,
      title={AlignedCut: Visual Concepts Discovery on Brain-Guided Universal Feature Space}, 
      author={Huzheng Yang and James Gee and Jianbo Shi},
      year={2024},
      eprint={2406.18344},
      archivePrefix={arXiv},
      primaryClass={cs.CV},
      url={https://arxiv.org/abs/2406.18344}, 
}
```
