Converting HSL to RBG - haskell

I'm trying to convert some HSL value to RBG with Data.Colour module. Hackage doc said that Hue is always in the range 0-360. But there are now any ranges of Saturation and Lightness values. Are they in [0,100] or in [0,1] ranges?
I suppose that first variant is right, but seems like it is not.
λ> hsl 100 50 50
RGB {channelRed = 866.6666666666692, channelGreen = -2400.0, channelBlue = 2500.0}
Than I tried to use the range [0, 1] for both saturation and lightness.
λ> fmap truncate . (\(h,s,l) -> hsl h s l) $ (0,0,0)
RGB {channelRed = 0, channelGreen = 0, channelBlue = 0}
it :: RGB Integer
That why I'm start thinking that only Saturation should be a Double in [0,1].
For example we have some color value in HSL format.
λ> let c = (34.0,0.54,68.0)
c :: (Double, Double, Double)
Than we convert it to RGB and truncate all values
λ> fmap truncate . (\(h,s,l) -> hsl h s l) $ c
RGB {channelRed = 31, channelGreen = 63, channelBlue = 104}
But (31,63,104)::RGB is (214,54,26)::HSL like some online color-converters said.
What am I doing wrong?

It looks like the package uses the range [0, 1] for both lightness and saturation, but note that it also uses this range for RGB values, and not [0, 255] as you seem to be assuming. Taking this into account, I get (almost) the expected values:
> fmap (truncate . (* 255)) $ hsl 214 0.54 0.26
RGB {channelRed = 30, channelGreen = 61, channelBlue = 102}

So finally I've figured out that both Saturation and Lightness value should be in the [0,1] range.
λ> fmap (round . (255*)). (\(h,s,l) -> hsl h s l) $ (34.0,0.54,0.68)
RGB {channelRed = 217, channelGreen = 179, channelBlue = 129}
it :: RGB Integer
It makes a sense, because (217,179,129)::RGB value is equal to (34,54,68)::HSL.
So, maybe it would be helpful to add that constrains in the docs.

Related

How to find camera rotation matrix when axis flips or changes

Let us assume that we have camera extrinsics [R|t](camera-to-world) and a permutation matrix P that flips or changes the axis, which may have variants regarding its determinant. For example, this
P = np.array([
[1, 0, 0],
[0, 0, 1],
[0, -1, 0]
]) # (sorry that I'm not writing in consistent manner.)
changes points(axis) (x, y, z) to (x, z, -y). This may affect the rotation matrix in new coordinate system, if my guess is correct, so that it results in a new rotation matrix R' that decides the orientation of the transformed camera. Is it just P[R|t] and I get R' = PR? How do I find this?
Fliping odd number of axises is not rotation ! But that does not matter you can use matrix inverse to compute this so if I see it correctly you have:
R' = R*P
Where R' is your new matrix (fliped) and R is original matrix and you want to know the P so:
R' = R*P // Inverse(R)*
Inverse(R)*R' = Inverse(R)*R*P
Inverse(R)*R' = P
In case your R is orthonormal then Inverse of it is the same as its Transponation which is way faster. If its just ortogonal you can still use Transpose instead of Inverse but you would need to correct the basis vector lenghts afterwards.

Convert manually CIE LChab values to RGB

