How to detect the crack and calculate its length ?

70 views (last 30 days)
This is my crack concrete image :
I've been trying to create the code, shown below
clear
clc
close all
img = imread('beton1.jpg');
BW=rgb2gray(img);
p = edge(BW, 'sobel');
binaryImage = bwmorph(p,'skel','inf');
measurements = regionprops(binaryImage, 'Area');
totalCrackLength = sum(binaryImage(:));
figure(1);
imshow(img);
figure(2);
imshow(p);
figure(3);
imshow(binaryImage);
And this is the result :
The result comes with so much noise and i cannot see the result of length measurement. I thought it will comes up with skeleton line and show the length beneath of the line.
The question is,
  1. How to reduce the noise and focus on the crack to make a better result ?
  2. How to measure the length of the crack ?
  3. How to see the result of the measurement ? Is it comes with same windows figure or it comes separated ?

Answers (2)

Image Analyst
Image Analyst on 14 Sep 2020
Try bwskel(). Here is a full demo. Adapt as needed.
% This demo computes the tortuosity and average width of a snake-like shape by dividing the actual longest spine distance by the straight line distance between the endpoints.
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 = 15;
%--------------------------------------------------------------------------------------------------------
% READ IN IMAGE
folder = pwd;
baseFileName = 'tortuosity.png';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
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(grayImage);
end
% Display the image.
hFig = figure;
subplot(1, 4, 1);
imshow(grayImage, []);
title('Original Grayscale Image', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
hFig.WindowState = 'maximized'; % May not work in earlier versions of MATLAB.
drawnow;
%--------------------------------------------------------------------------------------------------------
% SEGMENTATION
% Binarize the image
binaryImage = imbinarize(grayImage);
% Fill holes, if any.
binaryImage = imfill(binaryImage, 'holes');
% Take the largest blob only.
binaryImage = bwareafilt(binaryImage, 1);
% Display the binary image.
subplot(1, 4, 1);
cla;
imshow(binaryImage, []);
title('Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
axis('on', 'image');
%--------------------------------------------------------------------------------------------------------
% SKELETONIZATION
% Now skeletonize
skelImage = bwskel(binaryImage, 'MinBranchLength', 10); % First guess. Strangely bwskel() doesn't seem to have any short spurs, no matter what MinBranchLength is.
% skelImage = bwmorph(binaryImage, 'skel', inf); % First guess. Will have short spurs. Shouldn't use this, but going to just for the demo.
% Display the original skeleton image, with annoying spurs
subplot(1, 4, 2);
imshow(skelImage, []);
title('Original Skeleton Image', 'FontSize', fontSize, 'Interpreter', 'None');
axis('on', 'image');
% First get the area of the skeleton and take half of it to get the MinBranchLength.
% This should give use the longest spine path only, and get rid of all spurs (at least for THIS demo image).
MinBranchLength = round(sum(skelImage(:))/2)
% Now take the skeleton again using that min branch length we just computed.
skelImage = bwskel(binaryImage, 'MinBranchLength', MinBranchLength);
% Display the skeleton image.
subplot(1, 4, 3);
imshow(skelImage, []);
title('Skeleton Image', 'FontSize', fontSize, 'Interpreter', 'None');
axis('on', 'image');
% Overlay the skeleton on the original image.
subplot(1, 4, 1);
imshow(imoverlay(binaryImage, skelImage, 'r'));
title('Binary Image with Skeleton Overlaid', 'FontSize', fontSize, 'Interpreter', 'None');
%--------------------------------------------------------------------------------------------------------
% TORTUOSITY COMPUTATION
% Find the endpoints
endpointImage = bwmorph(skelImage, 'endpoints');
[rows, columns] = find(endpointImage)
% Draw a red line between them.
subplot(1, 4, 3);
hold on;
plot(columns, rows, 'r-', 'LineWidth', 2);
% Find the spine length.
% (Would be more accurate to find the spine length by traversing it.)
spineLength = sum(skelImage(:))
% Compute the straight line distance.
straightLineDistance = sqrt((columns(2) - columns(1))^2 + (rows(2) - rows(1))^2)
% Compute the tortuosity
tortuosity = spineLength / straightLineDistance
caption = sprintf('Skeleton Image. Tortuosity = %f', tortuosity);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
%--------------------------------------------------------------------------------------------------------
% AVERAGE WIDTH COMPUTATION
% Compute the Euclidean Distance Transform
edtImage = bwdist(~binaryImage);
subplot(1, 4, 4);
imshow(edtImage, []);
title('Distance Transform', 'FontSize', fontSize, 'Interpreter', 'None');
% Extract the distances only along the skeleton image to extract only radii along spine.
radii = edtImage(skelImage);
% These are the half widths. Multiply by 2 to get the full widths.
averageWidth = 2 * mean(radii)
caption = sprintf('Distance Transform. Mean Width = %.1f', averageWidth);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
  2 Comments
Daffa Anugrah
Daffa Anugrah on 15 Sep 2020
thank you so much! it helps me a lot. I will try it!
Aniq Anuar
Aniq Anuar on 26 Jan 2022
what is the meaning of the minbranchlength? is it possible if we use it to detect defect cracks on the bearing?

Sign in to comment.


KALYAN ACHARJYA
KALYAN ACHARJYA on 14 Sep 2020
Edited: KALYAN ACHARJYA on 14 Sep 2020
[S T]=graythresh(grayImage);
bwImage=imbinarize(grayImage,T);
SE = strel('diamond',1)
bwImage=imerode(bwImage,SE);
bwImage=bwareafilt(~bwImage,1);
bwImage=imdilate(~bwImage,SE);
imshow(bwImage);
  2 Comments
KALYAN ACHARJYA
KALYAN ACHARJYA on 14 Sep 2020
Edited: KALYAN ACHARJYA on 14 Sep 2020
1. How to reduce the noise and focus on the crack to make a better result ?
Done
2.How to measure the length of the crack ?
Are you asking ecudian distance between start crack point and end point? Please note it gives the shortest path.
More: pdist2
%% Distance Part
boundaries=bwboundaries(~bwImage);
dist=pdist2(cell2mat(boundaries),cell2mat(boundaries));
max_dist=max(dist(:))
% Important Note: #Please Verify
3.How to see the result of the measurement ? Is it comes with same windows figure or it comes separated ?
Sorry, the question is not clear for me, please modify.
Daffa Anugrah
Daffa Anugrah on 15 Sep 2020
thank you so much! it helps me a lot. I will try it!

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!