3

私はドローンで取り込まれた画像上のツリーの数を検出するためにregionprops関数を使用しています。 Original ImageMatLab - 画像内の接触しているオブジェクトを分離するためのセグメンテーション

まず私はブルーNDVIを使って地面を削除:しきい値と Image BNDVI

画像: Image with Threshold

それから私は、関数を使用した画像の上に木の数を検出するために、regionprops: Regionprops

しかし、領域15には問題があります。その領域上のすべてのツリーが接続され、1つのツリーとして検出されるためです。 私はWatershed Segmentationを使用して、その領域上の樹木を分離しようとしましたが、その作業はありません:

Watershed segmentation

私はこの間違った方法をやっていますか? ツリーを分離するためのより良い方法はありますか?

誰でもこの問題を解決することができたら、私は感謝します。それはここで、助け勾配の大きさの画像であれば Region 15

enter image description here

+0

**あなたは**どのように多くの木があります伝えることはできますか?もしそうなら、どうやってやったのですか。 – Shai

+0

確かに、手動でカウントすることもやりにくいので、画像に何本の木があるのか​​分かりません。しかし、地方自治体の機能によって、私はその地域の面積を知ることができます。そして、多くの場合、樹木は3000ピクセルの面積を持ち、研究対象地域は112,000ピクセルの面積を持つため、この地域には約37本の樹木があります。 –

答えて

4

この質問をしてからしばらくしています。答えが遅すぎることはないと思います。私は同様の質問で流域セグメンテーションを使用するという一般的な問題を抱えています。オブジェクトが離れていて、互いに触れ合わない場合もあります。like in this exampleそのような場合、画像をぼかすだけで、流域セグメンテーションを使用することができます。オブジェクトが密接に接してお互いに接触することがあるため、オブジェクトの境界は明確ではありませんlike in this example。そのような場合、distance transform - > blur - > watershedを使用すると便利です。この質問では、論理的アプローチは距離変換を使用する必要があります。しかし、今度は、樹木の上や近くの影によって境界がはっきりしない。このような場合、オブジェクト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) 

enter image description here

enter image description here

enter image description here

+0

SUPER! :D(15文字分制限) –

+0

この提案は間違いなく私を助け、私がこれまで持っていた最も近い近似を与えるでしょう。どうもありがとうございました –

1

あなたは、マーカーベースの流域を試してみることができここでは地面のない領域15があります。バニラ流域の変容は私の経験では決して変わらない。 imdist()を使用してセグメント化された領域の距離マップを最初に作成する方法があります。次に、imhmax()を呼び出すことでローカルな最大値を抑えることができます。次に、watershed()を呼び出すことは、通常、顕著に優れたパフォーマンスを発揮します。私は〜10分のパラメータの周りいじったが、かなり悪い結果だ

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. 

segmented trees

あなたがする必要があると思いをここで

はそれを行う方法についてのサンプルスクリプトですこれに仕事を注ぐ。主に、形態学的な前処理および後処理である。最初の部分でセグメンテーションの感度を下げることができれば、より多くの曲率がセグメンテーションに役立ちます。 h-minima変換のサイズも関心のあるパラメタです。あなたはおそらくこのように適切な結果を得ることができます。

おそらく、よりよいアプローチはクラスタリング技術の世界から来るでしょう。フォレスト内のツリーの数を見積もる方法がある場合、またはその方法を見つけることができれば、従来のクラスタリング方法を使用してツリーをセグメント化することができます。ガウス混合モデルやk-meansを使ったk-meansは、おそらく適切な量の木が得られれば、マーカーベースの流域よりもはるかに良く機能します。通常、私はh最大マキシマ変換で抑制された最大値の数に基づいてツリーの数を見積もりますが、あなたのラベルはあまりにもソーセージかもしれません。それは試してみる価値がある。

+0

提案していただきありがとうございます。私は試してみて、それが解決すればここに投稿します。 –

関連する問題