I want display sRGB values based on CIE LHab values, i didn't really know the topic aroud color theory but here is my code, i use colour library.
Did i miss something?
#Use Illuminant d65
d65 = [0.31382,0.33100]
# Maximun lightness of 100
lightess = 100
# Maximun chroma of 90
chroma = 90
# Create primary hue
hue = np.arange(0,360,45)
# Create np array
primary_rgb = np.array([[lightess,chroma, x] for x in hue])
# Convert to CIE L*a*b
primary_lab = colour.LCHab_to_Lab(primary_rgb)
# Convert to XYZ
primary_xyz = colour.Lab_to_XYZ(primary_lab)
# Convert to sRGB color
primary_rgb = colour.XYZ_to_sRGB(primary_xyz,d65,'Bradford')
# Denormalize values
primary_rgb*255
Output out of range with negative values...
array([[ 409.91335532, 170.93938038, 260.71868158],
[ 393.03002494, 198.83037084, 134.96104706],
[ 300.27298956, 250.59731666, 58.49528246],
[ 157.31758891, 283.79165255, 123.85945153],
[-1256.38350547, 296.51665099, 254.2577884 ],
[-2417.70063864, 292.21019209, 380.58920247],
[ -374.81508589, 264.85047515, 434.59056034],
[ 315.68646752, 211.99574857, 383.26874897]])
I want a correct ouput
The problem here is that you are constructing a hue sweep that covers a significant portion of the CIE Lab space, doing so, some of the colours, i.e. the negative ones, will be outside sRGB gamut:
import colour
import numpy as np
D65 = colour.CCS_ILLUMINANTS["CIE 1964 10 Degree Standard Observer"]["D65"]
hue = np.arange(0, 360, 45)
LCHab = colour.utilities.tstack([np.full(hue.shape, 100), np.full(hue.shape, 90), hue])
Lab = colour.LCHab_to_Lab(LCHab)
XYZ = colour.Lab_to_XYZ(Lab, D65)
sRGB = (
colour.cctf_encoding(
np.clip(colour.XYZ_to_sRGB(XYZ, apply_cctf_encoding=False), 0, 1)
)
* 255
)
print(sRGB)
figure, axes = colour.plotting.plot_RGB_colourspaces_in_chromaticity_diagram_CIE1976UCS(
"sRGB", diagram_opacity=0.25, standalone=False
)
uv = colour.Luv_to_uv(colour.XYZ_to_Luv(XYZ, D65))
axes.scatter(uv[..., 0], uv[..., 1])
colour.plotting.render()

Why do assigned RGB values get changed automatically?

First, consider this code:
from PIL import Image
im = Image.open("best_tt.jpg")
im2 = Image.new("RGB", im.size, (255,255,255))
b = 200
for i in range(im.size[0]):
for j in range(im.size[1]):
rgb = im.getpixel((i,j))
if rgb[0] <= b and rgb[1] <= b and rgb[2] <= b:
im2.putpixel((i,j), (0,0,0))
else:
im2.putpixel((i,j), (0, rgb[1], rgb[2]))
im2.save("tmp.jpg")
What I am doing is simply removing the RED component from each pixel (other than black pixels: the if statement checks for pixels that look black). In other words, I'm converting the given image to a yellow scale (since G+B = Y).
In that way, every pixel should have an RGB value like (0, G, B).
However, certain pixels of the new image returned values like:
(1, 255, 203)
(3, 205, 243)
(16, 242, 47)
though some had the red component as 0.
What causes this arbitrary adjustment of the RGB values?
The save() function will determine the type as a jpeg, which has a default compression quality of 75. The way the file is encoded and compressed can end up changing values after the fact.
See the PIL documentation for save() below:
https://pillow.readthedocs.io/en/3.1.x/handbook/image-file-formats.html

Flip a DICOM Image over the x = y Line

I am working on displaying a DICOM image. But it requires me to flip the incoming DICOM image about the x = y line. In other words, I want to rotates the image about the x = y axis with 180 degree
I have found setFlipOverOrigin() from vtkImageFlip. However, it seems not working. Could anyone suggest me a method or how to use setFlipOverOrigin() correctly if it helps.
Thanks in advance.
Try using vtkTransform class, and apply a 180 degrees rotation around the axe (1, 1, 0) => x = y = 1 ; z = 0
void vtkTransform::RotateWXYZ (double angle, double x, double y, double z );
Create a rotation matrix and concatenate it with the current
transformation according to PreMultiply or PostMultiply semantics. The
angle is in degrees, and (x,y,z) specifies the axis that the rotation
will be performed around.
vtkSmartPointer<vtkTransform> rotation = vtkSmartPointer<vtkTransform>::New();
rotation->RotateWXYZ (180, 1.0, 1.0, 0);
// rotation->setInputConnection( DicomReaderImage->GetOutputPort () ); // link your image into your pipeline
rotation->Update ();

Get RGB from Hue (S & L would be 100)

I need to get the RGB of a HSL with the SL both max. (get RGB from 125, 100, 100)
So, just the hue is changing.
Is there a simple formula for this?
Thanks
See Converting to RGB towards the end of http://en.wikipedia.org/wiki/HSL_and_HSV
In HSL color mode, if L = 100, then S = 0 and H = undefined.
Yes theres a formula. RGB = (255, 255, 255). When L is 100 (max), then your R,G,B is maxed (ie white), no matter what the Hue, or even Saturation.

Resources