Skip to content

Commit c1b1072

Browse files
committed
Add fastsam functions and notebook
1 parent 5ce7455 commit c1b1072

File tree

4 files changed

+231
-202
lines changed

4 files changed

+231
-202
lines changed

docs/examples/fast_sam.ipynb

Lines changed: 14 additions & 197 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@
44
"cell_type": "markdown",
55
"metadata": {},
66
"source": [
7-
"# Segmenting remote sensing imagery with text prompts and the Segment Anything Model (SAM)\n",
7+
"# Segmenting remote sensing imagery with FastSAM\n",
88
"\n",
9-
"[![image](https://studiolab.sagemaker.aws/studiolab.svg)](https://studiolab.sagemaker.aws/import/github/opengeos/segment-geospatial/blob/main/docs/examples/text_prompts.ipynb)\n",
10-
"[![image](https://img.shields.io/badge/Open-Planetary%20Computer-black?style=flat&logo=microsoft)](https://pccompute.westeurope.cloudapp.azure.com/compute/hub/user-redirect/git-pull?repo=https://github.com/opengeos/segment-geospatial&urlpath=lab/tree/segment-geospatial/docs/examples/text_prompts.ipynb&branch=main)\n",
11-
"[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/opengeos/segment-geospatial/blob/main/docs/examples/text_prompts.ipynb)\n",
12-
"\n",
13-
"This notebook shows how to generate object masks from text prompts with the Segment Anything Model (SAM). \n",
9+
"[![image](https://studiolab.sagemaker.aws/studiolab.svg)](https://studiolab.sagemaker.aws/import/github/opengeos/segment-geospatial/blob/main/docs/examples/fast_sam.ipynb)\n",
10+
"[![image](https://img.shields.io/badge/Open-Planetary%20Computer-black?style=flat&logo=microsoft)](https://pccompute.westeurope.cloudapp.azure.com/compute/hub/user-redirect/git-pull?repo=https://github.com/opengeos/segment-geospatial&urlpath=lab/tree/segment-geospatial/docs/examples/fast_sam.ipynb&branch=main)\n",
11+
"[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/opengeos/segment-geospatial/blob/main/docs/examples/fast_sam.ipynb)\n",
1412
"\n",
1513
"Make sure you use GPU runtime for this notebook. For Google Colab, go to `Runtime` -> `Change runtime type` and select `GPU` as the hardware accelerator. "
1614
]
@@ -30,7 +28,7 @@
3028
"metadata": {},
3129
"outputs": [],
3230
"source": [
33-
"# %pip install segment-geospatial groundingdino-py leafmap localtileserver"
31+
"# %pip install segment-geospatial segment-anything-fast"
3432
]
3533
},
3634
{
@@ -130,9 +128,9 @@
130128
"cell_type": "markdown",
131129
"metadata": {},
132130
"source": [
133-
"## Initialize LangSAM class\n",
131+
"## Initialize SamGeo class\n",
134132
"\n",
135-
"The initialization of the LangSAM class might take a few minutes. The initialization downloads the model weights and sets up the model for inference."
133+
"The initialization of the SamGeo class might take a few minutes. The initialization downloads the model weights and sets up the model for inference."
136134
]
137135
},
138136
{
@@ -141,6 +139,7 @@
141139
"metadata": {},
142140
"outputs": [],
143141
"source": [
142+
"from samgeo.fast_sam import SamGeo\n",
144143
"sam = SamGeo(model=\"FastSAM-x.pt\")"
145144
]
146145
},
@@ -159,160 +158,7 @@
159158
"metadata": {},
160159
"outputs": [],
161160
"source": [
162-
"sam.everything_prompt(\"mask.png\")"
163-
]
164-
},
165-
{
166-
"cell_type": "code",
167-
"execution_count": null,
168-
"metadata": {},
169-
"outputs": [],
170-
"source": [
171-
"sam.prompt_process.annotations"
172-
]
173-
},
174-
{
175-
"cell_type": "code",
176-
"execution_count": null,
177-
"metadata": {},
178-
"outputs": [],
179-
"source": [
180-
"sam.prompt_process.results[0].masks.annotations"
181-
]
182-
},
183-
{
184-
"cell_type": "markdown",
185-
"metadata": {},
186-
"source": [
187-
"## Specify text prompts"
188-
]
189-
},
190-
{
191-
"cell_type": "code",
192-
"execution_count": null,
193-
"metadata": {},
194-
"outputs": [],
195-
"source": [
196-
"text_prompt = \"tree\""
197-
]
198-
},
199-
{
200-
"cell_type": "markdown",
201-
"metadata": {},
202-
"source": [
203-
"## Segment the image\n",
204-
"\n",
205-
"Part of the model prediction includes setting appropriate thresholds for object detection and text association with the detected objects. These threshold values range from 0 to 1 and are set while calling the predict method of the LangSAM class.\n",
206-
"\n",
207-
"`box_threshold`: This value is used for object detection in the image. A higher value makes the model more selective, identifying only the most confident object instances, leading to fewer overall detections. A lower value, conversely, makes the model more tolerant, leading to increased detections, including potentially less confident ones.\n",
208-
"\n",
209-
"`text_threshold`: This value is used to associate the detected objects with the provided text prompt. A higher value requires a stronger association between the object and the text prompt, leading to more precise but potentially fewer associations. A lower value allows for looser associations, which could increase the number of associations but also introduce less precise matches.\n",
210-
"\n",
211-
"Remember to test different threshold values on your specific data. The optimal threshold can vary depending on the quality and nature of your images, as well as the specificity of your text prompts. Make sure to choose a balance that suits your requirements, whether that's precision or recall."
212-
]
213-
},
214-
{
215-
"cell_type": "code",
216-
"execution_count": null,
217-
"metadata": {},
218-
"outputs": [],
219-
"source": [
220-
"sam.predict(image, text_prompt, box_threshold=0.24, text_threshold=0.24)"
221-
]
222-
},
223-
{
224-
"cell_type": "markdown",
225-
"metadata": {},
226-
"source": [
227-
"## Visualize the results\n",
228-
"\n",
229-
"Show the result with bounding boxes on the map."
230-
]
231-
},
232-
{
233-
"cell_type": "code",
234-
"execution_count": null,
235-
"metadata": {},
236-
"outputs": [],
237-
"source": [
238-
"sam.show_anns(\n",
239-
" cmap='Greens',\n",
240-
" box_color='red',\n",
241-
" title='Automatic Segmentation of Trees',\n",
242-
" blend=True,\n",
243-
")"
244-
]
245-
},
246-
{
247-
"cell_type": "markdown",
248-
"metadata": {},
249-
"source": [
250-
"![](https://i.imgur.com/ytKMTlA.png)"
251-
]
252-
},
253-
{
254-
"cell_type": "markdown",
255-
"metadata": {},
256-
"source": [
257-
"Show the result without bounding boxes on the map."
258-
]
259-
},
260-
{
261-
"cell_type": "code",
262-
"execution_count": null,
263-
"metadata": {},
264-
"outputs": [],
265-
"source": [
266-
"sam.show_anns(\n",
267-
" cmap='Greens',\n",
268-
" add_boxes=False,\n",
269-
" alpha=0.5,\n",
270-
" title='Automatic Segmentation of Trees',\n",
271-
")"
272-
]
273-
},
274-
{
275-
"cell_type": "markdown",
276-
"metadata": {},
277-
"source": [
278-
"![](https://i.imgur.com/3Iq2kt1.png)"
279-
]
280-
},
281-
{
282-
"cell_type": "markdown",
283-
"metadata": {},
284-
"source": [
285-
"Show the result as a grayscale image."
286-
]
287-
},
288-
{
289-
"cell_type": "code",
290-
"execution_count": null,
291-
"metadata": {},
292-
"outputs": [],
293-
"source": [
294-
"sam.show_anns(\n",
295-
" cmap='Greys_r',\n",
296-
" add_boxes=False,\n",
297-
" alpha=1,\n",
298-
" title='Automatic Segmentation of Trees',\n",
299-
" blend=False,\n",
300-
" output='trees.tif',\n",
301-
")"
302-
]
303-
},
304-
{
305-
"cell_type": "markdown",
306-
"metadata": {},
307-
"source": [
308-
"![](https://i.imgur.com/KtHwFbF.png)"
309-
]
310-
},
311-
{
312-
"cell_type": "markdown",
313-
"metadata": {},
314-
"source": [
315-
"Convert the result to a vector format. "
161+
"sam.everything_prompt(output=\"mask.tif\")"
316162
]
317163
},
318164
{
@@ -321,14 +167,7 @@
321167
"metadata": {},
322168
"outputs": [],
323169
"source": [
324-
"sam.raster_to_vector(\"trees.tif\", \"trees.shp\")"
325-
]
326-
},
327-
{
328-
"cell_type": "markdown",
329-
"metadata": {},
330-
"source": [
331-
"Show the results on the interactive map."
170+
"sam.raster_to_vector(\"mask.tif\", \"mask.geojson\")"
332171
]
333172
},
334173
{
@@ -337,38 +176,16 @@
337176
"metadata": {},
338177
"outputs": [],
339178
"source": [
340-
"m.add_raster(\"trees.tif\", layer_name=\"Trees\", palette=\"Greens\", opacity=0.5, nodata=0)\n",
341-
"style = {\n",
342-
" \"color\": \"#3388ff\",\n",
343-
" \"weight\": 2,\n",
344-
" \"fillColor\": \"#7c4185\",\n",
345-
" \"fillOpacity\": 0.5,\n",
346-
"}\n",
347-
"m.add_vector(\"trees.shp\", layer_name=\"Vector\", style=style)\n",
179+
"m.add_raster(\"mask.tif\", opacity=0.5, layer_name=\"Mask\")\n",
180+
"m.add_vector(\"mask.geojson\", layer_name=\"Mask Vector\")\n",
348181
"m"
349182
]
350183
},
351184
{
352185
"cell_type": "markdown",
353186
"metadata": {},
354187
"source": [
355-
"## Interactive segmentation"
356-
]
357-
},
358-
{
359-
"cell_type": "code",
360-
"execution_count": null,
361-
"metadata": {},
362-
"outputs": [],
363-
"source": [
364-
"sam.show_map()"
365-
]
366-
},
367-
{
368-
"cell_type": "markdown",
369-
"metadata": {},
370-
"source": [
371-
"![](https://i.imgur.com/wydt5Xt.gif)"
188+
"![](https://i.imgur.com/LvEAMSl.png)"
372189
]
373190
}
374191
],
@@ -388,7 +205,7 @@
388205
"name": "python",
389206
"nbconvert_exporter": "python",
390207
"pygments_lexer": "ipython3",
391-
"version": "3.10.12"
208+
"version": "3.9.16"
392209
},
393210
"orig_nbformat": 4
394211
},

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,6 @@ nav:
6262
- API Reference:
6363
- common module: common.md
6464
- samgeo module: samgeo.md
65+
- fast_sam module: fast_sam.md
6566
- hq_sam module: hq_sam.md
6667
- text_sam module: text_sam.md

samgeo/common.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1228,7 +1228,7 @@ def draw_tile(source, lat0, lon0, lat1, lon1, zoom, filename, **kwargs):
12281228
return image
12291229

12301230

1231-
def raster_to_vector(source, output, simplify_tolerance=None, **kwargs):
1231+
def raster_to_vector(source, output, simplify_tolerance=None, dst_crs=None, **kwargs):
12321232
"""Vectorize a raster dataset.
12331233
12341234
Args:
@@ -1256,6 +1256,10 @@ def raster_to_vector(source, output, simplify_tolerance=None, **kwargs):
12561256
gdf = gpd.GeoDataFrame.from_features(fc)
12571257
if src.crs is not None:
12581258
gdf.set_crs(crs=src.crs, inplace=True)
1259+
1260+
if dst_crs is not None:
1261+
gdf = gdf.to_crs(dst_crs)
1262+
12591263
gdf.to_file(output, **kwargs)
12601264

12611265

0 commit comments

Comments
 (0)