多数の画像データの同一領域を集めたい (for loopの高速化)

3 views (last 30 days)
朋貴 熊田
朋貴 熊田 on 30 Jun 2023
Commented: 朋貴 熊田 on 4 Jul 2023
多数の画像データの同一領域を集めたいです。
例えば、100枚の画像データ対して行列(1:3,1:3)の同一領域を100枚の画像全てから集め1つのセルに格納し、
さらに1画素ズラして行列(2:4,1:3)の同一領域を100枚全ての画像から集め1つのセルに格納する。
という処理を行いたいです。
処理系としては以下のように記述し、やりたいことは出来ていると思うのですが、
処理の時間が長すぎて困っています。改善点やparforを使った処理で高速化出来ますでしょうか?
回答していただけると幸いです。
%フォルダの中の拡張子を指定して内容一覧にする。画像取り込み
P='D:\subimg_lineup';
bmpFiles = dir(fullfile(P,'*.bmp'));
numfiles = length(bmpFiles);
mydata = cell(numfiles,1);
bmpFiles=natsortfiles(bmpFiles);
for k = 1:numfiles
mydata{k} =single(imread(fullfile(P,bmpFiles(k).name)));
end
%3×3画素の分割領域
bl=3;br=3;
m=(bl-1)/2;
n=(br-1)/2;
[y,x]=size(mydata{1});
picsize=x*y;
stakimg1=cell(round(picsize/2,0),1);
stakimg2=cell(picsize-round(picsize/2,0),1);
lineup_img1=zeros(round(numfiles/2,0)*3,br);
lineup_img2=zeros((numfiles-round(numfiles/2,0))*3,br);
a=1;
for row=1:x
c=1;
for col=1:y
for k=1:2:numfiles-1
padimg2=single(padarray(mydata{k},[m n],"symmetric",'both'));%mydata[2]をパディング
padimg=single(padarray(mydata{k+1},[m n],"symmetric",'both'));%mydata[1]をパディング
splitimg1=padimg(col:col+bl-1,row:row+br-1);
splitimg2=padimg2(col:col+bl-1,row:row+br-1);
lineup_img1(c:c+bl-1,1:br)=splitimg1;
lineup_img2(c:c+bl-1,1:br)=splitimg2;
c=c+bl;
end
stakimg1{a}=lineup_img1;
stakimg2{a}=lineup_img2;
a=a+1;
end
end

Accepted Answer

