mork 0.1.3 → 0.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f334aa5882675284d8700705af5fe1015045234f
4
- data.tar.gz: 5d516e96fe0453f29179b08ded1d3d9786c27bff
3
+ metadata.gz: 023acadd6339d125a7764a4af516d86b7da951c3
4
+ data.tar.gz: fffbcdd3a134b60d02f46a380ba5192812c13b76
5
5
  SHA512:
6
- metadata.gz: fafa8bd3db5eb7a0c5f0c15274daf62046e2285bfee46704cf849eca984eb59edb0866b85d1fc489d44f2b3c6a452cfc166ffd06674b2c7242550a32d216097b
7
- data.tar.gz: 6b9244e99322ee533905329240618e0ed52bc729e313d99cb03078e3c63554d7194ab8956894f1c4917ff5ba0d72fad85e2f1bb3d1a15e94606a5597593dcd75
6
+ metadata.gz: 8bb3ec4c6ec605ce6d7866550ab7d66025520d99961a388ae303b513a2a5f57252818725ae8d8d64f891eab54f55d0f7c3d61cae3c16cea873612f53344ac31a
7
+ data.tar.gz: ad6e6df8e2ce80126e270760bc2909a2810555d1f68196e919f635feec29d55974444b98bda28e93dfdd510d938566289e4882ce4f96cb04460e0b385f2f3f59
data/Gemfile CHANGED
@@ -1,3 +1,2 @@
1
1
  source "http://rubygems.org"
2
- # gem 'prawn', git: 'git://github.com/prawnpdf/prawn', submodules: true
3
2
  gemspec
data/auto.txt ADDED
File without changes
data/lib/mork/grid_omr.rb CHANGED
@@ -2,14 +2,21 @@ require 'mork/grid'
2
2
 
3
3
  module Mork
4
4
  class GridOMR < Grid
5
- def initialize(page_width, page_height, options=nil)
5
+ def initialize(options=nil)
6
6
  super options
7
- @px = page_width.to_f
8
- @py = page_height.to_f
9
7
  end
10
8
 
11
- def barcode_bit_areas(code = 2**barcode_bits-1)
12
- barcode_bits.times.collect { |b| barcode_bit_area b }
9
+ def set_page_size(width, height)
10
+ @px = width.to_f
11
+ @py = height.to_f
12
+ end
13
+
14
+ def barcode_bit_areas(bitstring = '1' * barcode_bits)
15
+ areas = []
16
+ bitstring.reverse.each_char.with_index do |c, i|
17
+ areas << barcode_bit_area(i+1) if c=='1'
18
+ end
19
+ areas
13
20
  end
14
21
 
15
22
  # ====================================================
data/lib/mork/mimage.rb CHANGED
@@ -1,67 +1,103 @@
1
- require 'RMagick'
1
+ require 'mini_magick'
2
+ require 'mork/npatch'
2
3
 
3
4
  module Mork
4
- # The class Mimage is a wrapper for the core image library, currently RMagick
5
+ # The class Mimage is a wrapper for the core image library, currently mini_magick
5
6
  class Mimage
6
- def initialize(img, page=0)
7
- if img.class == String
8
- if File.extname(img) == '.pdf'
9
- @image = Magick::Image.read(img) { self.density = 200 }[page]
10
- else
11
- @image = Magick::ImageList.new(img)[page]
12
- end
13
- elsif img.class == Magick::ImageList
14
- @image = img[page]
15
- elsif img.class == Magick::Image
16
- @image = img
17
- else
18
- raise "Invalid initialization argument"
19
- end
7
+ def initialize(path, grom, page=0)
8
+ raise "File '#{path}' not found" unless File.exists? path
9
+ @path = path
10
+ @grom = grom
11
+ @grom.set_page_size width, height
12
+ @status = register
13
+ @cmd = []
14
+ end
15
+
16
+ def status
17
+ @status
18
+ end
19
+
20
+ def ink_black
21
+ reg_pixels.average @grom.ink_black_area
22
+ end
23
+
24
+ def paper_white
25
+ reg_pixels.average @grom.paper_white_area
26
+ end
27
+
28
+ def cal_cell_mean
29
+ @grom.calibration_cell_areas.collect { |c| reg_pixels.average c }.mean
30
+ end
31
+
32
+ def shade_of_barcode_bit(i)
33
+ reg_pixels.average @grom.barcode_bit_area i+1
34
+ end
35
+
36
+ def shade_of(q,c)
37
+ reg_pixels.average @grom.choice_cell_area(q, c)
38
+ end
39
+
40
+ def width
41
+ img_size[0].to_i
20
42
  end
