ORB特徴点検出カメラキャプチャプログラム

目次

1. 概要

主要技術:ORB(Oriented FAST and Rotated BRIEF)特徴点検出

プログラム概要
Webカメラからリアルタイム映像を取得し、ORB特徴点検出により画像間の重なり面積を自動計算、設定した閾値(80%)以下になった時点で新しい視点のフレームとして自動保存するカメラキャプチャプログラ

技術の論文

技術の新規性・特徴
ORBは従来のSIFT・SURFと比較して高速な特徴点検出・記述子計算を実現する。FAST(Features from Accelerated Segment Test)はコーナー検出に特化したアルゴリズムであり、BRIEF(Binary Robust Independent Elementary Features)はバイナリ形式(0と1)で特徴を表現するため計算量が少ない。従来手法が浮動小数点記述子を使用するのに対し、ORBはハミング距離によるマッチングを可能にする。

活用可能なアプリケーション例
リアルタイム物体認識、SLAM(Simultaneous Localization and Mapping)、AR(拡張現実)、画像マッチング、カメラトラッキング

技術的制約
テクスチャの少ない平面では特徴点検出が困難である。照明変化や視点変化に対する耐性に限界がある。リアルタイム処理と精度にはトレードオフ関係が存在する。

体験価値
リアルタイムカメラ映像から特徴点を自動検出し、重なり面積に基づいて新しい視点のフレームを自動保存するプログラムを確認

2. 事前準備

Python 3.12 のインストール

Pythonのインストールを行い、Pythonのプログラムを実行する環境を整える。扱う環境は、Windows搭載パソコンである。金子研究室では、Python 3.12.10を推奨する。

[Windows での Python 3.12 のインストール手順を見るには、ここをクリック]

Windows での Python 3.12 のインストール

以下のいずれかの方法でPython 3.12をインストールする。Pythonがインストール済みの場合、この手順は不要である。

方法 1:winget によるインストール

インストールコマンドの実行方法

