sqed 0.1.7 → 0.1.8

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
  SHA1:
3
- metadata.gz: bc7181ce86a616f52763dc679ac56b8a61757af2
4
- data.tar.gz: adad2a5e8268883aa92773ca9c9bb7e7388993b6
3
+ metadata.gz: 639226420485cffa59f748b6c0e5c66db21b239e
4
+ data.tar.gz: 425bd2c26e16339e4ef7b61b605f90bf2efb42db
5
5
  SHA512:
6
- metadata.gz: 48aad3560defbe2d110b108e137150bd00642fee93c7d3fdc230617395ee6e9c401d8bd1ed03164e509ff036fffad44cff4e46867d5e8125c8ccf88da7d2ab21
7
- data.tar.gz: f86ca07a14ffab425ce2dad714f3a4d8a3d0676b62ca2abcba6b7c7d199bec580b8dbcc4fe2b83894bb9031123b9c49d40eff99fe92d9076643cb7fe0be59760
6
+ metadata.gz: 0b40ba1db0b861fb88769d99997c840931f916dacd1731b0f321828c54fbe033e552c879298a0e2a5057b3859a534487c298e8870fbd4ea7316b3351e95a4504
7
+ data.tar.gz: 7bd37213c089d409778291ad30aa63c5c65a0ebdd10a311ed376388b9eddc2134da234b788600b7d4213042c6290ccb88a120969d5de08aed9571cd9d5c2a2f6
@@ -77,13 +77,13 @@ class Sqed
77
77
  # federate extraction options and apply user provided over-rides
78
78
  def extraction_metadata
79
79
  data = SqedConfig::EXTRACTION_PATTERNS[@pattern]
80
-
80
+
81
+ data.merge!(boundary_color: boundary_color)
81
82
  data.merge!(boundary_finder: @boundary_finder) if boundary_finder
83
+ data.merge!(has_border: has_border)
82
84
  data.merge!(layout: layout) if layout
83
85
  data.merge!(metadata_map: metadata_map) if metadata_map
84
- data.merge!(has_border: has_border)
85
86
  data.merge!(use_thumbnail: use_thumbnail)
86
- data.merge!(boundary_color: boundary_color)
87
87
  data
88
88
  end
89
89
 
@@ -133,6 +133,7 @@ class Sqed
133
133
  end
134
134
 
135
135
  def result
136
+ # pattern.nil? is no longer true -> must have values for all extraction_metadata keys
136
137
  return false if image.nil? || pattern.nil?
