2011-03-22 11 views
14

मैं अपने चार्ट को छवियों में सहेजने की प्रक्रिया को तेज करने की कोशिश कर रहा हूं। अभी मैं एक सीस्ट्रिंग ऑब्जेक्ट बना रहा हूं जहां मैं savefig का उपयोग करके चार्ट को सहेजता हूं; लेकिन मैं वास्तव में, छवि को बचाने के इस तरीके को बेहतर बनाने के लिए वास्तव में किसी भी मदद की सराहना करता हूं। मुझे इस ऑपरेशन को दर्जनों बार करना है, और savefig कमांड बहुत धीमा है; ऐसा करने का एक बेहतर तरीका होना चाहिए। मैंने इसे असम्पीडित कच्ची छवि के रूप में सहेजने के बारे में कुछ पढ़ा है, लेकिन मुझे इसका कोई संकेत नहीं है कि इसे कैसे किया जाए। अगर मैं एक और तेज बैकएंड पर भी स्विच कर सकता हूं तो मुझे वास्तव में एजीजी की परवाह नहीं है।Matplotlib, CSfring ऑब्जेक्ट में सहेजते समय प्रदर्शन सुधारने के लिए savefig() के विकल्प?

अर्थात्:

RAM = cStringIO.StringIO() 

CHART = plt.figure(.... 
**code for creating my chart** 

CHART.savefig(RAM, format='png') 

मैं FigureCanvasAgg बैकएंड साथ matplotlib उपयोग किया गया है।

धन्यवाद!

+0

मुझे इस बारे में बहुत कुछ पता नहीं है। लेकिन आप देख सकते हैं कि निम्न सहायता: 'format = 'raw'' या' format = 'rgba'' है। ऐसा लगता है कि वे एक ही आउटपुट का उत्पादन करते हैं। –

+0

क्या आपने यह देखने के लिए कोड को प्रोफाइल करने का प्रयास किया है कि अधिकांश समय से savefig कहां खर्च करता है? क्या आपने संकल्प (डीपीआई पैरामीटर) या अन्य छवि प्रकारों को कम करने की कोशिश की है (जेपीईजी, जीआईएफ, टीआईएफ, अगर समर्थित है)? – Bernhard

+0

@ बर्नार्ड: मैं इसे कैसे कर सकता हूं? – relima

उत्तर

33

तुम सिर्फ एक कच्चे बफर चाहते हैं, (, दोनों के बीच अंतर यह है कि raw RGBA है जबकि rgb rgb है।, यह भी नहीं है print_pngprint_ps, आदि) की कोशिश fig.canvas.print_rgb, fig.canvas.print_raw, आदि

हो जाएगा ताकि savefig (100 डीपीआई) के लिए डिफ़ॉल्ट डीपीआई मान के बजाय fig.dpi का उपयोग करें। फिर भी, fig.canvas.print_raw(f) और fig.savefig(f, format='raw', dpi=fig.dpi) की तुलना भी print_canvas संस्करण मामूली तेज़ी से असाधारण रूप से तेज़ है, क्योंकि यह धुरी पैच, आदि के रंग को रीसेट करने से परेशान नहीं है, savefig डिफ़ॉल्ट रूप से करता है।

भले ही, कच्चे प्रारूप में एक आकृति को बचाने में अधिकतर समय बिताया गया है, यह आंकड़ा खींच रहा है, जिसके पास घूमने का कोई तरीका नहीं है।

किसी भी हाल में एक व्यर्थ बल्कि मज़ा उदाहरण के रूप में, निम्नलिखित पर विचार:

import matplotlib.pyplot as plt 
import numpy as np 
import cStringIO 

plt.ion() 
fig = plt.figure() 
ax = fig.add_subplot(111) 
num = 50 
max_dim = 10 
x = max_dim/2 * np.ones(num) 
s, c = 100 * np.random.random(num), np.random.random(num) 
scat = ax.scatter(x,x,s,c) 
ax.axis([0,max_dim,0,max_dim]) 
ax.set_autoscale_on(False) 

for i in xrange(1000): 
    xy = np.random.random(2*num).reshape(num,2) - 0.5 
    offsets = scat.get_offsets() + 0.3 * xy 
    offsets.clip(0, max_dim, offsets) 
    scat.set_offsets(offsets) 
    scat._sizes += 30 * (np.random.random(num) - 0.5) 
    scat._sizes.clip(1, 300, scat._sizes) 
    fig.canvas.draw() 

Brownian walk animation

अगर हम कच्चे ड्रा समय पर नज़र डालें:

import matplotlib.pyplot as plt 
import numpy as np 
import cStringIO 

fig = plt.figure() 
ax = fig.add_subplot(111) 
num = 50 
max_dim = 10 
x = max_dim/2 * np.ones(num) 
s, c = 100 * np.random.random(num), np.random.random(num) 
scat = ax.scatter(x,x,s,c) 
ax.axis([0,max_dim,0,max_dim]) 
ax.set_autoscale_on(False) 

for i in xrange(1000): 
    xy = np.random.random(2*num).reshape(num,2) - 0.5 
    offsets = scat.get_offsets() + 0.3 * xy 
    offsets.clip(0, max_dim, offsets) 
    scat.set_offsets(offsets) 
    scat._sizes += 30 * (np.random.random(num) - 0.5) 
    scat._sizes.clip(1, 300, scat._sizes) 
    fig.canvas.draw() 

यह मेरी मशीन पर ~ 25 सेकंड लेता है।

हम बजाय एक cStringIO बफर करने के लिए एक कच्चे RGBA बफर डंप हैं, तो यह वास्तव में मामूली तेजी ~ 22 सेकंड में है (यह केवल सच है क्योंकि मैं एक इंटरैक्टिव बैकएंड का उपयोग कर रहा है अन्यथा यह बराबर होगा!।):

import matplotlib.pyplot as plt 
import numpy as np 
import cStringIO 

fig = plt.figure() 
ax = fig.add_subplot(111) 
num = 50 
max_dim = 10 
x = max_dim/2 * np.ones(num) 
s, c = 100 * np.random.random(num), np.random.random(num) 
scat = ax.scatter(x,x,s,c) 
ax.axis([0,max_dim,0,max_dim]) 
ax.set_autoscale_on(False) 

for i in xrange(1000): 
    xy = np.random.random(2*num).reshape(num,2) - 0.5 
    offsets = scat.get_offsets() + 0.3 * xy 
    offsets.clip(0, max_dim, offsets) 
    scat.set_offsets(offsets) 
    scat._sizes += 30 * (np.random.random(num) - 0.5) 
    scat._sizes.clip(1, 300, scat._sizes) 
    ram = cStringIO.StringIO() 
    fig.canvas.print_raw(ram) 
    ram.close() 

हम savefig का उपयोग कर, एक तुलनात्मक सेट डीपीआई के साथ करने के लिए इस की तुलना करें:

import matplotlib.pyplot as plt 
import numpy as np 
import cStringIO 

fig = plt.figure() 
ax = fig.add_subplot(111) 
num = 50 
max_dim = 10 
x = max_dim/2 * np.ones(num) 
s, c = 100 * np.random.random(num), np.random.random(num) 
scat = ax.scatter(x,x,s,c) 
ax.axis([0,max_dim,0,max_dim]) 
ax.set_autoscale_on(False) 

for i in xrange(1000): 
    xy = np.random.random(2*num).reshape(num,2) - 0.5 
    offsets = scat.get_offsets() + 0.3 * xy 
    offsets.clip(0, max_dim, offsets) 
    scat.set_offsets(offsets) 
    scat._sizes += 30 * (np.random.random(num) - 0.5) 
    scat._sizes.clip(1, 300, scat._sizes) 
    ram = cStringIO.StringIO() 
    fig.savefig(ram, format='raw', dpi=fig.dpi) 
    ram.close() 

यह लेता है ~ 23.5 सेकंड। असल में, savefig बस कुछ डिफ़ॉल्ट पैरामीटर सेट करता है और इस मामले में print_raw पर कॉल करता है, इसलिए बहुत कम अंतर होता है।

import matplotlib.pyplot as plt 
import numpy as np 
import cStringIO 

fig = plt.figure() 
ax = fig.add_subplot(111) 
num = 50 
max_dim = 10 
x = max_dim/2 * np.ones(num) 
s, c = 100 * np.random.random(num), np.random.random(num) 
scat = ax.scatter(x,x,s,c) 
ax.axis([0,max_dim,0,max_dim]) 
ax.set_autoscale_on(False) 

for i in xrange(1000): 
    xy = np.random.random(2*num).reshape(num,2) - 0.5 
    offsets = scat.get_offsets() + 0.3 * xy 
    offsets.clip(0, max_dim, offsets) 
    scat.set_offsets(offsets) 
    scat._sizes += 30 * (np.random.random(num) - 0.5) 
    scat._sizes.clip(1, 300, scat._sizes) 
    ram = cStringIO.StringIO() 
    fig.canvas.print_png(ram) 
    ram.close() 

यह लेता है ~ 52 सेकंड:

अब, अगर हम एक संकुचित छवि प्रारूप (PNG) के साथ एक रॉ इमेज फॉर्मेट की तुलना में, हम एक बहुत अधिक महत्वपूर्ण अंतर देखो! जाहिर है, एक छवि को संपीड़ित करने में बहुत अधिक ओवरहेड है।

किसी भी दर पर, यह शायद एक बेकार में जटिल उदाहरण है ... मुझे लगता है कि मैं सिर्फ वास्तविक कार्य से बचना चाहता था ...

+0

अच्छा उदाहरण जो, भले ही यह अधिक हो सकता है। मैं सोच रहा हूं कि क्या आपने डिस्क पर प्रत्येक पुनरावृत्ति द्वारा खींचे गए फ्रेम को सहेजा है और फिर उन्हें एनिमेटेड gif में ऑफ़लाइन संकलित किया है, या क्या एनिमेटेड gif में खींचे गए फ्रेम "इन-स्ट्रीम" को संकलित करने का कोई तरीका है? मेरा मतलब $ एनीमेशन $ मॉड्यूल का उपयोग नहीं करना है, क्योंकि मैं इंटरेक्टिव (माउस-इवेंट संचालित) प्लॉट द्वारा उत्पादित एनिमेशन को सहेजना चाहता हूं। – achennu

+1

अच्छा, कुछ खोज किया और मुझे लगता है कि आपका सुझाव यहां दिखाया जा सकता है: http://stackoverflow.com/a/14986894/467522, है ना? – achennu

+0

असल में, यह विशेष gif केवल प्रत्येक पुनरावृत्ति को सहेजकर और उन्हें ऑफ़लाइन संकलित करके बनाया गया था (छविमैजिक के 'कन्वर्ट' के साथ)। (मुझे लगता है कि यह उदाहरण 'एनीमेशन' मॉड्यूल के साथ एक matplotlib संस्करण की रिहाई को पूर्ववत करता है।) किसी भी दर पर, एनिमेटेड gif बनाने के लिए 'ffmpeg' का उपयोग करना संभव होना चाहिए, लेकिन यदि मुझे सही ढंग से याद किया जाता है, तो एक gif के रूप में सहेजना 'एनीमेशन 'मॉड्यूल काफी सही ढंग से काम नहीं करता है। (मैं गलत समझा जा सकता हूं, और यह अब तक तय किया जा सकता है, भले ही मैंने कोशिश की है।) –

2

मैं जल्दी से और साथ ही भूखंडों के बहुत उत्पन्न करने के लिए की जरूरत है। मैंने पाया कि मल्टीप्रोसेसिंग ने उपलब्ध कोर की संख्या के साथ साजिश गति में सुधार किया है। उदाहरण के लिए, यदि 100 प्लॉट्स को एक प्रक्रिया में 10 सेकंड लगते हैं, तो 4 कोर में कार्य को विभाजित होने पर ~ 3 सेकंड लग गए।

+7

क्या आप अपना कोड साझा कर सकते हैं? – bigbug

संबंधित मुद्दे