DEV Community

Cover image for Implementing Edge Detection with Python and OpenCV: A Step-by-Step Guide
Chidozie Managwu
Chidozie Managwu

Posted on

Implementing Edge Detection with Python and OpenCV: A Step-by-Step Guide

Introduction

Edge detection is fundamental in computer vision, allowing us to identify object boundaries within images. In this tutorial, we'll implement edge detection using the Sobel operator and the Canny edge detector with Python and OpenCV. We'll then create a simple web application using Flask, styled with Bootstrap, to allow users to upload images and view the results.

DEMO LINK: Edge Detection Demo

Prerequisites

  • Python 3.x installed on your machine.
  • Basic knowledge of Python programming.
  • Familiarity with HTML and CSS is helpful but not required.

Setting Up the Environment

1. Install Required Libraries

Open your terminal or command prompt and run:

pip install opencv-python numpy Flask
Enter fullscreen mode Exit fullscreen mode

2. Create the Project Directory

mkdir edge_detection_app
cd edge_detection_app
Enter fullscreen mode Exit fullscreen mode

Implementing Edge Detection

1. The Sobel Operator

The Sobel operator calculates the gradient of image intensity, emphasizing edges.

Code Implementation:

import cv2

# Load the image in grayscale
image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)
if image is None:
    print("Error loading image")
    exit()

# Apply Sobel operator
sobelx = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=5)  # Horizontal edges
sobely = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=5)  # Vertical edges
Enter fullscreen mode Exit fullscreen mode

2. The Canny Edge Detector

The Canny edge detector is a multi-stage algorithm for detecting edges.

Code Implementation:

# Apply Canny edge detector
edges = cv2.Canny(image, threshold1=100, threshold2=200)
Enter fullscreen mode Exit fullscreen mode

Creating a Flask Web Application

1. Set Up the Flask App

Create a file named app.py:

from flask import Flask, request, render_template, redirect, url_for
import cv2
import os

app = Flask(__name__)

UPLOAD_FOLDER = 'static/uploads/'
OUTPUT_FOLDER = 'static/outputs/'

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['OUTPUT_FOLDER'] = OUTPUT_FOLDER

# Create directories if they don't exist
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(OUTPUT_FOLDER, exist_ok=True)
Enter fullscreen mode Exit fullscreen mode

2. Define Routes

Upload Route:

@app.route('/', methods=['GET', 'POST'])
def upload_image():
    if request.method == 'POST':
        file = request.files.get('file')
        if not file or file.filename == '':
            return 'No file selected', 400
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
        file.save(filepath)
        process_image(file.filename)
        return redirect(url_for('display_result', filename=file.filename))
    return render_template('upload.html')
Enter fullscreen mode Exit fullscreen mode

Process Image Function:

def process_image(filename):
    image_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
    image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

    # Apply edge detection
    sobelx = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=5)
    edges = cv2.Canny(image, 100, 200)

    # Save outputs
    cv2.imwrite(os.path.join(app.config['OUTPUT_FOLDER'], 'sobelx_' + filename), sobelx)
    cv2.imwrite(os.path.join(app.config['OUTPUT_FOLDER'], 'edges_' + filename), edges)
Enter fullscreen mode Exit fullscreen mode

Result Route:

@app.route('/result/<filename>')
def display_result(filename):
    return render_template('result.html',
                           original_image='uploads/' + filename,
                           sobelx_image='outputs/sobelx_' + filename,
                           edges_image='outputs/edges_' + filename)
Enter fullscreen mode Exit fullscreen mode

3. Run the App

if __name__ == '__main__':
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode

Styling the Web Application with Bootstrap

Include Bootstrap CDN in your HTML templates for styling.

1. upload.html

Create a templates directory and add upload.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Edge Detection App</title>
    <!-- Bootstrap CSS CDN -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <h1 class="text-center mb-4">Upload an Image for Edge Detection</h1>
        <div class="row justify-content-center">
            <div class="col-md-6">
                <form method="post" enctype="multipart/form-data" class="border p-4">
                    <div class="form-group">
                        <label for="file">Choose an image:</label>
                        <input type="file" name="file" accept="image/*" required class="form-control-file" id="file">
                    </div>
                    <button type="submit" class="btn btn-primary btn-block">Upload and Process</button>
                </form>
            </div>
        </div>
    </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

2. result.html

Create result.html in the templates directory:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Edge Detection Results</title>
    <!-- Bootstrap CSS CDN -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <h1 class="text-center mb-5">Edge Detection Results</h1>
        <div class="row">
            <div class="col-md-6 mb-4">
                <h4 class="text-center">Original Image</h4>
                <img src="{{ url_for('static', filename=original_image) }}" alt="Original Image" class="img-fluid rounded mx-auto d-block">
            </div>
            <div class="col-md-6 mb-4">
                <h4 class="text-center">Sobel X</h4>
                <img src="{{ url_for('static', filename=sobelx_image) }}" alt="Sobel X" class="img-fluid rounded mx-auto d-block">
            </div>
            <div class="col-md-6 mb-4">
                <h4 class="text-center">Canny Edges</h4>
                <img src="{{ url_for('static', filename=edges_image) }}" alt="Canny Edges" class="img-fluid rounded mx-auto d-block">
            </div>
        </div>
        <div class="text-center mt-4">
            <a href="{{ url_for('upload_image') }}" class="btn btn-secondary">Process Another Image</a>
        </div>
    </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Running and Testing the Application

1. Run the Flask App

python app.py
Enter fullscreen mode Exit fullscreen mode

2. Access the Application

Open your web browser and navigate to http://localhost:5000.

  • Upload an image and click Upload and Process.
  • View the edge detection results.

SAMPLE RESULT

Image description

Conclusion

We've built a simple web application that performs edge detection using the Sobel operator and the Canny edge detector. By integrating Python, OpenCV, Flask, and Bootstrap, we've created an interactive tool that allows users to upload images and view edge detection results.

Next Steps

  • Enhance the Application: Add more edge detection options or allow parameter adjustments.
  • Improve the UI: Incorporate more Bootstrap components for a better user experience.
  • Explore Further: Deploy the app on other platforms like Heroku or AWS.

GitHub Repository: Edge Detection App

Top comments (1)

Collapse
 
damiklef profile image
damiklef

Newbies like us are glad to have people like you to learn from, thank you sir.

Love the project.