当前位置:网站首页>【图像处理】基于中轴变换实现图像骨架提取附matlab代码
【图像处理】基于中轴变换实现图像骨架提取附matlab代码
2022-07-30 05:30:00 【matlab_dingdang】
1 内容介绍
介绍了一种中轴变换算法。该算法修正了现存算法的缺点,可以快速去除二值图像中的冗余信息,准确抽取图像的单像素骨架,保留基本特征,特别是斜线和圆形焊盘特征。大量实验表明,该方法降低图像的复杂度,仅保留图像形状的拓扑信息,为后续处理提供理想的图像,提高整个系统的性能。
2 完整代码
% 中轴算法 Medial Axis Transfrom%% by HPC_ZY 20190802clear; close all; clcload data%% matlab% 求骨架ticskeleton = bwmorph(im,'skeleton',Inf);t1 = toc;% 去毛刺ticskeleton1 = bwmorph(skeleton,'spur',16);t2 = toc;figureshowres(im,skeleton,t1,1,2,1,'matlab库')showres(im,skeleton1,t2,1,2,2,'matlab库(消除毛刺)')%% 迭代删除% 迭代删除法ticskeleton1 = method1(im);t1 = toc;% 迭代删除法(查找表)ticskeleton2 = method2(im);t2 = toc;% 迭代删除法(简化)ticskeleton3 = method3(im);t3 = toc;figureshowres(im,skeleton1,t1,1,3,1,'迭代删除法')showres(im,skeleton2,t2,1,3,2,'迭代删除法(查找表)')showres(im,skeleton3,t3,1,3,3,'迭代删除法(简化)')%% ------------function--------------% 迭代删除法function skeleton = method1(bw)bw = double(bw); % 转为非逻辑类型,方便后面求和[M,N] = size(bw);skeleton = bw;deleCount = 1; % 用于记录一次迭代删除的像素个数while deleCount>0% 删(右,下)deleCount = 0;label = zeros(M,N,'logical');for i = 2:M-1for j = 2:N-1if skeleton(i,j) % 如果该点为1,判断周围像素p = [skeleton(i-1,j),skeleton(i-1,j+1),skeleton(i,j+1),skeleton(i+1,j+1),...skeleton(i+1,j),skeleton(i+1,j-1),skeleton(i,j-1),skeleton(i-1,j-1)];Np = sum(p);Tp = length(find(([p(2:end),p(1)]-p) == 1));if Np>1 && Np<7 && Tp==1 && p(1)*p(3)*p(5)==0 && p(7)*p(3)*p(5)==0deleCount = deleCount+1;label(i,j) = 1;endendendendskeleton(label) = 0;% 删(左,上)label = zeros(M,N,'logical');for i = 2:M-1for j = 2:N-1if skeleton(i,j) % 如果该点为1,判断周围像素p = [skeleton(i-1,j),skeleton(i-1,j+1),skeleton(i,j+1),skeleton(i+1,j+1),...skeleton(i+1,j),skeleton(i+1,j-1),skeleton(i,j-1),skeleton(i-1,j-1)];Np = sum(p);Tp = length(find(([p(2:end),p(1)]-p) == 1));if Np>1 && Np<7 && Tp==1 && p(1)*p(3)*p(7)==0 && p(1)*p(5)*p(7)==0deleCount = deleCount+1;label(i,j) = 1;endendendendskeleton(label) = 0;endend% 迭代删除法(查找表)function skeleton = method2(bw)bw = double(bw);[M,N] = size(bw);skeleton = bw;% 生成查找表[List1,List2] = getList1();[x,y] = find(bw);a = min(x);b = max(x);c = min(y);d = max(y);deleCount = 1;mat = [1,2,4,8,16,32,64,128];while deleCount>0deleCount = 0;% 删(右,下)label1 = zeros(M,N,'logical');for i = a:bfor j = c:dif skeleton(i,j)p = [skeleton(i-1,j),skeleton(i-1,j+1),skeleton(i,j+1),skeleton(i+1,j+1),...skeleton(i+1,j),skeleton(i+1,j-1),skeleton(i,j-1),skeleton(i-1,j-1)];idx = sum(p.*mat)+1;if List1(idx)label1(i,j) = true;deleCount = deleCount+1;endendendendskeleton(label1) = 0;% 删(左,上)label2 = zeros(M,N,'logical');for i = a:bfor j = c:dif skeleton(i,j)p = [skeleton(i-1,j),skeleton(i-1,j+1),skeleton(i,j+1),skeleton(i+1,j+1),...skeleton(i+1,j),skeleton(i+1,j-1),skeleton(i,j-1),skeleton(i-1,j-1)];idx = sum(p.*mat)+1;if List2(idx)label2(i,j) = true;deleCount = deleCount+1;endendendendskeleton(label2) = 0;endend% 迭代删除法(简化)function skeleton = method3(bw)bw = double(bw);[M,N] = size(bw);skeleton = bw;% 生成查找表List = getList2();% 收缩搜索范围[x,y] = find(bw);a = min(x);b = max(x);c = min(y);d = max(y);% 开始迭代deleCount = 1;mat = [1,2,4,8,16,32,64,128];while deleCount>0deleCount = 0;label = zeros(M,N,'logical');for i = a:bfor j = c:dif skeleton(i,j)p = [skeleton(i-1,j),skeleton(i-1,j+1),skeleton(i,j+1),skeleton(i+1,j+1),...skeleton(i+1,j),skeleton(i+1,j-1),skeleton(i,j-1),skeleton(i-1,j-1)];idx = sum(p.*mat)+1;if List(idx)label(i,j) = true;deleCount = deleCount+1;endendendendskeleton(label) = 0;endend% 生成查找表function [List1,List2] = getList1()List1 = zeros(256,1,'logical');List2 = zeros(256,1,'logical');for n = 0:255p = bitget(n,1:8);Np = sum(p);Tp = length(find(([p(2:end),p(1)]-p) == 1));if Np>1 && Np<7 && Tp==1% 右,下if p(1)*p(3)*p(5)==0 && p(7)*p(3)*p(5)==0List1(n+1) = true;end% 左,上if p(1)*p(3)*p(7)==0 && p(1)*p(5)*p(7)==0List2(n+1) = true;endendendend% 生成查找表(简化)function List = getList2()List = zeros(256,1,'logical');for n = 0:255p = bitget(n,1:8);Np = sum(p);Tp = length(find(([p(2:end),p(1)]-p) == 1));if Np>1 && Np<7 && Tp==1if (p(1)*p(3)*p(5)==0 && p(7)*p(3)*p(5)==0)||...(p(1)*p(3)*p(7)==0 && p(1)*p(5)*p(7)==0)List(n+1) = true;endendendend% 显示结果function showres(im,skeleton,t,i,j,k,titlename)subplot(i,j,k),imshow(im)hold on[x,y] = find(skeleton);plot(y,x,'r.')title(['\fontsize{16}',titlename])xlabel(['\fontsize{16}耗时(秒):',num2str(t)])end
3 运行结果


