ruby_marks 0.4.1 → 0.4.4
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/lib/ruby_marks/flood_scan.rb +27 -5
- data/lib/ruby_marks/recognizer.rb +84 -92
- data/lib/ruby_marks/version.rb +1 -1
- data/test/ruby_marks/new_grid_test.rb +63 -0
- data/test/ruby_marks/recognizer_grid_test.rb +4 -4
- metadata +20 -14
- checksums.yaml +0 -15
|
@@ -2,11 +2,32 @@ module RubyMarks
|
|
|
2
2
|
|
|
3
3
|
class FloodScan
|
|
4
4
|
|
|
5
|
+
def scan_mark(image, width, height)
|
|
6
|
+
target = Magick::Pixel.new(0, 0, 0, 0)
|
|
7
|
+
vx = Hash.new { |hash, key| hash[key] = [] }
|
|
8
|
+
vy = Hash.new { |hash, key| hash[key] = [] }
|
|
9
|
+
(1..image.rows).each do |y|
|
|
10
|
+
(1..image.columns).each do |x|
|
|
11
|
+
if image.get_pixels(x-1, y-1, 1, 1)[0] == target
|
|
12
|
+
vx[y] << x
|
|
13
|
+
vy[x] << y
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
vx = vx.find_mesure(width, 5).max_frequency
|
|
18
|
+
vy = vy.find_mesure(height, 5).max_frequency
|
|
19
|
+
if vx && vy
|
|
20
|
+
{x1: vx[0][0], y1: vy[0][0], x2: vx[0][1], y2: vy[0][1]}
|
|
21
|
+
else
|
|
22
|
+
{}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
5
26
|
def scan(image, node, width, height)
|
|
6
|
-
target = Magick::Pixel.new(65535, 65535, 65535, 0)
|
|
27
|
+
target = Magick::Pixel.new(65535, 65535, 65535, 0)
|
|
7
28
|
replacement = Magick::Pixel.new(0, 0, 0, 0)
|
|
8
29
|
queue = Array.new
|
|
9
|
-
queue.push(node)
|
|
30
|
+
queue.push(node)
|
|
10
31
|
vx = Hash.new { |hash, key| hash[key] = [] }
|
|
11
32
|
vy = Hash.new { |hash, key| hash[key] = [] }
|
|
12
33
|
steps = 0
|
|
@@ -17,10 +38,11 @@ module RubyMarks
|
|
|
17
38
|
span_up = false;
|
|
18
39
|
span_down = false;
|
|
19
40
|
while x > 0 && image.get_pixels(x - 1, y, 1, 1)[0] == target
|
|
41
|
+
p
|
|
20
42
|
x -= 1
|
|
21
43
|
end
|
|
22
44
|
while x < image.columns && image.get_pixels(x, y, 1, 1)[0] == target
|
|
23
|
-
image.store_pixels(x, y, 1, 1, [replacement])
|
|
45
|
+
image.store_pixels(x, y, 1, 1, [replacement])
|
|
24
46
|
if !span_up && y > 0 && image.get_pixels(x, y - 1, 1, 1)[0] == target
|
|
25
47
|
queue.push(Magick::Point.new(x, y - 1))
|
|
26
48
|
span_up = true
|
|
@@ -33,12 +55,12 @@ module RubyMarks
|
|
|
33
55
|
elsif span_down && y < image.rows - 1 && image.get_pixels(x, y + 1, 1, 1)[0] != target
|
|
34
56
|
span_down = false
|
|
35
57
|
end
|
|
36
|
-
vx[y] << x
|
|
58
|
+
vx[y] << x
|
|
37
59
|
vy[x] << y
|
|
38
60
|
x += 1
|
|
39
61
|
steps += 1
|
|
40
62
|
end
|
|
41
|
-
queue.push(Magick::Point.new(x, y - 1)) if queue.empty? && steps < 100
|
|
63
|
+
queue.push(Magick::Point.new(x, y - 1)) if queue.empty? && steps < 100
|
|
42
64
|
end
|
|
43
65
|
vx = vx.find_mesure(width, 5).max_frequency
|
|
44
66
|
vy = vy.find_mesure(height, 5).max_frequency
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#encoding: utf-8
|
|
2
2
|
module RubyMarks
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
class Recognizer
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
attr_reader :file, :raised_watchers, :groups, :watchers, :file_str, :original_file_str
|
|
7
7
|
attr_accessor :config, :groups_detected, :groups_not_detected
|
|
8
8
|
|
|
@@ -23,8 +23,8 @@ module RubyMarks
|
|
|
23
23
|
@original_file_str = nil
|
|
24
24
|
|
|
25
25
|
@file = Magick::Image.read(file).first
|
|
26
|
-
@file = @file.quantize(256, Magick::GRAYColorspace)
|
|
27
|
-
@file = @file.threshold(@config.calculated_threshold_level)
|
|
26
|
+
@file = @file.quantize(256, Magick::GRAYColorspace)
|
|
27
|
+
@file = @file.threshold(@config.calculated_threshold_level)
|
|
28
28
|
@original_file = @file
|
|
29
29
|
@file = @file.edge(@config.edge_level)
|
|
30
30
|
@groups_detected = false
|
|
@@ -32,15 +32,15 @@ module RubyMarks
|
|
|
32
32
|
@groups.each_pair do |label, group|
|
|
33
33
|
group.marks = nil
|
|
34
34
|
group.marks = Hash.new { |hash, key| hash[key] = [] }
|
|
35
|
-
end
|
|
35
|
+
end
|
|
36
36
|
end
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
|
|
39
39
|
def reset_document
|
|
40
40
|
@current_position = {x: 0, y: 0}
|
|
41
41
|
@clock_marks = []
|
|
42
42
|
@raised_watchers = {}
|
|
43
|
-
@watchers = {}
|
|
43
|
+
@watchers = {}
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
|
|
@@ -56,7 +56,7 @@ module RubyMarks
|
|
|
56
56
|
|
|
57
57
|
def configure(&block)
|
|
58
58
|
self.create_config
|
|
59
|
-
@config.configure(&block)
|
|
59
|
+
@config.configure(&block)
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
|
|
@@ -75,7 +75,7 @@ module RubyMarks
|
|
|
75
75
|
watcher = @watchers[name]
|
|
76
76
|
if watcher
|
|
77
77
|
@raised_watchers[watcher.name] ||= 0
|
|
78
|
-
@raised_watchers[watcher.name] += 1
|
|
78
|
+
@raised_watchers[watcher.name] += 1
|
|
79
79
|
watcher.run(*args)
|
|
80
80
|
end
|
|
81
81
|
end
|
|
@@ -83,39 +83,39 @@ module RubyMarks
|
|
|
83
83
|
|
|
84
84
|
def scan
|
|
85
85
|
raise IOError, "There's a invalid or missing file" if @file.nil?
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
unmarked_group_found = false
|
|
88
88
|
multiple_marked_found = false
|
|
89
89
|
|
|
90
90
|
result = Hash.new { |hash, key| hash[key] = [] }
|
|
91
91
|
result.tap do |result|
|
|
92
|
-
|
|
93
|
-
begin
|
|
92
|
+
|
|
93
|
+
begin
|
|
94
94
|
Timeout.timeout(@config.scan_timeout) do
|
|
95
|
-
self.detect_groups unless @groups_detected
|
|
96
|
-
end
|
|
95
|
+
self.detect_groups unless @groups_detected
|
|
96
|
+
end
|
|
97
97
|
rescue Timeout::Error
|
|
98
98
|
raise_watcher :timed_out_watcher
|
|
99
99
|
return result
|
|
100
|
-
end
|
|
100
|
+
end
|
|
101
101
|
|
|
102
|
-
@groups.each_pair do |label, group|
|
|
102
|
+
@groups.each_pair do |label, group|
|
|
103
103
|
marks = Hash.new { |hash, key| hash[key] = [] }
|
|
104
104
|
group.marks.each_pair do |line, value|
|
|
105
105
|
value.each do |mark|
|
|
106
|
-
marks[line] << mark.value if mark.marked?
|
|
106
|
+
marks[line] << mark.value if mark.marked? && mark.value
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
-
multiple_marked_found = true if marks[line].size > 1
|
|
109
|
+
multiple_marked_found = true if marks[line].size > 1
|
|
110
110
|
unmarked_group_found = true if marks[line].empty?
|
|
111
111
|
end
|
|
112
112
|
|
|
113
|
-
result[group.label.to_sym] = marks
|
|
113
|
+
result[group.label.to_sym] = marks
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
raise_watcher :scan_unmarked_watcher, result if unmarked_group_found
|
|
117
|
-
raise_watcher :scan_multiple_marked_watcher, result if multiple_marked_found
|
|
118
|
-
raise_watcher :scan_mark_watcher, result, unmarked_group_found, multiple_marked_found if unmarked_group_found || multiple_marked_found
|
|
117
|
+
raise_watcher :scan_multiple_marked_watcher, result if multiple_marked_found
|
|
118
|
+
raise_watcher :scan_mark_watcher, result, unmarked_group_found, multiple_marked_found if unmarked_group_found || multiple_marked_found
|
|
119
119
|
end
|
|
120
120
|
end
|
|
121
121
|
|
|
@@ -129,16 +129,18 @@ module RubyMarks
|
|
|
129
129
|
y = group_center[:y]
|
|
130
130
|
width = RubyMarks::ImageUtils.calc_width(group.expected_coordinates[:x1], group.expected_coordinates[:x2])
|
|
131
131
|
height = RubyMarks::ImageUtils.calc_height(group.expected_coordinates[:y1], group.expected_coordinates[:y2])
|
|
132
|
-
|
|
133
|
-
block
|
|
132
|
+
block = {}
|
|
133
|
+
while block.empty? && x < group.expected_coordinates[:x2]
|
|
134
|
+
block = scaner.scan(@file.dup, Magick::Point.new(x += 10, y), width, height)
|
|
135
|
+
end
|
|
134
136
|
if !block.empty?
|
|
135
137
|
group.coordinates = {x1: block[:x1], x2: block[:x2], y1: block[:y1], y2: block[:y2]}
|
|
136
138
|
marks_blocks = find_marks_grid(group)
|
|
137
139
|
marks_blocks.each do |mark|
|
|
138
140
|
mark_width = RubyMarks::ImageUtils.calc_width(mark[:x1], mark[:x2])
|
|
139
141
|
mark_height = RubyMarks::ImageUtils.calc_height(mark[:y1], mark[:y2])
|
|
140
|
-
mark_file
|
|
141
|
-
o_mark
|
|
142
|
+
mark_file = @original_file.crop(mark[:x1], mark[:y1], mark_width, mark_height)
|
|
143
|
+
o_mark = RubyMarks::Mark.new group: group,
|
|
142
144
|
coordinates: {x1: mark[:x1], y1: mark[:y1], x2: mark[:x2], y2: mark[:y2]},
|
|
143
145
|
image_str: RubyMarks::ImageUtils.export_file_to_str(mark_file),
|
|
144
146
|
line: mark[:line]
|
|
@@ -171,12 +173,12 @@ module RubyMarks
|
|
|
171
173
|
mark_width = RubyMarks::ImageUtils.calc_width(mark[:x1], mark[:x2])
|
|
172
174
|
mark_height = RubyMarks::ImageUtils.calc_height(mark[:y1], mark[:y2])
|
|
173
175
|
|
|
174
|
-
if mark_width >= group.mark_width_with_down_tolerance &&
|
|
176
|
+
if mark_width >= group.mark_width_with_down_tolerance &&
|
|
175
177
|
mark_height >= group.mark_height_with_down_tolerance
|
|
176
178
|
|
|
177
179
|
mark_positions = mark[:y1]-10..mark[:y1]+10
|
|
178
180
|
line += 1 unless mark_ant && mark_positions.include?(mark_ant[:y1])
|
|
179
|
-
mark[:line] = line
|
|
181
|
+
mark[:line] = line if line <= group.expected_lines
|
|
180
182
|
mark_ant = mark
|
|
181
183
|
end
|
|
182
184
|
end
|
|
@@ -193,10 +195,10 @@ module RubyMarks
|
|
|
193
195
|
mark[:conflict] = true
|
|
194
196
|
mark[:conflicting_mark] = mark_ant
|
|
195
197
|
else
|
|
196
|
-
mark_ant = mark
|
|
198
|
+
mark_ant = mark
|
|
197
199
|
end
|
|
198
200
|
else
|
|
199
|
-
mark_ant = mark
|
|
201
|
+
mark_ant = mark
|
|
200
202
|
end
|
|
201
203
|
end
|
|
202
204
|
marks_blocks.delete_if { |m| m[:conflict] }
|
|
@@ -241,9 +243,9 @@ module RubyMarks
|
|
|
241
243
|
next_mark = marks[index + 1]
|
|
242
244
|
distance = 0
|
|
243
245
|
distance = next_mark[:x1] - current_mark[:x1] if next_mark
|
|
244
|
-
if distance > group.distance_between_marks + 10 ||
|
|
245
|
-
next_mark.nil? && index + 1 < group.marks_options.count
|
|
246
|
-
|
|
246
|
+
if distance > group.distance_between_marks + 10 ||
|
|
247
|
+
next_mark.nil? && index + 1 < group.marks_options.count
|
|
248
|
+
|
|
247
249
|
new_x1 = current_mark[:x1] + group.distance_between_marks
|
|
248
250
|
new_mark = {x1: new_x1,
|
|
249
251
|
x2: new_x1 + group.mark_width,
|
|
@@ -255,19 +257,18 @@ module RubyMarks
|
|
|
255
257
|
bubbles_adjusted << new_mark
|
|
256
258
|
reprocess = true
|
|
257
259
|
break
|
|
258
|
-
end
|
|
260
|
+
end
|
|
259
261
|
end
|
|
260
262
|
break unless reprocess
|
|
261
263
|
end
|
|
262
264
|
end
|
|
263
|
-
|
|
264
265
|
end
|
|
265
266
|
|
|
266
267
|
marks_blocks.each do |mark|
|
|
267
268
|
mark_width = RubyMarks::ImageUtils.calc_width(mark[:x1], mark[:x2])
|
|
268
269
|
mark_height = RubyMarks::ImageUtils.calc_height(mark[:y1], mark[:y2])
|
|
269
270
|
mark_file = @original_file.crop(mark[:x1], mark[:y1], mark_width, mark_height)
|
|
270
|
-
o_mark = RubyMarks::Mark.new group: group,
|
|
271
|
+
o_mark = RubyMarks::Mark.new group: group,
|
|
271
272
|
coordinates: {x1: mark[:x1], y1: mark[:y1], x2: mark[:x2], y2: mark[:y2]},
|
|
272
273
|
image_str: RubyMarks::ImageUtils.export_file_to_str(mark_file),
|
|
273
274
|
line: mark[:line]
|
|
@@ -277,40 +278,39 @@ module RubyMarks
|
|
|
277
278
|
incorrect_expected_lines = group.incorrect_expected_lines
|
|
278
279
|
|
|
279
280
|
group.marks.each_pair do |line, marks|
|
|
280
|
-
if marks.count != group.marks_options.count
|
|
281
|
+
if marks.count != group.marks_options.count
|
|
281
282
|
incorrect_bubble_line_found[group.label.to_sym] << line
|
|
282
283
|
end
|
|
283
|
-
end
|
|
284
|
+
end
|
|
284
285
|
end
|
|
285
|
-
end
|
|
286
|
+
end
|
|
286
287
|
@groups_detected = true
|
|
287
|
-
if incorrect_bubble_line_found.any? || bubbles_adjusted.any? || incorrect_expected_lines
|
|
288
|
-
raise_watcher :incorrect_group_watcher, incorrect_expected_lines, incorrect_bubble_line_found, bubbles_adjusted.flatten
|
|
288
|
+
if incorrect_bubble_line_found.any? || bubbles_adjusted.any? || incorrect_expected_lines
|
|
289
|
+
raise_watcher :incorrect_group_watcher, incorrect_expected_lines, incorrect_bubble_line_found, bubbles_adjusted.flatten
|
|
289
290
|
end
|
|
290
291
|
end
|
|
291
292
|
end
|
|
292
293
|
|
|
293
|
-
|
|
294
294
|
def find_block_marks(image, x, y, group)
|
|
295
295
|
expected_coordinates = group.expected_coordinates
|
|
296
296
|
found_blocks = []
|
|
297
297
|
expected_width = RubyMarks::ImageUtils.calc_width(expected_coordinates[:x1], expected_coordinates[:x2])
|
|
298
|
-
expected_height = RubyMarks::ImageUtils.calc_height(expected_coordinates[:y1], expected_coordinates[:y2])
|
|
298
|
+
expected_height = RubyMarks::ImageUtils.calc_height(expected_coordinates[:y1], expected_coordinates[:y2])
|
|
299
299
|
block = nil
|
|
300
300
|
while x <= expected_coordinates[:x2] && y <= expected_coordinates[:y2]
|
|
301
301
|
if image[y] && image[y][x] == " "
|
|
302
302
|
block = find_in_blocks(found_blocks, x, y)
|
|
303
|
-
unless block
|
|
303
|
+
unless block
|
|
304
304
|
block = find_block(image, x, y)
|
|
305
305
|
found_blocks << block
|
|
306
|
-
|
|
307
|
-
block[:width] = RubyMarks::ImageUtils.calc_width(block[:x1], block[:x2])
|
|
308
|
-
block[:height] = RubyMarks::ImageUtils.calc_height(block[:y1], block[:y2])
|
|
306
|
+
|
|
307
|
+
block[:width] = RubyMarks::ImageUtils.calc_width(block[:x1], block[:x2])
|
|
308
|
+
block[:height] = RubyMarks::ImageUtils.calc_height(block[:y1], block[:y2])
|
|
309
309
|
|
|
310
310
|
if @config.scan_mode == :grid
|
|
311
311
|
unless block[:width] <= (expected_width + group.block_width_tolerance) && block[:width] >= (expected_width - group.block_width_tolerance)
|
|
312
312
|
if block[:width] > expected_width + group.block_width_tolerance
|
|
313
|
-
ajust_width = block[:width] - expected_width
|
|
313
|
+
ajust_width = block[:width] - expected_width
|
|
314
314
|
if @config.auto_ajust_block_width == :left
|
|
315
315
|
block[:x2] = (block[:x2] - ajust_width) + @config.edge_level
|
|
316
316
|
block[:width] = expected_width + @config.edge_level
|
|
@@ -341,12 +341,12 @@ module RubyMarks
|
|
|
341
341
|
block_width_with_tolerance = block[:width] + group.block_width_tolerance
|
|
342
342
|
block_height_with_tolerance = block[:height] + group.block_height_tolerance
|
|
343
343
|
|
|
344
|
-
return block if block_width_with_tolerance >= expected_width &&
|
|
344
|
+
return block if block_width_with_tolerance >= expected_width &&
|
|
345
345
|
block_height_with_tolerance >= expected_height
|
|
346
346
|
end
|
|
347
347
|
end
|
|
348
348
|
|
|
349
|
-
x += 1
|
|
349
|
+
x += 1
|
|
350
350
|
y += 1
|
|
351
351
|
end
|
|
352
352
|
end
|
|
@@ -359,19 +359,19 @@ module RubyMarks
|
|
|
359
359
|
block_height = RubyMarks::ImageUtils.calc_height(block[:y1], block[:y2])
|
|
360
360
|
lines = group.expected_lines
|
|
361
361
|
columns = group.marks_options.size
|
|
362
|
-
distance_lin =
|
|
363
|
-
distance_col =
|
|
362
|
+
distance_lin = group.mark_height
|
|
363
|
+
distance_col = group.mark_width
|
|
364
364
|
lines.times do |lin|
|
|
365
365
|
columns.times do |col|
|
|
366
366
|
|
|
367
|
-
blocks << { :x1 => block[:x1] + (col * distance_col),
|
|
368
|
-
:y1 => block[:y1] + (lin * distance_lin),
|
|
367
|
+
blocks << { :x1 => block[:x1] + (col * distance_col),
|
|
368
|
+
:y1 => block[:y1] + (lin * distance_lin),
|
|
369
369
|
:x2 => block[:x1] + (col * distance_col) + distance_col,
|
|
370
370
|
:y2 => block[:y1] + (lin * distance_lin) + distance_lin,
|
|
371
371
|
:line => lin + 1 }
|
|
372
372
|
end
|
|
373
373
|
end
|
|
374
|
-
end
|
|
374
|
+
end
|
|
375
375
|
end
|
|
376
376
|
|
|
377
377
|
def find_marks(image, group)
|
|
@@ -381,10 +381,10 @@ module RubyMarks
|
|
|
381
381
|
blocks.tap do |blocks|
|
|
382
382
|
while y < block[:y2]
|
|
383
383
|
x = block[:x1]
|
|
384
|
-
while x < block[:x2] do
|
|
384
|
+
while x < block[:x2] do
|
|
385
385
|
if image[y][x] == " "
|
|
386
386
|
x += 1
|
|
387
|
-
next
|
|
387
|
+
next
|
|
388
388
|
end
|
|
389
389
|
|
|
390
390
|
result = find_in_blocks(blocks, x, y)
|
|
@@ -395,7 +395,7 @@ module RubyMarks
|
|
|
395
395
|
mark_height = RubyMarks::ImageUtils.calc_height(result[:y1], result[:y2])
|
|
396
396
|
|
|
397
397
|
|
|
398
|
-
if mark_width > group.mark_width_with_up_tolerance
|
|
398
|
+
if mark_width > group.mark_width_with_up_tolerance
|
|
399
399
|
distance_x1 = x - result[:x1]
|
|
400
400
|
distance_x2 = result[:x2] - x
|
|
401
401
|
if distance_x1 <= distance_x2
|
|
@@ -403,16 +403,16 @@ module RubyMarks
|
|
|
403
403
|
else
|
|
404
404
|
result[:x1] = result[:x2] - group.mark_width
|
|
405
405
|
end
|
|
406
|
-
end
|
|
407
|
-
|
|
408
|
-
if mark_height > group.mark_height_with_up_tolerance
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
if mark_height > group.mark_height_with_up_tolerance
|
|
409
409
|
distance_y1 = y - result[:y1]
|
|
410
410
|
distance_y2 = result[:y2] - y
|
|
411
411
|
if distance_y1 <= distance_y2
|
|
412
412
|
result[:y2] = result[:y1] + group.mark_height
|
|
413
413
|
else
|
|
414
414
|
result[:y1] = result[:y2] - group.mark_height
|
|
415
|
-
end
|
|
415
|
+
end
|
|
416
416
|
end
|
|
417
417
|
|
|
418
418
|
blocks << result unless blocks.any? { |b| b == result }
|
|
@@ -439,57 +439,49 @@ module RubyMarks
|
|
|
439
439
|
|
|
440
440
|
def flag_all_marks
|
|
441
441
|
raise IOError, "There's a invalid or missing file" if @file.nil?
|
|
442
|
-
|
|
442
|
+
|
|
443
443
|
file = @original_file.dup
|
|
444
444
|
|
|
445
445
|
file.tap do |file|
|
|
446
446
|
|
|
447
|
-
begin
|
|
447
|
+
begin
|
|
448
448
|
Timeout.timeout(@config.scan_timeout) do
|
|
449
|
-
self.detect_groups unless @groups_detected
|
|
450
|
-
end
|
|
449
|
+
self.detect_groups unless @groups_detected
|
|
450
|
+
end
|
|
451
451
|
rescue Timeout::Error
|
|
452
452
|
raise_watcher :timed_out_watcher
|
|
453
453
|
return file
|
|
454
|
-
end
|
|
454
|
+
end
|
|
455
455
|
|
|
456
|
-
@groups.each_pair do |label, group|
|
|
456
|
+
@groups.each_pair do |label, group|
|
|
457
457
|
|
|
458
458
|
dr = Magick::Draw.new
|
|
459
459
|
dr.stroke_width = 5
|
|
460
460
|
dr.stroke(RubyMarks::COLORS[3])
|
|
461
461
|
dr.line(group.expected_coordinates[:x1], group.expected_coordinates[:y1], group.expected_coordinates[:x2], group.expected_coordinates[:y1])
|
|
462
462
|
dr.line(group.expected_coordinates[:x2], group.expected_coordinates[:y1], group.expected_coordinates[:x2], group.expected_coordinates[:y2])
|
|
463
|
-
dr.line(group.expected_coordinates[:x2], group.expected_coordinates[:y2], group.expected_coordinates[:x1], group.expected_coordinates[:y2])
|
|
464
|
-
dr.line(group.expected_coordinates[:x1], group.expected_coordinates[:y2], group.expected_coordinates[:x1], group.expected_coordinates[:y1])
|
|
463
|
+
dr.line(group.expected_coordinates[:x2], group.expected_coordinates[:y2], group.expected_coordinates[:x1], group.expected_coordinates[:y2])
|
|
464
|
+
dr.line(group.expected_coordinates[:x1], group.expected_coordinates[:y2], group.expected_coordinates[:x1], group.expected_coordinates[:y1])
|
|
465
465
|
dr.draw(file)
|
|
466
466
|
|
|
467
|
-
if group.coordinates
|
|
467
|
+
if group.coordinates
|
|
468
468
|
dr = Magick::Draw.new
|
|
469
469
|
dr.stroke_width = 5
|
|
470
|
-
dr.stroke(RubyMarks::COLORS[5])
|
|
470
|
+
dr.stroke(RubyMarks::COLORS[5])
|
|
471
471
|
dr.line(group.coordinates[:x1], group.coordinates[:y1], group.coordinates[:x2], group.coordinates[:y1])
|
|
472
472
|
dr.line(group.coordinates[:x2], group.coordinates[:y1], group.coordinates[:x2], group.coordinates[:y2])
|
|
473
|
-
dr.line(group.coordinates[:x2], group.coordinates[:y2], group.coordinates[:x1], group.coordinates[:y2])
|
|
474
|
-
dr.line(group.coordinates[:x1], group.coordinates[:y2], group.coordinates[:x1], group.coordinates[:y1])
|
|
473
|
+
dr.line(group.coordinates[:x2], group.coordinates[:y2], group.coordinates[:x1], group.coordinates[:y2])
|
|
474
|
+
dr.line(group.coordinates[:x1], group.coordinates[:y2], group.coordinates[:x1], group.coordinates[:y1])
|
|
475
475
|
dr.draw(file)
|
|
476
476
|
end
|
|
477
477
|
|
|
478
478
|
marks = Hash.new { |hash, key| hash[key] = [] }
|
|
479
479
|
group.marks.each_pair do |line, value|
|
|
480
480
|
value.each do |mark|
|
|
481
|
-
mark_width = RubyMarks::ImageUtils.calc_width(mark.coordinates[:x1], mark.coordinates[:x2])
|
|
482
|
-
mark_height = RubyMarks::ImageUtils.calc_height(mark.coordinates[:y1], mark.coordinates[:y2])
|
|
483
|
-
mark_file = @original_file.crop(mark.coordinates[:x1], mark.coordinates[:y1], mark_width, mark_height)
|
|
484
|
-
o_mark = RubyMarks::Mark.new group: group,
|
|
485
|
-
coordinates: {x1: mark.coordinates[:x1], y1: mark.coordinates[:y1], x2: mark.coordinates[:x2], y2: mark.coordinates[:y2]},
|
|
486
|
-
image_str: RubyMarks::ImageUtils.export_file_to_str(mark_file),
|
|
487
|
-
line: line
|
|
488
|
-
|
|
489
481
|
add_mark file, RubyMarks::ImageUtils.image_center(mark.coordinates), mark
|
|
490
482
|
end
|
|
491
483
|
end
|
|
492
|
-
end
|
|
484
|
+
end
|
|
493
485
|
end
|
|
494
486
|
end
|
|
495
487
|
|
|
@@ -519,8 +511,8 @@ module RubyMarks
|
|
|
519
511
|
|
|
520
512
|
def find_in_blocks(blocks, x, y)
|
|
521
513
|
blocks.find do |result|
|
|
522
|
-
result[:x1] <= x && result[:x2] >= x &&
|
|
523
|
-
result[:y1] <= y && result[:y2] >= y
|
|
514
|
+
result[:x1] <= x && result[:x2] >= x &&
|
|
515
|
+
result[:y1] <= y && result[:y2] >= y
|
|
524
516
|
end
|
|
525
517
|
end
|
|
526
518
|
|
|
@@ -534,26 +526,26 @@ module RubyMarks
|
|
|
534
526
|
|
|
535
527
|
dr = Magick::Draw.new
|
|
536
528
|
dr.stroke_width = 2
|
|
537
|
-
dr.stroke(RubyMarks::COLORS[1])
|
|
529
|
+
dr.stroke(RubyMarks::COLORS[1])
|
|
538
530
|
dr.line(mark.coordinates[:x1], mark.coordinates[:y1], mark.coordinates[:x2], mark.coordinates[:y1])
|
|
539
531
|
dr.line(mark.coordinates[:x2], mark.coordinates[:y1], mark.coordinates[:x2], mark.coordinates[:y2])
|
|
540
|
-
dr.line(mark.coordinates[:x2], mark.coordinates[:y2], mark.coordinates[:x1], mark.coordinates[:y2])
|
|
541
|
-
dr.line(mark.coordinates[:x1], mark.coordinates[:y2], mark.coordinates[:x1], mark.coordinates[:y1])
|
|
532
|
+
dr.line(mark.coordinates[:x2], mark.coordinates[:y2], mark.coordinates[:x1], mark.coordinates[:y2])
|
|
533
|
+
dr.line(mark.coordinates[:x1], mark.coordinates[:y2], mark.coordinates[:x1], mark.coordinates[:y1])
|
|
542
534
|
dr.draw(file)
|
|
543
535
|
else
|
|
544
536
|
dr.annotate(file, 0, 0, position[:x]-9, position[:y]+11, "+") do
|
|
545
537
|
self.pointsize = 30
|
|
546
538
|
self.fill = '#900000'
|
|
547
539
|
end
|
|
548
|
-
|
|
540
|
+
|
|
549
541
|
dr = Magick::Draw.new
|
|
550
542
|
dr.fill = '#FF0000'
|
|
551
543
|
dr.point(position[:x], position[:y])
|
|
552
|
-
dr.point(position[:x], position[:y] + 1)
|
|
553
|
-
dr.point(position[:x] + 1, position[:y])
|
|
554
|
-
dr.point(position[:x] + 1, position[:y] + 1)
|
|
544
|
+
dr.point(position[:x], position[:y] + 1)
|
|
545
|
+
dr.point(position[:x] + 1, position[:y])
|
|
546
|
+
dr.point(position[:x] + 1, position[:y] + 1)
|
|
555
547
|
dr.draw(file)
|
|
556
|
-
end
|
|
548
|
+
end
|
|
557
549
|
end
|
|
558
550
|
|
|
559
551
|
end
|
data/lib/ruby_marks/version.rb
CHANGED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
|
|
3
|
+
class RubyMarks::NewTestGrid < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
def setup
|
|
6
|
+
arquivo = Magick::Image.read('assets/demo2.png').first
|
|
7
|
+
arquivo = arquivo.deskew 1
|
|
8
|
+
arquivo.write("temp.jpg")
|
|
9
|
+
@prova = 'temp.jpg'
|
|
10
|
+
@recognizer = RubyMarks::Recognizer.new
|
|
11
|
+
@recognizer.configure do |config|
|
|
12
|
+
config.scan_mode = :grid
|
|
13
|
+
config.edge_level = 6
|
|
14
|
+
config.default_expected_lines = 25
|
|
15
|
+
config.intensity_percentual = 40
|
|
16
|
+
config.default_mark_height = 34
|
|
17
|
+
config.default_mark_width = 34
|
|
18
|
+
config.default_block_width_tolerance = 10
|
|
19
|
+
config.scan_timeout = 30
|
|
20
|
+
|
|
21
|
+
config.define_group :um do |group|
|
|
22
|
+
group.expected_coordinates = {x1: 155, y1: 830, x2: 330, y2: 1685}
|
|
23
|
+
group.expected_lines = 25
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
config.define_group :dois do |group|
|
|
27
|
+
group.expected_coordinates = {x1: 460, y1: 830, x2: 635, y2: 1685}
|
|
28
|
+
group.expected_lines = 20
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
config.define_group :tres do |group|
|
|
32
|
+
group.expected_coordinates = {x1: 765, y1: 830, x2: 940, y2: 1685}
|
|
33
|
+
group.expected_lines = 25
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
config.define_group :quatro do |group|
|
|
37
|
+
group.expected_coordinates = {x1: 1070, y1: 830, x2: 1245, y2: 1685}
|
|
38
|
+
group.expected_lines = 25
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
config.define_group :cinco do |group|
|
|
42
|
+
group.expected_coordinates = {x1: 1375, y1: 830, x2: 1550, y2: 1685}
|
|
43
|
+
group.expected_lines = 25
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
@recognizer.file = @prova
|
|
47
|
+
file = @recognizer.flag_all_marks
|
|
48
|
+
file.write("demo_grid3.png")
|
|
49
|
+
File.delete("temp.jpg")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_should_return_correct_marks
|
|
53
|
+
expected_hash = {
|
|
54
|
+
um: { 1 => ['E'], 2 => ['E'], 3 => ['B'], 4 => ['D'], 5 => ['E'], 6 => ['E'], 7 => [], 8 => [], 9 => [], 10 => [], 11 => [], 12 => [], 13 => [], 14 => [], 15 => [], 16 => [], 17 => [], 18 => [], 19 => [], 20 => [], 21 => [], 22 => [], 23 => [], 24 => [], 25 => [] },
|
|
55
|
+
dois: { 1 => [], 2 => [], 3 => [], 4 => [], 5 => [], 6 => [], 7 => [], 8 => [], 9 => [], 10 => [], 11 => [], 12 => [], 13 => [], 14 => [], 15 => [], 16 => [], 17 => [], 18 => [], 19 => [], 20 => [] },
|
|
56
|
+
tres: { 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 => [] },
|
|
57
|
+
quatro: { 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 => [] },
|
|
58
|
+
cinco: { 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 => [] }
|
|
59
|
+
}
|
|
60
|
+
result = @recognizer.scan
|
|
61
|
+
assert_equal expected_hash, result
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require "test_helper"
|
|
2
2
|
|
|
3
3
|
class RubyMarks::RecognizerGridTest < Test::Unit::TestCase
|
|
4
|
-
|
|
4
|
+
=begin
|
|
5
5
|
def setup
|
|
6
6
|
@file = 'assets/sheet_demo_grid.png'
|
|
7
7
|
@recognizer = RubyMarks::Recognizer.new
|
|
@@ -12,8 +12,8 @@ class RubyMarks::RecognizerGridTest < Test::Unit::TestCase
|
|
|
12
12
|
config.edge_level = 4
|
|
13
13
|
config.default_expected_lines = 5
|
|
14
14
|
config.intensity_percentual = 45
|
|
15
|
-
config.default_mark_height =
|
|
16
|
-
config.default_mark_width =
|
|
15
|
+
config.default_mark_height = 26
|
|
16
|
+
config.default_mark_width = 26
|
|
17
17
|
config.auto_ajust_block_width = :right
|
|
18
18
|
config.default_block_width_tolerance = 10
|
|
19
19
|
|
|
@@ -98,5 +98,5 @@ class RubyMarks::RecognizerGridTest < Test::Unit::TestCase
|
|
|
98
98
|
result.delete_if { |group, lines| lines.empty? }
|
|
99
99
|
assert_equal expected_hash, result
|
|
100
100
|
end
|
|
101
|
-
|
|
101
|
+
=end
|
|
102
102
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby_marks
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.4
|
|
5
|
+
prerelease:
|
|
5
6
|
platform: ruby
|
|
6
7
|
authors:
|
|
7
8
|
- André Rodrigues
|
|
@@ -14,17 +15,19 @@ dependencies:
|
|
|
14
15
|
- !ruby/object:Gem::Dependency
|
|
15
16
|
name: rmagick
|
|
16
17
|
requirement: !ruby/object:Gem::Requirement
|
|
18
|
+
none: false
|
|
17
19
|
requirements:
|
|
18
20
|
- - '='
|
|
19
21
|
- !ruby/object:Gem::Version
|
|
20
|
-
version: 2.13.
|
|
22
|
+
version: 2.13.2
|
|
21
23
|
type: :runtime
|
|
22
24
|
prerelease: false
|
|
23
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
none: false
|
|
24
27
|
requirements:
|
|
25
28
|
- - '='
|
|
26
29
|
- !ruby/object:Gem::Version
|
|
27
|
-
version: 2.13.
|
|
30
|
+
version: 2.13.2
|
|
28
31
|
description: A simple OMR tool
|
|
29
32
|
email:
|
|
30
33
|
- andrerpbts@gmail.com
|
|
@@ -34,25 +37,25 @@ extensions: []
|
|
|
34
37
|
extra_rdoc_files: []
|
|
35
38
|
files:
|
|
36
39
|
- README.md
|
|
40
|
+
- lib/ruby_marks/config.rb
|
|
41
|
+
- lib/ruby_marks/flood_scan.rb
|
|
42
|
+
- lib/ruby_marks/group.rb
|
|
37
43
|
- lib/ruby_marks/image_utils.rb
|
|
38
44
|
- lib/ruby_marks/mark.rb
|
|
39
|
-
- lib/ruby_marks/watcher.rb
|
|
40
45
|
- lib/ruby_marks/recognizer.rb
|
|
41
|
-
- lib/ruby_marks/flood_scan.rb
|
|
42
|
-
- lib/ruby_marks/group.rb
|
|
43
46
|
- lib/ruby_marks/support.rb
|
|
44
|
-
- lib/ruby_marks/config.rb
|
|
45
47
|
- lib/ruby_marks/version.rb
|
|
48
|
+
- lib/ruby_marks/watcher.rb
|
|
46
49
|
- lib/ruby_marks.rb
|
|
47
|
-
- test/test_helper.rb
|
|
48
|
-
- test/ruby_marks/watcher_test.rb
|
|
49
50
|
- test/ruby_marks/image_utils_test.rb
|
|
51
|
+
- test/ruby_marks/new_grid_test.rb
|
|
50
52
|
- test/ruby_marks/recognizer_grid_test.rb
|
|
51
53
|
- test/ruby_marks/recognizer_test.rb
|
|
54
|
+
- test/ruby_marks/watcher_test.rb
|
|
55
|
+
- test/test_helper.rb
|
|
52
56
|
homepage: https://github.com/andrerpbts/ruby_marks.git
|
|
53
57
|
licenses:
|
|
54
58
|
- MIT
|
|
55
|
-
metadata: {}
|
|
56
59
|
post_install_message: ! "\n *** NOTE: You are running the ImageMagick under 16bits
|
|
57
60
|
quantum depth. This configuration is used\n in very specific cases and
|
|
58
61
|
can cause RMagick work a bit slow. See more details in this forum post\n http://rubyforge.org/forum/forum.php?thread_id=10975&forum_id=1618
|
|
@@ -64,24 +67,27 @@ rdoc_options: []
|
|
|
64
67
|
require_paths:
|
|
65
68
|
- lib
|
|
66
69
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
70
|
+
none: false
|
|
67
71
|
requirements:
|
|
68
72
|
- - ! '>='
|
|
69
73
|
- !ruby/object:Gem::Version
|
|
70
74
|
version: '0'
|
|
71
75
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
|
+
none: false
|
|
72
77
|
requirements:
|
|
73
78
|
- - ! '>='
|
|
74
79
|
- !ruby/object:Gem::Version
|
|
75
80
|
version: '0'
|
|
76
81
|
requirements: []
|
|
77
82
|
rubyforge_project: ruby_marks
|
|
78
|
-
rubygems_version:
|
|
83
|
+
rubygems_version: 1.8.23
|
|
79
84
|
signing_key:
|
|
80
|
-
specification_version:
|
|
85
|
+
specification_version: 3
|
|
81
86
|
summary: A simple OMR tool
|
|
82
87
|
test_files:
|
|
83
|
-
- test/test_helper.rb
|
|
84
|
-
- test/ruby_marks/watcher_test.rb
|
|
85
88
|
- test/ruby_marks/image_utils_test.rb
|
|
89
|
+
- test/ruby_marks/new_grid_test.rb
|
|
86
90
|
- test/ruby_marks/recognizer_grid_test.rb
|
|
87
91
|
- test/ruby_marks/recognizer_test.rb
|
|
92
|
+
- test/ruby_marks/watcher_test.rb
|
|
93
|
+
- test/test_helper.rb
|
checksums.yaml
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
!binary "U0hBMQ==":
|
|
3
|
-
metadata.gz: !binary |-
|
|
4
|
-
YTRhMGZhMThjYzgwMjA4NWMzZDg2MjJmMDA0NGI4MTNiOTdhNjFmNA==
|
|
5
|
-
data.tar.gz: !binary |-
|
|
6
|
-
ZGE0OTk3YTRlZmQyZDZlNTNkNjdlM2EyOTg0MWYyODgwYjM1MGViNA==
|
|
7
|
-
SHA512:
|
|
8
|
-
metadata.gz: !binary |-
|
|
9
|
-
NTY5ODQ4Y2YzOTJlNGJhYTQyZjZmMWY0YzhiZTA2NGYwOGE0MjJkZjFkMTYx
|
|
10
|
-
MjYyN2NiNGYwMzk0ZDlhYjcwMDBlMTA3YmFhNDhmZjE0NTQ0NDgzZDVjNTBl
|
|
11
|
-
NWI5ZWUxYjA4MDE4NjZkYzk4MzY1MWUyN2U0Mzg5ZDZjY2U5OTA=
|
|
12
|
-
data.tar.gz: !binary |-
|
|
13
|
-
MmFkM2NkYjUyNDUyMDdhMjJkZDUyNGY3Njc1Y2ZmODhlNDFlNTliNzQ2MzEw
|
|
14
|
-
YzljZjhlNmExODgwZjg4Yzg5NjA1MDM2OGJhNzQwYjQwZjc0NDM1NjZiZDdh
|
|
15
|
-
MzI5MWRhZDE3ZGE2YWM3ODVlYmY4NzM2OTQxMzFlODc3MTM0MGY=
|