137
138
  extractor = Sqed::Extractor.new(
138
139
  boundaries: boundaries,
@@ -95,8 +95,8 @@ class Sqed::BoundaryFinder
95
95
  end
96
96
  end
97
97
 
98
- # @return
99
- # the column (x position) in the middle of the single green vertical line dividing the stage
98
+ # @return [Array]
99
+ # the x or y position returned as a start, mid, and end coordinate that represent the width of the colored line that completely divides the image, e.g. [9, 15, 16]
100
100
  #
101
101
  # @param image
102
102
  # the image to sample
@@ -178,7 +178,7 @@ class Sqed::BoundaryFinder
178
178
  end
179
179
 
180
180
  # return [Array]
181
- # the median position of all (pixel) positions that have a count greater than the cutoff
181
+ # the start, mid, endpoint position of all (pixel) positions that have a count greater than the cutoff
182
182
  def self.frequency_stats(frequency_hash, sample_cutoff = 0)
183
183
 
184
184
  return nil if sample_cutoff.nil? || sample_cutoff < 1
@@ -1,6 +1,6 @@
1
1
  require 'rmagick'
2
2
 
3
- # This was "green" line finder attempting to be agnostic; now it is reworked to be color-specific line finder
3
+ # An agnostic pattern finder for color-line delimited boundaries
4
4
  #
5
5
  class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
6
6
 
@@ -21,20 +21,45 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
21
21
  def find_bands
22
22
  case @layout # boundaries.coordinates are referenced from stage image
23
23
 
24
- when :vertical_split # can vertical and horizontal split be re-used to do cross cases?
25
- t = Sqed::BoundaryFinder.color_boundary_finder(image: img, boundary_color: @boundary_color) #detect vertical division, green line
24
+ # No specs for this yet
25
+ when :seven_slot
26
+ top_bottom_split = Sqed::BoundaryFinder.color_boundary_finder(image: img, scan: :columns, boundary_color: @boundary_color) # detect vertical division [array]
27
+ left_right_split = Sqed::BoundaryFinder.color_boundary_finder(image: img, sample_subdivision_size: 2, boundary_color: @boundary_color) # detect horizontal division [array]
28
+
29
+ boundaries.set(0, [0, 0, left_right_split[0], top_bottom_split[0] ])
30
+ boundaries.set(6, [0, top_bottom_split[2], left_right_split[0], img.rows - top_bottom_split[2] ] )
31
+
32
+ right_top_img = img.crop( left_right_split[2], 0, img.columns - left_right_split[2], top_bottom_split[0] , true) # sections 1,2
33
+ right_bottom_img = img.crop(left_right_split[2], top_bottom_split[2], img.columns - left_right_split[2], img.rows - top_bottom_split[2], true) # sections 3,4,5
34
+
35
+ right_top_split = Sqed::BoundaryFinder.color_boundary_finder(image: right_top_img, boundary_color: @boundary_color) # vertical line b/w 1 & 2
36
+
37
+ boundaries.set(1, [left_right_split[2], 0, left_right_split[2] + right_top_split[0], top_bottom_split[0] ])
38
+ boundaries.set(2, [left_right_split[2] + right_top_split[2], 0, right_top_img.columns - right_top_split[2], top_bottom_split[0] ] )
39
+
40
+ right_bottom_split = Sqed::BoundaryFinder.color_boundary_finder(image: right_bottom_img, scan: :columns, sample_subdivision_size: 2, boundary_color: @boundary_color) # horizontal line b/w (5,3) & 4
41
+
42
+ bottom_right_top_img = right_bottom_img.crop(0,0, img.columns - left_right_split[2], right_bottom_split[1], true) # 3,5 - we leave right_bottom_split at [1] (not 2) to take into account possible overlap error (crop gets full line at top of image)
43
+
44
+ boundaries.set(3, [ left_right_split[2] + right_top_split[2], top_bottom_split[2], left_right_split[2] + right_top_split[2], bottom_right_top_img.rows ] )
45
+ boundaries.set(5, [ left_right_split[2], top_bottom_split[2], left_right_split[2] + right_top_split[0], bottom_right_top_img.rows ] )
46
+
47
+ boundaries.set(4, [ left_right_split[2], top_bottom_split[2] + right_top_split[2], img.columns - left_right_split[2], right_bottom_img.rows - right_top_split[2] ] )
48
+
49
+ when :vertical_split
50
+ t = Sqed::BoundaryFinder.color_boundary_finder(image: img, boundary_color: @boundary_color) #detect vertical division
26
51
  return if t.nil?
27
52
  boundaries.set(0, [0, 0, t[0], img.rows]) # left section of image
28
53
  boundaries.set(1, [t[2], 0, img.columns - t[2], img.rows]) # right section of image
29
54
 
30
55
  when :horizontal_split
31
- t = Sqed::BoundaryFinder.color_boundary_finder(image: img, scan: :columns, boundary_color: @boundary_color) # set to detect horizontal division, (green line)
56
+ t = Sqed::BoundaryFinder.color_boundary_finder(image: img, scan: :columns, boundary_color: @boundary_color) # set to detect horizontal division
32
57
  return if t.nil?
33
58
 
34
59
  boundaries.set(0, [0, 0, img.columns, t[0]]) # upper section of image
35
60
  boundaries.set(1, [0, t[2], img.columns, img.rows - t[2]]) # lower section of image
36
61
 
37
- when :right_t # only 3 zones expected, with horizontal division in right-side of vertical division
62
+ when :right_t # only 3 zones expected, with horizontal division in right-side of vertical division
38
63
  vertical = self.class.new(image: @img, layout: :vertical_split, boundary_color: @boundary_color, use_thumbnail: false ).boundaries
39
64
 
40
65
  irt = img.crop(*vertical.for(1), true)
@@ -50,7 +75,7 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
50
75
  ilt = img.crop(*vertical.for(0), true)
51
76
  irt = img.crop(*vertical.for(1), true)
52
77
 
53
- left = self.class.new(image: ilt, layout: :horizontal_split, boundary_color: @boundary_color, use_thumbnail: false).boundaries # fails
78
+ left = self.class.new(image: ilt, layout: :horizontal_split, boundary_color: @boundary_color, use_thumbnail: false).boundaries # fails
54
79
  right = self.class.new(image: irt, layout: :horizontal_split, boundary_color: @boundary_color, use_thumbnail: false ).boundaries # OK
55
80
 
56
81
  boundaries.set(0, [0, 0, left.width_for(0), left.height_for(0) ])
@@ -61,7 +61,15 @@ class Sqed::Parser::OcrParser < Sqed::Parser
61
61
  },