21
43
 
22
- # outline!(cells, roundedness)
44
+ def height
45
+ img_size[1].to_i
46
+ end
47
+
48
+ # outline(cells, roundedness)
23
49
  #
24
50
  # draws on the Mimage a set of cell outlines
25
51
  # typically used to highlight the expected responses
26
- def outline!(cells, roundedness=nil)
27
- cells = [cells] if cells.is_a? Hash
52
+ def outline(cells, roundedness=nil)
28
53
  return if cells.empty?
29
- roundedness ||= [cells[0][:h], cells[0][:w]].min / 2
30
- out = Magick::Draw.new
31
- out.stroke 'green'
32
- out.stroke_width 4
33
- out.fill_opacity 0
34
- cells.each do |c|
35
- out.roundrectangle c[:x], c[:y], c[:x]+c[:w], c[:y]+c[:h], roundedness, roundedness
36
- out.draw @image
54
+ @cmd << [:stroke, 'green']
55
+ @cmd << [:strokewidth, '4']
56
+ @cmd << [:fill, 'none']
57
+ array_of(cells).each do |c|
58
+ roundedness ||= [c[:h], c[:w]].min / 2
59
+ pts = [c[:x], c[:y], c[:x]+c[:w], c[:y]+c[:h], roundedness, roundedness].join ' '
60
+ @cmd << [:draw, "roundrectangle #{pts}"]
37
61
  end
38
62
  end
39
63
 
40
- # =============
41
- # = Highlight =
42
- # =============
43
- def highlight_cells!(cells, roundedness=nil)
44
- cells = [cells] if cells.is_a? Hash
64
+ def highlight_all_choices
65
+ cells = (0...@grom.max_questions).collect { |i| (0...@grom.max_choices_per_question).to_a }
66
+ highlight_cells cells
67
+ end
68
+
69
+ # highlight_cells(cells, roundedness)
70
+ #
71
+ # partially transparent yellow on top of choice cells
72
+ def highlight_cells(cells, roundedness=nil)
45
73
  return if cells.empty?
46
- roundedness ||= [cells[0][:h], cells[0][:w]].min / 2
47
- cells.each do |c|
48
- out = Magick::Draw.new
49
- out.fill 'yellow'
50
- out.opacity '40%'
51
- out.roundrectangle c[:x], c[:y], c[:x]+c[:w], c[:y]+c[:h], roundedness, roundedness
52
- out.draw @image
74
+ @cmd << [:stroke, 'none']
75
+ @cmd << [:fill, 'rgba(255, 255, 0, 0.3)']
76
+ array_of(cells).each do |c|
77
+ roundedness ||= [c[:h], c[:w]].min / 2
78
+ pts = [c[:x], c[:y], c[:x]+c[:w], c[:y]+c[:h], roundedness, roundedness].join ' '
79
+ @cmd << [:draw, "roundrectangle #{pts}"]
53
80
  end
54
81
  end
55
82
 
56
- def highlight_rect!(areas)
57
- areas = [areas] if areas.is_a? Hash
83
+ def highlight_reg_area
84
+ highlight_rect [@rmsa[:tl], @rmsa[:tr], @rmsa[:br], @rmsa[:bl]]
85
+ return unless @status
86
+ join [@rm[:tl], @rm[:tr], @rm[:br], @rm[:bl]]
87
+ end
88
+
89
+ def highlight_barcode(bitstring)
90
+ highlight_rect @grom.barcode_bit_areas bitstring
91
+ end
92
+
93
+ def highlight_rect(areas)
94
+ return if areas.empty?
95
+ @cmd << [:fill, 'none']
96
+ @cmd << [:stroke, 'yellow']
97
+ @cmd << [:strokewidth, 3]
58
98
  areas.each do |c|
59
- out = Magick::Draw.new
60
- out.fill_opacity 0
61
- out.stroke 'yellow'
62
- out.stroke_width 3
63
- out.rectangle c[:x], c[:y], c[:x]+c[:w], c[:y]+c[:h]
64
- out.draw @image
99
+ pts = [c[:x], c[:y], c[:x]+c[:w], c[:y]+c[:h]].join ' '
100
+ @cmd << [:draw, "rectangle #{pts}"]
65
101
  end
66
102
  end
67
103
 
