Class: Mork::SheetOMR

Inherits:
Object
  • Object
show all
Defined in:
lib/mork/sheet_omr.rb

Overview

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.

Instance Method Summary collapse

Constructor Details

#initialize(path, layout = nil) ⇒ SheetOMR

Returns a new instance of SheetOMR.

Parameters:

  • path (String)

    the required path/filename to the saved image (.jpg, .jpeg, .png, or .pdf)

  • layout (String, Hash) (defaults to: nil)

    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.



20
21
22
23
# File 'lib/mork/sheet_omr.rb', line 20

def initialize(path, layout=nil)
  grom = GridOMR.new layout
  @mim = Mimage.new path, grom
end

Instance Method Details

#barcodeInteger

Sheet barcode as an integer

Returns:

  • (Integer)


48
49
50
51
# File 'lib/mork/sheet_omr.rb', line 48

def barcode
  return if not_registered
  barcode_string.to_i(2)
end

#barcode_stringString

Sheet barcode as a binary-like string

Returns:

  • (String)

    a string of 0s and 1s; the string is barcode_bits bits long, with most significant bits to the left



57
58
59
60
61
62
# 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?Boolean

Returns:

  • (Boolean)


32
33
34
# File 'lib/mork/sheet_omr.rb', line 32

def low_contrast?
  @mim.low_contrast?
end

#marked?(question, choice) ⇒ Boolean

True if the specified question/choice cell has been marked

Parameters:

  • question (Integer)

    the question number, zero-based

  • choice (Integer)

    the choice number, zero-based

Returns:

  • (Boolean)


93
94
95
96
# 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_choicesArray

The set of choice indices marked on the response sheet

Returns:

  • (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.



106
107
108
109
# File 'lib/mork/sheet_omr.rb', line 106

def marked_choices
  return if not_registered
  @mim.marked
end

#marked_choices_uniqueArray

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.

Returns:

  • (Array)

    an array of integers; each element contains the (zero-based) marked choice for the corresponding question.



117
118
119
120
121
122
# 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_lettersArray

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

Returns:

  • (Array)

    an array of arrays of 1-character strings; each element contains the list of letters marked for the corresponding question.



129
130
131
132
133
134
# 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_uniqueArray

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.

Returns:

  • (Array)

    an array of 1-character strings



142
143
144
145
146
147
# 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) ⇒ Object

Apply an overlay on the image

Parameters:

  • what (Symbol)

    the overlay type, choose from :outline, :check, :highlight

  • where (Array, Symbol) (defaults to: :marked)

    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



161
162
163
164
# File 'lib/mork/sheet_omr.rb', line 161

def overlay(what, where=:marked)
  return if not_registered
  @mim.overlay what, where
end

#save(fname) ⇒ Object

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

Parameters:

  • fname (String)

    the path/filename of the target image, including the extension (.jpg, .png)



171
172
173
174
# File 'lib/mork/sheet_omr.rb', line 171

def save(fname)
  return if not_registered
  @mim.save(fname, true)
end

#save_registration(fname) ⇒ Object

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.

Parameters:

  • fname (String)

    the path/filename of the target image, including the extension (.jpg, .png)



182
183
184
# File 'lib/mork/sheet_omr.rb', line 182

def save_registration(fname)
  @mim.save_registration fname
end

#set_choices(choices) ⇒ Boolean

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.

Parameters:

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

Returns:

  • (Boolean)

    True if the sheet is properly registered and ready to be marked; false otherwise.



78
79
80
81
82
83
84
85
86
# 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

#statusHash

Registration status for each of the four corners

Returns:

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



41
42
43
# File 'lib/mork/sheet_omr.rb', line 41

def status
  @mim.status
end

#valid?Boolean

True if sheet registration completed successfully

Returns:

  • (Boolean)


28
29
30
# File 'lib/mork/sheet_omr.rb', line 28

def valid?
  @mim.valid?
end