Skip to content
QGIS
Tutorial
GeoAI

Convert Raster to Vector in QGIS: 5 Methods

Three panels: a land cover raster drawn as a grid of coloured pixels, the same boundary traced by polygonize as a staircase, and the same boundary again as a smooth green line after dissolve, an area filter, simplify and smooth.

To convert a raster to vector polygons in QGIS, open Raster > Conversion > Polygonize (Raster to Vector), pick your band, name the output field, and run it. You get one polygon per connected group of pixels sharing a value, with that value in the attribute table. It is the right answer for a classified raster and the wrong one for a photograph. Four other methods cover the rasters polygonize cannot read.

Method 5 is a plugin we build, so weigh that section accordingly. It gets the same five lines as the other four.

Open the raster's properties and read two things: the band type and the number of distinct values. They pick the method for you.

Your inputMethodWhat it costs
Classified raster (land cover, a slope reclass, a mask)Method 1, Raster > Conversion > PolygonizeFree, in core QGIS
Continuous raster (NDVI, slope, a reflectance band)Method 2, Reclassify by table, then polygonizeFree, in core QGIS
DEM or any elevation surfaceMethod 3, Raster > Extraction > Contour, or Contour PolygonsFree, in core QGIS
Scanned paper map or a planMethod 4, GRASS r.thin plus r.to.vectFree, and slow. Paid AI tracing exists
Orthophoto, drone or satellite imageryMethod 5, a segmentation modelFree plugins need an NVIDIA card. Cloud plugins have free tiers, then a subscription

Every menu path, algorithm id and default below was checked against the QGIS 3.44 documentation and the GDAL stable docs on 23 August 2026. Menu paths assume the default QGIS layout, which a plugin can change.

Method 1: Polygonize

Work in a projected CRS. Two steps below take a distance or an area in layer units, and in degrees those numbers mean nothing.

The algorithm is Polygonize (raster to vector), id gdal:polygonize, wrapping the GDAL utility gdal_polygonize.

The QGIS 3.44 documentation page for Polygonize, with its INPUT, BAND, FIELD and EIGHT_CONNECTEDNESS parameters
The source for every default below: the QGIS 3.44 documentation for gdal:polygonize, captured 23 August 2026.

Open the tool

Raster > Conversion > Polygonize (Raster to Vector), or the Processing Toolbox under GDAL, Raster conversion.

Pick the band

Band 1 unless your classes live elsewhere. One band only, so reduce an RGB raster to a single class band.

Name the field

DN is the default. Rename it, landcover_code rather than DN.

Decide on 8-connectedness

Off by default, so pixels must share a full border to join. Turn it on and diagonally touching pixels join too. Left off, a thin diagonal feature splits into a chain of polygons.

Save to a real file

The default is a temporary layer. A large raster gives tens of thousands of features, so write straight to a GeoPackage.

The QGIS Polygonize dialog: Land cover 10 m [EPSG:32631], Band 1 (Palette), field landcover_code, 8-connectedness unticked, output to a GeoPackage.
The four parameters that matter, on a 10 m ESA WorldCover clip of the Drome valley. DN renamed to landcover_code, output straight to a GeoPackage.

Two things save you time. First, set a NoData value on the class you do not want: GDAL then reads the band's validity mask and skips those pixels instead of wrapping one enormous background polygon around everything. That is the most common complaint about polygonize output, and it is a raster property, not a tool setting.

The gdal_polygonize reference page on gdal.org, with the -8, -nomask and -mask options
The GDAL utility underneath the QGIS algorithm, captured 23 August 2026. The validity mask behaviour comes from its -nomask flag.

Second, watch the band type. gdal:polygonize always writes an integer field, so it casts a float band on the way in, and that fails in two ways depending on how the raster stores its values. Neither warns you. A Float32 band goes through Method 2 first.

The staircase, and the four steps that fix it

Polygonize traces pixel boundaries, so a diagonal field edge comes back as right-angled steps, one per pixel. A 10 m Sentinel classification gives 10 m stairs.

