大きな二次元配列から不特定の間隔かつ特定サイズの二次元行列をfor loopを使わずに取り出す方法に関して
이 질문을 팔로우합니다.
- 팔로우하는 게시물 피드에서 업데이트를 확인할 수 있습니다.
- 정보 수신 기본 설정에 따라 이메일을 받을 수 있습니다.
오류 발생
페이지가 변경되었기 때문에 동작을 완료할 수 없습니다. 업데이트된 상태를 보려면 페이지를 다시 불러오십시오.
이전 댓글 표시
0 개 추천
目的としては、大きな二次元の配列(画像等)から特定の大きさを持つ配列を抽出し、それをCell配列や通常のArrayとして格納したいと考えています。
具体的な状況は添付の写真のように、大きな二次元配列中に決まった間隔ではない、特定の大きさで、互いに接触しない1で識別された領域が存在するとします。この大きな配列から添付写真に示すような1で構成された3x3の像を初期の大きな像における位置関係を保持したまま、cell配列ないしは通常の配列変数としてfor loopを行わずに並び替えたいと考えています。
現時点で試したこととして、findや論理インデックスを利用して取り出す方法などを試していますが、この方法では1に対応する配列が列ごとに並び替えられて出力されてしまい、目的の形状に変形し保存が難しい状況にあります。結局やりたいこととしては、0に対応するすべての配列を削除し、残っている配列を位置関係を保持したまま結合させたいということです。
こちらのコードもforとifを利用して実装することはできるのですが、仮に何らかの0などの数値を除去する関数等があってループを使用せずに目的配列のデータが取得する事ができればすごく助かります。
ご不明な点が有ればコメントいただけると嬉しいです。よろしくお願いいたします。

채택된 답변
Hernia Baby
2021년 2월 27일
2 개 추천
まずは下準備
clc,clear,close all;
% 抜き出す部分行列はk×kとする
k = 3;
% ランダムな行列を作成
X = randn(11,12);
% 図と同じ分布を作る
A = zeros(11,12);
strt = [2, 2; 3,9; 7,7; 8,3];
for i = 1:size(strt(:,1))
A(strt(i,1):strt(i,1)+k-1,strt(i,2):strt(i,2)+k-1) = 1;
end
次に各部分行列の最初の行番号と列番号のみを抽出します。
それにそってk×kの行列を抜き出せばいいからです。
% 各部分行列の最初の(行,列)のみ抽出
vec_l = zeros(size(A(1,:)));
vec_r = zeros(size(A(:,1)));
A_lslide = [vec_l; A(1:end-1,:)];
A_lxor = xor(A,A_lslide);
A_l = A.*A_lxor;
A_l_rslide = [vec_r,A_l(:,1:end-1)];
A_l_rs_xor = xor(A_l,A_l_rslide);
A_lr = A_l.*A_l_rs_xor
A_lr =
0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
ができました
次に該当するセルの行番号、列番号を抜き出します。
今回は列の低い順(左から右)に進む順に番号を割り当てています。
ここまで行けば部分行列を抜き出せるので好きに連結できます。
[x, y] = find(A_lr ~= 0);
[x, y] % チェック用
ans =
2 2
8 3
7 7
3 9
最後に部分行列を抜き出して連結します。
length(x)分の部分行列(今回は4つ)ができますので、2×2にいったん分けます。
縦方向に連結した後に、横方向に連結しています。
% 連結
X_ph_s = X_p(:,:,1);
X_ph_f = X_p(:,:,length(x)/2+1);
cnt = 1;
while cnt < length(x)/2
X_ph_s = vertcat(X_ph_s,X_p(:,:,cnt+1));
X_ph_f = vertcat(X_ph_f,X_p(:,:,length(x)/2+cnt+1));
cnt = cnt + 1;
end
X_ex = horzcat(X_ph_s,X_ph_f)
X_ex =
-0.7049 1.3229 -0.7501 -0.0275 3.4553 -0.4563
0.8029 -0.4669 1.3345 2.6822 0.2942 -0.6431
-0.3228 -0.1699 0.0159 1.9408 -0.8317 -0.6652
-0.5139 -0.5316 1.7985 -2.6426 2.3228 -1.1011
-0.0719 -0.3853 -0.3498 0.8617 -1.5182 0.9805
0.4289 1.2715 0.0501 -1.3336 -0.3510 -0.5748
確認用に元のXで該当する部分だけを見てみましょう
X.*A

