mg6011
mg6011

Reputation: 43

Stretching an ellipse in an image to form a circle

I want to stretch an elliptical object in an image until it forms a circle. My program currently inputs an image with an elliptical object (eg. coin at an angle), thresholds and binarizes it, isolates the region of interest using edge-detect/bwboundaries(), and performs regionprops() to calculate major/minor axis lengths.

Essentially, I want to use the 'MajorAxisLength' as the diameter and stretch the object on the minor axis to form a circle. Any suggestions on how I should approach this would be greatly appreciated. I have appended some code for your perusal (unfortunately I don't have enough reputation to upload an image, the binarized image looks like a white ellipse on a black background).

EDIT: I'd also like to apply this technique to the gray-scale version of the image, to examine what the stretch looks like.

code snippet:

rgbImage = imread(fullFileName);
redChannel = rgbImage(:, :, 1);
binaryImage = redChannel < 90;
labeledImage = bwlabel(binaryImage);
area_measurements = regionprops(labeledImage,'Area');
allAreas = [area_measurements.Area];
biggestBlobIndex = find(allAreas == max(allAreas));
keeperBlobsImage = ismember(labeledImage, biggestBlobIndex);
measurements = regionprops(keeperBlobsImage,'Area','MajorAxisLength','MinorAxisLength')

Upvotes: 2

Views: 2648

Answers (2)

mg6011
mg6011

Reputation: 43

I finally managed to figure out the transform required thanks to a lot of help on the matlab forums. I thought I'd post it here, in case anyone else needed it.

    stats = regionprops(keeperBlobsImage, 'MajorAxisLength','MinorAxisLength','Centroid','Orientation');
    alpha = pi/180 * stats(1).Orientation;
    Q = [cos(alpha), -sin(alpha); sin(alpha), cos(alpha)];
    x0 = stats(1).Centroid.';
    a = stats(1).MajorAxisLength;
    b = stats(1).MinorAxisLength;
    S = diag([1, a/b]);
    C = Q*S*Q';
    d = (eye(2) - C)*x0;
    tform = maketform('affine', [C d; 0 0 1]');
    Im2 = imtransform(redChannel, tform);
    subplot(2, 3, 5); 
    imshow(Im2);

Upvotes: 0

ely
ely

Reputation: 77404

You know the diameter of the circle and you know the center is the location where the major and minor axes intersect. Thus, just compute the radius r from the diameter, and for every pixel in your image, check to see if that pixel's Euclidean distance from the cirlce's center is less than r. If so, color the pixel white. Otherwise, leave it alone.

[M,N] = size(redChannel);
new_image = zeros(M,N);
for ii=1:M
    for jj=1:N
        if( sqrt((jj-center_x)^2 + (ii-center_y)^2) <= radius )
            new_image(ii,jj) = 1.0;
        end
    end
end

This can probably be optimzed by using the meshgrid function combined with logical indices to avoid the loops.

Upvotes: 1

Related Questions