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

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

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. 建筑检测:分析建筑物表面的裂缝模式

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

相关推荐
NAGNIP11 小时前
一文搞懂深度学习中的通用逼近定理!
人工智能·算法·面试
冬奇Lab12 小时前
一天一个开源项目(第36篇):EverMemOS - 跨 LLM 与平台的长时记忆 OS,让 Agent 会记忆更会推理
人工智能·开源·资讯
冬奇Lab12 小时前
OpenClaw 源码深度解析(一):Gateway——为什么需要一个"中枢"
人工智能·开源·源码阅读
AngelPP16 小时前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年16 小时前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
九狼16 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS16 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区17 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈17 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
Ray Liang18 小时前
被低估的量化版模型,小身材也能干大事
人工智能·ai·ai助手·mindx