動画内の球体の速度を求めたい。

73 views (last 30 days)
Eiji Ishioka
Eiji Ishioka on 24 Dec 2019
Commented: Eiji Ishioka on 27 Dec 2019
水中を流れる球体(白と赤の2種類)があり、その球の速度を求めたいです。動画内にはスケールがあるので距離はわかります。また、120fpsとフレーム数が多いのでそれを利用できる方法があればな、と考えております。
現在は、イメージ内の円形オブジェクトの検出と測定(https://jp.mathworks.com/help/images/detect-and-measure-circular-objects-in-an-image.html)や、交通量のビデオ内の車の検出(https://jp.mathworks.com/help/images/detecting-cars-in-a-video-of-traffic.html)、複数オブジェクトの追跡(https://jp.mathworks.com/help/vision/ug/multiple-object-tracking.html)、カルマン フィルターを使用したオブジェクトの追跡(https://jp.mathworks.com/help/vision/examples/using-kalman-filter-for-object-tracking.html) などを参考に動画をインポートし、任意のフレーム(画像)を選択し、色のしきい値を調整することで(静止画内の)対象とする球を検出することまで出来ています。現在動画上で検出できるように挑戦しているところなのですが、動画内で追跡できたとしても速度を求める方法が見当たりません。
球の速度を求める方法(またはアイデア)を教えていただきたいです。
本ケースでは水中ということで背景も多少変化してしまうので、追跡等にも苦戦しています。
年内に完成させなければならず、行き当たりばったりなことができないので質問させていただきました。よろしくお願いいたします。
I=VideoReader('---.MP4')
%下式は動画Iの中の700フレーム目を画像として呼び出す
J=read(I,700);
imshow(J)
[BW,maskedRGBImage] = createMask1(J);
[centers,radii] = imfindcircles(BW,[15 28],'ObjectPolarity','bright','Sensitivity',0.91)
imshow(BW)
h = viscircles(centers,radii);
imshow(J)
h = viscircles(centers,radii);
以下、createMask1.m
function [BW,maskedRGBImage] = createMask(RGB)
I = rgb2lab(RGB);
channel1Min = 25.436;
channel1Max = 100.000;
channel2Min = 3.650;
channel2Max = 65.432;
channel3Min = 15.507;
channel3Max = 64.797;
% Create mask based on chosen histogram thresholds
sliderBW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
end
  2 Comments
Shunichi Kusano
Shunichi Kusano on 24 Dec 2019
シンプルに速度=距離÷時間の公式に則って計算するのではうまくいかなそうなのでしょうか。
Eiji Ishioka
Eiji Ishioka on 24 Dec 2019
ご回答ありがとうございます。
もちろん手動で距離と時間(or フレーム数)で速度を求めることはできますが、球の数、および動画数が多いのでmatlabで処理したいと考えました。
matlab上で同じことをするためによい方法はありませんでしょうか?
球を追跡し、一定区間(座標など)を通過するまでのフレーム数などで計算できないものかと考えていますが、役立つ関数などが見つかっておりません。
また、すでに同様の事例がありましたら参考にしたいと考え質問させていただいています。
よろしくお願いいたします。

Sign in to comment.

Accepted Answer

Shunichi Kusano
Shunichi Kusano on 25 Dec 2019
やりたいことがシンプルですので、特に関数も必要なく次の手順で実装するのがいいかと思います。
1.フレームごとに球の位置を取得
2.位置の変化から距離を計算
3.フレームレートからフレーム間の時間を計算
4.速度=距離÷時間で速度を計算
もし検出位置にばらつきがあるようでしたら、1フレーム毎ではなく複数フレームをまとめて計算すれば、安定した結果になるのではないかと思います。
  5 Comments
Shunichi Kusano
Shunichi Kusano on 27 Dec 2019
なるほど、複数あるんですね。その場合でしたら確かに検出だけではなく追跡が必要ですね。納得です。
ただ、この例ですと複数物体の追跡するには追記が必要になってしまいます。複数オブジェクトの追跡のサンプルが下記にあるので、こちらを参考にした方がいいのではないかと思います。
この例だと検出の原理が違う(foreground detection)ので、お手持ちのデータだとうまく動かないかもしれませんが、その場合は検出の部分だけ、今の色ベースのものに差し替えて使ってください。ちなみにこのサンプルも入れ子関数の構造になっていますので、少しわかりにくいです。
念のためif文の中についてざっと解説しておきます。
stats変数には検出できた車(と思われる)領域の面積(Area)と重心位置座標(Centroid)の情報が格納されています。
if文の中の処理は、isemptyで検出された車があれば実行されるよう条件付けされています。
処理の中身は、上から
  1. 一番面積の大きい領域の重心位置を取得(1-3行目)
  2. 重心位置(1点の情報)を5x5の領域に拡張(点だと面積1なので画像上で見づらいから広げているだけと思われます。fliplrは別にしなくてもいい。その場合はrowとcolが入れ替わる)(4-7行目)
  3. その領域を赤色(255,0,0)で塗りつぶす(taggedCarsは、読み込んだフレームに検出した車の重心位置を赤色でマーキングすることで検出結果を見やすく加工したものになる。)(残り)
となります。
Eiji Ishioka
Eiji Ishioka on 27 Dec 2019
お返事ありがとうございます。
動きに基づく複数オブジェクトの追跡ですが、背景が動かないことが前提だと思い、カルマンフィルタを使用したオブジェクトの追跡を参考にしておりました。検出部分の方法を入れ替えて挑戦してみたいと思います。
if文の中身を解説していただきありがとうございます。納得出来ました!
たくさん丁寧に教えていただきありがとうございます。

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!