{"id":1710,"date":"2026-10-29T07:03:58","date_gmt":"2026-10-29T07:03:58","guid":{"rendered":"https:\/\/helpwithmygisassignment.com\/blog\/?p=1710"},"modified":"2026-10-29T07:03:58","modified_gmt":"2026-10-29T07:03:58","slug":"sam-2-building-footprint-extraction-qgis-python","status":"publish","type":"post","link":"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/","title":{"rendered":"Automated Building Footprint Extraction using Segment Anything Model 2 (SAM 2) in QGIS and Python"},"content":{"rendered":"<div id=\"model-response-message-contentr_bb088f71f28ce627\" class=\"markdown markdown-main-panel md-content enable-luminous-fast-follows enable-updated-hr-color stronger tutor-markdown-rendering\" dir=\"ltr\" aria-busy=\"false\" aria-live=\"polite\">\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_89 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/#Automated_Building_Footprint_Extraction_using_Segment_Anything_Model_2_SAM_2_in_QGIS_and_Python\" >Automated Building Footprint Extraction using Segment Anything Model 2 (SAM 2) in QGIS and Python<\/a><ul class='ez-toc-list-level-2' ><li class='ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/#Introduction\" >Introduction<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/#Environment_Setup_Prerequisites\" >Environment Setup &amp; Prerequisites<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/#1_Creating_the_Conda_Environment\" >1. Creating the Conda Environment<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/#2_Installing_Core_Dependencies\" >2. Installing Core Dependencies<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/#Step-by-Step_Coding_Workflow\" >Step-by-Step Coding Workflow<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/#Step_1_Loading_High-Resolution_Orthophotos_and_Generating_Image_Embeddings\" >Step 1: Loading High-Resolution Orthophotos and Generating Image Embeddings<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/#Step_2_Passing_Prompt_Points_or_Bounding_Boxes_to_Isolate_Rooftop_Structures\" >Step 2: Passing Prompt Points or Bounding Boxes to Isolate Rooftop Structures<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/#Step_3_Extracting_Binary_Mask_Arrays_and_Polygonizing_Raster_Contours\" >Step 3: Extracting Binary Mask Arrays and Polygonizing Raster Contours<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/#Step_4_Smoothing_and_Converting_Pixel_Polygons_into_Clean_GIS_Shapefiles\" >Step 4: Smoothing and Converting Pixel Polygons into Clean GIS Shapefiles<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/#Visualizing_Results\" >Visualizing Results<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/#Integration_and_Advanced_GeoAI_Strategies\" >Integration and Advanced GeoAI Strategies<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/#Summary\" >Summary<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h1 class=\"\" data-path-to-node=\"0\"><span class=\"ez-toc-section\" id=\"Automated_Building_Footprint_Extraction_using_Segment_Anything_Model_2_SAM_2_in_QGIS_and_Python\"><\/span>Automated Building Footprint Extraction using Segment Anything Model 2 (SAM 2) in QGIS and Python<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<h2 class=\"\" data-path-to-node=\"1\"><span class=\"ez-toc-section\" id=\"Introduction\"><\/span>Introduction<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<div><span class=\"citation-20 citation-21\">Implementing <\/span><b data-path-to-node=\"1,0\" data-index-in-node=\"14\"><span class=\"citation-20 citation-21\">SAM 2 Building Footprint Extraction QGIS Python<\/span><\/b><span class=\"citation-20 citation-21 citation-end-21\"> pipelines allows geospatial analysts and data scientists to achieve state-of-the-art vector extraction without training custom neural networks from <\/span>scratch. In the rapidly evolving domain of Geographic Information Systems (GIS) and Remote Sensing, the extraction of vector building footprints from high-resolution aerial and satellite imagery has historically relied on task-specific deep learning architectures, such as U-Net, Mask R-CNN, or customized YOLO variants. While effective within specific training domains, these models demand extensive manual annotation datasets, rigorous hyperparameter tuning, and often suffer from severe domain shift when applied to unseen urban or rural topographies.<\/div>\n<div>The introduction of Meta\u2019s <b data-path-to-node=\"3\" data-index-in-node=\"27\">Segment Anything Model 2 (SAM 2)<\/b> represents a monumental paradigm shift. <span class=\"citation-9 citation-end-9\">As a promptable vision foundation model capable of zero-shot object segmentation across images and video streams, SAM 2 encodes rich spatial priors and hierarchical feature representations.<\/span> Implementing <b data-path-to-node=\"3\" data-index-in-node=\"303\">SAM 2 Building Footprint Extraction QGIS Python<\/b> pipelines allows geospatial analysts and data scientists to achieve state-of-the-art vector extraction without training custom neural networks from scratch. This comprehensive tutorial explores how to leverage SAM 2, Hugging Face <code data-path-to-node=\"3\" data-index-in-node=\"581\">transformers<\/code>, <code data-path-to-node=\"3\" data-index-in-node=\"595\">rasterio<\/code>, and <code data-path-to-node=\"3\" data-index-in-node=\"609\">geopandas<\/code> to programmatically extract, polygonize, smooth, and export rooftop geometries directly into analysis-ready GIS formats.<\/div>\n<h2 data-path-to-node=\"5\"><span class=\"ez-toc-section\" id=\"Environment_Setup_Prerequisites\"><\/span>Environment Setup &amp; Prerequisites<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<div>Before diving into the code, you must configure a robust Python environment capable of handling heavy tensor computations and spatial coordinate transformations. It is strongly recommended to use an NVIDIA GPU with at least 12GB of VRAM and CUDA installed.<\/div>\n<h3 data-path-to-node=\"7\"><span class=\"ez-toc-section\" id=\"1_Creating_the_Conda_Environment\"><\/span>1. Creating the Conda Environment<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div>Open your terminal and create a dedicated virtual environment:<\/div>\n<div class=\"code-block ng-tns-c2599462034-12 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\" data-hveid=\"0\" data-ved=\"0CAAQhtANahgKEwjejqv47tmXAxUAAAAAHQAAAAAQgwE\">\n<div class=\"formatted-code-block-internal-container ng-tns-c2599462034-12\">\n<div class=\"animated-opacity ng-tns-c2599462034-12\">\n<div class=\"code-block-decoration header-formatted gds-emphasized-body-m ng-tns-c2599462034-12 ng-star-inserted\">\n<p><span class=\"ng-tns-c2599462034-12\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c2599462034-12 ng-star-inserted\"><\/div>\n<\/div>\n<pre class=\"ng-tns-c2599462034-12\"><code class=\"code-container formatted ng-tns-c2599462034-12\" role=\"text\" data-test-id=\"code-content\">conda create -n geoai-sam2 python=3.10 -y\r\nconda activate geoai-sam2\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<h3 data-path-to-node=\"10\"><span class=\"ez-toc-section\" id=\"2_Installing_Core_Dependencies\"><\/span>2. Installing Core Dependencies<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div>Install PyTorch (matching your CUDA version) alongside Hugging Face <code data-path-to-node=\"11\" data-index-in-node=\"68\">transformers<\/code>, <code data-path-to-node=\"11\" data-index-in-node=\"82\">rasterio<\/code>, <code data-path-to-node=\"11\" data-index-in-node=\"92\">geopandas<\/code>, and ancillary spatial libraries:<\/div>\n<div class=\"code-block ng-tns-c2599462034-13 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\" data-hveid=\"0\" data-ved=\"0CAAQhtANahgKEwjejqv47tmXAxUAAAAAHQAAAAAQhAE\">\n<div class=\"formatted-code-block-internal-container ng-tns-c2599462034-13\">\n<div class=\"animated-opacity ng-tns-c2599462034-13\">\n<div class=\"code-block-decoration header-formatted gds-emphasized-body-m ng-tns-c2599462034-13 ng-star-inserted\">\n<p><span class=\"ng-tns-c2599462034-13\">Bash<\/span><\/p>\n<div class=\"buttons ng-tns-c2599462034-13 ng-star-inserted\"><\/div>\n<\/div>\n<pre class=\"ng-tns-c2599462034-13\"><code class=\"code-container formatted ng-tns-c2599462034-13\" role=\"text\" data-test-id=\"code-content\">pip install torch torchvision --index-url https:\/\/download.pytorch.org\/whl\/cu121\r\npip install transformers accelerate datasets\r\npip install rasterio geopandas shapely fiona scikit-image matplotlib\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div>Verify your installation by running a quick python check to ensure CUDA is accessible by PyTorch:<\/div>\n<div class=\"code-block ng-tns-c2599462034-14 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\" data-hveid=\"0\" data-ved=\"0CAAQhtANahgKEwjejqv47tmXAxUAAAAAHQAAAAAQhQE\">\n<div class=\"formatted-code-block-internal-container ng-tns-c2599462034-14\">\n<div class=\"animated-opacity ng-tns-c2599462034-14\">\n<div class=\"code-block-decoration header-formatted gds-emphasized-body-m ng-tns-c2599462034-14 ng-star-inserted\">\n<p><span class=\"ng-tns-c2599462034-14\">Python<\/span><\/p>\n<div class=\"buttons ng-tns-c2599462034-14 ng-star-inserted\"><\/div>\n<\/div>\n<pre class=\"ng-tns-c2599462034-14\"><code class=\"code-container formatted ng-tns-c2599462034-14\" role=\"text\" data-test-id=\"code-content\"><span class=\"hljs-keyword\">import<\/span> torch\r\nprint(<span class=\"hljs-string\">f\"CUDA Available: <span class=\"hljs-subst\">{torch.cuda.is_available()}<\/span>\"<\/span>)\r\nprint(<span class=\"hljs-string\">f\"Device Name: <span class=\"hljs-subst\">{torch.cuda.get_device_name(<span class=\"hljs-number\">0<\/span>) <span class=\"hljs-keyword\">if<\/span> torch.cuda.is_available() <span class=\"hljs-keyword\">else<\/span> 'CPU'}<\/span>\"<\/span>)\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<h2 data-path-to-node=\"16\"><span class=\"ez-toc-section\" id=\"Step-by-Step_Coding_Workflow\"><\/span>Step-by-Step Coding Workflow<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h3 data-path-to-node=\"17\"><span class=\"ez-toc-section\" id=\"Step_1_Loading_High-Resolution_Orthophotos_and_Generating_Image_Embeddings\"><\/span>Step 1: Loading High-Resolution Orthophotos and Generating Image Embeddings<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-1800\" src=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_yzfy52yzfy52yzfy-1024x572.jpg\" alt=\"System architecture diagram illustrating Automated Building Footprint Extraction using Segment Anything Model 2 (SAM 2) in QGIS and Python\" width=\"1024\" height=\"572\" srcset=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_yzfy52yzfy52yzfy-1024x572.jpg 1024w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_yzfy52yzfy52yzfy-300x167.jpg 300w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_yzfy52yzfy52yzfy-768x429.jpg 768w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_yzfy52yzfy52yzfy.jpg 1376w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<div>Geospatial rasters contain critical spatial referencing metadata\u2014specifically the Affine transform and Coordinate Reference System (CRS)\u2014that standard computer vision libraries ignore, which is especially vital when <a class=\"ng-star-inserted\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/cloud-optimized-geotiff-web-map-architecture\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwilpPTzw96XAxUAAAAAHQAAAAAQvw4\">Optimizing Enterprise Web Maps with Cloud-Optimized GeoTIFF (COG) <strong>Architecture<\/strong><\/a><strong>.<\/strong> We use <code data-path-to-node=\"18\" data-index-in-node=\"192\">rasterio<\/code> to read the orthophoto while retaining its geospatial anchor.<\/div>\n<div class=\"code-block ng-tns-c2599462034-15 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\" data-hveid=\"0\" data-ved=\"0CAAQhtANahgKEwjejqv47tmXAxUAAAAAHQAAAAAQhgE\">\n<div class=\"formatted-code-block-internal-container ng-tns-c2599462034-15\">\n<div class=\"animated-opacity ng-tns-c2599462034-15\">\n<div class=\"code-block-decoration header-formatted gds-emphasized-body-m ng-tns-c2599462034-15 ng-star-inserted\">\n<p><span class=\"ng-tns-c2599462034-15\">Python<\/span><\/p>\n<div class=\"buttons ng-tns-c2599462034-15 ng-star-inserted\"><\/div>\n<\/div>\n<pre class=\"ng-tns-c2599462034-15\"><code class=\"code-container formatted ng-tns-c2599462034-15\" role=\"text\" data-test-id=\"code-content\"><span class=\"hljs-keyword\">import<\/span> rasterio\r\n<span class=\"hljs-keyword\">from<\/span> rasterio.windows <span class=\"hljs-keyword\">import<\/span> Window\r\n<span class=\"hljs-keyword\">import<\/span> numpy <span class=\"hljs-keyword\">as<\/span> np\r\n<span class=\"hljs-keyword\">import<\/span> torch\r\n<span class=\"hljs-keyword\">from<\/span> PIL <span class=\"hljs-keyword\">import<\/span> Image\r\n<span class=\"hljs-keyword\">from<\/span> transformers <span class=\"hljs-keyword\">import<\/span> Sam2Model, Sam2Processor\r\n\r\n<span class=\"hljs-comment\"># Load the georeferenced aerial orthophoto<\/span>\r\nraster_path = <span class=\"hljs-string\">\"data\/nairobi_ortho_0.2m.tif\"<\/span>\r\n\r\n<span class=\"hljs-keyword\">with<\/span> rasterio.<span class=\"hljs-built_in\">open<\/span>(raster_path) <span class=\"hljs-keyword\">as<\/span> src:\r\n    meta = src.meta.copy()\r\n    crs = src.crs\r\n    transform = src.transform\r\n    <span class=\"hljs-comment\"># Read RGB bands (assuming bands 1, 2, 3 correspond to R, G, B)<\/span>\r\n    img_array = src.read([<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">2<\/span>, <span class=\"hljs-number\">3<\/span>])\r\n    <span class=\"hljs-comment\"># Reshape from (Bands, Height, Width) to (Height, Width, Bands) for PIL\/Transformers<\/span>\r\n    img_array = np.moveaxis(img_array, <span class=\"hljs-number\">0<\/span>, -<span class=\"hljs-number\">1<\/span>)\r\n    \r\n<span class=\"hljs-comment\"># Initialize SAM 2 Model and Processor from Hugging Face<\/span>\r\nmodel_id = <span class=\"hljs-string\">\"facebook\/sam2.1-hiera-large\"<\/span>\r\ndevice = <span class=\"hljs-string\">\"cuda\"<\/span> <span class=\"hljs-keyword\">if<\/span> torch.cuda.is_available() <span class=\"hljs-keyword\">else<\/span> <span class=\"hljs-string\">\"cpu\"<\/span>\r\n\r\nprint(<span class=\"hljs-string\">f\"Loading SAM 2 model (<span class=\"hljs-subst\">{model_id}<\/span>) onto <span class=\"hljs-subst\">{device}<\/span>...\"<\/span>)\r\nprocessor = Sam2Processor.from_pretrained(model_id)\r\nmodel = Sam2Model.from_pretrained(model_id).to(device)\r\n\r\n<span class=\"hljs-comment\"># Convert numpy array to PIL Image for the processor<\/span>\r\npil_image = Image.fromarray(img_array.astype(<span class=\"hljs-string\">'uint8'<\/span>))\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<h3 data-path-to-node=\"21\"><span class=\"ez-toc-section\" id=\"Step_2_Passing_Prompt_Points_or_Bounding_Boxes_to_Isolate_Rooftop_Structures\"><\/span>Step 2: Passing Prompt Points or Bounding Boxes to Isolate Rooftop Structures<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-1801\" src=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_aij7vyaij7vyaij7-1024x572.jpg\" alt=\"Infographic showing bounding box prompts and mask inference during Automated Building Footprint Extraction using Segment Anything Model 2 (SAM 2) in QGIS and Python\" width=\"1024\" height=\"572\" srcset=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_aij7vyaij7vyaij7-1024x572.jpg 1024w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_aij7vyaij7vyaij7-300x167.jpg 300w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_aij7vyaij7vyaij7-768x429.jpg 768w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_aij7vyaij7vyaij7.jpg 1376w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<div><span class=\"citation-8 citation-end-8\">To extract building footprints in a zero-shot fashion, we can either feed bounding box priors (generated via coarse object detection) or prompt points located on rooftops.<\/span><span class=\"\"> Below is an implementation utilizing bounding box prompts corresponding to detected industrial and residential structures.<\/span><\/div>\n<div class=\"code-block ng-tns-c2599462034-16 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\" data-hveid=\"0\" data-ved=\"0CAAQhtANahgKEwjejqv47tmXAxUAAAAAHQAAAAAQhwE\">\n<div class=\"formatted-code-block-internal-container ng-tns-c2599462034-16\">\n<div class=\"animated-opacity ng-tns-c2599462034-16\">\n<div class=\"code-block-decoration header-formatted gds-emphasized-body-m ng-tns-c2599462034-16 ng-star-inserted\">\n<p><span class=\"ng-tns-c2599462034-16\">Python<\/span><\/p>\n<div class=\"buttons ng-tns-c2599462034-16 ng-star-inserted\"><\/div>\n<\/div>\n<pre class=\"ng-tns-c2599462034-16\"><code class=\"code-container formatted ng-tns-c2599462034-16\" role=\"text\" data-test-id=\"code-content\"><span class=\"hljs-comment\"># Define bounding boxes [x_min, y_min, x_max, y_max] for target buildings in pixel coordinates<\/span>\r\ninput_boxes = [\r\n    [<span class=\"hljs-number\">450<\/span>, <span class=\"hljs-number\">320<\/span>, <span class=\"hljs-number\">680<\/span>, <span class=\"hljs-number\">510<\/span>],\r\n    [<span class=\"hljs-number\">720<\/span>, <span class=\"hljs-number\">610<\/span>, <span class=\"hljs-number\">950<\/span>, <span class=\"hljs-number\">800<\/span>]\r\n]\r\n\r\n<span class=\"hljs-comment\"># Format inputs for SAM 2 processor<\/span>\r\ninputs = processor(\r\n    images=pil_image,\r\n    input_boxes=[input_boxes],\r\n    return_tensors=<span class=\"hljs-string\">\"pt\"<\/span>\r\n).to(model.device)\r\n\r\n<span class=\"hljs-comment\"># Perform inference without gradient tracking<\/span>\r\n<span class=\"hljs-keyword\">with<\/span> torch.no_grad():\r\n    outputs = model(**inputs)\r\n\r\n<span class=\"hljs-comment\"># Post-process masks back to original image size<\/span>\r\nmasks = processor.post_process_masks(\r\n    outputs.pred_masks.cpu(),\r\n    inputs[<span class=\"hljs-string\">\"original_sizes\"<\/span>].cpu()\r\n)\r\n\r\n<span class=\"hljs-comment\"># Extract the highest scoring binary mask tensor<\/span>\r\n<span class=\"hljs-comment\"># masks[0] shape: (num_boxes, num_masks_per_box, H, W)<\/span>\r\npred_masks = masks[<span class=\"hljs-number\">0<\/span>][:, <span class=\"hljs-number\">0<\/span>, :, :].numpy()\r\nbinary_mask = (pred_masks.<span class=\"hljs-built_in\">sum<\/span>(axis=<span class=\"hljs-number\">0<\/span>) &gt; <span class=\"hljs-number\">0<\/span>).astype(np.uint8)\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<h3 data-path-to-node=\"25\"><span class=\"ez-toc-section\" id=\"Step_3_Extracting_Binary_Mask_Arrays_and_Polygonizing_Raster_Contours\"><\/span>Step 3: Extracting Binary Mask Arrays and Polygonizing Raster Contours<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div>Once we obtain the aggregated binary mask array representing all segmented building footprints, we convert the pixel-level raster predictions into clean geometric vector features using <code data-path-to-node=\"26\" data-index-in-node=\"185\">rasterio.features.shapes<\/code>.<\/div>\n<div class=\"code-block ng-tns-c2599462034-17 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\" data-hveid=\"0\" data-ved=\"0CAAQhtANahgKEwjejqv47tmXAxUAAAAAHQAAAAAQiAE\">\n<div class=\"formatted-code-block-internal-container ng-tns-c2599462034-17\">\n<div class=\"animated-opacity ng-tns-c2599462034-17\">\n<div class=\"code-block-decoration header-formatted gds-emphasized-body-m ng-tns-c2599462034-17 ng-star-inserted\">\n<p><span class=\"ng-tns-c2599462034-17\">Python<\/span><\/p>\n<div class=\"buttons ng-tns-c2599462034-17 ng-star-inserted\"><\/div>\n<\/div>\n<pre class=\"ng-tns-c2599462034-17\"><code class=\"code-container formatted ng-tns-c2599462034-17\" role=\"text\" data-test-id=\"code-content\"><span class=\"hljs-keyword\">from<\/span> rasterio.features <span class=\"hljs-keyword\">import<\/span> shapes\r\n<span class=\"hljs-keyword\">import<\/span> geopandas <span class=\"hljs-keyword\">as<\/span> gpd\r\n<span class=\"hljs-keyword\">from<\/span> shapely.geometry <span class=\"hljs-keyword\">import<\/span> shape\r\n\r\n<span class=\"hljs-comment\"># Extract shapes (polygons and values) from the binary mask array<\/span>\r\n<span class=\"hljs-comment\"># We apply the raster's affine transform to map pixels to geospatial coordinates<\/span>\r\nshape_generator = shapes(\r\n    binary_mask,\r\n    transform=transform\r\n)\r\n\r\n<span class=\"hljs-comment\"># Convert generator output into a list of Shapely geometries and attributes<\/span>\r\nrecords = []\r\n<span class=\"hljs-keyword\">for<\/span> geom, value <span class=\"hljs-keyword\">in<\/span> shape_generator:\r\n    <span class=\"hljs-keyword\">if<\/span> value == <span class=\"hljs-number\">1<\/span>:  <span class=\"hljs-comment\"># Keep foreground building features<\/span>\r\n        polygon = shape(geom)\r\n        records.append({<span class=\"hljs-string\">\"geometry\"<\/span>: polygon})\r\n\r\n<span class=\"hljs-comment\"># Construct initial GeoDataFrame in native CRS<\/span>\r\ngdf = gpd.GeoDataFrame.from_features(records, crs=crs)\r\nprint(<span class=\"hljs-string\">f\"Extracted <span class=\"hljs-subst\">{<span class=\"hljs-built_in\">len<\/span>(gdf)}<\/span> raw building polygons.\"<\/span>)\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<h3 data-path-to-node=\"29\"><span class=\"ez-toc-section\" id=\"Step_4_Smoothing_and_Converting_Pixel_Polygons_into_Clean_GIS_Shapefiles\"><\/span>Step 4: Smoothing and Converting Pixel Polygons into Clean GIS Shapefiles<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-1802\" src=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_4k2rnu4k2rnu4k2r-1024x572.jpg\" alt=\"Workflow diagram showing polygonization and smoothing stages for Automated Building Footprint Extraction using Segment Anything Model 2 (SAM 2) in QGIS and Python\" width=\"1024\" height=\"572\" srcset=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_4k2rnu4k2rnu4k2r-1024x572.jpg 1024w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_4k2rnu4k2rnu4k2r-300x167.jpg 300w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_4k2rnu4k2rnu4k2r-768x429.jpg 768w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_4k2rnu4k2rnu4k2r.jpg 1376w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<div>Raw raster-derived polygons often exhibit &#8220;stair-stepping&#8221; artifacts due to pixel grid discretization. To ensure cartographic and topological integrity, we apply buffer operations and Douglas-Peucker simplification before exporting to a GeoPackage (<code data-path-to-node=\"30\" data-index-in-node=\"249\">.gpkg<\/code>).<\/div>\n<div class=\"code-block ng-tns-c2599462034-18 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation\" data-hveid=\"0\" data-ved=\"0CAAQhtANahgKEwjejqv47tmXAxUAAAAAHQAAAAAQiQE\">\n<div class=\"formatted-code-block-internal-container ng-tns-c2599462034-18\">\n<div class=\"animated-opacity ng-tns-c2599462034-18\">\n<div class=\"code-block-decoration header-formatted gds-emphasized-body-m ng-tns-c2599462034-18 ng-star-inserted\">\n<p><span class=\"ng-tns-c2599462034-18\">Python<\/span><\/p>\n<div class=\"buttons ng-tns-c2599462034-18 ng-star-inserted\"><\/div>\n<\/div>\n<pre class=\"ng-tns-c2599462034-18\"><code class=\"code-container formatted ng-tns-c2599462034-18\" role=\"text\" data-test-id=\"code-content\"><span class=\"hljs-keyword\">from<\/span> shapely.geometry <span class=\"hljs-keyword\">import<\/span> Polygon\r\n\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">smooth_and_clean_polygon<\/span>(<span class=\"hljs-params\">poly, tolerance=<span class=\"hljs-number\">0.5<\/span>, buffer_dist=<span class=\"hljs-number\">0.6<\/span><\/span>):<\/span>\r\n    <span class=\"hljs-string\">\"\"\"\r\n    Applies negative\/positive buffering (morphological closing\/opening equivalent)\r\n    to fill small gaps, followed by Douglas-Peucker simplification.\r\n    \"\"\"<\/span>\r\n    <span class=\"hljs-keyword\">if<\/span> <span class=\"hljs-keyword\">not<\/span> poly.is_valid:\r\n        poly = poly.buffer(<span class=\"hljs-number\">0<\/span>)\r\n    <span class=\"hljs-comment\"># Morphological smoothing via buffering<\/span>\r\n    smoothed = poly.buffer(buffer_dist).buffer(-buffer_dist)\r\n    <span class=\"hljs-comment\"># Simplify geometry<\/span>\r\n    simplified = smoothed.simplify(tolerance, preserve_topology=<span class=\"hljs-literal\">True<\/span>)\r\n    <span class=\"hljs-keyword\">return<\/span> simplified\r\n\r\n<span class=\"hljs-comment\"># Apply cleaning function to all geometries<\/span>\r\ngdf[<span class=\"hljs-string\">\"geometry\"<\/span>] = gdf[<span class=\"hljs-string\">\"geometry\"<\/span>].apply(<span class=\"hljs-keyword\">lambda<\/span> p: smooth_and_clean_polygon(p, tolerance=<span class=\"hljs-number\">0.4<\/span>, buffer_dist=<span class=\"hljs-number\">0.5<\/span>))\r\n\r\n<span class=\"hljs-comment\"># Filter out sliver polygons falling below minimum area threshold (e.g., 5 square meters)<\/span>\r\ngdf = gdf[gdf.geometry.area &gt;= <span class=\"hljs-number\">5.0<\/span>].reset_index(drop=<span class=\"hljs-literal\">True<\/span>)\r\n\r\n<span class=\"hljs-comment\"># Export to production GeoPackage layer for QGIS consumption<\/span>\r\noutput_gpkg = <span class=\"hljs-string\">\"outputs\/extracted_buildings_sam2.gpkg\"<\/span>\r\ngdf.to_file(output_gpkg, layer=<span class=\"hljs-string\">\"sam2_buildings\"<\/span>, driver=<span class=\"hljs-string\">\"GPKG\"<\/span>)\r\nprint(<span class=\"hljs-string\">f\"Successfully exported cleaned vector footprints to <span class=\"hljs-subst\">{output_gpkg}<\/span>\"<\/span>)\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<h2 data-path-to-node=\"33\"><span class=\"ez-toc-section\" id=\"Visualizing_Results\"><\/span>Visualizing Results<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1712 size-full\" src=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/images-2.jpg\" alt=\"SAM 2 Building Footprint Extraction QGIS Python\" width=\"442\" height=\"226\" srcset=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/images-2.jpg 442w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/images-2-300x153.jpg 300w\" sizes=\"auto, (max-width: 442px) 100vw, 442px\" \/><\/p>\n<div class=\"attachment-container search-images md-has-block-component\"><\/div>\n<h2 data-path-to-node=\"36\"><span class=\"ez-toc-section\" id=\"Integration_and_Advanced_GeoAI_Strategies\"><\/span>Integration and Advanced GeoAI Strategies<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<div>Integrating Python-based GeoAI workflows directly into QGIS streamlines the transition from raw raster data to vector management:<\/div>\n<ol start=\"1\" data-path-to-node=\"38\">\n<li>\n<div><b data-path-to-node=\"38,0,0\" data-index-in-node=\"0\">PyQGIS Integration<\/b>: You can wrap the script above into a custom QGIS Processing Algorithm script, allowing desktop users to run SAM 2 inference via the graphical Processing Toolbox interface.<\/div>\n<\/li>\n<li>\n<div><b data-path-to-node=\"38,1,0\" data-index-in-node=\"0\">Anchor Detection Pipelines<\/b>: To automate bounding box generation across city-scale datasets without manual annotation, pair SAM 2 with object detection models. For instance, initial anchor coordinates can be generated using <a class=\"ng-star-inserted\" href=\"https:\/\/www.geowgs84.ai\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwjejqv47tmXAxUAAAAAHQAAAAAQiwE\">YOLOv8 satellite object detection<\/a> models trained specifically on overhead imagery.<\/div>\n<\/li>\n<li>\n<div><b data-path-to-node=\"38,2,0\" data-index-in-node=\"0\">Large Raster Handling<\/b>: For regional mosaics spanning gigabytes, implement windowed reading strategies as outlined in our <a class=\"ng-star-inserted\" href=\"https:\/\/www.geowgs84.ai\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwjejqv47tmXAxUAAAAAHQAAAAAQjAE\">Python rasterio tutorials<\/a> to process imagery in manageable spatial tiles with overlapping buffers to eliminate edge artifacts.<\/div>\n<\/li>\n<li>\n<div><b data-path-to-node=\"38,3,0\" data-index-in-node=\"0\">Cartographic Refinement<\/b>: Standardize rooftop angles and enforce orthogonal right angles using specialized <a class=\"ng-star-inserted\" href=\"https:\/\/www.geowgs84.ai\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwjejqv47tmXAxUAAAAAHQAAAAAQjQE\">cartographic generalization guides<\/a> and Python libraries like <code data-path-to-node=\"38,3,0\" data-index-in-node=\"167\">momepy<\/code> or <code data-path-to-node=\"38,3,0\" data-index-in-node=\"177\">shapely<\/code> envelope fitting.<\/div>\n<\/li>\n<\/ol>\n<h2 data-path-to-node=\"40\"><span class=\"ez-toc-section\" id=\"Summary\"><\/span>Summary<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<div>The integration of Meta&#8217;s Segment Anything Model 2 (SAM 2) into Python and QGIS workflows bridges the gap between state-of-the-art computer vision and operational GIS analytics. By combining Hugging Face transformer pipelines with <code data-path-to-node=\"41\" data-index-in-node=\"231\">rasterio<\/code> spatial referencing and <code data-path-to-node=\"41\" data-index-in-node=\"264\">geopandas<\/code> vector processing, GIS professionals can rapidly execute zero-shot building footprint extraction, bypass the bottleneck of manual training dataset creation, and produce high-fidelity spatial data layers for urban planning, infrastructure management, and disaster risk assessment.<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Automated Building Footprint Extraction using Segment Anything Model 2 (SAM 2) in QGIS and Python Introduction Implementing SAM 2 Building Footprint Extraction QGIS Python pipelines allows geospatial analysts and data scientists to achieve state-of-the-art vector extraction without training custom neural networks from scratch. In the rapidly evolving domain of Geographic Information Systems (GIS) and Remote &#8230; <a title=\"Automated Building Footprint Extraction using Segment Anything Model 2 (SAM 2) in QGIS and Python\" class=\"read-more\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/sam-2-building-footprint-extraction-qgis-python\/\" aria-label=\"Read more about Automated Building Footprint Extraction using Segment Anything Model 2 (SAM 2) in QGIS and Python\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":1800,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,4],"tags":[],"class_list":["post-1710","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","category-gis-articles"],"_links":{"self":[{"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/posts\/1710","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/comments?post=1710"}],"version-history":[{"count":4,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/posts\/1710\/revisions"}],"predecessor-version":[{"id":1803,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/posts\/1710\/revisions\/1803"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/media\/1800"}],"wp:attachment":[{"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/media?parent=1710"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/categories?post=1710"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/tags?post=1710"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}