一、簡介
1 基于闊值分割的裂縫檢測方法
基于門檻值分割的裂縫檢測方法是一種綜合的裂縫檢測算法,主要分為兩步:首先對輸入的圖像進行預處理,目的是去除混凝土表面圖像上的背景噪聲,同時增強裂縫特征;其次對預處理的圖像進行門檻值分割,提取裂縫。
例如,(1)預進行中利用圖像減操作去除微小的變化,如不均勻光照和陰影的幹擾;(2)然後利用線性增強處理,增強線性結構,消除塊狀結構等噪聲;(3)最後利用Otsu算法進行門檻值分割,其門檻值擷取依據灰階直方圖。
該算法能夠有效去除陰影幹擾,但是取決于預處理時圖像減操作的中值濾波器大小、線性增強的參數大小及門檻值選擇的準确性,在實際應用中不容易擷取。
2 基于形态學的裂縫檢測方法
基于形态學的裂縫檢測方法是數學形态學和曲率評估檢測複雜環境中類似裂縫的模型。通過定義一個矩形或其他形狀的結構元素,對混凝土表面圖像進行腐蝕、膨脹、開運算和閉運算等操作,使得圖像中不是裂縫的邊緣資訊盡量腐蝕掉,同時對裂縫邊緣進行填充,再進行裂縫識别。
基于形态學的裂縫檢測方法通常分三步:
(1)通過增強圖像背景中黑色像素來提高圖像對比度;
(2)采用數學形态學中描述的條件進行裂縫增強,即先使用高斯濾波去噪,然後進行門檻值分割;
(3)采用線性結構元素去除被增強的噪聲模型,利用較大的結構元素進行閉操作以去除比結構元素小的扭曲的裂縫部分。
該方法對複雜背景的混凝土表面圖像進行裂縫檢測時能夠有效利用裂縫的形狀屬性、連通性、曲率等,在裂縫檢測研究中應用較多。
3 基于區域生長的裂縫檢測方法
區域生長是将單個像素或者像素點組成的區域發展成更大區域的過程。
首先選擇種子像素點或者種子區域,然後對這些種子像素點進行區域增長是通過将與每個種子點或者區域有相似屬性(如強度、灰階級及紋理等)的相鄰像素點或者相鄰區域合并到種子區域,不斷疊代,直到處理完每個像素點。
使用區域生長算法進行裂縫檢測時,首先對裂縫圖像進行區域劃分,尋找種子區域,然後對裂縫區域進行矢量化,根據裂縫區域間的相似屬性與種子區域連接配接,不斷疊代,直到所有裂縫區域連接配接完畢。
該算法能夠實作斷裂裂縫的連接配接,但計算量大,噪聲區域的存在導緻部分噪聲區域被誤連接配接,影響裂縫檢測的精确率。
4 基于滲流模型的裂縫檢測方法
滲流算法是一種可變的局部處理方法。
基于滲流模型的裂縫檢測算法的基本思想是根據中心像素點的特征值判斷其是否為裂縫上的點,若中心像素點屬于裂縫像素,則滲流區域将線性生長,若中心像素點是背景像素,則滲流區域将向各方向生長。
滲流算法充分考慮了鄰域像素點間灰階值的連續性,進而保證了裂縫的連續性,此外,該算法同時利用裂縫的灰階特征和形狀特征,能夠精确檢測到不清晰的裂縫,但該算法處理時間長,不能很好地滿足實時性要求。
5 基于小波變換的裂縫檢測算法
小波變換是一種新的局部變換分析方法,能夠提供一個随頻率改變的視窗,即其形狀、時間窗和頻率窗都可以随時頻的改變而改變。
采用小波變換進行圖像處理時,首先将一幅固定的圖像經過變換分解為一系列運動的圖像,然後把函數看做是視野的移動。
當一幅圖像發生僞運動時,其小波系數會發生震蕩,震蕩的幅度會給出函數的頻率資訊,該方法将圖像變換到不同方向的子帶來進行裂縫提取。
6 基于神經網絡的裂縫檢測方法
基于神經網絡的裂縫檢測算法是一種非線性的分類算法。
首先對圖像進行方格采樣,擷取圖像的方格影像,并對每個方格影像依次進行直方圖均衡處理和二值化處理,然後提取方格特征,構成用于訓練和分類的特征向量。
該方法對網絡結構和訓練方案的選擇要求較高,否則會導緻直接用于資訊提取的結果魯棒性差。此外,裂縫形狀的多樣性及寬度的不确定性導緻訓練過程複雜,運作效率低。
二、部分源代碼
function [ ] = PavementCrackDelineation( )
% NOTE: It requires a compiled mex-file of the fast implementation
% of the max-blurring function.
if ~exist('./COSFIRE/dilate')
BeforeUsing();
end
% temporary
dataset = 2;
CRACK_IVC = 1;
CRACK_PV14 = 2;
if dataset == CRACK_IVC
error('Dataset not yet available.')
return;
elseif dataset == CRACK_PV14
dname = 'CrackPV14';
imagesdir = 'cracks14';
gtdir = 'cracks14_gt';
prefix_gt = '';
end
% Binarization thresholds
thresholds = 0.01:0.01:0.99;
nthresholds = numel(thresholds);
%% Symmetric filter params and configuration
x = 101; y = 101; % center
line1(:, :) = zeros(201);
line1(:, x) = 1; %prototype line
% Parameters determined in the paper
% N.Strisciuglio, G. Azzopardi, N.Petkov, "Detection of curved lines
% with B-COSFIRE filters: A case study on crack delineation", CAIP 2017
sigma = 3.3;
len = 14;
sigma0 = 2;
alpha = 1;
% Symmetric filter params
symmfilter = cell(1);
symm_params = SystemConfig;
% COSFIRE params
symm_params.inputfilter.DoG.sigmalist = sigma;
symm_params.COSFIRE.rholist = 0:2:len;
symm_params.COSFIRE.sigma0 = sigma0 / 6;
symm_params.COSFIRE.alpha = alpha / 6;
% Orientations
numoriens = 12;
symm_params.invariance.rotation.psilist = 0:pi/numoriens:pi-pi/numoriens;
% Configuration
symmfilter{1} = configureCOSFIRE(line1, round([y x]), symm_params);
% Prepare the filter set
filterset(1) = symmfilter;
%% APplication of B-COSFIRE for crack delineation
files = rdir(['./data/' dname '/' imagesdir '/*.bmp']);
nfiles = size(files, 1);
% Initialize result matrix
nmetrics = 3;
RESULTS = zeros(nfiles + 1, nmetrics, nthresholds);
for n = 1:nfiles
fprintf('Processing image %d of %d. ', n, nfiles);
% Read image
imageInput = double(imread(files(n).name)) ./ 255;
% Read groud truth
[p, name, ext] = fileparts(files(n).name);
gt = double(imread(['./data/' dname '/' gtdir '/' prefix_gt name '.bmp'])) ./ 255;
imageInput = imcomplement(imageInput);
% Pad input image to avoid border effects
NP = 50; imageInput = padarray(imageInput, [NP NP], 'replicate');
% Filter response
inhibFactor = 0;
tuple = computeTuples(imageInput, filterset);
[response, rotations] = applyCOSFIRE_inhib(imageInput, filterset, inhibFactor, tuple);
response = response{1};
response = response(NP+1:end-NP, NP+1:end-NP);
% Cropping out the central part (unpadding)
rotations_final = zeros(size(response, 1), size(response, 2), size(rotations, 3));
for j = 1:size(rotations, 3)
rotations_final(:,:,j) = rotations(NP+1:end-NP, NP+1:end-NP, j);
end
% Evaluation
fprintf(' Result evaluation...\n');
for j = 1:nthresholds
% Thinning and Histeresis thresholding (using different
% thresholds). The threshold of the CAIP17 paper is th=49. Here
% we compute the performance for differen thresholds anyway to
% build and show the ROC curve.
binImg = binarize(rotations_final, thresholds(j));
binImg2 = bwmorph(binImg, 'close');
binImg2 = bwmorph(binImg2,'skel',Inf);
figure(j)
imshow(binImg2);
% Compute the result metrics for a tolerance of d = 2 (as in
% the paper)
[cpt2, crt2, F2] = evaluate(binImg2, gt, 2);
%[cpt3, crt3, F3] = evaluate(binImg2, gt, 3);
RESULTS(n, :, j) = [cpt2, crt2, F2];
end
end
% Average Results
avg_results = reshape(mean(RESULTS(1:nfiles, :, :)), nmetrics, nthresholds)';
[M, idx] = max(avg_results(:,3));
fprintf('\nResults of the CAIP17 paper\n');
fprintf('Pr: %.3f, Re: %.3f, F: %.3f\n', avg_results(idx, 1), avg_results(idx, 2), avg_results(idx, 3));
PrintROCcurve(avg_results);
end
function [cpt, crt, F] = evaluate(binImg, gt, d)
A = zeros(d*2+1, d*2+1); A(d+1,d+1) = 1; B = bwdist(A) <= d;
[m, n] = size(binImg);
%binImg = bwmorph(binImg,'skel',Inf);
gt = padarray(gt, [d d], 0);
%binImg = padarray(binImg, [d d], 0);
Lr = 0;
bad = zeros(size(binImg));
for x = 1:m
for y = 1:n
%if gt(x, y) == 1
if binImg(x,y) == 1
%patch = binImg(x:x+2*d, y:y+2*d); %
patch = gt(x+d-d:x+d+d, y-d+d:y+d+d);
s = sum(patch(:) .* B(:));
if s > 0
Lr = Lr + 1;
else
bad(x,y) = 1;
end
end
end
end
Lgt = sum(gt(:));
Ln = sum(binImg(:));
cpt = min(1, Lr / Lgt);
crt = min(1, Lr / Ln);
F = 2 * cpt * crt / (cpt + crt);
end
function [binarymap] = binarize(rotoutput1, highthresh)
%%%%%%%%%%%%%%%%% BEGIN BINARIZATION %%%%%%%%%%%%%%%%%%
% compute thinning
orienslist = 0:pi/12:pi-pi/12;
[viewResult, oriensMatrix] = calc_viewimage(rotoutput1,1:numel(orienslist), orienslist);
thinning = calc_thinning(viewResult, oriensMatrix, 1);
%figure; imagesc(thinning);
%
% % Choose high threshold of hysteresis thresholding
% if nargin == 4
% bins = 64;p = 0.05; %Keep the strongest 10% of the pixels in the resulting thinned image
% f = find(thinning > 0);
% counts = imhist(thinning(f),bins);
% highthresh = find(cumsum(counts) > (1-p)*length(f),1,'first') / bins;
% end
%
binarymap = calc_hysteresis(thinning, 1, 0.5*highthresh*max(thinning(:)), highthresh*max(thinning(:)));
%figure;imagesc(binarymap);colormap gray; axis image;
% show binarized image
% figure;
% subplot(1,2,1);imagesc(img);axis off;axis image;colormap(gray);
% subplot(1,2,2);imagesc(imcomplement(binarymap));axis off;axis image;colormap(gray);
%%%%%%%%%%%%%%%%% END BINARIZATION %%%%%%%%%%%%%%%%%%%%
end
function [] = PrintROCcurve(avg_results)
pr = avg_results(:,1);
re = avg_results(:,2);
figure;
linewidth = 3;
plot(re, pr, 'linewidth',linewidth,'color',[0.25 0.25 0.25],'markersize',10);
set(gca,'YGrid','off');
set(gca,'XGrid','off');
set(gca,'XTick',0:.1:1)
set(gca,'XTickLabel',0:.1:1)
axis square;
% Plot other methods results
hold on;
% 1: Zou14 - data set
% 2: CrackTree
% 3: FoSA
Pr = [0.872 0.821 0.845;
0.842 0.625 0.733;
0.846 0.885 0.897;
0.793 0.753 0.756;
0.949 0.845 0.860;
0.671 0.780 0.836;
0.960 0.698 0.716;
0.846 0.696 0.749;
0.767 0.722 0.779;
0.833 0.927 0.811;
0.833 0.839 0.792;
0.997 0.847 0.868;
0.499 0.775 0.696;
0.848 0.948 0.925];
Re = [0.965 0.691 0.628 ;
0.904 0.605 0.568 ;
0.905 0.713 0.612 ;
0.903 0.776 0.691 ;
0.939 0.600 0.577;
0.843 0.649 0.647 ;
0.915 0.605 0.552 ;
0.929 0.668 0.654 ;
0.996 0.669 0.636 ;
0.961 0.860 0.805;
0.993 0.967 0.937 ;
0.823 0.923 0.805 ;
0.890 0.706 0.663 ;
0.988 0.985 0.880];
F = [0.916 0.751 0.721 ;
0.872 0.614 0.640 ;
0.874 0.790 0.728 ;
0.845 0.764 0.722 ;
0.944 0.700 0.691;
0.747 0.708 0.729 ;
0.937 0.648 0.623 ;
0.886 0.682 0.698 ;
0.867 0.695 0.700 ;
0.892 0.892 0.808;
0.906 0.898 0.858 ;
0.893 0.883 0.835 ;
0.639 0.739 0.679 ;
0.913 0.966 0.901];
avgPr = mean(Pr);
avgRe = mean(Re);
avgF = mean(F);
linewidth = 2;
plot(avgRe(1), avgPr(1), 'o', 'linewidth',linewidth,'color',[0.25 0.25 0.25],'markersize',10);
plot(avgRe(2), avgPr(2), 's', 'linewidth',linewidth,'color',[0.25 0.25 0.25],'markersize',10);
plot(avgRe(3), avgPr(3), 'd', 'linewidth',linewidth,'color',[0.25 0.25 0.25],'markersize',10);
xlabel('Recall');
ylabel('Precision');
legend({'COSFIRE', 'Zou14', 'CrackTree', 'FoSA'}, 'Location', 'southwest');
title('ROC curve');
fprintf('\nResults of Zou et al.\n');
fprintf('Pr: %.3f, Re: %.3f, F: %.3f\n', avgPr(1), avgRe(1), avgF(1));
fprintf('\nResults of CrackTree.\n');
fprintf('Pr: %.3f, Re: %.3f, F: %.3f\n', avgPr(2), avgRe(2), avgF(2));
fprintf('\nResults of FoSA.\n');
fprintf('Pr: %.3f, Re: %.3f, F: %.3f\n', avgPr(3), avgRe(3), avgF(3));
end