2012-02-28 42 views
2

我最近遇到了一個問題,我的Django項目和WebFaction上的內存使用情況。在Django中裁剪圖像導致大量內存增加

這裏是webfaction在內存中運行該項目的兩個過程:

30396 4-20:20:00 13486 
30404 4-20:20:00 13487 

視圖後運行過程中的一個將大幅增加:

69720 4-20:20:22 13486 
30404 4-20:20:22 13487 

正如你所看到的第一個進程在內存使用中翻了一番!由於這個功能經常被使用,我需要弄清楚發生了什麼。我相信我已縮小到以下視圖(這是一個上傳圖像,添加細節,剪裁縮略圖的3步過程)。

這是下面的視圖。它獲取一個照片對象,從文件加載圖像,獲取用戶提交的框座標,然後創建一個200,200大小的圖像。這個新創建的圖像被回寫到磁盤上,文件名中包含一個.thumbnail文件,照片對象被保存。

@login_required 
def upload3(request, photo_pk): 
    photo = get_object_or_404(Photo, pk=photo_pk, user=request.user) 
    if request.method == "POST": 
     form = upload3Form(request.POST) 
     if form.is_valid(): 
      im = Image.open(photo.image.path) 
      try: 
       box =(form.cleaned_data['x1'],form.cleaned_data['y1'],form.cleaned_data['x2'],form.cleaned_data['y2']) 
      except: 
       box = ('0','0','1000','1000') 
      cropped = im.crop(box) 
      cropped.thumbnail((200,200),Image.ANTIALIAS) 
      result = os.path.splitext(photo.image.path) 
      cropped.save(result[0] + '.thumbnail' + result[1]) 
      photo.status = 3 
      photo.save() 

任何想法,我可能做錯了將不勝感激。

Update 1:用於測試的圖像全部爲Jpeg,尺寸約爲3600 x 2700,每張圖像大小約爲2 MB。

+0

您是否縮小了視圖中的哪些操作會導致內存使用增加?如果視圖被多次調用會發生什麼? – 2012-02-28 00:02:31

+0

不,我沒有,因爲我無法在活動服務器(如pdb)上執行儘可能多的調試。似乎並不是每次調用視圖時都會發生,但大多數情況下都是如此。 (幾個星期前我上傳了幾張圖片後,一次處理的內存使用量高於112 MB)。 – Fernker 2012-02-28 00:11:05

+0

你介意用典型的圖像大小和格式更新你的問題嗎? – 2012-03-05 22:32:52

回答

0

經過大量的挖掘和死衚衕,我嘗試了一些沒有建議任何地方,它的工作。

在包含PIL中使用的圖像對象的每個對象上,我必須在完成它之後刪除該對象。例如:

im = Image.open(photo.image.path) 
try: 
    box =(form.cleaned_data['x1'],form.cleaned_data['y1'],form.cleaned_data['x2'],form.cleaned_data['y2']) 
except: 
    box = ('0','0','1000','1000') 
cropped = im.crop(box) 
newimage = cropped.resize((form.cleaned_data['dw'],form.cleaned_data['dh']),Image.ANTIALIAS) 
del im 
del cropped 

因此,一旦我完成了對象的調用,我就會調用del該項。它似乎已經解決了這個問題。我不再有記憶力增加,我不能更快樂。

+0

用你找到的解決方案更新你的問題,而不是回答你自己的問題,並從我的答案中取回接受,會更好。 – 2012-03-15 17:07:17

+0

我覺得我的答案更完整,當人們提出問題時,他們比綠色複選框更適合原始問題的更新。我仍然給你賞金... – Fernker 2012-03-21 17:10:53

2

2M數字用於壓縮的JPEG圖像,但未壓縮,3600 x 2700真彩色將約爲38M(每像素4B的9,720,000像素),接近您遇到的內存使用增加。

這是PIL的一個已知問題,我可以通過向您發送一張40000x40000像素的黑色圖片作爲png來生成像素炸彈。在加載之前總是檢查分辨率(或者使用處理OutOfMemory的try/except塊來保護代碼)。查看使用im.tile屬性來按塊處理圖像塊是否會降低內存佔用量。

可能需要檢查:

一些替代品與較大的圖片的時候可以更好地處理內存說:

  • GDAL(地理空間數據抽象庫)
  • OIIO(OpenImageIO)
  • Mahotas(NumPy的)

[更新]

你知道,如果有一個在PIL的方式從內存中釋放對象做什麼?因爲理論上這對於這個觀點來說是最好的,因爲我需要它像它一樣工作,但是更好地處理圖像。

  • 爲了避免內存尖峯可以檢測巨大的圖像,並嘗試處理他們使用im.tile塊代替im.crop(可惜的是在較低的水平運行)。
  • 您可以儘快刪除中間圖像對象,以便獲得更短的尖峯(使用gc module,您可以強制清理垃圾收集器)。
+0

哦,這是有道理的,我從來沒有想過圖片被壓縮。我已經開始更多地瞭解你的建議,並且我會看看它們是否有效。你知道PIL中有沒有辦法從內存中釋放對象?因爲理論上這對於這個觀點來說是最好的,因爲我需要它像它一樣工作,但是更好地處理圖像。謝謝。 – Fernker 2012-03-06 15:24:00

+0

對不起,我沒有意識到你已經更新了你的答案。謝謝你的回答,因爲你提供了洞察導致內存峯值的原因。 (這是我的問題是)。我將與WebFaction交談,看看他們是否有任何想法,因爲我有一個體面的解決方案,不需要我花費幾個小時的工作。 – Fernker 2012-03-08 16:30:38