माटप्लोटलिब प्लॉट्स: धुरी, किंवदंतियों और सफेद स्थानों को हटाना


285

मैं पायथन और मैटलोटलिब के लिए नया हूं, मैं बस एक छवि पर कॉलोरामैप लागू करना चाहता हूं और परिणामी छवि को लिखूंगा, बिना एक्सिस, लेबल, शीर्षक या कुछ भी उपयोग किए बिना आमतौर पर स्वचालित रूप से मैटलपोटलिब द्वारा जोड़ा जाता है। मैंने जो किया था यह रहा:

def make_image(inputname,outputname):
    data = mpimg.imread(inputname)[:,:,0]
    fig = plt.imshow(data)
    fig.set_cmap('hot')
    fig.axes.get_xaxis().set_visible(False)
    fig.axes.get_yaxis().set_visible(False)
    plt.savefig(outputname)

यह आंकड़ा की धुरी को सफलतापूर्वक हटाता है, लेकिन बचाए गए आंकड़े एक सफेद गद्दी और वास्तविक छवि के चारों ओर एक फ्रेम प्रस्तुत करता है। मैं उन्हें कैसे निकाल सकता हूं (कम से कम सफेद पैडिंग)? धन्यवाद


2
इस प्रश्न के सभी समाधानों पर ध्यान केंद्रित किया गया है imshow। यदि आपके पास एक स्कैल्पलॉट है, तो इसके बजाय निम्नलिखित उत्तर आपकी सहायता कर सकते हैं: stackoverflow.com/a/40727744/4124317
ImportanceOfBeingErnest

जवाबों:


373

मुझे लगता है कि कमान axis('off')प्रत्येक धुरी और सीमा को अलग-अलग बदलने की तुलना में अधिक संक्षेप में समस्याओं में से एक का ख्याल रखती है। यह अभी भी सीमा के आसपास सफेद स्थान छोड़ देता है। कमांड bbox_inches='tight'को जोड़ने से savefigआप लगभग वहां पहुंच जाते हैं, आप नीचे दिए गए उदाहरण में देख सकते हैं कि बचा हुआ सफेद स्थान बहुत छोटा है, लेकिन फिर भी मौजूद है।

ध्यान दें कि bbox_inches=0स्ट्रिंग के बजाय 'tight'माटाप्लोटिब के नए संस्करणों की आवश्यकता हो सकती है (@episodeyang और @ कद्रच के माध्यम से)

from numpy import random
import matplotlib.pyplot as plt

data = random.random((5,5))
img = plt.imshow(data, interpolation='nearest')
img.set_cmap('hot')
plt.axis('off')
plt.savefig("test.png", bbox_inches='tight')

यहां छवि विवरण दर्ज करें


4
Unutbu के सुझाव के बाद, आप इस्तेमाल कर सकते हैं fig = plt.figure(), ax = plt.axes([0,0,1,1])है, तो plt.imshow(data,interpolation="nearest"। के साथ संयुक्त plt.axis("off"), यह छवि के बगल में सब कुछ से छुटकारा चाहिए, उम्मीद है!
PhilMacKay

5
प्रश्न ({fig.axes.get_xaxis) () से_विशेष (गलत) और fig.axes.get_yaxis ()। Set_vanish (झूठा)} के तरीकों को मिलाकर {plt .axis ('बंद')}) के लिए समस्या को ठीक किया। मुझे। (अब कोई व्हाट्सएप नहीं)। और Savefig में अपने {pad_inches} को 0.
Domagoj

3
मैं सिर्फ इस मुद्दे पर भागा, इस सूत्र में कोई भी समाधान नहीं है, और इससे जुड़े लोगों ने काम किया। हालांकि स्पष्ट रूप से निर्दिष्ट करने bbox_inches=0से चाल चली गई।
kadrach

1
ध्यान दें कि यदि आप plt.imshow पर 'प्लॉटिंग' सामान कर रहे हैं, जैसा कि plt.plot (x, y) में है, तो आपको मैट्रिक्स के आकार के लिए xlim और ylim सेट करने की आवश्यकता है।
मैथ्यू जेर

