找到最大的子矩阵

问题描述 投票:0回答:1

奇数大小的最大子矩阵

import numpy as np

array = np.array([[np.nan, 255, 255, 0, 0, 0, 0, 0, 255, np.nan],
                  [np.nan, 255, 255, 255, 0, 0, 0, 0, 255, np.nan],
                  [np.nan, 255, 255, 255, 255, 0, 0, 255, 255, np.nan],
                  [np.nan, 255, 255, 255, 255, 255, 255, 255, 255, np.nan],
                  [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
                  [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
                  [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
                  [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
                  [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
                  [np.nan, 255, 255, 255, 255, 255, 255, 255, 255, np.nan],
                  [np.nan, 255, 255, 255, 255, 0, 255, 255, 255, np.nan],
                  [np.nan, 255, 255, 255, 0, 0, 0, 255, 255, np.nan],
                  [np.nan, 255, 255, 0, 0, 0, 0, 0, 255, np.nan],
                  [np.nan, 255, 255, 255, 0, 0, 0, 0, 255, np.nan],
                  [np.nan, 255, 255, 255, 255, 0, 255, 255, 255, np.nan],
                  [np.nan, 255, 255, 255, 255, 255, 255, 255, 255, np.nan],
                  [np.nan, 255, 255, 255, 255, 255, 255, 255, 255, np.nan],
                  [np.nan, 255, 255, 255, 255, 255, 255, 255, 255, np.nan],
                  [np.nan, 255, 255, 255, 255, 0, 255, 255, 255, np.nan],
                  [np.nan, 255, 255, 255, 255, 255, 255, 255, 255, np.nan],
                  [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
                  [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
                  [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
                  [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
                  [np.nan, 255, 255, 255, 255, 255, 255, 255, 255, np.nan],
                  [np.nan, 255, 255, 255, 255, 255, 255, 255, 255, np.nan]])

预期输出是


    [[255, 255, 255, 255, 255, 255, 255, 255],
    [255, 255, 255, 255, 0, 255, 255, 255, ],
    [255, 255, 255, 0, 0, 0, 255, 255],
    [255, 255, 0, 0, 0, 0, 0, 255],
    [255, 255, 255, 0, 0, 0, 0, 255],
    [255, 255, 255, 255, 0, 255, 255, 255],
    [255, 255, 255, 255, 255, 255, 255, 255],
    [255, 255, 255, 255, 255, 255, 255, 255],
    [255, 255, 255, 255, 255, 255, 255, 255],
    [255, 255, 255, 255, 0, 255, 255, 255],
    [255, 255, 255, 255, 255, 255, 255, 255]]


m, n = array.shape

# Initialize the maximum submatrix size and its starting indices
max_submatrix_size = 0
max_submatrix_start_i = 0
max_submatrix_start_j = 0

# Iterate over all possible starting indices of the window
for i in range(m):
    for j in range(n):
        # Initialize the window size
        window_size = 0
        # Expand the window until it reaches the end of the array or encounters a non-255 value
        while i + window_size < m and j + window_size < n and array[i + window_size, j + window_size] == 255:
            window_size += 1
        # Update the maximum submatrix size and its starting indices
        if window_size > max_submatrix_size:
            max_submatrix_size = window_size
            max_submatrix_start_i = i
            max_submatrix_start_j = j
        # Shrink the window size and check again
        for k in range(1, window_size + 1):
            if i + k >= m or j + k >= n or array[i + k, j + k] != 255:
                break
            # Update the maximum submatrix size and its starting indices
            if k + 1 > max_submatrix_size:
                max_submatrix_size = k + 1
                max_submatrix_start_i = i
                max_submatrix_start_j = j
                window_size = k
            break

# Extract the largest submatrix
largest_submatrix = array[max_submatrix_start_i:max_submatrix_start_i + max_submatrix_size,
                          max_submatrix_start_j:max_submatrix_start_j + max_submatrix_size]

print(largest_submatrix)

我得到的输出是


[[255. 255. 255.   0.   0.   0. 255. 255.]
 [255. 255.   0.   0.   0.   0.   0. 255.]
 [255. 255. 255.   0.   0.   0.   0. 255.]
 [255. 255. 255. 255.   0. 255. 255. 255.]
 [255. 255. 255. 255. 255. 255. 255. 255.]
 [255. 255. 255. 255. 255. 255. 255. 255.]
 [255. 255. 255. 255. 255. 255. 255. 255.]
 [255. 255. 255. 255.   0. 255. 255. 255.]]


我尝试过使用滑动窗口,但没有从中得到太多帮助(如果有人可以解决它)。如果有的话,还要考虑最大子矩阵内部可以有 nan 值的情况。如果可能的话也可以建议不同的方法。

python numpy matrix 2d nan
1个回答
0
投票

这是一个递归函数。如果矩阵非常稀疏并且超过递归深度,您可以将其更改为使用

while
循环:

def largest_submatrix(arr):
  """
  Obtain the largest submatrix
  """

  def find_index(arr, idx):
    """
    Obtain the row and col slices containing non-na values
    """
    n,m = arr.shape
    if len(idx) == 2:
      row1, row2 = (idx[0], idx[0] + 1) if idx[0] < n else (idx[0] - 1, idx[0])
      col1, col2 = (idx[1], idx[1] + 1) if idx[1] < m else (idx[1] - 1, idx[1])
      idx = row1, row2, col1,col2,0
    else:  row1, row2, col1, col2,_ = idx
    
    # move up
    if arr[row1-1:row2, col1:col2].all():
      row1 = row1 - 1 if row1> 0 else 0 
    # move down
    if arr[row1:row2+1, col1:col2].all():
      row2 = row2 + 1 if row2 < n else n
    # move left
    if arr[row1:row2, col1-1:col2].all():
      col1 = col1 - 1 if col1> 0 else 0 
    # move right
    if arr[row1:row2, col1:col2+1].all():
      col2 = col2 + 1 if col2 < m else m
    # any movement? if yes, repeat the process above.
    if (np.r_[row1, row2, col1, col2] != idx[:-1]).any():
      return find_index(arr, (row1, row2, col1, col2, 0))
    return row1, row2, col1, col2, (row1 - row2) * (col1 - col2)

  def sub_indices(arr_bool, index, vals = None):
    """
    Compare the slices and obtain the slices with the most values
    """
    row, col = index
    r1, r2, c1, c2, size  = indices = find_index(arr_bool,(row[0], col[0]))
    # slices with max region
    vals = indices if vals is None or size > vals[-1] else vals
    
    # any non-nan value not within the have not been traversed? Repeat
    if (i2 := ~((r1 <= row) & (row <= r2) & (c1 <= col) & (col <= c2))).any():
      return sub_indices(arr_bool, (row[i2], col[i2]), vals)
    return vals
  
  arr_bool = ~np.isnan(arr)
  r1,r2, c1, c2,_= sub_indices(arr_bool, np.where(arr_bool))
  return arr[r1:r2, c1:c2]
          
largest_submatrix(array)
array([[255., 255., 255., 255., 255., 255., 255., 255.],
       [255., 255., 255., 255.,   0., 255., 255., 255.],
       [255., 255., 255.,   0.,   0.,   0., 255., 255.],
       [255., 255.,   0.,   0.,   0.,   0.,   0., 255.],
       [255., 255., 255.,   0.,   0.,   0.,   0., 255.],
       [255., 255., 255., 255.,   0., 255., 255., 255.],
       [255., 255., 255., 255., 255., 255., 255., 255.],
       [255., 255., 255., 255., 255., 255., 255., 255.],
       [255., 255., 255., 255., 255., 255., 255., 255.],
       [255., 255., 255., 255.,   0., 255., 255., 255.],
       [255., 255., 255., 255., 255., 255., 255., 255.]])

目前还不清楚

even
子矩阵的含义。如果您想要偶数列/行,您可以简单地将其包含在代码中,以确保返回的值捕获子矩阵是否为偶数/奇数。然后您可以使用它来确定最佳区域:

© www.soinside.com 2019 - 2024. All rights reserved.