Polygonize output over a 10 m land cover raster at about 1:1,500. Pink cropland between green tree cover and yellow grassland, every diagonal boundary a flight of one-pixel steps.
Raw gdal:polygonize output, 3,551 polygons, over the ESA WorldCover raster it came from. Count the steps along any diagonal: each one is a 10 m pixel.

That is correct output, and no setting inside polygonize changes it. The fix is four vector geometry algorithms, in this order.

Dissolve by the class field

native:dissolve, on the class field you just created. Run it first, while the geometry is exact: merging simplified edges leaves slivers along every shared boundary. Tick Keep disjoint features separate for one row per patch instead of one multipart feature per class.

Filter by area

native:extractbyexpression, in Vector selection, with $area > 500 in layer CRS units. On a 10 m classification, 500 m2 is five pixels, about where speckle stops. The figure below used 2,000 m2, because at 500 the surviving slivers crossed each other once simplified. Read the histogram of your own areas. For solid patches, run native:deleteholes after this step, with 0.0 to remove every hole.

Simplify

native:simplifygeometries. Tolerance defaults to 1.0 in layer units. Set it to roughly one pixel and the stairs collapse into straight runs, the boundary moving less than a reader can see. The method dropdown offers Douglas-Peucker (distance based), Visvalingam (area based) and snap to grid. Visvalingam holds small features better at a high tolerance.

Smooth, but only on curves

native:smoothgeometry, on genuinely curved things: streams, coastlines, vegetation patches. Offset defaults to 0.25, iterations control how round it gets. Set Maximum node angle to smooth to 90 and sharper corners stay sharp, which saves the corners of buildings and parcels.

The same land cover extent after cleanup: smooth outlines over the pixel grid, and the small speckle polygons gone.
Same extent, after Dissolve, an area filter at 2,000 m2, deleteholes, Simplify at 10 m and Smooth with maximum node angle 90. The count drops from 3,551 to 724 and the steps read as curves.

Use it when: the raster holds classes as integers.

Skip it when: the band is a float, a photograph or elevation.

Method 2: Reclassify, then polygonize

Polygonize on a continuous raster fails in one of two ways, depending on how the values are stored.

Stored as scaled whole numbers, which is how NDVI products ship, you get a polygon for nearly every pixel. I measured 39,801 polygons out of 40,000 pixels on a Sentinel-2 scene.

Stored as raw floats between -1 and 1, the cast to integer flattens every value to -1, 0 or 1 before the trace starts. The same scene came back as 238 polygons in two classes. That looks clean, but the values are gone.

An NDVI raster over farmland at about 1:1,000, every 10 m pixel carrying its own polygon outline. The layer panel reads ndvi_polygonized with 39801 features.
NDVI from a Sentinel-2 scene of 11 August 2025, stored as scaled whole numbers, polygonized as it comes. 39,801 polygons out of 40,000 pixels.

Slope, elevation, temperature and a raw reflectance band all do the same. The tool traces boundaries between integer values, and a continuous raster has none worth tracing. So make the classes yourself, with Reclassify by table, id native:reclassifybytable.

Open Reclassify by table

Processing Toolbox, Raster analysis. The continuous raster is the input.

Type the class table

Three columns: minimum, maximum, new value. It accepts -inf, inf and nan for NoData. A vegetation mask is three rows.

MinimumMaximumValue
-inf0.21
0.20.52
0.5inf3

Set the output data type

In the advanced parameters, Output data type defaults to Float32. Set it to Byte or Int16 and polygonize behaves.

Check the range boundaries

Range boundaries defaults to min < value <= max, which decides where a pixel at exactly 0.2 lands. Pick what your class definition means.

Polygonize the result

Run Method 1 on the reclassified raster, then the four cleanup steps.

The QGIS Reclassify by Table dialog on the Float32 NDVI raster: Output data type set to Byte, Range boundaries at min less than value less than or equal to max, and the three-row class table.
The three-row vegetation mask in the fixed table. The two defaults worth changing sit behind it: Output data type, here Byte, and Range boundaries.

Use it when: you can say in numbers where one class stops and the next starts.

Skip it when: the thing you want is an object rather than a value range.

Method 3: Contours from a DEM

For elevation, do not polygonize. Use Contour at Raster > Extraction > Contour, id gdal:contour.

Open Contour

