segment-geospatial 1.0.2__tar.gz → 1.1.0__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.
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/workflows/ubuntu.yml +5 -3
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/PKG-INFO +1 -1
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/pyproject.toml +2 -2
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/samgeo/__init__.py +1 -1
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/samgeo/common.py +42 -12
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/samgeo/samgeo3.py +57 -4
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/segment_geospatial.egg-info/PKG-INFO +1 -1
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.editorconfig +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/FUNDING.yml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/dependabot.yaml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/workflows/docker-image.yml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/workflows/docker-publish.yml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/workflows/docs-build.yml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/workflows/docs.yml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/workflows/draft-pdf.yml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/workflows/macos.yml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/workflows/pypi.yml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/workflows/windows.yml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.gitignore +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.pre-commit-config.yaml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/CITATION.cff +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/CODE_OF_CONDUCT.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/Dockerfile +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/LICENSE +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/MANIFEST.in +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/README.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/CNAME +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/assets/README.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/assets/favicon.png +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/assets/logo.png +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/assets/logo_rect.png +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/caption.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/changelog.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/changelog_update.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/common.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/contributing.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/arcgis.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/automatic_mask_generator.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/automatic_mask_generator_hq.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/box_prompts.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/data/tree_boxes.geojson +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/fast_sam.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/image_captioning.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/input_prompts.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/input_prompts_hq.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/maxar_open_data.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam2_automatic.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam2_box_prompts.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam2_point_prompts.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam2_predictor.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam2_text_prompts.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam2_video.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_automated_segmentation.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_batch_segmentation.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_box_prompts.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_image_segmentation.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_image_segmentation_jpg.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_interactive.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_object_tracking.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_point_prompts.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_point_prompts_batch.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_video_masks.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_video_prompts.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_video_segmentation.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/satellite-predictor.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/satellite.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/text_prompts.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/text_prompts_batch.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/text_swimming_pools.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/tree_mapping.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/faq.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/fast_sam.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/hq_sam.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/index.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/installation.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/overrides/main.html +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/samgeo.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/samgeo2.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/samgeo3.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/text_sam.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/usage.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/workshops/AIforGood_2025.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/workshops/IPPN_2024.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/workshops/cn_workshop.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/workshops/jupytext.toml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/workshops/purdue.ipynb +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/mkdocs.yml +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/paper/10.21105.joss.05663.pdf +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/paper/paper.bib +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/paper/paper.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/qgis-samgeo-plugin/LICENSE +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/qgis-samgeo-plugin/README.md +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/qgis-samgeo-plugin/__init__.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/qgis-samgeo-plugin/icons/icon.png +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/qgis-samgeo-plugin/install_plugin.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/qgis-samgeo-plugin/install_plugin.sh +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/qgis-samgeo-plugin/map_tools.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/qgis-samgeo-plugin/metadata.txt +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/qgis-samgeo-plugin/resources.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/qgis-samgeo-plugin/samgeo_plugin.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/qgis-samgeo-plugin/test_plugin.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/requirements.txt +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/requirements_dev.txt +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/requirements_docs.txt +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/samgeo/caption.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/samgeo/fast_sam.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/samgeo/fer.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/samgeo/hq_sam.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/samgeo/samgeo.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/samgeo/samgeo2.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/samgeo/text_sam.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/samgeo/utmconv.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/segment_geospatial.egg-info/SOURCES.txt +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/segment_geospatial.egg-info/dependency_links.txt +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/segment_geospatial.egg-info/requires.txt +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/segment_geospatial.egg-info/top_level.txt +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/setup.cfg +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/tests/__init__.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/tests/test_common.py +0 -0
- {segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/tests/test_samgeo.py +0 -0
|
@@ -48,6 +48,8 @@ jobs:
|
|
|
48
48
|
pip install --user -r requirements.txt
|
|
49
49
|
pip install --user -r requirements_dev.txt
|
|
50
50
|
pip install --user .
|
|
51
|
-
- name:
|
|
52
|
-
run:
|
|
53
|
-
|
|
51
|
+
- name: Test import
|
|
52
|
+
run: python -c "import samgeo; print('samgeo import successful')"
|
|
53
|
+
# - name: PKG-TEST
|
|
54
|
+
# run: |
|
|
55
|
+
# python -m unittest discover tests/
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "segment-geospatial"
|
|
7
|
-
version = "1.0
|
|
7
|
+
version = "1.1.0"
|
|
8
8
|
dynamic = [
|
|
9
9
|
"dependencies",
|
|
10
10
|
]
|
|
@@ -111,7 +111,7 @@ dependencies = {file = ["requirements.txt"]}
|
|
|
111
111
|
universal = true
|
|
112
112
|
|
|
113
113
|
[tool.bumpversion]
|
|
114
|
-
current_version = "1.0
|
|
114
|
+
current_version = "1.1.0"
|
|
115
115
|
commit = true
|
|
116
116
|
tag = true
|
|
117
117
|
|
|
@@ -3737,27 +3737,50 @@ def make_temp_dir(**kwargs) -> str:
|
|
|
3737
3737
|
return temp_dir
|
|
3738
3738
|
|
|
3739
3739
|
|
|
3740
|
-
def geotiff_to_jpg(
|
|
3740
|
+
def geotiff_to_jpg(
|
|
3741
|
+
geotiff_path: str,
|
|
3742
|
+
output_path: str,
|
|
3743
|
+
bands: Optional[List[int]] = None,
|
|
3744
|
+
) -> None:
|
|
3741
3745
|
"""Convert a GeoTIFF file to a JPG file.
|
|
3742
3746
|
|
|
3743
3747
|
Args:
|
|
3744
3748
|
geotiff_path (str): The path to the input GeoTIFF file.
|
|
3745
3749
|
output_path (str): The path to the output JPG file.
|
|
3750
|
+
bands (List[int], optional): List of band indices (1-based) to use for RGB.
|
|
3751
|
+
For example, [4, 3, 2] for NIR-R-G false color composite.
|
|
3752
|
+
If None, uses the first 3 bands. Defaults to None.
|
|
3746
3753
|
"""
|
|
3747
3754
|
|
|
3748
3755
|
from PIL import Image
|
|
3749
3756
|
|
|
3750
3757
|
# Open the GeoTIFF file
|
|
3751
3758
|
with rasterio.open(geotiff_path) as src:
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3759
|
+
if bands is not None:
|
|
3760
|
+
# Validate band indices (1-based)
|
|
3761
|
+
if len(bands) != 3:
|
|
3762
|
+
raise ValueError("bands must contain exactly 3 band indices for RGB.")
|
|
3763
|
+
for band in bands:
|
|
3764
|
+
if band < 1 or band > src.count:
|
|
3765
|
+
raise ValueError(
|
|
3766
|
+
f"Band index {band} is out of range. "
|
|
3767
|
+
f"Image has {src.count} bands (1-indexed)."
|
|
3768
|
+
)
|
|
3769
|
+
# Read specified bands (rasterio uses 1-based indexing)
|
|
3770
|
+
array = np.stack([src.read(b) for b in bands], axis=0)
|
|
3771
|
+
else:
|
|
3772
|
+
# Read all bands
|
|
3773
|
+
array = src.read()
|
|
3774
|
+
|
|
3775
|
+
# If the array has more than 3 bands, reduce it to the first 3 (RGB)
|
|
3776
|
+
if array.shape[0] >= 3:
|
|
3777
|
+
array = array[:3, :, :] # Select the first 3 bands (R, G, B)
|
|
3778
|
+
elif array.shape[0] == 1:
|
|
3779
|
+
# For single-band images, repeat the band to create a grayscale RGB
|
|
3780
|
+
array = np.repeat(array, 3, axis=0)
|
|
3781
|
+
elif array.shape[0] == 2:
|
|
3782
|
+
# For two-band images, repeat the first band to create a 3-band image
|
|
3783
|
+
array = np.concatenate([array, array[0:1, :, :]], axis=0)
|
|
3761
3784
|
|
|
3762
3785
|
# Transpose the array from (bands, height, width) to (height, width, bands)
|
|
3763
3786
|
array = np.transpose(array, (1, 2, 0))
|
|
@@ -3774,12 +3797,19 @@ def geotiff_to_jpg(geotiff_path: str, output_path: str) -> None:
|
|
|
3774
3797
|
image.save(output_path)
|
|
3775
3798
|
|
|
3776
3799
|
|
|
3777
|
-
def geotiff_to_jpg_batch(
|
|
3800
|
+
def geotiff_to_jpg_batch(
|
|
3801
|
+
input_folder: str,
|
|
3802
|
+
output_folder: str = None,
|
|
3803
|
+
bands: Optional[List[int]] = None,
|
|
3804
|
+
) -> str:
|
|
3778
3805
|
"""Convert all GeoTIFF files in a folder to JPG files.
|
|
3779
3806
|
|
|
3780
3807
|
Args:
|
|
3781
3808
|
input_folder (str): The path to the folder containing GeoTIFF files.
|
|
3782
3809
|
output_folder (str): The path to the folder to save the output JPG files.
|
|
3810
|
+
bands (List[int], optional): List of band indices (1-based) to use for RGB.
|
|
3811
|
+
For example, [4, 3, 2] for NIR-R-G false color composite.
|
|
3812
|
+
If None, uses the first 3 bands. Defaults to None.
|
|
3783
3813
|
|
|
3784
3814
|
Returns:
|
|
3785
3815
|
str: The path to the output folder containing the JPG files.
|
|
@@ -3800,7 +3830,7 @@ def geotiff_to_jpg_batch(input_folder: str, output_folder: str = None) -> str:
|
|
|
3800
3830
|
geotiff_path = os.path.join(input_folder, filename)
|
|
3801
3831
|
jpg_filename = os.path.splitext(filename)[0] + ".jpg"
|
|
3802
3832
|
output_path = os.path.join(output_folder, jpg_filename)
|
|
3803
|
-
geotiff_to_jpg(geotiff_path, output_path)
|
|
3833
|
+
geotiff_to_jpg(geotiff_path, output_path, bands=bands)
|
|
3804
3834
|
|
|
3805
3835
|
return output_folder
|
|
3806
3836
|
|
|
@@ -244,6 +244,7 @@ class SamGeo3:
|
|
|
244
244
|
self,
|
|
245
245
|
image: Union[str, np.ndarray],
|
|
246
246
|
state=None,
|
|
247
|
+
bands: Optional[List[int]] = None,
|
|
247
248
|
) -> None:
|
|
248
249
|
"""Set the input image as a numpy array.
|
|
249
250
|
|
|
@@ -251,6 +252,10 @@ class SamGeo3:
|
|
|
251
252
|
image (Union[str, np.ndarray, Image]): The input image as a path,
|
|
252
253
|
a numpy array, or an Image.
|
|
253
254
|
state (optional): An optional state object to pass to the processor's set_image method (Meta backend only).
|
|
255
|
+
bands (List[int], optional): List of band indices (1-based) to use for RGB
|
|
256
|
+
when the input is a GeoTIFF with more than 3 bands. For example,
|
|
257
|
+
[4, 3, 2] for NIR-R-G false color composite. If None, uses the
|
|
258
|
+
first 3 bands for multi-band images. Defaults to None.
|
|
254
259
|
"""
|
|
255
260
|
if isinstance(image, str):
|
|
256
261
|
if image.startswith("http"):
|
|
@@ -260,8 +265,50 @@ class SamGeo3:
|
|
|
260
265
|
raise ValueError(f"Input path {image} does not exist.")
|
|
261
266
|
|
|
262
267
|
self.source = image
|
|
263
|
-
|
|
264
|
-
|
|
268
|
+
|
|
269
|
+
# Check if image is a GeoTIFF and handle band selection
|
|
270
|
+
if image.lower().endswith((".tif", ".tiff")):
|
|
271
|
+
import rasterio
|
|
272
|
+
|
|
273
|
+
with rasterio.open(image) as src:
|
|
274
|
+
if bands is not None:
|
|
275
|
+
# Validate band indices (1-based)
|
|
276
|
+
if len(bands) != 3:
|
|
277
|
+
raise ValueError(
|
|
278
|
+
"bands must contain exactly 3 band indices for RGB."
|
|
279
|
+
)
|
|
280
|
+
for band in bands:
|
|
281
|
+
if band < 1 or band > src.count:
|
|
282
|
+
raise ValueError(
|
|
283
|
+
f"Band index {band} is out of range. "
|
|
284
|
+
f"Image has {src.count} bands (1-indexed)."
|
|
285
|
+
)
|
|
286
|
+
# Read specified bands (rasterio uses 1-based indexing)
|
|
287
|
+
array = np.stack([src.read(b) for b in bands], axis=0)
|
|
288
|
+
else:
|
|
289
|
+
# Read all bands
|
|
290
|
+
array = src.read()
|
|
291
|
+
# If more than 3 bands, use first 3
|
|
292
|
+
if array.shape[0] >= 3:
|
|
293
|
+
array = array[:3, :, :]
|
|
294
|
+
elif array.shape[0] == 1:
|
|
295
|
+
array = np.repeat(array, 3, axis=0)
|
|
296
|
+
elif array.shape[0] == 2:
|
|
297
|
+
# Repeat the first band to make 3 bands: [band1, band2, band1]
|
|
298
|
+
array = np.concatenate([array, array[0:1, :, :]], axis=0)
|
|
299
|
+
# Transpose from (bands, height, width) to (height, width, bands)
|
|
300
|
+
array = np.transpose(array, (1, 2, 0))
|
|
301
|
+
|
|
302
|
+
# Normalize to 8-bit (0-255) range
|
|
303
|
+
array = array.astype(np.float32)
|
|
304
|
+
array -= array.min()
|
|
305
|
+
if array.max() > 0:
|
|
306
|
+
array /= array.max()
|
|
307
|
+
array *= 255
|
|
308
|
+
image = array.astype(np.uint8)
|
|
309
|
+
else:
|
|
310
|
+
image = cv2.imread(image)
|
|
311
|
+
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
|
265
312
|
self.image = image
|
|
266
313
|
elif isinstance(image, np.ndarray):
|
|
267
314
|
self.image = image
|
|
@@ -3467,7 +3514,7 @@ class SamGeo3Video:
|
|
|
3467
3514
|
if not os.path.exists(bpe_path):
|
|
3468
3515
|
bpe_dir = os.path.dirname(bpe_path)
|
|
3469
3516
|
os.makedirs(bpe_dir, exist_ok=True)
|
|
3470
|
-
url = "https://
|
|
3517
|
+
url = "https://huggingface.co/datasets/giswqs/geospatial/resolve/main/bpe_simple_vocab_16e6.txt.gz"
|
|
3471
3518
|
bpe_path = common.download_file(url, bpe_path, quiet=True)
|
|
3472
3519
|
|
|
3473
3520
|
print(f"Using GPUs: {gpus_to_use}")
|
|
@@ -3492,6 +3539,7 @@ class SamGeo3Video:
|
|
|
3492
3539
|
output_dir: Optional[str] = None,
|
|
3493
3540
|
frame_rate: Optional[int] = None,
|
|
3494
3541
|
prefix: str = "",
|
|
3542
|
+
bands: Optional[List[int]] = None,
|
|
3495
3543
|
) -> None:
|
|
3496
3544
|
"""Load a video or time series images for segmentation.
|
|
3497
3545
|
|
|
@@ -3507,12 +3555,17 @@ class SamGeo3Video:
|
|
|
3507
3555
|
frame_rate (int, optional): Frame rate for extracting frames from video.
|
|
3508
3556
|
Only used when video_path is an MP4 file. Defaults to None.
|
|
3509
3557
|
prefix (str): Prefix for extracted frame filenames. Defaults to "".
|
|
3558
|
+
bands (List[int], optional): List of band indices (1-based) to use for RGB
|
|
3559
|
+
when the input is a GeoTIFF directory with multi-band images. For example,
|
|
3560
|
+
[4, 3, 2] for NIR-R-G false color composite. If None, uses the
|
|
3561
|
+
first 3 bands for multi-band images. Defaults to None.
|
|
3510
3562
|
|
|
3511
3563
|
Example:
|
|
3512
3564
|
>>> sam = SamGeo3Video()
|
|
3513
3565
|
>>> sam.set_video("video.mp4") # Load MP4 video
|
|
3514
3566
|
>>> sam.set_video("frames/") # Load from JPEG frames directory
|
|
3515
3567
|
>>> sam.set_video("landsat_ts/") # Load GeoTIFF time series
|
|
3568
|
+
>>> sam.set_video("landsat_ts/", bands=[4, 3, 2]) # NIR-R-G composite
|
|
3516
3569
|
"""
|
|
3517
3570
|
if isinstance(video_path, str):
|
|
3518
3571
|
if video_path.startswith("http"):
|
|
@@ -3541,7 +3594,7 @@ class SamGeo3Video:
|
|
|
3541
3594
|
self._tif_dir = video_path
|
|
3542
3595
|
self._tif_names = files
|
|
3543
3596
|
# Convert GeoTIFFs to JPEGs for SAM3
|
|
3544
|
-
video_path = common.geotiff_to_jpg_batch(video_path)
|
|
3597
|
+
video_path = common.geotiff_to_jpg_batch(video_path, bands=bands)
|
|
3545
3598
|
print(f"Converted GeoTIFFs to JPEGs: {video_path}")
|
|
3546
3599
|
|
|
3547
3600
|
if not os.path.exists(video_path):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/.github/ISSUE_TEMPLATE/feature_request.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/automatic_mask_generator.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam2_point_prompts.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_batch_segmentation.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_image_segmentation.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_object_tracking.ipynb
RENAMED
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_point_prompts.ipynb
RENAMED
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_point_prompts_batch.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_video_prompts.ipynb
RENAMED
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/sam3_video_segmentation.ipynb
RENAMED
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/satellite-predictor.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/text_prompts_batch.ipynb
RENAMED
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/docs/examples/text_swimming_pools.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/segment_geospatial.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/segment_geospatial.egg-info/requires.txt
RENAMED
|
File without changes
|
{segment_geospatial-1.0.2 → segment_geospatial-1.1.0}/segment_geospatial.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|