详解基于Matlab的空心散点检测

目录
  • 问题描述
  • 过程展示
    • 图像导入
    • 依据RGB值图像二值化
    • 图像腐蚀
    • 图像边缘清理
    • 联通区域查找与坐标均值计算
    • 圈查找
  • 完整代码
  • 其它形状空心散点检测

问题描述

有一张这样的图片,如何提取里面的红色圈圈坐标,并且连接这些坐标形成两个封闭的环路?

过程展示

图像导入

oriPic=imread('test1.png');

subplot(2,2,1)
imshow(oriPic)

依据RGB值图像二值化

原理就是图中颜色种类比较少,只有红黑白,而红色和白色都是R通道数值较大,因此我们可以利用这一点进行图像分割

% 删除红色外的部分并构造二值图
grayPic=rgb2gray(oriPic);
grayPic(oriPic(:,:,1)<250)=255;
grayPic(grayPic<250)=0;

%subplot(2,2,2)
figure
imshow(grayPic)

图像腐蚀

对于白色来说是腐蚀,对于黑色来说是膨胀,这一步是为了让那些有缺口的小圆圈将缺口补起来

% 图像膨胀,使未连接边缘连接
SE=[0 1 0;1 1 1;0 1 0];
bwPic=imerode(grayPic,SE);

figure
imshow(bwPic)

图像边缘清理

就是把和边缘连接的不被黑色包围的区域变成黑色:

% 边缘清理:保留圆圈联通区域
bwPic=imclearborder(bwPic);
%subplot(2,2,3)
figure
imshow(bwPic)

联通区域查找与坐标均值计算

现在每一个白点都是一个坐标区域,我们检测所有联通区域并计算各个区域的重心即可:

% 获取每一个联通区域
[LPic,labelNum]=bwlabel(bwPic);

% 计算每一个联通区域 坐标均值
pointSet=zeros(labelNum,2);
for i=1:labelNum
    [X,Y]=find(LPic==i);
    Xmean=mean(X);
    Ymean=mean(Y);
    pointSet(i,:)=[Xmean,Ymean];
end

% 画个图展示一下
%subplot(2,2,4)
figure
imshow(bwPic)
hold on
scatter(pointSet(:,2),pointSet(:,1),'r','LineWidth',1)

可以看出定位结果还是非常准确的:

圈查找

就以一个点开始不断找最近的点呗,没啥好说的:

n=1;
while ~isempty(pointSet)
    circleSetInd=1;
    for j=1:length(pointSet)
        disSet=sqrt(sum((pointSet-pointSet(circleSetInd(end),:)).^2,2));
        [~,ind]=sort(disSet);
        ind=ind(1:5);
        [~,~,t_ind]=intersect(circleSetInd,ind);
        ind(t_ind)=[];
        if ~isempty(ind)
            circleSetInd=[circleSetInd;ind(1)];
        else
            circleSet{n}=pointSet(circleSetInd,:);
            pointSet(circleSetInd,:)=[];
            n=n+1;
            break
        end
    end
end

figure
imshow(oriPic)
hold on
for i=1:n-1
plot(circleSet{i}(:,2),circleSet{i}(:,1),'LineWidth',2)
end

这效果就很美滋滋:

完整代码

function redPnt
oriPic=imread('test1.png');
%subplot(2,2,1)
figure
imshow(oriPic)

% 删除红色外的部分并构造二值图
grayPic=rgb2gray(oriPic);
grayPic(oriPic(:,:,1)<250)=255;
grayPic(grayPic<250)=0;
%subplot(2,2,2)
figure
imshow(grayPic)

% 图像膨胀,使未连接边缘连接
SE=[0 1 0;1 1 1;0 1 0];
bwPic=imerode(grayPic,SE);
figure
imshow(bwPic)

% 边缘清理:保留圆圈联通区域
bwPic=imclearborder(bwPic);
%subplot(2,2,3)
figure
imshow(bwPic)

% 获取每一个联通区域
[LPic,labelNum]=bwlabel(bwPic);

% 计算每一个联通区域 坐标均值
pointSet=zeros(labelNum,2);
for i=1:labelNum
    [X,Y]=find(LPic==i);
    Xmean=mean(X);
    Ymean=mean(Y);
    pointSet(i,:)=[Xmean,Ymean];
end

%subplot(2,2,4)
figure
imshow(bwPic)
hold on
scatter(pointSet(:,2),pointSet(:,1),'r','LineWidth',1)

