Search code examples
pythonarraysmatplotlibclickmplcursors

Return x,y values of a 2D plot with mouse click


I'm plotting a simple image and like to get the x,y value, where I click with the mouse.

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

image = Image.open('points.jpg')

data = np.array(image)

plt.imshow(data)
plt.show()

Image with 4 points

So, I can navigate the mouse towards each point, click and at the end obtain a list with 4 x,y values.


Solution

  • First off, for images to click on, 'png' is usually a more suitable format than 'jpg'. The compression used for 'jpg' colors can smear colors out.

    mplcursors is a small package that supports clicking (or hovering) on a plot. Standard it displays an annotation tooltip with coordinates. In your application showing an annotation tooltip seems useful. If not, you can suppress that behavior with sel.annotation.set_visible(False) and still receive the event with the coordinates.

    The coordinates come in two flavors: x and y using the coordinate system of the axes, or an index (i,j) to indicate the pixel. With imshow's extent= parameter you can flexibly set the desired ranges (default x and y go from 0 to the width and height of the image). The x,y at the center of each pixel are integer values. So, you can either append the (i,j) indices or the (x,y) to your list.

    Some code to experiment:

    from PIL import Image
    import numpy as np
    import matplotlib.pyplot as plt
    import mplcursors
    
    image = Image.open('points.png')
    data = np.array(image)
    img = plt.imshow(data)
    
    points = []
    
    cursor = mplcursors.cursor(img, hover=False)
    @cursor.connect("add")
    def cursor_clicked(sel):
        # sel.annotation.set_visible(False)
        sel.annotation.set_text(
            f'Clicked on\nx: {sel.target[0]:.2f} y: {sel.target[1]:.2f}\nindex: {sel.target.index}')
        points.append(sel.target.index)
        print("Current list of points:", points)
    
    plt.show()
    print("Selected points:", points)