sqed 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc1ae71edf574734410eb4f86efc79658fe01e416e6a8a2082a077107c9f982c
4
- data.tar.gz: 81264b5a221c5dfdd0a2485a89dcc31962225d99de1541968a999bb10fb92e17
3
+ metadata.gz: ecff3bc24d06653a25e90dd950faea277de23da61cdc7503e288d6098d8c4250
4
+ data.tar.gz: dd87d00a794d8edf2387c6d37d01382480ab0c161963f063764fadeee75a7f40
5
5
  SHA512:
6
- metadata.gz: a87471a1a81d33c3c56b6e996578f0de936a78e983b8eaac5c03b68a2e806adbb11a1e846deff3a8d8b7b101c1845f04f7c42fb9cd9ba323e61e172ae5ab655e
7
- data.tar.gz: 65f21307aec7b020c7c2bb27df4aeb8802724ad16e9b18fcc87afab864a102df14e0b345ca92a97a7909507f4a1e2fb6453593acf1e81f42a8731807f8b4dd98
6
+ metadata.gz: 52aab726722c000e95af2e3e0de8e2ac584191972d74f6efa7e8127ee70404ebca0eb80493b2686f596e82a836a7302bcbc9f98b8d42759491d74313bd0f98f4
7
+ data.tar.gz: 2594a64f5b2f575515690314176aa00db01a69dfaef925aa5a1449c7e88b67373f20060f9f4fc172b5b07198c15636d3815a95d7d518e5380d45eda82924cefe
@@ -6,108 +6,108 @@ class Sqed
6
6
  # Layouts are Hashes defined in EXTRACTION_PATTERNS[<pattern>][<layout>]
7
7
  #
8
8
  class Boundaries
9
- include Enumerable
10
-
11
- # stores a hash
12
- # References the section by integer index!
13
- # In the pattern integer => [x1,y1, width, height] (ImageMagick convention rectangle descriptors)
14
- # e.g.
15
- # 0 => [10,10,40,40]
16
- attr_reader :coordinates
17
-
18
- # A symbol from Sqed::Config::LAYOUTS.keys
19
- # :right_t
20
- attr_accessor :layout
21
-
22
- # @return [Boolean] whether or not the last method to populate this object
23
- # executed to completion
24
- attr_accessor :complete
25
-
26
- def initialize(layout = nil)
27
- raise 'unrecognized layout' if layout && !SqedConfig::LAYOUTS.include?(layout)
28
- @complete = false
29
-
30
- @layout = layout
31
- @coordinates = {}
32
- initialize_coordinates if !@layout.nil?
33
- end
9
+ include Enumerable
10
+
11
+ # stores a hash
12
+ # References the section by integer index!
13
+ # In the pattern integer => [x1,y1, width, height] (ImageMagick convention rectangle descriptors)
14
+ # e.g.
15
+ # 0 => [10,10,40,40]
16
+ attr_reader :coordinates
17
+
18
+ # A symbol from Sqed::Config::LAYOUTS.keys
19
+ # :right_t
20
+ attr_accessor :layout
21
+
22
+ # @return [Boolean] whether or not the last method to populate this object
23
+ # executed to completion
24
+ attr_accessor :complete
25
+
26
+ def initialize(layout = nil)
27
+ raise Sqed::Error, 'unrecognized layout' if layout && !SqedConfig::LAYOUTS.include?(layout)
28
+ @complete = false
29
+
30
+ @layout = layout
31
+ @coordinates = {}
32
+ initialize_coordinates if !@layout.nil?
33
+ end
34
34
 
35
- def initialize_coordinates
36
- SqedConfig::LAYOUTS[@layout].each do |k|
37
- @coordinates.merge!(k => [nil, nil, nil, nil] )
35
+ def initialize_coordinates
36
+ SqedConfig::LAYOUTS[@layout].each do |k|
37
+ @coordinates.merge!(k => [nil, nil, nil, nil] )
38
+ end
38
39
  end
39
- end
40
40
 
41
- # @return [Sqed::Boundaries instance]
42
- # the idea here is to create a deep copy of self, offsetting by boundary
43
- # as we go
44
- def offset(boundary)
45
- b = Sqed::Boundaries.new
46
- (0..coordinates.length - 1).each do |i|
47
- b.set(i,
48
- [(x_for(i) + boundary.x_for(0)),
49
- (y_for(i) + boundary.y_for(0)),
50
- width_for(i),
51
- height_for(i)])
41
+ # @return [Sqed::Boundaries instance]
42
+ # the idea here is to create a deep copy of self, offsetting by boundary
43
+ # as we go
44
+ def offset(boundary)
45
+ b = Sqed::Boundaries.new
46
+ (0..coordinates.length - 1).each do |i|
47
+ b.set(i,
48
+ [(x_for(i) + boundary.x_for(0)),
49
+ (y_for(i) + boundary.y_for(0)),
50
+ width_for(i),
51
+ height_for(i)])
52
+ end
53
+ b.complete = complete
54
+ b
52
55
  end
