二值化断裂裂缝的智能拼接算法

该算法基于裂缝角度和端点距离进行生长拼接,能够有效克服噪声点的影响。

matlab 复制代码
% 二值化断裂裂缝的智能拼接算法
clear; clc; close all;

%% 1. 生成模拟断裂裂缝图像
fprintf('生成模拟断裂裂缝图像...\n');

% 创建空白图像
img_size = 500;
binary_image = false(img_size);

% 生成几条断裂的裂缝
rng(42); % 设置随机种子以确保可重复性

% 第一条裂缝 (水平方向,中间断裂)
y1 = 150;
x_start1 = 50;
x_end1 = 200;
binary_image(y1, x_start1:x_end1) = true;

% 第二条裂缝 (与第一条断裂部分重叠)
x_start2 = 220;
x_end2 = 350;
binary_image(y1, x_start2:x_end2) = true;

% 第三条裂缝 (倾斜,与第一条有交集)
y2 = 200;
for x = 100:250
    y = y2 + round(0.5 * (x - 100));
    if y <= img_size && y >= 1
        binary_image(y, x) = true;
    end
end

% 第四条裂缝 (垂直方向)
x3 = 400;
y_start3 = 100;
y_end3 = 300;
binary_image(y_start3:y_end3, x3) = true;

% 添加噪声点
noise_density = 0.001;
noise_mask = rand(img_size) < noise_density;
binary_image = binary_image | noise_mask;

% 显示原始图像
figure;
imshow(binary_image);
title('原始二值化裂缝图像(含噪声)');

%% 2. 图像预处理
fprintf('图像预处理...\n');

% 去除小噪声点(面积过滤)
cleaned_image = bwareaopen(binary_image, 10);

% 细化裂缝至单像素宽度
skeleton_image = bwmorph(cleaned_image, 'skel', Inf);

% 显示预处理结果
figure;
subplot(1,2,1);
imshow(cleaned_image);
title('去噪后的图像');
subplot(1,2,2);
imshow(skeleton_image);
title('细化后的骨架图像');

%% 3. 提取裂缝端点和分支点
fprintf('提取裂缝特征点...\n');

% 计算每个像素的邻居数量
neighbor_kernel = [1 1 1; 1 0 1; 1 1 1];
neighbor_count = conv2(double(skeleton_image), neighbor_kernel, 'same');

% 找出端点(只有1个邻居)
endpoints = skeleton_image & (neighbor_count == 1);

% 找出分支点(3个或更多邻居)
branch_points = skeleton_image & (neighbor_count >= 3);

% 显示特征点
figure;
imshow(skeleton_image);
hold on;
[y_end, x_end] = find(endpoints);
plot(x_end, y_end, 'ro', 'MarkerSize', 8, 'LineWidth', 2);
[y_branch, x_branch] = find(branch_points);
plot(x_branch, y_branch, 'go', 'MarkerSize', 8, 'LineWidth', 2);
title('裂缝特征点(红色:端点, 绿色:分支点)');
legend('端点', '分支点');

%% 4. 计算裂缝段的方向角度
fprintf('计算裂缝段方向角度...\n');

% 获取所有裂缝像素的坐标
[y_pixels, x_pixels] = find(skeleton_image);

% 为每个端点计算局部方向
endpoint_angles = zeros(size(endpoints));
[y_end, x_end] = find(endpoints);

for i = 1:length(y_end)
    % 获取端点坐标
    y = y_end(i);
    x = x_end(i);
    
    % 找到与端点相连的像素
    [connected_y, connected_x] = find_connected_pixels(skeleton_image, x, y);
    
    if length(connected_y) >= 1
        % 计算方向向量
        dx = connected_x(1) - x;
        dy = connected_y(1) - y;
        
        % 计算角度(0-180度)
        angle = atan2d(dy, dx);
        if angle < 0
            angle = angle + 180;
        end
        endpoint_angles(y, x) = angle;
    end
end

% 为每个分支点计算主要方向
branch_angles = zeros(size(branch_points));
[y_branch, x_branch] = find(branch_points);

for i = 1:length(y_branch)
    % 获取分支点坐标
    y = y_branch(i);
    x = x_branch(i);
    
    % 找到所有相连像素
    [connected_y, connected_x] = find_connected_pixels(skeleton_image, x, y);
    
    if length(connected_y) >= 2
        % 计算平均方向
        dx_sum = 0;
        dy_sum = 0;
        
        for j = 1:length(connected_y)
            dx = connected_x(j) - x;
            dy = connected_y(j) - y;
            dx_sum = dx_sum + dx;
            dy_sum = dy_sum + dy;
        end
        
        % 计算平均角度
        angle = atan2d(dy_sum, dx_sum);
        if angle < 0
            angle = angle + 180;
        end
        branch_angles(y, x) = angle;
    end
