You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

153 lines
6.4 KiB

# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Vishnu KP(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
import base64
import PIL
import cmake
import cv2
import dlib
import face_recognition
from io import BytesIO
import numpy
import numpy as np
import os
from PIL import Image
import time
from odoo.exceptions import AccessError
from odoo.http import request
from odoo.addons.hr_attendance.controllers.main import HrAttendance
from odoo import _, http
class HrAttendances(HrAttendance):
"""Controllers Overrides to add the Face detection feature"""
@http.route('/hr_attendance/attendance_employee_data', type="json",
auth="public")
def employee_attendance_data(self, token, employee_id):
"""In this Code section the face detection is added to
employee_attendance_data"""
company = self._get_company(token)
employee_pic = request.env['hr.employee'].sudo().browse(
employee_id).image_1920
sub_folder = os.path.abspath(os.path.dirname(__file__))
project_folder = os.path.abspath(os.path.join(sub_folder, os.pardir))
eye_cascade_path = os.path.join(project_folder, 'data',
'haarcascade_eye_tree_eyeglasses.xml')
face_cascade_path = os.path.join(project_folder, 'data',
'haarcascade_frontalface_default.xml')
face_cascade = cv2.CascadeClassifier(face_cascade_path)
eye_cascade = cv2.CascadeClassifier(eye_cascade_path)
binary_data = base64.b64decode(employee_pic)
image_bytes = BytesIO(binary_data)
pil_image = Image.open(image_bytes)
np_image = np.array(pil_image)
img = cv2.cvtColor(np_image, cv2.COLOR_BGR2RGB)
# Extract features from the referenced eye(s)
orb = cv2.ORB_create()
referenced_key_points, referenced_descriptors = orb.detectAndCompute(
img, None)
encoded_face = face_recognition.face_encodings(img)
start_time = time.time()
camera_time = 0
face_recognized = 0
eyes_match_fail_index = 0
eyes_match_index = 0
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
while ret and camera_time < 9:
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.bilateralFilter(gray, 5, 1, 1)
faces = face_cascade.detectMultiScale(gray, 1.3, 5,
minSize=(200, 200))
if len(faces) == 1:
for (x, y, w, h) in faces:
frame = cv2.rectangle(frame, (x, y), (x + w, y + h),
(0, 255, 0), 2)
eyes = eye_cascade.detectMultiScale(gray, scaleFactor=1.3,
minNeighbors=5)
current_key_points, current_descriptors = orb.detectAndCompute(
gray, None)
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(referenced_descriptors,
current_descriptors)
good_matches = [m for m in matches if m.distance < 70]
if len(good_matches) >= 5:
eyes_match_index += 1
else:
eyes_match_fail_index += 1
if len(eyes) == 0:
img_frame = cv2.resize(frame, (0, 0), None, 0.25, 0.25)
img_frame = cv2.cvtColor(img_frame, cv2.COLOR_BGR2RGB)
face_current_frame = face_recognition.face_locations(
img_frame)
encode_current_frame = face_recognition.face_encodings(
img_frame, face_current_frame)
for encode_face, face_loc in zip(encode_current_frame,
face_current_frame):
face_matches = face_recognition.compare_faces(
encoded_face, encode_face)
face_distance = face_recognition.face_distance(
encoded_face, encode_face)
match_index = np.argmin(face_distance)
elapsed_time = time.time() - start_time
if face_matches[
match_index] and eyes_match_index > eyes_match_fail_index:
face_recognized = 1
if elapsed_time > 6:
time.sleep(1)
else:
face_recognized = 0
# cv2.imshow('frame', frame)
# the imshow is removed from here because it is not needed anymore
# Also it is making error while running the code second time.
cv2.waitKey(0)
else:
# Reset the counters and related variables when no face is
# detected
camera_time += 1
eyes_match_index = 0
eyes_match_fail_index = 0
cap.release()
cv2.destroyAllWindows()
camera_time = 0
if company and face_recognized != 1:
raise AccessError(
_("Sorry, Can't recognize you. Please try again"))
else:
employee = request.env['hr.employee'].sudo().browse(employee_id)
if employee.company_id == company:
return self._get_employee_info_response(employee)
cv2.waitKey(0)
return {}