53
- b.complete = complete
54
- b
55
- end
56
56
 
57
- def for(section)
58
- @coordinates[section]
59
- end
57
+ def for(section)
58
+ @coordinates[section]
59
+ end
60
60
 
61
- def each(&block)
62
- @coordinates.each do |section_index, coords|
63
- block.call([section_index, coords])
61
+ def each(&block)
62
+ @coordinates.each do |section_index, coords|
63
+ block.call([section_index, coords])
64
+ end
64
65
  end
65
- end
66
66
 
67
- # Overrides Enumerable
68
- def count
69
- @coordinates.length
70
- end
67
+ # Overrides Enumerable
68
+ def count
69
+ @coordinates.length
70
+ end
71
71
 
72
- def x_for(index)
73
- @coordinates[index][0]
74
- end
72
+ def x_for(index)
73
+ @coordinates[index][0]
74
+ end
75
75
 
76
- def y_for(index)
77
- @coordinates[index][1]
78
- end
76
+ def y_for(index)
77
+ @coordinates[index][1]
78
+ end
79
79
 
80
- def width_for(index)
81
- @coordinates[index][2]
82
- end
80
+ def width_for(index)
81
+ @coordinates[index][2]
82
+ end
83
83
 
84
- def height_for(index)
85
- @coordinates[index][3]
86
- end
84
+ def height_for(index)
85
+ @coordinates[index][3]
86
+ end
87
87
 
88
- def set(index, coordinates)
89
- @coordinates[index] = coordinates
90
- end
88
+ def set(index, coordinates)
89
+ @coordinates[index] = coordinates
90
+ end
91
91
 
92
- def populated?
93
- each do |index, coords|
94
- coords.each do |c|
95
- return false if c.nil?
92
+ def populated?
93
+ each do |index, coords|
94
+ coords.each do |c|
95
+ return false if c.nil?
96
+ end
96
97
  end
98
+ true
97
99
  end
98
- true
99
- end
100
100
 
101
- def zoom(width_factor, height_factor)
102
- coordinates.keys.each do |i|
103
- set(i, [
101
+ def zoom(width_factor, height_factor)
102
+ coordinates.keys.each do |i|
103
+ set(i, [
104
104
  (x_for(i).to_f * width_factor).to_i,
105
105
  (y_for(i).to_f * height_factor).to_i,
106
106
  (width_for(i).to_f * width_factor).to_i,
107
107
  (height_for(i).to_f * height_factor).to_i
108
- ])
108
+ ])
109
+ end
109
110
  end
110
- end
111
111
 
112
112
  end
113
113
  end
@@ -15,7 +15,7 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
15
15
 
16
16
  super(image: image, layout: layout, use_thumbnail: use_thumbnail)
17
17
 
18
- raise 'No layout provided.' if @layout.nil?
18
+ raise Sqed::Error, 'No layout provided.' if @layout.nil?
19
19
 
20
20
  # !@#? why this
21
21
  @boundary_color = boundary_color
@@ -201,6 +201,16 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
201
201
  boundaries.set(1, [ vertical.x_for(1), 0, right.width_for(0), right.height_for(0) ] )
202
202
  boundaries.set(2, [ vertical.x_for(1), right.y_for(1), right.width_for(1), right.height_for(1)] )
203
203
 
204
+ when :left_t
205
+ vertical = self.class.new(image: @image, layout: :vertical_split, boundary_color: boundary_color, use_thumbnail: false ).boundaries
206
+
207
+ ilft = image.crop(*vertical.for(0), true)
208
+ left = self.class.new(image: ilft, layout: :horizontal_split, boundary_color: boundary_color, use_thumbnail: false ).boundaries
209
+
210
+ boundaries.set(0, vertical.for(1))
211
+ boundaries.set(1, [ vertical.x_for(0), 0, left.width_for(0), left.height_for(0) ] )
212
+ boundaries.set(2, [ vertical.x_for(0), left.y_for(1), left.width_for(1), left.height_for(1)] )
213
+
204
214
  when :seven_slot
205
215
  top_bottom_split = Sqed::BoundaryFinder.color_boundary_finder(image: image, scan: :columns, boundary_color: boundary_color) # detect vertical division [array]
