class Mork::SheetOMR

Optical mark recognition of a response sheet that was: 1) generated with SheetPDF, 2) printed on plain paper, 3) filled out by a responder, and 4) acquired as a image file.

The sheet is automatically registered upon object creation, after which it is possible to perform queries, as well as save a copy of the scanned image with various overlays superimposed, highlighting the expected correc choices, the actually marked ones, etc.

Public Class Methods

new(path, layout=nil) click to toggle source

@param path [String] the required path/filename to the saved image

(.jpg, .jpeg, .png, or .pdf)

@param layout [String, Hash] the sheet description. Send a hash of

parameters or a string to specify the path/filename of a YAML file
containing the parameters. See the README file for a full listing
of the available parameters.
# File lib/mork/sheet_omr.rb, line 20
def initialize(path, layout=nil)
  grom = GridOMR.new layout
  @mim = Mimage.new path, grom
end

Public Instance Methods

barcode() click to toggle source

Sheet barcode as an integer

@return [Integer]

# File lib/mork/sheet_omr.rb, line 48
def barcode
  return if not_registered
  barcode_string.to_i(2)
end
barcode_string() click to toggle source

Sheet barcode as a binary-like string

@return [String] a string of 0s and 1s; the string is `barcode_bits`

bits long, with most significant bits to the left
# File lib/mork/sheet_omr.rb, line 57
def barcode_string
  return if not_registered
  @mim.barcode_bits.map do |b|
    b ? '1' : '0'
  end.join.reverse
end
low_contrast?() click to toggle source
# File lib/mork/sheet_omr.rb, line 32
def low_contrast?
  @mim.low_contrast?
end
marked?(question, choice) click to toggle source

True if the specified question/choice cell has been marked

@param question [Integer] the question number, zero-based @param choice [Integer] the choice number, zero-based @return [Boolean]

# File lib/mork/sheet_omr.rb, line 93
def marked?(question, choice)
  return if not_registered
  marked_choices[question].find {|x| x==choice} ? true : false
end
marked_choices() click to toggle source

The set of choice indices marked on the response sheet

@return [Array] an array of arrays of integers; each element contains

the (zero-based) list of marked choices for the corresponding question.
For example, the following `marked_choices` array: `[[0], [], [3,4]]`
indicates that the responder has marked the first choice for the first
question, none for the second, and the fourth and fifth choices for the
third question.
# File lib/mork/sheet_omr.rb, line 106
def marked_choices
  return if not_registered
  @mim.marked
end
marked_choices_unique() click to toggle source

The set of choice indices marked on the response sheet. If more than one choice was marked for a question, the response is regarded as invalid and treated as if it had been left blank.

@return [Array] an array of integers; each element contains

the (zero-based) marked choice for the corresponding question.
# File lib/mork/sheet_omr.rb, line 117
def marked_choices_unique
  return if not_registered
  marked_choices.map do |c|
    c.length == 1 ? c.first : nil
  end
end
marked_letters() click to toggle source

The set of letters marked on the response sheet. At this time, only the latin sequence 'A, B, C…' is supported.

@return [Array] an array of arrays of 1-character strings; each element

contains the list of letters marked for the corresponding question.
# File lib/mork/sheet_omr.rb, line 129
def marked_letters
  return if not_registered
  marked_choices.map do |q|
    q.map { |cho| (65+cho).chr }
  end
end
marked_letters_unique() click to toggle source

The set of letters marked on the response sheet. At this time, only the latin sequence 'A, B, C…' is supported. If more than one choice was marked for an item, the response is regarded as invalid and treated as if it had been left blank.

@return [Array] an array of 1-character strings

# File lib/mork/sheet_omr.rb, line 142
def marked_letters_unique
  return if not_registered
  marked_choices_unique.map do |c|
    c.nil?? '' : (65+c).chr
  end
end
overlay(what, where=:marked) click to toggle source

Apply an overlay on the image

@param what [Symbol] the overlay type, choose from `:outline`, `:check`,

`:highlight`

@param where [Array, Symbol] where to apply the overlay. Either an array

of arrays of (zero-based) indices to specify target cells, or one of
the following symbols: `:marked`: all marked cells, among those
specified by the `choices` argument during object creation
(this is the default); `:all`: all cells in `choices`;
`:max`: maximum number of cells allowed by the layout (can be larger
than `:all`); `:barcode`: the dark barcode elements; `:cal` the
calibration cells
# File lib/mork/sheet_omr.rb, line 161
def overlay(what, where=:marked)
  return if not_registered
  @mim.overlay what, where
end
save(fname) click to toggle source

Saves a copy of the source image after registration; the output image will also contain any previously applied overlays.

@param fname [String] the path/filename of the target image, including

the extension (`.jpg`, `.png`)
# File lib/mork/sheet_omr.rb, line 171
def save(fname)
  return if not_registered
  @mim.save(fname, true)
end
save_registration(fname) click to toggle source

Saves a copy of the original image with overlays showing the crop areas used to localize the registration marks and the detected registration mark centers.

@param fname [String] the path/filename of the target image, including

the extension (`.jpg`, `.png`)
# File lib/mork/sheet_omr.rb, line 182
def save_registration(fname)
  @mim.save_registration fname
end
set_choices(choices) click to toggle source

Setting the choices/questions to analyze. If this function is not called, the maximum number of choices/questions allowed by the layout will be evaluated.

@param choices [Integer, Array] the questions/choices we want subsequent

scoring/overlaying to apply to. Normally, `choices` should be an array
of integers, with each element indicating the number of available
choices for the corresponding question (i.e. `choices.length` is the
number of questions). As a shortcut, `choices` can also be a single
integer value, indicating the number of questions; in such case, the
maximum number of choices allowed by the layout will be considered.

@return [Boolean] True if the sheet is properly registered and ready to

be marked; false otherwise.
# File lib/mork/sheet_omr.rb, line 78
def set_choices(choices)
  return false unless valid?
  @mim.set_ch case choices
              when Integer; @mim.choxq[0...choices]
              when Array; choices
              else fail ArgumentError, 'Invalid choice set'
              end
  true
end
status() click to toggle source

Registration status for each of the four corners

@return [Hash] { tl: Symbol, tr: Symbol, br: Symbol, bl: Symbol } where

symbol is either `:ok` or `:edgy`, meaning that the centroid was found
to be too close to the edge of the search area to be considered reliable
# File lib/mork/sheet_omr.rb, line 41
def status
  @mim.status
end
valid?() click to toggle source

True if sheet registration completed successfully

@return [Boolean]

# File lib/mork/sheet_omr.rb, line 28
def valid?
  @mim.valid?
end