I have made a JPEG compression using matlab, but i feel confused how to add zig zag scanning, rle, and huffman. I hope you can help me.
This is the code that i have made. Input file is an image (*.bmp).
% dctmtx generates an 8 * 8
dct_matrix = dctmtx(8);
% define function handlers for DCT
dct = #(block_struct) dct_matrix * block_struct.data * dct_matrix';
% define function handlers for inverse DCT
idct = #(block_struct) dct_matrix' * block_struct.data * dct_matrix;
% quantization tables
q_max = 255;
% the quality factor is hardwired here
qf = get(handles.popupmenu1,'Value');
% quantization table for luminance
q_y = ...
[16 11 10 16 24 40 51 61;
12 12 14 19 26 58 60 55;
14 13 16 24 40 57 69 56;
14 17 22 29 51 87 80 62;
18 22 37 56 68 109 103 77;
24 35 55 64 81 104 113 92;
49 64 78 87 103 121 120 101;
72 92 95 98 112 100 103 99].*qf;
% quantization table for chrominance
q_c = ...
[17 18 24 47 99 99 99 99;
18 21 26 66 99 99 99 99;
24 26 56 99 99 99 99 99;
47 66 99 99 99 99 99 99;
99 99 99 99 99 99 99 99;
99 99 99 99 99 99 99 99;
99 99 99 99 99 99 99 99;
99 99 99 99 99 99 99 99].*qf;
% RGB to YCbCr
orig = handles.citra;
ycc = rgb2ycbcr(im2double(orig));
%display the ycbcr
y = ycc(:, :, 1);
cb = ycc(:, :, 2);
cr = ycc(:, :, 3);
% Discrete cosine transform, with scaling before quantization
% q_max is the quantization
% set up the blockprocess functions for the DCT
y = blockproc(y, [8 8], dct) .*q_max;
cb = blockproc(cb, [8 8], dct) .*q_max;
cr = blockproc(cr, [8 8], dct) .*q_max;
% implement the quantization
y = blockproc(y, [8 8], #(block_struct) round(round(block_struct.data) ./ q_y));
cb = blockproc(cb, [8 8], #(block_struct) round(round(block_struct.data) ./ q_c));
cr = blockproc(cr, [8 8], #(block_struct) round(round(block_struct.data) ./ q_c));
% Dequantize DCT coefficients
y = blockproc (y, [ 8 8 ], #(block_struct) block_struct.data .*q_y ) ;
cb = blockproc (cb, [ 8 8 ], #(block_struct) block_struct.data .*q_c ) ;
cr = blockproc (cr, [ 8 8 ], #(block_struct) block_struct.data .*q_c ) ;
% Inverse DCT
y = blockproc (y ./ q_max , [ 8 8 ] , idct);
cb = blockproc (cb ./ q_max , [ 8 8 ] , idct);
cr = blockproc (cr ./ q_max , [ 8 8 ] , idct);
% Concatenate the channels
ycc1 = ycbcr2rgb(cat(3, y, cb ,cr));
axes(handles.axes_hasil);
imshow(ycc1);
Please check "Digital image processing Using MATLAB" book, there is a detailed chapter of JPEG Compression
it has some helpful code for JPEG compression
for the rle, this code might of help
function out=rle(image)
L=prod(size(image));
im=reshape(image,1,L);
x=1;
out=[];
while L~=0;
temp=min(find(im==x));
if isempty(temp)
out=[out L];
break;
end;
out=[out temp-1];
x=1-x;
im=im(temp:L);
L=L-temp+1;
end;
end
Related
Take a 4-D matrix A with s1=size(A,1), s2=size(A,2), s3=size(A,3), s4=size(A,4).
Consider
B=reshape(A, s1*s2*s3*s4,1)
For example,
s1=2;
s2=3;
s3=2;
s4=4;
A(:,:,1,1)=[1 2 3; 4 5 6];
A(:,:,1,2)=[7 8 9; 10 11 12];
A(:,:,1,3)=[13 14 15; 16 17 18];
A(:,:,1,4)=[19 20 21; 22 23 24];
A(:,:,2,1)=[25 26 27; 28 29 30];
A(:,:,2,2)=[31 32 33; 34 35 36];
A(:,:,2,3)=[37 38 39; 40 41 42];
A(:,:,2,4)=[43 44 45; 46 47 48];
B=reshape(A, s1*s2*s3*s4,1);
%B=[1;4;2;5;3;6;25;28;26;29;27;30;7;10;8;11;9;12;...];
Given coordinates (i,j,h,k), I would like your help to write a function that gives me the position of A(i,j,h,k) in B.
I know how to do that when A is a 3-D matrix. In that case,
position_in_B= i + ( j-1 + (h-1)*s2 ) * s1;
How can I extend this result to 4-D matrices?
Here you can use sub2ind , for example:
B(sub2ind(size(A),1,1,1,4))
or you can continue with the extension you wrote:
position_in_B= #(i,j,h,k) i + ( j-1 + ( h-1 + (k-1) *s3 ) *s2 ) * s1;
B(position_in_B(1,1,1,4))
I need to find the difference between positive and negative peaks where the difference is greater than +-3.
I am using findpeaks function in MATLAB to find the positive and negative peaks of the data.
In an example of my code:
[Ypos, Yposloc] = findpeaks(YT0);
[Yneg, Ynegloc] = findpeaks(YT0*-1);
Yneg = Yneg*-1;
Yposloc and Ynegloc return the locations of the positive and negative peaks in the data.
I want to concatenate Ypos and Yneg based on the order of the peaks.
For example, my peaks are
Ypos = [11 6 -10 -10 6 6 6 6 6 -5]
Yneg = [-12 -14 -11 -11 -11 5 5 5 -6]
Locations in YT0
Yposloc = [24 63 79 84 93 95 97 100 156]
Ynegloc = [11 51 78 81 85 94 96 99 154]
In this case, where both Yposloc and Ynegloc are 9x1, I can do the following;
nColumns = size(Yposs,2);
YTT0 = [Yneg, Ypos]';
YTT0 = reshape(YTT0(:),nColumns,[])';
YTT0 = diff(YTT0)
YT0Change = numel(YTT0(YTT0(:)>=3 | YTT0(:)<=-3));
Total changes that I am interested is 6
However, I need to concatenate Yneg and Ypos automatically, based on their locations. So I think I need to to do an if statement to figure out if my positive or negative peaks come first? Then, I am not sure how to tackle the problem of when Ypos and Yneg are different sizes.
I am running this script multiple times where data changes and the negative/positive peak order are constantly changing. Is there a simple way I can compare the peak locations or am I on the right track here?
I would check each minimum with both the previous and the next maxima. In order to do that you can first combine positive and negative peaks according to their order:
Y = zeros(1, max([Yposloc, Ynegloc]));
Yloc = zeros(size(Y));
Yloc(Yposloc) = Yposloc;
Yloc(Ynegloc) = Ynegloc;
Y(Yposloc) = Ypos; % I think you inserted one extra '6' in your code!
Y(Ynegloc) = Yneg;
Y = Y(Yloc ~= 0) % this is the combined signal
Yloc = Yloc(Yloc ~= 0) % this is the combined locations
% Y =
%
% -12 11 -14 6 -11 -10 -11 -10 -11 6 5 6 5 6 5 6 -6 -5
%
% Yloc =
%
% 11 24 51 63 78 79 81 84 85 93 94 95 96 97 99 100 154 156
And then calculate the differences:
diff(Y)
% ans =
%
% 23 -25 20 -17 1 -1 1 -1 17 -1 1 -1 1 -1 1 -12 1
If you want changes of at least 6 units:
num = sum(abs(diff(Y)) > 6)
% num =
%
% 6
Ypos = [11 6 -10 -10 6 6 6 6 -5];
Yneg = [-12 -14 -11 -11 -11 5 5 5 -6];
Yposloc = [24 63 79 84 93 95 97 100 156];
Ynegloc = [11 51 78 81 85 94 96 99 154];
TOTAL=[Yposloc Ynegloc;Ypos Yneg];
%creatin a vector with positions in row 1 and values in row 2
[~,position]=sort(TOTAL(1,:));
%resort this matrix so the values are in the orginial order
TOTAL_sorted=TOTAL(:,position);
%look at the changes of the values
changes=diff(TOTAL_sorted(2,:));
if changes(1)>0
disp('First value was a Minimum')
else
disp('First value was a MAximum')
end
%same structure at the TOTAL matrix
%abs(changes)>3 produces a logical vector that shows where the absolute values was bigger
%than 3, in my opinon its rather intresting where the end is then were the start is
% thats why i add +1
Important_changes=TOTAL_sorted(:,find(abs(changes)>3)+1);
plot(TOTAL_sorted(1,:),TOTAL_sorted(2,:))
hold on
plot(Important_changes(1,:),Important_changes(2,:),...
'Marker','o','MarkerSize',10, 'LineStyle','none');
hold off
I would like to remove the diagonal of the following matrix;
[0 1 1
0 0 0
0 1 0]
and put this in a vector as such
[1 1 0 0 0 1]
Is there a one-way function to do this?
Most other solutions I found on Stack Overflow delete all zeros.
If two lines are fine...
x = x.'; %'// transpose because you want to work along 2nd dimension first
result = x(~eye(size(x))).'; %'// index with logical mask to remove diagonal
Here's an almost one-liner -
[m,n] = size(x);
x(setdiff(reshape(reshape(1:numel(x),m,n).',1,[]),1:m+1:numel(x),'stable'))
And I will put up my fav bsxfun here -
xt = x.'; %//'
[m,n] = size(x);
out = xt(bsxfun(#ne,(1:n)',1:m)).'
Sample run -
>> x
x =
52 62 37 88
23 68 98 91
49 40 4 79
>> [m,n] = size(x);
>> x(setdiff(reshape(reshape(1:numel(x),m,n).',1,[]),1:m+1:numel(x),'stable'))
ans =
62 37 88 23 98 91 49 40 79
>> xt = x.';
>> xt(bsxfun(#ne,(1:n)',1:m)).'
ans =
62 37 88 23 98 91 49 40 79
I'm trying get a basic circular temperature contour graph in MATLAB.
Instead, I'm getting a straight line and doesn't resemble at all to
MATLAB's examples for contour maps. I want 4 circular zones
representing 90 degrees, 80 degrees, 70 degrees, and 60 degrees.
Here is my code:
long = [0 1 2 3; 4 5 6 7; 8 9 10 11; 12 13 14 15];
lat = [15 16 17 18; 19 20 21 22; 23 24 25 26; 27 28 29 30];
temp = [98 95 94 92; 85 82 81 80; 72 75 74 71; 65 62 61 69];
figure;
contour(long,lat,temp,4)
The problem is that you've only provided a line of data and not a matrix. You need to provide a temperature for each pair of long and lat. So if long and lat are both 1x15 then temp should be 15x15.
For example:
x = 1:3
y = 1:3
z = [1 2 1; 2 3 2; 1 2 1];
contour(x,y,z);
Assume we have the following data:
H_T = [36 66 21 65 52 67 73; 31 23 19 33 36 39 42]
P = [40 38 39 40 35 32 37]
Using MATLAB 7.0, I want to create three new matrices that have the following properties:
The matrix H (the first part in matrix H_T) will be divided to 3 intervals:
Matrix 1: the 1st interval contains the H values between 20 to 40
Matrix 2: the 2nd interval contains the H values between 40 to 60
Matrix 3: the 3rd interval contains the H values between 60 to 80
The important thing is that the corresponding T and P will also be included in their new matrices meaning that H will control the new matrices depending on the specifications defined above.
So, the resultant matrices will be:
H_T_1 = [36 21; 31 19]
P_1 = [40 39]
H_T_2 = [52; 36]
P_2 = [35]
H_T_3 = [66 65 67 73; 23 33 39 42]
P_3 = [38 40 32 37]
Actually, this is a simple example and it is easy by looking to create the new matrices depending on the specifications, BUT in my values I have thousands of numbers which makes it very difficult to do that.
Here's a quick solution
[~,bins] = histc(H_T(1,:), [20 40 60 80]);
outHT = cell(3,1);
outP = cell(3,1);
for i=1:3
idx = (bins == i);
outHT{i} = H_T(:,idx);
outP{i} = P(idx);
end
then you access the matrices as:
>> outHT{3}
ans =
66 65 67 73
23 33 39 42
>> outP{3}
ans =
38 40 32 37