縦方向、もしくは横方​向のみに規定幅(50​ピクセル)での畳み込​みを行いたいのですが

2 views (last 30 days)
Takumi Enomoto
Takumi Enomoto on 7 Mar 2022
Commented: Takumi Enomoto on 17 Mar 2022
50*50ピクセルの画像を横方向に5枚、縦方向に4枚づつ並べた、一枚の写真の行列画像(5*4=250*200ピクセル)を用意します。その画像をCNNにかけるために畳み込みをしたいのですが、行列画像の各要素の情報を畳み込みたいため、縦、横それぞれで畳み込みをしたいです。イメージは以下の図の通りです。このような縦方向、もしくは横方向のみに規定幅(50ピクセル)での畳み込みを行いたいのですがMATLABで行うにはどのような操作が必要になりますでしょうか。お力をお貸しください。

Answers (3)

Atsushi Ueno
Atsushi Ueno on 8 Mar 2022
Edited: Atsushi Ueno on 9 Mar 2022
MATLABなら(他の言語でも)、上図の様に50*50*5*4にすれば考え易いです。
base = imread('coins.png');
base = base(51:100, 51:100); % baseは50*50ピクセルの画像
stack = repmat(base,[1 1 5 4]); % 横方向に5枚、縦方向に4枚づつ重ねる
size(stack)
ans = 1×4
50 50 5 4
for i = 1:size(stack,1)
for j = 1:size(stack,2)
cnv1(i,j) = mean(stack(i,j,:,1)); % 横方向に5枚串刺しで画素値を平均する(変わらない)
cnv2(i,j) = mean(stack(i,j,1,:)); % 縦方向に4枚串刺しで画素値を平均する(変わらない)
end % 畳み込みの演算内容は適当に平均(mean関数)にしました
end
cnv1 = uint8(cnv1); % 結果は元の画像(base)と同じ
cnv2 = uint8(cnv2); % 結果は元の画像(base)と同じ

Atsushi Ueno
Atsushi Ueno on 9 Mar 2022
image processing toolboxがあれば、上記の各種関数を参考にすべきと思います。
先の回答と同様に50*50*5*4の画像積層データを作成し、blockproc関数で関数 fun をサイズ [1 1] の各ブロックに適用します。
base = imread('coins.png');
base = base(51:100, 51:100); % baseは50*50ピクセルの画像
stack = repmat(base,[1 1 5 4]); % 横方向に5枚、縦方向に4枚づつ重ねる
fun = @(block_struct) mean(block_struct.data(:,:,:)); % 畳み込みの代わりに平均を演算する関数
tate = uint8(blockproc(squeeze(stack(:,:,:,1)),[1 1],fun)); % 横方向に5枚串刺しで画素値を平均する(変わらない)
yoko = uint8(blockproc(squeeze(stack(:,:,1,:)),[1 1],fun)); % 縦方向に4枚串刺しで画素値を平均する(変わらない)
% blockproc関数は画像データを想定していて3次元データしか受け付けないので
% 縦と横それぞれのデータを引数に渡す際にsqueze関数で1次元減らしています。

Atsushi Ueno
Atsushi Ueno on 9 Mar 2022
先の回答1先の回答2を振り返ると、自分の考えばかりで肝心の質問の回答になっていないと反省しました。
上記畳み込み関数を使用しました。
base = imread('coins.png'); % サンプル画像
base = base(51:100, 51:100); % トリミング
sb = size(base) % baseは50*50ピクセルの画像
sb = 1×2
50 50
sample = repmat(base,[4 5]); % 横方向に5枚、縦方向に4枚づつ並べた一枚の写真の行列画像
st = size(sample)./sb % 縦横に並べた枚数(50*50ピクセルが(5枚,4枚)=250*200ピクセル)
st = 1×2
4 5
imshow(sample) % sampleは横250*縦200ピクセルの画像
for i = 1:1:sb(1) % 行列画像の各要素の情報を畳み込みたいため、縦、横それぞれで畳み込みをしたい
for j = 1:1:sb(2) % このような縦方向、もしくは横方向のみに規定幅(50ピクセル)での畳み込みを行いたい
cnv1(i,j) = conv(sample(i:sb(1):end, j),ones(st(1), 1),'valid'); % 縦方向のみに規定幅(50ピクセル)での畳み込み
cnv2(i,j) = conv(sample(i, j:sb(2):end),ones(1, st(2)),'valid'); % 横方向のみに規定幅(50ピクセル)での畳み込み
end % この例では、畳み込みの係数は全て1とします(↑ここ)
end
imshow(uint8(cnv1./st(1))) % 枚数で割れば元の画像になります
  1 Comment
Takumi Enomoto
Takumi Enomoto on 17 Mar 2022
ご返事遅れてしまい申し訳ありません。
丁寧な解説で頭が上がりません。例を挙げて教えてくださったおかげで理解できました。
ありがとうございます。

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!