Python中实现色彩数学的环形数值范围判断方案
色轮色相环形范围判断解决方案
问题说明
我正在用Python开发色轮功能:先生成随机RGB颜色,转成HSL格式后固定饱和度(S)和亮度(L),只保留色相(H)变化。现在需要比较两个颜色的色相,判断颜色2的色相是否处于颜色1色相的±90度环形范围内——比如颜色1色相为300时,有效范围是210到30(而非390)。现有if语句无法处理这种环形范围逻辑,求解决方法。
原代码片段:
# 生成随机RGB颜色 import random no_of_colors= 23 rgb_colors =["#"+''.join([random.choice('0123456789ABCDEF') for i in range(6)]) for j in range(no_of_colors)] # 转换为HSL from hsluv import hex_to_hsluv, hsluv_to_hex hsl_colors = list() for i in rgb_colors: col = hex_to_hsluv(i) hsl_colors.append(col) # 转为可变列表 hsl_colors = [list(elem) for elem in hsl_colors] # 固定饱和度和亮度 for i in hsl_colors: i[1] = 75 for i in hsl_colors: i[2] = 75 # 同理生成第二个色相列表hsl_colors2 # 这里是判断逻辑的问题点 if hsl_colors2[0] > (hsl_colors[0]-90) or hsl_colors2[0] < (hsl_colors[0]+90): print(hsl_colors[j][0]) else: print("not within range") # 尝试过的错误逻辑 if hsl_colors2[0] > (hsl_colors[0]-90) or hsl_colors2[0] < (hsl_colors[0]+90): if hsl_colors[0]+90 > 360: hsl_colors[0]+90 / 360 print(hsl_colors[0]+90 / 360) else: print("not within range")
解决思路
色相是0-360度的环形值,直接用大小比较会忽略环形特性。核心是计算两个色相的最小环形差值,或者处理范围跨0/360的情况:
- 最小差值法:计算两个色相的差值,取模360后,判断最小的环形距离是否≤90。比如300和30的差值,
(300-30) % 360 = 270,最小距离是360-270=90,刚好符合条件。 - 范围拆分法:把基准色相的±90范围拆成两种情况:
- 如果基准色相+90 ≤360,直接判断颜色2色相在
[基准-90, 基准+90]之间 - 如果基准色相+90 >360,判断颜色2色相在
[基准-90, 360]或者[0, 基准+90-360]之间
- 如果基准色相+90 ≤360,直接判断颜色2色相在
实现代码
推荐用最小差值法,逻辑更简洁:
def is_hue_in_range(hue1, hue2, delta=90): # 确保色相在0-360范围内 hue1 = hue1 % 360 hue2 = hue2 % 360 # 计算环形差值 diff = abs(hue1 - hue2) # 取最小的环形距离 min_diff = min(diff, 360 - diff) return min_diff <= delta # 使用示例 hue1 = hsl_colors[0][0] hue2 = hsl_colors2[0][0] if is_hue_in_range(hue1, hue2): print(f"色相{hue2}在{hue1}的±90度范围内") else: print("色相不在范围内")
如果用范围拆分法,代码如下:
def is_hue_in_range(hue1, hue2, delta=90): hue1 = hue1 % 360 hue2 = hue2 % 360 lower = hue1 - delta upper = hue1 + delta if upper <= 360: return lower <= hue2 <= upper else: # 范围跨0度,判断是否在[lower,360]或[0, upper-360] return hue2 >= lower or hue2 <= (upper - 360) # 使用示例 hue1 = hsl_colors[0][0] hue2 = hsl_colors2[0][0] if is_hue_in_range(hue1, hue2): print(f"色相{hue2}在{hue1}的±90度范围内") else: print("色相不在范围内")
完整修改后的代码
把判断逻辑整合到原流程中:
import random from hsluv import hex_to_hsluv, hsluv_to_hex def generate_hue_list(no_of_colors): # 生成随机RGB并转为固定S=75、L=75的HSL列表 rgb_colors = ["#"+''.join([random.choice('0123456789ABCDEF') for _ in range(6)]) for _ in range(no_of_colors)] hsl_colors = [] for rgb in rgb_colors: h, s, l = hex_to_hsluv(rgb) hsl_colors.append([h, 75, 75]) return hsl_colors def is_hue_in_range(hue1, hue2, delta=90): hue1 = hue1 % 360 hue2 = hue2 % 360 diff = abs(hue1 - hue2) min_diff = min(diff, 360 - diff) return min_diff <= delta # 生成两个色相列表 no_of_colors = 23 hsl_colors = generate_hue_list(no_of_colors) hsl_colors2 = generate_hue_list(no_of_colors) # 比较第一个元素的色相 hue1 = hsl_colors[0][0] hue2 = hsl_colors2[0][0] if is_hue_in_range(hue1, hue2): print(f"色相{hue2:.2f}在{hue1:.2f}的±90度环形范围内") else: print("色相不在范围内")
内容的提问来源于stack exchange,提问作者Doda
相关产品推荐
相关产品推荐

