12

以下のような写真があり、Python で表示されるバグ (色/灰色の連続した塊) の数を数えたいと思います。どうすればこれを最もうまく行うことができますか?

騒々しい背景のバグ

これまでImageChops、SciPy、PILを見てきましたが、何を使用できる/すべきかわかりません...

私は使用できると思いますがndimage.gaussian_filter()scipy.ndimage.measurements.label()後者を使用してガウス化された画像の青い点をカウントする方法はまだわかりません...次のようになりますここに画像の説明を入力


わかった、

上の画像で、次のコードを取得しました。

#! /usr/bin/python

import numpy as np
import scipy
import pylab
import pymorph
import mahotas
from PIL import Image
import PIL.ImageOps
from scipy import ndimage

image = Image.open('bugs.jpg')   
inverted_image = PIL.ImageOps.invert(image)    
inverted_image.save('in_bugs.jpg')
dna = mahotas.imread('in_bugs.jpg')
#pylab.imshow(dna)
pylab.gray()
#pylab.show()
T = mahotas.thresholding.otsu(dna)
pylab.imshow(dna > T)
#pylab.show()
dnaf = ndimage.gaussian_filter(dna, 8)
T = mahotas.thresholding.otsu(dnaf)
pylab.imshow(dnaf > T)
#pylab.show()
labeled,nr_objects = ndimage.label(dnaf > T)
print nr_objects
pylab.imshow(labeled)
pylab.jet()
pylab.show()

問題は、これが 5 という数字を返すことです。これはそれほど悪いことではありませんが、もっと正確にする必要があります。2 つ見たいのです。これどうやってするの?ガウス フィルターを適用する前に画像をぼかすと効果がありますか?

手伝ってくれてありがとう!

ロン

4

2 に答える 2

13

あなたのガウスフィルタリングはすでにほとんど問題ありませんが、タスクに必要なよりも大きな半径を検討しています。たとえば、例として半径 15 のカーネルを考えてみましょう。得られるものの表現を次に示します。

ここに画像の説明を入力

2 つの明確な谷があり (はい、代わりにピークとして表示されます)、フィルター処理された画像のヒストグラムは、使用可能なデータのほとんどが可能な最大値に近づいていることを示しています。

ここに画像の説明を入力

ヒストグラムの一部のみを考慮すると、関心のあるデータの部分、つまり暗いスポットがよくわかります。

ここに画像の説明を入力

したがって、単純なしきい値を使用0.5すると、結果は次のようになります (バグの場所と一致します)。

ここに画像の説明を入力

関連する機能をどのように実装するか (または使用するライブラリを実装するか) によって、このしきい値は異なります。しかし、ヒストグラムを見ると、適切なしきい値を見つけることができます。ここで、ヒストグラムを見てこのしきい値を推測したくない場合は、ガウス フィルタリングを超えて画像を前処理する必要があります。このステップを適切に行うことで、イメージは十分に単純になり、Otsu によって提供されたような方法で、目的のしきい値を自動的に見つけることができます。モルフォロジー クロージングに続いてモルフォロジー オープニングを実行し、次に Otsu で 2 値化すると、次の結果が得られます。

ここに画像の説明を入力

せいぜい輪郭をぼかす線形ローパス フィルターに依存していないため、形状は初期の形状に近くなっています。

編集:

質問にはいくつかのコードが含まれているため、大津をコードとして使用することがなぜ間違っているのかを説明する必要があると感じました。Otsu が示したしきい値処理の方法は、実際にはデータがバイモーダルであることを想定していますが、上記のヒストグラム プロットが示すように、ここでは当てはまりません。Otsu は右側の巨大なピークに近すぎるしきい値を提供しますが、0.5 の良い点はそこから非常に離れています。この回答に示されている最初の結果を再現するために、いくつかの基本的なコードを次に示します。

import sys
import numpy
from PIL import Image
from scipy.ndimage import gaussian_filter, label

img = Image.open(sys.argv[1]).convert('L')
im = numpy.array(img)

im_g = gaussian_filter(im, 3)
im_norm = (im_g - im_g.min()) / (float(im_g.max()) - im_g.min())
im_norm[im_norm < 0.5] = 0
im_norm[im_norm >= 0.5] = 1

result = 255 - (im_norm * 255).astype(numpy.uint8)
print u"Objects: %d" % label(result)[1]

Image.fromarray(result).save(sys.argv[2])

このコードはsigma = 3(もともと 7.5 が使用されていましたが) ガウス カーネルを使用していることに注意してください。ガウス カーネルは、scipy内部的にそれよりも 4 倍大きい半径のウィンドウを構築します。この特定の画像では、sigma2 から 10 までの広範囲の作業でも同じ結果が得られます (2 つのオブジェクトが検出されました)。

于 2013-01-26T02:00:01.380 に答える
3

これはコンピューター ビジョンのタスクであり、一般的なOpenCVで解決できます。

ノイズを除去するために、いくつかのモルフォロジー操作 (例:を開く) を使用して画像を処理することを検討することをお勧めします。おそらく、あるしきい値を超える面積を持つ連続したブロブの数を数えることができます。


調べる必要のあるリソース:

于 2013-01-25T22:20:09.343 に答える