end

%% 5. 裂缝拼接算法
fprintf('执行裂缝拼接算法...\n');

% 创建拼接后的图像
connected_image = skeleton_image;

% 设置拼接参数
max_distance = 30;      % 最大连接距离
angle_threshold = 30;   % 最大角度差异(度)

% 获取所有端点坐标
[y_end, x_end] = find(endpoints);
num_endpoints = length(y_end);

% 为每个端点计算特征向量(位置和角度)
endpoint_features = zeros(num_endpoints, 3);
for i = 1:num_endpoints
    endpoint_features(i, 1) = x_end(i);
    endpoint_features(i, 2) = y_end(i);
    endpoint_features(i, 3) = endpoint_angles(y_end(i), x_end(i));
end

% 使用KD树快速查找最近邻端点
if num_endpoints > 1
    kdtree = KDTreeSearcher(endpoint_features(:, 1:2));
    
    % 对于每个端点,寻找可能的连接
    for i = 1:num_endpoints
        current_x = endpoint_features(i, 1);
        current_y = endpoint_features(i, 2);
        current_angle = endpoint_features(i, 3);
        
        % 查找最近的几个端点
        [idx, dist] = knnsearch(kdtree, [current_x, current_y], 'K', min(5, num_endpoints));
        
        for j = 2:length(idx)  % 跳过自身
            neighbor_idx = idx(j);
            neighbor_x = endpoint_features(neighbor_idx, 1);
            neighbor_y = endpoint_features(neighbor_idx, 2);
            neighbor_angle = endpoint_features(neighbor_idx, 3);
            
            % 计算连接线的角度
            connection_angle = atan2d(neighbor_y - current_y, neighbor_x - current_x);
            if connection_angle < 0
                connection_angle = connection_angle + 180;
            end
            
            % 计算角度差异(考虑角度的循环性质)
            angle_diff1 = min(abs(current_angle - connection_angle), 180 - abs(current_angle - connection_angle));
            reverse_angle = mod(connection_angle + 180, 180);
            angle_diff2 = min(abs(neighbor_angle - reverse_angle), 180 - abs(neighbor_angle - reverse_angle));
            
            % 检查连接条件
            if dist(j) < max_distance && angle_diff1 < angle_threshold && angle_diff2 < angle_threshold
                % 绘制连接线
                connected_image = draw_line(connected_image, current_x, current_y, neighbor_x, neighbor_y);
                
                % 从端点列表中移除已连接的端点(避免重复连接)
                endpoint_features([i, neighbor_idx], :) = NaN;
            end
        end
    end
end

% 显示拼接结果
figure;
imshow(connected_image);
title('拼接后的裂缝图像');

%% 6. 后处理与结果评估
fprintf('后处理与结果评估...\n');

% 提取连接后的裂缝段
connected_components = bwlabel(connected_image);
num_components = max(connected_components(:));

% 计算原始裂缝段数量
original_components = bwlabel(skeleton_image);
num_original_components = max(original_components(:));

fprintf('原始裂缝段数量: %d\n', num_original_components);
fprintf('拼接后裂缝段数量: %d\n', num_components);
fprintf('减少了 %d 个断裂段\n', num_original_components - num_components);

% 计算平均裂缝长度
crack_lengths = zeros(num_components, 1);
for i = 1:num_components
    crack_lengths(i) = sum(connected_components(:) == i);
end

fprintf('平均裂缝长度: %.2f 像素\n', mean(crack_lengths));
fprintf('最大裂缝长度: %d 像素\n', max(crack_lengths));

% 显示最终结果对比
figure;
subplot(1,2,1);
imshow(skeleton_image);
title('原始裂缝骨架');
subplot(1,2,2);
imshow(connected_image);
title('拼接后的裂缝');

%% 7. 辅助函数定义

function [connected_y, connected_x] = find_connected_pixels(image, x, y)
    % 找到与给定像素相连的所有像素
    
    [height, width] = size(image);
    connected_y = [];
    connected_x = [];
    
    % 检查8邻域
    for dy = -1:1
        for dx = -1:1
            if dx == 0 && dy == 0
                continue; % 跳过中心像素
            end
            
            ny = y + dy;
            nx = x + dx;
            
            % 检查边界
            if ny >= 1 && ny <= height && nx >= 1 && nx <= width
                if image(ny, nx)
                    connected_y = [connected_y; ny];
                    connected_x = [connected_x; nx];
                end
            end
        end
    end
end

