6

私は、砂浜のような騒々しい背景(砂のために騒々しい)のような騒がしい背景で、ゴミやランダムゴミを検出するコンピュータビジョンプログラムを作成しようとしています。ノイズの多い背景で小さなオブジェクトを検出することが困難です。これを修正する方法はありますか?

オリジナル画像:任意の画像処理なし

enter image description here

キャニーエッジ検出:

enter image description here

Iは、画像処理技術の特定の組み合わせは、私は私の目標を達成するのに役立ちますことを実現騒々しい砂の背景を無視し、地上のゴミや物をすべて検出します。

私は遊んで、ぼかしの中央値をプリフォームしようとしたチューニングパラメータを、そしてそれは私にこれを与えた:

enter image description here

それは砂の背景を無視するという点でもプリフォームが、それはいくつかの検出に失敗しますおそらくそれがぼやけている(あまり確かではない)ため、地面にある他の多くの物体のことです。

ノイズの多い砂地の背景を無視し、すべてのオブジェクトを見つけて、すべてのオブジェクトで輪郭を検出して輪郭を描くことができるようにしながら、アルゴリズムや画像処理技術を改善する方法はありますか?

コード:

from pyimagesearch.transform import four_point_transform 
from matplotlib import pyplot as plt 
import numpy as np 
import cv2 
import imutils 

im = cv2.imread('images/beach_trash_3.jpg') 


#cv2.imshow('Original', im) 

# Histogram equalization to improve contrast 




### 
#im = np.fliplr(im) 

im = imutils.resize(im, height = 500) 

imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) 

# Contour detection 
#ret,thresh = cv2.threshold(imgray,127,255,0) 

#imgray = cv2.GaussianBlur(imgray, (5, 5), 200) 
imgray = cv2.medianBlur(imgray, 11) 

cv2.imshow('Blurred', imgray) 

''' 
hist,bins = np.histogram(imgray.flatten(),256,[0,256]) 
plt_one = plt.figure(1) 
cdf = hist.cumsum() 
cdf_normalized = cdf * hist.max()/ cdf.max() 

cdf_m = np.ma.masked_equal(cdf,0) 
cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min()) 
cdf = np.ma.filled(cdf_m,0).astype('uint8') 
imgray = cdf[imgray] 

cv2.imshow('Histogram Normalization', imgray) 
''' 
''' 
imgray = cv2.adaptiveThreshold(imgray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\ 
      cv2.THRESH_BINARY,11,2) 
''' 

thresh = imgray 

#imgray = cv2.medianBlur(imgray,5) 
#imgray = cv2.Canny(imgray,10,500) 
thresh = cv2.Canny(imgray,75,200) 
#thresh = imgray 
cv2.imshow('Canny', thresh) 


