代码之家  ›  专栏  ›  技术社区  ›  J.J.

使用pil中的image.point()方法处理像素数据

  •  19
  • J.J.  · 技术社区  · 15 年前

    我正在使用 Python Imaging Library 使用定义颜色关系的查找表为黑白图像着色。查找表只是一个包含256个元素的RGB元组列表:

    >>> len(colors)
    256
    >>> colors[0]
    (255, 237, 237)
    >>> colors[127]
    (50, 196, 33)
    >>> 
    

    我的第一个版本使用了 getpixel() putpixel() 方法:

        for x in range(w):
            for y in range(h):
                pix = img.getpixel((x,y))
                img.putpixel((x,y), colors[pix[0]])
    

    这太慢了。一 profile 报告指向 putpixel getpixel 方法作为罪犯。一点调查(即阅读文件),我发现” 请注意,此方法相对较慢。 “R: 像素点 . ( 实际运行时间 53S在 像素点 50年代 获取像素 对于1024x1024图像)

    根据文档中的建议,我使用 im.load() 直接像素访问:

        pixels = img.load()
        for x in range(w):
            for y in range(h):
                pix = pixels[x, y]
                pixels[x, y] = colors[pix[0]]                
    

    处理速度加快了一个数量级,但仍然 慢: 大约3.5秒处理1024x1024图像。

    对PIL文档的更深入研究似乎表明 Image.point() 确切地 用于此目的:

    im.point(table) 图像=

    im.point(function) 图像=

    返回图像的副本,其中每个像素都已通过给定的表映射。该表应包含图像中每个波段的256个值。如果使用函数,则应采用单个参数。对每个可能的像素值调用一次函数,结果表将应用于图像的所有带区。

    我花了一些时间在这个界面上闲逛,但似乎没能把它弄好。请原谅我的无知,但是PIL的文档很简陋,我没有太多的图像处理经验。我搜索了一下,找到了几个例子,但没有什么能让我“点击”这个用法。因此,最后,我的问题是:

    • 图像点 这项工作的合适工具?
    • 什么格式/结构 图像点 要桌子吗?
    • 有人能粗略设计一个示例实现吗?到目前为止,我尝试的每一次迭代都以一个直接的黑色图像结束。
    2 回复  |  直到 12 年前
        1
  •  15
  •   Nadia Alramli    15 年前
    < Buff行情>

    是image.point()的正确工具 这份工作?

    < /块引用>

    是的,确实如此, image.point() is perfect for this job

    什么格式/结构 image.point()是否需要该表?

    < /块引用>

    您应该展平列表,以便代替 [(12,140,10),(10,100,200),…] use:。

    [12,140,10,10,100,200,…]
    < /代码> 
    
    

    下面是我刚刚尝试的一个简单示例:

    im=im.point(range(256,0,-1)*3)
    < /代码> 
    
    

    顺便说一句,如果你需要更多的颜色控制,你会感觉到图像。Point不适合你,你也可以使用image.getdataimage.putdata比两者都更快速地改变颜色loadputPixel。它慢于image.pointthough.

    image.getdata为您提供所有像素的列表,使用image.putdata修改并写回它们。就是这么简单。但请尝试使用image.point.first.


    编辑

    我在第一个解释中犯了一个错误,现在我要正确解释:

    颜色表实际上是这样的

    [0,1,2,3,4,5,…255,0,1,2,3,….255,0,1,2,3,….255]
    < /代码> 
    
    

    每个波段彼此相邻。 要将颜色(0,0,0)更改为(10,100,10),需要如下所示:

    [10,1,2,3,4,5,…255,100,1,2,3,….255,10,1,2,3,….255]
    < /代码> 
    
    

    要将颜色列表转换为正确的格式,请尝试以下操作:

    table=sum(zip(*colors),())
    < /代码> 
    
    

    我认为我的第一个示例应该为您演示格式。

    或 这份工作?

    是的, Image.point() 非常适合这份工作

    什么格式/结构 image.point()是否需要该表?

    你应该把名单展平,所以不要 [(12, 140, 10), (10, 100, 200), ...] 用途:

    [12, 140, 10, 10, 100, 200, ...]
    

    下面是我刚刚尝试的一个简单示例:

    im = im.point(range(256, 0, -1) * 3)
    

    alt text alt text

    顺便说一句,如果你需要更多的颜色控制,你会感觉到图像。Point不适合你,你也可以使用 Image.getdata Image.putdata 比两种颜色都更快地改变颜色 load putpixel . 它比 Image.point 不过。

    获取数据 提供所有像素的列表,修改它们并使用 图像数据 . 就是这么简单。但是试着用 图像点 第一。


    编辑

    我在第一个解释中犯了一个错误,现在我将正确解释:

    颜色表实际上是这样的

    [0, 1, 2, 3, 4, 5, ...255, 0, 1, 2, 3, ....255, 0, 1, 2, 3, ...255]
    

    每个波段彼此相邻。 要将颜色(0,0,0)更改为(10,100,10),需要如下所示:

    [10, 1, 2, 3, 4, 5, ...255, 100, 1, 2, 3, ....255, 10, 1, 2, 3, ...255]
    

    要将颜色列表转换为正确的格式,请尝试以下操作:

    table = sum(zip(*colors), ())
    

    我认为我的第一个示例应该为您演示格式化。

        2
  •  3
  •   Jonathan Root Josep Valls    12 年前

    我认为这可能更典型 point 像这样一条一条地(直接从PIL中提升 tutorial ):

    # split the image into individual bands
    source = im.split()
    
    R, G, B = 0, 1, 2
    
    # select regions where red is less than 100
    mask = source[R].point(lambda i: i < 100 and 255)
    
    # process the green band
    out = source[G].point(lambda i: i * 0.7)
    
    # paste the processed band back, but only where red was < 100
    source[G].paste(out, None, mask)
    
    # build a new multiband image
    im = Image.merge(im.mode, source)
    
    推荐文章