Raster > Extraction > Contour, with the DEM as input.

Set the interval

Defaults to 10.0 in raster units, so a metric DEM gets a line every 10 m.

Name the attribute

Elevation goes into ELEV by default. Keep it, and label from it.

Decide on Produce 3D vector

Tick it for the height on every vertex. Leave it off for a printed map, since a lot of software drops the Z.

Switch to contour polygons for filled bands

The sibling algorithm gdal:contour_polygon gives filled bands between two elevations, with ELEV_MIN and ELEV_MAX on each polygon. That is the one for a hypsometric map or an inundation extent, and it saves polygonizing a reclassified DEM by hand.

The QGIS Contour dialog on Copernicus DEM 30 m: interval 10, attribute name ELEV, Produce 3D vector unticked.
gdal:contour on a Copernicus DEM 30 m tile over the Drome. Interval 10 in raster units, elevation in ELEV, Produce 3D vector off.
Two panels of the same hilly extent: brown 10 m contour lines over a grey hillshade, the 50 m lines thicker and labelled 400, 450, 500, 550, 600 and 650, then the same terrain as filled bands from green valleys to brown tops.
Same DEM, same 10 m interval, two algorithms. gdal:contour gives lines labelled from ELEV. gdal:contour_polygon gives filled bands with ELEV_MIN and ELEV_MAX, what a hypsometric map needs.

Contours from a lidar DEM come out noisy, because the surface is noisy. Smooth the raster before the contour step, never the lines afterwards: smoothed lines cross each other.

Use it when: the thing you want is a level: elevation, depth, rainfall, concentration.

Skip it when: the raster already holds classes.

Method 4: Scanned paper maps

If you came from ArcGIS looking for the QGIS equivalent of ArcScan, there is not one. Interactive raster tracing, where you click a line on a scan and the tool follows it, is a real gap in QGIS, and I would rather say so than have you hunt the menus.

The free path runs through GRASS, which ships with most QGIS installers.

Threshold the scan

Turn the scanned sheet into a binary raster: line work in one value, paper in the other.

Thin the lines

r.thin reduces each stroke to a single pixel wide.

Vectorize

r.to.vect with feature type line. The GRASS documentation warns that this creates excessive nodes at junctions and dangling spurs, so budget for cleanup.

Two other routes exist. Potrace and AutoTrace run outside QGIS: bitmap in, vector out, then you georeference the result. They are good on high-contrast scans and blind to geography.

Inside QGIS, Bunting Labs AI Vectorizer (QGIS repository listing) autocompletes a line as you digitize, aimed at geologic maps, as-builts and plans. It sends raster chunks to their servers, there is no free tier beyond a trial, and published prices start at 29 dollars a month, read 23 August 2026.

For a handful of features, hand-digitizing with snapping still wins. I would not build a tracing workflow for fewer than about fifty features.

Use it when: the scan carries clean line work and hundreds of features.

Skip it when: the sheet is faint, hatched or annotated over the lines.

Method 5: A segmentation model for photographs

A segmentation model has learned what the objects look like, so it finds them in a photograph where no pixel value separates them. We build one of these, AI Segmentation. This section is about our own tool.

Point polygonize at the same orthophoto and you get noise. A red roof and a red car have similar pixel values, and so do a grey roof and a grey road. The classes exist in your head, not in the file.

Install from the plugin manager

No GPU, no Python environment, no model weights to fetch.

Create an account

It needs one. Free allowance, then 39 euros a month excluding VAT.

Pick a mode

Both cloud modes send imagery to a server. The small local model stays on your machine.

Run it over your extent

Back comes a polygon layer in the project CRS, with label, class, score, area_m2 and perimeter_m on every feature.

Filter the output

Raw model output needs filtering the way polygonize output needs cleaning. On one run over central Paris I kept 82 polygons out of 635, and those 82 held 84 percent of the built area.

A suburban street on Google Satellite imagery in QGIS. Six house roofs right of the road outlined in red, more polygons over the houses on the left.
Model-based extraction over Google Satellite imagery, captured 23 August 2026. Every roof is its own polygon, editable like any vector feature. Polygonize cannot produce this: nothing in the pixel values separates a roof from a driveway.

