ファイル名に通し番号​を含めたい(broc​kproc関数のルー​プ処理)

4 vues (au cours des 30 derniers jours)
Yuka Sashihara
Yuka Sashihara le 20 Avr 2022
Commenté : Yuka Sashihara le 25 Avr 2022
以下を参考に画像を9等分しようとしています。
これを画像11枚についてループ処理したいです。ファイル名に連番(i)をふくめて保存するにはどうすればいいでしょうか。
上記では、以下のように別ファイルに関数cropAndSaveBlock.mを作成し、
function cropAndSaveBlock(bs)
save_loc = 'D:\easypcctest\20220408\cuts';
fileName = [save_loc, '\img', 'cut',int2str(bs.location(1)), '_', int2str(bs.location(2)), '.jpg'];
imwrite(bs.data, fileName)
end
それを本コードで呼び出しています。
%im_nameに画像名を格納しています。ファイル名以外はうまくいきます
for i=1:size(im_name,1)
I=imread(im_name{i});
[a, b]=size(I);
blockSize =[a/3 b/3];
blockproc(I, blockSize, @cropAndSaveBlock)
end
①cropAndSaveBlock.mのfileNameをいじってもうまくいきません(iがコードに属する変数ではないため?)
fileName = [save_loc, '\img',int2str(i), 'cut',int2str(bs.location(1)), '_', int2str(bs.location(2)), '.jpg'];
②cropAndSaveBlock.mの中身を本コードに直接書けばファイル名にiを入れられますが、brockproc関数はそのようなことが可能ではないという理解であっていますか(やってみるとbs.locationを解決できませんといわれます)
こうした別の関数を呼び出す操作に慣れていません。よろしくお願いいたします。

Réponse acceptée

Atsushi Ueno
Atsushi Ueno le 20 Avr 2022
【参考】
>関数は block_struct を入力として受け入れ、配列、ベクトル、スカラーのいずれかを返さなければなりません。
>"ブロック構造体" は、ブロック データなどのブロックに関する情報を含む MATLAB 構造体です。
【回答】
>①cropAndSaveBlock.mのfileNameをいじってもうまくいきません(iがコードに属する変数ではないため?)
「本コード」と「cropAndSaveBlock関数」のスコープが異なる為、互いの変数にアクセス出来ないのです。
  • 「本コード」のスコープは「ベースワークスペース」
  • 「cropAndSaveBlock関数」のスコープは「関数ワークスペース」
>②cropAndSaveBlock.mの中身を本コードに直接書けばファイル名にiを入れられますが、brockproc関数はそのようなことが可能ではないという理解であっていますか(やってみるとbs.locationを解決できませんといわれます)
⇒あってます。①と同じでスコープを超えられないからです。しかし代替手段はあります。上記blockproc関数の説明の通り、bs(ブロック構造体)にiを入れる為の場所が無いだけで、あるとすればブロック画像データにiを入れる方法があります。(コメントで説明します)
【対策案】
2つの案を検証しました。2番目のevalin関数の方が簡単で無駄がありませんでした。
  1. (下図参照)ブロック画像データに4層目を作り、そこにiを入れcropAndSaveBlock関数に渡す(コメントで追記します)
  2. evalin関数によりcropAndSaveBlock関数内からベースワークスペースのiを参照する方法
2番目の方法を検証しました。3行目を変更しています
function cropAndSaveBlock(bs)
save_loc = 'D:\easypcctest\20220408\cuts';
fileName = [save_loc, '\img', int2str(evalin("base","i")), 'cut', int2str(bs.location(1)), '_', int2str(bs.location(2)), '.jpg'];
imwrite(bs.data, fileName)
end
本コードの方は変更不要です。evalin("base","i") によりスコープの壁を越えられます。
  2 commentaires
Atsushi Ueno
Atsushi Ueno le 20 Avr 2022
1番目の方法を検証しました。画像データに4層目を儲けてiの値で埋めると、どのブロック画像データにもiの値が渡るようになります。
im_name = {'lena_color.tiff'}; % ファイルは1個だけしか試してません
for i = 1:size(im_name,1)
I = imread(im_name{i});
I(:,:,4) = i; % 4層目を作りiの値をコピーする(多過ぎ!)
blockSize = size(I(:,:,1))./ 4; % 3分割でうまくいかなかったので勝手ながら4分割にしました
blockproc(I, blockSize, @cropAndSaveBlock);
end
function cropAndSaveBlock(bs)
save_loc = 'D:\easypcctest\20220408\cuts';
fileName = [save_loc, '\img', int2str(bs.data(1,1,4)), 'cut', int2str(bs.location(1)), '_', int2str(bs.location(2)), '.jpg'];
imwrite(bs.data(:,:,1:3), fileName) % 4層目を作ったので1~3層目のみファイルに書き出す
end
1番目の方法の欠点は下記の通りです。
  • i(スカラ値)を渡す為だけに画像データを1層追加し余計なメモリアクセスを増やしてしまう事
  • 画像データの型はuint8なので、i=255を超えると上記プログラムではうまくいかなくなる事
2番目の欠点の対策としてはiの値を文字列にして各ブロックの先頭数要素に埋め込む方法が考えられます(検証はしてません)
Yuka Sashihara
Yuka Sashihara le 25 Avr 2022
ご丁寧な解答ありがとうございます!!!無事できました。他の方法もじっくり読んで理解します。

Connectez-vous pour commenter.

Plus de réponses (0)

Community Treasure Hunt

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

Start Hunting!