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 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
-