def process_centreline(geom):
    try:
        line = Centerline(geom)
    except centerline.exceptions.TooFewRidgesError:
        line = Centerline(geom, interpolation_distance=0.1)

    line = remove_short_lines(linemerge(line))
    return line.simplify(1, preserve_topology=True)
Exemplo n.º 2
0
def test_creating_centerline_using_too_large_interp_dist_raises_runtimeerror(
        create_polygon):
    polygon = create_polygon(exterior=[[0, 0], [10, 0], [10, 10], [0, 10]])
    with pytest.raises(TooFewRidgesError):
        Centerline(polygon, 10)

    centerline = Centerline(polygon, 5)
    assert isinstance(centerline, Centerline)
    assert isinstance(centerline, geometry.MultiLineString)
Exemplo n.º 3
0
def test_centerline_has_attributes_assigned_to_it(simple_polygon):
    ATTRIBUTES = {"id": 1, "name": "polygon", "valid": True}

    centerline = Centerline(simple_polygon, **ATTRIBUTES)

    assert isinstance(centerline, Centerline)
    assert isinstance(centerline, geometry.MultiLineString)
    assert centerline.id == ATTRIBUTES.get("id")
    assert centerline.name == ATTRIBUTES.get("name")
    assert centerline.valid == ATTRIBUTES.get("valid")
def gen_centerlines(df, interpolation_distance=0.5):
    """
    """
    centerlines = []

    for i, row in df.iterrows():
        cl = Centerline(row.geometry, interpolation_distance=interpolation_distance)
        centerlines.append(cl)

    return centerlines
Exemplo n.º 5
0
def extract_centerlines(shapes):
    shapes = (shape.buffer(0) for shape in shapes)
    polys = [
        poly for poly in shapes
        if type(poly) == geom.Polygon and type(poly.envelope) == geom.Polygon
    ]
    centerlines = [Centerline(p, valid=True) for p in polys]

    center_geoms = [line.geoms for line in centerlines]
    center_geom_lines = [geom.MultiLineString(line) for line in center_geoms]
    center_geom_lines = [ops.linemerge(line) for line in center_geom_lines]
    return center_geom_lines
Exemplo n.º 6
0
def extract_centerlines(edges):
    ''' Extract centerlines  using Centerline python library '''
    shapes = vector_trace(edges)
    shapes = (shape.buffer(0) for shape in shapes)
    polys = [
        poly for poly in shapes
        if type(poly) == geom.Polygon and type(poly.envelope) == geom.Polygon
    ]
    centerlines = [Centerline(p, valid=True) for p in polys]

    center_geoms = [line.geoms for line in centerlines]
    center_geom_lines = [geom.MultiLineString(line) for line in center_geoms]
    center_geom_lines = [ops.linemerge(line) for line in center_geom_lines]
    center_geom_lines = explode_multilines(center_geom_lines)

    # prune lines too long/short
    center_geom_lines = [
        line for line in center_geom_lines if
        max(line.length,
            geom.Point(line.coords[0]).distance(geom.Point(
                line.coords[-1]))) > 4
    ]

    return center_geom_lines
Exemplo n.º 7
0
def test_centerline_geometry_is_valid(complex_polygon):
    centerline = Centerline(complex_polygon)
    assert centerline.is_valid is True
Exemplo n.º 8
0
def test_centerline_has_length_greater_than_zero(complex_polygon):
    centerline = Centerline(complex_polygon)
    assert centerline.length > 0
Exemplo n.º 9
0
def test_creating_centerline_from_geometry_collection_raises_typeerror(
        geometry_collection):
    with pytest.raises(InvalidInputTypeError):
        Centerline(geometry_collection)
Exemplo n.º 10
0
def test_creating_centerline_from_multipolygon_returns_centerline(
        multipolygon):
    centerline = Centerline(multipolygon)
    assert isinstance(centerline, Centerline)
    assert isinstance(centerline, geometry.MultiLineString)
Exemplo n.º 11
0
def test_polygon_contains_the_centerline(complex_polygon):
    centerline = Centerline(complex_polygon)
    assert complex_polygon.contains(centerline) is True
Exemplo n.º 12
0
def test_centerline_does_not_touch_the_polygons_boundary(complex_polygon):
    centerline = Centerline(complex_polygon)
    assert centerline.intersects(complex_polygon.boundary) is False
