Creating Artistic Outlines: Combining Python, OpenCV, and Turtle Graphics

SHREERAJ
EpochIIITS
Published in
5 min readJun 30, 2024

Artists and developers alike often seek new ways to blend technology with creativity. Python’s versatility allows us to merge image processing techniques with interactive graphics, enabling us to automate complex tasks while retaining artistic expression. In this tutorial, we’ll delve into the process of outlining images programmatically, using techniques that are both educational and visually appealing.

Step-by-Step Process

Setting Up the Environment and Installing Dependencies

To ensure a clean and organized setup for our project, follow these steps to create a directory, set up a virtual environment, and install the required Python packages:

1. Create a Project Directory:
— Open your terminal or command prompt.
— Create a new directory for your project:


mkdir artistic_outlines_project
cd artistic_outlines_project

2. Set Up a Virtual Environment:
— Using `venv`, create a virtual environment for isolating project dependencies:


python -m venv venv

- Activate the virtual environment. Note that commands vary based on your operating system:

Windows:

venv\Scripts\activate

MacOS / Linux:

source venv/bin/activate

3. Install Required Packages:
— With the virtual environment activated, install the necessary Python packages:


pip install numpy matplotlib opencv-python turtle

- Package Explanation:
`numpy`: Essential for numerical operations and array manipulations.
`matplotlib`: Used for visualizing the processed image.
`opencv-python`: Provides image processing capabilities, including Gaussian blur and adaptive thresholding.
`turtle`: Implements interactive graphics for drawing the image outline.

Directory Structure

After setting up, your directory structure should look like this:


artistic_outlines_project/

├── venv/
│ ├── Include/
│ ├── Lib/
│ ├── Scripts/
│ └── …

├── 1.png
├── outline_image.py
├── processed_image.png
  • `venv/`: Virtual environment directory.
    - `1.png`: Input image for processing.
    - `outline_image.py`: Python script containing the outline generation and drawing code.

Running the Python Script:
— Execute the script to generate the outline and draw it using Turtle graphics:


python outline_image.py

Exploring the Code in outline_image.py

Step 1: Loading and Preparing the Image

Firstly, we load an image (1.png) using OpenCV (cv2) and convert it to grayscale. Grayscale images simplify processing while retaining essential details for our outline generation.

import cv2
image = './1.png'
im = cv2.imread(image, 0)

Explanation:
- `cv2.imread(image, 0)`: This function loads the image specified by `image` into a NumPy array in grayscale mode (`0` parameter). Grayscale images are single-channel images where pixel values represent intensity levels ranging from 0 (black) to 255 (white).

Step 2: Creating an Outline with OpenCV

To highlight the edges of the image, we apply Gaussian blur and adaptive thresholding. This technique effectively isolates the contours and prepares the image for subsequent processing.

def outline():
src_image = cv2.imread(image, 0)
blurred = cv2.GaussianBlur(src_image, (7, 7), 0)
th3 = cv2.adaptiveThreshold(
blurred,
maxValue=255,
adaptiveMethod=cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
thresholdType=cv2.THRESH_BINARY,
blockSize=9,
C=2
)
return th3

th3 = outline()

Explanation:
- `cv2.GaussianBlur()`: Applies Gaussian smoothing to `src_image` with a kernel size of `(7, 7)`. This reduces noise and ensures smoother edges in the resulting image.
- `cv2.adaptiveThreshold()`: Applies adaptive thresholding to the blurred image (`blurred`). Adaptive thresholding calculates thresholds for small image regions, which helps in dealing with varying illumination.

Step 3: Visualizing the Processed Image

Using Matplotlib, we visualize the outlined image (`th3`) to ensure our processing has captured the desired outlines effectively.

from matplotlib import pyplot as plt
plt.imshow(th3)
plt.axis('off')
plt.tight_layout()
plt.savefig('./processed_image.png')

Explanation:
- `plt.imshow(th3)`: Displays the processed image (`th3`) using Matplotlib.
- `plt.axis(‘off’)`: Turns off the axis labels for a cleaner display.
- `plt.tight_layout()`: Adjusts subplot parameters to give specified padding.
- `plt.savefig(‘./processed_image.png’)`: Saves the displayed image as `processed_image.png`.

Step 4: Implementing Turtle Graphics

With the outline prepared, we transition to Turtle graphics. Turtle graphics provides an interactive canvas where we can programmatically trace the outlines of the image, akin to drawing with a pen on paper.

import turtle
import numpy as np
import time

# Initialize turtle screen
screen = turtle.Screen()

# Extract width and height of the image
WIDTH = im.shape[1]
HEIGHT = im.shape[0]

# Define a cutoff length for drawing segments
CUTOFF_LEN = ((WIDTH + HEIGHT) / 2) / 60 # Adjust as needed

# Convert image outline to coordinates
iH, iW = np.where(th3 == [0])
iW = iW - WIDTH / 2
iH = -1 * (iH - HEIGHT / 2)
positions = [list(iwh) for iwh in zip(iW, iH)]

# Initialize turtle properties
turtle.tracer(0)
t = turtle.Turtle()
t.color("brown")
t.shapesize(1)
t.pencolor("gray30")
t.speed(0)

# Move to the starting position
t.penup()
t.goto(positions[0])
t.pendown()

# Draw the outline
p = positions[0]
while p:
p = find_closest(p)
if p:
current_pos = np.asarray(t.pos())
new_pos = np.asarray(p)
length = np.linalg.norm(new_pos - current_pos)
if length < CUTOFF_LEN:
t.goto(p)
turtle.update()
else:
t.penup()
t.goto(p)
t.pendown()
positions.remove(p)
else:
p = None

# Keep the turtle window open
screen.mainloop()

Explanation:
- Turtle Graphics Setup:
`turtle.Screen()`: Initializes the turtle graphics screen, providing an interactive canvas for drawing.
`WIDTH = im.shape[1]`, `HEIGHT = im.shape[0]`: Extracts the width and height of the grayscale image (`im`) using NumPy arrays.
`CUTOFF_LEN`: Defines a threshold length for drawing segments, ensuring smooth and connected outlines.

- Drawing with Turtle:
`turtle.tracer(0)`: Turns off animation to improve drawing performance (`0` means no animation).
`turtle.update()`: Updates the screen after drawing to show changes.
`t.penup()`, `t.pendown()`, `t.goto()`: Turtle methods to control the pen state (up or down) and move to specific coordinates (`goto()`).

Left Side (1.png) Right Side (processed_image.png)

Real-Life Applications

Imagine applying this technique to enhance photographs for artistic purposes or to generate stylized images for educational materials. By combining image processing algorithms with interactive graphics, developers can create unique visual experiences that blend creativity with computational efficiency.

In conclusion, Python, OpenCV, and Turtle graphics provide a dynamic platform for exploring digital artistry through automated image processing and interactive visualization. This tutorial serves as a starting point to inspire further exploration and innovation in the intersection of technology and artistic expression.

By following these steps and understanding the underlying concepts, you can begin creating your own digital masterpieces using Python’s rich ecosystem of tools and libraries.

Resources

Author : M ShreeRaj (shreeraj.m22@iiits.in)

--

--