I have written the following code in order to convolve an image first
% Convoluton and deconvolution
% Firstly convultion
a = imread('duas.jpg');
subplot(231);
imshow(a)
b = rgb2gray(a);
subplot(232);
imshow(b);
% convolving with h, High Pass filter now
h = [1 2 1; 1 2 1];
c = conv2(b,h);
subplot(233);
imshow(c);
Now I need to deconvolve it , what to do ? I think I should get the original image using it ?
You can use MATLAB's Wiener Filter and use Noise Std of zero.
Deconvolution is usually done in the frequency domain.
I'll illustrate the steps to do direct Deconvolution (Which coincide with Wiener Filter for zero noise).
I assume Deconvolution (As opposed to Blind Deconvolution) where the applied filter is given:
Apply FFT on the filtered image.
Add zeros at the end of LPF filter in the Spatial Domain to have the same size as the image.
Apply FFT on this Filter Matrix.
Divide point by point the image by the filter.
If the filter has zero values set the output to be zero.
Apply IFFT on the output image.
Good Luck.
Related
I am trying to apply a double-bandstop filter using frequency sampling from a given data file.
The method I am using is as follows
Inverse fft (ifft) of the given frequency sampling file
Circular shifting of the real values given from step 1
Perform an fft of the result from step 2
Apply the filter on the audio file using convolution. (frequency domain)
The problem is that the bandstop frequencies (925Hz & 2090Hz) still exist. Is there any problem with my code or do I miss something?
[wave,fs]=audioread('audio.WAV');
data=importdata ('freqSampling.txt')
y=(ifft(data,401))
x=real (y)
r=circshift (x,200)
f=fft (r,4096);
new_sound=conv (wave, f)
sound(new_sound,fs,16);
Can anyone help me with that?
The first two steps
Inverse fft (ifft) of the given frequency sampling file
Circular shifting of the real values given from step 1
should correctly give you the time-domain coefficients of a filter constructed from your specifications, provided the freqSampling.txt file correctly specifies the desired full double-sided spectrum (see "Validating specifications" below). The number of ifft points may also need to be adjusted/increased if the frequency specification contains steep transients. Performing the convolution in the frequency domain as you indicated in step 4 however does not correspond to a typical filtering operation, but would rather be equivalent to a time-domain multiplication of the two signals.
Time-domain filtering
From the result of step 2 you could filter your wave data directly in the time-domain using either conv:
new_sound = conv(r, wave);
or filter:
new_sound = filter(r, 1, wave);
conv would be giving you the full length(wave)+length(r)-1 convolution, whereas filter is a more signal processing oriented function returning the first length(wave) samples of the convolution (and can also handle recursive filters which conv does not support directly).
Frequency-domain filtering
Alternatively to perform the filtering in the frequency-domain you would
Perform an FFT of the result from step 2, using a size that is at least length(r)+length(wave)-1
Perform an FFT of the wave data, using the same size as in step 3
Apply the filter on the audio file using multiplication (frequency domain).
Compute the inverse FFT (ifft) of the result from step 5
Take the real part of the result from step 6 (technically not required, but often needed due to small numerical round-off errors)
This can be implemented using the following:
N = length(wave)+length(r)-1;
wave_fd = fft(wave, N); % step 3
filter_fd = fft(r, N); % step 4
filtered_fd = wave_fd .* filter_fd; % step 5
new_sound = real(ifft(filtered_fd)); % step 6 & 7
Note that you could also perform this frequency-domain filtering operation in smaller chunks using the overlap-add method.
Validating specifications
Based on your comments, the data imported from the freqSampling.txt file could be reconstructed with:
N = 401;
data = ones(N,1);
data(19:23) = [2 1 0 1 2]/3;
data(51:56) = [2 1 0 1 2]/3;
data(N-[2:(N+1)/2]+2) = data([2:(N+1)/2]);
To validate that this would filter the desired frequencies, we can plot this specification as a function of frequency. To do this we would need the sampling rate used (fs), which seem to be 22050 according to your graph. You should then be able to plot these with:
hold off; plot([0:N-1]*fs/N, data);
hold on; plot([925 925;2090 2090]', [0 1.2;0 1.2]', 'k:');
axis([0 3000 0 1.2]);
xlabel('Frequency (Hz)');
ylabel('Amplitude');
legend('Specs', 'Tones');
Which should give a plot that looks like:
Based on this, it seems that the specifications do not provide any attenuation at the tone frequencies. A better fit could be constructed with:
N = 401;
data = ones(N,1);
data(round(925*N/fs)+1+[-2:2]) = [2 1 0 1 2]/3; % data([16:20])
data(round(2090*N/fs)+1+[-2:2]) = [2 1 0 1 2]/3; % data([37:41])
data(N-[2:(N+1)/2]+2) = data([2:(N+1)/2]);
Yielding a validation plot that looks like:
P.S.: based on your signal's frequency-domain graph, it would seem that the second tone is closer to 2600Hz rather than the indicated 2090Hz.
I have written some code below in MATLAB to filter a Noisy signal (noise_f is the noisy signal, where it is a 1 x 256 vector):
s_nf = size(noise_f);
size_f = s_nf(2);
lp_tresh = ceil((2/3)*size_f);
lp_f = zeros(1,256);
for n = 1:lp_tresh
lp_f(n) = noise_f(n);
end
subplot(4,3,7);
plot(abs(lp_f)); title('LowPass Filter Result');
Here is a time domain image of the noisy signal:
Here is a time domain analysis of this signal:
Once I plot the result of the lowpass filter, I get this:
Now I apply the ifft on the 1 x 256 vector that represents the filtered signal and for some reason, I get this image :
Can someone explain to me how to get the proper plot of the filtered signal? All help and suggestions will be appreciated!
To get a strictly real result, the input to an IFFT must be complex conjugate symmetric. Chopping off the part of the FFT above bin N/2 (or below bin 0) destroys that symmetry if any of those bins are non-zero.
Thus, a low-pass filter will only work in the frequency domain if it's cutoff is below bin N/2 (representing Fs/2). Then make sure the filtered result is conjugate symmetric before doing the IFFT.
I have the following code in MATLAB:
I=imread(image);
h=fspecial('gaussian',si,sigma);
I=im2double(I);
I=imfilter(I,h,'conv');
figure,imagesc(I),impixelinfo,title('Original Image after Convolving with gaussian'),colormap('gray');
How can I define and apply a Gaussian filter to an image without imfilter, fspecial and conv2?
It's really unfortunate that you can't use the some of the built-in methods from the Image Processing Toolbox to help you do this task. However, we can still do what you're asking, though it will be a bit more difficult. I'm still going to use some functions from the IPT to help us do what you're asking. Also, I'm going to assume that your image is grayscale. I'll leave it to you if you want to do this for colour images.
Create Gaussian Mask
What you can do is create a grid of 2D spatial co-ordinates using meshgrid that is the same size as the Gaussian filter mask you are creating. I'm going to assume that N is odd to make my life easier. This will allow for the spatial co-ordinates to be symmetric all around the mask.
If you recall, the 2D Gaussian can be defined as:
The scaling factor in front of the exponential is primarily concerned with ensuring that the area underneath the Gaussian is 1. We will deal with this normalization in another way, where we generate the Gaussian coefficients without the scaling factor, then simply sum up all of the coefficients in the mask and divide every element by this sum to ensure a unit area.
Assuming that you want to create a N x N filter, and with a given standard deviation sigma, the code would look something like this, with h representing your Gaussian filter.
%// Generate horizontal and vertical co-ordinates, where
%// the origin is in the middle
ind = -floor(N/2) : floor(N/2);
[X Y] = meshgrid(ind, ind);
%// Create Gaussian Mask
h = exp(-(X.^2 + Y.^2) / (2*sigma*sigma));
%// Normalize so that total area (sum of all weights) is 1
h = h / sum(h(:));
If you check this with fspecial, for odd values of N, you'll see that the masks match.
Filter the image
The basics behind filtering an image is for each pixel in your input image, you take a pixel neighbourhood that surrounds this pixel that is the same size as your Gaussian mask. You perform an element-by-element multiplication with this pixel neighbourhood with the Gaussian mask and sum up all of the elements together. The resultant sum is what the output pixel would be at the corresponding spatial location in the output image. I'm going to use the im2col that will take pixel neighbourhoods and turn them into columns. im2col will take each of these columns and create a matrix where each column represents one pixel neighbourhood.
What we can do next is take our Gaussian mask and convert this into a column vector. Next, we would take this column vector, and replicate this for as many columns as we have from the result of im2col to create... let's call this a Gaussian matrix for a lack of a better term. With this Gaussian matrix, we will do an element-by-element multiplication with this matrix and with the output of im2col. Once we do this, we can sum over all of the rows for each column. The best way to do this element-by-element multiplication is through bsxfun, and I'll show you how to use it soon.
The result of this will be your filtered image, but it will be a single vector. You would need to reshape this vector back into matrix form with col2im to get our filtered image. However, a slight problem with this approach is that it doesn't filter pixels where the spatial mask extends beyond the dimensions of the image. As such, you'll actually need to pad the border of your image with zeroes so that we can properly do our filter. We can do this with padarray.
Therefore, our code will look something like this, going with your variables you have defined above:
N = 5; %// Define size of Gaussian mask
sigma = 2; %// Define sigma here
%// Generate Gaussian mask
ind = -floor(N/2) : floor(N/2);
[X Y] = meshgrid(ind, ind);
h = exp(-(X.^2 + Y.^2) / (2*sigma*sigma));
h = h / sum(h(:));
%// Convert filter into a column vector
h = h(:);
%// Filter our image
I = imread(image);
I = im2double(I);
I_pad = padarray(I, [floor(N/2) floor(N/2)]);
C = im2col(I_pad, [N N], 'sliding');
C_filter = sum(bsxfun(#times, C, h), 1);
out = col2im(C_filter, [N N], size(I_pad), 'sliding');
out contains the filtered image after applying a Gaussian filtering mask to your input image I. As an example, let's say N = 9, sigma = 4. Let's also use cameraman.tif that is an image that's part of the MATLAB system path. By using the above parameters, as well as the image, this is the input and output image we get:
I have an image and my aim is to binarize the image. I have filtered the image with a low pass Gaussian filter and have computed the intensity histogram of the image.
I now want to perform smoothing of the histogram so that I can obtain the threshold for binarization. I used a low pass filter but it did not work. This is the filter I used.
h = fspecial('gaussian', [8 8],2);
Can anyone help me with this? What is the process with respect to smoothing of a histogram?
imhist(Ig);
Thanks a lot for all your help.
I've been working on a very similar problem recently, trying to compute a threshold in order to exclude noisy background pixels from MRI data prior to performing other computations on the images. What I did was fit a spline to the histogram to smooth it while maintaining an accurate fit of the shape. I used the splinefit package from the file exchange to perform the fitting. I computed a histogram for a stack of images treated together, but it should work similarly for an individual image. I also happened to use a logarithmic transformation of my histogram data, but that may or may not be a useful step for your application.
[my_histogram, xvals] = hist(reshape(image_volume), 1, []), number_of_bins);
my_log_hist = log(my_histogram);
my_log_hist(~isfinite(my_log_hist)) = 0; % Get rid of NaN values that arise from empty bins (log of zero = NaN)
figure(1), plot(xvals, my_log_hist, 'b');
hold on
breaks = linspace(0, max_pixel_intensity, numberofbreaks);
xx = linspace(0, max_pixel_intensity, max_pixel_intensity+1);
pp = splinefit(xvals, my_log_hist, breaks, 'r');
plot(xx, ppval(pp, xx), 'r');
Note that the spline is differentiable and you can use ppdiff to get the derivative, which is useful for finding maxima and minima to help pick an appropriate threshold. The numberofbreaks is set to a relatively low number so that the spline will smooth the histogram. I used linspace in the example to pick the breaks, but if you know that some portion of the histogram exhibits much greater curvature than elsewhere, you'd want to have more breaks in that region and less elsewhere in order to accurately capture the shape of the histogram.
To smooth the histogram you need to use a 1-D filter. This is easily done using the filter function. Here is an example:
I = imread('pout.tif');
h = imhist(I);
smooth_h = filter(normpdf(-4:4, 0,1),1,h);
Of course you can use any smoothing function you choose. The mean would simply be ones(1,8).
Since your goal here is just to find the threshold to binarize an image you could just use the graythresh function which uses Otsu's method.
I need to test some basic image processing techniques in Matlab. I need to test and compare especially two types of filters: mean filter and median filter.
To smooth image using median filtering, there is a great function medfilt2 from image processing toolbox. Is there any similar function for mean filter? Or how to use the filter2 function to create the mean filter?
One of the most important things for me is to have the possibility of setting radius of the filter. I.e. for median filter, if I want the [3 x 3] radius (mask), I just use
imSmoothed = medfilt2(img, [3 3]);
I would like to achieve something similar for mean filter.
h = fspecial('average', n);
filter2(h, img);
See doc fspecial:
h = fspecial('average', n) returns an averaging filter. n is a 1-by-2 vector specifying the number of rows and columns in h.
I see good answers have already been given, but I thought it might be nice to just give a way to perform mean filtering in MATLAB using no special functions or toolboxes. This is also very good for understanding exactly how the process works as you are required to explicitly set the convolution kernel. The mean filter kernel is fortunately very easy:
I = imread(...)
kernel = ones(3, 3) / 9; % 3x3 mean kernel
J = conv2(I, kernel, 'same'); % Convolve keeping size of I
Note that for colour images you would have to apply this to each of the channels in the image.
I = imread('peppers.png');
H = fspecial('average', [5 5]);
I = imfilter(I, H);
imshow(I)
Note that filters can be applied to intensity images (2D matrices) using filter2, while on multi-dimensional images (RGB images or 3D matrices) imfilter is used.
Also on Intel processors, imfilter can use the Intel Integrated Performance Primitives (IPP) library to accelerate execution.
and the convolution is defined through a multiplication in transform domain:
conv2(x,y) = fftshift(ifft2(fft2(x).*fft2(y)))
if one channel is considered... for more channels this has to be done every channel
f=imread(...);
h=fspecial('average', [3 3]);
g= imfilter(f, h);
imshow(g);