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