如何将二进制图像转换为2D三角剖分?

8次观看(最近30天)
盖特
盖特 2013年8月23日
Answered: Sathyanarayan Rao2017年8月10日
有人知道吗? a fast and accurate implementation for converting a binary image into a 2D triangulation ? As an example consider the following image: http://tinypic.com/view.php?pic=25qulat&s=5 。代码应该能够将左图转换为右图像...
我自己做了一个实施,但老实说,这是一个(丑陋的)解决方法,我不再使用它。但是,它可以在少量时间内完成工作。
这是我的代码工作原理的一个示例:
%生成二进制图像
nx = 100;
NY = 100;
image_binary = phantom('Modified Shepp-Logan',nx)> 0;
% specify image domain
x = linspace(-1,1,nx);
y = -linspace(-1,1,纽约);
用零的%垫图像以在图像边界处启用边框
temp = zeros(size(image_binary)+2);
temp(2:end-1,2:end-1) = image_binary;
image_binary = temp;
x = [x(1) - (x(2)-x(1)),x,x(end)+(x(x(2)-x(1))];
y = [y(1)-(y(2)-y(1)), y, y(end)+(y(2)-y(1))];
[X,Y] = meshgrid(x,y);
%生成图像的边缘(从原始图像中减去图像)
image_binary_edge = image_binary-imerode(image_binary,strel('disk',,,,1));
%仅用一个邻居去除像素
image_binary_edge_filtered = imfilter(image_binary_edge,ones(3,3),'same');
image_binary_edge(image_binary_edge_filtered == 2)= 0;
%计算Image_binary_edge中的所有连接组件
cc = bwconncomp(image_binary_edge,8);
%初始化Delaunaytriangulation函数的向量
x_coor = [];
y_coor = [];
约束= [];
max_dist = sqrt((x(2)-x(1))^2+(y(2)-y(1))^2);
%循环在所有组件上
为了II = 1:cc.numobjects
current = cc.PixelIdxList{ii};
x_coor_current = X(current);
y_coor_current = Y(current);
% reorder coordinates such that they are ordered in a clockwise fashion
x_coor_reordered = zeros(size(x_coor_current));
y_coor_reordered = zeros(size(y_coor_current));
x_coor_reordered(1)= x_coor_current(1);
y_coor_reordered(1)= y_coor_current(1);
x_coor_current(1) = [];
y_coor_current(1)= [];
kk = 2;
while~isempty(x_coor_current)
[index,dist] = knnsearch([x_coor_current,y_coor_current],[x_coor_reordered(kk-1),y_coor_reordered(kk-1)]);
%如果dist对大,而当前像素不相邻
% pixel, this is why we do not at these pixels to the reordered
%向量
如果(dist> 2*max_dist)
x_coor_current(index) = [];
y_coor_current(index)= [];
别的
x_coor_reordered(kk) = x_coor_current(index);
y_coor_reordered(kk)= y_coor_current(index);
x_coor_current(index) = [];
y_coor_current(index)= [];
kk = kk + 1;
结尾
结尾
x_coor_reordered = x_coor_reordered(1:kk-1);%删除零条目
y_coor_reordered = y_coor_reordered(1:kk-1);%删除零条目
%仅获取所有边界样品的一半(这阻止了过度采样
% the border)
x_coor_reordered = x_coor_reordered(1:2:end);
y_coor_reordered = y_coor_reordered(1:2:end);
x_coor = [x_coor; x_coor_reordered];
y_coor = [y_coor;y_coor_reordered];
constraints_temp = [[length(constraints)+1:length(constraints)+length(x_coor_reordered)]',。。。
circshift([length(constraints)+1:length(constraints)+length(x_coor_reordered)]',-1)];
约束= [约束; constraints_temp];
结尾
% construct delaunay triangulation
dt = delaunayTriangulation(x_coor,y_coor,constraints);
%仅维护内部
内部= dt.isinterior();
%构建代表内部的三角剖分
tr =三角剖分(dt(内部,:),dt.points);
目前,所有顶点都位于二进制图像的边缘,
% therefore, sample vertices inside the binary image as well:
pointstemp = tr.points;
connectivityListtemp = tr.ConnectivityList;
pointsinside = zeros(size(X));
为了t = 1:size(ChincnitivityListTemp,1)
vertsXY = pointstemp(connectivityListtemp(t,:),:);
pointsinside = pointsinside | inpolygon(X,Y, vertsXY(:,1), vertsXY(:,2));
结尾
pointsinside(1:5:end,:) = 0;
pointsinside(2:5:end,:) = 0;
pointsinside(3:5:end,:) = 0;
PointInside(4:5:end,:) = 0;
PointInside(:,1:5:end)= 0;
PointInside(:,2:5:end)= 0;
pointsinside(:,3:5:end) = 0;
PointInside(:,4:5:end)= 0;
% construct the triangulation again
dt = delaunayTriangulation([x_coor;X(pointsinside==1)],[y_coor;Y(pointsinside==1)],constraints);
内部= dt.isinterior();
tr =三角剖分(dt(内部,:),dt.points);
% remove points which do not belong to triangle
点= tr.points;
connectivityList = tr.connectivityList;
II = 1;
while(ii <=长度(点))
如果(〜Isempty(find(ConnectivityList == ii,1)))))))
II = II + 1;
别的
Points(ii,:) = [];
connectivitionList(ChannevitivitionList> II)= ChangnitiveList(ChangnitiveList> II)-1;
结尾
结尾
tr =三角剖分(ConnectivityList,点);
%绘制结果
数字();
子图(1,2,1)
imshow(image_binary,[])
标题('Binary Image'
子图(1,2,2)
triplot(tr.connectivityList,tr.points(:1),tr.points(:,2))
标题('triangulation'

接受的答案

Sven
Sven 2013年8月28日
编辑:Sven 2013年8月28日
盖特,这就是我的做法。请注意我使用 isocontour 为了one step. Just a simple MATLAB "contour" call may also do the job, but that requires plotting to a figure so I went with an FEX function.
%获得二进制图像
i = phantom('Modified Shepp-Logan',nx)> 0;
用零的%垫图像以在图像边界处启用边框
temp = zeros(size(I)+2);
温度(2:end-1,2:end-1)= i;
i = temp;
% Get an isocontour
轮廓线= 0.5;
[Lines,Vertices,Objects] = isocontour(I,contourThreshold);
Vertices = fliplr(Vertices);% Get it back in XY from IJ
%三角剖分Isocontour中的所有PT,并检查哪些三重分输入/输出
DT = delaunayTriangulation(Vertices);
fc = dt.incenter;
in = Interp2(i,fc(::,1),fc(::,2))> =轮廓tresthreshold;
% Show the result
图,imagsc(i),保持on,,,,
修补('vertices',,,,DT.Points,'faces',,,,DT.ConnectivityList(in,:),“ faceColor”,,,,'g'
修补('vertices',,,,DT.Points,'faces',,,,DT.ConnectivityList(~in,:),“ faceColor”,,,,'c'
plot(fc(in,1),fc(in,2),'b。',,,,fc(~in,1),fc(~in,2),'y.'
为了i=1:length(Objects)
点=对象{i};
绘图(顶点(点,1),顶点(点,2),,'颜色',,,,'M');
结尾
请注意,您也可以通过 bwperim 而不是Isocontour ...看起来像:
% Get an isocontour
[a,b] = find(bwperim(i));
Vertices = [b,a];
%三角剖分Isocontour中的所有PT,并检查哪些三重分输入/输出
DT = delaunayTriangulation(Vertices);
fc = dt.incenter;
in = Interp2(i,fc(::,1),fc(::,2))== 1;
% Show the result
图,imagsc(i),保持on,,,,
修补('vertices',,,,DT.Points,'faces',,,,DT.ConnectivityList(in,:),“ faceColor”,,,,'g'
修补('vertices',,,,DT.Points,'faces',,,,DT.ConnectivityList(~in,:),“ faceColor”,,,,'c'
plot(fc(in,1),fc(in,2),'b。',,,,fc(~in,1),fc(~in,2),'y.'
And if you were going for minimal traingulation, you could try something like this:
% Get a reduced set of boundary vertices
bb = bwboundaries(I);
为了k = 1:长度(bb)
dp = diff(bb {k},[],1);
pdiff = bsxfun(@rdivide, dP, sum(abs(dP),2));
idx = find(任何(pdiff -pdiff -circshift(pdiff,1),2));
bb {k} = bb {k}(idx,:);
结尾
顶点= fliplr(cat(1,bb {:}));
%三角剖分Isocontour中的所有PT,并检查哪些三重分输入/输出
DT = delaunayTriangulation(Vertices);
fc = dt.incenter;
in = Interp2(i,fc(::,1),fc(::,2))> 0;
图,imagsc(i),保持on,,,,
修补('vertices',,,,DT.Points,'faces',,,,DT.ConnectivityList(in,:),“ faceColor”,,,,'g'
修补('vertices',,,,DT.Points,'faces',,,,DT.ConnectivityList(~in,:),“ faceColor”,,,,'c'
plot(fc(in,1),fc(in,2),'b。',,,,fc(~in,1),fc(~in,2),'y.'
1条评论
盖特
盖特 2013年8月29日
Thx Sven,这为我提供了一些完成工作的好方法。非常感谢!顺便说一句,我也提高了代码的鲁棒性,我对问题进行了适当的调整...

Sign in to comment.

更多答案(2)

Anand
Anand on 24 Aug 2013
Try using bwperim and delaunay. Something like this:
BW = bwperim(im);
[x,y] = find(bw);
tri = delaunay(x,y);
希望这可以帮助!
2条评论
盖特
盖特 2013年8月28日
Sven,
I've cleaned up my code and put it in a single m-file. I added it to my question. Suggestions for speed-up, improved robustness, etc. are very welcome!

Sign in to comment.


Sathyanarayan Rao
Sathyanarayan Rao 2017年8月10日
检查使用GMSH的代码
https://nl.mathworks.com/matlabcentral/fileexchange/61507-binary-image-to-finite-element-mesh---gmsh-geo-file--?s_tid=prof_contriblnk

社区寻宝

在Matlab Central中找到宝藏,发现社区如何为您提供帮助!

开始狩猎!