Xóa khoảng trắng xung quanh ảnh đã lưu trong matplotlib


172

Tôi cần phải chụp ảnh và lưu nó sau một quá trình. Con số trông ổn khi tôi hiển thị nó, nhưng sau khi lưu hình, tôi có một khoảng trắng xung quanh ảnh đã lưu. Tôi đã thử 'tight'tùy chọn cho savefigphương thức, cũng không hoạt động. Mật mã:

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

Tôi đang cố gắng vẽ một biểu đồ cơ bản bằng cách sử dụng NetworkX trên một hình và lưu nó. Tôi nhận ra rằng không có biểu đồ, nó hoạt động, nhưng khi thêm biểu đồ tôi sẽ có khoảng trắng xung quanh ảnh đã lưu;

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


Điều thực sự hiệu quả với tôi là cắt pdf bằng một công cụ khác, chẳng hạn như pdfcrop.
toliveira

Câu trả lời:


169

Tôi không thể khẳng định tôi biết chính xác lý do tại sao hoặc cách thức giải pháp trên máy tính của tôi, nhưng đây là điều tôi phải làm khi tôi muốn phác thảo phác thảo của một vài phần của aerofoil - không có lề trắng - vào tệp PDF. (Lưu ý rằng tôi đã sử dụng matplotlib trong sổ ghi chép IPython, với cờ -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)

Tôi đã cố gắng hủy kích hoạt các phần khác nhau của điều này, nhưng điều này luôn dẫn đến một lề trắng ở đâu đó. Bạn thậm chí có thể sửa đổi điều này để giữ cho các đường mỡ gần giới hạn của hình không bị cạo do thiếu lề.


6
Cuối cùng một cái gì đó hoạt động, cảm ơn bạn rất nhiều! Nhân tiện, trong trường hợp của tôi chỉ có hai dòng sử dụng set_major_locatorlà cần thiết.
Florian Brucker

6
Tôi đã dành một giờ cuối cùng để thử nhiều thứ khác nhau và không thể thoát khỏi viền trắng 1px. Đây là điều duy nhất có hiệu quả - cụ thể là pad_inches=0những câu trả lời khác không đề cập.
AnnanFay

1
set_major_locatorlà chìa khóa cho tôi.
kmac

16
pad_inchesđã giúp tôi
Myles Baker

5
matplotlib.ticker.NullLocator ()
Joop

200

Bạn có thể xóa phần đệm trắng bằng cách đặt bbox_inches="tight"vào savefig:

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

Bạn sẽ phải đặt đối số thành bbox_inchesmột chuỗi, có lẽ đây là lý do tại sao nó không hoạt động sớm hơn đối với bạn.


Các bản sao có thể có:

Lô Matplotlib: loại bỏ trục, truyền thuyết và khoảng trắng

Làm thế nào để thiết lập lề cho một con số matplotlib?

Giảm lề trái và phải trong lô matplotlib


1
Nếu bạn có nhiều ô con và muốn lưu từng ô, bạn cũng có thể sử dụng nó fig.savefig(). ( plt.savefig()sẽ không hoạt động trong trường hợp đó.)
Abhranil Das

30
Điều đó không hoàn toàn đúng. Khi bạn sử dụng bbox_inchestùy chọn đó, sẽ có một mặc định khác để lại một khoảng trống. Nếu bạn thực sự muốn thoát khỏi mọi thứ, bạn cũng cần phải sử dụng pad_inches=0.0. Tất nhiên, phần đệm chặt chẽ như vậy thường xuyên bị cắt, ví dụ: số mũ ...
Mike

5
Để xóa cạnh đen, bạn có thể cần phải đặtpad_inches=-0.1
lenhhoxung

10
Điều này chỉ đơn giản là không hoạt động, bạn vẫn có khoảng trắng xung quanh hình. Đặt tùy chọn trong suốt (như đã đề cập trong một số câu trả lời) cũng không thực sự giúp ích, khoảng trắng vẫn còn đó, nó chỉ trong suốt.
BjornW

1
@piperchester đó là một câu hỏi hay, nhưng có lẽ nên được hỏi như một câu hỏi mới hoàn toàn để nó không bị lạc trong các bình luận. Bạn nên liên kết câu hỏi mới với câu hỏi cũ!
Móc vào

21

