5 Best Ways to Draw an Arrowed Line on an Image in OpenCV Python

πŸ’‘ Problem Formulation: You have an image and need to annotate it by drawing an arrowed line to highlight specific areas or to point to something. In OpenCV Python, this can be done through various methods. Imagine you have an image representing a map, and you want to draw an arrow from one city to another to illustrate the route. This article will explain five different ways to achieve this, each with a simple example.

Method 1: Using the cv2.arrowedLine Function

The cv2.arrowedLine() function is the most straightforward method in OpenCV for drawing arrowed lines. It requires the image object, the starting and ending points of the line, the color, the thickness, and additional parameters for the tip length and line type. It’s ideal for quick annotations with minimal coding.

Here’s an example:

import cv2

# Load an image
image = cv2.imread('example.jpg')

# Define the starting and ending points of the arrow line
start_point = (50, 50)
end_point = (200, 200)

# Draw a red arrowed line on the image
color = (0, 0, 255)
thickness = 2
cv2.arrowedLine(image, start_point, end_point, color, thickness)

# Save the output image
cv2.imwrite('arrowed_example.jpg', image)

The output will be the original image with a red arrowed line from point (50, 50) to point (200, 200).

This code snippet loads an image, defines start and end points, and draws a red arrowed line between these points using the cv2.arrowedLine() function. The resultant image is then saved with the new annotation. This function is simple and effective for adding single arrow annotations to an image.

Method 2: Custom Arrow using Polylines

If you need more control over the appearance of the arrow, you can use the combination of cv2.polylines() and cv2.line() to draw a custom arrow. This requires calculation of the arrowhead points and gives you the flexibility to style the arrow as needed.

Here’s an example:

import cv2
import numpy as np

# Load an image
image = cv2.imread('example.jpg')

# Define points for the arrow shaft
points = np.array([[100, 100], [300, 300]], dtype=np.int32)

# Draw the shaft of the arrow
cv2.polylines(image, [points], False, (0, 255, 0), thickness=5)

# Calculate and draw the arrowhead
arrowhead = np.array([[280, 270], [300, 300], [270, 280]], dtype=np.int32)
cv2.fillConvexPoly(image, arrowhead, (0, 255, 0))

# Save the output image
cv2.imwrite('custom_arrow_example.jpg', image)

The output is the original image with a custom green arrow from point (100, 100) to point (300, 300).

This snippet demonstrates how to draw a custom arrow using the cv2.polylines() function for the shaft and the cv2.fillConvexPoly() function for the arrowhead. This method provides customizability in arrow design but requires additional calculations for the arrowhead geometry.

Method 3: Using Matplotlib for Advanced Styling

When you want to add arrows with advanced styling, such as dashed lines or semi-transparent arrows, Matplotlib combined with OpenCV provides a high level of control and customization.

Here’s an example:

import cv2
import matplotlib.pyplot as plt

# Load an image
image = cv2.imread('example.jpg')
BGR_img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # Convert BGR to RGB

# Plot the image
plt.imshow(BGR_img)

# Draw arrowed line with Matplotlib
plt.arrow(100, 100, 50, 50, width=1, head_width=10, head_length=10, fc='yellow', ec='yellow')

# Display the image
plt.show()

The output is the original image displayed with a yellow arrow within a Matplotlib plot.

By using Matplotlib’s plt.arrow() function, this code overlays an arrow on the image. Notice the RGB color format is used in Matplotlib, as opposed to BGR in OpenCV, thus requiring color space conversion before plotting. This approach is well-suited for detailed visualizations that need advanced graphics features.’

Method 4: Combining Arrows and Text Annotations

Sometimes, your visual annotations require both arrows and text. OpenCV facilitates this by allowing you to use cv2.arrowedLine() with cv2.putText() to create comprehensive annotations on your images.

Here’s an example:

import cv2

# Load an image
image = cv2.imread('example.jpg')

# Draw an arrowed line with OpenCV 
start_point = (50, 250)
end_point = (50, 50)
cv2.arrowedLine(image, start_point, end_point, (255, 0, 0), 3)

# Add text with OpenCV
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(image, 'Start', (start_point[0] + 10, start_point[1]), font, 1, (255, 0, 0), 2)

# Save the annotated image
cv2.imwrite('arrow_text_example.jpg', image)

The output is the image with a blue arrowed line and a text label “Start” positioned at the starting point of the arrow.

This snippet loads an image, draws a blue arrow, and pairs it with a text annotation at the starting point, providing context for the arrow drawn on the image. Combining arrows with text can convey more information and context, which is especially useful in educational materials and presentations.

Bonus One-Liner Method 5: Drawing Multiple Arrows with a Loop

For drawing multiple arrowed lines efficiently, you can loop through an array of points with the arrowed lines code in OpenCV. This method is perfect when you have several annotations to make on an image.

Here’s an example:

import cv2

# Load an image
image = cv2.imread('example.jpg')

# Points for multiple arrowed lines
arrow_points = [((10, 10), (100,100)), ((200, 50), (300, 50))]

# Draw multiple arrowed lines with a loop
for start, end in arrow_points:
    cv2.arrowedLine(image, start, end, (255, 255, 0), 3)

# Save the output image
cv2.imwrite('multiple_arrows_example.jpg', image)

The output is the image with multiple arrowed lines connecting each pair of points specified in the arrow_points array.

By defining pairs of coordinates in the arrow_points list and iterating through them, multiple arrows are drawn on the image with minimal code. This one-liner approach inside a loop is time-saving when dealing with numerous annotations.

Summary/Discussion

  • Method 1: cv2.arrowedLine(). Straightforward and fast. Limited in customization.
  • Method 2: Custom Arrow using Polylines. Full control over arrow shape and style. Requires manual calculations and more code.
  • Method 3: Using Matplotlib for Advanced Styling. Offers advanced graphics features. Involves additional steps and libraries.
  • Method 4: Combining Arrows and Text Annotations. Context-rich annotations. Slightly more complex due to text positioning.
  • Method 5: Drawing Multiple Arrows with a Loop. One-liner within a loop for simplicity. Efficient for multiple annotations but simplistic.