206
216
  left_right_split = Sqed::BoundaryFinder.color_boundary_finder(image: image, sample_subdivision_size: 1, boundary_color: boundary_color) # detect horizontal division [array]
@@ -263,7 +273,7 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
263
273
  boundaries.set(0, [0, 0, image.columns, t[0]]) # upper section of image
264
274
  boundaries.set(1, [0, t[2], image.columns, image.rows - t[2]]) # lower section of image
265
275
 
266
- else # no @layout provided !?
276
+ else # Hits :stage
267
277
  boundaries.set(0, [0, 0, image.columns, image.rows]) # totality of image as default
268
278
  end
269
279
 
@@ -46,11 +46,11 @@ class Sqed::BoundaryFinder::StageFinder < Sqed::BoundaryFinder
46
46
 
47
47
  # Returns a Proc that, given a set of pixels (an edge of the image) decides
48
48
  # whether that edge is a border or not.
49
- #
50
- # (img, samples = 5, threshold = 0.95, fuzz_factor = 0.5) # initially
49
+ #
50
+ # (img, samples = 5, threshold = 0.95, fuzz_factor = 0.5) # initially
51
51
  # (img, samples = 50, threshold = 0.9, fuzz_factor = 0.1) # semi-working on synthetic images 08-dec-2014 (x)
52
52
  # (img, samples = 20, threshold = 0.8, fuzz_factor = 0.2) # WORKS with synthetic images and changes to x0, y0, width, height
53
- #
53
+ #
54
54
  # appears to assume sharp transition will occur in 5 pixels x/y
55
55
  #
56
56
  # how is threshold defined?
@@ -33,8 +33,8 @@ class Sqed
33
33
  @layout = opts[:layout]
34
34
  @image = opts[:image]
35
35
 
36
- raise 'No layout provided.' if layout.nil?
37
- raise 'No image provided.' if image.nil? || image.class.name != 'Magick::Image'
36
+ raise Sqed::Error, 'No layout provided.' if layout.nil?
37
+ raise Sqed::Error, 'No image provided.' if image.nil? || image.class.name != 'Magick::Image'
38
38
 
39
39
  true
40
40
  end
@@ -166,7 +166,7 @@ class Sqed
166
166
  elsif scan == :columns
167
167
  j = image.crop(s * sample_subdivision_size, 0, 1, image.rows, true)
168
168
  else
169
- raise
169
+ raise Sqed::Error
170
170
  end
171
171
 
172
172
  j.each_pixel do |pixel, c, r|
@@ -4,6 +4,10 @@ class Sqed
4
4
 
5
5
  # An Extractor takes Boundaries object and a metadata_map and returns a Sqed::Result
6
6
  #
7
+ # Extract assumes a successful preprocessing (e.g. finding boundaries, cropping images)!
8
+ #
9
+ # Only Tesseract based raises errors should be occurring at this point.
10
+ #
7
11
  class Extractor
8
12
 
9
13
  class Error < StandardError; end;
@@ -23,9 +27,10 @@ class Sqed
23
27
  @boundaries = opts[:boundaries]
24
28
  @image = opts[:image]
25
29
 
26
- raise Error, 'boundaries not provided or provided boundary is not a Sqed::Boundaries' if boundaries.nil? || !boundaries.class.name == 'Sqed::Boundaries'
27
- raise Error, 'metadata_map not provided or metadata_map not a Hash' if metadata_map.nil? || !metadata_map.class.name == 'Hash'
28
- raise Error, 'image not provided' if image.nil? || !image.class.name == 'Magick::Image'
30
+ # TODO: `.extractable?` catches the nil? case
31
+ raise Sqed::Error, 'boundaries not provided or provided boundary is not a Sqed::Boundaries' if boundaries.nil? || !boundaries.kind_of?(Sqed::Boundaries)
32
+ raise Sqed::Error, 'metadata_map not provided or metadata_map not a Hash' if metadata_map.nil? || !metadata_map.kind_of?(Hash)
33
+ raise Sqed::Error, 'image not provided' if image.nil? || !image.kind_of?(Magick::Image)
29
34
  end
30
35
 
31
36
  def result
data/lib/sqed/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Sqed
2
- VERSION = '0.7.0'.freeze
2
+ VERSION = '0.8.0'.freeze
3
3
  end
data/lib/sqed.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  recent_ruby = RUBY_VERSION >= '2.4.1'
4
- raise 'IMPORTANT: sqed gem requires ruby >= 2.4.1' unless recent_ruby
4
+ raise Sqed::Error, 'IMPORTANT: sqed gem requires ruby >= 2.4.1' unless recent_ruby
5
5
 
