基于图像处理的铁路裂缝检测系统

一、系统架构与核心思路

1.1 检测原理

铁路裂缝在图像中表现为:

  • 形态特征:细长、曲折、暗色线条
  • 灰度特征:局部低灰度值区域
  • 纹理特征:破坏轨面均匀纹理

1.2 处理流程

复制代码
原始图像 → 预处理 → 裂缝增强 → 分割提取 → 形态学优化 → 特征筛选 → 标记输出

二、完整 MATLAB 实现

2.1 主程序

matlab 复制代码
%% 基于图像处理的铁路裂缝检测系统
clear; clc; close all;

%% 1. 读取图像
img_path = 'rail_crack.jpg';  % 替换为实际图像路径
I = imread(img_path);

% 如果是彩色图则转换
if ndims(I) == 3
    I_gray = rgb2gray(I);
else
    I_gray = I;
end

I_gray = im2double(I_gray);
fprintf('图像尺寸: %d × %d\n', size(I_gray,1), size(I_gray,2));

%% 2. 预处理
fprintf('预处理...\n');
I_denoised = denoise_rail_image(I_gray);

%% 3. 裂缝增强(多方法融合)
fprintf('裂缝增强...\n');
I_enhanced = enhance_crack(I_denoised);

%% 4. 分割提取
fprintf('分割提取...\n');
BW_raw = segment_crack(I_enhanced);

%% 5. 形态学优化
fprintf('形态学优化...\n');
BW_clean = morphological_refinement(BW_raw, size(I_gray));

%% 6. 特征筛选(去除伪裂缝)
fprintf('特征筛选...\n');
[crack_mask, crack_props] = filter_crack_regions(BW_clean, I_gray);

%% 7. 可视化结果
fprintf('绘制结果...\n');
visualize_crack_detection(I, I_gray, I_enhanced, BW_raw, crack_mask, crack_props);

%% 8. 定量输出
fprintf('\n========== 检测结果 ==========\n');
if ~isempty(crack_props)
    for i = 1:length(crack_props)
        fprintf('裂缝 #%d: 面积=%d px, 长度≈%.1f px, 平均宽度≈%.1f px, 方向=%.1f°\n', ...
            i, crack_props(i).Area, crack_props(i).MajorAxisLength, ...
            crack_props(i).MeanWidth, crack_props(i).Orientation);
    end
else
    fprintf('未检测到裂缝。\n');
end

2.2 预处理模块

matlab 复制代码
function I_out = denoise_rail_image(I)
    % 铁路图像专用去噪:保留边缘,抑制轨面纹理噪声
    
    % 1. 引导滤波 / 双边滤波(保边去噪)
    I_out = imbilatfilt(I, 'DegreeOfSmoothing', 0.1, 'SpatialSigma', 2, 'RangeSigma', 0.05);
    
    % 2. 轻度高斯平滑(进一步压制椒盐噪声)
    I_out = imgaussfilt(I_out, 0.5);
    
    % 3. 对比度受限自适应直方图均衡(CLAHE)--- 拉出暗裂缝对比度
    I_out = adapthisteq(I_out, 'ClipLimit', 0.02, 'Distribution', 'rayleigh');
end

2.3 裂缝增强(核心)

matlab 复制代码
function I_enh = enhance_crack(I)
    % 用 Hessian 多尺度血管/裂纹增强(Frangi filter 思路简化版)
    % 辅以顶帽变换抓极暗细节
    
    %% 方法1:基于 Hessian 的第二方向增强(裂缝=线性暗结构)
    scales = [1.5, 2.5, 4];  % 对应不同裂缝宽度
    resp = zeros(size(I));
    
    for s = scales
        [~,~, hess, ~] = imgradientxy(imgaussfilt(I, s), 'central');
        % Hessian: [Ixx Ixy; Ixy Iyy]
        Ix = imgradientx(imgaussfilt(I, s));
        Iy = imgradienty(imgaussfilt(I, s));
        Ixx = imgradientx(Ix);
        Iyy = imgradienty(Iy);
        Ixy = imgradienty(Ix);
        
        % 特征值(2×2 Hessian)
        % 裂缝希望 λ1≈0,λ2负大(暗脊沿λ1方向)
        % 用 |λ2|/(|λ1|+eps) 作为线性度
        for r = 1:size(I,1)
            for c = 1:size(I,2)
                H = [Ixx(r,c) Ixy(r,c); Ixy(r,c) Iyy(r,c)];
                [V,D] = eig(H);
                l = diag(D);
                l = sort(l, 'descend');  % l1≥l2
                if l(2) < 0  % 沿第二特征方向是"暗"
                    score = abs(l(2)) / (abs(l(1)) + 1e-6);
                    resp(r,c) = max(resp(r,c), score * (1 - exp(l(2)/0.01)));
                end
            end
        end
    end
    
    %% 方法2:顶帽(Top-hat)抓暗细节
    se = strel('disk', 7);
    top = imtophat(I, se);                 % 亮异常
    bot = imbothat(I, se);                 % 暗异常
    I_bot = mat2gray(bot);                 % 暗细节图
    
    %% 融合
    I_enh = mat2gray(resp) .* 0.7 + I_bot .* 0.3;
    I_enh = mat2gray(I_enh);
