5 Best Ways to Display the Coordinates of Points Clicked on an Image in OpenCV Python

πŸ’‘ Problem Formulation: When working with images in OpenCV using Python, developers often need to interact with the image through clicks to obtain the coordinates of points of interest for further processing or analysis. This article presents solutions for capturing user clicks on an image window and displaying the pixel coordinates (X, Y) in OpenCV. For example, given an image presented in a window, the desired output would display the (X, Y) coordinates when the user clicks on the image.

Method 1: Basic Callback Function Using OpenCV’s setMouseCallback

OpenCV provides a function setMouseCallback that allows you to define a callback to be executed whenever a mouse event happens. For displaying coordinates of points clicked on an image, a simple callback function can be created within Python to print these details to the console.

Here’s an example:

import cv2

def click_event(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        print('Mouse Clicked at:', x, y)

cv2.namedWindow('image')
cv2.setMouseCallback('image', click_event)

img = cv2.imread('image.jpg')
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Output:

Mouse Clicked at: X Y

This code snippet sets up a window named ‘image’ and binds a click event function to it. Whenever the left mouse button is clicked inside the image window, the click_event function is called, printing to the console the position where the mouse was clicked, in the form of X and Y coordinates.

Method 2: Adding Coordinates as Text on the Image

Rather than printing the coordinates to the console, you could also display them directly on the image using OpenCV’s text drawing capabilities. This provides a visual feedback on the image itself which can be very useful for presentations or further image processing.

Here’s an example:

import cv2

def click_event(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        cv2.putText(img, str(x) + ',' + str(y), (x, y), cv2.FONT_HERSHEY_COMPLEX,
                    0.5, (255, 0, 0), 1)
        cv2.imshow('image', img)

img = cv2.imread('image.jpg')
cv2.imshow('image', img)
cv2.setMouseCallback('image', click_event)
cv2.waitKey(0)
cv2.destroyAllWindows()

The function putText is used to draw the coordinates directly on the image. It takes parameters such as the image, the text to display, bottom-left corner of the text in the image, font type, font scale, color, and thickness.

Method 3: Using a Global List to Store the Clicked Points

For applications that require handling multiple points, storing the coordinates in a global list becomes handy. You can then use the list for other purposes such as drawing or analysis.

Here’s an example:

import cv2

points = []

def click_event(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        points.append((x, y))
        print('Added to list:', points)

cv2.namedWindow('image')
cv2.setMouseCallback('image', click_event)

img = cv2.imread('image.jpg')
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

This code prints and stores each clicked point into a list called points. After the window is closed, you have all click positions stored for later use.

Method 4: Combining Clicks with User Feedback through Circles

Another interactive way to display coordinates is by drawing a small circle at the click location and simultaneously displaying the coordinates. This gives immediate visual confirmation of the clicked point.

Here’s an example:

import cv2

def click_event(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        cv2.circle(img, (x, y), 3, (0, 255, 0), -1)
        cv2.imshow('image', img)
        print('Mouse Clicked at:', x, y)

img = cv2.imread('image.jpg')
cv2.imshow('image', img)
cv2.setMouseCallback('image', click_event)
cv2.waitKey(0)
cv2.destroyAllWindows()

The function circle draws a small filled green circle at the mouse click location. With this method, each click’s location is marked directly on the image and the corresponding coordinates are printed to the console.

Bonus One-Liner Method 5: One-Off Click Display Using Lambda Functions

Sometimes, you might want to write less code for a simple one-off task. Python’s lambda functions can help set up a quick mouse event callback inline without formally defining a function.

Here’s an example:

import cv2

img = cv2.imread('image.jpg')
cv2.imshow('image', img)
cv2.setMouseCallback('image', lambda event, x, y, flags, param: print((x, y)) if event == cv2.EVENT_LBUTTONDOWN else None)
cv2.waitKey(0)
cv2.destroyAllWindows()

Output:

(X, Y)

This one-liner sets a mouse event callback that prints the coordinates only when the left mouse button is clicked. It uses a lambda function to create a simple conditional callback inline.

Summary/Discussion

  • Method 1: Basic Callback Function. Strengths: Simple and straightforward, good for learning. Weaknesses: No visual feedback on the image.
  • Method 2: Adding Coordinates on the Image. Strengths: Provides direct visual feedback on the image. Weaknesses: Permanently alters the image if saved.
  • Method 3: Using a Global List. Strengths: Good for handling multiple points, efficient for subsequent processing. Weaknesses: Requires additional code to visualize or display points.
  • Method 4: Feedback through Circles. Strengths: Immediate visual confirmation of points. Weaknesses: Alters the image similarly to text, but less obtrusive.
  • Bonus One-Liner Method 5: Lambda Functions. Strengths: Quick, compact, good for scripts. Weaknesses: May be less readable to newcomers, less flexible for complex interactions.