MATLAB Answers

Identifying the circle that fits the outer white pixels in a binary image (or make external mask)

4 views (last 30 days)
Dyhia Bouhadjra
Dyhia Bouhadjra on 27 Mar 2020
Edited: Dyhia Bouhadjra on 1 Apr 2020
Hi all,
I want to process a series of images similar to the attached one in order to measure their porosities: V_pores / V_total. For my case, in a 2D context, V_total is the surface of circle containing all pores. It is important to know that the radius and center of the circle changes, and also many circular shapes can be identified in between, however, I am only interested, at this moment, in measuring the general surface of the circle (Vt).
Alernatively, I would be interested in applying a mask to the image. But it seems to be more difficult.
Any help would be appreciated. Many thanks.

  0 Comments

Sign in to comment.

Accepted Answer

KSSV
KSSV on 27 Mar 2020
I = imread("SampleXRmorph.PNG");
[y,x] = find(I) ;
% Get center of cricle
C = [mean(x) mean(y)] ;
% GEt raidus
d = sqrt((C(1)-x).^2+(C(2)-y).^2) ;
R = max(d) ;
% plot circle
th = linspace(0,2*pi) ;
xc = C(1)+R*cos(th) ;
yc = C(2)+R*sin(th) ;
%
imshow(I)
hold on
plot(xc,yc,'r')

  9 Comments

Show 6 older comments
Dyhia Bouhadjra
Dyhia Bouhadjra on 28 Mar 2020
Yeah, this works but not for a series of pics. I may wotk on it if needed. However,
[idx area] = boundary(x,y) ;
works very well, this is what I need, a contour and the surface of it. We'll keep in touch for future troubles xD. Thank you KSSV ^_^
Dyhia Bouhadjra
Dyhia Bouhadjra on 29 Mar 2020
Hi Again,
Following the previous question, and after identification of the boundary of the images, I've calculated the surface of the circle, however I don't know how to calculate the surface of black pixels inside the boundary circel.
To measure the surface of the white pixels I did:
A=imread('moreQuestion.png');
A=dounle(A);
[x,y]=find(A);
[idx Surf]=boundary(x,y); %this will allow drowing the boundary circle as mentioned above.
%Surf is the area of the circle.
Sw=sum(sum(A)); % surface of white pixels
Sb=sum(sum(~A)); %surface of the total black pixels.
Sb1= ? %The black pixels' surface incide the circle
%One may say: Sb1=Surf-Sw; but it's negative and shouldn't be!!
Do you please have an idea of how to do it?

Sign in to comment.

More Answers (1)

Image Analyst
Image Analyst on 29 Mar 2020
Edited: Image Analyst on 29 Mar 2020
Sorry I didn't see this earlier, but anyway...
How I'd solve it is
  1. Use bwconvhull() to get a convex hull of all the blobs.
  2. Uuse imerode() to shrink that a certain amount to get a smaller circular blob.
  3. Use the eroded image to erase every blob in the interior so you have only the outer blobs.
  4. If you need a perfect circle, call regionprops(mask, 'Centroid') to get a list of (x,y) coordinates.
  5. Use the FAQ to fit a circle through the centroids.
% Initialization steps.
clc; % Clear the command window.
fprintf('Beginning to run %s.m ...\n', mfilename);
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format short g;
format compact;
fontSize = 15;
mask = imread('morequestion.png');
imshow(mask);
if ndims(mask) > 2
mask = mask(:, :, 1); % Take red channel
end
mask2 = bwconvhull(mask, 'union');
se = strel('disk', 20, 0);
smallMask = imerode(mask2, se);
mask3 = mask & ~smallMask;
props = regionprops(mask3, 'Centroid');
xy = vertcat(props.Centroid);
x = xy(:, 1);
y = xy(:, 2);
[xc,yc,R,a] = circfit(x,y);
viscircles([xc, yc], R);
fprintf('Done running %s.m ...\n', mfilename);
function [xc,yc,R,a] = circfit(x,y)
%CIRCFIT Fits a circle in x,y plane
%
% [XC, YC, R, A] = CIRCFIT(X,Y)
% Result is center point (yc,xc) and radius R. A is an optional
% output describing the circle's equation:
%
% x^2+y^2+a(1)*x+a(2)*y+a(3)=0
% by Bucher izhak 25/oct/1991
n=length(x); xx=x.*x; yy=y.*y; xy=x.*y;
A=[sum(x) sum(y) n;sum(xy) sum(yy) sum(y);sum(xx) sum(xy) sum(x)];
B=[-sum(xx+yy) ; -sum(xx.*y+yy.*y) ; -sum(xx.*x+xy.*y)];
a=A\B;
xc = -.5*a(1);
yc = -.5*a(2);
R = sqrt((a(1)^2+a(2)^2)/4-a(3));
end
Adapt as needed.

  5 Comments

Show 2 older comments
Dyhia Bouhadjra
Dyhia Bouhadjra on 30 Mar 2020
Dear Image Analyst, thank you indeed for this complete answer. Your example will serve me to solve other issues I had. To make my question more clear, I tried to make this figure:
Figure (a) is the original image. Figure (b) is after application of bwmorph and [idx, area]=boundary(x,y), after which I could’ve plot the contour circle, and have itssurface. I believe the surface of white spaceherecanbecalculated by sum(sum(bw)) (is it correct?). Now, I want to measure the area of black pixels. Figure (c) is showing the result of using bwperim. Let’s say that what I meant by measuring the surface of black pixels is to measure the sum of its surfaces as shown in fig(c).
After measuring this area (white and black spaces within the circle), I'll see if I need to smooth the circle or not.
PS to everyone: I deleted the attached images because of confidentiality issues, but I will make instead a figure that explains the whole exchange. Also, I'll promise to summarize the whole thing when I finish. ^_^
Thnak you in advance
Image Analyst
Image Analyst on 31 Mar 2020
To get the area of the white in the mask, I'd do
numWhitePixels = nnz(mask)
% Now to get the area of the holes
holesImage = imclearborder(~mask);
imshow(holesImage);
numHolePixels = nnz(holesImage)
Dyhia Bouhadjra
Dyhia Bouhadjra on 1 Apr 2020
This works pretty well. Thabk you for the help, and keep in touch for future exchange.
Keep safe and happy confinement ^^

Sign in to comment.

Sign in to answer this question.