the difference between makecform('srgb2xyz') and rgb2xyz() in matlab - matlab

I wonder what the matlab does when using the function rgb2xyz()?
I cannot re-produce the results using the rgb2xyz conversion matrix..
Moreover, is there any difference between using makecform('srgb2xyz') and using rgb2xyz()? they produce difference results..

The default white point for makecform('srgb2xyz') appears to be D50, whereas rgb2xyz defaults to D65.
>> applycform([.2 .3 .4],makecform('srgb2xyz','AdaptedWhitePoint',whitepoint('D65')))
ans =
0.0638 0.0690 0.1356
>> rgb2xyz([.2 .3 .4])
ans =
0.0638 0.0690 0.1356
>> applycform([.2 .3 .4],makecform('srgb2xyz'))
ans =
0.0617 0.0679 0.1024
>> rgb2xyz([.2 .3 .4],'WhitePoint','D50')
ans =
0.0616 0.0679 0.1025
Note the documentation for makecform suggests using the more recent rgb2xyz instead. As for your comment about reproducing the results using a matrix, note that the matrices are generally derived from / applied to linear data. If you want to reproduce the results you'll need to model the srgb gamma correction as well.

Related

rng('default') for rand() function in MATLAB vs Octave

I have a matlab piece of code that generates same random numbers (rand(n,1)) when I initialize with rng('default');
Example:
>> rng('default');
>> rand(3,1)
ans =
0.8147
0.9058
0.1270
Now I need to generate the same output in Octave. Is there an equivalent function for rng('default') in Octave? Please advise on how to get the same set of random numbers as MATLAB in Octave.
From the rand documentation for Octave
By default, the generator is initialized from /dev/urandom if it is available, otherwise from CPU time, wall clock time, and the current fraction of a second. Note that this differs from MATLAB, which always initializes the state to the same state at startup. To obtain behavior comparable to MATLAB, initialize with a deterministic state vector in Octave’s startup files (see ‘Startup Files’).
To get around this difference, you will have to seed both the MATLAB and Octave random number generator, and specify the generation method, to try and ensure they're doing the same thing. Note I say "try" because fundamentally they're different languages and there is no equivalency guarantee.
However, it appears that MATLAB and Octave don't use equivalent seeds. User Markuman has provided an example on the Octave wiki to get around this
Octave
function ret = twister_seed(SEED=0)
ret = uint32(zeros(625,1));
ret(1) = SEED;
for N = 1:623
## initialize_generator
# bit-xor (right shift by 30 bits)
uint64(1812433253)*uint64(bitxor(ret(N),bitshift(ret(N),-30)))+N; # has to be uint64, otherwise in 4th iteration hit maximum of uint32!
ret(N+1) = uint32(bitand(ans,uint64(intmax('uint32')))); # untempered numbers
endfor
ret(end) = 1;
endfunction
octave:1> rand('twister',twister_seed) # notice: default seed is 0 in the function
octave:2> rand
ans = 0.548813503927325
octave:3> rand
ans = 0.715189366372419
octave:4> rand
ans = 0.602763376071644
MATLAB
>> rand('twister',0)
>> rand
ans =
0.548813503927325
>> rand
ans =
0.715189366372419
>> rand
ans =
0.602763376071644
So from the documentation quote at the top of this answer, you could set the random number generator seed during Octave startup if you want this behaviour by default.

integral2 returns 0 when it shouldn't