n=1;
while ~isempty(pointSet)
    circleSetInd=1;
    for j=1:length(pointSet)
        disSet=sqrt(sum((pointSet-pointSet(circleSetInd(end),:)).^2,2));
        [~,ind]=sort(disSet);
        ind=ind(1:5);
        [~,~,t_ind]=intersect(circleSetInd,ind);
        ind(t_ind)=[];
        if ~isempty(ind)
            circleSetInd=[circleSetInd;ind(1)];
        else
            circleSet{n}=pointSet(circleSetInd,:);
            pointSet(circleSetInd,:)=[];
            n=n+1;
            break
        end
    end
end

figure
imshow(oriPic)
hold on
for i=1:n-1
plot(circleSet{i}(:,2),circleSet{i}(:,1),'LineWidth',2)
end

end

其它形状空心散点检测

来波正方形试试:

可以看出效果还是很棒的,当然大家可以根据实际情况自行更改图像腐蚀模板形状,如果散点是其它颜色请自行更改第一步的图像分割条件。

后注:

若是因为点较为密集而导致圈形路径内部白色区域没被清除,可能会将内部区域也算作散点造成错误,解决方法是计算每个联通区域面积并剔除远远大于区域面积中位数的联通区域:

问题出现原因的图片描述:

如图所示种间那一大片区域也被算作散点

更改后代码如下:

function redPnt
oriPic=imread('test2.png');
figure
imshow(oriPic)

% 删除红色外的部分并构造二值图
grayPic=rgb2gray(oriPic);
grayPic(oriPic(:,:,1)<250)=255;
grayPic(grayPic<250)=0;
figure
imshow(grayPic)

% 图像膨胀,使未连接边缘连接
SE=[0 1 0;1 1 1;0 1 0];
bwPic=imerode(grayPic,SE);
figure
imshow(bwPic)

% 边缘清理:保留圆圈联通区域
bwPic=imclearborder(bwPic);
figure
imshow(bwPic)

% 获取每一个联通区域
[LPic,labelNum]=bwlabel(bwPic);

% 筛掉超大区域
pointSizeSet=zeros(1,labelNum);
for i=1:labelNum
    pointSizeSet(i)=sum(sum(LPic==i));
end
[~,ind]=find(pointSizeSet>10*median(pointSizeSet));

% 计算每一个联通区域 坐标均值
pointSet=zeros(labelNum,2);
for i=1:labelNum
    [X,Y]=find(LPic==i);
    Xmean=mean(X);
    Ymean=mean(Y);
    pointSet(i,:)=[Xmean,Ymean];
end
pointSet(ind,:)=[];

figure
imshow(bwPic)
hold on
scatter(pointSet(:,2),pointSet(:,1),'r','LineWidth',1)

n=1;
while ~isempty(pointSet)
    circleSetInd=1;
    for j=1:length(pointSet)
        disSet=sqrt(sum((pointSet-pointSet(circleSetInd(end),:)).^2,2));
        [~,ind]=sort(disSet);
        ind=ind(1:min(5,length(ind)));
        [~,~,t_ind]=intersect(circleSetInd,ind);
        ind(t_ind)=[];
        if ~isempty(ind)
            circleSetInd=[circleSetInd;ind(1)];
        else
            circleSet{n}=pointSet(circleSetInd,:);
            pointSet(circleSetInd,:)=[];
            n=n+1;
            break
        end
    end
end

figure
imshow(oriPic)
hold on
for i=1:n-1
plot(circleSet{i}(:,2),circleSet{i}(:,1),'LineWidth',2)
end

end

注:

2016版本及以前可能这句:

disSet=sqrt(sum((pointSet-pointSet(circleSetInd(end),:)).^2,2));

会出现数组大小不匹配问题,可以将其改为:

tempMat=repmat(pointSet(circleSetInd(end),:),[size(pointSet,1),1]);
disSet=sqrt(sum((pointSet-tempMat).^2,2));

以上就是详解基于Matlab的空心散点检测的详细内容,更多关于Matlab空心散点检测的资料请关注我们其它相关文章!

(0)

