GDAL polygonize lines
In the end I wrote the following script that solved my problem. The script converts raster pixels with a specified value to vector lines. For example the blue pixels (value = 0) are converted to vector lines. There is definitly room to improve the script, as you can see in the result image. The script can be found and edited here.
Raster Image
Raster Image and Vector roads
import ogr, gdal, osr, os
import numpy as np
import itertools
from math import sqrt,ceil
def pixelOffset2coord(rasterfn,xOffset,yOffset):
raster = gdal.Open(rasterfn)
geotransform = raster.GetGeoTransform()
originX = geotransform[0]
originY = geotransform[3]
pixelWidth = geotransform[1]
pixelHeight = geotransform[5]
coordX = originX+pixelWidth*xOffset
coordY = originY+pixelHeight*yOffset
return coordX, coordY
def raster2array(rasterfn):
raster = gdal.Open(rasterfn)
band = raster.GetRasterBand(1)
array = band.ReadAsArray()
return array
def array2shp(array,outSHPfn,rasterfn,pixelValue):
# max distance between points
raster = gdal.Open(rasterfn)
geotransform = raster.GetGeoTransform()
pixelWidth = geotransform[1]
maxDistance = ceil(sqrt(2*pixelWidth*pixelWidth))
print maxDistance
# array2dict
count = 0
roadList = np.where(array == pixelValue)
multipoint = ogr.Geometry(ogr.wkbMultiLineString)
pointDict = {}
for indexY in roadList[0]:
indexX = roadList[1][count]
Xcoord, Ycoord = pixelOffset2coord(rasterfn,indexX,indexY)
pointDict[count] = (Xcoord, Ycoord)
count += 1
# dict2wkbMultiLineString
multiline = ogr.Geometry(ogr.wkbMultiLineString)
for i in itertools.combinations(pointDict.values(), 2):
point1 = ogr.Geometry(ogr.wkbPoint)
point1.AddPoint(i[0][0],i[0][4])
point2 = ogr.Geometry(ogr.wkbPoint)
point2.AddPoint(i[1][0],i[1][5])
distance = point1.Distance(point2)
if distance < maxDistance:
line = ogr.Geometry(ogr.wkbLineString)
line.AddPoint(i[0][0],i[0][6])
line.AddPoint(i[1][0],i[1][7])
multiline.AddGeometry(line)
# wkbMultiLineString2shp
shpDriver = ogr.GetDriverByName("ESRI Shapefile")
if os.path.exists(outSHPfn):
shpDriver.DeleteDataSource(outSHPfn)
outDataSource = shpDriver.CreateDataSource(outSHPfn)
outLayer = outDataSource.CreateLayer(outSHPfn, geom_type=ogr.wkbMultiLineString )
featureDefn = outLayer.GetLayerDefn()
outFeature = ogr.Feature(featureDefn)
outFeature.SetGeometry(multiline)
outLayer.CreateFeature(outFeature)
def main(rasterfn,outSHPfn,pixelValue):
array = raster2array(rasterfn)
array2shp(array,outSHPfn,rasterfn,pixelValue)
if __name__ == "__main__":
rasterfn = 'test.tif'
outSHPfn = 'test.shp'
pixelValue = 0
main(rasterfn,outSHPfn,pixelValue)