contours, hierarchy = cv2.findContours(thresh.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 

cnts = sorted(contours, key = cv2.contourArea, reverse = True)[:5] 

test = im.copy() 
cv2.drawContours(test, cnts, -1,(0,255,0),2) 
cv2.imshow('All contours', test) 

print '---------------------------------------------' 
##### Code to show each contour ##### 
main = np.array([[]]) 
for c in cnts: 
    epsilon = 0.02*cv2.arcLength(c,True) 
    approx = cv2.approxPolyDP(c,epsilon,True) 

    test = im.copy() 
    cv2.drawContours(test, [approx], -1,(0,255,0),2) 
    #print 'Contours: ', contours 
    if len(approx) == 4: 
     print 'Found rectangle' 
     print 'Approx.shape: ', approx.shape 
     print 'Test.shape: ', test.shape 

     # frame_f = frame_f[y: y+h, x: x+w] 
     frame_f = test[approx[0,0,1]:approx[2,0,1], approx[0,0,0]:approx[2,0,0]] 

     print 'frame_f.shape: ', frame_f.shape 
     main = np.append(main, approx[None,:][None,:]) 
     print 'main: ', main 


    # Uncomment in order to show all rectangles in image 
    #cv2.imshow('Show Ya', test) 


    #print 'Approx: ', approx.shape 
    #cv2.imshow('Show Ya', frame_f) 
    cv2.waitKey() 
print '---------------------------------------------' 
cv2.drawContours(im, cnts, -1,(0,255,0),2) 
print main.shape 
print main 
cv2.imshow('contour-test', im) 
cv2.waitKey() 
+0

どのアルゴリズムを使用するかについての質問をしているように見えるので、質問が話題にならないかどうかはわかりません。 –

+0

さて、私はそれをupvoted。 –

+1

グレースケール画像ではなく、HSV画像(Hチャンネル)でぼかしとキャニーを試してください。そして/またはメディアンの代わりにバイラテラルフィルターを使用します。 – Micka

答えて

3

私があなたの問題から理解しているのは、本質的に可変である背景からフォアグラウンドオブジェクトをセグメント化することです(砂のグレーレベルは他の多くの条件に依存します)。

がこの種の問題にアプローチするためのさまざまな方法があります。

アプローチ1:

は、フォアグラウンドよりも数字で常にはるかになります一つのことは、背景色のピクセル、ことは明らかであるあなたのイメージからは最も簡単な初期セグメンテーションを開始する方法は次のとおりです。

  1. イメージをグレーに変換します。
  2. ヒストグラムを作成します。
  3. ヒストグラムのピークインデックス、すなわち最大ピクセルを有するインデックスを見つける。
  4. のために、今、あなたが中心にこのインデックス値を入れて、25以上と以下のようにその周りにある範囲の値を取ることができ、3段階以上の

はあなたの背景のアイデアを与えるがゲームはここで終了されていません例:あなたのピークインデックスが(あなたの場合のように)あなたの場合のように75から225までのグレーレベルの範囲としきい値画像を選択すると、上記の方法の性質に従ってフォアグラウンドオブジェクトの検出に使用することができます。形態素解析のようないくつかの後処理ステップを実行して、オブジェクトの抽出後に異なるオブジェクトをセグメント化します。細かいレベルのセグメンテーションのためにいくつかの分類項目を適用して偽陽性を取り除くことができます。

アプローチ2:画像のピクセルのいくつかの統計で

プレイ、グレー値の小さいデータセットを作成し、

  1. ようにすることは、彼らに砂例1のクラス1および2を、ラベル
  2. 両方のクラスからのピクセルの平均と分散(標準偏差)を見つけ、両方のクラス(num_pix_per_class/total_num_pix)の確率を計算し、後で使用するためにこれらの統計を保存するようになりました。
  3. 画像に戻って、各ピクセルを1つずつ取り出し、ガウス分布pdf:1/2 * pi シグマ(exp( - (pix-mean)/ 2 * sigma))を適用します。平均を取る場所では平均を計算し、シグマは標準偏差で計算します。
  4. ステージ3を適用した後、2つのクラスの各ピクセルにつき2つの確率値が得られます。より高い確率を持つクラスを選択するだけです。

アプローチ3:あなたは、セグメントに砂型テクスチャをいくつかのテクスチャベースの操作を使用することができますが、テクスチャベースの方法を適用するために、私はより教師付き分類をお勧めします:

アプローチ3は、2つ以上のより複雑です教師なし(k-meansなど)。あなたが使用することができます 異なるテクスチャ特徴は以下のとおりです。

基本:定義された近所のグレーレベルの

  1. レンジ。
  2. 局所平均および分散またはエントロピー。
  3. グレイレベル共起行列(GLCM)。

高度:

  1. ローカルバイナリパターン。
  2. ウェーブレット変換。
  3. ガボール変換。など

PS:私の意見であなたはそれが仕事の多くを解決することができます1と2に近づくために試してみる必要があります。 :)

2

がより良い結果を得るためにあなたは多くのアルゴリズムを適用する必要があります。 OpenCVチュートリアルは、常にOpenCVの1つの機能に焦点を当てています。実際のCVアプリケーションでは、できるだけ多くのテクニックとアルゴリズムを使用する必要があります。

私は騒々しい写真で生物細胞を検出するのに使用しましたし、私はいくつかのコンテキスト情報適用し、非常に良い結果得た:細胞の

  • 予想サイズを
  • 全ての細胞が持っているという事実と同様のサイズ
  • 期待されるセル数 私は多くのパラメータを変更し、私が探しているものを検出しようとしました。

エッジ検出を使用する場合、砂はむしろランダムな形状を示します。 cannyのパラメータを変更し、線、矩形、円、etsを検出しようとします。 - どんな形であっても、ごみの可能性が高い。検出されたオブジェクトの位置を各パラメータセットと位置に記憶し、形状が最も頻繁に検出された位置(エリア)に優先順位を与えます。

色分解を使用してください。色 - ヒストグラムのピークは、砂の色の分布がより均一でなければならないため、ゴミのヒントになる可能性があります。あなたがobject matchingを適用することができ、タバコ、スタブのようないくつかのしばしば登場する、小さなオブジェクトの場合

P.S: クールなアプリケーション!好奇心から出てきたユースは、クワドコプターでビーチをスキャンしようとしていますか?

+0

複数の検出器を体系的に結合する方法について、他の参考文献がありますか? – Micka

+1

いいえ、ハードコードされている部分もありますが、SVMを使った部分もあります。最初はOpenCVの "適切な使用準備ができているソリューション"を探して、 "ホイールを再発明しない"ために多くの時間を費やしました。最後に私のコードとOpenCVの組み合わせを使用しました。後でOpenCVの専門家が私に確認しましたが、OpenCVを文字通り使用しないようにしました。彼らはすべてのユースケースについて考えることはできません。私は文脈やドメインの情報を考慮することができるために、自動的に機能の選択を実装しました。 –

0

このような均一な背景でオブジェクトを検出したい場合は、まず画像内の主な色を検出する必要があります。あなたがすべての砂を探知し、その物体は残りの部分にあります。 Arnaud LeTrotterとLudovic Lluciaの両方でこのタイプの「主な色の検出」を使用した論文があります。

+1

背景は決して均一ではありません!砂は乾燥しているか濡れているかもしれませんが、砂の色は異なる場合があります。シャドー、時間は色がかなり変わるなどです。 –

+0

与えられたイメージのために均一でなければなりません!彼らが使用するアルゴリズムは、各画像で計算されます。一度ではありません。 – FiReTiTi

関連する問題