質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.59%

Webカメラから動画を取り込み、OpenCV(PythonもしくはProcessing)で複数個の形をリアルタイムで識別し位置を取得したい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,151

Nannana

score 12

 前提・実現したいこと 

初めて質問します。主にProcessingを用いたインタラクションデザインを学んでおります。
テンプレートマッチングどころか、OpenCVも初めて触るレベルでして、凄く初歩的な質問でしたら申し訳ございません。

現在、リアルタイムの動画をwebカメラから取り込み、映ったもの(幾何学模様が2,3個を想定)の位置を認識するプログラミングを調べています。

最終的に目指しているのは、アクリル板の台の下にwebカメラを置き、台の上に置かれたものの底に幾何学模様を貼り付けて、その位置に映像を上から映し出す作品です。

テンプレートマッチングで実装出来そうなのですが、参考に出来るようなサンプルプログラムが見つからず、お手上げの状態です。
また、テンプレートマッチングだと認識できる位置が、テンプレート画像内での位置になってしまうかと思うのですがいかがでしょうか。。。

現状でのコードを一応貼って置きます。画像によるテンプレートマッチングです。

一歩でも動き始められるようなヒントでも良いので、どなたか助言を下されば幸いです。

何卒宜しくお願い致します。

現状でのコード

import processing.video.*;
import gab.opencv.*;
import org.opencv.core.Mat;
import org.opencv.core.CvType;
import org.opencv.imgproc.Imgproc;
import org.opencv.core.Core.MinMaxLocResult;
import org.opencv.core.Core;

//Capture Camera; //本当はこれで読み込むビデオを入力画像として使いたい

// 入力画像の準備
PImage inputImage = loadImage("tiisakusita1.jpg");
OpenCV inputCV = new OpenCV(this, inputImage); 
Mat inputMat = OpenCV.imitate(inputCV.getGray()); 

// テンプレート画像の準備
PImage templateImage = loadImage("tiisakusita2.jpg"); 

OpenCV templateCV = new OpenCV(this, templateImage);
Mat templateMat = OpenCV.imitate(templateCV.getGray());

// 結果格納用の行列の準備
int resultCols = inputMat.cols() - templateMat.cols() + 1; 
int resultRows = inputMat.rows() - templateMat.rows() + 1; 
Mat resultMat = new Mat(resultRows, resultCols, CvType.CV_32FC1);

// テンプレートマッチングを実行
Imgproc.matchTemplate(inputCV.getColor(), templateCV.getColor(), resultMat, Imgproc.TM_CCOEFF_NORMED);

// 結果を描画
println("OK!");
size(400, 300);
image(inputImage, 100, 0);
image(templateImage, 10, 10,80,80);

MinMaxLocResult mmlr = Core.minMaxLoc(resultMat);

if (mmlr.maxVal > 0.1) { 
  println("Val: " + mmlr.maxVal); 
  stroke(255, 0, 0);
  strokeWeight(3);
  noFill();
  rect((int)mmlr.maxLoc.x + 100, (int)mmlr.maxLoc.y, templateMat.cols(), templateMat.rows()); 
}

参考動画

1
2

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

 テンプレートマッチングが使える条件

  • 検出対象の大きさが固定
  • 検出対象が回転していない

また、テンプレートマッチングだと認識できる位置が、テンプレート画像内での位置になってしまうかと思うのですがいかがでしょうか。。。

元画像の座標系での位置で検出できます。

テンプレートマッチングの仕組み

 模様が形状で判断できる場合

findContours() で輪郭を抽出する方法がよいと思います。


 追記

輪郭抽出ベースだと以下のような感じになります。
形状が丸、四角、三角、円など単純な形であれば、輪郭抽出ベースのやり方をおすすめします。

イメージ説明

import cv2
import matplotlib.pyplot as plt
import numpy as np

# 画像を読み込む。
img = cv2.imread('sample.png')
img = cv2.flip(img, 1)

