python—将r、b、g数组列表转换为颜色名称

tmb3ates  于 2021-08-25  发布在  Java
关注(0)|答案(2)|浏览(498)

这个问题在这里已经有了答案

如何将列表元素作为参数传递(1个答案)
昨天关门了。
我正在尝试将图像中的rbg值转换为颜色名称。我使用的函数输出rbg值如下: get_colors(image, 3, False)[array([180.60849865, 187.12872355, 191.33901941]), array([254.80780926, 254.83214586, 254.8409425 ]), array([191.33977471, 197.17187803, 200.97835918])] 我想通过以下函数以三个一对的方式迭代这些变量作为单个参数:

def recognize_color(R,G,B):
    minimum = 10000
    for i in range(len(csv)):
        d = abs(R- int(csv.loc[i,"R"])) + abs(G- int(csv.loc[i,"G"]))+ abs(B- int(csv.loc[i,"B"]))
        if(d<=minimum):
            minimum = d
            cname = csv.loc[i,"color_name"]
    return cname

我主要是在处理这个数组列表,并将它们排列到函数中。理想情况下,我希望从rgb阵列列表中创建一个颜色名称列表

cnwbcb6i

cnwbcb6i1#

您可以将理解与参数解包一起使用:

[recognize_color(*color) for color in get_colors(image, 3, False)]

在每次迭代中, color 将是一个包含三个元素的数组,可以将其扩展为任意iterable,并将其扩展为一个参数元组 recognize_color .
结果将是一个名称列表,每个名称的返回值对应一个名称 get_colors .
你也可以使用 itertools.starmap 为此:

result = itertools.starmap(recognize_color, get_colors(image, 3, False))

这将产生一个惰性生成器,您可以迭代该生成器以按需获取值,包括将其转换为列表:

list(result)
1tuwyuhd

1tuwyuhd2#

for循环的替代方法:矢量化

这个答案有点不同。通常,如果您可以将操作矢量化,那么执行时间可能会显著减少。
下面是一个解决方案,它处理整个 [R, G, B] 点,而不使用任何 for
复制步骤:
运行c段
运行b部分
运行段a
最后运行最上面的代码块。
或者,您可以运行此笔记本:


# This will return a pandas.Series of the

# color-names for each color

recognize_colors(dfColors = dfc, 
                 dfColorRef=dfr, 
                 target_column="COLOR", 
                 color_cols=["R", "G", "B"], 
                 threshold=10_000)

a。矢量化代码:识别颜色()

你只需要这个函数就可以得到你想要的,而不需要使用任何函数 for

from pandas import DataFrame
from typing import List

def recognize_colors(dfColors: DataFrame, 
                     dfColorRef: DataFrame, 
                     target_column: str="COLOR", 
                     color_cols: List[str] = ["R", "G", "B"],
                     threshold: int= 10_000):
    from numpy import abs
    ### The following four lines explain what is happening here 
    #   Here we use numpy array broadcasting to calculate ``d``
    #   in the foloowing four steps.
    # dR = np.abs(dfc.R.values.reshape(-1, 1) - df.R.values.reshape(1, -1))
    # dG = np.abs(dfc.G.values.reshape(-1, 1) - df.G.values.reshape(1, -1))
    # dB = np.abs(dfc.B.values.reshape(-1, 1) - df.B.values.reshape(1, -1))
    # d = dR + dG + dB
    #----------------------------------------------------------------------
    ## This is a condensed one-line construction of ``d`` using 
    #  numpy array broadcasting.
    d = abs(dfColors[color_cols].values.reshape(-1,1,3) - 
               dfColorRef[color_cols].values.reshape(1,-1,3)).sum(axis=2)
    return dfColorRef.loc[(d * (d <= threshold)).argmin(axis=1), target_column]

b。虚拟数据

我们将使用以下5行颜色作为虚拟数据来测试解决方案。

|   R |   G |   B |
|----:|----:|----:|
|  40 | 149 | 225 |
|  20 | 140 | 250 |
| 141 | 205 | 135 |
| 165 |  25 | 136 |
|  64 |  49 |  81 |

现在,让我们创建虚拟数据并将其加载到两个 Dataframe 中: dfc :要为其命名的颜色的数据框 dfr :数据框中包含名称的颜色 target_column 颜色

import numpy as np
import pandas as pd

