2016-08-14 10 views
1

私はビデオを持っており、MATLAB上にSobelマスクを作成しました。今度は、各フレームをforループで読み込んで、ビデオの各フレームにそのSobelマスクを適用する必要があります。プロセスは次のようなものです:double型のフレームは、0〜1の範囲内でなければなりません。MATLAB

  • ステップ1:読み込みフレーム。
  • ステップ2:rgb2grayを使用してグレースケールに変換します。
  • 手順3:2倍に変換します。ここで

、私は結果video.aviファイルにフレームを書き込みしようとすると、マスクを適用した後、私は次のエラーを取得する:

"Frames of type double must be in the range of 0 to 1"

私のコードが間違っていますか?私が書いたコードを以下に示します。

vid = VideoReader('me.mp4'); 
frames = read(vid); 
total = get(vid, 'NumberOfFrames'); 
write = VideoWriter('me.avi'); 
open(write); 
mask1 = [-1 -2 -1; 0 0 0; 1 2 1]; % Horizontal mask 
mask2 = [-1 0 1; -2 0 2; -1 0 1]; %Vertical Mask 
for k = 1 : 125 
    image = frames(:,:,:,k); 
    obj = image; 
    obj1 = rgb2gray(obj); 
    obj2=double(obj1); 
    for row = 2 : size(obj2, 1) - 1 
     for col = 2 : size(obj2, 2) - 1 
      c1 = obj2(row - 1, col - 1) * mask1(1 ,1); 
      c2 = obj2(row - 1, col) * mask1(1 ,2); 
      c3 = obj2(row - 1, col + 1) * mask1(1 ,3); 
      c4 = obj2(row, col - 1)*mask1(2, 1); 
      c5 = obj2(row, col)*mask1(2, 2); 
      c6 = obj2(row, col + 1)*mask1(2, 3); 
      c7 = obj2(row + 1, col - 1)*mask1(3,1); 
      c8 = obj2(row + 1, col)*mask1(3,2); 
      c9 = obj2(row + 1, col + 1)*mask1(3,3); 
      c11 = obj2(row - 1, col - 1)*mask2(1 , 1); 
      c22 = obj2(row, col - 1)*mask2(2, 1); 
      c33 = obj2(row + 1, col - 1)*mask2(3, 1); 
      c44 = obj2(row -1, col)*mask2(1, 2); 
      c55 = obj2(row, col)*mask2(2 , 2); 
      c66 = obj2(row +1, col)*mask2(2 , 3); 
      c77 = obj2(row - 1, col + 1)*mask2(1 , 3); 
      c88 = obj2(row, col +1)*mask2(2 , 3); 
      c99 = obj2(row + 1, col + 1)*mask2(3 , 3); 
      result = c1 + c2 + c3 +c4 +c5+ c6+ c7+ c8 +c9; 
      result2 = c11 + c22 + c33 + c44 + c55 + c66 + c77 + c88 + c99; 
      %result = double(result); 
      %result2 = double(result2); 
      rim1(row, col) = ((result^2+result2^2) *1/2); 
      rim2(row, col) = atan(result/result2); 
     end 
    end 
    writeVideo(write, rim2); %This line has the problem with rim2 as rim2 is the frame i'm trying to write on the video file. 
end 
close(write); 

答えて

2

rim2があります。画像処理ツールボックスと一緒に、私はあなたがコンピュータビジョンツールボックスを持つなどの画像処理ツールボックスを持っていると仮定します(あなたがVideoWriterオブジェクトを使用しているとして、あなたはこれを持っている)は、ほとんどの人が持っているものです末尾に範囲[-pi/2, pi/2]があり、これは[0,1]の範囲を想定する書き込み関数と互換性がありません。予想通り、すなわち

writeVideo(write, mat2gray(rim2)); 

あなたのコードは、その後動作します、mat2gray機能を使用して[0,1]範囲に変換 (私のマシン上で確認しました)。

ところで、これはコードには影響しませんが、おそらくではなくim2double(A)を実行することを意味していました。前者は[0,1]の範囲の「適切な」グレースケール画像を生成しますが、後者は[0,255]の範囲のuint8画像をdouble形式(つまり[0.0、255.0])に変換します。

+0

助けていただきありがとうございます。あなたの提案した 'mat2gray'が働きました。しかし、私はこれらすべての事柄のコンセプトを理解したいと思います。あなたに少し時間を与えることができれば、私はあなたとチャットをしたいと思います。 –

+0

確かに、私はうれしいです。私の答えを受け入れてくれてありがとう。私はあなたが@ rayryengの上にそれを優先したと思う。それは短くて、それを寄付するという私の意図であった点(すなわち「問題を解決した」)にまっすぐに行ったからだ。 rayryengはあなたの仕事に関わる問題や概念の驚くほど有益な内訳をあなたに与えてくれました。彼の貢献をあきらめ、愛を広げて(つまり賞の評判:))、あなたが関わっている概念を理解するために必要なすべての背景情報がうまくレイアウトされています。 (レイ:申し訳ありませんが、盗むことを意味しませんでした) –