댓글 수: 6
Hernia Baby
2021년 2월 27일
作ったコードはこちら
clc,clear,close all;
% 抜き出す部分行列はk×kとする
k = 3;
% ランダムな行列を作成
X = randn(11,12);
% 図と同じ分布を作る
A = zeros(11,12);
strt = [2, 2; 3,9; 7,7; 8,3];
for i = 1:size(strt(:,1))
A(strt(i,1):strt(i,1)+k-1,strt(i,2):strt(i,2)+k-1) = 1;
end
% 各部分行列の最初の(行,列)のみ抽出
vec_l = zeros(size(A(1,:)));
vec_r = zeros(size(A(:,1)));
A_lslide = [vec_l; A(1:end-1,:)];
A_lxor = xor(A,A_lslide);
A_l = A.*A_lxor;
A_l_rslide = [vec_r,A_l(:,1:end-1)];
A_l_rs_xor = xor(A_l,A_l_rslide);
A_lr = A_l.*A_l_rs_xor;
[x, y] = find(A_lr ~= 0);
% 各部分行列を抽出
for i = 1:size(x)
X_p(:,:,i) = X(x(i):x(i)+k-1,y(i):y(i)+k-1);
end
% 連結
X_ph_s = X_p(:,:,1);
X_ph_f = X_p(:,:,length(x)/2+1);
cnt = 1;
while cnt < length(x)/2
X_ph_s = vertcat(X_ph_s,X_p(:,:,cnt+1));
X_ph_f = vertcat(X_ph_f,X_p(:,:,length(x)/2+cnt+1));
cnt = cnt + 1;
end
X_ex = horzcat(X_ph_s,X_ph_f)
K.S.
2021년 3월 2일
ご回答誠にありがとうございます!
非常に参考になりました。まずお礼申し上げます。
しかし、依然として配置関係を維持したまま切り取りデータを並び替える部分がうまくいきません。
最終的な出力arrayであるX_exでは、右斜め下のデータが右上に配置されています。これを正確な位置に配置するためのルールをどのように設けるかを考察中です。
例えば第一セルに配置される初期インデックス(2,2)を2*2などとして並び替える方法を考えてみましたが、この場合は例えば以下の様な数列が得られている場合エラーになるのだろうか?という所で現在止まっています。
いずれにせよ非常に参考になったので、ありがとうございました!!
Hernia Baby
2021년 3월 2일
sortrows関数を使って並べ替えを行えばできます。
まず左から右順に座標を並べ替えて左半分と右半分の行列を分断します。
上から下順にそれぞれの行列を並べ替えます。
% 順番を並び替える
[x, y] = find(A_lr ~= 0);
% 左から右の順番に並び替える
idx = sortrows([x,y],2);
% 半分に区切って上から下の順番にそれぞれ並び替える
idx(1:2,:) = sortrows(idx(1:2,:),1);
idx(3:4,:) = sortrows(idx(3:4,:),1);
% x,yを更新
x = idx(:,1);
y = idx(:,2);
突貫で作りましたが、以下のコードになります。
4つの行列を抽出する場合、限定です。
clc,clear,close all;
% 抜き出す部分行列はk×kとする
k = 3;
% ランダムな行列を作成
X = randn(11,12);
% 図と同じ分布を作る
A = zeros(11,12);
strt = [2, 2; 3,9; 7,7; 8,3];
for i = 1:size(strt(:,1))
A(strt(i,1):strt(i,1)+k-1,strt(i,2):strt(i,2)+k-1) = 1;
end
% 各部分行列の最初の(行,列)のみ抽出
vec_l = zeros(size(A(1,:)));
vec_r = zeros(size(A(:,1)));
A_lslide = [vec_l; A(1:end-1,:)];
A_lxor = xor(A,A_lslide);
A_l = A.*A_lxor;
A_l_rslide = [vec_r,A_l(:,1:end-1)];
A_l_rs_xor = xor(A_l,A_l_rslide);
A_lr = A_l.*A_l_rs_xor;
% 順番を並び替える
[x, y] = find(A_lr ~= 0);
% 左から右の順番に並び替える
idx = sortrows([x,y],2);
% 半分に区切って上から下の順番にそれぞれ並び替える
idx(1:2,:) = sortrows(idx(1:2,:),1);
idx(3:4,:) = sortrows(idx(3:4,:),1);
% x,yを更新
x = idx(:,1);
y = idx(:,2);
% 各部分行列を抽出
for i = 1:size(x)
X_p(:,:,i) = X(x(i):x(i)+k-1,y(i):y(i)+k-1);
end
% 連結
X_ph_s = X_p(:,:,1);
X_ph_f = X_p(:,:,length(x)/2+1);
cnt = 1;
while cnt < length(x)/2
X_ph_s = vertcat(X_ph_s,X_p(:,:,cnt+1));
X_ph_f = vertcat(X_ph_f,X_p(:,:,length(x)/2+cnt+1));
cnt = cnt + 1;
end
X_ex = horzcat(X_ph_s,X_ph_f)
X_ex =
-0.0890 -0.3186 0.3060 -1.9272 0.2569 -0.9979
-1.7734 -0.4938 -1.2305 0.2996 0.4722 -0.8652
-2.2755 0.1394 0.4226 1.5051 -1.6795 0.1100
-2.5442 0.4766 1.0540 -1.0678 1.5880 -0.4633
0.7820 -0.8282 -0.7393 0.0909 -0.3851 -0.7445
1.2671 -1.7880 0.7750 -0.1203 0.3233 -1.5090
X.*A

