Menghapus ruang putih di sekitar gambar yang disimpan di matplotlib

172

Saya perlu mengambil gambar dan menyimpannya setelah beberapa proses. Angka itu terlihat baik-baik saja ketika saya menampilkannya, tetapi setelah menyimpan gambar itu, saya mendapat ruang putih di sekitar gambar yang disimpan. Saya telah mencoba 'tight'opsi untuk savefigmetode, tidak berhasil. Kode:

  import matplotlib.image as mpimg
  import matplotlib.pyplot as plt

  fig = plt.figure(1)
  img = mpimg.imread(path)
  plt.imshow(img)
  ax=fig.add_subplot(1,1,1)

  extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
  plt.savefig('1.png', bbox_inches=extent)

  plt.axis('off') 
  plt.show()

Saya mencoba menggambar grafik dasar dengan menggunakan NetworkX pada gambar dan menyimpannya. Saya menyadari bahwa tanpa grafik itu berfungsi, tetapi ketika menambahkan grafik saya mendapatkan ruang putih di sekitar gambar yang disimpan;

import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import networkx as nx

G = nx.Graph()
G.add_node(1)
G.add_node(2)
G.add_node(3)
G.add_edge(1,3)
G.add_edge(1,2)
pos = {1:[100,120], 2:[200,300], 3:[50,75]}

fig = plt.figure(1)
img = mpimg.imread("C:\\images\\1.jpg")
plt.imshow(img)
ax=fig.add_subplot(1,1,1)

nx.draw(G, pos=pos)

extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
plt.savefig('1.png', bbox_inches = extent)

plt.axis('off') 
plt.show()
Ahmet Tuğrul Bayrak
sumber
1
Kemungkinan duplikat dari Menyimpan figur matplotlib / networkx tanpa margin
Joel
Apa yang benar-benar bekerja untuk saya adalah memotong pdf menggunakan alat lain, seperti pdfcrop.
toliveira

Jawaban:

169

Saya tidak dapat mengklaim bahwa saya tahu persis mengapa atau bagaimana "solusi" saya bekerja, tetapi inilah yang harus saya lakukan ketika saya ingin merencanakan garis besar beberapa bagian aerofoil - tanpa margin putih - ke file PDF. (Perhatikan bahwa saya menggunakan matplotlib di dalam notebook IPython, dengan flag -pylab.)

plt.gca().set_axis_off()
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
            hspace = 0, wspace = 0)
plt.margins(0,0)
plt.gca().xaxis.set_major_locator(plt.NullLocator())
plt.gca().yaxis.set_major_locator(plt.NullLocator())
plt.savefig("filename.pdf", bbox_inches = 'tight',
    pad_inches = 0)

Saya telah mencoba untuk menonaktifkan bagian yang berbeda dari ini, tetapi ini selalu mengarah pada margin putih di suatu tempat. Anda bahkan mungkin telah memodifikasi ini untuk menjaga garis-garis lemak di dekat batas gambar agar tidak dicukur oleh kurangnya margin.

Johannes S.
sumber
6
Akhirnya sesuatu yang berhasil, terima kasih banyak! Ngomong-ngomong, dalam kasus saya hanya set_major_locatorperlu menggunakan dua baris .
Florian Brucker
6
Saya telah menghabiskan satu jam terakhir mencoba berbagai hal dan tidak dapat menghilangkan batas putih 1px. Ini adalah satu-satunya hal yang berhasil - khususnya pad_inches=0yang tidak disebutkan jawaban lain.
AnnanFay
1
set_major_locatoradalah kunci bagi saya.
kmac
16
pad_inchesmembantuku.
Myles Baker
5
matplotlib.ticker.NullLocator ()
Joop
200

Anda dapat menghapus padding ruang putih dengan menetapkan bbox_inches="tight"di savefig:

plt.savefig("test.png",bbox_inches='tight')

Anda harus meletakkan argumen bbox_inchessebagai string, mungkin ini sebabnya tidak bekerja lebih awal untuk Anda.


Kemungkinan duplikat:

