How to measure crack width

45 Ansichten (letzte 30 Tage)
yasmin ismail
yasmin ismail am 7 Mär. 2023
Beantwortet: yasmin ismail am 2 Jun. 2023 um 13:11
I noticed that when I reduced the minimum acceptable area the crack width decreased although the appearance of blobs in this situation, while when i increased minimum acceptable area and the blobs removed and the width increased
for example:
clc; % Clear the command window.
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 long g;
format compact;
fontSize = 10;
% Read in image and convert to gray scale.
rgbImage = imread('7004-46.jpg');
I = rgb2gray(rgbImage);
subplot(2,2,1);
imshow(I);
title('7004-46');
% Take histogram.
subplot(2,2,2);
histogram(I);
grid on; %to make grid line
title('histogram Gray image');
% Binarize image.
threshold = 145;
xline(threshold, 'Color', 'r', 'LineWidth',2)
mask=I < threshold;
mask = imfill(mask, 'holes');
% Filter image.
se = strel('line',1, 0);
filteredImage = imclose(mask, se);
subplot(2, 2, 3);
imshow(filteredImage);
title('closed Image');
%%% Measure the areas to determin minAcceptableArea show the histogram of
%%% area
% props = regionprops(filteredImage, 'Area');
% allAreas = sort([props.Area], 'descend');
% histogram(allAreas)
%%Look at the histogram. What area do you think is the minimum size to be a valid crack?
minAcceptableArea =20;
mask = bwareafilt(filteredImage, [minAcceptableArea, inf]);
subplot(2, 2, 4);
imshow(mask);
%
% % Measure size of crack.
props = regionprops(mask, 'Area');
allAreas = [props.Area];
out=bwferet(mask)
% Measure the areas to know the area not to be considered
% props = regionprops(mask, 'Area');
% allAreas = sort([props.Area], 'descend')
% Get width = area / maximum length
averageWidths = sort(allAreas ./ out.MaxDiameter, 'descend');
message = sprintf('The average width = %.2f pixels.', averageWidths(1));
fprintf('%s\n', message);
caption = sprintf('Binary Image of Cracks larger than %d\nAverage width of largest = %.2f pixels', minAcceptableArea, averageWidths(1));
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
uiwait(helpdlg(message));
  2 Kommentare
yasmin ismail
yasmin ismail am 7 Mär. 2023

Melden Sie sich an, um zu kommentieren.

Antworten (3)

Image Analyst
Image Analyst am 8 Mär. 2023
That doesn't look like the right algorithm if you want to find crack widths. Did you see my post where I found the mean width of a blob (image of lightning)? Basically you want to
  1. Threshold/mask your image
  2. Get the Euclidean Distance Transform (EDT) of your mask
  3. Get the skeleton of your mask
  4. Multiply your EDT image by your skeleton image to get the radius of the blob at each point along it's skeleton;
  5. Double the radii to get the widths.
  6. Display the histogram to see the distribution, or take the mean.
See attached demo.
  24 Kommentare
Image Analyst
Image Analyst am 23 Apr. 2023
  1. Sum up the skeleton image (will count all cracks in the image if there is more than one). This will give you a pixel count.
  2. Not sure what you mean but atand or atan2d will give you angles, given a delta y and delta x.

Melden Sie sich an, um zu kommentieren.


yasmin ismail
yasmin ismail am 24 Apr. 2023
@Image Analyst another question:
To find width,if I used (bwperim) instead of (bwskel) will be more accurate?
  8 Kommentare
Image Analyst
Image Analyst am 27 Mai 2023 um 17:25
Yes, try various spatial filters so that you can get as much contrast between the crack and the background, and have the background be fairly flat (same gray level range). Then you can apply a fixed global threshold to discriminate crack from background.

Melden Sie sich an, um zu kommentieren.