@@ -75,69 +111,98 @@ module Mork
75
111
  end
76
112
  end
77
113
 
78
- def join!(p)
79
- poly = Magick::Draw.new
80
- poly.fill_opacity 0
81
- poly.stroke 'green'
82
- poly.stroke_width 3
83
- poly.polygon p[0][:x], p[0][:y], p[1][:x], p[1][:y], p[2][:x], p[2][:y], p[3][:x], p[3][:y]
84
- poly.draw @image
114
+ # write the underlying MiniMagick::Image to disk;
115
+ # if the 2nd arg is false, then stretching is not applied
116
+ def write(fname, reg=true)
117
+ img = MiniMagick::Image.open @path
118
+ img.combine_options do |c|
119
+ c.distort(:perspective, perspective_points) if reg
120
+ @cmd.each do |cmd|
121
+ c.send *cmd
122
+ end
123
+ end
124
+ img.write fname
85
125
  end
86
126
 
87
- # ============
88
- # = Cropping =
89
- # ============
90
- def crop(c)
91
- Mimage.new @image.crop(c[:x], c[:y], c[:w], c[:h])
92
- end
127
+ # ============================================================#
128
+ private #
129
+ # ============================================================#
93
130
 
94
- def crop!(c)
95
- @image.crop!(c[:x], c[:y], c[:w], c[:h])
96
- self
97
- end
98
-
99
- # ============
100
- # = Blurring =
101
- # ============
102
- def blur(a, b)
103
- Mimage.new @image.blur_image(a, b)
104
- end
105
-
106
- def blur!(a, b)
107
- @image = @image.blur_image(a, b)
108
- self
131
+ def img_size
132
+ @img_size ||= IO.read("|identify -format '%w,%h' #{@path}").split ','
109
133
  end
110
134
 
111
- # ==============
112
- # = Stretching =
113
- # ==============
114
- def stretch(points)
115
- Mimage.new @image.distort(Magick::PerspectiveDistortion, points)
135
+ def raw_pixels
136
+ @raw_pixels ||= begin
137
+ bytes = IO.read("|convert #{@path} gray:-").unpack 'C*'
138
+ NPatch.new bytes, width, height
139
+ end
116
140
  end
117
141
 
118
- def stretch!(points)
119
- @image = @image.distort(Magick::PerspectiveDistortion, points)
120
- self
142
+ def reg_pixels
143
+ @reg_pixels ||= begin
144
+ bytes = IO.read("|convert #{@path} -distort Perspective '#{perspective_points}' gray:-").unpack 'C*'
145
+ NPatch.new bytes, width, height
146
+ end
121
147
  end
122
148
 
123
- # returns the raw pixels from the entire image or from the area
124
- # defined in opts
125
- def pixels(opts = {})
126
- c = {x: 0, y: 0, w: width, h: height}.merge(opts)
127
- @image.export_pixels(c[:x], c[:y], c[:w], c[:h], "I")
149
+ def perspective_points
150
+ [
151
+ @rm[:tl][:x], @rm[:tl][:y], 0, 0,
152
+ @rm[:tr][:x], @rm[:tr][:y], width, 0,
153
+ @rm[:br][:x], @rm[:br][:y], width, height,
154
+ @rm[:bl][:x], @rm[:bl][:y], 0, height
155
+ ].join ' '
128
156
  end
129
-
130
- def width
131
- @image.columns
157
+
158
+ def join(p)
159
+ @cmd << [:fill, 'none']
160
+ @cmd << [:stroke, 'green']
161
+ @cmd << [:strokewidth, 3]
162
+ pts = [p[0][:x], p[0][:y], p[1][:x], p[1][:y], p[2][:x], p[2][:y], p[3][:x], p[3][:y]].join ' '
163
+ @cmd << [:draw, "polygon #{pts}"]
164
+ end
165
+
166
+ def array_of(cells)
167
+ out = []
168
+ cells.each_with_index do |q, i|
169
+ q.each do |c|
170
+ out << @grom.choice_cell_area(i, c)
171
+ end
172
+ end
173
+ out
132
174
  end
133
-
134
- def height
135
- @image.rows
175
+
176
+ def register
177
+ # find the XY coordinates of the 4 registration marks
178
+ @rm = {} # registration mark centers
179
+ @rmsa = {} # registration mark search area
180
+ @rm[:tl] = reg_centroid_on(:tl)
181
+ @rm[:tr] = reg_centroid_on(:tr)
182
+ @rm[:br] = reg_centroid_on(:br)
183
+ @rm[:bl] = reg_centroid_on(:bl)
184
+ # return the status
185
+ @rm.all? { |k,v| v[:status] == :ok }
136
186
  end