input_colors = np.array([
    [ 40, 149, 225],
    [ 20, 140, 250],
    [141, 205, 135],
    [165,  25, 136],
    [ 64,  49,  81]
])

# Create a dataframe with all the colors

dfc = pd.DataFrame(input_colors, columns=["R", "G", "B"])

# Create another dataframe with some reference columns

# While creating this I assume column "COLOR" is

# the name if the color.

# Note: In your case, you will read-in this information

# from some ".csv" file.

dfr = reference_colors(colors=None, show_progressbar=False)

c。虚拟数据代码

以下所有代码仅用于创建虚拟数据,而不是主解决方案所需的代码。


# @title**Dummy Data Functions: `RUN`**

# import numpy as np

# import pandas as pd

# from tqdm.notebook import tqdm_notebook as tqdm

# from typing import Iterable, Optional, Union, List

def prepare_random_colors(
    seed: int=1234, 
    step: int=10, 
    offset_delta: int=0, 
    use_rgba: bool=False, 
    alpha: Optional[Union[int, float]] = None) -> np.ndarray:
    """Returns an array of colors of shape: (N, 3) or (N, 4).

    Logic:
        - An array ``base`` is created with values between 
          [0, 255] at steps of ``step``.
        - Another array ``offset`` of shape as shown below 
          is created randomly:
          - Shape:
            - (N, 3): for rgb colors
            - (N, 4): for rgba colors
          - N = base.shape[0]
          - The highest value

    Params:
        seed (int): Random number generator seed. 
                    - Constraint: ``seed >= 0``
                    - Default: `1234`
        step (int): Steps at which base-colors are generated. 
                    - Constraint: ``step >=1``
                    - Default: `10`
        offset_delta (int): An integer (+ or -). 
                            - Recommended: ``abs(offset_delta) <= step``
                            - Default: `0`
        use_rgba (bool): A flag on whether to use "rgba". When ``False``, 
                         "rgb" colors are generated.
                     - Default: `False`
        alpha (int, float, None): If you want to use a fixed alpha value in 
                                  rgba colors (must set ``use_rgba`` to ``True``),
                                  set ``alpha`` to a fixed value (int or float): 
                                  - ``[0., 1.]`` (int) 
                                  - ``[0, 255]`` (float)
                                  If, ``alpha`` = ``None``, and if ``use_rgba`` = ``True``,
                                  then randomly generated alpha values are used.

    Example:

        colors = prepare_colors(seed=1234)

    """
    rng = np.random.RandomState(seed)
    base = np.arange(0, 255, step)
    cols = 4 if use_rgba else 3
    offsets = rng.randint(0, step + offset_delta, size=(base.size, cols))
    colors = np.clip(base.reshape(-1, 1) + offsets, 0, 255)
    if (alpha is not None) and use_rgba:
        colors[:,:,:,-1] = alpha
    return colors

def clamp(x): 
  return max(0, min(x, 255))

def rgb2hex(r, g, b):
    r, g, b = clamp(r), clamp(g), clamp(b)
    return "#{0:02x}{1:02x}{2:02x}".format(r, g, b)

def rgba2hex(r, g, b, a):
    r, g, b = clamp(r), clamp(g), clamp(b), clamp(a)
    return '#{:02x}{:02x}{:02x}{:02x}'.format(r, g , b, a)

def reference_colors(colors: Optional[np.ndarray]=None, 
                     demoseed: int=1234, 
                     show_progressbar: bool=False):
    """Creates a reference-colors' dataframe from a numpy array of colors.

    Params:
        colors (numpy.ndarray): Array of colors. Shape: (num_rows, 3)
        demoseed (int): A seed for generating demo data for colors. 
                        This is used when ``colors = None``.

    Example:

        # colors = prepare_colors(seed=1234)
        df = reference_colors(colors=None, show_progressbar=False)

    """
    if colors is None:
        colors = prepare_random_colors(seed=demoseed)
    df = pd.DataFrame(colors, columns=["R", "G", "B"])
    if show_progressbar:
        # source: https://towardsdatascience.com/progress-bars-in-python-and-pandas-f81954d33bae 
        tqdm.pandas()
        df["HEX"] = df.progress_apply(lambda row: rgb2hex(*row), axis=1).str.upper()
    else:
        df["HEX"] = df.apply(lambda row: rgb2hex(*row), axis=1).str.upper()
    df["COLOR"] = df["HEX"]
    return df

相关问题