Contact angle in a video of a sessile droplet
Hey all
Okay so i have this script to analyze videos of single droplets drying now i want to calculate the contact angles using the script i made which is also attachted but the method i am using now results in results that are not consistent and jaggery so do any of you have suggestions on how to improve the contact angle determination, i think it could also have something to do with how we binarize and determine the edge of the droplet? normally the script processes videos of around 30s at 100 fps but i couldnt attach that so here is a very short sample video. here is the code that calculates the contact angle
%binary image creation
backgroundDiff = abs(double(grayFrame) – averageBackground);
    % threshold
binaryImage = backgroundDiff > backgroundThreshold;
    % morphological operations to preserve droplet
cleanedImage = imopen(binaryImage, strel(‘disk’, morphOpenDiskSize));
cleanedImage = imclose(cleanedImage, strel(‘disk’, morphCloseDiskSize));
filledImage = imfill(cleanedImage, ‘holes’);
dropletOutsideSurface = filledImage & ~surfaceMask_logical;
dropletAll = filledImage;
% Find droplet boundary
dropletBoundary = bwboundaries(dropletMask);
if ~isempty(dropletBoundary)
outline = dropletBoundary{1};
x_outline = outline(:,2); % Column indices (x-coordinates)
y_outline = outline(:,1); % Row indices (y-coordinates)
            if numel(x_outline) >= 20 % Need sufficient points
% Convert to physical coordinates (meters)
x_phys = x_outline * scale_Image * 1e-6;
y_phys = y_outline * scale_Image * 1e-6;
                % Find contact points (points near the surface)
surface_y_phys = minYSurface * scale_Image * 1e-6;
contact_threshold = equiv_radius * 0.3; % 30% of droplet radius
                % Find all points near the surface
near_surface_indices = find(abs(y_phys – surface_y_phys) < contact_threshold);
                if length(near_surface_indices) >= 4
% Find the leftmost and rightmost contact points
x_contact = x_phys(near_surface_indices);
y_contact = y_phys(near_surface_indices);
                    [x_min, left_idx] = min(x_contact);
[x_max, right_idx] = max(x_contact);
                    left_contact_point = [x_min, y_contact(left_idx)];
right_contact_point = [x_max, y_contact(right_idx)];
                    % ADVANCED: Calculate contact angles using tangent method (from original)
tangent_range = equiv_radius * 0.2; % Distance for tangent calculation
                    % LEFT CONTACT ANGLE
left_contact_idx = near_surface_indices(left_idx);
distances_from_left = sqrt((x_phys – left_contact_point(1)).^2 + …
(y_phys – left_contact_point(2)).^2);
tangent_indices_left = find(distances_from_left <= tangent_range & …
distances_from_left > 0);
                    if length(tangent_indices_left) >= 3
above_contact = tangent_indices_left(y_phys(tangent_indices_left) < left_contact_point(2));
if length(above_contact) >= 3
x_fit = x_phys(above_contact);
y_fit = y_phys(above_contact);
[x_fit, sort_idx] = sort(x_fit);
y_fit = y_fit(sort_idx);
                            if length(unique(x_fit)) >= 2 && length(x_fit) >= 2
try
p_left = polyfit(x_fit, y_fit, 1);
slope_left = p_left(1);
catch
slope_left = NaN;
end
else
slope_left = NaN;
end
                            if ~isnan(slope_left)
angle_rad_left = atan(slope_left);
contact_angle_left = 180 – rad2deg(angle_rad_left);
if contact_angle_left < 0
contact_angle_left = contact_angle_left + 180;
elseif contact_angle_left > 180
contact_angle_left = contact_angle_left – 180;
end
end
end
end
                    % RIGHT CONTACT ANGLE (similar process)
right_contact_idx = near_surface_indices(right_idx);
distances_from_right = sqrt((x_phys – right_contact_point(1)).^2 + …
(y_phys – right_contact_point(2)).^2);
tangent_indices_right = find(distances_from_right <= tangent_range & …
distances_from_right > 0);
                    if length(tangent_indices_right) >= 3
