scipy: savefig không có khung, trục, chỉ có nội dung


92

Trong numpy / scipy, tôi có một hình ảnh được lưu trữ trong một mảng. Tôi có thể hiển thị nó, tôi muốn lưu nó bằng cách sử dụng savefig mà không có bất kỳ đường viền, trục, nhãn, tiêu đề, ... Chỉ là hình ảnh thuần túy, không có gì khác.

Tôi muốn tránh các gói như PyPNGhoặc scipy.misc.imsave, đôi khi chúng có vấn đề (không phải lúc nào chúng cũng cài đặt tốt, chỉ cơ bản savefig()đối với tôi

Câu trả lời:


115

BIÊN TẬP

Thay đổi aspect='normalđể aspect='auto'từ đó thay đổi trong các phiên bản gần đây của matplotlib (nhờ @ Luke19).


Giả định :

import matplotlib.pyplot as plt

Để tạo hình mà không có khung:

fig = plt.figure(frameon=False)
fig.set_size_inches(w,h)

Để làm cho nội dung lấp đầy toàn bộ hình

ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)

Sau đó, vẽ hình ảnh của bạn trên đó:

ax.imshow(your_image, aspect='auto')
fig.savefig(fname, dpi)

Các aspecttham số thay đổi kích thước pixel để đảm bảo họ điền vào kích thước con số quy định tại fig.set_size_inches(…). Để biết cách chơi với những thứ này, hãy đọc qua tài liệu của matplotlib , đặc biệt là về chủ đề Axes, Axis và Artist.


4
nope, tôi vẫn có một số biên giới nhỏ trong suốt, và những gì tôi muốn là không có biên giới nào cả , hình ảnh tinh khiết
Jakub M.

5
Nếu bạn đặt thủ công các tham số whtrong fig.set_size_inches(w,h)dpitham số vào fig.savefig(fname, dpi)sao cho kết quả là 24px x 24px, nó sẽ hoạt động tốt. Ví dụ, w = h = 1dpi = 24
matehat,

5
Tôi đã phải kết hợp cả câu trả lời này và câu trả lời dưới đây của Mostafa Pakparvar. Bạn không chỉ cần tắt các trục mà còn cần set_visible thành false để đảm bảo khoảng trắng biến mất. (wtf?)
Bryce Guinta

6
Chỉ cần thử điều này bằng cách sử dụng matplotlib v2.2.2, nó hoạt động hoàn hảo (ngoại trừ imshowcú pháp của nó được thay đổi thành aspect='auto'thay vì 'normal').
Luke

2
Đây là cách tiếp cận đúng. ax = plt.Axes(fig, [0., 0., 1., 1.])là những gì làm cho nó hoạt động.
greatvovan

73

Một giải pháp dễ dàng hơn dường như là:

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

2
Điều này làm việc rất tốt cho tôi. Ngoài ra, pad_inches có thể được thay đổi thành kích thước mong muốn một cách dễ dàng. Cảm ơn!
Curious2learn

27
Tôi vẫn nhận được lợi nhuận trắng với điều này.
Fábio Perez

3
Tôi đã có thể cập nhật điều này cho các phiên bản mới hơn / vấn đề về lề còn lại chỉ bằng cách thêm transparent = True fig.savefig('out.png', bbox_inches='tight',transparent=True, pad_inches=0)
mdoc-2011

2
Vẫn có các trục và dấu tích và mọi thứ với cái này :(
BjornW

3
Điều này không làm bất cứ điều gì cả. Nó sẽ cung cấp cho bạn hình với tất cả các trục và nhãn.
1313e

27

Bạn có thể tìm thấy hộp của hình ảnh bên trong trục (bằng cách sử dụng get_window_extent) và sử dụng bbox_inchestham số để chỉ lưu phần đó của hình ảnh:

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)

Tôi đã học được mẹo này từ Joe Kington ở đây .


6
chỉ plt.axis('off')giúp. Các câu trả lời khác không giúp ích nhiều.
imsrgadich

3
Điều này hoạt động khá tốt. Tuy nhiên trong trường hợp của tôi vẫn có một đường viền nhỏ màu trắng. Bất kỳ ý tưởng về cách loại bỏ đường viền này?
user3731622

@ user3731622, vui lòng thử plt.savefig('/temp/test.png', bbox_inches='tight', transparent=True, pad_inches=0)thay vìplt.savefig('/tmp/test.png', bbox_inches=extent)
Cloud Cho

17

Tôi đã thử một số tùy chọn trong trường hợp của mình và giải pháp tốt nhất là:

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

sau đó lưu hình của bạn với savefig


1
Trong số tất cả các giải pháp này, đây là giải pháp duy nhất phù hợp với tôi.
Puff

8

Tôi sẽ đề xuất câu trả lời heron13 với một bổ sung nhỏ được mượn từ đây để loại bỏ phần đệm còn lại sau khi đặt bbox ở chế độ chặt chẽ, do đó:

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)

Tôi gặp lỗi nói rằng get_xaxis () và get_yaxis () không tồn tại. Bất kỳ ý tưởng tại sao điều đó sẽ xảy ra?
Jacob Malachowski

Thực hiện một trục () đối tượng, sau đó sử dụng ax.xaxis và ax.yaxis
perigon

Gặp lỗi khi nói đối tượng 'danh sách' không có thuộc tính 'get_xaxis'
Haozhe Xie

7

Cái này phù hợp với tôi

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

3

Tôi đã gặp vấn đề tương tự khi thực hiện một số hình dung bằng librosa , nơi tôi muốn trích xuất nội dung của cốt truyện mà không có bất kỳ thông tin nào khác. Vì vậy, đây là cách tiếp cận của tôi. câu trả lời unutbu cũng giúp tôi thực hiện để làm việc.

    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()

Điều này đã giúp tôi đi đúng hướng, nhưng tôi gặp hai vấn đề: 1) Tôi phải đặt dpi thành một số lớn hơn 1 để tránh lỗi phông chữ trong sổ ghi chép jupyter của tôi; và 2) vẫn còn một đường viền nhỏ nên tôi phải thay đổi phạm vi Bbox theo cách thủ công extent.get_points()*np.array([[1.1],[.9]]).
Bob Baxley

cảm ơn vì câu trả lời đầy đủ có thể giúp ích cho người khác.
GPrathap

3

Đối với bất kỳ ai đang cố gắng làm điều này trong Jupyter

 plt.axis('off')

 spec = plt.imshow

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

2

Mặc dù các câu trả lời ở trên giải quyết việc xóa lề và đệm, nhưng chúng không hoạt động đối với tôi trong việc xóa nhãn. Đây là những gì đã hiệu quả, cho bất kỳ ai sau này gặp phải câu hỏi này:

Giả sử bạn muốn có một lưới 2x2 các ô con từ bốn hình ảnh được lưu trữ trong 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

Tôi cũng đã cố gắng loại bỏ đường viền, sử dụng các mẹo ở đây nhưng không thực sự hiệu quả. Một số lần mò mẫm và tôi thấy rằng việc thay đổi màu sắc khiến tôi không có đường viền trong jupyter labs (Bất kỳ màu nào cũng dẫn đến việc loại bỏ đường viền trắng). Hi vọng điêu nay co ich.

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()

nhập mô tả hình ảnh ở đây



0

Đối với tôi, mã này tạo ra kích thước hình ảnh đầu vào tương tự không có khung và trục từ các mã matehat , unutbuWHZW :

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)

Môi trường thời gian chạy:
Python
3.6.10 Matplotlib 3.2.1
Hệ điều hành Windows 10

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.