前提・実現したいこと
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/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
回答1件
あなたの回答
tips
プレビュー