This package allows the recognition of optical encoded information related to SBB use cases. It is built on top of google_mlkit and runs solely on-device.
Table Of Contents
Click to expand
Getting-Started
Supported platforms
Preconditions
This package uses the Flutter Camera plugin to access the device camera. Make sure to follow their installation instructions.
Futhermore, follow the instructions on google_mlkit_barcode_scanning and google_mlkit_text_recognition for proper setup. Specifically, setup the minimum iOS and Android SDKs and the Podfile.
In Code Usage
After importing the library, you can add a DataScanner
to your widget tree.
You can control its size by wrapping it in a SizedBox
for example.
If there are no size constraints (e.g. in a Row
or Column
), the DataScanner
will not exceed
the screen's width and/or height (depending on orientation).
SizedBox(
height: 250,
width: 400,
child: DataScanner( /* ... */ ),
)
If you want a full-page scanner, you can use the DataScannerPage
widget instead.
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => DataScannerPage( /* ... */ ),
),
);
Documentation
Features
Feature | iOS | Android |
---|---|---|
Optical Character Recognition | :white_check_mark: | :white_check_mark: |
Barcode Scanning | :white_check_mark: | :white_check_mark: |
QR Code Scanning | :white_check_mark: | :white_check_mark: |
UIC Number recognition | :white_check_mark: | :white_check_mark: |
DataScanner Configuration
You can configure the DataScanner
by passing a DataScannerConfiguration<T>
into it, where T
stands for whichever type a successful extraction will return. This will be covered in detail in the Extractors section, but is commonly inferred by the compiler. Almost all fields have default values, the exceptions being the required values processor
and extractor
which will be covered in their respective sections.
DataScanner(
scannerConfiguration: DataScannerConfiguration<T>(
processors: // Covered in their own section
extractors: // Covered in their own section
routeObserver: RouteObserver<ModalRoute>(),
onExtracted: (T value) {
// Called for every extracted value which is
// a) inside the detection area,
// b) not null, and
// c) not equal to the previously extracted value
},
onPermissionDenied: () {
// Called when the app does not have camera permissions
},
onError: (String error) {
// Called when the library encounters any other camera error
},
showTorchToggle: true,
torchToggleMargin: EdgeInsets.all(32),
torchToggleAlignment: Alignment.bottomCenter,
showOverlay: true,
upperHelper: Text('Appears above the detection area'),
lowerHelper: Text('Appears below the detection area'),
detectionAreaHeight: 75,
detectionAreaWidth: 250,
detectionAreaMode: DetectionAreaMode.containsRect,
detectionOutline: DetectionOutlineConfig(
margin: 5,
padding: 10,
activeOutlineColor: Colors.green,
inactiveOutlineColor: Colors.grey,
outlineWidth: 2,
cornerRadius: 5,
enableLabel: true,
labelColor: Colors.white,
labelSize: 12,
labelPosition: DetectionLabelPosition.bottomLeft,
),
enableZoom: true,
onZoomChanged: (double zoom) {
// is called if zoom changes with a minimum change sensitivity of 0.01
}
),
)
Vision Processors
The purpose of vision processors is to detect elements in an image and return their value and position relative to an origin point (usually the top left corner). The library ships with three preconfigured vision processors, all based on Google ML Kit:
TextRecognitionVisionProcessor
OneDimensionalBarcodeVisionProcessor
TwoDimensionalBarcodeVisionProcessor
Processor Name | Note |
---|---|
TextRecognitionVisionProcessor | Recognize text in images. Only supports the Latin script. Please contact a maintainer for other scripts. |
OneDimensionalBarcodeVisionProcessor | This extractor extracts the value of UIC numbers and provides information and detailed descriptions for it. |
TwoDimensionalBarcodeVisionProcessor | This extractor extracts the value of GS1 codes and provides information and detailed descriptions for it. |
Add a list of processor(s) to the DataScannerConfiguration
processors
argument:
DataScanner(
scannerConfiguration: DataScannerConfiguration(
// ...
processors: [
TextRecognitionVisionProcessor(),
// OneDimensionalBarcodeVisionProcessor(),
// TwoDimensionalBarcodeVisionProcessor()
],
),
)
Additionally, it is possible create your own custom vision processor by implementing the VisionProcessor
interface.
This allows the library to also detect elements other than text, QR-codes and barcodes:
abstract class VisionProcessor {
Future<Map<Rect, String?>> getBoundingBoxes({
required CameraImage image,
required int imageRotation,
});
}
Extractors
An extractor takes the values detected by the vision processor,
and tries to extract data in a certain format (like URLs, UIC Numbers or GS1 codes).
At the same time, it also works as a filter, since detected values which to not match the given format are dismissed.
The library ships with three preconfigured extractors, which can be supplied to the DataScannerConfiguration
via the
extractors
parameter.
Extractor Name | Return Type (<T> of DataScannerConfiguration) | Note |
---|---|---|
RawTextExtractor | String? | Only for unit testing |
UICDetailsExtractor | UICDetails? | This extractor extracts the value of UIC numbers and provides information and detailed descriptions for it. |
GS1DetailsExtractor | GS1Details? | This extractor extracts the value of GS1 codes and provides information and detailed descriptions for it. |
Exemplary UICDetailsExtractor
implementation:
DataScanner(
scannerConfiguration: DataScannerConfiguration<UICDetails>(
// ...
extractors: [
UICDetailsExtractor( /* ... */ ),
],
),
)
Custom Extractors
But what about URLs, phone numbers, and brands owned by Nestlé, etc.?
Fear not, it's quite simple to extract these kind of formats.
Simply implement the Extractor<T>
interface, and you're good to go.
abstract class Extractor<T> {
T? extract(String? input);
}
The extract
method must return a nullable type. So, when do we return null
?
It's simple: When the value cannot be extracted due to formatting, missing components in input
, or an error.
This causes the ScannerConfiguration.onExracted
to not be fired, as the detected value has an invalid format.
For example, here is a simple CompoundSentenceExtractor
which only extracts values which are a compund sentence,
as indicated by a comma and trailing period.
class CompoundSentenceExtractor implements Extractor<String> {
String? extract(String? input) {
if (input == null) return null;
final containsComma = input.contains(',');
final isSentence = input.endsWith('.');
// Why yes, of course ",." is a valid compound sentence!
return containsComma && isSentence ? input : null;
}
}
You can now use your own extractor:
DataScanner(
scannerConfiguration: DataScannerConfiguration<String>(
// ...
extractors: [
CompoundSentenceExtractor(),
],
),
)
License
This project is licensed under MIT.
Contributing
This repository includes a CONTRIBUTING.md file that outlines how to contribute to the project, including how to submit bug reports, feature requests, and pull requests.
Maintainer
Credits
In addition to the contributors on Github, we thank the following people for their work on previous versions:
- Ulrich Raab (previous maintainer)
Coding Standards
See CODING_STANDARDS.md.
Code of Conduct
See CODE_OF_CONDUCT.md.
Libraries
- drawables/_drawables
- drawables/device_drawable
- drawables/flashlight_off_drawable
- drawables/flashlight_on_drawable
- drawables/sbb_drawable
- extensions/_extensions
- extensions/barcode_x
- extensions/camera_image_x
- extensions/rect_x
- extractors/_extractors
- extractors/gs1_details_extractor
- extractors/raw_text_extractor
- extractors/uic_details_extractor
- interfaces/_interfaces
- interfaces/extractor
- interfaces/on_extracted
- interfaces/vision_processor
- models/_models
- models/gs1_details
- models/localized_string
- models/uic_details
- sbb_data_scanner
- services/_services
- services/camera_service
- services/gs1_details_service
- services/gs1_validation_service
- services/uic_details_service
- services/uic_validation_service
- vision_processors/_vision_processors
- vision_processors/one_dimensional_barcode_vision_processor
- vision_processors/text_recognition_vision_processor
- vision_processors/two_dimensional_barcode_vision_processor
- widgets/_widgets
- widgets/camera_builder
- widgets/camera_overlay
- widgets/data_scanner
- widgets/data_scanner_page
- widgets/detection_outline
- widgets/hole_painter
- widgets/sized_camera_preview
- widgets/torch_toggle
- widgets/zoom