在Matlab中查找pcolor中的轮廓/边缘

我试图在Matlab中的pcolor图中制作一个跟随“像素”边缘的轮廓。 这可能是图片中最好的解释。 这是我的数据情节。 黄色数据(数据== 1)和蓝色数据(数据== 0)之间存在明显的界限:

Pcolor情节

请注意,这是一个pcolor图,所以每个“方形”本质上是一个像素。 我想返回一个跟随黄色数据像素面的轮廓, 不仅仅是黄色数据的边缘。

我想要这个输出

所以输出轮廓(绿线)通过像素的脸部中点(红点)。

请注意,我不想让轮廓跟随数据的中心点(黑点),这会做出像绿线这样的事情。 这可以通过contour轻松实现。

我不想要这个结果

另外,如果有任何帮助,我有几个可能有用的网格。 我有像素中间的点(很明显,因为这是我在这里绘制的),我也有角点,并且我有西/东面和北面/南面的点。 如果你熟悉荒川电网,这是一个荒川-C电网,所以我有rho-,u-,v-和psi-点。

我尝试过插值,交织网格和其他一些东西,但我没有任何运气。 任何帮助都会受到高度赞赏,并会阻止我发疯。

干杯,戴夫

编辑:

对不起,我简化了图片,使我想解释更明显,但这是一个更大(缩小)的图像我试图分开的区域: 缩小图像

正如你所看到的那样,这是一个复杂的轮廓,在“西北”方向前进,然后环绕并移回“东北方向”。 这里是我想通过黑点画出的红线:

预期的输出线


看看下面的代码:

% plotting some data:
data = [0 0 0 0 0 0 1 1
    0 0 0 0 0 1 1 1
    0 0 0 0 1 1 1 1
    0 0 0 0 0 1 1 1
    0 0 0 0 1 1 1 1
    0 0 0 0 1 1 1 1
    0 0 0 0 1 1 1 1];
p = pcolor(data);
axis ij
% compute the contour
x = size(data,2)-cumsum(data,2)+1;
x = x(:,end);
y = (1:size(data,1));
% compute the edges shift
Y = get(gca,'YTick');
y_shift = (Y(2)-Y(1))/2;
% plot it:
hold on
plot(x,y+y_shift,'g','LineWidth',3,'Marker','o',...
    'MarkerFaceColor','r','MarkerEdgeColor','none')

它产生这个:

这是你寻找的吗?

上面最重要的行是:

x = size(data,2)-cumsum(data,2)+1;
x = x(:,end);

它发现每一行在0到1之间移动的位置( 假设在一行中只有一个 )。

然后,在plot我将y移动两个相邻y轴刻度之间距离的一半,所以它们将被放置在边缘的中心。


编辑:

经过这些数据的一些试验后,我得到了这样的结果:

imagesc(data);
axis ij
b = bwboundaries(data.','noholes');
x = b{1}(:,1);
y = b{1}(:,2);
X = reshape(bsxfun(@plus,x,[0 -0.5 0.5]),[],1);
Y = reshape(bsxfun(@plus,y,[0 0.5 -0.5]),[],1);
k = boundary(X,Y,1);
hold on
plot(X(k),Y(k),'g','LineWidth',3,'Marker','o',...
    'MarkerFaceColor','r','MarkerEdgeColor','none')

这并不完美,但可能会以更简单的方式让你更接近你想要的东西:

在这里输入图像描述


您可以通过对发布到相关问题的解决方案进行一些修改来解决此问题。 我在data问题中使用了一段样本图像掩码。 首先,您需要填充蒙版中的孔,您可以使用图像处理工具箱中的imfill完成蒙版中的孔:

x = 1:15;  % X coordinates for pixels
y = 1:17;  % Y coordinates for pixels
mask = imfill(data, 'holes');

接下来,应用我的其他答案中的方法来计算一组有序的轮廓坐标(位于像素拐角处):

% Create raw triangulation data:
[cx, cy] = meshgrid(x, y);
xTri = bsxfun(@plus, [0; 1; 1; 0], cx(mask).');
yTri = bsxfun(@plus, [0; 0; 1; 1], cy(mask).');
V = [xTri(:) yTri(:)];
F = reshape(bsxfun(@plus, [1; 2; 3; 1; 3; 4], 0:4:(4*nnz(mask)-4)), 3, []).';

% Trim triangulation data:
[V, ~, Vindex] = unique(V, 'rows');
V = V-0.5;
F = Vindex(F);

% Create triangulation and find free edge coordinates:
TR = triangulation(F, V);
freeEdges = freeBoundary(TR).';
xOutline = V(freeEdges(1, [1:end 1]), 1);  % Ordered edge x coordinates
yOutline = V(freeEdges(1, [1:end 1]), 2);  % Ordered edge y coordinates

最后,您可以在像素边缘的中心获得所需的坐标,如下所示:

ex = xOutline(1:(end-1))+diff(xOutline)./2;
ey = yOutline(1:(end-1))+diff(yOutline)./2;

这里是一个显示结果的图表:

imagesc(x, y, data);
axis equal
set(gca, 'XLim', [0.5 0.5+size(mask, 2)], 'YLim', [0.5 0.5+size(mask, 1)]);
hold on;
plot(ex([1:end 1]), ey([1:end 1]), 'r', 'LineWidth', 2);
plot(ex, ey, 'k.', 'LineWidth', 2);

在这里输入图像描述


好吧,我想我已经解决了它......足够接近以开心。

首先,我将原始数据(我称之为mask_rho并使用它来制作蒙版mask_umask_v ,它类似于mask_rho但分别在水平和垂直方向稍稍移位。

%make mask_u and mask_v  
for i = 2:size(mask_rho,2)
for j = 1:size(mask_rho,1)
    mask_u(j, i-1) = mask_rho(j, i) * mask_rho(j, i-1);
end
end
for i = 1:size(mask_rho,2)
for j = 2:size(mask_rho,1)
    mask_v(j-1, i) = mask_rho(j, i) * mask_rho(j-1, i);
end
end

然后我使改性掩模mask_u1mask_v1它们是相同mask_rho但分别与相邻点在水平和垂直方向上平均化,。

%make mask which is shifted E/W (u) and N/S (v)
mask_u1 = (mask_rho(1:end-1,:)+mask_rho(2:end,:))/2;
mask_v1 = (mask_rho(:,1:end-1)+mask_rho(:,2:end))/2;

然后我使用掩模之间的差异来定位掩模在水平方向(在u掩模中)和在垂直方向(在v掩模中)从0变为1和1变为0的位置。

% mask_u-mask_u1 gives the NEXT row with a change from 0-1.
diff_mask_u=logical(mask_u-mask_u1);
lon_u_bnds=lon_u.*double(diff_mask_u);
lon_u_bnds(lon_u_bnds==0)=NaN;
lat_u_bnds=lat_u.*double(diff_mask_u);
lat_u_bnds(lat_u_bnds==0)=NaN;
lon_u_bnds(isnan(lon_u_bnds))=[];
lat_u_bnds(isnan(lat_u_bnds))=[];
%now same for changes in mask_v
diff_mask_v=logical(mask_v-mask_v1);
lon_v_bnds=lon_v.*double(diff_mask_v);
lon_v_bnds(lon_v_bnds==0)=NaN;
lat_v_bnds=lat_v.*double(diff_mask_v);
lat_v_bnds(lat_v_bnds==0)=NaN;
lon_v_bnds(isnan(lon_v_bnds))=[];
lat_v_bnds(isnan(lat_v_bnds))=[];
bnd_coords_cat = [lon_u_bnds,lon_v_bnds;lat_u_bnds,lat_v_bnds]'; %make into 2 cols, many rows

结果抓取边界边缘的所有坐标:

大多解决了..

现在我的答案有点错误。 如果我把上面的矢量plot(bnd_coords_cat(:,1),bnd_coords_cat(:,2),'kx'成点plot(bnd_coords_cat(:,1),bnd_coords_cat(:,2),'kx'我得到上面的图像,这很好,但是如果我加入这一行,如: plot(bnd_coords_cat(:,1),bnd_coords_cat(:,2),'-'然后线跳转,因为点不排序当我按sortpdist2排序最近的点选择奇怪的点......但我想我会包括这个代码作为附录,和可选的额外。有人可能知道一个更好的方法来排序输出向量bnds_coords_cat

% now attempt to sort
[~,I]=sort([lon_u_bnds,lon_v_bnds]);
bnd_coords_inc1 = bnd_coords_cat(I,1);
bnd_coords_inc2 = bnd_coords_cat(I,2);
bnd_coords = [bnd_coords_inc1,bnd_coords_inc2];
bnd_coords_dist = pdist2(bnd_coords,bnd_coords);
bnd_coords_sort = nan(1,size(bnd_coords,1));
bnd_coords_sort(1)=1;
for ii=2:size(bnd_coords,1)
 bnd_coords_dist(:,bnd_coords_sort(ii-1)) = Inf; %don't go backwards?
 [~,closest_idx] = min(bnd_coords_dist(bnd_coords_sort(ii-1),:));
 bnd_coords_sort(ii)=closest_idx;
end
bnd_coords_final(:,1)=bnd_coords(bnd_coords_sort,1);
bnd_coords_final(:,2)=bnd_coords(bnd_coords_sort,2);

请注意, pdist2方法是由同事建议的,也是从这个SO回答中,在matlab中排列坐标点。 这是最终的结果:

好的,排序有点麻烦

说实话,绘制没有线是好的。 所以就我而言,这足够接近于可以回答的问题!

链接地址: http://www.djcxy.com/p/67301.html

上一篇: Find contour/edge in pcolor in Matlab

下一篇: Draws the intersecting volume of two spheres in MATLAB?