Plot matplotlib: menghilangkan sumbu, legenda dan spasi putih

Bagaimana cara mengatur margin untuk angka matplotlib?

Kurangi margin kiri dan kanan di plot matplotlib

Doyan
sumber
1
Jika Anda memiliki beberapa subplot dan ingin menyimpannya masing-masing, Anda dapat menggunakannya fig.savefig()juga. ( plt.savefig()tidak akan bekerja dalam kasus itu.)
Abhranil Das
30
Itu tidak cukup tepat. Ketika Anda menggunakan bbox_inchesopsi itu, ada standar lain yang menyisakan sedikit ruang. Jika Anda benar-benar ingin menyingkirkan semuanya, Anda juga harus menggunakannya pad_inches=0.0. Tentu saja, padding ketat seperti itu sering terputus, misalnya eksponen ...
Mike
5
Untuk menghapus tepi hitam juga, Anda mungkin perlu mengaturpad_inches=-0.1
lenhhoxung
10
Ini tidak berhasil, Anda masih mendapatkan spasi di sekitar gambar. Mengatur opsi transparan (seperti yang disebutkan dalam beberapa jawaban) juga tidak membantu, spasi masih ada, hanya transparan.
BjornW
1
@piperchester itu pertanyaan yang bagus, tapi mungkin harus ditanyakan sebagai pertanyaan baru sehingga tidak hilang dalam komentar. Anda harus menghubungkan pertanyaan baru dengan yang lama!
Hooked
21

Setelah mencoba jawaban di atas tanpa hasil (dan banyak posting stack lainnya) apa yang akhirnya berhasil untuk saya adalah adil

plt.gca().set_axis_off()
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
            hspace = 0, wspace = 0)
plt.margins(0,0)
plt.savefig("myfig.pdf")

Yang penting ini tidak termasuk argumen bbox atau padding.

SuaveSouris
sumber
4
Ini harus menjadi jawaban yang diterima. Selain itu, Anda bahkan tidak perlu menelepon set_axis_off. Ini tidak mempengaruhi gambar yang disimpan karena setelah subplots_adjustsumbu terletak di luar batas gambar dan dia tidak akan pernah terlihat. Namun, di notebook Jupyter, Anda perlu menonaktifkan sumbu secara eksplisit, karena backend inline menimpa pengaturan ini.
MaxPowers
20

Saya menemukan sesuatu dari Arvind Pereira ( http://robotics.usc.edu/~ampereir/wordpress/?p=626 ) dan sepertinya bekerja untuk saya:

plt.savefig(filename, transparent = True, bbox_inches = 'tight', pad_inches = 0)
kurang sopan
sumber
7
transparent=Trueakan membuatnya tampak seperti tidak ada masalah tetapi itu hanya akan menyembunyikan ruang putih, dimensi gambar tidak akan baik-baik saja.
Vlady Veselinov
Terima kasih telah menyebutkan pad_inches! Saya berharap saya tahu opsi ini sebelumnya!
ingomueller.net
1
Ini berfungsi untuk sebagian besar plot, tetapi ini menghilangkan batas kanan untuk matriks kebingungan saya. Tambahkan saja padding kecilpad_inches=.25
YTZ
14

Fungsi berikut menggabungkan jawaban johannes di atas. Saya telah mengujinya dengan plt.figuredan plt.subplots()dengan beberapa sumbu, dan bekerja dengan baik.

def save(filepath, fig=None):
    '''Save the current image with no whitespace
    Example filepath: "myfig.png" or r"C:\myfig.pdf" 
    '''
    import matplotlib.pyplot as plt
    if not fig:
        fig = plt.gcf()

    plt.subplots_adjust(0,0,1,1,0,0)
    for ax in fig.axes:
        ax.axis('off')
        ax.margins(0,0)
        ax.xaxis.set_major_locator(plt.NullLocator())
        ax.yaxis.set_major_locator(plt.NullLocator())
    fig.savefig(filepath, pad_inches = 0, bbox_inches='tight')
TomNorway
sumber
Bekerja seperti pesona. Jawaban sebelumnya adalah beberapa perintah yang diperlukan dalam ekspor saya.
Kevin S
11

Saya menemukan kode-kode berikut berfungsi dengan baik untuk pekerjaan itu.

fig = plt.figure(figsize=[6,6])
ax = fig.add_subplot(111)
ax.imshow(data)
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)
ax.set_frame_on(False)
plt.savefig('data.png', dpi=400, bbox_inches='tight',pad_inches=0)
Richard Yu Liu
sumber
2
Secara umum, jawaban akan jauh lebih membantu jika mereka menyertakan penjelasan tentang apa yang dimaksudkan untuk dilakukan oleh kode, dan mengapa itu memecahkan masalah tanpa memperkenalkan orang lain.
Tim Diekmann
7

