पिक्सल में सटीक आकार के साथ एक आकृति को निर्दिष्ट और सहेजना


152

मान लें कि मेरे पास 3841 x 7195 पिक्सेल आकार की एक छवि है। मैं आकृति की सामग्री को डिस्क में सहेजना चाहूंगा, जिसके परिणामस्वरूप मैं पिक्सेल में निर्दिष्ट सटीक आकार की एक छवि प्राप्त करूंगा।

कोई धुरी नहीं, कोई उपाधि नहीं। बस छवि। मैं व्यक्तिगत रूप से डीपीआई के बारे में परवाह नहीं करता हूं, क्योंकि मैं केवल उस छवि को निर्दिष्ट करना चाहता हूं जो पिक्सेल में डिस्क में स्क्रीन पर ले जाती है ।

मैंने अन्य सूत्र पढ़े हैं , और वे सभी रूपांतरण इंच के लिए करते हैं और फिर इंच में आंकड़े के आयामों को निर्दिष्ट करते हैं और किसी तरह डीपीआई को समायोजित करते हैं। मैं सटीकता के संभावित नुकसान से निपटने से बचना चाहूंगा जो पिक्सेल से इंच रूपांतरणों के परिणामस्वरूप हो सकता है।

मैंने कोशिश की है:

w = 7195
h = 3841
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(im_np, aspect='normal')
fig.savefig(some_path, dpi=1)