6
6
  require 'rmagick'
7
7
  require 'sqed_utils'
@@ -23,9 +23,33 @@ class Sqed
23
23
  require_relative 'sqed/result'
24
24
 
25
25
 
26
- # initial image which is an instance of ImageMagick::Image, containing background and stage, or just stage
26
+ # @return [Sqed::Boundaries instance, nil]
27
+ # Contains the coordinates of the internal stage sections. Calculates when set.
28
+ attr_accessor :boundaries
29
+
30
+ # @return [Symbol] like `:red`, `:green`, `:blue`, defaults to `:green`
31
+ # describing the boundary color within the stage
32
+ attr_accessor :boundary_color
33
+
34
+ # @return [Sqed::BoundaryFinder::<Klass>]
35
+ # Provide a boundary_finder, overrides metadata taken from pattern
36
+ attr_accessor :boundary_finder
37
+
38
+ # @return [Boolean] defaults to `true`
39
+ # when true detects border on initialization
40
+ attr_accessor :has_border
41
+
42
+ # initial image which is an instance of Magick::Image, containing background and stage, or just stage
27
43
  attr_accessor :image
28
44
 
45
+ # @return [Symbol] like `:cross`
46
+ # !! Provide a specific layout, passed as option :layout, overrides layout metadata taken from :pattern, defaults to `:cross`
47
+ attr_accessor :layout
48
+
49
+ # Provide a metadata map, overrides metadata taken from pattern.
50
+ # No calculations are done here.
51
+ attr_accessor :metadata_map
52
+
29
53
  # !optional! A lookup macro that if provided sets boundary_finder, layout, and metadata_map.
30
54
  # These can be individually overwritten.
31
55
  # Legal values are symbols taken from SqedConfig::EXTRACTION_PATTERNS.
@@ -39,41 +63,20 @@ class Sqed
39
63
  # not required if layout, metadata_map, and boundary_finder are provided
40
64
  attr_accessor :pattern
41
65
 
42
- # @return [Symbol] like `:cross`
43
- # !! Provide a specific layout, passed as option :layout, overrides layout metadata taken from :pattern, defaults to `:cross`
44
- attr_accessor :layout
45
-
46
- # the image that is the cropped content for parsing
66
+ # The image that is the cropped content for parsing
67
+ # !! Does not require `metadata_map` or `layout`
47
68
  attr_accessor :stage_image
48
69
 
49
70
  # @return [Sqed::Boundaries instance]
50
71
  # stores the coordinates of the stage
72
+ # !! Does not require `metadata_map` or `layout`
51
73
  attr_accessor :stage_boundary
52
74
 
53
- # @return [Sqed::Boundaries instance]
54
- # contains the coordinates of the internal stage sections
55
- attr_accessor :boundaries
56
-
57
- # @return [Boolean] defaults to `true`
58
- # when true detects border on initialization
59
- attr_accessor :has_border
60
-
61
- # @return [Symbol] like `:red`, `:green`, `:blue`, defaults to `:green`
62
- # describing the boundary color within the stage
63
- attr_accessor :boundary_color
64
-
65
75
  # @return [Boolean] defaults to `true` (faster, less accurate)
66
76
  # if `true` do the boundary detection (not stage detection at present)
67
77
  # against a thumbnail version of the passed image
68
78
  attr_accessor :use_thumbnail
69
79
 
70
- # Provide a metadata map, overrides metadata taken from pattern
71
- attr_accessor :metadata_map
72
-
73
- # @return [Sqed::BoundaryFinder::<Klass>]
74
- # Provide a boundary_finder, overrides metadata taken from pattern
75
- attr_accessor :boundary_finder
76
-
77
80
  def initialize(**opts)
78
81
  # extraction metadata
79
82
  @image = opts[:image]
@@ -86,71 +89,102 @@ class Sqed
86
89
  # federate extraction options
87
90
  def extraction_metadata
88
91
  {
89
- boundary_finder: boundary_finder,
90
- layout: layout,
91
- metadata_map: metadata_map,
92
- boundary_color: boundary_color,
93
- has_border: has_border,
94
- use_thumbnail: use_thumbnail
92
+ boundary_finder: boundary_finder,
93
+ layout: layout,
94
+ metadata_map: metadata_map,
95
+ boundary_color: boundary_color,
96
+ has_border: has_border,
97
+ use_thumbnail: use_thumbnail
95
98
  }
96
99
  end
97
100
 
98
- # @return [ImageMagick::Image]
101
+ # @return [Magick::Image]
99
102
  # set the image if it's not set during initialize(), not commonly used
