def mrz_tool(filename, except_score): # Return 1 if image is success increase, 0 if failed, 2 if no need to change mrz_file = read_mrz(filename) method = 1 count = 1 while mrz_file == None or mrz_file.valid_score < except_score: if method == 1: # First try to increase brightness path, new_frame = Filter.increase_brightness(filename, 3) # return a path method = 2 elif method == 2: # Second try to increase contrast path, new_frame = Filter.increase_contrast(filename, 127) method = 3 else: # Last try to increase both path, new_frame = Filter.increase_brightness(path, 3) method = 4 mrz_file = read_mrz(path) # Re-identify again if mrz_file == None: print(str(count) + ': ' + 'Failed') count += 1 if method == 4: return filename, 0 continue else: print(str(count) + ': ' + str(mrz_file.valid_score)) count += 1 if mrz_file.valid_score > except_score: return path, 1 # return a new frame if mrz_file.valid_score > except_score: return filename, 2
def preprocessCamUpload(cvImage): try: MRZ_Image = detectMRZ.getMRZ_ROI(cvImage) mrz_data = None if MRZ_Image is not None: if len(MRZ_Image.shape) > 2: MRZ_Image = cv2.cvtColor(MRZ_Image, cv2.COLOR_BGR2GRAY) mrz_data = passporteye.read_mrz(MRZ_Image) if mrz_data is None: MRZ_Image = rotateImage(MRZ_Image, 180) mrz_data = passporteye.read_mrz(MRZ_Image) if mrz_data is None: grayImage = cv2.cvtColor(cvImage, cv2.COLOR_BGR2GRAY) mrz_data = passporteye.read_mrz(grayImage) return mrz_data except Exception, e: print e return None
def scan_file(file_id): from blueocr.ocr.utils import create_contour_image doc = OcrUploadedFile.objects.get(id=file_id) try: download_file = doc.download() logger.info("Downloaded file to {}".format(download_file)) except Exception as e: logger.warning("Couldn't download file - {}".format(e)) doc.enter_failed() doc.save() result = OcrResult.objects.create(state='failed', scanned_data={}) doc.ocr_result = result doc.save() else: try: if not is_image(download_file): converted_file = convert_to_image(download_file) os.remove(download_file) download_file = converted_file mrz = read_mrz(download_file) custom_check(mrz) print(mrz.to_dict()) mrz1 = mrz if mrz is None or mrz.valid_score < 70: logger.warning( "MRZ valid score bellow threshold. Performing step 2.") create_contour_image(download_file) mrz = read_mrz(download_file) custom_check(mrz) print(mrz.to_dict()) if mrz is None: raise Exception("MRZ zone not identified") except Exception as e: logger.warning("Couldn't process document {} - {}".format( file_id, e)) doc.enter_failed() result = OcrResult.objects.create(state='failed', scanned_data={}) doc.ocr_result = result doc.save() else: if mrz1 is not None and mrz1.valid_score > mrz.valid_score: mrz = mrz1 mrz_dict = mrz.to_dict() adjust_data(mrz_dict) result = OcrResult.objects.create(state='completed', scanned_data=mrz_dict) doc.ocr_result = result logger.info("OCR finished for file document {}".format(doc)) os.remove(download_file) doc.enter_processed() doc.save() send_file_callback(file_id)
def get(self, request, format=None): from passporteye import read_mrz mrz = read_mrz( 'http://127.0.0.1:8000/media/project-vue/src/assets/passport/' + 'sa_JU7r2P5.jpg') mrz_data = mrz.to_dict() return Response(mrz_data)
def get_mrz(): cap = cv2.VideoCapture(1) tmp_file = 'tmp_capture.png' mrz_list = None sleep_time = .100 logging.info("Checking for valid MRZ every {0} seconds".format(sleep_time)) while (True): _, frame = cap.read() cv2.imwrite(tmp_file, frame) try: mrz = read_mrz(tmp_file) except ValueError as e: logging.warning(e.message) continue # print("Trying...") if mrz != None: mrz_list = [mrz.number, mrz.date_of_birth, mrz.expiration_date] print(mrz_list) valid_number = validate_doc_number(mrz.number, mrz.check_number) if (valid_number != None ) & mrz.valid_date_of_birth & mrz.valid_expiration_date: mrz_list = [ valid_number, mrz.date_of_birth, mrz.expiration_date ] print(mrz_list) break time.sleep(sleep_time) cap.release() cv2.destroyAllWindows() os.remove(tmp_file) return mrz_list
def get_mrz(self): tmp_file = self.tmp_file mrz_list = self.mrz_list _, frame = self.cap.read() cv2.imwrite(tmp_file, frame) try: mrz = read_mrz(tmp_file) logging.info(mrz) except ValueError as e: logging.warning("Something went wrong...") return None print("Trying...") if mrz != None: mrz_list = [mrz.number, mrz.date_of_birth, mrz.expiration_date] # print("OCR: checking string [{}]".format(mrz_list)) logging.info("OCR: checking string [{}]".format(mrz_list)) valid_number = self.validate_doc_number(mrz.number, mrz.check_number) if (valid_number != None ) & mrz.valid_date_of_birth & mrz.valid_expiration_date: mrz_list = [ valid_number, mrz.date_of_birth, mrz.expiration_date ] # print(mrz_list) os.remove(tmp_file) return mrz_list return None
def upload_file(): if request.method == 'POST': if 'file' not in request.files: return "No file" else: f = request.files['file'] filename = secure_filename(f.filename) #Save to passporteye folder to process os.chdir( "C:/Users/shahi/AppData/Local/Programs/Python/Python36-32/Lib/site-packages/passporteye" ) file_path = "C:/Users/shahi/AppData/Local/Programs/Python/Python36-32/Lib/site-packages/passporteye/" + filename static_path = "C:/Users/shahi/AppData/Local/Programs/Python/Python36-32/static/images/" + filename f.save(filename) mrz = read_mrz(filename) mrz_data = mrz.to_dict() #Save to static folder to view copyfile(filename, static_path) os.remove(filename) #return json.dumps(mrz_data) return render_template('results.html', the_name=mrz_data['names'], the_DOB=mrz_data['date_of_birth'], the_PassportNumber=mrz_data['number'], the_filename=filename)
def read_info(path): results = read_mrz(path).to_dict() if results: print(results) return results else: return "Could not be processed"
def unit_extraction(image_folder, image_sample, mrz_format): """ This function implements Passporteye read_mrz() function to extract identity information from the MRZ of an identity document. Input parameters: - image_folder: path to the folder containing the image of the identity document - image_sample: name of the image of the identity document containing information to extract - mrz_format: format of an MRZ Example: valid_mrz = { "mrz_type": "TD3", "type": "P", "country": "CMR", "number": "01312168", "check_number": "4", "date_of_birth": "830408", "check_date_of_birth": "1", "expiration_date": "140611", "check_expiration_date": "5", "nationality": "CMR", "sex": "M", "names": "ADAMOU", "surname": "NCHANGE KOUOTOU" } Return: - mrz_data: dictionary containing identity information extacted """ # Process image mrz = read_mrz(image_folder + '/' + image_sample) mrz_data = filter_mrz(mrz.to_dict(), mrz_format) return mrz_data
def process_passport(filename): mrz = read_mrz(filename, 1) if mrz is None: return "MRZ Barcode not found! Check your image and try again!" mrz_data = mrz.to_dict() dob = mrz_data['date_of_birth'] doe = mrz_data['expiration_date']
def handle_address_confirmation(): try: mrz = read_mrz(request.data) if mrz: return jsonify(mrz.to_dict()) else: print(f"Could not extract anything on first pass, will try base64") raise ValueError except ValueError: # https://stackoverflow.com/a/49459036/419338 # some JS implementation do not pad enough, but py3 will truncate redundant padding decoded = base64.b64decode(request.data + b"=====") mrz = read_mrz(BytesIO(decoded), flip_horizontal=request.headers.get('flip')) if not mrz: print(f"Could not extract anything on second pass") return jsonify({}) d = mrz.to_dict() print(f"Got doc type {d.get('type')} from {d.get('country')} with score {d['valid_score']}") return jsonify(d)
def main(argv=None): #cv2.imshow("Image", image) #cv2.imshow("ROI", roi) from mrz import process_passport mrz = read_mrz('roi.jpg', 1) data = process_passport(mrz) #print(data) #formatt json outputS s1 = json.dumps(data) parsed = json.loads(s1) print(json.dumps(parsed, indent=2, sort_keys=False))
def create(self, validated_data): from passporteye import read_mrz img = validated_data['imageUpload'] mrz = read_mrz(img.read(), save_roi=True) mrz_data = mrz.to_dict() print(mrz_data['names']) content = ImageModel(imageUpload=img, name=mrz_data['names'], surname=mrz_data['surname']) content.save() return content
def upload_file(): if request.method == 'POST': # check if the post request has the file part front = request.files['front'] back = request.files['back'] true_selfie = request.files['true_selfie'] fake_selfie = request.files['fake_selfie'] front_path = os.path.join(app.config['UPLOAD_FOLDER'], front.filename) back_path = os.path.join(app.config['UPLOAD_FOLDER'], back.filename) true_selfie_path = os.path.join(app.config['UPLOAD_FOLDER'], true_selfie.filename) fake_selfie_path = os.path.join(app.config['UPLOAD_FOLDER'], fake_selfie.filename) front.save(front_path) back.save(back_path) true_selfie.save(true_selfie_path) fake_selfie.save(fake_selfie_path) out_dir = './tmp' dirname = uuid4().__str__() tmp_path = os.path.abspath(os.path.join(out_dir, dirname)) back = prep(back_path, 'back', tmp_path) front = prep(front_path, 'front', tmp_path) true_selfie_path = prep(true_selfie_path, 'true_selfie', tmp_path) false_selfie_path = prep(fake_selfie_path, 'false_selfie', tmp_path) mrz = read_mrz(back).to_dict() doc_face = get_face_blob(front, 'front_face', tmp_path) true_selfie = get_face_blob(true_selfie_path, 'true_selfie_face', tmp_path, mirror=True) true_selfie = cv2.cvtColor(true_selfie, cv2.COLOR_RGB2BGR) false_selfie = get_face_blob(false_selfie_path, 'false_selfie_face', tmp_path, mirror=True) false_selfie = cv2.cvtColor(false_selfie, cv2.COLOR_RGB2BGR) doc_encoding = face_recognition.face_encodings(doc_face, num_jitters=10, model='large') selfie_encoding = face_recognition.face_encodings(true_selfie, num_jitters=10, model='large')[0] dist = face_recognition.face_distance(doc_encoding, selfie_encoding)[0] pred1 = classify(true_selfie) pred2 = classify(false_selfie) return { 'mrz_data': mrz, 'similarity': (1 - dist) * 100, 'prediction_for_original': pred1, 'prediction_for_fake': pred2 }
def detect_mrz(image_path): preprocess_image(image_path) try: mrz = read_mrz('test_pass.png', save_roi=True) except Exception as e: print(e) return True if not mrz: return False imsave('test_roi.png', mrz.aux['roi']) # preprocess_image() text = pytesseract.image_to_string(Image.open('test_roi.png')) return mrz
def create(self, validated_data): from passporteye import read_mrz img = validated_data['imageUpload'] mrz = read_mrz(img.read(), save_roi=True) mrz_data = mrz.to_dict() content = ImageModel(imageUpload=img, name=mrz_data['names'], surname=mrz_data['surname'], iin=mrz_data['optional1'].replace('<', ''), birthday=mrz_data['date_of_birth'], gender=mrz_data['sex'], nationality=mrz_data['nationality']) content.save() return content
def extract_mrz(self): """ Extract mrz data from document as a string :return: a string representation of mrz. """ try: mrz = read_mrz(self.document.file.file, extra_cmdline_params='--oem 0', save_roi=True) return mrz.aux['text'].replace('\n', '') except AttributeError as attr_error: LOGGER.error("Error during idcard analysis (%s) : %s", self, attr_error) raise attr_error
def preprocessFileUpload(cvImage): try: MRZ_Images = detectMRZ.getMRZ_ROI(cvImage) mrz_data = None if len(MRZ_Images) > 0: for MRZ_Image in MRZ_Images: if len(MRZ_Image.shape) > 2: MRZ_Image = cv2.cvtColor(MRZ_Image, cv2.COLOR_BGR2GRAY) mrz_data = passporteye.read_mrz(MRZ_Image) if mrz_data is None: MRZ_Image = cropRoiImage.rotateImage(MRZ_Image, 180) mrz_data = passporteye.read_mrz(MRZ_Image) if mrz_data is not None: break if mrz_data is None: grayImage = cv2.cvtColor(cvImage, cv2.COLOR_BGR2GRAY) mrz_data = passporteye.read_mrz(grayImage) return mrz_data except Exception, e: print e return None # # img = cv2.imread("/Users/naunidhsingh/Desktop/HSBC/docs/eid/image013.jpg") # print preprocessCamUpload(img)
def upload_file_rest(): if request.method == 'POST': if 'file' not in request.files: return "No file" else: f = request.files['file'] filename = secure_filename(f.filename) #Save to passporteye folder to process os.chdir( "C:/Users/shahi/AppData/Local/Programs/Python/Python36-32/Lib/site-packages/passporteye" ) f.save(filename) mrz = read_mrz(filename) mrz_data = mrz.to_dict() os.remove(filename) return json.dumps(mrz_data)
def POST(self): # try: data = web.data() newfile = tempfile.NamedTemporaryFile(mode='w+b', delete=False) newfile.write(data) print(newfile.name) mrz = read_mrz(newfile.name, extra_cmdline_params="--oem 0 -l eng") if mrz is None: mrz_data = {} else: mrz_data = mrz.to_dict() newfile.close() print(json.dumps(mrz_data)) return (json.dumps(mrz_data))
def uploadPassport(request): print('UPLOAD') if request.method == 'POST': file_obj = request.FILES.get('file', None) print('file', file_obj) if file_obj: print('MRZ ', file_obj) mrz = read_mrz(file_obj) form = PersonForm() print(mrz) return render(request, 'voter/add_person.html', { 'title': 'Voter-add', 'form': form }) return render(request, 'camera-capture.html')
def first_mrz_to_dict(img_mrz): """ attempts to read the mrz of the image using passporteye's read_mrz() :param img_mrz: image of mrz :return: dictionary of relevant information (dict), type of document (str) """ mrz_dict = None try: img_mrz = to_bytes(img_mrz) img_mrz = read_mrz(img_mrz) mrz_dict = img_mrz.to_dict() type_mrz = mrz_dict.get("mrz_type") mrz_dict = get_data(mrz_dict, type_mrz) if not check_mrz(mrz_dict): mrz_dict = None except AttributeError: type_mrz = "" return mrz_dict, type_mrz
def upload_file(): if request.method == 'POST': filei = request.files['file'] if filei and allowed_file(filei.filename): # Mime Type Check mime = MimeTypes() mime_type, encoding = mime.guess_type(filei.filename) # Mime-Type condition if mime_type in ('image/png', 'image/tiff', 'image/jpeg', 'application/pdf'): print('**found file', filei.filename, mime_type) #filename = secure_filename(filei.filename) filename = str(uuid.uuid4()) filei.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) tempfile = './uploads/' + filename # Start OCR proccess with MRZ mrz1 = read_mrz(tempfile) # Python put data to dictionary d1 = mrz1.to_dict() if mrz1 is not None else {'mrz_type': None, 'valid': False, 'valid_score': 0} # Retrive valid_score valid_score = int(d1['valid_score']) # Check valid score condition if valid_score > 70: os.remove(tempfile) return json.dumps(d1, ensure_ascii=False) else: d2 = detect_document(tempfile) os.remove(tempfile) return json.dumps(d2, ensure_ascii=False) else: return '{"status": "Error mime-type of uploaded file. File is not Image"}' # For test GET type return '''
def parser(file): try: #filename = sys.argv[0] # getting file name mrz = read_mrz(file) data = mrz.to_dict() holder = dict() holder["first name"] = get_first_name(data.get("names").upper()) holder["last name"] = data.get("surname").upper() holder["country code"] = data.get("country_code") holder["country"] = check_country(holder.get("country_code")) holder["nationality"] = check_country(data.get("nationality")) holder["id"] = data.get("number") holder["sex"] = data.get("sex") return holder except FileNotFoundError: return print("File Does Not Exist") except TypeError: return print("Image Unreadable")
def __verify_age(passport_bytes, job): ''' Verifies the user's age and cross references information between the driving license and the passport. if failed, just check the information provided. get mrz date of birth, get date of birth from the data provided. compare, then compare with the driving license. Finally, check the driving license number, make sure that the ifnroamtion in that matches the date of birth in teh license. make sure the documents are not expired. then post and we can now look to display the info/. TOMORROW> Get this finished, then commit and fix up the api and app. From there, we need to verify the images. Once those are done then we need to develop the admin lgoin, to then verify new users. Once verified, tehe user can request a code. Once a code is made in the API then we can hold that in the database. When scanned by the POS, we know that we can verify through the api. ''' passport_mrz_data = read_mrz(passport_bytes) if(passport_mrz_data.valid_score < 50 or not passport_mrz_data.valid_date_of_birth): print("Failed MRZ checker.") license_data = job["LicenseData"] passport_data = job["PassportData"] passport_dob = passport_mrz_data.date_of_birth # Add spaces after each 2 characters in the string passport_dob = " ".join(passport_dob[i:i+2] for i in range(0, len(passport_dob), 2)) passport_dob = time.strptime(passport_dob, "%y %m %d") errors_in_data = compare_mobile_data(license_data, passport_data) if(errors_in_data > 3 or errors_in_data < 0): return (False, "Quality of information provided not good enough.") return (True, "Information provided is sutiable")
def pp_mrz_(file_path1): mrz = read_mrz(file_path1) # Return the result as json result = {"mrz": mrz.to_dict()} return jsonify(result)
def getMRZDataFromImage(image): # load the image, resize it, and convert it to grayscale image = imutils.resize(image, height=600) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # smooth the image using a 3x3 Gaussian, then apply the blackhat # morphological operator to find dark regions on a light background gray = cv2.GaussianBlur(gray, (3, 3), 0) blackhat = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, rectKernel) # compute the Scharr gradient of the blackhat image and scale the # result into the range [0, 255] gradX = cv2.Sobel(blackhat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1) gradX = np.absolute(gradX) (minVal, maxVal) = (np.min(gradX), np.max(gradX)) gradX = (255 * ((gradX - minVal) / (maxVal - minVal))).astype("uint8") # apply a closing operation using the rectangular kernel to close # gaps in between letters -- then apply Otsu's thresholding method gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel) thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] # perform another closing operation, this time using the square # kernel to close gaps between lines of the MRZ, then perform a # serieso of erosions to break apart connected components thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) thresh = cv2.erode(thresh, None, iterations=4) # during thresholding, it's possible that border pixels were # included in the thresholding, so let's set 5% of the left and # right borders to zero p = int(image.shape[1] * 0.05) thresh[:, 0:p] = 0 thresh[:, image.shape[1] - p:] = 0 # find contours in the thresholded image and sort them by their # size cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) cnts = sorted(cnts, key=cv2.contourArea, reverse=True) #if we have found our mrz contour found = False # loop over the contours for c in cnts: # compute the bounding box of the contour and use the contour to # compute the aspect ratio and coverage ratio of the bounding box # width to the width of the image (x, y, w, h) = cv2.boundingRect(c) ar = w / float(h) crWidth = w / float(gray.shape[1]) # check to see if the aspect ratio and coverage width are within # acceptable criteria if ar > 5 and crWidth > 0.75: # pad the bounding box since we applied erosions and now need # to re-grow it pX = int((x + w) * 0.03) pY = int((y + h) * 0.03) (x, y) = (x - pX, y - pY) (w, h) = (w + (pX * 2), h + (pY * 2)) # extract the ROI from the image and draw a bounding box # surrounding the MRZ roi = image[y:y + h, x:x + w].copy() cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) found = True break if found: #use random temp filename because we might get into trouble #with concurrent requests otherwise filename = ''.join( random.choices(string.ascii_uppercase + string.digits, k=5)) fn = filename + "_roi_temp.png" print(fn) cv2.imwrite(fn, roi) mrz = read_mrz(fn) os.remove(fn) if mrz is not None: return mrz, found else: return {}, False return {}, found
def load_file(): # file_val = request.files.get('file') #read_mrz(file_val) #if request.method == 'POST': # print(read_mrz(file_val)) # print(read_mrz(file_val)) # return render_template('tests.html') # return file_val if request.method == 'POST': # check if the post request has the file part if 'file' not in request.files: flash('No file part') return redirect(request.url) file = request.files['file'] # if user does not select file. browser also # submits an empty part without filename if file.filename == '': flash('No selected file') return redirect(request.url) if file and allowed_file(file.filename): # secure_filename secures a filename before storing it directly to the filesystem. filename = secure_filename(file.filename) file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) # redirect() returns a response object and redirects the user to another target location with specified status code. filename1 = safe_join(app.config['UPLOAD_FOLDER'], filename) mrz1 = read_mrz(filename1, save_roi=True) mrz = mrz1.to_dict() # Converting sex output if mrz['sex'] == 'F': mrz['sex'] = 'Female' elif mrz['sex'] == 'M': mrz['sex'] = 'Male' else: mrz['sex'] = 'Unknown' # Converting country output if coco.convert(names=mrz['country'], to='name_short') == 'not found': mrz['country'] = mrz['country'] else: mrz['country'] = coco.convert(names=mrz['country'], to='name_short') # Converting nationality output if coco.convert(names=mrz['nationality'], to='name_short') == 'not found': mrz['nationality'] = mrz['nationality'] else: mrz['nationality'] = coco.convert(names=mrz['nationality'], to='name_short') # Converting date of birth output try: dd = datetime.datetime.strptime(mrz['date_of_birth'], '%y%m%d').date() if dd.year > now.year: mrz['date_of_birth'] = dd.replace(year=dd.year - 100) else: mrz['date_of_birth'] = dd print(dd) except ValueError: mrz['date_of_birth'] = 'Unknown' # Converting expiration output try: dd = datetime.datetime.strptime(mrz['expiration_date'], '%y%m%d').date() if dd.year > now.year: mrz['expiration_date'] = dd else: mrz['expiration_date'] = dd print(dd) except ValueError: mrz['expiration_date'] = 'Unknown' print(mrz['date_of_birth']) return jsonify(mrz)
mrz_data = mrz.to_dict() dob = mrz_data['date_of_birth'] doe = mrz_data['expiration_date'] mrz_data = mrz.to_dict() date_of_birth = mrz_data['date_of_birth'] date_of_expiration = mrz_data['expiration_date'] id_type = mrz_data['type'] name = mrz_data['names'] name_split = name.split() first_name, middle_name = get_given_name(name_split) data = { "first Name": first_name, "Middle Name": middle_name, "Surname": mrz_data['surname'], "Date of Birth": normalize_date(date_of_birth), "Gender": mrz_data['sex'], "ID Type": get_idType(id_type), "ID Number": mrz_data['number'], "Date of Expiration": normalize_date(date_of_expiration), "Nationality": mrz_data['nationality'], } return data mrz = read_mrz('C:\\Users\\User\Anaconda3\mrz\roi.jpg', 1) data1 = process_passport(mrz) print(data1) #process_passport(mrz)
# on instancie l'outil de traduction translator = Translator(to_lang="fr") # %% On utilise passportEye pour les Passeports # on va chercher l'ensemble des fichiers concernant les passeports liste_fichiers = glob.glob("./../src/Data/Passeport interieur/*.jpg") # on instancie un kpi de réussite res = 0 # pour chaque fichier dans la liste des fichiers for i in range(len(liste_fichiers)): # on lit l'image et identifie les informations du Machine Readable Zone mrz = read_mrz(liste_fichiers[i]) # on identifie le nom du fichier qui expose le résultat attendue du programme nom_fichier = liste_fichiers[i].split("\\")[-1] # on essaye de le transformer en dictionnaire de données try: mrz_data = mrz.to_dict() # si la transformation a fonctionné, on relève le code ISO 3 du document country = mrz_data['country'] # on identifie le nom complet du pays grâce à la base de données des codes ISO 3 pays = iso.loc[iso["code"] == country, "nationality"].values[0] # on traduit le nom du pays en français pays_fr = translator.translate(pays) # on affiche le résultat print(f"{bcolors.WIN}{nom_fichier} vient de {pays_fr} car {country}")