ruby_marks 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +168 -139
- data/lib/ruby_marks/config.rb +14 -35
- data/lib/ruby_marks/group.rb +43 -13
- data/lib/ruby_marks/image_utils.rb +109 -1
- data/lib/ruby_marks/mark.rb +42 -0
- data/lib/ruby_marks/recognizer.rb +304 -315
- data/lib/ruby_marks/scan_area.rb +11 -0
- data/lib/ruby_marks/version.rb +1 -1
- data/lib/ruby_marks.rb +28 -19
- data/test/ruby_marks/image_utils_test.rb +17 -1
- data/test/ruby_marks/recognizer_test.rb +51 -55
- metadata +10 -10
- data/lib/ruby_marks/clock_mark.rb +0 -65
- data/test/ruby_marks/clock_mark_test.rb +0 -44
- data/test/ruby_marks/group_test.rb +0 -26
@@ -7,18 +7,116 @@ module RubyMarks
|
|
7
7
|
x2.to_i - x1.to_i + 1
|
8
8
|
end
|
9
9
|
|
10
|
+
|
10
11
|
def self.calc_height(y1, y2)
|
11
12
|
y2.to_i - y1.to_i + 1
|
12
13
|
end
|
13
14
|
|
15
|
+
|
14
16
|
def self.calc_middle_horizontal(x, width)
|
15
17
|
x.to_i + width.to_i / 2
|
16
18
|
end
|
17
19
|
|
20
|
+
|
18
21
|
def self.calc_middle_vertical(y, height)
|
19
22
|
y.to_i + height.to_i / 2
|
20
23
|
end
|
21
|
-
|
24
|
+
|
25
|
+
|
26
|
+
def self.image_center(coordinates)
|
27
|
+
width = self.calc_width(coordinates[:x1], coordinates[:x2])
|
28
|
+
height = self.calc_height(coordinates[:y1], coordinates[:y2])
|
29
|
+
|
30
|
+
x = self.calc_middle_horizontal(coordinates[:x1], width)
|
31
|
+
y = self.calc_middle_vertical(coordinates[:y1], height)
|
32
|
+
return {x: x, y: y}
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def self.flood_scan(image, x, y, character=" ", coordinates={})
|
37
|
+
coordinates = {x1: 0, y1: 0, x2: image[0].size, y2: image.size} unless coordinates.any?
|
38
|
+
result_mask = Hash.new { |hash, key| hash[key] = [] }
|
39
|
+
result_mask.tap do |result_mask|
|
40
|
+
process_queue = Hash.new { |hash, key| hash[key] = [] }
|
41
|
+
process_line = true
|
42
|
+
|
43
|
+
loop do
|
44
|
+
|
45
|
+
break if y > coordinates[:y2] - 1 || y < coordinates[:y1]
|
46
|
+
reset_process = false
|
47
|
+
|
48
|
+
if process_line
|
49
|
+
current_x = x
|
50
|
+
loop do
|
51
|
+
position = image[y][current_x]
|
52
|
+
|
53
|
+
break if position != character || current_x - 1 <= coordinates[:x1]
|
54
|
+
process_queue[y] << current_x unless process_queue[y].include?(current_x) || result_mask[y].include?(current_x)
|
55
|
+
result_mask[y] << current_x unless result_mask[y].include?(current_x)
|
56
|
+
current_x = current_x - 1
|
57
|
+
end
|
58
|
+
|
59
|
+
current_x = x.to_i
|
60
|
+
loop do
|
61
|
+
position = image[y][current_x]
|
62
|
+
|
63
|
+
break if position != character || current_x + 1 >= coordinates[:x2]
|
64
|
+
process_queue[y] << current_x unless process_queue[y].include?(current_x) || result_mask[y].include?(current_x)
|
65
|
+
result_mask[y] << current_x unless result_mask[y].include?(current_x)
|
66
|
+
current_x = current_x + 1
|
67
|
+
end
|
68
|
+
|
69
|
+
result_mask[y] = result_mask[y].sort
|
70
|
+
process_queue[y] = process_queue[y].sort
|
71
|
+
end
|
72
|
+
|
73
|
+
process_line = true
|
74
|
+
|
75
|
+
process_queue[y].each do |element|
|
76
|
+
if y - 1 >= coordinates[:y1]
|
77
|
+
position = image[y-1][element]
|
78
|
+
|
79
|
+
if position == character && !result_mask[y-1].include?(element)
|
80
|
+
x = element
|
81
|
+
y = y - 1
|
82
|
+
reset_process = true
|
83
|
+
break
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
next if reset_process
|
89
|
+
|
90
|
+
process_queue[y].each do |element|
|
91
|
+
if y + 1 <= coordinates[:y2]
|
92
|
+
position = image[y+1] && image[y+1][element]
|
93
|
+
|
94
|
+
if position && position == character && !result_mask[y+1].include?(element)
|
95
|
+
x = element
|
96
|
+
y = y + 1
|
97
|
+
reset_process = true
|
98
|
+
break
|
99
|
+
else
|
100
|
+
process_queue[y].delete(element)
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
next if reset_process
|
107
|
+
|
108
|
+
process_queue.each do |k,v|
|
109
|
+
process_queue.delete(k) if v.empty?
|
110
|
+
end
|
111
|
+
|
112
|
+
break if process_queue.empty?
|
113
|
+
|
114
|
+
process_line = false
|
115
|
+
y = process_queue.first[0] if process_queue.first.is_a?(Array)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
22
120
|
|
23
121
|
def self.to_hex(red, green, blue)
|
24
122
|
red = get_hex_from_color(red)
|
@@ -27,6 +125,16 @@ module RubyMarks
|
|
27
125
|
"##{red}#{green}#{blue}".upcase
|
28
126
|
end
|
29
127
|
|
128
|
+
|
129
|
+
def self.export_file_to_str(file)
|
130
|
+
image = file.export_pixels_to_str
|
131
|
+
image = image.gsub!(Regexp.new('\xFF\xFF\xFF', nil, 'n'), " ,") if image
|
132
|
+
image = image.gsub!(Regexp.new('\x00\x00\x00', nil, 'n'), ".,") if image
|
133
|
+
image = image.split(',') if image
|
134
|
+
image = image.each_slice(file.page.width).to_a if image
|
135
|
+
end
|
136
|
+
|
137
|
+
|
30
138
|
private
|
31
139
|
def self.get_hex_from_color(color)
|
32
140
|
color = color.to_s(16)[0..1]
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module RubyMarks
|
2
|
+
|
3
|
+
class Mark
|
4
|
+
|
5
|
+
attr_accessor :coordinates, :group, :position, :line, :image_str, :distance_from_previous
|
6
|
+
|
7
|
+
def initialize(params={})
|
8
|
+
params.each do |k, v|
|
9
|
+
self.send("#{k}=", v) if self.respond_to?("#{k}=")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def marked?
|
14
|
+
if @image_str
|
15
|
+
colors = []
|
16
|
+
|
17
|
+
@image_str.each do |y|
|
18
|
+
y.each do |x|
|
19
|
+
colors << x
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
intensity = colors.count(".") * 100 / colors.size
|
24
|
+
return intensity >= @group.recognizer.config.intensity_percentual
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def unmarked?
|
29
|
+
!marked?
|
30
|
+
end
|
31
|
+
|
32
|
+
def value
|
33
|
+
if @group
|
34
|
+
position = @group.marks[line].index(self)
|
35
|
+
|
36
|
+
values = @group.marks_options
|
37
|
+
return position && values[position]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|