1
यह अब काम नहीं करता है। मुझे यह पता लगाने के लिए एक घंटा लगा। नीचे उत्तर देखें।
एपिसोड

107

मैंने इस तरकीब को matehat से सीखा , यहाँ :

import matplotlib.pyplot as plt
import numpy as np

def make_image(data, outputname, size=(1, 1), dpi=80):
    fig = plt.figure()
    fig.set_size_inches(size)
    ax = plt.Axes(fig, [0., 0., 1., 1.])
    ax.set_axis_off()
    fig.add_axes(ax)
    plt.set_cmap('hot')
    ax.imshow(data, aspect='equal')
    plt.savefig(outputname, dpi=dpi)

# data = mpimg.imread(inputname)[:,:,0]
data = np.arange(1,10).reshape((3, 3))

make_image(data, '/tmp/out.png')

पैदावार

यहां छवि विवरण दर्ज करें


3
मुझे पूरा यकीन है कि आपके पास सही उत्तर है (हालांकि ऐसा करने का एक से अधिक तरीका है), लेकिन मैं सोच रहा हूं कि क्या आप बता सकते हैं कि यह सही उत्तर क्यों है? आपके कोड के बारे में सफेद स्थान को क्या हटाता है?
यानि

4
@Yann, दस्तावेज़ीकरण के अलावा, मुझे एक बार में एक पंक्ति में यह देखने के लिए बहुत उपयोगी लगता है कि प्रत्येक कमांड का क्या प्रभाव होता है। यह अनुभवजन्य तरीका है!
unutbu

4
सफेद सीमा को हटाने वाली रेखा है plt.Axes(fig, [0,0,1,1])। यह (0%, 0%) पर स्थित बिंदु पर निचले बाएँ कोने के साथ कुल्हाड़ियों का एक सेट बनाने के लिए, और (100%, 100%) की चौड़ाई और ऊंचाई के साथ मैट्रिक्स को बताता है।
फिलमाकेय

यह अधिक सही उत्तर है, क्योंकि यह न केवल सहेजी गई छवि के लिए सफेद स्थान को हटाता है, बल्कि ऑनस्क्रीन भूखंडों के लिए भी है।
मैक्सएनो

धन्यवाद, यह केवल मेरे Ubuntu पर ठीक काम करता है :)
AlphaGoMK

56

संभव सरलतम उपाय:

मैंने सवाल में वर्णित विधि और हुक द्वारा उत्तर से विधि को संयुक्त किया।

fig = plt.imshow(my_data)
plt.axis('off')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
plt.savefig('pict.png', bbox_inches='tight', pad_inches = 0)

इस कोड के बाद कोई व्हाट्सएप और कोई फ्रेम नहीं है।

कोई व्हाट्सएप, एक्सिस या फ्रेम नहीं


3
आपकी विधि ने इस छवि के आसपास के सभी सफेद रिक्त स्थान को निकाल दिया, अच्छा काम, लेकिन मुझे अभी भी नहीं पता है कि कमांड fig.axes.get_xaxis().set_visible(False)को समस्या को हल करने के लिए क्यों जोड़ें । धन्यवाद
ollydbg23

5
हां यदि आप इस आदेश को नहीं कहते हैं तो अधिकांश श्वेत रिक्त स्थान हटा दिए जाएंगे। हालाँकि मेरे मामले में मेरे प्लॉट और किनारे की छवि (शायद 2px चौड़ी) के बीच कुछ जगह अभी भी थी। निम्नलिखित आदेशों को कॉल करके मैंने उन जिद्दी स्थानों से छुटकारा पा लिया है।
डोमगोज

3
ध्यान दें, हालांकि, ऊपर एक ही आकृति में कई कुल्हाड़ियों की उपस्थिति में विफल हो जाएगा (मेरे मामले में साजिश में एक एम्बेडेड छवि)। समाधान: fig.axes[0]और सामान्य रूप से सभी या चयनित कुल्हाड़ियों में।
आयोनिस फिलिपिपिडिस