100
103
  def image=(value)
101
- @image = value
102
- set_stage_boundary
103
- @image
104
- end
105
-
106
- def boundaries(force = false)
107
- @boundaries = get_section_boundaries if @boundaries.nil? || force
108
- @boundaries
104
+ @image = value if value.kind_of?(::Magick::Image)
109
105
  end
110
106
 
111
107
  def stage_boundary
112
- set_stage_boundary if !@stage_boundary.populated?
108
+ compute_stage_boundary if !@stage_boundary.populated?
113
109
  @stage_boundary
114
110
  end
115
111
 
116
112
  def stage_image
117
- crop_image if @stage_image.nil?
118
- @stage_image
119
- end
120
-
121
- # @return [Sqed::Boundaries instance, nil]
122
- # a boundaries instance that has the original image (prior to cropping stage) coordinates
123
- def native_boundaries
124
- if @boundaries.complete
125
- @boundaries.offset(stage_boundary)
126
- else
127
- nil
128
- end
113
+ @stage_image ||= crop_image
129
114
  end
130
115
 
131
116
  # @return [Image]
132
117
  # crops the stage if not done, then sets/returns @stage_image
133
118
  def crop_image
134
- if has_border
135
- @stage_image = image.crop(*stage_boundary.for(SqedConfig.index_for_section_type(:stage, :stage)), true)
136
- else
137
- @stage_image = image
119
+
120
+ begin
121
+
122
+ if has_border && image
123
+ @stage_image = image.crop(*stage_boundary.for(SqedConfig.index_for_section_type(:stage, :stage)), true)
124
+ elsif image
125
+ @stage_image = image
126
+ end
127
+ @stage_image
128
+
129
+ rescue Sqed::Error
130
+ raise
131
+ rescue
132
+ raise Sqed::Error, 'error cropping image'
133
+ end
134
+
135
+ end
136
+
137
+ def boundaries(force = false)
138
+ begin
139
+
140
+ if force
141
+ @boundaries = get_section_boundaries
142
+ else
143
+ @boundaries ||= get_section_boundaries
144
+ end
145
+
146
+ @boundaries
147
+
148
+ rescue Sqed::Error
149
+ raise
150
+ rescue # XXXX
151
+ raise Sqed::Error, 'error processing boundaries'
138
152
  end
139
- @stage_image
140
153
  end
141
154
 
155
+ # @return [Boolean]
156
+ # `true` if all boundary detection and image processing
157
+ # has been calculated with error
158
+ #
159
+ def extractable?
160
+ stage_image && metadata_map && boundaries
161
+ end
162
+
163
+ # @return [Sqed::Result, false]
142
164
  def result
143
- return false if image.nil?
165
+ return false unless extractable?
144
166
 
145
167
  extractor = Sqed::Extractor.new(
146
168
  boundaries: boundaries,
147
- metadata_map: metadata_map, # extraction_metadata[:metadata_map],
169
+ metadata_map: metadata_map,
148
170
  image: stage_image
149
171
  )
150
172
 
151
173
  extractor.result
152
174
  end
153
175
 
176
+ private
177
+
178
+ # @return [Sqed::Boundaries instance, nil]
179
+ # a boundaries instance that has the original image (prior to cropping stage) coordinates
180
+ def native_boundaries
181
+ if @boundaries.complete
182
+ @boundaries.offset(stage_boundary)
183
+ else
184
+ nil
185
+ end
186
+ end
187
+
154
188
  # @return [Hash]
155
189
  # an overview of data/metadata, for debugging purposes only
156
190
  def attributes
@@ -160,8 +194,6 @@ class Sqed
160
194
  }.merge!(extraction_metadata)
161
195
  end
162
196
 
163
- protected
164
-
165
197
  def configure(opts)
166
198
  configure_from_pattern(opts[:pattern])
167
199
  configure_boundary_finder(opts)
@@ -183,7 +215,7 @@ class Sqed
183
215
  def configure_from_pattern(value)
184
216
  return if value.nil?
185
217
  value = value.to_sym
186
- raise "provided extraction pattern '#{value}' not defined" if !SqedConfig::EXTRACTION_PATTERNS.keys.include?(value)
218
+ raise Sqed::Error, "provided extraction pattern '#{value}' not defined" if !SqedConfig::EXTRACTION_PATTERNS.keys.include?(value)
187
219
  @pattern = value
188
220
  a = SqedConfig::EXTRACTION_PATTERNS[pattern]
189
221
  @boundary_finder = a[:boundary_finder]
