Skipping Photoshop: How we made ID Badge creation 10x faster by using facial recognition

By on November 1st, 2016 in Product and Technology
TrueAccord Blog

Recently TrueAccord has grown to the size where our compliance stance requires the addition of photo ID badges. It’s a rite of passage all small-but-growing companies endure and ours is no different.

Since I have previous experience setting up badge systems and dealing with the printers, I volunteered to kickoff this process. I’ve evaluated pre-existing badge creation software in the past and found them all significantly lacking. In a previous environment, I wrote my own badge creation software which fit the needs at the time. The key phrase being “at the time“. For tech startups, it’s not unusual to go from onboarding one person every other week, to 10 people a week in a year or two. That means every manual step for onboarding someone will go from an “oh well, it’s just once every other week” to “we need to dedicate several hours of someone’s time every week to this process.” Typically that same growth period also happens to be when your operations (IT, Facilities, and Office Admin) organizations are the most short staffed and the least likely to have the free time to do that. “Where is this going?” and “How much work does this mean for me?”, you ask? Allow me to share with you how I automated our badge system – Photoshop included.

Typical process for creating a badge:
Before we talk about automation, let’s look at a common sample proccess.

  • Line up your new employees in a specific order (so that way you don’t forget which picture goes to which person).
  • Take a picture of each person; typically this happens with a DSLR or Point-And-Shoot, but in rare instances a webcam is used (which is just terrible quality, but skips the next step).
  • Copy all the pictures to your computer.
  • Open all pictures in Photoshop, crop them down to just the face. If you’re feeling generous and have an overabundance of time, do some simple color correct and light balance edits.
  • Upload all the pictures to your badge software.
  • Put in all the information for each person, for each badge.
  • Save/Generate Badge.
  • Download the badge, if your system is cloud based.
  • Print the badge.

Much of this process can be automated, depending on your software and what integrations you have available. However the most common section that gets left to manual work is photo post-processing (upload, crop, corrections). As previously mentioned, even if this is a minor amount of work, it can add up quickly as companies start to scale.

Our highly automated badge process:
In contrast to the lengthy and time consuming process above, here’s what we do today.

  • Select person from a list of all employees
  • Click the “Take Photo” button and snap a photo of the person
  • Click the “Upload” button
  • Click “Generate & Print”

That is certainly a shorter list of steps and more importantly, much faster. With it there are a number of subtle and not-so-subtle automation steps.

How do we automate it?
First, we skip the computer with webcam AND the dedicated camera… instead we opt to use a phone. The photo quality of modern smartphones rivals that of many cheap DSLRs and point-and-shoots. We built the entire keycard interface to be mobile-first (and responsive) so we can take advantage of things like form fields forcing number input (for badge numbers) or upload buttons that trigger the phone’s camera. The employee’s photo is pushed right into AWS S3 for safe keeping.

Second, we load the keycard database with all of the currently active employees from Okta, which is our SSO system of choice. 99% of the badges we’re ever going to be issuing will be employees or contractors that require an Okta account to access our corporate resources. We store the Okta data along with our manual input and some extra metadata in AWS DynamoDB. Since this application only has one or two simultaneous users we can opt for a provisioned throughput of single digits which ends up cost ~$0.01/mo. Later if we need to scale up database usage, it’s only a few clicks.

Third, we run a simple python script on our office network which monitors a badge “print queue” (another DynamoDB table) for entries. It then fetches the finished badges from S3 and sends them to our Fargo Badge Printer with the following:

call("lp -d DTC1250e -o media=CR80 "+badgeFile, shell=True)

Of course, you probably noticed that I missed the part where we generate the badge. As that’s the best, I saved it for last. The process in a very simplified manner is:

  • Fetch original employee photo from S3.
  • Find the face
  • Crop the face
  • Merge the face picture with our “background plate” for the badge.
  • Add the pertinent text (Employee name, employee number, etc).

Most of this is very simple to accomplish using Pillow (a fork of the Python Image Library) though it could be accomplished in most languages using GD/ImageMagik bindings.

Automating out Photoshop – Find the Face
The really fun part is the ever so boringly named step of “find the face”. Typically this is where your human intervention would be required, be it in the precision placement of your subject during photography, or cropping and correction in Photoshop. Instead we opted to take a surprisingly cheap and more reliable approach, using the Google Cloud Vision API. The GCVA advertises a lot of fun features like image tagging, OCR and NSFW detection, however we’re most interested in the “Face Detection”. Here’s the relevant code snippet:

batch_request = [{
    'image': { 'content': base64.b64encode(originalEmployeePhoto).decode('UTF-8') },
    'features': [{ 'type': 'FACE_DETECTION', 'maxResults': 1 }]

service = get_vision_service()
request = service.images().annotate(body={ 'requests': batch_request })
response = request.execute()

face = response['responses'][0]['faceAnnotations'][0]:
box = [(v.get('x', 0.0), v.get('y', 0.0)) for v in face['boundingPoly']['vertices']]
xDiff = (box[1][0] - box[0][0])
yDiff = (box[2][1] - box[1][1])
expandedBox = (box[0][0]-(xDiff/4),box[0][1]-(yDiff/4),box[2][0]+(xDiff/4),box[2][1]+(yDiff/4))

img =
croppedFace = img.crop(expandedBox)

This sample snippet takes an already open image file, fires off a request to the GCVA then processes the return information. The API can return any number of bounding boxes for faces, however we’re only interested in one (since we assume there is only one person in the badge photo). The bounding box on the face is fairly tight (forehead to chin), but centered on the nose, so we’ve figured out the box size and expanded it by an additional 25% – then cropped on that. Google has provided a good multi-language tutorial for the GVCA if you want to learn more.

Sample Results
Below is four sample of before & after image sets from our badge generation system. As you will notice, all the of the “after” images are very uniform in the face location, size and positioning. This extreme uniformity means that the rest of the badge layout can be planned with tighter tolerances or more creative designs (such as overlaying circular portraits).

Original Image GVCA Face Detection & Crop

From the US Senate

From The Nixon Foundation
From the FDR Presidential Library & Museum

From Gilbert Stuart / The Clark

Cost is not an issue
If you’re creating less than 1,000 badges a month, using this API will not cost you a penny. Beyond that you’re looking to pay anywhere from $0.0025 to $0.0006 per face detection (per badge). It’ll end up costing more in S3 storage fees and DynamoDB access than it will ever cost to use the GCVA.

Unfortunately we don’t have a full copy of the code to release at the time as it is currently very custom to our environment, but a competent coder should be able to hack together a clone in a weekend (which is about how long it took me to create ours). With the steps above and a little ingenuity (like running the badge generation function in AWS Lambda) anyone can have their own nearly fully automated badge software that costs a few cents a month total. We’ve estimated that the process for issuing a badge from start (taking a picture) to finish (printed badge) takes us less than 1 minute per person, with roughly 30 seconds of that time being spent waiting for the printer. Automation has moved our bottleneck from human speed to printer speed (which we could reduce further with more printers).