Skip to content

Instantly share code, notes, and snippets.

@seenitall
Last active May 15, 2019 09:28
Show Gist options
  • Save seenitall/622a5dd016ee36910485108010874699 to your computer and use it in GitHub Desktop.
Save seenitall/622a5dd016ee36910485108010874699 to your computer and use it in GitHub Desktop.
Polygon interpolation functions in numpy
import numpy as np
import cv2
import math
import torch
###### POLYGON INTERPOLATION FUNCTIONS NUMPY ######
def segments(poly):
"""A sequence of (x,y) numeric coordinates pairs """
return zip(poly, poly[1:] + [poly[0]])
def perimeter(poly):
"""A sequence of (x,y) numeric coordinates pairs """
return abs(sum(math.hypot(x0-x1, y0-y1) for ((x0, y0), (x1, y1)) in segments(poly)))
def average_int_distance(poly):
return abs(np.mean([math.hypot(x0-x1, y0-y1) for ((x0, y0), (x1, y1)) in segments(poly)]))
def median_int_distance(poly):
return abs(np.median([math.hypot(x0-x1, y0-y1) for ((x0, y0), (x1, y1)) in segments(poly)]))
def quantile_int_distance(poly, quantile):
return abs(np.quantile([math.hypot(x0-x1, y0-y1) for ((x0, y0), (x1, y1)) in segments(poly)], quantile))
def n_int_distance_above_quantile(poly, int_quantile_dist):
total = sum((math.hypot(x0-x1, y0-y1) > int_quantile_dist) for ((x0, y0), (x1, y1)) in segments(poly))
return total
def interpolate_polygon(polygon, K, device):
"""
interpolation in Pytorch: https://github.com/pytorch/pytorch/issues/1552
https://gist.github.com/peteflorence/a1da2c759ca1ac2b74af9a83f69ce20e
"""
if len(polygon) > K:
"""randomly select K points"""
random_ix = np.sort(np.random.randint(len(polygon), size=K))
new_points = [polygon[i] for i in random_ix]
assert len(new_points) == K
return new_points
if not isinstance(polygon, list):
lpol = polygon.tolist()
n_points_per_int = (K - len(lpol)) / len(lpol)
remaining_points = (K - len(lpol)) % len(lpol)
quantile = 1 - math.modf(n_points_per_int)[0]
new_points = []
per = perimeter(lpol)
try:
int_quantile_dist = quantile_int_distance(lpol, quantile)
except:
print(math.modf(n_points_per_int), len(lpol), polygon)
n_above_quantile = n_int_distance_above_quantile(lpol, int_quantile_dist)
if n_above_quantile > remaining_points:
n_above_quantile = remaining_points
n_to_dist = remaining_points // n_above_quantile if n_above_quantile > 0 else 0
for _, (p0, p1) in enumerate(zip(lpol, lpol[1::] + lpol[:1])):
n_points = n_points_per_int
dist = math.hypot(p0[0] - p1[0], p0[1] - p1[1]) # math.sqrt((x0-x1)**2 + (y0-y1)**2)
if dist > int_quantile_dist and remaining_points > 0:
n_points += n_to_dist
remaining_points -= n_to_dist
deltas = np.sort(np.random.random_sample(size=int(n_points)))
x_points = [p0[0] + i * (p1[0] - p0[0]) for i in deltas]
y_points = np.interp(x_points, [p0[0], p1[0]], [p0[1], p1[1]])
new_points.append(p0)
for x, y in zip(x_points, y_points):
new_points.append([x, y])
assert len(new_points) <= K, (len(new_points), len(lpol), polygon)
pad_len = K - len(new_points)
last_point = new_points[-1] if len(new_points) > 0 else 0.
new_points = np.pad(new_points, ((0, pad_len), (0, 0)), mode='constant', constant_values=((0,last_point),(0,0)))
else:
lpol = polygon
new_points = [[0., 0.]] * K
new_points = np.array(new_points)
return new_points
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment