Average filter without built-in function - matlab

I am having a problem with the output. I am using 5*5 filter for making image smooth. As average filter smooth our image but this one is making the image more dull. Can anyone help me with this problem?
Input Image is:
img_2 = imread('White-Bars.png');
filter = ones(5 , 5)/25;
working_img = img_2(:,:,1);
img_4 = img_2(:,:,1);
[rows,cols] = size(working_img); sum=0;
for row=4:(rows-3)
for col=4:(cols-3)
for rowindex=(-2): (3)
for colindex=(-2): (3)
img_4(row,col) = mean2(double(working_img(row+rowindex,col+colindex)) * filter(1:5,1:5));
end
end
end
end
subplot(1,2,1);
imshow(working_img);
subplot(1,2,2);
imshow(img_4);
So, this is the output:

You dont understand what you are doing!
This is clearly homework, so I am not providing full code. You are doing image convolution, which you can do with way better code, (fft, conv2, imfilter, etc) but I assume you are doing this for learning.
First, sit down with your lecture notes and learn what filtering is. When you apply a filter over a pixel (the first 2 loops are to choose each pixel in the image) what you want to do is multiply your chosen filter over that pixel, and all the surrounding pixels, and accumulate the result of that in the output image.
Once you are in a specific pixel (row,col), then you iterate around all the neighboring pixels, (offset by rowindex,colindex). For each of these, you want to multiply the current pixel to the filter on that specific location, i.e. 1 value, and add it to the result. Depends on what the filter is, it will do something different. In your case, a filter with all the same value will do an average. You do not need to use the mean2 function, the mathematics you are applying do the filtering.
In short, this line is wrong:
img_4(row,col) = mean2(double(working_img(row+rowindex,col+colindex)) * filter(1:5,1:5));
Both the use of mean2 and the index on the variable filter.
Video explaining convolution: https://www.youtube.com/watch?v=C_zFhWdM4ic

Related

Select certain slices in 3D image

I have a 3D image and I want to select certain slices within that image.
So let's say it's a 3D image with dimensions 100x100x40. What I want is to select the image intensities within a certain range for every dimension; x=[22,39], y=[17,32], z=[26,42]. I'm thinking a for loop that runs through all indices within the image and keeps those intensities that are within the range for every dimension.
Any clue on how I should do this?
Btw, I can't use imcrop cause I want my output image to have the same dimensions as the input.
Edit
I figured I could do something like this:
NewIndex_x = 1;
index_x = [];
for i=22:39;
index_slice_x = find(Im(i,:,:));
index_x(NewIndex_x) = index_slice_x;
NewIndex_x = NewIndex_x + 1;
end
find does not work for a range so I thought I could do this for all x,y and z slices and then find the overlapping indices.
My for loop does not work, any ideas on how to properly append an array to another array within a for loop?
Cheers!
Was not exactly sure if you wanted a subimage based on the x,y,z range and then apply the intensity level to that or something else. The code below does this. So it first gets the subimage and then sets the intensity level filter for that. If this is not what were aiming for, please add some clarification. Hope this helps.
% Sample data
im = round(rand(100,100,40)*255);
% Subimage that we want to process
xrange=22:39;
yrange=17:32;
zrange=26:39;
% Get all points from within the defined range
imnew = zeros(size(im));
imnew(xrange,yrange,zrange) = im(xrange,yrange,zrange);
% Now you can apply your intensity level filter if you want
min_intensity_level = 100;
imnew = imnew .* (imnew > min_intensity_level);
% At this point, imnew contains the points within the specified range that
% also exceed the minimum intensity level.

Which kind of filtering is used in SPCImage for binning?

I was wondering if anyone knows which kind of filter is applied by SPCImage from the Becker & Hickl system.
I am taking some FLIM data with my system and I want to create the lifetime images. For doing so I want to bin my images in the same way as it does SPCImage, so I can increase my SN ratio. The binning goes like 1x1, 3x3, 5x5, etc. I have created the function for doing a 3x3 binning, but each time it gets more complicated...
I want to do it in MATLAB, and maybe there is already a function that can help me with this.
Many thanks for your help.
This question is old, but for anyone else wondering: You want to sum the pixels in an (2M+1) x (2M+1) neighborhood for each plane (M integer). So I am pretty sure you can go about the problem by treating it like a convolution.
#This is your original 3D SDT image
#I assume that you have ordered the image with spatial dimensions along the
#first and second and the time channels are the third dimension.
img = ... #<- your 3D image goes here
#This describes your filter. M=1 means take 1 a one pixel rect around your
#center pixel and add the values to your center, etc... (i.e. M=1 equals a
#total of 3x3 pixels accumulated)
M=2
#this is the (2D) filter for your convolution
filtr = ones(2*M+1, 2*M+1);
#the resulting binned image (3D)
img_binned = convn(img, filtr, 'same');
You should definitely check the result against your calculation, but it should do the trick.
I think that you need to test/investigate image filter functions to apply to this king of images Fluorescence-lifetime imaging microscopy.
A median filter as showing here is good for smoothering things. Or a weihgted moving average filter where applied to the image erase de bright spots and only are maintained the broad features
So you need to review of the digital image processing in matlab

Autonomous seam detection in Images on matlab

I'm trying to detect seams in welding images for an autonomous welding process.
I want to find pixel positions of the detected line (the red line in the desired image) in the original image.
I used the following code and finally removed noise from the image to reach the result below.
clc,clear,clf;
im = imread('https://i.stack.imgur.com/UJcKA.png');
imshow(im);title('Original image'); pause(0.5);
sim = edge(im, 'sobel');
imshow(sim);title('after Sobel'); pause(0.5);
mask = im > 5;
se = strel('square', 5);
mask_s = imerode(mask, se);
mask(mask_s) = false;
mask = imdilate(mask, se);
sim(mask) = false;
imshow(sim);title('after mask');pause(0.5);
sim= medfilt2(sim);
imshow(sim);title('after noise removal')
Unfortunately there is nothing remaining in the image to find the seam perfectly.
Any help would be appreciated.
Download Original image.
You need to make your filter more robust to noise. This can be done by giving it a larger support:
filter = [ones(2,9);zeros(1,9);-ones(2,9)];
msk = imerode(im > 0, ones(11)); % only object pixels, discarding BG
fim =imfilter(im,filter);
robust = bwmorph((fim>0.75).*msk,'skel',inf); % get only strong pixels
The robust mask looks like:
As you can see, the seam line is well detected, we just need to pick it as the largest connected component:
st = regionprops(bwlabel(robust,8), 'Area', 'PixelList');
[ma mxi] = max([st.Area]); % select the region with the largest area
Now we can fit a polygon (2nd degree) to the seem:
pp=polyfit(st(mxi).PixelList(:,1), st(mxi).PixelList(:,2), 2);
And here it is over the image:
imshow(im, 'border','tight');hold on;
xx=1:size(im,2);plot(xx,polyval(pp,xx)+2,'r');
Note the +2 Y offset due to filter width.
PS,
You might find this thread relevant.
Shai gives a great answer, but I wanted to add a bit more context about why your noise filtering doesn't work.
Why median filtering doesn't work
Wikipedia suggests that median filtering removes noise while preserving edges, which is why you might have chosen to use it. However, in your case it will almost certainly not work, here's why:
Median filtering slides a window across the image. In each area, it replaces the central pixel with the median value from the surrounding window. medfilt2 uses a 3x3 window by default. Let's look at a 3x3 block near your line,
A 3x3 block around [212 157] looks like this
[0 0 0
1 1 1
0 0 0]
The median value is 0! So even though we're in the middle of a line segment, the pixel will be filtered out.
The alternative to median filtering
Shai's method for removing noise instead finds the largest connected group of pixels and ignores smaller groups of pixels. If you also wanted to remove these small groups from your image, Matlab provides a filter bwareaopen which removes small objects from binary images.
For example, if you replace your line
sim= medfilt2(sim);
with
sim= bwareaopen(sim, 4);
The result is much better
Alternative edge detectors
One last note, Shai uses a horizontal gradient filter to find horizontal edges in your image. It works great because your edge is horizontal. If you edge will not always be horizontal, you might want to use another edge detection method. In your original code, you use Sobel, but Matlab provides many options, all of which perform better if you tune their thresholds. As an example, in the following image, I've highlighted the pixels selected by your code (with bwareaopen modification) using four different edge detectors.

Filter in Frequency Domain

I have an assignment to filter in the frequency domain. It gives me various filters to use in part of the question but I am just trying to figure out how to add even one. I'm still learning Matlab and image processing in general.
Assignment Question: Use index2gray to convert “tees.tif” to gray level image. Filter the gray level image in
the frequency domain using 2D fft (fft2), after performing the operation you can use 2D
ifft (ifft2) to display the filtered image in the spatial domain for:
a- Rectangular low pass filter using cutoff frequency of (uc=N/8,vc=M/8) where N and M
are the row and column sizes of the image.
My Current code is:
[I,cmap] = imread('trees.tif');
img = ind2gray(I,cmap);
[rows columns] = size(img);
imshow(img);
fftO = fft2(double(img));
shifted = fftshift(fftO);
logged = log(1+abs(shifted));
imshow(logged,[]);
If I understand this correctly, I have the grey level image in the frequency domain and now need to filter it. I'm confused about the filtering part. I need to make a rectangular low pass filter using cutoff frequencies. How do I go about adding cutoff frequencies? I assume I will be using a Gaussian or Butterworth filter and have the filter size be equal to the image.
After I figure out this filter thing, I should be able to do (H is filter)
filtered = logged.*H;
invert = real(ifft2(filtered));
imshow(invert);
Anyone know how I need to proceed with the filter section?
KevinMc essentially told you what the answer is. fspecial certainly allows you to define certain 2D filters, but it doesn't have rectangular filters. You can create your own though! You create a filter / mask that is the same size as your image where the centre of this mask is a rectangle with height N/8 and width M/8. Once you do this, you simply multiply with your image in the frequency domain and you then take the ifft2 as you have specified in your code.
You've got the code correct... you just need to create the mask! As such, use meshgrid to generate a 2D grid of (x,y) co-ordinates, then use Boolean conditions to find those pixels that span between -N/8 to N/8 for the height and -M/8 to M/8 for the width, making sure that the centre of the mask is the origin (0,0). Therefore:
[X,Y] = meshgrid(1:columns, 1:rows);
H = (X - floor(columns/2) >= -columns/8) & (X - floor(columns/2) <= columns/8) & ...
(Y - floor(rows/2) >= -rows/8) & (Y - floor(rows/2) <= rows/8);
H = double(H);
The last line of code is important, as we need to cast to double so that you can convolve / filter your image by multiplying with the frequency domain version of the image. You can only multiply things in MATLAB provided that they are of the same type. H is a logical after applying the Boolean conditions, so you need to convert to double before you proceed.
As an example, let's say rows = 200 and cols = 200. This means that for the rectangular filter, this should span from horizontal frequencies of -25 to 25, and the same for the vertical frequencies. This means that we should get a square of 50 x 50. If we run this code, this is the image I get:
As such, just use those two lines of code, and your mask will be stored in H. You can then use this to filter your image.
Good luck!

