sqed 0.7.1 → 0.8.0
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 +4 -4
- data/lib/sqed/boundaries.rb +80 -80
- data/lib/sqed/boundary_finder/color_line_finder.rb +11 -1
- data/lib/sqed/boundary_finder/stage_finder.rb +3 -3
- data/lib/sqed/extractor.rb +8 -3
- data/lib/sqed/version.rb +1 -1
- data/lib/sqed.rb +104 -69
- data/lib/sqed_config.rb +29 -13
- data/spec/lib/sqed_config_spec.rb +2 -2
- data/spec/lib/sqed_spec.rb +1 -4
- data/spec/lib/stage_handling/left_t_stage_spec.rb +61 -0
- data/spec/lib/stage_handling/stage_spec.rb +55 -0
- data/spec/support/files/stage_images/left_t_stage.png +0 -0
- data/spec/support/files/stage_images/stage.png +0 -0
- data/spec/support/image_helpers.rb +8 -0
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ecff3bc24d06653a25e90dd950faea277de23da61cdc7503e288d6098d8c4250
|
4
|
+
data.tar.gz: dd87d00a794d8edf2387c6d37d01382480ab0c161963f063764fadeee75a7f40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52aab726722c000e95af2e3e0de8e2ac584191972d74f6efa7e8127ee70404ebca0eb80493b2686f596e82a836a7302bcbc9f98b8d42759491d74313bd0f98f4
|
7
|
+
data.tar.gz: 2594a64f5b2f575515690314176aa00db01a69dfaef925aa5a1449c7e88b67373f20060f9f4fc172b5b07198c15636d3815a95d7d518e5380d45eda82924cefe
|
data/lib/sqed/boundaries.rb
CHANGED
@@ -6,108 +6,108 @@ class Sqed
|
|
6
6
|
# Layouts are Hashes defined in EXTRACTION_PATTERNS[<pattern>][<layout>]
|
7
7
|
#
|
8
8
|
class Boundaries
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
58
|
-
|
59
|
-
|
57
|
+
def for(section)
|
58
|
+
@coordinates[section]
|
59
|
+
end
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
# Overrides Enumerable
|
68
|
+
def count
|
69
|
+
@coordinates.length
|
70
|
+
end
|
71
71
|
|
72
|
-
|
73
|
-
|
74
|
-
|
72
|
+
def x_for(index)
|
73
|
+
@coordinates[index][0]
|
74
|
+
end
|
75
75
|
|
76
|
-
|
77
|
-
|
78
|
-
|
76
|
+
def y_for(index)
|
77
|
+
@coordinates[index][1]
|
78
|
+
end
|
79
79
|
|
80
|
-
|
81
|
-
|
82
|
-
|
80
|
+
def width_for(index)
|
81
|
+
@coordinates[index][2]
|
82
|
+
end
|
83
83
|
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
def height_for(index)
|
85
|
+
@coordinates[index][3]
|
86
|
+
end
|
87
87
|
|
88
|
-
|
89
|
-
|
90
|
-
|
88
|
+
def set(index, coordinates)
|
89
|
+
@coordinates[index] = coordinates
|
90
|
+
end
|
91
91
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
102
|
-
|
103
|
-
|
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
|
@@ -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 #
|
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?
|
data/lib/sqed/extractor.rb
CHANGED
@@ -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
|
-
|
27
|
-
raise Sqed::Error, '
|
28
|
-
raise Sqed::Error, '
|
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
data/lib/sqed.rb
CHANGED
@@ -23,9 +23,33 @@ class Sqed
|
|
23
23
|
require_relative 'sqed/result'
|
24
24
|
|
25
25
|
|
26
|
-
#
|
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
|
-
#
|
43
|
-
# !!
|
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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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 [
|
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
|
-
|
108
|
+
compute_stage_boundary if !@stage_boundary.populated?
|
113
109
|
@stage_boundary
|
114
110
|
end
|
115
111
|
|
116
112
|
def stage_image
|
117
|
-
|
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
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
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
|
165
|
+
return false unless extractable?
|
144
166
|
|
145
167
|
extractor = Sqed::Extractor.new(
|
146
168
|
boundaries: boundaries,
|
147
|
-
metadata_map: 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)
|
@@ -213,28 +245,31 @@ class Sqed
|
|
213
245
|
def stub_results
|
214
246
|
@boundaries = nil
|
215
247
|
@stage_boundary = Sqed::Boundaries.new(:internal_box)
|
216
|
-
|
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
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
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
|
269
|
+
def compute_stage_boundary
|
235
270
|
if has_border
|
236
271
|
boundary = Sqed::BoundaryFinder::StageFinder.new(image: image).boundaries
|
237
|
-
if boundary
|
272
|
+
if boundary&.populated?
|
238
273
|
@stage_boundary.set(0, boundary.for(0))
|
239
274
|
else
|
240
275
|
raise Sqed::Error, 'error detecting stage'
|
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
|
-
# |
|
78
|
-
#
|
79
|
+
# 2 | 1
|
80
|
+
#
|
79
81
|
#
|
80
82
|
# 0 | 1 :inverted_t
|
81
83
|
# -----
|
82
84
|
# 2
|
83
85
|
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
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
|
14
|
+
expect(SqedConfig.metadata[:layouts].keys).to contain_exactly(*SqedConfig::EXTRACTION_PATTERNS.keys)
|
15
15
|
end
|
16
16
|
|
17
17
|
end
|
data/spec/lib/sqed_spec.rb
CHANGED
@@ -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
|
Binary file
|
Binary file
|
@@ -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.
|
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:
|
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.
|
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
|