from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden import cv2 import numpy as np import base64 import os from django.views.decorators.csrf import csrf_exempt import json import datetime from django.conf import settings from django.core.files.base import ContentFile from proctoring.models.image import Image,FaceCheckImage from proctoring.models.imageTypes import ImageTypes from collections import Counter from proctoring.services.face_compare_v2 import compare_id_images, FaceVerificationError import logging logger = logging.getLogger(__name__) def load_image_from_s3(file_path): storage = settings.s3_storage if not storage.exists(file_path): raise FileNotFoundError(f"The file {file_path} does not exist in S3.") with storage.open(file_path, mode='rb') as s3_file: file_bytes = s3_file.read() np_arr = np.frombuffer(file_bytes, np.uint8) image = cv2.imdecode(np_arr, cv2.IMREAD_COLOR) _, buffer = cv2.imencode('.jpg', image) image_base64 = base64.b64encode(buffer).decode('utf-8') return image_base64 @csrf_exempt def CheckImage(request): if request.method != "POST": return HttpResponseForbidden("Only POST requests are allowed") try: data = json.loads(request.body) base64image = data.get("base64_image", "") shareId = data.get("shareId", "") isIdentityCheck = data.get("isIdentityCheck", False) except json.JSONDecodeError: return HttpResponseBadRequest("Invalid JSON data") if base64image == "" or shareId == "": return HttpResponseBadRequest("Missing parameters") model = settings.model if "," in base64image: base64image = base64image.split(",")[1] img_bytes = base64.b64decode(base64image) nparr = np.frombuffer(img_bytes, np.uint8) img = cv2.imdecode(nparr, cv2.IMREAD_COLOR) if img is None: return HttpResponseBadRequest("Could not decode image") verified = True distance = None faceCheckPhoto = Image.objects.filter( shareId=shareId, path__icontains="identity-check/face" ).first() if faceCheckPhoto: try: faceCheckPhotoPath = faceCheckPhoto.path.split("amazonaws.com/")[-1] faceCheckPhotoBase64 = load_image_from_s3(faceCheckPhotoPath) verified, distance = compare_id_images(base64image, faceCheckPhotoBase64) except FaceVerificationError as e: logger.warning(f"Face verification failed: {e}") verified = False distance = None except Exception as e: logger.exception("Unexpected error during face verification") verified = False distance = None if not verified: response = {"pass": False, "message": "Face does not match with face check photo"} return HttpResponse(json.dumps(response)) results = model(img) detection_labels = [] for result in results: for det in result.boxes.data: class_id = int(det[-1]) label = result.names[class_id] detection_labels.append(label) counts = Counter(detection_labels) personCount = counts.get("person", 0) prohibitedObjectsCount = ( counts.get("book", 0) + counts.get("laptop", 0) + counts.get("cell phone", 0) ) imgWidth = 240 imgHeight = 135 img = cv2.resize(img, (imgWidth, imgHeight), interpolation=cv2.INTER_AREA) outputImage = cv2.imencode(".jpg", img)[1].tobytes() save_folder = os.path.join("proctoring_images", shareId) filename = datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%S.jpg") if not isIdentityCheck: if personCount == 1 and prohibitedObjectsCount == 0 and verified: folder = os.path.join(save_folder, "passed") imageType = ImageTypes.Acceptable else: folder = os.path.join(save_folder, "failed") imageType = ImageTypes.AttentionRequired else: if personCount == 1 and prohibitedObjectsCount == 0 and verified: folder = os.path.join(save_folder, "identity-check", "face") imageType = ImageTypes.FaceCheck else: folder = None if folder: filepath = os.path.join(folder, filename) content_file = ContentFile(outputImage, name=filename) saved_path = settings.s3_storage.save(filepath, content_file) FaceCheckImage( path=f"{settings.AWS_S3_ACCESS_DOMAIN}/{saved_path}", personCount=personCount, prohibitedObjectsCount=prohibitedObjectsCount, type=imageType, shareId=shareId, similarityScore=(1.0 - distance) if distance is not None else None, ).save() response = { "personCount": personCount, "prohibitedObjectsCount": prohibitedObjectsCount, "similarityScore": (1.0 - distance) if distance is not None else None, } return HttpResponse(json.dumps(response))