Sau khi thử các câu trả lời trên mà không thành công (và một loạt các bài đăng ngăn xếp khác), cuối cùng tôi cũng làm được

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

Điều quan trọng này không bao gồm các đối số bbox hoặc padding.


4
Đây phải là câu trả lời được chấp nhận. Ngoài ra, bạn thậm chí không cần phải gọi set_axis_off. Nó không ảnh hưởng đến hình ảnh đã lưu vì sau khi subplots_adjusttrục nằm ngoài phạm vi của hình và dù sao thì henve sẽ không bị ảnh hưởng. Tuy nhiên, trong sổ ghi chép Jupyter, bạn cần vô hiệu hóa trục một cách rõ ràng, vì phần phụ trợ nội tuyến ghi đè lên các cài đặt này.
MaxPowers

20

Tôi đã tìm thấy thứ gì đó từ Arvind Pereira ( http://robotics.usc.edu/~ampereir/wordpress/?p=626 ) và dường như hoạt động với tôi:

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

7
transparent=Truesẽ làm cho nó có vẻ như không có vấn đề gì nhưng nó sẽ chỉ ẩn khoảng trắng, kích thước hình ảnh sẽ không ổn.
Vlady Veselinov

Cảm ơn đã đề cập pad_inches! Tôi ước tôi đã biết về tùy chọn này sớm hơn!
ingomueller.net

1
Điều này hoạt động cho hầu hết các lô, nhưng điều này đã loại bỏ đường viền bên phải cho ma trận nhầm lẫn của tôi. Chỉ cần thêm một phần đệm nhỏpad_inches=.25
YTZ

14

Các chức năng sau đây kết hợp câu trả lời johannes-s ở trên. Tôi đã thử nghiệm nó với plt.figureplt.subplots()với nhiều trục, và nó hoạt động độc đáo.

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

Làm việc như người ở. Câu trả lời trước đó là một số lệnh bắt buộc trong xuất khẩu của tôi.
Kevin S

11

Tôi tìm thấy các mã sau đây hoạt động hoàn hảo cho công việc.

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)

2
Nói chung, câu trả lời sẽ hữu ích hơn nhiều nếu chúng bao gồm một lời giải thích về những gì mã được dự định làm và tại sao điều đó giải quyết vấn đề mà không giới thiệu người khác.
Tim Diekmann

7

tôi theo trình tự này và nó hoạt động như một lá bùa.

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)

1
Trên thực tế, tôi thấy câu trả lời này là dễ dàng và thuận tiện hơn để sử dụng.
sikisis

1
Cái này làm việc cho tôi; câu trả lời được chấp nhận là không.
Joe

3

Đối với bất cứ ai muốn làm việc bằng pixel thay vì inch thì điều này sẽ hoạt động.

Cộng với thông thường bạn cũng sẽ cần

from matplotlib.transforms import Bbox

Sau đó, bạn có thể sử dụng như sau:

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)

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


Bạn không phải chỉ định dpi, fig.dpithay vào đó bạn có thể sử dụng cái mặc định
intsco

1

Một cách tiếp cận đơn giản hơn nhiều tôi tìm thấy là sử dụng plt.imsave:

    import matplotlib.pyplot as plt
    arr = plt.imread(path)
    plt.imsave('test.png', arr)

Câu trả lời không nản lòng. Điều này giúp tôi sau một thời gian dài tìm kiếm cách giữ lại độ phân giải và xóa khoảng trắng với plt.savefig().
nihal111

Điều này chỉ hoạt động trong trường hợp bạn muốn lưu một mảng (!) Làm hình ảnh. Điều này không cho phép lưu một con số tùy ý.
MaxPowers

Bạn có ý nghĩa gì bởi hình ảnh tùy ý? Không phải là một hình ảnh một mảng các giá trị?
Parth92

0

Bạn có thể thử điều này. Nó giải quyết vấn đề của tôi.

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

-1

Nếu bạn muốn hiển thị những gì sẽ được lưu, tôi khuyên bạn nên sử dụng plt.tight_layoutchuyển đổi, điều này thực sự thích hợp hơn vì nó không thực hiện cắt xén không cần thiết khi sử dụngplt.savefig

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

-4

Điều này làm việc cho tôi để lưu một mảng numpy được vẽ với imshow để tập tin

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