Add Text to your certificate image in seconds with Django and OpenCV
Tags: django, opencv, webdev, python
Published: 2023-10-04 21:34:09

When dealing with certificates in a Django web application, you may encounter situations where you need to customize and generate certificate images dynamically. Whether it's for personalizing the recipient's name or adding other dynamic information, OpenCV, a popular computer vision library, can be a valuable tool for such tasks. In this tutorial, we'll guide you through the process of updating certificate images using Django and OpenCV.

## Prerequisites

Before we begin, make sure you have the following prerequisites installed:

- Python3
- Django
- OpenCV
- Python Decouple


## Steps

### 1. Create a Virtual Environment and Install Packages

Using a virtual environment is a good practice to isolate your project dependencies. Follow these steps to create one:

**Windows:**
Open Command prompt
```shell
python -m venv venv
venv\Scripts\activate.bat
```

**Linux/Mac**
- Open a terminal window.

```shell
python -m venv venv
source venv/bin/activate
```

Once your virtual environment is activated, install the required packages:

```shell
pip install django opencv-python python-decouple
```

### 2. Create a Django project and app.
Start a new Django project and create an app within it:

```shell
django-admin startproject myproject
cd myproject
python manage.py startapp certificate
```

### 3. Manage Sensitive Information with Environment Variables
To keep sensitive information like secret keys and API tokens secure, use environment variables. Create a **`.env`** file in your project's root directory and add your secrets to it:
```env
# .env

SECRET_KEY=mysecretkey
DEBUG=True
```
In your **`settings.py`** file, use the **`python-decouple`** library to load these environment variables:

```python
# settings.py

from decouple import config

SECRET_KEY = config('SECRET_KEY')
DEBUG = config('DEBUG', default=False, cast=bool)

```

### 4. Configure Media Settings
Django allows you to store user-uploaded files (such as certificate images) using the media files handling system. First, configure your project's media settings in the settings.py file:


```python
# settings.py

import os

# Define the media root and URL for user-uploaded files (e.g., certificate images)
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

```

### 5. Define the Certificate Model
In your **`models.py`** file of the certificate app, define the Certificate model:

```python
from django.db import models

class Certificate(models.Model):
    user_name = models.CharField(max_length=255)
    certificate_image = models.ImageField(upload_to='certificates/')
    timestamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.user_name

```

### 6. Define Views for Generating and Displaying Certificates

**Getting the coordinates of where to update in the template image**
This code allows you to click on the certificate template image to obtain the desired coordinates:
You can save this code as a separate Python script, let's say **`coordinate_selector.py`**. Running this script will allow you to click on the certificate template image to obtain the coordinates

```python
# Import the required libraries
import cv2

# Define a function to display the coordinates of
# the points clicked on the image
def click_event(event, x, y, flags, params):
   if event == cv2.EVENT_LBUTTONDOWN:
      print(f'Coordinates: ({x}, {y})')
      
      # Put coordinates as text on the image
      cv2.putText(img, f'({x}, {y})', (x, y),
                  cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
      
      # Draw a point on the image
      cv2.circle(img, (x, y), 3, (0, 255, 255), -1)

# Read the input image (your certificate template)
img = cv2.imread('path_to_your_certificate_template.png')

# Create a window
cv2.namedWindow('Select Coordinates')

# Bind the callback function to the window
cv2.setMouseCallback('Select Coordinates', click_event)

# Display the image
while True:
   cv2.imshow('Select Coordinates', img)
   k = cv2.waitKey(1) & 0xFF
   if k == 27:  # Press 'Esc' to exit
      break

# Close all OpenCV windows
cv2.destroyAllWindows()
```

Define the views in your **`views.py`** file to handle the generation and display of certificates:


