0

I have an 256x256 image and I want to be able to plot a regression line through the points. To do this I converted the image to a scatter plot and then tried to convert the scatter plot back to a numpy array. However, conversion back to a numpy array made the numpy array 480x640.

Would anyone please be able to explain to me why the shape changes, mainly why it's no longer a square image, and if there's any conversion to fix it?

Making my x and y points from binary image

imagetile = a[2]
x, y = np.where(imagetile>0)
imagetile.shape

Out: (256L, 256L)

Version 1

from numpy import polyfit
from numpy import polyval

imagetile = a[2]
x, y = np.where(imagetile>0)

from numpy import polyfit
from numpy import polyval

p2 = polyfit(x, y, 2)

fig = plt.figure()
ax = fig.add_axes([0.,0.,1.,1.])
xp = np.linspace(0, 256, 256)
plt.scatter(x, y)
plt.xlim(0,256)
plt.ylim(0,256)
plt.plot(xp, polyval(p2, xp), "b-")
plt.show()

fig.canvas.draw()
X = np.array(fig.canvas.renderer._renderer)
X.shape

Out: (480L, 640L, 4L)

Version 2

def fig2data ( fig ):
    """
    @brief Convert a Matplotlib figure to a 4D numpy array with RGBA channels and return it
    @param fig a matplotlib figure
    @return a numpy 3D array of RGBA values
    """
    # draw the renderer
    fig.canvas.draw ( )
 
    # Get the RGBA buffer from the figure
    w,h = fig.canvas.get_width_height()
    buf = np.fromstring ( fig.canvas.tostring_argb(), dtype=np.uint8 )
    buf.shape = ( w, h,4 )
 
    # canvas.tostring_argb give pixmap in ARGB mode. Roll the ALPHA channel to have it in RGBA mode
    buf = np.roll ( buf, 3, axis = 2 )
    return buf

figure = matplotlib.pyplot.figure(  )
plot   = figure.add_subplot ( 111 )
 

x, y = np.where(imagetile>0)
p2 = polyfit(x, y, 2)
plt.scatter(x, y)
plt.xlim(0,256)
plt.ylim(0,256)
plt.plot(xp, polyval(p2, xp), "b-")

data = fig2data(figure)
data.shape

Out: (640L, 480L, 4L)

Thank you

2
  • I guess this is due to your matplotlib DPI settings in combination with your default figure size. Imho converting an image to an array when you have the image-input-data as an array is not a good thing anyways. Commented Apr 16, 2019 at 8:43
  • Thanks, I agree. Do you know of any other way to plot a regression line on an image though? Commented Apr 16, 2019 at 8:58

1 Answer 1

1

If you call matplotlib.pyplot.figure without setting the argument figsize, it takes on a default shape (quote from the documentation):

figsize : (float, float), optional, default: None width, height in inches. If not provided, defaults to rcParams["figure.figsize"] = [6.4, 4.8].

So, you could set the shape by doing

matplotlib.pyplot.figure(figsize=(2.56,2.56))

Not knowing what your data looks like, I think your approach is rather roundabout, so, I suggest something like this:

import numpy as np
import matplotlib.pyplot as plt

# generating simulated polynomial data:
arr = np.zeros((256, 256))
par = [((a-128)**2, a) for a in range(256)]
par = [p for p in par if p[0]<255]
arr[zip(*par)] = 1

x, y = np.where(arr>0)
p2 = np.polyfit(y, x, 2)
xp = np.linspace(0,256,256)

plt.imshow(arr) # show the image, rather than the conversion to datapoints

p = np.poly1d(p2) # recommended in the documentation for np.polyfit

plt.plot(xp, p(xp))

plt.ylim(0,256)
plt.xlim(0,256)

plt.show()

link to the documentation of np.polyfit

Sign up to request clarification or add additional context in comments.

3 Comments

Please can I ask another question? I'm trying to implement polyfit in a for loop and with my x and y taken from np.where(all_image_tiles[i] > 0) and it works fine for the first subplot but then returns the error "expected non-empty vector for x" on the next iteration. x and y are np arrays. Do you know where I might be going wrong?
could you either edit your original question to show the code that generates the error, or alternatively open a new question? This makes it a bit easier to troubleshoot
Sorry I realised it was because I didn't actually have any data points in one of my images. I've deleted the question. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.