grpc_server.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import sys
  2. import tempfile
  3. import grpc
  4. from concurrent import futures
  5. import os
  6. from deepface import DeepFace
  7. sys.path.insert(0, os.path.join(os.path.dirname(__file__), "proto"))
  8. from proto import face_recognition_pb2, face_recognition_pb2_grpc
  9. EMPLOYEE_DB_PATH = "data/employees"
  10. class FaceRecognitionServicer(face_recognition_pb2_grpc.FaceRecognitionServiceServicer):
  11. def Recognize(self, request, context):
  12. print("[INFO] Received recognition request...")
  13. temp_file = None
  14. try:
  15. # Save incoming image to a temporary file
  16. with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp:
  17. temp_file = tmp.name
  18. tmp.write(request.image)
  19. print("[INFO] Running DeepFace search...")
  20. result = DeepFace.find(
  21. img_path=temp_file,
  22. db_path=EMPLOYEE_DB_PATH,
  23. detector_backend="opencv",
  24. enforce_detection=False
  25. )
  26. if isinstance(result, list):
  27. result = result[0]
  28. if result is None or len(result) == 0:
  29. print("[INFO] No match found.")
  30. return face_recognition_pb2.FaceResponse(
  31. name="Unknown",
  32. confidence=0.0,
  33. image=b""
  34. )
  35. best_row = result.iloc[0]
  36. matched_image_path = best_row["identity"]
  37. name = os.path.splitext(os.path.basename(matched_image_path))[0]
  38. # Convert distance to rough confidence
  39. distance = best_row.get("VGG-Face_cosine", 0.3)
  40. confidence = float(max(0.0, 1.0 - distance))
  41. # Read matched image bytes
  42. with open(matched_image_path, "rb") as f:
  43. matched_image_bytes = f.read()
  44. print(f"[INFO] Match: {name}, confidence: {confidence:.2f}")
  45. return face_recognition_pb2.FaceResponse(
  46. name=name,
  47. confidence=confidence,
  48. image=matched_image_bytes
  49. )
  50. except Exception as e:
  51. print("[ERROR] DeepFace failed:", e)
  52. return face_recognition_pb2.FaceResponse(
  53. name="Error",
  54. confidence=0.0,
  55. image=b""
  56. )
  57. finally:
  58. if temp_file and os.path.exists(temp_file):
  59. try:
  60. os.remove(temp_file)
  61. except Exception as cleanup_error:
  62. print(
  63. f"[WARN] Could not delete temp file {temp_file}: {cleanup_error}")
  64. def EnrollFace(self, request, context):
  65. """
  66. Handles enrollment of a new employee.
  67. Saves the uploaded image in EMPLOYEE_DB_PATH with the employee's name.
  68. """
  69. try:
  70. name = request.name
  71. image_bytes = request.image
  72. if not name or not image_bytes:
  73. return face_recognition_pb2.EnrollFaceResponse(
  74. success=False,
  75. message="Name or image missing"
  76. )
  77. os.makedirs(EMPLOYEE_DB_PATH, exist_ok=True)
  78. file_path = os.path.join(EMPLOYEE_DB_PATH, f"{name}.jpg")
  79. with open(file_path, "wb") as f:
  80. f.write(image_bytes)
  81. print(f"[INFO] Enrolled employee: {name}, saved at {file_path}")
  82. return face_recognition_pb2.EnrollFaceResponse(
  83. success=True,
  84. message="Enrollment successful"
  85. )
  86. except Exception as e:
  87. print(f"[ERROR] Enrollment failed: {e}")
  88. return face_recognition_pb2.EnrollFaceResponse(
  89. success=False,
  90. message=str(e)
  91. )
  92. def GetAllEmployees(self, request, context):
  93. try:
  94. employee_files = [
  95. f for f in os.listdir(EMPLOYEE_DB_PATH)
  96. if f.lower().endswith((".jpg", ".png", ".jpeg"))
  97. ]
  98. employees = []
  99. for file in employee_files:
  100. path = os.path.join(EMPLOYEE_DB_PATH, file)
  101. name = os.path.splitext(file)[0]
  102. with open(path, "rb") as f:
  103. image_bytes = f.read()
  104. employees.append(face_recognition_pb2.Employee(
  105. name=name,
  106. image=image_bytes
  107. ))
  108. return face_recognition_pb2.EmployeeListResponse(
  109. employees=employees
  110. )
  111. except Exception as e:
  112. print("[ERROR] Failed to list employees:", e)
  113. return face_recognition_pb2.EmployeeListResponse(employees=[])
  114. def DeleteEmployee(self, request, context):
  115. try:
  116. found = False
  117. for file in os.listdir(EMPLOYEE_DB_PATH):
  118. if os.path.splitext(file)[0] == request.name:
  119. os.remove(os.path.join(EMPLOYEE_DB_PATH, file))
  120. found = True
  121. break
  122. message = "Deleted successfully" if found else "Employee not found"
  123. return face_recognition_pb2.DeleteEmployeeResponse(
  124. success=found,
  125. message=message
  126. )
  127. except Exception as e:
  128. print("[ERROR] Failed to delete employee:", e)
  129. return face_recognition_pb2.DeleteEmployeeResponse(
  130. success=False,
  131. message=str(e)
  132. )
  133. def serve():
  134. server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
  135. face_recognition_pb2_grpc.add_FaceRecognitionServiceServicer_to_server(
  136. FaceRecognitionServicer(), server
  137. )
  138. server.add_insecure_port("[::]:50051")
  139. server.start()
  140. print("[INFO] gRPC Face Recognition server running on port 50051")
  141. server.wait_for_termination()
  142. if __name__ == "__main__":
  143. os.makedirs(EMPLOYEE_DB_PATH, exist_ok=True)
  144. serve()