Zero pad image before FFT in MATLAB - matlab

I have an image of size 64x64 and I should take its Fourier transform. I should pad with zeros to the right and bottom of the original image to make it 128x128, and then again take its Fourier transform. And then repeat this procedure for 256x256 and 512x512 sized images and find a relation between the final Fourier transforms.
Can anyone tell me how should I do this? I don't know how to zero pad the image to get a double sized image with half zeros.

There are multiple ways to zero pad. You can just create an array using zeros of double the size, and then put in the image in the indices on the top left:
A = imread('coins.png');
[s1, s2] = size(A);
B = zeros(s1*2, s2*2, class(A));
B(1:s1,1:s2) = A;
To make sure that the new array B is of the same type as the original image A, I used class(A).
Alternatively you can use padarray. Specify the number of elements to pad in each direction, what to pad, and where to put it ('post').
C = padarray(A, [s1 s2], 0, 'post');

Related

Negative values in Watershed algorithm leading to black image

I'm using the watershed algorithm to try and segment touching nuclei. A typical image may look like:
or this:
I'm trying to apply the watershed algorithm with this code:
show(RGB_img)
%Convert to grayscale image
I = rgb2gray(RGB_img);
%Take structuring element of a disk of size 10, for the morphological transformations
%Attempt to subtract the background from the image: top hat is the
%subtraction of the open image from the original
%Morphological transformation to subtract background noise from the image
%Tophat is the subtraction of an opened image from the original. Remove all
%images smaller than the structuring element of 10
I1 = imtophat(I, strel('disk', 10));
%Increases contrast
I2 = imadjust(I1);
%show(I2,'contrast')
%Assume we have background and foreground and assess thresh as such
level = graythresh(I2);
%Convert to binary image based on graythreshold
BW = im2bw(I2,level);
show(BW,'C');
BW = bwareaopen(BW,8);
show(BW,'C2');
BW = bwdist(BW) <= 1;
show(BW,'joined');
%Complement because we want image to be black and background white
C = ~BW;
%Use distance tranform to find nearest nonzero values from every pixel
D = -bwdist(C);
%Assign Minus infinity values to the values of C inside of the D image
% Modify the image so that the background pixels and the extended maxima
% pixels are forced to be the only local minima in the image (So you could
% hypothetically fill in water on the image
D(C) = -Inf;
%Gets 0 for all watershed lines and integers for each object (basins)
L = watershed(D);
show(L,'L');
%Takes the labels and converts to an RGB (Using hot colormap)
fin = label2rgb(L,'hot','w');
% show(fin,'fin');
im = I;
%Superimpose ridgelines,L has all of them as 0 -> so mark these as 0(black)
im(L==0)=0;
clean_img = L;
show(clean_img)
After C = ~BW; the whole image goes dark. I believe this is because the image pixels are all -inf or some smaller negative number. This is there a way around this and if so what could I change in my code to get this algorithm working? I've experimented a ton and I don't really know what's happening. Any help would be great!
The problem is with your show command. As you said in the comments this uses imshow under the hood. If you try imshow directly you'll see you also get a black image. However, if you call it with appropriate limits:
imshow(clean_img,[min(clean_img(:)), max(clean_img(:))])
you'll see everything you expect to see.
In general I usually prefer imagesc for that reason. imshow makes arbitrary judgements as to what range to represent, and I usually can't be bothered to keep up with it. I think in your case, your end image is uint16 so imshow chooses to represent the range [1, 65025]. Since all your pixel values are below 400, they look black to the naked eye for that range.

Split up a binary image using their white boundaries in MATLAB

I'm trying to read the values in this image into variables using OCR in MATLAB. I'm having trouble doing so, so I tried to split up this image into smaller parts using the white boundary lines then trying to read it, but I dont know how to do this. Any help would be appreciated, thanks.
If the blocks are always delimited by a completely vertical line, you can find where they are by comparing the original image (here transformed from RGB to grayscale to be a single plane) to a matrix that is made of repeats of the first row of the original image only. Since the lines are vertical the intensity of the pixels in the first line will be the same throughout. This generates a binary mask that can be used in conjunction with a quick thresholding to reject those lines that are all black pixels in every row. Then invert this mask and use regionprops to locate the bounding box of each region. Then you can pull these out and do what you like.
If the lines dividing the blocks of text are not always vertical or constant intensity throughout then there's a bit more work that needs to be done to locate the dividing lines, but nothing that's impossible. Some example data would be good to have in that case, though.
img = imread('http://puu.sh/cU3Nj/b020b60f0b.png');
imshow(img);
imgGray = rgb2gray(img);
imgMatch = imgGray == repmat(imgGray(1,:), size(imgGray, 1), 1);
whiteLines = imgMatch & (imgGray > 0);
boxes = regionprops(~whiteLines, 'BoundingBox');
for k = 1:6
subplot(3,2,k)
boxHere = round(boxes(k).BoundingBox);
imshow(img(boxHere(2):(boxHere(2)+boxHere(4)-1), boxHere(1):(boxHere(1)+boxHere(3)-1), :));
end
You can sum along the columns of a binary image corresponding to that input image and find peaks from the sum values. This is precisely achieved in the code here -
img = imread('http://puu.sh/cU3Nj/b020b60f0b.png');
BW = im2bw(img,0.1); %// convert to a binary image with a low threshold
peak_sum_max = 30; %// max of sum of cols to act as threshold to decide as peak
peaks_min_width = 10; %// min distance between peaks i.e. min width of each part
idx = find( sum(BW,1)>=peak_sum_max );
split_idx = [1 idx( [true diff(idx)>peaks_min_width ] )];
split_imgs = arrayfun(#(x) img(:,split_idx(x):split_idx(x+1)),...
1:numel(split_idx)-1,'Uni',0);
%// Display split images
for iter = 1:numel(split_imgs)
figure,imshow(split_imgs{iter})
end
Please note that the final output split_imgs is a cell array with each cell holding image data for each split image.
If you would like to have the split images directly without the need for messing with cell arrays, after you have split_idx, you can do this -
%// Get and display split images
for iter = 1:numel(split_idx)-1
split_img = img(:,split_idx(iter):split_idx(iter+1));
figure,imshow(split_img)
end
There is now a built-in ocr function in the Computer Vision System Toolbox.

Matlab padarray function

I have an image of size 350X450. I'm trying to pad with zeros the matrix which represents the image in a way that I'll have the original matrix in the center of the new padded matrix with a new dimensions of 700X900. Here is what I want to do:
I'm trying to implement that using padarray function:
(Suppose w is the desired width, h is the desired height and im is the image(matrix))
new_image=paddarray(im, [0.5*w 0.5*h]);
I don't get the desired result. What am I missing? Is there a better way to do this?
Your syntax is right, you should set w = ceil((700-350)/2) and h = ceil((900-450)/2).
As the HELP entry says:
B = padarray(A,PADSIZE)
pads array A with PADSIZE(k) number of zeros along the k-th dimension of A.
padarray([1 2; 3 4],[1 1]) %makes a 4x4 matrix
You don't want to pad with w and h, you want to pad with
(wDesired - wCurrent)/2 %floor or ceil, depending on your mood.

Is there an efficient way to pad a matrix with zeros on all sides?

I'm performing texture synthesis on images using the Efros and Leung Algorithm. My goal is to grow the size of my current textured image and, to do it, I'd like to pad the current image matrix with zeros on all sides.
My current plan given an original image matrix of size MxN and a desired growth size of P:
(1) Create a target matrix of size (M+2P)x(N+2P)
(2) Set the value of target(i+P,j+P) = original(i,j)
(3) Run Efros and Leung
Is there a way I can eliminate (1) and (2) and just operate on the original image to pad it in all directions with P zeros?
If you have access to the Image Processing Toolbox, you can use the function PADARRAY:
imgPadded = padarray(img, [p p], 0, 'both');
Otherwise you can simply use matrix indexing:
sz = size(img);
imgPadded = zeros([sz(1:2)+2*p size(img,3)], class(img));
imgPadded((1:sz(1))+p, (1:sz(2))+p, :) = img;
This should work for both grayscale and RGB images.
>> y = [zeros(P,N+2*P) ; [zeros(M,P), x, zeros(M,P)] ; zeros(P,N+2*P)];
where x is the original image matrix and y is the output should work. If the matrix has 3 planes, adjust to:
>> y = [zeros(P,N+2*P,3) ; [zeros(M,P,3), x, zeros(M,P,3)] ; zeros(P,N+2*P,3)];
Use padarray:
y = padarray(x, [P P]);

matlab image processing 3d

i have 100 b&w image of smthing.the probllem is i want to scan each image in 0&1 formatin mby n format and then place each image to one over one and again scan and save them in mbynby100 form.
how i do this and from where i should start
_jaysean
Your question is vague and hard to understand, but my guess is that you want to take 100 M-by-N grayscale intensity images, threshold them to create logical matrices (i.e. containing zeroes and ones), then put them together into one M-by-N-by-100 matrix. You can do the thresholding by simply picking a threshold value yourself, like 0.5, and applying it to an image A as follows:
B = A > 0.5;
The matrix B will now be an M-by-N logical matrix with ones where A is greater than 0.5 and zeroes where A is less than or equal to 0.5.
If you have the Image Processing Toolbox, you could instead use the function GRAYTHRESH to pick a threshold and the function IM2BW to apply it:
B = im2bw(A,graythresh(A));
Once you do this, you can easily put the images into an M-by-N-by-100 logical matrix. Here's an example of how you could do this in a loop, assuming the variables M and N are defined:
allImages = false(M,N,100); %# Initialize the matrix to store all the images
for k = 1:100
%# Here, you would load your image into variable A
allImages(:,:,k) = im2bw(A,graythresh(A)); %# Threshold A and add it to
%# the matrix allImages
end