Detect Swimming Pools in QGIS: 5 Methods

To detect swimming pools in
, check OpenStreetMap first: Vector > QuickOSM > QuickOSM…, key leisure, value swimming_pool. Where the map is thin, threshold the blue in the raster calculator or run a segmentation model. Ground resolution decides which.
Where the web gets this wrong
Three answers get repeated on forums and in tutorials, and each one costs you a day.
"Run NDWI on Sentinel-2 and count the pools." Green and NIR come at 10 m and SWIR at 20 m, while a new inground pool is 29 to 30 m². That is a third of a pixel. MNDWI over a suburb returns the reservoir at the edge of town and nothing in the gardens.
"Threshold the blue and you have your pools." A colour rule reads colour and nothing else. A blue metal roof and a tarpaulin over a woodpile pass it, a dark-liner pool and an algae-green pool fail it, and a covered pool is not in the image at all.
"The detection is the list." The French tax administration ran this on IGN photography and still sent a letter to every owner. A detection is a candidate, and joining it to a parcel and a name makes it personal data.
The short answer
| Your input | Method | What it costs |
|---|---|---|
| Any area with active OSM mappers | Method 1, QuickOSM on leisure=swimming_pool | Free, one query |
| RGB orthophoto at 5 to 30 cm | Method 2, colour threshold in the raster calculator | Free, in core QGIS |
| Imagery with a near-infrared or SWIR band | Method 3, a water index, then a threshold | Free, blind to garden pools on satellite |
| Multispectral imagery and an afternoon | Method 4, SCP or dzetsaka | Free plugins, your time drawing training areas |
| RGB orthophoto and hundreds of pools | Method 5, a segmentation model | Free plugins want your own model or a GPU. Cloud plugins have free tiers, then a subscription |
How I compared them
Five criteria: input, whether imagery leaves your machine, how much output you hand-check, cost, install effort. Every version, price and menu path was read on 3 September 2026 against the QGIS 3.44 manual and each tool's docs. I ran the free methods on a French suburban orthophoto and a Sentinel-2 scene of the same block.
We build one of the five, and it is Method 5. For a sweep where somebody signs off a published accuracy figure, use Mapflow instead. It ships a dedicated Swimming pools model, on request, with an F1 above 0.95 next to it. We publish no figure for pools.
Before you start
Work in a projected CRS, since three steps below filter on area in layer units. Then 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.
The French tax administration runs this on IGN aerial photography. 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. Each one still went through a letter to the owner.
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.

Use it when: you need public and commercial pools.
Skip it when: the job is finding what nobody declared.
Method 2: Threshold the blue in the raster calculator
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.

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.

Use it when: one consistent orthophoto you'll check by hand.
Skip it when: a mosaic of several flights.
Method 3: A water index, on imagery that has the bands
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 2. 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.

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 4: 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.

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.
Method 5: 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. 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 euros 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.

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.

Four others do this job, read 3 September 2026.
| Tool | What you install | GPU | Account | Imagery leaves your machine | Pool support | Cost |
|---|---|---|---|---|---|---|
| Deepness | Plugin manager, its Python packages, an ONNX model | Optional, CPU works | No | No | Whatever model you supply | Free |
| Geo-SAM | Plugin manager, dependencies, model weights | Optional | No | No | One object per click or box | Free |
| samgeo | A Python package, no QGIS panel | Recommended | No | No | Scriptable, no pool class | Free |
| Mapflow | Plugin manager | No | Yes | Yes | A Swimming pools model, on request | Credits, paid |
| AI Segmentation (ours) | Plugin manager | No | Yes | Yes in both cloud modes, no for the local model | Type swimming pool | Free allowance, then 39 euros 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.
The five methods side by side
| What you have | Method |
|---|---|
| A well-mapped town, public pools are enough | Method 1, QuickOSM |
| One RGB orthophoto finer than 30 cm | Method 2, colour threshold, then filter |
| An orthophoto with a NIR band | Method 3, NDWI |
| Sentinel-2 or anything at 10 m | None of them for garden pools. Get finer imagery |
| Several flights, a workflow you'll repeat | Method 4, SCP or dzetsaka |
| Hundreds of pools and no patience for false positives | Method 5, a segmentation model |
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 2. 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.
Is it legal to detect swimming pools from aerial imagery?
Join a detection to a parcel and an owner's name and it becomes personal data, which in the EU needs a lawful basis under the GDPR. A tax administration has one written into law. A private company usually does not, so ask your data protection officer before the join, and never let a model's output be the last step before a bill.
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.
For the filtering step in full, read detecting building footprints in QGIS. For the cleanup behind any mask, raster to vector in QGIS. The QGIS AI hub has the rest.