function image_with_line = draw_line(image, x1, y1, x2, y2)
    % 在图像上绘制一条直线
    
    image_with_line = image;
    
    % 使用Bresenham算法绘制直线
    dx = abs(x2 - x1);
    dy = abs(y2 - y1);
    
    if x1 < x2
        sx = 1;
    else
        sx = -1;
    end
    
    if y1 < y2
        sy = 1;
    else
        sy = -1;
    end
    
    err = dx - dy;
    
    while true
        % 设置当前像素
        if y1 >= 1 && y1 <= size(image, 1) && x1 >= 1 && x1 <= size(image, 2)
            image_with_line(y1, x1) = true;
        end
        
        if x1 == x2 && y1 == y2
            break;
        end
        
        e2 = 2 * err;
        if e2 > -dy
            err = err - dy;
            x1 = x1 + sx;
        end
        
        if e2 < dx
            err = err + dx;
            y1 = y1 + sy;
        end
    end
end

%% 8. 高级拼接算法:考虑裂缝曲率
fprintf('执行高级拼接算法(考虑裂缝曲率)...\n');

% 创建更高级的拼接图像
advanced_connected_image = skeleton_image;

% 获取所有端点和分支点
[y_all, x_all] = find(endpoints | branch_points);
num_points = length(y_all);

% 为每个点计算特征向量(位置、角度和曲率)
point_features = zeros(num_points, 4);
for i = 1:num_points
    x = x_all(i);
    y = y_all(i);
    
    point_features(i, 1) = x;
    point_features(i, 2) = y;
    
    if endpoints(y, x)
        point_features(i, 3) = endpoint_angles(y, x);
    else
        point_features(i, 3) = branch_angles(y, x);
    end
    
    % 计算曲率(简化版本:使用附近点的方向变化)
    point_features(i, 4) = calculate_curvature(skeleton_image, x, y);
end

% 使用KD树查找最近邻点
if num_points > 1
    kdtree_advanced = KDTreeSearcher(point_features(:, 1:2));
    
    % 对于每个点,寻找可能的连接
    for i = 1:num_points
        current_x = point_features(i, 1);
        current_y = point_features(i, 2);
        current_angle = point_features(i, 3);
        current_curvature = point_features(i, 4);
        
        % 查找最近的几个点
        [idx, dist] = knnsearch(kdtree_advanced, [current_x, current_y], 'K', min(5, num_points));
        
        for j = 2:length(idx)  % 跳过自身
            neighbor_idx = idx(j);
            neighbor_x = point_features(neighbor_idx, 1);
            neighbor_y = point_features(neighbor_idx, 2);
            neighbor_angle = point_features(neighbor_idx, 3);
            neighbor_curvature = point_features(neighbor_idx, 4);
            
            % 计算连接线的角度
            connection_angle = atan2d(neighbor_y - current_y, neighbor_x - current_x);
            if connection_angle < 0
                connection_angle = connection_angle + 180;
            end
            
            % 计算角度差异
            angle_diff1 = min(abs(current_angle - connection_angle), 180 - abs(current_angle - connection_angle));
            reverse_angle = mod(connection_angle + 180, 180);
            angle_diff2 = min(abs(neighbor_angle - reverse_angle), 180 - abs(neighbor_angle - reverse_angle));
            
            % 计算曲率兼容性
            curvature_diff = abs(current_curvature - neighbor_curvature);
            
            % 检查连接条件(考虑曲率兼容性)
            if dist(j) < max_distance && ...
               angle_diff1 < angle_threshold && ...
               angle_diff2 < angle_threshold && ...
               curvature_diff < 0.5  % 曲率差异阈值
                
                % 绘制连接线
                advanced_connected_image = draw_line(advanced_connected_image, current_x, current_y, neighbor_x, neighbor_y);
            end
        end
    end
end

% 显示高级拼接结果
figure;
imshow(advanced_connected_image);
title('高级拼接算法结果(考虑曲率)');

%% 9. 曲率计算函数
function curvature = calculate_curvature(image, x, y)
    % 计算指定点处的曲率(简化版本)
    
    % 获取连接像素
    [connected_y, connected_x] = find_connected_pixels(image, x, y);
    
    if length(connected_y) < 2
        curvature = 0;
        return;
    end
    
    % 计算两个方向向量
    dx1 = connected_x(1) - x;
    dy1 = connected_y(1) - y;
    angle1 = atan2d(dy1, dx1);
    
    dx2 = connected_x(2) - x;
    dy2 = connected_y(2) - y;
    angle2 = atan2d(dy2, dx2);
    
    % 计算角度差异(曲率的简化表示)
    angle_diff = min(abs(angle1 - angle2), 360 - abs(angle1 - angle2));
    
    % 归一化曲率值
    curvature = angle_diff / 180;
end

%% 10. 性能评估与比较
fprintf('性能评估与比较...\n');