Five other plugins do this job, ours in the last row. Costs and free tiers read 23 August 2026.

ToolWhat you installGPUAccountImagery leaves your machineWhat comes outCost
Deepness (source)Plugin manager, then its Python packages and an ONNX modelOptional, CPU worksNoNoPolygon layer, bounding boxes, or a rasterFree
Geo-SAMPlugin manager, then dependencies and model weights from its settings dialogOptional, clicking runs on CPUNoNoPolygon layer, pixel-level or simplifiedFree
samgeoA Python package in your environment, no QGIS panelRecommendedNoNoGeoJSON, Shapefile or GeoPackage you load yourselfFree
Mapflow (site)Plugin managerNoYesYes, your GeoTIFF upload or the tile service you point atPolygon layerCredits, paid
Bunting Labs AI VectorizerPlugin managerNoYesYes, in raster chunksVertices into the layer you are digitizingTrial, then 29 dollars a month
AI Segmentation (ours)Plugin managerNoYesYes in both cloud modes, no for the small local modelPolygon layer in the project CRS, with label, class, score, area_m2 and perimeter_mFree allowance, then 39 euros a month excluding VAT

One limit each.

  • Deepness runs the model you hand it, so you find or train one first.
  • Geo-SAM takes clicks and boxes, one object at a time.
  • samgeo has no QGIS interface. You write Python.
  • Mapflow ships a fixed catalogue: buildings, forest, roads and construction sites, so it cannot find an object nobody trained it for.
  • Bunting Labs AI Vectorizer follows line work as you digitize. It does not find every object in a zone.
  • AI Segmentation, ours, sends imagery to a server in both cloud modes. Only the small local model stays local.

Use it when: the input is a photograph and there are more objects than you would draw by hand.

Skip it when: the imagery cannot leave your machine, which points at Deepness or Geo-SAM.

Try it free in QGIS, no card needed

What to remember

What the properties sayMethod
Integer band, under a hundred distinct valuesMethod 1, polygonize, then dissolve, filter, simplify
Float band, thousands of distinct valuesMethod 2, reclassify by table, then Method 1
Elevation in metres, or any smooth surfaceMethod 3, contour or contour polygons
A scanned sheet with no class values at allMethod 4, GRASS, or digitize by hand
Three bands of a photographMethod 5, a segmentation model

The distinct-value count settles it. Under a hundred, somebody has already classified the raster, and polygonize traces those classes cleanly.

In the thousands, nobody has classified anything, so you draw the thresholds yourself in Method 2 or hand the job to a model in Method 5.

The staircase is correct output, and no setting inside polygonize removes it. Dissolve, an area filter, simplify and smooth do, in that order.

Every cleanup step moves vertices, so compute any area that feeds a report from the raster rather than from the polygons.

Polygonize cannot read a photograph at any setting, because the classes are in your head and not in the file.

Questions people ask

Why does polygonize give me one giant polygon around everything?

The background class has no NoData value set, so GDAL traces it as real data. Set NoData on that class in the raster's properties, then run Method 1 again.

Why did polygonize create a polygon for almost every pixel?

The raster is continuous, not classified, so almost no two neighbouring pixels hold the same value. Reclassify it first: Method 2.

How do I get rid of the staircase edges?

Run the four cleanup algorithms in Method 1: dissolve, area filter, simplify, smooth. Compute areas from the raster if they feed a report.

Does QGIS have an ArcScan equivalent?

No. Core QGIS has no interactive raster tracing. Method 4 has the free path, GRASS r.thin then r.to.vect, and the paid one, the Bunting Labs plugin from 29 dollars a month.

Can I polygonize an aerial photo or a satellite image?

No, and the output will look like static, since a red roof and a red car share pixel values. Use a segmentation model: Method 5.

Is raster to vector free in QGIS?

Yes for Methods 1 to 3: polygonize, reclassify, contour and the cleanup algorithms are all core QGIS. Only the photograph case and paid scan tracing cost money.

The building footprints guide walks the filtering step end to end, and the SAM in QGIS post covers which objects these models find well. The QGIS AI hub compares the plugins side by side. If all you need is buildings, our free building footprints tool pulls them from open data in the browser, with no plugin.