Max pool operation in Matlab? - matlab

Is there a function that allows to compute a 2d max-pooling with predefined, kernel size and window stride in Matlab?
I was looking around but couldn't find anything so far...
Say I have a 3D cube of data [HxWxC], I'd like to run a 2d max-pooling on every channel separately (similar to the max-pool operation known from neural networks).
A similar opencv function would also help me out...

Here's another solution that doesn't require the neural network function.
You could do a convolution with your kernel on each channel and then select the slices of the resulting matrix that you want to keep (which corresponds to the stride). Here's a code sample for a generic case of linear average pooling.
% pool
kernel = ones(k)/k^2;
temp = conv2(padarray(data, [p p]), kernel, 'valid');
% downsample
pooled_data = temp(1:stride:end, 1:stride:end);
You could, of course, use an order statistic filter instead of the linear averaging in this example, or any other pooling function. You can also play around with the padarray value parameter to get the padding behavior you desire.

I ended up using matconvnet
k = 3; % kernel_size
p = 1; % padding size
data_pooled = vl_nnpool(single(data),[k,k],'Pad',[p,p,p,p]);

Related

How can I put a constraint on the output signal from deconvolution using deconvwnr or other deconvolution methods?

I want to deconvolve a signal with a point spread function to retrieve a "ground truth" signal. I know that the ground truth is roughly Gaussian and should be 7x7 pixels.
Desired Output
This works when I do deconvolution with the raw signal. However, when I alter the signal with interpolation then try to deconvolve I get this weird periodic semi-gaussian signal that is the same length as the point spread function (47 pixels).
Actual Output
Is it possible to restrict the size of the output to be a 7x7 image? Or to constrain it so that the output has a Gaussian spread?
Here is the code. The variables are in the dropbox link:
deconvwnr(temp,sptint,0)
https://www.dropbox.com/s/r2ajzo52el6gy57/answers.mat?dl=0
Edit: If Weiner filter deconvolution can't do it, is there any deconvolution that can? Or alternatively, is there some mathematical way to restore the 7x7 Gaussian signal using what I have?
edit 2: I have attached a comma separated sheet: https://www.dropbox.com/s/7tmrpsfbhaxixcj/Alexa%20Fluor%20647.csv?dl=0
To generate the Gaussian I do
w=116.4736
px=106.6667
truth = fspecial('gaussian',7,w/px);
Then to generate sptint I do
load 'Alexa Fluor 647.csv';
spt = Alexa_Fluor_647(:,3);
sptint=interp1(300:900,spt,600:5:800);
Then to generate temp I do
sptimg = conv2(truth,spt');
sptimg(:,end-(3-1):end)=[];
sptimg(:,1:3)=[];
sptimg2 = interp1(300:900,sptimg',600:5:800)';
temp=zeros(7,47)
temp(:,4:44)=sptimg2(:,:,1);
A weighted average can be considered.
Using a sliding window, you move a 7 by 7 window from left to right of temp, mulitpy the numbers by a weight (sptint for that window) and add the result iteratively.
startAvg = 1:47-6;
avg = zeros(7);
for ii = 1:length(startAvg)
avg = avg + temp(:,startAvg(ii):startAvg(ii)+6)*sptint(ii);
end
avg = avg/ii

why do k-means clustering different results everytime?

I am using k-means clustering for segmentation of retinal image. However everytime when I run my code segmentation yeilds different results for same image. What is the reason of this change? Following are three segmentation results of same image.
Below is the code used for this segmenation.
idx = kmeans(double(imreslt1(:)),2);
classimage = reshape(idx, size(imreslt1));
minD = min( classimage (:));
maxD = max( classimage (:));
g = (double(classimage ) - minD) ./ (maxD - minD);
imshow(g);
This is the initialization problem for kmeans, as when kmeans starts it picks up the random initial points to cluster your data. Then matlab selects k number of random points and calculates the distance of points in your data to these locations and finds new centroids to further minimize the distance. so because of these random initial points you get different results for centroid locations, but the answer is similar.
If you read the MATLAB help file for the kmeans function, you'll see that the initial points for the k-means clustering algorithm are chosen randomly according to the k-means++ algorithm. To make this reproducible, you can either pass in your own initial points as follows:
kmeans(...,'Start',[random_points_matrix])
or, you could try seeding the MATLAB internal random number generator using the following:
rng(seed); % where seed is some constant you choose
idx = kmean(...);
However, I'm not clear on the internals of the kmean function, so I can't guarantee that this will necessarily produce reproducible results.

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.

Would Richardson–Lucy deconvolution work for recovering the latent kernel?

I am aware that Richardson–Lucy deconvolution is for recovering the latent image, but suppose we have a noisy image and the original image. Can we find the kernel that caused the transformation?
Below is a MATLAB code for Richardson-Lucy deconvolution and I am wondering if it is easy to modify and make it recover the kernel instead of the latent image. My thoughts are that we change the convolution options to valid so the output would represent the kernel, what do you think?
function latent_est = RL_deconvolution(observed, psf, iterations)
% to utilise the conv2 function we must make sure the inputs are double
observed = double(observed);
psf = double(psf);
% initial estimate is arbitrary - uniform 50% grey works fine
latent_est = 0.5*ones(size(observed));
% create an inverse psf
psf_hat = psf(end:-1:1,end:-1:1);
% iterate towards ML estimate for the latent image
for i= 1:iterations
est_conv = conv2(latent_est,psf,'same');
relative_blur = observed./est_conv;
error_est = conv2(relative_blur,psf_hat,'same');
latent_est = latent_est.* error_est;
end
Thanks in advance.
This is a very simple problem. Convolution is commutative. Hence, you don't need to change the implementation of RL deconvolution to obtain PSF, you can simply call it as follows:
psf = RL_deconvolution(observed, latent_est, iterations)

Gaussian filter in MATLAB

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.