```python
# views.py

from django.shortcuts import render, redirect
from django.core.files.base import ContentFile
import cv2
import os
from django.conf import settings
from .models import Certificate

# Load the template certificate image (save it in the static folder)
template_image = cv2.imread(os.path.join(settings.STATIC_ROOT, 'template.png'))

# Function to update the image with text
def update_certificate_template(template_image, user_name):
    # Make a copy of the template to work on
    template = template_image.copy()
    coords = (x,y) # Replace with coordinate of where to update

    # Define the font, color, and size for the text to be added
    font = cv2.FONT_HERSHEY_SCRIPT_SIMPLEX
    font_color = (0, 0, 0)  # Black color (BGR format)
    font_scale = 1
    thickness = 1
    line_type = cv2.LINE_AA

    # Put the user's name at the specified coordinates
    cv2.putText(template, user_name, coords, font, font_scale, font_color, thickness, lineType=line_type)

    return template

# View for generating and updating certificates
def generate_certificate(request):
    if request.method == 'POST':
        user_name = request.POST['user_name']

        updated_template = update_certificate_template(template_image, user_name)

        # Convert the updated image to a format suitable for saving
        ret, buf = cv2.imencode('.png', updated_template)
        image = ContentFile(buf.tobytes())

        certificate = Certificate(user_name=user_name)
        certificate.certificate_image.save(f"{user_name}.png", image)
        certificate.save()

        return redirect('certificate_display', id=certificate.id)
    else:
        return render(request, 'certificate-form.html')

# View for displaying the updated certificate
def certificate_display(request, id):
    certificate = Certificate.objects.get(id=id)
    return render(request, 'certificate-display.html', {'certificate': certificate})

```
**Note**: Save the template certificate image (e.g., template.png) in the static folder of your Django project. Adjust the path in the code accordingly.


### 7. Define URL Patterns
Configure your URL patterns in the **`urls.py`** file of the **`certificate`** app:

```python
# urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('generate/', views.generate_certificate, name='generate_certificate'),
    path('display/<int:id>/', views.certificate_display, name='certificate_display'),
]

```

### 8. Create a Template for the Form
Create a template file **`certificate-form.html`** in your certificate/templates directory to display the form for users to input their names and submit. Here's an example of the form template:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Generate Certificate</title>
</head>
<body>
    <h1>Generate Certificate</h1>
    <form method="post">
        {% csrf_token %}
        <label for="user_name">Recipient's Name:</label>
        <input type="text" id="user_name" name="user_name" required>
        <br>
        <input type="submit" value="Generate Certificate">
    </form>
</body>
</html>

```
### 9. Create a Template to Display the Updated Image and Enable Download
Create a template file certificate-display.html in your certificate/templates directory to display the updated certificate image with the option to download it. Here's an example of the display template:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Certificate</title>
</head>
<body>
    <h1>Certificate for {{ certificate.user_name }}</h1>
    <img src="{{ certificate.certificate_image.url }}" alt="Certificate">
    <br>
    <a href="{{ certificate.certificate_image.url }}" download="{{ certificate.user_name }}_certificate.png">
        Download Certificate
    </a>
</body>
</html>

```

### 10. Create Database Migrations
Before you can use the Certificate model, create database migrations:

```shell
python manage.py makemigrations certificate
python manage.py migrate
```

### 11. Start the Development Server
Finally, start the Django development server to see your application in action:

```shell
python manage.py runserver
```
Now, you can access your application in a web browser by navigating to http://localhost:8000/generate/. Users can use the provided form to generate customized certificates

## Conclusion
In this tutorial, we've explored how to dynamically update certificate images using Django and OpenCV. By following the steps outlined in this guide, you've learned how to create a Django project, configure media settings, manage sensitive information using environment variables, and create views for generating and displaying personalized certificates.

We also provided developers with a Python code snippet that allows them to select coordinates on the certificate template image, empowering them to precisely specify where they want their names to appear on the certificate.

Customizing and extending this solution is possible to meet various requirements. Depending on your use case, you may want to add more features, error handling, or security measures.

The combination of Django and OpenCV opens up numerous possibilities for generating dynamic content, not limited to certificates alone. You can apply these techniques to various web applications, such as generating personalized images, graphics, or documents.

As you continue to work with Django and OpenCV, you'll find that this powerful combination allows you to create versatile and interactive web applications that can handle a wide range of content generation tasks. Experiment, explore, and have fun with your projects!

We hope this tutorial has been valuable in helping you get started with dynamic certificate generation in Django. If you have any questions or encounter any challenges along the way, don't hesitate to consult Django's documentation or seek assistance from the vibrant Django community.

Happy coding!