Is there a substitute for blockproc in Matlab? - matlab

I've been using blockproc for processing images blockwise. Unfortunately, blockproc is part of the Image Processing Toolbox, which I don't have on my personal computer.
Is there a combination of functions in base Matlab that can substitute for blockproc?
My initial guess was to use im2col to transform each block into columns, and then arrayfun to process each column. Then I realized that im2col is also a part of the Image Processing Toolbox, so that doesn't solve my problem.

Here is an example using MAT2CELL. It dividing the image into N-by-M tiles, and handles the case when the image size is not evenly divisible by the number of tiles.
%# 2D grayscale image
I = imread('coins.png');
%# desird number of horizontal/vertical tiles to divide the image into
numBlkH = 4;
numBlkW = 4;
%# compute size of each tile in pixels
[imgH,imgW,~] = size(I);
szBlkH = [repmat(fix(imgH/numBlkH),1,numBlkH-1) imgH-fix(imgH/numBlkH)*(numBlkH-1)];
szBlkW = [repmat(fix(imgW/numBlkW),1,numBlkW-1) imgW-fix(imgW/numBlkW)*(numBlkW-1)];
%# divide into tiles, and linearize using a row-major order
C = mat2cell(I, szBlkH, szBlkW)';
C = C(:);
%# display tiles i subplots
figure, imshow(I)
figure
for i=1:numBlkH*numBlkW
subplot(numBlkH,numBlkW,i), imshow( C{i} )
end
The input image and the resulting tiles:

Won't mat2tiles together with cellfun and cell2mat do more or less what blockproc does?
You could write a wrapper yourself to make it use the same arguments as blockproc, I don't think it should be that hard to do.

Related

Expanding a 2D Matrix in Matlab with Interpolation

Let's say I have a 4 pixel by 4 pixel image with values between 0 and 255 and I want to expand it to an 8-by-8 image, interpolating where necessary. I know how to interpolate a vector this way with interp1:
interp1(linspace(0,1,numel(vector)), vector, linspace(0,1,newSize))
But I'm unclear how to use interp2 to do the same thing for a matrix.
EDIT: Would it be the same if I were to create a meshgrid after using linspace for each dimension?
EDIT2: Yep, that worked. It's the same, but with a meshgrid.
For data structured in the form of a regular grid, you can use interp2 as you correctly stated, but since you are dealing with an image, I suggest you to use the imresize function, which is fine-tuned for rescaling images using appropriate interpolation algorithms:
% Load an image and display it...
img = imread('peppers.png');
figure(),imshow(img);
% Create a second image that is
% twice the size of the original
% one and display it...
img2 = imresize(img,2);
figure(),imshow(img2);
Anyway, if you really want to use the aforementioned function, here is how I would perform the interpolation:
% Load an image, convert it into double format
% and retrieve its basic properties...
img = imread('rice.png');
img = im2double(img);
[h,w] = size(img);
% Perform the interpolation...
x = linspace(1,w,w*2);
y = linspace(1,h,h*2);
[Xq,Yq] = meshgrid(x,y);
img2 = interp2(img,Xq,Yq,'cubic') ./ 255;
% Display the original image...
figure(),imshow(img);
%Display the rescaled image...
figure(),imshow(img2,[]);

Dividing image into blocks in Matlab [duplicate]

I've been using blockproc for processing images blockwise. Unfortunately, blockproc is part of the Image Processing Toolbox, which I don't have on my personal computer.
Is there a combination of functions in base Matlab that can substitute for blockproc?
My initial guess was to use im2col to transform each block into columns, and then arrayfun to process each column. Then I realized that im2col is also a part of the Image Processing Toolbox, so that doesn't solve my problem.
Here is an example using MAT2CELL. It dividing the image into N-by-M tiles, and handles the case when the image size is not evenly divisible by the number of tiles.
%# 2D grayscale image
I = imread('coins.png');
%# desird number of horizontal/vertical tiles to divide the image into
numBlkH = 4;
numBlkW = 4;
%# compute size of each tile in pixels
[imgH,imgW,~] = size(I);
szBlkH = [repmat(fix(imgH/numBlkH),1,numBlkH-1) imgH-fix(imgH/numBlkH)*(numBlkH-1)];
szBlkW = [repmat(fix(imgW/numBlkW),1,numBlkW-1) imgW-fix(imgW/numBlkW)*(numBlkW-1)];
%# divide into tiles, and linearize using a row-major order
C = mat2cell(I, szBlkH, szBlkW)';
C = C(:);
%# display tiles i subplots
figure, imshow(I)
figure
for i=1:numBlkH*numBlkW
subplot(numBlkH,numBlkW,i), imshow( C{i} )
end
The input image and the resulting tiles:
Won't mat2tiles together with cellfun and cell2mat do more or less what blockproc does?
You could write a wrapper yourself to make it use the same arguments as blockproc, I don't think it should be that hard to do.

