-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathutils.py
59 lines (47 loc) · 1.61 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from collections import namedtuple
from math import hypot
from operator import itemgetter
from typing import List
import numpy as np
from PIL import Image
Point = namedtuple("Point", ["x", "y"])
def polygon_area(points: List[Point]) -> float:
# https://stackoverflow.com/questions/24467972/calculate-area-of-polygon-given-x-y-coordinates
x = np.array(list(map(itemgetter(0), points)))
y = np.array(list(map(itemgetter(1), points)))
return 0.5 * np.abs(np.dot(x, np.roll(y, 1)) - np.dot(y, np.roll(x, 1)))
def polygon_centroid(points: List[Point]) -> Point:
x = np.array(list(map(itemgetter(0), points)))
y = np.array(list(map(itemgetter(1), points)))
return Point(sum(x) / len(points), sum(y) / len(points))
def polygon_mean_side_len(points: List[Point]) -> float:
ptdiff = lambda p1, p2: hypot(p1.x - p2.x, p1.y - p2.y)
diffs = [
ptdiff(p1, p2)
for p1, p2 in zip(
points,
points[1:]
+ [
points[0],
],
)
]
return sum(diffs) / len(diffs)
def polygon_scale(points: List[Point], scale: float) -> List[Point]:
centroid = polygon_centroid(points)
return list(
map(
lambda pnt: Point(
scale * (pnt.x - centroid.x) + centroid.x,
scale * (pnt.y - centroid.y) + centroid.y,
),
points,
)
)
def polygon_points_inside_image(points: List[Point], image_pil: Image) -> bool:
return all(
map(
lambda pnt: 0 <= pnt.x < image_pil.width and 0 <= pnt.y < image_pil.height,
points,
)
)