예제 #1
0
 def respond_to_server(self):
     while True:
         req = self.recv()
         if req is None:
             break
         elif req == "SCAN":
             camera.scan_face()
         elif req == "ALIVE":
             self.send("OK")
             info("[PING] Alive.")
예제 #2
0
 def report(self):
     if len(self.reports) > 10:
         if self.is_connected:
             info("[Reporter] Reporting.")
             self.reports_col.insert_many(self.reports)
             self.reports = []
         else:
             if not self.is_connecting:
                 db_t = threading.Thread(target=self.connect_to_db)
                 db_t.daemon = True
                 db_t.start()
예제 #3
0
def update_recognizer():
    global recognizer
    info("[Recognizer] Updating the recognizer instance.")
    faces: List[vision.Frame] = []
    ids: List[str] = []
    for student in database.students_info.all():
        frame = vision.Frame.open_path(
            f"{data.KNOWN_FACES_PATH}/{student['face-path']}")
        faces.append(frame)
        ids.append(student['inserted-id'])
    recognizer = vision.FaceRecognizer(zip(faces, ids))
    info("[Recognizer] Recognizer update finished.")
예제 #4
0
def scan_face():
    info("[Scanner] Scanning.")
    success, db = get_mongo_client(database.mongo_remote_url)
    students_col = db.get_collection("students")
    while True:
        frame = current_frame.copy()
        faces = vision.FaceDetector.opencv(frame)
        if len(faces) == 0:
            connection.client.send("!")
            continue
        faces = vision.FaceDetector.ageitgey(frame)
        if len(faces) != 1:
            info("[Scanner] Detection failure.")
            connection.client.send("!")
            continue
        info("[Scanner] Successfully scanned a face.")
        connection.client.send("OK")
        break
    student_id = connection.client.recv()
    student_name = connection.client.recv()
    classroom = connection.client.recv()
    reload = connection.client.recv() == "RELOAD"
    face_bin = io.BytesIO()
    faces[0].write(face_bin, ".jpg")
    student = {
        "id": student_id,
        "name": student_name,
        "classroom": classroom,
        "face": face_bin.getvalue()
    }
    students_col.insert_one(student)
    if reload:
        database.sync_database()
        update_recognizer()
예제 #5
0
def sync_database():
    success, db = get_mongo_client(mongo_remote_url)
    info("[Database] Syncing the local database.")
    if not success:
        info(
            "[Database] Cannot sync the local database, server is unavailable."
        )
        return
    students_collection = db.get_collection("students")
    ids = []
    for student in students_collection.find({}, {"face": 0}):
        inserted_id = str(student['_id'])
        res = students_info.search(tinydb.where('inserted-id') == inserted_id)
        ids.append(inserted_id)
        if len(res) == 1:
            continue
        info(
            f"[Database] Adding a new student to the database with id {student['id']}."
        )
        face = students_collection.find_one({'_id': student['_id']},
                                            {"face": 1})['face']
        face = vision.Frame.open_bytes(face)
        relative_path = f"{inserted_id}.jpg"
        face.save(f"{data.KNOWN_FACES_PATH}/{relative_path}")
        students_info.insert({
            'inserted-id': inserted_id,
            'id': student['id'],
            'name': student['name'],
            'classroom': student['classroom'],
            'face-path': relative_path
        })
    for student in students_info.all():
        if student['inserted-id'] not in ids:
            students_info.remove(
                tinydb.where('inserted-id') == student['inserted-id'])
            info(
                f"[Database] Student with id {student['id']} is removed from the local database."
            )
    info("[Database] Synchronization finished.")
예제 #6
0
 def detect_students(self):
     frame = current_frame.copy()
     faces = vision.FaceDetector.opencv(frame)
     if len(faces) > 0:
         info(f"[Detector] Found {len(faces)} face(s).")
     for student_id, face in recognizer.recognize_threaded(faces):
         if isinstance(student_id, str):
             student_id = bson.ObjectId(student_id)
             timestamp = datetime.datetime.now(tz=data.tz)
             self.reports.append({
                 "pi-id": data.config["pi"]["pi-id"],
                 "location": data.config["pi"]["location"],
                 "student-id": student_id,
                 "timestamp": timestamp
             })
             info(
                 f"[Detector] Detected a student with database-id {student_id}."
             )
             if data.config["settings"]["save-images"]:
                 path = f"{data.DETECTED_FACES_PATH}/{student_id}"
                 if not os.path.isdir(path):
                     os.mkdir(path)
                 face.save(f"{path}/{timestamp}.jpg")
