Documentation
How to extract information from National IDs using SoceTonAI Script OCRΒΆ
In this guide, Iβll show how to use SoceTonAI Script OCR to automatically extract key information from a National IDs. 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: NID
description: "Extract key information from National ID card using OCR"
development: true
return_ocr_output: false
return_full_text: false
fields:
- name: id_number
label: "ID Number"
find:
type: text
keywords:
- keyword: "ID"
index: 1
next_keyword_position: [ 1, -1, 1, 10 ]
- keyword: "Number"
next_keyword_position: [ 1, -1, 1, 3 ]
- keyword: ":"
position_of_value: [1, -1, 2, 8]
words: 5
debug: false
returns:
- keywords
- words
- position
- name: full_name
label: "Name"
find:
type: text
keywords:
- keyword: "Name"
index: 0
position_of_value: [1, -1, 4.5, 20]
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"
position_of_value: [1, -1, 4.2, 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: date_of_issue
label: "Date of Issue"
find:
type: text
keywords:
- keyword: "Date"
index: 1
next_keyword_position: [ 1, -1, 1, 7 ]
- keyword: "of"
next_keyword_position: [ 1, -1, 1, 7 ]
- keyword: "Issue"
position_of_value: [1, -1, 4.2, 10]
words: 10
debug: false
returns:
- keywords
- words
- position
- name: date_of_expiry
label: "Date of Expiry"
find:
type: text
keywords:
- keyword: "Date"
index: 2
next_keyword_position: [ 1, -1, 1, 7 ]
- keyword: "of"
next_keyword_position: [ 1, -1, 1, 7 ]
- keyword: "Expiry"
position_of_value: [1, -1, 4.2, 10]
words: 10
debug: false
returns:
- keywords
- words
- position
The imageΒΆ
InΒ [1]:
from PIL import Image
img = Image.open("dummies/resized-images/nid-1_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/nid-1_0.jpg",
"dummies/ymls/nid-1.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))
{
"id_number": "US - 98347201",
"full_name": "John Doe",
"date_of_birth": "Jan 15 , 1990",
"address": "1234 Demo Street , Example City , CA 90010",
"date_of_issue": "Jan 10 , 2025",
"date_of_expiry": "Jan 10 , 2035"
}
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 resultΒΆ
InΒ [4]:
print(json.dumps(result, indent=4))
{
"success": true,
"result": {
"id_number": {
"value": "US - 98347201",
"keywords": [
{
"page_idx": 0,
"block_idx": 2,
"line_idx": 0,
"word_idx": 0,
"value": "ID",
"confidence": 0.9876700639724731,
"x1": 0.2480338777979431,
"y1": 0.2753128555176337,
"x2": 0.3272837265577737,
"y2": 0.2946530147895335
},
{
"page_idx": 0,
"block_idx": 2,
"line_idx": 0,
"word_idx": 1,
"value": "Number",
"confidence": 0.992880403995514,
"x1": 0.2480338777979431,
"y1": 0.2753128555176337,
"x2": 0.3272837265577737,
"y2": 0.2946530147895335
},
{
"page_idx": 0,
"block_idx": 2,
"line_idx": 0,
"word_idx": 2,
"value": ":",
"confidence": 0.9793447852134703,
"x1": 0.2480338777979431,
"y1": 0.2753128555176337,
"x2": 0.3272837265577737,
"y2": 0.2946530147895335
}
],
"words": [
{
"page_idx": 0,
"block_idx": 2,
"line_idx": 0,
"word_idx": 3,
"value": "US",
"confidence": 0.980813443660736,
"x1": 0.3321234119782214,
"y1": 0.2753128555176337,
"x2": 0.3472474289171204,
"y2": 0.2946530147895335
},
{
"page_idx": 0,
"block_idx": 2,
"line_idx": 0,
"word_idx": 4,
"value": "-",
"confidence": 0.990292191505432,
"x1": 0.3484573502722323,
"y1": 0.2753128555176337,
"x2": 0.352692075015124,
"y2": 0.2946530147895335
},
{
"page_idx": 0,
"block_idx": 2,
"line_idx": 0,
"word_idx": 5,
"value": "98347201",
"confidence": 0.9898763298988342,
"x1": 0.352692075015124,
"y1": 0.2753128555176337,
"x2": 0.4119782214156079,
"y2": 0.2946530147895335
}
],
"position": {
"top": 0.2559726962457339,
"left": 0.3272837265577737,
"bottom": 0.3139931740614333,
"right": 0.6442831215970962
}
},
"full_name": {
"value": "John Doe",
"keywords": [
{
"page_idx": 0,
"block_idx": 3,
"line_idx": 0,
"word_idx": 0,
"value": "Name",
"confidence": 0.9934477806091307,
"x1": 0.249243799153055,
"y1": 0.3208191126279863,
"x2": 0.2885662431941924,
"y2": 0.3447098976109215
}
],
"words": [
{
"page_idx": 0,
"block_idx": 3,
"line_idx": 0,
"word_idx": 2,
"value": "John",
"confidence": 0.9922775030136108,
"x1": 0.294615849969752,
"y1": 0.3208191126279863,
"x2": 0.323653962492438,
"y2": 0.3435722411831627
},
{
"page_idx": 0,
"block_idx": 3,
"line_idx": 0,
"word_idx": 3,
"value": "Doe",
"confidence": 0.9642711281776428,
"x1": 0.3290986085904416,
"y1": 0.3208191126279863,
"x2": 0.3532970356926799,
"y2": 0.3424345847554039
}
],
"position": {
"top": 0.29692832764505106,
"left": 0.29348154869933457,
"bottom": 0.36860068259385675,
"right": 0.4851784633998793
}
},
"date_of_birth": {
"value": "Jan 15 , 1990",
"keywords": [
{
"page_idx": 0,
"block_idx": 4,
"line_idx": 0,
"word_idx": 0,
"value": "Date",
"confidence": 0.988333225250244,
"x1": 0.249243799153055,
"y1": 0.3697383390216154,
"x2": 0.3345432546884452,
"y2": 0.3924914675767918
},
{
"page_idx": 0,
"block_idx": 4,
"line_idx": 0,
"word_idx": 1,
"value": "of",
"confidence": 0.9839328527450562,
"x1": 0.249243799153055,
"y1": 0.3697383390216154,
"x2": 0.3345432546884452,
"y2": 0.3924914675767918
},
{
"page_idx": 0,
"block_idx": 4,
"line_idx": 0,
"word_idx": 2,
"value": "Birth",
"confidence": 0.9879787564277648,
"x1": 0.249243799153055,
"y1": 0.3697383390216154,
"x2": 0.3345432546884452,
"y2": 0.3924914675767918
}
],
"words": [
{
"page_idx": 0,
"block_idx": 4,
"line_idx": 0,
"word_idx": 4,
"value": "Jan",
"confidence": 0.97020161151886,
"x1": 0.3418027828191167,
"y1": 0.3697383390216154,
"x2": 0.3617664851784634,
"y2": 0.3924914675767918
},
{
"page_idx": 0,
"block_idx": 4,
"line_idx": 0,
"word_idx": 5,
"value": "15",
"confidence": 0.9855862855911256,
"x1": 0.3666061705989111,
"y1": 0.3697383390216154,
"x2": 0.3811252268602541,
"y2": 0.3924914675767918
},
{
"page_idx": 0,
"block_idx": 4,
"line_idx": 0,
"word_idx": 6,
"value": ",",
"confidence": 0.9694351553916932,
"x1": 0.38173018753781,
"y1": 0.3697383390216154,
"x2": 0.3853599516031458,
"y2": 0.3924914675767918
},
{
"page_idx": 0,
"block_idx": 4,
"line_idx": 0,
"word_idx": 7,
"value": "1990",
"confidence": 0.9899269938468932,
"x1": 0.3895946763460375,
"y1": 0.3697383390216154,
"x2": 0.4192377495462795,
"y2": 0.3924914675767918
}
],
"position": {
"top": 0.346985210466439,
"left": 0.3388082274652147,
"bottom": 0.41524459613196824,
"right": 0.5477918935269207
}
},
"address": {
"value": "1234 Demo Street , Example City , CA 90010",
"keywords": [
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 0,
"value": "Address",
"confidence": 0.9874629378318788,
"x1": 0.2474289171203871,
"y1": 0.4175199089874857,
"x2": 0.3067150635208711,
"y2": 0.4414106939704209
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 1,
"value": ":",
"confidence": 0.9598589539527892,
"x1": 0.2474289171203871,
"y1": 0.4175199089874857,
"x2": 0.3067150635208711,
"y2": 0.4414106939704209
}
],
"words": [
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 2,
"value": "1234",
"confidence": 0.9860724806785583,
"x1": 0.3109497882637628,
"y1": 0.4175199089874857,
"x2": 0.3411978221415608,
"y2": 0.4414106939704209
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 3,
"value": "Demo",
"confidence": 0.991941213607788,
"x1": 0.3454325468844525,
"y1": 0.4175199089874857,
"x2": 0.382335148215366,
"y2": 0.4414106939704209
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 4,
"value": "Street",
"confidence": 0.9833234548568726,
"x1": 0.3865698729582577,
"y1": 0.4175199089874857,
"x2": 0.4246823956442831,
"y2": 0.4414106939704209
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 5,
"value": ",",
"confidence": 0.955698013305664,
"x1": 0.4246823956442831,
"y1": 0.4175199089874857,
"x2": 0.4283121597096189,
"y2": 0.4414106939704209
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 6,
"value": "Example",
"confidence": 0.9922839403152466,
"x1": 0.4319419237749546,
"y1": 0.4175199089874857,
"x2": 0.4857834240774349,
"y2": 0.4414106939704209
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 7,
"value": "City",
"confidence": 0.9756269454956056,
"x1": 0.4906231094978826,
"y1": 0.4175199089874857,
"x2": 0.514216575922565,
"y2": 0.4414106939704209
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 8,
"value": ",",
"confidence": 0.9828117489814758,
"x1": 0.5136116152450091,
"y1": 0.4175199089874857,
"x2": 0.5172413793103449,
"y2": 0.4414106939704209
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 9,
"value": "CA",
"confidence": 0.9872676134109496,
"x1": 0.5208711433756806,
"y1": 0.4175199089874857,
"x2": 0.5378100423472474,
"y2": 0.4414106939704209
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 0,
"word_idx": 10,
"value": "90010",
"confidence": 0.9906875491142272,
"x1": 0.5420447670901392,
"y1": 0.4175199089874857,
"x2": 0.5807622504537205,
"y2": 0.4414106939704209
}
],
"position": {
"top": 0.3936291240045505,
"left": 0.3067150635208711,
"bottom": 0.46530147895335605,
"right": 0.6878402903811254
}
},
"date_of_issue": {
"value": "Jan 10 , 2025",
"keywords": [
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 1,
"word_idx": 0,
"value": "Date",
"confidence": 0.9904552102088928,
"x1": 0.249243799153055,
"y1": 0.4653014789533561,
"x2": 0.3369630973986691,
"y2": 0.4869169510807736
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 1,
"word_idx": 1,
"value": "of",
"confidence": 0.9856268167495728,
"x1": 0.249243799153055,
"y1": 0.4653014789533561,
"x2": 0.3369630973986691,
"y2": 0.4869169510807736
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 1,
"word_idx": 2,
"value": "Issue",
"confidence": 0.9636290073394777,
"x1": 0.249243799153055,
"y1": 0.4653014789533561,
"x2": 0.3369630973986691,
"y2": 0.4869169510807736
}
],
"words": [
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 1,
"word_idx": 4,
"value": "Jan",
"confidence": 0.9654110074043274,
"x1": 0.3430127041742287,
"y1": 0.4653014789533561,
"x2": 0.3629764065335753,
"y2": 0.4869169510807736
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 1,
"word_idx": 5,
"value": "10",
"confidence": 0.979788899421692,
"x1": 0.3684210526315789,
"y1": 0.4653014789533561,
"x2": 0.3829401088929219,
"y2": 0.4869169510807736
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 1,
"word_idx": 6,
"value": ",",
"confidence": 0.9731096029281616,
"x1": 0.38173018753781,
"y1": 0.4653014789533561,
"x2": 0.3859649122807017,
"y2": 0.4869169510807736
},
{
"page_idx": 0,
"block_idx": 5,
"line_idx": 1,
"word_idx": 7,
"value": "2025",
"confidence": 0.9778118133544922,
"x1": 0.3901996370235934,
"y1": 0.4653014789533561,
"x2": 0.4210526315789473,
"y2": 0.4869169510807736
}
],
"position": {
"top": 0.4436860068259386,
"left": 0.3413490623109498,
"bottom": 0.5085324232081911,
"right": 0.5562613430127044
}
},
"date_of_expiry": {
"value": "Jan 10 , 2035",
"keywords": [
{
"page_idx": 0,
"block_idx": 6,
"line_idx": 0,
"word_idx": 0,
"value": "Date",
"confidence": 0.9857668876647948,
"x1": 0.249848759830611,
"y1": 0.5119453924914675,
"x2": 0.3442226255293406,
"y2": 0.5358361774744027
},
{
"page_idx": 0,
"block_idx": 6,
"line_idx": 0,
"word_idx": 1,
"value": "of",
"confidence": 0.981400191783905,
"x1": 0.249848759830611,
"y1": 0.5119453924914675,
"x2": 0.3442226255293406,
"y2": 0.5358361774744027
},
{
"page_idx": 0,
"block_idx": 6,
"line_idx": 0,
"word_idx": 2,
"value": "Expiry",
"confidence": 0.9862617254257202,
"x1": 0.249848759830611,
"y1": 0.5119453924914675,
"x2": 0.3442226255293406,
"y2": 0.5358361774744027
}
],
"words": [
{
"page_idx": 0,
"block_idx": 6,
"line_idx": 0,
"word_idx": 4,
"value": "Jan",
"confidence": 0.9725005626678468,
"x1": 0.3490623109497883,
"y1": 0.5119453924914675,
"x2": 0.3690260133091349,
"y2": 0.5358361774744027
},
{
"page_idx": 0,
"block_idx": 6,
"line_idx": 0,
"word_idx": 5,
"value": "10",
"confidence": 0.9817256927490234,
"x1": 0.3744706594071385,
"y1": 0.5119453924914675,
"x2": 0.3895946763460375,
"y2": 0.5358361774744027
},
{
"page_idx": 0,
"block_idx": 6,
"line_idx": 0,
"word_idx": 6,
"value": ",",
"confidence": 0.971858561038971,
"x1": 0.3889897156684815,
"y1": 0.5119453924914675,
"x2": 0.3932244404113733,
"y2": 0.5358361774744027
},
{
"page_idx": 0,
"block_idx": 6,
"line_idx": 0,
"word_idx": 7,
"value": "2035",
"confidence": 0.979802131652832,
"x1": 0.3956442831215971,
"y1": 0.5119453924914675,
"x2": 0.4277071990320629,
"y2": 0.5358361774744027
}
],
"position": {
"top": 0.48805460750853236,
"left": 0.34894131881427704,
"bottom": 0.5597269624573379,
"right": 0.5801572897761645
}
}
}
}