above_contact = tangent_indices_right(y_phys(tangent_indices_right) < right_contact_point(2));
if length(above_contact) >= 3
x_fit = x_phys(above_contact);
y_fit = y_phys(above_contact);
[x_fit, sort_idx] = sort(x_fit);
y_fit = y_fit(sort_idx);
                            if length(unique(x_fit)) >= 2 && length(x_fit) >= 2
try
p_right = polyfit(x_fit, y_fit, 1);
slope_right = p_right(1);
catch
slope_right = NaN;
end
else
slope_right = NaN;
end
                            if ~isnan(slope_right)
angle_rad_right = atan(slope_right);
contact_angle_right = rad2deg(angle_rad_right);
if contact_angle_right < 0
contact_angle_right = contact_angle_right + 180;
elseif contact_angle_right > 180
contact_angle_right = contact_angle_right – 180;
end
end
end
end
                    % Calculate average contact angle
if ~isnan(contact_angle_left) && ~isnan(contact_angle_right)
contact_angle_avg = (contact_angle_left + contact_angle_right) / 2;
elseif ~isnan(contact_angle_left)
contact_angle_avg = contact_angle_left;
elseif ~isnan(contact_angle_right)
contact_angle_avg = contact_angle_right;
end
end
end
endHey all
Okay so i have this script to analyze videos of single droplets drying now i want to calculate the contact angles using the script i made which is also attachted but the method i am using now results in results that are not consistent and jaggery so do any of you have suggestions on how to improve the contact angle determination, i think it could also have something to do with how we binarize and determine the edge of the droplet? normally the script processes videos of around 30s at 100 fps but i couldnt attach that so here is a very short sample video. here is the code that calculates the contact angle
%binary image creation
backgroundDiff = abs(double(grayFrame) – averageBackground);
    % threshold
binaryImage = backgroundDiff > backgroundThreshold;
    % morphological operations to preserve droplet
cleanedImage = imopen(binaryImage, strel(‘disk’, morphOpenDiskSize));
cleanedImage = imclose(cleanedImage, strel(‘disk’, morphCloseDiskSize));
filledImage = imfill(cleanedImage, ‘holes’);
dropletOutsideSurface = filledImage & ~surfaceMask_logical;
dropletAll = filledImage;
% Find droplet boundary
dropletBoundary = bwboundaries(dropletMask);
if ~isempty(dropletBoundary)
outline = dropletBoundary{1};
x_outline = outline(:,2); % Column indices (x-coordinates)
y_outline = outline(:,1); % Row indices (y-coordinates)
            if numel(x_outline) >= 20 % Need sufficient points
% Convert to physical coordinates (meters)
x_phys = x_outline * scale_Image * 1e-6;
y_phys = y_outline * scale_Image * 1e-6;
                % Find contact points (points near the surface)
surface_y_phys = minYSurface * scale_Image * 1e-6;
contact_threshold = equiv_radius * 0.3; % 30% of droplet radius
                % Find all points near the surface
near_surface_indices = find(abs(y_phys – surface_y_phys) < contact_threshold);
                if length(near_surface_indices) >= 4
% Find the leftmost and rightmost contact points
x_contact = x_phys(near_surface_indices);
y_contact = y_phys(near_surface_indices);
                    [x_min, left_idx] = min(x_contact);
[x_max, right_idx] = max(x_contact);
                    left_contact_point = [x_min, y_contact(left_idx)];
right_contact_point = [x_max, y_contact(right_idx)];
                    % ADVANCED: Calculate contact angles using tangent method (from original)
tangent_range = equiv_radius * 0.2; % Distance for tangent calculation
                    % LEFT CONTACT ANGLE
left_contact_idx = near_surface_indices(left_idx);
distances_from_left = sqrt((x_phys – left_contact_point(1)).^2 + …
(y_phys – left_contact_point(2)).^2);
tangent_indices_left = find(distances_from_left <= tangent_range & …
distances_from_left > 0);
                    if length(tangent_indices_left) >= 3
