Find minimum enclosing circle
19 次查看(过去 30 天)
显示 更早的评论
I am using the function minboundcircle from:
However, it is not finding the absolute edge which is introducing some error. Is there a way I can mitigate the error and find the absolute edge.
Example:
2 个评论
Benjamin Thompson
2022-4-11
Since this is code from a third party author on the File Exchange site, you should ask the author directly. You can post your question to the link on File Exchange above.
John D'Errico
2022-4-11
I cannot know how you used the code, or what you tried to do. So I cannot guess what you did wrong either.
回答(3 个)
Walter Roberson
2022-4-11
Use regionprops() to find the Centroid and PixelList . The circle center goes at the centroid. The maximum distance between the Centroid and the PixelList coordinates defines the radius of the circle.
0 个评论
John D'Errico
2022-4-11
So let me use my own code to solve your problem.
im = imread('IMG_3108.jpg');
[redpixr,redpixc] = find((im(:,:,1) > 140) & (im(:,:,2) < 65) & (im(:,:,3) < 65));
[C,R] = minboundcircle(redpixr,redpixc);
t = linspace(0,2*pi);
X = R*cos(t) + C(1);
Y = R*sin(t) + C(2);
plot(redpixr,redpixc,'b.',X,Y,'r-')
axis equal

Which works fine. Don't forget that the axes there are screwed up as I plotted it, because I used plot, and I plotted pixel coordinates in terms of rows and columns of the original array.
This is probably where your attempt failed. Of course, I'm making only a wild-ass guess here. So you will need to carefully transform the center of that circle back into the correct domain for that image.
3 个评论
Image Analyst
2022-4-11
Here's my code. Looks like it works as expected for me and John. What did you do differently? Did you not use viscircles()???
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
%===============================================================================
% Get the name of the image the user wants to use.
baseFileName = 'IMG_3108.jpg';
folder = pwd;
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
%=======================================================================================
% Read in demo image.
rgbImage = imread(fullFileName);
% Get the dimensions of the image.
[rows, columns, numberOfColorChannels] = size(rgbImage)
% Display image.
subplot(2, 2, 1);
imshow(rgbImage, []);
impixelinfo;
axis on;
caption = sprintf('Original Color Image\n%s', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0.05 1 0.95]);
% Get rid of tool bar and pulldown menus that are along top of figure.
% set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
drawnow;
% Create the mask for the red regions.
[mask, maskedRGBImage1] = createMask(rgbImage);
% Display the color segmentation mask image.
subplot(2, 2, 2);
imshow(mask, []);
title('Color Segmentation Mask Alone', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
axis('on', 'image');
drawnow;
% Now do clean up by hole filling, and getting rid of small blobs.
mask = imfill(mask, 'holes');
mask = bwareafilt(mask, 1); % Take largest blob only.
% Display the color segmentation mask image.
subplot(2, 2, 3);
imshow(mask, []);
title('Final Mask', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
axis('on', 'image');
drawnow;
% Get x and y
boundary = bwboundaries(mask);
x = boundary{1}(:, 2);
y = boundary{1}(:, 1);
subplot(2, 2, 1);
% Get the minimum bounding circle.
hullflag = true;
[center,radius] = minboundcircle(x,y,hullflag)
% Display image.
subplot(2, 2, 4);
imshow(rgbImage, []);
impixelinfo;
axis on;
caption = sprintf('With Boundary and Bounding Circle');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Display boundary
hold on;
plot(x, y, 'b-', 'LineWidth', 4);
% Show circle
viscircles(center, radius, 'color', 'r');
uiwait(helpdlg('Done!'));
function [BW,maskedRGBImage] = createMask(RGB)
%createMask Threshold RGB image using auto-generated code from colorThresholder app.
% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
% auto-generated code from the colorThresholder app. The colorspace and
% range for each channel of the colorspace were set within the app. The
% segmentation mask is returned in BW, and a composite of the mask and
% original RGB images is returned in maskedRGBImage.
% Auto-generated by colorThresholder app on 11-Apr-2022
%------------------------------------------------------
% Convert RGB image to chosen color space
I = rgb2hsv(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.888;
channel1Max = 0.202;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.333;
channel2Max = 1.000;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.000;
channel3Max = 1.000;
% Create mask based on chosen histogram thresholds
sliderBW = ( (I(:,:,1) >= channel1Min) | (I(:,:,1) <= channel1Max) ) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
end

8 个评论
Image Analyst
2022-4-12
Well now we're all confused because you uploaded an image and now you say you're not working with images. Well, anyway, I think we all showed that John's function works.
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!