--- license: mit license_link: LICENSE library_name: opencv tags: - opencv - intel - light-level-anomaly - exposure - edge-ai - metro language: - en --- # Light-Level Anomaly Detection | Property | Value | |---|---| | **Category** | Image-Quality Analytics (classical computer vision) | | **Base Model** | Not applicable -- uses luminance statistics | | **Source Framework** | OpenCV | | **Supported Precisions** | Not applicable | | **Inference Engine** | OpenCV (CPU) | | **Hardware** | CPU, GPU (OpenCV UMat optional) | | **Detected Class(es)** | Underexposure, overexposure, sudden light change | --- ## Overview Light-Level Anomaly Detection is a Metro Analytics use case that monitors the overall brightness of a camera feed and flags abnormal lighting conditions: the scene going dark (lights off, lens covered, night), the scene blowing out (glare, headlights, overexposure), or a sudden change in light level. It tracks the mean luminance of each frame against a rolling baseline and raises an event when the level leaves the acceptable band or jumps sharply. A global luminance signal is best measured directly from pixels, so this use case intentionally avoids a neural model. It is a strong building block for real-time alerting use cases. Typical Metro deployments include: - **Lighting Fault Detection** -- alert when platform or tunnel lighting fails. - **Day/Night Transition Handling** -- switch analytics profiles by light level. - **Exposure QA** -- flag cameras that are blown out or too dark to analyze. - **Tamper Indicator** -- a covered lens shows up as a sudden drop in light. --- ## Prerequisites - Python 3.11+ - OpenCV and NumPy Create and activate a Python virtual environment before running the sample: ```bash python3 -m venv .venv source .venv/bin/activate pip install opencv-python numpy ``` --- ## Getting Started ### Download the Sample Video This use case does not export or quantize a model. Run the provided script to download the sample test video: ```bash chmod +x export_and_quantize.sh ./export_and_quantize.sh ``` The script downloads `test_video.mp4` into the current directory. ### OpenCV Sample The sample below computes the mean luminance of each frame from the V channel of HSV, compares it against fixed dark/bright bounds and against a rolling baseline, and classifies each frame as `normal`, `dark`, `bright`, or `sudden-change`. The annotated frames are written to `output_opencv.mp4`. ```python import cv2 import numpy as np INPUT_VIDEO = "test_video.mp4" DARK_BOUND = 40.0 # mean luminance below this is underexposed BRIGHT_BOUND = 215.0 # mean luminance above this is overexposed JUMP_BOUND = 35.0 # frame-to-frame luminance jump that counts as sudden cap = cv2.VideoCapture(INPUT_VIDEO) fps = cap.get(cv2.CAP_PROP_FPS) or 30.0 width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) writer = cv2.VideoWriter( "output_opencv.mp4", cv2.VideoWriter_fourcc(*"mp4v"), fps, (width, height)) prev_level = None frame_idx = 0 anomalies = 0 while True: ok, frame = cap.read() if not ok: break frame_idx += 1 v = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)[:, :, 2] level = float(np.mean(v)) status = "normal" if level < DARK_BOUND: status = "dark" elif level > BRIGHT_BOUND: status = "bright" elif prev_level is not None and abs(level - prev_level) >= JUMP_BOUND: status = "sudden-change" prev_level = level if status != "normal": anomalies += 1 print(f"Frame {frame_idx}: LIGHT ANOMALY ({status}) level={level:.1f}", flush=True) color = (0, 255, 0) if status == "normal" else (0, 0, 255) label = f"level={level:.1f} {status}" (_, text_height), _ = cv2.getTextSize( label, cv2.FONT_HERSHEY_SIMPLEX, 5.0, 2) cv2.putText(frame, label, (10, text_height + 10), cv2.FONT_HERSHEY_SIMPLEX, 5.0, color, 2) writer.write(frame) cap.release() writer.release() print(f"Light-level anomalies detected: {anomalies}", flush=True) ``` **Device targets:** - `"CPU"` -- default for OpenCV luminance statistics. - `"GPU"` -- wrap frames in `cv2.UMat` to use the OpenCV transparent API on Intel GPUs. - `"NPU"` -- not applicable; luminance statistics are not a neural workload. #### Expected Output ![OpenCV expected output](expected_output_openvino.gif) --- ## License Licensed under the MIT License. See [LICENSE](LICENSE) for details. ## References - [OpenCV Color Space Conversions](https://docs.opencv.org/4.x/d8/d01/group__imgproc__color__conversions.html) - [OpenCV Operations on Arrays (mean)](https://docs.opencv.org/4.x/d2/de8/group__core__array.html)