from typing import Optional
import uuid
from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.responses import HTMLResponse, JSONResponse
import os
from fastapi.middleware.cors import CORSMiddleware
from utils import crop_images_from_detections, detect_licensePlate, upload_to_s3
# from pinecone import Pinecone
# from deepface import DeepFace
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"]
)
# Directory to save the uploaded images
# Create the upload directory if it doesn't exist
os.makedirs('uploads', exist_ok=True)
os.makedirs('license', exist_ok=True)
@app.get("/", response_class=HTMLResponse)
async def read_items():
html_content = """
API Documentation
Welcome to VVIMS AI App! 😊
Explore the wonders of our OCR and ANPR APIs! These powerful tools utilize AI to effortlessly decipher and recognize elements within Cameroonian ID cards, extracting valuable information with just a simple call to the "/idextract"
endpoint. With our technology, you'll gain the ability to see beyond the surface and effortlessly identify vehicle license plates using the "/carplate"
endpoint. The power is now yours to wield. Unleash the full potential of these tools and revolutionize your workflow..
Let this app be the beginning of your journey towards greatness!
/idextract Endpoint
The /idextract
endpoint extracts information from ID cards.
Request Body
The request body should contain the following:
- Front file: Binary file containing the front of the ID card.
- Back file: Binary file containing the back of the ID card.
Response
The endpoint returns a data object with the following attributes:
text_front
: Text extracted from the front of the ID card.
text_back
: Text extracted from the back of the ID card.
entity_front
: Entities extracted from the front of the ID card.
entity_back
: Entities extracted from the back of the ID card.
/license Endpoint
The /license
endpoint extracts text from a license image.
Request Body
The request body should contain the following:
- Image file: Upload file containing the license image.
Response
The endpoint returns a list of tuples containing the extracted text and model confidence.
Extracted Text |
Confidence |
Text 1 |
Confidence 1 |
Text 2 |
Confidence 2 |
"""
return HTMLResponse(content=html_content, status_code=200)
@app.post("/idextract", description="This endpoint expects two files one named front and the other back which corresponds to the front and back of the id card, and returns a list of with entity_back and entity_front being the extracted infomation from the image")
async def upload_files(
front: UploadFile = File(...),
back: UploadFile = File(...),
face: Optional[UploadFile]= None
):
"""
Endpoint to receive front and back image uploads and save them to disk.
Args:
- front: The uploaded front image file.
- back: The uploaded back image file.
Returns:
- dict: A dictionary containing information about the uploaded files.
"""
try:
# Check if either front or back image is missing
if not front or not back:
raise HTTPException(status_code=400, detail="Both front and back images are required.")
# Save the front image to disk
front_path = os.path.join("uploads", 'front.jpg')
with open(front_path, "wb") as front_file:
front_file.write(await front.read())
# Save the back image to disk
back_path = os.path.join("uploads", 'back.jpg')
with open(back_path, "wb") as back_file:
back_file.write(await back.read())
front_id = crop_images_from_detections(front_path)
back_id = crop_images_from_detections(back_path)
print(f"[*] ---- Text front ----> {front_id}")
print(f"[*] ---- Text back ----> {back_id}")
front_url = upload_to_s3(front_path)
back_url = upload_to_s3(back_path)
# front_text = read_text_img(front_path)
# back_text = read_text_img(back_path)
# ent_front = ner_recog(front_text)
# ent_back = ner_recog(back_text)
# print(f"[*] ---- Entity front ----> {ent_front}")
# print(f"[*] ---- Entity back ----> {ent_back}")
if face is not None:
# Save the face image to disk
face_path = os.path.join("uploads", 'face.jpg')
with open(face_path, "wb") as face_file:
face_file.write(await face.read())
face_url = upload_to_s3(face_path)
serial_number = ''
print(f"[*] --- Serial ---> {serial_number}")
# embedding = DeepFace.represent(img_path=face_path, model_name='DeepFace')
# embedding_vector = embedding[0]['embedding']
# existing_user = lookup_user_metadata(index, embedding_vector, serial_number)
# print(f"[*] --- Existing user ---> {existing_user}")
# if (len(existing_user["matches"]) <= 0):
# print(f"[*] --- No match found --->")
# await index.upsert(
# vectors=[
# {
# "id": str(uuid.uuid4()),
# "values" : embedding_vector,
# "metadata" : {"name": serial_number}
# }
# ],
# namespace="ns1"
# )
# elif(len(existing_user["matches"]) > 0):
# if (existing_user["matches"][0]["score"] >= 0.79):
# pass
# # return JSONResponse(content={"message": "This user and id card already exist"}, status_code=200)
# elif(existing_user["matches"][0]["score"]):
# return HTTPException(content={"message" : "This card belongs to someone else"}, status_code=404)
return JSONResponse(content = {"message": "Upload successful", "data":{'front_url': front_url , 'entity_front': front_id, 'back_url': back_url, 'entity_back': back_id}}, status_code=200)
except Exception as e:
return HTTPException(status_code=500, detail=f"Internal server error {str(e)}")
@app.post("/carplate", description="This endpoint expects a file named license and return a list of turple having the detected number plates and the extracted text")
async def carplate(license: UploadFile = File(...)):
try:
if not license:
raise HTTPException(status_code=500, detail=f"Internal server error {str(e)}")
# Save the back image to disk
car_path = os.path.join("uploads", 'cars.jpg')
with open(car_path, "wb") as face_file:
face_file.write(await license.read())
car_url = upload_to_s3(car_path)
print(f"[*] --- Image URL --> {car_url}")
print(" [*] --- This is the license path --> :", car_path)
result = detect_licensePlate(car_path)
return JSONResponse( content = {"message" : "Upload successful", "data" : result, "car_url": car_url},
status_code = 200
)
except Exception as e:
return HTTPException(status_code=400, detail=f"Internal server error {str(e)}")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)