# coding: utf-8
# In[ ]:
#色検出:動画から色を抜き出す
import cv2
import numpy as np
capture=cv2.VideoCapture(r"C:\Users\omoiy\data\movie/mobility.mp4")
while True:
#ウィンドウサイズを小さくしておく(元画像が大きすぎる)
cv2.namedWindow("img",cv2.WINDOW_NORMAL)
cv2.resizeWindow("img",640,480)
#1フレームだけ読み込む
ret,frame=capture.read()
if ret==False: #最終フレームなら抜ける
break
hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)#読み込んだ1フレームをBGRからHSV形式に変換する
#黄色っぽい色を定義
lower=np.array([20,50,50])#Hue=20とすると実際は40になる
upper=np.array([25,255,255])
frame_mask=cv2.inRange(hsv,lower,upper)#hsvと黄色の定義を渡す
dst=cv2.bitwise_and(frame,frame,mask=frame_mask)#2値画像の論理積(共通する部分)を取り出す。mask黄色だけが抽出される
#画像を表示する
cv2.imshow("img",dst)
if cv2.waitKey(10)==27:
break
cv2.destroyAllWindows()
# オプティカルフロー : 動画中の特徴点を追跡する
(1)特徴点を見つける
(2)特徴点とその周りは同じ方向へ流れると仮定して
フローベクトを求める
フローベクトルを求める 特徴点の画素値I
I(x,y,t)=I(x+⊿x,y+⊿y,t+⊿t)
右辺をテーラー展開して、1次の項までを採用すると
I(x+⊿x,y+⊿y,t+⊿t)=I(x,y,t)[1+ (∂I/∂x)*⊿x + (∂I/∂y)*⊿y + (∂I/∂t)*⊿t]
よって、元の式は
I(x,y,t)=I(x,y,t)[1+ (∂I/∂x)*⊿x + (∂I/∂y)*⊿y + (∂I/∂t)*⊿t]
1=1+ (∂I/∂x)*⊿x + (∂I/∂y)*⊿y + (∂I/∂t)*⊿t
(∂I/∂x)*⊿x + (∂I/∂y)*⊿y + (∂I/∂t)*⊿t=0
ここで偏微分を
(∂I/∂x)=Ix
(∂I/∂y)=Iy
(∂I/∂t)=It
とおくと
I(x,y,t)=I(x,y,t)[1+ (Ix*⊿x) + (Iy*⊿y) + (It*⊿t)]
なので
1=1+ (Ix*⊿x) + (Iy*⊿y) + (It*⊿t)
(Ix*⊿x) + (Iy*⊿y) + (It*⊿t)=0
さらに両辺を⊿tで割ると
(Ix*⊿x/⊿t) + (Iy*⊿y/⊿t) +It=0
ここで
⊿x/⊿t=u
⊿y/⊿t=v
とおくと
(Ix*u) + (Iy*v) +It=0
(Ix,Iy)*(u,v)+It=0
このベクトル(u,v)をフローベクトルという。
特徴点の周辺のフローベクトルと連立させて解く
参考URL:https://www.slideshare.net/hitoshinishimura75/lucas-kanade
# In[ ]:
import cv2
#動画サイズを小さくしておく
cv2.namedWindow("img",cv2.WINDOW_NORMAL)
cv2.resizeWindow("img",1200,800)
#パラメータの設定
COUNT=500 # 500点 特徴点を検出する
"""ルーカス・カナデ法
画像ピラミッド:解像度を落とした画像を段階的に作って、軽くした状態で特徴点を分析する
winSize:ウィンドウサイズ 探索窓の大きさ
maxLevel:ピラミッドの階層の数
収束条件:最大反復回数 もしくは 値が動かなくなったら
"""
criterita=(cv2.TERM_CRITERIA_MAX_ITER|cv2.TERM_CRITERIA_EPS,20,0.03)
lucas_kanade_params=dict(winSize=(10,10),maxLevel=4,criteria=criterita)
#1フレームを読み込む
capture=cv2.VideoCapture(r"C:\Users\omoiy\data\movie/Cosmos.mp4")
ret,frame=capture.read()
frame_pre=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)#グレースケール化して、一個前のフレームとして定義する
while True:
ret,frame=capture.read()
if ret==False:#画像がなくなったらブレークする
break
frame_now=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)#グレースケール化した画像を現在フレームとする
feature_pre=cv2.goodFeaturesToTrack(frame_pre,COUNT,0.001,5)#追いかけるべき特徴点を見つける コーナー検出精度、コーナー間の最低限の距離
if feature_pre is None:#特徴点がなかったら、再びwhile文の先頭に戻って、また次のフレームを読み込んでくる
continue
#うまく特徴点を見つけられたら
feature_now,status,err=cv2.calcOpticalFlowPyrLK(frame_pre,frame_now,feature_pre,None,**lucas_kanade_params)#ルーカスカナデ本体
#描画する
for i in range(COUNT):
pre_x=feature_pre[i][0][0]
pre_y=feature_pre[i][0][1]
now_x=feature_now[i][0][0]
now_y=feature_now[i][0][1]
cv2.line(frame,(pre_x,pre_y),(now_x,now_y),(255,0,0),3)
cv2.imshow("img",frame)
frame_pre=frame_now.copy()
if cv2.waitKey(10)==27:
break
cv2.destroyAllWindows()
# MeanShift / CamShift
ピクセル密度(画素値)が最大の場所へ向かっていく
①ある場所から探索窓が出発する(ユーザーが指定)
②探索窓内の画素値の重心を計算する
③探索窓の中心を重心に移す
②③を繰り返す
CamShiftは窓の大きさが可変になる
# In[ ]:
import cv2
cap=cv2.VideoCapture(r"C:\Users\omoiy\data\movie/Cruse.mp4")
ret,frame=cap.read()
h,w,ch=frame.shape#動画サイズを抜き出す
rct=(600,500,100,100)#探索窓の開始点x,y,窓の大きさ⊿x,⊿y
cv2.namedWindow("win",cv2.WINDOW_NORMAL) #名前を付ける
cv2.resizeWindow("win",1200,800)#動画の名前を指定して、動画サイズの変更
criteria=(cv2.TERM_CRITERIA_COUNT|cv2.TERM_CRITERIA_EPS,10,1) #反復回数の閾値(10回動いたら または 1ピクセルしか動かなくなったら)
while True:
threshold=100#二値化の閾値
ret,frame=cap.read()#まずは1フレームを読み込む
if ret==False:#最後まで読み込んでいたらブレークで終わる
break
img_gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)#グレースケール化する
ret,img_bin=cv2.threshold(img_gray,threshold,255,cv2.THRESH_BINARY)#グレースケールを二値化する
ret,rct=cv2.CamShift(img_bin,rct,criteria)#二値化画像をmeanShift または CamShiftしてrct(四角)を得る
x,y,w,h=rct#rct:四角の座標と大きさ
frame=cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),3)#四角を書く
#frame=cv2.rectangle(img_bin,(x,y),(x+w,y+h),(255,0,0),3)#四角を書く
cv2.imshow("win",frame) # frame または img_bin
if cv2.waitKey(10)==27:
break
cv2.destroyAllWindows()
#背景差分
背景かそれ以外かを分離することができる
現在フレーム-背景フレーム=背景差分
# In[ ]:
import cv2
import numpy as np
cv2.namedWindow("img",cv2.WINDOW_NORMAL)
cv2.resizeWindow("img",1200,800)
cap=cv2.VideoCapture(r"C:\Users\omoiy\data\movie/Pepole.mp4")
ret,frame=cap.read()#1フレームだけ読む
h,w,ch=frame.shape
frame_back=np.zeros((h,w,ch),dtype=np.float32)#float32に指定しないと差分をとれない
while True:
ret,frame=cap.read()#1フレームだけ読む
if ret==False:
break
frame_diff=cv2.absdiff(frame.astype(np.float32),frame_back)#差分を作る
cv2.accumulateWeighted(frame,frame_back,0.03)#3%ずつ混ぜていく:
#フレームバックをだんだんフレームに近づけていく
#移動しているものは白く映る
cv2.imshow("img",frame_diff.astype(np.uint8))
if cv2.waitKey(10)==27:
break
cv2.destroyAllWindows()
# In[1]:
#パーティクルフィルター
import cv2
import numpy as np
import random2
import likelihood as li
cap=cv2.VideoCapture(r"C:\Users\omoiy\data\movie/Tram.mp4")
ret,frame=cap.read()
h,w=frame.shape[:2]
np.random.seed(100)
Np=500
px=np.zeros((Np),dtype=np.int64)
py=np.zeros((Np),dtype=np.int64)
lp=np.zeros((Np))
for i in range(Np):
px[i]=int(np.random.uniform(0,w))
py[i]=int(np.random.uniform(0,h))
obj=[0,110,160]
while True:
ret,frame=cap.read()
if ret==False:
break
lp=li.likelihood(frame,px,py,obj,Np,sigma2=0.001)
pxnew=np.array(random2.choices(population=px,weights=lp,k=Np))+np.random.randint(-15,15,Np)
pynew=np.array(random2.choices(population=py,weights=lp,k=Np))+np.random.randint(-15,15,Np)
px=np.where(pxnew>w-1,w-1,pxnew)
py=np.where(pynew>h-1,h-1,pynew)
px=np.where(px<0,0,px)
py=np.where(py<0,0,py)
for i in range(Np):
cv2.circle(frame,(px[i],py[i]),1,(0,255,0),1)
cv2.imshow("img",frame)
if cv2.waitKey(10)==27:
break
cv2.destroyAllWindows()