end

如果觉得 Hessian 逐像素 eig 太慢,可用 imgradient + 结构张量 的简化版:

matlab 复制代码
function I_enh = enhance_crack_fast(I)
    % 更快的裂缝增强(结构张量 / 方向二阶导)
    I = im2double(I);
    I_enh = zeros(size(I));
    
    for sigma = [1.5, 2.5, 4]
        G = fspecial('gaussian', ceil(sigma*6), sigma);
        Ig = conv2(I, G, 'same');
        
        % 一阶导
        [gx, gy] = imgradientxy(Ig, 'central');
        % 二阶导沿梯度垂直方向 ( -gy, gx )
        Jxx = conv2(gx.^2, G, 'same');
        Jxy = conv2(gx.*gy, G, 'same');
        Jyy = conv2(gy.^2, G, 'same');
        
        % 沿垂直方向的二阶导(类似"暗线"响应)
        Jdet = Jxx.*Jyy - Jxy.^2 + 1e-10;
        Jtr  = Jxx + Jyy;
        % 线性度:|λmin|大且各向异性
        lin = sqrt(max((Jtr.^2 - 4*Jdet),0)) ./ (Jtr + eps);
        dark_line_resp = -min(Jxx, Jyy);   % 暗区+线状
        score = lin .* (dark_line_resp);
        I_enh = max(I_enh, score);
    end
    I_enh = mat2gray(I_enh);
end

2.4 分割提取

matlab 复制代码
function BW = segment_crack(I_enh)
    % 多阈值策略:Otsu + 局部自适应底线
    
    % 全局 Otsu(裂缝应为低灰度/高增强值,注意上面增强输出在 0-1)
    T_otsu = graythresh(I_enh);
    BW1 = I_enh > T_otsu * 1.1;       % 增强图上用">",因增强后裂缝亮
    
    % 如果上一步得到的反了(视增强极性),也可用原图暗区:
    T_dark = graythresh(I_enh);
    BW2 = I_enh < T_dark * 0.6;       % 若裂缝是暗的,用<
    
    % 融合(OR),并对边缘做一下清理
    BW = BW1 | BW2;
    BW = imfill(BW, 'holes');
    BW = bwareaopen(BW, 20);          % 去极小噪点
end

2.5 形态学优化(非常关键)

matlab 复制代码
function BW_out = morphological_refinement(BW, imgsize)
    % 根据裂缝"细长"特性做连接与修剪
    
    % 1. 先轻度开:去掉毛刺
    se1 = strel('line', 6, 0);
    BW  = imopen(BW, se1);   % 水平方向开运算
    se2 = strel('line', 6, 90);
    BW  = imopen(BW, se2);   % 竖直方向开运算
    
    % 2. 闭运算:连接断裂裂缝(短断开)
    se3 = strel('line', 12, 45);  % 沿典型裂缝方向
    BW  = imclose(BW, se3);
    BW  = imclose(BW, strel('disk',2));
    
    % 3. 再去掉小区域
    BW_out = bwareaopen(BW, 50);
end

2.6 特征筛选(拒绝伪裂缝:油污/阴影/锈迹)

matlab 复制代码
function [mask, props] = filter_crack_regions(BW, I_gray)
    % 用区域几何+灰度特征筛掉非裂缝
    
    CC = bwconncomp(BW);
    mask = false(size(BW));
    props = [];
    idx = 0;
    
    for k = 1:CC.NumObjects
        region = false(size(BW));
        region(CC.PixelIdxList{k}) = true;
        
        % 基本几何
        stats = regionprops(region, I_gray, ...
            {'Area','MajorAxisLength','MinorAxisLength','Orientation', ...
             'Eccentricity','Solidity','Centroid','PixelIdxList'});
        s = stats(1);
        
        % 平均宽度估计
        if s.MinorAxisLength > 0
            MeanWidth = s.Area / s.MajorAxisLength;
        else
            MeanWidth = 0;
        end
        
        % ---- 规则:裂缝先验 ----
        % 1) 面积不能太小
        rule1 = s.Area > 80;
        % 2) "细长":长度 >> 宽度
        rule2 = (s.MajorAxisLength / max(MeanWidth,1)) > 3.5;
        % 3) 偏心/实心度:裂缝通常不太"蓬松"
        rule3 = s.Eccentricity > 0.7 && s.Solidity > 0.3;
        % 4) 灰度:裂缝应在轨面偏暗侧
        region_vals = I_gray(s.PixelIdxList);
        rule4 = mean(region_vals) < graythresh(I_gray)*0.85;
        
        if rule1 && rule2 && rule3 && rule4
            idx = idx + 1;
            mask = mask | region;
            props(idx).Area = s.Area;
            props(idx).MajorAxisLength = s.MajorAxisLength;
            props(idx).MeanWidth = MeanWidth;
            props(idx).Orientation = s.Orientation;
            props(idx).Centroid = s.Centroid;
        end
    end
