OpenCV で目標を捕捉する方法について。目標は1つ(複数でない)とする。今回は1羽のトビを追跡する。
作成した動画
処理概要
まずは、トビを判定する。HSV の色情報を使う。トビは背景よりも暗いので、v <= 100 でトビを判定し、マスクする。後工程のために、マスクはカラーではなく、白黒で準備する。
マスク画像の重心(x, y)は、
mu = cv2.moments(maskGray, False)
x, y= int(mu["m10"]/mu["m00"]) , int(mu["m01"]/mu["m00"])
で算出できる。
最後に枠で囲む。cv2.rectangle(画像, 左上の座標, 右下の座標, 色(BGR) , 枠のタイプ) で枠をつけられる。
コード
import cv2
import sys
import numpy as np
import moviepy.editor as mp
# 画像を加工する
def mkimg(img):
mask, maskGray = mkmask(img,0,255,0,255,0,100)
mu = cv2.moments(maskGray,False)
x, y= int(mu["m10"]/mu["m00"]) , int(mu["m01"]/mu["m00"])
cv2.rectangle(img, (x - 100, y - 100),(x + 100, y + 100),(0, 0, 255),3)
return ct(img)
# HSV情報からmaskを作成
def mkmask(img,hmin,hmax,smin,smax,vmin,vmax):
h,s,v = np.float32(cv2.split(cv2.cvtColor(img,cv2.COLOR_BGR2HSV))) # 色空間をBGRからHSVに変換
mask = (cv2.inRange(h,hmin,hmax)/255) \
* (cv2.inRange(s,smin,smax)/255) \
* cv2.inRange(v,vmin,vmax)
return cv2.cvtColor(ct(mask), cv2.COLOR_GRAY2BGR), mask
# 値を0-255にclipして、typeをuint8にする
def ct(img):
return np.clip(img,0,255).astype(np.uint8)
# 動画関連 -------------------------------------------------------------
def set_audio(srcfile,imgfile,outfile):
# Extract audio from input video.
clip_input = mp.VideoFileClip(srcfile)
clip_input.audio.write_audiofile('audio.mp3')
# Add audio to output video.
clip = mp.VideoFileClip(imgfile).subclip()
clip.write_videofile(outfile, audio='audio.mp3')
# 動画のファイル名 設定
srcfile = sys.argv[1]
imgfile = "out.mp4"
outfile = sys.argv[1].replace(".mp4","out.mp4").replace(".MP4","out.MP4")
video = cv2.VideoCapture(srcfile)
# 幅と高さを取得
width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
size = (width, height)
# 総フレーム数/フレームレートを取得
frame_count = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
frame_rate = int(video.get(cv2.CAP_PROP_FPS))
# 保存用
fmt = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
writer = cv2.VideoWriter(imgfile, fmt, frame_rate, size)
for i in range(frame_count):
ret, frame = video.read()
write_frame = mkimg(frame)
writer.write(write_frame)
cv2.imshow("newf", write_frame)
# qキーが押されたら途中終了
if cv2.waitKey(25) & 0xFF == ord('q'):
break
writer.release()
video.release()
cv2.destroyAllWindows()
# 最後に音をつける
set_audio(srcfile,imgfile,outfile)
コメント