#002 How to draw lines, rectangles, circles and write text on images with OpenCV in Python?

#002 How to draw lines, rectangles, circles and write text on images with OpenCV in Python?

Highlight: Hello and welcome back to our Hacking OpenCV series in Python. In this post we are going to explain how to draw basic and more advanced shapes, as well as how to write text on images. You will learn to draw lines, rectangles, circles, ellipses, polylines and how to write a textual content on the image. This knowledge will be very useful later on when we start to develop our facial recognition algorithms with OpenCV. For example, when we need to draw a rectangle highlighting the detected faces in the processed image.

OpenCV provides a large number of functions to draw basic shapes in different colors. Now, let’s see how to draw some lines, rectangles and circles.

Tutorial overview:

  1. How to draw lines, rectangles and circles?
  2. How to draw arrows, polygons and ellipses?
  3. How to write a text with OpenCV in Python?

1. How to draw lines, rectangles and circles?

How to draw lines?

The first function that we are going to check out is cv2.line(). This function draws a line on our image by connecting two coordinate points. As we can see in the following example, in our code we need to define coordinates of these points and the thickness and color arguments. 

First, we are going to create our image:

# Necessary imports
import cv2
import numpy as np
import matplotlib.pyplot as plt
# Necessary import if we are working in Google Colab. Otherwise, 
# if will use cv2.imshow(), this import is not required. 
from google.colab.patches import cv2_imshow
# Creating our black image with coordinates (500,500)
img = np.zeros((500, 500, 3), dtype="uint8")
cv2_imshow(img)

Output:

Now, we will provide code for drawing multiple lines on the picture with different coordinates, colors and widths.

# Changing the color of the image
img[:] = (255,255,255)
# Drawing a black line
cv2.line(img, (0,0), (500,500), (0,0,0), (10))
# Drawing a blue line
cv2.line(img, (0,500), (500,0), (255,0,0), (20))
# Drawing a red line
cv2.line(img, (0,250), (250,0), (0,0,255), (5))
# Drawing a green line
cv2.line(img, (500,250), (0,250), (0,255,0), (30))
# Drawing a yellow line
cv2.line(img, (500,250), (250,500), (0,200,200), (10))
# Drawing a violet line
cv2.line(img, (250,0), (500,250), (200,50,100), (10))
# Drawing a cyan line
cv2.line(img, (0,250), (250,500), (255,255,0), (15))
# Drawing a orange line
cv2.line(img, (250,0), (250,500), (0,100,255), (10))

cv2_imshow(img)

Output:

OpenCV, Python, line

How to draw rectangles?

The function that draws a rectangle is cv2.rectangle(). Our rectangle is defined with two points in two opposite corners. The first one is at the top left corner and the second one is at the bottom right corner. It is good to remember that negative values for the thickness parameter, will give us a filled shape as our output.

# Drawing a green rectangle
cv2.rectangle(img, (100,100), (300,300), (0,255,0), (20))
# Drawing a blue rectangle
cv2.rectangle(img, (200,100), (400,300), (255,0,0), (10))
# Drawing a red rectangle. Negative parameter -1
# indicates that we want to draw filled shape
cv2.rectangle(img, (100,350), (400,400), (0,0,255), (-1))
# Drawing a yellow rectangle
cv2.rectangle(img, (20,100), (80,300), (0,200,200), (5))
# Drawing a violet rectangle
cv2.rectangle(img, (420,50), (450,450), (200,50,100), (-1))
cv2_imshow(img)

Output:

OpenCV, Python, rectangle

How to draw draw circles?

To draw a circle we apply a function cv2.circle(). This function draws a circle on the image and as parameters we need to define the center and a radius of our circle. Negative values for the thickness parameter, will give us a filled shape as our output.

# Drawing a red circle. Negative parameter -1
# indicates that we want to draw filled shape
cv2.circle(img, (250,250), 150, (0,0,255), (-1))
# Drawing a blue circle
cv2.circle(img, (70,70), 50, (255,0,0), (5))
# Drawing a green circle
cv2.circle(img, (430,430), 50, (0,255,0), (10))
cv2_imshow(img)

Output:

OpenCV, Python, circle

2. How to draw arrows, polygons and ellipses?

In this chapter, we are going to see how to draw some more advanced shapes like arrows, ellipses, clip lines, and polygons.

How to draw an arrow?

For drawing arrows, we are going to use the function cv2.arrowedLine(). This function is similar to the previous one with the addition of a new argument that represents the tip length, as we can see in the following example.

# Creating our image
img = np.zeros((500, 500, 3), dtype="uint8")
# Drawing a red arrow
cv2.arrowedLine(img, (100,100), (400,100), (0,0,255), (10), 8,0,0.1)
# Drawing a blue arrow
cv2.arrowedLine(img, (100,200), (400,200), (255,0,0), (20), 8,0,0.3)
# Drawing a green arrow
cv2.arrowedLine(img, (400,300), (100,300), (0,255,0), (5), 8,0,0.4)
cv2_imshow(img)

