Two things happened that caused your pixel positions to be disabled.
The items used to calculate the text position are different from those used to save the shape.
When you use the bbox_inches parameter in a savefig call, it removes many spaces. You do not take this into account when drawing circles using PIL (or checking where someone clicked). You also add an add-on to this savefig call, which you might need to take into account if it is very large (since I am in my example below). It probably doesn't matter if you are still using 0.01.
To fix this first problem, just make the shape and savefig call use the same DPI.
To fix the second problem, write down the (0,0) position (s) of the axes in pixels and shift your text positions accordingly.
Here's a slightly modified version of your code:
#!/usr/bin/env python
Step number 2 does not change
Step 3 takes into account the origin
# Step 3: use PIL to draw dots on top of the labels from PIL import Image, ImageDraw im = Image.open("test.png") draw = ImageDraw.Draw(im) for x, y in midpoints: # deal with shift x = x-origin[0]+padding[0] y = y-origin[1]+padding[1] y = im.size[1] - y # PIL counts rows from top not bottom draw.ellipse((x-5, y-5, x+5, y+5), fill="#ff0000") im.save("test.png", "PNG")
It leads to:

Please note that I used the exaggerated PADDING value to verify that everything is still working, and a value of 0.01 will lead to the original shape.
source share