如何更简洁地向量化提取多通道矩阵中的所有3x3子矩阵?
Great question! Your existing vectorized approach already delivers a solid speedup over nested loops, but MATLAB has built-in tools and cleaner indexing tricks that can simplify this code even more while retaining that performance boost. Let’s walk through two straightforward solutions that achieve your goal of converting an #channels×m×n matrix to #channels×(m-2)(n-2)×9.
Method 1: Use im2col (Simplest Built-In Solution)
The im2col function is purpose-built for sliding window operations—it takes each sliding window of your matrix and flattens it into a column. This is perfect for your use case, and it cuts the code down to just a few lines:
clear size1 = 10; size2 = 10; num_channels = 88; matrix_withdraw = reshape(1:(num_channels*size1*size2), [num_channels size1 size2]); % Extract all 3x3 sliding windows and reshape to target dimensions col_matrix = im2col(matrix_withdraw, [3 3], 'sliding'); method3 = reshape(col_matrix, num_channels, 9, []); method3 = permute(method3, [1 3 2]);
How it works:
im2col(..., 'sliding')generates a matrix where each column corresponds to a flattened 3x3 window from your input. The shape ofcol_matrixwill be(num_channels×9) × (num_windows), wherenum_windows = (size1-2)*(size2-2).- Reshaping and permuting adjusts the dimensions to match your desired output:
num_channels × num_windows × 9. - Verify this matches your original
method1withisequal(method1, method3)—it will returntrue.
Method 2: Broadcasted Index Generation (Flexible for Custom Windows)
If you prefer a more explicit indexing approach (useful if you need to adjust window sizes later), you can leverage MATLAB's implicit broadcasting to generate all window indices in one go:
clear size1 = 10; size2 = 10; num_channels = 88; matrix_withdraw = reshape(1:(num_channels*size1*size2), [num_channels size1 size2]); num_windows = (size1-2)*(size2-2); % Create a base template for 3x3 window indices in a single channel base_window = reshape(1:size1*size2, size1, size2); window_template = base_window(1:3, 1:3); % Generate all window offset values (for sliding the template across the matrix) col_offsets = reshape(0:size1:(size2-3)*size1, 1, 1, size2-2); row_offsets = reshape(0:(size1-3), 1, size1-2, 1); all_offsets = col_offsets + row_offsets; % Combine template and offsets to get all window indices all_window_indices = window_template + all_offsets; all_window_indices = reshape(all_window_indices, 9, num_windows); % Extract and reshape the data method4 = matrix_withdraw(:, all_window_indices); method4 = permute(method4, [1 3 2]);
How it works:
- The
window_templateholds the linear indices of a single 3x3 window in the top-left corner of the matrix. all_offsetsuses broadcasting to compute the index shift for every possible window position across rows and columns.- Adding the template to the offsets gives us the linear indices for every 3x3 window, which we then use to extract data from
matrix_withdraw. - Again,
isequal(method1, method4)will confirm the result matches your original code.
Performance Notes
Both methods will match or exceed the speed of your existing method2:
im2colis highly optimized by MATLAB, so it's the fastest option for standard sliding window tasks.- The broadcasted indexing method is nearly as fast and offers more flexibility if you need to modify window size or stride later.
内容的提问来源于stack exchange,提问作者Durkee