管理者権限コマンドプロンプトを起動する(手順:Windowsキーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。そして、コマンド全体をコマンドプロンプトにコピー&ペーストする。

--scope machine を指定することで、システム全体(全ユーザー向け)にインストールされる。このオプションの実行には管理者権限が必要である。インストール完了後、コマンドプロンプトを再起動するとPATHが反映される。

REM Python 3.12 をシステム領域にインストール
winget install --id Python.Python.3.12 -e --scope machine --silent --accept-source-agreements --accept-package-agreements --override "/quiet InstallAllUsers=1 PrependPath=1 Include_test=0 Include_pip=1 Include_launcher=1 InstallLauncherAllUsers=1 TargetDir=\"C:\Program Files\Python312\""

REM Python と Scripts を PATH 先頭に追加
powershell -NoProfile -Command "$p='C:\Program Files\Python312'; $s=\"$p\Scripts\"; $c=[Environment]::GetEnvironmentVariable('Path','Machine'); if((Test-Path $p) -and (';'+$c+';' -notlike \"*;$p;*\") -and (';'+$c+';' -notlike \"*;$s;*\")){[Environment]::SetEnvironmentVariable('Path',\"$p;$s;$c\",'Machine')}"

方法 2:インストーラーによるインストール

  1. Python公式サイト(https://www.python.org/downloads/)にアクセスし、「Download Python 3.x.x」ボタンからWindows用インストーラーをダウンロードする。
  2. ダウンロードしたインストーラーを実行する。
  3. 初期画面の下部に表示される「Add python.exe to PATH」にチェックを入れてから「Customize installation」を選択する。このチェックを入れ忘れると、コマンドプロンプトから python コマンドを実行できない。
  4. 「Install Python 3.xx for all users」にチェックを入れ、「Install」をクリックする。

インストールの確認

コマンドプロンプトで以下を実行する。

python --version

バージョン番号(例:Python 3.12.x)が表示されればインストール成功である。「'python' は、内部コマンドまたは外部コマンドとして認識されていません。」と表示される場合は、インストールが正常に完了していない。

Python の開発環境 Visual Studio Code のインストールと Python 用の設定

Python の開発環境Visual Studio Code(プログラムを編集するソフトウェア。以下、VS Code)を整える。

[Windows での Visual Studio Code のインストールと Python 用の設定手順を見るには、ここをクリック]

Windows での Visual Studio Code のインストールと Python 用の設定手順

1. VS Code と拡張機能のインストール

以下のコマンドにより,既存の VS Code を削除し,全ユーザー共有の設定で再インストールしたうえで,拡張機能(VS Code に機能を追加するソフトウェア)をまとめて導入する.

インストールコマンドの実行方法

管理者権限コマンドプロンプトを起動する(手順:Windows キーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。そして,コマンド全体をコマンドプロンプトにコピー&ペーストする。

インストールコマンド


REM ============================================================
REM Microsoft Visual Studio Code
REM ============================================================
winget uninstall -e --id Microsoft.VisualStudioCode --silent --disable-interactivity --accept-source-agreements
rmdir /s /q C:\ProgramData\vscode-extensions 2>nul
rmdir /s /q "%APPDATA%\Code" 2>nul
rmdir /s /q "%USERPROFILE%\.vscode" 2>nul
rmdir /s /q "%LOCALAPPDATA%\Microsoft\vscode-update" 2>nul

REM VS Code をシステム領域に新規インストール
winget install --scope machine --id Microsoft.VisualStudioCode -e --silent --accept-source-agreements --accept-package-agreements

REM 全ユーザー共有の拡張機能フォルダ
mkdir C:\ProgramData\vscode-extensions 2>nul
icacls "C:\ProgramData\vscode-extensions" /grant "Everyone:(OI)(CI)M" /T

REM スタートメニューのショートカットを --extensions-dir 付きで再作成
rmdir /s /q "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code" 2>nul
del "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code.lnk" 2>nul
powershell -NoProfile -Command "$s=New-Object -ComObject WScript.Shell; $lnk=$s.CreateShortcut('C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code.lnk'); $lnk.TargetPath='C:\Program Files\Microsoft VS Code\Code.exe'; $lnk.Arguments='--extensions-dir \"C:\ProgramData\vscode-extensions\"'; $lnk.Save()"
REM ショートカットの検証
powershell -NoProfile -Command "$s=New-Object -ComObject WScript.Shell; $lnk=$s.CreateShortcut('C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code.lnk'); Write-Host 'TargetPath:' $lnk.TargetPath; Write-Host 'Arguments:' $lnk.Arguments"

REM ファイル / フォルダ右クリックの「Code で開く」を登録
reg add "HKLM\SOFTWARE\Classes\*\shell\VSCode\command" /ve /d "\"C:\Program Files\Microsoft VS Code\Code.exe\" --extensions-dir \"C:\ProgramData\vscode-extensions\" \"%1\"" /f
reg add "HKLM\SOFTWARE\Classes\Directory\shell\VSCode\command" /ve /d "\"C:\Program Files\Microsoft VS Code\Code.exe\" --extensions-dir \"C:\ProgramData\vscode-extensions\" \"%1\"" /f
reg add "HKLM\SOFTWARE\Classes\Directory\Background\shell\VSCode\command" /ve /d "\"C:\Program Files\Microsoft VS Code\Code.exe\" --extensions-dir \"C:\ProgramData\vscode-extensions\" \"%V\"" /f

REM --extensions-dir 付きで起動する code.cmd ラッパを作成
REM (%* を echo で書くと対話的 cmd で失われるため、PowerShell で [char]37+'*' を書き出す)
powershell -NoProfile -Command "$pct=[char]37; $q=[char]34; $c='@echo off'+[char]13+[char]10+$q+'C:\Program Files\Microsoft VS Code\bin\code.cmd'+$q+' --extensions-dir '+$q+'C:\ProgramData\vscode-extensions'+$q+' '+$pct+'*'+[char]13+[char]10; [IO.File]::WriteAllText('C:\ProgramData\vscode-extensions\vscode.cmd',$c,[Text.Encoding]::ASCII)"

REM 拡張機能のインストール
set "CODE=C:\Program Files\Microsoft VS Code\bin\code.cmd"
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --uninstall-extension GitHub.copilot
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --uninstall-extension GitHub.copilot-chat
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension ms-python.python
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension ms-python.vscode-pylance
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension ms-python.debugpy
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension MS-CEINTL.vscode-language-pack-ja
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension saoudrizwan.claude-dev
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension rust-lang.rust-analyzer
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension tamasfe.even-better-toml
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension anthropic.claude-code
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension almenon.arepl
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --list-extensions --show-versions
echo === セットアップ完了 ===

2. Python インタプリタの選択

同一マシンに複数の Python がインストールされている場合,VS Code で使用する Python 本体(インタプリタ:Python プログラムを解釈・実行するソフトウェア)を選択する必要がある.

  1. コマンドパレット(コマンド名で機能を呼び出す VS Code の入力欄)を開く(Ctrl+Shift+P
  2. Python: Select Interpreter と入力する
  3. 表示される一覧から,使用する Python(例:C:\Program Files\Python312\python.exe)を選択する.

必要ライブラリのインストール

コマンドプロンプトを管理者として実行(手順:Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)し、以下を実行する

pip install opencv-python numpy pillow

3. 動作原理

基本概念
特徴点とは画像内の特徴的な点(コーナー、エッジ等)である。記述子は特徴点周辺の画像パターンを数値化した情報であり、マッチングは異なる画像間で対応する特徴点を見つける処理である。

処理手順
ORBは特徴点を検出し記述子を計算、マッチングを行う。ホモグラフィ行列(画像間の幾何学的変換を表す行列)で画像変換を計算し、グリッドベースで重なり面積を算出する。重なり面積が閾値以下の場合に新しい視点として判断する。

4. プログラムコード

# ORB特徴点検出カメラキャプチャプログラム
# Webカメラから重なり面積が閾値以下のフレームを自動保存
# 論文: Rublee, E., Rabaud, V., Konolige, K., & Bradski, G. (2011). ORB: An efficient alternative to SIFT or SURF. ICCV 2011.
# GitHub: https://github.com/opencv/opencv
# 特徴: ORBは特徴点検出・記述子計算手法、リアルタイム処理対応
#       FAST+BRIEF組み合わせ、バイナリ記述子による効率性
# 学習済モデル: 使用なし(手作りアルゴリズム)
# 前準備: pip install opencv-python numpy pillow (管理者権限のコマンドプロンプトで実行)

import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont

# 定数定義
OVERLAP_THRESHOLD = 0.8
GRID_RATIO = 0.02  # 画像サイズに対するグリッド間隔の比率
HOMOGRAPHY_RANSAC_THRESHOLD = 5.0
FONT_PATH = 'C:/Windows/Fonts/meiryo.ttc'
FONT_SIZE = 20

# カメラ初期化
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
if not cap.isOpened():
    cap = cv2.VideoCapture(0)

if not cap.isOpened():
    print("エラー: カメラを開けません")
    exit()

cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)

# 変数初期化
frame_count = 0
ref_frame = None
ref_kp = None
ref_desc = None
orb = cv2.ORB_create()

# ガイダンス表示
print("=" * 60)
print("ORB特徴点検出カメラキャプチャプログラム")
print("=" * 60)
print("【概要】")
print("  カメラ映像から特徴点を検出し、基準フレームとの重なりが")
print("  80%以下になった場合に自動的にフレームを保存します")
print("")
print("【操作方法】")
print("  - カメラを動かすと自動的に新しい領域を検出して保存")
print("  - 'q'キー: プログラム終了")
print("")
print("【注意事項】")
print("  - 十分な特徴点が検出できる被写体を映してください")
print("  - 急激なカメラ移動は避けてください")
print("=" * 60)
print("")

# フォント設定
try:
    font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
except:
    font = None
    print("日本語フォントの読み込みに失敗しました。英語表示になります。")

# メイン処理
while True:
    # 最新フレーム取得
    cap.grab()
    ret, frame = cap.retrieve()
    if not ret:
        break
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    h, w = gray.shape

    # 解像度に応じたグリッドサイズ計算
    grid_size = max(1, int(min(w, h) * GRID_RATIO))

    # 初回フレーム処理
    if ref_frame is None:
        ref_frame = gray.copy()
        ref_kp, ref_desc = orb.detectAndCompute(ref_frame, None)

        if ref_desc is not None:
            cv2.imwrite(f"frame_{frame_count:03d}.jpg", frame)
            print(f"基準フレーム保存: frame_{frame_count:03d}.jpg")
            frame_count += 1
    else:
        # 特徴点抽出とマッチング
        curr_kp, curr_desc = orb.detectAndCompute(gray, None)

        if (curr_desc is not None and ref_desc is not None and
            len(ref_desc) >= 4 and len(curr_desc) >= 4):

            bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
            matches = bf.match(ref_desc, curr_desc)

            if len(matches) >= 4:
                # ホモグラフィ計算(現在→基準への変換)
                ref_pts = np.float32([ref_kp[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2)
                curr_pts = np.float32([curr_kp[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2)

                H, mask = cv2.findHomography(curr_pts, ref_pts, cv2.RANSAC, HOMOGRAPHY_RANSAC_THRESHOLD)

                if H is not None:
                    # 重なり面積計算:現在フレームの点を基準フレーム座標系に変換
                    total = 0
                    inside = 0
                    for x in range(0, w, grid_size):
                        for y in range(0, h, grid_size):
                            total += 1
                            # 現在フレームの点を基準フレーム座標系に変換
                            pt = np.float32([[[x, y]]])
                            transformed_pt = cv2.perspectiveTransform(pt, H)
                            # 変換後の点が基準フレーム内にあるか判定
                            tx, ty = transformed_pt[0, 0]
                            if 0 <= tx < w and 0 <= ty < h:
                                inside += 1

                    overlap = inside / total if total > 0 else 0

                    if overlap < OVERLAP_THRESHOLD:
                        cv2.imwrite(f"frame_{frame_count:03d}.jpg", frame)
                        print(f"保存: frame_{frame_count:03d}.jpg (重なり: {overlap:.2%})")
                        frame_count += 1

                        # 基準更新
                        ref_frame = gray.copy()
                        ref_kp, ref_desc = orb.detectAndCompute(ref_frame, None)

    # 画面表示(日本語テキスト付き)
    display_frame = frame.copy()
    if font is not None:
        img_pil = Image.fromarray(cv2.cvtColor(display_frame, cv2.COLOR_BGR2RGB))
        draw = ImageDraw.Draw(img_pil)
        draw.text((10, 10), f"保存数: {frame_count}", font=font, fill=(0, 255, 0))
        draw.text((10, 40), "終了: 'q'", font=font, fill=(0, 255, 0))
        display_frame = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
    else:
        cv2.putText(display_frame, f"Saved: {frame_count}", (10, 30),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
        cv2.putText(display_frame, "Press 'q' to quit", (10, 60),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)

    cv2.imshow('Camera', display_frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 終了処理
cap.release()
cv2.destroyAllWindows()
print(f"\n終了。保存フレーム数: {frame_count}")

5. 使用方法

実行手順

  1. 上記のプログラムを実行する
操作方法

出力結果

6. 実験・探求のアイデア

AIモデル選択の実験

ORB以外の特徴点検出手法との比較を行う。代表的な手法にはSIFT、SURF、AKAZE、BRISKがある。各手法の検出速度、検出精度、マッチング精度を比較し、手法間の性能差と適用場面の違いを理解する。

実験要素の調整

  1. 閾値パラメータの調整
    • OVERLAP_THRESHOLDを0.5、0.7、0.9に変更して保存頻度の変化を観察(閾値と保存タイミングの関係を理解)
    • GRID_SIZEを5、15、20に変更して計算精度と速度の関係を確認(精度と処理速度のトレードオフを学習)
  2. ORBパラメータの調整
    • nfeatures(特徴点数)を500、1000、2000に変更して検出性能を比較(特徴点数と認識精度の関係を分析)
    • scaleFactor(スケール係数)を1.1、1.3、1.5に変更してマルチスケール性能を確認(スケール変化への対応能力を評価)