Hernia Baby
2021년 3월 2일
편집: Hernia Baby
2021년 3월 2일
ちなみにこのコードはパッと考える限り二つほど弱点があるなと思いました
1.以下のようなケース
001110011100000000
001110011100000000
001110011100000000
000000000111011100
000000000111011100
000000000111011100
順番がおかしくなります
2.以下のようなケース
000111000000111000
000111000000111000
000111000000111000
000111000000111000
000111000000111000
000111000000111000
上二つしか行列を抽出してくれません
(下の二つは消える)
----------------
これは別途考える必要があるなと思っています
並べ替えはここで書くと長くなりそうなので、
どうしてもだめでしたら再度MATLAB ANSWERSにご投稿ください
Hernia Baby
2021년 3월 20일
K.S.
2021년 3월 21일
ありがとうございます!!!!!
こちらも、いくつか実行時エラーが出てきていましたので事前に領域区分した状態で数値が存在している部分を探索するようなコードを記述して解決してきました。まだ、Hernia様のコードは確認できておりませんが、取り急ぎお礼のご連絡まで。
추가 답변 (0개)
카테고리
도움말 센터 및 File Exchange에서 Shifting and Sorting Matrices에 대해 자세히 알아보기
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!웹사이트 선택
번역된 콘텐츠를 보고 지역별 이벤트와 혜택을 살펴보려면 웹사이트를 선택하십시오. 현재 계신 지역에 따라 다음 웹사이트를 권장합니다:
또한 다음 목록에서 웹사이트를 선택하실 수도 있습니다.
사이트 성능 최적화 방법
최고의 사이트 성능을 위해 중국 사이트(중국어 또는 영어)를 선택하십시오. 현재 계신 지역에서는 다른 국가의 MathWorks 사이트 방문이 최적화되지 않았습니다.
미주
- América Latina (Español)
- Canada (English)
- United States (English)
유럽
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)