Określanie i zapisywanie rysunku o dokładnym rozmiarze w pikselach

Powiedzmy, że mam obraz o rozmiarze 3841 x 7195 pikseli. Chciałbym zapisać zawartość rysunku na dysku, co daje obraz dokładny rozmiar podam w pikselach.

Bez osi, bez tytułów. Tylko obraz. Osobiście nie dbam o DPIs, ponieważ chcę tylko określić rozmiar obrazu na ekranie w Dysku w pikselach .

Przeczytałem Inne wątki, a wszystkie wydają się wykonywać konwersje na cale, a następnie określać wymiary rysunku w calach i dostosować dpi w jakiś sposób. Chciałbym uniknąć radzenia sobie z potencjalną utratą dokładności, która może wynikać z konwersji pikseli na cale.

Próbowałem z:

w = 7195
h = 3841
fig = plt.figure(frameon=False)
fig.set_size_inches(w,h)
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
ax.imshow(im_np, aspect='normal')
fig.savefig(some_path, dpi=1)

Bez powodzenia (Python narzeka, że szerokość i wysokość muszą być poniżej 32768 (?))

Z wszystkiego, co widziałem, matplotlib wymaga, aby wielkość rysunku była określona w inches i dpi, ale interesuje mnie tylko piksele , które rysunek zajmuje na dysku. Jak mogę to zrobić?

Dla wyjaśnienia: szukam sposobu, aby to zrobić z matplotlib, a nie z innymi bibliotekami zapisującymi obrazy.

Author: Community, 2012-12-05

3 answers

Matplotlib nie działa bezpośrednio z pikselami, ale raczej z fizycznymi rozmiarami i DPI. Jeśli chcesz wyświetlić figurę o określonym rozmiarze piksela, musisz znać rozdzielczość DPI swojego monitora. Na przykład ten link wykryje to za Ciebie.

Jeśli masz obraz o wymiarach 3841x7195 pikseli, jest mało prawdopodobne, aby monitor był tak duży, więc nie będziesz w stanie pokazać figury o takim rozmiarze (matplotlib wymaga, aby figura zmieściła się na ekranie, jeśli poprosisz o zbyt duży rozmiar, będzie to możliwe zmniejsz do rozmiaru ekranu). Wyobraźmy sobie, że chcesz obraz 800x800 pikseli tylko dla przykładu. Oto jak wyświetlić obraz o rozdzielczości 800x800 pikseli na moim monitorze (my_dpi=96):

plt.figure(figsize=(800/my_dpi, 800/my_dpi), dpi=my_dpi)

Więc po prostu dzielisz wymiary w calach przez DPI.

Jeśli chcesz zapisać figurę o określonej wielkości, to jest to inna sprawa. Ekranowe DPI nie są już tak ważne (chyba że poprosisz o cyfrę, która nie zmieści się na ekranie). Korzystając z tego samego przykładu figury 800x800 pikseli, możemy zapisz go w różnych rozdzielczościach używając słowa kluczowego dpi z savefig. Aby zapisać go w tej samej rozdzielczości co ekran, wystarczy użyć tego samego dpi:

plt.savefig('my_fig.png', dpi=my_dpi)
Aby zapisać obraz w rozdzielczości 8000x8000 pikseli, użyj dpi 10 razy większego:]}
plt.savefig('my_fig.png', dpi=my_dpi * 10)

Zauważ, że ustawienie DPI nie jest obsługiwane przez wszystkie backendy. Tutaj używany jest backend PNG, ale backend pdf i ps zaimplementuje rozmiar inaczej. Również zmiana DPI i rozmiarów wpłynie na rzeczy takie jak fontsize. Większe DPI będzie zachowaj te same względne rozmiary czcionek i elementów, ale jeśli chcesz mniejszych czcionek dla większej liczby, musisz zwiększyć rozmiar fizyczny zamiast DPI.

Wracając do twojego przykładu, jeśli chcesz zapisać obraz o rozdzielczości 3841 x 7195 pikseli, możesz wykonać następujące czynności:

plt.figure(figsize=(3.841, 7.195), dpi=100)
( your code ...)
plt.savefig('myfig.png', dpi=1000)

Zauważ, że używałem cyfry dpi 100, aby zmieścić się w większości ekranów, ale zapisałem ją dpi=1000, aby osiągnąć wymaganą rozdzielczość. W moim systemie tworzy to png o rozdzielczości 3840x7190 pikseli - wydaje się, że zapisane DPI jest zawsze o 0.02 pikseli/cal mniejsze od wybranej wartości, co będzie miało (mały) wpływ na duże rozmiary obrazów. Więcej o tym tutaj.

 103
Author: tiago,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:54

To działało dla mnie, na podstawie Twojego kodu, generując 93mb obraz png z szumem kolorów i pożądanymi wymiarami:

import matplotlib.pyplot as plt
import numpy

w = 7195
h = 3841

im_np = numpy.random.rand(h, w)

fig = plt.figure(frameon=False)
fig.set_size_inches(w,h)
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
ax.imshow(im_np, aspect='normal')
fig.savefig('figure.png', dpi=1)

Używam ostatnich wersji Pip bibliotek Pythona 2.7 W Linux Mint 13.

Mam nadzieję, że to pomoże!
 11
Author: heltonbiker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-05 01:26:23

Na podstawie zaakceptowanej odpowiedzi tiago, oto mała ogólna funkcja, która eksportuje tablicę numpy do obrazu o tej samej rozdzielczości co tablica:

import matplotlib.pyplot as plt
import numpy as np

def export_figure_matplotlib(arr, f_name, dpi=200, resize_fact=1, plt_show=False):
    """
    Export array as figure in original resolution
    :param arr: array of image to save in original resolution
    :param f_name: name of file where to save figure
    :param resize_fact: resize facter wrt shape of arr, in (0, np.infty)
    :param dpi: dpi of your screen
    :param plt_show: show plot or not
    """
    fig = plt.figure(frameon=False)
    fig.set_size_inches(arr.shape[1]/dpi, arr.shape[0]/dpi)
    ax = plt.Axes(fig, [0., 0., 1., 1.])
    ax.set_axis_off()
    fig.add_axes(ax)
    ax.imshow(arr)
    plt.savefig(f_name, dpi=(dpi * resize_fact))
    if plt_show:
        plt.show()
    else:
        plt.close()

Jak wspomniano w poprzedniej odpowiedzi tiago, najpierw należy znaleźć DPI ekranu, co można zrobić na przykład tutaj: http://dpi.lv

Dodałem dodatkowy argument resize_fact w funkcji, którą można wyeksportować obraz do 50% (0,5) oryginalnej rozdzielczości, na przykład.

 0
Author: Cyril,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-20 08:58:28