How to count the number of overlapping blocks in an Image - matlab

I have a 512X512 size of image and I have made 4x4 overlapping blocks for the entire image.How can i count the number of overlapping blocks and save it in an Array in matlab.
I have done like below for 4x4 overlapping blocks. Now how to count the no of blocks and store it using an Array.
[e f] = size(outImg);
l=0;
for i=2:e-2
for j=2:f-2
H =double(outImg((i-1:i+2),(j-1:j+2)));
eval(['out_' num2str(l) '=H']);
l=l+1
end;
end;

From what I understand the question, you want to know how many blocks of 4x4 can fit in the image, and then store them.
Calculating the number of blocks is trivial, in the code that you give as example, l is the number of element counted. Of course, that its value is deterministic (determined by f and e). No need to loop over them to get the value of the count.
count = (f-3)*(e-3);
If you want to save the values in an array (assuming that you mean here a matrix and not a cell array) you need to decide how to represent it, you can store it as a 4D e-3 x f-3 x 4 x 4 matrix (as #Steffen suggested), or as a 3D 4 x 4 x count matrix, I think that the later is more intuitive. In any case you should assign the memory for the matrix in advance and not on the fly:
[e f] = size(outImg);
count = (f-3)*(e-3);
outMat = zeros(4,4,count); % assign the memory for the matrix
l = 0;
for i=2:e-2
for j=2:f-2
l = l + 1;
outMat(:,:,l) = double(outImg((i-1:i+2),(j-1:j+2)));
end;
end;
The number of blocks is stored as both count and l, but calculating count in advance allows to assign the needed memory in advance, the i block is stored as outMat(:,:,i).
An implementation using the 4D matrix would be:
[e f] = size(outImg);
count = (f-3)*(e-3);
outMat = zeros((f-3),(e-3),4,4); % assign the memory for the matrix
for i=2:e-2
for j=2:f-2
outMat(i,j,:,:) = double(outImg((i-1:i+2),(j-1:j+2)));
end;
end;
In this case, l isn't needed and each block (indexed i,j) is located at outMat(i,j,:,:)
Regarding cell array vs. a matrix, since a matrix requires a continuous place in the memory, you may want to consider using a cell array instead of a matrix. A 512x512x4 matrix of doubles requires (assuming 8 Byte representation) 8MB (512*512*8*4 = 8*1024*1024). If the dimensions were bigger, or if you are strapped for (continuous) memory a cell array may be a better solution. You can read more about the difference at Difference between cell and matrix in matlab?.
The implementation would be very similar.
[e f] = size(outImg);
count = (f-3)*(e-3);
outArray = cell(1,count);
l = 0;
for i=2:e-2
for j=2:f-2
l = l + 1;
outArray{1,l} = double(outImg((i-1:i+2),(j-1:j+2)));
end;
end;

The answer is very simple. Each loop iteration will access 1 overlapping block in your image. All you have to do is count how many times the loop iterates, which is ((e-2) - 2 + 1) x ((f - 2) - 2 + 1) = (e - 3) x (f - 3). There's no need to keep a loop iteration variable.
Minor note. Under no circumstances should you use eval unless absolutely necessary. The MATLAB gods will smite any offenders swiftly. That code to assign a new variable to each increment of l is absolutely unnecessary. If you were to have 10000 overlapping blocks, you would have 10000 variables. You can just simply take a look at l at the end and this would tell you how many overlapping blocks you have.
Remove that line of code. WE HATES IT. IT BURNS US.
See this post by Loren Shure for more details on why using eval is bad.

For the 1-D case, the correct formula to estimate the total number of overlapping blocks is:
(#Of_blocks) = (#Image_width - #Block_width) / (#Block_width - #Block_overlap) + 1
If the result is not integer you just take the floor of #Of_blocks, this means that the whole interval can't be covered using that setup.

Related

Multiply two vectors with dimensions increasing along time

I have two vectors (called A and B) with length N. Then I need to multiply both of them, but as an "integration" process. Which means I have to multiply first A(1)*B(1), then A(1:2)*B(1:2), until A(1:N)*B(1:N). The result of multiplying booth vector is a number, since B is a column vector. I've done it with a for loop:
for k = 1:N
C(k) = A(1:k) * B(1:k).';
end
But I wanted to ask you if this is the best solution or there is any other option more time-efficient, since N is very large (about 110,000)
C = cumsum(A.*B)
does the same thing without for loop. As EBH suggested in the comments if you are not sure whether A and B have same orientation, then use
C = cumsum(A(:).*B(:))

Assigning matrix elements to variables in a data set

Hello I'm new to Matlab.
I've written this script :
k2=2*pi();
z1 = 1;
z2 = 2;
z3 = 4;
for l = linspace(0,1,11)
A = [ -1 1 1 0 ; 1 z1/z2 -z1/z2 0 ; 0 exp(-i*k2*l) exp(i*k2*l) -1 ; 0 exp(- i*k2*l) -exp(i*k2*l) -z2/z3];
B = [ 1 ; 1 ; 0 ; 0];
D = inv(A);
C = mtimes(D,B) ;
display(C)
r = C(1,1); % this is supposed to set r = the 1,1 element in the matrix C
t = C(1,4); % see above
end
My idea for taking the values of r and t from C didnt appear to work. How can I do this properly?
Also I want to plot a graph of |r|,|t|, arg(r) and arg(t) for each value of l, my for loop overwrites the values of r and t? how can I either plot one point per loop or make r and t assign the new values so that they become lists of data.
Thanks a lot!
Matlab sets the first dimension of a matrix as row number (i.e. y position).
So you want t=C(4, 1), as you should see that the size of C is 4x1. As a note Matlab is quite good at suppressing singleton dimensions so you could do also do C(1) and C(4).
For your second point you want to set a particular element of r and t in each loop. This is the same as when you access at particular element of C when setting the values. For your case you can use the index l to determine the element. Remembering that in matlab arrays start at element 1 (not 0 as in many other languages). So you want something like r(l+1)=C(1); (or change l to start at 1).
In the more general case if you are not looping over an integer for some reason you may need to create a separate counter variable which you increase in the loop. Also it is good practice to preallocate such arrays when the size is known beforehand, often by r=zeros(11, 1) or similar (note: zeros(11) is an 11x11 matrix). This isn't significant in this case but can drastically increase execution time for large multi-dimensional arrays so is a good practice.

How to find a value of one vector, in a range of value in another vector in matlab

I have a vector A with size of 54000 x 1 and vector B with size of 54000 x 1 which is standard deviation of elements of A. From the other side, I have vector C with size of 300000 x 1. Now I want to find that each element of vector C correspondences to which row of vector A with accepted range 3*standard deviation? I have written the below code and it works fine for small vector but for large vector such that I have it is too too slow!!
for i=1:length(A)
L=A(i,1)- 3*B(i,1);
U=A(i,1)+ 3*B(i,1);
inds{i,1} = not(abs(sign(sign(L - C) + sign(U - C))));
end
Does anybody know how can I make this code faster or does anybody know another solution? THX.
MATLAB is an acronym for Matrix Laboratory and was developed to simply and speed up matrix(vector) calculations. Compared to C or any other programming language you can often skip the for loops when working with matrices. For your code you should be able to skip the for loop and do it as this:
L = A - 3*STD;
U = A + 3*STD;
inds = not(abs(sign(sign(L - C) + sign(U - C))));
And remember that i means the complex number in Matlab. Don't know if it affects speed though.
Edit:
Getting the result as a cell:
inds = num2cell(inds)

MATLAB: Indexing a large matrix for Monte Carlo Simulation

I'm trying to index a large matrix in MATLAB that contains numbers monotonically increasing across rows, and across columns, i.e. if the matrix is called A, for every (i,j), A(i+1,j) > A(i,j) and A(i,j+1) > A(i,j).
I need to create a random number n and compare it with the values of the matrix A, to see where that random number should be placed in the matrix A. In other words, the value of n may not equal any of the contents of the matrix, but it may lie in between any two rows and any two columns, and that determines a "bin" that identifies its position in A. Once I find this position, I increment the corresponding index in a new matrix of the same size as A.
The problem is that I want to do this 1,000,000 times. I need to create a random number a million times and do the index-checking for each of these numbers. It's a Monte Carlo Simulation of a million photons coming from a point landing on a screen; the matrix A consists of angles in spherical coordinates, and the random number is the solid angle of each incident photon.
My code so far goes something like this (I haven't copy-pasted it here because the details aren't important):
for k = 1:1000000
n = rand(1,1)*pi;
for i = length(A(:,1))
for j = length(A(1,:))
if (n > A(i-1,j)) && (n < A(i+1,j)) && (n > A(i,j-1)) && (n < A(i,j+1))
new_img(i,j) = new_img(i,j) + 1; % new_img defined previously as zeros
end
end
end
end
The "if" statement is just checking to find the indices of A that form the bounds of n.
This works perfectly fine, but it takes ridiculously long, especially since my matrix A is an image of dimensions 11856 x 11000. is there a quicker / cleverer / easier way of doing this?
Thanks in advance.
You can get rid of the inner loops by performing the calculation on all elements of A at once. Also, you can create the random numbers all at once, instead of one at a time. Note that the outermost pixels of new_img can never be different from zero.
randomNumbers = rand(1,1000000)*pi;
new_img = zeros(size(A));
tmp_img = zeros(size(A)-2);
for r = randomNumbers
tmp_img = tmp_img + A(:,1:end-2)<r & A(:,3:end)>r & A(1:end-1,:)<r & A(3:end,:)>r;
end
new_img(2:end-1,2:end-1) = tmp_img;
/aside: If the arrays were smaller, I'd have used bsxfun for the comparison, but with the array sizes in the OP, the approach would run out of memory.
Are the values in A bin edges? Ie does A specify a grid? If this is the case then you can QUICKLY populate A using hist3.
Here is an example:
numRand = 1e
n = randi(100,1e6,1);
nMatrix = [floor(data./10), mod(data,10)];
edges = {0:1:9, 0:10:99};
A = hist3(dataMat, edges);
If your A doesn't specify a grid, then you should create all of your random values once and sort them. Then iterate through those values.
Because you know that n(i) >= n(i-1) you don't have to check bins that were too small for n(i-1). This is a very easy way to optimize away most redundant checks.
Here is a snippet that should help a lot in the inner loop, it finds the location of the greatest point that is smaller than your value.
idx1 = A<value
idx2 = A(idx1) == max(A(idx1))
if you want to find the exact location you can wrap it with a find.

How to change row number in a FOR loop... (MATLAB newbie)

I have a set of data that is <106x25 double> but this is inside a struct and I want to extract the data into a matrix. I figured a simple FOR loop would accomplish this but I have hit a road block quite quickly in my MATLAB knowledge.
This is the only piece of code I have, but I just don't know enough about MATLAB to get this simple bit of code working:
>> x = zeros(106,25); for i = 1:106, x(i,:) = [s(i).surveydata]; end
??? Subscripted assignment dimension mismatch.
's' is a very very large file (in excess of 800MB), it is a <1 x 106 struct>. Suffice it to say, I just need to access a small portion of this which is s.surveydata where most rows are a <1 x 25 double> (a row vector IIRC) and some of them are empty and solely return a [].
s.surveydata obviously returns the results for all of the surveydata contained where s(106).surveydata would return the result for the last row. I therefore need to grab s(1:106).surveydata and put it into a matrix x. Is creating the matrix first by using x = zeros(106,25) incorrect in this situation?
Cheers and thanks for your time!
Ryan
The easiest, cleanest, and fastest way to write all the survey data into an array is to directly catenate it, using CAT:
x = cat(1,s.surveydata);
EDIT: note that if any surveydata is empty, x will have fewer rows than s has elements. If you need x to have the same amount of rows as s has elements, you can do the following:
%# find which entries in s have data
%# note that for the x above, hasData(k) contains the
%# element number in s that the k-th row of x came from
hasData = find(arrayfun(#(x)~isempty(x.surveydata),s));
%# initialize x to NaN, so as to not confuse the
%# real data with missing data entries. The call
%# to hasData when indexing makes this robust to an
%# empty first entry in s
x = NaN(length(s),length(s(hasData(1)).surveydata);
%# fill in only the rows of x that contain data
x(hasData,:) = cat(1,s(hasData).surveydata);
No, creating an array of zeroes is not incorrect. In fact it's a good idea. You don't have to declare variables in Matlab before using them, but for loops, pre-allocating has speed benefits.
x = zeros(size(s), size(s(1)));
for i = 1:106
if ~isempty(s(i).surveydata)
x(i, :) = s(i).surveydata;
end
end
Should accomplish what you want.
EDIT: Since OP indicated that some rows are empty, I accounted for that like he said.
what about this?
what s is?
if s(i).surveydata is scalar:
x = zeros(106,25);
for i = 1:106
x(i,1) = [s(i).surveydata];
end
I am guessing that is what you want tough it is not clear at all :
if s(i).surveydata is row vector:
x = zeros(106,25);
for i = 1:106
x(i,:) = [s(i).surveydata];
end
if s(i).surveydata is column vector:
x = zeros(106,25);
for i = 1:106
x(i,:) = [s(i).surveydata]';
end