Reputation: 3854
I have a task that is compute the mean value of a sub-image that extract from input image I. Let explain my task. I have a image I (i.e, 9x9), and a window (i.e size 3x3). The window will be run from top-left to bottom-right of image. Hence, it will extract the input image into many subimage. I want to compute the mean value of these sub-images. Could you suggest to me some matlab code to compute it.
This is my solution. But it does not work.
Compute the mean value of each sub-window
%% Given Image I,Defined a Gaussian Kernel
sigma=3;
K=fspecial('gaussian',round(2*sigma)*2+1,sigma);
KI=conv2(I,K,'same');
%% mean value
mean(KI)
The problem in here is that mean value off all sub-image will have size similar image I. Because each pixel in image will made a sub-image. But my code returns only a value. What is problem?
Upvotes: 0
Views: 850
Reputation: 104484
If it is your desire to compute the average value in each sub-image once you filter your image with a Gaussian kernel, simply convolve your image with a mean or average filter. This will collect sub-images within your original image and for each output location, you will compute the average value.
Going with your initial assumption that the mask size is 3 x 3, simply use conv2
in conjunction with a 3 x 3 mask that has all 1/9 coefficients. In other words:
%// Your code
%% Given Image I,Defined a Gaussian Kernel
sigma=3;
K=fspecial('gaussian',round(2*sigma)*2+1,sigma);
KI=conv2(I,K,'same');
%// New code
mask = (1/9)*ones(3,3);
out = conv2(KI, mask, 'same');
Each location in out
will give you what the average value was for each 3 x 3 sub-image in your Gaussian filtered result.
You can also create the averaging mask by using fspecial
with the flag average
and specifying the size / width of your mask. Given that you are already using it in your code, you already know of its existence. As such, you can also do:
mask = fspecial('average', 3);
The above code assumes the width and height of the mask are the same, and so it'll create a 3 x 3 mask of all 1/9 coefficients.
conv2
is designed for general 2D signals. If you are looking to filter an image, I recommend you use imfilter
instead. You should have access to it, since fspecial
is part of the Image Processing Toolbox, and so is imfilter
. imfilter
is known to be much more efficient than conv2
, and also makes use of Intel Integrated Performance Primitives (Intel IPP) if available (basically if you are running MATLAB on a computer that has an Intel processor that supports IPP). Therefore, you should really perform your filtering this way:
%// Your code
%% Given Image I,Defined a Gaussian Kernel
sigma=3;
K=fspecial('gaussian',round(2*sigma)*2+1,sigma);
KI=imfilter(I,K,'replicate'); %// CHANGE
%// New code
mask = fspecial('average', 3);
out = imfilter(KI, mask, 'replicate'); %// CHANGE
The replicate
flag is for handling the boundary conditions. When your mask goes out of bounds of the original image, replicate
simply replicates the border of each side of your image so that the mask can fit comfortably within the image when performing your filtering.
Given your comment, you want to extract the subimages that are seen in KI
. You can use the very powerful im2col
function that's part of the Image Processing Toolbox. You call it like so:
B = im2col(A,[m n]);
A
will be your input image, and B
will be a matrix that is of size mn x L
where L
would be the total number of possible sub-images that exist in your image and m
, n
are the height and width of each sub-image respectively. How im2col
works is that for each sub-image that exists in your image, it warps them so that it fits into a single column in B
. Therefore, each column in B
produces a single sub-image that is warped into a column. You can then use each column in B
for your GMM modelling.
However, im2col
only returns valid sub-images that don't go out of bounds. If you want to handle the edge and corner cases, you'll need to pad the image first. Use padarray
to facilitate this padding. Therefore, to do what you're asking, we simply do:
Apad = padarray(KI, [1 1], 'replicate');
B = im2col(Apad, [3 3]);
The first line of code will pad the image so that you have a 1 pixel border that surrounds the image. This will allow you to extract 3 x 3 sub-images at the border locations. I use the replicate
flag so that you can simply duplicate the border pixels. Next, we use im2col
so that you get 3 x 3 sub-images that are then stored in B
. As such, B
will become a 9 x L
matrix where each column gives you a 3 x 3 sub-image.
Be mindful that im2col
warps these columns in column-major format. That means that for each sub-image that you have, it takes each column in the sub-image and stacks them on top of each other giving you a 9 x 1
column. You will have L
total sub-images, and these are concatenated horizontally to produce a 9 x L
matrix. Also, keep in mind that the sub-images are read top-to-bottom, then left-to-right as this is the nature of MATLAB operating in column-major order.
Upvotes: 1