Skip to content
AI Segmentation
QGIS
Tutorial

Detect Swimming Pools in QGIS: 5 Methods

Published Updated

Suburban houses with back gardens from the air, before and after automatic swimming pool detection (after)
Suburban houses with back gardens from the air, before and after automatic swimming pool detection (before)
ImageryDetected
Drag to compare
One automatic pass over a suburban block on Long Island, on Google Satellite imagery. Forty pools outlined in magenta, including the small ones under trees. Drag the handle to compare.

To detect swimming pools in QGIS, check OpenStreetMap first: Vector > QuickOSM > QuickOSM…, key leisure, value swimming_pool. Where the map is thin, run a segmentation model or threshold the blue in the raster calculator. Ground resolution decides which.

Your inputMethodWhat it costs
Any area with active OSM mappersMethod 1, QuickOSM on leisure=swimming_poolFree, one query
RGB orthophoto and hundreds of poolsMethod 2, a segmentation modelFree plugins want your own model or a GPU. Cloud plugins have free tiers, then a subscription
RGB orthophoto at 5 to 30 cmMethod 3, colour threshold in the raster calculatorFree, in core QGIS
Imagery with a near-infrared or SWIR bandMethod 4, a water index, then a thresholdFree, blind to garden pools on satellite
Multispectral imagery and an afternoonMethod 5, SCP or dzetsakaFree plugins, your time drawing training areas

Every version, price and menu path here was read on 3 September 2026 against the QGIS 3.44 manual and each tool's own documentation.

Method 1: Pull the pools somebody already mapped

OpenStreetMap carries 3,036,801 objects tagged leisure=swimming_pool, 2,731,704 of them ways with real geometry, on taginfo on 3 September 2026.

Open QuickOSM and query

Vector > QuickOSM > QuickOSM…, which queries the Overpass API. Key leisure, value swimming_pool, on the canvas extent or a named administrative area.

Keep polygons, filter to gardens

A pool mapped as a node has no area, so take the polygon layer. 1,808,809 of these pools also carry access=private, the filter for backyard pools.

leisure=swimming_area is a different object: a designated place to swim in a lake or the sea.

A suburban block on satellite imagery with OSM swimming pool polygons in blue over three pools, and seven other visible pools with no polygon at all.
Three pools mapped, seven not. Mappers draw public and hotel pools. Private garden pools are the ones nobody bothers with, and the ones a tax office is looking for.

Use it when: you need public and commercial pools.

Skip it when: the job is finding what nobody declared.

Method 2: A segmentation model

A segmentation model reads shape and context, which is how it tells a pool from a tarpaulin of the same colour. We build one of these, AI Segmentation (complete guide). This section is about our own tool.

Install and sign in

Plugin manager, QGIS 3.22 or later. No GPU, no model weights. An account, a free allowance, then €39 a month excluding VAT.

Draw a zone, type the word, filter

Type swimming pool and run. Polygons come back in the project CRS with area, perimeter and a confidence score. Sort, then delete what is wrong.

Two numbers from our tuning table, read at runtime. A pool run asks for roughly 0.13 m per pixel in tiles of at most 300 m, because a pool blurs into its terrace at anything coarser. The review opens at 0.20 confidence for swimming pool against 0.30 for building, since pool masks score lower than roofs.

A residential block on aerial imagery in QGIS, every backyard swimming pool filled with its own colour, roofs and gardens untouched.
One zone, one word, over 20 cm imagery. Each pool is its own polygon with an area, editable like any vector feature.

One limit: a covered pool never reaches the model, so it comes back missed. Both cloud modes send imagery to our servers in the European Union.

Two panels of the same three gardens. On the winter image two pools carry a cyan detection outline while a circled pool under a tan cover carries none. On the summer image that circled spot is open blue water.
Same gardens, two images. The circled pool sits under a cover in winter and the run walks past it. Over the whole tile the same prompt returned 58 pools on the summer image and 2 on the winter one, though the two images come from different providers as well as different seasons.

Four others do this job, read 3 September 2026.