above_contact = tangent_indices_left(y_phys(tangent_indices_left) < left_contact_point(2));
if length(above_contact) >= 3
x_fit = x_phys(above_contact);
y_fit = y_phys(above_contact);
[x_fit, sort_idx] = sort(x_fit);
y_fit = y_fit(sort_idx);
                            if length(unique(x_fit)) >= 2 && length(x_fit) >= 2
try
p_left = polyfit(x_fit, y_fit, 1);
slope_left = p_left(1);
catch
slope_left = NaN;
end
else
slope_left = NaN;
end
                            if ~isnan(slope_left)
angle_rad_left = atan(slope_left);
contact_angle_left = 180 – rad2deg(angle_rad_left);
if contact_angle_left < 0
contact_angle_left = contact_angle_left + 180;
elseif contact_angle_left > 180
contact_angle_left = contact_angle_left – 180;
end
end
end
end
                    % RIGHT CONTACT ANGLE (similar process)
right_contact_idx = near_surface_indices(right_idx);
distances_from_right = sqrt((x_phys – right_contact_point(1)).^2 + …
(y_phys – right_contact_point(2)).^2);
tangent_indices_right = find(distances_from_right <= tangent_range & …
distances_from_right > 0);
                    if length(tangent_indices_right) >= 3
above_contact = tangent_indices_right(y_phys(tangent_indices_right) < right_contact_point(2));
if length(above_contact) >= 3
x_fit = x_phys(above_contact);
y_fit = y_phys(above_contact);
[x_fit, sort_idx] = sort(x_fit);
y_fit = y_fit(sort_idx);
                            if length(unique(x_fit)) >= 2 && length(x_fit) >= 2
try
p_right = polyfit(x_fit, y_fit, 1);
slope_right = p_right(1);
catch
slope_right = NaN;
end
else
slope_right = NaN;
end
                            if ~isnan(slope_right)
angle_rad_right = atan(slope_right);
contact_angle_right = rad2deg(angle_rad_right);
if contact_angle_right < 0
contact_angle_right = contact_angle_right + 180;
elseif contact_angle_right > 180
contact_angle_right = contact_angle_right – 180;
end
end
end
end
                    % Calculate average contact angle
if ~isnan(contact_angle_left) && ~isnan(contact_angle_right)
contact_angle_avg = (contact_angle_left + contact_angle_right) / 2;
elseif ~isnan(contact_angle_left)
contact_angle_avg = contact_angle_left;
elseif ~isnan(contact_angle_right)
contact_angle_avg = contact_angle_right;
end
end
end
end Hey all
Okay so i have this script to analyze videos of single droplets drying now i want to calculate the contact angles using the script i made which is also attachted but the method i am using now results in results that are not consistent and jaggery so do any of you have suggestions on how to improve the contact angle determination, i think it could also have something to do with how we binarize and determine the edge of the droplet? normally the script processes videos of around 30s at 100 fps but i couldnt attach that so here is a very short sample video. here is the code that calculates the contact angle
%binary image creation
backgroundDiff = abs(double(grayFrame) – averageBackground);
    % threshold
binaryImage = backgroundDiff > backgroundThreshold;
    % morphological operations to preserve droplet
cleanedImage = imopen(binaryImage, strel(‘disk’, morphOpenDiskSize));
cleanedImage = imclose(cleanedImage, strel(‘disk’, morphCloseDiskSize));
filledImage = imfill(cleanedImage, ‘holes’);
dropletOutsideSurface = filledImage & ~surfaceMask_logical;
dropletAll = filledImage;
% Find droplet boundary
dropletBoundary = bwboundaries(dropletMask);
if ~isempty(dropletBoundary)
outline = dropletBoundary{1};
x_outline = outline(:,2); % Column indices (x-coordinates)
y_outline = outline(:,1); % Row indices (y-coordinates)
            if numel(x_outline) >= 20 % Need sufficient points
