Why is there difference in the DCT coefficients between matlab and libjpeg - matlab

I need to manipulate the DCT coefficients of a JPEG image, so I got the values using libjpeg and matlab. The problem is that I am getting different values.
I am working on the following image:
libjpeg
I have used jpeg_read_coefficients to get the virtual array and then iterate over it and printed the DCT values, for the first array and first dct block I got the following values:
9 8 10 6 3 1 1 0 -6 0 1 0 0 0 0 0 6 -1 -1 0 0 0 0 0 5 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
This is the coefficients in straight order as said in the documentation.
Matlab
In order to get the coefficients I read the image and ran dct2 function on its first 8X8 block:
A = imread('test2.jpg');
dct2(A(1:8,1:8,1));
and came up with the following values(For the RGB color space):
404.7500 -2.5251 15.1704 18.4835 14.7500 8.0465 10.4933 1.6169
-50.4069 0.4634 3.2328 -0.3498 -0.6745 0.9465 0.4599 0.5694
16.0546 -1.7709 -3.3624 -0.0164 0.2310 -0.9791 -0.1250 -1.0587
14.7190 0.9301 -0.0935 0.2866 -0.5779 -0.2573 1.2260 0.1872
15.5000 0.4715 -1.2505 -0.9827 -0.0000 0.1208 0.2474 1.4739
9.4079 0.5931 -0.3263 0.0659 0.4536 0.2866 -0.3059 0.3997
10.6682 0.2906 0.1250 -0.6038 -0.0957 -0.0583 -0.8876 -1.2576
0.7863 -0.1074 -0.7177 -0.4161 0.9382 -0.6301 -0.7815 0.4634
And those values for YCbCr color space:
1.0e+03 *(
1.0305 0.0142 0.0168 0.0151 0.0130 0.0071 0.0085 0.0003
-0.0100 0.0002 0.0029 -0.0001 -0.0002 0.0006 -0.0004 -0.0005
0.0151 -0.0024 -0.0025 -0.0000 0 -0.0002 -0.0005 -0.0000
0.0132 -0.0000 -0.0004 -0.0007 -0.0008 -0.0008 -0.0001 0.0011
0.0140 -0.0004 0.0003 -0.0010 0.0005 -0.0002 0.0001 -0.0004
0.0086 0.0001 -0.0000 0.0002 0.0004 0.0004 -0.0003 0.0001
0.0078 -0.0002 -0.0005 -0.0000 0 -0.0003 -0.0000 -0.0005
0.0003 -0.0000 -0.0003 0.0003 0.0012 -0.0003 -0.0002 -0.0005)
My guess, since I couldn't approve it with the libjpeg documentation, is that the coefficients are for the YCbCr space.
I understand that the values in the libjpeg are after quantization error and the first DC component is decoded by the difference so lets take a look at the second component, its quantization constant is 2 (retrieved with hex dump from the raw data) so the difference can be at most 2.
The computed DCT value for the second coefficient in the Matlab calculation is 14.2 while in the raw image its 8. And I cant figure out what I have done wrong, any ideas and suggestions are welcome.

Related

How Solve equation having Matrix parameters in Matlab