I am having the following issue. I am trying to integrate a pdf function of bivariate normal over the entire support. However, Matlab returns 0 for d, which shouldn't be the case. What is wrong with my approach?
The code is below:
mu1=100;
mu2=500;
sigma1=1;
sigma2=2;
rho=0.5;
var1=sigma1^2;
var2=sigma2^2;
pdf = #(x,y) (1/(2*pi*sigma1*sigma2*sqrt(1-rho^2))).*exp((-1/(2*(1-rho^2)))*(((x-mu1).^2/var1)+((y-mu2).^2/var2)-((2*rho*(x-mu1).*(y-mu2))/(sigma1*sigma2))));
d = integral2(pdf,-Inf,Inf,-Inf,Inf)
As #Andras Deak commented, the "exponentials cut off very fast away from the peak".
As a matter of fact, you can visualize it:
mu1=100;
mu2=500;
sigma1=1;
sigma2=2;
rho=0.5;
var1=sigma1^2;
var2=sigma2^2;
pdf = #(x,y) (1/(2*pi*sigma1*sigma2*sqrt(1-rho^2))).*exp((-1/(2*(1-rho^2)))*(((x-mu1).^2/var1)+((y-mu2).^2/var2)-((2*rho*(x-mu1).*(y-mu2))/(sigma1*sigma2))));
figure
fsurf(pdf,[90 110 490 510])
figure
fsurf(pdf,[0 200 400 600])
In the first figure, the limits are close to the means you provided. You can see the shape of the bivariate normal:
If you extend the limits, you will see what it looks like a discontinuity:
The built-in integral functions try to evaluate the integrals, but if your limits are -inf and inf, your function is zero almost everywhere, with a discontinuity close to the means.
To treat singularities, you should break your domain, as suggested by MATLAB. Since the function is zero almost everywhere, you can integrate only around the means:
d = integral2(pdf,90,110,490,510)
> d =
>
> 1.0000
You can also write it as a function of your variables. The empirical rule states that 99.7% of your data is within 3 standard deviations from the means, so:
d = integral2(pdf,mu1-3*sigma1,mu1+3*sigma1,mu2-3*sigma2,mu2+3*sigma2)
> d =
>
> 0.9948
which will get you a pretty good result.
We can elaborate more. In the wikipedia page of the empirical rule, the expression
erf(x/sqrt(2))
will give the "Expected fraction of population inside range mu+-x*sigma". For the short precision shown as standard in MATLAB, if you choose, say x=5, you will get:
x = 5;
erf(x/sqrt(2))
> ans =
>
> 1.0000
Pretty much every data is contained within 5 standard deviations. So, you may neglect the domain outside this range in the double integration to avoid the (almost) singularity.
d = integral2(pdf,mu1-x*sigma1,mu1+x*sigma1,mu2-x*sigma2,mu2+x*sigma2)
> d =
>
> 1.0000

Two versions of the same code return different results

I expect to get the same results when compressing these two MATLAB lines of code into one, but I don't!
Code in 2 lines:
[b,a]= butter(2,[0.4 0.6]) % Transfer function coefficients of the filter
[A,B,C,D] = tf2ss(b,a) % State-space representation of the filter
Code in 1 line:
[A,B,C,D]= butter(2,[0.4 0.6]) % State-space representation of the filter
butter :
returns the transfer function coefficients when b,a are Outputs
returns the state-space matrices when A,B,C,D are Outputs
tf2ss :
Convert transfer function filter parameters to state-space form
The two state-space representations you are obtaining are valid. The state-space representation of a filter is not unique. The two give the same results when applied to an input signal.
The likely reason why the two state-space representations are not the same is that they are obtained following different routes:
In the two-step version of your code, you obtain the transfer-function representation and then convert to state-space, using tf2ss.
In the one-step version, butter internally obtains the zero-pole representation and then converts to state-space, using zp2ss (at least this it what it does in R2018b).
Here is a check that they are indeed equivalent.
[b,a]= butter(2,[0.4 0.6]);
[A2,B2,C2,D2] = tf2ss(b,a); % 2 steps
[A1,B1,C1,D1]= butter(2,[0.4 0.6]); % 1 step
Define an input signal:
x = rand(1,100);
Create the two filter objects from their state-space representations:
Hd2 = dfilt.statespace(A2,B2,C2,D2);
Hd1 = dfilt.statespace(A1,B1,C1,D1);
Obtain the two outputs:
y2 = Hd2.filter(x);
y1 = Hd1.filter(x);
Compare the outputs. The difference is of the order of eps, that is, neglibible:
max(abs(y1))
max(abs(y2))
max(abs(y1-y2))
ans =
0.348561524872161
ans =
0.348561524872160
ans =
8.153200337090993e-16
You can also check that both state-space representations give the same transfer-function representation:
[b1,a1] = ss2tf(A1,B1,C1,D1)
[b2,a2] = ss2tf(A2,B2,C2,D2)
b1 =
0.067455273889072 0.000000000000000 -0.134910547778144 0.000000000000000 0.067455273889072
a1 =
1.000000000000000 -0.000000000000001 1.142980502539900 -0.000000000000001 0.412801598096187
b2 =
0.067455273889072 0.000000000000000 -0.134910547778144 -0.000000000000000 0.067455273889072
a2 =
1.000000000000000 -0.000000000000001 1.142980502539899 -0.000000000000002 0.412801598096187
Actually, the line 1 code should be changed to below.
[A,B,C,D]= tf2ss(butter(2,[0.4 0.6]));
But, this also will not give the desired answer since, trf2ss required two inputs as input parameters. The above code gives only one input, which is a vector with two values. In Matlab, vectors are a separate type of variables, hence will not work as we expect some times.

Simulations of discrete transfer functions with different results

