Bubble detection - separate bubbles + connect them with bottomedge + delete inner circl

6 views (last 30 days)
"I have a frame where bubbles are sticking to the bottom of the frame. Then I adjust this frame a bit with the following commands to have better contrast and to distinguish the bubbles better. (if desired, I also added a photo for the same image without bubbles, as I see in the literature that it's best to subtract both photos from each other - however this image has some visual heatwaves)
% Read the frame
frame = imread('CAM1_C001H001S0014001202.png');
% Adjust the image for better contrast
J = imadjust(frame);
% Define the threshold values for Canny Edge Detection
threshold_high = 0.7;
threshold_low = 0.4 * threshold_high;
sigma = sqrt(2);
% Crop the frame
J_cropped = imcrop(J,[0.5 4.5 1023 230]);
% Perform Canny Edge Detection
A = edge(J_cropped, 'canny', [threshold_low, threshold_high], sigma);
% Find the contours in the image
B = bwboundaries(A);
% Determine the bottom of the frame
bottom_frame = size(J_cropped, 1);
% Loop over all contours
for k = 1:length(B)
boundary = B{k};
% Check each point of the contour
for i = 1:size(boundary, 1)
% If the y-coordinate of the point is close to the bottom of the frame
if boundary(i, 1) >= bottom_frame - 1
% Connect this point to the bottom of the frame
boundary(i, 1) = bottom_frame;
end
end
% Save the updated contour
B{k} = boundary;
end
% Plot the original frame with the updated bubbles
figure;
imshow(J_cropped);
hold on;
for k = 1:length(B)
boundary = B{k};
plot(boundary(:, 2), boundary(:, 1), 'r', 'LineWidth', 2);
end
hold off;
This gives the contours of the bubbles. However, at the bottom of the frame, sometimes the left or right contact point of the bubble (such as the bubble all the way to the right) does not touch the bottom of the frame since Matlab does not detect this contour. That contact point thus starts slightly higher than the bottom. Does anyone have an idea how to connect this loose end of the bubble to the bottom of the frame? Furthermore, Matlab also creates some inner circles within the bubbles (bubble 1 and 2) that are not desired - is it possible to remove these? And finally, in bubbles 3-5, you can see that Matlab actually takes 3 bubbles together but does not distinguish between them. Is it possible to connect the top and bottom parts to obtain 3 bubbles?"

Answers (1)

VINAYAK LUHA
VINAYAK LUHA on 12 Jul 2024
Hi Thomas,
I understand that you want to address the following issues in your MATLAB bubble detection workflow:
  • Some bubbles have double boundaries
  • Some bubbles have their ends disconnected from the frame base
  • Some closely located bubbles are detected as a single unit instead of individual bubbles
To improve the results, I preprocessed the given image to detect vertical lines between the bubbles and filled the holes in the shiny parts within the bubbles. This preprocessing step significantly enhanced the results.
Here is the preprocessing code
% Load the image
img = imread('CAM1_C001H001S0014001202.png');
% Convert the image to a binary format
img = ~imbinarize(img);
% Detect edges using the Sobel operator
edges = edge(img, 'sobel');
% Apply the Hough transform to detect lines
[H, T, R] = hough(edges);
% Find peaks in the Hough transform
P = houghpeaks(H, 1000, 'threshold', ceil(0.1 * max(H(:))));
% Extract lines based on the detected peaks
lines = houghlines(edges, T, R, P, 'FillGap', 5, 'MinLength', 3);
% Fill holes in the binary bubble image and modify background
img = imfill(img, 'holes');
img =imclose(img,strel('disk',8));
img =imopen(img,strel('disk',8));
imshow(img);
title('After Pre-Processing')
hold on;
% Initialize an array to store x-coordinates of vertical lines
vertical_lines = [];
% Iterate through the detected lines to find vertical ones
for k = 1:length(lines)
% Get the endpoints of the line
xy = [lines(k).point1; lines(k).point2];
% Calculate the angle of the line
angle = atan2d(diff(xy(:, 2)), diff(xy(:, 1)));
xy(:, 2) = [0, 1024];
if abs(angle) > 80 && abs(angle) < 100
% Store the x-coordinate of the vertical line
vertical_lines = [vertical_lines; xy(1, 1)];
end
end
% Sort the x-coordinates of the vertical lines
vertical_lines = sort(vertical_lines);
goodFilteredLines = [];
% Plot vertical lines that are at least 25 pixels apart
last_x = -inf;
for k = 1:length(vertical_lines)
if vertical_lines(k) - last_x >= 25
goodFilteredLines = [goodFilteredLines, vertical_lines(k)];
last_x = vertical_lines(k);
end
end
% Manually exclude certain false lines from being plotted
% (this step can be avoided by tweaking the line detection parameters appropriately)
for k = 1:length(goodFilteredLines)
if k == 3 || k == 9 || k == 21
continue;
end
plot([goodFilteredLines(k), goodFilteredLines(k)], [0, 1024], 'LineWidth', 1, 'Color', 'k');
end
hold off;
frame = getframe(gca);
capturedImage = frame.cdata;
imgGray = (rgb2gray(capturedImage));
imwrite(imgGray, 'processedImage.png');
Here are the results after preprocessing the image and after applying your algorithm on the preprocessed image:
Hope this helps
Regards,
Vinayak

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!