Documentation
How to extract information from Driving Licenses using SoceTonAI Script OCRΒΆ
In this guide, Iβll show how to use SoceTonAI Script OCR to automatically extract key information from a Driving Licences. We begin by collecting the API credentials from soceton.com, then create a YAML script that instructs the OCR engine to read the information we need (YAML is provided at the end of this document). Finally, we send a read request to api.soceton.com to retrieve the structured output.
YAML that I am using for this requestΒΆ
document_type: DrivingLicense
description: "Extract key information from Driving License card using OCR"
development: true
return_ocr_output: false
return_full_text: false
fields:
- name: license_no
label: "License No"
find:
type: text
keywords:
- keyword: "License"
index: 0
next_keyword_position: [ 1, -1, 1, 10 ]
- keyword: "No"
next_keyword_position: [ 1, -1, 1, 3 ]
- keyword: ":"
position_of_value: [1, -1, 7, 15]
words: 5
debug: false
returns:
- keywords
- words
- position
- name: full_name
label: "Name"
find:
type: text
keywords:
- keyword: "Name"
index: 0 # First matched keyword
next_keyword_position: [ 1, -1, 1, 3 ]
- keyword: ":"
position_of_value: [1, -1, 4, 15]
words: 5
debug: false
returns:
- keywords
- words
- position
- name: date_of_birth
label: "Date of Birth"
find:
type: text
keywords:
- keyword: "Date"
index: 0
next_keyword_position: [ 1, -1, 1, 3 ]
- keyword: "of"
next_keyword_position: [ 1, -1, 1, 7 ]
- keyword: "Birth"
next_keyword_position: [ 1, -1, 1, 3 ]
- keyword: ":"
position_of_value: [1, -1, 4, 10]
words: 5
debug: false
returns:
- keywords
- words
- position
- name: address
label: "Address"
find:
type: text
keywords:
- keyword: "Address"
index: 0
next_keyword_position: [ 1, -1, 1, 3 ]
- keyword: ":"
position_of_value: [1, -1, 7, 45]
words: 10
debug: false
returns:
- keywords
- words
- position
- name: class
label: "Class"
find:
type: text
keywords:
- keyword: "Class"
index: 0
next_keyword_position: [ 1, -1, 1, 3 ]
- keyword: ":"
position_of_value: [1, -1, 5, 10]
words: 10
debug: false
returns:
- keywords
- words
- position
- name: sex
label: "Sex"
find:
type: text
keywords:
- keyword: "Sex"
index: 0
next_keyword_position: [ 1, -1, 1, 3 ]
- keyword: ":"
position_of_value: [1, -1, 3, 10]
words: 10
debug: false
returns:
- keywords
- words
- position
- name: height
label: "Height"
find:
type: text
keywords:
- keyword: "Height"
index: 0
next_keyword_position: [ 1, -1, 1, 3 ]
- keyword: ":"
position_of_value: [1, -1, 6.2, 10]
words: 10
debug: false
returns:
- keywords
- words
- position
The imageΒΆ
InΒ [1]:
from PIL import Image
img = Image.open("dummies/resized-images/driving-license_0.jpg")
img = img.convert("RGB")
img
Out[1]:
Sending the requestΒΆ
InΒ [2]:
import json
import requests
from config import SOCETONAI_API_SECRET, SOCETONAI_API_KEY
def generate_result(url, image_path, rules_path, headers):
data = {}
files = {
"doc": open(image_path, "rb"),
"rules": open(rules_path, "r", encoding="utf-8")
}
response = requests.post(url, data=data, headers=headers, files=files)
return response
result = generate_result(
"https://api.soceton.com/script-ocr/read",
"dummies/resized-images/driving-license_0.jpg",
"dummies/ymls/driving-license_0.yml", {
"X-API-KEY": SOCETONAI_API_KEY,
"X-API-SECRET": SOCETONAI_API_SECRET
})
result = result.json()
values = {}
for k in result["result"].keys():
try:
values[k] = result["result"][k]["value"]
except Exception as e:
print(k, ":", e)
print(json.dumps(values, indent=4))
{
"license_no": "DL - 48293017",
"full_name": "John Doe",
"date_of_birth": "Jan 15 , 1990",
"address": "1234 Demo Street , Example City , CA 90010",
"class": "C",
"sex": "M",
"height": "5'11 \""
}
Annotating the result on the image (Optional)ΒΆ
Keywords are in green, value positions are in blue, and value words are in red.
InΒ [3]:
import numpy as np
import cv2
w, h = img.size
img_copy = np.asarray(img).copy()
def annotate_value(key):
try:
thickness = 2
color = (0, 0, 255)
position = result["result"][key]["position"]
top, left, bottom, right = int(position["top"] * h), int(position["left"] * w), int(position["bottom"] * h), int(position["right"] * w)
cv2.rectangle(img_copy, (left, top), (right, bottom), color, thickness)
except Exception as e:
print(e)
try:
thickness = 2
color = (0, 255, 0)
for keyword in result["result"][key]["keywords"]:
y1, x1, y2, x2 = int(keyword["y1"] * h), int(keyword["x1"] * w), int(keyword["y2"] * h), int(keyword["x2"] * w)
cv2.rectangle(img_copy, (x1, y1), (x2, y2), color, thickness)
except Exception as e:
print(e)
try:
thickness = 2
color = (255, 0, 0)
for word in result["result"][key]["words"]:
y1, x1, y2, x2 = int(word["y1"] * h), int(word["x1"] * w), int(word["y2"] * h), int(word["x2"] * w)
cv2.rectangle(img_copy, (x1, y1), (x2, y2), color, thickness)
except Exception as e:
print(e)
for k in result["result"].keys():
annotate_value(k)
Image.fromarray(img_copy)
Out[3]:
Printing the valuesΒΆ
InΒ [4]:
print(json.dumps(result, indent=4))
{
"success": true,
"result": {
"license_no": {
"value": "DL - 48293017",
"keywords": [
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 0,
"value": "License",
"confidence": 0.9913142919540404,
"x1": 0.2589231699939504,
"y1": 0.3003194888178914,
"x2": 0.3411978221415608,
"y2": 0.3184238551650692
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 1,
"value": "No",
"confidence": 0.9741203784942628,
"x1": 0.2589231699939504,
"y1": 0.3003194888178914,
"x2": 0.3411978221415608,
"y2": 0.3184238551650692
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 2,
"value": ":",
"confidence": 0.969878315925598,
"x1": 0.2589231699939504,
"y1": 0.3003194888178914,
"x2": 0.3411978221415608,
"y2": 0.3184238551650692
}
],
"words": [
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 3,
"value": "DL",
"confidence": 0.98962664604187,
"x1": 0.3454325468844525,
"y1": 0.3003194888178914,
"x2": 0.3635813672111312,
"y2": 0.3184238551650692
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 4,
"value": "-",
"confidence": 0.9864776134490968,
"x1": 0.3629764065335753,
"y1": 0.3003194888178914,
"x2": 0.367816091954023,
"y2": 0.3184238551650692
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 5,
"value": "48293017",
"confidence": 0.9919999837875366,
"x1": 0.367211131276467,
"y1": 0.3003194888178914,
"x2": 0.4337568058076225,
"y2": 0.3184238551650692
}
],
"position": {
"top": 0.28221512247071356,
"left": 0.3411978221415608,
"bottom": 0.33652822151224704,
"right": 0.5175006481721546
}
},
"full_name": {
"value": "John Doe",
"keywords": [
{
"page_idx": 0,
"block_idx": 6,
"line_idx": 0,
"word_idx": 0,
"value": "Name",
"confidence": 0.984792411327362,
"x1": 0.2583182093163944,
"y1": 0.349307774227902,
"x2": 0.3055051421657592,
"y2": 0.3759318423855165
},
{
"page_idx": 0,
"block_idx": 6,
"line_idx": 0,
"word_idx": 1,
"value": ":",
"confidence": 0.9680795073509216,
"x1": 0.2583182093163944,
"y1": 0.349307774227902,
"x2": 0.3055051421657592,
"y2": 0.3759318423855165
}
],
"words": [
{
"page_idx": 0,
"block_idx": 6,
"line_idx": 0,
"word_idx": 2,
"value": "John",
"confidence": 0.9877939820289612,
"x1": 0.3073200241984271,
"y1": 0.3482428115015974,
"x2": 0.3393829401088929,
"y2": 0.3748668796592119
},
{
"page_idx": 0,
"block_idx": 6,
"line_idx": 0,
"word_idx": 3,
"value": "Doe",
"confidence": 0.9891143441200256,
"x1": 0.3436176648517846,
"y1": 0.349307774227902,
"x2": 0.3714458560193587,
"y2": 0.3738019169329074
}
],
"position": {
"top": 0.32268370607028746,
"left": 0.3055051421657592,
"bottom": 0.40255591054313106,
"right": 0.48245614035087725
}
},
"date_of_birth": {
"value": "Jan 15 , 1990",
"keywords": [
{
"page_idx": 0,
"block_idx": 7,
"line_idx": 0,
"word_idx": 0,
"value": "Date",
"confidence": 0.9878840446472168,
"x1": 0.2589231699939504,
"y1": 0.4046858359957401,
"x2": 0.3557168784029038,
"y2": 0.4270500532481363
},
{
"page_idx": 0,
"block_idx": 7,
"line_idx": 0,
"word_idx": 1,
"value": "of",
"confidence": 0.9864633083343506,
"x1": 0.2589231699939504,
"y1": 0.4046858359957401,
"x2": 0.3557168784029038,
"y2": 0.4270500532481363
},
{
"page_idx": 0,
"block_idx": 7,
"line_idx": 0,
"word_idx": 2,
"value": "Birth",
"confidence": 0.9885376691818236,
"x1": 0.2589231699939504,
"y1": 0.4046858359957401,
"x2": 0.3557168784029038,
"y2": 0.4270500532481363
},
{
"page_idx": 0,
"block_idx": 7,
"line_idx": 0,
"word_idx": 3,
"value": ":",
"confidence": 0.97165447473526,
"x1": 0.2589231699939504,
"y1": 0.4046858359957401,
"x2": 0.3557168784029038,
"y2": 0.4270500532481363
}
],
"words": [
{
"page_idx": 0,
"block_idx": 7,
"line_idx": 0,
"word_idx": 4,
"value": "Jan",
"confidence": 0.981728494167328,
"x1": 0.3575317604355716,
"y1": 0.4046858359957401,
"x2": 0.3793103448275862,
"y2": 0.4270500532481363
},
{
"page_idx": 0,
"block_idx": 7,
"line_idx": 0,
"word_idx": 5,
"value": "15",
"confidence": 0.9816383719444276,
"x1": 0.3853599516031458,
"y1": 0.4046858359957401,
"x2": 0.4004839685420447,
"y2": 0.4270500532481363
},
{
"page_idx": 0,
"block_idx": 7,
"line_idx": 0,
"word_idx": 6,
"value": ",",
"confidence": 0.968222975730896,
"x1": 0.4004839685420447,
"y1": 0.4046858359957401,
"x2": 0.4041137326073805,
"y2": 0.4270500532481363
},
{
"page_idx": 0,
"block_idx": 7,
"line_idx": 0,
"word_idx": 7,
"value": "1990",
"confidence": 0.9886678457260132,
"x1": 0.4095583787053841,
"y1": 0.4046858359957401,
"x2": 0.440411373260738,
"y2": 0.4281150159744409
}
],
"position": {
"top": 0.3823216187433439,
"left": 0.3557168784029038,
"bottom": 0.44941427050053245,
"right": 0.5977011494252873
}
},
"address": {
"value": "1234 Demo Street , Example City , CA 90010",
"keywords": [
{
"page_idx": 0,
"block_idx": 8,
"line_idx": 0,
"word_idx": 0,
"value": "Address",
"confidence": 0.9905146956443788,
"x1": 0.2583182093163944,
"y1": 0.4579339723109691,
"x2": 0.3200241984271022,
"y2": 0.4813631522896698
},
{
"page_idx": 0,
"block_idx": 8,
"line_idx": 0,
"word_idx": 1,
"value": ":",
"confidence": 0.9695435166358948,
"x1": 0.2583182093163944,
"y1": 0.4579339723109691,
"x2": 0.3200241984271022,
"y2": 0.4813631522896698
}
],
"words": [
{
"page_idx": 0,
"block_idx": 8,
"line_idx": 0,
"word_idx": 2,
"value": "1234",
"confidence": 0.98670494556427,
"x1": 0.3248638838475499,
"y1": 0.4579339723109691,
"x2": 0.3575317604355716,
"y2": 0.4813631522896698
},
{
"page_idx": 0,
"block_idx": 8,
"line_idx": 0,
"word_idx": 3,
"value": "Demo",
"confidence": 0.991857886314392,
"x1": 0.3623714458560194,
"y1": 0.4579339723109691,
"x2": 0.4016938898971567,
"y2": 0.4813631522896698
},
{
"page_idx": 0,
"block_idx": 8,
"line_idx": 0,
"word_idx": 4,
"value": "Street",
"confidence": 0.9867011904716492,
"x1": 0.4065335753176043,
"y1": 0.4579339723109691,
"x2": 0.4470659407138536,
"y2": 0.4813631522896698
},
{
"page_idx": 0,
"block_idx": 8,
"line_idx": 0,
"word_idx": 5,
"value": ",",
"confidence": 0.9810553193092346,
"x1": 0.4470659407138536,
"y1": 0.4579339723109691,
"x2": 0.4506957047791893,
"y2": 0.4813631522896698
},
{
"page_idx": 0,
"block_idx": 8,
"line_idx": 0,
"word_idx": 6,
"value": "Example",
"confidence": 0.9912849068641664,
"x1": 0.455535390199637,
"y1": 0.4579339723109691,
"x2": 0.5124016938898972,
"y2": 0.4813631522896698
},
{
"page_idx": 0,
"block_idx": 8,
"line_idx": 0,
"word_idx": 7,
"value": "City",
"confidence": 0.9533565640449524,
"x1": 0.5172413793103449,
"y1": 0.4579339723109691,
"x2": 0.543254688445251,
"y2": 0.4813631522896698
},
{
"page_idx": 0,
"block_idx": 8,
"line_idx": 0,
"word_idx": 8,
"value": ",",
"confidence": 0.958345353603363,
"x1": 0.5420447670901392,
"y1": 0.4579339723109691,
"x2": 0.5462794918330308,
"y2": 0.4813631522896698
},
{
"page_idx": 0,
"block_idx": 8,
"line_idx": 0,
"word_idx": 9,
"value": "CA",
"confidence": 0.9829576015472412,
"x1": 0.5505142165759226,
"y1": 0.4579339723109691,
"x2": 0.5686630369026013,
"y2": 0.4813631522896698
},
{
"page_idx": 0,
"block_idx": 8,
"line_idx": 0,
"word_idx": 10,
"value": "90010",
"confidence": 0.9901785254478456,
"x1": 0.5722928009679371,
"y1": 0.4579339723109691,
"x2": 0.6146400483968542,
"y2": 0.4813631522896698
}
],
"position": {
"top": 0.4345047923322684,
"left": 0.3200241984271022,
"bottom": 0.5047923322683705,
"right": 0.7167055569959384
}
},
"class": {
"value": "C",
"keywords": [
{
"page_idx": 0,
"block_idx": 9,
"line_idx": 0,
"word_idx": 0,
"value": "Class",
"confidence": 0.9502596259117126,
"x1": 0.2583182093163944,
"y1": 0.5111821086261981,
"x2": 0.3000604960677556,
"y2": 0.5303514376996805
},
{
"page_idx": 0,
"block_idx": 9,
"line_idx": 0,
"word_idx": 1,
"value": ":",
"confidence": 0.9661848545074464,
"x1": 0.2583182093163944,
"y1": 0.5111821086261981,
"x2": 0.3000604960677556,
"y2": 0.5303514376996805
}
],
"words": [
{
"page_idx": 0,
"block_idx": 9,
"line_idx": 0,
"word_idx": 2,
"value": "C",
"confidence": 0.9787306189537048,
"x1": 0.3036902601330913,
"y1": 0.5111821086261981,
"x2": 0.3127646702964307,
"y2": 0.5303514376996805
}
],
"position": {
"top": 0.4920127795527156,
"left": 0.3000604960677556,
"bottom": 0.549520766773163,
"right": 0.383545069570478
}
},
"sex": {
"value": "M",
"keywords": [
{
"page_idx": 0,
"block_idx": 10,
"line_idx": 0,
"word_idx": 0,
"value": "Sex",
"confidence": 0.9733372330665588,
"x1": 0.2583182093163944,
"y1": 0.5633652822151225,
"x2": 0.2861464004839685,
"y2": 0.582534611288605
},
{
"page_idx": 0,
"block_idx": 10,
"line_idx": 0,
"word_idx": 1,
"value": ":",
"confidence": 0.9797183275222778,
"x1": 0.2583182093163944,
"y1": 0.5633652822151225,
"x2": 0.2861464004839685,
"y2": 0.582534611288605
}
],
"words": [
{
"page_idx": 0,
"block_idx": 10,
"line_idx": 0,
"word_idx": 2,
"value": "M",
"confidence": 0.9804967641830444,
"x1": 0.2909860859044162,
"y1": 0.5633652822151225,
"x2": 0.3024803387779794,
"y2": 0.5814696485623003
}
],
"position": {
"top": 0.54419595314164,
"left": 0.2861464004839685,
"bottom": 0.6017039403620874,
"right": 0.3789070377092156
}
},
"height": {
"value": "5'11 \"",
"keywords": [
{
"page_idx": 0,
"block_idx": 11,
"line_idx": 0,
"word_idx": 0,
"value": "Height",
"confidence": 0.9852599501609802,
"x1": 0.2583182093163944,
"y1": 0.6144834930777423,
"x2": 0.3109497882637628,
"y2": 0.6389776357827476
},
{
"page_idx": 0,
"block_idx": 11,
"line_idx": 0,
"word_idx": 1,
"value": ":",
"confidence": 0.9744938611984252,
"x1": 0.2583182093163944,
"y1": 0.6144834930777423,
"x2": 0.3109497882637628,
"y2": 0.6389776357827476
}
],
"words": [
{
"page_idx": 0,
"block_idx": 11,
"line_idx": 0,
"word_idx": 2,
"value": "5'11",
"confidence": 0.9515934586524964,
"x1": 0.3145795523290986,
"y1": 0.6134185303514377,
"x2": 0.3418027828191167,
"y2": 0.6368477103301384
},
{
"page_idx": 0,
"block_idx": 11,
"line_idx": 0,
"word_idx": 3,
"value": "\"",
"confidence": 0.9554415345191956,
"x1": 0.3411978221415608,
"y1": 0.6134185303514377,
"x2": 0.3490623109497883,
"y2": 0.6347177848775293
}
],
"position": {
"top": 0.589989350372737,
"left": 0.3127041742286751,
"bottom": 0.6634717784877529,
"right": 0.3986690865093768
}
}
}
}