forked from quran/ayah-detection
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlines.py
130 lines (112 loc) · 3.97 KB
/
lines.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import sys
from PIL import Image, ImageDraw
"""
algorithm for determining rows
- find out the number of non-white pixels in each row
- rows with low pixel count (20 and below, for example) are break points
- combine them into ranges, such that we have line+1 groups
- if midpoint[i+1] - height is within range, use it - otherwise, start at
either low[i] and end at low[i] + height or at high[i] and end after height
depending on where we are relative to the range at i
then, for each line's ys, find the min x and max across them.
we then have the bounding box for each line
"""
def is_not_blank(pt):
return sum(pt) < 200 * len(pt)
def find_lines(image, line_height, max_pixels, mode):
ranges = []
range_end = -1
range_start = -1
restrict_lines = True
if mode == 1:
restrict_lines = False
data = image.getdata()
width, height = image.size
for y in range(0, height):
filled_pixels = 0
for x in range(0, width):
pt = data[y * width + x]
if is_not_blank(pt):
filled_pixels = filled_pixels + 1
# print "line " + str(y) + " has " + str(filled_pixels)
if filled_pixels < max_pixels:
if range_start == -1:
if restrict_lines and filled_pixels == 0 and len(ranges) == 0:
continue
range_start = y
range_end = y
elif y - range_end < 20:
range_end = y
else:
# print "adding range " + str(range_start) + "," + str(range_end)
ranges.append((range_start, range_end))
range_start = -1
range_end = -1
if range_start > -1:
ranges.append((range_start, range_end))
line_ys = []
should_skip = False
for i in range(0, len(ranges) - 1):
if should_skip:
should_skip = False
continue
top = ranges[i]
bottom = ranges[i + 1]
midpoint = (bottom[0] + bottom[1]) / 2
if bottom[1] - top[0] < line_height:
top_midpoint = ((top[0] + top[1]) / 2)
top = (top_midpoint, midpoint)
bottom = ranges[i + 2]
midpoint = (bottom[0] + bottom[1]) / 2
should_skip = True
top_y = midpoint - line_height
if top[0] <= top_y <= top[1]:
# within range, we keep it
line_ys.append((top_y, midpoint))
elif top_y < top[0]:
if top[0] + line_height < height:
line_ys.append((top[0], top[0] + line_height))
else:
if top[1] + line_height < height:
line_ys.append((top[1], top[1] + line_height))
lines = []
for yrange in line_ys:
first_x = width
last_x = 0
for y in range(int(yrange[0]), int(yrange[1])):
for x in range(0, width):
pt = data[y * width + x]
if is_not_blank(pt):
if first_x > x:
first_x = x - 1
break
for x in reversed(range(0, width)):
pt = data[y * width + x]
if is_not_blank(pt):
if x > last_x:
last_x = x
break
lines.append(((first_x, yrange[0]), (last_x, yrange[1])))
return lines
# for debugging, this method draws boxes around each line
def draw(image, lines, output):
drawing = ImageDraw.Draw(image)
for line in lines:
drawing.rectangle([line[0], line[1]], None, (255, 0, 0))
del drawing
image.save(output)
def main():
if len(sys.argv) < 2:
print("usage: " + sys.argv[0] + " [image]")
sys.exit(1)
image = Image.open(sys.argv[1]).convert('RGBA')
# 100/35/0 for warsh
# 110/87/0 for shamerly
# 175/75/1 for qaloon
lines = find_lines(image, 110, 87, 0)
for line in lines:
print(line)
draw(image, lines, 'test.png')
print("lines: %d" % len(lines))
if __name__ == "__main__":
main()