Butler Labs is an AI-powered optical character recognition (OCR) platform with models fine tuned to extract important data from a variety of commonly encountered documents:
Driver’s Licenses
Passports
Health Insurance Cards
Paystubs
Invoices
Receipts
W9s
Mortgage Statements
What makes this platform even more attractive from a developer standpoint is that they provide a generous free tier of 500 scans per month and a comprehensive REST API. This means you can basically add an OCR upgrade to your app today.
Setup
API Key
To start using the Butler Labs OCR product, you’ll need two values:
An API key
A model-specific queue ID
After creating an account, you’ll find your API key at the top of the “Settings” page. The API key is a sensitive value that enables access to your account. For that reason, you should avoid adding it to version control and instead pass it to your app using dart-define:
Or my preferred method, dart-define-from-file. First create a config.json file in your app’s asset folder:
Then run your app using the following command:
Inside the app, you can retrieve dart-define values using the String.fromEnvironment() constructor:
Queue ID
In this post, we’ll be using the US Driver’s License model to extract a ton of information from images of driver’s licenses. Before we can do this though, we’ll need a queue ID (aka API ID) for our instance of the model. On the “Explore Models” page, locate the US Driver’s License model.
The process for adding any model is the same:
Click on it to add it to your “My Models” page
On the “My Models” page, select the new model
Select the “APIs” tab
Copy the queue ID at the top of the page
Image Picker
Users will need to either capture or upload images to your app so they can be analyzed and by far the easiest way to accomplish this is with the image_picker package. It works seamlessly on Android, iOS, and the mobile and desktop variants of web. Add the dependency to your pubspec.yaml:
And then create a simple button that users can tap to take an image.
In the next step we’ll send the user’s image to Butler Labs and parse the result.
Click on each one separately on the wiki and download it. Once you have an image on your computer, you can drag it onto your Android emulator to add it to the list of files.
Now onto the fun part!
Making the Request
After a user selects an image, we want to send it to the extract endpoint where Butler Labs will analyze it and return a JSON object with the parsed results. An example response looks like this:
The image files need to be sent to the API in a Multipart request. Luckily the http package comes with out-of-the-box support for this so the first step is to import that and a few others:
Finally, we need to add the image to the request. This can be done using the image’s file path or its raw bytes and the option you choose will depend on the platform you’re using. Files returned by ImagePicker on Flutter web will not have a path so on the web you will need to use the bytes method. I’ve included the full code snippets for both methods below.
Using the Image Path
Using the Image Bytes
The bytes method will work on all platforms so I suggest using that
Deciphering the Results
The request may take a few seconds but soon you should have a nice, juicy JSON blob to sink your teeth into. The shape of the result is fairly consistent from model to model too, meaning you won’t have to build custom deserializers if you add more models later.
Each result will contain the following top-level fields:
Document ID: Unique ID for the document you uploaded
Upload ID: An ID you can use to delete the image that was uploaded
Document Type: The type of the document, typically matching the model you used (ex. Health Insurance Card)
Confidence Score: A Low/Medium/High value indicating the model’s overall confidence in the parsed results. You can see the breakdown of all your organization’s confidence scores on the Butler Labs dashboard
Beneath these top-level fields you will also find a list of “Form Fields” corresponding to the fields identified by your model (see the model’s page in the Butler Docs). Each form field will contain the following values:
Field Name
Value: The value detected by the model for this field
Confidence Score: A Low/Medium/High value indicating the model’s confidence in this specific field
Confidence Value: A value between 0 and 1 indicating the likelihood the result is correct
OCR Confidence Value: A value between 0 and 1 indicating the likelihood the model found the correct field
In the sample app linked below, I used the confidence scores and values to create a simple UI illustrating the model’s performance:
Butler Labs Package
While the code required for this OCR product is fairly unsophisticated, you can avoid the hassle of piecing everything together yourself and use the butler_labs package on pub.dev. This package currently only supports the Extract document endpoint. It includes a generic ButlerResult class and models specific to each model on the Butler Labs Website so you can convert the generic result from the API into something that’s more usable.
Conclusion
OCR is a solved problem and Butler Labs has a product that is more than satisfactory for many common use cases. If the built-in models don’t meet your needs, their platform also allows you to create your own models. You can read more about that here. Happy coding!