Output:

OpenCV, Python, arrows

How to draw an ellipse?

Here, we will use the function cv2.ellipse() which allows us to draw an ellipse. We just need to add a few arguments like axes, angle, start angle, and end angle. Parameter “angle” defines the angle of the ellipse relative to the coordinates. If an angle is 0 Parameters “startAngle” and “endAngle” define the elliptic arc. That means that if “startAngle” is \(0^{\circ} \) and “endAngle” is \(360^{\circ} \), we will get a closed ellipse.

# Drawing a red ellipse. Negative parameter -1
# indicates that we want to draw a filled shape.
cv2.ellipse(img, (250,250), (90,50), 0, 0, 360, (0,0,255), (-1))
# Drawing a blue ellipse.
cv2.ellipse(img, (120,120), (100,70), 0,0,360, (255,0,0), (20))
# Drawing a green ellipse.
cv2.ellipse(img, (400,300), (30,140),0,0,360, (0,255,0), (3))
# Drawing a yellow one. If we have same values for the axes
# we can draw a circle   
cv2.ellipse(img, (80,400), (60,60), 0, 0, 360, (0,200,200), (6))
# Drawing a white ellipse with an angle of 45 degrees
cv2.ellipse(img, (250,380), (60,40), 45,0,360, (255,255,255), (10))
# Drawing a violet ellipse with an end angle of 270 degrees
cv2.ellipse(img, (300,80), (60,40),0,0,270, (200,50,100), (3))
cv2_imshow(img)

Output:

OpenCV, Python, elipse

How to draw a clip line?

In some cases we want to draw a line painted with different colors for different parts of an image. In such a case it is convenient to use a line that is clipped against the rectangle. First thing that we need to do is create our rectangle and line. Next, we will use the function cv2.clipLine(). This function will return the segment defined by the first and the second point inside the rectangle. If both points are inside the rectangle, function returns “True” and line will change its color. We can better understand this if we check out the code below.

# Drawing a line
cv2.line(img, (0, 0), (500, 500), (255,0,0), 3)
# Drawing a rectangle
cv2.rectangle(img, (0, 0), (150, 150), (0,0,255), 3)
# Function cv2.clipLine clips the segment against the defined rectangle
# We defining pt1 and pt2 (segment inside rectangle) 
# and starting and ending point of our line
ret, p1, p2 = cv2.clipLine((0, 0, 150, 150), (0, 0), (500, 500))
if ret:
  cv2.line(img,p1,p2,(0,255,0),3)
cv2_imshow(img)

Output:

OpenCV, Python, clip line

How to draw polygons?

Now we will learn how to draw polygons. Here we will use the function cv2.polylines() which allows us to create polygonal curves. The most important parameter that we need to create here is an array of points which defines our polygonal curve. Then, the function cv2.polylines()will connect these points starting at the first point that we have defined. An important parameter here is isClosed. It is a boolean data type which will optionally close the polygon. If we put “True”, the function will connect last dot to first. Otherwise the result will be an opened polygon.

# Creating a Numpy array of points
pts = np.array([[50, 250], [150, 100], [250, 250],[100,400],[200,400]], np.int32)
# Creating a yellow polygon. Parameter "False" indicates
# that our line is not closed
cv2.polylines(img, [pts], False, (0,200,200), 3)
cv2_imshow(img)

Output:

OpenCV, Python, polygon

Now lets create a few more polygons.

# Creating a Numpy array of points
pts = np.array([[50, 250], [150, 100], [250, 250],[100,400],[200,400]], np.int32)
# Creating a yellow polygon. Parameter "False" indicates
# that our line is not closed
cv2.polylines(img, [pts], False, (0,200,200), 3)
# Creating an array of points
pts = np.array([[350, 200], [400, 150], [450, 200],[430,250],[370,250]], np.int32)
# Creating a red pentagon
cv2.polylines(img, [pts], True, (0,0,255), 5)
# Creating an array of points
pts = np.array([[350, 80], [400, 120], [450, 80]], np.int32)
# Creating a blue triangle
cv2.polylines(img, [pts], True, (255,0,0), 8)
# Creating an array of points
pts = np.array([[200,50], [300, 50], [300, 150],[200,150]], np.int32)
# Creating a green rectangle
cv2.polylines(img, [pts], True, (0,255,0), 10)
# Creating an array of points
pts = np.array([[300, 300], [400, 300], [300, 400],[400,400]], np.int32)
# # Creating a violet polygon
cv2.polylines(img, [pts], True, (200,50,100), 3)
cv2_imshow(img)

Output:

OpenCV, Python, polygons

3. How to write text with OpenCV in Python?

Writing text on images is absolutely essential for image processing. So lets learn how to do this.

