Python 人を検出してモザイク処理する動画編集「OpenCV」

 本記事では、下記リンク先のように人(全身)にモザイク処理する動画編集の雛形コードを載せました。ライブラリは「OpenCV」を活用します。

www.youtube.com

人の全身の他に、顔、目だけなどといったカスケードファイル(学習済み分類学習器)を用いることで同様のことができます。ダウンロード方法は下記リンク先を参照下さい。

hk29.hatenablog.jp

 

■本プログラム
検出精度を高めるには、パラメータの最適解を探索する。 もしくは自分で学習器を作成するかです。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import cv2
from PIL import Image, ImageFont, ImageDraw
import moviepy.editor as mp


# 全身を検出してモザイクをかける関数
def image_recognition_and_mosaic_func(img):
    # グレイスケールへ変換
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 一枚の画像から複数を検出する
    detection_list = cascade.detectMultiScale(
        gray,
        scaleFactor = 1.1, # >1
        minNeighbors = 2, # 
        minSize=(20, 20)
    )

    # モザイク処理
    for (x, y, w, h) in detection_list:
        #print('w h', w, h)
        # 検出範囲をイメージ抽出
        detection= img[y:y+h, x:x+w]
        # 小さいサイズへ変換(ここでは5%)
        reduc = cv2.resize(detection, (int(w * 0.05), int(h * 0.05)))
        # 元サイズへ戻す
        mosaic = cv2.resize(reduc,(w, h))
        # 元へはめ込む(モザイクになる)
        img[y:y+h, x:x+w] = mosaic
        
        # テキストの挿入
        text = 'pepole'
        cv2.putText(img, text, (x, y-10),
            cv2.FONT_HERSHEY_SIMPLEX, 1, (255,0,0), 2, cv2.LINE_AA)

    # モザイク画像を返す
    return img


# 音声を動画に加える関数(編集した動画は一旦、音声がなくなるため)
def extract_and_set_audio(input_video1, input_video2, out_file, out_audio):
    # オリジナル動画をメモリにクリップ
    clip_in = mp.VideoFileClip(input_video1).subclip()
    
    # オリジナル動画から音声ファイルを抽出して、ファイルに出力する
    clip_in.audio.write_audiofile(out_audio)
    
    # (音声を付与したい)動画をメモリにクリップする
    clip_out = mp.VideoFileClip(input_video2).subclip()
    
    # 音声を付与して、ファイルに出力する
    clip_out.write_videofile(out_file, audio = out_audio)


def main():
    # 動画とそのフレームワーク情報を取得
    video = cv2.VideoCapture(input_video)
    width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
    size = (width, height)
    frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
    fps = int(video.get(cv2.CAP_PROP_FPS))

    # 出力フォーマットの指定
    fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
    writer = cv2.VideoWriter(out_video1, fourcc, fps, (width, height))

    # フレーム1枚ずつ処理する
    for i in range(frames):
        ret, frame = video.read()
        dst = image_recognition_and_mosaic_func(frame)
        writer.write(dst)
        if i % 10 == 0:
            print(str(i) + "/" + str(frames))
            #cv2.imwrite('mosaic' + str(i) + '.jpg', dst)
            
    # 後処理
    writer.release()
    video.release()
    print("frames -> " + str(frames))
    print("fps -> " + str(fps))


    # 作成したモザイク動画には音声がないため、音声を付与する
    input_video2 = out_video1
    extract_and_set_audio(input_video, input_video2, out_video2, out_audio)


# メイン関数
if __name__ == '__main__':
    # ファイル名
    input_video = 'IMG_2790.MOV' # オリジナル動画(モザイクをかけたい)
    out_video1 = 'zzz_mosaic.mp4' # 作成するモザイク動画名
    out_audio = 'zzz_voice.mp3' # 作成する音声ファイル名
    out_video2 = 'zzz_mosaic_with_voice.mp4' # 最終動画名(音声付モザイク動画)

    # カスケードファイル(学習分類器)のパスを指定
    cascade_path = r'C:/Users/[ユーザー名]/Anaconda3/Lib/site-packages/cv2/data/haarcascade_fullbody.xml'
    cascade = cv2.CascadeClassifier(cascade_path)
    
    # メイン関数の実行
    main()

以上

<広告>