To deploy the road damage segmentation web application, some environment configuration steps need to be performed. Below are the details on how to configure the environment and install the required libraries for the application.
5.2.1. Install Python environment and necessary libraries
The application uses Python combined with Flask to build the web interface and YOLO to segment damage on images and videos. To deploy, it is necessary to install some important libraries as follows:
We use Terminal >>>
pip install flask
pip install ultralytics
pip install opencv-python
pip install pillow
pip install werkzeug
pip install numpy
- Flask: A web framework used to build applications, handle requests from users, and manage file uploads.
- Ultralytics (YOLO): This is a library that helps load and use the YOLO model to detect damage.
- OpenCV (Open Source Computer Vision Library): Used for image and video processing, including operations such as reading video files, drawing rectangles around objects, and saving video frames.
- Pillow: This library supports image processing, allowing opening and editing image files, such as adding blur effects to damage.
- Werkzeug: This library provides tools to support uploading image or video files from the user side.
- NumPy (Numerical Python): This is a library that helps perform array operations, which are essential in image and video processing.
5.2.2. Configure Flask application environment
After installing the necessary libraries, the next step is to configure the environment for the Flask application. The upload and output directories need to be set up so that it is easy to manage temporary files and output files.
- Configuring the upload and output directories: User uploads will be stored in the static/uploads/ directory, while segmented output will be stored in the static/Output/ directory. To ensure that these directories always exist, we need to add code to create them if they do not already exist:
os.makedirs(UPLOAD_FOLDER, exist_ok=True) os.makedirs(OUTPUT_FOLDER, exist_ok=True)
- Upload file size limit: To prevent uploading files that are too large and may affect system performance, we will limit the upload file size (50MB):
app.config['MAX_CONTENT_LENGTH'] = 50 * 1024 * 1024 5.2.3. YOLO model configuration
The application uses the YOLO model to detect and segment damage in images and videos. The YOLO model will be loaded and used throughout the image and video analysis process. The steps to install the YOLO model include:
- Loading the YOLO model: To use YOLO, we need to load the pre-trained model. The following code snippet helps to load the YOLO model from a specific path:
def load_model(model_path='models/best.pt'):
try:
model = YOLO(model_path) return model
except Exception as e:
print(f"Error loading model: {e}") return None
- Model Path: The trained YOLO model needs to be stored in the models/
folder. When the model is loaded, the system will use this model to recognize damage in images or videos.
5.2.4. Image and video processing
The application requires image and video processing to detect and segment the damage. The processing steps include:
- Image processing: When the user uploads an image, the YOLO model will be used to detect and segment the damage. The results will be saved with blur effects and color overlays for the damage.
def process_image(filepath, output_path):
try:
# Run YOLO model results = model(filepath)
# Open original image
image = Image.open(filepath).convert('RGB') draw = ImageDraw.Draw(image)
# Process each detection
for result in results[0].boxes.xywh.cpu().numpy():
x_center, y_center, width, height = result[:4]
x1 = int((x_center - width / 2) * image.width) y1 = int((y_center - height / 2) * image.height) x2 = int((x_center + width / 2) * image.width) y2 = int((y_center + height / 2) * image.height)
# Apply effects for road damage (class 0) if result[-1] == 0:
region = image.crop((x1, y1, x2, y2))
blurred_region = region.filter(ImageFilter.GaussianBlur(5)) image.paste(blurred_region, (x1, y1, x2, y2))
# Process segmentation masks if results[0].masks is not None:
for i, mask in enumerate(results[0].masks.data.cpu().numpy()):
if results[0].boxes.cls[i] == 0:
mask_image = Image.fromarray((mask * 255).astype('uint8')) mask_image = mask_image.resize((image.width, image.height)) mask_color = Image.new('RGB', image.size, (255, 0, 0))
mask_image = mask_image.filter(ImageFilter.GaussianBlur(5)) image = Image.composite(mask_color, image,
mask_image.convert('L'))
image.save(output_path)
print(f"Saved output image at: {output_path}") except Exception as e:
print(f"Error processing image: {e}")
- Video Processing: Similar to images, when a user uploads a video, each frame in the video is processed using the YOLO model. The detected objects are boxed and marked, and then saved as a segmented video.
def process_video(input_path, output_path):
try:
cap = cv2.VideoCapture(input_path) if not cap.isOpened():
print("Error: Cannot open video file.") return
fourcc = cv2.VideoWriter_fourcc(*'avc1') # H.264 codec for better browser support
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
while cap.isOpened():
ret, frame = cap.read() if not ret:
break
# Run YOLO model results = model(frame)
# Process bounding boxes and masks
for box, conf, cls, mask in zip(results[0].boxes.xyxy.cpu().numpy(), results[0].boxes.conf.cpu().numpy(),
results[0].boxes.cls.cpu().numpy(), (results[0].masks.data.cpu().numpy() if results[0].masks is not None else [])):
x1, y1, x2, y2 = map(int, box) confidence = conf
class_label = "Pothole" if int(cls) == 0 else f"Class {int(cls)}"
# Draw rectangle
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 2)
# Add label
label = f"{class_label} {confidence:.2f}"
label_size, _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
label_bg = (x1, y1 - label_size[1] - 5, x1 + label_size[0] + 5, y1) cv2.rectangle(frame, (label_bg[0], label_bg[1]), (label_bg[2], label_bg[3]), (0, 0, 255), -1)
cv2.putText(frame, label, (x1, y1 - 5),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
# Apply mask for class 0 (Pothole) if int(cls) == 0 and mask is not None:
mask_resized = cv2.resize(mask, (frame.shape[1], frame.shape[0]))
mask_binary = (mask_resized > 0.5).astype(np.uint8)
# Create colored overlay for the mask
red_overlay = np.zeros_like(frame, dtype=np.uint8)
red_overlay[:, :, 2] = mask_binary * 255 # Set red channel
# Blend mask with frame
frame = cv2.addWeighted(frame, 1, red_overlay, 0.5, 0)
# Write the frame to the output video out.write(frame)
cap.release() out.release()
print(f"Saved output video at: {output_path}")
# Convert the processed video to ensure it's browser-compatible convert_video_to_h264(output_path, output_path)
except Exception as e:
print(f"Error processing video: {e}")
5.2.5. Configure Flask application to run on localhost
Finally, to deploy the web application, Flask will be configured to run on localhost with port 5001. The code below will get the Flask application up and ready to serve HTTP requests from users:
if __name__ == "__main__":
app.run(port=5001, debug=True, use_reloader=False)
Once the application is running, you can access the web application at http://127.0.0.1:5001 to upload images or videos and view the segmentation results.