Saya mengikuti urutan ini dan itu bekerja seperti pesona.

plt.axis("off")
fig=plt.imshow(image array,interpolation='nearest')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
plt.savefig('destination_path.pdf',
    bbox_inches='tight', pad_inches=0, format='pdf', dpi=1200)
Khan
sumber
1
Sebenarnya, saya menemukan jawaban ini mudah dan lebih nyaman digunakan.
sikisis
1
Yang ini bekerja untuk saya; jawaban yang diterima tidak.
Joe
3

Bagi siapa pun yang ingin bekerja dalam piksel daripada inci, ini akan berfungsi.

Plus yang biasa Anda juga perlu

from matplotlib.transforms import Bbox

Kemudian Anda dapat menggunakan yang berikut ini:

my_dpi = 100 # Good default - doesn't really matter

# Size of output in pixels
h = 224
w = 224

fig, ax = plt.subplots(1, figsize=(w/my_dpi, h/my_dpi), dpi=my_dpi)

ax.set_position([0, 0, 1, 1]) # Critical!

# Do some stuff
ax.imshow(img)
ax.imshow(heatmap) # 4-channel RGBA
ax.plot([50, 100, 150], [50, 100, 150], color="red")

ax.axis("off")

fig.savefig("saved_img.png",
            bbox_inches=Bbox([[0, 0], [w/my_dpi, h/my_dpi]]),
            dpi=my_dpi)

masukkan deskripsi gambar di sini

Simon Thomas
sumber
Anda tidak harus menentukan dpi, Anda dapat menggunakan salah satu standar fig.dpibukannya
intsco
1

Pendekatan yang jauh lebih sederhana yang saya temukan adalah menggunakan plt.imsave:

    import matplotlib.pyplot as plt
    arr = plt.imread(path)
    plt.imsave('test.png', arr)
Parth92
sumber
Jawaban yang diremehkan. Ini membantu saya setelah pencarian panjang untuk bagaimana mempertahankan resolusi dan menghapus spasi dengan plt.savefig().
nihal111
Ini hanya berfungsi jika Anda ingin menyimpan array (!) Sebagai gambar. Ini tidak memungkinkan untuk menyimpan angka yang sewenang-wenang.
MaxPowers
Apa yang Anda maksudkan dengan citra sewenang-wenang? Bukankah gambar adalah array nilai?
Parth92
0

Anda dapat mencoba ini. Itu memecahkan masalah saya.

import matplotlib.image as mpimg
img = mpimg.imread("src.png")
mpimg.imsave("out.png", img, cmap=cmap)
pengguna1410665
sumber
-1

Jika Anda ingin menampilkan apa yang harus disimpan, saya sarankan menggunakan plt.tight_layouttransformasi yang sebenarnya lebih disukai karena tidak melakukan pemotongan yang tidak perlu saat menggunakanplt.savefig

import matplotlib as plt    
plt.plot([1,2,3], [1,2,3])
plt.tight_layout(pad=0)
plt.savefig('plot.png')
Keto
sumber
-4

Ini berfungsi untuk saya menyimpan array numpy diplot dengan imshow ke file

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(10,10))
plt.imshow(img) # your image here
plt.axis("off")
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
        hspace = 0, wspace = 0)
plt.savefig("example2.png", box_inches='tight', dpi=100)
plt.show()
Alejandro Sazo
sumber