Can I compute Haar-features using "Coefficients" in a IntegralKernel defined filter instead of integralFilter() function? - matlab

I define a Haar-like feature filter H by the IntegralKernel class in Matlab.
H = integralKernel(integralKernel([1,1,im_width,im_height;...
2, 2, w, h;...
2+w, 2, w, h;],...
[0,1,-1]);
im_width and im_height are width and height of the image; w and h are width and height of the bounding box of the filter. The returned filte H is a Matlab struct type variable, which contains the fields like:
BoundingBoxes
Weights
Coefficients - Conventional filter coefficients.
Center
Size
In Matlab document, it uses the function integralFilter(IntegralImage, H), when computing the feature from the given integral image. The code is like:
HaarFeature = integralFilter(integralImage(I), H)
But this takes a long time if the number of images are large (e.g., 10,000 images), because I need to use a for-loop to compute every image. However, I found that is much quicker if I just compute the sum of the given original image I and the coefficients in the filer H. The code is like:
HaarFeature = sum(sum(I .* H.Coefficients));
Both I and H.Coefficients are double type in Matlab.
My question is that if these two ways to compute the Haar Features are equivalent? Thanks!

Do you have to filter each image with multiple kernels?
In that case you should only call integralImage(I) once for each image, and store and re-use the result. Computing the integral image takes some time. However, once you have it, applying an integral kernel to the resulting integral image should be very fast.

Related

Discrete Wavelet Transform Matlab

I am trying to use the functions provided in the Matlab Wavelet Toolbox to create a multi-level discrete wavelet decomposition of an image, extracting the coefficients, manipulating them, and recomposing them back into the image.
I tried using a number of functions but none of them seem to do what I need. These are the steps to do this.
Use wavedec2 to decompose the image into [C,S].
[C,S] = wavedec2(X,N,Lo_D,Hi_D)
I then must use detcoef2 to extract the detail coefficients from [C,S]. [C,S] is the 'wavelet decomposition structure', it does not represent the actual coefficients such as cD, cH, cV.
[H,V,D] = detcoef2('all',C,S,N)
Manipulate the data
Reconstruct [C,S] ???? no function does this.
Use waverec2 to recompose the original image.
X = waverec2(C,S,Lo_R,Hi_R)
The problem is with step 4. There is no function that recreates the [C,S] and I can't call the function waverec2 because it needs the manipulated version of C and S.
Do I not need wavedec2 and waverec2? Perhaps should I just use detcoef2 and upcoef2?
Someone with some experience with DWT could solve this in a minute, I am fairly new to it.
Thanks
I'm curious as to why you can't use dwt2 for computing the 2D DWT of images. What you have there is a lot more work than what you should be doing. dwt2 is much more suitable to do what you want. You'd call dwt2 like so:
[LL,LH,HL,HH] = dwt2(X,Lo_D,Hi_D);
X is your image, and Lo_D and Hi_D are your low-pass and high-pass filters you want to apply to the image. LL is the low-passed version of the image, where the horizontal and vertical directions are low-passed, LH is where the vertical direction is low-passed and the horizontal direction is high-passed, HL is the vertical direction is high-passed and the horizontal direction is low-passed, and HH is where both directions are high-passed. As such LH, HL and HH are the detail coefficients while LL contains the structure.
You can also specify the filter you want with a string as the second parameter:
[LL,LH,HL,HH] = dwt2(X,'wname');
'wname' is a string that specifies what filter you want. You can type in help wfilters to see what filters are available.
For example, by doing using cameraman.tif from MATLAB's system path, we can do a one level 2D DWT (using the Haar wavelet) and show all of the components like so:
im = imread('cameraman.tif');
[LL, LH, HL, HH] = dwt2(im2double(im), 'haar');
imshow([LL LH; HL HH], []);
I use im2double to convert the image to double precision to ensure accuracy. We get this image:
Note that the image is subsampled by 2 in order to produce the decompositions of LL, LH, HL and HH.
Once you have these components, you can certainly manipulate them to your heart's content. Once you manipulate them, you can simply use idwt2 like so:
Y = idwt2(LL,LH,HL,HH,Lo_R,Hi_R); %//or
Y = idwt2(LL,LH,HL,HH,'wname');
The four components are assumed to be double, and so you can convert the images back to whatever type that was representing the image. Assuming your image was uint8, you can do: Y = im2uint8(Y); to convert back.
This should hopefully be what you're looking for!

How do I create and apply a Gaussian filter in MATLAB without using fspecial, imfilter or conv2?

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:

Discrete Approximation to Gaussian smoothing

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.

Image deblurring using MATLAB

I have two images, one is degraded and one is part of the original image. I need to enhance the first image by using the second one, and I need to do this in the frequency domain. I cut the same area from the degraded image, took its FFT, and tried to calculate the transfer function, but when I applied that function to the image the result was terrible.
So I tried h=fspecial('motion',9,45); to be my transfer function and then reconstructed the image with the code given below.
im = imread('home_degraded.png');
im = rgb2gray(im);
h = fspecial('motion',9,45);
H = zeros(519,311);
H(1:7,1:7) = h;
Hf = fft2(H);
d = 0.02;
Hf(find(abs(Hf)<d))=1;
I = ifft2(fft2(im)./Hf);
imshow(mat2gray(abs(I)))
I have two questions now:
How can I generate a transfer function by using the small rectangles (I mean by not using h=fspecial('motion',9,45);)?
What methods can I use to remove noise from an enhanced image?
I can recommend you a few ways to do that:
Arithmetic mean filter:
f = imfilter(g, fspecial('average', [m n]))
Geometric mean filter
f = exp(imfilter(log(g), ones(m, n), 'replicate')) .^ (1/(m*n))
Harmonic mean filter
f = (m*n) ./ imfilter(1 ./ (g + eps), ones(m, n), 'replicate');
where n and m are size of a mask (for instance, you can set m = 3 n = 3)
Basically what you want to do has two steps (at least) to it:
Estimate the PSF (blur kernel) by using the patch of the image with the squares in it.
Use the estimated kernel to do deconvolution to your blurry image
If you want to "guess" the PSF for step 1, that's fine but it's better to calculate it.
For step 2, you MUST first use edgetaper which will subside the ringing effects in your image, which you call noise.
The you use non-blind deconvolution (step 2) by using the function deconvlucy following this syntax:
J = deconvlucy(I,PSF)
this deconvolution procedure adds some noise, especially if your PSF is not 100% accurate, but you can make it smoother if you allow for more iterations (trading in details, NFL).
For the first step, if you don't care about the fact that you have the "sharp" square, you can just use blind deconvolution deconvblind and get some estimate for the PSF.
If you want to do it correctly and use the sharp patch then you can use it as your data term target in any optimization scheme involving the estimation of the PSF.

Gaussian smoothing in MATLAB

For an m x n array of elements with some noisy images, I want to perform Gaussian smoothing. How do I do that in MATLAB?
I've read the math involves smoothing everything with a kernel at a certain scale, but I have no idea how to do this in MATLAB.
Hopefully, you have the Image Processing toolbox. If so, then you can create a Gaussian filter with the fspecial function like so:
myfilter = fspecial('gaussian',[3 3], 0.5);
I have used the default values for hsize ([3 3]) and sigma (0.5) here, but you might want to play around with them. hsize is just the size of the filter, in this case it is a 3 x 3 matrix. Sigma is the sigma of the gaussian function (see the bottom of the fspecial function page).
Now you can use imfilter to filter your image:
myfilteredimage = imfilter(unfilteredimage, myfilter, 'replicate');
here I have simply passed in the unfilteredimage, the filter, and a parameter that says how the filter should handle the boundaries. In this case, I've chosen replicate which sets input array values outside the bounds of the array to the nearest array border value, but you can try some other values (or leaving off that option sets all outside of image values to 0).