ToolWhat you installGPUAccountImagery leaves your machinePool supportCost
DeepnessPlugin manager, its Python packages, an ONNX modelOptional, CPU worksNoNoWhatever model you supplyFree
Geo-SAMPlugin manager, dependencies, model weightsOptionalNoNoOne object per click or boxFree
samgeoA Python package, no QGIS panelRecommendedNoNoScriptable, no pool classFree
MapflowPlugin managerNoYesYes in the cloud service, enterprise on-premise offeredA Swimming pools model, on requestCredits, paid
AI Segmentation (ours)Plugin managerNoYesYes in both cloud modes, no for the local modelType swimming poolFree allowance, then €39 a month excluding VAT

Use it when: more pools than you would outline by hand.

Skip it when: the imagery cannot leave your machine. Use Deepness or Geo-SAM.

For a sweep where somebody signs off a published accuracy figure, Mapflow ships a dedicated Swimming pools model, on request, with an F1 above 0.95 next to it. We publish no figure for pools.

Method 3: Threshold the blue in the raster calculator

Work in a projected CRS, since three steps below filter on area in layer units.

The closest core QGIS gets. Open Raster > Raster Calculator…, where bands are layer_name@band_number. On an RGB orthophoto this keeps bright, saturated blue:

("ortho@3" > 90) AND ("ortho@3" - "ortho@1" > 25) AND ("ortho@3" - "ortho@2" > 10)

Those numbers are mine, from a 20 cm orthophoto. Sample twenty pool pixels and twenty roof pixels, then move them.

Polygonize with Raster > Conversion > Polygonize (Raster to Vector), then filter with native:extractbyexpression: $area > 6 AND $area < 400 for size, and my own ratio 4 * pi() * $area / ($perimeter ^ 2) > 0.5 for shape, since QGIS ships no compactness function.

A suburban orthophoto with a red mask from the raster calculator covering every swimming pool, a blue metal roof, and a blue tarpaulin over a woodpile.
The rule above, over 20 cm imagery. It finds every open pool. It also finds a blue metal roof and a tarpaulin.

RGB values slide with sun angle and exposure, so a threshold tuned on one flight line breaks on the next. Hue and saturation hold up better, via the Processing Toolbox module i.rgb.his, which "transforms raster maps from RGB (Red-Green-Blue) color space to HIS (Hue-Intensity-Saturation) color space".

Neither rule knows what the blue thing is.

  • Shadow. Shaded roof slopes read dark blue. Raise the floor and you lose pools under trees.
  • Blue roofs and tarpaulins. Bright, blue, often the right shape.
  • Dark-bottom and green pools. A black liner reads as asphalt, algae as lawn. My rule missed both.
  • Covered pools. Not in the image at all.
Three tight crops side by side: a blue tarpaulin over a garden, a shaded roof slope, and a dark-bottom pool in a garden.
The tarp and the shadow pass the colour rule and should not. The dark-bottom pool fails it and should not. Crops from 20 cm imagery over Cape Coral, Florida.

Use it when: one consistent orthophoto you'll check by hand.

Skip it when: a mosaic of several flights.

Method 4: A water index, on imagery that has the bands

Check resolution. The French pool federation puts a new inground pool at 29 to 30 m², 3,000 pixels on a 10 cm orthophoto and a third of one pixel on a 10 m Sentinel-2 band.

Water absorbs near-infrared almost completely, so it goes black in NIR while a blue roof stays bright.

  • NDWI, McFeeters 1996: (Green - NIR) / (Green + NIR). On Sentinel-2, (B3 - B8) / (B3 + B8).
  • MNDWI, Xu 2006: (Green - SWIR) / (Green + SWIR). On Sentinel-2, (B3 - B11) / (B3 + B11). Swapping NIR for SWIR suppresses built-up land, the point over a suburb.

Threshold above zero, polygonize, filter as in Method 3. Rodríguez-Cuenca and Alonso tuned a Normalized Difference Swimming Pools Index for this job in 2014.

Sentinel-2 delivers B3 and B8 at 10 m and B11 at 20 m, so a 30 m² pool never separates from the garden. MNDWI over a residential block returns the reservoir at the edge of town and nothing else.