137
187
 
138
- # write the underlying Magick::Image to disk
139
- def write(fname)
140
- @image.write fname
188
+ # returns the centroid of the dark region within the given area
189
+ # in the XY coordinates of the entire image
190
+ def reg_centroid_on(corner)
191
+ 1000.times do |i|
192
+ @rmsa[corner] = @grom.rm_search_area(corner, i)
193
+ cx, cy = raw_pixels.dark_centroid @rmsa[corner]
194
+ if cx.nil?
195
+ status = :insufficient_contrast
196
+ elsif (cx < @grom.rm_edgy_x) or
197
+ (cy < @grom.rm_edgy_y) or
198
+ (cy > @rmsa[corner][:h] - @grom.rm_edgy_y) or
199
+ (cx > @rmsa[corner][:w] - @grom.rm_edgy_x)
200
+ status = :edgy
201
+ else
202
+ return {status: :ok, x: cx + @rmsa[corner][:x], y: cy + @rmsa[corner][:y]}
203
+ end
204
+ return {status: status, x: nil, y: nil} if @rmsa[corner][:w] > @grom.rm_max_search_area_side
205
+ end
141
206
  end
142
207
  end
143
- end
208
+ end
@@ -1,4 +1,4 @@
1
- require 'RMagick'
1
+ # require 'RMagick'
2
2
 
3
3
  module Mork
4
4
  # The class MimageList
data/lib/mork/npatch.rb CHANGED
@@ -1,51 +1,75 @@
1
1
  require 'narray'
2
2
 
3
3
  module Mork
4
- # Handles low-level computations on a Mimage
5
- # Typically used on smaller patches
4
+ # NPatch handles low-level computations on pixels
5
+ # it is basically a wrapper around NArray
6
6
  class NPatch
7
- def initialize(mim)
8
- @mim = mim
9
- @width = mim.width
10
- @height = mim.height
7
+ def initialize(source, width, height)
8
+ @patch = NArray.byte(width, height)
9
+ @patch[true] = case source
10
+ when Array
11
+ source
12
+ when String
13
+ IO.read("|convert #{source} gray:-").unpack 'C*'
14
+ else
15
+ raise 'Invalid NPatch init param'
16
+ end
17
+ @width = width
18
+ @height = height
11
19
  end
12
20
 
13
- def average
14
- narr.mean
21
+ def average(c=nil)
22
+ crop(c).mean
15
23
  end
16
24
 
17
- def dark_centroid
18
- sufficient_contrast? or return
19
- xp = patch.sum(1).to_a
20
- yp = patch.sum(0).to_a
25
+ def length
26
+ @patch.length
27
+ end
28
+
29
+ def dark_centroid(c = nil)
30
+ p = crop c
31
+ sufficient_contrast?(p) or return
32
+ xp = p.sum(1).to_a
33
+ yp = p.sum(0).to_a
21
34
  # find the intensity trough
22
35
  ctr_x = xp.find_index(xp.min)
23
36
  ctr_y = yp.find_index(yp.min)
24
- # return :edgy if edgy?(ctr_x, ctr_y)
25
37
  return ctr_x, ctr_y
26
38
  end
27
39
 
28
- private
29
- def patch
30
- @the_npatch ||= blurry_narr.reshape!(@width, @height)
31
- end
40
+ private
32
41
 
33
- def narr
34
- NArray[@mim.pixels]
42
+ def crop(c)
43
+ c = {x: 0, y: 0, w: @width, h: @height} if c.nil?
44
+ x = c[:x]...c[:x]+c[:w]
45
+ y = c[:y]...c[:y]+c[:h]
46
+ p = NArray.float c[:w], c[:h]
47
+ p[true,true] = @patch[x, y]
48
+ p
35
49
  end
36
50
 
37
- def blurry_narr
38
- @blurry_narr ||= NArray[@mim.blur!(10,5).pixels]
39
- end
40
-
41
- def sufficient_contrast?
42
- # just a wild guess for now
43
- blurry_narr.stddev > 5000
44
- end
45
-
46
- def edgy?(x, y)
47
- tol = 5
48
- (x < tol) or (y < tol) or (y > @height - tol) or (x > @width - tol)
51
+ def sufficient_contrast?(p)
52
+ # tested with the few examples: spec/samples/rm0x.jpeg
53
+ p.stddev > 20
49
54
  end