29

imsaveअभी तक किसी ने उल्लेख नहीं किया है, जो इसे वन-लाइनर बनाता है:

import matplotlib.pyplot as plt
import numpy as np

data = np.arange(10000).reshape((100, 100))
plt.imsave("/tmp/foo.png", data, format="png", cmap="hot")

यह इमेज को सीधे स्टोर करता है जैसा कि है, अर्थात इसमें कोई एक्सिस या बॉर्डर / पैडिंग नहीं है।

यहां छवि विवरण दर्ज करें


यह वही है जो मैं ज्यादातर समय करता हूं, लेकिन ऐसे उदाहरण हैं जब मुझे कलरबार की आवश्यकता होती है, और इन मामलों में imsave मुझे बचा नहीं सकता है।
एलियास

9

आप आंकड़े की सीमा को bbox_inchesतर्क तक भी निर्दिष्ट कर सकते हैं । यह आंकड़ा के आसपास सफेद गद्दी से छुटकारा मिलेगा।

def make_image(inputname,outputname):
    data = mpimg.imread(inputname)[:,:,0]
    fig = plt.imshow(data)
    fig.set_cmap('hot')
    ax = fig.gca()
    ax.set_axis_off()
    ax.autoscale(False)
    extent = ax.get_window_extent().transformed(plt.gcf().dpi_scale_trans.inverted())
    plt.savefig(outputname, bbox_inches=extent)

8

इससे सभी पैडिंग और सीमाएँ हटा दी जानी चाहिए:

from matplotlib import pyplot as plt

fig = plt.figure()
fig.patch.set_visible(False)

ax = fig.add_subplot(111)

plt.axis('off')
plt.imshow(data)

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

अधूरा जवाब! यह मुझे वहां के 99% तरह से मिला। अधिक अपवित्र होना चाहिए क्योंकि यह सबसे अधिक अद्यतित है
नाथन

अगर आपके पास एक्सिस ऑब्जेक्ट ( ax) नहीं है तो भी यह काम करता है extent = plt.gca().get_window_extent().transformed(fig.dpi_scale_trans.inverted())
टोस्ट


3

उत्कीर्ण जवाब अब काम नहीं करता है। इसे काम पर लाने के लिए आपको मैन्युअल रूप से एक अक्ष सेट करना होगा [0, 0, 1, 1], या आकृति के तहत पैच को हटा दें।

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(5, 5), dpi=20)
ax = plt.Axes(fig, [0., 0., 1., 1.])
fig.add_axes(ax)
plt.imshow([[0, 1], [0.5, 0]], interpolation="nearest")
plt.axis('off')                                # same as: ax.set_axis_off()

plt.savefig("test.png")

वैकल्पिक रूप से, आप केवल पैच को हटा सकते हैं। गद्दी हटाने के लिए आपको एक सबप्लॉट जोड़ने की आवश्यकता नहीं है। नीचे दिए गए व्लादि के जवाब से यह सरल हो गया है

fig = plt.figure(figsize=(5, 5))
fig.patch.set_visible(False)                   # turn off the patch

plt.imshow([[0, 1], [0.5, 0]], interpolation="nearest")
plt.axis('off')

plt.savefig("test.png", cmap='hot')

यह 3.0.32019/06/19 पर संस्करण के साथ परीक्षण किया गया है। छवि देखें bellow:

यहां छवि विवरण दर्ज करें

उपयोग करने के लिए एक बहुत आसान काम है pyplot.imsave। विवरण के लिए, लुटर के उत्तर को देखें


मेरे लिए केवल एक्सिस संस्करण काम करता है। मैं पैच बंद संस्करण के साथ गद्दी मिलता है। वैसे भी!
save_jeff

2

मुझे उबंटू का जवाब पसंद आया , लेकिन यह स्पष्ट रूप से नहीं दिखा रहा था कि गैर-वर्ग छवियों के लिए आकार कैसे आउट-ऑफ-द-बॉक्स सेट किया जाए, इसलिए मैंने इसे आसान कॉपी-पेस्ट के लिए संशोधित किया:

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

