idvpackage 3.0.10__py3-none-any.whl → 3.0.12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- idvpackage/common.py +4 -964
- idvpackage/iraq_id_extraction_withopenai.py +374 -893
- idvpackage/jor_passport_extraction.py +1 -6
- idvpackage/liveness_spoofing_v2.py +2 -45
- idvpackage/ocr.py +1051 -2448
- idvpackage/ocr_utils.py +144 -486
- idvpackage/pse_passport_extraction.py +18 -292
- idvpackage/qatar_id_extraction.py +4 -956
- idvpackage/sudan_passport_extraction.py +0 -928
- idvpackage/syr_passport_extraction.py +27 -402
- idvpackage/uae_id_extraction.py +87 -151
- {idvpackage-3.0.10.dist-info → idvpackage-3.0.12.dist-info}/METADATA +1 -1
- idvpackage-3.0.12.dist-info/RECORD +34 -0
- {idvpackage-3.0.10.dist-info → idvpackage-3.0.12.dist-info}/WHEEL +1 -1
- idvpackage/ekyc.py +0 -78
- idvpackage/genai_utils.py +0 -309
- idvpackage/iraq_id_extraction.py +0 -992
- idvpackage/iraq_passport_extraction.py +0 -588
- idvpackage/lazy_imports.py +0 -44
- idvpackage/lebanon_passport_extraction.py +0 -161
- idvpackage/sau_id_extraction.py +0 -248
- idvpackage/sudan_id_extraction.py +0 -764
- idvpackage-3.0.10.dist-info/RECORD +0 -42
- {idvpackage-3.0.10.dist-info → idvpackage-3.0.12.dist-info}/licenses/LICENSE +0 -0
- {idvpackage-3.0.10.dist-info → idvpackage-3.0.12.dist-info}/top_level.txt +0 -0
|
@@ -1,292 +1,7 @@
|
|
|
1
|
-
# import re
|
|
2
|
-
# import google.generativeai as genai
|
|
3
|
-
# from datetime import datetime
|
|
4
|
-
# from googletrans import Translator
|
|
5
|
-
# import json
|
|
6
|
-
# import logging
|
|
7
|
-
|
|
8
|
-
# def configure_genai(api_key):
|
|
9
|
-
# try:
|
|
10
|
-
# genai.configure(api_key=api_key)
|
|
11
|
-
# model = genai.GenerativeModel(model_name = "gemini-2.0-flash-lite")
|
|
12
|
-
# logging.info("GenAI model configured successfully.")
|
|
13
|
-
# return model
|
|
14
|
-
# except Exception as e:
|
|
15
|
-
# logging.error(f"Error configuring GenAI: {e}")
|
|
16
|
-
# return None
|
|
17
|
-
|
|
18
|
-
# def genai_vision_pse(detected_text, model):
|
|
19
|
-
# result = model.generate_content(
|
|
20
|
-
# [detected_text, "\n\n", "From provided {detected_text} give me all required information in english. full_name, first_name, last_name, mother_name, passport_number(only digits, i.e N° or No), id_number, dob(Date of Birth dd/mm/yy format), Place of Birth, gender(M/F), issuing_date(dd/mm/yy format), expiry_date (dd/mm/yy format), Place of Issue, occupation(profession), nationality and both lines of the MRZ, please give me just dictionary dont write anything else - full_name, first_name, last_name, mother_name, passport_number, id_number, dob, place_of_birth: gender, issuing_date, expiry_date, issuing_place, occupation, mrz1, mrz2. Note that mrz1 is the line that starts with P and mrz2 is the line that starts with passport number"]
|
|
21
|
-
# )
|
|
22
|
-
# logging.info(f"GenAI Raw Output: {result.text}")
|
|
23
|
-
# return result.text
|
|
24
|
-
|
|
25
|
-
# def reformat_date(date_str):
|
|
26
|
-
# try:
|
|
27
|
-
# date_obj = datetime.strptime(date_str, '%d-%m-%Y')
|
|
28
|
-
|
|
29
|
-
# return date_obj.strftime('%d/%m/%Y')
|
|
30
|
-
# except ValueError:
|
|
31
|
-
# return date_str
|
|
32
|
-
|
|
33
|
-
# def swap_dates_if_needed(data_dict):
|
|
34
|
-
# try:
|
|
35
|
-
# # Parse the dates
|
|
36
|
-
# issuing_date = datetime.strptime(data_dict['issuing_date'], '%d/%m/%Y')
|
|
37
|
-
# expiry_date = datetime.strptime(data_dict['expiry_date'], '%d/%m/%Y')
|
|
38
|
-
|
|
39
|
-
# if issuing_date > expiry_date:
|
|
40
|
-
# data_dict['issuing_date'], data_dict['expiry_date'] = data_dict['expiry_date'], data_dict['issuing_date']
|
|
41
|
-
# logging.info("Dates swapped: Issuing date and expiry date were in the wrong order.")
|
|
42
|
-
|
|
43
|
-
# except ValueError as e:
|
|
44
|
-
# logging.info(f"Error parsing dates: {e}")
|
|
45
|
-
|
|
46
|
-
# return data_dict
|
|
47
|
-
|
|
48
|
-
# def mrz_add(mrz_data_dict):
|
|
49
|
-
# mrz_2 = mrz_data_dict['mrz2']
|
|
50
|
-
# mrz_1 = mrz_data_dict['mrz1']
|
|
51
|
-
|
|
52
|
-
# # 1. Extract Passport Number
|
|
53
|
-
# try:
|
|
54
|
-
# if 'passport_number' not in mrz_data_dict:
|
|
55
|
-
# pattern_passport = r'^(\d{7})'
|
|
56
|
-
# match_passport = re.search(pattern_passport, mrz_2)
|
|
57
|
-
# if match_passport:
|
|
58
|
-
# passport_number = match_passport.group(1)
|
|
59
|
-
# mrz_data_dict['passport_number'] = passport_number
|
|
60
|
-
# except Exception as e:
|
|
61
|
-
# print(f"Error extracting passport number for PSE: {e}")
|
|
62
|
-
|
|
63
|
-
# # 2. Extract Nationality
|
|
64
|
-
# try:
|
|
65
|
-
# if 'nationality' not in mrz_data_dict:
|
|
66
|
-
# pattern_nationality = r'<\d([A-Z]{3})'
|
|
67
|
-
# match_nationality = re.search(pattern_nationality, mrz_2)
|
|
68
|
-
# if match_nationality:
|
|
69
|
-
# nationality = match_nationality.group(1)
|
|
70
|
-
# mrz_data_dict['nationality'] = nationality
|
|
71
|
-
# except Exception as e:
|
|
72
|
-
# logging.info(f"Error extracting nationality for PSE: {e}")
|
|
73
|
-
|
|
74
|
-
# # 3. Extract Date of Birth (DD/MM/YYYY format)
|
|
75
|
-
# try:
|
|
76
|
-
# if 'dob' not in mrz_data_dict:
|
|
77
|
-
# pattern_birth_date = r'\d{7}<\d[A-Z]{3}(\d{6})'
|
|
78
|
-
# match_birth_date = re.search(pattern_birth_date, mrz_2)
|
|
79
|
-
# if match_birth_date:
|
|
80
|
-
# birth_date_raw = match_birth_date.group(1)
|
|
81
|
-
# year_prefix = '19' if int(birth_date_raw[:2]) > 23 else '20'
|
|
82
|
-
# birth_date = f"{birth_date_raw[4:]}/{birth_date_raw[2:4]}/{year_prefix}{birth_date_raw[:2]}"
|
|
83
|
-
# mrz_data_dict['dob'] = birth_date
|
|
84
|
-
# except Exception as e:
|
|
85
|
-
# logging.info(f"Error extracting date of birth for PSE: {e}")
|
|
86
|
-
|
|
87
|
-
# # 4. Extract Gender
|
|
88
|
-
# try:
|
|
89
|
-
# if 'gender' not in mrz_data_dict:
|
|
90
|
-
# pattern_gender = r'[A-Z]{3}\d{6}([MF])'
|
|
91
|
-
# match_gender = re.search(pattern_gender, mrz_2)
|
|
92
|
-
# if match_gender:
|
|
93
|
-
# gender = match_gender.group(1)
|
|
94
|
-
# mrz_data_dict['gender'] = gender
|
|
95
|
-
# except Exception as e:
|
|
96
|
-
# print(f"Error extracting gender for PSE: {e}")
|
|
97
|
-
|
|
98
|
-
# # 5. Extract Expiration Date (DD/MM/YYYY format)
|
|
99
|
-
# try:
|
|
100
|
-
# if 'expiry_date' not in mrz_data_dict:
|
|
101
|
-
# pattern_expiration_date = r'[MF](\d{6})'
|
|
102
|
-
# match_expiration_date = re.search(pattern_expiration_date, mrz_2)
|
|
103
|
-
# if match_expiration_date:
|
|
104
|
-
# expiration_date_raw = match_expiration_date.group(1)
|
|
105
|
-
# year_prefix = '19' if int(expiration_date_raw[:2]) > 50 else '20'
|
|
106
|
-
# expiration_date = f"{expiration_date_raw[4:]}/{expiration_date_raw[2:4]}/{year_prefix}{expiration_date_raw[:2]}"
|
|
107
|
-
# mrz_data_dict['expiry_date'] = expiration_date
|
|
108
|
-
# except Exception as e:
|
|
109
|
-
# logging.info(f"Error extracting expiration date for PSE: {e}")
|
|
110
|
-
|
|
111
|
-
# # 6. Extract Surname from MRZ_1
|
|
112
|
-
# # Updated to handle multiple variations of MRZ structures.
|
|
113
|
-
# try:
|
|
114
|
-
# if 'last_name' not in mrz_data_dict:
|
|
115
|
-
# pattern_surname = r'P<PSE([A-Z]+)<'
|
|
116
|
-
# match_surname = re.search(pattern_surname, mrz_1)
|
|
117
|
-
# if match_surname:
|
|
118
|
-
# surname = match_surname.group(1)
|
|
119
|
-
# mrz_data_dict['last_name'] = surname
|
|
120
|
-
# except Exception as e:
|
|
121
|
-
# print(f"Error extracting surname for PSE: {e}")
|
|
122
|
-
|
|
123
|
-
# # 7. Extract Given Name (First Name) from MRZ_1
|
|
124
|
-
# # Modified pattern to not rely on `<F`, as MRZ_1 structure can vary.
|
|
125
|
-
# try:
|
|
126
|
-
# if 'first_name' not in mrz_data_dict:
|
|
127
|
-
# pattern_given_name = r'<([A-Z]+)<[A-Z]<'
|
|
128
|
-
# match_given_name = re.search(pattern_given_name, mrz_1)
|
|
129
|
-
# if match_given_name:
|
|
130
|
-
# given_name = match_given_name.group(1)
|
|
131
|
-
# mrz_data_dict['first_name'] = given_name
|
|
132
|
-
# except Exception as e:
|
|
133
|
-
# print(f"Error extracting first name for PSE: {e}")
|
|
134
|
-
|
|
135
|
-
# # 8. If the surname or name isn't filled, use a fallback approach
|
|
136
|
-
# # If MRZ_1 structure varies, you can adjust these patterns.
|
|
137
|
-
# try:
|
|
138
|
-
# if 'last_name' not in mrz_data_dict:
|
|
139
|
-
# # Fallback to capture everything after the country code
|
|
140
|
-
# fallback_pattern_surname = r'P<PSE([A-Z]+)'
|
|
141
|
-
# match_surname = re.search(fallback_pattern_surname, mrz_1)
|
|
142
|
-
# if match_surname:
|
|
143
|
-
# mrz_data_dict['last_name'] = match_surname.group(1)
|
|
144
|
-
# except Exception as e:
|
|
145
|
-
# print(f"Error extracting surname for PSE: {e}")
|
|
146
|
-
|
|
147
|
-
# try:
|
|
148
|
-
# if 'first_name' not in mrz_data_dict:
|
|
149
|
-
# # Fallback to capture first name in different structures
|
|
150
|
-
# fallback_pattern_given_name = r'<([A-Z]+)<'
|
|
151
|
-
# match_given_name = re.search(fallback_pattern_given_name, mrz_1)
|
|
152
|
-
# if match_given_name:
|
|
153
|
-
# mrz_data_dict['first_name'] = match_given_name.group(1)
|
|
154
|
-
# except Exception as e:
|
|
155
|
-
# print(f"Error extracting first name for PSE: {e}")
|
|
156
|
-
|
|
157
|
-
# return mrz_data_dict
|
|
158
|
-
|
|
159
|
-
# def translate_arabic_words(dictionary):
|
|
160
|
-
# translator = Translator()
|
|
161
|
-
# translated_dict = {}
|
|
162
|
-
# for key, value in dictionary.items():
|
|
163
|
-
# if key not in ['mrz1', 'mrz2']:
|
|
164
|
-
# if isinstance(value, str):
|
|
165
|
-
|
|
166
|
-
# detected_lang = translator.detect(value).lang
|
|
167
|
-
# if detected_lang == 'ar':
|
|
168
|
-
# translated_text = translator.translate(value, src='ar', dest='en').text
|
|
169
|
-
# translated_dict[key] = translated_text
|
|
170
|
-
# else:
|
|
171
|
-
# translated_dict[key] = value
|
|
172
|
-
# else:
|
|
173
|
-
# translated_dict[key] = value
|
|
174
|
-
# else:
|
|
175
|
-
|
|
176
|
-
# translated_dict[key] = value
|
|
177
|
-
# return translated_dict
|
|
178
|
-
|
|
179
|
-
# def extract_nationality(mrz_line):
|
|
180
|
-
# match = re.match(r"^.{10}([A-Z]{3})", mrz_line)
|
|
181
|
-
# if match:
|
|
182
|
-
# return match.group(1)
|
|
183
|
-
# else:
|
|
184
|
-
# return None
|
|
185
|
-
|
|
186
|
-
# def palestine_passport_extraction(passport_text, api_key):
|
|
187
|
-
# try:
|
|
188
|
-
# logging.info(f"Starting Palestine Passport Extraction using api_key.{api_key[:4]}")
|
|
189
|
-
# model = configure_genai(api_key)
|
|
190
|
-
# jor_passport_result_ai = genai_vision_pse(passport_text, model)
|
|
191
|
-
|
|
192
|
-
# logging.info(f"GenAI Raw Output: {jor_passport_result_ai}")
|
|
193
|
-
# json_match = re.search(r'```(json|python|plaintext)?\s*(.*?)\s*```', jor_passport_result_ai, re.DOTALL)
|
|
194
|
-
# if json_match:
|
|
195
|
-
# json_str = json_match.group(2)
|
|
196
|
-
# passport_final_result = json.loads(json_str)
|
|
197
|
-
|
|
198
|
-
# else:
|
|
199
|
-
# json_str = jor_passport_result_ai.replace('```json', '').replace('```', '').strip()
|
|
200
|
-
# json_str = json_str.replace('null', 'None')
|
|
201
|
-
# passport_final_result = eval(json_str)
|
|
202
|
-
|
|
203
|
-
# try:
|
|
204
|
-
# passport_final_result = mrz_add(passport_final_result)
|
|
205
|
-
# except Exception as e:
|
|
206
|
-
# print(f"Error adding MRZ data: {e}")
|
|
207
|
-
|
|
208
|
-
# try:
|
|
209
|
-
# passport_final_result = swap_dates_if_needed(passport_final_result)
|
|
210
|
-
# except Exception as e:
|
|
211
|
-
# print(f"Error swapping dates: {e}")
|
|
212
|
-
|
|
213
|
-
# try:
|
|
214
|
-
# passport_final_result = translate_arabic_words(passport_final_result)
|
|
215
|
-
# except Exception as e:
|
|
216
|
-
# print(f"Error translating: {e}")
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
# if passport_final_result and not passport_final_result.get('passport_number', ''):
|
|
220
|
-
# ## Passport Number Pattern
|
|
221
|
-
# passport_number_pattern = r"(\d{8}|\d{7}|\d{6})"
|
|
222
|
-
# passport_number_match = re.search(passport_number_pattern, passport_text)
|
|
223
|
-
# if passport_number_match:
|
|
224
|
-
# passport_number = passport_number_match.group(0)
|
|
225
|
-
|
|
226
|
-
# if passport_number:
|
|
227
|
-
# passport_final_result['passport_number'] = passport_number
|
|
228
|
-
# else:
|
|
229
|
-
# passport_number_match = re.search(passport_number_pattern, passport_final_result.get('mrz2', ''))
|
|
230
|
-
# if passport_number_match:
|
|
231
|
-
# passport_number = passport_number_match.group(0)
|
|
232
|
-
# passport_final_result['passport_number'] = passport_number
|
|
233
|
-
|
|
234
|
-
# ## Nationality Pattern
|
|
235
|
-
# if 'nationality' not in passport_final_result:
|
|
236
|
-
# try:
|
|
237
|
-
# nationality = extract_nationality(passport_final_result.get('mrz2', ''))
|
|
238
|
-
# passport_final_result['nationality'] = nationality
|
|
239
|
-
# except:
|
|
240
|
-
# mrz2 = passport_final_result.get('mrz2', '')
|
|
241
|
-
# nationality_pattern = r'[A-Z]{3}'
|
|
242
|
-
# nationality_match = re.search(nationality_pattern, mrz2)
|
|
243
|
-
# if nationality_match:
|
|
244
|
-
# nationality = nationality_match.group(0)
|
|
245
|
-
# passport_final_result['nationality'] = nationality
|
|
246
|
-
# else:
|
|
247
|
-
# mrz2 = passport_final_result.get('mrz2', '')
|
|
248
|
-
# if mrz2:
|
|
249
|
-
# nationality = mrz2.split('<')[0][-3:]
|
|
250
|
-
# passport_final_result['nationality'] = nationality
|
|
251
|
-
|
|
252
|
-
# mrz1 = passport_final_result.get('mrz1', '')
|
|
253
|
-
# mrz2 = passport_final_result.get('mrz2', '')
|
|
254
|
-
# if mrz1 and mrz2:
|
|
255
|
-
# passport_final_result['mrz'] = f"{mrz1} {mrz2}"
|
|
256
|
-
|
|
257
|
-
# if "gender" in passport_final_result:
|
|
258
|
-
# gender = passport_final_result["gender"].strip().upper()
|
|
259
|
-
# if gender == "F":
|
|
260
|
-
# passport_final_result["gender"] = "FEMALE"
|
|
261
|
-
# elif gender == "M":
|
|
262
|
-
# passport_final_result["gender"] = "MALE"
|
|
263
|
-
|
|
264
|
-
# if 'gender' in passport_final_result:
|
|
265
|
-
# passport_final_result["gender"] = passport_final_result["gender"].strip().upper()
|
|
266
|
-
|
|
267
|
-
# if 'issuing_place' in passport_final_result:
|
|
268
|
-
# passport_final_result['place_of_issue'] = passport_final_result['issuing_place'].strip().upper()
|
|
269
|
-
|
|
270
|
-
# if passport_final_result.get('nationality', '') and len(passport_final_result['nationality']) > 3:
|
|
271
|
-
# passport_final_result['nationality'] = 'PSE'
|
|
272
|
-
|
|
273
|
-
# if not passport_final_result.get('nationality', ''):
|
|
274
|
-
# passport_final_result['nationality'] = 'PSE'
|
|
275
|
-
|
|
276
|
-
# passport_final_result['issuing_country'] = 'PSE'
|
|
277
|
-
|
|
278
|
-
# return passport_final_result
|
|
279
|
-
|
|
280
|
-
# except Exception as e:
|
|
281
|
-
# logging.error(f"Error occurred in GenAI: {e}")
|
|
282
|
-
# print(f"Error occured in GenAI {e}")
|
|
283
|
-
# return {}
|
|
284
|
-
|
|
285
1
|
|
|
286
2
|
import base64
|
|
287
3
|
import time
|
|
288
4
|
from io import BytesIO
|
|
289
|
-
from typing import Optional
|
|
290
5
|
import cv2
|
|
291
6
|
|
|
292
7
|
from openai import OpenAI
|
|
@@ -305,21 +20,26 @@ Extract ALL fields from this Palestine Passport **front side** image with high a
|
|
|
305
20
|
|
|
306
21
|
Return a JSON object with the following fields (use the exact field names):
|
|
307
22
|
|
|
308
|
-
- dob: Date of birth exactly as shown on the card
|
|
309
|
-
- expiry_date: Date of expiry exactly as shown on the card
|
|
23
|
+
- dob: Date of birth exactly as shown on the card, strictly convert to accurate DD/MM/YYYY format
|
|
24
|
+
- expiry_date: Date of expiry exactly as shown on the card, strictly convert to accurate DD/MM/YYYY format
|
|
310
25
|
- mrz1: First line of the MRZ,
|
|
311
26
|
- mrz2: Second line of the MRZ,
|
|
312
27
|
- full_name: Full name as printed on the card (extract exactly as written)
|
|
313
28
|
- gender: Gender as either MALE or FEMALE (extract exactly as printed)
|
|
314
29
|
- mother_name: Mother's Name (extract exactly as printed)
|
|
315
30
|
- place_of_birth: Place of birth in English (extract exactly as printed)
|
|
316
|
-
- issuing_date: Date of issue exactly as shown on the card
|
|
31
|
+
- issuing_date: Date of issue exactly as shown on the card, strictly convert to accurate DD/MM/YYYY format
|
|
317
32
|
- place_of_issue: Place of issue as printed on the card
|
|
318
33
|
- id_number: ID number as printed on the card (exactly 9 characters)
|
|
319
34
|
- passport_number: Passport number as printed beside N° or No (exactly 7 characters)
|
|
320
35
|
- header_verified: Return True if any of these texts are present in the image: P<PSE, PSE, PALESTINIAN AUTHORITY, or PALESTINE; otherwise False.
|
|
321
36
|
- first_name: First name extracted from full_name (if full_name contains multiple words, use the first word)
|
|
322
37
|
- last_name: Last name extracted from full_name (if full_name contains multiple words, use the last word)
|
|
38
|
+
- gender_mrz: Gender extracted from MRZ line 2: 'M' for Male, 'F' for Female.
|
|
39
|
+
- expiry_date_mrz: Expiry date extracted from MRZ line 2 in DD/MM/YYYY format.
|
|
40
|
+
- dob_mrz: Date of birth extracted from MRZ line 2 in DD/MM/YYYY format.
|
|
41
|
+
- id_number_mrz: ID number extracted from MRZ line 2.
|
|
42
|
+
- passport_number_mrz: Passport number extracted from MRZ line 2 which has only digits.
|
|
323
43
|
|
|
324
44
|
|
|
325
45
|
Instructions:
|
|
@@ -331,10 +51,10 @@ class PalestinePassportFront(BaseModel):
|
|
|
331
51
|
|
|
332
52
|
|
|
333
53
|
dob: str = Field(...,
|
|
334
|
-
description = "The date of birth exactly as shown on the card
|
|
54
|
+
description = "The date of birth exactly as shown on the card,convert to accurate DD/MM/YYYY format",
|
|
335
55
|
)
|
|
336
56
|
expiry_date: str = Field(...,
|
|
337
|
-
description = "The date of expiry exactly as shown on the card
|
|
57
|
+
description = "The date of expiry exactly as shown on the card ,convert to accurate DD/MM/YYYY format",
|
|
338
58
|
)
|
|
339
59
|
|
|
340
60
|
mrz1: str = Field(...,
|
|
@@ -365,7 +85,7 @@ class PalestinePassportFront(BaseModel):
|
|
|
365
85
|
|
|
366
86
|
|
|
367
87
|
issuing_date: str = Field(...,
|
|
368
|
-
description = "The date of issue exactly as shown on the card
|
|
88
|
+
description = "The date of issue exactly as shown on the card,convert to accurate DD/MM/YYYY format" ,
|
|
369
89
|
)
|
|
370
90
|
|
|
371
91
|
place_of_issue: str = Field(...,
|
|
@@ -373,7 +93,7 @@ class PalestinePassportFront(BaseModel):
|
|
|
373
93
|
)
|
|
374
94
|
|
|
375
95
|
id_number: str = Field(..., min_length=9, max_length=9,
|
|
376
|
-
description = "ID number as printed on the card, extract exactly as written on the card"
|
|
96
|
+
description = "ID number as printed on the card, extract exactly as written on the card "
|
|
377
97
|
)
|
|
378
98
|
|
|
379
99
|
passport_number: str = Field(..., min_length=7, max_length=7,
|
|
@@ -394,6 +114,12 @@ class PalestinePassportFront(BaseModel):
|
|
|
394
114
|
description="Last name extracted from full_name",
|
|
395
115
|
)
|
|
396
116
|
|
|
117
|
+
gender_mrz: str = Field(...,description="Gender extracted from MRZ line 2:Return 'M' for Male, 'F' for female.")
|
|
118
|
+
expiry_date_mrz: str = Field(...,description="Expiry date extracted from MRZ line 2 in DD/MM/YYYY format.")
|
|
119
|
+
dob_mrz: str = Field(...,description="Date of birth extracted from MRZ line 2 in DD/MM/YYYY format.")
|
|
120
|
+
passport_number_mrz: str = Field(..., min_length = 7, max_length= 7,description="Passport number extracted from MRZ line 2 which has only digits.")
|
|
121
|
+
id_number_mrz: str = Field(...,min_length= 9, max_length =9, description="ID number extracted from MRZ line 2.")
|
|
122
|
+
|
|
397
123
|
def process_image(side):
|
|
398
124
|
|
|
399
125
|
if side == "first" or side=='page1':
|