Exemplo n.º 13
0
with open('/input/features.geojson', 'r') as f:
    features = json.load(f)['features']

with open('input/border_density', 'r') as f:
    border_density = float(f.read())

output_file_path = '/output/centerlines.geojson'

centerlines = []
i = 0

print("Total " + str(len(features)) + " Features")

for feature in features:
    s = shape(feature["geometry"])
    centerline = Centerline(s, border_density)
    f = {"type": "Feature", "properties": {}, "geometry": mapping(centerline)}
    centerlines.append(f)
    i = i + 1
    print("Done " + str(i))

gjson = {
    "type": "FeatureCollection",
    "name": "input-clean",
    "crs": {
        "type": "name",
        "properties": {
            "name": "urn:ogc:def:crs:EPSG::4326"
        }
    },
    "features": centerlines
Exemplo n.º 14
0
def test_qhull_error(create_polygon):
    # https://github.com/fitodic/centerline/issues/24
    polygon = create_polygon(exterior=[
        (107, 189),
        (106, 190),
        (100, 190),
        (99, 191),
        (95, 191),
        (94, 192),
        (92, 192),
        (91, 193),
        (90, 193),
        (89, 194),
        (88, 194),
        (87, 195),
        (86, 195),
        (85, 196),
        (84, 196),
        (82, 198),
        (82, 203),
        (86, 207),
        (87, 207),
        (90, 210),
        (91, 210),
        (92, 211),
        (94, 211),
        (95, 212),
        (98, 212),
        (99, 213),
        (101, 213),
        (102, 214),
        (105, 214),
        (106, 215),
        (108, 215),
        (109, 216),
        (111, 216),
        (112, 217),
        (114, 217),
        (115, 218),
        (117, 218),
        (118, 219),
        (120, 219),
        (121, 220),
        (126, 220),
        (127, 221),
        (133, 221),
        (134, 222),
        (136, 222),
        (137, 223),
        (138, 223),
        (139, 224),
        (139, 227),
        (137, 229),
        (137, 230),
        (136, 231),
        (135, 231),
        (133, 233),
        (132, 233),
        (130, 235),
        (129, 235),
        (126, 238),
        (125, 238),
        (124, 239),
        (123, 239),
        (122, 240),
        (121, 240),
        (120, 241),
        (119, 241),
        (118, 242),
        (116, 242),
        (115, 243),
        (114, 243),
        (113, 244),
        (112, 244),
        (110, 246),
        (109, 246),
        (108, 247),
        (107, 247),
        (106, 248),
        (105, 248),
        (104, 249),
        (102, 249),
        (101, 250),
        (99, 250),
        (98, 251),
        (97, 251),
        (96, 252),
        (94, 252),
        (92, 254),
        (91, 254),
        (90, 255),
        (89, 255),
        (88, 256),
        (87, 256),
        (86, 257),
        (85, 257),
        (84, 258),
        (83, 258),
        (82, 259),
        (80, 259),
        (79, 260),
        (78, 260),
        (70, 268),
        (70, 269),
        (69, 270),
        (69, 272),
        (68, 273),
        (68, 276),
        (71, 279),
        (73, 279),
        (74, 280),
        (83, 280),
        (84, 279),
        (90, 279),
        (91, 278),
        (94, 278),
        (95, 277),
        (97, 277),
        (98, 276),
        (99, 276),
        (100, 275),
        (101, 275),
        (103, 273),
        (105, 273),
        (106, 272),
        (108, 272),
        (109, 271),
        (111, 271),
        (112, 270),
        (113, 270),
        (114, 269),
        (115, 269),
        (116, 268),
        (117, 268),
        (120, 265),
        (121, 265),
        (122, 264),
        (124, 264),
        (125, 263),
        (126, 263),
        (127, 262),
        (128, 262),
        (129, 261),
        (130, 261),
        (132, 259),
        (133, 259),
        (135, 257),
        (136, 257),
        (137, 256),
        (138, 256),
        (139, 255),
        (141, 255),
        (142, 254),
        (143, 254),
        (145, 252),
        (146, 252),
        (149, 249),
        (150, 249),
        (153, 246),
        (154, 246),
        (158, 242),
        (158, 241),
        (164, 235),
        (164, 234),
        (165, 233),
        (165, 232),
        (166, 231),
        (166, 230),
        (167, 229),
        (167, 227),
        (168, 226),
        (168, 223),
        (169, 222),
        (169, 220),
        (170, 219),
        (170, 212),
        (169, 211),
        (169, 210),
        (168, 209),
        (168, 208),
        (167, 207),
        (167, 206),
        (162, 201),
        (161, 201),
        (159, 199),
        (158, 199),
        (157, 198),
        (155, 198),
        (154, 197),
        (153, 197),
        (151, 195),
        (150, 195),
        (149, 194),
        (147, 194),
        (146, 193),
        (144, 193),
        (143, 192),
        (139, 192),
        (138, 191),
        (132, 191),
        (131, 190),
        (122, 190),
        (121, 189),
    ])
    attributes = {"id": 1, "name": "polygon", "valid": True}
    centerline = Centerline(polygon, **attributes)

    assert isinstance(centerline, Centerline)
    assert isinstance(centerline, geometry.MultiLineString)
def main():
	#-- Read the system arguments listed after the program
	long_options=['DIR=','FILTER=','CLOBBER']
	optlist,arglist = getopt.getopt(sys.argv[1:],'D:F:C',long_options)

	#-- Set default settings
	subdir = 'atrous_32init_drop0.2_customLossR727.dir'
	FILTER = 0.
	flt_str = ''
	clobber = False
	for opt, arg in optlist:
		if opt in ("-D","--DIR"):
			subdir = arg
		elif opt in ("-F","--FILTER"):
			if arg not in ['NONE','none','None','N','n',0]:
				FILTER = float(arg)
				flt_str = '_%.1fkm'%(FILTER/1000)
		elif opt in ("-C","--CLOBBER"):
			clobber = True
			
	
	#-- Get list of files
	pred_dir = os.path.join(ddir,'stitched.dir',subdir)
	fileList = os.listdir(pred_dir)
	pred_list = [f for f in fileList if (f.endswith('.tif') and ('mask' not in f))]
	#-- output directory
	output_dir = os.path.join(pred_dir,'shapefiles.dir')
	#-- make directories if they don't exist
	if not os.path.exists(output_dir):
		os.mkdir(output_dir)
	#-- if CLOBBBER is False, we are not overwriting old files, so remove exisiting files from list
	if not clobber:
		print('Removing exisitng files.')
		existingList = os.listdir(output_dir)
		existing = [f for f in existingList if (f.endswith('.shp') and ('ERR' not in f) and f.startswith('gl_'))]
		rem_list = []
		for p in pred_list:
			if p.replace('.tif','%s.shp'%flt_str) in existing:
				#-- save index for removing at the end
				rem_list.append(p)
		for p in rem_list:
			print('Ignoring %s.'%p)
			pred_list.remove(p)
	
	# pred_list = ['gl_069_181218-181224-181224-181230_014095-025166-025166-014270_T110614_T110655.tif']
	# pred_list = ['gl_007_180518-180524-180530-180605_021954-011058-022129-011233_T050854_T050855.tif']
	print('# of files: ', len(pred_list))

	#-- threshold for getting contours and centerlines
	eps = 0.3

	#-- loop through prediction files
	#-- get contours and save each as a line in shapefile
	#-- also save training label as line
	for f in pred_list:
		#-- read file
		raster = rasterio.open(os.path.join(pred_dir,f),'r')
		im = raster.read(1)
		#-- get transformation matrix
		trans = raster.transform

		#-- also read the corresponding mask file
		mask_file = os.path.join(pred_dir,f.replace('.tif','_mask.tif'))
		print(mask_file)
		mask_raster = rasterio.open(mask_file,'r')
		mask = mask_raster.read(1)
		mask_raster.close()

		#-- get contours of prediction
		#-- close contour ends to make polygons
		im[np.nonzero(im[:,0] > eps),0] = eps
		im[np.nonzero(im[:,-1] > eps),-1] = eps
		im[0,np.nonzero(im[0,:] > eps)] = eps
		im[-1,np.nonzero(im[-1,:] > eps)] = eps
		contours = skimage.measure.find_contours(im, eps)
		#-- make contours into closed polyons to find pinning points
		#-- also apply noise filter and append to noise list
		x = {}
		y = {}
		noise = []
		pols = [None]*len(contours)
		pol_type = [None]*len(contours)
		for n,contour in enumerate(contours):
			#-- convert to coordinates
			x[n],y[n] = rasterio.transform.xy(trans, contour[:,0], contour[:,1])

			pols[n] = Polygon(zip(x[n],y[n]))
			#-- get elements of mask the contour is on
			submask = mask[np.round(contour[:, 0]).astype('int'), np.round(contour[:, 1]).astype('int')]
			#-- if more than half of the elements are from test tile, count contour as test type
			if np.count_nonzero(submask) > submask.size/2.:
				pol_type[n] = 'Test'
			else:
				pol_type[n] = 'Train'
		
		#-- Loop through all the polygons and taking any overlapping areas out
		#-- of the enclosing polygon and ignore the inside polygon
		ignore_list = []
		for i in range(len(pols)):
			for j in range(len(pols)):
				if (i != j) and pols[i].contains(pols[j]):
					pols[i] = pols[i].difference(pols[j])
					ignore_list.append(j)

		#-- loop through and apply noise filter
		for n in range(len(contours)):
			#-- apply filter
			if (n not in ignore_list) and (len(x[n]) < 2 or LineString(zip(x[n],y[n])).length <= FILTER):
				noise.append(n)

		#-- loop through remaining polygons and determine which ones are 
		#-- pinning points based on the width and length of the bounding box
		pin_list = []
		box_ll = [None]*len(contours)
		box_ww = [None]*len(contours)
		for n in range(len(contours)):
			box_ll[n] = pols[n].length
			box_ww[n] = pols[n].area/box_ll[n]
			if (n not in noise) and (n not in ignore_list):
				#-- make bounding box
				# box = pols[n].minimum_rotated_rectangle
				# bx,by = box.exterior.coords.xy
				# #-- get the dimensions of the sides of the box
				# edge_length = (Point(bx[0],by[0]).distance(Point(bx[1],by[1])), Point(bx[1],by[1]).distance(Point(bx[2],by[2])))
				#-- length is the larger dimension
				# box_ll = max(edge_length)
				# #-- width is the smaller dimension
				# box_ww = min(edge_length)
				#-- if the with is larger than 1/4 of the length, it's a pinning point
				if box_ww[n] > box_ll[n]/25:
					pin_list.append(n)

		#-- find overlap between ignore list nad noise list
		if len(list(set(noise) & set(ignore_list))) != 0:
			sys.exit('Overlap not empty: ', list(set(noise) & set(ignore_list)))

		#-- initialize list of contour linestrings
		er = [None]*len(contours)
		cn = [] #[None]*(len(contours)-len(ignore_list)-len(noise))
		n = 0  # total center line counter
		pc = 1 # pinning point counter
		lc = 1 # line counter
		er_type = [None]*len(er)
		cn_type = [] #[None]*len(cn)
		er_class = [None]*len(er)
		cn_class = [] #[None]*len(cn)
		er_lbl = [None]*len(er)
		cn_lbl = [] #[None]*len(cn)
		#-- loop through polygons, get centerlines, and save
		for idx,p in enumerate(pols):
			er[idx] = [list(a) for a in zip(x[idx],y[idx])]
			er_type[idx] = pol_type[idx]
			if idx in noise:
				er_class[idx] = 'Noise'				
			elif idx in ignore_list:
				er_class[idx] = 'Inner Contour'
			else:
				if idx in pin_list:
					#-- pinning point. Just get perimeter of polygon
					xc,yc = pols[idx].exterior.coords.xy
					cn.append([[list(a) for a in zip(xc,yc)]])
					cn_class.append(['Pinning Point'])
					cn_type.append([pol_type[idx]])
					#-- set label
					cn_lbl.append(['pin%i'%pc])
					pc += 1 #- incremenet pinning point counter
				else:
					#-- get centerlines
					attributes = {"id": idx, "name": "polygon", "valid": True}
					#-- loop over interpolation distances until we can get a single line
					dis = pols[idx].length/400	#100
					try:
						cl = Centerline(p,interpolation_distance=dis, **attributes)
					except:
						print('not enough ridges. Skip')
						continue
					else:
						#-- merge all the lines
						merged_lines = linemerge(cl)
						if merged_lines.geom_type == 'LineString':
							#-- save coordinates of linestring
							xc,yc = merged_lines.coords.xy
							cn.append([[list(a) for a in zip(xc,yc)]])
							cn_class.append(['Grounding Line'])
							cn_lbl.append(['line%i'%lc])
							cn_type.append([pol_type[idx]])
							er_class[idx] = 'GL Uncertainty'
							#-- set label
							er_lbl[idx] = 'err%i'%lc
							lc += 1 #- incremenet line counter
						else:
							nml = len(merged_lines)
							#-- for lines with many bifurcations, the average segment is 
							#-- about 300m, so if # of segments is length/300 or more, ignore.
							if nml < pols[idx].length/300:
								coord_list = []
								for nn in range(nml):
									xc,yc = merged_lines[nn].coords.xy
									coord_list.append([list(a) for a in zip(xc,yc)])
								cn.append(coord_list)
								cn_class.append(['Grounding Line']*nml)
								cn_lbl.append(['line%i'%lc]*nml)
								cn_type.append([pol_type[idx]]*nml)
								er_class[idx] = 'GL Uncertainty'
								#-- set label
								er_lbl[idx] = 'err%i'%lc
								lc += 1 #- incremenet line counter
		
		#-- save all linestrings to file
		#-- make separate files for centerlines and errors
		# 1) GL file
		gl_file = os.path.join(output_dir,f.replace('.tif','%s.shp'%flt_str))
		w = shapefile.Writer(gl_file)
		w.field('ID', 'C')
		w.field('Type','C')
		w.field('Class','C')
		#-- loop over contour centerlines
		for n in range(len(cn)):
			for nn in range(len(cn[n])):
				w.line([cn[n][nn]])
				w.record(cn_lbl[n][nn], cn_type[n][nn], cn_class[n][nn])
		w.close()
		# create the .prj file
		prj = open(gl_file.replace('.shp','.prj'), "w")
		prj.write(raster.crs.to_wkt())
		prj.close()

		# 2) Err File
		er_file = os.path.join(output_dir,f.replace('.tif','%s_ERR.shp'%flt_str))
		w = shapefile.Writer(er_file)
		w.field('ID', 'C')
		w.field('Type','C')
		w.field('Class','C')
		w.field('Length','C')
		w.field('Width','C')
		#-- loop over contours and write them
		for n in range(len(er)):
			w.line([er[n]])
			w.record(er_lbl[n] , er_type[n], er_class[n], box_ll[n], box_ww[n])
		w.close()
		# create the .prj file
		prj = open(er_file.replace('.shp','.prj'), "w")
		prj.write(raster.crs.to_wkt())
		prj.close()

		#-- close input file
		raster.close()
Exemplo n.º 16
0
def test_centerline_is_not_empty(complex_polygon):
    centerline = Centerline(complex_polygon)
    assert centerline.is_empty is False
Exemplo n.º 17
0
def test_centerline_is_simple(complex_polygon):
    centerline = Centerline(complex_polygon)
    assert centerline.is_simple is True
Exemplo n.º 18
0
def test_creating_centerline_from_point_raises_typeerror(point):
    with pytest.raises(InvalidInputTypeError):
        Centerline(point)
Exemplo n.º 19
0
import cv2
import numpy as np
import matplotlib.pyplot as plt

import gdal
from shapely.geometry import Polygon
from centerline.geometry import Centerline
import math

polygon = Polygon([[0, 0], [0, 4], [4, 4], [4, 0]])
attributes = {"id": 1, "name": "polygon", "valid": True}
centerline = Centerline(polygon, **attributes)
print(centerline.id == 1)

x  = math.log2(3, 2)


"""
def nothing(x):
    pass


img_file = r'I:\DVRPC\Fill_gap\StreetView\images\kXg-PRDBdAix6L11lAtONA_-75.675715_40.050323_0_74.77_landcover.png'

cv2.namedWindow('image')

img = cv2.imread(img_file)
cv2.namedWindow('image')
cv2.createTrackbar('Er/Di', 'image', 0, 1, nothing)
# 创建腐蚀或膨胀选择滚动条,只有两个值
cv2.createTrackbar('size', 'image', 0, 21, nothing)
Exemplo n.º 20
0
def test_creating_centerline_from_multilinestring_raises_typeerror(
        multilinestring):
    with pytest.raises(InvalidInputTypeError):
        Centerline(multilinestring)