50
55
  end
51
- end
56
+ end
57
+
58
+
59
+ # def edgy?(x, y)
60
+ # tol = 5
61
+ # (x < tol) or (y < tol) or (y > @height - tol) or (x > @width - tol)
62
+ # end
63
+ #
64
+ # def patch
65
+ # @the_npatch ||= blurry_narr.reshape!(@width, @height)
66
+ # end
67
+ #
68
+ # def narr
69
+ # NArray[@mim.pixels]
70
+ # end
71
+ #
72
+ # def blurry_narr
73
+ # @blurry_narr ||= NArray[@mim.blur!(10,5).pixels]
74
+ # end
75
+ #
@@ -1,28 +1,13 @@
1
1
  require 'mork/grid_omr'
2
2
  require 'mork/mimage'
3
3
  require 'mork/mimage_list'
4
- require 'mork/npatch'
5
4
 
6
5
  module Mork
7
6
  class SheetOMR
8
- def initialize(im, grom=nil)
9
- @raw = case im
10
- when String
11
- Mimage.new im
12
- when Mork::Mimage
13
- im
14
- else
15
- raise "A new sheet requires either a Mimage or the name of the source image file, but it was a: #{im.class}"
16
- end
17
- @grom = case grom
18
- when String, Hash, NilClass
19
- GridOMR.new @raw.width, @raw.height, grom
20
- else
21
- raise 'Invalid argument in SheetOMR initialization'
22
- end
23
- @rm = {}
24
- @rmsa = {}
25
- @ok_reg = register @raw
7
+ def initialize(path, grom=nil)
8
+ @grom = GridOMR.new grom
9
+ @mim = Mimage.new path, @grom
10
+ @ok_reg = @mim.status
26
11
  end
27
12
 
28
13
  def valid?
@@ -53,7 +38,7 @@ module Mork
53
38
  # false otherwise
54
39
  def marked?(q, c)
55
40
  return if not_registered
56
- shade_of(q, c) < choice_threshold
41
+ @mim.shade_of(q, c) < choice_threshold
57
42
  end
58
43
 
59
44
  # TODO: define method ‘mark’ to retrieve the choice array for a single item
@@ -88,65 +73,41 @@ module Mork
88
73
 
89
74
  def outline(cells)
90
75
  return if not_registered
91
- @crop.outline! array_of cells
76
+ raise "Invalid cells’ argument" unless cells.kind_of? Array
77
+ @mim.outline cells
92
78
  end
93
79
 
94
- def highlight_all
80
+ def highlight_marked
95
81
  return if not_registered
96
- cells = (0...@grom.max_questions).collect { |i| (0...@grom.max_choices_per_question).to_a }
97
- @crop.highlight_cells! array_of cells
98
- @crop.highlight_cells! @grom.calibration_cell_areas
99
- @crop.highlight_rect! [@grom.ink_black_area, @grom.paper_white_area]
100
- @crop.highlight_rect! @grom.barcode_bit_areas
82
+ @mim.highlight_cells mark_array
101
83
  end
102
84
 
103
- def highlight_marked
85
+ def highlight_all_choices
104
86
  return if not_registered
105
- @crop.highlight_cells! array_of mark_array
87
+ @mim.highlight_all_choices
106
88
  end
107
89
 
108
90
  def highlight_barcode
109
91
  return if not_registered
110
- @grom.barcode_bits.times do |bit|
111
- if barcode_string.reverse[bit] == '1'
112
- @crop.highlight_rect! @grom.barcode_bit_area bit+1
113
- end
114
- end
92
+ @mim.highlight_barcode barcode_string
115
93
  end
116
94
 
117
- def highlight_reg_area
118
- @raw.highlight_rect! [@rmsa[:tl], @rmsa[:tr], @rmsa[:br], @rmsa[:bl]]
119
- return if not_registered
120
- @raw.join! [@rm[:tl],@rm[:tr],@rm[:br],@rm[:bl]]
95
+ def highlight_registration
96
+ @mim.highlight_reg_area
121
97
  end
122
98
 
123
99
  def write(fname)
124
100
  return if not_registered
125
- @crop.write(fname)
101
+ @mim.write(fname)
126
102
  end
127
103
 
128
104
  def write_raw(fname)
