fourier and zero padding - image

I'm filtering an image using a mask and the Discret Fourier Trasform, till now i have this
A=double(imread('C:\Users\samsung\Documents\Lab Imagenes\CHE.jpg','jpg'));
B=[1 4 6 4 1; 4 16 24 16 4; 6 24 36 24 6; 4 16 24 16 4; 1 4 6 4 1];
F=(1/256).*(B);
DFT_A=fftshift(fft2(A));
imshow(DFT_A);
DFT_A_F=DFT_A.*F;
figure
imshow(DFT_A_F)
but when i want to see partial results I got this error
??? Error using ==> times
Matrix dimensions must agree.
Error in ==> fourier1 at 10
DFT_A_F=DFT_A.*F;
I know that i need to do zero padding to the mask, but i don't know how to do it, please I need help
Thanks!

what you want is called 'padarray' , just after you define DFT_A:
padsize= [round(0.5*size(DFT_A,1)-0.5*size(F,1)) round(0.5*size(DFT_A,2)-0.5*size(F,2))];
F = padarray(F, padsize);
DFT_A_F=DFT_A.*F;
...
But why won't you just (given that A is a 2D matrix, so rgb2gray it if needed):
DFT_A_F = conv2(A,B,'same');
It is faster, because you don't need to multiply all these zeros, and should get you the same result.

Related

Find the coordinates (indexes) of an element matrix knowing its linear value

The title isn't very accurate because I didn't know the specific terms to describe it.
I have a matrix of known dimensions width and height. This matrix contains every
integer from 0 to width*height-1 so for example:
width = 7
height = 4
0 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 26 27
n = 18
x = ?
y = ?
Now if I'm given the value n = 18 I want the program to set x = 4 and y = 2 .
What is the mathematical operation behind it?
It feels like it should be pretty easy but I can wrap my head around it.
I thought the answer was x = n % width and y = n / height but it's not working, unless I'm just implementing it the wrong way
SOLVED
I'll leave the post here in case someone needs it.
The answer was actually x = n % width and y = n / width and I feel kinda dumb. You can also use height instead of width but keep in mind that you'll need to swap the operations.

Transposing matrix / Trouble understanding how bsxfun works