I have created 'same' discrete transfer function in two different modes. Then I simulated them against the same input.
Why are the results different? What is the difference between the two?
Code:
close all;clear;clc;
Ts=0.001;
t = 0:Ts:10;
%input
u=rand(length(t),1);
%1st TF
test_tf=c2d( tf([8 18 32],[1 6 14 24]),Ts );
y=lsim(test_tf,u,t);
%2nd TF
test_d_tf=tf([0.007985 -0.01595 0.007967],[1 -2.994 2.988 -0.994],Ts);
y_d=lsim(test_d_tf,u,t);
%plotting
plot(t,u,'k:',t,y,'b-',t,y_d,'r--');
And their results are:
Entire simulation interval:
and Zoomed:
My guess is because the tfs aren't actually the same, they only look it because of the formatting:
>>format long
>>test_d_tf.Numerator{1}
ans =
0 0.007985000000000 -0.015950000000000 0.007967000000000
>> test_tf.Numerator{1}
ans =
0 0.007985016651180 -0.015952055311304 0.007967070564278

Octave inaccurately solving systems of linear equations?

I found that Octave inaccurately solves system of equations.
k= [1.0000e+015, -2.6667e-001, 3.3333e-002;-2.6667e-001, 5.3333e-001, -2.6667e-001;3.3333e-002, -2.6667e-001, 2.3333e-001];
f = [0;6.66667;41.66667];
x = (k\f)
x1 = inv(k)*f
x = (k\f) gives
-3.8893e-031
-1.9136e+001
1.1192e+001
x1 = inv(k)*f gives
4.8339e-014
2.3752e+002
4.5003e+002
There is difference between two answers. Just to check whether other software can solve it, I tried in python numpy.
import numpy as np
k = np.array ([[1.0000e+015, -2.6667e-001, 3.3333e-002],[-2.6667e-001, 5.3333e-001, -2.6667e-001],[ 3.3333e-002, -2.6667e-001, 2.3333e-001]])
f = np.array([[0],[6.66667],[41.66667]])
x = np.linalg.solve(k, f)
print(x)
[[ 4.83388655e-14]
[ 2.37521517e+02]
[ 4.50034428e+02]]
And it solves correctly.
I want to use operator \ in octave to solve equations (I guess this is recommended method in MATLAB). Any suggestions?
Using Octave 4.2.x on Windows.
EDIT:
Why the answer is downvoted? Here is what GNU Octave says https://www.gnu.org/software/octave/:
Drop-in compatible with many Matlab scripts
Try running the same script in MATLAB and think yourself.
Commenters blame on ill-conditioned matrix. A good solver should able to solve with sufficient accuracy (as numpy and MATLAB do).
Summary: Octave developers have chosen to return the "minimum norm solution" for a (flagged) singular system of equations.
===============
The first element of k is much larger than all the others, while the corresponding term of f is 0. In the x1 solution
4.8339e-014
2.3752e+002
4.5003e+002
the first term is virtually 0.
Performing the solve on the remaining 2x2 matrix, produces the same values:
>> inv(k(2:end,2:end))*f(2:end)
ans =
237.52
450.03
>> k(2:end,2:end)\f(2:end)
ans =
237.52
450.03
and in numpy:
In [518]: np.linalg.solve(k[1:,1:],f[1:])
Out[518]:
array([[ 237.52151737],
[ 450.0344278 ]])
=================
For some reason, the \ solver is more sensitive to matrix singularity.
>> k\f
warning: matrix singular to machine precision, rcond = 6.66612e-17
warning: matrix singular to machine precision, rcond = 6.66612e-17
and yes, testing this solution shows that it's way off
>> k*(k\f)
ans =
5.4761
-13.1904
7.7144
>> rcond(k)
ans = 6.6661e-17
>> rcond(k(2:end,2:end))
ans = 0.083327
I'm not sure of the significance of this, but the numpy lstsqr solver returns the same bad-values as k\f:
In [525]: np.linalg.lstsq(k,f)
Out[525]:
(array([[ -3.88925778e-31],
[ -1.91360857e+01],
[ 1.11917602e+01]]),
array([], dtype=float64),
2,
array([ 1.00000000e+15, 6.89292234e-01, 7.73677656e-02]))
>> pinv(k)*f # Moore-Penrose pseudoinverse
ans =
-3.8893e-31
-1.9136e+01
1.1192e+01
http://savannah.gnu.org/bugs/?42181 - claims that this is documented. For an singular, or under or overdetermined equation Octave returns the "minimum norm solution", as opposed to a "basic solution" (MATLAB's choice).
http://wiki.octave.org/FAQ#Solvers_for_singular.2C_under-_and_over-determined_matrices