Two panels of the same suburb: a 20 cm orthophoto with eleven visible pools, and the Sentinel-2 MNDWI of the same extent showing a uniform grey with no pool visible.
Eleven pools on the left, none on the right. Same extent, same week. A 30 m² pool never reaches a 10 m sensor as an object.

Use it when: your orthophoto has a NIR band at 50 cm or finer. It beats colour outright.

Skip it when: three-band RGB, or Sentinel-2 and you want garden pools.

Method 5: Train a classifier on your own imagery

A classifier learns your pool pixels from examples you draw, so it survives a mosaic that breaks a fixed threshold.

Semi-Automatic Classification Plugin by Luca Congedo is the usual choice. Create a training input (.scpx) in the SCP dock, draw ROIs, then run SCP > Band processing > Classification in the main window. Six algorithms, from Minimum Distance to Random Forest. Version 9.0.4 shipped 11 July 2026 but declares a QGIS minimum of 3.99, so QGIS 3.x still installs 8.5.0.

dzetsaka 5.0.11, by Nicolas Karasiak, is lighter: eleven classifiers, and its Gaussian Mixture Model runs without scikit-learn.

Draw a blue-roof class and a shadow class too. A classifier only rejects what you showed it.

Two panels of the same suburb: a 20 cm orthophoto, and a minimum distance classification of it with the pool class in cyan, where one blue-grey roof comes out larger than either of the two real pools next to it.
A minimum distance classification of the same 20 cm orthophoto, its pool class trained on the 58 pools in this tile. Across the tile, 46% of the pixels it calls pool are not a pool, and most of that is blue-grey roof, like the one in the middle here.

Use it when: several flights or seasons, and you'll reuse the workflow.

Skip it when: one orthophoto, one pass. Both classify pixels, not objects, so you still polygonize and filter.

The five methods side by side

What you haveMethod
A well-mapped town, public pools are enoughMethod 1, QuickOSM
Hundreds of pools and no patience for false positivesMethod 2, a segmentation model
One RGB orthophoto finer than 30 cmMethod 3, colour threshold, then filter
An orthophoto with a NIR bandMethod 4, NDWI
Sentinel-2 or anything at 10 mNone of them for garden pools. Get finer imagery
Several flights, a workflow you'll repeatMethod 5, SCP or dzetsaka

What to remember

Resolution decides first, then the bands, then how much hand-checking you can absorb.

A 30 m² pool never separates from its garden at 10 m, so Sentinel-2 is the wrong sensor for backyard pools whatever index you run.

A colour threshold returns every blue thing on the block, so filter on area and compactness before you look at the result.

A covered pool is missing from the imagery, so no method on this page finds it and no price changes that.

A detection is a candidate. Whatever you run, open the ten lowest-confidence polygons before anyone acts on the layer.

Try it free in QGIS, no card needed

Questions people ask

Can QGIS detect swimming pools on its own?

Not as a feature. Core QGIS gives you the raster calculator, polygonize and the vector filters, which is Method 3. Recognising a pool as an object needs a plugin.

Can I find backyard pools in Sentinel-2 imagery?

No. Green and NIR are 10 m bands and SWIR is 20 m, so a 30 m² pool is a third of a pixel. Use aerial imagery at 30 cm or better.

Why do blue roofs keep coming back as pools?

A painted metal roof is brighter and bluer than pool water, and a colour rule only reads colour. Filter on area and compactness, move to NDWI, or use a model.

What accuracy should I expect?

One number would be false, since it moves with your imagery and the season. Open pools at 20 cm come back well, covered pools are missed by everything here, and blue roofs are what you delete by hand.

Is a detection already a list of pools I can act on?

The French tax administration ran this on IGN photography and still sent a letter to every owner. Its Foncier innovant pilot taxed 20,356 pools across nine departments for 2022, worth 9.8 million euros, and the 2023 national pass found 150,000 taxable pools missing from the roll. A detection is a candidate, and joining it to a parcel and a name makes it personal data.

For the filtering step in full, read detecting building footprints in QGIS. For the cleanup behind any mask, raster to vector in QGIS. For running the same detect-then-filter pass over a whole commune's imagery, AI Agent carries out the steps from one instruction inside QGIS. The QGIS AI hub has the rest.