2

I am trying to plot data over a background image in Python for the purpose of data verification, i.e. to see how close the curve I have generated from my own data fits one from a paper that I have a screenshot of saved as a png.

I have tried the code here using the extent keyword with imshow: Adding a background image to a plot with known corner coordinates and here is my code:

import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import imread
import matplotlib.cbook as cbook

np.random.seed(0)
x = np.random.uniform(0.0,10.0,15)
y = np.random.uniform(0.0,1.25,15)

datafile = cbook.get_sample_data('C:\\Users\\andrew.hills\\Desktop\\Capture.png')
img = imread(datafile)
plt.scatter(x,y,zorder=1)
plt.imshow(img, zorder=0, extent=[0.0, 10.0, 0.00, 1.25])
plt.show()

The problem I am having is that the figure appears distorted which I believe is happening because each pixel is set to 1x1 on the axes but my data range is 0.0-10.0 in the x direction and 0.00-1.25 in the y direction:

enter image description here

How do I change this so the image does not appear distorted?

Andrew Hills
  • 23
  • 1
  • 4

2 Answers2

6

The problem is indeed that the image get a new data range through the extent argument and that the aspect ratio of the image, which is "equal" by default will therefore lead to a distorted image.

What you need to do is to calculate a new aspect ratio that takes the new data range into account.

new_aspect = #pixels along y /

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(0)
x = np.random.uniform(0.0,10.0,15)
y = np.random.uniform(0.0,1.25,15)
plt.scatter(x,y,zorder=1)

img = plt.imread("house.png")

ext = [0.0, 10.0, 0.00, 1.25]
plt.imshow(img, zorder=0, extent=ext)

aspect=img.shape[0]/float(img.shape[1])*((ext[1]-ext[0])/(ext[3]-ext[2]))
plt.gca().set_aspect(aspect)

plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
0

I think what you are saying is that you would like your image to conform to the aspect ratio of the axes you are adding it to, not adjust that axes to have a 1-to-1 aspect ratio. If that's the case, try adding aspect='auto' to your imshow call.

plt.imshow(img, zorder=0, extent=[0.0, 10.0, 0.00, 1.25], aspect='auto')
K. Holst
  • 31
  • 2
  • 1
    `aspect="auto"` will only work if the aspect of the image matches (coincidently) the default matplotlib axes size. This might be the case if the image shown has itself been produced with matplotlib, but will fail in the general case. – ImportanceOfBeingErnest Aug 15 '17 at 09:23