有在你的代碼的幾個錯誤,所以我會盡量採取他們一個接一個。這裏是你的原代碼,重新格式化了一下:
img = [0 0 0 0 0;
0 1 1 0 0;
0 0 0 0 0;];
[m n] = size(img)
img = padarray(img, [2 2], 0)
fi_neighbors = zeros(1,8);
for i = 1:m
for j = 1:n
for r = 3:m
for c = 3:n
neighbors(1) = img(r-1,c-1); % Upper left.
neighbors(2) = img(r-1,c); % Upper middle.
neighbors(3) = img(r-1,c+1); % Upper right.
neighbors(4) = img(r,c-1); % left.
neighbors(5) = img(r,c+1); % right.
neighbors(6) = img(r+1,c+1); % Lower right. <-- corrected
neighbors(7) = img(r+1,c); % lower middle.
neighbors(8) = img(r+1,c-1); % Lower left.
end
end
fi_neighbors = [neighbors;fi_neighbors]
end
end
第一個錯誤是,循環變量i
和j
從不使用。因此它們是無用的(除了讓我們執行相同的計算m x n
次)。讓我們把它們拿出來。
img = [0 0 0 0 0;
0 1 1 0 0;
0 0 0 0 0;];
[m n] = size(img)
img = padarray(img, [2 2], 0)
fi_neighbors = zeros(1,8);
for r = 3:m
for c = 3:n
neighbors(1) = img(r-1,c-1); % Upper left.
neighbors(2) = img(r-1,c); % Upper middle.
neighbors(3) = img(r-1,c+1); % Upper right.
neighbors(4) = img(r,c-1); % left.
neighbors(5) = img(r,c+1); % right.
neighbors(6) = img(r+1,c+1); % Lower right.
neighbors(7) = img(r+1,c); % lower middle.
neighbors(8) = img(r+1,c-1); % Lower left.
end
end
fi_neighbors = [neighbors;fi_neighbors]
隨着這些循環的方式進行,我們可以看到,你只更新fi_neighbors
數組,你已經做了所有的計算後的一次。這就是爲什麼你之前得到相同結果m x n
次。我們需要移動的循環,結果就是每個組計算後更新內部(我已經離開了這個設定的時間和僅列循環):
for r = 3:m
for c = 3:n
neighbors(1) = img(r-1,c-1); % Upper left.
neighbors(2) = img(r-1,c); % Upper middle.
neighbors(3) = img(r-1,c+1); % Upper right.
neighbors(4) = img(r,c-1); % left.
neighbors(5) = img(r,c+1); % right.
neighbors(6) = img(r+1,c+1); % Lower right.
neighbors(7) = img(r+1,c); % lower middle.
neighbors(8) = img(r+1,c-1); % Lower left.
fi_neighbors = [neighbors;fi_neighbors] %// moved inside loops
end
end
接下來是我們的循環範圍。您在每一邊填充了2個零的數組,因此您從行/列3
開始。這很好,但你仍然在m
和n
處結束循環。這意味着你處理(m-2) x (n-2)
像素。你需要擴大範圍。但實際上,你的填充量超過了你的需要。每邊一個像素的填充就足夠了,所以讓我們一次都做,改變填充和糾正範圍:
img = [0 0 0 0 0;
0 1 1 0 0;
0 0 0 0 0;];
[m n] = size(img)
img = padarray(img, [1 1], 0)
fi_neighbors = zeros(1,8);
for r = 2:m+1
for c = 2:n+1
neighbors(1) = img(r-1,c-1); % Upper left.
neighbors(2) = img(r-1,c); % Upper middle.
neighbors(3) = img(r-1,c+1); % Upper right.
neighbors(4) = img(r,c-1); % left.
neighbors(5) = img(r,c+1); % right.
neighbors(6) = img(r+1,c+1); % Lower right.
neighbors(7) = img(r+1,c); % lower middle.
neighbors(8) = img(r+1,c-1); % Lower left.
fi_neighbors = [neighbors;fi_neighbors]
end
end
現在你應該有一個工作計劃,讓你正確的輸出:
fi_neighbors =
0 0 0 0 0 0 0 0 <-- img(m,n) neighbors
1 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0
0 1 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 1 0 0 0 0
0 0 0 1 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 1
0 0 0 0 0 0 1 1
0 0 0 0 0 1 1 0
0 0 0 0 0 1 0 0 <-- img(1,1) neighbors
0 0 0 0 0 0 0 0
這可以工作,但看看我添加到輸出的筆記。結果的第一行包含像素img(m,n)
的鄰居:圖像中的最後像素。倒數第二行包含img(1,1)
的鄰居,最後一行由於您初始化爲zeros(1,8)
而剛剛掛在那裏。所有這些對我來說都不自然,所以我要翻轉結果數組,以便img(1,1)
是第一行。而且,在每個循環迭代中增長一個數組是很慢的。我們想要預分配數組,然後將數據放在適當的位置。
由於我們引用原始圖像中的像素,但是在填充圖像上計算,添加計數器變量比執行所有行/列索引計算容易得多,所以我添加了pix
作爲計數器:
img = [0 0 0 0 0;
0 1 1 0 0;
0 0 0 0 0;];
[m n] = size(img);
img = padarray(img, [1 1], 0)
fi_neighbors = zeros(m*n,8); % preallocate result array
pix = 0; % pixel counter
for r = 2:m+1
for c = 2:n+1
pix = pix + 1; % find neighbors for next pixel
neighbors(1) = img(r-1,c-1); % Upper left.
neighbors(2) = img(r-1,c); % Upper middle.
neighbors(3) = img(r-1,c+1); % Upper right.
neighbors(4) = img(r,c-1); % left.
neighbors(5) = img(r,c+1); % right.
neighbors(6) = img(r+1,c+1); % Lower right.
neighbors(7) = img(r+1,c); % lower middle.
neighbors(8) = img(r+1,c-1); % Lower left.
fi_neighbors(pix,:) = neighbors; % update the correct row
end
end
結果:
fi_neighbors =
0 0 0 0 0 1 0 0
0 0 0 0 0 1 1 0
0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 1
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 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 1 1 0 0 0 0 0
1 1 0 0 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
現在,img(1,1)
鄰居們都在第1行的img(m,n)
鄰居們都行m * n個。
最後,您可以進行一些快速優化。他們都需要改變結果的順序。如果你願意以不同的順序呈現像素和鄰居,我將試圖清楚地表明,那麼我們可以首先改變循環的順序以利用MATLAB的列主要順序。
相反的:
for r = 2:m+1
for c = 2:n+1
...
end
end
,我們將使用:
for c = 2:n+1 % be sure to swap m and n as well!
for r = 2:m+1
...
end
end
對於大型矩陣,這應該與緩存保持我們正在當前列有幫助。這將改變像素的排序,以便代替第二像素是img(1,2)
,現在將是img(2,1)
,然後img(3,1)
,直到img(m,1)
,然後是img(1,2)
。
第二個變化凝聚所有的鄰居計算爲2行(也許3),但它改變,因爲我將在下面顯示的順序:
pix = 0; % pixel counter
for c = 2:n+1
for r = 2:m+1
pix = pix + 1; % find neighbors for next pixel
neighbors = img(r-1:r+1,c-1:c+1);
neighbors = neighbors(:).';
fi_neighbors(pix,:) = neighbors; % update the correct row
end
end
這需要的img
子矩陣當前像素周圍,然後使用冒號表示將其轉換爲列向量,最後將其轉換爲行向量。下面是導致鄰居位置的內neighbors
:
neighbors(1) % Upper left.
neighbors(2) % left.
neighbors(3) % Lower left.
neighbors(4) % Upper middle.
neighbors(5) % *** current pixel ***
neighbors(6) % Lower middle.
neighbors(7) % Upper right.
neighbors(8) % right.
neighbors(9) % Lower right.
但是現在我們已經在neighbors
9個元素包括當前像素!如果您確實不想列出當前像素,我們可以修復該問題,但無論哪種方式,我們都需要將fi_neighbors
的大小更改爲(m*n,9)
。如果需要,我們可以從結果中刪除第5列。
下面是最終代碼:
img = [0 0 0 0 0;
0 1 1 0 0;
0 0 0 0 0;];
[m n] = size(img);
img = padarray(img, [1 1], 0);
fi_neighbors = zeros(m*n,9); % preallocate result array
pix = 0; % pixel counter
for c = 2:n+1
for r = 2:m+1
pix = pix + 1; % find neighbors for next pixel
neighbors = img(r-1:r+1,c-1:c+1);
neighbors = neighbors(:).';
fi_neighbors(pix,:) = neighbors; % update the correct row
end
end
fi_neighbors(:,5) = []; % OPTIONAL - remove current pixel from each row
顯然,還有更多你可以做,但是這應該是一個很好的開始。
這是不是正確的?又名,它目前輸出了什麼? – Adriaan
預期產量是多少?該代碼只是簡單地將圖像中每個像素的所有8個像素鄰域強度連接成一個巨型陣列。 – rayryeng
您在2個內部循環中覆蓋結果的事實可能會很麻煩。你計算一些元素,然後放在'neighbors(1:8)'中。你在循環中每次都這樣做。除此之外。有最近鄰計算的Matlab函數。最好的選擇取決於你想要做什麼。除此之外。如果代碼看起來像在Matlab的問題中爲你做的那樣,你應該考慮重新格式化。這可以通過標記所有內容並選擇重新格式化或菜單中的某些內容來完成。 – patrik