예제 #7
0
 def connect_to_db(self):
     info("[Detector] Attempting to connect to the database.")
     self.is_connecting = True
     success, db = get_mongo_client(database.mongo_remote_url)
     if success:
         info("[Detector] Database connection is successful.")
         self.reports_col = db.get_collection("reports")
         self.is_connected = True
     else:
         info("[Detector] Database connection failed.")
         self.is_connected = False
     self.is_connecting = False
예제 #8
0
 def recv_continuous_client(self):
     while True:
         req = self.recv()
         if req is None:
             break
         elif req == "UNBIND":
             self.selected_cam = None
             info(f"[Server] UNBIND request from {self.sock_name}")
         elif self.selected_cam is not None:
             self.selected_cam.send(req)
             if req == "SCAN":
                 info(
                     f"[Server] SCAN request from {self.sock_name} to {self.selected_cam.sock_name}"
                 )
                 while True:
                     res = self.selected_cam.recv()
                     self.send(res)
                     if res == "OK":
                         break
         elif req == "CAMERAS":
             info(f"[Server] CAMERAS request from {self.sock_name}")
             self.server.check_alive(Role.Role_Camera)
             res = {"pi-id": [], "location": []}
             for cam in self.server.get_role(Role.Role_Camera):
                 res["pi-id"].append(cam.pi_id)
                 res["location"].append(cam.location)
             self.send(json.dumps(res))
         elif req.startswith("BIND"):
             info(f"[Server] BIND request from {self.sock_name}")
             req = req.split("BIND ")[1]
             selected_cam = None
             for cam in self.server.get_role(Role.Role_Camera):
                 if cam.pi_id == req:
                     selected_cam = cam
                     break
             if selected_cam is None:
                 self.send("!")
             else:
                 self.send("OK")
                 self.selected_cam = selected_cam
예제 #9
0
def connect_to_server():
    global is_connected_server
    global client
    info("[Client] Attempting to connect to the server.")
    client = Client(networking.create_tcp_socket())
    status = client.connect(address[0], address[1])
    if status == networking.ConnectionStatus.CONNECTION_FAILED:
        is_connected_server = False
        info("[Client] Server connection is failed. Connection failure.")
        return
    client.send(address[2])
    client.send(address[3])
    res = client.recv()
    if res != "OK":
        is_connected_server = False
        info("[Client] Server connection is failed. Unmet credentials.")
        return
    client.send("CAMERA")
    client.send(data.config['pi']['pi-id'])
    client.send(data.config['pi']['location'])
    is_connected_server = True
    info("[Client] Server connection is successful.")
예제 #10
0
 def new_client(self, client: Client) -> bool:
     client.server = self
     client.sock_name = client.tcp_socket.getpeername()
     username = client.recv()
     password = client.recv()
     info(
         f"[Server] A new client attempted to connect: address: {client.sock_name}, username: {username}"
     )
     res = database.users.search((tinydb.where("username") == username)
                                 & (tinydb.where("password") == password))
     if len(res) != 1:
         client.send("!")
         info(
             f"[Server] Client connection failed. Wrong password or username. "
             f"address: {client.sock_name}")
         return False
     info(
         f"[Server] Client connection successful. address: {client.sock_name}"
     )
     client.send("OK")
     pos = client.recv()
     if pos == "CAMERA":
         client.role = Role.Role_Camera
         client.pi_id = client.recv()
         client.location = client.recv()
         info(
             f"[Server] Client added as camera. address: {client.sock_name}"
         )
     elif pos == "CLIENT":
         client.role = Role.Role_Client
         self.executor.submit(client.recv_continuous_client)
         info(f"[Server] Client added. address: {client.sock_name}")
     else:
         client.send("!")
         info(f"[Server] Client connection is refused. Didnt specify role. "
              f"address: {client.sock_name}")
         return False
     return True
예제 #11
0
 def connection_broke(self):
     self.server.clients.remove(self)
     info(f"[Server] Client is no longer alive. address: {self.sock_name}")
예제 #12
0
def start():
    info("[Server] Starting the server.")
    server = Server(Client)
    info("[Server] Listening for incoming connections.")
    server.listen(data.config["server"]["port"], data.config["server"]["host"])
예제 #13
0
 def check_alive(self, role: Role):
     info("[Server] Pinging clients.")
     for cam in self.get_role(role):
         cam.is_alive()
예제 #14
0
 def connection_broke(self):
     global is_connected_server
     info("[Client] Connection broken.")
     is_connected_server = False
예제 #15
0
def shutdown():
    info("[RPi] Exiting.")
    detector.report()