Partition an image into 8 rows via Matlab, not all partitions shown - image

I wish to ask if anybody out there knows how to partition an image into 8 different rows and 1 column? I have tried using mat2cell() and using the demo on their wiki as a reference, I tried partitioning the image into 8 rows, however not all image partition rows are displayed.
If you see the image below, 2, 4, 6, 8 is not displayed. I am also not sure why is it of 16 blocks.
Can somebody help me check my code? I am not really used to the MatLab syntax and language. I trying my best to understand now.
My code for splitting the blocks are as follows:
blockSizeR = 50; % Rows in block.
blockSizeC = 512; % Columns in block.
wholeBlockRows = floor(rows / blockSizeR);
blockVectorR = [blockSizeR * ones(1, wholeBlockRows), rem(rows, blockSizeR)];
wholeBlockCols = floor(columns / blockSizeC);
blockVectorC = [blockSizeC * ones(1, wholeBlockCols), rem(columns, blockSizeC)];
if numberOfColorBands > 1
% It's a color image.
ca = mat2cell(rgbImage, blockVectorR, blockVectorC, numberOfColorBands);
else
ca = mat2cell(rgbImage, blockVectorR, blockVectorC);
end
% Now display all the blocks.
plotIndex = 1;
numPlotsR = size(ca, 1);
numPlotsC = size(ca, 2);
for r = 1 : numPlotsR
for c = 1 : numPlotsC
fprintf('plotindex = %d, c=%d, r=%d\n', plotIndex, c, r);
% Specify the location for display of the image.
subplot(numPlotsR, 1, plotIndex);
% Extract the numerical array out of the cell
% just for tutorial purposes.
rgbBlock = ca{r,c};
imshow(rgbBlock); % Could call imshow(ca{r,c}) if you wanted to.
[rowsB columnsB numberOfColorBandsB] = size(rgbBlock);
% Make the caption the block number.
caption = sprintf('Block #%d of %d\n%d rows by %d columns', ...
plotIndex, numPlotsR*numPlotsC, rowsB, columnsB);
title(caption);
drawnow;
% Increment the subplot to the next location.
plotIndex = plotIndex + 1;
end
end
I am new to MatLab, so is there is a simpler method to do this that I missed out, please do suggest or better still, if there are references that I can refer to. Many thanks (:

If you know the dimensions of your matrix, you can do the math to figure out how to divide the number of rows into 4 equal parts:
e.g. If: size(rockinsMatrix) == [10 20] (a 10row x 20column) matrix,
then you could split it into a set of 4 sub-matrices, two with 3 rows, and 2 with 2 columns.
If you want the matrices in a cell array then you can do that at that time.

I managed to solve already, the error lies in the for loop. I changed the for r = 1 : numPlotsR into r = 1 : (number of rows I want) for c = 1 : numPlotsC into c= 1: 1(as I only want one column), and used subplot(8,1,k) or (8,2,k) where k is the plot index. Just answering this in case anybody encounter such problem in future and want to use my code as a reference. Cheers!

Related

Using a 3D hankel matrix to index a 3D matrix in MATLAB

Given the following three dimensional hankel matrix:
hankel_matrix = hankel(1:21, 21:999);
hankel_matrix = repmat(hankel_matrix, [1 1 no_of_weighted_composites]);
And the matrix:
composites_collection = permute(reshape(data_composites.', size(data_composites, 2),1,[]),[2 3 1]);
where data_composites is a 999 x 56 matrix.
Essentially what I want to achieve is use the hankel matrix to index the 56 different pages of single rows found in the composites collection.
I had assumed this would be as easy as data_composites_collection(hankel_matrix) but that simply uses the first page of data_composites_collection and repeats this for all 56 pages.
My current implementation is:
function subsequent_hankel_index = createMovingSnapshotsOfValues(~, matrix_of_numbers, data_composites, windows, no_of_weighted_composites)
data_composites_collection = permute(reshape(data_composites.', size(data_composites, 2),1,[]),[2 3 1]);
hankel_index = NaN(260, 999, no_of_weighted_composites, size(windows, 2));
for window_size = 1:size(windows, 2);
for composite = 1:no_of_weighted_composites;
hankel_matrix = hankel(1:windows(window_size), windows(window_size):length(matrix_of_numbers));
desired_row = data_composites_collection(:,:,composite);
[rows, columns] = size(desired_row(hankel_matrix));
hankel_index(1:rows,1:columns,composite,window_size) = desired_row(hankel_matrix);
subsequent_hankel_index = hankel_index;
end
end
end
However, this is incredibly slow for the amount of data I have. I have assumed vectorising the above would greatly help the speed of my programme. Any tips or approaches to the indexing would be greatly appreciated.
Many thanks in advance!

Is there any way to control the concatenation of the blockproc output?

This is a follow up to the question: Overlapping sliding window over an image using blockproc or im2col?
So by using the code :
B = blockproc(A, [1 1], #block_fun, 'BorderSize', [2 2], 'TrimBorder', false, 'PadPartialBlocks', true)
I was able to create an overlapping sliding window over my image and calculate the dct2 for each window. But the problem is that blockproc concatenates the output in a way that I cannot use. The output greatly depends on the block size and the size of the output matrix is different because of it every time.
My dct2 function creates a 1 x 200 vector for every block or window. So I assumed that if there are 64 blocks I should get something like 64 x 200 or 200 x 64 output, but I get something like 64 x 1600 or in case of larger blocks I get 15 x 400.
Looking into the blockproc function the problem is caused by
% write 4 corner blocks
b(1:ul_output_size(1),1:ul_output_size(2),:) = ul_output;
if ll_processed
last_row_start = final_rows - size(ll_output,1) + 1;
last_row_width = size(ll_output,2);
b(last_row_start:end,1:last_row_width,:) = ll_output;
end
if ur_processed
last_col_start = final_cols - size(ur_output,2) + 1;
last_col_height = size(ur_output,1);
b(1:last_col_height,last_col_start:end,:) = ur_output;
end
if lr_processed
last_row_start = final_rows - size(ll_output,1) + 1;
last_col_start = final_cols - size(ur_output,2) + 1;
b(last_row_start:end,last_col_start:end,:) = lr_output;
end
Apparently, blockproc further divides the blocks into upper left, upper right, lower left and lower right and concatenates that result. And that is why I am getting all this mixed outputs.
I need the output of each block in its each row, for each window. Each window should just give me a 1x200 output, that I can feed into my classifier.
Can I force the output of blockproc in the way that I want it, just give the output of each block.
If not, I would really appreciate an alternative solution to have an overlapping sliding window over the image.
edit: would it be possible to save the blocks data using block_struct.data for every block into a cell array inside the function block_fun and then use that array to extract my features?
Thank you
edit:
B = blockproc(images_m{1}, [64 64], #(x)reshape(x.data(:),[1 1 numel(x.data)]), 'BorderSize', [10 10], 'TrimBorder', false, 'PadPartialBlocks', true, 'PadMethod', 'replicate');
imgs = {};
for i = 1:size(B,1)
for j = 1:size(B,2)
tempy = squeeze(B(i,j,:));
tempy2 = reshape(tempy, [84 84]);
feats{end+1} = block_dct2(tempy2); %calculates dct2 for the block and returns a 1*200 vector
end
end
Maybe reshape you data in the third dimension?
>> A = magic(3)
A =
8 1 6
3 5 7
4 9 2
>> B = blockproc(A, [1 1], #(x)reshape(x.data(:),[1 1 numel(x.data)]), 'BorderSize', [1 1], 'TrimBorder', false, 'PadPartialBlocks', true);
>> whos B
Name Size Bytes Class Attributes
B 3x3x9 648 double
>> squeeze(B(1,1,:))
ans =
0
0
0
0
8
3
0
1
5
>>
An alternate using MAT2CELL:
function extractFeatures
images_m{1} = rand(128);
B = blockproc(images_m{1}, [64 64], #processBlock,...
'BorderSize', [10 10], 'TrimBorder', false,...
'PadPartialBlocks', true, 'PadMethod', 'replicate');
%B is 2x400 i.e 2x2 blocks of each block being a 1x200 feature vector
m = ones(1,size(B,1));
n = 200*ones(1,size(B,2)/200);
% The MAT2CELL help does a good job, just read it carefully and run the
% examples
feats = mat2cell(B,m,n);
feats = feats(:);
end
function feature = processBlock(bstruct)
% I dont know what block_dct2 does:
%feature = block_dct2(bstruct.data);
% So I'll put in a place holder which returns a 1x200 'feature'
% for each overlapping image block
feature = repmat(mean(bstruct.data(:)), [1 200]);
end

Reshape vector to matrix with column-wise zero padding in matlab

for an input matrix
in = [1 1;
1 2;
1 3;
1 4;
2 5;
2 6;
2 7;
3 8;
3 9;
3 10;
3 11];
i want to get the output matrix
out = [1 5 8;
2 6 9;
3 7 10;
4 0 11];
meaning i want to reshape the second input column into an output matrix, where all values corresponding to one value in the first input column are written into one column of the output matrix.
As there can be different numbers of entries for each value in the first input column (here 4 values for "1" and "3", but only 3 for "2"), the normal reshape function is not applicable. I need to pad all columns to the maximum number of rows.
Do you have an idea how to do this matlab-ish?
The second input column can only contain positive numbers, so the padding values can be 0, -x, NaN, ...
The best i could come up with is this (loop-based):
maxNumElem = 0;
for i=in(1,1):in(end,1)
maxNumElem = max(maxNumElem,numel(find(in(:,1)==i)));
end
out = zeros(maxNumElem,in(end,1)-in(1,1));
for i=in(1,1):in(end,1)
tmp = in(in(:,1)==i,2);
out(1:length(tmp),i) = tmp;
end
Either of the following approaches assumes that column 1 of in is sorted, as in the example. If that's not the case, apply this initially to sort in according to that criterion:
in = sortrows(in,1);
Approach 1 (using accumarray)
Compute the required number of rows, using mode;
Use accumarray to gather the values corresponding to each column, filled with zeros at the end. The result is a cell;
Concatenate horizontally the contents of all cells.
Code:
[~, n] = mode(in(:,1)); %//step 1
out = accumarray(in(:,1), in(:,2), [], #(x){[x; zeros(n-numel(x),1)]}); %//step 2
out = [out{:}]; %//step 3
Alternatively, step 1 could be done with histc
n = max(histc(in(:,1), unique(in(:,1)))); %//step 1
or with accumarray:
n = max(accumarray(in(:,1), in(:,2), [], #(x) numel(x))); %//step 1
Approach 2 (using sparse)
Generate a row-index vector using this answer by #Dan, and then build your matrix with sparse:
a = arrayfun(#(x)(1:x), diff(find([1,diff(in(:,1).'),1])), 'uni', 0); %//'
out = full(sparse([a{:}], in(:,1), in(:,2)));
Introduction to proposed solution and Code
Proposed here is a bsxfun based masking approach that uses the binary operators available as builtins for use with bsxfun and as such I would consider this very appropriate for problems like this. Of course, you must also be aware that bsxfun is a memory hungry tool. So, it could pose a threat if you are dealing with maybe billions of elements depending also on the memory available for MATLAB's usage.
Getting into the details of the proposed approach, we get the counts of each ID from column-1 of the input with histc. Then, the magic happens with bsxfun + #le to create a mask of positions in the output array (initialized by zeros) that are to be filled by the column-2 elements from input. That's all you need to tackle the problem with this approach.
Solution Code
counts = histc(in(:,1),1:max(in(:,1)))'; %//' counts of each ID from column1
max_counts = max(counts); %// Maximum counts for each ID
mask = bsxfun(#le,[1:max_counts]',counts); %//'# mask of locations where
%// column2 elements are to be placed
out = zeros(max_counts,numel(counts)); %// Initialize the output array
out(mask) = in(:,2); %// place the column2 elements in the output array
Benchmarking (for performance)
The benchmarking presented here compares the proposed solution in this post against the various methods presented in Luis's solution. This skips the original loopy approach presented in the problem as it appeared to be very slow for the input generated in the benchmarking code.
Benchmarking Code
num_ids = 5000;
counts_each_id = randi([10 100],num_ids,1);
num_runs = 20; %// number of iterations each approach is run for
%// Generate random input array
in = [];
for k = 1:num_ids
in = [in ; [repmat(k,counts_each_id(k),1) rand(counts_each_id(k),1)]];
end
%// Warm up tic/toc.
for k = 1:50000
tic(); elapsed = toc();
end
disp('------------- With HISTC + BSXFUN Masking approach')
tic
for iter = 1:num_runs
counts = histc(in(:,1),1:max(in(:,1)))';
max_counts = max(counts);
out = zeros(max_counts,numel(counts));
out(bsxfun(#le,[1:max_counts]',counts)) = in(:,2);
end
toc
clear counts max_counts out
disp('------------- With MODE + ACCUMARRAY approach')
tic
for iter = 1:num_runs
[~, n] = mode(in(:,1)); %//step 1
out = accumarray(in(:,1), in(:,2), [], #(x){[x; zeros(n-numel(x),1)]}); %//step 2
out = [out{:}];
end
toc
clear n out
disp('------------- With HISTC + ACCUMARRAY approach')
tic
for iter = 1:num_runs
n = max(histc(in(:,1), unique(in(:,1))));
out = accumarray(in(:,1), in(:,2), [], #(x){[x; zeros(n-numel(x),1)]}); %//step 2
out = [out{:}];
end
toc
clear n out
disp('------------- With ARRAYFUN + Sparse approach')
tic
for iter = 1:num_runs
a = arrayfun(#(x)(1:x), diff(find([1,diff(in(:,1).'),1])), 'uni', 0); %//'
out = full(sparse([a{:}], in(:,1), in(:,2)));
end
toc
clear a out
Results
------------- With HISTC + BSXFUN Masking approach
Elapsed time is 0.598359 seconds.
------------- With MODE + ACCUMARRAY approach
Elapsed time is 2.452778 seconds.
------------- With HISTC + ACCUMARRAY approach
Elapsed time is 2.579482 seconds.
------------- With ARRAYFUN + Sparse approach
Elapsed time is 1.455362 seconds.
slightly better, but still uses a loop :(
out=zeros(4,3);%set to zero matrix
for i = 1:max(in(:,1)); %find max in column 1, and loop for that number
ind = find(in(:,1)==i); %
out(1: size(in(ind,2),1),i)= in(ind,2);
end
don't know if you can avoid the loop...

How do I quickly calculate changes in two n-by-4 matrices?

I have two matrices (tri1 and tri2) which represent a Delaunay triangulation. tri1 is the triangulation before inserting a new point, tri2 is the result after adding a new point. Each row has 4 columns. The rows represent tetrahedra.
I would like to calculate a relation between lines from tri1 to tri2. A result could look like this:
result =
1 1
2 2
3 3
4 4
0 0 % tri1(5, :) was not found in tri2 (a lot more lines could be missing)
6 5
7 6
8 7
9 8
10 9
Currently my source code looks like this:
% sort the arrays
[~, idx1] = sort(tri1(:, 1), 'ascend');
[~, idx2] = sort(tri2(:, 1), 'ascend');
stri1 = tri1(idx1, :);
stri2 = tri2(idx2, :);
result = zeros(size(tri1, 1), 2);
% find old cells in new triangulation
deleted = 0;
for ii = 1:size(tri1, 1)
found = false;
for jj = ii-deleted:size(tri2, 1)
if sum(stri1(ii, :) == stri2(jj, :)) == 4 % hot spot according to the profiler
found = true;
break;
end
if (stri1(ii, 1) < stri2(jj, 1)), break, end;
end
if found == false
deleted = deleted + 1;
else
result(idx1(ii), 1) = idx1(ii);
result(idx1(ii), 2) = idx2(jj);
end
end
The above source code gives me the results that I want, but not fast enough. I am not very experienced with MATLAB, I usually work with C++. My question: How can I speed up the comparison of two rows?
Some additional information (just in case):
the number of rows in tri can grow to about 10000
this function will be called once per inserted vertex (about 1000)
I cannot follow your example code completely, but judging from your explanation you want to see whether a row from matrix A occurs in matrix B.
In this case a very efficient implentation is available:
[Lia, Locb] = ismember(A,B,'rows');
Check the doc for more information about this function and see whether it is what you need.

Pattern matching – Normalized Correlation

as a part of my homework i need to implement this pattern matching.
the goal is to "Detect as many of the 0's (zeros) as you can in image coins4.tif."
i was given the NGC function. and i need to use it
this is my main.m file
Image = readImage('coins4.tif');
Pattern = readImage('zero.tif');
showImage(Image);
showImage(Pattern);
message = sprintf('Pattern matching Normalized Correlation');
PatternMatching(Image , Pattern);
uiwait(msgbox(message,'Done', 'help'));
close all
this is my PatternMatching function.
function [ output_args ] = PatternMatching( Image , Pattern )
% Pattern matching – Normalized Correlation
% Detect as many of the 0's (zeros) as you can in image coins4.tif.
% Use the 0 of the 10 coin as pattern.
% Use NGC_pm and find good threshold. Display original image with? detected regions marked using drawRect.
% NGCpm(im,pattern);
% drawRect(rectCoors,color);
% rectCoors = [r0,c0,rsize,csize] - r0,c0 = top-left corner of rect.
% rsize = number of rows, csize = number of cols
%
% color = an integer >=1 representing a color in the color wheel
% (curerntly cycles through 8 different colors
showImage(Image);
hold on
res = NGCpm(Image, Pattern);
for i = 1:size(res,1)
for j = 1:size(res,2)
if res(i,j) > 0.9999
drawRect([i j size(Pattern,1) size(Pattern,2)], 5)
end
end
end
end
this is the Given NGCpm.m file
function res=NGC_PM(im,pattern)
[n m]=size(pattern);
[im_row,im_col]=size(im);
if ~(var(pattern(:))==0)
res = normxcorr2(pattern, im);
res=res(n:im_row,m:im_col);
else
res=zeros(size(im)-size(pattern)+1);
end;
res = 1-abs(res); % res = abs(res);
this is the pattern i'm trying to find and the results, i'm getting
i'm trying to find as many "Zeros" as possiable using the zero pattern of the coin 10.
i'm tryingto understand if there is something wrong with my algorithm in the PatternMatching function. since the NGCpm function is already given to me, all i need to do is just loop of the best threshold ,correct?
or do i need to blur the image or the pattern?
this is the fixed version of this function.
function [ output_args ] = patternMatching( Image , Pattern )
% Pattern matching – Normalized Correlation
% Detect as many of the 0's (zeros) as you can in image coins4.tif.
% Use the 0 of the 10 coin as pattern.
% Use NGC_pm and find good threshold. Display original image with? detected regions marked using drawRect.
% NGCpm(im,pattern);
% drawRect(rectCoors,color);
% rectCoors = [r0,c0,rsize,csize] - r0,c0 = top-left corner of rect.
% rsize = number of rows, csize = number of cols
%
% color = an integer >=1 representing a color in the color wheel
% (curerntly cycles through 8 different colors
showImage(Image);
hold on
res = 1-NGCpm(Image, Pattern);
normalized_corellation = uint8(255*res/max(max(res)));
res_thresh = thresholdImage(normalized_corellation,100);
for i = 1:size(res_thresh,1)
for j = 1:size(res_thresh,2)
if res_thresh(i,j) > 0
drawRect([i j size(Pattern,1) size(Pattern,2)], 5)
end
end
end
end

Resources