62
62
  deterimination_labels: {
63
63
  psm: 3
64
+ },
65
+ other_labels: {
66
+ psm: 3
67
+ },
68
+ collecting_event_labels: {
69
+ psm: 3
64
70
  }
71
+
72
+
65
73
  }
66
74
 
67
75
  # the text extracted from the image
@@ -85,16 +93,18 @@ class Sqed::Parser::OcrParser < Sqed::Parser
85
93
  # img.write('tmp/foo4.jpg')
86
94
  # img = img.quantize(2, Magick::GRAYColorspace)
87
95
  # #img = img.threshold(0.5)
88
- # img.write('foo4.jpg') # for debugging purposes, this is the image that is sent to OCR
96
+ # img.write('foo4.jpg')
89
97
  # img = img.equalize #(32, Magick::GRAYColorspace)
90
- # img.write('foo5.jpg') # for debugging purposes, this is the image that is sent to OCR
91
- # #img.write('foo3.jpg') # for debugging purposes, this is the image that is sent to OCR
98
+ # img.write('foo5.jpg')
99
+ # #img.write('foo3.jpg')
92
100
  #
93
- # img.write('foo.jpg') # for debugging purposes, this is the image that is sent to OCR
101
+ # img.write('foo.jpg')
94
102
  # img = img.white_threshold(245)
95
103
  # img
96
104
  # end
97
-
105
+
106
+ # @return [String]
107
+ # the ocr text
98
108
  def text(section_type: :default)
99
109
  img = @image
100
110
  params = SECTION_PARAMS[:default].merge(SECTION_PARAMS[section_type])
@@ -1,3 +1,3 @@
1
1
  class Sqed
2
- VERSION = "0.1.7"
2
+ VERSION = "0.1.8"
3
3
  end
@@ -58,6 +58,14 @@ module SqedConfig
58
58
  # | 0 | :internal_box
59
59
  # -----
60
60
  #
61
+ # 0 | 1 | 2
62
+ # ------------
63
+ # | 5 | 3 :seven_slot
64
+ # 6 |--------
65
+ # | 4
66
+ #
67
+ #
68
+ #
61
69
 
62
70
  # Hash values are used to stub out
63
71
  # the Sqed::Boundaries instance.
@@ -69,29 +77,38 @@ module SqedConfig
69
77
  vertical_split: [0,1],
70
78
  right_t: [0,1,2],
71
79
  left_t: [0,1,2],
72
- internal_box: [0]
80
+ internal_box: [0],
81
+ seven_slot: [0,1,2,3,4,5,6]
73
82
  }
74
83
 
75
84
  # Each element of the layout is a "section".
76
85
  LAYOUT_SECTION_TYPES = [
77
- :stage, # the image contains the full stage
78
- :specimen, # the specimen only, no metadata should be present
79
- :annotated_specimen, # a specimen is present, and metadata is too
80
- :determination_labels, # the section contains text that determines the specimen
81
- :labels, # the section contains collecting event and non-determination labels
82
- :identifier, # the section contains an identifier (e.g. barcode or unique number)
83
- :image_registration, # the section contains only image registration information,
84
- :curator_metadata, # the section contains text with curator metadata
85
- :nothing # section is empty
86
+ :annotated_specimen, # a specimen is present, and metadata is too
87
+ :collecting_event_labels, # the section that contains collecting event labels (only)
88
+ :curator_metadata, # the section contains text with curator metadata
89
+ :determination_labels, # the section contains text that determines the specimen (only)
90
+ :identifier, # the section contains an identifier (e.g. barcode or unique number)
91
+ :image_registration, # the section contains only image registration information,
92
+ :labels, # the section contains collecting event and other non-determination labels
93
+ :nothing, # section is empty
94
+ :other_labels, # the section that contains text that misc.
95
+ :specimen, # the specimen only, no metadata should be present
96
+ :stage, # the image contains the full stage
86
97
  ]
87
98
 
88
99
  # Links section types to data parsers