First, we need to have several parameters. Second, we need to define our font type. OpenCV uses several font types. Here, you can see all the available fonts in OpenCV.

  1. FONT_HERSHEY_SIMPLEX
  2. FONT_HERSHEY_PLAIN
  3. FONT_HERSHEY_DUPLEX
  4. FONT_HERSHEY_COMPLEX
  5. FONT_HERSHEY_TRIPLEX
  6. FONT_HERSHEY_COMPLEX_SMALL
  7. FONT_HERSHEY_SCRIPT_SIMPLEX
  8. FONT_HERSHEY_SCRIPT_COMPLEX

Once we pick our font type, we can move on. The function that we are going to use is cv2.putText(). After adding some arguments like the starting point( provided text string stars at the upper-left corner), size, color and the line type of our text, we are ready to go. Last provided parameter, is line type. There are three available line types in OpenCV (cv2.LINE_4, cv2.LINE_8, cv2.LINE_AA).

# Choosing our font
font=cv2.FONT_ITALIC
# Writing our text
cv2.putText(img,"OpenCV with Python!", (90,250), font, 1, (255,255,255), 3, cv2.LINE_AA)
cv2_imshow(img)

Output:

OpenCV, Python, text

Now, let’s have a little fun and try to recreate our Datahacker.rs logo.

# Creating our image
img = np.zeros((400, 400, 3), dtype="uint8")
img[:] = (255,255,255)
# Creating "Datahacker" logo
cv2.rectangle(img, (76,76), (324,300), (0,0,0), (2))
font=cv2.FONT_ITALIC
font2=cv2.FONT_HERSHEY_PLAIN
cv2.putText((img),"H A C K E R", (100,350), font, (1), (0,0,0), 2, cv2.LINE_AA)
cv2.putText((img),"D", (120,162), font2, (5), (0,0,0), 5, cv2.LINE_AA)
cv2.putText((img),"T", (120,264), font2, (5), (0,0,0), 5, cv2.LINE_AA)
cv2.putText((img),"A", (240,164), font2, (5), (0,0,0), 5, cv2.LINE_AA)
cv2.putText((img),"A", (240,264), font2, (5), (0,0,0), 5, cv2.LINE_AA)
cv2_imshow(img)

Output:

If we want to create a GIF out of this logo, we will use the following code:

# Creating the images
img = np.zeros((400, 400, 3), dtype="uint8")
img[:] = (255,255,255)
plt.imshow(img)
cv2.rectangle(img, (76,76), (324,300), (0,0,0), (2))
font=cv2.FONT_ITALIC
font2=cv2.FONT_HERSHEY_PLAIN

cv2.putText((img),"D", (120,162), font2, (5), (0,0,0), 5, cv2.LINE_AA)
plt.axis("off")
# Ploting the image that we are created
plt.imshow(img)
# Saving an image that we are created 
# Dots per inch (dpi) is resolution that we chose
plt.savefig("d_001.jpg", dpi = 800)

cv2.putText((img),"A", (240,164), font2, (5), (0,0,0), 5, cv2.LINE_AA)
plt.axis("off")
plt.imshow(img)
plt.savefig("d_002.jpg", dpi = 800)
cv2.putText((img),"T", (120,264), font2, (5), (0,0,0), 5, cv2.LINE_AA)
plt.axis("off")
plt.imshow(img)
plt.savefig("d_003.jpg", dpi = 800)

cv2.putText((img),"A", (240,264), font2, (5), (0,0,0), 5, cv2.LINE_AA)
plt.axis("off")
plt.imshow(img)
plt.savefig("d_004.jpg", dpi = 800)

cv2.putText((img),"H A C ", (100,350), font, (1), (0,0,0), 2, cv2.LINE_AA)
plt.axis("off")
plt.imshow(img)
plt.savefig("d_005.jpg", dpi = 800)


cv2.putText((img),"H A C K E R", (100,350), font, (1), (0,0,0), 2, cv2.LINE_AA)
plt.axis("off")
plt.imshow(img)
plt.savefig("d_006.jpg", dpi = 800)
# This will load saved .jpg files and create a gif animation
import os
import imageio

png_dir = '../content'
images = []
for file_name in sorted(os.listdir(png_dir)):
  print(file_name)                            
  if file_name.endswith('.jpg'):
    file_path = os.path.join(png_dir, file_name)
    images.append(imageio.imread(file_path))
imageio.mimsave('../content/movie1.gif', images, fps = 1)

Output:

Summary

In this post, we learned how to draw shapes and write text with OpenCV in Python. We explained how to draw very basic shapes like lines, rectangles and circles and some more advanced shapes like ellipsis, arrows and polygons. In the next post we are going to cover basic image processing techniques like resizing, flipping, translating and rotating images with OpenCV in Python.

References:

[1] Drawing and Writing on Image – OpenCV with Python for Image and Video Analysis 3

[2] Mastering OpenCV 4 with Python by Alberto Fernández Villán