@@ -213,31 +245,34 @@ class Sqed
213
245
  def stub_results
214
246
  @boundaries = nil
215
247
  @stage_boundary = Sqed::Boundaries.new(:internal_box)
216
- set_stage_boundary if @image
248
+ compute_stage_boundary if @image
217
249
  end
218
250
 
251
+ # @return [Boundaries, nil]
219
252
  def get_section_boundaries
253
+
220
254
  boundary_finder.new(**section_params).boundaries
255
+
221
256
  end
222
257
 
223
258
  # @return [Hash]
224
259
  # variables for the isolated stage image
225
260
  def section_params
226
261
  {
227
- image: stage_image,
228
- use_thumbnail: use_thumbnail,
229
- layout: layout,
230
- boundary_color: boundary_color
262
+ image: stage_image,
263
+ use_thumbnail: use_thumbnail,
264
+ layout: layout,
265
+ boundary_color: boundary_color
231
266
  }
232
267
  end
233
268
 
234
- def set_stage_boundary
269
+ def compute_stage_boundary
235
270
  if has_border
236
271
  boundary = Sqed::BoundaryFinder::StageFinder.new(image: image).boundaries
237
- if boundary.populated?
272
+ if boundary&.populated?
238
273
  @stage_boundary.set(0, boundary.for(0))
239
274
  else
240
- raise 'error detecting stage'
275
+ raise Sqed::Error, 'error detecting stage'
241
276
  end
242
277
  else
243
278
  @stage_boundary.set(0, [0, 0, image.columns, image.rows])
data/lib/sqed_config.rb CHANGED
@@ -50,12 +50,7 @@ module SqedConfig
50
50
  # 6 |---- 3
51
51
  # | 4 |
52
52
  #
53
- #
54
- # | 1
55
- # 0 |---- :right_t
56
- # | 2
57
- #
58
- #
53
+ # #
59
54
  # 0 | 1 | 2
60
55
  # ------------
61
56
  # | 5 | 3 :seven_slot
@@ -73,35 +68,50 @@ module SqedConfig
73
68
  # 0 | 1 :vertical_split
74
69
  # |
75
70
  #
71
+ # -------
72
+ # |-----|
73
+ # || 0 || :internal_box
74
+ # |-----|
75
+ # -------
76
+ #
77
+ # 0 :t
76
78
  # -----
77
- # | 0 | :internal_box
78
- # -----
79
+ # 2 | 1
80
+ #
79
81
  #
80
82
  # 0 | 1 :inverted_t
81
83
  # -----
82
84
  # 2
83
85
  #
84
- # 0 :t
85
- # -----
86
- # 2 | 1
86
+ # 0 |
87
+ # ---| 1 : left_t
88
+ # 2 |
87
89
  #
90
+ # | 1
91
+ # 0 |--- :right_t
92
+ # | 2
88
93
  #
94
+ # -----
95
+ # | 0 | :stage
96
+ # -----
89
97
  #
90
98
  # Hash values are used to stub out
91
99
  # the Sqed::Boundaries instance.
92
100
  LAYOUTS = {
93
101
  t: [0,1,2],
94
102
  inverted_t: [0, 1, 2],
103
+ right_t: [0, 1, 2],
104
+ left_t: [0, 1, 2],
95
105
  cross: [0, 1, 2, 3],
96
106
  horizontal_offset_cross: [0, 1, 2, 3],
97
107
  horizontal_split: [0, 1],
98
108
  lep_stage: [0, 1, 2, 3, 4, 5, 6],
99
109
  lep_stage2: [0, 1, 2, 3, 4, 5, 6],
100
- right_t: [0, 1, 2],
101
110
  seven_slot: [0, 1, 2, 3, 4, 5, 6],
102
111
  vertical_offset_cross: [0, 1, 2, 3],
103
112
  vertical_split: [0, 1],
104
- internal_box: [0]
113
+ internal_box: [0],
114
+ stage: [0]
105
115
  }.freeze
106
116
 
107
117
  # Each element of the layout is a "section".
@@ -177,6 +187,12 @@ module SqedConfig
177
187
  metadata_map: { 0 => :curator_metadata, 1 => :collecting_event_labels, 2 => :image_registration, 3 => :identifier, 4 => :other_labels, 5 => :determination_labels, 6 => :specimen }
178
188
  },
179
189
 
