Image compression using orthogonal polynomial Transformation [duplicate] - matlab

I am working on Image compression based on orthogonal polynomial transformation. My input image is gray scale image of size 256*256. i divide this image into 4 by 4 blocks. and than apply the orthogonal polynomial operator on each block. but I am not getting correct coefficient.
Example:
If I have a block 4x4 of Input image:
I=[5 11 8 10;9 8 4 12; 1 10 11 4;19 6 15 7];
and my polynomial operator for n=4 is:
[M] = [p0 p1 p2 p3]=[1 -3 1 -3;1 -1 -1 9;1 1 -1 -9;1 3 1 3]
After finding the outer product:
[20 -24 24 -16; -24 84 -80 24;24 -80 84 -24;-16 24 -24 20]
when I applied this on input image blocks, my answer is:
[-396 172 88 -104; 1012 -248 -376 616 -972 320 436 -552; 492 -104 4 172]
which is wrong. It should be
[140 0 -6 -10; 32 -112 2 -174; 22 -30 8 -40;34 -54 84 -8]
what I have done wrong?
My MATLAB code to find orthogonal polynomial operator is given below.
clc
clear all
close all
ID=imread('cameraman.tif'); % input image
I=double(ID);
imshow(ID);
[r,c]=size(I);
y1=zeros(r,c);
x=1:4;
n=4;
mu=(n+1)/2;
p0=[1 1 1 1];
p1=x-mu;
p2=(x-mu).^2-(n.^2-1)/12;
p3=(x-mu).^3-((x-mu)*(3*n.^2-7))/20;
P=[p0;p1; p2; p3];
N=[1 1 1 1;-1.5 -0.5 0.5 1.5;1 -1 -1 1;-0.3 0.9 -0.9 0.3];
M=[1 1 1 1;-3 -1 1 3;1 -1 -1 1;-3 9 -9 3]; % after sacling
v=M';
O=M.*v;
T=O'; % Orthogonal polynomial operator
for i=1:4:r
for j=1:4:c
y1(i:i+3,j:j+3)=I(i:i+3,j:j+3).*(double(T));
end
end
figure,imshow(uint8(y1))
y1

Related

How to apply orthogonal polynomial transformation on an image for image compression?

I am working on Image compression based on orthogonal polynomial transformation. My input image is gray scale image of size 256*256. i divide this image into 4 by 4 blocks. and than apply the orthogonal polynomial operator on each block. but I am not getting correct coefficient.
Example:
If I have a block 4x4 of Input image:
I=[5 11 8 10;9 8 4 12; 1 10 11 4;19 6 15 7];
and my polynomial operator for n=4 is:
[M] = [p0 p1 p2 p3]=[1 -3 1 -3;1 -1 -1 9;1 1 -1 -9;1 3 1 3]
After finding the outer product:
[20 -24 24 -16; -24 84 -80 24;24 -80 84 -24;-16 24 -24 20]
when I applied this on input image blocks, my answer is:
[-396 172 88 -104; 1012 -248 -376 616 -972 320 436 -552; 492 -104 4 172]
which is wrong. It should be
[140 0 -6 -10; 32 -112 2 -174; 22 -30 8 -40;34 -54 84 -8]
what I have done wrong?
My MATLAB code to find orthogonal polynomial operator is given below.
clc
clear all
close all
ID=imread('cameraman.tif'); % input image
I=double(ID);
imshow(ID);
[r,c]=size(I);
y1=zeros(r,c);
x=1:4;
n=4;
mu=(n+1)/2;
p0=[1 1 1 1];
p1=x-mu;
p2=(x-mu).^2-(n.^2-1)/12;
p3=(x-mu).^3-((x-mu)*(3*n.^2-7))/20;
P=[p0;p1; p2; p3];
N=[1 1 1 1;-1.5 -0.5 0.5 1.5;1 -1 -1 1;-0.3 0.9 -0.9 0.3];
M=[1 1 1 1;-3 -1 1 3;1 -1 -1 1;-3 9 -9 3]; % after sacling
v=M';
O=M.*v;
T=O'; % Orthogonal polynomial operator
for i=1:4:r
for j=1:4:c
y1(i:i+3,j:j+3)=I(i:i+3,j:j+3).*(double(T));
end
end
figure,imshow(uint8(y1))
y1

