笑い男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インスタンスを作るってことをやってる。