0
2

More than 3 years have passed since last update.

画像やWebカメラを加工してみる パート3 ~モザイク処理編~

Last updated at Posted at 2019-11-02

はじめに

Pythonを使って、画像やWebカメラを加工してみた パート3

前回に引き続き、 OpenCV を使って画像(映像)加工をやってみた
今回は画像とWebカメラの映像にモザイクを入れる処理!

お品書きは下記の通り

  • モジュール,ディレクトリ構造など
  • 画像モザイク
  • Webカメラモザイク

モジュール,ディレクトリ構造など

モジュール

モジュールは前回と同様のものを使用
必要があればインストールしてください!

pip install opencv-python # OpenCVの機能を使用するときに必要(python上ではcv2で使う)
pip install numpy         # 数値計算を効率的に行うための拡張モジュール
pip install os            # osに依存している機能を利用できる

ディレクトリ構造

ディレクトリ構造は下記の通り

-- rgb.py
   -- camera_mosaic.py # new
   -- color_process.py
   -- photo_process.py
   -- photo_mosaic.py  # new
   -- rgb.py
   -- img
      -- fruit.jpg

写真は前回同様、果物たちを使用する
fruit.jpg

画像モザイク

モザイクをかけたい部分を縮小しもとに戻す

プログラム

photo_mosaic.py
import cv2
import os

PATH = './img'
FILES = os.listdir(PATH)

OLD_WINDOW_NAME = 'old'
NEW_WINDOW_NAME = 'new'
ratio = 0.1 # モザイクの粗さ

# get file name
def get_file_name():
    print('*** All  Pictures ***')
    print(*FILES, sep='\n')
    print('***      End      ***')

    while True:
        file_name = input('Which use file name ?: ')
        if file_name in FILES:
            return file_name
        else:
            print('not exist: ' + file_name)

# モザイク処理
def mosaic(src):
    small = cv2.resize(src, None, fx=ratio, fy=ratio, interpolation=cv2.INTER_NEAREST)
    return cv2.resize(small, src.shape[:2][::-1], interpolation=cv2.INTER_NEAREST)

# モザイク部分を設定
def mosaic_area(src, x, y, width, height):
    dst = src.copy()
    dst[y:y + height, x:x + width] = mosaic(dst[y:y + height, x:x + width])
    return dst

if __name__ == '__main__':

    old_file_name = get_file_name()
    file_prefixes = old_file_name.rsplit('.', 1)
    new_file_name = file_prefixes[0] + '_mosaic.' + file_prefixes[1]

    # 元の画像を読み込む
    old_img = cv2.imread(PATH + '/'+ old_file_name)

    # モザイク化
    new_img = mosaic_area(old_img, 100, 50, 100, 150)

    # ウィンドウを作成
    cv2.namedWindow(OLD_WINDOW_NAME)
    cv2.namedWindow(NEW_WINDOW_NAME)

    # ウィンドウに表示
    cv2.imshow(OLD_WINDOW_NAME, old_img)
    cv2.imshow(NEW_WINDOW_NAME, new_img)

    # ファイルに保存
    cv2.imwrite(r'img/{}'.format(new_file_name), new_img)

    # 終了処理
    cv2.waitKey(0)
    cv2.destroyAllWindows()

少し解説

dst = src.copy()

src(元の画像)をdst(加工する画像)にコピーする
最初は以下のようにコーディングしていて頭を抱えた…
dst = src
※気になる方は実行してみてどうなるか試してみたください(笑)

dst[y:y + height, x:x + width] = mosaic(dst[y:y + height, x:x + width])

dstで指定した範囲をmosaic関数から送られてきた画像に変える処理
xとyが逆になっているので注意!

small = cv2.resize(src, None, fx=ratio, fy=ratio, interpolation=cv2.INTER_NEAREST)

cv2.resizeで画像のサイズを変更
ratio が小さいほど粗く,大きいほど細かくモザイク加工できる

INTER_NEARESTは最近傍補間法というもの
最近傍にある画素をそのまま使用する方法

return cv2.resize(small, src.shape[:2][::-1], interpolation=cv2.INTER_NEAREST)

元の大きさに戻す
src.shapeで配列の形状を取得
今回は(150, 100, 3)なので、100×3の150次元配列です
これを加工していくと以下のようになる

src.shape => (150, 100, 3)
src.shape[:2] => (150, 100)
src.shape[:2][::-1] => (100, 150) 

これで元の大きさに戻るらしい

出力結果

コマンドライン
gazou3.PNG

画像モザイク
ratio = 0.1のとき
fruit_mosaic_01.jpg

ratio = 0.9のとき
fruit_mosaic_06.jpg

Webカメラモザイク

webカメラを使用して、映像に全体モザイクを入れてみた
全体モザイクするには、mosaic_area関数を通らずにモザイク処理をしてあげる

プログラム

camera_mosaic.py
import cv2

cap = cv2.VideoCapture(0)
ratio = 0.1

def mosaic(src):
    small = cv2.resize(src, None, fx=ratio, fy=ratio, interpolation=cv2.INTER_NEAREST)
    return cv2.resize(small, src.shape[:2][::-1], interpolation=cv2.INTER_NEAREST)

if __name__ == '__main__':

    while True:
        ret, old_frame = cap.read()
        copy_frame = old_frame .copy()
        # モザイク化
        new_frame = mosaic(copy_frame)

        cv2.imshow('OldRawFrame', old_frame)
        cv2.imshow('NewRawFrame', new_frame)

        k = cv2.waitKey(1)
        if k == 27:
            break

    cap.release()
    cv2.destroyAllWindows()

少し解説

cap = cv2.VideoCapture(0)

動画又は、カメラ映像を読み込む
()内に動画パスを入力すると動画データが読み込まれる

カメラ映像の場合は0が内蔵カメラ,1がUSBカメラとのこと…?
※私のPCには内蔵カメラがなかったため0がUSBカメラになっていました

ret, old_frame = cap.read()

読み込んだ動画を1フレームずつ読み込んでいく
ret にはTrue/Falseが入力される
正しく読み込まれない場合、ret = False となり、強制終了される

old_flameには1フレーム画像データが入力される
while文でループすることにより、映像になっている

k = cv2.waitKey(1)
if k == 27:
break

プログラム終了用
いつもは cv2.waitKey(0) を使用するのですが、
動画のときは、 cv2.waitKey(1) を使用する

k == 27 (Escキーを押す)の時だけwhileから脱出
if文の前にprint(k)を置けばボタン番号がわかるので、お好きな番号でどうぞ!

出力結果

python camera_mosaic.py

上記スクリプトを実行すると全体にモザイクがかかったウェブカメラが動き出すはず

(なぜかGIFが添付できなかったので、HUEちゃんの静止画をご覧ください…)
hue.PNG

思った以上にwebカメラの遅延がなかったので、いろいろこれで作れそう
次回は顔を認識してモザイクかけちゃうプログラムを作成する予定( ˘ω˘ )

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2