10

変化するバックグラウンド強度で粒子を検出するための適切なアルゴリズムはありますか? たとえば、次の画像があるとします。

蛍光

左下に向かって明らかに異なる背景が表示されている場合でも、小さな白い粒子をカウントする方法はありますか?

もう少し明確にするために、画像にラベルを付けて、これらの粒子が重要であると判断するアルゴリズムを使用して粒子を数えたいと思います。

ラベル付き粒子

、、、、などのモジュールで多くのPILことを試しました。この非常によく似た SO questionからいくつかのヒントを得ました。一見すると、次のような単純なしきい値を使用できるように見えます。cvscipynumpy

im = mahotas.imread('particles.jpg')
T = mahotas.thresholding.otsu(im)

labeled, nr_objects = ndimage.label(im>T)
print nr_objects
pylab.imshow(labeled)

しかし、背景が変化するため、次のようになります。 bad_threshold_image

また、足を測定するために見つけたテクニックなど、他のアイデアも試しました。この方法で実装しました。

import numpy as np
import scipy
import pylab
import pymorph
import mahotas
from scipy import ndimage
import cv


def detect_peaks(image):
    """
    Takes an image and detect the peaks usingthe local maximum filter.
    Returns a boolean mask of the peaks (i.e. 1 when
    the pixel's value is the neighborhood maximum, 0 otherwise)
    """

    # define an 8-connected neighborhood
    neighborhood = ndimage.morphology.generate_binary_structure(2,2)

    #apply the local maximum filter; all pixel of maximal value 
    #in their neighborhood are set to 1
    local_max = ndimage.filters.maximum_filter(image, footprint=neighborhood)==image
    #local_max is a mask that contains the peaks we are 
    #looking for, but also the background.
    #In order to isolate the peaks we must remove the background from the mask.

    #we create the mask of the background
    background = (image==0)

    #a little technicality: we must erode the background in order to 
    #successfully subtract it form local_max, otherwise a line will 
    #appear along the background border (artifact of the local maximum filter)
    eroded_background = ndimage.morphology.binary_erosion(background, structure=neighborhood, border_value=1)

    #we obtain the final mask, containing only peaks, 
    #by removing the background from the local_max mask
    detected_peaks = local_max - eroded_background

    return detected_peaks

im = mahotas.imread('particles.jpg')
imf = ndimage.gaussian_filter(im, 3)
#rmax = pymorph.regmax(imf)
detected_peaks = detect_peaks(imf)
pylab.imshow(pymorph.overlay(im, detected_peaks))
pylab.show()

しかし、これも運が悪く、次の結果を示しています。

bad_result_from_detect_peaks

地域の最大関数を使用して、正しい粒子識別を行っているように見える画像を取得しますが、ガウス フィルタリングに応じて、間違った場所に粒子が多すぎたり少なすぎたりします (画像のガウス フィルターは 2,3, & 4):

2 のガウス 3 のガウス 4 のガウス

また、次のような画像でも動作する必要があります。

蛍光

これは上の画像と同じタイプですが、粒子の密度がはるかに高いだけです。

編集:解決済みの解決策: 次のコードを使用して、この問題に対するまともな解決策を得ることができました:

import cv2
import pylab
from scipy import ndimage

im = cv2.imread('particles.jpg')
pylab.figure(0)
pylab.imshow(im)

gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5,5), 0)
maxValue = 255
adaptiveMethod = cv2.ADAPTIVE_THRESH_GAUSSIAN_C#cv2.ADAPTIVE_THRESH_MEAN_C #cv2.ADAPTIVE_THRESH_GAUSSIAN_C
thresholdType = cv2.THRESH_BINARY#cv2.THRESH_BINARY #cv2.THRESH_BINARY_INV
blockSize = 5 #odd number like 3,5,7,9,11
C = -3 # constant to be subtracted
im_thresholded = cv2.adaptiveThreshold(gray, maxValue, adaptiveMethod, thresholdType, blockSize, C) 
labelarray, particle_count = ndimage.measurements.label(im_thresholded)
print particle_count
pylab.figure(1)
pylab.imshow(im_thresholded)
pylab.show()

これにより、次のような画像が表示されます。

粒子_与えられた (与えられた画像です)

カウントされた粒子

(これはカウントされた粒子です)

粒子数を 60 として計算します。

4

2 に答える 2

6

Adaptive Contrastと呼ばれる手法で調整された差分しきい値を使用して、「背景の可変輝度」を解決しました。これは、グレースケール画像とそれ自体のぼかしバージョンとの線形結合 (この場合は差分) を実行し、それにしきい値を適用することによって機能します。

  1. 適切な統計演算子を使用してイメージを畳み込みます。
  2. 必要に応じて強度スケール/ガンマを修正し、畳み込み画像からオリジナルを減算します。
  3. 差分画像を定数でしきい値処理します。

(原紙)

scipy.ndimage次のように、浮動小数点ドメインでこれを非常にうまく実行しました(整数画像処理よりも良い結果が得られました)。

original_grayscale = numpy.asarray(some_PIL_image.convert('L'), dtype=float)
blurred_grayscale = scipy.ndimage.filters.gaussian_filter(original_grayscale, blur_parameter)
difference_image = original_grayscale - (multiplier * blurred_grayscale);
image_to_be_labeled = ((difference_image > threshold) * 255).astype('uint8')  # not sure if it is necessary

labelarray, particle_count = scipy.ndimage.measurements.label(image_to_be_labeled)

お役に立てれば!!

于 2013-04-22T18:39:27.710 に答える
3

明確な答えを出すことはできませんが、以下にいくつかのヒントを示します。

  1. この関数mahotas.morph.regmaxは、疑似最大値を削除するため、最大フィルターよりも優れている可能性があります。おそらく、これをグローバルしきい値、ローカルしきい値 (ウィンドウの平均など)、またはその両方と組み合わせます。

  2. 複数の画像と同じ不均一な背景がある場合は、平均的な背景を計算してそれに対して正規化するか、空の画像を背景の推定値として使用できます。これは、顕微鏡を持っている場合に当てはまります。私が見たすべての顕微鏡と同様に、照明は不均一です。

何かのようなもの:

average = average_of_many(images)
# smooth it
average = mahotas.gaussian_filter(average,24)

次のように、画像を前処理します。

preproc = image/average

またはそのようなもの。

于 2013-04-20T15:48:37.893 に答える