diff --git a/camera-client/camera_monitor.py b/camera-client/camera_monitor.py new file mode 100644 index 0000000..69beb37 --- /dev/null +++ b/camera-client/camera_monitor.py @@ -0,0 +1,100 @@ +import cv2 +import time +import requests +import numpy as np +from datetime import datetime +import os +import json +import logging +import argparse + +class CameraMonitor: + def __init__(self, config, logger): + self.config = config + self.logger = logger + + def initialize_camera(self): + """ + Initialize the camera and return the VideoCapture object. + """ + cap = cv2.VideoCapture(self.config['camera_address']) + if not cap.isOpened(): + raise Exception(f"Failed to open camera at {self.config['camera_address']}") + return cap + + def log_scene_change(self): + """ + Log a scene change notification to the Scenesense server. + """ + current_time = int(time.time()) + human_readable_time = datetime.utcfromtimestamp(current_time).strftime('%Y-%m-%d %H:%M:%S') + description = f'Scene change detected at {human_readable_time}' + payload = {'timestamp': current_time, 'description': description} + + try: + response = requests.post(self.config['api_url'], json=payload) + response.raise_for_status() + self.logger.info(f'Scene change logged: {description}') + except requests.exceptions.RequestException as e: + self.logger.error(f'Error connecting to Scenesense server: {e}') + except requests.exceptions.HTTPError as e: + self.logger.error(f'HTTP error: {e}') + + def detect_scene_change(self, previous_frame, current_frame): + """ + Detect scene change based on frame differences. + """ + frame_diff = cv2.absdiff(previous_frame, current_frame) + mean_diff = np.mean(frame_diff) + return mean_diff > self.config['sensitivity_threshold'] + + def run(self): + try: + with self.initialize_camera() as cap: + previous_frame = None + + while True: + ret, current_frame = cap.read() + + if not ret: + raise Exception("Failed to read frame") + + if previous_frame is not None: + if self.detect_scene_change(previous_frame, current_frame): + self.log_scene_change() + + previous_frame = current_frame + + except KeyboardInterrupt: + self.logger.info("Camera monitoring stopped by user.") + except Exception as e: + self.logger.error(f"An error occurred: {e}") + +def parse_command_line_args(): + parser = argparse.ArgumentParser(description='Camera Monitor for Scenesense') + parser.add_argument('--config', type=str, default='config.json', help='Path to configuration file') + return parser.parse_args() + +def load_config(config_path): + try: + with open(config_path, 'r') as config_file: + return json.load(config_file) + except FileNotFoundError: + raise Exception(f"Config file not found: {config_path}") + except json.JSONDecodeError: + raise Exception(f"Invalid JSON format in config file: {config_path}") + +def setup_logging(): + logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') + return logging.getLogger('CameraMonitor') + +def main(): + args = parse_command_line_args() + config = load_config(args.config) + logger = setup_logging() + + monitor = CameraMonitor(config, logger) + monitor.run() + +if __name__ == "__main__": + main() diff --git a/camera-client/requirements.txt b/camera-client/requirements.txt new file mode 100644 index 0000000..5c20811 --- /dev/null +++ b/camera-client/requirements.txt @@ -0,0 +1,3 @@ +numpy +opencv-python-headless +requests \ No newline at end of file