使用HSI颜色空间使用'hip'库的Haskell域着色

v09wglhw  于 9个月前  发布在  其他
关注(0)|答案(1)|浏览(101)

Hakell库hip允许进行2D图像处理,它提供了几个颜色空间,例如众所周知的RGB空间。
我正在使用这个hip库来做一些2D图像。
例如,我使用自定义颜色Map(和椭圆函数)在RGB颜色空间中制作了这张图像

现在我想使用另一个颜色Map与HSI颜色空间。我不明白发生了什么:每次我的颜色Map计算H(色调)值时,我都会得到一个错误,如“* 异常:HSI像素未正确缩放,色调:120.0”。然而,在谷歌上找到的文档声称H值范围从0到360。那么为什么像120.0这样的值是无效的呢?

9rnv2umw

9rnv2umw1#

hip的文档本身没有说明范围,但我们可以看看代码:

下面是相关的源代码。然而,并不是所有的东西都被定义了,比如getRGB,但是经过多次尝试,我终于理解了。
从这个代码中可以清楚地看出,H的范围不是[0,360],而是[0,1]或[0,2pi](我们将看到)。

instance Elevator e => ToRGB HSI e where
  toPixelRGB (fmap toDouble -> PixelHSI h' s i) = getRGB (h'*2*pi) where
    !is = i*s
    !second = i - is
    getFirst !a !b = i + is*cos a/cos b
    {-# INLINE getFirst #-}
    getThird !v1 !v2 = i + 2*is + v1 - v2
    {-# INLINE getThird #-}
    getRGB h
      | h < 0      = error ("HSI pixel is not properly scaled, Hue: "++show h')
      | h < 2*pi/3 = let !r = getFirst h (pi/3 - h)
                         !b = second
                         !g = getThird b r
                     in PixelRGB r g b  
      | h < 4*pi/3 = let !g = getFirst (h - 2*pi/3) (h + pi)
                         !r = second
                         !b = getThird r g
                     in PixelRGB r g b
      | h < 2*pi   = let !b = getFirst (h - 4*pi/3) (2*pi - pi/3 - h)
                         !g = second
                         !r = getThird g b
                     in PixelRGB r g b
      | otherwise  = error ("HSI pixel is not properly scaled, Hue: "++show h')
    {-# INLINE getRGB #-}
  {-# INLINE toPixelRGB #-}

基于这段代码,我取得了一些进展。首先,范围确实不是[0,360],与谷歌的说法相反。
这是我的彩色Map:

colorMap2 :: Complex Double -> (Double, Double, Double)
colorMap2 z =
    let a = phase z
    in 
    let arg = if a < 0 
        then a + pi 
        else a
    in
    let h = min (arg/2/pi) 0.9999999
    in 
    let w = 2 * pi * log(1 + abs arg)
    in 
    let s = sqrt((1.0 + sin w ) / 2.0)
    in 
    let l = (1.0 + cos w ) / 2.0
    in 
    (h, s, l)

注意这一行:let h = min (arg/2/pi) 0.9999999。剩下的是我的彩色Map的东西。H值(在此用h表示)的范围从0到几乎为1。我不取1,因为我遇到了一些NaN,而值正好是1。
此外,我的实验表明,我认为S和I必须介于0和1之间,而不是Google上声称的介于0和100之间。
最后,它工作了,但这个颜色Map对于这个例子来说并不漂亮:

相关问题