mindee 3.1.0 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +57 -7
- data/bin/mindee.rb +160 -83
- data/docs/bank_account_details_v2.md +137 -0
- data/docs/bank_check_v1.md +179 -0
- data/docs/barcode_reader_v1.md +104 -0
- data/docs/carte_vitale_v1.md +123 -0
- data/docs/code_samples/barcode_reader_v1.txt +19 -0
- data/docs/code_samples/cropper_v1.txt +16 -0
- data/docs/code_samples/idcard_fr_v2.txt +19 -0
- data/docs/code_samples/invoice_splitter_v1_async.txt +6 -54
- data/docs/code_samples/multi_receipts_detector_v1.txt +19 -0
- data/docs/code_samples/us_w9_v1.txt +16 -0
- data/docs/cropper_v1.md +97 -0
- data/docs/custom_v1.md +101 -0
- data/docs/expense_receipts_v5.md +306 -0
- data/docs/financial_document_v1.md +384 -0
- data/docs/{ruby-getting-started.md → getting_started.md} +22 -6
- data/docs/idcard_fr_v2.md +253 -0
- data/docs/invoice_splitter_v1.md +85 -0
- data/docs/invoices_v4.md +369 -0
- data/docs/license_plates_v1.md +91 -0
- data/docs/multi_receipts_detector_v1.md +105 -0
- data/docs/passport_v1.md +186 -0
- data/docs/proof_of_address_v1.md +207 -0
- data/docs/us_driver_license_v1.md +268 -0
- data/docs/us_w9_v1.md +207 -0
- data/lib/mindee/client.rb +95 -16
- data/lib/mindee/geometry/quadrilateral.rb +5 -0
- data/lib/mindee/http/.rubocop.yml +8 -0
- data/lib/mindee/http/endpoint.rb +14 -6
- data/lib/mindee/http/error.rb +104 -0
- data/lib/mindee/http.rb +1 -0
- data/lib/mindee/input/sources.rb +84 -15
- data/lib/mindee/parsing/common/api_response.rb +11 -1
- data/lib/mindee/parsing/common/inference.rb +2 -2
- data/lib/mindee/parsing/common/ocr/ocr.rb +1 -0
- data/lib/mindee/parsing/common.rb +0 -1
- data/lib/mindee/parsing/standard/company_registration_field.rb +1 -1
- data/lib/mindee/parsing/standard/locale_field.rb +1 -1
- data/lib/mindee/parsing/standard/payment_details_field.rb +1 -1
- data/lib/mindee/parsing/standard/position_field.rb +10 -3
- data/lib/mindee/parsing/standard/{text_field.rb → string_field.rb} +1 -1
- data/lib/mindee/parsing/standard.rb +1 -1
- data/lib/mindee/pdf/pdf_processing.rb +2 -1
- data/lib/mindee/product/barcode_reader/barcode_reader_v1.rb +37 -0
- data/lib/mindee/product/barcode_reader/barcode_reader_v1_document.rb +44 -0
- data/lib/mindee/product/barcode_reader/barcode_reader_v1_page.rb +32 -0
- data/lib/mindee/product/cropper/cropper_v1.rb +37 -0
- data/lib/mindee/product/cropper/cropper_v1_document.rb +13 -0
- data/lib/mindee/product/cropper/cropper_v1_page.rb +49 -0
- data/lib/mindee/product/custom/custom_v1.rb +1 -0
- data/lib/mindee/product/eu/license_plate/license_plate_v1.rb +1 -0
- data/lib/mindee/product/eu/license_plate/license_plate_v1_document.rb +2 -2
- data/lib/mindee/product/financial_document/financial_document_v1.rb +1 -0
- data/lib/mindee/product/financial_document/financial_document_v1_document.rb +24 -24
- data/lib/mindee/product/fr/bank_account_details/bank_account_details_v1.rb +1 -0
- data/lib/mindee/product/fr/bank_account_details/bank_account_details_v1_document.rb +6 -6
- data/lib/mindee/product/fr/bank_account_details/bank_account_details_v2.rb +1 -0
- data/lib/mindee/product/fr/bank_account_details/bank_account_details_v2_document.rb +6 -6
- data/lib/mindee/product/fr/carte_vitale/carte_vitale_v1.rb +1 -0
- data/lib/mindee/product/fr/carte_vitale/carte_vitale_v1_document.rb +6 -6
- data/lib/mindee/product/fr/id_card/id_card_v1.rb +1 -0
- data/lib/mindee/product/fr/id_card/id_card_v1_document.rb +16 -16
- data/lib/mindee/product/fr/id_card/id_card_v2.rb +39 -0
- data/lib/mindee/product/fr/id_card/id_card_v2_document.rb +107 -0
- data/lib/mindee/product/fr/id_card/id_card_v2_page.rb +53 -0
- data/lib/mindee/product/invoice/invoice_v4.rb +1 -0
- data/lib/mindee/product/invoice/invoice_v4_document.rb +24 -24
- data/lib/mindee/product/invoice_splitter/invoice_splitter_v1.rb +1 -0
- data/lib/mindee/product/invoice_splitter/invoice_splitter_v1_document.rb +5 -3
- data/lib/mindee/product/multi_receipts_detector/multi_receipts_detector_v1.rb +37 -0
- data/lib/mindee/product/multi_receipts_detector/multi_receipts_detector_v1_document.rb +35 -0
- data/lib/mindee/product/multi_receipts_detector/multi_receipts_detector_v1_page.rb +32 -0
- data/lib/mindee/product/passport/passport_v1.rb +1 -0
- data/lib/mindee/product/passport/passport_v1_document.rb +16 -16
- data/lib/mindee/product/proof_of_address/proof_of_address_v1.rb +1 -0
- data/lib/mindee/product/proof_of_address/proof_of_address_v1_document.rb +14 -14
- data/lib/mindee/product/receipt/receipt_v4_document.rb +6 -6
- data/lib/mindee/product/receipt/receipt_v5.rb +1 -0
- data/lib/mindee/product/receipt/receipt_v5_document.rb +12 -12
- data/lib/mindee/product/us/bank_check/bank_check_v1.rb +1 -0
- data/lib/mindee/product/us/bank_check/bank_check_v1_document.rb +8 -8
- data/lib/mindee/product/us/driver_license/driver_license_v1.rb +1 -0
- data/lib/mindee/product/us/driver_license/driver_license_v1_document.rb +28 -28
- data/lib/mindee/product/us/w9/w9_v1.rb +39 -0
- data/lib/mindee/product/us/w9/w9_v1_document.rb +15 -0
- data/lib/mindee/product/us/w9/w9_v1_page.rb +102 -0
- data/lib/mindee/product.rb +5 -0
- data/lib/mindee/version.rb +5 -1
- data/lib/mindee.rb +47 -0
- metadata +43 -9
- data/docs/ruby-api-builder.md +0 -123
- data/docs/ruby-invoice-ocr.md +0 -271
- data/docs/ruby-passport-ocr.md +0 -165
- data/docs/ruby-receipt-ocr.md +0 -196
- data/lib/mindee/parsing/common/error.rb +0 -24
data/lib/mindee/input/sources.rb
CHANGED
@@ -8,6 +8,7 @@ require_relative '../pdf'
|
|
8
8
|
module Mindee
|
9
9
|
module Input
|
10
10
|
module Source
|
11
|
+
# Mime types accepted by the server.
|
11
12
|
ALLOWED_MIME_TYPES = [
|
12
13
|
'application/pdf',
|
13
14
|
'image/heic',
|
@@ -17,36 +18,99 @@ module Mindee
|
|
17
18
|
'image/webp',
|
18
19
|
].freeze
|
19
20
|
|
21
|
+
# Standard error for invalid mime types
|
22
|
+
class MimeTypeError < StandardError
|
23
|
+
end
|
24
|
+
|
25
|
+
# Error sent if the file's mimetype isn't allowed
|
26
|
+
class InvalidMimeTypeError < MimeTypeError
|
27
|
+
# @return [String]
|
28
|
+
attr_reader :invalid_mimetype
|
29
|
+
|
30
|
+
# @param mime_type [String]
|
31
|
+
def initialize(mime_type)
|
32
|
+
@invalid_mimetype = mime_type
|
33
|
+
super("'#{@invalid_mimetype}' mime type not allowed, must be one of #{ALLOWED_MIME_TYPES.join(', ')}")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Error sent if a pdf file couldn't be fixed
|
38
|
+
class UnfixablePDFError < MimeTypeError
|
39
|
+
def initialize
|
40
|
+
super("Corrupted PDF couldn't be repaired.")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
20
44
|
# Base class for loading documents.
|
21
45
|
class LocalInputSource
|
22
46
|
# @return [String]
|
23
47
|
attr_reader :filename
|
24
48
|
# @return [String]
|
25
49
|
attr_reader :file_mimetype
|
26
|
-
# @return [
|
50
|
+
# @return [StringIO]
|
27
51
|
attr_reader :io_stream
|
28
52
|
|
29
|
-
# @param io_stream [
|
30
|
-
|
53
|
+
# @param io_stream [StringIO]
|
54
|
+
# @param filename [String]
|
55
|
+
# @param fix_pdf [Boolean]
|
56
|
+
def initialize(io_stream, filename, fix_pdf: false)
|
31
57
|
@io_stream = io_stream
|
32
58
|
@filename = filename
|
33
|
-
@file_mimetype =
|
34
|
-
|
59
|
+
@file_mimetype = if fix_pdf
|
60
|
+
Marcel::MimeType.for @io_stream
|
61
|
+
else
|
62
|
+
Marcel::MimeType.for @io_stream, name: @filename
|
63
|
+
end
|
35
64
|
return if ALLOWED_MIME_TYPES.include? @file_mimetype
|
36
65
|
|
37
|
-
|
66
|
+
if filename.end_with?('.pdf') && fix_pdf
|
67
|
+
rescue_broken_pdf(@io_stream)
|
68
|
+
@file_mimetype = Marcel::MimeType.for @io_stream
|
69
|
+
|
70
|
+
return if ALLOWED_MIME_TYPES.include? @file_mimetype
|
71
|
+
end
|
72
|
+
|
73
|
+
raise InvalidMimeTypeError, @file_mimetype.to_s
|
74
|
+
end
|
75
|
+
|
76
|
+
# Attempts to fix pdf files if mimetype is rejected.
|
77
|
+
# "Broken PDFs" are often a result of third-party injecting invalid headers.
|
78
|
+
# This attempts to remove them and send the file
|
79
|
+
# @param stream [StringIO]
|
80
|
+
def rescue_broken_pdf(stream)
|
81
|
+
stream.gets('%PDF-')
|
82
|
+
raise UnfixablePDFError if stream.eof? || stream.pos > 500
|
83
|
+
|
84
|
+
stream.pos = stream.pos - 5
|
85
|
+
data = stream.read
|
86
|
+
@io_stream.close
|
87
|
+
|
88
|
+
@io_stream = StringIO.new
|
89
|
+
@io_stream << data
|
38
90
|
end
|
39
91
|
|
92
|
+
# Shorthand for pdf mimetype validation.
|
40
93
|
def pdf?
|
41
94
|
@file_mimetype.to_s == 'application/pdf'
|
42
95
|
end
|
43
96
|
|
97
|
+
# Parses a PDF file according to provided options.
|
98
|
+
# @param options [Hash, nil] Page cutting/merge options:
|
99
|
+
#
|
100
|
+
# * `:page_indexes` Zero-based list of page indexes.
|
101
|
+
# * `:operation` Operation to apply on the document, given the `page_indexes specified:
|
102
|
+
# * `:KEEP_ONLY` - keep only the specified pages, and remove all others.
|
103
|
+
# * `:REMOVE` - remove the specified pages, and keep all others.
|
104
|
+
# * `:on_min_pages` Apply the operation only if document has at least this many pages.
|
44
105
|
def process_pdf(options)
|
45
106
|
@io_stream.seek(0)
|
46
107
|
@io_stream = PdfProcessor.parse(@io_stream, options)
|
47
108
|
end
|
48
109
|
|
110
|
+
# Reads a document. Packs it into bytes if needed.
|
111
|
+
# Note: only needs filename in case of some pdf files.
|
49
112
|
# @param close [Boolean]
|
113
|
+
# @return [Array<String, [String, aBinaryString ], [Hash, nil] >]
|
50
114
|
def read_document(close: true)
|
51
115
|
@io_stream.seek(0)
|
52
116
|
# Avoids needlessly re-packing some files
|
@@ -54,16 +118,17 @@ module Mindee
|
|
54
118
|
@io_stream.close if close
|
55
119
|
return ['document', data, { filename: @filename }] if pdf?
|
56
120
|
|
57
|
-
['document', [data].pack('m')
|
121
|
+
['document', [data].pack('m')]
|
58
122
|
end
|
59
123
|
end
|
60
124
|
|
61
125
|
# Load a document from a path.
|
62
126
|
class PathInputSource < LocalInputSource
|
63
127
|
# @param filepath [String]
|
64
|
-
|
128
|
+
# @param fix_pdf [Boolean]
|
129
|
+
def initialize(filepath, fix_pdf: false)
|
65
130
|
io_stream = File.open(filepath, 'rb')
|
66
|
-
super(io_stream, File.basename(filepath))
|
131
|
+
super(io_stream, File.basename(filepath), fix_pdf: fix_pdf)
|
67
132
|
end
|
68
133
|
end
|
69
134
|
|
@@ -71,10 +136,11 @@ module Mindee
|
|
71
136
|
class Base64InputSource < LocalInputSource
|
72
137
|
# @param base64_string [String]
|
73
138
|
# @param filename [String]
|
74
|
-
|
139
|
+
# @param fix_pdf [Boolean]
|
140
|
+
def initialize(base64_string, filename, fix_pdf: false)
|
75
141
|
io_stream = StringIO.new(base64_string.unpack1('m*'))
|
76
142
|
io_stream.set_encoding Encoding::BINARY
|
77
|
-
super(io_stream, filename)
|
143
|
+
super(io_stream, filename, fix_pdf: fix_pdf)
|
78
144
|
end
|
79
145
|
end
|
80
146
|
|
@@ -82,19 +148,22 @@ module Mindee
|
|
82
148
|
class BytesInputSource < LocalInputSource
|
83
149
|
# @param raw_bytes [String]
|
84
150
|
# @param filename [String]
|
85
|
-
|
151
|
+
# @param fix_pdf [Boolean]
|
152
|
+
def initialize(raw_bytes, filename, fix_pdf: false)
|
86
153
|
io_stream = StringIO.new(raw_bytes)
|
87
154
|
io_stream.set_encoding Encoding::BINARY
|
88
|
-
super(io_stream, filename)
|
155
|
+
super(io_stream, filename, fix_pdf: fix_pdf)
|
89
156
|
end
|
90
157
|
end
|
91
158
|
|
92
159
|
# Load a document from a file handle.
|
93
160
|
class FileInputSource < LocalInputSource
|
161
|
+
# @param file_handle [String]
|
94
162
|
# @param filename [String]
|
95
|
-
|
163
|
+
# @param fix_pdf [Boolean]
|
164
|
+
def initialize(file_handle, filename, fix_pdf: false)
|
96
165
|
io_stream = file_handle
|
97
|
-
super(io_stream, filename)
|
166
|
+
super(io_stream, filename, fix_pdf: fix_pdf)
|
98
167
|
end
|
99
168
|
end
|
100
169
|
|
@@ -6,14 +6,21 @@ require 'time'
|
|
6
6
|
module Mindee
|
7
7
|
module Parsing
|
8
8
|
module Common
|
9
|
+
# Potential values for queue in asynchronous calls.
|
9
10
|
module JobStatus
|
11
|
+
# Document is waiting to be processed.
|
10
12
|
WAITING = :waiting
|
13
|
+
# Document is currently being parsed.
|
11
14
|
PROCESSING = :processing
|
15
|
+
# Document parsing is complete.
|
12
16
|
COMPLETED = :completed
|
13
17
|
end
|
14
18
|
|
19
|
+
# Potential values for requests.
|
15
20
|
module RequestStatus
|
21
|
+
# Failed.
|
16
22
|
FAILURE = :failure
|
23
|
+
# Success.
|
17
24
|
SUCCESS = :success
|
18
25
|
end
|
19
26
|
|
@@ -88,10 +95,13 @@ module Mindee
|
|
88
95
|
attr_reader :job
|
89
96
|
# @return [Mindee::Parsing::Common::ApiRequest]
|
90
97
|
attr_reader :api_request
|
98
|
+
# @return [String]
|
99
|
+
attr_reader :raw_http
|
91
100
|
|
92
101
|
# @param product_class [Class<Mindee::Product>]
|
93
102
|
# @param http_response [Hash]
|
94
|
-
def initialize(product_class, http_response)
|
103
|
+
def initialize(product_class, http_response, raw_http)
|
104
|
+
@raw_http = raw_http
|
95
105
|
if http_response.key?('api_request')
|
96
106
|
@api_request = Mindee::Parsing::Common::ApiRequest.new(http_response['api_request'])
|
97
107
|
end
|
@@ -33,8 +33,8 @@ module Mindee
|
|
33
33
|
out_str << "\n:Product: #{@product.name} v#{@product.version}"
|
34
34
|
out_str << "\n:Rotation applied: #{is_rotation_applied}"
|
35
35
|
out_str << "\n\nPrediction\n=========="
|
36
|
-
out_str << "\n#{@prediction}"
|
37
|
-
out_str << "\
|
36
|
+
out_str << "\n#{@prediction.to_s.size.positive? ? "#{@prediction}\n" : ''}"
|
37
|
+
out_str << "\nPage Predictions\n================\n\n"
|
38
38
|
out_str << @pages.map(&:to_s).join("\n\n")
|
39
39
|
end
|
40
40
|
end
|
@@ -29,12 +29,19 @@ module Mindee
|
|
29
29
|
@value = @polygon
|
30
30
|
end
|
31
31
|
|
32
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
33
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
32
34
|
# @return [String]
|
33
35
|
def to_s
|
34
|
-
|
35
|
-
|
36
|
-
|
36
|
+
return "Polygon with #{@polygon.size} points." if @polygon&.size&.positive?
|
37
|
+
return "Polygon with #{@bounding_box.size} points." if @bounding_box&.size&.positive?
|
38
|
+
return "Polygon with #{@rectangle.size} points." if @rectangle&.size&.positive?
|
39
|
+
return "Polygon with #{@quadrangle.size} points." if @quadrangle&.size&.positive?
|
40
|
+
|
41
|
+
''
|
37
42
|
end
|
43
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
44
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
38
45
|
|
39
46
|
private
|
40
47
|
|
@@ -8,5 +8,5 @@ require_relative 'standard/date_field'
|
|
8
8
|
require_relative 'standard/payment_details_field'
|
9
9
|
require_relative 'standard/position_field'
|
10
10
|
require_relative 'standard/tax_field'
|
11
|
-
require_relative 'standard/
|
11
|
+
require_relative 'standard/string_field'
|
12
12
|
require_relative 'standard/locale_field'
|
@@ -6,9 +6,10 @@ require_relative 'pdf_tools'
|
|
6
6
|
|
7
7
|
module Mindee
|
8
8
|
module PDF
|
9
|
-
#
|
9
|
+
# PDF document processing
|
10
10
|
module PdfProcessor
|
11
11
|
Origami::PDF.class_eval { include PDFTools }
|
12
|
+
# Default options for pdf documents processing.
|
12
13
|
DEFAULT_OPTIONS = {
|
13
14
|
page_indexes: [0],
|
14
15
|
operation: :KEEP_ONLY,
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../parsing'
|
4
|
+
require_relative 'barcode_reader_v1_document'
|
5
|
+
require_relative 'barcode_reader_v1_page'
|
6
|
+
|
7
|
+
module Mindee
|
8
|
+
module Product
|
9
|
+
# Barcode Reader module.
|
10
|
+
module BarcodeReader
|
11
|
+
# Barcode Reader V1 prediction inference.
|
12
|
+
class BarcodeReaderV1 < Mindee::Parsing::Common::Inference
|
13
|
+
@endpoint_name = 'barcode_reader'
|
14
|
+
@endpoint_version = '1'
|
15
|
+
|
16
|
+
# @param prediction [Hash]
|
17
|
+
def initialize(prediction)
|
18
|
+
super
|
19
|
+
@prediction = BarcodeReaderV1Document.new(prediction['prediction'], nil)
|
20
|
+
@pages = []
|
21
|
+
prediction['pages'].each do |page|
|
22
|
+
@pages.push(BarcodeReaderV1Page.new(page))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
# Name of the endpoint for this product.
|
28
|
+
# @return [String]
|
29
|
+
attr_reader :endpoint_name
|
30
|
+
# Version for this product.
|
31
|
+
# @return [String]
|
32
|
+
attr_reader :endpoint_version
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../parsing'
|
4
|
+
|
5
|
+
module Mindee
|
6
|
+
module Product
|
7
|
+
module BarcodeReader
|
8
|
+
# Barcode Reader V1 document prediction.
|
9
|
+
class BarcodeReaderV1Document < Mindee::Parsing::Common::Prediction
|
10
|
+
include Mindee::Parsing::Standard
|
11
|
+
# List of decoded 1D barcodes.
|
12
|
+
# @return [Array<Mindee::Parsing::Standard::StringField>]
|
13
|
+
attr_reader :codes_1d
|
14
|
+
# List of decoded 2D barcodes.
|
15
|
+
# @return [Array<Mindee::Parsing::Standard::StringField>]
|
16
|
+
attr_reader :codes_2d
|
17
|
+
|
18
|
+
# @param prediction [Hash]
|
19
|
+
# @param page_id [Integer, nil]
|
20
|
+
def initialize(prediction, page_id)
|
21
|
+
super()
|
22
|
+
@codes_1d = []
|
23
|
+
prediction['codes_1d'].each do |item|
|
24
|
+
@codes_1d.push(StringField.new(item, page_id))
|
25
|
+
end
|
26
|
+
@codes_2d = []
|
27
|
+
prediction['codes_2d'].each do |item|
|
28
|
+
@codes_2d.push(StringField.new(item, page_id))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [String]
|
33
|
+
def to_s
|
34
|
+
codes_1d = @codes_1d.join("\n #{' ' * 13}")
|
35
|
+
codes_2d = @codes_2d.join("\n #{' ' * 13}")
|
36
|
+
out_str = String.new
|
37
|
+
out_str << "\n:Barcodes 1D: #{codes_1d}".rstrip
|
38
|
+
out_str << "\n:Barcodes 2D: #{codes_2d}".rstrip
|
39
|
+
out_str[1..].to_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../parsing'
|
4
|
+
require_relative 'barcode_reader_v1_document'
|
5
|
+
|
6
|
+
module Mindee
|
7
|
+
module Product
|
8
|
+
module BarcodeReader
|
9
|
+
# Barcode Reader V1 page.
|
10
|
+
class BarcodeReaderV1Page < Mindee::Parsing::Common::Page
|
11
|
+
# @param prediction [Hash]
|
12
|
+
def initialize(prediction)
|
13
|
+
super(prediction)
|
14
|
+
@prediction = BarcodeReaderV1PagePrediction.new(
|
15
|
+
prediction['prediction'],
|
16
|
+
prediction['id']
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Barcode Reader V1 page prediction.
|
22
|
+
class BarcodeReaderV1PagePrediction < BarcodeReaderV1Document
|
23
|
+
# @return [String]
|
24
|
+
def to_s
|
25
|
+
out_str = String.new
|
26
|
+
out_str << "\n#{super}"
|
27
|
+
out_str
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../parsing'
|
4
|
+
require_relative 'cropper_v1_document'
|
5
|
+
require_relative 'cropper_v1_page'
|
6
|
+
|
7
|
+
module Mindee
|
8
|
+
module Product
|
9
|
+
# Cropper module.
|
10
|
+
module Cropper
|
11
|
+
# Cropper V1 prediction inference.
|
12
|
+
class CropperV1 < Mindee::Parsing::Common::Inference
|
13
|
+
@endpoint_name = 'cropper'
|
14
|
+
@endpoint_version = '1'
|
15
|
+
|
16
|
+
# @param prediction [Hash]
|
17
|
+
def initialize(prediction)
|
18
|
+
super
|
19
|
+
@prediction = CropperV1Document.new
|
20
|
+
@pages = []
|
21
|
+
prediction['pages'].each do |page|
|
22
|
+
@pages.push(CropperV1Page.new(page))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
# Name of the endpoint for this product.
|
28
|
+
# @return [String]
|
29
|
+
attr_reader :endpoint_name
|
30
|
+
# Version for this product.
|
31
|
+
# @return [String]
|
32
|
+
attr_reader :endpoint_version
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../parsing'
|
4
|
+
require_relative 'cropper_v1_document'
|
5
|
+
|
6
|
+
module Mindee
|
7
|
+
module Product
|
8
|
+
module Cropper
|
9
|
+
# Cropper V1 page.
|
10
|
+
class CropperV1Page < Mindee::Parsing::Common::Page
|
11
|
+
# @param prediction [Hash]
|
12
|
+
def initialize(prediction)
|
13
|
+
super(prediction)
|
14
|
+
@prediction = CropperV1PagePrediction.new(
|
15
|
+
prediction['prediction'],
|
16
|
+
prediction['id']
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Cropper V1 page prediction.
|
22
|
+
class CropperV1PagePrediction < CropperV1Document
|
23
|
+
include Mindee::Parsing::Standard
|
24
|
+
|
25
|
+
# List of documents found in the image.
|
26
|
+
# @return [Array<Mindee::Parsing::Standard::PositionField>]
|
27
|
+
attr_reader :cropping
|
28
|
+
|
29
|
+
# @param prediction [Hash]
|
30
|
+
# @param page_id [Integer, nil]
|
31
|
+
def initialize(prediction, page_id)
|
32
|
+
@cropping = []
|
33
|
+
prediction['cropping'].each do |item|
|
34
|
+
@cropping.push(PositionField.new(item, page_id))
|
35
|
+
end
|
36
|
+
super()
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [String]
|
40
|
+
def to_s
|
41
|
+
cropping = @cropping.join("\n #{' ' * 18}")
|
42
|
+
out_str = String.new
|
43
|
+
out_str << "\n:Document Cropper: #{cropping}".rstrip
|
44
|
+
out_str
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -10,7 +10,7 @@ module Mindee
|
|
10
10
|
class LicensePlateV1Document < Mindee::Parsing::Common::Prediction
|
11
11
|
include Mindee::Parsing::Standard
|
12
12
|
# List of all license plates found in the image.
|
13
|
-
# @return [Array<Mindee::Parsing::Standard::
|
13
|
+
# @return [Array<Mindee::Parsing::Standard::StringField>]
|
14
14
|
attr_reader :license_plates
|
15
15
|
|
16
16
|
# @param prediction [Hash]
|
@@ -19,7 +19,7 @@ module Mindee
|
|
19
19
|
super()
|
20
20
|
@license_plates = []
|
21
21
|
prediction['license_plates'].each do |item|
|
22
|
-
@license_plates.push(
|
22
|
+
@license_plates.push(StringField.new(item, page_id))
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|