-
Notifications
You must be signed in to change notification settings - Fork 0
/
balloon.py
75 lines (58 loc) · 1.77 KB
/
balloon.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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# IMPORTS #
from PIL import Image, ImageOps
import numpy as np
from math import cos, sin, pi
# CONSTANTES #
k = .9
k1 = .8
def gonfle(v, forcex, forcey):
"Applique la force de gonflement à chaque point de la courbe"
l = len(v)
newv = l*[(0,0)]
for s,(x,y) in enumerate(v):
fx, fy = forcex[round(y),round(x)], forcey[round(y),round(x)]
#Calcul du vecteur normal
ny = -(v[(s+1)%l][0] - v[(s-1)%l][0])
nx = v[(s+1)%l][1] - v[(s-1)%l][1]
module = (nx**2 + ny**2)**.5
if module==0 :
newv[s] = v[s]
continue
ny /= module
nx /= module
#Calcul du nouveau point
dx, dy = k1*nx + fx, k1*ny + fy
newv[s] = (x+dx, y+dy)
return newv
def fusion(v):
newv = [v[0]]
for i in range(1, len(v)):
if v[i] != newv[-1]:
newv.append(v[i])
return newv
def get_contours(
image : Image.Image,
niteration : int,
npoints : int,
initial_guess_radius : float) -> 'list[tuple[int, int]]':
image = ImageOps.grayscale(image)
center = (image.size[0]//2, image.size[1]//2)
imagearr = np.asarray(image)
gradx,grady = np.gradient(imagearr)
potentiel = -(gradx**2 + grady**2)
forcey, forcex = np.gradient(potentiel)
for i in range(len(forcex)):
for j in range(len(forcex[0])):
l = (forcex[i,j]**2 + forcey[i,j]**2)**.5
if l != 0:
forcex[i,j] *= k/l
forcey[i,j] *= k/l
v = [
((center[0]+initial_guess_radius*cos(theta)),
(center[1]+initial_guess_radius*sin(theta)))
for theta in np.linspace(0, 2*pi, npoints+1)
]
for _ in range(niteration):
v = fusion(v)
v = gonfle(v, forcex, forcey)
return [(int(x), int(y)) for x,y in v]