当前位置:首页 > 文章列表 > 文章 > python教程 > Python colorsys 怎样在 RGB 与 HLS 之间转换

Python colorsys 怎样在 RGB 与 HLS 之间转换

来源:17golang原创 2026-10-30 19:42:56 0浏览 收藏

如果手里拿的是常见的 (R, G, B) 三通道整数,Python 标准库 colorsys 的正确用法是:先把每个通道除以 255 归一化,再调用 rgb_to_hls;需要显示或保存时,使用 hls_to_rgb 转回 0 到 1 的 RGB,最后再裁剪、四舍五入到 0 到 255。

最容易出错的地方有两个:colorsys 接受的是 0 到 1 的浮点数,HLS 元组顺序是 (h, l, s),不是 HSV 的 (h, s, v)。

官方文档:https://docs.python.org/3/library/colorsys.html

先分清 colorsys 的数值范围

colorsys 同时提供 RGB、YIQ、HLS 和 HSV 之间的双向转换。对 RGB、HLS、HSV 来说,坐标都使用 0 到 1 的浮点数;因此网页颜色常见的 255 不能直接作为参数传入。

HLS 的三个位置分别是色相 h、亮度 l、饱和度 s。其中色相也是 0 到 1 的归一化坐标,如果业务界面需要角度,可以把它乘以 360;亮度和饱和度则继续保持 0 到 1。

RGB 0 到 255 归一化后通过 rgb_to_hls 得到 HLS h l s 的静态关系说明图
图1:RGB 到 HLS 的数值范围与坐标关系说明图,不是运行截图。

最小配方:RGB 转 HLS

先写一个只负责换算的函数,把外部常见的 8 位 RGB 和 colorsys 的内部坐标隔离开。这样后面无论颜色来自表单、接口还是图片元数据,都不会把两种尺度混在一起。

import colorsys


def rgb255_to_hls(rgb):
    # 把外部常见的 0 到 255 通道转换为 colorsys 使用的 0 到 1 浮点数。
    normalized = tuple(channel / 255 for channel in rgb)
    # HLS 的返回顺序固定是 hue、lightness、saturation。
    return colorsys.rgb_to_hls(*normalized)


color_hls = rgb255_to_hls((52, 152, 219))
# h 是 0 到 1 的色相坐标,乘 360 后更适合在角度界面中展示。
print(color_hls[0] * 360, color_hls[1], color_hls[2])

这个配方的关键不是把除法写在一行,而是明确边界:函数输入是 0 到 255,函数输出是 (h, l, s)。调用方如果需要色相角度,只在展示层转换,不要把角度再传回 hls_to_rgb。

HLS 里的亮度和饱和度怎样调整

HLS 适合表达“保持大致色相,只把颜色调亮一点”这类操作。可以先解包元组,再限制调整后的亮度和饱和度仍在 0 到 1。色相通常按环形坐标处理,超过 1 或小于 0 时用取模回到这个范围。

def shift_hls(hls, lightness_delta=0.0, saturation_delta=0.0):
    h, l, s = hls
    # 色相是环形坐标,取模可以处理超过 1 或小于 0 的情况。
    h = h % 1.0
    # 亮度和饱和度是区间值,调整后要限制在合法范围内。
    l = min(1.0, max(0.0, l + lightness_delta))
    s = min(1.0, max(0.0, s + saturation_delta))
    return h, l, s


brighter = shift_hls(color_hls, lightness_delta=0.08)
# brighter 仍然是 colorsys 可以接受的 (h, l, s) 三元组。
print(brighter)

这里的“限制”是业务层保护,不是 colorsys 额外提供的校验器。把参数集中在一个小函数里,能避免多个页面分别处理边界,最后出现同一颜色在不同页面亮度不一致的情况。

调整 HLS 后怎样转回 RGB

hls_to_rgb 返回的三个通道仍然是 0 到 1 的浮点数。要交给 CSS、JSON 接口或图像库时,再统一乘以 255,并用 round 得到整数。乘法前后都保留裁剪,可以防止浮点误差把边界推到合法范围之外。

HLS 参数调整后通过 hls_to_rgb 和 clip round 转回 0 到 255 RGB 的静态关系说明图
图2:HLS 回到 8 位 RGB 的静态关系说明图,不是运行截图。
def hls_to_rgb255(hls):
    h, l, s = hls
    # hls_to_rgb 要求 h、l、s 都是 0 到 1 的坐标,而不是色相角度。
    rgb01 = colorsys.hls_to_rgb(h % 1.0, l, s)
    # 裁剪并四舍五入,得到 CSS 或接口常用的 8 位整数通道。
    return tuple(round(min(1.0, max(0.0, channel)) * 255) for channel in rgb01)


