Matplotlib colormap को लागू करने वाली PIL छवि में एक NumPy सरणी कैसे परिवर्तित करें


134

मुझे एक साधारण समस्या है, लेकिन मुझे इसका कोई अच्छा समाधान नहीं मिल रहा है।

मैं एक NumPy 2D सरणी लेना चाहता हूं, जो एक ग्रेस्केल छवि का प्रतिनिधित्व करता है, और इसे कुछ matplotlib colormaps को लागू करते हुए RGB PIL छवि में परिवर्तित करता है।

मैं pyplot.figure.figimageकमांड का उपयोग करके उचित पीएनजी आउटपुट प्राप्त कर सकता हूं :

dpi = 100.0
w, h = myarray.shape[1]/dpi, myarray.shape[0]/dpi
fig = plt.figure(figsize=(w,h), dpi=dpi)
fig.figimage(sub, cmap=cm.gist_earth)
plt.savefig('out.png')

हालाँकि मैं जो चाहता हूं उसे पाने के लिए इसे अनुकूलित कर सकता हूं (शायद स्ट्रिंगो का उपयोग करके पीआईएल छवि प्राप्त करता है), मुझे आश्चर्य है कि अगर ऐसा करने का कोई सरल तरीका नहीं है, क्योंकि यह छवि विज़ुअलाइज़ेशन की एक बहुत ही स्वाभाविक समस्या लगती है। आइए बताते हैं, कुछ इस तरह:

colored_PIL_image = magic_function(array, cmap)

जवाबों:


222

काफी व्यस्त एक लाइनर, लेकिन यहाँ यह है:

  1. पहले अपने NumPy सरणी को सुनिश्चित करें myarray, पर अधिकतम मूल्य के साथ सामान्यीकृत है 1.0
  2. कोलोराप को सीधे लागू करें myarray
  3. सीमा तक पुनर्विक्रय करें 0-255
  4. पूर्णांक में कनवर्ट करें, का उपयोग कर np.uint8()
  5. का उपयोग करें Image.fromarray()

और आपने कल लिया:

from PIL import Image
from matplotlib import cm
im = Image.fromarray(np.uint8(cm.gist_earth(myarray)*255))

साथ plt.savefig():

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

साथ im.save():

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


7
"कॉलोर्माप को सीधे लागू करें myarray" भाग को सीधे दिल में काट लें! मुझे नहीं पता था कि यह संभव था, धन्यवाद!
हेलटनबीकर

34
LinearSegmentedColormap (जिसमें cm.gist_earth एक उदाहरण है) के बारे में डॉक्स का अध्ययन करते हुए, मैंने पाया कि इसे "बाइट्स" तर्क के साथ कॉल करना संभव है जो पहले से ही इसे uint8 में बदल देता है। फिर, वन-लाइनर बहुत शांत हो जाता है:im = Image.fromarray(cm.gist_earth(myarray, bytes=True))
हेल्टनबिकर

1
@CiprianTomoiaga, सरणी का आकार आपके इच्छित छवि आयाम होना चाहिए। उदाहरण के लिए, एक वीजीए छवि आकृति (1024,768) के साथ एक सरणी से उत्पन्न होगी। आपको ध्यान देना चाहिए कि यह मोनोक्रोम छवियों के लिए लागू होता है। यह महत्वपूर्ण है क्योंकि आमतौर पर जब आप RGB छवि को एक सरणी में बदलते हैं, तो इसका आकार, उदाहरण के लिए, (1024,768,3) है, क्योंकि इसमें तीन चैनल हैं।
हेल्टनबिकर

5
मुझे त्रुटि मिल रही हैNameError: name 'cm' is not defined
rnso

10
@ मीसोfrom matplotlib import cm
क्वांटम 7

10
  • input = numpy_image
  • np.unit8 -> पूर्णांक में कनवर्ट करता है
  • कन्वर्ट ('RGB') -> RGB में कनवर्ट करता है
  • Image.fromarray -> एक छवि वस्तु देता है

    from PIL import Image
    import numpy as np
    
    PIL_image = Image.fromarray(np.uint8(numpy_image)).convert('RGB')
    
    PIL_image = Image.fromarray(numpy_image.astype('uint8'), 'RGB')

5
आशा है कि यह समस्या को हल कर देगा, लेकिन कृपया इसके साथ अपने कोड की व्याख्या जोड़ें ताकि उपयोगकर्ता को सही समझ मिल जाएगी जिसे वह वास्तव में चाहता है।
जयमिल पटेल

1
अच्छा, अद्यतन उत्तर। पहले वाले कई साल पहले से हैं।
कैटालिना चिरकु जूल

7

स्वीकृत उत्तर में वर्णित विधि ने अपनी टिप्पणियों में उल्लिखित परिवर्तनों को लागू करने के बाद भी मेरे लिए काम नहीं किया। लेकिन नीचे सरल कोड काम किया:

import matplotlib.pyplot as plt
plt.imsave(filename, np_array, cmap='Greys')

np_array 0..1 फ्लोट्स o2 0..255 uint8 से मानों के साथ या तो 2 डी सरणी हो सकता है, और उस स्थिति में इसे cmap की आवश्यकता होती है। 3D सरणियों के लिए, cmap को अनदेखा किया जाएगा।

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