ruby_marks 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/ruby_marks/version.rb
CHANGED
data/lib/ruby_marks.rb
CHANGED
@@ -5,26 +5,20 @@ require 'ruby_marks/support'
|
|
5
5
|
|
6
6
|
|
7
7
|
module RubyMarks
|
8
|
+
mattr_accessor :edge_level
|
9
|
+
@@edge_level = 4
|
10
|
+
|
8
11
|
mattr_accessor :threshold_level
|
9
12
|
@@threshold_level = 60
|
10
13
|
|
11
|
-
mattr_accessor :
|
12
|
-
@@
|
13
|
-
|
14
|
-
mattr_accessor :expected_clocks_count
|
15
|
-
@@expected_clocks_count = 0
|
16
|
-
|
17
|
-
mattr_accessor :clock_marks_scan_x
|
18
|
-
@@clock_marks_scan_x = 62
|
19
|
-
|
20
|
-
mattr_accessor :clock_width
|
21
|
-
@@clock_width = 26
|
14
|
+
mattr_accessor :adjust_inconsistent_bubbles
|
15
|
+
@@adjust_inconsistent_bubbles = true
|
22
16
|
|
23
|
-
mattr_accessor :
|
24
|
-
@@
|
17
|
+
mattr_accessor :default_mark_width_tolerance
|
18
|
+
@@default_mark_width_tolerance = 4
|
25
19
|
|
26
|
-
mattr_accessor :
|
27
|
-
@@
|
20
|
+
mattr_accessor :default_mark_height_tolerance
|
21
|
+
@@default_mark_height_tolerance = 4
|
28
22
|
|
29
23
|
mattr_accessor :default_mark_width
|
30
24
|
@@default_mark_width = 20
|
@@ -41,20 +35,35 @@ module RubyMarks
|
|
41
35
|
mattr_accessor :default_distance_between_marks
|
42
36
|
@@default_distance_between_marks = 25
|
43
37
|
|
44
|
-
|
45
|
-
|
38
|
+
mattr_accessor :default_expected_lines
|
39
|
+
@@default_expected_lines = 20
|
40
|
+
|
41
|
+
COLORS = %w{ #d80000
|
42
|
+
#00d8d8
|
43
|
+
#d8006c
|
44
|
+
#d86c00
|
45
|
+
#006cd8
|
46
|
+
#00d86c
|
47
|
+
#d8d800
|
48
|
+
#00d86c
|
49
|
+
#6c00d8
|
50
|
+
#a5a500
|
51
|
+
#a27b18
|
52
|
+
#18a236
|
53
|
+
#df4f27 }
|
46
54
|
|
47
55
|
AVAILABLE_WATCHERS = [
|
48
56
|
:scan_mark_watcher,
|
49
57
|
:scan_unmarked_watcher,
|
50
58
|
:scan_multiple_marked_watcher,
|
51
|
-
:
|
59
|
+
:incorrect_group_watcher
|
52
60
|
]
|
53
61
|
end
|
54
62
|
|
55
|
-
require 'ruby_marks/clock_mark'
|
56
63
|
require 'ruby_marks/config'
|
57
64
|
require 'ruby_marks/group'
|
58
65
|
require 'ruby_marks/image_utils'
|
66
|
+
require 'ruby_marks/mark'
|
59
67
|
require 'ruby_marks/recognizer'
|
68
|
+
require 'ruby_marks/scan_area'
|
60
69
|
require 'ruby_marks/watcher'
|
@@ -1,7 +1,23 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class RubyMarks::ImageUtilsTest < Test::Unit::TestCase
|
4
|
-
|
4
|
+
|
5
|
+
def test_should_calculate_the_correct_width_of_given_coordinates
|
6
|
+
assert_equal 11, RubyMarks::ImageUtils.calc_width(10, 20)
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_should_calculate_the_correct_height_of_given_coordinates
|
10
|
+
assert_equal 11, RubyMarks::ImageUtils.calc_height(10, 20)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_calculate_the_correct_middle_horizontal_of_given_coordinates
|
14
|
+
assert_equal 15, RubyMarks::ImageUtils.calc_middle_horizontal(10, 11)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_should_calculate_the_correct_middle_vertical_of_given_coordinates
|
18
|
+
assert_equal 15, RubyMarks::ImageUtils.calc_middle_vertical(10, 11)
|
19
|
+
end
|
20
|
+
|
5
21
|
def test_should_return_the_white_color_in_hexa_receiving_8bits
|
6
22
|
color = RubyMarks::ImageUtils.to_hex(255, 255, 255)
|
7
23
|
assert_equal "#FFFFFF", color
|
@@ -8,38 +8,37 @@ class RubyMarks::RecognizerTest < Test::Unit::TestCase
|
|
8
8
|
@positions = {}
|
9
9
|
@positions[:marked_position] = {x: 161, y: 794}
|
10
10
|
@positions[:unmarked_position] = {x: 161, y: 994}
|
11
|
-
@positions[:first_clock_position] = {x: 62, y: 794}
|
12
|
-
@positions[:invalid_clock] = {x: 62, y: 1032}
|
13
11
|
|
14
|
-
@recognizer.configure do |config|
|
15
|
-
config.expected_clocks_count = 20
|
12
|
+
@recognizer.configure do |config|
|
16
13
|
config.define_group :first do |group|
|
17
|
-
group.
|
18
|
-
group.x_distance_from_clock = 87
|
14
|
+
group.expected_coordinates = {x1: 145, y1: 780, x2: 270, y2: 1290}
|
19
15
|
end
|
20
16
|
|
21
17
|
config.define_group :second do |group|
|
22
|
-
group.
|
23
|
-
group.x_distance_from_clock = 310
|
18
|
+
group.expected_coordinates = {x1: 370, y1: 780, x2: 500, y2: 1290}
|
24
19
|
end
|
25
20
|
|
26
21
|
config.define_group :third do |group|
|
27
|
-
group.
|
28
|
-
group.x_distance_from_clock = 535
|
22
|
+
group.expected_coordinates = {x1: 595, y1: 780, x2: 720, y2: 1290}
|
29
23
|
end
|
30
24
|
|
31
25
|
config.define_group :fourth do |group|
|
32
|
-
group.
|
33
|
-
group.x_distance_from_clock = 760
|
26
|
+
group.expected_coordinates = {x1: 820, y1: 780, x2: 950, y2: 1290}
|
34
27
|
end
|
35
28
|
|
36
29
|
config.define_group :fifth do |group|
|
37
|
-
group.
|
38
|
-
group.x_distance_from_clock = 985
|
30
|
+
group.expected_coordinates = {x1: 1045, y1: 780, x2: 1170, y2: 1290}
|
39
31
|
end
|
32
|
+
|
40
33
|
end
|
41
34
|
|
42
35
|
@recognizer.file = @file
|
36
|
+
|
37
|
+
# file = @recognizer.file
|
38
|
+
# temp_filename = "ttemp_sheet_demo1.png"
|
39
|
+
# File.delete(temp_filename) if File.exist?(temp_filename)
|
40
|
+
# file.write(temp_filename)
|
41
|
+
|
43
42
|
end
|
44
43
|
|
45
44
|
def test_should_initialize_a_recognizer_with_a_valid_file
|
@@ -48,9 +47,9 @@ class RubyMarks::RecognizerTest < Test::Unit::TestCase
|
|
48
47
|
|
49
48
|
def test_should_pass_the_configuration_to_recognizer_config
|
50
49
|
@recognizer.configure do |config|
|
51
|
-
config.
|
50
|
+
config.threshold_level = 70
|
52
51
|
end
|
53
|
-
assert_equal
|
52
|
+
assert_equal 70, @recognizer.config.threshold_level
|
54
53
|
end
|
55
54
|
|
56
55
|
def test_should_get_the_default_configuration_of_config_in_group
|
@@ -74,8 +73,7 @@ class RubyMarks::RecognizerTest < Test::Unit::TestCase
|
|
74
73
|
|
75
74
|
|
76
75
|
def test_should_return_a_file_with_a_position_flagged
|
77
|
-
@recognizer.
|
78
|
-
flagged_document = @recognizer.flag_position
|
76
|
+
flagged_document = @recognizer.flag_position @positions[:marked_position]
|
79
77
|
assert_equal Magick::Image, flagged_document.class
|
80
78
|
|
81
79
|
# temp_filename = "temp_sheet_demo1.png"
|
@@ -84,19 +82,21 @@ class RubyMarks::RecognizerTest < Test::Unit::TestCase
|
|
84
82
|
end
|
85
83
|
|
86
84
|
def test_should_recognize_marked_position
|
87
|
-
@recognizer.
|
88
|
-
|
85
|
+
@recognizer.detect_groups
|
86
|
+
group = @recognizer.groups[:first]
|
87
|
+
line = group.marks[1]
|
88
|
+
mark = line.first
|
89
|
+
assert mark.marked?, "The position wasn't recognized as marked"
|
89
90
|
end
|
90
91
|
|
91
92
|
def test_should_recognize_not_marked_position
|
92
|
-
@recognizer.
|
93
|
-
|
93
|
+
@recognizer.detect_groups
|
94
|
+
group = @recognizer.groups[:first]
|
95
|
+
line = group.marks[2]
|
96
|
+
mark = line.first
|
97
|
+
assert mark.unmarked?, "The position wasn't recognized as unmarked"
|
94
98
|
end
|
95
99
|
|
96
|
-
def test_should_recognize_the_recognizer_clock_marks
|
97
|
-
@recognizer.scan_clock_marks
|
98
|
-
assert_equal 20, @recognizer.clock_marks.count
|
99
|
-
end
|
100
100
|
|
101
101
|
def test_should_return_the_recognizer_with_all_marks_flagged
|
102
102
|
flagged_recognizer = @recognizer.flag_all_marks
|
@@ -107,47 +107,43 @@ class RubyMarks::RecognizerTest < Test::Unit::TestCase
|
|
107
107
|
flagged_recognizer.write(temp_filename)
|
108
108
|
end
|
109
109
|
|
110
|
-
def test_should_move_the_current_position_in_10_and_20_pixels
|
111
|
-
@recognizer.current_position = @positions[:marked_position]
|
112
|
-
expected_position = {x: 171, y: 814}
|
113
|
-
|
114
|
-
assert_equal expected_position, @recognizer.move_to(10, 20)
|
115
|
-
end
|
116
110
|
|
117
111
|
def test_should_scan_the_recognizer_and_get_a_hash_of_marked_marks
|
118
112
|
expected_hash = {
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
group_second: ['B'],
|
126
|
-
group_third: ['B']
|
113
|
+
first: {
|
114
|
+
1 => ['A'],
|
115
|
+
2 => ['B'],
|
116
|
+
3 => ['C'],
|
117
|
+
4 => ['D'],
|
118
|
+
5 => ['E']
|
127
119
|
},
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
120
|
+
second: {
|
121
|
+
1 => ['A'],
|
122
|
+
2 => ['B'],
|
123
|
+
3 => ['C'],
|
124
|
+
4 => ['D'],
|
125
|
+
5 => ['E']
|
132
126
|
},
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
},
|
138
|
-
clock_5: {
|
139
|
-
group_first: ['E'],
|
140
|
-
group_second: ['E']
|
127
|
+
third: {
|
128
|
+
2 => ['B'],
|
129
|
+
3 => ['D'],
|
130
|
+
4 => ['D']
|
141
131
|
}
|
142
132
|
}
|
143
133
|
assert_equal expected_hash, @recognizer.scan
|
144
134
|
end
|
145
135
|
|
146
|
-
|
147
|
-
|
136
|
+
|
137
|
+
def test_should_make_watcher_raise_up
|
138
|
+
@file = 'assets/sheet_demo1_invalid.png'
|
139
|
+
@recognizer.file = @file
|
140
|
+
|
141
|
+
@recognizer.add_watcher :incorrect_group_watcher
|
148
142
|
|
149
143
|
@recognizer.scan
|
150
|
-
assert @recognizer.raised_watchers.include?(:
|
144
|
+
assert @recognizer.raised_watchers.include?(:incorrect_group_watcher)
|
151
145
|
end
|
146
|
+
|
147
|
+
|
152
148
|
end
|
153
149
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_marks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -37,17 +37,16 @@ extensions: []
|
|
37
37
|
extra_rdoc_files: []
|
38
38
|
files:
|
39
39
|
- README.md
|
40
|
-
- lib/ruby_marks/clock_mark.rb
|
41
40
|
- lib/ruby_marks/config.rb
|
42
41
|
- lib/ruby_marks/group.rb
|
43
42
|
- lib/ruby_marks/image_utils.rb
|
43
|
+
- lib/ruby_marks/mark.rb
|
44
44
|
- lib/ruby_marks/recognizer.rb
|
45
|
+
- lib/ruby_marks/scan_area.rb
|
45
46
|
- lib/ruby_marks/support.rb
|
46
47
|
- lib/ruby_marks/version.rb
|
47
48
|
- lib/ruby_marks/watcher.rb
|
48
49
|
- lib/ruby_marks.rb
|
49
|
-
- test/ruby_marks/clock_mark_test.rb
|
50
|
-
- test/ruby_marks/group_test.rb
|
51
50
|
- test/ruby_marks/image_utils_test.rb
|
52
51
|
- test/ruby_marks/recognizer_test.rb
|
53
52
|
- test/ruby_marks/watcher_test.rb
|
@@ -55,10 +54,13 @@ files:
|
|
55
54
|
homepage: https://github.com/andrerpbts/ruby_marks.git
|
56
55
|
licenses:
|
57
56
|
- MIT
|
58
|
-
post_install_message: ! "\n ***
|
59
|
-
|
60
|
-
|
61
|
-
***\n
|
57
|
+
post_install_message: ! "\n *** NOTE: You are running the ImageMagick under 16bits
|
58
|
+
quantum depth. This configuration is used\n in very specific cases and
|
59
|
+
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
|
60
|
+
***\n\n We changed the way it recognizes the marks. It's not based on clocks
|
61
|
+
anymore. If you are updating the gem \n from 0.1.4 version, you should refactor
|
62
|
+
your code to eliminate the clocks parameters and adjust \n some new configurations.
|
63
|
+
More information can be obtained on README file.\n "
|
62
64
|
rdoc_options: []
|
63
65
|
require_paths:
|
64
66
|
- lib
|
@@ -81,8 +83,6 @@ signing_key:
|
|
81
83
|
specification_version: 3
|
82
84
|
summary: A simple OMR tool
|
83
85
|
test_files:
|
84
|
-
- test/ruby_marks/clock_mark_test.rb
|
85
|
-
- test/ruby_marks/group_test.rb
|
86
86
|
- test/ruby_marks/image_utils_test.rb
|
87
87
|
- test/ruby_marks/recognizer_test.rb
|
88
88
|
- test/ruby_marks/watcher_test.rb
|
@@ -1,65 +0,0 @@
|
|
1
|
-
#encoding: utf-8
|
2
|
-
module RubyMarks
|
3
|
-
|
4
|
-
class ClockMark
|
5
|
-
|
6
|
-
attr_accessor :recognizer, :coordinates
|
7
|
-
|
8
|
-
def initialize(params={})
|
9
|
-
params.each do |k, v|
|
10
|
-
self.send("#{k}=", v) if self.respond_to?("#{k}=")
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def valid?
|
15
|
-
|
16
|
-
return false if !self.recognizer.config.clock_width_tolerance_range.include?(self.width) ||
|
17
|
-
!self.recognizer.config.clock_height_tolerance_range.include?(self.height)
|
18
|
-
|
19
|
-
|
20
|
-
self.recognizer.export_file_to_str if self.recognizer.file_str.nil?
|
21
|
-
|
22
|
-
x_pos = coordinates[:x1]..coordinates[:x2]
|
23
|
-
y_pos = coordinates[:y1]..coordinates[:y2]
|
24
|
-
|
25
|
-
colors = []
|
26
|
-
|
27
|
-
y_pos.each do |y|
|
28
|
-
x_pos.each do |x|
|
29
|
-
|
30
|
-
color = self.recognizer.file_str[y][x]
|
31
|
-
|
32
|
-
colors << color
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
intensity = colors.count(".") * 100 / colors.size
|
37
|
-
return intensity >= 70 ? true : false
|
38
|
-
end
|
39
|
-
|
40
|
-
def invalid?
|
41
|
-
!valid?
|
42
|
-
end
|
43
|
-
|
44
|
-
def width
|
45
|
-
RubyMarks::ImageUtils.calc_width(@coordinates[:x1], @coordinates[:x2])
|
46
|
-
end
|
47
|
-
|
48
|
-
def height
|
49
|
-
RubyMarks::ImageUtils.calc_height(@coordinates[:y1], @coordinates[:y2])
|
50
|
-
end
|
51
|
-
|
52
|
-
def horizontal_middle_position
|
53
|
-
RubyMarks::ImageUtils.calc_middle_horizontal(@coordinates[:x1], self.width)
|
54
|
-
end
|
55
|
-
|
56
|
-
def vertical_middle_position
|
57
|
-
RubyMarks::ImageUtils.calc_middle_vertical(@coordinates[:y1], self.height)
|
58
|
-
end
|
59
|
-
|
60
|
-
def to_s
|
61
|
-
self.coordinates
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
65
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class RubyMarks::ClockMarkTest < Test::Unit::TestCase
|
4
|
-
|
5
|
-
def setup
|
6
|
-
@file = 'assets/sheet_demo1.png'
|
7
|
-
@recognizer = RubyMarks::Recognizer.new
|
8
|
-
@recognizer.file = @file
|
9
|
-
@positions = {}
|
10
|
-
@positions[:first_clock_position] = {x1: 49, x2: 74, y1: 790, y2: 801}
|
11
|
-
@positions[:not_a_clock] = {x1: 62, x2: 63, y1: 859, y2: 860}
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_should_obtain_the_clock_mark_width
|
15
|
-
clock = RubyMarks::ClockMark.new(recognizer: @recognizer, coordinates: @positions[:first_clock_position])
|
16
|
-
assert_equal 26, clock.width
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_should_obtain_the_clock_mark_height
|
20
|
-
clock = RubyMarks::ClockMark.new(recognizer: @recognizer, coordinates: @positions[:first_clock_position])
|
21
|
-
assert_equal 12, clock.height
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_should_obtain_the_horizontal_middle_position
|
25
|
-
clock = RubyMarks::ClockMark.new(recognizer: @recognizer, coordinates: @positions[:first_clock_position])
|
26
|
-
assert_equal 62, clock.horizontal_middle_position
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_should_obtain_the_vertical_middle_position
|
30
|
-
clock = RubyMarks::ClockMark.new(recognizer: @recognizer, coordinates: @positions[:first_clock_position])
|
31
|
-
assert_equal 796, clock.vertical_middle_position
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_should_recognize_a_valid_clock
|
35
|
-
clock = RubyMarks::ClockMark.new(recognizer: @recognizer, coordinates: @positions[:first_clock_position])
|
36
|
-
assert clock.valid?, "Not recognized a valid clock"
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_should_recognize_a_invalid_clock
|
40
|
-
clock = RubyMarks::ClockMark.new(recognizer: @recognizer, coordinates: @positions[:not_a_clock])
|
41
|
-
assert clock.invalid?, "Recognized a invalid clock as a valid one"
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class RubyMarks::GroupTest < Test::Unit::TestCase
|
4
|
-
|
5
|
-
def setup
|
6
|
-
@file = 'assets/sheet_demo1.png'
|
7
|
-
@recognizer = RubyMarks::Recognizer.new
|
8
|
-
@recognizer.file = @file
|
9
|
-
@group = RubyMarks::Group.new(:test, @recognizer)
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_should_convert_fixnum_into_range_in_clocks_range
|
13
|
-
@group.clocks_range = 1
|
14
|
-
assert_equal 1..1, @group.clocks_range
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_should_return_that_group_belongs_to_a_clock
|
18
|
-
@group.clocks_range = 1..10
|
19
|
-
assert @group.belongs_to_clock?(1), "Not recognized that group belongs to group 1"
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_should_not_return_that_group_belongs_to_a_clock
|
23
|
-
@group.clocks_range = 1..10
|
24
|
-
assert !@group.belongs_to_clock?(11), "Recognized that group belongs to group 11"
|
25
|
-
end
|
26
|
-
end
|