Search code examples
matlabgraphicsrasterstandard-deviation

Calculate the Mean and Standard Deviation


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 ?


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) )