end

2.7 可视化

matlab 复制代码
function visualize_crack_detection(I_rgb, I_gray, I_enh, BW_raw, mask, props)
    figure('Position',[100 100 1400 900]);
    
    subplot(2,3,1);
    if ndims(I_rgb)==3, imshow(I_rgb); else imshow(I_rgb,[]); end
    title('原始图像');
    
    subplot(2,3,2);
    imshow(I_gray,[]); title('灰度图');
    
    subplot(2,3,3);
    imshow(I_enh,[]); title('裂缝增强图');
    
    subplot(2,3,4);
    imshow(BW_raw); title('分割二值图(粗)');
    
    subplot(2,3,5);
    imshow(mask); title('裂缝掩膜(精)');
    
    subplot(2,3,6);
    if ndims(I_rgb)==3, imshow(I_rgb); else imshow(I_gray,[]); end; hold on;
    % 轮廓标红
    if any(mask(:))
        BW3 = imdilate(mask, strel('disk',2));
        [B,L] = bwboundaries(mask,'noholes');
        for b = 1:length(B)
            boundary = B{b};
            plot(boundary(:,2), boundary(:,1), 'r', 'LineWidth', 2);
        end
        % 中心点
        for i = 1:length(props)
            plot(props(i).Centroid(1), props(i).Centroid(2), 'yo', ...
                'MarkerSize',8,'LineWidth',2);
        end
    end
    title('裂缝标记结果');
    hold off;
end

参考代码 利用图像处理的铁路裂缝检测 www.youwenfan.com/contentcsv/79246.html

三、针对"轨面反光/阴影"的实用技巧

铁路现场图像经常有:

  • 轨面镜面反光(亮斑)
  • 锈迹/油污(大面积暗色但不是裂缝)
  • 枕木/扣件边缘(直线但不是裂缝)

对策 :在 filter_crack_regions 里再加两条硬规则即可大幅降误报:

matlab 复制代码
% 5) 不是大面积暗块:对比度局部应高(裂缝两侧灰度跳变)
edgeStrength = mean(imgradient(I_gray));  % 全局参考
localGrad = imgradient(region_vals .* double(region));  % 伪
% 更直接:沿主轴方向灰度剖面应有"低-高(背景)-低"三明治
rule5 = (std(region_vals) / (mean(region_vals)+eps)) > 0.18;

% 6) 长宽比 + 面积上限:拒绝"大片暗斑"
rule6 = s.Area < prod(size(I_gray)) * 0.08;
相关推荐
EnCi Zheng1 小时前
09abb-SwiGLU激活函数
人工智能
菜鸡旭旭1 小时前
【AI培训中台项目介绍】
人工智能
Elastic 中国社区官方博客1 小时前
Hacknight Beijing:基于阿里云与 Elastic 构建 AI Agents
大数据·运维·人工智能·elasticsearch·搜索引擎·阿里云·云计算
柏舟飞流1 小时前
大数据与 AI 融合:高阶架构与实践
大数据·人工智能·架构
Database_Cool_1 小时前
数据仓库弹性扩缩容怎么实现?阿里云 AnalyticDB MySQL Serverless 弹性架构详解
数据库·人工智能·阿里云
羑悻的小杀马特1 小时前
从 Claude Code 到 QClaw:AgentSkills 规范的跨生态实践与工程取舍!
人工智能·自动化·agent·skills·openclaw·qclaw
zhangfeng11331 小时前
超算中心 高性能计算 htc命令module use的作用
人工智能·机器学习
Rocky Ding*1 小时前
深入浅出完整解析AIGC时代中GAN(Generative Adversarial Network)系列模型核心基础知识(下篇)
论文阅读·人工智能·深度学习·机器学习·aigc·gan·ai-native
软件开发技术深度爱好者1 小时前
当前的AI或者说大语言模型与《中庸》思想关联意义的探讨
人工智能·学习心得