#python #arrays #numpy #matplotlib
#python #массивы #numpy #matplotlib
Вопрос:
У меня есть изображение размером 256×256, и я хочу иметь возможность построить линию регрессии через точки. Для этого я преобразовал изображение в точечный график, а затем попытался преобразовать точечный график обратно в массив numpy. Однако преобразование обратно в массив numpy сделало массив numpy размером 480×640.
Кто-нибудь, пожалуйста, сможет объяснить мне, почему форма меняется, в основном, почему это больше не квадратное изображение, и есть ли какое-либо преобразование для его исправления?
Создание моих точек x и y из двоичного изображения
imagetile = a[2]
x, y = np.where(imagetile>0)
imagetile.shape
Выход: (256L, 256L)
Версия 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
Выход: (480L, 640L, 4L)
Версия 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
Выход: (640L, 480L, 4L)
Спасибо
Комментарии:
1. Я предполагаю, что это связано с вашими настройками DPI matplotlib в сочетании с вашим размером фигуры по умолчанию. Imho преобразование изображения в массив, когда у вас есть image-input-data в виде массива, в любом случае не очень хорошо.
2. Спасибо, я согласен. Знаете ли вы какой-либо другой способ построения линии регрессии на изображении?
Ответ №1:
Если вы вызываете matplotlib.pyplot.figure без установки аргумента figsize, он принимает форму по умолчанию (цитата из документации):
figsize : (float, float), необязательно, по умолчанию: Нет ширина, высота в дюймах. Если не указано, по умолчанию используется значение rcParams[«figure.figsize»] = [6.4, 4.8].
Итак, вы можете задать форму, выполнив
matplotlib.pyplot.figure(figsize=(2.56,2.56))
Не зная, как выглядят ваши данные, я думаю, что ваш подход довольно обходной, поэтому я предлагаю что-то вроде этого:
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()
Комментарии:
1. Пожалуйста, могу я задать еще один вопрос? Я пытаюсь реализовать polyfit в цикле for и с моими x и y, взятыми из np.where(all_image_tiles[i]> 0), и он отлично работает для первого подзаголовка, но затем возвращает ошибку «ожидаемый непустой вектор для x» на следующей итерации. x и y являются np-массивами. Вы знаете, где я могу ошибаться?
2. не могли бы вы либо отредактировать свой исходный вопрос, чтобы показать код, который генерирует ошибку, либо, альтернативно, открыть новый вопрос? Это немного упрощает устранение неполадок
3. Извините, я понял, что это потому, что на самом деле у меня не было точек данных ни на одном из моих изображений. Я удалил вопрос. Спасибо.