在各个像素的RGB值上迭代函数

时间:2014-04-02 01:45:58

标签: python arrays image-processing numpy python-imaging-library

我已经打开了我的图像,可以访问各个像素的RGB值,但我现在要做的是将一个函数分别应用于每个像素的RGB值。也就是说,我不想以相同的方式在整个图像中的所有像素上应用它;我想以不同的方式应用它,具体取决于是否为每个像素,蓝色值是>红色>绿色(而不是绿色>红色>蓝色等等)。

所以我的问题是,如何访问每个像素中的单个RGB元素(而不是一次访问整个图像中的所有红色,绿色和蓝色值)?最终我的问题是“最快的方法是什么?”因为显然需要一段时间才能在每个像素上单独应用一个功能,但是现在我很高兴只需要任何解决方案。

感谢您的任何建议。

编辑清晰度/更具特异性:

我实际上是根据127.5 - abs(127.5 - 红色/绿色/蓝色)的顺序尝试应用不同的指令集,而不仅仅是红色>绿色>蓝色的顺序(如上所述, bc我试图简化)。一旦针对给定像素确定了该排序,则应用适当的指令集。同样,这是逐像素的 - 我没有根据图像中的所有红色值来订购东西,只是单个像素的rgbs。所以我想要做的就是这样(这里我只是玩了六个可能的命令中的一个;为了简洁,我省略了其他五种可能性):

def rgb_manip(red,green,blue):
    r_max = int(127.5 - abs(127.5 - red))
    g_max = int(127.5 - abs(127.5 - green))
    b_max = int(127.5 - abs(127.5 - blue))
    if r_max >= g_max >= b_max:
        if r_max >= g_max  +  b_max:
            new_red = red + g_max + b_max
            new_green = green - g_max
            new_blue = blue - b_max
        else:
            new_red = red + r_max
            new_green = green - r_max + b_max
            new_blue = blue - b_max
    # elif... And so on, with a different set of instructions for each of the 6 possibilities depending on the order of the r_max, g_max, b_max values (e.g., r_max >= b_max >= g_max or g_max >= r_max >= b_max, etc, etc)

1 个答案:

答案 0 :(得分:2)

如果将图像转换为数组,则可以访问一个像素的RGB值,或所有像素的R,G或B值之一:

from __future__ import division
import numpy as np
from PIL import Image

im = Image.open(imfile)
arr = np.asarray(im)

arr[..., 0]  # All Red values
arr[..., 1]  # All Green values
arr[..., 2]  # All Blue values
arr[0, 0]    # RGB for first corner pixel
arr[m, n]    # RGB for pixel at [m, n]
arr[m, n, 0] # R value for pixel [m, n]
arr[m, n, c] # value for color c at pixel [m, n]

您可以使用argsort获取每个像素的排名,如:

def transform(a, c=255/2):
    return c - np.abs(c - a)

ranking = transform(arr).argsort(axis=-1)

将标准值从最后(颜色)轴的最小值到最大值进行排序。所以这给出了一个新的数组,其中每个'颜色'数组而不是RGB值是转换后的R,B和G值的排序(称为“R',B',G'”),所以如果角落像素为G' > B' > R',然后ranking[0, 0][0, 2, 1],因为R'(0)最小,接着是B'(2),最后是最大的是G'(1)。

执行上述操作的优点是您有一个数组,说明在哪个像素上使用哪种方法。它最多可以有六个变换通道的排序。我建议为每个排序定义一个单独的函数。然后,必须在函数内做出一个决定(第二个嵌套if / else在你的例子中),并且它可以用np.where完成,它将一个东西应用于满足条件的数组部分,并且其他的事情。这仅适用于两个选项,但如果有多个选项(if / elif / else),其他技术也可以同样有效。

def bgr(a):
    """ for when B' < G' < R'
    """
    t = transform(a)
    red, green, blue = a.transpose([2,0,1])
    # same as: red, green, blue = a[..., 0], a[..., 1], a[..., 2] 
    r_max, g_max, b_max = t.transpose([2,0,1])
    assert np.all((b_max <= g_max) & (g_max <= r_max)), "doesn't match rank"
    condition = r_max >= g_max + b_max
    new_red = np.where(condition, red + g_max + b_max, red + r_max)
    new_green = np.where(condition, green - g_max, green - r_max + b_max)
    new_blue = blue - b_max
    return np.dstack([new_red, new_green, new_blue])

此功能仅适用于您的第一个if。我会为这六件事中的每一件做一个新的功能,并将它们填入一个像这样的字典:

functions = {
        (0, 1, 2) : rgb, # for R'<G'<B'
        (0, 2, 1) : rbg, # for R'<B'<G'
        #etc...
        }

如果您的输出也具有RGB值:

out = np.empty_like(arr)

然后遍历所有六个排名/功能:

for rank, func in functions.items():
    mask = np.all(transform(arr).argsort(-1) == rank, -1)
    out[mask] = func(arr[mask])