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
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,[]);
I'm trying to read the values in this image into variables using OCR in MATLAB. I'm having trouble doing so, so I tried to split up this image into smaller parts using the white boundary lines then trying to read it, but I dont know how to do this. Any help would be appreciated, thanks.
If the blocks are always delimited by a completely vertical line, you can find where they are by comparing the original image (here transformed from RGB to grayscale to be a single plane) to a matrix that is made of repeats of the first row of the original image only. Since the lines are vertical the intensity of the pixels in the first line will be the same throughout. This generates a binary mask that can be used in conjunction with a quick thresholding to reject those lines that are all black pixels in every row. Then invert this mask and use regionprops to locate the bounding box of each region. Then you can pull these out and do what you like.
If the lines dividing the blocks of text are not always vertical or constant intensity throughout then there's a bit more work that needs to be done to locate the dividing lines, but nothing that's impossible. Some example data would be good to have in that case, though.
img = imread('http://puu.sh/cU3Nj/b020b60f0b.png');
imshow(img);
imgGray = rgb2gray(img);
imgMatch = imgGray == repmat(imgGray(1,:), size(imgGray, 1), 1);
whiteLines = imgMatch & (imgGray > 0);
boxes = regionprops(~whiteLines, 'BoundingBox');
for k = 1:6
subplot(3,2,k)
boxHere = round(boxes(k).BoundingBox);
imshow(img(boxHere(2):(boxHere(2)+boxHere(4)-1), boxHere(1):(boxHere(1)+boxHere(3)-1), :));
end
You can sum along the columns of a binary image corresponding to that input image and find peaks from the sum values. This is precisely achieved in the code here -
img = imread('http://puu.sh/cU3Nj/b020b60f0b.png');
BW = im2bw(img,0.1); %// convert to a binary image with a low threshold
peak_sum_max = 30; %// max of sum of cols to act as threshold to decide as peak
peaks_min_width = 10; %// min distance between peaks i.e. min width of each part
idx = find( sum(BW,1)>=peak_sum_max );
split_idx = [1 idx( [true diff(idx)>peaks_min_width ] )];
split_imgs = arrayfun(#(x) img(:,split_idx(x):split_idx(x+1)),...
1:numel(split_idx)-1,'Uni',0);
%// Display split images
for iter = 1:numel(split_imgs)
figure,imshow(split_imgs{iter})
end
Please note that the final output split_imgs is a cell array with each cell holding image data for each split image.
If you would like to have the split images directly without the need for messing with cell arrays, after you have split_idx, you can do this -
%// Get and display split images
for iter = 1:numel(split_idx)-1
split_img = img(:,split_idx(iter):split_idx(iter+1));
figure,imshow(split_img)
end
There is now a built-in ocr function in the Computer Vision System Toolbox.
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)
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.
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