Find the difference between positive and negative peaks MATLAB

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

How is full convolution performed using MATLAB's conv2 function?

I am trying to get some input on MATLAB's conv2 function. Suppose that we have an image I of dimensions 5 x 5 and a kernel K that is 3 x 3.
conv2(I,K) would return a 7 x 7 matrix. What extra operations are being done that I am not aware of? I can totally understand how conv2(I,K,'valid') and conv2(I,K,'same') works from a mathematical point of view. However, the default operation returns a larger matrix. Does anyone know what it actually does?
If you know how the 'valid' flag and 'same' flag work, then it's not that far of a stretch to go to what the default option is, which is the 'full' option. As you slide the kernel across the image / matrix, as soon as at least one element from the kernel touches any element from the image / matrix, that is considered valid output. The output of the operation is dictated by the centre of where the kernel is when there is a valid output. For example, take a look at the following 5 x 5 image I below with an example 3 x 3 kernel K:
I = [1 2 3 4 5 ] K = [1 0 1]
[6 7 8 9 10] [1 0 1]
[11 12 13 14 15] [1 0 1]
[16 17 18 19 20]
[21 22 23 24 25]
Note that the numbers aren't that important but they're used for illustration. Also note that the kernel is symmetric and so performing a 180 degree rotation results in the same kernel. This is required of convolution before we start. In the 'full' configuration, we slide the kernel from the top left to bottom right in a left to right, up to down fashion. The output of the first element in the output matrix happens when the bottom right of the kernel touches the top left of the image / matrix:
[1 0 1]
[1 `0` 1]
[1 0 [1*1] 2 3 4 5]
[6 7 8 9 10]
[11 12 13 14 15]
[16 17 18 19 20]
[21 22 23 24 25]
Note that the centre of the kernel as we sweep across the image is the location where we need to output in the image, denoted by the `` symbols. Remember that to compute convolution here, we find the weighted and element-wise sum of products between each element in the kernel and where it touches in the matrix / image.
Note that for any elements of the kernel that are out of bounds we ignore and so the output is simply where the bottom right of the kernel and the top left of the image touch and we multiply these elements together. The output is simply 1*1 = 1. Now let's move over to the next element, which is 1 to the right:
[ 1 0 1]
[ 1 `0` 1]
[1 [0*1] [2*1] 3 4 5 ]
[6 7 8 9 10]
[11 12 13 14 15]
[16 17 18 19 20]
[21 22 23 24 25]
Note where the centre is as well as what elements the kernel touches the matrix. The output is thus 0*1 + 2*1 = 2. You would continue this until you hit the end of this row where the bottom left of the kernel touches the top right of the image. You would then move down to the next row, repeat the sweep over all of the columns and continue up until the very end until the top left of the kernel touches the bottom right of the image / matrix.
Here are a couple more examples just to be sure you have the theory right. Let's do the point where the kernel touches the top right of the image / matrix
[ 1 0 1]
[ 1 `0` 1]
[1 2 3 4 [5*1]] 0 1]
[6 7 8 9 10]
[11 12 13 14 15]
[16 17 18 19 20]
[21 22 23 24 25]
Remember that we ignore all places where the kernel doesn't touch the image / matrix. The output in this case would simply be 5 and also note where the output location is. Here's another example:
[1 2 3 4 5 ]
[6 7 8 9 10]
[11 12 13 14 15]
[16 17 18 19 20]
[1 0 [[21*1] 22 23 24 25]
[1 `0` 1]
[1 0 1]
This location is at the bottom left corner of the image / matrix and the output here would simply be 21*1. Another one just to be sure:
[1 2 3 4 5]
[6 7 8 9 10]
[11 12 13 14 [1*15]] 0 1]
[16 17 18 19 [1*20]] `0` 1]
[21 22 23 24 [1*25]] 0 1]
This location is a bit more complicated. The kernel overlaps the image / matrix fully by its first column and so the output is simply 1*15 + 1*20 + 1*25 = 60. Also note that the output position is at the third-last row because there are still two more rows of filtering to perform. One where the first two rows of the kernel are touching the bottom last two rows of the image / matrix and one where the first row of the kernel touches the bottom last row of the image / matrix.
Therefore, the final output matrix would look something like this.
[1 2 * * * * 5 ]
[* * * * * * * ]
[* * * * * * * ]
[* * * * * * * ]
[* * * * * * 60]
[* * * * * * *]
[21 * * * * * *]
The elements marked as * are unknown as I haven't calculated those, but the point is to notice what the final size of the matrix is. Specifically, note where the output positions are of where we need to write to the matrix for the first couple of cases that you see above. This is the reason why you get a larger matrix - to accommodate for the results when the kernel is not fully contained within the image / matrix itself but still performs valid operations. As you can see, you would need two additional rows: 1 for the top and 1 for the bottom, and two additional columns: 1 for the left and 1 for the right. This results in a (5 + 2) x (5 + 2) = 7 x 7 output matrix. In general if the kernel size is odd, the output you get from use 'full' 2D convolution is usually (rows + 2*floor(kernel_rows/2)) x (cols + 2*floor(kernel_cols/2)) where rows and cols are the rows and columns of the image / matrix to filter and kernel_rows and kernel_cols are the rows and columns of the kernel.
If you want to have a look at what MATLAB actually produces, we can. Using the input image / matrix and kernel I defined earlier, this is what we get:
>> I = reshape(1:25,5,5).'; %'
>> K = [1 0 1; 1 0 1; 1 0 1];
>> out = conv2(I,K)
out =
`1` `2` 4 6 8 4 `5`
7 9 18 22 26 13 15
18 21 42 48 54 27 30
33 36 72 78 84 42 45
48 51 102 108 114 57 `60`
37 39 78 82 86 43 45
`21` 22 44 46 48 24 25
Note that I've marked the sample calculations that we did in MATLAB's output with `` characters. This does agree with the calculations.
Now your true question is how 'valid' and 'same' factor into all this. Where 'valid' and 'same' come in are simply truncated versions of the 'full' convolution. 'same' gives you an output that is the same size as the image / matrix to be filtered and 'valid' gives you an output such that you only provide outputs where the kernel was fully contained inside the image / matrix. Any time the kernel is out of bounds with respect to the image / matrix, we do not include those outputs as part of the final output. Simply put, 'valid' and 'same' use the 'full' result but remove certain portions of the borders of the result to facilitate the option that you choose.

