質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

2919閲覧

水中の気泡をトラッキングしたい

tanaka_sa

総合スコア3

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/06/23 05:18

編集2021/06/24 05:09

前提・実現したいこと

Pthonコード作成1ヵ月の初心者です。

VBcodeでPython、OpenCVを使用して、水中カメラ映像で気泡を検出するシステムを作っています。
背景差分法(MOG2)で画面を2値化した後、ノイズ除去(cv2.medianBlur(img,5))、縮小処理を行いました。
気泡の座標取得は出来たのですが、気泡以外のノイズも拾っています。

気泡は下から上に移動しますので、
1.2値化することで、気泡検出する。
2.2値化した箇所の中心座標を取得する。
3.中止座標に沿って、移動物体にラインを引く。
4.縦方向のライン検査を行い、検出できればTrue返し、気泡と判断する。
ということを行いたいと考えております。

###発生している問題・エラーメッセージ

中心座標を取得することまでは出来たのですが、背景差分法では水中を漂うゴミ、水面等も拾ってしまいノイズとなってします。

中心座標に沿って線を引こうとしたのですが、「気泡と水面」、「水面とゴミ」等、ランダムに線を引いてしまい、実現出来ませんでした。※上記3が実現できておりません。

下から上に移動した座標(気泡)のみを取り出せれば実現可能なのではと思っているのですがなにか方法はないでしょうか。
ベクトルを取得出来ればよいのではと考えているのですが、参考となるサイトがわかりませんでした。

参考となるサイトだけでも教えていただければ幸いです。

※オプティカルフロー(コーナー検出)でコーナー検出の精度を調整すれば実現可能では、と思いましたが気泡にコーナーはありませんので、無理でした。

該当のソースコード

##初心者の為、読みづらいことについてはご容赦頂きたく存じます。

import numpy as np
import cv2
from numpy.lib.twodim_base import mask_indices

#カルマンフィルタ変数定義
meas=[]
pred=[]
mp = np.array((2,1), np.float32) # measurement
tp = np.zeros((2,1), np.float32) # tracked / prediction
kalman = cv2.KalmanFilter(4,2)
kalman.measurementMatrix = np.array([[1,0,0,0],[0,1,0,0]],np.float32)
kalman.transitionMatrix = np.array([[1,0,1,0],[0,1,0,1],[0,0,1,0],[0,0,0,1]],np.float32)
kalman.processNoiseCov = np.array([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],np.float32) * 0.03

#動画の読み込み
filepath = "img.mp4"
cap = cv2.VideoCapture(filepath)

##背景差分法の設定
fgbg = cv2.createBackgroundSubtractorMOG2()

def onmouse(x, y):
global mp,meas
mp = np.array([[np.float32(x)],[np.float32(y)]])
meas.append((x, y))

def paint():
global fgmask,meas,pred
for i in range(len(meas)-1):
img_paint1 = cv2.line(fgmask,meas[i],meas[i+1],(0,100,0))
for i in range(len(pred)-1):
img_paint2 = cv2.line(fgmask,pred[i],pred[i+1],(0,0,200))
return img_paint1, img_paint2

while(1):
ret, frame = cap.read()
frame = cv2.resize(frame,dsize=None,fx=0.5,fy=0.5)

#背景差分法の出力 fgmask = fgbg.apply(frame) #ノイズ除去処理 ksize=5 #中央値フィルタ fgmask = cv2.medianBlur(fgmask,ksize) # 縮小処理 # 近傍の定義 neiborhood = np.array([[0, 2, 0],[2, 2, 2],[0, 2, 0]], np.uint8) fgmask = cv2.erode(fgmask,neiborhood,iterations=2) # 中心位置の取得 # 複数の重心を計算 contours, _ = cv2.findContours(fgmask, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) for c in contours: M = cv2.moments(c) if M["m00"] == 0: # ゼロ除算回避 continue x = int(M["m10"] / M["m00"]) y = int(M["m01"] / M["m00"]) frame = cv2.circle(frame, (x, y), 4, 100, 2, 4) #カルマンフィルタ onmouse(x, y) kalman.correct(mp) tp = kalman.predict() pred.append((int(tp[0]),int(tp[1]))) for i in range(len(meas)-1): frame = cv2.line(frame,meas[i],meas[i+1],(0,100,0)) # for i in range(len(pred)-1): # frame = cv2.line(frame,pred[i],pred[i+1],(0,0,200)) cv2.imshow('frame',frame) k = cv2.waitKey(30) & 0xff if k == 27: break

cap.release()
cv2.destroyAllWindows()

試したこと

下記方法試しましたがうまくいきませんでした。
・オプティカルフローでの物体追跡
_Shi-Tomasi法で求めた特徴点をLucasKanade法で追跡を試みましたが、気泡のコーナーは検出できず、
追跡出来ませんでした。
・カルマンフィルタでの物体追跡
_上記の方法で取得した座標を使用し、物体追跡を試みましたが、コードが悪いようで、物体検出が出来ませんでした。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2021/06/23 05:45

「最終的にやりたい話はコレなんだけど,何となくやってみたコードではできていません.どうしましょう?」という形じゃなくて, 「AしてBしてCすればいけると考えているが,Bの部分がこうなっちゃうからCのところでこのように困ることになる.Bの結果をこういう方向に改善できれば良いのだが,そのための方法が…」とか何とか, 具体的な部分問題にまで落とし込むことはできないのですか?
fana

