ruby_marks 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,402 @@
1
+ Ruby Marks
2
+ ==========
3
+
4
+ [![Build Status](https://secure.travis-ci.org/andrerpbts/ruby_marks.png?branch=master)](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
+ [![Document Example](https://raw.github.com/andrerpbts/ruby_marks/master/assets/sheet_demo2.png)](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|
@@ -1,3 +1,3 @@
1
1
  module RubyMarks
2
- VERSION = "0.1.2".freeze
2
+ VERSION = "0.1.3".freeze
3
3
  end
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.2
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.rdoc
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
@@ -1,4 +0,0 @@
1
- = Ruby Marks {<img src="https://secure.travis-ci.org/andrerpbts/ruby_marks.png" />}[http://travis-ci.org/andrerpbts/ruby_marks]
2
-
3
- A simple OMR ({Optical Mark Recognition}[http://en.wikipedia.org/wiki/Optical_mark_recognition]) gem.
4
-