交感神経優位なあかべぇ
Edited: 交感神経優位なあかべぇ on 30 Jun 2023
sub2indを使用して、1画像ファイルから取る全領域を一度に取得する線形インデックスをあらかじめ作成してから、画像の領域データを取得するといった方法で作成してみました。
% サンプル画像の作成(画像ファイル数1)
I = im2gray(imread("peppers.png"));
I = {I(100:300, 100:300)};
imshow(I{1}); %元画像の表示
%75×75の画素の分割領域(サンプルなので大きめにした)
bl=75;br=75;
iSize = size(I{1});
rowNum = iSize(1) - bl + 1;%列あたりの画像数
columnNum = iSize(2) - br + 1;%行当たりの画像数
rowIdxPerField = repmat((1:bl)',br,1);%1領域あたりの列ベクトル
columnIdxPerField = repelem((1:br)',bl,1);%1領域あたりの行ベクトル
rowIdxPerColumn = rowIdxPerField + (0 : rowNum - 1);%1列当たりの列ベクトル
rowIdx = repmat(rowIdxPerColumn(:), 1, columnNum);%全領域当たりの列ベクトル
columnIdxPerColumn = columnIdxPerField + (0 : columnNum - 1);%1行あたりの行ベクトル
columnIdx = repmat(columnIdxPerColumn, rowNum, 1);%全領域あたりの行ベクトル
ind = sub2ind(iSize, rowIdx(:), columnIdx(:)); %ひとつの画像から領域全て抽出する配列要素の作成
pictureParts = cell(length(I), 1);
for i = 1 : length(I)%画像ファイルごとに実行
picturePartsData = I{i}(ind);%全領域の画像の抽出
pictureParts{i} = reshape(picturePartsData, bl, br, rowNum * columnNum); %画像データとして表示しやすい配列に再配置(配列順 : (縦ピクセル, 横ピクセル, 各領域))
end
% 4隅の画像部分の抽出(結果の表示)
showPicture = pictureParts{1};
leftUpImage = showPicture(:,:,1);% 左上
leftBottomImage = showPicture(:,:,rowNum);% 左下
rightUpImage = showPicture(:,:,rowNum * columnNum - rowNum + 1); % 右上
rightBottomIdx = showPicture(:,:,rowNum * columnNum); % 右下
% 4隅の画像の表示
montage({leftUpImage, ...
rightUpImage, ...
leftBottomImage, ...
rightBottomIdx});
  3 Comments
交感神経優位なあかべぇ
Edited: 交感神経優位なあかべぇ on 3 Jul 2023
領域を保存する変数picturePartsの配列の持たせ方を少し変えました。
% サンプル画像の作成(画像ファイル数2)
I = im2gray(imread("peppers.png"));
I = {I(101:300, 1:200), I(101:300, 201:400)};
montage(I, 'BorderSize', 10); %元画像の表示
%75×75の画素の分割領域(サンプルなので大きめにした)
bl=75;br=75;
iSize = size(I{1});
rowNum = iSize(1) - bl + 1;%列あたりの画像数
columnNum = iSize(2) - br + 1;%行当たりの画像数
rowIdxPerField = repmat((1:bl)',br,1);%1領域あたりの列インデックス
columnIdxPerField = repelem((1:br)',bl,1);%1領域あたりの行インデックス
rowIdxPerColumn = rowIdxPerField + (0 : rowNum - 1);%1列当たりの列インデックス
rowIdx = repmat(rowIdxPerColumn(:), 1, columnNum);%全領域当たりの列インデックス
columnIdxPerColumn = columnIdxPerField + (0 : columnNum - 1);%1行あたりの行インデックス
columnIdx = repmat(columnIdxPerColumn, rowNum, 1);%全領域あたりの行インデックス
ind = sub2ind(iSize, rowIdx(:), columnIdx(:)); %ひとつの画像から領域全て抽出する配列要素の作成
pictureParts = zeros([br,bl,rowNum, columnNum,length(I)], 'like', I{1});
for i = 1 : length(I)%画像ファイルごとに実行
picturePartsData = I{i}(ind);%全領域の画像の抽出
pictureParts(:,:,:,:,i)= reshape(picturePartsData, bl, br, rowNum, columnNum); %画像データとして表示しやすい配列に再配置(配列順 : (ピクセル(縦), ピクセル(横), 領域(縦), 領域(横), ファイル))
end
% 4隅の画像部分の抽出(結果の表示)
leftUpImage1 = pictureParts(:,:,1,1,1);% 左上(画像1)
leftUpImage2 = pictureParts(:,:,1,1,2);% 左上(画像2)
leftBottomImage1 = pictureParts(:,:,rowNum,1,1);% 左下(画像1)
leftBottomImage2 = pictureParts(:,:,rowNum,1,2);% 左下(画像2)
rightUpImage1 = pictureParts(:,:,1,columnNum,1); % 右上(画像1)
rightUpImage2 = pictureParts(:,:,1,columnNum,2); % 右上(画像2)
rightBottomIdx1 = pictureParts(:,:,rowNum,columnNum,1); % 右下(画像1)
rightBottomIdx2 = pictureParts(:,:,rowNum,columnNum,2); % 右下(画像2)
% 4隅の画像の表示(上から左上、左下、右上、右下の画像(左側は画像1,右側は画像2))
montage({leftUpImage1, leftUpImage2, ...
leftBottomImage1, leftBottomImage2, ...
rightUpImage1, rightUpImage2, ...
rightBottomIdx1, rightBottomIdx2}, 'Size', [4,2]);
作成したpicturePartsの配列の要素について下記に示します。
  • 1次元目 : ピクセルの縦(要素数 br)
  • 2次元目 : ピクセルの横(要素数 bl)
  • 3次元目 : 画像の領域の縦(要素数 rowNum)
  • 4次元目 : 画像の領域の横(要素数 columnNum)
  • 5次元目 : 画像ファイル
>>画像の畳み込み処理のように、
>>行列(1:3,1:3),(2:4,1:3),(3:5,1:3)...(iSize(1)-2:iSize(1),iSize(2)-2:iSize(2))
>>と画像全領域のから所望の分割画像の取得は可能でしょうか?
→ pictureParts(: , :, m, n, 1);のmとnの値を変えることで、ファイル1の所望の分割画像を取得できます。
>>複数の画像データの行列(1:3,1:3)だけを集めたファイルを作製することは可能でしょうか?
→ pictureParts(: , :, 1, 1, 1:3);のように指定すると、1~3枚目の画像データの左上部分だけを抽出できます。
朋貴 熊田
朋貴 熊田 on 4 Jul 2023
ご教授ありがとうございます。
頂いた知識最大限に活用させて頂きます。

Sign in to comment.

More Answers (0)

Categories

Find more on イメージ in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!