ruby_marks 0.1.2 → 0.1.3
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 +402 -0
- data/lib/ruby_marks/recognizer.rb +6 -1
- data/lib/ruby_marks/version.rb +1 -1
- metadata +3 -3
- data/README.rdoc +0 -4
data/README.md
ADDED
@@ -0,0 +1,402 @@
|
|
1
|
+
Ruby Marks
|
2
|
+
==========
|
3
|
+
|
4
|
+
[](http://travis-ci.org/andrerpbts/ruby_marks)
|
5
|
+
|
6
|
+
A simple OMR ([Optical Mark Recognition](http://en.wikipedia.org/wiki/Optical_mark_recognition)) gem for ruby 1.9.x.
|
7
|
+
|
8
|
+
|
9
|
+
Requirements
|
10
|
+
------------
|
11
|
+
|
12
|
+
This gem uses [ImageMagick](http://www.imagemagick.org) to manipulate the given images.
|
13
|
+
You can verify if this utility is installed by the command line `which convert`, which should return
|
14
|
+
the current ImageMagick path.
|
15
|
+
|
16
|
+
For example, `/usr/local/bin/convert`.
|
17
|
+
|
18
|
+
If not installed:
|
19
|
+
|
20
|
+
### MacOS X
|
21
|
+
|
22
|
+
If you're on Mac OS X, Homebrew may be your best option:
|
23
|
+
|
24
|
+
brew install imagemagick
|
25
|
+
|
26
|
+
|
27
|
+
### Ubuntu
|
28
|
+
|
29
|
+
On Ubuntu, the `apt-get` should be enough:
|
30
|
+
|
31
|
+
apt-get install imagemagick
|
32
|
+
|
33
|
+
|
34
|
+
Supported versions
|
35
|
+
------------------
|
36
|
+
|
37
|
+
* Ruby 1.9.2
|
38
|
+
* Ruby 1.9.3
|
39
|
+
|
40
|
+
|
41
|
+
Install
|
42
|
+
-------
|
43
|
+
|
44
|
+
If you are using `Bundler`, just put this line in your Gemfile:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
gem 'ruby_marks'
|
48
|
+
```
|
49
|
+
|
50
|
+
Then run bundle install command:
|
51
|
+
|
52
|
+
bundle
|
53
|
+
|
54
|
+
If not, you still can run a default gem installation method:
|
55
|
+
|
56
|
+
gem install ruby_marks
|
57
|
+
|
58
|
+
And require it in your ruby code:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
require 'ruby_marks'
|
62
|
+
```
|
63
|
+
|
64
|
+
|
65
|
+
How it Works
|
66
|
+
------------
|
67
|
+
|
68
|
+
The gem will scan a document column search for this small full-filled black rectangles **(clock marks)**.
|
69
|
+
For each clock mark found, it will perform a line scan in each group looking for a marked position.
|
70
|
+
In the end, returns a hash with each correspondent mark found in the group and the clock.
|
71
|
+
|
72
|
+
The gem will not perform deskew in your documents. If the document have skew, then you should apply your own
|
73
|
+
deskew method on the file before.
|
74
|
+
|
75
|
+
|
76
|
+
Usage
|
77
|
+
-----
|
78
|
+
|
79
|
+
Unfortunatelly, this gem will require a bit more configuration to work, since the implementation depends
|
80
|
+
a lot of your document sizes, positions, brightness, etc...
|
81
|
+
|
82
|
+
That said, lets describe it's basic structure. The example will assume a directory with some png images like this one:
|
83
|
+
|
84
|
+
[](https://github.com/andrerpbts/ruby_marks/blob/master/assets/sheet_demo2.png)
|
85
|
+
|
86
|
+
Then, we write a basic code to scan it and print result on console:
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
recognizer = RubyMarks::Recognizer.new
|
90
|
+
recognizer.configure do |config|
|
91
|
+
|
92
|
+
config.clock_marks_scan_x = 42
|
93
|
+
config.clock_width = 29
|
94
|
+
config.clock_height = 12
|
95
|
+
|
96
|
+
config.define_group :one do |group|
|
97
|
+
group.clocks_range = 1..5
|
98
|
+
group.x_distance_from_clock = 89
|
99
|
+
end
|
100
|
+
|
101
|
+
config.define_group :two do |group|
|
102
|
+
group.clocks_range = 1..5
|
103
|
+
group.x_distance_from_clock = 315
|
104
|
+
end
|
105
|
+
|
106
|
+
config.define_group :three do |group|
|
107
|
+
group.clocks_range = 1..5
|
108
|
+
group.x_distance_from_clock = 542
|
109
|
+
end
|
110
|
+
|
111
|
+
config.define_group :four do |group|
|
112
|
+
group.clocks_range = 1..5
|
113
|
+
group.x_distance_from_clock = 769
|
114
|
+
end
|
115
|
+
|
116
|
+
config.define_group :five do |group|
|
117
|
+
group.clocks_range = 1..5
|
118
|
+
group.x_distance_from_clock = 996
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
Dir["./*.png"].each do |file|
|
123
|
+
recognizer.file = file
|
124
|
+
puts recognizer.scan
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
This should puts each scan in a hash, like this:
|
129
|
+
|
130
|
+
```
|
131
|
+
{
|
132
|
+
:clock_1 => {
|
133
|
+
:group_one => ['A'],
|
134
|
+
:group_two => ['E'],
|
135
|
+
:group_three => ['B'],
|
136
|
+
:group_four => ['B'],
|
137
|
+
:group_five => ['B']
|
138
|
+
},
|
139
|
+
:clock_2 => {
|
140
|
+
:group_one => ['C'],
|
141
|
+
:group_two => ['A'],
|
142
|
+
:group_three => ['B'],
|
143
|
+
:group_four => ['E'],
|
144
|
+
:group_five => ['A']
|
145
|
+
},
|
146
|
+
:clock_3 => {
|
147
|
+
:group_one => ['B'],
|
148
|
+
:group_two => ['B'],
|
149
|
+
:group_three => ['D'],
|
150
|
+
:group_four => ['A'],
|
151
|
+
:group_five => ['A']
|
152
|
+
},
|
153
|
+
:clock_4 => {
|
154
|
+
:group_one => ['B'],
|
155
|
+
:group_two => ['A'],
|
156
|
+
:group_three => ['B'],
|
157
|
+
:group_four => ['C'],
|
158
|
+
:group_five => ['C']
|
159
|
+
},
|
160
|
+
:clock_5 => {
|
161
|
+
:group_one => ['D'],
|
162
|
+
:group_two => ['B'],
|
163
|
+
:group_three => ['B'],
|
164
|
+
:group_four => ['D'],
|
165
|
+
:group_five => ['D']
|
166
|
+
}
|
167
|
+
}
|
168
|
+
```
|
169
|
+
|
170
|
+
|
171
|
+
General Configuration Options
|
172
|
+
-----------------------------
|
173
|
+
|
174
|
+
As you may see, it's necessary configure some document aspects to make this work properly. So, lets describe
|
175
|
+
each general configuration option available:
|
176
|
+
|
177
|
+
### Threshold level
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
# Applies the given percentual in the image in order to get it back with only black and white pixels.
|
181
|
+
# Low percentuals will result in a bright image, as High percentuals will result in a more darken image.
|
182
|
+
# The default value is 60
|
183
|
+
|
184
|
+
config.threshold_level = 60
|
185
|
+
```
|
186
|
+
|
187
|
+
### Distance in axis X from margin to scan the clock marks
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
# Defines the X distance from the left margin (in pixels) to look for the valids (black) pixels
|
191
|
+
# of the clock marks in this column. This configuration is very important because each type of document may
|
192
|
+
# have the clock marks in a specific and different column, and this configuration that will indicate
|
193
|
+
# a X pixel column that cross all the clocks.
|
194
|
+
# The default value is 62 but only for tests purposes. You SHOULD calculate this value and set
|
195
|
+
# a new one.
|
196
|
+
|
197
|
+
config.clock_marks_scan_x = 62
|
198
|
+
```
|
199
|
+
|
200
|
+
### Clock sizes
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
# Defines the expected width and height of clock marks (in pixels). With the tolerance, if the first
|
204
|
+
# recognized clock exceeds or stricts those values, it will be ignored...
|
205
|
+
# The default values is 26 to width and 12 to height. Since the clock marks can be different, you SHOULD
|
206
|
+
# calculate those sizes for your documents.
|
207
|
+
|
208
|
+
config.clock_width = 26
|
209
|
+
config.clock_height = 12
|
210
|
+
```
|
211
|
+
|
212
|
+
### Tolerance on the size of clock mark
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
# Indicates the actual tolerance (in pixels) for the clock mark found. That means the clock can be smaller or
|
216
|
+
# larger than expected, by the number of pixels set in this option.
|
217
|
+
# The default value is 2
|
218
|
+
|
219
|
+
config.clock_mark_size_tolerance = 2
|
220
|
+
```
|
221
|
+
|
222
|
+
### Expected clocks count
|
223
|
+
|
224
|
+
```ruby
|
225
|
+
# If this value is defined (above 0), the scan will perform a check if the clocks found on document
|
226
|
+
# is identical with this expected number. If different, the scan will be stopped.
|
227
|
+
# This config is mandatory if you want to raise the Clock Mark Difference Watcher.
|
228
|
+
# The default value is 0
|
229
|
+
|
230
|
+
config.expected_clocks_count = 0
|
231
|
+
```
|
232
|
+
|
233
|
+
### Default mark sizes
|
234
|
+
|
235
|
+
```ruby
|
236
|
+
# Defines the expected width and height of the marks (in pixels). With the tolerance, if the first recognized
|
237
|
+
# mark exceeds or stricts those values, it will be ignored.
|
238
|
+
# The default values is 20 to width and 20 to height. Since the marks can be different, you SHOULD
|
239
|
+
# calculate those sizes for your documents.
|
240
|
+
|
241
|
+
config.default_mark_width = 20
|
242
|
+
config.default_mark_height = 20
|
243
|
+
```
|
244
|
+
|
245
|
+
### Intensity percentual
|
246
|
+
|
247
|
+
```ruby
|
248
|
+
# Set the intensity sensitivity (in percentual) expected to recognize a mark as a marked one.
|
249
|
+
# When the scan find some potential marked area, then it will analyse if the count of valid pixels (black pixels)
|
250
|
+
# have this minimun percentage.
|
251
|
+
# Increasing this value, the recognition becomes more sensitive and can ignore valid weaker markings.
|
252
|
+
# Decreasing this value, recognition becomes less sensitive and can recognize false markings.
|
253
|
+
# The default value is 50.
|
254
|
+
|
255
|
+
config.intensity_percentual = 50
|
256
|
+
```
|
257
|
+
|
258
|
+
### Default marks options
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
# Set the marks options that the groups represents. When the scan recognizes a mark in some position,
|
262
|
+
# it will return they value in the result hash.
|
263
|
+
# The default value is the [A, B, C, D, E] array.
|
264
|
+
|
265
|
+
config.default_marks_options = %w{A B C D E}
|
266
|
+
```
|
267
|
+
|
268
|
+
### Default distance between each mark in group
|
269
|
+
|
270
|
+
```ruby
|
271
|
+
# Defines the distance (in pixel) between the middle of a mark and the middle of the next mark in the same group.
|
272
|
+
# The scan will begin in the first mark, by the value in pixels it have from the right corner of the clock.
|
273
|
+
# After it, each mark option in the group will be checked based in this distance.
|
274
|
+
# The default value is 25
|
275
|
+
|
276
|
+
config.default_distance_between_marks = 25
|
277
|
+
```
|
278
|
+
|
279
|
+
|
280
|
+
Group Configuration Options
|
281
|
+
---------------------------
|
282
|
+
|
283
|
+
The General Configuration Options is more generic for the entire document. So, you can have some particularities
|
284
|
+
when defining a group. So:
|
285
|
+
|
286
|
+
### Mark sizes
|
287
|
+
|
288
|
+
```ruby
|
289
|
+
# It overwrites the default_mark_width and default_mark_height values for the group you configure it.
|
290
|
+
|
291
|
+
group.mark_width = RubyMarks.default_mark_width
|
292
|
+
group.mark_height = RubyMarks.default_mark_height
|
293
|
+
```
|
294
|
+
|
295
|
+
### Marks options
|
296
|
+
|
297
|
+
```ruby
|
298
|
+
# It overwrites the default_marks_options values for the group you configure it.
|
299
|
+
|
300
|
+
group.marks_options = RubyMarks.default_marks_options
|
301
|
+
```
|
302
|
+
|
303
|
+
### Distance in axis X from clock
|
304
|
+
|
305
|
+
```ruby
|
306
|
+
# Defines the distance from the right corner of the clock mark to the middle of the first mark in the group
|
307
|
+
# It don't have a default value, you MUST set this value for each group in your document
|
308
|
+
|
309
|
+
group.x_distance_from_clock = 89
|
310
|
+
```
|
311
|
+
|
312
|
+
### Distance Between Marks
|
313
|
+
|
314
|
+
```ruby
|
315
|
+
# It overwrites the default_distance_between_marks values for the group you configure it.
|
316
|
+
|
317
|
+
group.distance_between_marks = RubyMarks.default_distance_between_marks
|
318
|
+
```
|
319
|
+
|
320
|
+
### Clocks range
|
321
|
+
|
322
|
+
```ruby
|
323
|
+
# Defines the clock ranges this group belongs to. This range that will consider what clock mark
|
324
|
+
# should be returned in the result of the scan.
|
325
|
+
|
326
|
+
group.clocks_range = 1..5
|
327
|
+
```
|
328
|
+
|
329
|
+
|
330
|
+
Watchers
|
331
|
+
--------
|
332
|
+
|
333
|
+
Sometimes, due some image flaws, the scan can't recognize some clock mark, or a mark, or even recognize
|
334
|
+
more than one mark in a clock row in the same group when it is not expected. Then, you can place some
|
335
|
+
watchers, that will perform some custom code made by yourself in those cases. The available watchers are:
|
336
|
+
In the watchers you can, for example, apply a deskew in image and re-run the scan. But, be advised, if you
|
337
|
+
call the scan method again inside the watcher, you should make sure that you have a way to leave the watcher
|
338
|
+
to avoid a endless loop. You always can check how many times the watcher got raised by checking in
|
339
|
+
`recognizer.raised_watchers[:watcher_name]` hash.
|
340
|
+
|
341
|
+
|
342
|
+
### Scan Mark Watcher
|
343
|
+
|
344
|
+
```ruby
|
345
|
+
# Will execute your custom code if didn't recognizes some mark or recognizes more than one mark in a clock
|
346
|
+
# row and the same group.
|
347
|
+
# It returns the recognizer object, the result of scan hash, a boolean value if this watcher was raised by unmarked
|
348
|
+
# options and a boolean value if the watcher was raised by a multiple marks options
|
349
|
+
|
350
|
+
recognizer.add_watcher :scan_mark_watcher do |recognizer, result, unmarked_group_found, multiple_marked_found|
|
351
|
+
# place your custom code
|
352
|
+
end
|
353
|
+
```
|
354
|
+
|
355
|
+
### Scan Unmarked Watcher
|
356
|
+
|
357
|
+
```ruby
|
358
|
+
# Will execute your custom code if didn't recognizes some mark.
|
359
|
+
# It returns the recognizer object, the result of scan hash.
|
360
|
+
|
361
|
+
recognizer.add_watcher :scan_unmarked_watcher do |recognizer, result|
|
362
|
+
# place your custom code
|
363
|
+
end
|
364
|
+
```
|
365
|
+
|
366
|
+
### Scan Multiple Marked Watcher
|
367
|
+
|
368
|
+
```ruby
|
369
|
+
# Will execute your custom code if recognizes more than one mark in a clock row and the same group.
|
370
|
+
# It returns the recognizer object, the result of scan hash.
|
371
|
+
|
372
|
+
recognizer.add_watcher :scan_multiple_marked_watcher do |recognizer, result|
|
373
|
+
# place your custom code
|
374
|
+
end
|
375
|
+
```
|
376
|
+
|
377
|
+
### Clock Mark Difference Watcher
|
378
|
+
|
379
|
+
```ruby
|
380
|
+
# Will execute your custom code if didn't recognizes your expected clock marks count.
|
381
|
+
# In order to raise this watcher you must define the `config.expected_clocks_count`.
|
382
|
+
# It returns the recognizer object.
|
383
|
+
|
384
|
+
recognizer.add_watcher :clock_mark_difference_watcher do |recognizer|
|
385
|
+
# place your custom code
|
386
|
+
end
|
387
|
+
```
|
388
|
+
|
389
|
+
Contributing
|
390
|
+
------------
|
391
|
+
|
392
|
+
* Fork it
|
393
|
+
* Make your implementations
|
394
|
+
* Send me a pull request
|
395
|
+
|
396
|
+
Thank you!
|
397
|
+
|
398
|
+
|
399
|
+
License
|
400
|
+
-------
|
401
|
+
|
402
|
+
Copyright © 2012 André Rodrigues, Ronaldo Araújo, Rodrigo Virgilio, Lucas Correa. See MIT-LICENSE for further details.
|
@@ -216,7 +216,12 @@ module RubyMarks
|
|
216
216
|
|
217
217
|
file.tap do |file|
|
218
218
|
position_before = @current_position
|
219
|
-
|
219
|
+
|
220
|
+
dr = Magick::Draw.new
|
221
|
+
dr.fill(RubyMarks::COLORS[4])
|
222
|
+
dr.line(@config.clock_marks_scan_x, 0, @config.clock_marks_scan_x, file.page.height)
|
223
|
+
dr.draw(file)
|
224
|
+
|
220
225
|
scan_clock_marks unless clock_marks.any?
|
221
226
|
|
222
227
|
clock_marks.each_with_index do |clock, index|
|
data/lib/ruby_marks/version.rb
CHANGED
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.1.
|
4
|
+
version: 0.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -35,8 +35,9 @@ email:
|
|
35
35
|
executables: []
|
36
36
|
extensions: []
|
37
37
|
extra_rdoc_files:
|
38
|
-
- README.
|
38
|
+
- README.md
|
39
39
|
files:
|
40
|
+
- README.md
|
40
41
|
- lib/ruby_marks/clock_mark.rb
|
41
42
|
- lib/ruby_marks/config.rb
|
42
43
|
- lib/ruby_marks/group.rb
|
@@ -46,7 +47,6 @@ files:
|
|
46
47
|
- lib/ruby_marks/version.rb
|
47
48
|
- lib/ruby_marks/watcher.rb
|
48
49
|
- lib/ruby_marks.rb
|
49
|
-
- README.rdoc
|
50
50
|
- test/ruby_marks/clock_mark_test.rb
|
51
51
|
- test/ruby_marks/group_test.rb
|
52
52
|
- test/ruby_marks/image_utils_test.rb
|
data/README.rdoc
DELETED