You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Haskell的hip库复现R包imager的RGBtoHSI功能?

实现从Haskell hip库RGB图到imager风格HSI图的转换

一、解析R imager包RGBtoHSI的核心逻辑

imager的RGBtoHSI核心是标准RGB到HSI的颜色空间转换,关键要注意数值范围和细节处理:

  • 输入预处理:将0-255的整数RGB值归一化到0-1的浮点数
  • 亮度(I)计算:I = (R + G + B) / 3
  • 饱和度(S)计算:若I=0则S=0,否则S = 1 - (min(R,G,B) / I)
  • 色相(H)计算:
    1. 先算delta = max(R,G,B) - min(R,G,B),若delta=0则H=0(灰度)
    2. 否则根据最大值所在通道计算:
      • 最大值为R:H = 60 * ((G - B)/delta) mod 6,结果为负则加360转正
      • 最大值为G:H = 60 * ((B - R)/delta + 2)
      • 最大值为B:H = 60 * ((R - G)/delta + 4)
    3. 最终H范围为0-360度
  • 输出处理:H保留0-360范围,S、I保留0-1范围,可视化时将H映射为色相,S/I对应饱和度、亮度

二、在Haskell hip库中实现该逻辑

hip库无直接对应内置函数,需手动实现转换,以下是完整步骤:

1. 类型定义与归一化

先将hip生成的Word8类型RGB图(0-255)转为0-1范围的浮点数:

import Graphics.HIP as HIP
import Data.Word (Word8)

-- 自定义HSI类型
data HSI a = HSI { h :: a, s :: a, i :: a } deriving (Show, Eq, Functor)

-- 归一化RGB通道到0-1浮点数
normalizeRGB :: Image RGB Word8 -> Image RGB Float
normalizeRGB = HIP.map (\(RGB r g b) -> RGB (fromIntegral r / 255) 
                                           (fromIntegral g / 255) 
                                           (fromIntegral b / 255))

2. 实现RGB到HSI的转换函数

rgbToHSI :: RGB Float -> HSI Float
rgbToHSI (RGB r g b) = HSI h' s' i'
  where
    i' = (r + g + b) / 3
    minVal = minimum [r, g, b]
    maxVal = maximum [r, g, b]
    delta = maxVal - minVal
    
    -- 计算饱和度S
    s' = if i' == 0 then 0 else 1 - (minVal / i')
    
    -- 计算色相H(0-360度)
    h' = case () of
      _ | delta == 0 -> 0
        | maxVal == r -> let temp = ((g - b) / delta) * 60 in if temp < 0 then temp + 360 else temp
        | maxVal == g -> ((b - r) / delta + 2) * 60
        | maxVal == b -> ((r - g) / delta + 4) * 60
        | otherwise -> 0 -- 分支不可达

3. 应用转换到整图并转回可视化RGB

imager的HSI可视化是将HSI转回RGB,需实现反向转换:

-- HSI转RGB(0-1浮点数)
hsiToRGB :: HSI Float -> RGB Float
hsiToRGB (HSI h' s' i') = RGB r g b
  where
    hNormalized = h' / 60 -- 转为0-6范围
    c = i' * s'
    x = c * (1 - abs (mod hNormalized 2 - 1))
    (r1, g1, b1) = case floor hNormalized of
      0 -> (c, x, 0)
      1 -> (x, c, 0)
      2 -> (0, c, x)
      3 -> (0, x, c)
      4 -> (x, 0, c)
      5 -> (c, 0, x)
      _ -> (0, 0, 0)
    m = i' - c
    r = r1 + m
    g = g1 + m
    b = b1 + m

-- 转换为可保存的Word8类型RGB图
convertAndVisualize :: Image RGB Word8 -> Image RGB Word8
convertAndVisualize img = HIP.map (\hsi -> let RGB r g b = hsiToRGB hsi 
                                           in RGB (round $ r * 255) 
                                                  (round $ g * 255) 
                                                  (round $ b * 255)) 
                                 (HIP.map rgbToHSI $ normalizeRGB img)

4. 完整使用示例

main :: IO ()
main = do
  -- 读取hip生成的RGB图
  rgbImg <- HIP.readImage "hip_generated_rgb.jpg"
  -- 执行转换并保存结果
  let resultImg = convertAndVisualize rgbImg
  HIP.writeImage "converted_hsi_image.png" resultImg

关键注意点

  • hip内置的rgbToHsi是将H转为0-2π的弧度值,而imager用0-360角度值,这是两者核心差异,需手动实现角度版计算
  • 严格控制数值范围的归一化与反归一化,避免颜色偏差
  • 若hip生成的图像已是0-1范围的Float类型,可跳过normalizeRGB步骤

内容的提问来源于stack exchange,提问作者Stéphane Laurent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 02:58:18