-
Notifications
You must be signed in to change notification settings - Fork 14
/
ishihara.py
112 lines (83 loc) · 3.32 KB
/
ishihara.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import math
import random
import sys
from PIL import Image, ImageDraw
try:
from scipy.spatial import cKDTree as KDTree
import numpy as np
IMPORTED_SCIPY = True
except ImportError:
IMPORTED_SCIPY = False
BACKGROUND = (255, 255, 255)
TOTAL_CIRCLES = 1500
color = lambda c: ((c >> 16) & 255, (c >> 8) & 255, c & 255)
COLORS_ON = [
color(0xF9BB82), color(0xEBA170), color(0xFCCD84)
]
COLORS_OFF = [
color(0x9CA594), color(0xACB4A5), color(0xBBB964),
color(0xD7DAAA), color(0xE5D57D), color(0xD1D6AF)
]
def generate_circle(image_width, image_height, min_diameter, max_diameter):
radius = random.triangular(min_diameter, max_diameter,
max_diameter * 0.8 + min_diameter * 0.2) / 2
angle = random.uniform(0, math.pi * 2)
distance_from_center = random.uniform(0, image_width * 0.48 - radius)
x = image_width * 0.5 + math.cos(angle) * distance_from_center
y = image_height * 0.5 + math.sin(angle) * distance_from_center
return x, y, radius
def overlaps_motive(image, circle):
x, y, r = circle
points_x = [x, x, x, x-r, x+r, x-r*0.93, x-r*0.93, x+r*0.93, x+r*0.93]
points_y = [y, y-r, y+r, y, y, y+r*0.93, y-r*0.93, y+r*0.93, y-r*0.93]
for xy in zip(points_x, points_y):
if image.getpixel(xy)[:3] != BACKGROUND:
return True
return False
def circle_intersection(circle1, circle2):
x1, y1, r1 = circle1
x2, y2, r2 = circle2
return (x2 - x1)**2 + (y2 - y1)**2 < (r2 + r1)**2
def circle_draw(draw_image, image, circle):
fill_colors = COLORS_ON if overlaps_motive(image, circle) else COLORS_OFF
fill_color = random.choice(fill_colors)
x, y, r = circle
draw_image.ellipse((x - r, y - r, x + r, y + r),
fill=fill_color,
outline=fill_color)
def main():
image = Image.open(sys.argv[1]).convert('RGB')
image2 = Image.new('RGB', image.size, BACKGROUND)
draw_image = ImageDraw.Draw(image2)
width, height = image.size
min_diameter = (width + height) / 200
max_diameter = (width + height) / 75
circle = generate_circle(width, height, min_diameter, max_diameter)
circles = [circle]
circle_draw(draw_image, image, circle)
try:
for i in range(TOTAL_CIRCLES):
tries = 0
if IMPORTED_SCIPY:
kdtree = KDTree([(x, y) for (x, y, _) in circles])
while True:
circle = generate_circle(width, height, min_diameter, max_diameter)
elements, indexes = kdtree.query([(circle[0], circle[1])], k=12)
for element, index in zip(elements[0], indexes[0]):
if not np.isinf(element) and circle_intersection(circle, circles[index]):
break
else:
break
tries += 1
else:
while any(circle_intersection(circle, circle2) for circle2 in circles):
tries += 1
circle = generate_circle(width, height, min_diameter, max_diameter)
print('{}/{} {}'.format(i, TOTAL_CIRCLES, tries))
circles.append(circle)
circle_draw(draw_image, image, circle)
except (KeyboardInterrupt, SystemExit):
pass
image2.show()
if __name__ == '__main__':
main()