yasmin ismail
yasmin ismail am 2 Jun. 2023 um 13:11
I used filters as you advised me before and I could determine the threshold as shown in attached image but still the diameter image and distance transform the lines of crack is too small not clear enough, although I reduced (skeletons longer than 1 pixels)
but still not clear , can you help to fix it please
% Program to compute the mean width of a blob in an image.
clearvars;
close all;
clc;
fontSize = 15;
% Read in original image, with white lightning on black background.
baseFileName = 'A2.jpg';
fullFileName = fullfile(pwd, baseFileName);
grayImage = imread(fullFileName);
% Get the dimensions of the image.
% numberOfColorChannels should be = 1 for a gray scale image, and 3 for an RGB color image.
[rows, columns, numberOfColorChannels] = size(grayImage)
if numberOfColorChannels > 1
% It's not really gray scale like we expected - it's color.
% Use weighted sum of ALL channels to create a gray scale image.
% grayImage = rgb2gray(rgbImage);
% ALTERNATE METHOD: Convert it to gray scale by taking only the green channel,
% which in a typical snapshot will be the least noisy channel.
grayImage = grayImage(:, :, 2); % Take green channel.
else
grayImage = grayImage; % It's already gray scale.
end
% Now it's gray scale with range of 0 to 255.
subplot(2, 3, 1);
imshow(grayImage, [])
impixelinfo; % Let user mouse around and see values in the status line at the lower right.
title('Original Image', 'FontSize', fontSize);
% Binarize the image.
% mask = imbinarize(grayImage);
lowThreshold = 0;
highThreshold = 40;
% Interactively and visually set a threshold on a gray scale image.
% https://www.mathworks.com/matlabcentral/fileexchange/29372-thresholding-an-image?s_tid=srchtitle
[lowThreshold, highThreshold] = threshold(lowThreshold, highThreshold, grayImage);
mask = grayImage >= lowThreshold & grayImage <= highThreshold;
% Fill holes.
mask = imfill(mask, 'holes');
subplot(2, 3, 2);
imshow(mask)
impixelinfo; % Let user mouse around and see values in the status line at the lower right.
title('Mask', 'FontSize', fontSize)
% Take largest blob only.
% mask = bwareafilt(mask, 1);
% Compute the skeleton
skelImage = bwskel(mask);
% Find the areas of all the skeletons.
props = regionprops(skelImage, 'Area');
allAreas = sort([props.Area])
% Extract only skeletons longer than 60 pixels.
skelImage = bwareaopen(skelImage, 1);
subplot(2, 3, 3);
imshow(skelImage)
impixelinfo; % Let user mouse around and see values in the status line at the lower right.
title('Thinned', 'FontSize', fontSize)
% Enlarge figure to full screen.
g = gcf;
g.WindowState = 'maximized';
% Compute the Euclidean distance image.
edtImage = bwdist(~mask);
subplot(2, 3, 4);
imshow(edtImage, [])
title('Distance Transform Image', 'FontSize', fontSize);
impixelinfo; % Let user mouse around and see values in the status line at the lower right.
% Multiply them to get an image where the only pixels in the image
% are along the skeleton and their value is the radius.
% Multiply radius image by 2 to get diameter image.
diameterImage = 2 * edtImage .* single(skelImage);
subplot(2, 3, 5);
imshow(diameterImage, [])
title('Diameter Image', 'FontSize', fontSize);
impixelinfo; % Let user mouse around and see values in the status line at the lower right.
% Get the widths. These will be where the image is not zero.
widths = diameterImage(diameterImage > 0);
% Show histogram of widths.
subplot(2, 3, 6);
histogram(widths);
grid on;
xlabel('Width in Pixels', 'FontSize', fontSize);
ylabel('Count', 'FontSize', fontSize);
% Compute the mean width
meanWidth = mean(widths)
% Put a line on the histogram at the mean width
xline(meanWidth, 'LineWidth', 2, 'Color', 'r');
caption = sprintf('Histogram of Widths. Mean Width = %.1f Pixels', meanWidth);
title(caption, 'FontSize', fontSize);
message = sprintf('Mean Width = %.1f Pixels', meanWidth);
msgbox(message);
% Compute the max width
maxWidth = max(widths)
% Put a line on the histogram at the max width
xline(maxWidth, 'LineWidth', 2, 'Color', 'r');
caption = sprintf('Histogram of Widths. Max Width = %.1f Pixels', maxWidth);
title(caption, 'FontSize', fontSize);
message = sprintf('Max Width = %.1f Pixels', maxWidth);
msgbox(message);

Community Treasure Hunt

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

Start Hunting!

Translated by