相关推荐

  • Matlab实现图像边缘检测

    为了在一幅图像 f 的(x,y)位置寻找边缘的强度和方向,所选择的工具就是梯度,梯度使用向量来表示: 该向量指出了图像 f 在位置(x,y)处的最大变化率的方向,梯度向量的大小表示为: 它是梯度向量方向变化率的值. 梯度向量的方向表示为: 梯度算子 roberts算子: sobel算子: prewitt算子: Matlab实现 function output = my_edge(input_img,method) if size(input_img,3)==3 input_img=rgb2gra

  • Matlab处理图像后实现简单的人脸检测

    1.人脸检测原理框图 整体思路是寻找图片中最大的连通域,将其认定为人脸. 第一个环节均值滤波,是为了减弱图像的相关细节部分,以免毛刺影响后期连通域的形成,二值化方便形态学处理,减少运算量.考虑到人脸有黑人和白人黄种人,黑人肤色较深,在二值化之后面部区域不容易形成较大的连通域,如果采取形态学边界提取的办法,就可以避免这个问题,形态学边界提取,只要结构元素够大,也可以形成较大的封闭连通域. 然后就是纵向闭合操作,这一步我选择采用竖向长条状的结构元素进行闭合运算,因为人的脸部和颈部以及头发和衣物等等都

  • 基于Matlab图像处理的公路裂缝检测实现

    目录 一.简介 1案例背景 2理论基础 3程序实现 二.部分源代码 三.运行结果 一.简介 1 案例背景 随着国家对公路建设的大力投入,我国的公路通车总里程己经位居世界前列,这样进一步促进了我国经济建设的发展.随着公路的大量投运,公路日常养护和管理已经成为制约公路运营水平提高的瓶颈,特别是路面状态采集.检测维护等工作更是对传统的公路运维模式提出了挑战.路面裂缝是公路日常养护管理中最常见的路面损坏,也是影响公路状态评估和进行必要的公路维修的重要因素!.一般而言,如果路面裂缝能够在被恶化成坑槽之前得

  • Matlab 数字图像的滤波及边缘检测

    目录 一.图像滤波 1.1 线性滤波器 1.1.1 均值滤波 1.1.2 高斯滤波 1.2 非线性滤波器 1.2.1 中值滤波器 1.2.2 双边滤波器 1.3 滤波器的 Matlab 代码实现 二.图像边缘检测 2.1 一阶边缘检测算子 2.1.1 Sobel 算子 2.1.2 Canny 算子 2.2 二阶边缘检测算子 2.2.1 拉普拉斯算子 2.3 边缘检测的 Matlab 代码实现 2.4 边缘检测算法总结 三.参考资料 一.图像滤波 图像滤波的主要目的就是在尽量保留图像细节特征的条件

  • 基于matlab MFCC+GMM的安全事件声学检测系统

    一.安全事件声学检测简介(附lunwen) 1 选题背景 公共安全问题是社会安全稳定所聚焦的话题之一.近年来,检测技术与监控自动化正深刻地改变着人们的生活.尤其在安防领域,闭路电视CCTV(Closed Circuit Television).视频流分析.智能监控等新技术得到了广泛应用,大大提高了安防监控的管理效率.然而值得注意的是,基于视频流的监控手段不可避免地也具有一定的先天性缺漏,例如存在视野盲区.易受光照影响等问题,对于事件检测,还可能存在语义不明的问题,监控手段不够全面.纯视频手段在枪

  • 详解基于Matlab的空心散点检测

    目录 问题描述 过程展示 图像导入 依据RGB值图像二值化 图像腐蚀 图像边缘清理 联通区域查找与坐标均值计算 圈查找 完整代码 其它形状空心散点检测 问题描述 有一张这样的图片,如何提取里面的红色圈圈坐标,并且连接这些坐标形成两个封闭的环路? 过程展示 图像导入 oriPic=imread('test1.png'); subplot(2,2,1) imshow(oriPic) 依据RGB值图像二值化 原理就是图中颜色种类比较少,只有红黑白,而红色和白色都是R通道数值较大,因此我们可以利用这一点

  • 详解基于python的图像Gabor变换及特征提取

    1.前言 在深度学习出来之前,图像识别领域北有"Gabor帮主",南有"SIFT慕容小哥".目前,深度学习技术可以利用CNN网络和大数据样本搞事情,从而取替"Gabor帮主"和"SIFT慕容小哥"的江湖地位.但,在没有大数据和算力支撑的"乡村小镇"地带,或是对付"刁民小辈","Gabor帮主"可以大显身手,具有不可撼动的地位.IT武林中,有基于C++和OpenCV,或

  • mysql数据库详解(基于ubuntu 14.0.4 LTS 64位)

    1.mysql数据库的组成与相关概念 首先明白,mysql是关系型数据库,和非关系型数据库中最大的不同就是表的概念不一样. +整个mysql环境可以理解成一个最大的数据库:A +用mysql创建的数据库B是属于A的,是数据的仓库,相当于系统中的文件夹 +数据表C:是存放数据的具体场所,相当于系统中的文件,一个数据库B中包含若干个数据表C(注意此处的数据库B和A不一样) +记录D:数据表中的一行称为一个记录,因此,我们在创建数据表时,一定要创建一个id列,用于标识"这是第几条记录",id

  • 详解基于django实现的webssh简单例子

    本文介绍了详解基于django实现的webssh简单例子,分享给大家,具体如下: 说明 新建一个 django 程序,本文为 chain. 以下仅为简单例子,实际应用 可根据自己平台情况 进行修改. 打开首页后,需要输入1,后台去登录主机,然后返回登录结果. 正常项目 可以post 主机和登录账户,进行权限判断,然后去后台读取账户密码,进行登录. djang后台 需要安装以下模块 安装后会有一个版本号报错,不影响 channels==2.0.2 channels-redis==2.1.0 amq

  • zabbix 4.04 安装文档教程详解(基于CentOS 7.6)

    1    安装前准备: 1.1   安装JDK 卸载openjdk # rpm -qa | grep java # yum remove java-1.8.0-openjdk # yum remove java-1.8.0-openjdk-headless 安装JDK包 # rpm -ivh jdk-8u191-linux-x64.rpm 1.2   安装依赖包 # yum install -y net-snmp net-snmp-devel OpenIPMI-devel libssh2-dev

  • 详解基于Jupyter notebooks采用sklearn库实现多元回归方程编程

    一.导入excel文件和相关库 import pandas; import matplotlib; from pandas.tools.plotting import scatter_matrix; data = pandas.read_csv("D:\\面积距离车站.csv",engine='python',encoding='utf-8') 显示文件大小 data.shape data 二.绘制多个变量两两之间的散点图:scatter_matrix()方法 #绘制多个变量两两之间的

  • 详解基于Spring Data的领域事件发布

    领域事件发布是一个领域对象为了让其它对象知道自己已经处理完成某个操作时发出的一个通知,事件发布力求从代码层面让自身对象与外部对象解耦,并减少技术代码入侵. 一. 手动发布事件 // 实体定义 @Entity public class Department implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer departmentId; @Enumerate

  • 详解基于Mybatis-plus多租户实现方案

    一.引言 小编先解释一下什么叫多租户,什么场景下使用多租户. 多租户是一种软件架构技术,在多用户的环境下,共有同一套系统,并且要注意数据之间的隔离性. 举个实际例子:小编曾经开发过一套支付宝程序,这套程序应用在不同的小程序上,当使用者访问不同,并且进入相对应的小程序页面,小程序则会把用户相关数据传输到小编这里.在传输的时候需要带上小程序标识(租户ID),以便小编将数据进行隔离. 当不同的租户使用同一套程序,这里就需要考虑一个数据隔离的情况. 数据隔离有三种方案: 1.独立数据库:简单来说就是一个

  • 详解基于IDEA2020.1的JAVA代码提示插件开发例子

    之前因为项目组有自己的代码规范,为了约束平时的开发规范,于是基于2019.1.3版本开发了一个代码提示的插件.但是在把IDEA切换到2020.1版本的时候,却发现疯狂报错,但是网上关于IDEA插件开发的相关文章还是不够多,只能自己解决.于是根据官方的SDK文档,使用Gradle重新构建了一下项目,把代码拉了过来.下文会根据2020.1版本简单开发一个代码异常的提示插件,把容易踩坑的地方提示一下. 1.首先先根据IDEA插件开发官方文档,用Gradle新建一个project 选中file -> n

  • Java 添加、删除、格式化Word中的图片步骤详解( 基于Spire.Cloud.SDK for Java )

    本文介绍使用Spire.Cloud.SDK for Java提供的ImagesApi接口来操作Word中的图片.具体可通过addImage()方法添加图片.deleteImage()方法删除图片.updateImageFormat()格式化Word中的图片以及getImageFormat()获取Word中的图片格式等.操作方法和代码示例可参考下文中的步骤. 步骤1:导入jar文件 创建Maven项目程序,通过maven仓库下载导入.以IDEA为例,新建Maven项目,在pom.xml文件中配置m

随机推荐