人生成り行き

立川談志とイチローに憧れるソフトウェアエンジニアの日記

笑い男GIFで顔隠蔽(OpenCV3+Python3)

動機

pythonで画像処理サービスとか作ってみたいけど、とりあえず面白そうなことやってみようということで、割りと定番の笑い男合成。

以下のサイトがかなり参考になりました。 というかほとんどパクリに近い… pythonのOpenCVでリアルタイムに笑い男 - BlankTar

一応、gifを対象としましたっていうのがこの記事の違い。

事前準備

使うのはPython3とOpenCV3とNumpy。 Homebrew使ってれば基本的には下で環境は整うはず。

brew install python3
pip3 install numpy
brew tap homebrew/science
brew install opencv3 --with-python3 --without-python --with-contrib

コード

GIFの扱い

ここが今回のキモ。 といってもgifを扱うのはimreadでなくて、VideoCaptureです。ってだけ。

対応するのは下の2箇所。

gif_cap = cv2.VideoCapture("laughing_man.gif")
_, lm = gif_cap.read()
segmented_lm, mask = segment_lm(lm)
def stream_lm_gif(gif_cap):

    gif_cap.grab()
    gif_cap.grab()
    gif_ret, lm = gif_cap.read()
    if not gif_ret:
        gif_cap = cv2.VideoCapture("laughing_man.gif")
        gif_ret, lm = gif_cap.read()

    return lm, gif_cap

ちなみに、gifの透過画像化ってのはできないみたいだったので、以下関数を入れてる。

# Segment Laughing Man (to make gif transparent)
def segment_lm(lm):
    lm_region = np.zeros(lm.shape)
    for v, line in enumerate(lm):
        non_white_pxs = np.array(np.where(line < 250))
        if non_white_pxs.size > 0:
            min_h, max_h = np.min(non_white_pxs, axis=1)[0], np.max(non_white_pxs, axis=1)[0]
            lm_region[v, min_h:max_h, :] = 1

    segmented_lm = lm_region * lm

    return segmented_lm, lm_region

言い訳

今回はなぜかVideoCaptureのsetメソッドによるgifのリプレイが出来なかったため、最後のフレームまでいったらもう一回VideoCaptureインスタンスを作るってことをやってる。