2021/06/23 05:47

> 気泡のコーナーは検出できず、追跡出来ませんでした。 とか言われても, 「気泡には "コーナー" が確かに存在するのだけども,それを現状ではうまく検出できていない.これを検出できればいけるハズなのだが」 という話なのか,それとも 「そもそも気泡には目ぼしい "コーナー" なんて存在しないのだから,コーナー検出でいけるわけないよねw」 って話なのか? (仮に後者側だとすれば,そもそも何でそれを試したのか? 無意味なことは明らかだ)
fana

2021/06/23 06:16 編集

> 気泡以外のノイズも拾っています と言われても,どんな形でどの程度ノイズが残ってるのか? 等々,他者には不明だし, そもそも,その取り切れないノイズが後段処理に悪影響を及ぼしているという話なのか? もわからない. --- 要は,あなたが「本当に」困っていること/障害となっていること というのは何なのか? という具体的なところが伝わらないので, これだと誰かがあなたにとって有益な回答を付けるのは難しいんじゃないか? ってことです. 例えば,同じような話(?)でも, https://teratail.com/questions/304648 では,考えている方法論や困っている事柄を具体的に示してますよね.
fana

2021/06/23 06:05

ま,それはそれとして, 例えば, 「同一の気泡に相当する「白色箇所」は,隣接フレーム間で一部分が重なる」みたいなことは無いんですかね. (動画の撮影速度(FPS)と気泡の移動速度との兼ね合い次第になります) もしも 【隣接フレーム間で2値画像のANDを取ったならば,同一の気泡の「白色箇所」というのは十分な面積を残す】 みたいな話があったりするならば,そこらへんを追跡の足掛かりにできるかもしれません.
tanaka_sa

2021/06/24 05:12

fana様 ご回答、及び私の質問に対するご指摘ありがとうございます。 質問内容を変更いたしました。
tanaka_sa

2021/06/24 05:13

jbpb0様 ご回答ありがとうございます。 教えていただいたサイトを参考にさせていただきます。
guest

回答1

0

ベストアンサー

どんな映像を相手にしているのか不明だが…

  • フレーム間で最も「似ている」領域を探して追跡するようなシンプルな話ではどのような問題が生じるのか?を一度やってみることは,検討の方向性を定めるのに有効かもしれない.
  • 「泡」のフレーム間での移動量次第では,背景差分で得た2値画像の隣接フレーム間でのANDを見ることは,各フレームで独立して出てくるノイズを除去して泡だけを観測することの助けになるかもしれない.
  • とりあえず farneback のオプティカルフローを可視化して眺めてみてはどうか.この処理が「泡」の移動量をよく表すならば,時間方向に像を追跡する処理の有効なヒントになり得る.
  • 例えば,あるフレームにおいて泡がx=150の位置に存在するのだとしよう.そのフレームを含むNフレーム分の画像からそれぞれx=150の部分(横1pixel*縦がフレーム画像の縦幅 の画像)を切り出してきて,それらをフレームの順番に横方向に並べることで「横N*縦がフレーム画像の縦幅」な画像を作ったならば,それはどのような画像になるだろうか?

このようにして作った画像に対して画像処理を行えば,泡の移動速度を推定することができるかもしれない.
(こういうの,何て呼ぶんだっけ?)


背景差分の結果の2値画像から領域を検出して… という方向の処理で
泡と水面とかノイズの領域がくっついちゃうとか,そういうことが問題となるのであれば,
全く別方向の(「領域」から出発しない)話を考えてみればどうでしょうか.

(処理時間の面の問題があるかもしれませんが)
farnebackのような,全画素を対象としたオプティカルフローを複数フレームにわたって追跡してみてはどうでしょう.

例えば,

  • フレーム1とフレーム2との間で計算したフローから,フレーム1で(x1,y1)にあった像がフレーム2では(x2,y2)に動いたのだと推測される
  • フレーム2とフレーム3との間で計算したフローから,フレーム2で(x2,y2)にあった像がフレーム3では(x3,y3)に動いたのだと推測される

という結果から,
「フレーム3で(x3,y3)にある像と言うのは,フレーム2では(x2,y2)にあり,その前のフレーム1では(x1,y1)にあった」
という追跡を行うことができる.

この追跡を,例えば,フレーム3の2値化結果で白である全画素についてやる:
すなわち,現在のフレーム(フレーム3)で泡かノイズかわからない箇所が,過去数フレームではどのような動きをしていたのか? というのを見る.

このようにしてNフレームにわたって追跡した軌跡群のうち「泡」のように安定的に上方向に動いている軌跡の場所は「泡」と推測でき,
そうでない動きのフローの部分はノイズ的なものだと推測できる.

…のではないでしょうか.

投稿2021/06/23 15:16

編集2021/06/24 06:14
fana

総合スコア11996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tanaka_sa

2021/06/25 07:49

fana様 ご回答いただきありがとうございます。 全画素を対象としたオプティカルフローがあったのですね。farnebackを使用したところ、気泡の上方向のベクトルを明確に表示出来ました。処理速度が極端に遅くなったため、処理する範囲を狭める等、別の方法も取り入れ模索していきます。 新たな方向性を決める手助けをしていただき、誠にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問