File size: 5,021 Bytes
baba668
 
 
 
 
 
 
 
 
 
 
 
693596e
baba668
 
693596e
baba668
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
693596e
 
 
 
baba668
 
 
 
693596e
 
 
a60e50a
 
baba668
 
 
 
 
 
 
a60e50a
 
baba668
a8b8b1e
 
 
 
 
 
 
 
 
693596e
baba668
 
693596e
9c7849e
 
 
 
 
693596e
 
 
9c7849e
a8b8b1e
d942552
 
 
 
 
 
 
baba668
693596e
9c7849e
693596e
 
 
 
 
d942552
 
693596e
d942552
 
 
693596e
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import os

from dotenv import load_dotenv

load_dotenv(override=True)

import io
import os
from typing import Union

import easyocr
import firebase_admin
import gradio as gr
from firebase_admin import credentials, firestore
from loguru import logger
from PIL import Image
from thefuzz import fuzz

from processor import ImageHandler, PreprocessingConfig, ProcessedImage


class EasyOCRReader:
    def __init__(self):
        self.reader = easyocr.Reader(["fr", "en"], gpu=False)
        self.process = ImageHandler()
        self.config = PreprocessingConfig()

    def chat(self, image):
        processed: ProcessedImage = self.process.preprocess_image(image, self.config)
        image = Image.fromarray(processed.image)
        # Convert image to bytes
        img_byte_arr = io.BytesIO()
        image.save(img_byte_arr, format="PNG")
        img_byte_arr = img_byte_arr.getvalue()

        # Call readtext with image bytes
        texts = self.reader.readtext(img_byte_arr, detail=0)
        logger.info(" ".join(texts))
        return texts


class FirebaseConnector:
    def get_config(self):
        return {
            "type": os.getenv("type"),
            "project_id": os.getenv("project_id"),
            "private_key_id": os.getenv("private_key_id"),
            "private_key": os.getenv("private_key").replace("\\n", "\n"),
            "client_email": os.getenv("client_email"),
            "client_id": os.getenv("client_id"),
            "auth_uri": os.getenv("auth_uri"),
            "token_uri": os.getenv("token_uri"),
            "auth_provider_x509_cert_url": os.getenv("auth_provider_x509_cert_url"),
            "client_x509_cert_url": os.getenv("client_x509_cert_url"),
            "universe_domain": os.getenv("universe_domain"),
        }

    def __init__(self):
        # print(os.environ)
        firebase_config = self.get_config()
        cred = credentials.Certificate(firebase_config)
        firebase_admin.initialize_app(cred)
        self.db = firestore.client()

    def add(self, ocr: str, key: str):
        doc_ref = self.db.collection("id-card").document(key)
        if doc_ref.get().exists:
            raise ValueError(f"Document with key {key} already exists.")
        return self.db.collection("id-card").add({"ocr": ocr}, document_id=key)


def search_element(words: list[str], target: str, thr: float = 60):
    scores = list(map(lambda x: fuzz.partial_ratio(x, target), words))
    word_scores = [(w, s) for w, s in zip(words, scores) if s >= thr]
    return word_scores


class VoterCardVerifier:
    def __init__(self):
        self.db = FirebaseConnector()
        self.ocr_engine = EasyOCRReader()

    def verify_card(self, image: Union[str, Image.Image], card_number, thr: float = 60):
        # Convertir l'image pour Groq
        if isinstance(image, str):
            image = Image.open(image)

        # Préparer la requête pour le modèle et l'appeler
        ocr_data = self.ocr_engine.chat(image)

        score1 = search_element(ocr_data, "camer", thr)
        score2 = search_element(ocr_data, card_number, thr)

        ocr_data = score1 + score2
        logger.info(str(ocr_data))

        # valider les entrées
        is_valid = len(score1) and len(score2)
        try:
            if is_valid:
                # Sauvegarder dans Firebase
                self.save_card_number(ocr_data, card_number)
                return "Your ID Card have been recorded, thank you !!!"
            else:
                return "Numéro de carte non trouvé sur l'image"
        except:
            return "ID Card already saved in the database"

    def save_card_number(self, ocr_data, card_number):
        return self.db.add(str(ocr_data), str(card_number))

    def get_id_counted(self):
        docs = self.db.db.collection(collecttion_name).stream()
        count = sum(1 for _ in docs)
        return count


# Interface Gradio
def create_interface():
    verifier = VoterCardVerifier()
    # n_cards = verifier.get_id_counted()
    description = (
        "Card ID Counter is an application designed to count voter card numbers "
        "by analyzing uploaded images using OCR technology. It ensures accuracy by "
        "checking if the provided number appears on the card and confirming its from Cameroon.\n\n"
        "🌟 **Code Repository**: [Card ID Counter GitHub](https://github.com/Nganga-AI/card-counter)"
    )

    def process(image, card_number: str):
        if not card_number.strip():
            return "Enter your elect count number"
        return verifier.verify_card(image, card_number)

    interface = gr.Interface(
        fn=process,
        inputs=[
            gr.Image(type="pil", label="Upload ID Card Image"),
            gr.Textbox(label="Card Number"),
        ],
        outputs=gr.Textbox(label="Result"),
        title="Voters ID Counter",
        description=description,
    )

    return interface


if __name__ == "__main__":

    # Créer et lancer l'interface
    demo = create_interface()
    demo.launch()