colfiltを使った演算について

6 ビュー (過去 30 日間)
朋貴 熊田
朋貴 熊田 2021 年 10 月 11 日
コメント済み: 朋貴 熊田 2021 年 10 月 15 日
colfiltを使って、任意のブロックサイズの分散を1画素ごとずらしながら求めようとしています。
しかし、エラー:reshape要素数を変更してはなりません。と出てしまいます。
プログラムは以下の様に書きました。
img=imread('1111.bmp');
img2=imread('2222.bmp');
fun=@(block_struct) std2(block_struct)^2;
varimg=colfilt(img,[5 5],'sliding',fun);%imgの分散
varimg2=colfilt(img2,[5 5],'sliding',fun);%img2の分散
この時何が問題で、プログラムにエラーが出ているのでしょうか?
ご教授お願い致します。

採用された回答

Shunichi Kusano
Shunichi Kusano 2021 年 10 月 12 日
colfiltのドキュメントには下記のように書いています。
  • まず、colfilt A m n 列の各近傍を、関数 im2col を使用して一時行列の列に再配置します。
  • 次に、colfilt は関数 fun をこの一時行列に適用します。fun は、一時行列の各列の単一値を含む行ベクトルを返さなければなりません (sum などの列圧縮関数は適切なタイプの出力を返します)。
  • 最後に、colfilt fun で返されるベクトルを、関数 reshape を使用して A と同じサイズの行列に形状を変更します。
どういうことかというと例えば入力する画像が100x100の大きさだったとして、colfilt(A,[5 5],'sliding',fun)を実行すると、
  1. まずim2colにより、大きさ25x10000の配列ができます。これは、行方向に各ブロックの値が1列に並び替えられてできたものです。slidingを指定しているので、となり合う列同士で値の重複は結構あります。
  2. そのあとこの配列に例えばsumみたいな列圧縮関数(何も引数を指定しないと列ごと行方向に和をとって一つの値が計算される)を処理すると、結果1x10000の配列ができます。
  3. これをreshapeで100x100に形を直すことで、スライディングブロックごとに和を取った結果の配列ができます。
ということで、エラーが出る理由はstd2関数を使っているからです。std2を使うと2次元配列の全ての値を使って標準偏差が計算されるので、上記で言うと25x10000の配列が1x1の大きさに圧縮されてしまいます。そのあと100x100にreshapeできなくなってしまうのでエラーが出ます。std2ではなくstdを使えば大丈夫のはずです。
  4 件のコメント
朋貴 熊田
朋貴 熊田 2021 年 10 月 15 日
ご回答ありがとうございます。
示したコードの方は私が間違えていいたので、共分散のcov関数で大丈夫です。ありがとうございます。
colfiltは3次元を入れられないのですね...
来年のMatlabで対応されることを待ち望んでおります。
ご教授ありがとうございました。

サインインしてコメントする。

その他の回答 (0 件)

Community Treasure Hunt

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

Start Hunting!