2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

開発のお役立ち情報Advent Calendar 2023

Day 25

Pythonでリアルタイムにセグメント分けして塗りつぶす

Last updated at Posted at 2023-12-25

こんにちは!

最近OpenCVを使った記事を書いたので、これを使って、何か面白いことできないかな、と考えてました。

ちょうど、とあるバーでリアルタイムなプロジェクションマッピングの話が出たので、まずは、カメラを通して取得したフレームを、ランダムに塗りつぶすことをやってみます:slight_smile:

やりたいこと

  • カメラを通してフレームを取得
  • セグメントに分ける
  • セグメントごとに塗りつぶす

環境構築

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の生成に使用されます。

コード

main.py
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

カメラが起動し、セグメント分けされて、様々な色で塗りつぶされてます。
fig1.png

なんとなく、顔と手、後ろのカーテンも分かりますね。
fig2.png

そして、生成されたアニメーションGIFはこちらです!
segmented_animation.gif

まとめ

今回は、OpenCVとscikit-imageを使って、リアルタイムにセグメント分けをして塗りつぶしてみました。

プロジェクションマッピングとは異なるとは思いますが、これとプロジェクターを連携させたら、リアルタイムに形状を抽出して、テーマに沿ったカラーリングができそうです。

もう少し工夫したら面白いものが作れそうなので、引き続きチャレンジしてみます!

みなさんも一緒に頑張りましょう:smiley:

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?