89
100
  SECTION_PARSERS = {
90
- labels: [ Sqed::Parser::OcrParser ],
91
- identifier: [ Sqed::Parser::BarcodeParser, Sqed::Parser::OcrParser ],
92
- deterimination_labels: [ Sqed::Parser::OcrParser ],
101
+ annotated_specimen: [ Sqed::Parser::OcrParser],
102
+ collecting_event_labels: [ Sqed::Parser::OcrParser],
93
103
  curator_metadata: [ Sqed::Parser::OcrParser ],
94
- annotated_specimen: [ Sqed::Parser::OcrParser]
104
+ deterimination_labels: [ Sqed::Parser::OcrParser ],
105
+ identifier: [ Sqed::Parser::BarcodeParser, Sqed::Parser::OcrParser ],
106
+ image_registration: [],
107
+ labels: [ Sqed::Parser::OcrParser ],
108
+ nothing: [],
109
+ other_labels: [ Sqed::Parser::OcrParser ],
110
+ specimen: [],
111
+ stage: []
95
112
  }
96
113
 
97
114
  EXTRACTION_PATTERNS = {
@@ -123,6 +140,12 @@ module SqedConfig
123
140
  boundary_finder: Sqed::BoundaryFinder::StageFinder,
124
141
  layout: :internal_box,
125
142
  metadata_map: {0 => :stage}
143
+ },
144
+
145
+ seven_slot: {
146
+ boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
147
+ layout: :seven_slot,
148
+ metadata_map: {0 => :collecting_event_labels, 1 => :determination_labels, 2 => :other_labels, 3 => :image_registration, 4 => :curator_metadata, 5 => :identifier, 6 => :specimen }
126
149
  }
127
150
  }
128
151
 
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'handling 7 slot stages' do
4
+
5
+ let(:image) { ImageHelpers.inhs_stage_7_slot }
6
+ let(:sqed) { Sqed.new( image: image, pattern: :seven_slot, boundary_color: :red, has_border: false ) }
7
+
8
+ context 'parses' do
9
+ specify 'new() without errors' do
10
+ expect( sqed ).to be_truthy
11
+ end
12
+
13
+ specify 'get_result without errors' do
14
+ expect( sqed.result ).to be_truthy
15
+ end
16
+ end
17
+
18
+ end
@@ -31,7 +31,9 @@ module ImageHelpers
31
31
  get_image 'stage_images/frost_stage_medimum.jpg'
32
32
  end
33
33
 
34
-
34
+ def inhs_stage_7_slot
35
+ get_image 'stage_images/inhs_7_slot.jpg'
36
+ end
35
37
 
36
38
  def crossy_green_line_specimen
37
39
  get_image 'stage_images/CrossyGreenLinesSpecimen.jpg'
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.1.7
4
+ version: 0.1.8
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: 2015-09-17 00:00:00.000000000 Z
12
+ date: 2015-12-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -176,6 +176,7 @@ files:
176
176
  - spec/lib/sqed/parser_spec.rb
177
177
  - spec/lib/sqed/result_spec.rb
178
178
  - spec/lib/sqed_spec.rb
179
+ - spec/lib/stage_handling/seven_slot_spec.rb
179
180
  - spec/spec_helper.rb
180
181
  - spec/support/files/barcode_images/code_128_barcode.png
181
182
  - spec/support/files/barcode_images/datamatrix_barcode.png
@@ -197,6 +198,8 @@ files:
197
198
  - spec/support/files/stage_images/frost_stage_medium.jpg
198
199
  - spec/support/files/stage_images/frost_stage_thumb.jpg
199
200
  - spec/support/files/stage_images/greenlineimage.jpg
201
+ - spec/support/files/stage_images/inhs_7_slot.jpg
202
+ - spec/support/files/stage_images/inhs_four_thirds.jpg
200
203
  - spec/support/files/test0.jpg
201
204
  - spec/support/files/test1.jpg
202
205
  - spec/support/files/test2.jpg
@@ -242,6 +245,7 @@ test_files:
242
245
  - spec/lib/sqed/parser_spec.rb
243
246
  - spec/lib/sqed/result_spec.rb
244
247
  - spec/lib/sqed_spec.rb
248
+ - spec/lib/stage_handling/seven_slot_spec.rb
245
249
  - spec/spec_helper.rb
246
250
  - spec/support/files/barcode_images/code_128_barcode.png
247
251
  - spec/support/files/barcode_images/datamatrix_barcode.png
@@ -263,6 +267,8 @@ test_files:
263
267
  - spec/support/files/stage_images/frost_stage_medium.jpg
264
268
  - spec/support/files/stage_images/frost_stage_thumb.jpg
265
269
  - spec/support/files/stage_images/greenlineimage.jpg
270
+ - spec/support/files/stage_images/inhs_7_slot.jpg
271
+ - spec/support/files/stage_images/inhs_four_thirds.jpg
266
272
  - spec/support/files/test0.jpg
267
273
  - spec/support/files/test1.jpg
268
274
  - spec/support/files/test2.jpg