我使用regionprops函数来检测无人机拍摄的图像上的树木数量。
但是区域15存在问题,因为该区域上的所有树都已连接,并且它检测为一棵树。 我尝试使用Watershed Segmentation分隔该区域的树,但它不起作用:
我这样做是错误的吗? 是否有更好的方法来分离树木?
答案 0 :(得分:7)
问这个问题已经有一段时间了。我希望答案还为时不晚。我看到在类似问题中使用分水岭分割的一般问题。有时物体是分开的,彼此不接触like in this example。在这种情况下,仅模糊图像就足以使用分水岭分割。有时物体彼此靠近并相互接触,因此物体的边界不清晰like in this example。在这种情况下,使用距离变换 - >模糊 - >分水岭有帮助。在这个问题中,逻辑方法应该是使用距离变换。然而,这次由于树木上和附近的阴影,边界不清晰。在这种情况下,最好使用任何有助于分离对象as in here或强调对象本身的信息。
在这个问题中,我建议使用颜色信息来强调树像素 以下是MATLAB代码和结果。
im=imread('https://i.stack.imgur.com/aBHUL.jpg');
im=im(58:500,86:585,:);
imOrig=im;
%% Emphasize trees
im=double(im);
r=im(:,:,1);
g=im(:,:,2);
b=im(:,:,3);
tmp=((g-r)./(r-b));
figure
subplot(121);imagesc(tmp),axis image;colorbar
subplot(122);imagesc(tmp>0),axis image;colorbar
%% Transforms
% Distance transform
im_dist=bwdist(tmp<0);
% Blur
sigma=10;
kernel = fspecial('gaussian',4*sigma+1,sigma);
im_blured=imfilter(im_dist,kernel,'symmetric');
figure
subplot(121);imagesc(im_dist),axis image;colorbar
subplot(122);imagesc(im_blured),axis image;colorbar
% Watershed
L = watershed(max(im_blured(:))-im_blured);
[x,y]=find(L==0);
figure
subplot(121);
imagesc(imOrig),axis image
hold on, plot(y,x,'r.','MarkerSize',3)
%% Local thresholding
trees=zeros(size(im_dist));
centers= [];
for i=1:max(L(:))
ind=find(L==i & im_blured>1);
mask=L==i;
[thr,metric] =multithresh(g(ind),1);
trees(ind)=g(ind)>thr*1;
trees_individual=trees*0;
trees_individual(ind)=g(ind)>thr*1;
s=regionprops(trees_individual,'Centroid');
centers=[centers; cat(1,[],s.Centroid)];
end
subplot(122);
imagesc(trees),axis image
hold on, plot(y,x,'r.','MarkerSize',3)
subplot(121);
hold on, plot(centers(:,1),centers(:,2),'k^','MarkerFaceColor','r','MarkerSize',8)
答案 1 :(得分:1)
您可以尝试基于标记的分水岭。根据我的经验,香草流域变换从未开箱即用。执行一种方法的一种方法是首先使用imdist()创建分割区域的距离图。然后你可以通过调用imhmax()来抑制局部最大值。然后调用watershed()通常会表现得更好。
以下是有关如何操作的示例脚本:
bwTrees = imopen(bwTrees, strel('disk', 10));
%stabilize the borders to lessen oversegmentation
distTrees = -bwDist(~bwTrees); %Distance transform
distTrees(~bwTrees) = -Inf; %set background to -Inf
distTrees = imhmin(distTrees, 3); %suppress local minima
basins = watershed(distTrees);
ridges = basins == 0;
segmentedTrees = bwTrees & ~ridges; %segment
segmentedTrees = imopen(segmentedTrees, strel('disk', 2));
%remove 'segmentation trash' caused by oversegmentation near the borders.
我摆弄了大约10分钟的参数,但得到了相当差的结果:
你需要把工作投入其中。主要通过形态学进行预处理和后处理。如果您可以降低第一部分中分割的灵敏度,则更多曲率将有助于分割。 h-minima变换的大小也是感兴趣的参数。你可以用这种方式获得足够的结果。
可能更好的方法来自群集技术的世界。如果您已经或者可以找到估算林中树木数量的方法,那么您应该能够使用传统的聚类方法来分割树木。如果你得到几乎合适数量的树木,那么高斯混合模型或具有k树的k均值可能比基于标记的分水岭更好。通常我会根据h-maxima变换上的抑制最大值数来估算树木的数量,但是你的标签可能有点过于香肠。不过值得一试。