0

I have a vector of R, G and B signal from a video along with the time of frame capture and each vector size like R is 1 x 100 double. I want to generate the Hue from these vectors of RGB signals that I have. I find the formula for it from Wikipedia and it simply looks as follows:

RGB.mat: below is an example of R, G, B,t. Each are vector of 1x800 double, which I only included a 5 here:

R = 12.7    15.7    15.9    15.8    15.7
G=  12.7    12.7    12.7    12.5    12.4
B = 16.4    16.1    16.1    16.0    15.9
t = 0.03    0.06    0.10    0.13    0.16

so, I am very new in Matlab and i tried myself and complete code is:

%% load R and G and B data
load('RGB.mat')
subplot(3,1,1)
plot(t,R,'r')
subplot(3,1,2)
plot(t,G,'g')
subplot(3,1,3)
plot(t,B,'b')
T1 = max([R; G; B]);
T2 = min([R; G; B]);
T3 = T1 -T2
% get hue
%R, G, B are row vectors
ncols = length([R, G, B]);
hprime = zeros(1, ncols);
for H = 1:ncols
    if T3(H) == 0
        hprime(H) = 0;
    elseif T1(H) == R(H)
        hprime(H) = mod((G(H)-B(H))/T3(H), 6);
    elseif T1(H) == G(H)
        hprime(H) = ((B(H)-R(H))/T3(H))+2;
    elseif T1(H) == B(H)
        hprime(H) = ((R(H)-G(H))/T3(H))+4;
    else
        error('undefined hue at index %d', H);
    end
end

I found some similar post that could answer my questions such as 1 but it is in another language than Matlab. It would be great if you can provide your help with the code that I can also run it on my side as well.

Bilgin
  • 499
  • 1
  • 10
  • 25
  • Change `ncols = length([R, G, B]);` to `ncols = length(R);`. You're getting an out of bounds error. – beaker Jun 16 '19 at 23:12
  • @beaker thank you for your comment. That's true. I had it by mistake. now fixed. I am wondering if you have any suggestion on how I can normalize the raw hue. Thanks. – Bilgin Jun 16 '19 at 23:26
  • Ah, was that your question? I would think that `H = 60 * hprime` would give you the answer in degrees. You should also normalize your RGB values by dividing by 255. – beaker Jun 16 '19 at 23:44

2 Answers2

0

Don't try to reinvent the wheel, use rgb2hsv.

Given vectors R, G and B you can do:

hsv = rgb2hsv([R(:),G(:),B(:)]);
H = hsv(:,1);
Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • Thanks for your comment. I tried that method from Matlab central already. Also when i run ```hsv = rgb2hsv([R(:),G(:),B(:)]);``` it is giving me error as ```Error using rgb2hsv>parseInputs (line 101) Valid colormaps cannot have values outside the range [0,1].``` . I used the ```R = R / 255``` but I am not sure if it's correct. My point by using the formula above that I mentioned to learn the process and I can able to further normalized and process that hue signal. It would be great if you can help me to find a way to implement the code that I mentioned. Thanks for your time. – Bilgin Jun 16 '19 at 18:19
  • @beaker I added my entire code in the post and I am not using built-in function. I am using the math formula from the wiki and i want to learn to do this way. Thanks for your help. – Bilgin Jun 16 '19 at 21:32
  • @Bilgin: Indeed, if your data is doubles, you need to divide by 255 to get into the [0,1] range, such as [Theron explained in their answer](https://stackoverflow.com/a/56626147/7328782). I'm not sure why you are having a problem with your code. I changed `ncols = numel(R)`, and you also need to convert your number 0-6 to a number 0-360 by multiplying `hprime = hprime * 60`. Other than that it works correctly, no? – Cris Luengo Jun 17 '19 at 17:04
  • thanks for your comment. My data is indeed double. @beaker as well commented to use only ```ncols = length(R)``` but I have not tried your comment. I will use your comment and update you soon. My final goal is to be able to detrend the hue and then normalize it and that why i am trying to learn basics from you all and move forward. All the comments are very useful now and making sense as i am new in this domain. – Bilgin Jun 17 '19 at 17:13
0

If you try

x=[R(:),G(:),B(:)]

x ends up with a 2D matrix. Yet hsv2rgb() requires input to be a 3D one. So

I_rgb = zeros(1, length(R), 3);
I_rgb(:, :, 1) = R;
I_rgb(:, :, 2) = G;
I_rgb(:, :, 3) = B;
I_hsv = rgb2hsv(uint8(I_rgb));
h = I_hsv(:, :, 1);

Note that if you do not convert I_rgb into uint8, the range of resulting I_hsv(:, :, 3) will be [0 255] rather than [0, 1]. But if you do not convert it to uint8 but divide I_rgb by 255 beforehand. The resulting range will still be [0, 1], the range of h will always be the same though.

It is just a MATLAB convention of dealing with RGBs in different ranges.

Theron
  • 567
  • 1
  • 7
  • 21
  • `rgb2hsv` takes a color map as input (nx3 matrix). It doesn't need to be a 3D array. Other than that, your comments about data type and limits is correct. – Cris Luengo Jun 17 '19 at 16:59
  • @Theron Thanks for your comment. I think I can use the conversion you explained to 2d and fixed the issue. But my point is to able to normalize it later by mean and std, I guess. I will add more detail in the post after trying your approach. – Bilgin Jun 17 '19 at 17:08
  • @Bilgin. It is a case-by-case issue where to do the normalisation--`y=(x-mean)/std`, but a normalisation should be separated from data range. – Theron Jun 18 '19 at 00:48
  • @CrisLuengo. Yes, it does. Yet the range of RGB colour map should fall into [0, 1], which seems not to be his case. Please see the doc. https://www.mathworks.com/help/matlab/ref/rgb2hsv.html – Theron Jun 18 '19 at 00:54