如何在Python中按3×3块聚合缩小二进制矩阵并保留所有1?
二进制矩阵按3×3块聚合的实现方法
以下是几种针对需求的实现方案,核心逻辑均为判断每个3×3子块中是否存在1,存在则目标位置设为1,否则为0:
一、Python 实现
1. NumPy 高效向量化解法
利用NumPy的维度重塑和批量操作,适合处理大矩阵,效率极高:
import numpy as np # 假设原矩阵为binary_matrix,形状(648, 2340),元素为0或1 binary_matrix = np.random.randint(0, 2, (648, 2340), dtype=np.uint8) # 重塑维度:将原矩阵拆分为(216, 3, 780, 3)的块结构 blocked_matrix = binary_matrix.reshape(216, 3, 780, 3) # 交换轴,让块的维度集中在最后两位:(216, 780, 3, 3) blocked_matrix = blocked_matrix.transpose(0, 2, 1, 3) # 对每个3×3块判断是否存在1,最后转换为uint8类型 result_matrix = np.any(blocked_matrix, axis=(2, 3)).astype(np.uint8)
逻辑说明:通过reshape和transpose将原矩阵划分成独立的3×3子块,再用np.any批量检查每个块内是否有1,直接得到结果矩阵。
2. 基于稀疏性的优化解法
由于原矩阵大部分是0、仅少量1,可只处理含1的位置,大幅减少计算量:
import numpy as np binary_matrix = np.random.randint(0, 2, (648, 2340), dtype=np.uint8) result_matrix = np.zeros((216, 780), dtype=np.uint8) # 获取所有1的坐标 rows, cols = np.where(binary_matrix == 1) # 计算每个1对应的目标块坐标 target_rows = rows // 3 target_cols = cols // 3 # 将这些目标位置设为1 result_matrix[target_rows, target_cols] = 1
逻辑说明:先定位所有1的位置,再映射到目标矩阵的对应块索引,直接标记这些块为1,其余保持0,适合稀疏矩阵场景。
3. 纯Python循环解法(适合理解逻辑,效率较低)
如果不依赖NumPy,可手动遍历每个子块:
# 假设原矩阵是列表的列表:binary_matrix = [[0,1,...], ...] binary_matrix = [[0]*2340 for _ in range(648)] result_matrix = [[0]*780 for _ in range(216)] for i in range(216): for j in range(780): # 计算当前块在原矩阵的起始坐标 start_row = i * 3 start_col = j * 3 # 遍历3×3块内的元素 has_one = False for x in range(3): for y in range(3): if binary_matrix[start_row + x][start_col + y] == 1: has_one = True break if has_one: break result_matrix[i][j] = 1 if has_one else 0
二、C++ 实现(基于OpenCV)
利用OpenCV的矩阵操作,适合工程场景:
#include <opencv2/opencv.hpp> using namespace cv; int main() { // 读取或创建原二进制矩阵,尺寸648×2340,类型CV_8U Mat binary_matrix(648, 2340, CV_8U); randu(binary_matrix, 0, 2); // 示例生成随机二进制矩阵 Mat result_matrix(216, 780, CV_8U, Scalar(0)); for (int i = 0; i < 216; ++i) { for (int j = 0; j < 780; ++j) { // 提取3×3子块 Rect roi(j*3, i*3, 3, 3); Mat block = binary_matrix(roi); // 判断块内是否有非零元素(即1) if (countNonZero(block) > 0) { result_matrix.at<uchar>(i, j) = 1; } } } return 0; }
三、MATLAB 实现
使用blockproc函数直接处理块:
% 原二进制矩阵,尺寸648×2340 binary_matrix = randi([0,1], 648, 2340); % 定义块处理函数:判断块内是否有1 block_func = @(block_struct) any(block_struct.data(:)) * 1; % 按3×3块处理,得到216×780的结果矩阵 result_matrix = blockproc(binary_matrix, [3 3], block_func);
内容的提问来源于stack exchange,提问作者Geng Wang
相关产品推荐
相关产品推荐

