Leptonで人を検出する

これは、オープンソースのコンピュータビジョンライブラリ OpenCV を使用して、FLIR Leptonカメラで基本的な人を検出するアルゴリズムを実装するためのチュートリアルです。

目的

サーマルカメラは、ほぼすべての照明条件下で哺乳動物を見つけるのに優れています。機能を探る実践練習として、Leptonの視野にいる人を検出して、OpenCVでその人の周りにアウトラインを描いてみましょう。

ツール

必要なハードウェア:

  1. Lepton
  2. PureThermalボード
  3. Python 2.7環境にOpenCVバインドをインストールする これは、Windows、OSX、またはLinuxで設定できます。
  4. PIL - 画像を保存することができます。

セットアップ

Python環境の設定とOpenCVのインストールを行うには、お使いのプラットフォームに関するチュートリアルに従ってください。設定が完了したら、Webカメラストリームを表示して、すべての機能を確認します。

cv2をインポートする
cv2.namedWindow("プレビュー")
カメラID = 0
vc = cv2.VideoCapture(カメラID)

if vc.isOpened(): # 最初のフレーム取得を試みる
rval, frame = vc.read()
else:
rval = 誤

rval の場合:
cv2.imshow("プレビュー", フレーム)
rval, frame = vc.read()
key = cv2.waitKey(20)
if key == 27: # exit on ESC
改行

ストリームが表示されます。Webカメラが接続されている場合、またはコンピューターに内蔵されている場合、cameraIDを0以外の値に変更する必要がある場合があります。開発マシンのPureThermalボードIDは1です。

アプローチ

OpenCVのWebカメラのキャプチャーコードは、放射計の熱データを取得する能力はありませんが、ユーザー数の計算に理想的な形式で、PureThermal ボードから色付きのフィードを取得できます。わずかな前処理でアウトラインを描くのに十分な性能を発揮します。

特に、人間はデフォルトのカラーパレットで非常に明るい色として現れる傾向があるため、RGB画像をHSVに変換しVチャンネルを見ると、体温オブジェクトが場面のどこにあるのか、かなり明確に把握できます。

cv2.imshow("プレビュー"、フレーム) を次のように入れ替えてお試しください。

frame_hsv = cv2.cvtColor(frame, cv2.COLOR_RGB2HSV)
frame_v = frame_hsv[:,:,,2]
cv2.imshow("プレビュー", frame_v)

人がいる場所は、今や明らかになっています。コンピュータ・ビジョンを使えるものも揃っています。

OpenCVの入力

OpenCV は、Python にバインドされた C++ 用の非常に人気のあるコンピュータ・ビジョン・ライブラリです。これは、さまざまな一般的なコンピュータ・ビジョン操作を提供し、これを使用してアウトラインを描きます。

まずは、キャニーエッジ検出から始めましょう。これは、画像内のエッジを見つけるための堅牢な技術です。

OpenCV が次のコードで検出したエッジを表示します。

しきい値 = 50
edges = cv2.Canny(frame_v,thresh,thresh*2, L2gradient=True)
cv2.imshow("プレビュー", エッジ)

しかし、これはあまり良いとは言えません。エッジ検出は、高周波数ノイズを多く拾い過ぎるため、エッジとして誤検知しています。少し画像をスムージングすることで整理できるはずです。両側フィルターと呼ばれる、エッジ保存の画像スムージング法を使用します。これはガウスぼかしのようなものですが、最初に見つけようとしていたエッジへの影響は減少します。

blurredBrightness = cv2.bilateralFilter(frame_v,9,150,150)
しきい値 = 70
edges = cv2.Canny(blurredBrightness,thresh,thresh*2, L2gradient=True)
cv2.imshow("プレビュー", エッジ)

これはよりよく見えますが、まだ改善の余地があります。人として輪郭が描かれている照度のようなものを減らしてみましょう。これには注意がいりますが、OpenCVはそれを行う方法を提供します。まず、元の画像にしきい値を付け、ピクセルが温かい場所には1を、そうでない場合は0 を付けてバイナリ画像を作成します。次に、OpenCVを使用して、その操作によって作成された1のブロブで腐食を除去します。その後、これらのブロブを、以前とほぼ同じサイズに拡張します。

_,mask = cv2.threshold(blurredBrightness,200,1,cv2.THRESH_BINARY)
erodeSize = 5
dilateSize = 7
npとしてnumpyをインポート
eroded = cv2.erode(mask, np.ones((erodeSize, erodeSize)))
mask = cv2.dilate(eroded, np.ones((dilateSize, dilateSize)))

侵食と拡張の後、バイナリー画像は基本的に同じままになりますが、小さな形状はすべて取り除かれます。まさに、それが私たちが望むものです。小さな形状のエッジをすべてマスクするのに使用できます。

では、検出されたエッジにこれを適用した場合の様子を見てみましょう。

悪くないですね! また、ソース画像にも非常によく重ねられています。

最後のコードは、こんな感じです。定数を好みに合わせて調整する必要があるかもしれません。また、OpenCV は、特定のニーズに合わせて結果を改善するために使用できるさまざまなツールを提供します。

インポート cv2
npとしてnumpyをインポート
cv2.namedWindow("プレビュー")
カメラID = 0
vc = cv2.VideoCapture(カメラID)

if vc.isOpened(): # 最初のフレーム取得を試みる
rval, frame = vc.read()
else:
rval = 誤

rval の場合:
frame_v = cv2.cvtColor(frame, cv2.COLOR_RGB2HSV)[:,:,2]

blurredBrightness = cv2.bilateralFilter(frame_v,9,150,150)
しきい値 = 50
edges = cv2.Canny(blurredBrightness,thresh,thresh*2, L2gradient=True)

_,mask = cv2.threshold(blurredBrightness,200,1,cv2.THRESH_BINARY)
erodeSize = 5
dilateSize = 7
eroded = cv2.erode(mask, np.ones((erodeSize, erodeSize)))
mask = cv2.dilate(eroded, np.ones((dilateSize, dilateSize)))

cv2.imshow("プレビュー", cv2.resize(cv2.cvtColor(mask*edges, cv2.COLOR_GRAY2RGB) | フレーム, (640, 480), 補間 = cv2.INTER_CUBIC))

rval, frame = vc.read()
key = cv2.waitKey(20)
if key == 27: # exit on ESC
改行

関連記事