How to show only the existing data points on x axis of bar graph in MATLAB?

I need to simple plot B vs. A as bar plot in MATLAB, but I don't want my x axis showing completely from 1 to 274. I only need to show the existing data point on my x axis, which can be done easily in Excel as in the image below. How can MATLAB do this?
A=[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 18 20 25 27 29 37 40 42 43 48 73 204 242 274];
B=[30 15 5 9 5 6 3 3 2 1 4 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1];
You need to set both 'XTick' and 'XTickLabel' axes properties:
bar(B);
set(gca,'XTickLabel',A)
set(gca,'XTick',1:numel(A));
xlim([0 numel(A)+1]);
Here is an inelegant, but, nonetheless, working solution to your question:
x = [1,4, 6, 7]; % Your data
uni = unique(x)
yMax = length(find(x == mode(x))) + 1;
c = cell(1, length(uni));
c = strread(num2str(uni),'%s')
hist(1:length(uni));
axis([0 length(uni) 0 yMax])
set(gca, 'XTick', 1:length(uni));
set(gca, 'XTickLabel', c);
Basically, this plots the histogram as if the data were spread from 1 to the number of unique elements. Then, it sets the tick marks at each histogram value. Then, it labels each tick mark with the correct number.

matlab - graph plotting

I have two arrays to plot, in x axis : array a. In y axis array b (ones and zeros)
I want to plot vertical lines when the values of array b =1
i.e
a=[23 12 76 43 21 90]
b=[1 0 1 1 0 1]
You may try bar plot.
a=[23 12 76 43 21 90];
b=[1 0 1 1 0 1];
bar(a,b)