Can this piece of matlab script be vectorized further?
So what I am trying to do with this code is find all pixels on a line of an image that are below a certain threshold. The problem, however, is that this code is executed in a double for loop (yeah I know :( ), once for each pixel, so it's very slow. I'm wondering if there's anything else I can do.
Some tips would be great, as I'm pretty new to MATLAB optimization, and I know only the basics (try not to use loops, or call scripts many times in inner functions, etc). If this doesn't work out, I might have to resort to MEX files, and that'll be harder to maintain for the other researchers in my group. Thank you!
for y = 1:y_len
for x = 1:x_len
%//...do stuff to calc slope and offset for the line,
%//this can be vectorized pretty easily.
yIndices = xIndices.*slope + offset;
yIndices = round(yIndices);
yIndices = yIndices + 1;
xIndices = xIndices + 1;
valid_points = (yIndices <= 308) & (yIndices > 0);
%this line is bottle necking----------------------------------------
valid_points = yIndices(valid_points)+(xIndices(valid_points)-1)*308;
%-------------------------------------------------------------------
valid_points = valid_points(phaseMask_R(valid_points));
t_vals = abs(phase_R(valid_points)-currentPhase);
point_vals = [XsR(valid_points);YsR(valid_points)] - 1;
matchedPtsCoordsR = point_vals(:,(t_vals<phaseThreshold) |(abs(192-t_vals)<phaseThreshold));
matchedIndex = size(matchedPtsCoordsR,2);
if(matchedIndex ==0)
continue
end
centersMinMaxR = zeros(1,matchedIndex);
cmmIndexR = 1;
for a = 1:matchedInde开发者_开发知识库x;
if(a==1)
avgPosition = matchedPtsCoordsR(:,a);
centersMinMaxR(1,1) =1;
else
currentPosition = matchedPtsCoordsR(:,a);
%also very slow----------------------------------------------
distance = sum(abs(currentPosition-avgPosition));
%------------------------------------------------------------
if(distance>4) % We are now likely in a different segment.
centersMinMaxR(2,cmmIndexR) = a-1;
cmmIndexR = cmmIndexR + 1;
centersMinMaxR(1,cmmIndexR) = a;
end
avgPosition = matchedPtsCoordsR(:,a);
end
end
centersMinMaxR(2,cmmIndexR) = a;
centersR = round(sum(centersMinMaxR)/2);
%//...do stuff with centersR
%//I end up concatenating all the centersR into a
%//large vector arrray with the start and end of
%//each segment.
First off, MatLab Profiler is your best friend and it I assume you know about it because you know what line is bottle necking.
A quick fix to remove the double loop is to use the :
command. Instead of using a double loop, you can use a single loop but calculate along an entire dimension for each row or column index. For a simple example:
m = magic(2);
slope = 5;
m =
1 3
4 2
m(1,:) * slope =
5 15
m(:,1) * slope =
5
20
Instead of using jagged arrays, use sparse arrays. Matlab has built-in support for them:
Matlab Create Sparse Array
Matlab Sparse Matrix Operations
UPDATE
In regard to the pro-cons of using a sparse vs normal array: Sparse vs Normal Array Matlab
Sparse matrices are a true boon for the person who uses truly sparse matrices, but 25% non-zeros is simply not "sparse" enough for any gain in most cases.
Look for more updates as I have more time to review your code :p
精彩评论