I want to solve the following equation for X. All parameters in my equation are matrices:
( [A]' * [X] )+( [X] * [A] ) = -I
I =
0 0 0 0
0 0 0 0
0 0 6.7955 -2.8529
0 0 -2.8529 3.9426
and
[A] =
-0.0038 -0.0011 -0.0012 -0.0012
-0.0011 -0.0049 -0.0012 -0.0023
1.0000 0 0 0
0 1.0000 0 0
You can use sylvester:
>> sylvester(A', A, -I)
ans =
1.0e+06 *
2.2772 -1.4202 0.0071 -0.0045
-1.4202 0.9749 -0.0043 0.0032
0.0071 -0.0043 0.0011 -0.0005
-0.0045 0.0032 -0.0005 0.0005

MvNormal Error with Symmetric & Positive Semi-Definite Matrix

The summary of my problem is that I am trying to replicate the Matlab function:
mvnrnd(mu', sigma, 200)
into Julia using:
rand( MvNormal(mu, sigma), 200)'
and the result is a 200 x 7 matrix, essentially generating 200 random return time series data.
Matlab works, Julia doesn't.
My input matrices are:
mu = [0.15; 0.03; 0.06; 0.04; 0.1; 0.02; 0.12]
sigma = [0.0035 -0.0038 0.0020 0.0017 -0.0006 -0.0028 0.0009;
-0.0038 0.0046 -0.0011 0.0001 0.0003 0.0054 -0.0024;
0.0020 -0.0011 0.0041 0.0068 -0.0004 0.0047 -0.0036;
0.0017 0.0001 0.0068 0.0125 0.0002 0.0109 -0.0078;
-0.0006 0.0003 -0.0004 0.0002 0.0025 -0.0004 -0.0007;
-0.0028 0.0054 0.0047 0.0109 -0.0004 0.0159 -0.0093;
0.0009 -0.0024 -0.0036 -0.0078 -0.0007 -0.0093 0.0061]
Using Distributions.jl, running the line:
MvNormal(sigma)
Produces the error:
ERROR: LoadError: Base.LinAlg.PosDefException(4)
The matrix sigma is symmetrical but only positive semi-definite:
issym(sigma) #symmetrical
> true
isposdef(sigma) #positive definite
> false
using LinearOperators
check_positive_definite(sigma) #check for positive (semi-)definite
> true
Matlab produces the same results for these tests however Matlab is able to generate the 200x7 random return sample matrix.
Could someone advise as to what I could do to get it working in Julia? Or where the issue lies?
Thanks.
The issue is that the covariance matrix is indefinite. See
julia> eigvals(sigma)
7-element Array{Float64,1}:
-3.52259e-5
-2.42008e-5
2.35508e-7
7.08269e-5
0.00290538
0.0118957
0.0343873
so it is not a covariance matrix. This might have happened because of rounding so if you have access to unrounded data you can try that instead. I just tried and I also got an error in Matlab. However, in contrast to Julia, Matlab does allow the matrix to be positive semidefinite.
A way to make this work is to add a diagonal matrix to the original matrix and then input that to MvNormal. I.e.
julia> MvNormal(randn(7), sigma - minimum(eigvals(Symmetric(sigma)))*I)
Distributions.MvNormal{PDMats.PDMat{Float64,Array{Float64,2}},Array{Float64,1}}(
dim: 7
μ: [0.889004,-0.768551,1.78569,0.130445,0.589029,0.529418,-0.258474]
Σ: 7x7 Array{Float64,2}:
0.00353523 -0.0038 0.002 0.0017 -0.0006 -0.0028 0.0009
-0.0038 0.00463523 -0.0011 0.0001 0.0003 0.0054 -0.0024
0.002 -0.0011 0.00413523 0.0068 -0.0004 0.0047 -0.0036
0.0017 0.0001 0.0068 0.0125352 0.0002 0.0109 -0.0078
-0.0006 0.0003 -0.0004 0.0002 0.00253523 -0.0004 -0.0007
-0.0028 0.0054 0.0047 0.0109 -0.0004 0.0159352 -0.0093
0.0009 -0.0024 -0.0036 -0.0078 -0.0007 -0.0093 0.00613523
)
The "covariance" matrix is of course not the same anymore, but it is very close.

for loops and matrices in matlab

I am trying to link two equations, where I use a for loop calculate the value of k from the range of frequencies (eg. 1-5 Hz) then use each of the k values and substitute the values of k into a 6x6 matrix. Can anyone help show me how to create a matrix for each value of k in Matlab?
1st Equation
for f = 1:5; % Range of Frequencies (Hz)
f;
w = 2.*pi.*f; % Angular Frequency (Hz)
p = 8050;% Density of Mild Steel(kg/m^3)
v = 0.30; % Poissons Ratio of Mild Steel
R = 0.02; % Radius of Pipe (m)
E = 210*10^9; % Youngs Modulus of Mild Steel (pa)
a = (w.^2).*p;
b = (p.*(1-(v.^2)).*(R.^2).*(w.^2)-E);
c = (p.*(R.^2).*(w.^2)-E).*E;
**k(f) = sqrt((a.*b)/c); % k = Wave Number**
end
2nd Equation (6x6 Matrix)
k =
L1=0.1;
L2=0.6;
L3=0.6;
D= [0,0,exp(-k*L1),exp(-k*L2),0,0; exp(-k*L1),1,exp(-k*L1),exp(-k*L2),0,0; -k*exp(-k*L1),k,k*exp(-k*L1),-k*exp(-k*L2),0,0;0,0,exp(-k*(L1+L2)),k,-exp(-k*(L1+L2)),-exp(-k*L3);0,0,-k*exp(-k*(L1+L2)),1,k*exp(-k*(L1+L2)),k*exp(-k*L3);0,0,exp(-k*(L1+L2)),1,0,0]
(Answer modified following the comment)
You can try definig the output array D as a 3 dimensions array.
D=NaN(6,6,length(k))
for i=1:length(k)
D(:,:,i)= [0,0,exp(-k(i)*L1),exp(-k(i)*L2),0,0; exp(-k(i)*L1),1,exp(-k(i)*L1),exp(-k(i)*L2),0,0; -k(i)*exp(-k(i)*L1),k(i),k(i)*exp(-k(i)*L1),-k(i)*exp(-k(i)*L2),0,0;0,0,exp(-k(i)*(L1+L2)),k(i),-exp(-k(i)*(L1+L2)),-exp(-k(i)*L3);0,0,-k(i)*exp(-k(i)*(L1+L2)),1,k(i)*exp(-k(i)*(L1+L2)),k(i)*exp(-k(i)*L3);0,0,exp(-k(i)*(L1+L2)),1,0,0]
end
The D array will be:
D(:,:,1) =
0 0 0.9999 0.9993 0 0
0.9999 1.0000 0.9999 0.9993 0 0
-0.0012 0.0012 0.0012 -0.0012 0 0
0 0 0.9991 0.0012 -0.9991 -0.9993
0 0 -0.0012 1.0000 0.0012 0.0012
0 0 0.9991 1.0000 0 0
D(:,:,2) =
0 0 0.9998 0.9985 0 0
0.9998 1.0000 0.9998 0.9985 0 0
-0.0025 0.0025 0.0025 -0.0025 0 0
0 0 0.9983 0.0025 -0.9983 -0.9985
0 0 -0.0025 1.0000 0.0025 0.0025
0 0 0.9983 1.0000 0 0
D(:,:,3) =
0 0 0.9996 0.9978 0 0
0.9996 1.0000 0.9996 0.9978 0 0
-0.0037 0.0037 0.0037 -0.0037 0 0
0 0 0.9974 0.0037 -0.9974 -0.9978
0 0 -0.0037 1.0000 0.0037 0.0037
0 0 0.9974 1.0000 0 0
D(:,:,4) =
0 0 0.9995 0.9971 0 0
0.9995 1.0000 0.9995 0.9971 0 0
-0.0049 0.0049 0.0049 -0.0049 0 0
0 0 0.9966 0.0049 -0.9966 -0.9971
0 0 -0.0049 1.0000 0.0049 0.0049
0 0 0.9966 1.0000 0 0
D(:,:,5) =
0 0 0.9994 0.9963 0 0
0.9994 1.0000 0.9994 0.9963 0 0
-0.0061 0.0062 0.0061 -0.0061 0 0
0 0 0.9957 0.0062 -0.9957 -0.9963
0 0 -0.0061 1.0000 0.0061 0.0061
0 0 0.9957 1.0000 0 0
Hope this helps.
I will try to answer your question...
Firstly, you don't need the initial for loop. You can calculate all values of wavelength without loops.
f = 1:5; % Range of Frequencies (Hz)
w = 2.*pi.*f; % Angular Frequency (Hz)
p = 8050;% Density of Mild Steel(kg/m^3)
v = 0.30; % Poissons Ratio of Mild Steel
R = 0.02; % Radius of Pipe (m)
E = 210*10^9; % Youngs Modulus of Mild Steel (pa)
a = (w.^2).*p;
b = (p.*(1-(v.^2)).*(R.^2).*(w.^2)-E);
c = (p.*(R.^2).*(w.^2)-E).*E;
k = sqrt((a.*b)./c); % k = Wave Number
L1=0.1;
L2=0.6;
L3=0.6;
Then you can use a for loop to calculate the D matrix and a cell array to store the results:
results = cell(1, length(k));
for i = 1:length(k)
results{i} = [
0,0,exp(-k(i)*L1),exp(-k(i)*L2),0,0;...
exp(-k(i)*L1),1,exp(-k(i)*L1),exp(-k(i)*L2),0,0;...
-k(i)*exp(-k(i)*L1),k(i),k(i)*exp(-k(i)*L1),-k(i)*exp(-k(i)*L2),0,0;...
0,0,exp(-k(i)*(L1+L2)),k(i),-exp(-k(i)*(L1+L2)),-exp(-k(i)*L3);...
0,0,-k(i)*exp(-k(i)*(L1+L2)),1,k(i)*exp(-k(i)*(L1+L2)),k(i)*exp(-k(i)*L3);...
0,0,exp(-k(i)*(L1+L2)),1,0,0
]
end
P.S. Without trying to get on to you, I think that what you just want is to someone solve an excercise for you. If this is not the case, ignore my p.s.

MatLab: Create 3D Histogram from sampled data

I have sampled data in the interval [0,1] in an Array transitions=zeros(101,101) which I want to plot as a 3D-histogram. transitions is filled with data similar to the example data provided at the end of this thread.
The first columns refers to the first observed variable X, the second column to the second variable Y and the third column is the normalized frequency. I.e. for the first row: the observed normalized frequency of the variable pair (0,0) is 0.9459. The sum of the normalized frequencies for (0,Y)thus is 1.
I tried to make (sort of) a 3D histogram with the following code:
x_c = (transitions(:,1) * 100)+1;
y = (transitions(:,2) * 100)+1;
z = transitions(:,4);
%A = zeros(10,10);
A = zeros(max(x_c),max(y));
for i = 1:length(x_c)
try
if(z(i)>0)
A(int32(x_c(i)), int32(y(i))) = abs(log(z(i)));
else
% deal with exceptions regarding log(0)
A(int32(x_c(i)), int32(y(i))) = 0;
end
catch
disp('');
end
end
bar3(A);
However, since it is sampled data in a discrete space A the output looks like the plot below. This is somehow misleading as there are 'gaps' in the plot (z-value = 0 for coordinates where I have no sampled data). I rather would like to have the sampled data being assigned to their corresponding plots, thus resulting in a 'real' 3d histogram.
By the way, as a result of my 'hack' of creating A also the x-,y- and z-scale is not correct. The 3D histogram's axes (all three) should be in the interval of [0,1].
ans =
0 0 0.9459
0 0.0500 0.0256
0 0.1000 0.0098
0 0.1100 0.0004
0 0.1500 0.0055
0 0.1600 0.0002
0 0.2000 0.0034
0 0.2100 0.0001
0 0.2500 0.0024
0 0.2600 0.0001
0 0.3000 0.0018
0 0.3200 0.0000
0 0.3700 0.0000
0 0.4000 0.0010
0 0.4200 0.0000
0 0.4500 0.0007
0 0.5000 0.0007
0 0.5300 0.0000
0 0.5500 0.0005
0 0.6000 0.0005
0 0.6300 0.0000
0 0.7000 0.0002
0 0.7400 0
0 0.7500 0.0003
0 0.7900 0.0000
0 0.8000 0.0002
0 0.8400 0.0000
0 0.8500 0.0002
0 0.8900 0.0000
0 0.9000 0.0002
0 0.9500 0.0001
0 1.0000 0.0001
0.0500 0 0.0235
0.0500 0.0500 0.0086
0.0500 0.1000 0.0045
. . .
. . .
. . .
. . .
. . .
0.9500 0.9000 0.0035
0.9500 0.9500 0.0066
0.9500 1.0000 0.0180
1.0000 0 0.0001
1.0000 0.0500 0.0001
1.0000 0.1000 0.0001
1.0000 0.1100 0.0000
1.0000 0.1500 0.0001
1.0000 0.1600 0.0000
1.0000 0.2000 0.0001
1.0000 0.2100 0.0000
1.0000 0.2500 0.0001
1.0000 0.2600 0.0000
1.0000 0.3000 0.0001
1.0000 0.3200 0.0000
1.0000 0.3700 0.0000
1.0000 0.4000 0.0002
1.0000 0.4200 0
1.0000 0.4500 0.0002
1.0000 0.5000 0.0003
1.0000 0.5300 0.0000
1.0000 0.5500 0.0004
1.0000 0.6000 0.0004
1.0000 0.6300 0.0000
1.0000 0.7000 0.0007
1.0000 0.7400 0.0000
1.0000 0.7500 0.0010
1.0000 0.7900 0.0000
1.0000 0.8000 0.0015
1.0000 0.8400 0.0001
1.0000 0.8500 0.0024
1.0000 0.8900 0.0002
1.0000 0.9000 0.0042
1.0000 0.9500 0.0111
1.0000 1.0000 0.3998
I found a solution by working on the non-aggregated data. In particular each row of the data set transitions contains one observation of Xand Y. I used the code below to produce a normalized 3D histogram (and a 2D map) as folllows:
function createHistogram(transitions)
uniqueValues = unique(transitions(:,1));
biases = cell(numel(uniqueValues),1);
for i = 1:numel(uniqueValues)
start = min(find(transitions(:,1) == uniqueValues(i)));
stop = max(find(transitions(:,1) == uniqueValues(i)));
biases(i) = mat2cell(transitions(start:stop,2));
end
combinedBiases = padcat(biases{1},biases{2},biases{3},biases{4},...
biases{5},biases{6},biases{7},biases{8},biases{9},biases{10},...
biases{11},biases{12},biases{13},biases{14},biases{15},biases{16},...
biases{17},biases{18},biases{19});
bins = 0:0.1:1;
[f, x] = hist(combinedBiases, bins);
%
% normalize
%
for i = 1:numel(f(1,:))
for j = 1:numel(f(:,i))
f(j,i) = f(j,i)/numel(biases{i});
end
end
bHandle = bar3(x, f);
ylim([-0.04,1.04])
for k = 1:length(bHandle)
zdata = get(bHandle(k),'ZData');
set(bHandle(k),'CData',zdata, 'FaceColor','interp');
end
colormap('autumn');
hcol = colorbar();
axis('square');
cpos=get(hcol,'Position');
cpos(4)=cpos(4)/3; % Halve the thickness
cpos(2)=0.4; % Move it down outside the plot#
cpos(1)=0.82;
set(hcol, 'Position',cpos);
xlabel('Enrollment biases');
ylabel('Aging biases');
zlabel('Bias transition probability');
title(strcat('Probability mass function of bias transitions (', device,')'));
set(gca,'XTick',0:2:20);
set(gca,'XTickLabel',0:0.1:1);
print('-dpng','-r600',strcat('tau_PMF3D_enrollment-ageing-', device));
view(2);
cpos(1)=0.84;
set(hcol, 'Position',cpos);
print('-dpng','-r600',strcat('tau_PMF2D_enrollment-ageing-', device));
end
From the comment on the question it appears you have the values you want to represent each bin count. If so an alternative solution is to plot using hist3 with "junk" data using correct x and y scales and then update the zdata of the surface object created with your bin data (modified to be in the correct format).
This modification to the bin data is fairly simple and consists of reshaping into a matrix then replicating and padding all the elements, the method is included in the code below.
Based on the ans variable at the end of the question, assuming
ans(:,1) gives x values
ans(:,2) gives y values
ans(:,3) gives the normalised bin counts
code
%// Inputs
zdata=ans(:,3); %// zdata=rand(21*21,1); % for testing
xvalues = 0:0.05:1;
yvalues = 0:0.05:1;
%// plot with junk data, [0,0] in this case
nx = numel(xvalues); ny = numel(yvalues);
bincenters = { xvalues , yvalues };
hist3([0,0],bincenters);
Hsurface = get(gca,'children');
%// apply bin count format
pad = [0 0 0 0 0;0 1 1 0 0;0 1 1 0 0;0 0 0 0 0;0 0 0 0 0]; %// padding for each point
ztrans=kron(reshape(zdata,[nx,ny]),pad); %// apply padding to each point
%// update plot
set(Hsurface,'ZData',ztrans)
%// to set colour based on bar height
colormap('autumn');
set(Hsurface,'CData',ztrans,'FaceColor','interp')
output

Matlab: Avoid exp(-3) conversion at text data input

I have a txt file with data, so I used the following function
M = dlmread('data.txt', '\t');
But My data is getting converted to exp(-3) how do I avoid that?
Here how the data look like:
M =
1.0e+03 *
0 0.0080 0.3500 0.1500 4.6990 0.0145 0.0740 0
0 0.0080 0.4000 0.1700 4.7460 0.0120 0.0710 0
0 0.0080 0.4000 0.1750 4.3850 0.0120 0.0720 0
0 0.0060 0.2500 0.0720 3.1580 0.0195 0.0750 0
0 0.0080 0.3040 0.1500 3.8920 0.0125 0.0720 0
0 0.0080 0.3500 0.1450 4.4400 0.0140 0.0750 0
0 0.0060 0.2500 0.1050 3.8970 0.0185 0.0750 0
0 0.0060 0.1630 0.1330 3.4100 0.0158 0.0780 0.0010
0 0.0080 0.2600 0.1100 4.0600 0.0190 0.0770 0
As H Muster says, this is a display issue.
A better way (in my opinion) of displaying your data is via num2str.
If you run
num2str(M)
you will see
ans =
0 0.008 0.35 0.15 4.699 0.0145 0.074 0
0 0.008 0.4 0.17 4.746 0.012 0.071 0
0 0.008 0.4 0.175 4.385 0.012 0.072 0
0 0.006 0.25 0.072 3.158 0.0195 0.075 0
0 0.008 0.304 0.15 3.892 0.0125 0.072 0
0 0.008 0.35 0.145 4.44 0.014 0.075 0
0 0.006 0.25 0.105 3.897 0.0185 0.075 0
0 0.006 0.163 0.133 3.41 0.0158 0.078 0.001
0 0.008 0.26 0.11 4.06 0.019 0.077 0
which is probably what you were expecting in the first place.
If you want more precision, pass a format string to num2str.
For example:
num2str(M,'%8g')