OpenCV で目標を捕捉する

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)

コメント

タイトルとURLをコピーしました