scipy: savefig โดยไม่มีเฟรมแกนเนื้อหาเท่านั้น


92

ใน numpy / scipy ฉันมีภาพเก็บไว้ในอาร์เรย์ ฉันสามารถแสดงได้ฉันต้องการบันทึกโดยsavefig ไม่มีขอบแกนป้ายชื่อเรื่อง ... เป็นเพียงภาพที่บริสุทธิ์ไม่มีอะไรอื่น

ฉันต้องการหลีกเลี่ยงแพ็กเกจเช่นPyPNGหรือscipy.misc.imsaveบางครั้งก็มีปัญหา (ไม่ได้ติดตั้งได้ดีเสมอไป แต่เป็นพื้นฐานsavefig()สำหรับฉันเท่านั้น

คำตอบ:


115

แก้ไข

เปลี่ยนaspect='normalเป็นaspect='auto'ตั้งแต่ที่มีการเปลี่ยนแปลงใน matplotlib เวอร์ชันล่าสุด (ขอบคุณ @ Luke19)


สมมติว่า:

import matplotlib.pyplot as plt

ในการสร้างรูปโดยไม่มีกรอบ:

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(your_image, aspect='auto')
fig.savefig(fname, dpi)

พารามิเตอร์การเปลี่ยนแปลงขนาดพิกเซลเพื่อให้แน่ใจว่าพวกเขากรอกตัวเลขขนาดที่ระบุไว้ในaspect fig.set_size_inches(…)หากต้องการทราบว่าจะเล่นกับสิ่งต่างๆประเภทนี้ได้อย่างไรโปรดอ่านเอกสารประกอบของ matplotlibโดยเฉพาะในหัวข้อ Axes, Axis และ Artist


4
ไม่ฉันยังมีขอบโปร่งใสเล็ก ๆ และสิ่งที่ฉันต้องการคือไม่มีขอบเลยภาพที่บริสุทธิ์
Jakub M.

5
หากคุณตั้งค่าพารามิเตอร์wและhในfig.set_size_inches(w,h)และdpiพารามิเตอร์ด้วยตนเองfig.savefig(fname, dpi)เพื่อให้ได้ผลลัพธ์เป็น 24px x 24px ก็น่าจะใช้ได้ดี ตัวอย่างเช่นw = h = 1และdpi = 24
เพื่อนที่

5
ฉันต้องรวมทั้งคำตอบนี้และคำตอบด้านล่างโดย Mostafa Pakparvar คุณไม่เพียง แต่ต้องปิดแกนเท่านั้น แต่คุณต้อง set_visible to false เพื่อให้แน่ใจว่าพื้นที่สีขาวหายไป (wtf?)
Bryce Guinta

6
เพิ่งลองสิ่งนี้โดยใช้ matplotlib v2.2.2 ซึ่งทำงานได้อย่างสมบูรณ์ (ยกเว้นimshowไวยากรณ์ของนั้นเปลี่ยนเป็นaspect='auto'แทน'normal')
ลุ

2
นี่คือแนวทางที่ถูกต้อง ax = plt.Axes(fig, [0., 0., 1., 1.])คือสิ่งที่ทำให้มันใช้งานได้
greatvovan

73

ทางออกที่ง่ายกว่าน่าจะเป็น:

fig.savefig('out.png', bbox_inches='tight', pad_inches=0)

2
สิ่งนี้ได้ผลดีสำหรับฉัน นอกจากนี้ pad_inches ยังสามารถเปลี่ยนเป็นขนาดที่ต้องการได้อย่างง่ายดาย ขอบคุณ!
Curious2learn

27
ฉันยังมีขอบสีขาวด้วยสิ่งนี้
Fábio Perez

4
ฉันสามารถอัปเดตสิ่งนี้สำหรับเวอร์ชันที่ใหม่กว่า / ปัญหาระยะขอบที่เหลือเพียงแค่ใส่ transparent = True fig.savefig('out.png', bbox_inches='tight',transparent=True, pad_inches=0)
mdoc-2011

2
ยังคงมีแกนและเครื่องหมายและทุกอย่างด้วย :(
BjornW

3
นี้ไม่ได้ทำอะไรเลย มันจะให้ภาพที่มีแกนและป้ายกำกับทั้งหมด
1313e

27

คุณสามารถค้นหา bbox ของรูปภาพภายในแกน (โดยใช้get_window_extent) และใช้bbox_inchesพารามิเตอร์เพื่อบันทึกเฉพาะส่วนนั้นของรูปภาพ:

import numpy as np
import matplotlib.pyplot as plt

data=np.arange(9).reshape((3,3))
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
plt.axis('off')
plt.imshow(data)

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

ผมได้เรียนรู้เคล็ดลับนี้จากโจ Kington ที่นี่


6
แค่plt.axis('off')ช่วย คำตอบอื่น ๆ ไม่ได้ช่วยอะไรมาก
imsrgadich

3
สิ่งนี้ได้ผลดี อย่างไรก็ตามในกรณีของฉันยังมีขอบสีขาวเล็ก ๆ มีความคิดอย่างไรในการลบเส้นขอบนี้?
user3731622

@ user3731622 โปรดลองplt.savefig('/temp/test.png', bbox_inches='tight', transparent=True, pad_inches=0)แทนplt.savefig('/tmp/test.png', bbox_inches=extent)
Cloud Cho

17

ฉันได้ลองใช้หลายตัวเลือกในกรณีของฉันและทางออกที่ดีที่สุดคือ:

fig.subplots_adjust(bottom = 0)
fig.subplots_adjust(top = 1)
fig.subplots_adjust(right = 1)
fig.subplots_adjust(left = 0)

จากนั้นบันทึกรูปของคุณด้วย savefig


1
จากวิธีแก้ปัญหาทั้งหมดนี้เป็นวิธีเดียวที่ใช้ได้ผลสำหรับฉัน
พัฟ

8

ฉันจะแนะนำคำตอบ heron13 ด้วยการเพิ่มเล็กน้อยที่ยืมมาจากที่นี่เพื่อลบช่องว่างที่เหลือหลังจากตั้งค่า bbox เป็นโหมดแน่นดังนั้น:

axes = fig.axes()
axes.get_xaxis().set_visible(False)
axes.get_yaxis().set_visible(False)
fig.savefig('out.png', bbox_inches='tight', pad_inches=0)

ฉันได้รับข้อผิดพลาดที่แจ้งว่า get_xaxis () และ get_yaxis () ไม่มีอยู่จริง มีความคิดว่าทำไมถึงเกิดขึ้น?
Jacob Malachowski

สร้างวัตถุแกน () จากนั้นใช้ ax.xaxis และ ax.yaxis
perigon

มีข้อผิดพลาดแจ้งว่าวัตถุ 'รายการ' ไม่มีแอตทริบิวต์ 'get_xaxis'
Haozhe Xie


3

ฉันมีปัญหาเดียวกันขณะทำการสร้างภาพโดยใช้librosaซึ่งฉันต้องการแยกเนื้อหาของพล็อตโดยไม่มีข้อมูลอื่น ๆ นี่คือแนวทางของฉัน คำตอบ unutbu ยังช่วยให้ฉันทำงานได้

    figure = plt.figure(figsize=(500, 600), dpi=1)
    axis = plt.subplot(1, 1, 1)
    plt.axis('off')
    plt.tick_params(axis='both', left='off', top='off', right='off', bottom='off', labelleft='off', labeltop='off',
                    labelright='off', labelbottom='off')

     # your code goes here. e.g: I used librosa function to draw a image
    result = np.array(clip.feature_list['fft'].get_logamplitude()[0:2])
    librosa.display.specshow(result, sr=api.Clip.RATE, x_axis='time', y_axis='mel', cmap='RdBu_r')


    extent = axis.get_window_extent().transformed(figure.dpi_scale_trans.inverted())
    plt.savefig((clip.filename + str("_.jpg")), format='jpg', bbox_inches=extent, pad_inches=0)
    plt.close()

สิ่งนี้ทำให้ฉันมาถูกทาง แต่ฉันมีปัญหาสองประการ: 1) ฉันต้องตั้งค่า dpi เป็นตัวเลขที่มากกว่า 1 เพื่อหลีกเลี่ยงข้อผิดพลาดแบบอักษรในสมุดบันทึก jupyter ของฉัน และ 2) ยังคงมีชายแดนเล็ก ๆ ดังนั้นผมจึงต้องเปลี่ยนขอบเขต Bbox extent.get_points()*np.array([[1.1],[.9]])ตนเอง
Bob Baxley

