To do a low-pass filter, I have used a Gaussian kernel, then do a convolution with this kernel to have the smoothed version of my image. Since the spline basis function tend to give a sharper cut-off, I would like to build a spline 2d kernel. Does anyone have an idea about this? Thank you in advance!
Thank you for your response. In fact I have a look on butterworth filter, but I suppose it is in frequency domain and require infinite support. My problem is very specific. I want to find the coefficients matrix that apply the filtering directly on the image.
I have use Gaussian as following:
Build the kernel
Gau2D=#(x,y) 1/(sigma*2*pi)*exp(-(x.^2+y.^2)/sigma^2/2);
[x,y] = meshgrid(-(k)/2:(k)/2);
ker = Gau2D(x,y);
ker = ker./sum(ker(:));
BLUR = convmtx2(ker,[M N]);
Apply on an image
img_filtered=BLUR*img(:);
I am thinking, for example, instead of using Gaussian kernel, I can use something like cardinal spline kernel, to increase the sharpness of the filter. But still, I can find the way to deal with it. Please help!
Related
I am looking at some FFT code in a matlab project and the FFT and inverse FFT is computed this way:
% Here image is a 2D image.
image_fft = fftshift(image,1);
image_fft = fftshift(image_fft,2);
image_fft = fft(image_fft,[],1);
image_fft = fft(image_fft,[],2);
image_fft = fftshift(image_fft,1);
image_fft = fftshift(image_fft,2);
% Some processing and then same sequence of fftshift, ifft and fftshift to move to
% time domain
I tried to find some information online but am having trouble wondering why the fftshift needs to be done before computing the FFT.
Another question I have is whether this is something really Matlab specific. For example, I am planning to port this code to C++ and use KISS FFT. Do I need to be vary of this?
The reason why people like to swap prior to the DFT is because it makes the center pixel of the image the one with zero-phase shift. It often makes algorithms that depend on phase easier to think about and implement. It is not matlab specific and if you want to port an exact version of the code to another language, you'll need to perform the quadswap beforehand too.
EDIT:
Let me give an example that I hope will clear things up. Let's say that our image is the sum of a bunch of sinc functions with varying locations throughout the image. In the frequency domain, each of these sinc functions is a rect function with the same amplitude but with a different linear phase component that determines the location of the sinc in the image domain. By swapping the image prior to taking the DFT, we make the linear phase component of the frequency domain representation of the center pixel be zero. Moreover, the linear phase components of the other sinc functions will now be a function of their distance from the center pixel. If we didn't swap the image beforehand, then the linear phase components of the rect functions would be a function of their distance from the pixel in the top-left of the image. This would be non-intutive and would involve the same kind of phase wrapping considerations that one sees with equating the frequencies in the range (pi,2pi) rad/sample with more the intuitive (-pi,0) rad/sample.
For images, it's better to use fft2. It's matlab's convention to arrange 2D ffts with the DC in the corners. Presumably because of the row/array conventions. fftshift allows for a more intuitive display of the FFT with the DC in the center.
I don't fully understand what the piece of code you copied is about, here is an example of fft and inverse fft of an image using matlab.
And a more detailed tutorial here.
I have an image that I converted to a vector and plotted:
img = imread(image.png');
grayImage = rgb2gray(img);
grayImage(2:2:end,:)=fliplr(grayImage(2:2:end,:));
B = rot90(grayImage);
C = flipud(B);
[x,y]=size(C);
vector = reshape(C ,1,x*y);
plot(vector);
The problem is that although I can visually see a wave pattern, there is a lot of noise that occurs. By noise I mean the signals rapidly go up and down eventually forming a sinusoidal wave but I want to be able to just connect the crest of each spike to one another in order to create a continuous wave pattern. If anyone understands what I am trying to do, help would be appreciated.
Thank you in advance.
Not 100% sure about what you're asking, but the medfilt1 median filter function might be what you're looking for, it's a 1D smoothing filter. Example usage would be:
vector_filt = medfilt1(vector);
Check out the documentation and example at http://www.mathworks.com/help/signal/ref/medfilt1.html.
I think performing a gaussian convolution on the vector should solve your problem. Here is a link to a stack overflow question that has a very nice answer on how to do a gaussian convolution in matlab: Gaussian Filter on a vector in Matlab
I am trying to find a discrete approximation to the Gaussian smoothing operation, as shown in the link :
http://bit.ly/1cSgkwt
G is some discrete smoothing kernel, a Gaussian in this case and * is the convolution operation. Basically, I want to apply a smoothing kernel to each pixel in the image. I am doing this in MATLAB and using the following code to create the matrix G, which is naive and hence painfully slow :
z = rgb2gray(imread('train_02463_1.bmp'));
im_sz = size(z);
ksize = 5;
% Gaussian kernel of size ksize*ksize
gw_mat = g_sigma(1,2*ksize+1)'*g_sigma(1,2*ksize+1);
G = sparse(length(ksize+1:im_sz(1)-ksize),prod(im_sz));
for i = ksize+1:im_sz(1)-ksize
for j = ksize+1:im_sz(2)-ksize
[x,y] = meshgrid(i-ksize:i+ksize,j-ksize:j+ksize);
row_num = sub2ind(im_sz,i,j);
colnums = sub2ind(im_sz,x,y);
G(row_num,colnums(:)) = gw_mat(:)';
end
end
Is there a more efficient way to do this ?
EDIT: I should apologize for not complete specifying the problem. Most of the answers below are valid ones, but the issue here is the above approximation is part of a optimization objective where the variable is z. The whole problem looks something like this :
http://goo.gl/rEE02y
Thus, I have to pre-generate a matrix G which approximates a smoothing function in order to feed this objective to a solver. I am using cvx, if that helps.
Typically people do it by applying two 1D Gaussian functions sequentially instead of one 2D function (idea of separable filters). You can approximate 1D horizontal Gaussian pretty fast, apply it to each pixel, save result in temp, and then apply a vertical Gaussian to temp. The expected speed up is quite significant: O(ksize*ksize) -> O(ksize+ksize)
You can use approximate Gaussian smoothing via box filters, e.g see integgaussfilt.m:
This function approximates Gaussian filtering by repeatedly applying
averaging filters. The averaging is performed via integral images which
results in a fixed and very low computational cost that is independent of
the Gaussian size.
The fastest way to apply Spatially Invariant Filter on an image using MATLAB would be using imfilter.
imfilter will automatically notice "Seperable" Kernel and will apply it in 2 steps (Vertically / Horizontally).
For creating some known and useful kernels you may look at fspecial.
Let's say For each pixel, the gradient ∇g= [∂f/∂x, ∂f/∂y]. Then the first derivative should be measured by two operators like 1/2[1,0,1;0,0,0;-1,0,-1] & 1/2[-1,0,1;0,0,0;-1,0,-1]
then:
[i,j]=gradient(im);
filt1=[1,0,1;0,0,0;-1,0,-1];
filt2=[-1,0,1;0,0,0;-1,0,-1];
ii=(1./2).*(conv2(filt1,i));
jj=(1./2).*(conv2(filt2,j));
G_x=conv2(ii,im);
G_y=conv2(jj,im);
Is it correct or I should first multiply 1/2 to the operators, and then convolve them?
since associativity (with scalars) is a quality of convolutions the order of the multiplication should not play any rolle.
On the other hand your filters don't seem to me like they perform a differentiation. The classical filter for the discrete differentiation would be a Sobel that looks something like this:
[1,0,-1
2,0,-2
1,0,-1]
and
[1,2,1
0,0,0
-1,-2,-1]
For the purposes of optimizing the computation, it helps to apply the scaling of 1/2 directly to the filter kernels
filt1 = filt1/2;
Otherwise, if done afterward, N^2 additional multiplications have to be done to the NxN image pixels, instead of just 9 multiplications to a 3x3 kernel.
Beyond that, I agree with McMa. Your computations don't look anything like a differentiation. In fact, you already apply gradient() in the very first line, so I don't understand what more you need.
I'd be inclined to use the imgradient and imgradientxy functions in MATLAB. If you want directional gradients, use imgradientxy and if you want gradient magnitude and direction components, use imgradient.
You can choose to have derivatives computed using Sobel,Prewitt or Roberts gradient kernels or using central or intermediate differences.
Here's an example:
[Gx,Gy] = imgradientxy(im,'Sobel');
Instead if you want to continue using conv2, you can get gradient kernels using the fspecial function.
kernelx = fspecial('sobel');
kernely = kernelx';
Does the 'gaussian' filter in MATLAB convolve the image with the Gaussian kernel? Also, how do you choose the parameters hsize (size of filter) and sigma? What do you base it on?
You first create the filter with fspecial and then convolve the image with the filter using imfilter (which works on multidimensional images as in the example).
You specify sigma and hsize in fspecial.
Code:
%%# Read an image
I = imread('peppers.png');
%# Create the gaussian filter with hsize = [5 5] and sigma = 2
G = fspecial('gaussian',[5 5],2);
%# Filter it
Ig = imfilter(I,G,'same');
%# Display
imshow(Ig)
#Jacob already showed you how to use the Gaussian filter in Matlab, so I won't repeat that.
I would choose filter size to be about 3*sigma in each direction (round to odd integer). Thus, the filter decays to nearly zero at the edges, and you won't get discontinuities in the filtered image.
The choice of sigma depends a lot on what you want to do. Gaussian smoothing is low-pass filtering, which means that it suppresses high-frequency detail (noise, but also edges), while preserving the low-frequency parts of the image (i.e. those that don't vary so much). In other words, the filter blurs everything that is smaller than the filter.
If you're looking to suppress noise in an image in order to enhance the detection of small features, for example, I suggest to choose a sigma that makes the Gaussian just slightly smaller than the feature.
In MATLAB R2015a or newer, it is no longer necessary (or advisable from a performance standpoint) to use fspecial followed by imfilter since there is a new function called imgaussfilt that performs this operation in one step and more efficiently.
The basic syntax:
B = imgaussfilt(A,sigma) filters image A with a 2-D Gaussian smoothing kernel with standard deviation specified by sigma.
The size of the filter for a given Gaussian standard deviation (sigam) is chosen automatically, but can also be specified manually:
B = imgaussfilt(A,sigma,'FilterSize',[3 3]);
The default is 2*ceil(2*sigma)+1.
Additional features of imgaussfilter are ability to operate on gpuArrays, filtering in frequency or spacial domain, and advanced image padding options. It looks a lot like IPP... hmmm. Plus, there's a 3D version called imgaussfilt3.