Dsift (vl_feat) and Matlab

I have a (naïve probably) question, I just wanted to clarify this part. So, when I take a dsift on one image I generally get an 128xn matrix. Thing is, that n value, is not always the same across different images. Say image 1 gets an 128x10 matrix, while image 2 gets a 128x18 matrix. I am not quite sure why is this happening.
I think that each column of 128dimension represents a single image feature or a single patch detected from the image. So in the case of 128x18, we have extracted 18 patches and described them with 128 values each. If this is correct, why cant we have a fixed numbers of patches per image, say 20 patches, so every time our matrixes would be 128x20.
Cheers!
This is because the number of reliable features that are detected per image change. Just because you detect 10 features in one image does not mean that you will be able to detect the same number of features in the other image. What does matter is how close one feature from one image matches with another.
What you can do (if you like) is extract the, say, 10 most reliable features that are matched the best between the two images, if you want to have something constant. Choose a number that is less than or equal to the minimum of the number of patches detected between the two. For example, supposing you detect 50 features in one image, and 35 features in another image. After, when you try and match the features together, this results in... say... 20 best matched points. You can choose the best 10, or 15, or even all of the points (20) and proceed from there.
I'm going to show you some example code to illustrate my point above, but bear in mind that I will be using vl_sift and not vl_dsift. The reason why is because I want to show you visual results with minimal pre- and post-processing. Should you choose to use vl_dsift, you'll need to do a bit of work before and after you compute the features by dsift if you want to visualize the same results. If you want to see the code to do that, you can check out the vl_dsift help page here: http://www.vlfeat.org/matlab/vl_dsift.html. Either way, the idea about choosing the most reliable features applies to both sift and dsift.
For example, supposing that Ia and Ib are uint8 grayscale images of the same object or scene. You can first detect features via SIFT, then match the keypoints.
[fa, da] = vl_sift(im2single(Ia));
[fb, db] = vl_sift(im2single(Ib));
[matches, scores] = vl_ubcmatch(da, db);
matches contains a 2 x N matrix, where the first row and second row of each column denotes which feature index in the first image (first row) matched best with the second image (second row).
Once you do this, sort the scores in ascending order. Lower scores mean better matches as the default matching method between two features is the Euclidean / L2 norm. As such:
numBestPoints = 10;
[~,indices] = sort(scores);
%// Get the numBestPoints best matched features
bestMatches = matches(:,indices(1:numBestPoints));
This should then return the 10 best matches between the two images. FWIW, your understanding about how the features are represented in vl_feat is spot on. These are stored in da and db. Each column represents a descriptor of a particular patch in the image, and it is a histogram of 128 entries, so there are 128 rows per feature.
Now, as an added bonus, if you want to display how each feature from one image matches to another image, you can do the following:
%// Spawn a new figure and show the two images side by side
figure;
imagesc(cat(2, Ia, Ib));
%// Extract the (x,y) co-ordinates of each best matched feature
xa = fa(1,bestMatches(1,:));
%// CAUTION - Note that we offset the x co-ordinates of the
%// second image by the width of the first image, as the second
%// image is now beside the first image.
xb = fb(1,bestMatches(2,:)) + size(Ia,2);
ya = fa(2,bestMatches(1,:));
yb = fb(2,bestMatches(2,:));
%// Draw lines between each feature
hold on;
h = line([xa; xb], [ya; yb]);
set(h,'linewidth', 1, 'color', 'b');
%// Use VL_FEAT method to show the actual features
%// themselves on top of the lines
vl_plotframe(fa(:,bestMatches(1,:)));
fb2 = fb; %// Make a copy so we don't mutate the original
fb2(1,:) = fb2(1,:) + size(Ia,2); %// Remember to offset like we did before
vl_plotframe(fb2(:,bestMatches(2,:)));
axis image off; %// Take out the axes for better display