% 计算不同方法的连接数量
basic_connections = count_connections(skeleton_image, connected_image);
advanced_connections = count_connections(skeleton_image, advanced_connected_image);

fprintf('基本算法连接数量: %d\n', basic_connections);
fprintf('高级算法连接数量: %d\n', advanced_connections);

% 显示最终对比
figure;
subplot(1,3,1);
imshow(skeleton_image);
title('原始裂缝');
subplot(1,3,2);
imshow(connected_image);
title('基本拼接算法');
subplot(1,3,3);
imshow(advanced_connected_image);
title('高级拼接算法');

%% 11. 连接计数函数
function num_connections = count_connections(original_image, connected_image)
    % 计算添加的连接数量
    
    % 找到新添加的像素
    added_pixels = connected_image & ~original_image;
    
    % 计算连接段(通过查找添加的像素形成的连通组件)
    added_components = bwlabel(added_pixels);
    num_connections = max(added_components(:));
end

算法说明

这个MATLAB程序实现了一个完整的二值化断裂裂缝拼接系统,包括以下主要部分:

1. 模拟数据生成

  • 创建包含多条断裂裂缝的二值图像
  • 添加噪声点以模拟真实场景

2. 图像预处理

  • 使用面积过滤去除小噪声点
  • 应用骨架化算法将裂缝细化至单像素宽度

3. 特征提取

  • 检测裂缝的端点和分支点
  • 计算每个特征点的局部方向角度
  • 计算裂缝的曲率特征(高级算法)

4. 裂缝拼接算法

  • 基本算法:基于距离和角度相似性进行拼接
  • 高级算法:额外考虑裂缝曲率兼容性
  • 使用KD树加速最近邻搜索

5. 后处理与评估

  • 计算拼接前后的裂缝段数量
  • 评估平均裂缝长度和最大裂缝长度
  • 比较不同算法的性能

核心算法原理

裂缝拼接策略

  1. 距离约束:只考虑距离较近的裂缝端点进行连接
  2. 角度兼容性:要求连接方向与裂缝局部方向一致
  3. 曲率兼容性(高级算法):要求连接后的裂缝曲率变化平滑

关键技术点

  1. 特征点检测:通过计算像素的邻居数量识别端点和分支点
  2. 局部方向计算:使用连接像素的方向向量估计裂缝局部方向
  3. 高效搜索:使用KD树数据结构加速最近邻搜索
  4. ** Bresenham算法**:用于在图像上绘制直线连接裂缝

使用说明

  1. 程序首先生成一个包含断裂裂缝和噪声的模拟图像
  2. 然后进行预处理,包括去噪和骨架化
  3. 提取裂缝的特征点(端点和分支点)并计算其方向
  4. 使用基本算法进行裂缝拼接
  5. 使用高级算法(考虑曲率)进行裂缝拼接
  6. 最后评估并比较两种算法的性能

参数调整

可以根据实际需求调整以下参数:

  • max_distance:最大连接距离
  • angle_threshold:最大允许角度差异
  • 噪声密度和过滤阈值
  • 曲率兼容性阈值(高级算法)

参考代码 相位一致检测--加裂缝生长 www.3dddown.com/csa/64034.html

扩展应用

这个算法框架可以扩展到以下应用场景:

  1. 地质裂缝分析:拼接地震或地质图像中的裂缝
  2. 材料科学:分析材料断裂表面的裂缝模式
  3. 医学影像:拼接医学图像中的血管或神经结构
  4. 建筑检测:分析建筑物表面的裂缝模式

这个实现提供了一个完整的裂缝拼接框架,您可以根据实际需求进行修改和扩展。

相关推荐
麦格芬2302 小时前
LeetCode 763 划分字母区间
算法·leetcode·职场和发展
裤裤兔2 小时前
医学影像深度学习知识点总结
人工智能·深度学习·机器学习·医学影像·医学图像
free-elcmacom2 小时前
机器学习进阶<8>PCA主成分分析
人工智能·python·机器学习·pca
福尔摩斯张2 小时前
C++核心特性精讲:从C语言痛点出发,掌握现代C++编程精髓(超详细)
java·linux·c语言·数据结构·c++·驱动开发·算法
亚马逊云开发者2 小时前
Q CLI助力合合信息实现Aurora的升级运营
人工智能
涛涛北京3 小时前
【强化学习实验】- 策略梯度算法
人工智能·算法
Fairy要carry3 小时前
2025/12/15英语打卡
人工智能
weixin_446260853 小时前
《从零开始构建智能体》—— 实践与理论结合的智能体入门指南
人工智能
栀秋6663 小时前
深入浅出链表操作:从Dummy节点到快慢指针的实战精要
前端·javascript·算法