Pothole Detection System Project Code Explanation
Pothole Detection System Project Code Explanation
Comprehensive Explanation
Introduction to the System
This code creates a web application that can detect potholes using a camera or uploaded videos.
The system uses artificial intelligence to recognize potholes in real-time and can even sound an
alarm when potholes are detected.
This imports Flask, which is like the foundation for building web applications. Think of Flask as
the skeleton of your website.
This brings in tools to handle user logins and security. It's like having a security guard for your
website who checks IDs.
import cv2
OpenCV (cv2) is a computer vision library. Think of it as the "eyes" of your application that can
process and understand images and videos.
import winsound
This is used to play alarm sounds on Windows computers when potholes are detected.
from ultralytics import YOLO
YOLO is the AI model that actually detects potholes in images. Think of it as the "brain" that
recognizes what a pothole looks like.
import time
import os
import platform
import logging
These are utilities for timing operations, working with files and directories, identifying the
operating system, and keeping track of what's happening (logging).
This helps make sure that uploaded file names are safe to use and won't cause security
problems.
import numpy as np
NumPy is used for mathematical operations on arrays, which is helpful when processing image
data.
import threading
Threading allows your program to do multiple things at once, like processing video while also
serving web pages.
These help with type hints to make the code more reliable and easier to understand.
import requests
Used for making HTTP requests, which might be needed when connecting to cameras over the
network.
import socket
import netifaces
These help identify and work with network interfaces and IP addresses, useful for connecting to
cameras over a network.
Logging Setup
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
This sets up logging to keep track of what happens in the application. It's like having a diary that
records important events with timestamps. This can help you troubleshoot problems later.
current_dir = os.path.dirname(os.path.abspath(__file__))
template_dir = os.path.join(current_dir, 'templates')
static_dir = os.path.join(current_dir, 'static')
uploads_dir = os.path.join(static_dir, 'uploads')
logs_dir = os.path.join(current_dir, 'logs')
app = Flask(__name__,
template_folder=template_dir,
static_folder=static_dir)
app.secret_key = os.environ.get('FLASK_SECRET_KEY',
'your_secret_key_here')
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max file
size
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
login_manager.login_message_category = 'info'
class User(UserMixin):
def __init__(self, id):
self.id = id
self.name = id
@staticmethod
def get(user_id):
if user_id not in users:
return None
return User(user_id)
users = {
'admin': {'password': 'admin123'}
}
try:
model_path = os.path.join(current_dir,
'runs/detect/pothole_detector/weights/best.pt')
model = YOLO(model_path)
logger.info("YOLO model loaded successfully")
except Exception as e:
logger.error(f"Error loading YOLO model: {str(e)}")
raise
Detection Configuration
class DetectionConfig:
CONF_THRESHOLD = 0.45
IOU_THRESHOLD = 0.45
MIN_AREA_RATIO = 0.01
MAX_AREA_RATIO = 0.5
ALARM_COOLDOWN = 2
class CameraHandler:
def __init__(self):
self.camera = None
self.current_source = None
self.last_alarm_time = 0
self.is_mobile = False
self.camera_lock = threading.Lock()
self.connection_timeout = 10
self.retry_delay = 1
self.ivcam_connection_retries = 3
self.client_ip = None
def get_all_network_ips(self):
"""Get all possible IP addresses in the network"""
# [Implementation details]
This method scans the network for possible IP addresses where cameras might be connected.
Think of it as looking around your network neighborhood to find cameras.
This tests if an iVCam camera is available at a specific IP address. Note that there's a hardcoded
IP address here (192.168.1.11).
def test_ip_camera_connection(self):
"""Test if IP camera is available"""
url = 'http://192.168.1.3:8080/video'
return self.test_connection(url)
This method tries to actually connect to a camera and grab a frame to see if it's working. Think
of it as checking if a camera is actually on and sending images.
Camera Handler Class Methods
initialize_camera Method
This starts a function that sets up the camera. The with self.camera_lock: creates a
protected section where only one part of the program can access the camera at a time.
If there's already an active camera, this shuts it down first before setting up a new one.
self.is_mobile = is_mobile
self.client_ip = client_ip
logger.info(f"Initializing camera - Source: {source_type},
Mobile: {is_mobile}, Client IP: {client_ip}")
This saves information about the device connecting and writes a log message with these
details.
try:
# Determine the best camera source
if source_type == 'auto':
source_type = self.get_camera_source(is_mobile,
client_ip)
This tries to automatically pick the best camera type if 'auto' was selected.
if source_type == 'system':
return self._init_system_camera()
elif source_type == 'ivcam':
return self._init_ivcam_camera()
elif source_type == 'ip':
return self._init_ip_camera()
else:
raise ValueError(f"Invalid camera source type:
{source_type}")
This calls the appropriate setup function based on which camera type was chosen.
except Exception as e:
logger.error(f"Camera initialization error: {str(e)}")
return False
If anything goes wrong during setup, this catches the error, logs it, and returns False to indicate
failure.
_init_system_camera Method
def _init_system_camera(self):
"""Initialize system camera with retry logic"""
for idx in range(2): # Try first two camera indices
This function starts a loop to try the first two camera devices (0 and 1).
try:
camera = cv2.VideoCapture(idx, cv2.CAP_DSHOW)
This creates a connection to the camera. cv2.CAP_DSHOW uses DirectShow on Windows for
better compatibility.
if self._verify_camera(camera):
self.camera = camera
self.current_source = 'system'
return True
If the camera passes the verification test, it's saved as the active camera and the function
returns success.
camera.release()
except Exception as e:
logger.error(f"System camera error: {str(e)}")
time.sleep(1)
return False
_init_ivcam_camera Method
def _init_ivcam_camera(self):
"""Initialize iVCam with improved connection handling"""
url = 'http://192.168.1.11:4747/video' # Updated IP and port
logger.info(f"Attempting to connect to iVCam at: {url}")
This sets the network address for the iVCam app and logs the connection attempt.
# url = f'http://{self.client_ip}:8080/video'
# logger.info(f"Attempting to connect to iVCam at: {url}")
These commented lines show an alternative way to connect using the client's own IP address.
try:
camera = cv2.VideoCapture()
camera.set(cv2.CAP_PROP_BUFFERSIZE, 3)
camera.set(cv2.CAP_PROP_FOURCC,
cv2.VideoWriter_fourcc(*'MJPG'))
camera.set(cv2.CAP_PROP_FPS, 30)
camera.open(url)
This attempts to open the connection to the camera using the provided URL.
if self._verify_camera(camera):
self.camera = camera
self.current_source = 'ivcam'
logger.info(f"Successfully connected to iVCam at {url}")
return True
If verification succeeds, the camera is saved and the function returns success.
camera.release()
return False
_init_ip_camera Method
def _init_ip_camera(self):
"""Initialize IP camera connection"""
url = 'http://192.168.1.3:8080/video'
try:
camera = cv2.VideoCapture()
camera.set(cv2.CAP_PROP_BUFFERSIZE, 3)
camera.set(cv2.CAP_PROP_FOURCC,
cv2.VideoWriter_fourcc(*'MJPG'))
camera.set(cv2.CAP_PROP_FPS, 30)
camera.open(url)
This creates and configures the camera connection, similar to the iVCam setup.
if self._verify_camera(camera):
self.camera = camera
self.current_source = 'ip'
return True
If verification succeeds, the camera is saved and the function returns success.
camera.release()
If verification fails, resources are released.
except Exception as e:
logger.error(f"Failed to connect to IP camera: {str(e)}")
return False
_verify_camera Method
success_count = 0
start_time = time.time()
These variables track successful frame reads and the start time for the verification process.
If a valid frame is read, the success count increases. Once 3 frames are successfully read, the
camera is considered working.
time.sleep(0.1)
return False
release_camera Method
def release_camera(self):
"""Release camera resources safely"""
with self.camera_lock:
try:
if self.camera is not None:
self.camera.release()
self.camera = None
self.current_source = None
logger.info("Camera released successfully")
This safely releases the camera resources and clears related variables.
except Exception as e:
logger.error(f"Error releasing camera: {str(e)}")
Alarm Functions
def play_alarm():
"""Platform-specific alarm implementation"""
try:
if platform.system() == 'Windows':
winsound.Beep(1000, 500)
time.sleep(0.1)
winsound.Beep(2000, 500)
This plays two beeps at different frequencies (1000Hz and 2000Hz) for 500 milliseconds each,
with a small pause in between, but only on Windows.
else:
logger.info("Alarm triggered - sound not available on
non-Windows systems")
except Exception as e:
logger.error(f"Error playing alarm: {str(e)}")
def should_play_alarm(camera_handler):
current_time = time.time()
if current_time - camera_handler.last_alarm_time >=
DetectionConfig.ALARM_COOLDOWN:
camera_handler.last_alarm_time = current_time
return True
return False
This checks if enough time has passed since the last alarm to play a new one.
def play_alarm_if_needed(camera_handler):
if should_play_alarm(camera_handler):
alarm_thread = threading.Thread(target=play_alarm)
alarm_thread.daemon = True
alarm_thread.start()
If an alarm should be played, this starts it in a separate thread so it doesn't interrupt the main
program.
This extracts the confidence level and bounding box from a detection.
This calculates how much of the frame is occupied by the detected object.
This returns True if the detection meets confidence and size requirements.
except Exception as e:
logger.error(f"Error validating detection: {str(e)}")
return False
Any errors are caught, logged, and the detection is considered invalid.
This runs the AI model on a frame and prepares a list to store detection information.
if len(results.boxes) > 0:
valid_detections = [box for box in results.boxes if
is_valid_detection(box, frame.shape)]
if valid_detections:
play_alarm_if_needed(camera_handler)
For each valid detection, this extracts the confidence and coordinates.
detections.append({
'confidence': conf,
'box': (x1, y1, x2, y2),
'timestamp': datetime.now().isoformat()
})
except Exception as e:
logger.error(f"Error processing frame: {str(e)}")
return frame, []
Any errors are caught and logged, returning the original frame and empty detections.
camera_handler = CameraHandler()
def generate_frames():
try:
while True:
with camera_handler.camera_lock:
if camera_handler.camera is None:
break
frame = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame +
b'\r\n')
except Exception as e:
logger.error(f"Error in generate_frames: {str(e)}")
finally:
camera_handler.release_camera()
This tells the login system how to load a user from their ID.
Main Routes
@app.route('/')
def home():
return redirect(url_for('login'))
If a user is already logged in, this sends them to the main application.
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
If the login details are valid, the user is logged in and sent to the requested page or main page.
return render_template('login.html')
@app.route('/index')
@login_required
def index():
# Enhanced mobile detection
user_agent = request.headers.get('User-Agent', '').lower()
is_mobile = any(device in user_agent for device in [
'mobile', 'android', 'iphone', 'ipad', 'ipod',
'webos', 'blackberry', 'windows phone'
])
This checks if the user is on a mobile device by looking at their browser information.
This shows the main application page, with a flag indicating if the user is on mobile.
@app.route('/start_camera/<source_type>')
@login_required
def start_camera(source_type):
try:
# Enhanced client detection
user_agent = request.headers.get('User-Agent', '').lower()
is_mobile = any(device in user_agent for device in [
'mobile', 'android', 'iphone', 'ipad', 'ipod',
'webos', 'blackberry', 'windows phone'
])
client_ip = request.remote_addr
This determines the device type and gets the user's IP address.
# Log connection attempt
logger.info(f"Camera start request - Source: {source_type}")
logger.info(f"Client Info - IP: {client_ip}, Mobile:
{is_mobile}")
logger.info(f"User Agent: {user_agent}")
# Initialize camera
success = camera_handler.initialize_camera(source_type,
is_mobile, client_ip)
if success:
return jsonify({
'status': 'success',
'source': source_type,
'is_mobile': is_mobile
})
except Exception as e:
logger.error(f"Error starting camera: {str(e)}")
return jsonify({'status': 'error', 'message': str(e)}), 500
@app.route('/check_camera_status')
@login_required
def check_camera_status():
"""Check if camera is connected and working"""
try:
if camera_handler.camera is None:
return jsonify({
'status': 'disconnected',
'source': None,
'is_mobile': camera_handler.is_mobile
})
else:
return jsonify({
'status': 'error',
'message': 'Camera not reading frames',
'source': camera_handler.current_source,
'is_mobile': camera_handler.is_mobile
})
If the camera exists but can't read frames, this returns an error.
except Exception as e:
return jsonify({
'status': 'error',
'message': str(e),
'source': camera_handler.current_source,
'is_mobile': camera_handler.is_mobile
})
@app.route('/video_feed')
@login_required
def video_feed():
try:
return Response(generate_frames(),
mimetype='multipart/x-mixed-replace;
boundary=frame')
This creates a continuous video stream using the frame generator.
except Exception as e:
logger.error(f"Error in video_feed: {str(e)}")
return "Camera error", 500
@app.route('/upload_video', methods=['POST'])
@login_required
def upload_video():
if 'video' not in request.files:
return jsonify({'error': 'No video file'}), 400
video_file = request.files['video']
if video_file.filename == '':
return jsonify({'error': 'No selected file'}), 400
try:
filename = secure_filename(video_file.filename)
video_path = os.path.join(uploads_dir, filename)
video_file.save(video_path)
output_filename = f'processed_{filename}'
output_path = os.path.join(uploads_dir, output_filename)
cap = cv2.VideoCapture(video_path)
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = int(cap.get(cv2.CAP_PROP_FPS))
out = cv2.VideoWriter(output_path,
cv2.VideoWriter_fourcc(*'mp4v'),
fps,
(frame_width, frame_height))
while True:
success, frame = cap.read()
if not success:
break
This processes each frame for potholes and writes it to the output video.
cap.release()
out.release()
if os.path.exists(video_path):
os.remove(video_path)
processed_video_url = url_for('static',
filename=f'uploads/{output_filename}')
return jsonify({
'status': 'success',
'processed_video': processed_video_url
})
except Exception as e:
logger.error(f"Error processing video: {str(e)}")
return jsonify({'error': str(e)}), 500
@app.route('/stop_camera', methods=['POST'])
@login_required
def stop_camera():
try:
camera_handler.release_camera()
return jsonify({
'status': 'success',
'message': 'Camera stopped successfully'
})
except Exception as e:
logger.error(f"Error stopping camera: {str(e)}")
return jsonify({
'status': 'error',
'message': str(e)
}), 500
Logout Route
@app.route('/logout')
@login_required
def logout():
try:
camera_handler.release_camera()
except Exception as e:
logger.error(f"Error during logout camera cleanup: {str(e)}")
logout_user()
return redirect(url_for('login'))
This logs the user out and redirects to the login page.
Unauthorized Handler
@login_manager.unauthorized_handler
def unauthorized():
flash('You must be logged in to access this page.')
return redirect(url_for('login'))
This shows a message and redirects to login when someone tries to access a protected page
without logging in.
Application Startup
if __name__ == '__main__':
try:
# Add configuration for handling larger video files
app.config['MAX_CONTENT_LENGTH'] = 64 * 1024 * 1024 # 64MB
max file size
except Exception as e:
logger.error(f"Application error: {str(e)}")
finally:
camera_handler.release_camera()
This detailed breakdown shows how each line of code contributes to the complete pothole
detection system, from camera management to video processing to the web interface.
Files Explanination
🚀
Core Application (Flask Web App & Detection Script)
File/Folder Purpose
app.py Main Flask app that launches the pothole detection web interface and
streams video with detection.
templates/ Contains HTML templates for the Flask app (e.g., index.html).
requirements. (Empty now) Used to list dependencies like Flask, OpenCV, etc., to set
txt up the project environment.
📁 Dataset Related
File/Folder Purpose
training_log_*.l Text log files of each training session – shows metrics, losses,
og etc.
⚙️ Project Metadata
File/Folder Purpose
● Scripts:
🖥️ Backend
✅ Flask (Python Web Framework)
● Main App File: app.py
● Purpose: Serves the web interface, handles camera selection, runs live detection, plays
alarm sounds.
● Folders:
○ flask
○ opencv-python
○ ultralytics or torch
🎨 Frontend
✅ HTML + CSS + JavaScript via Flask
● Directory: templates/, static/
● Function:
🔧 Utility Scripts
Script/File Purpose
filter.bat Possibly a batch file to quickly run a task (e.g., launch app.py
or run detection).
📂 Dataset Management
Folder Purpose
runs/ Default YOLO output folder for training and detection results
📹 Media Output
File Purpose
✅ Summary Table
Component Technology Used Files/Folders
🔧
Project Architecture & Tech Stack
● Scripts: Python scripts handle training, inference, camera streams, logging, and
monitoring.
● Storage: Local file system to store input videos, logs, and output results.
Q2. Which technologies and frameworks have you used in this project?
A:
Answer:
This project is a step toward improving road safety and reducing accidents caused by
potholes, which are a huge issue, especially in developing countries. Roads with potholes can
lead to vehicle damage, accidents, and traffic disruptions. Our system offers a quick, automated
way to detect potholes in real time, which can be used by municipalities, government
agencies, and road safety organizations to take action faster. It helps in reducing road
maintenance costs and preventing injuries from road-related accidents.
2. Are there already software solutions available in the market for pothole
detection?
Answer:
Yes, there are some commercial solutions like Roadroid and StreetScan, but they often rely
on specialized equipment or manual data collection, which can be expensive and
time-consuming. They also may not provide real-time detection. Our solution offers a more
affordable, flexible, and scalable approach. It can use existing mobile cameras or simple
webcams, making it accessible even to small road maintenance teams. Moreover, it's designed
to be lightweight and easy to deploy.
3. What makes your project stand out from the existing solutions in the
market?
Answer:
Our project stands out in several ways:
● Real-time Detection: Unlike most solutions that require pre-recorded data or long-term
analysis, our system detects potholes in real time as a video stream is captured. This
enables instant responses, making it ideal for proactive road maintenance.
● Integrated Alert System: Our system not only detects potholes but also alerts the user
immediately via an alarm. This makes it practical for use in vehicles, drones, or on-site
monitoring stations.
● Flexibility: It's designed to be modular, meaning it can easily be integrated into different
platforms like web applications or mobile apps, providing high customization options
for various user needs.
Answer:
The social impact is significant. By improving road safety and reducing accidents, this project
could save lives, minimize injuries, and make commuting safer for everyone. The
environmental impact is also noteworthy—keeping roads in good condition means fewer
vehicles breaking down or getting stuck in potholes, reducing emissions and fuel consumption
caused by vehicles detouring or idling on damaged roads.
Answer:
We chose this project because potholes are an everyday problem in many regions, and there’s
a clear need for a solution that’s both effective and affordable. Seeing the negative impact
potholes have on road safety and the environment, we wanted to create a system that can be
easily adopted and used by road maintenance authorities, even in resource-constrained
areas. The potential to make a real difference in people's lives and reduce accidents was a
major motivation for us.
6. What future enhancements do you see for this project?
Answer:
We plan to improve the model by:
● Using drones for aerial pothole detection, allowing for large-scale monitoring of
highways.
● Adding AI-based predictive analytics to not only detect potholes but predict areas
where potholes are likely to form based on weather, traffic, and road conditions.
● Integrating the system with smart city infrastructure to enable automated road
repairs and more efficient traffic management.
Answer:
This project can revolutionize road infrastructure management by making it data-driven,
real-time, and more proactive. Instead of relying on periodic manual inspections, authorities
can now receive continuous updates and alerts about road conditions, leading to faster repairs,
better resource allocation, and lower costs for road maintenance. Over time, this could lead to
smarter cities with roads that are continuously monitored and maintained.
2. A live video stream (from a webcam or mobile camera) is given as input.
3. The model processes each frame and highlights potholes with bounding boxes.
5. The detection is shown in real-time through a web browser using a Flask web app.
🧰 Technologies Used
Component Tool / Tech Used Purpose
Storage Local files and logs For storing detections, training logs, etc.
○ Lets the user choose a camera source (webcam, IP camera, iPhone camera)
✅ End Goal
To build an efficient, working system that can: