Find contour/edge in pcolor in Matlab
我正在尝试在Matlab的
请注意,这是一个
因此,输出轮廓(绿线)穿过像素脸部(红点)的中点。
请注意,我不希望轮廓跟随数据的中心点(黑点),而这样做会像这样的绿线。使用
另外,如果有帮助,我可以提供一些网格。我在像素中间有个点(很明显,这就是我在此处绘制的点),在角上也有点,在西/东面和北/南面上也有点。如果您熟悉Arakawa网格,则这是Arakawa-C网格,因此我有rh-,u-,v-和psi-点。
我已经尝试过插值,交织网格和其他一些事情,但是我没有任何运气。任何帮助将不胜感激,并将阻止我发疯。
干杯,戴夫
编辑:
抱歉,我简化了图像以使我想解释的内容更加明显,但这是我要分离的区域的较大图像(放大后):
如您所见,它是一个复杂的轮廓,在环绕并移回"东北"之前朝着"西南"方向前进。这是我想通过黑点画的红线:
您可以通过对我发布到相关问题的解决方案进行一些修改来解决此问题。我在问题
1 2 3 | x = 1:15; % X coordinates for pixels y = 1:17; % Y coordinates for pixels mask = imfill(data, 'holes'); |
接下来,使用我的其他答案中的方法来计算轮廓坐标的有序集合(位于像素角上):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | % 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 |
最后,您可以在像素边缘的中心处获得所需的坐标,如下所示:
这是显示结果的图:
1 2 3 4 5 6 |
看下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | % 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') |
它产生此:
这是您要找的东西吗?
上面最重要的几行是:
它找到每一行在0到1之间转换的位置(假设一行中只有一个)。
然后,在
编辑:
经过对此类数据的一些试验,我得到了以下结果:
1 2 3 4 5 6 7 8 9 10 11 | 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') |
它并不完美,但是可以通过更简单的方法使您更接近所需的内容:
好的,我想我已经解决了……距离足够近,可以开心。
首先,我获取原始数据(我称其为
1 2 3 4 5 6 7 8 9 10 11 |
然后,我制作修改的蒙版
1 2 3 | %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的位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | % 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 |
结果将获取边界边缘的所有坐标:
现在我的回答有点不对劲。如果将上面的矢量绘制为点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | % 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); |
请注意,
老实说,没有界限的绘图就可以了。就我而言,这已经足够接近答案了!