经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » MATLAB » 查看文章
详解基于Matlab的空心散点检测
来源:jb51  时间:2022/2/28 13:24:13  对本文有异议

问题描述

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

过程展示

图像导入

  1. oriPic=imread('test1.png');
  2.  
  3. subplot(2,2,1)
  4. imshow(oriPic)

依据RGB值图像二值化

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

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

图像腐蚀

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

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

图像边缘清理

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

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

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

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

  1. % 获取每一个联通区域
  2. [LPic,labelNum]=bwlabel(bwPic);
  3.  
  4. % 计算每一个联通区域 坐标均值
  5. pointSet=zeros(labelNum,2);
  6. for i=1:labelNum
  7. [X,Y]=find(LPic==i);
  8. Xmean=mean(X);
  9. Ymean=mean(Y);
  10. pointSet(i,:)=[Xmean,Ymean];
  11. end
  12.  
  13. % 画个图展示一下
  14. %subplot(2,2,4)
  15. figure
  16. imshow(bwPic)
  17. hold on
  18. scatter(pointSet(:,2),pointSet(:,1),'r','LineWidth',1)

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

圈查找

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

  1. n=1;
  2. while ~isempty(pointSet)
  3. circleSetInd=1;
  4. for j=1:length(pointSet)
  5. disSet=sqrt(sum((pointSet-pointSet(circleSetInd(end),:)).^2,2));
  6. [~,ind]=sort(disSet);
  7. ind=ind(1:5);
  8. [~,~,t_ind]=intersect(circleSetInd,ind);
  9. ind(t_ind)=[];
  10. if ~isempty(ind)
  11. circleSetInd=[circleSetInd;ind(1)];
  12. else
  13. circleSet{n}=pointSet(circleSetInd,:);
  14. pointSet(circleSetInd,:)=[];
  15. n=n+1;
  16. break
  17. end
  18. end
  19. end
  20.  
  21. figure
  22. imshow(oriPic)
  23. hold on
  24. for i=1:n-1
  25. plot(circleSet{i}(:,2),circleSet{i}(:,1),'LineWidth',2)
  26. end

这效果就很美滋滋:

完整代码

  1. function redPnt
  2. oriPic=imread('test1.png');
  3. %subplot(2,2,1)
  4. figure
  5. imshow(oriPic)
  6.  
  7. % 删除红色外的部分并构造二值图
  8. grayPic=rgb2gray(oriPic);
  9. grayPic(oriPic(:,:,1)<250)=255;
  10. grayPic(grayPic<250)=0;
  11. %subplot(2,2,2)
  12. figure
  13. imshow(grayPic)
  14.  
  15. % 图像膨胀,使未连接边缘连接
  16. SE=[0 1 0;1 1 1;0 1 0];
  17. bwPic=imerode(grayPic,SE);
  18. figure
  19. imshow(bwPic)
  20.  
  21. % 边缘清理:保留圆圈联通区域
  22. bwPic=imclearborder(bwPic);
  23. %subplot(2,2,3)
  24. figure
  25. imshow(bwPic)
  26.  
  27. % 获取每一个联通区域
  28. [LPic,labelNum]=bwlabel(bwPic);
  29.  
  30. % 计算每一个联通区域 坐标均值
  31. pointSet=zeros(labelNum,2);
  32. for i=1:labelNum
  33. [X,Y]=find(LPic==i);
  34. Xmean=mean(X);
  35. Ymean=mean(Y);
  36. pointSet(i,:)=[Xmean,Ymean];
  37. end
  38.  
  39.  
  40. %subplot(2,2,4)
  41. figure
  42. imshow(bwPic)
  43. hold on
  44. scatter(pointSet(:,2),pointSet(:,1),'r','LineWidth',1)
  45.  
  46. n=1;
  47. while ~isempty(pointSet)
  48. circleSetInd=1;
  49. for j=1:length(pointSet)
  50. disSet=sqrt(sum((pointSet-pointSet(circleSetInd(end),:)).^2,2));
  51. [~,ind]=sort(disSet);
  52. ind=ind(1:5);
  53. [~,~,t_ind]=intersect(circleSetInd,ind);
  54. ind(t_ind)=[];
  55. if ~isempty(ind)
  56. circleSetInd=[circleSetInd;ind(1)];
  57. else
  58. circleSet{n}=pointSet(circleSetInd,:);
  59. pointSet(circleSetInd,:)=[];
  60. n=n+1;
  61. break
  62. end
  63. end
  64. end
  65.  
  66. figure
  67. imshow(oriPic)
  68. hold on
  69. for i=1:n-1
  70. plot(circleSet{i}(:,2),circleSet{i}(:,1),'LineWidth',2)
  71. end
  72.  
  73. end

其它形状空心散点检测

来波正方形试试:

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

后注:

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

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

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

更改后代码如下:

  1. function redPnt
  2. oriPic=imread('test2.png');
  3. figure
  4. imshow(oriPic)
  5.  
  6. % 删除红色外的部分并构造二值图
  7. grayPic=rgb2gray(oriPic);
  8. grayPic(oriPic(:,:,1)<250)=255;
  9. grayPic(grayPic<250)=0;
  10. figure
  11. imshow(grayPic)
  12.  
  13. % 图像膨胀,使未连接边缘连接
  14. SE=[0 1 0;1 1 1;0 1 0];
  15. bwPic=imerode(grayPic,SE);
  16. figure
  17. imshow(bwPic)
  18.  
  19. % 边缘清理:保留圆圈联通区域
  20. bwPic=imclearborder(bwPic);
  21. figure
  22. imshow(bwPic)
  23.  
  24. % 获取每一个联通区域
  25. [LPic,labelNum]=bwlabel(bwPic);
  26.  
  27. % 筛掉超大区域
  28. pointSizeSet=zeros(1,labelNum);
  29. for i=1:labelNum
  30. pointSizeSet(i)=sum(sum(LPic==i));
  31. end
  32. [~,ind]=find(pointSizeSet>10*median(pointSizeSet));
  33.  
  34. % 计算每一个联通区域 坐标均值
  35. pointSet=zeros(labelNum,2);
  36. for i=1:labelNum
  37. [X,Y]=find(LPic==i);
  38. Xmean=mean(X);
  39. Ymean=mean(Y);
  40. pointSet(i,:)=[Xmean,Ymean];
  41. end
  42. pointSet(ind,:)=[];
  43.  
  44.  
  45. figure
  46. imshow(bwPic)
  47. hold on
  48. scatter(pointSet(:,2),pointSet(:,1),'r','LineWidth',1)
  49.  
  50. n=1;
  51. while ~isempty(pointSet)
  52. circleSetInd=1;
  53. for j=1:length(pointSet)
  54. disSet=sqrt(sum((pointSet-pointSet(circleSetInd(end),:)).^2,2));
  55. [~,ind]=sort(disSet);
  56. ind=ind(1:min(5,length(ind)));
  57. [~,~,t_ind]=intersect(circleSetInd,ind);
  58. ind(t_ind)=[];
  59. if ~isempty(ind)
  60. circleSetInd=[circleSetInd;ind(1)];
  61. else
  62. circleSet{n}=pointSet(circleSetInd,:);
  63. pointSet(circleSetInd,:)=[];
  64. n=n+1;
  65. break
  66. end
  67. end
  68. end
  69.  
  70. figure
  71. imshow(oriPic)
  72. hold on
  73. for i=1:n-1
  74. plot(circleSet{i}(:,2),circleSet{i}(:,1),'LineWidth',2)
  75. end
  76.  
  77. end

注:

2016版本及以前可能这句:

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

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

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

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号