MatLab - 分割以分离图像中的触摸对象
MatLab - Segmentation to separate touching objects in an image
我正在使用函数 regionprops 来检测无人机拍摄的图像上的树木数量。
首先,我使用蓝色 NDVI 去除了地面:
带阈值的图像:
然后我使用函数 regionprops 来检测图像上的树木数量:
但是区域 15 有问题,因为该区域的所有树都是相连的,它被检测为一棵树。
我尝试使用 Watershed Segmentation 分隔该区域的树木,但它不起作用:
我是不是做错了?
有没有更好的分离树的方法?
如果有人能帮我解决这个问题,我将不胜感激。这是没有地面的区域 15:
如果有帮助,这里是梯度幅值图像:
您可以尝试基于标记的分水岭。根据我的经验,Vanilla watershed 转换永远不会开箱即用。执行此操作的一种方法是首先使用 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 分钟的参数,但结果相当糟糕:
你需要为此付出努力。主要是通过形态学进行预处理和 post 处理。如果您可以降低第一部分中分割的灵敏度,则更大的曲率将有助于分割。 h-最小值变换的大小也是一个感兴趣的参数。这样你可能会得到足够的结果。
可能更好的方法来自聚类技术领域。如果你有或可以找到一种方法来估计森林中的树木数量,你应该能够使用传统的聚类方法来分割树木。如果您获得几乎正确数量的树,高斯混合模型或带有 k 树的 k 均值可能比基于标记的分水岭更好。通常我会根据 h-maxima 变换上抑制的最大值的数量来估计树的数量,但你的标签可能有点太香肠了。不过值得一试。
问这个问题已经有一段时间了。我希望现在回答还为时不晚。我看到在类似问题中使用分水岭分割的普遍问题。有时对象是分开的,没有相互接触 . In such cases, only blurring the image is enough to use watershed segmentation. Sometimes the objects are located closely and touch each other, thus the boundaries of objects are not clear . In such cases, using distance transform-->blur-->watershed helps. In this question, the logical approach should be using distance transform. However, this time the boundaries are not clear due to shadows on and nearby the trees. In such cases, it is good to use any information that helps to separate the objects 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)
我正在使用函数 regionprops 来检测无人机拍摄的图像上的树木数量。
首先,我使用蓝色 NDVI 去除了地面:
带阈值的图像:
然后我使用函数 regionprops 来检测图像上的树木数量:
但是区域 15 有问题,因为该区域的所有树都是相连的,它被检测为一棵树。 我尝试使用 Watershed Segmentation 分隔该区域的树木,但它不起作用:
我是不是做错了? 有没有更好的分离树的方法?
如果有人能帮我解决这个问题,我将不胜感激。这是没有地面的区域 15:
如果有帮助,这里是梯度幅值图像:
您可以尝试基于标记的分水岭。根据我的经验,Vanilla watershed 转换永远不会开箱即用。执行此操作的一种方法是首先使用 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 分钟的参数,但结果相当糟糕:
你需要为此付出努力。主要是通过形态学进行预处理和 post 处理。如果您可以降低第一部分中分割的灵敏度,则更大的曲率将有助于分割。 h-最小值变换的大小也是一个感兴趣的参数。这样你可能会得到足够的结果。
可能更好的方法来自聚类技术领域。如果你有或可以找到一种方法来估计森林中的树木数量,你应该能够使用传统的聚类方法来分割树木。如果您获得几乎正确数量的树,高斯混合模型或带有 k 树的 k 均值可能比基于标记的分水岭更好。通常我会根据 h-maxima 变换上抑制的最大值的数量来估计树的数量,但你的标签可能有点太香肠了。不过值得一试。
问这个问题已经有一段时间了。我希望现在回答还为时不晚。我看到在类似问题中使用分水岭分割的普遍问题。有时对象是分开的,没有相互接触
在这道题中,我建议使用颜色信息来强调树像素。
这是 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)