# 輪郭抽出する。
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, contours, _ = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 輪郭を近似する。
approx_contours = []
for cnt in contours:
    # 輪郭の周囲の長さを計算する。
    arclen = cv2.arcLength(cnt, True)
    # 輪郭を近似する。
    approx_cnt = cv2.approxPolyDP(cnt, epsilon=0.005 * arclen, closed=True)
    approx_contours.append(approx_cnt)

# 判定する。
for cnt in approx_contours:
    num_points = len(cnt)
    cv2.drawContours(img, [cnt], -1, (0, 0, 255), 3)

    if num_points == 3:
        cv2.drawContours(img, [cnt], -1, (255, 0, 0), 3)
        print('三角形')
    elif num_points == 4:
        cv2.drawContours(img, [cnt], -1, (0, 255, 0), 3)
        print('四角形')
    else:
        cv2.drawContours(img, [cnt], -1, (0, 255, 255), 3)
        print('その他')

# 画像を表示する。
fig, axes = plt.subplots(figsize=(6, 6))
axes.imshow(img)
axes.axis('off')
plt.show()

イメージ説明
結果

三角形が赤
四角形が緑
それ以外が水色
で検出されています。位置ももちろん、取得できます。

 追記

import cv2

device_id = 0
cap = cv2.VideoCapture(device_id)

while True:
    # 1フレームずつ取得する。
    ret, frame = cap.read()
    if not ret:
        break  # 映像取得に失敗

    result = detect(frame)  # フレームから図形を検出する。
    # 検出結果を使ってなにかする。

    cv2.imshow('Frame', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break  # q キーを押したら終了する。

cap.release()
cv2.destroyAllWindows()

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/01 16:11

    具体的に示してくださり大変参考になります。
    Processingで動かす場合についてもう少し詳しく教えていただけますでしょうか。。

    キャンセル

  • 2018/11/02 13:04

    追記に OpenCV でカメラから映像を取得する方法も書きました。
    やりたいことを実現するには以下の流れになると思います。
    1. 映像を取得する。
    2. 映像から模様を2値化して、輪郭抽出で検出する。
    3. 検出結果を使ってなにかする。(映像を上から映し出す?)

    Processing は使ったことがないのでわからないです。
    OpenCV を使うのであれば、言語にかかわらず API は共通なので、Python のコードを参考にすればできるはずです。

    キャンセル

  • 2018/11/04 12:38

    詳しく教えてくださりありがとうございます。
    Pythonをほぼ触ったことがないので、なんとかProcessingに変換したいと思います!
    ありがとうございました。

    キャンセル

0

単純なテンプレートマッチングで
やりたいことを実現可能なのかどうかを調査すべきです.

台の上に置かれたもの

の置かれ具合(底面の模様の回転の有無)がどの程度かに依るでしょう.


(私は使った経験無いので,本当に使えるかどうかわからないのですが)
AR toolkit とか使えないか調べてみると良いのかも?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/01 14:48

    ご回答をくださり誠にありがとうございます。

    回転がある場合には、やはりテンプレートマッチングは難しいですよね。。

    AR toolkitについて調べてみたいと思います。
    ご提案くださりありがとうございます。

    キャンセル

  • 2018/11/01 15:15

    回転があるなら,
    {何か回転不変な特徴を利用できる,あるいは回転方向が簡単に推定できる}ように模様側デザインを決めると良いかと.
    また,リアルタイム性のために縮小した画像上で処理することも考えると,細かいデザインではない方が良いと思います.

    キャンセル

  • 2018/11/04 12:39

    そうですね、、貼り付ける側のデザインについても考慮してみたいと思います。
    為になるアドバイスをくださり、ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • Pythonに関する質問
  • Webカメラから動画を取り込み、OpenCV(PythonもしくはProcessing)で複数個の形をリアルタイムで識別し位置を取得したい