Холст Matplotlib как артефакты массива - PullRequest
0 голосов
/ 20 мая 2018

Я хочу преобразовать фигуру matplotlib в массив numpy.Я был в состоянии сделать это, непосредственно обращаясь к содержимому средства визуализации.Тем не менее, когда я вызываю imshow для массива numpy, он выглядит как артефакты сглаживания по краям, которых нет на исходном рисунке.

Я пытался поиграться с различными параметрами, но не могу понятьКак исправить артефакты из imshow.Различия в изображениях сохраняются, если я сохраняю рисунки в файл изображения.

Обратите внимание, что я хочу добиться того, чтобы убедиться, что содержимое массива такое же, как на рисунке, который я просматривал ранее.Я думаю, что, вероятно, эти артефакты отсутствуют в массиве numpy, но создаются во время вызова imshow.Возможно, проблема в конфигурации imshow может решить проблему.

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Rectangle
import math

fig = plt.figure(frameon=False)
ax = plt.gca()
ax.add_patch(Rectangle((0,0), 1, 1, angle=45, color="red"))
ax.set_xlim(-2,2)
ax.set_ylim(-2,2)
ax.set_aspect(1)
plt.axis("off")
fig.canvas.draw()
plt.savefig("rec1.png")
plt.show()
X = np.array(fig.canvas.renderer._renderer)

fig = plt.figure(frameon=False)
ax = plt.gca()
plt.axis("off")
plt.imshow(X)
plt.savefig("rec2.png")
plt.show()

enter image description here

Ответы [ 5 ]

0 голосов
/ 30 мая 2018

Изображение, показанное на втором графике, изображено меньше, чем первое изображение;причина в том, что полное изображение первой фигуры сжимается во вновь созданные меньшие оси - это было бы очевидно, если не выключать оси.

Чтобы убедиться, что вторая фигура показывает только само изображение,Вы можете отрегулировать поля так, чтобы между краем фигуры и осями не было промежутка, используя subplots_adjust.

fig = plt.figure(frameon=False)
fig.subplots_adjust(0,0,1,1)
ax = plt.gca()
plt.axis("off")
plt.imshow(X)

. Таким образом, вы получите желаемый график.

Обратите внимание, чтомассив не совсем одинаковый из-за сглаживания, применяемого при сохранении файла png.Вы можете узнать через

X = np.array(fig.canvas.renderer._renderer)/255.
Y = plt.imread("rec1.png")
print(np.all(X==Y))  
## This prints False

Иными словами, если вы хотите иметь тот же массив numpy, что и сохраненный, вы должны обязательно использовать самого сохраненного изображения.

plt.savefig("rec1.png")
X = plt.imread("rec1.png")
# use X from here onwards
0 голосов
/ 30 мая 2018

Это явно артефакты передискретизации, которых можно избежать, используя plt.figimage, который специально добавляет изображение без передискретизации к рисунку.

plt.figimage(X)
plt.show()

Обратите внимание, что это не будетработать с %matplotlib inline в Jupyter Notebook, но он отлично работает с %matplotlib notebook и с бэкэндами графического интерфейса.

0 голосов
/ 29 мая 2018

Добавив fig.tight_layout с отступом -1.08, я смог получить точное изображение как реальное изображение.

X = np.array(fig.canvas.renderer._renderer)
fig = plt.figure(frameon=False)
ax = plt.gca()
plt.axis("off")
plt.imshow(X)
fig.tight_layout(pad=-1.08)
plt.savefig("rec2.png")
plt.show()

Real Image

Из массива numy

Я надеюсь, что это решит вашу проблему, по крайней мере, пока вы не найдете лучший способ.Приветствия.

0 голосов
/ 30 мая 2018

Лучшее, что я могу придумать, это использовать библиотеку cv2 (openCV-python).Мое решение требует сохранения изображения, и в случае цветных изображений декодированные изображения будут иметь каналы, сохраненные в порядке BGR .

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Rectangle
import math
import cv2 #import openCV

fig = plt.figure(frameon=False)
ax = plt.gca()
ax.add_patch(Rectangle((0,0), 1, 1, angle=45, color="red"))
ax.set_xlim(-2,2)
ax.set_ylim(-2,2)
ax.set_aspect(1)
plt.axis("off")
fig.canvas.draw()
plt.savefig("rec1.png")
plt.show()`

im = cv2.imread("rec1.png")
print(type(im)) #prints numpy.ndarray

cv2.imshow("pic",im) #creates a window named pic, loads im
cv2.waitKey(0) #has no time limit, window destroyed on any key press
cv2.destroyAllWindows()

Конечный результат выглядит как

result

Поскольку это простой массив, вы можете вызывать методы для его сравнения.

print(im.shape) #prints (288, 432, 3)
0 голосов
/ 27 мая 2018

Спасибо за комментарии, которые указали на интерполяцию как на причину.Я нашел следующий код (адаптированный для Python 3), который отображает изображение так, как я хочу;идентично первому изображению, но через массив numpy.

import PIL.Image
from io import BytesIO
import IPython.display
import numpy as np
def showarray(a, fmt='png'):
    a = np.uint8(a)
    f = BytesIO()
    PIL.Image.fromarray(a).save(f, fmt)
    IPython.display.display(IPython.display.Image(data=f.getvalue()))

source: https://gist.github.com/kylemcdonald/2f1b9a255993bf9b2629

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...