├── requirements.txt ├── config.env ├── LICENSE.md ├── ROI_point_finder.py ├── README.md └── CCTV_Alert.py /requirements.txt: -------------------------------------------------------------------------------- 1 | opencv-python==4.10.0.84 2 | opencv-contrib-python==4.10.0.84 3 | requests==2.32.3 4 | python-dotenv==1.0.1 5 | PyAutoGUI==0.9.54 6 | pillow==10.4.0 7 | python-telegram-bot==21.9 8 | -------------------------------------------------------------------------------- /config.env: -------------------------------------------------------------------------------- 1 | CHAT_ID = 2 | ROI_START_POINT = #you can get using run the ROI_point_finder.py 3 | ROI_END_POINT = #you can get using run the ROI_point_finder.py 4 | IP_CAMERA_URL = #Example:http://192.0.0.4:2323/video OR If you put ID,PASSWORD for camera put like http://:@192.0.0.4:2323/video 5 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Harishkumar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ROI_point_finder.py: -------------------------------------------------------------------------------- 1 | import pyautogui 2 | from tkinter import Tk, Canvas 3 | from PIL import Image, ImageTk 4 | 5 | def get_screen_rect(): 6 | screen = pyautogui.screenshot() 7 | return screen 8 | 9 | def on_click(event): 10 | global roi_start_x, roi_start_y, drawing 11 | roi_start_x, roi_start_y = event.x, event.y 12 | drawing = True 13 | 14 | def on_drag(event): 15 | if drawing: 16 | canvas.delete("rect") 17 | canvas.create_rectangle(roi_start_x, roi_start_y, event.x, event.y, outline="green", width=2, tags="rect") 18 | 19 | def on_release(event): 20 | global roi_end_x, roi_end_y, drawing 21 | roi_end_x, roi_end_y = event.x, event.y 22 | drawing = False 23 | print(f"ROI_START_POINT = {roi_start_x}, {roi_start_y}") 24 | print(f"ROI_END_POINT = {roi_end_x}, {roi_end_y}") 25 | root.destroy() 26 | 27 | # Setup tkinter window 28 | root = Tk() 29 | root.title("Select ROI") 30 | screen_img = get_screen_rect() 31 | screen_img = ImageTk.PhotoImage(screen_img) 32 | canvas = Canvas(root, width=screen_img.width(), height=screen_img.height()) 33 | canvas.pack() 34 | canvas.create_image(0, 0, anchor="nw", image=screen_img) 35 | canvas.bind("", on_click) 36 | canvas.bind("", on_drag) 37 | canvas.bind("", on_release) 38 | 39 | drawing = False 40 | roi_start_x = roi_start_y = roi_end_x = roi_end_y = 0 41 | 42 | root.mainloop() 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 📸 IP Camera Motion Detection with Telegram Alerts 2 | [![License](https://img.shields.io/github/license/whitehatboy005/Motion-Detection-Alert-System-for-CCTV)](LICENSE.md) 3 | 4 | This repository contains two main tools: 5 | 1. **ROI Selector Tool**: A graphical tool to help users easily select a Region of Interest (ROI) from the screen. 6 | 2. **IP Camera Motion Detection Tool**: A CCTV-like system that monitors an IP camera feed for motion within the defined ROI and sends alerts via Telegram. 7 | 8 | ## 🚀 Features 9 | ### 1. ROI Point Finder Tool: 10 | - Graphically select the **Region of Interest (ROI)** on your screen. 11 | - Print the start and end coordinates of the ROI for use in motion detection. 12 | - Simplifies the process of defining an ROI for motion detection. 13 | 14 | ### 2. IP Camera Motion Detection Tool: 15 | - **Monitor an IP camera stream**: Detect motion in a specified area of the video feed (ROI). 16 | - **Send Telegram alerts**: When motion is detected, a snapshot of the frame is sent to a Telegram chat. 17 | - **Configurable settings**: Set up the Telegram Bot Token, IP Camera URL, and ROI coordinates via environment variables. 18 | - **Efficient motion detection**: Only monitors motion within the defined ROI to minimize unnecessary alerts. 19 | # 20 | ## 📌 Instructions 21 | To get Chat ID visit [@GetMyChatID_Bot](https://t.me/GetMyChatID_Bot) Now you will copy the chat Id and config it. 22 | 23 | To access the bot [@SecurityAlertBot](http://t.me/CAMSEC_AlertBot) and START it. 24 | # 25 | ## Start the Telegram Bot 26 | ![Screenshot 2024-12-13 104535](https://github.com/user-attachments/assets/22b7d49f-11ed-41c1-ab90-90339fe06ab1) 27 | ## Program Running interface 28 | ![Screenshot 2024-12-13 104848](https://github.com/user-attachments/assets/e546e0a9-aea9-4187-b11e-f51f96c52d9e) 29 | ## Telegram Bot Alert 30 | ![Screenshot 2024-12-13 111934](https://github.com/user-attachments/assets/9b307fa0-4e57-4bc3-bc48-a4e02e8916b4) 31 | # 32 | ## ⚙️ Installation 33 | ## Clone the Repository 34 | ```bash 35 | git clone https://github.com/whitehatboy005/Motion-Detection-Alert-System-for-CCTV 36 | cd Motion-Detection-Alert-System-for-CCTV 37 | ``` 38 | ## Install Dependencies 39 | ```bash 40 | pip install -r requirements.txt 41 | ``` 42 | ## Find ROI Point for alert zone 43 | ```bash 44 | python ROI_point_finder.py 45 | ``` 46 | ## Configure Environment Variables 47 | ```bash 48 | notepad config.env 49 | ``` 50 | ## Ensure start the bot 51 | Start it --> [@SecurityAlertBot](http://t.me/CAMSEC_AlertBot) 52 | # 53 | ## Run the main Program 54 | ```bash 55 | python CCTV_Alert.py 56 | ``` 57 | # 58 | ## To check on configuration in Telegram 59 | Type [/check] Then check it out. 60 | # 61 | ## WEBCAM Motion Detection Alert System Repository for project submission 62 | **Check on this repository** https://github.com/whitehatboy005/Motion-Detection-Alert-System-for-Webcam 63 | # 64 | 65 | ## 👨‍💻 Contribution: 66 | **Contributions are welcome! If you have any suggestions for improvements or bug fixes, feel free to submit a pull request.** 67 | 68 | ## 📝 License 69 | This project is licensed under the terms of the [MIT license](LICENSE.md). 70 | -------------------------------------------------------------------------------- /CCTV_Alert.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import requests 3 | import os 4 | import threading 5 | from time import time, sleep 6 | from dotenv import load_dotenv 7 | from telegram import Update 8 | from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes 9 | 10 | # Load environment variables 11 | load_dotenv('config.env') 12 | BOT_TOKEN = "7787875894:AAFUdd-82IZbgg33vgViV70fHBIRJDOfZlQ" 13 | CHAT_ID = os.getenv("CHAT_ID") 14 | roi_start_point_str = os.getenv('ROI_START_POINT') 15 | roi_end_point_str = os.getenv('ROI_END_POINT') 16 | ip_camera_url = os.getenv("IP_CAMERA_URL") 17 | 18 | # Convert ROI start and end points from strings to tuples 19 | roi_start_point = tuple(map(int, roi_start_point_str.split(','))) if isinstance(roi_start_point_str, 20 | str) else roi_start_point_str 21 | roi_end_point = tuple(map(int, roi_end_point_str.split(','))) if isinstance(roi_end_point_str, 22 | str) else roi_end_point_str 23 | 24 | 25 | # Function to send an alert with photo 26 | def send_alert(photo_path): 27 | url = f'https://api.telegram.org/bot{BOT_TOKEN}/sendPhoto' 28 | with open(photo_path, 'rb') as photo: 29 | files = {'photo': photo} 30 | payload = { 31 | 'chat_id': CHAT_ID, 32 | 'caption': 'Alert! Someone entered the restricted area.' 33 | } 34 | try: 35 | response = requests.post(url, data=payload, files=files) 36 | if response.status_code == 200: 37 | print("Alert with photo sent successfully!") 38 | else: 39 | print(f"Failed to send alert: {response.status_code} - {response.text}") 40 | except Exception as e: 41 | print(f"Exception occurred: {e}") 42 | 43 | 44 | # Function to send an alert when the IP camera connection is lost 45 | def send_connection_lost_alert(): 46 | url = f'https://api.telegram.org/bot{BOT_TOKEN}/sendMessage' 47 | payload = { 48 | 'chat_id': CHAT_ID, 49 | 'text': 'Alert! Connection to the IP camera was lost.' 50 | } 51 | try: 52 | response = requests.post(url, data=payload) 53 | if response.status_code == 200: 54 | print("Connection lost alert sent successfully!") 55 | else: 56 | print(f"Failed to send connection lost alert: {response.status_code} - {response.text}") 57 | except Exception as e: 58 | print(f"Exception occurred: {e}") 59 | 60 | 61 | # Async command for checking configuration 62 | async def check(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: 63 | config_message = ( 64 | f"Chat ID: {CHAT_ID}\n" 65 | f"ROI Start Point: {roi_start_point_str}\n" 66 | f"ROI End Point: {roi_end_point_str}\n" 67 | f"IP Camera Url: {ip_camera_url}\n" 68 | ) 69 | await update.message.reply_text(config_message) 70 | 71 | 72 | # Motion detection logic with cooldown for repeated alerts 73 | def motion_detection(): 74 | cap = cv2.VideoCapture(ip_camera_url) 75 | 76 | # Background subtractor and detection settings 77 | background_subtractor = cv2.createBackgroundSubtractorMOG2() 78 | min_contour_area = 5000 79 | persistence_threshold = 5 # Frames required for persistent detection 80 | alert_interval = 10 # Time in seconds between alerts 81 | object_detected_frames = 0 # Counter for frames with persistent object detection 82 | last_alert_time = 0 83 | last_connection_status = True 84 | 85 | while True: 86 | ret, frame = cap.read() 87 | 88 | # Check if connection is lost 89 | if not ret: 90 | if last_connection_status: # Send alert only when the connection is lost initially 91 | send_connection_lost_alert() 92 | last_connection_status = False # Update status to avoid repeated alerts 93 | print("Failed to grab frame from IP camera") 94 | sleep(5) # Retry after some delay 95 | continue 96 | else: 97 | last_connection_status = True # Reset status when connection is restored 98 | 99 | # Draw the ROI for visualization 100 | cv2.rectangle(frame, roi_start_point, roi_end_point, (0, 255, 0), 2) 101 | 102 | # Extract the ROI from the frame 103 | roi = frame[roi_start_point[1]:roi_end_point[1], roi_start_point[0]:roi_end_point[0]] 104 | 105 | # Apply background subtraction to detect motion in the ROI 106 | fg_mask = background_subtractor.apply(roi) 107 | _, fg_mask = cv2.threshold(fg_mask, 25, 255, cv2.THRESH_BINARY) 108 | fg_mask = cv2.dilate(fg_mask, None, iterations=2) 109 | 110 | # Find contours in the mask 111 | contours, _ = cv2.findContours(fg_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 112 | 113 | object_in_roi = False 114 | for contour in contours: 115 | if cv2.contourArea(contour) > min_contour_area: 116 | object_in_roi = True 117 | break 118 | 119 | # If object is detected within the ROI, increment the counter 120 | if object_in_roi: 121 | object_detected_frames += 1 122 | else: 123 | object_detected_frames = 0 # Reset if no object is detected in the ROI 124 | 125 | # Trigger alert if object is persistent in ROI and enough time has passed since last alert 126 | current_time = time() 127 | if object_detected_frames >= persistence_threshold and (current_time - last_alert_time) > alert_interval: 128 | photo_path = 'motion_alert.jpg' 129 | cv2.imwrite(photo_path, frame) 130 | send_alert(photo_path) 131 | last_alert_time = current_time 132 | object_detected_frames = 0 # Reset after alert 133 | 134 | # Display the frame with the ROI 135 | cv2.imshow('Frame', frame) 136 | 137 | # Exit on pressing 'q' 138 | if cv2.waitKey(30) & 0xFF == ord('q'): 139 | break 140 | 141 | # Release resources 142 | cap.release() 143 | cv2.destroyAllWindows() 144 | 145 | 146 | print("Alerting System Activated...") 147 | 148 | # Set up the bot application 149 | app = ApplicationBuilder().token(BOT_TOKEN).build() 150 | app.add_handler(CommandHandler("check", check)) 151 | 152 | # Start motion detection in a separate thread 153 | motion_detection_thread = threading.Thread(target=motion_detection) 154 | motion_detection_thread.start() 155 | 156 | # Start the bot 157 | app.run_polling() 158 | --------------------------------------------------------------------------------