129
- @raw.write(fname)
130
- end
131
-
132
- # =================================
133
- # = compute shading with NPatches =
134
- # =================================
135
- def shade_of(q, c)
136
- naverage @grom.choice_cell_area(q, c)
105
+ @mim.write(fname, false)
137
106
  end
138
107
 
139
- private
140
-
141
- def array_of(cells)
142
- out = []
143
- cells.each_with_index do |q, i|
144
- q.each do |c|
145
- out << @grom.choice_cell_area(i, c)
146
- end
147
- end
148
- out
149
- end
108
+ # ============================================================#
109
+ private #
110
+ # ============================================================#
150
111
 
151
112
  def question_range(r)
152
113
  if r.nil?
@@ -161,82 +122,19 @@ module Mork
161
122
  end
162
123
 
163
124
  def barcode_bit_value(i)
164
- shade_of_barcode_bit(i) < barcode_threshold ? "1" : "0"
125
+ @mim.shade_of_barcode_bit(i) < barcode_threshold ? "1" : "0"
165
126
  end
166
127
 
167
- def shade_of_barcode_bit(i)
168
- naverage @grom.barcode_bit_area i+1
169
- end
170
-
171
128
  def barcode_threshold
172
- @barcode_threshold ||= (paper_white + ink_black) / 2
129
+ @barcode_threshold ||= (@mim.paper_white + ink_black) / 2
173
130
  end
174
131
 
175
132
  def choice_threshold
176
- @choice_threshold ||= (ccmeans.mean - ink_black) * 0.9 + ink_black
177
- end
178
-
179
- def ccmeans
180
- @calcmeans ||= @grom.calibration_cell_areas.collect { |c| naverage c }
181
- end
182
-
183
- def paper_white
184
- @paper_white ||= naverage @grom.paper_white_area
133
+ @choice_threshold ||= (@mim.cal_cell_mean - ink_black) * 0.9 + ink_black
185
134
  end
186
135
 
187
136
  def ink_black
188
- @ink_black ||= naverage @grom.ink_black_area
189
- end
190
-
191
- def shade_of_blank_cells
192
- # @grom.
193
- end
194
-
195
- # ================
196
- # = Registration =
197
- # ================
198
-
199
- # this method uses a 'stretch' strategy, i.e. where the image after
200
- # registration has the same size in pixels as the original scanned file
201
- def register(img)
202
- # find the XY coordinates of the 4 registration marks
203
- @rm[:tl] = reg_centroid_on(img, :tl)
204
- @rm[:tr] = reg_centroid_on(img, :tr)
205
- @rm[:br] = reg_centroid_on(img, :br)
206
- @rm[:bl] = reg_centroid_on(img, :bl)
207
- return false if @rm.any? { |k,v| v[:status] != :ok }
208
- # stretch the 4 points to fit the original size and return the resulting image
209
- @crop = img.stretch [
210
- @rm[:tl][:x], @rm[:tl][:y], 0, 0,
211
- @rm[:tr][:x], @rm[:tr][:y], img.width, 0,
212
- @rm[:br][:x], @rm[:br][:y], img.width, img.height,
213
- @rm[:bl][:x], @rm[:bl][:y], 0, img.height
214
- ]
215
- true
216
- end
217
-
218
- # returns the centroid of the dark region within the given area
219
- # in the XY coordinates of the entire image
220
- def reg_centroid_on(img, corner)
221
- 1000.times do |i|
222
- @rmsa[corner] = @grom.rm_search_area(corner, i)
223
- cx, cy = NPatch.new(img.crop(@rmsa[corner])).dark_centroid
224
- if cx.nil?
225
- status = :insufficient_contrast
226
- elsif (cx < @grom.rm_edgy_x) or
227
- (cy < @grom.rm_edgy_y) or
228
- (cy > @rmsa[corner][:h] - @grom.rm_edgy_y) or
229
- (cx > @rmsa[corner][:w] - @grom.rm_edgy_x)
230
- status = :edgy
231
- else
232
- return {status: :ok, x: cx + @rmsa[corner][:x], y: cy + @rmsa[corner][:y]}
233
- end
234
- return {status: status, x: nil, y: nil} if @rmsa[corner][:w] > @grom.rm_max_search_area_side
235
- end
236
- end
237
-
238
- def naverage(where)
239
- NPatch.new(@crop.crop where).average
137
+ @ink_black ||= @mim.ink_black
240
138
  end
241
139
 
242
140
  def not_registered
data/lib/mork/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mork
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.1"
3
3
  end