-1

半径の 1 つのベクトルと数百の[X,Y]座標の 2 番目のベクトルがあります。可能な座標と半径のペアごとに、入力バイナリ イメージの円 (中心が座標に配置されている) 内のすべての黒いピクセルをカウントしました。

それを行う最も速い方法は何ですか?私の唯一のアイデアは、画像のすべてのピクセルを反復処理し、円の方程式を確認してからピクセルの色を確認することですが、そのような数百の操作にはあまり最適化されていないようです。

4

2 に答える 2

1

1 つの実装を次に示します。

利点:

  • いいえloopsmeshgrid/ndgrid。代わりに、より速くbsxfunpdist2

  • 円が重なっても、ドットは 1 回だけカウントされます。

  • 使用する変数radius(すべての円の半径は同じではありません)

コード:

%// creating a binary image with little black dots
A = randi(600,256); 
imbw = A ~= 1;

%// Your binary image with black dots
imshow(imbw);

%// getting the index of black dots
[dotY, dotX] = find(~imbw);

nCoords = 10;               %// required number of circles

%// generating its random coordinates as it is unknown here
Coords = randi(size(A,1),nCoords,2);

%// calculating the distance from each coordinate with every black dots
out = pdist2(Coords,[dotX, dotY]).';  %//'

%// Getting only the black dots within the radius
%// using 'any' avoids calculating same dot twice
radius = randi([10,25],1,size(Coords,1));
pixelMask = any(bsxfun(@lt, out, radius),2);
nPixels = sum(pixelMask);

%// visualizing the results by plotting
hold on
scatter(dotX(pixelMask),dotY(pixelMask));
viscircles([Coords(:,1),Coords(:,2)],radius.');    %//'
hold off

出力:

>> nPixels

nPixels =

19

ここに画像の説明を入力

于 2015-05-23T13:44:23.983 に答える
1

Matlab は、行列構文のおかげで画像の操作に最適です。インデックスでも機能するため、ほとんどの場合、「ピクセルの反復処理」を回避できます (ただし、必要な場合もあります)。

各円内のすべてのピクセルをチェックし、2 回カウントされたピクセル数を検出する代わりに、画像と同じサイズのマスクを作成する別の方法があります。円ごとにこのマスクを非表示にし (重なり合うピクセルは 1 回だけ「非表示」にします)、元の画像にマスクを適用し、残りの照らされたピクセルを数えます。

例として、いくつかのサンプル データ、画像を取得する必要があります。

load trees
BW = im2bw(X,map,0.4);
imshow(BW)

木BW

20 個のランダムな点/円の座標 (点の数と最小/最大半径は簡単に変更できます):

%// still building sample data
s = size(BW) ;
npt = 20 ; Rmin=5 ; Rmax=20 ; %// problem constants

x = randi([1 s(2)]   ,npt,1); %// random X coordinates
y = randi([1 s(1)]   ,npt,1); %//        Y
r = randi([Rmin Rmax],npt,1); %// radius size between 5 to 20 pixels.

次に、カスタム マスクを作成します。

%// create empty mask with enough overlap for the circles on the border of the image
mask = false( s+2*Rmax ) ; 

%// prepare grid for a sub-mask of pixels, as wide as the maximum circle
xmask = -Rmax:Rmax ; 
[xg,yg] = ndgrid(xmask,xmask) ;
rg = sqrt( (xg.^2+yg.^2) ) ;    %// radius of each pixel in the subgrid

for ip=1:npt
    mrow = xmask+Rmax+y(ip) ;  %// calc coordinates of subgrid on original mask
    mcol = xmask+Rmax+x(ip) ;  %// calc coordinates of subgrid on original mask

    cmask = rg <= r(ip) ;      %// calculate submask for this radius
    mask(mrow,mcol) = mask(mrow,mcol) | cmask ; %// apply the sub-mask at the x,y coordinates
end
%// crop back the mask to image original size (=remove border overlap)
mask = mask(Rmax+1:end-Rmax,Rmax+1:end-Rmax) ;
imshow(mask)

泡

次に、 mask と count を適用するだけです:

%% // Now apply on original image
BWm = ~BW & mask ; %// note the ~ (not) operator because you want the "black" pixels
nb_black_pixels = sum(sum(BWm)) ;
imshow(BWm)

nb_black_pixels =
        5283

木の仮面

于 2015-05-23T13:54:37.243 に答える