diff --git a/README.md b/README.md index a15d2c8..adc9eaf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,22 @@ # SecurityCam -A simple python program to record security cam footage by detecting a face and body of a person in the frame. +A simple python program to record webcam footage when a face or full body is detected. This code was created by me, but following tutorials and learning more about haarscascades. -Credit to TechwithTim. +Credit to TechwithTim. + +## Usage + +Install the required dependencies: + +```bash +pip install opencv-python +``` + +Run the application: + +```bash +python Security/cam.py +``` + +Press `q` to stop the program. diff --git a/Security/cam.py b/Security/cam.py index 5f85da9..5f3b1c3 100644 --- a/Security/cam.py +++ b/Security/cam.py @@ -1,61 +1,78 @@ -import cv2 -import time -import datetime - -cap = cv2.VideoCapture(0) # 0 is the id of the camera - -face_cascade = cv2.CascadeClassifier( - cv2.data.haarcascades + "haarcascade_frontalface_default.xml") # Load the cascade trained on thousands of photos - -body_cascade = cv2.CascadeClassifier( - cv2.data.haarcascades + "haarcascade_fullbody.xml") # Load the cascade trained on thousands of photos - -detection = False -detection_stopped_time = None -timer_started = False -SECONDS_TO_RECORD_AFTER_DETECTION = 5 - -frame_size = (int(cap.get(3)), int(cap.get(4))) -fourcc = cv2.VideoWriter_fourcc(*"mp4v") - - -while True: - _, frame = cap.read() # Read the frame - - gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # Convert to grayscale - faces = face_cascade.detectMultiScale( - gray, 1.3, 5) # Detect the faces in the frame - bodies = body_cascade.detectMultiScale(gray, 1.3, 5) - - if len(faces) + len(bodies) > 0: - if detection: - timer_started = False # Reset the timer - else: - detection = True # Start the timer - current_time = datetime.datetime.now().strftime( - "%d-%m-%Y-%H-%M-%S") # Get the time when the detection stopped - out = cv2.VideoWriter(f"{current_time}.mp4", - fourcc, 20, frame_size) # Create a video file - print("Started recording!") - elif detection: - if timer_started: - if time.time() + detection_stopped_time >= SECONDS_TO_RECORD_AFTER_DETECTION: - detection = False - timer_started = False - out.release() - print("Stopped recording!") - else: - timer_started = True # Start the timer - detection_stopped_time = time.time() # Get the time when the detection stopped - - if detection: - out.write(frame) # Write the frame to the video file - - cv2.imshow("Camera", frame) # Display the frame - - if cv2.waitKey(1) == ord('q'): # Exit if the user presses 'q' - break - -out.release() # Release the video writer -cap.release() # Release the camera -cv2.destroyAllWindows() # Close all the frames +"""Utility to record webcam footage when a face or body is detected.""" + +from __future__ import annotations + +import datetime +import time +from pathlib import Path + +import cv2 + + +FACE_CASCADE = cv2.CascadeClassifier( + cv2.data.haarcascades + "haarcascade_frontalface_default.xml" +) +BODY_CASCADE = cv2.CascadeClassifier( + cv2.data.haarcascades + "haarcascade_fullbody.xml" +) + +SECONDS_TO_RECORD_AFTER_DETECTION = 5 +FOURCC = cv2.VideoWriter_fourcc(*"mp4v") + + +def _new_writer(frame_size: tuple[int, int]) -> cv2.VideoWriter: + """Return a ``cv2.VideoWriter`` with a timestamped filename.""" + + timestamp = datetime.datetime.now().strftime("%d-%m-%Y-%H-%M-%S") + filename = Path(f"{timestamp}.mp4") + return cv2.VideoWriter(str(filename), FOURCC, 20, frame_size) + + +def main() -> None: + cap = cv2.VideoCapture(0) + frame_size = ( + int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), + int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)), + ) + + recording = False + last_detection = None + out: cv2.VideoWriter | None = None + + while True: + ret, frame = cap.read() + if not ret: + break + + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + faces = FACE_CASCADE.detectMultiScale(gray, 1.3, 5) + bodies = BODY_CASCADE.detectMultiScale(gray, 1.3, 5) + + if len(faces) > 0 or len(bodies) > 0: + if not recording: + out = _new_writer(frame_size) + recording = True + print("Started recording!") + last_detection = time.time() + + if recording: + assert out is not None # for type checkers + out.write(frame) + if last_detection and time.time() - last_detection > SECONDS_TO_RECORD_AFTER_DETECTION: + recording = False + out.release() + out = None + print("Stopped recording!") + + cv2.imshow("Camera", frame) + if cv2.waitKey(1) == ord("q"): + break + + if out is not None: + out.release() + cap.release() + cv2.destroyAllWindows() + + +if __name__ == "__main__": + main()