This project provides a Python script designed to monitor image uploads from a camera, typically to an FTP server or a local directory. It analyzes a specific Region of Interest (ROI) within these images for significant changes (new, removed, or moved objects). The analysis intelligently considers varying lighting conditions (daytime, and the status of up to two independent motion-activated lights). When meaningful movement is detected, the script saves a copy of the original image with the detected changes highlighted. The system uses the watchdog library for real-time, event-driven monitoring of new files after an initial historical scan.
The primary goal is to provide a configurable system that can adapt to different environments and user preferences for sensitivity, helping to minimize false positives while still capturing relevant events.
- Event-Driven Directory Monitoring: Uses the
watchdoglibrary to react instantly to new image files in monitored directories after an initial historical scan. - Mask-Based Analysis: Uses user-defined masks to specify:
- The primary Region of Interest (ROI) for change detection.
- Areas to determine the status of two independent motion lights.
- Adaptive Light State Detection:
- Determines ambient light (Day/Night).
- Detects the ON/OFF status of two motion lights.
- Combines these into a composite light state (e.g.,
daytime,night_l1_on_l2_off).
- Advanced Baseline Management: Maintains separate reference "baseline" images for each composite light state. Baselines are updated using an Exponentially Weighted Moving Average (EWMA) for frames with no motion, allowing gradual adaptation. Direct updates occur if motion is detected and
update_baseline_on_motionis configured totrue. - Change Detection:
- Compares the current image's ROI with the appropriate baseline.
- Uses configurable parameters (blur, difference threshold, contour area) to identify significant changes.
- Conditional Output: Saves a copy of the original image with changes highlighted only when significant motion is detected.
- Configurable: Most operational parameters are controlled via a
config.jsonfile. - Logging: Comprehensive logging of script activities and errors.
- (Implemented) Support for multiple camera input directories.
- (Implemented) Stuck motion detection and intelligent baseline reset.
- (Implemented) Duplicate file detection and deletion.
- Python 3.x (tested with 3.7+)
- OpenCV for Python (
opencv-python) watchdoglibrary (pip install watchdog)
-
Get the Code: Clone this repository to your desired location:
git clone <repository_url> cd <repository_directory_name>
Or, if you've downloaded the script files (
image_detection.py,detection_utils.py,config.jsonetc.), navigate to that directory. -
Create and Activate a Virtual Environment (Recommended): Using a virtual environment helps manage project-specific dependencies.
- Create the virtual environment (e.g., named
envor.venv):python -m venv env
- Activate the virtual environment:
- On Windows:
.\env\Scripts\activate
- On macOS and Linux:
source env/bin/activate
(env)). - On Windows:
- Create the virtual environment (e.g., named
-
Install Dependencies: With your virtual environment activated, install the required packages: Ensure you have a
requirements.txtfile in your project directory. Then run:pip install -r requirements.txt
-
Directory Structure: The script expects images to be uploaded to a specific directory structure, typically organized by camera and then by date. For example:
/path/to/ftp/images/ ├── camera_1_name/ │ ├── YYYY-MM-DD/ │ │ ├── image_timestamp1.jpg │ │ └── image_timestamp2.jpg │ └── YYYY-MM-DD/ │ └── ... └── camera_2_name/ ├── YYYY-MM-DD/ │ └── ... └── ...The
input_directory(orpathwithininput_configurationsinconfig.json) should point to the parent directory (e.g.,/path/to/ftp/images/camera_1_name/). The script will automatically look for date-named subdirectories (e.g.,2023-10-27). -
Mask Creation: Masks are crucial for defining analysis regions. They must be binary (black and white) images (PNG format recommended).
- White pixels (255): Indicate areas to include in the analysis for that mask's purpose.
- Black pixels (0): Indicate areas to ignore.
- Dimensions: All masks MUST have the exact same dimensions (height and width) as the source images from your camera.
You will need to create at least:
- ROI Mask: Defines the main area where you want to detect changes.
- Light 1 Area Mask (Optional but Recommended): Defines the area to check if motion light 1 is on.
- Light 2 Area Mask (Optional but Recommended): Defines the area to check if motion light 2 is on.
Save these masks to a location accessible by the script and update their paths in
config.json. -
Configuration (
config.json): This JSON file is the heart of the script's customization. Create aconfig.jsonfile in the same directory asimage_detection.py(or specify its path if modified).Refer to the example
config.jsonstructure inimage_detection_tech_spec.txt(Section 6) or the providedconfig.json.example. Key parameters to configure:input_configurations: An array, where each object defines a camera setup.path: Path to the base directory for a specific camera (e.g.,/path/to/ftp/images/camera_1_name).masks:roi: Path to your ROI mask file.light1_area: Path to your Light 1 area mask file.light2_area: Path to your Light 2 area mask file.
light_detection_params: Thresholds for detecting light states.change_detection_params: Crucial for sensitivity tuning.update_baseline_on_motion(boolean, optional, defaults totrue):- If
true: The baseline is updated directly with the current ROI when motion is detected. During no-motion periods, it's updated via EWMA (seebaseline_ewma_alpha). - If
false: The baseline is only updated via EWMA during no-motion periods. It is not updated when motion is detected.
- If
baseline_ewma_alpha(float, optional, defaults to0.05): The alpha value for the Exponentially Weighted Moving Average used to update baselines during no-motion periods. A smaller value (e.g., 0.01-0.1) means slower, more gradual adaptation.
output_directory: Where highlighted images with detected motion will be saved.log_file_path: Path for the main system log file.log_level: Logging verbosity (e.g.,INFO,DEBUG).polling_interval_seconds(no longer used for primary monitoring withwatchdog, but kept for potential future fallback or specific utility functions if any).output_image_prefix: Prefix for saved motion images.max_history(integer, optional): Number of recent images to keep in history for the "stuck motion baseline reset" feature.consecutive_motion_reset_threshold(integer, optional): Number of consecutive motion detections before triggering a baseline reset.duplicate_time_threshold_ms(integer, optional): Time window (in milliseconds) for considering images with the same hash as duplicates.
Navigate to the directory containing image_detection.py in your terminal and run:
python image_detection.py