segment-geospatial 1.2.0__tar.gz → 1.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.pre-commit-config.yaml +2 -2
  2. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/PKG-INFO +28 -3
  3. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/README.md +26 -1
  4. segment_geospatial-1.2.2/docs/faq.md +48 -0
  5. segment_geospatial-1.2.2/docs/installation.md +277 -0
  6. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/pyproject.toml +3 -3
  7. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/samgeo/__init__.py +1 -1
  8. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/samgeo/common.py +54 -12
  9. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/samgeo/fer.py +2 -2
  10. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/samgeo/samgeo3.py +31 -7
  11. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/samgeo/text_sam.py +1 -1
  12. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/segment_geospatial.egg-info/PKG-INFO +28 -3
  13. segment_geospatial-1.2.0/docs/faq.md +0 -1
  14. segment_geospatial-1.2.0/docs/installation.md +0 -102
  15. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.editorconfig +0 -0
  16. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/FUNDING.yml +0 -0
  17. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  18. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  19. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  20. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/dependabot.yaml +0 -0
  21. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/workflows/docker-image.yml +0 -0
  22. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/workflows/docker-publish.yml +0 -0
  23. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/workflows/docs-build.yml +0 -0
  24. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/workflows/docs.yml +0 -0
  25. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/workflows/draft-pdf.yml +0 -0
  26. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/workflows/macos.yml +0 -0
  27. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/workflows/pypi.yml +0 -0
  28. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/workflows/ubuntu.yml +0 -0
  29. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.github/workflows/windows.yml +0 -0
  30. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/.gitignore +0 -0
  31. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/CITATION.cff +0 -0
  32. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/CODE_OF_CONDUCT.md +0 -0
  33. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/Dockerfile +0 -0
  34. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/LICENSE +0 -0
  35. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/MANIFEST.in +0 -0
  36. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/CNAME +0 -0
  37. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/assets/README.md +0 -0
  38. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/assets/favicon.png +0 -0
  39. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/assets/logo.png +0 -0
  40. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/assets/logo_rect.png +0 -0
  41. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/caption.md +0 -0
  42. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/changelog.md +0 -0
  43. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/changelog_update.py +0 -0
  44. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/common.md +0 -0
  45. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/contributing.md +0 -0
  46. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/arcgis.ipynb +0 -0
  47. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/automatic_mask_generator.ipynb +0 -0
  48. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/automatic_mask_generator_hq.ipynb +0 -0
  49. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/box_prompts.ipynb +0 -0
  50. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/data/tree_boxes.geojson +0 -0
  51. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/fast_sam.ipynb +0 -0
  52. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/image_captioning.ipynb +0 -0
  53. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/input_prompts.ipynb +0 -0
  54. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/input_prompts_hq.ipynb +0 -0
  55. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/maxar_open_data.ipynb +0 -0
  56. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam2_automatic.ipynb +0 -0
  57. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam2_box_prompts.ipynb +0 -0
  58. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam2_point_prompts.ipynb +0 -0
  59. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam2_predictor.ipynb +0 -0
  60. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam2_text_prompts.ipynb +0 -0
  61. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam2_video.ipynb +0 -0
  62. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam3_automated_segmentation.ipynb +0 -0
  63. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam3_batch_segmentation.ipynb +0 -0
  64. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam3_box_prompts.ipynb +0 -0
  65. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam3_image_segmentation.ipynb +0 -0
  66. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam3_image_segmentation_jpg.ipynb +0 -0
  67. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam3_interactive.ipynb +0 -0
  68. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam3_object_tracking.ipynb +0 -0
  69. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam3_point_prompts.ipynb +0 -0
  70. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam3_point_prompts_batch.ipynb +0 -0
  71. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam3_tiled_segmentation.ipynb +0 -0
  72. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam3_video_masks.ipynb +0 -0
  73. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam3_video_prompts.ipynb +0 -0
  74. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/sam3_video_segmentation.ipynb +0 -0
  75. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/satellite-predictor.ipynb +0 -0
  76. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/satellite.ipynb +0 -0
  77. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/text_prompts.ipynb +0 -0
  78. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/text_prompts_batch.ipynb +0 -0
  79. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/text_swimming_pools.ipynb +0 -0
  80. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/examples/tree_mapping.ipynb +0 -0
  81. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/fast_sam.md +0 -0
  82. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/hq_sam.md +0 -0
  83. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/index.md +0 -0
  84. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/overrides/main.html +0 -0
  85. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/samgeo.md +0 -0
  86. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/samgeo2.md +0 -0
  87. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/samgeo3.md +0 -0
  88. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/text_sam.md +0 -0
  89. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/usage.md +0 -0
  90. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/workshops/AIforGood_2025.ipynb +0 -0
  91. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/workshops/IPPN_2024.ipynb +0 -0
  92. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/workshops/cn_workshop.ipynb +0 -0
  93. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/workshops/jupytext.toml +0 -0
  94. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/docs/workshops/purdue.ipynb +0 -0
  95. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/mkdocs.yml +0 -0
  96. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/paper/10.21105.joss.05663.pdf +0 -0
  97. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/paper/paper.bib +0 -0
  98. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/paper/paper.md +0 -0
  99. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/qgis-samgeo-plugin/LICENSE +0 -0
  100. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/qgis-samgeo-plugin/README.md +0 -0
  101. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/qgis-samgeo-plugin/__init__.py +0 -0
  102. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/qgis-samgeo-plugin/icons/icon.png +0 -0
  103. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/qgis-samgeo-plugin/install_plugin.py +0 -0
  104. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/qgis-samgeo-plugin/install_plugin.sh +0 -0
  105. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/qgis-samgeo-plugin/map_tools.py +0 -0
  106. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/qgis-samgeo-plugin/metadata.txt +0 -0
  107. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/qgis-samgeo-plugin/resources.py +0 -0
  108. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/qgis-samgeo-plugin/samgeo_plugin.py +0 -0
  109. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/qgis-samgeo-plugin/test_plugin.py +0 -0
  110. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/requirements.txt +0 -0
  111. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/requirements_dev.txt +0 -0
  112. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/requirements_docs.txt +0 -0
  113. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/samgeo/caption.py +0 -0
  114. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/samgeo/fast_sam.py +0 -0
  115. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/samgeo/hq_sam.py +0 -0
  116. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/samgeo/samgeo.py +0 -0
  117. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/samgeo/samgeo2.py +0 -0
  118. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/samgeo/utmconv.py +0 -0
  119. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/segment_geospatial.egg-info/SOURCES.txt +0 -0
  120. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/segment_geospatial.egg-info/dependency_links.txt +0 -0
  121. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/segment_geospatial.egg-info/requires.txt +0 -0
  122. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/segment_geospatial.egg-info/top_level.txt +0 -0
  123. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/setup.cfg +0 -0
  124. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/tests/__init__.py +0 -0
  125. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/tests/test_common.py +0 -0
  126. {segment_geospatial-1.2.0 → segment_geospatial-1.2.2}/tests/test_samgeo.py +0 -0