+0

いいえ私は@rayryengを失望させたり傷つけたりするつもりはありませんでした。彼の提案はすごいですが、私の気持ちは分かりましたが、彼のコードについていくつかのアイデアがありましたが(しかしすべてを理解できませんでしたが)理解するのはかなり難しかったです。まだ画像処理が行われているので、私は彼のコードを理解できませんでした。あなたの提案は短かったので私はちょうどそれを私のコードの中に入れました、それが私がそのことに関する私の考えをクリアするように頼んだ理由です。 –

2

あなたダブルforループ内rim2のラインは正と負の両方である値を生成します。これは、atanを使用している - -pi/2から+ PI/2に正確に。 rim2は、[0,1]の間の値しか持たないと予想されます。正確に何をしているのかわかりませんが、ピクセル位置ごとに大きさと勾配の角度を計算しているようです。マグニチュードを計算したい場合は、結果を平方根で取る必要があります。単純に1/2を掛け合わせるだけではありません。勾配の計算(...またはソーベルフィルタの計算全体...)は非常に面白いです。

私はちょうどあなたの目的のために働いていると仮定しますので、適切な表示のためにrim2の出力を変更する方法はわかりませんが、ビデオを書く前に[0,1]の範囲この範囲内である。あなたは、フレームを書く前に、このような何かがうまくいく

rim2 = (rim2 - min(rim2(:)))/(max(rim2(:)) - min(rim2(:))); 
writeVideo(write, rim2); 

は上記を実際に見ているあなたの典型的な最小 - 最大の正規化です。具体的には、最小値は0であり、最大値は1フレームあたり1であることが保証されます。すべてのフレームで一貫性を持たせたい場合は、単にpi/2を追加し、次にpiで割ります。これは、最小値が-1であり、最大値がすべてで+1 であることを前提としています。

rim2 = (rim2 + pi/2)/pi; 
writeVideo(write, rim2); 

しかし、私はあなたがファイルへの大きさではなく、角度を書きたいと思います。したがって、rim1のビデオ書き込みを、rim2の代わりに書き込むフレームとして置き換えてから、正規化してください。計算するforループを使用していない、

rim1 = (rim1 - min(rim1(:)))/(max(rim1(:)) - min(rim1(:))); 
writeVideo(write, rim1); 

をしかし、私は効率の方法を提供することができる場合:今すぐファイルに書き込め

rim1(row, col) = ((result^2+result2^2)^(1/2)); 
% or use sqrt: 
% rim1(row, col) = sqrt(result^2 + result2^2); 

:あなたの勾配計算がが正しいことを確認してください勾配と角度。conv2を使用し、画像処理ツールボックスの'same 'フラグまたはimfilterを使用してフィルタリングを実行してから、ベクトル化されたグラデーションと角度を計算します。また、グレースケールに変換して、メインループでフレームを1つにキャストします。

vid = VideoReader('me.mp4'); 
frames = read(vid); 
total = get(vid, 'NumberOfFrames'); 
write = VideoWriter('me.avi'); 
open(write); 
mask1 = [-1 -2 -1; 0 0 0; 1 2 1]; % Horizontal mask 
mask2 = [-1 0 1; -2 0 2; -1 0 1]; %Vertical Mask 
for k = 1 : 125 
    obj2 = double(rgb2gray(frames(:,:,:,k))); % New 
    grad1 = imfilter(obj2, mask1); % New 
    grad2 = imfilter(obj2, mask2); % New 
    rim1 = sqrt(grad1.^2 + grad2.^2); % New 
    rim2 = atan2(grad1, grad2); % New 

    % Normalize 
    rim2 = (rim2 - min(rim2(:)))/(max(rim2(:)) - min(rim2(:))); 
    writeVideo(write, rim2); 
end 
close(write); 
+0

本当にありがとう、私は自分自身のビデオを作らなければならなかった仕事を与えられました。そして、私は各フレームで私の体の縁を見つけなければなりません。この目的のために、フレームはグレースケールのイメージでなければならないので、私はdoubleを使用しないとrgb2grayで変換しました。atanはunit8イメージを入力パラメータとして受け入れないので、 "atan"私はそれを倍に変換しました。これらのすべての処理の後、私はそのフレームを新しいビデオファイルに書き込む必要があります。 –

+0

@MehranKhanああ、私は参照してください。 OK、あなたの水平と垂直のグラデーションがOKであるように見えます...あなたは角度を見つけたいと思っています。代わりに 'atan2'を使用することをお勧めします。なぜなら、あなたの宇宙でのポイントがどこにあるのかを尊重するからです。私の編集を試して、それが動作するかどうか確認してください。最小〜最大正規化はあなたの目的に適しているはずですが、角度を計算するのではなく、大きさを計算したいと思っています。 – rayryeng

+0

天使を計算しないと、望む結果が得られませんが、天使の計算ではうまくいきます。私はあなたに画像を見せたいが、ここに画像を投稿する方法は分からない。 –

関連する問題