Question

Greetings Overflowers,

I have a gray image matrix in MatLab and few specific pixel coordinates of that image. I want to calculate the mean and standard deviation of values within a rectangular area in that matrix such that:

  1. it is positioned at an angle (e.g. 0, 45, 90, 135)
  2. it contains all the few pixels
  3. its area is minimum for each angle and its height >= its width

For now I would be happy if I can do so for the vertical, horizontal and both diagonals cases, though I would really appreciate if I can do it for any angle in hand.

Any ideas ?

Was it helpful?

Solution

So, given the input angle theta, and bunch of coordinates points, you want the minimum enclosing rectangle at that angle (what does that mean? -- the height axis is set at that angle? the width axis? And angle from vertical-clockwise (like headings) or horizontal-anticlockwise (like maths)?). Further more, we adjust the height so that it's >= the width.

In that case, I think the following might work:

  1. Convert the coordinates into a new coordinate system which is just the x-y axis rotated by angle theta (use a rotation matrix for this)
  2. Find the minimum enclosing rectangle in this coordinate system: this is now just finding the minimum enclosing rectangle in the horizontal-vertical dimensions (so we don't need to worry about theta any more since we've already transformed the coordinates)
  3. Make sure the minimum enclosing rectangle has height >= width
  4. Convert the rectangle back to the original coordinate system (rotate it back by theta).
  5. Use these coordinates to calculate mean/stddev.

Something like this could work (untested), tweak to your desire:

% pts is 2xn
% theta is in degrees, anticlockwise from horizontal.
% returns 2xn matrix of indices into the min enclosing rectangle.
function minClosingRect = calcMinEnclosingRect( pts, theta )
    % convert to radians and rotate by theta degrees ANTICLOCKWISE
    thRad  = theta*pi/180;
    rotMat = [ cos(thRad) -sin(thRad); sin(thRad) cos(thRad) ];

    ptsRot = rotMat * pts;

    % find minimum enclosing rectangle of ptsRot
    %  in the horizontal-vertical direction
    % this is just min/max coords.
    minX = min(ptsRot(1,:));
    maxX = min(ptsRot(1,:));
    minY = min(ptsRot(2,:));
    maxY = max(ptsRot(2,:));

    % make sure height >= width
    if (maxY-minY)<(maxX-minX)
        % NOTE: depending on how you want you can extend
        % - out the bottom
        % - the top
        % - centred (etc)
        % e.g. to make the rectangle taller out the bottom
        minY = maxY - (maxX-minX);
    end

    % construct indices into rectangle
    [X Y] = meshgrid( minX:maxX, minY:maxY )


    % convert indices back by rotating thRad degrees backwards.
    rotMatInv = [ cos(-thRad) -sin(-thRad); sin(-thRad) cos(-thRad) ];
    minClosingRect = rotMatInv * [X(:) Y(:)]';

Then use it like this (the one caveat is X/Y vs i/j):

minClosingRect = calcMinEnclosingRect( pts, theta );
mean2( Img(minClosingRect) )
std2(  Img(minClosingRect) )
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top