1

我有一個Python函數,它需要像「(add(sub 10 5)5)」這樣的字符串s表達式,其中「add」和「sub」實際上是圖像處理函數,並且評估並創建圖像中表示的圖像串。圖像處理功能採用常量,變量或其他圖像(表示爲矢量列表),並以相同的方式返回圖像。 PIL用於將表示爲矢量列表的圖像轉換爲圖像文件。該圖像處理代碼可以優化以使用更少的內存嗎?

爲了評估前綴表示法s表達式,我將s-expr轉換爲列表,將其反轉,然後迭代令牌,直到找到函數,此時執行圖像處理函數並將結果圖像替換函數及其參數列表中。這樣做直到只有一個元素留在列表中,這是最終的圖像。

圖像處理函數很簡單 - 大多數對圖像中的每個(r,g,b)值執行一些數學運算。

問題是如果我想爲更復雜的表達式製作體面大小的圖像,我的電腦會陷入停頓。可以優化使用更少的內存嗎?

def createImage(self, sexpr, filename, (picWidth, picHeight)): 
    """Use the image processing functions in ImgProcessing 
     to create an image from the procedural information 
     contained in the s-expression.""" 

    img = Image.new("RGB",(picWidth,picHeight),(255,255,255)) 
    ip = ImgProcessing(picWidth,picHeight) 

    # Split s-expression into list of tokens and reverse 
    sList = sexpr.replace("(","").replace(")","").split() 
    sList.reverse() 

    while len(sList) > 1: 

     for index,token in enumerate(sList): 
      # If token is an image processing function 
      if type(token) == str and self.FuncSet.has_key(token): 
       # If this function takes one argument 
       if self.FuncSet[token] == 1: 
        rawImage = eval("ip." + token + "(" + "\"" + str(sList[index-1]) + 
            "\"" + ")") 
        sList = sList[:index-1] + [rawImage] + sList[index+1:] 
        break 
       # If this function takes two arguments 
       elif self.FuncSet[token] == 2: 
        rawImage = eval("ip." + token + "(" + "\"" + str(sList[index-1]) + 
            "\"" + "," + "\"" + str(sList[index-2]) + "\"" + 
            ")") 
        sList = sList[:index-2] + [rawImage] + sList[index+1:] 
        break 

    img.putdata(sList[0]) 
    img.save(filename) 
+0

有時候你不得不使用'eval',但99%的真實世界'eval'使用 - 包括這個 - 絕對不合適。如果你認爲你必須使用'eval',一個好的經驗法則是你錯了。在使用'eval'之前,因爲必須使用'eval',請參考CS362課程確定您真正需要使用'eval'的少量案例,並將完整的考試信用和申請費用發送到社團管理權限在非常少的情況下,在你真正需要的情況下''評估',在非常少的情況下,你真的需要書面許可使用'eval'。 – bobince 2010-07-27 01:15:53

回答

2

Profiling可以告訴你程序在哪裏花費大部分時間。

二,是str(sList[index-1])Image轉換爲字符串? ip.token(...)是否會返回圖片?如果是這樣,你要在字符串和圖像之間轉換多次。這可能非常緩慢。

這可能有助於改變

rawImage = eval("ip." + token + "(" + "\"" + str(sList[index-1]) + 
            "\"" + ")") 

喜歡的東西

getattr(ip,token)(sList[index-1]) 

,但當然,這要看是什麼類型參數ip.token預計。我找不到有關Google搜索ImgProcessing的任何信息。這是一個自定義類嗎?如果是這樣,它可能有助於更多地解釋它是如何工作的。 如果ip.token可以從採取字符串到拍照,這可能是一個很大的改進。

0

根據我的經驗,任何你在一個大圖像上以純Python或PIL逐像素方式進行的操作,在一月份都會變得很慢。考慮將底層的東西移動到用C編寫的Python擴展中。我使用過OpenCV,但需要一些學習。

+2

我不認爲跳到C是正確的答案,直到你已經儘可能優化你的Python代碼。在我看來,早期跳到低級語言只是另一種不成熟的優化方式。 – 2010-07-27 00:36:12