rgb255 = hls_to_rgb255(brighter)
print(rgb255)

如果你要生成 CSS,可以把结果拼成 rgb(r g b);如果接口约定的是小数 RGB,则不要做最后的乘 255,直接保留 rgb01 即可。

HLS 和 HSV 不要把位置顺序混用

同一个模块里还有 rgb_to_hsv 和 hsv_to_rgb。HLS 使用 (h, l, s),HSV 使用 (h, s, v),第二、第三个值的含义不同。把 HSV 元组直接传给 HLS 的逆转换,代码通常不会报错,却会得到明显不同的颜色。

目标调用返回顺序坐标范围
RGB 转 HLSrgb_to_hls(r, g, b)h, l, s都在 0 到 1
HLS 转 RGBhls_to_rgb(h, l, s)r, g, b都在 0 到 1
RGB 转 HSVrgb_to_hsv(r, g, b)h, s, v都在 0 到 1

几个实际使用时容易踩到的坑

  • 把 0 到 255 直接传入。先在入口归一化,返回显示值时再反向换算。
  • 把色相角度传给逆函数。界面上的 180 度要先除以 360,才能成为 colorsys 的 h。
  • 混淆 HLS 和 HSV 的顺序。看到第二个值时先确认它是 lightness 还是 saturation。
  • 忽略灰度色。当饱和度接近 0 时,色相对视觉颜色区分的作用很弱,业务上不应依赖灰度色的 h 值做分类。
  • 直接截断浮点数。显示层优先使用 round,并在乘 255 前后保持 0 到 1 的边界保护。

可以直接复用的完整片段

如果项目只需要一条稳定的 RGB/HLS 往返路径,可以把归一化、调整和反归一化收拢成下面这个小工具。它不负责读取图片文件,输入输出也保持为普通 Python 元组,便于在 Web 接口或颜色选择器中复用。

import colorsys


def rgb255_to_hls(rgb):
    # 统一把 8 位 RGB 通道送入 0 到 1 的标准库坐标。
    r, g, b = (channel / 255 for channel in rgb)
    return colorsys.rgb_to_hls(r, g, b)


def hls_to_rgb255(hls):
    h, l, s = hls
    # 亮度和饱和度由调用方控制,色相按环形坐标归一化。
    rgb01 = colorsys.hls_to_rgb(h % 1.0, l, s)
    # 将标准库输出转换为可显示的整数 RGB,并抵抗边界浮点误差。
    return tuple(round(min(1.0, max(0.0, value)) * 255) for value in rgb01)


original = (52, 152, 219)
hls = rgb255_to_hls(original)
# 只调整亮度,保持色相和饱和度的业务含义不变。
adjusted_hls = (hls[0], min(1.0, hls[1] + 0.08), hls[2])
adjusted_rgb = hls_to_rgb255(adjusted_hls)
print(adjusted_rgb)

这套写法的边界很清楚:输入输出层使用 0 到 255,转换层使用 0 到 1,HLS 内部始终按 h、l、s 解包。后续如果换成 HSV,只需要同时替换函数名和元组语义,不要只改一个调用点。

相关问题

colorsys 的色相为什么不是 0 到 360?

它把色相也表示为 0 到 1 的归一化坐标。需要角度时在展示边界乘以 360,传回转换函数前再除以 360。

能不能把十六进制颜色直接传给 colorsys?

不能直接传入。先把十六进制拆成三个 0 到 255 的通道,再按本文的归一化方式转换。

只想调亮颜色,为什么不直接给 RGB 每个通道加值?

直接改 RGB 会同时改变颜色的综合色相和饱和度。先转到 HLS,可以把亮度调整表达得更清楚,再统一转回显示通道。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Java PropertyChangeSupport 怎样只监听指定属性Java PropertyChangeSupport 怎样只监听指定属性
上一篇
Java PropertyChangeSupport 怎样只监听指定属性
JavaScript DocumentFragment 插入文档后为什么变成空片段
下一篇
JavaScript DocumentFragment 插入文档后为什么变成空片段
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    797次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    787次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    875次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    845次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    677次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码