ขอบคุณสำหรับคำตอบที่ตอบสนองซึ่งอาจช่วยคนอื่นได้
GPrathap

3

สำหรับใครที่พยายามทำใน Jupyter

 plt.axis('off')

 spec = plt.imshow

 plt.savefig('spec',bbox_inches='tight',transparent=True, pad_inches=0)

2

ในขณะที่คำตอบด้านบนกล่าวถึงการลบระยะขอบและช่องว่างภายใน แต่ก็ไม่ได้ผลสำหรับฉันในการลบป้ายกำกับ นี่คือสิ่งที่ได้ผลสำหรับทุกคนที่พบคำถามนี้ในภายหลัง:

สมมติว่าคุณต้องการตารางย่อย 2x2 จากสี่ภาพที่เก็บไว้ในimages:

matplotlib.pyplot.figure(figsize = (16,12)) # or whatever image size you require
for i in range(4):
    ax = matplotlib.pyplot.subplot(2,2,i+1)
    ax.axis('off')
    imshow(images[i])
matplotlib.pyplot.savefig(path, bbox_inches='tight')

1

ฉันพยายามกำจัดเส้นขอบด้วยโดยใช้เคล็ดลับที่นี่ แต่ก็ไม่ได้ผลจริงๆ บางคนเล่นซอและฉันพบว่าการเปลี่ยนสีของใบหน้าทำให้ฉันไม่มีขอบในห้องทดลอง jupyter (สีใดก็ได้ที่ทำให้ขอบสีขาวหลุดออกไป) หวังว่านี่จะช่วยได้

def show_num(data):
data = np.rot90(data.reshape((16,16)), k=3)
data = np.fliplr(data)
fig = plt.figure(frameon=False, facecolor='white')
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
ax.imshow(data)
plt.show()

ป้อนคำอธิบายภาพที่นี่


1

อันที่จริงฉันได้ลองสิ่งนี้เมื่อไม่นานมานี้และแทนที่จะใช้บรรทัดเหล่านี้ทั้งหมดคุณสามารถใช้ได้

plt.imsave(image_path, image)

ใช้งานได้เหมือนมีเสน่ห์ เพียงบรรทัดเดียวและแก้ไขปัญหาได้

imsave()

เอกสารประกอบ ( https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.imsave.html )


0

สำหรับฉันรหัสนี้ทำให้ขนาดภาพอินพุตที่คล้ายกันโดยไม่มีเฟรมและแกนจากรหัส matehat , unutbuและWHZW :

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
plt.axis('off')
viridis = cm.get_cmap('gist_gray', 256)
plt.imshow(data, aspect='auto', cmap=viridis)
plt.tight_layout()
plt.savefig(out_file, bbox_inches='tight', transparent=True, pad_inches=0)

สภาพแวดล้อมรันไทม์:
Python 3.6.10
Matplotlib 3.2.1
OS Windows 10

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.