From 70beed73465ab27449a59c62043d94c16efe00c5 Mon Sep 17 00:00:00 2001 From: Franoosh Date: Wed, 15 Oct 2025 14:42:29 +0200 Subject: Added camera support. Movement recognition and video streaming. Web server and frontend. Work in progress. To be fixed: frontend reloading information about client and a page after major changes like camera name or address change, camera removal. Add certificates before testing on actual distributed hardware. Add user login logic. --- helpers.py | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'helpers.py') diff --git a/helpers.py b/helpers.py index 409a253..8190782 100644 --- a/helpers.py +++ b/helpers.py @@ -8,6 +8,8 @@ __author__ = "Franoosh Corporation" import logging +import subprocess +import cv2 class CustomLoggingFormatter(logging.Formatter): @@ -42,3 +44,64 @@ class CustomLoggingFormatter(logging.Formatter): return result +def process_frame(frame): + """Process frame for contour detection.""" + # Convert to grayscale: + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + # Apply Gaussian blur: + blurred = cv2.GaussianBlur(gray, (21, 21), 0) + + return blurred + +def compute_contours(frame_deque): + """Compute contours from a deque of frames.""" + contours = [] + if len(frame_deque) < 2: + return contours + all_contours = [] + + for idx, frame in enumerate(frame_deque): + frame_0 = process_frame(frame) + try: + frame_1 = process_frame(frame_deque[idx+1]) + except IndexError: + break + frame_delta = cv2.absdiff(frame_0, frame_1) + threshold = cv2.threshold(frame_delta, 25, 255, cv2.THRESH_BINARY)[1] + threshold = cv2.dilate(threshold, None, iterations=2) + contours, _ = cv2.findContours(threshold.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + all_contours.extend(contours) + + return all_contours + +def draw_contours(frame, contours, min_contour_area=500): + """Draw contours on the frame.""" + for contour in contours: + if cv2.contourArea(contour) > min_contour_area: + (x, y, w, h) = cv2.boundingRect(contour) + cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) + + return frame + +def detect_movement(contours, min_area=500): + """Detect movement based on contours found from frame diff.""" + for contour in contours: + if cv2.contourArea(contour) >= min_area: + return True + return False + +def get_available_cameras(): + """ + Get list of available camera devices. + At the moment it does not work. At all. It is useless. + """ + proc = subprocess.Popen(['v4l2-ctl', '--list-devices'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = proc.communicate() + candidate_devices = [i.strip() for i in stdout.decode('utf-8').strip().splitlines()[1:]] + verified_devices = [] + for device in candidate_devices: + cap = cv2.VideoCapture(device) + if cap.isOpened(): + verified_devices.append(device) + cap.release() + return verified_devices \ No newline at end of file -- cgit v1.2.3