4 参考文献
[1]史聪伟, 赵杰煜, 常俊生. 基于中轴变换的骨架特征提取算法[J]. 计算机工程, 2019, 45(7):9.
博主简介:擅长智能优化算法、神经网络预测、信号处理、元胞自动机、图像处理、路径规划、无人机等多种领域的Matlab仿真,相关matlab代码问题可私信交流。
部分理论引用网络文献,若有侵权联系博主删除。
边栏推荐
- Acwing perfect number
- RadonDB MySQL on K8s 2.1.4 发布!
- Seata exception: endpoint format should like ip:port
- This article will take you through js to deal with the addition, deletion, modification and inspection of tree structure data
- "Hou Lang" programmer version, a speech dedicated to a new generation of programmers, He Bing's "Hou Lang" speech imitation show
- 光明区关于促进科技创新的若干措施(征求意见稿)
- 号称年薪30万占比最多的专业,你知道是啥嘛?
- Divide and conquer. L2-025
- Oracle补丁体系及Opatch工具介绍
- mysql cannot connect remotely Can't connect to MySQL server on 'xxx.xxx.xxx.xxx' (10060 "Unknown error")
猜你喜欢

Hexagon_V65_Programmers_Reference_Manual (11)

Go语学习笔记 - gorm使用 - 事务操作 Web框架Gin(十一)

Docker-compose安装mysql

oracle触发器的自治事务

Path dependence: the poor hard science to counter attack breakthrough

MYSQL-InnoDB的线程模型

mysql 中 in 的用法

Acwing perfect number

无代码开发平台重新申请入门教程

It's time to have to learn English, give yourself multiple paths
随机推荐
分布式事务之 Seata框架的原理和实战使用(三)
腾讯面试居然跟我扯了半小时的CountDownLatch
行业案例|数字化经营底座助力寿险行业转型
Thymeleaf简介
JVM 类加载机制 超详细学习笔记(三)
关于组织开展2022年广东省技术先进型服务企业认定工作的通知
[GLib] 什么是GType
程序员大保健指南,给自己的身心偶尔放松的机会
G巴士计数(Google Kickstart2014 Round D Problem B)(DAY 89)
从字节码角度带你彻底理解异常中catch,return和finally,再也不用死记硬背了
容器化|在 S3 备份恢复 RadonDB MySQL 集群数据
IIS网站出现401未授权访问
4461. 范围分区(Google Kickstart2022 Round C Problem B)
pytorch官网中如何选择以及后面的安装和pycharm测试步骤
Acwing perfect number
WeChat payment and payment callback
Summary of skills in using ms project2010 project management software
How can I make (a == 1 && a == 2 && a == 3) to be true?
期末作业C#实现学生宿舍管理系统
mysql高阶语句(一)