def save_image_fix_dpi(data, dpi=100):
    shape=np.shape(data)[0:2][::-1]
    size = [float(i)/dpi for i in shape]

    fig = plt.figure()
    fig.set_size_inches(size)
    ax = plt.Axes(fig,[0,0,1,1])
    ax.set_axis_off()
    fig.add_axes(ax)
    ax.imshow(data)
    fig.savefig('out.png', dpi=dpi)
    plt.show()

बॉर्डर के बिना छवियों को सहेजना आसान है जो भी आप चुनते हैं अगर पिक्सेल_साइज़ / डीपीआई = आकार रखा जाता है।

data = mpimg.imread('test.png')
save_image_fix_dpi(data, dpi=100)

यहां छवि विवरण दर्ज करें

हालाँकि प्रदर्शित करना डरावना है। यदि आप छोटी डीपीआई चुनते हैं, तो आपकी छवि का आकार आपकी स्क्रीन से बड़ा हो सकता है और आपको प्रदर्शन के दौरान सीमा मिलती है। फिर भी, यह बचत को प्रभावित नहीं करता है।

के लिए

save_image_fix_dpi(data, dpi=20)

प्रदर्शन सीमाबद्ध हो जाता है (लेकिन काम बचाता है): यहां छवि विवरण दर्ज करें


1

सबसे पहले, कुछ छवि प्रारूपों (यानी TIFF ) के लिए आप वास्तव में हेडर में कॉलोरामैप को सेव कर सकते हैं और अधिकांश दर्शक आपके डेटा को कॉलमैप के साथ दिखाएंगे।

वास्तविक matplotlibछवि को सहेजने के लिए , जो छवियों में एनोटेशन या अन्य डेटा जोड़ने के लिए उपयोगी हो सकता है, मैंने निम्नलिखित समाधान का उपयोग किया है:

fig, ax = plt.subplots(figsize=inches)
ax.matshow(data)  # or you can use also imshow
# add annotations or anything else
# The code below essentially moves your plot so that the upper
# left hand corner coincides with the upper left hand corner
# of the artist
fig.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)
# now generate a Bbox instance that is the same size as your
# single axis size (this bbox will only encompass your figure)
bbox = matplotlib.transforms.Bbox(((0, 0), inches))
# now you can save only the part of the figure with data
fig.savefig(savename, bbox_inches=bbox, **kwargs)

0

हर किसी से भयानक जवाब के लिए धन्यवाद ... मुझे बिल्कुल यही समस्या थी कि कोई छवि बिना किसी अतिरिक्त पैडिंग / स्पेस आदि के प्लॉट करना चाहता था, इसलिए यहां हर किसी के विचारों को खोजने के लिए सुपर खुश था।

बिना पैडिंग वाली छवि के अलावा, मैं केवल एक सरल छवि प्लॉट से परे, एनोटेशन आदि को आसानी से जोड़ने में सक्षम होना चाहता था।

इसलिए मैंने जो काम किया , वह आंकड़ा सृजन के समय में एक साधारण आवरण बनाने के लिए डेविड के जवाब को सिस्नेम्स के साथ जोड़ रहा था । जब आप इसका उपयोग करते हैं, तो आपको बाद में imsave () या कुछ और के साथ किसी भी बदलाव की आवश्यकता नहीं होती है:

def get_img_figure(image, dpi):
    """
    Create a matplotlib (figure,axes) for an image (numpy array) setup so that
        a) axes will span the entire figure (when saved no whitespace)
        b) when saved the figure will have the same x/y resolution as the array, 
           with the dpi value you pass in.

    Arguments:
        image -- numpy 2d array
        dpi -- dpi value that the figure should use

    Returns: (figure, ax) tuple from plt.subplots
    """

    # get required figure size in inches (reversed row/column order)
    inches = image.shape[1]/dpi, image.shape[0]/dpi

    # make figure with that size and a single axes
    fig, ax = plt.subplots(figsize=inches, dpi=dpi)

    # move axes to span entire figure area
    fig.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)

    return fig, ax
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.