Daily Tech Briefing
AI 科技速览
每天 5 分钟内学习 AI。获取最新的人工智能新闻,理解其重要性,并学习如何将其应用于您的工作。
Hacker News · 2026/8/4 15:16:22

Show HN: Simple algorithm and color space to generate diverse skin tones
AI 中文解读
一位独立开发者带来了一个贴心的小项目:他们设计了一套简单的算法和色彩空间,专门用来生成多样且均匀的肤色。简单说,以前在游戏捏脸或数字绘画软件里选肤色,色板常常偏白偏亮,深色肤色的选项不仅少,还往往不均匀,很难调出理想效果。这个项目相当于给创作者提供了一把“标准尺”,让程序能均匀地覆盖从浅到深的各类肤色,只要输入几个参数,就能生成自然多样的肤色选择。开发者还贴心地公开了Python和JavaScript代码,任何创作者都能直接拿来用。这意味着,未来的角色创建系统、美颜滤镜甚至AI绘画工具,都能更轻松地做到对不同肤色人群的包容和尊重。它虽然是个技术性小工具,却反映了科技行业正越来越重视“多样性”这个看似微小、实则影响无数人日常体验的细节。
What Colors Are We? Constructing A Good Enough Color Space For Skin Tones
If you're just looking for the results, below is a custom color picker based on the color space written
in Javascript and a sample procedural generation algorithm in Python (Javascript equivalents are in the
page source) - feel free to take this math and go have fun depicting our diverse world!
The goal of this project was to define a color space that makes it easier to build inclusive
color tools for a variety of contexts - such as character creators or digital art. If you see something
here that sparks your curiosity, I would love for you to stick around and read below this section to
learn more!
R² =
(What's R²?)
│
Show Sphere
What is each direction on the picker adjusting? Jump to that explanation
here.
# Plug the output of one of the select_point implementations into to_rgb(t, u, v)
def select_point(r_square: float = 2.) -> tuple[float, float, float]:
"""Uniformly sample from the sphere deterministically"""
radius = r_square ** (1. / 2)
phi = uniform(0, 2 * math.pi)
costheta = uniform(-1, 1)
n = uniform(0, 1)
theta = math.acos(costheta)
r = radius * (n ** (1.0 / 3))
t = r * math.sin(theta) * math.cos(phi)
u = r * math.sin(theta) * math.sin(phi)
v = r * math.cos(theta)
return (t, u, v)
def select_point(r_square: float = 2.) -> tuple[float, float, float]:
"""Uniformly sample from the sphere using rejection sampling"""
radius = r_square ** (1. / 2)
R = radius + 1
while R > radius:
t = uniform(-radius, radius)
u = uniform(-radius, radius)
v = uniform(-radius, radius)
R = (t**2 + u**2 + v**2) ** (1.0 / 2)
return (t, u, v)
def to_rgb(t, u, v) -> tuple[int, int, int]:
x = (t - 0.15) / 0.45
y = (v - 1.2 * t ** 2 + 0.2 * t + 0.655) / 1.84
z = u / 3.6
r = 28.77438370854 * x + 36.78307445559 * y - 19.69766918644 * z + 187.1436241611
g = 35.38327306318 * x - 2.009931981182 * y + 47.93462563172 * z + 137.1073825503
b = 36.14733717939 * x - 43.54346996173 * y - 28.50821294135 * z + 108.2241610738
return int(r), int(g), int(b)
#
Overview
What colors are we? The short answer is maybe something like “brown” and the long answer is very,
very long. Representing the broad range of human skin tones digitally is a hard problem.
Often, a limited set of colors is presented as being good enough to cover the full spectrum of
diversity. However, in using a specific set of colors, large groups of people are unable to
accurately be represented, or might be unintentionally excluded.
The goal of this work is to identify the broadest inclusive range of colors in the RGB color space that
correspond to plausible, but simplified skin tones. In particular, the aim was to identify simple, “good
enough” equations which define that area, allowing the range to be used in a variety of contexts.
Calling the equations "good enough" is intended to keep the limitations of this
分享
阅读原文 ↗