File size: 5,139 Bytes
16c6d7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
import face_recognition as fr
import pickle
import shutil

# Use persistent storage path
DATA_DIR = "/data"
KNOWN_USER_DIR = os.path.join(DATA_DIR, "known_users")
UNKNOWN_USER_DIR = os.path.join(DATA_DIR, "unknown_users")
ENCODINGS_DIR = os.path.join(DATA_DIR, "encodings")

# Ensure directories exist
os.makedirs(KNOWN_USER_DIR, exist_ok=True)
os.makedirs(UNKNOWN_USER_DIR, exist_ok=True)
os.makedirs(ENCODINGS_DIR, exist_ok=True)


def save_image_from_path(image_path, student_id):
    """Save student image from file path and compute face encoding"""
    try:
        if not image_path or not os.path.exists(image_path):
            return False, "No image provided"
        
        # Destination path
        dest_path = os.path.join(KNOWN_USER_DIR, f"{student_id}.jpg")
        
        # Copy image to destination
        shutil.copy2(image_path, dest_path)
        
        # Compute and save face encoding
        image = fr.load_image_file(dest_path)
        face_encodings = fr.face_encodings(image)
        
        if len(face_encodings) > 0:
            encoding = face_encodings[0]
            encoding_path = os.path.join(ENCODINGS_DIR, f"{student_id}.pkl")
            
            with open(encoding_path, "wb") as f:
                pickle.dump(encoding, f)
            
            return True, "Image and face encoding saved successfully!"
        else:
            # Delete image if no face found
            if os.path.exists(dest_path):
                os.remove(dest_path)
            return False, "No face detected in the image. Please upload a clear face photo."
            
    except Exception as e:
        return False, f"Error processing image: {str(e)}"


def save_temp_image_from_path(image_path):
    """Save temporary image from file path for login"""
    try:
        if not image_path or not os.path.exists(image_path):
            return None
        
        temp_path = os.path.join(UNKNOWN_USER_DIR, "temp_login.jpg")
        shutil.copy2(image_path, temp_path)
        return temp_path
        
    except Exception as e:
        print(f"Error saving temp image: {e}")
        return None


def delete_temp_image():
    """Delete temporary login image"""
    temp_path = os.path.join(UNKNOWN_USER_DIR, "temp_login.jpg")
    if os.path.exists(temp_path):
        try:
            os.remove(temp_path)
        except Exception as e:
            print(f"Error deleting temp image: {e}")


def recognize_face(unknown_image_path, tolerance=0.5):
    """
    Recognize face by comparing with stored encodings
    Returns: (is_match, student_id, confidence, message)
    """
    try:
        # Load unknown image
        if not os.path.exists(unknown_image_path):
            return False, None, 0, "Image file not found"
        
        unknown_image = fr.load_image_file(unknown_image_path)
        unknown_encodings = fr.face_encodings(unknown_image)
        
        if len(unknown_encodings) == 0:
            return False, None, 0, "No face detected in the image"
        
        unknown_encoding = unknown_encodings[0]
        
        # Compare with all stored encodings
        best_match_id = None
        best_distance = float('inf')
        
        encoding_files = [f for f in os.listdir(ENCODINGS_DIR) if f.endswith('.pkl')]
        
        if not encoding_files:
            return False, None, 0, "No registered students found in database"
        
        for encoding_file in encoding_files:
            student_id = encoding_file.replace('.pkl', '')
            encoding_path = os.path.join(ENCODINGS_DIR, encoding_file)
            
            with open(encoding_path, 'rb') as f:
                known_encoding = pickle.load(f)
            
            distance = fr.face_distance([known_encoding], unknown_encoding)[0]
            
            if distance < best_distance:
                best_distance = distance
                best_match_id = student_id
        
        # Check if best match is within tolerance
        if best_distance < tolerance:
            confidence = (1 - best_distance) * 100
            return True, best_match_id, confidence, "Face matched successfully!"
        else:
            return False, None, 0, "No matching face found in database"
            
    except Exception as e:
        return False, None, 0, f"Error during recognition: {str(e)}"


def get_image_path(student_id):
    """Get path to student's image"""
    return os.path.join(KNOWN_USER_DIR, f"{student_id}.jpg")


def image_exists(student_id):
    """Check if student's image exists"""
    return os.path.exists(get_image_path(student_id))


def delete_image(student_id):
    """Delete student's image and encoding"""
    image_path = os.path.join(KNOWN_USER_DIR, f"{student_id}.jpg")
    encoding_path = os.path.join(ENCODINGS_DIR, f"{student_id}.pkl")
    
    if os.path.exists(image_path):
        os.remove(image_path)
    if os.path.exists(encoding_path):
        os.remove(encoding_path)


def get_all_images():
    """Get list of all student IDs with images"""
    return [f.replace('.jpg', '') for f in os.listdir(KNOWN_USER_DIR) if f.endswith('.jpg')]