भाग्य के साथ नहीं (पायथन की शिकायत है कि चौड़ाई और ऊंचाई प्रत्येक 32768 (?) से कम होनी चाहिए।

सब कुछ मैंने देखा है से, matplotlibकी आवश्यकता है आंकड़ा आकार में निर्दिष्ट किया जा करने के लिए inchesऔर dpiहै, लेकिन मैं केवल में दिलचस्पी है पिक्सल आंकड़ा डिस्क में ले जाता है। मैं यह कैसे कर सकता हूँ?

स्पष्ट करने के लिए: मैं ऐसा करने के लिए एक रास्ता ढूंढ रहा हूं matplotlib, और अन्य छवि-बचत पुस्तकालयों के साथ नहीं।


मेटप्लोटलिब के साथ, आकृति का आकार सीधे इंच में सेट करना संभव नहीं है।
टीआईजीओ

जवाबों:


175

Matplotlib पिक्सल के साथ सीधे काम नहीं करता है, बल्कि भौतिक आकार और DPI के साथ काम करता है। यदि आप एक निश्चित पिक्सेल आकार के साथ एक आंकड़ा प्रदर्शित करना चाहते हैं, तो आपको अपने मॉनिटर की डीपीआई जानने की आवश्यकता है। उदाहरण के लिए यह लिंक आपके लिए यह पता लगाएगा।

यदि आपके पास 3841x7195 पिक्सेल की छवि है, तो यह संभव नहीं है कि आप मॉनिटर करेंगे कि वह बड़ा है, इसलिए आप उस आकार का एक आंकड़ा नहीं दिखा पाएंगे (matplotlib को स्क्रीन में फिट होने के लिए आकृति की आवश्यकता होती है, यदि आप एक आकार पूछते हैं बहुत बड़ी स्क्रीन आकार में सिकुड़ जाएगी)। आइए कल्पना करें कि आप एक उदाहरण के लिए 800x800 पिक्सेल की छवि चाहते हैं। मेरे मॉनिटर में 800x800 पिक्सेल की छवि दिखाने का तरीका यहां बताया गया है my_dpi=96:

plt.figure(figsize=(800/my_dpi, 800/my_dpi), dpi=my_dpi)

तो आप मूल रूप से केवल अपने डीपीआई द्वारा इंच में आयामों को विभाजित करते हैं।

यदि आप एक विशिष्ट आकार का एक आंकड़ा बचाना चाहते हैं, तो यह अलग बात है। स्क्रीन डीपीआई अब इतना महत्वपूर्ण नहीं है (जब तक कि आप एक आंकड़ा नहीं मांगते हैं जो स्क्रीन में फिट नहीं होगा)। 800x800 पिक्सेल आकृति के एक ही उदाहरण का उपयोग करके, हम dpiकीवर्ड के उपयोग से इसे विभिन्न प्रस्तावों में सहेज सकते हैं savefig। इसे उसी रिज़ॉल्यूशन में सेव करने के लिए, जैसे स्क्रीन एक ही डीपीआई का उपयोग करती है:

plt.savefig('my_fig.png', dpi=my_dpi)

8000x8000 पिक्सेल छवि के रूप में इसे सहेजने के लिए, dpi का 10 गुना बड़ा उपयोग करें:

plt.savefig('my_fig.png', dpi=my_dpi * 10)

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

अपने उदाहरण पर वापस जा रहे हैं, अगर आप 3841 x 7195 पिक्सेल के साथ एक छवि को सहेजना चाहते हैं, तो आप निम्न कार्य कर सकते हैं:

plt.figure(figsize=(3.841, 7.195), dpi=100)
( your code ...)
plt.savefig('myfig.png', dpi=1000)

ध्यान दें कि मैंने अधिकांश स्क्रीन में फिट होने के लिए 100 के आंकड़े dpi का उपयोग किया, लेकिन dpi=1000आवश्यक रिज़ॉल्यूशन प्राप्त करने के लिए सहेजा गया। मेरे सिस्टम में यह 3840x7190 पिक्सल के साथ एक पीएनजी पैदा करता है - ऐसा लगता है कि बचाया गया डीपीआई हमेशा चयनित मूल्य से 0.02 पिक्सेल / इंच छोटा होता है, जिसका बड़े छवि आकारों पर एक (छोटा) प्रभाव होगा। इसकी कुछ और चर्चा यहाँ


5
यह याद रखना आसान है कि मॉनिटर के आकार (और इसलिए मानक ब्राउज़र और यूआई विंडो आकार) सामान्य रूप से 96 डीपीआई के संदर्भ में हैं - 96 के गुणक। अचानक 1440 पिक्सल की तरह संख्या सार्थक (15 इंच) इस तरह से सोचा जाने पर।
डैनी स्टेपल

पास figsizeकरने के लिए यह काम नहीं कर सका plt.figure। इसका समाधान अन्य उत्तरों के अनुसार करना था और इसे बिना बुलाए करने के बाद figsize, फिर कॉल करेंfig.set_size_inches(w,h)
त्रिनिदाद

के लिए डॉक्स figureऔर savefig
संभालें

लिंक Apple वज्र प्रदर्शन के लिए सही मान नहीं दिखाता है।
दिमित्री

मुझे यह समाधान पसंद है, लेकिन मेरे पास एक चेतावनी है। पाठ का आकार डीपीआई के रूप में विपरीत रूप से मापता है। (मेरा सिस्टम मैकबुक प्रो, ओएस एक्स है), इसलिए इंटरएक्टिव प्रिंटिंग के लिए डीपीआई को बड़े (10 * my_dpi की तरह) बनाने के लिए पाठ को अदृश्यता के करीब ले जाता है।
प्रो हस्टर

16

यह मेरे लिए आपके कोड के आधार पर काम करता है, जिसमें रंग शोर और वांछित आयामों के साथ 93Mb png छवि उत्पन्न होती है:

import matplotlib.pyplot as plt
import numpy

w = 7195
h = 3841

im_np = numpy.random.rand(h, w)

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(im_np, aspect='normal')
fig.savefig('figure.png', dpi=1)

मैं लिनक्स मिंट 13 में पायथन 2.7 पुस्तकालयों के अंतिम पीआईपी संस्करणों का उपयोग कर रहा हूं।

उम्मीद है की वो मदद करदे!


4
बहुत कम डीपीआई सेट करने का मतलब होगा कि फॉन्ट शायद ही दिखाई देंगे, जब तक कि बहुत बड़े फॉन्ट साइज स्पष्ट रूप से उपयोग न किए जाएं।
टीआईजीओ

1
यह शायद बेहतर है कि एक उच्च डीपीआई सेट करें और उस डीपीआई द्वारा अपने इंच आकार (जो किसी भी तरह से मनमाना है) को विभाजित करें। इसके अलावा, आपका सेटअप पिक्सेल प्रजनन के लिए एक सटीक पिक्सेल का उत्पादन करता है, धन्यवाद!
फ्रेंचकेवलर

मैं इस पर कथानक तत्वों (हलकों, लाइनों, ...) के साथ चित्रों को सहेजने से पहले इसका उपयोग करने की कोशिश कर रहा हूं। यह लिनिविथ को परेशान करता है, जिससे कि तत्व मुश्किल से दिखाई देते हैं।
गौथियर

5

टियागो द्वारा स्वीकार किए गए जवाब के आधार पर, यहां एक छोटा जेनेरिक फ़ंक्शन है जो एक छवि के लिए एक समान सरणी का निर्यात करता है जिसमें समान रिज़ॉल्यूशन होता है:

import matplotlib.pyplot as plt
import numpy as np

def export_figure_matplotlib(arr, f_name, dpi=200, resize_fact=1, plt_show=False):
    """
    Export array as figure in original resolution
    :param arr: array of image to save in original resolution
    :param f_name: name of file where to save figure
    :param resize_fact: resize facter wrt shape of arr, in (0, np.infty)
    :param dpi: dpi of your screen
    :param plt_show: show plot or not
    """
    fig = plt.figure(frameon=False)
    fig.set_size_inches(arr.shape[1]/dpi, arr.shape[0]/dpi)
    ax = plt.Axes(fig, [0., 0., 1., 1.])
    ax.set_axis_off()
    fig.add_axes(ax)
    ax.imshow(arr)
    plt.savefig(f_name, dpi=(dpi * resize_fact))
    if plt_show:
        plt.show()
    else:
        plt.close()

जैसा कि tiago द्वारा पिछले उत्तर में कहा गया है, स्क्रीन DPI को पहले खोजने की आवश्यकता है, जो कि उदाहरण के लिए यहां किया जा सकता है: http://dpi.lv

मैंने resize_factफ़ंक्शन में एक अतिरिक्त तर्क जोड़ा है जो आप छवि को मूल रिज़ॉल्यूशन के 50% (0.5) में निर्यात कर सकते हैं, उदाहरण के लिए।


2

ओपी 1: 1 पिक्सेल डेटा संरक्षित करना चाहता है। विज्ञान छवियों के साथ काम करने वाले एक खगोल विज्ञानी के रूप में मैं छवि डेटा के किसी भी प्रक्षेप को अनुमति नहीं दे सकता क्योंकि यह अज्ञात और अप्रत्याशित शोर और त्रुटियों को पेश करेगा। उदाहरण के लिए, यहाँ एक 480x480 छवि से एक स्निपेट है जिसे pyplot.savefig () के माध्यम से सहेजा गया है: पिक्सेल का विस्तार, जो matplotlib लगभग 2x2 होने का संकल्प लेता है , लेकिन 1x2 पिक्सेल के कॉलम पर ध्यान दें

आप देख सकते हैं कि अधिकांश पिक्सेल केवल दोगुने थे (इसलिए 1x1 पिक्सेल 2x2 हो जाता है) लेकिन कुछ कॉलम और पंक्तियाँ 1x2 या 2x1 प्रति पिक्सेल बन गईं, जिसका अर्थ है कि मूल विज्ञान डेटा बदल दिया गया है।

जैसा कि अलका ने संकेत दिया था, plt.imsave () जो ओपी के लिए पूछ रहा है वह हासिल करेगा। मान लें कि आपके पास छवि डेटा छवि छवि im में संग्रहीत है, तो कोई ऐसा कुछ कर सकता है

plt.imsave(fname='my_image.png', arr=im, cmap='gray_r', format='png')

जहाँ फ़ाइल नाम में इस उदाहरण में "पीएनजी" एक्सटेंशन है (लेकिन आपको अभी भी प्रारूप को प्रारूप = 'पीएनजी' के साथ निर्दिष्ट करना होगा जहाँ तक मैं बता सकता हूं), छवि सरणी को गिरफ्तार किया गया है, और हमने उलटा ग्रेस्केल "ग्रे_आर" चुना उपनिवेश के रूप में। मैं डायनामिक रेंज निर्दिष्ट करने के लिए आमतौर पर vmin और vmax जोड़ता हूं लेकिन ये वैकल्पिक हैं।

अंतिम परिणाम im सरणी के समान पिक्सेल आयामों की एक png फ़ाइल है।

नोट: ओपी ने कोई कुल्हाड़ी निर्दिष्ट नहीं की, आदि जो कि यह समाधान वास्तव में करता है। यदि कोई कुल्हाड़ियों, टिक्स आदि को जोड़ना चाहता है, तो मेरा पसंदीदा तरीका यह है कि एक अलग प्लॉट पर, पारदर्शी = ट्रू (PNG या PDF) के साथ सेव करके बाद में इमेज पर बाद में ओवरले करें। यह गारंटी देता है कि आपने मूल पिक्सेल बरकरार रखा है।


धन्यवाद। जब से मैंने यह प्रश्न पूछा है, तब से कुछ साल हो गए हैं, लेकिन जो मुझे याद है और आपके उत्तर में देख रहा हूँ, यह तब अच्छी तरह से काम करेगा जब आप एक चित्र के रूप में डेटा की एक सरणी को सहेजने का प्रयास कर रहे हों, लेकिन क्या होगा यदि आप सहेजना चाहते हैं समझ में ही (चाहे उसकी सारी सामग्री को) और अभी भी नियंत्रित कर बिल्कुल जिसके परिणामस्वरूप छवि फ़ाइल के पिक्सेल आयाम?
Amelio Vazquez-Reina

-1

plt.imsave ने मेरे लिए काम किया। आप यहाँ दस्तावेज़ पा सकते हैं: https://matplotlib.org/3.2.1/api/_as_gen/matplotlib.pyplot.imsave.html

#file_path = directory address where the image will be stored along with file name and extension
#array = variable where the image is stored. I think for the original post this variable is im_np
plt.imsave(file_path, array)

कृपया नमूना कोड जोड़ें, जो यह निर्धारित कर रहा है कि आप मूल पोस्ट के उपयोग मामले के लिए कौन से पैरामीटर सेट कर रहे हैं और मूल्यों की अनुशंसा करते हैं।
सारा मेसर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.