如何用感知一致性对HSV空间进行采样

2024-09-25 16:32:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我可以对HSV空间进行采样(固定sv

hue_gradient = np.linspace(0, 360,16)#sample 16 different equally spread hues
hsv = np.ones(shape=(1, len(hue_gradient), 3), dtype=float)*0.75#set sat and brightness to 0.75
hsv[:, :, 0] = hue_gradient#make one array
hsv


array([[[  0.  ,   0.75,   0.75],
        [ 24.  ,   0.75,   0.75],
        [ 48.  ,   0.75,   0.75],
        [ 72.  ,   0.75,   0.75],
        [ 96.  ,   0.75,   0.75],
        [120.  ,   0.75,   0.75],
        [144.  ,   0.75,   0.75],
        [168.  ,   0.75,   0.75],
        [192.  ,   0.75,   0.75],
        [216.  ,   0.75,   0.75],
        [240.  ,   0.75,   0.75],
        [264.  ,   0.75,   0.75],
        [288.  ,   0.75,   0.75],
        [312.  ,   0.75,   0.75],
        [336.  ,   0.75,   0.75],
        [360.  ,   0.75,   0.75]]])

然而,所有这些颜色在感知上并不一致

enter image description here

我可以通过运行colormath软件包中的deltaE2000方程(deltaE2000)来确认这一点。结果如下所示:

enter image description here

这些值是三角形值,颜色0-15对应于色调角度位置。如您所见,有些颜色低于感知阈值

enter image description here

所以,问题是,我是否有可能在sv固定的情况下对hsv空间进行统一采样?如果没有,我如何以一种方式对空间进行采样,使颜色排列为色调相似的邻域,并且sv的变化尽可能小


Tags: sample颜色np空间色调arrayhsvhue
1条回答
网友
1楼 · 发布于 2024-09-25 16:32:24

我尝试了一些方法,但最终似乎奏效了。它均匀地隔开色调值,然后轻推它们,直到它们在视觉上是一致的

from colormath import color_objects, color_diff, color_conversions

SAT = 1.0
VAL = 1.0
COLOR_COUNT = 16
NUDGE_SIZE = 0.2


def hue_to_lab(hue):
    return color_conversions.convert_color(
        color_objects.HSVColor(hue, SAT, VAL), color_objects.LabColor
    )


def get_equally_spaced(number, iters=100):
    # Create hues with evenly spaced values in hue space
    hues = [360 * x / number for x in range(number)]
    for _ in range(iters):
        # Convert hues to CIELAB colours
        cols = [hue_to_lab(h) for h in hues]
        # Work out the perceptual differences between pairs of adjacent
        # colours
        deltas = [
            color_diff.delta_e_cie2000(cols[i], cols[i - 1]) for i in range(len(cols))
        ]
        # Nudge each hue towards whichever adjacent colour is furthest
        # away perceptually
        nudges = [
            (deltas[(i + 1) % len(deltas)] - deltas[i]) * NUDGE_SIZE
            for i in range(len(deltas))
        ]
        hues = [(h + d) % 360 for (h, d) in zip(hues, nudges)]
    return hues


print(get_equally_spaced(COLOR_COUNT, iters=1000))

NUDGE_SIZE如果设置错误(将其更改为2在这里不会产生类似彩虹的效果),那么NUDGE_SIZE可能会把它搞砸,我认为最佳值取决于您进行了多少次迭代以及生成了多少种颜色。相邻颜色的delta_e_cie2000值(给定设置)是[16.290288769191324, 16.290288766871242, 16.290288753399196, 16.290288726186013, 16.290288645469946, 16.290288040904777, 16.290288035037598, 16.290288051426675, 16.290288079361915, 16.290288122430887, 16.290288180738187, 16.290288265350803, 16.290288469198916, 16.29028866254433, 16.2902887136652],这是非常一致的:我认为iters=1000对于这几个颜色来说太过分了。我在这里使用普通列表,但它应该转换为NumPy数组,并且可能运行得更快一些

算法的工作原理如下:

  1. 从一组天真的均匀色调开始
  2. 计算相邻颜色对之间的感知差异
  3. 将每个色调稍微移向其相邻色调中感知上最不同的一个。这个运动的大小与NUDGE_SIZE成正比
  4. 重复2-3次,直到颜色被轻推iters

相关问题 更多 >