2D convolution of slices of 3D matrix

I'm trying to do a bunch of rolling sums over matrices in MATLAB. In order to avoid loops I've used repmat to layer my 2D matrices into a 3D structure. However, now the fast convolution function conv2 can no longer be used for the accumulator. However, the N-dimensional convolution function (convn) is not what I'm looking for either as it literally convolves all 3 dimensions. I want something that will do a 2D convolution on each slice and return a 3D matrix.
Tiling the matrices in 2D instead of layering them in 3D won't work because it will corrupt the convolution edge cases. I could pad with zeros in between but then it starts getting kind of messy.
In other words, without a for-loop, how can I perform the following:
A = ones(5,5,5);
B = zeros(size(A));
for i = 1 : size(A, 3)
B(:,:,i) = conv2(A(:,:,i), ones(2), 'same');
end
Thanks in advance for the help!
convn will work with an n-dimensional matrix and a 2-dimensional filter. Simply:
A = ones(5,5,5);
B = convn(A, ones(2), 'same');
You can use some padding with zeros and reshaping like so -
%// Store size parameters
[m,n,r] = size(A)
[m1,n1] = size(kernel)
%// Create a zeros padded version of the input array. We need to pad zeros at the end
%// rows and columns to replicate the convolutionoperation around those boundaries
Ap = zeros(m+m1-1,n+n1-1,r);
Ap(1:m,1:n,:) = A;
%// Reshape the padded version into a 3D array and apply conv2 on it and
%// reshape back to the original 3D array size
B_vect = reshape(conv2(reshape(Ap,size(Ap,1),[]),kernel,'same'),size(Ap))
%// Get rid of the padded rows and columns for the final output
B_vect = B_vect(1:m,1:n,:);
The basic idea is to reshape the input 3D array into a 2D array and then apply the 2D convolution on it. Extra step is needed with padding so as to have the same behavior as you would see with conv2 around the boundaries.

Image filtering by dividing the image grids with blockproc in Matlab

I try to divide the image as same size grids and get the response of a filter over those grids. Each response matrix for each grid need to be obtained as separeate. For instance if I am filtering and image in size 500x500 with grid size 100x100 than I need to obtain 5*5 = 25 different response matrices in the size of 100x100. How could I do it at Matlab?
I 've tried blockproc but it does not give separate responses for each image grid instead it grids the image and run the filters on and gives even large response vector. Here is the code I used for blockproc
fun = #(x) imfilter(x.data,filter,'conv');
img_res=blockproc(img,[100 100],fun,'UseParallel',1,'TrimBorder',1,'PadPartialBlocks',1);
Ho can I do what I proposed? Any suggestion?
Here is what I did
% step 1 divide into blocks
szM = size(image)
nb = szM ./ grid_size % number of blocks in each dimension
C = mat2cell(image,repmat(grid_size(1),1,nb(1)), repmat(grid_size(2),1,nb(2)))
% step 2: do something for each block (here MIN)
C2 = cellfun(#(x) min(x(:)), C, 'un', 0)
M2 = cell2mat(C2)

matlab image processing 3d

i have 100 b&w image of smthing.the probllem is i want to scan each image in 0&1 formatin mby n format and then place each image to one over one and again scan and save them in mbynby100 form.
how i do this and from where i should start
_jaysean
Your question is vague and hard to understand, but my guess is that you want to take 100 M-by-N grayscale intensity images, threshold them to create logical matrices (i.e. containing zeroes and ones), then put them together into one M-by-N-by-100 matrix. You can do the thresholding by simply picking a threshold value yourself, like 0.5, and applying it to an image A as follows:
B = A > 0.5;
The matrix B will now be an M-by-N logical matrix with ones where A is greater than 0.5 and zeroes where A is less than or equal to 0.5.
If you have the Image Processing Toolbox, you could instead use the function GRAYTHRESH to pick a threshold and the function IM2BW to apply it:
B = im2bw(A,graythresh(A));
Once you do this, you can easily put the images into an M-by-N-by-100 logical matrix. Here's an example of how you could do this in a loop, assuming the variables M and N are defined:
allImages = false(M,N,100); %# Initialize the matrix to store all the images
for k = 1:100
%# Here, you would load your image into variable A
allImages(:,:,k) = im2bw(A,graythresh(A)); %# Threshold A and add it to
%# the matrix allImages
end