4
\$\begingroup\$

I have the following MATLAB Code which I want to optimize.
It's related to an image matrix (2D) which I want to filter.
Though it is MATLAB code, the same problem would arise in C code.

The problem is that I'm trying to access neighbors of the pixel which might cause problems at the boundaries of the image matrix.

vWeightsCoeff = zeros((2 * numRows * numCols), 1);
weightsIdx = -3;
% Filteration
for iColIdx = 1:numCols
 for iRowIdx = 1:numRows
 if(mod((iRowIdx + iColIdx), 2) == 0)
 continue;
 end
 weightsIdx = weightsIdx + 4;
 refPixel = mOutputImage(iRowIdx, iColIdx);
 if(iRowIdx < numRows)
 relPixel1 = mOutputImage((iRowIdx + 1), iColIdx);
 relWeight1 = vRangeTable(round((refPixel - relPixel1) * RANGE_RESOLUTION) + RANGE_CENTER_IDX);
 else
 relPixel1 = 0;
 relWeight1 = 0;
 end
 if(iRowIdx > 1)
 relPixel2 = mOutputImage((iRowIdx - 1), iColIdx);
 relWeight2 = vRangeTable(round((refPixel - relPixel2) * RANGE_RESOLUTION) + RANGE_CENTER_IDX);
 else
 relPixel2 = 0;
 relWeight2 = 0;
 end
 if(iColIdx < numCols)
 relPixel3 = mOutputImage(iRowIdx, (iColIdx + 1));
 relWeight3 = vRangeTable(round((refPixel - relPixel3) * RANGE_RESOLUTION) + RANGE_CENTER_IDX);
 else
 relPixel3 = 0;
 relWeight3 = 0;
 end
 if(iColIdx > 1)
 relPixel4 = mOutputImage(iRowIdx, (iColIdx - 1));
 relWeight4 = vRangeTable(round((refPixel - relPixel4) * RANGE_RESOLUTION) + RANGE_CENTER_IDX);
 else
 relPixel4 = 0;
 relWeight4 = 0;
 end
 weightsNormalizationFactor = PREDICT_NORMALIZATION_FACTOR / (relWeight1 + relWeight2 + relWeight3 + relWeight4);
 relWeight1 = relWeight1 * weightsNormalizationFactor;
 relWeight2 = relWeight2 * weightsNormalizationFactor;
 relWeight3 = relWeight3 * weightsNormalizationFactor;
 relWeight4 = relWeight4 * weightsNormalizationFactor;
 mOutputImage(iRowIdx, iColIdx) = mOutputImage(iRowIdx, iColIdx) - ((relWeight1 * relPixel1) + (relWeight2 * relPixel2) + (relWeight3 * relPixel3)+ (relWeight4 * relPixel4));
 vWeightsCoeff(weightsIdx:(weightsIdx + 3)) = [relWeight1; relWeight2; relWeight3; relWeight4];
 end
end

Just to clarify the variables:

  • mOutputImage is the image matrix.
  • numCols and numRows are the matrix dimensions.
  • vWeightsCoeff is the vector of the weights.

Since each pixel is related to 4 others yet working only on half the pixels its size is 2 times the number of pixels.

Now, the questions are:

  1. Can I do something smart to go over the same pixels yet skip the first if which works like dividing the pixels as in chess board (White Black Board)?
  2. Can I do something to avoid the if which secures I'm not stepping out of boundaries and yet go through the same pixels?

If someone comes which a completely different arrangement I will be open for that as well.

asked Jun 14, 2014 at 18:51
\$\endgroup\$
3
  • \$\begingroup\$ Why are you doing the if(mod((iRowIdx + iColIdx), 2) == 0) near the top? Is that part of the filter? Could you describe the filter in words? \$\endgroup\$ Commented Jun 16, 2014 at 19:21
  • \$\begingroup\$ @brechmos, The reason is simple. Think on the matrix as a chessboard, each entry is either white or black. Now, I want to work only on the black / white. This if separates white form black (Or the other way). Thank You. \$\endgroup\$ Commented Jun 16, 2014 at 21:29
  • \$\begingroup\$ What are RANGE_RESOLUTION and PREDICT_NORMALIZATION_FACTOR ? The code doesn't work without the two. \$\endgroup\$ Commented Jul 26, 2016 at 11:38

1 Answer 1

2
\$\begingroup\$

visiting black chess board squares

You might do a mod2 pre-calculation of mod(iRowIdx + iColIdx, 2) by creating a chess board boolean matrix before the loop, using matrix operations.

But much better would be to step iColIdx by 2. And have iRowIdx start at 1 or 2 as appropriate, and then step it by 2.

boundary checking

Your matrix now is C x R. Simply allocate a (C+2) x (R+2) matrix, so you have zeros running along all four sides. Then iterate over just the middle, rather than over the whole matrix as you are now. So iColIdx for example would start at 2 and stop one short of the end.

Doing this will delete a great many ifs, to give you Version2 of the code. You might even find that puts you in a position to produce Version3, which takes advantage of matrix operations instead of scalar operations, pushing much of the looping work down into matlab primitives, which would be faster.

style

It would have been helpful to see the method signature, but your English description that mOutputImage is the only return value worked well enough.

Typo: % Filteration

It would be natural to express the normalization e.g. like this:

 relWeight4 *= weightsNormalizationFactor;

Leave a blank after if, please.

The extra parentheses in mod and places like this:

 relPixel1 = mOutputImage((iRowIdx + 1), iColIdx);

are a little odd, you could safely elide them.

answered Sep 1, 2017 at 18:07
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.