はじめに
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
画像モザイク
モザイクをかけたい部分を縮小しもとに戻す
プログラム
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)
これで元の大きさに戻るらしい
出力結果
Webカメラモザイク
webカメラを使用して、映像に全体モザイクを入れてみた
全体モザイクするには、mosaic_area関数を通らずにモザイク処理をしてあげる
プログラム
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ちゃんの静止画をご覧ください…)
思った以上にwebカメラの遅延がなかったので、いろいろこれで作れそう
次回は顔を認識してモザイクかけちゃうプログラムを作成する予定( ˘ω˘ )