Digital Image Processing: Determine the area for no perfectly round circles
3 views (last 30 days)
Show older comments
Hey MathWorks Community,
it is the first time, I am doing digital image processing with MatLab. Aim of work is to extract an area of a figure. Therefore a camera films a little tank from above (1024x1024 px,100 Hz). At t = 0 s a stone is thrown near the center of the image, so that a wave propagetes through the water. The first problem I have is finding the real center with image processing because the stone does not reach the real center. In addition the stone disturbes not just one px but almost an area 12x12 px. The next step is to get a value of the circle's area. The problem here is that "imfindcircles" does not find any circles because there is no steady movement of the propagating wave, so that the radius differs for various angles (using polarcoordinates). What I acutally did is to import the image and converted it from greylevel to a bw picture. In this picture I filled the not perfectly round circle black. The outter area remains white. So there is a matrix A (1024x1024) filled with ones and zeros.
My idea now is to find the outter ring of the wave by image processing and get it in a mathematical function in polarcoordinates. With any optimization, regarding the value of the area, there might be a mean radius that fits the area best and I can find the real center of the wave.
Can you help me by finding some helpful commands or functions that I can solve the problem by myself? Or might it be to difficult for a newbe to solve this?
Thanks for Your help and have a really nice weekend, Christian
5 Comments
Image Analyst
on 23 Aug 2024
Uh, we meant the original gray scale image, not the already-binarized images. Well anyway, since it's been over 8 years ago, I guess you figured it out.
Answers (1)
Vidhi Agarwal
on 23 Aug 2024
Edited: Vidhi Agarwal
on 23 Aug 2024
Hi Christian,
I understand you are facing a query regarding finding the real center, extracting the wave’s outer ring, and fitting a circular model. Following are approaches for the same that might help you in solving the problem:
- In case of finding the real center using morphological operation to clean the binary image will be helpful. Functions like “imdilate” and “imerode” can help refine the binary image and using “regionprops” function to find the centroid of the largest connected component, which can help estimate the center of the wave.
- For extracting wave’s outer ring edge detection techniques can be used to find the boundary of the wave. Functions like “edge” with methods such as 'Canny', 'Sobel', or 'Prewitt' can be useful. Once you have the edges, you can use “bwboundaries” to extract the contour of the detected edges.
- Least Squares Circle Fit: Try fitting a circle to the boundary points using a least squares approach. This involves minimizing the distance between the boundary points and a circle equation.
- Optimization: Use the “fminsearch” or “lsqcurvefit” functions to optimize the circle parameters (center and radius) based on the extracted boundary points.
Here’s is the sample code for provided image.
% Load your image
A = imread('fin.jpg');
% Convert to grayscale if necessary
if size(A, 3) == 3
A_gray = rgb2gray(A);
else
A_gray = A;
end
% Convert to binary image
A_bw = imbinarize(A_gray);
% Clean up the binary image using morphological operations
A_bw = imopen(A_bw, strel('disk', 5)); % Remove noise
A_bw = imclose(A_bw, strel('disk', 5)); % Close gaps in edges
% Detect edges
edges = edge(A_bw, 'Canny');
% Find connected components
CC = bwconncomp(edges);
% Measure properties of image regions
stats = regionprops(CC, 'Centroid', 'Area');
% Find the largest component
[~, idx] = max([stats.Area]);
center = stats(idx).Centroid;
% Extract boundary of the largest component
boundary = bwboundaries(edges);
largest_boundary = boundary{idx};
% Fit a circle to the boundary points
x = largest_boundary(:, 2);
y = largest_boundary(:, 1);
circle_params = untitled2([x, y]); % Fit circle
% Extract circle parameters
fitted_center = circle_params(1:2);
fitted_radius = abs(real(circle_params(3))); % Ensure radius is real and non-negative
% Display results
imshow(A_gray);
hold on;
plot(center(1), center(2), 'r+', 'MarkerSize', 15, 'LineWidth', 2); % Original center
% Validate radius before plotting
if isreal(fitted_radius) && fitted_radius > 0
viscircles(fitted_center, fitted_radius, 'EdgeColor', 'b'); % Fitted circle
else
warning('Fitted radius is not valid. Circle will not be drawn.');
end
title('Detected Center and Fitted Circle of the Wave');
%%function untitled2
function circle_params = untitled2(XY)
% untitled2 - Fits a circle to a set of 2D points using Pratt's method
% XY is an Nx2 matrix of 2D points
% circle_params is a 1x3 vector [center_x, center_y, radius]
x = XY(:,1);
y = XY(:,2);
centroid = mean(XY);
x = x - centroid(1);
y = y - centroid(2);
Z = x.^2 + y.^2;
ZXY = [Z, x, y, ones(size(x))];
M = ZXY' * ZXY;
[V, D] = eig(M);
[~, idx] = min(diag(D));
A = V(:, idx);
a = A(2) / 2;
b = A(3) / 2;
c = A(4);
radius = sqrt((a^2 + b^2) - c);
circle_params = [a + centroid(1), b + centroid(2), radius];
end
For detailed understanding of functions “imdilate”, “imerode”, “regionprops”, “edge” and “bwboundaries”, refer to the following documentation:
- https://www.mathworks.com/help/images/ref/imdilate.html
- https://www.mathworks.com/help/images/ref/imerode.html
- https://www.mathworks.com/help/images/ref/regionprops.html
- https://www.mathworks.com/help/images/ref/edge.html
- https://www.mathworks.com/help/images/ref/bwboundaries.html
To understand the usage of “lsqcurvefit” refer to following MATLAB answer:
Hope that Helps.
1 Comment
Image Analyst
on 23 Aug 2024
% Load your image
A = imread('fin.JPG');
% Convert to grayscale if necessary
if size(A, 3) == 3
A_gray = rgb2gray(A);
else
A_gray = A;
end
% Convert to binary image
A_bw = imbinarize(A_gray);
% Clean up the binary image using morphological operations
A_bw = imopen(A_bw, strel('disk', 5)); % Remove noise
A_bw = imclose(A_bw, strel('disk', 5)); % Close gaps in edges
% Detect edges
edges = edge(A_bw, 'Canny');
% Find connected components
CC = bwconncomp(edges);
% Measure properties of image regions
stats = regionprops(CC, 'Centroid', 'Area');
% Find the largest component
[~, idx] = max([stats.Area]);
center = stats(idx).Centroid;
% Extract boundary of the largest component
boundary = bwboundaries(edges);
largest_boundary = boundary{idx};
% Fit a circle to the boundary points
x = largest_boundary(:, 2);
y = largest_boundary(:, 1);
circle_params = untitled2([x, y]); % Fit circle
% Extract circle parameters
fitted_center = circle_params(1:2);
fitted_radius = abs(real(circle_params(3))); % Ensure radius is real and non-negative
% Display results
imshow(A_gray);
hold on;
plot(center(1), center(2), 'r+', 'MarkerSize', 15, 'LineWidth', 2); % Original center
% Validate radius before plotting
if isreal(fitted_radius) && fitted_radius > 0
viscircles(fitted_center, fitted_radius, 'EdgeColor', 'b'); % Fitted circle
else
warning('Fitted radius is not valid. Circle will not be drawn.');
end
title('Detected Center and Fitted Circle of the Wave');
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!