I would like to divide an image into 8 by 6 blocks and then from each block would like to get the average of red, green and blue values then store the average values from each block into an array. Say that if I have image divided into 4 blocks the result array would be:
A = [average_red, average_green, average_blue,average_red, ...
average_green, average_blue,average_red, average_green, ...
average_blue,average_red, average_green, average_blue,...
average_red, average_green, average_blue,]
The loop I have created looks very complicated, takes a long time to run and I'm not even sure if it's working properly or not as I have no clue how to check. Is there any simpler way to implement this.
Here is the loop:
[rows, columns, ~] = size(img);
[rows, columns, ~] = size(img);
rBlock = 6;
cBlock = 8;
NumberOfBlocks = rBlock * cBlock;
bRow = ceil(rows/rBlock);
bCol = ceil(columns/cBlock);
row = bRow;
col = bCol;
r = zeros(row*col,1);
g = zeros(row*col,1);
b = zeros(row*col,1);
n = 1;
cl = 1;
rw = 1;
for x = 1:NumberOfBlocks
for i = cl : col
for j = rw : row
% some code
end
end
%some code
if i == columns && j ~= rows
cl = 1;
rw = j - (bRow -1);
col = (col - col) + bCol;
row = row + bRaw;
elseif a == columns && c == rows
display('done');
else
cl = i + 1;
rw = j - (bRow -1);
col = col + col;
row = row + row;
end
end
Because there are only 48 block, you may use simple for loop iterating blocks. (I think it's going to be fast enough).
Here is my code:
%Build test image
img = double(imresize(imread('peppers.png'), [200, 300]));
[rows, columns, ~] = size(img);
rBlock = 6;
cBlock = 8;
NumberOfBlocks = rBlock * cBlock;
bRow = ceil(rows/rBlock);
bCol = ceil(columns/cBlock);
idx = 1;
A = zeros(1, rBlock*cBlock*3);
for y = 0:rBlock-1
for x = 0:cBlock-1
%Block (y,x) boundaries: (x0,y0) to (x1,y1)
x0 = x*bCol+1;
y0 = y*bRow+1;
x1 = min(x0+bCol-1, columns); %Limit x1 to columns
y1 = min(y0+bRow-1, rows); %Limit y1 to rows
redMean = mean2(img(y0:y1, x0:x1, 1)); %Mean of red pixel in block (y,x)
greenMean = mean2(img(y0:y1, x0:x1, 2)); %Mean of green pixel in block (y,x)
blueMean = mean2(img(y0:y1, x0:x1, 3)); %Mean of blue pixel in block (y,x)
%Fill 3 elements of array A.
A(idx) = redMean;
A(idx+1) = greenMean;
A(idx+2) = blueMean;
%Advance index by 3.
idx = idx + 3;
end
end
I have a question about Matlab mesh generations:
How do I manage the size ofthe mesh in Matlab?
What can I do to workaround this error?
Error message
Error using message
Error filling holes for pdelib:initmesh:LargeMesh. Floating point numbers are not
allowed as holes. They should be converted to strings.
Error in initmesh (line 135)
fprintf(['\n' message('pdelib:initmesh:LargeMesh', ntg).getString() '\n']);
Error in pdegplot>plotTwoDGeometry (line 112)
[p1,~,t1]=initmesh(g,'hmax',0.1,'init','on', 'MesherVersion','R2013a');
Error in pdegplot (line 73)
hh = plotTwoDGeometry(g.geom, plotEdgeNums, plotSubLabels);
Error in test_ellips_10 (line 102)
pdegplot(model,'EdgeLabels','on','SubdomainLabels','on')
This Error is generated by Matlab R2015b when the following code is run:
% Rectangle R1
R1_x1 = 0;
R1_x2 = 3810;
R1_y1 = 0;
R1_y2 = 6800;
% Rectangle R2
R2_x1 = (3810/4);
R2_x2 = (3*3810/4);
R2_y1 = (6800+3810/4);
R2_y2 = 6800;
% Rectangle R5
R5_x1 = (3810/4);
R5_x2 = (3*3810/4);
R5_y1 = 0;
R5_y2 = -(3810/4);
% Rectangle R3
R3_x1 = (3810/2-75);
R3_x2 = (3810/2+75);
R3_y1 = (6800+3810/4+100);
R3_y2 = (6800+3810/4);
% Rectangle R4
R4_x1 = (3810/2-75);
R4_x2 = (3810/2+75);
R4_y1 = -3810/4;
R4_y2 = -(3810/4+100);
% Ellipse E1
% pdeellip(xc,yc,a,b,phi,label)
E1_xc = 3810/4;
E1_yc = 6800;
E1_a = 3810/4;
E1_b = 3810/4;
E1_phi = 0;
% Ellipse E2
% pdeellip(xc,yc,a,b,phi,label)
E2_xc = 3*3810/4;
E2_yc = 6800;
E2_a = 3810/4;
E2_b = 3810/4;
E2_phi = 0;
% Ellipse E3
% pdeellip(xc,yc,a,b,phi,label)
E3_xc = 3810/4;
E3_yc = 0;
E3_a = 3810/4;
E3_b = 3810/4;
E3_phi = 0;
% Ellipse E4
% pdeellip(xc,yc,a,b,phi,label)
E4_xc = 3*3810/4;
E4_yc = 0;
E4_a = 3810/4;
E4_b = 3810/4;
E4_phi = 0;
model = createpde(1);
% Rectangle is code 3, 4 sides,
% followed by x-coordinates and then y-coordinates
R1 = [3, 4, R1_x1,R1_x2,R1_x2, R1_x1, R1_y1, R1_y1, R1_y2, R1_y2]';
R1 = [3, 4, R1_x1,R1_x2,R1_x2, R1_x1, R1_y1, R1_y1, R1_y2, R1_y2]';
R2 = [3, 4, R2_x1,R2_x2,R2_x2, R2_x1, R2_y1, R2_y1, R2_y2, R2_y2]';
R3 = [3, 4, R3_x1,R3_x2,R3_x2, R3_x1, R3_y1, R3_y1, R3_y2, R3_y2]';
R4 = [3, 4, R4_x1,R4_x2,R4_x2, R4_x1, R4_y1, R4_y1, R4_y2, R4_y2]';
R5 = [3, 4, R5_x1,R5_x2,R5_x2, R5_x1, R5_y1, R5_y1, R5_y2, R5_y2]';
% Ellipse is code 1, center (E1_x,E1_y), First semiaxis length (strictly positive),Second semiaxis length (strictly positive),Angle in radians from x axis to first semiaxis
E1 = [4,E1_xc,E1_yc,E1_a,E1_b,E1_phi]';
E2 = [4,E2_xc,E2_yc,E2_a,E2_b,E2_phi]';
E3 = [4,E3_xc,E3_yc,E3_a,E3_b,E3_phi]';
E4 = [4,E4_xc,E4_yc,E4_a,E4_b,E4_phi]';
% Pad E1 with zeros to enable concatenation with R1
E1 = [E1;zeros(length(R1) - length(E1),1)];
E2 = [E2;zeros(length(R1) - length(E2),1)];
E3 = [E3;zeros(length(R1) - length(E3),1)];
E4 = [E4;zeros(length(R1) - length(E4),1)];
% Combine the shapes into one matrix
geom = [R1,R2,R3,R4,R5,E1,E2,E3,E4];
% Names for the geometric objects
ns = (char('R1','R2','R3','R4','R5','E1','E2','E3','E4'));
ns = ns';
% Set formula
sf = 'R1+R2+R3+R4+R5+E1+E2+E3+E4';
% Create geometry
DL=decsg(geom,sf,ns);
% Check model
% If all elements of 0 geometry is OK
gstat=csgchk(geom);
% Include the geometry in the model
geometryFromEdges(model,DL);
% View geometry
pdegplot(model,'EdgeLabels','on','SubdomainLabels','on')
xlim('auto')
ylim('auto')
axis equal
generateMesh(model,'Hgrad',1.3,'Hmax',10,'Box','on','Init','on','jiggle','on','MesherVersion','R2013a');
pdeplot(model)
Mathwork's support answer that it's a bug of matlab. To fix you need to patch pdeplot:
>>edit pdegplot
edit the line 112
[p1,~,t1]=initmesh(g,'hmax',0.1,'init','on', 'MesherVersion','R2013a');
change it to
[p1,~,t1]=initmesh(g,'init','on', 'MesherVersion','R2013a');
Given a 2x3 matrix x and a 4x2 matrix y, I'd like to use each row of y to index into x. If the value in x is not equal to -1 I'd like to remove that row from y. Here's an example that does what I'd like, except I'd like to do it in a fast, simple way without a loop.
x = [1, 2, 3; -1, 2, -1];
y = [1, 1; 1, 3; 2, 1; 2, 3];
for i=size(y,1):-1:1
if x(y(i,1), y(i,2)) ~= -1
y(i,:) = [];
end
end
This results in:
y =
2 1
2 3
A raw approach to what sub2ind follows (as used by this pretty nice-looking solution posted by Luis) inherently would be this -
y = y(x((y(:,2)-1)*size(x,1)+y(:,1))==-1,:)
Benchmarking
Benchmarking Code
N = 5000;
num_runs = 10000;
x = round(rand(N,N).*2)-1;
y = zeros(N,2);
y(:,1) = randi(size(x,1),N,1);
y(:,2) = randi(size(x,2),N,1);
disp('----------------- With sub2ind ')
tic
for k = 1:num_runs
y1 = y(x(sub2ind(size(x), y(:,1), y(:,2)))==-1,:);
end
toc,clear y1
disp('----------- With raw version of sub2ind ')
tic
for k = 1:num_runs
y2 = y(x((y(:,2)-1)*size(x,1)+y(:,1))==-1,:);
end
toc
Results
----------------- With sub2ind
Elapsed time is 4.095730 seconds.
----------- With raw version of sub2ind
Elapsed time is 2.405532 seconds.
This can be easily vectorized as follows (see sub2ind):
y = y(x(sub2ind(size(x), y(:,1), y(:,2)))==-1,:);
>> x = [1, 2, 3; -1, 2, -1];
>>y = [1, 1;
1, 2;
1, 3;
2, 1;
2, 2;
2, 3];
>>row_idx = reshape((x == -1)',1,6);
>>y = y(row_idx,:);
I think you didn't include all the index of x in y. I included all of them in y. Have a look..
Generalized version:
>> x = [1, 2, 3; -1, 2, -1];
>>y = [1, 1;
1, 2;
1, 3;
2, 1;
2, 2;
2, 3];
>>row_idx = reshape((x == -1)',1,size(x,1)*size(x,2));
>>y = y(row_idx,:);
I'm trying to do some basic arithmetic within a for loop in MatLab.
Basically I want to copy and operate on each element one-by-one. First I want to subtract 3.6: testDataMean from each element, raise each element to the power of 2 then sum up each variable. The finally divide the variable s by 5 (sizeOfTestData)
This should calculate approximately ~1.05.
The testData variable is a 1x5 vector containing the numbers 3, 4, 2, 5, 4
s = 0;
for k = 1:sizeTestData
p = testData(k);
q = p - testDataMean;
r = q^2;
s = s + r;
s/5;
end
This loop actually throws an error on the last line s = s + r. I am aware I can use the sum function in most circumstances when operating on vectors of the same size, but in the context of a for loop I'm not sure.
Note that sum(s) / numel(s) by definition is the same as mean(s).
The loop free approach:
testData = [3, 4, 2, 5, 4]
q = testData - mean(testData);
s = mean(q.^2);
s = 1.0400
The one-liner:
s = mean((testData-mean(testData)).^2)
s = 1.0400
And your initial approach:
(After bug fixing)
testData = [3, 4, 2, 5, 4]
s = 0;
sizeTestData = length(testData);
testDataMean = mean(testData);
for k = 1:sizeTestData
p = testData(k);
q = p - testDataMean;
r = q^2;
s = s + r;
end
s = s / numel(s);
s = 1.0400