190
+ left_t: {
191
+ boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
192
+ layout: :right_t,
193
+ metadata_map: { 0 => :annotated_specimen, 1 => :identifier, 2 => :image_registration }
194
+ },
195
+
180
196
  right_t: {
181
197
  boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
182
198
  layout: :right_t,
@@ -7,11 +7,11 @@ describe SqedConfig do
7
7
  end
8
8
 
9
9
  specify 'layouts' do
10
- expect(SqedConfig.metadata[:layouts].keys).to contain_exactly(:t, :inverted_t, :cross, :horizontal_offset_cross, :horizontal_split, :lep_stage, :lep_stage2, :right_t, :seven_slot, :vertical_offset_cross, :vertical_split)
10
+ expect(SqedConfig.metadata[:layouts].keys).to contain_exactly(:stage, :t, :left_t, :inverted_t, :cross, :horizontal_offset_cross, :horizontal_split, :lep_stage, :lep_stage2, :right_t, :seven_slot, :vertical_offset_cross, :vertical_split)
11
11
  end
12
12
 
13
13
  specify 'layouts are in patterns' do
14
- expect(SqedConfig.metadata[:layouts].keys + [:stage]).to contain_exactly(*SqedConfig::EXTRACTION_PATTERNS.keys)
14
+ expect(SqedConfig.metadata[:layouts].keys).to contain_exactly(*SqedConfig::EXTRACTION_PATTERNS.keys)
15
15
  end
16
16
 
17
17
  end
@@ -2,10 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Sqed do
4
4
 
5
- let(:s) { Sqed.new(
6
- pattern: :cross
7
- )
8
- }
5
+ let(:s) { Sqed.new( pattern: :cross) }
9
6
 
10
7
  context 'attributes' do
11
8
 
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'handling T stage images' do
4
+
5
+ let(:image) { ImageHelpers.left_t_stage }
6
+ let(:sqed) do
7
+ Sqed.new(
8
+ image: image,
9
+ pattern: :left_t,
10
+ boundary_color: :red,
11
+ has_border: false )
12
+ end
13
+
14
+ let(:m) do
15
+ { 0 => 'annotated_specimen',
16
+ 1 => 'identifier',
17
+ 2 => 'image_registration'
18
+ }
19
+ end
20
+
21
+ context 'simple boundaries - without thumbnail' do
22
+ let(:s) { Sqed.new(
23
+ image: image, metadata_map: m, use_thumbnail: false,
24
+ layout: :left_t,
25
+ boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
26
+ boundary_color: :red,
27
+ has_border: false ) }
28
+
29
+ specify 'boundaries are reasonable' do
30
+ s.result
31
+ c = s.boundaries.coordinates
32
+ c.each do |section, values|
33
+ c[section].each_with_index do |v, i|
34
+ msg = "section #{section}, index #{i} has a bad value '#{v}'"
35
+ expect(v > -1).to be_truthy, msg
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ context 'boundaries - with_thumbnail' do
42
+ let(:s) { Sqed.new(
43
+ image: image,
44
+ use_thumbnail: true,
45
+ pattern: :left_t,
46
+ boundary_color: :red,
47
+ has_border: false ) }
48
+
49
+ specify 'boundaries are reasonable' do
50
+ s.result
51
+ c = s.boundaries.coordinates
52
+ c.each do |section, values|
53
+ c[section].each_with_index do |v, i|
54
+ msg = "section #{section}, index #{i} has a bad value '#{v}'"
55
+ expect(v > -1).to be_truthy, msg
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'handling stage images' do
4
+
5
+ let(:image) { ImageHelpers.stage }
6
+ let(:sqed) do
7
+ Sqed.new(
8
+ image: image,
9
+ pattern: :stage,
10
+ has_border: false )
11
+ end
12
+
13
+ let(:m) do
14
+ { 0 => 'stage' }
15
+ end
16
+
17
+ context 'simple boundaries - without thumbnail' do
18
+ let(:s) { Sqed.new(
19
+ image: image, metadata_map: m, use_thumbnail: false,
20
+ layout: :stage,
21
+ boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
22
+ has_border: false ) }
23
+
24
+ specify 'boundaries are reasonable' do
25
+ s.result
26
+ c = s.boundaries.coordinates
27
+ c.each do |section, values|
28
+ c[section].each_with_index do |v, i|
29
+ msg = "section #{section}, index #{i} has a bad value '#{v}'"
30
+ expect(v > -1).to be_truthy, msg
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ context 'boundaries - with_thumbnail' do
37
+ let(:s) { Sqed.new(
38
+ image: image,
39
+ use_thumbnail: true,
40
+ pattern: :stage,
41
+ has_border: false ) }
42
+
43
+ specify 'boundaries are reasonable' do
44
+ s.result
45
+ c = s.boundaries.coordinates
46
+ c.each do |section, values|
47
+ c[section].each_with_index do |v, i|
48
+ msg = "section #{section}, index #{i} has a bad value '#{v}'"
49
+ expect(v > -1).to be_truthy, msg
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ end
@@ -16,6 +16,10 @@ module ImageHelpers
16
16
 
17
17
  # Stage images
18
18
 
19
+ def stage
20
+ get_image 'stage_images/stage.png'
21
+ end
22
+
19
23
  def t_stage
20
24
  get_image 'stage_images/t_stage.png'
21
25
  end
@@ -24,6 +28,10 @@ module ImageHelpers
24
28
  get_image 'stage_images/inverted_t_stage.png'
25
29
  end
26
30
 
31
+ def left_t_stage
32
+ get_image 'stage_images/left_t_stage.png'
33
+ end
34
+
27
35
  def cross_green
28
36
  get_image 'stage_images/boundary_cross_green.jpg'
29
37
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqed
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Yoder
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-05-07 00:00:00.000000000 Z
12
+ date: 2023-05-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -156,9 +156,11 @@ files:
156
156
  - spec/lib/sqed_utils_spec.rb
157
157
  - spec/lib/stage_handling/horizontal_offset_cross_spec.rb
158
158
  - spec/lib/stage_handling/inverted_t_stage_spec.rb
159
+ - spec/lib/stage_handling/left_t_stage_spec.rb
159
160
  - spec/lib/stage_handling/lep_stage2_spec.rb
160
161
  - spec/lib/stage_handling/lep_stage_spec.rb
161
162
  - spec/lib/stage_handling/seven_slot_spec.rb
163
+ - spec/lib/stage_handling/stage_spec.rb
162
164
  - spec/lib/stage_handling/t_stage_spec.rb
163
165
  - spec/spec_helper.rb
164
166
  - spec/support/files/barcode_images/code_128_barcode.png
@@ -188,9 +190,11 @@ files:
188
190
  - spec/support/files/stage_images/inhs_7_slot3.jpg
189
191
  - spec/support/files/stage_images/inhs_four_thirds.jpg
190
192
  - spec/support/files/stage_images/inverted_t_stage.png
193
+ - spec/support/files/stage_images/left_t_stage.png
191
194
  - spec/support/files/stage_images/lep_stage.jpg
192
195
  - spec/support/files/stage_images/lep_stage2.jpg
193
196
  - spec/support/files/stage_images/lep_stage3.jpg
197
+ - spec/support/files/stage_images/stage.png
194
198
  - spec/support/files/stage_images/t_stage.png
195
199
  - spec/support/files/test0.jpg
196
200
  - spec/support/files/test1.jpg
@@ -219,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
219
223
  - !ruby/object:Gem::Version
220
224
  version: '0'
221
225
  requirements: []
222
- rubygems_version: 3.2.22
226
+ rubygems_version: 3.4.12
223
227
  signing_key:
224
228
  specification_version: 4
225
229
  summary: Specimens Quickly extracted and Digitized, or just "squid". A ruby gem for
@@ -240,9 +244,11 @@ test_files:
240
244
  - spec/lib/sqed_utils_spec.rb
241
245
  - spec/lib/stage_handling/horizontal_offset_cross_spec.rb
242
246
  - spec/lib/stage_handling/inverted_t_stage_spec.rb
247
+ - spec/lib/stage_handling/left_t_stage_spec.rb
243
248
  - spec/lib/stage_handling/lep_stage2_spec.rb
244
249
  - spec/lib/stage_handling/lep_stage_spec.rb
245
250
  - spec/lib/stage_handling/seven_slot_spec.rb
251
+ - spec/lib/stage_handling/stage_spec.rb
246
252
  - spec/lib/stage_handling/t_stage_spec.rb
247
253
  - spec/spec_helper.rb
248
254
  - spec/support/files/barcode_images/code_128_barcode.png
@@ -272,9 +278,11 @@ test_files:
272
278
  - spec/support/files/stage_images/inhs_7_slot3.jpg
273
279
  - spec/support/files/stage_images/inhs_four_thirds.jpg
274
280
  - spec/support/files/stage_images/inverted_t_stage.png
281
+ - spec/support/files/stage_images/left_t_stage.png
275
282
  - spec/support/files/stage_images/lep_stage.jpg
276
283
  - spec/support/files/stage_images/lep_stage2.jpg
277
284
  - spec/support/files/stage_images/lep_stage3.jpg
285
+ - spec/support/files/stage_images/stage.png
278
286
  - spec/support/files/stage_images/t_stage.png
279
287
  - spec/support/files/test0.jpg
280
288
  - spec/support/files/test1.jpg