@@ -12,7 +12,7 @@ repos:
12
12
  args: ["--maxkb=500"]
13
13
 
14
14
  - repo: https://github.com/astral-sh/ruff-pre-commit
15
- rev: v0.14.9
15
+ rev: v0.14.14
16
16
  hooks:
17
17
  - id: ruff
18
18
  types_or: [pyi, jupyter]
@@ -29,6 +29,6 @@ repos:
29
29
  ]
30
30
 
31
31
  - repo: https://github.com/kynan/nbstripout
32
- rev: 0.8.2
32
+ rev: 0.9.0
33
33
  hooks:
34
34
  - id: nbstripout
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: segment-geospatial
3
- Version: 1.2.0
4
- Summary: Meta AI' Segment Anything Model (SAM) for Geospatial Data.
3
+ Version: 1.2.2
4
+ Summary: Meta AI's Segment Anything Model (SAM) for Geospatial Data.
5
5
  Author-email: Qiusheng Wu <giswqs@gmail.com>
6
6
  License: MIT license
7
7
  Project-URL: Homepage, https://github.com/opengeos/segment-geospatial
@@ -146,6 +146,31 @@ SamGeo is also available as a [QGIS plugin](https://github.com/opengeos/qgis-sam
146
146
 
147
147
  ## Installation
148
148
 
149
+ ### Install with pixi (Recommended)
150
+
151
+ For the most reliable installation experience, especially on Windows or when dealing with complex dependencies like PyTorch/CUDA and SAM 3, we recommend using [pixi](https://pixi.prefix.dev/latest). Pixi provides faster and more reliable dependency resolution than conda/mamba and avoids common numpy version conflicts. See the [full pixi installation guide](https://samgeo.gishub.org/installation/#install-with-pixi-recommended) for detailed instructions.
152
+
153
+ Quick start with pixi:
154
+
155
+ ```bash
156
+ # Install pixi (Linux/macOS)
157
+ curl -fsSL https://pixi.sh/install.sh | sh
158
+
159
+ # Or on Windows (PowerShell)
160
+ powershell -ExecutionPolicy Bypass -c "irm -useb https://pixi.sh/install.ps1 | iex"
161
+
162
+ # Create a new pixi project
163
+ pixi init geo
164
+ cd geo
165
+
166
+ # Edit pixi.toml with your configuration (see docs for GPU/CPU examples)
167
+ # Then install
168
+ pixi install
169
+
170
+ # Start Jupyter Lab
171
+ pixi run jupyter lab
172
+ ```
173
+
149
174
  ### Install from PyPI
150
175
 
151
176
  **segment-geospatial** is available on [PyPI](https://pypi.org/project/segment-geospatial/) and can be installed in several ways so that its dependencies can be controlled more granularly. This reduces package size for CI environments, since not every time all of the models will be used.
@@ -191,7 +216,7 @@ If your system has a GPU, but the above commands do not install the GPU version
191
216
  conda install -c conda-forge segment-geospatial "pytorch=*=cuda*"
192
217
  ```
193
218
 
194
- Samgeo-geospatial has some optional dependencies that are not included in the default conda environment. To install these dependencies, run the following command:
219
+ segment-geospatial has some optional dependencies that are not included in the default conda environment. To install these dependencies, run the following command:
195
220
 
196
221
  ```bash
197
222
  conda install -c conda-forge groundingdino-py segment-anything-fast
@@ -47,6 +47,31 @@ SamGeo is also available as a [QGIS plugin](https://github.com/opengeos/qgis-sam
47
47
 
48
48
  ## Installation
49
49
 
50
+ ### Install with pixi (Recommended)
51
+
52
+ For the most reliable installation experience, especially on Windows or when dealing with complex dependencies like PyTorch/CUDA and SAM 3, we recommend using [pixi](https://pixi.prefix.dev/latest). Pixi provides faster and more reliable dependency resolution than conda/mamba and avoids common numpy version conflicts. See the [full pixi installation guide](https://samgeo.gishub.org/installation/#install-with-pixi-recommended) for detailed instructions.
53
+
54
+ Quick start with pixi:
55
+
56
+ ```bash
57
+ # Install pixi (Linux/macOS)
58
+ curl -fsSL https://pixi.sh/install.sh | sh
59
+
60
+ # Or on Windows (PowerShell)
61
+ powershell -ExecutionPolicy Bypass -c "irm -useb https://pixi.sh/install.ps1 | iex"
62
+
63
+ # Create a new pixi project
64
+ pixi init geo
65
+ cd geo
66
+
67
+ # Edit pixi.toml with your configuration (see docs for GPU/CPU examples)
68
+ # Then install
69
+ pixi install
70
+
71
+ # Start Jupyter Lab
72
+ pixi run jupyter lab
73
+ ```
74
+
50
75
  ### Install from PyPI
51
76
 
52
77
  **segment-geospatial** is available on [PyPI](https://pypi.org/project/segment-geospatial/) and can be installed in several ways so that its dependencies can be controlled more granularly. This reduces package size for CI environments, since not every time all of the models will be used.
@@ -92,7 +117,7 @@ If your system has a GPU, but the above commands do not install the GPU version
92
117
  conda install -c conda-forge segment-geospatial "pytorch=*=cuda*"
93
118
  ```
94
119
 
95
- Samgeo-geospatial has some optional dependencies that are not included in the default conda environment. To install these dependencies, run the following command:
120
+ segment-geospatial has some optional dependencies that are not included in the default conda environment. To install these dependencies, run the following command:
96
121
 
97
122
  ```bash
98
123
  conda install -c conda-forge groundingdino-py segment-anything-fast
@@ -0,0 +1,48 @@
1
+ # Frequently Asked Questions (FAQ)
2
+
3
+ ## Coordinate Reference Systems (CRS)
4
+
5
+ ### Does samgeo automatically convert my imagery to EPSG:4326?
6
+
7
+ **No.** samgeo does **NOT** automatically reproject or convert your GeoTIFF files to EPSG:4326. Your imagery stays in its native coordinate system throughout the entire segmentation process.
8
+
9
+ **Key points:**
10
+ - When you load a GeoTIFF with `set_image()` or use `generate_masks_tiled()`, the image data is read directly without any CRS transformation
11
+ - The output masks inherit the same CRS as your input imagery
12
+ - The `reproject()` function in `samgeo.common` has EPSG:4326 as a default parameter, but it's **only used when you explicitly call that function** - it is NOT called automatically during segmentation
13
+
14
+ **Why might you see distortion?**
15
+ 1. Your visualization tool is displaying the results in EPSG:4326 (like some web map libraries)
16
+ 2. You're manually calling the `reproject()` function somewhere in your workflow
17
+ 3. Your original imagery already has CRS-related issues
18
+
19
+ **Recommendation:**
20
+ - Verify your input TIF has the correct CRS metadata using `gdalinfo` or rasterio (`src.crs`)
21
+ - The output masks will preserve the same CRS as your input
22
+ - If you need to reproject for visualization, do it as a separate step AFTER segmentation:
23
+ ```python
24
+ from samgeo import common
25
+ common.reproject("input_masks.tif", "output_epsg4326.tif", dst_crs="EPSG:4326")
26
+ ```
27
+
28
+ ### How can I check the CRS of my GeoTIFF?
29
+
30
+ Using GDAL:
31
+ ```bash
32
+ gdalinfo your_file.tif
33
+ ```
34
+
35
+ Using Python with rasterio:
36
+ ```python
37
+ import rasterio
38
+ with rasterio.open("your_file.tif") as src:
39
+ print(f"CRS: {src.crs}")
40
+ ```
41
+
42
+ ### My imagery looks distorted during segmentation
43
+
44
+ The segmentation algorithm works on pixel values, not geographic coordinates, so CRS should not affect segmentation quality. If you're seeing distortion:
45
+
46
+ 1. **Check if it's a visualization issue:** The distortion might only appear when viewing results in a different CRS
47
+ 2. **Verify your input data:** Use `gdalinfo` to check if the CRS metadata is correct
48
+ 3. **Try reprojecting to a more suitable CRS:** Some projections preserve shape better than others for specific regions (e.g., UTM for local areas)
@@ -0,0 +1,277 @@
1
+ # Installation
2
+
3
+ ## Install with pixi (Recommended)
4
+
5
+ Installing **segment-geospatial** with `uv` or `pip` can be challenging on some platforms (especially Windows) due to complicated pytorch/cuda dependencies and numpy version conflicts. [Pixi](https://pixi.prefix.dev/latest) is recommended to avoid these issues, as it provides faster and more reliable dependency resolution than conda or mamba.
6
+
7
+ ### 1) Install Pixi
8
+
9
+ #### Linux/macOS (bash/zsh)
10
+
11
+ ```bash
12
+ curl -fsSL https://pixi.sh/install.sh | sh
13
+ ```
14
+
15
+ Close and re-open your terminal (or reload your shell) so `pixi` is on your `PATH`. Then confirm:
16
+
17
+ ```bash
18
+ pixi --version
19
+ ```
20
+
21
+ #### Windows (PowerShell)
22
+
23
+ Open **PowerShell** (preferably as a normal user, Admin not required), then run:
24
+
25
+ ```powershell
26
+ powershell -ExecutionPolicy Bypass -c "irm -useb https://pixi.sh/install.ps1 | iex"
27
+ ```
28
+
29
+ Close and re-open PowerShell, then confirm:
30
+
31
+ ```powershell
32
+ pixi --version
33
+ ```
34
+
35
+ ---
36
+
37
+ ### 2) Create a Pixi project
38
+
39
+ Navigate to a directory where you want to create the project and run:
40
+
41
+ ```bash
42
+ pixi init geo
43
+ cd geo
44
+ ```
45
+
46
+ ---
47
+
48
+ ### 3) Configure `pixi.toml`
49
+
50
+ Open `pixi.toml` in the `geo` directory and replace its contents with the following depending on your system.
51
+
52
+ If you have an NVIDIA GPU with CUDA, run `nvidia-smi` to check the CUDA version.
53
+
54
+ #### For GPU with CUDA 12.x:
55
+
56
+ ```toml
57
+ [workspace]
58
+ channels = ["https://prefix.dev/conda-forge"]
59
+ name = "geo"
60
+ platforms = ["linux-64", "win-64"]
61
+
62
+ [system-requirements]
63
+ cuda = "12.0"
64
+
65
+ [dependencies]
66
+ python = "3.12.*"
67
+ pytorch-gpu = ">=2.7.1,<3"
68
+ segment-geospatial = ">=1.2.0"
69
+ sam3 = ">=0.1.0.20251211"
70
+ jupyterlab = "*"
71
+ ipykernel = "*"
72
+ libopenblas = ">=0.3.30"
73
+ ```
74
+
75
+ #### For GPU with CUDA 13.x:
76
+
77
+ ```toml
78
+ [workspace]
79
+ channels = ["https://prefix.dev/conda-forge"]
80
+ name = "geo"
81
+ platforms = ["linux-64", "win-64"]
82
+
83
+ [system-requirements]
84
+ cuda = "13.0"
85
+
86
+ [dependencies]
87
+ python = "3.12.*"
88
+ pytorch-gpu = ">=2.7.1,<3"
89
+ segment-geospatial = ">=1.2.0"
90
+ sam3 = ">=0.1.0.20251211"
91
+ jupyterlab = "*"
92
+ ipykernel = "*"
93
+ ```
94
+
95
+ #### For CPU:
96
+
97
+ ```toml
98
+ [workspace]
99
+ channels = ["https://prefix.dev/conda-forge"]
100
+ name = "geo"
101
+ platforms = ["linux-64", "win-64"]
102
+
103
+ [dependencies]
104
+ python = "3.12.*"
105
+ pytorch-cpu = ">=2.7.1,<3"
106
+ segment-geospatial = ">=1.2.0"
107
+ sam3 = ">=0.1.0.20251211"
108
+ jupyterlab = "*"
109
+ ipykernel = "*"
110
+ libopenblas = ">=0.3.30"
111
+ ```
112
+
113
+ ---
114
+
115
+ ### 4) Install the environment
116
+
117
+ From the `geo` folder:
118
+
119
+ ```bash
120
+ pixi install
121
+ ```
122
+
123
+ This step may take several minutes on first install depending on your internet connection and system.
124
+
125
+ ---
126
+
127
+ ### 5) Verify PyTorch + CUDA
128
+
129
+ If you have an NVIDIA GPU with CUDA, run the following command to verify the PyTorch + CUDA installation:
130
+
131
+ ```bash
132
+ pixi run python -c "import torch; print('PyTorch:', torch.__version__); print('CUDA available:', torch.cuda.is_available()); print('GPU:', (torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'None'))"
133
+ ```
134
+
135
+ Expected output should be like this:
136
+
137
+ - `PyTorch: 2.7.1` (or higher)
138
+ - `CUDA available: True`
139
+ - `GPU: NVIDIA RTX 4090` (your GPU name)
140
+
141
+ If CUDA is `False`, check:
142
+
143
+ - `nvidia-smi` works in your terminal
144
+ - NVIDIA driver is up to date
145
+
146
+ ---
147
+
148
+ ### 6) Request access to SAM 3 (Optional)
149
+
150
+ To use SAM 3, you will need to request access by filling out this form on Hugging Face at <https://huggingface.co/facebook/sam3>. Once your request has been approved, run the following command in the terminal to authenticate:
151
+
152
+ ```bash
153
+ pixi run hf auth login
154
+ ```
155
+
156
+ After authentication, you can download the SAM 3 model from Hugging Face:
157
+
158
+ ```bash
159
+ pixi run hf download facebook/sam3
160
+ ```
161
+
162
+ **Important Note**: SAM 3 currently requires an NVIDIA GPU with CUDA support. You won't be able to use SAM 3 if you have a CPU only system ([source](https://github.com/facebookresearch/sam3/issues/164)). You will get an error message like this: `Failed to load model: Torch not compiled with CUDA enabled`.
163
+
164
+ ---
165
+
166
+ ### 7) Start Jupyter Lab
167
+
168
+ To start using segment-geospatial in Jupyter Lab:
169
+
170
+ ```bash
171
+ pixi run jupyter lab
172
+ ```
173
+
174
+ This will open Jupyter Lab in your default browser. You can now create a new notebook and start using segment-geospatial!
175
+
176
+ ---
177
+
178
+ ## Install from PyPI
179
+
180
+ **segment-geospatial** is available on [PyPI](https://pypi.org/project/segment-geospatial/). To install **segment-geospatial**, run this command in your terminal:
181
+
182
+ ```bash
183
+ pip install segment-geospatial
184
+ ```
185
+
186
+ ## Install from conda-forge
187
+
188
+ **segment-geospatial** is also available on [conda-forge](https://anaconda.org/conda-forge/segment-geospatial). If you have
189
+ [Anaconda](https://www.anaconda.com/distribution/#download-section) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html) installed on your computer, you can install segment-geospatial using the following commands. It is recommended to create a fresh conda environment for **segment-geospatial**. The following commands will create a new conda environment named `geo` and install **segment-geospatial** and its dependencies:
190
+
191
+ ```bash
192
+ conda create -n geo python
193
+ conda activate geo
194
+ conda install -c conda-forge mamba
195
+ mamba install -c conda-forge segment-geospatial
196
+ ```
197
+
198
+ If your system has a GPU, but the above commands do not install the GPU version of pytorch, you can force the installation of the GPU version of pytorch using the following command:
199
+
200
+ ```bash
201
+ mamba install -c conda-forge segment-geospatial "pytorch=*=cuda*"
202
+ ```
203
+
204
+ Samgeo-geospatial has some optional dependencies that are not included in the default conda environment. To install these dependencies, run the following command:
205
+
206
+ ```bash
207
+ mamba install -c conda-forge groundingdino-py segment-anything-fast
208
+ ```
209
+
210
+ ## Install from GitHub
211
+
212
+ To install the development version from GitHub using [Git](https://git-scm.com/), run the following command in your terminal:
213
+
214
+ ```bash
215
+ pip install git+https://github.com/opengeos/segment-geospatial
216
+ ```
217
+
218
+ ## Use docker
219
+
220
+ You can also use [docker](https://hub.docker.com/r/giswqs/segment-geospatial/) to run segment-geospatial:
221
+
222
+ ```bash
223
+ docker run -it -p 8888:8888 giswqs/segment-geospatial:latest
224
+ ```
225
+
226
+ To enable GPU for segment-geospatial, run the following command to run a short benchmark on your GPU:
227
+
228
+ ```bash
229
+ docker run --rm -it --gpus=all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark
230
+ ```
231
+
232
+ The output should be similar to the following:
233
+
234
+ ```text
235
+ Run "nbody -benchmark [-numbodies=<numBodies>]" to measure performance.
236
+ -fullscreen (run n-body simulation in fullscreen mode)
237
+ -fp64 (use double precision floating point values for simulation)
238
+ -hostmem (stores simulation data in host memory)
239
+ -benchmark (run benchmark to measure performance)
240
+ -numbodies=<N> (number of bodies (>= 1) to run in simulation)
241
+ -device=<d> (where d=0,1,2.... for the CUDA device to use)
242
+ -numdevices=<i> (where i=(number of CUDA devices > 0) to use for simulation)
243
+ -compare (compares simulation results running once on the default GPU and once on the CPU)
244
+ -cpu (run n-body simulation on the CPU)
245
+ -tipsy=<file.bin> (load a tipsy model file for simulation)
246
+
247
+ NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.
248
+
249
+ > Windowed mode
250
+ > Simulation data stored in video memory
251
+ > Single precision floating point simulation
252
+ > 1 Devices used for simulation
253
+ GPU Device 0: "Turing" with compute capability 7.5
254
+
255
+ > Compute 7.5 CUDA device: [Quadro RTX 5000]
256
+ 49152 bodies, total time for 10 iterations: 69.386 ms
257
+ = 348.185 billion interactions per second
258
+ = 6963.703 single-precision GFLOP/s at 20 flops per interaction
259
+ ```
260
+
261
+ If you encounter the following error:
262
+
263
+ ```text
264
+ nvidia-container-cli: initialization error: load library failed: libnvidia-ml.so.1: cannot open shared object file: no such file or directory: unknown.
265
+ ```
266
+
267
+ Try adding `sudo` to the command:
268
+
269
+ ```bash
270
+ sudo docker run --rm -it --gpus=all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark
271
+ ```
272
+
273
+ Once everything is working, you can run the following command to start a Jupyter Notebook server:
274
+
275
+ ```bash
276
+ docker run -it -p 8888:8888 --gpus=all giswqs/segment-geospatial:latest
277
+ ```
@@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "segment-geospatial"
7
- version = "1.2.0"
7
+ version = "1.2.2"
8
8
  dynamic = [
9
9
  "dependencies",
10
10
  ]
11
- description = "Meta AI' Segment Anything Model (SAM) for Geospatial Data."
11
+ description = "Meta AI's Segment Anything Model (SAM) for Geospatial Data."
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.10"
14
14
  license = {text = "MIT license"}
@@ -111,7 +111,7 @@ dependencies = {file = ["requirements.txt"]}
111
111
  universal = true
112
112
 
113
113
  [tool.bumpversion]
114
- current_version = "1.2.0"
114
+ current_version = "1.2.2"
115
115
  commit = true
116
116
  tag = true
117
117
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  __author__ = """Qiusheng Wu"""
4
4
  __email__ = "giswqs@gmail.com"
5
- __version__ = "1.2.0"
5
+ __version__ = "1.2.2"
6
6
 
7
7
 
8
8
  from .samgeo import * # noqa: F403
@@ -328,6 +328,7 @@ def reproject(
328
328
 
329
329
  """
330
330
  import rasterio as rio
331
+ import shutil
331
332
  from rasterio.warp import Resampling, calculate_default_transform, reproject
332
333
 
333
334
  if isinstance(resampling, str):
@@ -339,6 +340,15 @@ def reproject(
339
340
  if not os.path.exists(os.path.dirname(output)):
340
341
  os.makedirs(os.path.dirname(output))
341
342
 
343
+ # Check if input and output are the same file (in-place reprojection)
344
+ in_place = os.path.normpath(image) == os.path.normpath(output)
345
+
346
+ # If in-place, use a temporary file to avoid file locking issues on Windows
347
+ if in_place:
348
+ temp_output = temp_file_path(".tif")
349
+ else:
350
+ temp_output = output
351
+
342
352
  with rio.open(image, **kwargs) as src:
343
353
  transform, width, height = calculate_default_transform(
344
354
  src.crs, dst_crs, src.width, src.height, *src.bounds
@@ -353,7 +363,7 @@ def reproject(
353
363
  }
354
364
  )
355
365
 
356
- with rio.open(output, "w", **kwargs) as dst:
366
+ with rio.open(temp_output, "w", **kwargs) as dst:
357
367
  for i in range(1, src.count + 1):
358
368
  reproject(
359
369
  source=rio.band(src, i),
@@ -366,6 +376,10 @@ def reproject(
366
376
  **kwargs,
367
377
  )
368
378
 
379
+ # If in-place, replace the original file with the temporary file
380
+ if in_place:
381
+ shutil.move(temp_output, output)
382
+
369
383
  if to_cog:
370
384
  image_to_cog(output, output)
371
385
 
@@ -1818,7 +1832,7 @@ def update_package(out_dir=None, keep=False, **kwargs):
1818
1832
  shutil.rmtree(pkg_dir)
1819
1833
  try:
1820
1834
  os.remove(filename)
1821
- except:
1835
+ except Exception:
1822
1836
  pass
1823
1837
 
1824
1838
  print("Package updated successfully.")
@@ -1872,7 +1886,7 @@ def sam_map_gui(
1872
1886
  # Skip the image layer if localtileserver is not available
1873
1887
  try:
1874
1888
  m.add_raster(sam.source, layer_name="Image")
1875
- except:
1889
+ except Exception:
1876
1890
  pass
1877
1891
 
1878
1892
  m.fg_markers = []
@@ -2265,7 +2279,7 @@ def sam_map_gui(
2265
2279
  ):
2266
2280
  try:
2267
2281
  os.remove(sam.prediction_fp)
2268
- except:
2282
+ except Exception:
2269
2283
  pass
2270
2284
  # Skip the image layer if localtileserver is not available
2271
2285
  try:
@@ -2291,7 +2305,7 @@ def sam_map_gui(
2291
2305
  zoom_to_layer=False,
2292
2306
  )
2293
2307
 
2294
- except:
2308
+ except Exception:
2295
2309
  pass
2296
2310
  output.clear_output()
2297
2311
  segment_button.value = False
@@ -2386,9 +2400,9 @@ def sam_map_gui(
2386
2400
  bg_count.value = 0
2387
2401
  try:
2388
2402
  os.remove(sam.prediction_fp)
2389
- except:
2403
+ except Exception:
2390
2404
  pass
2391
- except:
2405
+ except Exception:
2392
2406
  pass
2393
2407
 
2394
2408
  reset_button.observe(reset_button_click, "value")
@@ -2605,7 +2619,7 @@ def text_sam_gui(
2605
2619
  # Skip the image layer if localtileserver is not available
2606
2620
  try:
2607
2621
  m.add_raster(sam.source, layer_name="Image")
2608
- except:
2622
+ except Exception:
2609
2623
  pass
2610
2624
 
2611
2625
  widget_width = "280px"
@@ -2953,7 +2967,7 @@ def text_sam_gui(
2953
2967
  if hasattr(m, "layer_name") and m.find_layer(m.layer_name) is not None:
2954
2968
  m.remove_layer(m.find_layer(m.layer_name))
2955
2969
  m.clear_drawings()
2956
- except:
2970
+ except Exception:
2957
2971
  pass
2958
2972
 
2959
2973
  reset_button.observe(reset_button_click, "value")
@@ -3520,9 +3534,22 @@ def images_to_video(
3520
3534
  height, width, _ = frame.shape
3521
3535
  video_size = (width, height)
3522
3536
 
3523
- # TODO: This video codec is giving me some problems, not sure if it's the correct one
3524
- fourcc = cv2.VideoWriter_fourcc(*"avc1") # Define the codec for mp4
3525
- video_writer = cv2.VideoWriter(output_video, fourcc, fps, video_size)
3537
+ # Try different codecs for compatibility across platforms
3538
+ codecs = ["avc1", "mp4v", "XVID"]
3539
+ video_writer = None
3540
+
3541
+ for codec in codecs:
3542
+ fourcc = cv2.VideoWriter_fourcc(*codec)
3543
+ video_writer = cv2.VideoWriter(output_video, fourcc, fps, video_size)
3544
+ if video_writer.isOpened():
3545
+ break
3546
+ video_writer.release()
3547
+
3548
+ if not video_writer or not video_writer.isOpened():
3549
+ raise RuntimeError(
3550
+ f"Failed to initialize video writer for {output_video}. "
3551
+ "Please ensure you have the necessary codecs installed."
3552
+ )
3526
3553
 
3527
3554
  for image_path in images:
3528
3555
  frame = cv2.imread(image_path)
@@ -3536,6 +3563,21 @@ def images_to_video(
3536
3563
  video_writer.write(frame)
3537
3564
 
3538
3565
  video_writer.release()
3566
+
3567
+ # Verify the video file was created
3568
+ if not os.path.exists(output_video):
3569
+ raise RuntimeError(
3570
+ f"Failed to create video file {output_video}. "
3571
+ "The video writer completed but the file was not saved to disk."
3572
+ )
3573
+
3574
+ # Verify the file has content
3575
+ if os.path.getsize(output_video) == 0:
3576
+ raise RuntimeError(
3577
+ f"Video file {output_video} was created but is empty. "
3578
+ "This may indicate a codec problem."
3579
+ )
3580
+
3539
3581
  print(f"Video saved as {output_video}")
3540
3582
 
3541
3583
 
@@ -996,7 +996,7 @@ def regularize(
996
996
 
997
997
  try:
998
998
  RecSim, rering = RecSimilar(dpolygon)
999
- except:
999
+ except Exception:
1000
1000
  continue
1001
1001
  if RecSim == 1:
1002
1002
  oupolygon.AddGeometry(rering)
@@ -1014,7 +1014,7 @@ def regularize(
1014
1014
 
1015
1015
  try:
1016
1016
  vx = VListDiret(vList)
1017
- except:
1017
+ except Exception:
1018
1018
  continue
1019
1019
  svList = Smooth(vList, vx, 25, averageLength)
1020
1020