こんにちは!
最近OpenCVを使った記事を書いたので、これを使って、何か面白いことできないかな、と考えてました。
ちょうど、とあるバーでリアルタイムなプロジェクションマッピングの話が出たので、まずは、カメラを通して取得したフレームを、ランダムに塗りつぶすことをやってみます
やりたいこと
- カメラを通してフレームを取得
- セグメントに分ける
- セグメントごとに塗りつぶす
環境構築
Pythonの仮想環境を作ります。
python -m venv color-randomly
cd color-randomly
ディレクトリに移動した直後の状態
$ ls
bin/ include/ lib/ pyvenv.cfg
仮想環境の有効化
source bin/activate
必要なライブラリのインストール
pip install opencv-python numpy scikit-image imageio
opencv-pythonとは
画像とビデオの処理、解析、顔認識、オブジェクト検出、特徴抽出などに使用されます。
numpyとは
数学計算のためのライブラリで、高性能な数値計算機能を提供します。
多次元配列の操作、科学計算、データ分析などに使用されます。
scikit-imageとは
画像処理ライブラリです。画像のセグメンテーション、フィルタリング、画像変換、特徴抽出などに使用されます。
imageioとは
画像入出力ライブラリで、多様な画像形式の読み書きが可能です。
画像の読み込み、保存、アニメーションGIFの生成に使用されます。
コード
import cv2
import numpy as np
from skimage.segmentation import slic
from skimage.util import img_as_float
import imageio
# ユニークな色を生成する関数
def generate_unique_colors(num_colors):
return [tuple(np.random.randint(0, 255, 3).tolist()) for _ in range(num_colors)]
# SLICを用いて画像をセグメントする関数
def segment_image_slic(image, n_segments=250, compactness=10):
# 画像を浮動小数点数の型に変換
image = img_as_float(image)
# SLICでセグメントに分ける
segments = slic(image, n_segments=n_segments, compactness=compactness, start_label=1)
# 生成されたピクセルにユニークな色を割り当てる
unique_colors = generate_unique_colors(len(np.unique(segments)))
segmented_image = np.zeros(image.shape, dtype=np.float64)
for (i, seg_val) in enumerate(np.unique(segments)):
mask = segments == seg_val
segmented_image[mask] = unique_colors[i]
# 値を0から255の範囲にスケールして整数にキャスト
segmented_image = (segmented_image * 255).astype(np.uint8)
return segmented_image
# カメラのセットアップ
cap = cv2.VideoCapture(0)
# アニメーションGIFにするためのフレームリスト
frames_for_gif = []
# 何フレーム分の画像を取得するか
num_frames = 10
# フレームを取得する
while num_frames > 0:
ret, frame = cap.read()
if not ret:
break
# SLICによるセグメンテーション
segmented_frame = segment_image_slic(frame, n_segments=250, compactness=10)
frames_for_gif.append(segmented_frame)
# 結果を表示
cv2.imshow('Frame', segmented_frame)
# 'q'キーでループを抜ける
if cv2.waitKey(1) & 0xFF == ord('q'):
break
num_frames -= 1
# カメラとウィンドウのリリース
cap.release()
cv2.destroyAllWindows()
# アニメーションGIFを無限ループで保存する
imageio.mimsave('./segmented_animation.gif', frames_for_gif, fps=2, loop=0)
実行結果
python main.py
カメラが起動し、セグメント分けされて、様々な色で塗りつぶされてます。
まとめ
今回は、OpenCVとscikit-imageを使って、リアルタイムにセグメント分けをして塗りつぶしてみました。
プロジェクションマッピングとは異なるとは思いますが、これとプロジェクターを連携させたら、リアルタイムに形状を抽出して、テーマに沿ったカラーリングができそうです。
もう少し工夫したら面白いものが作れそうなので、引き続きチャレンジしてみます!
みなさんも一緒に頑張りましょう