% Convert to physical coordinates (meters)
x_phys = x_outline * scale_Image * 1e-6;
y_phys = y_outline * scale_Image * 1e-6;
                % Find contact points (points near the surface)
surface_y_phys = minYSurface * scale_Image * 1e-6;
contact_threshold = equiv_radius * 0.3; % 30% of droplet radius
                % Find all points near the surface
near_surface_indices = find(abs(y_phys – surface_y_phys) < contact_threshold);
                if length(near_surface_indices) >= 4
% Find the leftmost and rightmost contact points
x_contact = x_phys(near_surface_indices);
y_contact = y_phys(near_surface_indices);
                    [x_min, left_idx] = min(x_contact);
[x_max, right_idx] = max(x_contact);
                    left_contact_point = [x_min, y_contact(left_idx)];
right_contact_point = [x_max, y_contact(right_idx)];
                    % ADVANCED: Calculate contact angles using tangent method (from original)
tangent_range = equiv_radius * 0.2; % Distance for tangent calculation
                    % LEFT CONTACT ANGLE
left_contact_idx = near_surface_indices(left_idx);
distances_from_left = sqrt((x_phys – left_contact_point(1)).^2 + …
(y_phys – left_contact_point(2)).^2);
tangent_indices_left = find(distances_from_left <= tangent_range & …
distances_from_left > 0);
                    if length(tangent_indices_left) >= 3
above_contact = tangent_indices_left(y_phys(tangent_indices_left) < left_contact_point(2));
if length(above_contact) >= 3
x_fit = x_phys(above_contact);
y_fit = y_phys(above_contact);
[x_fit, sort_idx] = sort(x_fit);
y_fit = y_fit(sort_idx);
                            if length(unique(x_fit)) >= 2 && length(x_fit) >= 2
try
p_left = polyfit(x_fit, y_fit, 1);
slope_left = p_left(1);
catch
slope_left = NaN;
end
else
slope_left = NaN;
end
                            if ~isnan(slope_left)
angle_rad_left = atan(slope_left);
contact_angle_left = 180 – rad2deg(angle_rad_left);
if contact_angle_left < 0
contact_angle_left = contact_angle_left + 180;
elseif contact_angle_left > 180
contact_angle_left = contact_angle_left – 180;
end
end
end
end
                    % RIGHT CONTACT ANGLE (similar process)
right_contact_idx = near_surface_indices(right_idx);
distances_from_right = sqrt((x_phys – right_contact_point(1)).^2 + …
(y_phys – right_contact_point(2)).^2);
tangent_indices_right = find(distances_from_right <= tangent_range & …
distances_from_right > 0);
                    if length(tangent_indices_right) >= 3
above_contact = tangent_indices_right(y_phys(tangent_indices_right) < right_contact_point(2));
if length(above_contact) >= 3
x_fit = x_phys(above_contact);
y_fit = y_phys(above_contact);
[x_fit, sort_idx] = sort(x_fit);
y_fit = y_fit(sort_idx);
                            if length(unique(x_fit)) >= 2 && length(x_fit) >= 2
try
p_right = polyfit(x_fit, y_fit, 1);
slope_right = p_right(1);
catch
slope_right = NaN;
end
else
slope_right = NaN;
end
                            if ~isnan(slope_right)
angle_rad_right = atan(slope_right);
contact_angle_right = rad2deg(angle_rad_right);
if contact_angle_right < 0
contact_angle_right = contact_angle_right + 180;
elseif contact_angle_right > 180
contact_angle_right = contact_angle_right – 180;
end
end
end
end
                    % Calculate average contact angle
if ~isnan(contact_angle_left) && ~isnan(contact_angle_right)
contact_angle_avg = (contact_angle_left + contact_angle_right) / 2;
elseif ~isnan(contact_angle_left)
contact_angle_avg = contact_angle_left;
elseif ~isnan(contact_angle_right)
contact_angle_avg = contact_angle_right;
end
end
end
end image processing, image analysis MATLAB Answers — New Questions