This could be a weird question because Many would be wondering why to use such a complicated function like bsxfun for transposing while you have the .' operator.
But, transposing isn't a problem for me. I frame my own questions and try to solve using specific functions so that i learn how the function actually works. I tried solving some examples using bsxfun and have succeeded in getting desired results. But my thought, that i have understood how this function works, changed when i tried this example.
The example image i've taken is a square 2D image, so that i'm not trying to access an index which is unavailable.
Here is my code:
im = imread('cameraman.tif');
imshow(im);
[rows,cols] = size(im);
imout = bsxfun(#(r,c) im(c,r),(1:rows).',1:cols);
Error i got:
Error using bsxfun
Invalid output dimensions.
Error in test (line 9)
imout = bsxfun(#(r,c) im(c,r),(1:rows).',1:cols);
PS: I tried interchanging r and c inside im( , ) (like this: bsxfun(#(r,c) im(r,c),(1:rows).',1:cols)) which didn't pose any error and i got the same exact image as the input.
I also tried this using loops and simple transpose using .' operator which works perfectly.
Here is my loopy code:
imout(size(im)) = 0;
for i = 1:rows
for j = 1:cols
imout(i,j) = im(j,i);
end
end
Answer i'm expecting is, what is wrong with my code, what does the error signify and how could the code be modified to make it work.
You can use the anonymous function with bsxfun like so -
%// Create the tranposed indices with BSXFUN
idx = bsxfun(#(r,c) (c-1)*size(im,1)+r,1:rows,(1:cols).') %//'
%// Index into input array with those indices for the final transposed output
imout = im(idx)
The problem here is that your function doesn't return an output the same shape as the input it is given. Although the requirement for bsxfun is that the function operates element-wise, it is not called with scalar elements. So, you need to do this:
x = randi(5, 4, 5)
[m, n] = size(x);
bsxfun(#(r, c) transpose(x(c, r)), (1:n)', 1:m)
I wanted to know how bsxfun works so i created a function like this:
bsxfun test function:
function out = bsxfuntest(r,c)
disp([size(r) , size(c)]);
out = r + c; // just normal addition so that it works fine.
end
My script:
im = magic(5);
[rows,cols] = size(im);
bsxfun(#bsxfuntest ,(1:rows).',1:cols);
Output: (not the value of output of the function. These are those which are printed within bsxfuntest.m function using disp)
5 1 1 1
5 1 1 1
5 1 1 1
5 1 1 1
5 1 1 1
Conclusion:
bsxfun passes each column into the function instead of each element.
If either one of the input is a scalar, then the function is called only one time i.e the matrix whether it is 2D or 3D or nD, is passed in one go.
Try this:
bsxfun(#bsxfuntest , repmat(5,[5 5 5]) ,1);
Also if both the inputs are of same dimensions, then also the function is called only one time.
Try this:
bsxfun(#bsxfuntest , repmat(5,[5 5 2]) , repmat(2,[5 5 2]))
If none of them is a scalar, and both the inputs are of different dimensions, then The inputs are passed as column vectors.
Try this:
bsxfun(#bsxfuntest , repmat(5,[5 5 1]) ,permute(1:3,[1 3 2]));
and this:
bsxfun(#bsxfuntest , repmat(5,[5 5 2]) ,permute(1:2,[1 3 2]));
Coming to the problem
>> im
im =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
Taking the code in the question:
imout = bsxfun(#(r,c) im(c,r),(1:rows).',1:cols);
When i try im(c,r) i.e im(1,(1:5).')
>> im(1,(1:5).')
ans =
17 24 1 8 15
Here, bsxfun expects a column vector while the output is a row vector. I guess that is the reason why MatLab produces an error stating
Invalid output dimensions.
This was also the reason why i didn't get any error when i replaced r and c in the above code like this bsxfun(#(r,c) im(r,c),(1:rows).',1:cols). Because here, the output was a column vector itself.
So i tried to transpose the results to obtain the column vector like this:
>> imout = bsxfun(#(r,c) (im(c,r)).',(1:rows).',1:cols)
imout =
17 23 4 10 11
24 5 6 12 18
1 7 13 19 25
8 14 20 21 2
15 16 22 3 9
The code is exactly the same as Edrics's solution and it gives the expected results.

MATLAB Greyscale 12 bit to 8 bit

I'm trying to create an algorithm to convert a greyscale from 12 bit to 8 bit.
I got a greyscale like this one:
The scale is represented in a Matrix. The problem is, that the simple multiplication with 1/16 destroys the first grey-columns.
Here the Codeexample:
in =[
1 1 1 3 3 3 15 15 15 63 63 63;
1 1 1 3 3 3 15 15 15 63 63 63;
1 1 1 3 3 3 15 15 15 63 63 63;
1 1 1 3 3 3 15 15 15 63 63 63
];
[zeilen spalten] = size(in);
eight = round(in/16);
imshow(uint8(eight));
Destroy mean, that the New Columns are Black now
Simply rescale the image so that you divide every single element by the maximum possible intensity that corresponds to a 12-bit (or 2^12 - 1 = 4095) unsigned integer and then multiply by the maximum possible intensity that corresponds to an 8-bit unsigned integer (or 2^8 - 1 = 255).
Therefore:
out = uint8((255.0/4095.0)*(double(in)));
You need to cast to double to ensure that you maintain floating point precision when performing this scaling, and then cast to uint8 so that the image type is ensured to be 8-bit. You have cleverly deduced that this scaling factor is roughly (1/16) (since 255.0/4095.0 ~ 1/16). However, the output of your test image will have its first 6 columns to surely be zero because intensities of 1 and 3 for a 12-bit image are just too small to be represented in its equivalent 8-bit form, which is why it gets rounded down to 0. If you think about it, for every 16 intensity increase that you have for your 12-bit image, this registers as an equivalent single intensity increase for an 8-bit image, or:
12-bit --> 8-bit
0 --> 0
15 --> 1
31 --> 2
47 --> 3
63 --> 4
... --> ...
4095 --> 255
Because your values of 1 and 3 are not high enough to get to the next level, these get rounded down to 0. However, your values of 15 get mapped to 1, and the values of 63 get mapped to 4, which is what we expect when you run the above code on your test input.

sorting 2d points into a matrix

I have the following problem:
An image is given and I am doing some blob detection. As a limit, lets say I have a max of 16 blobs and from each blob I calculate the centroid (x,y position).
If no distorion happends, these centroids are arranged in an equidistant 4x4 grid but they could be really much distorted.
The assumption is that they keep more or less the grid form but they could be really much warped.
I need to sort the blobs such that I know which one is the nearest left, right, up and down. So the best would be to write these blobs into a matrix.
If this is not enough, it could happen that I detect less then 16 and then I also need to sort them into a matrix.
Does anyone know how this could be efficiently solved in Matlab?
Thanks.
[update 1:]
I uploaded an image and the red numbers are the numbers which my blob detection algorithm assign each blob.
The resulting matrix should look like this with these numbers:
1 2 4 3
6 5 7 8
9 10 11 12
13 16 14 15
e.g. I start with blob 11 and the nearest right number is 12 and so on
[update 2:]
The posted solution looks quite nice. In reality it could happen, that one of the outer spots is missing or maybe two ... I know that this makes everything much more complicated and I just want to get a feeling if this is worth spending time.
These problems arise if you analyze a wavefront with a shack-hartmann wavefront sensor and you want to increase the dynamic range :-)
The spots could be really warped such that the dividing lines are not orthogonal any more.
Maybe someone knows a good literature for classification algorithms.
Best solution would be one, which could be implemented on a FPGA without to much effort but this is at this stage not so much important.
This will work as long as the blobs form a square and are relatively ordered:
Image:
Code:
bw = imread('blob.jpg');
bw = im2bw(bw);
rp = regionprops(bw,'Centroid');
% Must be a square
side = sqrt(length(rp));
centroids = vertcat(rp.Centroid);
centroid_labels = cellstr(num2str([1:length(rp)]'));
figure(1);
imshow(bw);
hold on;
text(centroids(:,1),centroids(:,2),centroid_labels,'Color','r','FontSize',60);
hold off;
% Find topleft element - minimum distance from origin
[~,topleft_idx] = min(sqrt(centroids(:,1).^2+centroids(:,2).^2));
% Find bottomright element - maximum distance from origin
[~,bottomright_idx] = max(sqrt(centroids(:,1).^2+centroids(:,2).^2));
% Find bottom left element - maximum normal distance from line formed by
% topleft and bottom right blob
A = centroids(bottomright_idx,2)-centroids(topleft_idx,2);
B = centroids(topleft_idx,1)-centroids(bottomright_idx,1);
C = -B*centroids(topleft_idx,2)-A*centroids(topleft_idx,1);
[~,bottomleft_idx] = max(abs(A*centroids(:,1)+B*centroids(:,2)+C)/sqrt(A^2+B^2));
% Sort blobs based on distance from line formed by topleft and bottomleft
% blob
A = centroids(bottomleft_idx,2)-centroids(topleft_idx,2);
B = centroids(topleft_idx,1)-centroids(bottomleft_idx,1);
C = -B*centroids(topleft_idx,2)-A*centroids(topleft_idx,1);
[~,leftsort_idx] = sort(abs(A*centroids(:,1)+B*centroids(:,2)+C)/sqrt(A^2+B^2));
% Reorder centroids and redetermine bottomright_idx and bottomleft_idx
centroids = centroids(leftsort_idx,:);
bottomright_idx = find(leftsort_idx == bottomright_idx);
bottomleft_idx = find(leftsort_idx == bottomleft_idx);
% Sort blobs based on distance from line formed by bottomleft and
% bottomright blob
A = centroids(bottomright_idx,2)-centroids(bottomleft_idx,2);
B = centroids(bottomleft_idx,1)-centroids(bottomright_idx,1);
C = -B*centroids(bottomleft_idx,2)-A*centroids(bottomleft_idx,1);
[~,bottomsort_idx] = sort(abs(A*reshape(centroids(:,1),side,side)+B*reshape(centroids(:,2),side,side)+C)/sqrt(A^2+B^2),'descend');
disp(leftsort_idx(bsxfun(#plus,bottomsort_idx,0:side:side^2-1)));
Output:
2 12 13 20 25 31
4 11 15 19 26 32
1 7 14 21 27 33
3 8 16 22 28 34
6 9 17 24 29 35
5 10 18 23 30 36
Just curious, are you using this to automate camera calibration through a checkerboard or something?
UPDATE:
For skewed image
tform = maketform('affine',[1 0 0; .5 1 0; 0 0 1]);
bw = imtransform(bw,tform);
Output:
1 4 8 16 21 25
2 5 10 18 23 26
3 6 13 19 27 29
7 9 17 24 30 32
11 14 20 28 33 35
12 15 22 31 34 36
For rotated image:
bw = imrotate(bw,20);
Output:
1 4 10 17 22 25
2 5 12 18 24 28
3 6 14 21 26 31
7 9 16 23 30 32
8 13 19 27 33 35
11 15 20 29 34 36

Summation of difference between matrix elements

I am in the process of building a function in MATLAB. As a part of it I have to calculate differences between elements in two matrices and sum them up.
Let me explain considering two matrices,
1 2 3 4 5 6
13 14 15 16 17 18
and
7 8 9 10 11 12
19 20 21 22 23 24
The calculations in the first row - only four elements in both matrices are considered at once (zero indicates padding):
(1-8)+(2-9)+(3-10)+(4-11): This replaces 1 in initial matrix.
(2-9)+(3-10)+(4-11)+(5-12): This replaces 2 in initial matrix.
(3-10)+(4-11)+(5-12)+(6-0): This replaces 3 in initial matrix.
(4-11)+(5-12)+(6-0)+(0-0): This replaces 4 in initial matrix. And so on
I am unable to decide how to code this in MATLAB. How do I do it?
I use the following equation.
Here i ranges from 1 to n(h), n(h), the number of distant pairs. It depends on the lag distance chosen. So if I choose a lag distance of 1, n(h) will be the number of elements - 1.
When I use a 7 X 7 window, considering the central value, n(h) = 4 - 1 = 3 which is the case here.
You may want to look at the circshfit() function:
a = [1 2 3 4; 9 10 11 12];
b = [5 6 7 8; 12 14 15 16];
for k = 1:3
b = circshift(b, [0 -1]);
b(:, end) = 0;
diff = sum(a - b, 2)
end

Resources