numpy(numerical python)是 python 科学计算生态系统的核心库,提供了高性能的多维数组对象和用于处理这些数组的工具。如:矩阵数据类型、矢量处理,以及精密的运算库。它是几乎所有数据科学、机器学习和科学计算库的基础。广泛应用于数据分析、机器学习等领域,是 pandas 、 scikit-learn 等库的基础。
下图是NumPy通过蒙特卡洛方法估算圆周率π,并提供详细的代码实现和可视化,感兴趣可在后文根据详细注解一探究竟;
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

与Python列表的比较,直观体现性能优势:
<code class="javascript">import numpy as npimport time# Python 列表的性能问题python_list = list(range(1000000))start_time = time.time()result = [x * 2 for x in python_list]end_time = time.time()print(f"Python列表计算时间: {end_time - start_time:.6f}秒")# NumPy 数组的性能优势numpy_array = np.arange(1000000)start_time = time.time()result = numpy_array * 2end_time = time.time()print(f"NumPy数组计算时间: {end_time - start_time:.6f}秒")</code>结果展示:
<code class="javascript">Python列表计算时间: 0.045234秒NumPy数组计算时间: 0.001567秒</code>
<code class="javascript">import numpy as np# 从列表创建arr1 = np.array([1, 2, 3, 4, 5])print("从列表创建:", arr1)# 创建特殊数组zeros = np.zeros((3, 4)) # 全0数组ones = np.ones((2, 3)) # 全1数组empty = np.empty((2, 2)) # 未初始化数组full = np.full((2, 2), 7) # 填充指定值identity = np.eye(3) # 单位矩阵print("全0数组:", zeros)print("单位矩阵:", identity)# 创建序列数组range_arr = np.arange(0, 10, 2) # 类似range,但返回数组linear_arr = np.linspace(0, 1, 5) # 等间隔数列random_arr = np.random.rand(3, 3) # 随机数组print("arange创建:", range_arr)print("linspace创建:", linear_arr)print("随机数组:", random_arr)</code>输出结果:
<code class="javascript">从列表创建: [1 2 3 4 5]全0数组: [[0. 0. 0. 0.] [0. 0. 0. 0.] [0. 0. 0. 0.]]单位矩阵: [[1. 0. 0.] [0. 1. 0.] [0. 0. 1.]]arange创建: [0 2 4 6 8]linspace创建: [0. 0.25 0.5 0.75 1. ]随机数组: [[0.39898071 0.38841929 0.25706792] [0.4805703 0.79778008 0.96680553] [0.75744912 0.35779339 0.96884091]]</code>
<code class="javascript">import numpy as np# 创建一个示例数组arr = np.array([[1, 2, 3], [4, 5, 6]])print("数组:", arr)print("形状:", arr.shape) # 数组维度print("大小:", arr.size) # 元素总数print("维度:", arr.ndim) # 轴的数量print("数据类型:", arr.dtype) # 元素类型print("每个元素字节数:", arr.itemsize)print("总字节数:", arr.nbytes)</code>输出结果:
<code class="javascript">组: [[1 2 3] [4 5 6]]形状: (2, 3)大小: 6维度: 2数据类型: int32每个元素字节数: 4总字节数: 24</code>
<code class="javascript">import numpy as np# 创建示例数组arr = np.arange(1, 13).reshape(3, 4)print("原始数组:", arr)# 基本索引print("第一个元素:", arr[0, 0])print("第一行:", arr[0])print("第一列:", arr[:, 0])# 切片操作print("前两行:", arr[:2])print("后两列:", arr[:, -2:])print("子数组:", arr[1:3, 1:3])# 布尔索引bool_mask = arr > 5print("布尔掩码:", bool_mask)print("大于5的元素:", arr[bool_mask])# 花式索引print("选择特定行:", arr[[0, 2]])print("选择特定列:", arr[:, [1, 3]])</code>输出结果:
<code class="javascript">始数组: [[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]]第一个元素: 1第一行: [1 2 3 4]第一列: [1 5 9]前两行: [[1 2 3 4] [5 6 7 8]]后两列: [[ 3 4] [ 7 8] [11 12]]子数组: [[ 6 7] [10 11]]布尔掩码: [[False False False False] [False True True True] [ True True True True]]大于5的元素: [ 6 7 8 9 10 11 12]选择特定行: [[ 1 2 3 4] [ 9 10 11 12]]选择特定列: [[ 2 4] [ 6 8] [10 12]]</code>
<code class="javascript">import numpy as nparr = np.arange(12)print("一维数组:", arr)# 改变形状reshaped = arr.reshape(3, 4)print("重塑为3x4:", reshaped)# 展平数组flattened = reshaped.flatten()print("展平:", flattened)# 转置transposed = reshaped.Tprint("转置:", transposed)# 增加/减少维度expanded = np.expand_dims(arr, axis=0)print("增加维度:", expanded.shape)squeezed = np.squeeze(expanded)print("压缩维度:", squeezed.shape)</code>输出结果:
<code class="javascript">维数组: [ 0 1 2 3 4 5 6 7 8 9 10 11]重塑为3x4: [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]]展平: [ 0 1 2 3 4 5 6 7 8 9 10 11]转置: [[ 0 4 8] [ 1 5 9] [ 2 6 10] [ 3 7 11]]增加维度: (1, 12)压缩维度: (12,)</code>
<code class="javascript">import numpy as npa = np.array([1, 2, 3])b = np.array([4, 5, 6])# 算术运算print("加法:", a + b)print("减法:", a - b)print("乘法:", a * b) # 元素乘法,不是矩阵乘法print("除法:", a / b)print("幂运算:", a ** 2)# 比较运算print("相等:", a == b)print("大于:", a > 2)# 聚合函数print("总和:", np.sum(a))print("均值:", np.mean(a))print("标准差:", np.std(a))print("最大值:", np.max(a))print("最小值:", np.min(a))# 三角函数angles = np.array([0, np.pi/2, np.pi])print("正弦值:", np.sin(angles))</code>输出结果:
<code class="javascript">法: [5 7 9]减法: [-3 -3 -3]乘法: [ 4 10 18]除法: [0.25 0.4 0.5 ]幂运算: [1 4 9]相等: [False False False]大于: [False False True]总和: 6均值: 2.0标准差: 0.816496580927726最大值: 3最小值: 1正弦值: [0.0000000e+00 1.0000000e+00 1.2246468e-16]</code>
<code class="javascript">import numpy as np# 标量与数组arr = np.array([[1, 2, 3], [4, 5, 6]])print("数组 + 标量:", arr + 10)# 不同形状数组vector = np.array([10, 20, 30])print("数组 + 向量:", arr + vector)# 广播规则示例a = np.array([[1], [2], [3]]) # 形状 (3, 1)b = np.array([10, 20, 30]) # 形状 (3,)print("广播加法:", a + b)</code>输出结果:
<code class="javascript">数组 + 标量: [[11 12 13] [14 15 16]]数组 + 向量: [[11 22 33] [14 25 36]]广播加法: [[11 21 31] [12 22 32] [13 23 33]]</code>
<code class="javascript">import numpy as np# 创建示例数据data = np.random.rand(5, 3)# 保存到文件np.savetxt('data.txt', data, delimiter=',')# 从文件加载loaded_data = np.loadtxt('data.txt', delimiter=',')print("从文件加载的数据:", loaded_data)# 二进制格式(更高效)np.save('data.npy', data)binary_loaded = np.load('data.npy')print("二进制加载的数据:", binary_loaded)</code>输出结果:
<code class="javascript">从文件加载的数据: [[0.4553778 0.49906932 0.97523208] [0.35906304 0.55012335 0.38348623] [0.29169913 0.90129311 0.22774977] [0.97325678 0.32749914 0.85698094] [0.82758157 0.36911462 0.42524159]]二进制加载的数据: [[0.4553778 0.49906932 0.97523208] [0.35906304 0.55012335 0.38348623] [0.29169913 0.90129311 0.22774977] [0.97325678 0.32749914 0.85698094] [0.82758157 0.36911462 0.42524159]]</code>
<code class="javascript">import numpy as np# 设置随机种子(确保可重复性)np.random.seed(42)# 生成随机数uniform = np.random.rand(5) # [0,1)均匀分布normal = np.random.randn(5) # 标准正态分布integers = np.random.randint(0, 10, 5) # 随机整数print("均匀分布:", uniform)print("正态分布:", normal)print("随机整数:", integers)# 随机抽样choices = np.random.choice(['A', 'B', 'C'], size=10, p=[0.5, 0.3, 0.2])print("随机选择:", choices)</code>输出结果:
<code class="javascript">匀分布: [0.37454012 0.95071431 0.73199394 0.59865848 0.15601864]正态分布: [ 0.27904129 1.01051528 -0.58087813 -0.52516981 -0.57138017]随机整数: [5 8 0 9 2]随机选择: ['A' 'C' 'A' 'C' 'B' 'A' 'A' 'C' 'B' 'A']</code>
<code class="javascript">import numpy as np# 创建示例数据集data = np.array([ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])# 数据筛选filtered = data[data > 5]print("大于5的值:", filtered)# 条件修改data[data % 2 == 0] = -1 # 将所有偶数改为-1print("修改后的数据:", data)# 数据统计print("每列均值:", np.mean(data, axis=0))print("每行最大值:", np.max(data, axis=1))</code>输出结果:
<code class="javascript">大于5的值: [ 6 7 8 9 10 11 12]修改后的数据: [[ 1 -1 3 -1] [ 5 -1 7 -1] [ 9 -1 11 -1]]每列均值: [ 5. -1. 7. -1.]每行最大值: [ 3 7 11]</code>
<code class="javascript">import numpy as np# 模拟一个灰度图像(10x10像素)image = np.random.randint(0, 256, (10, 10))print("原始图像数据:", image)# 图像处理操作brightened = np.clip(image + 50, 0, 255) # 增加亮度inverted = 255 - image # 颜色反转threshold = (image > 128).astype(int) # 二值化print("亮度增强:", brightened)print("颜色反转:", inverted)print("二值化:", threshold)</code>输出结果:
<code class="javascript"> 始图像数据: [[ 23 218 156 90 149 255 116 104 8 60] [ 70 42 74 180 227 17 189 92 11 90] [207 61 110 223 21 153 47 136 20 225] [ 8 93 153 81 81 14 112 107 249 50] [160 149 95 60 214 233 149 247 127 7] [140 183 32 82 247 128 174 16 44 212] [ 34 203 210 89 98 59 48 200 181 111] [111 23 99 101 108 130 65 215 123 205] [170 93 210 84 230 213 82 126 87 247] [187 250 8 157 78 54 54 227 89 164]]亮度增强: [[ 73 255 206 140 199 255 166 154 58 110] [120 92 124 230 255 67 239 142 61 140] [255 111 160 255 71 203 97 186 70 255] [ 58 143 203 131 131 64 162 157 255 100] [210 199 145 110 255 255 199 255 177 57] [190 233 82 132 255 178 224 66 94 255] [ 84 253 255 139 148 109 98 250 231 161] [161 73 149 151 158 180 115 255 173 255] [220 143 255 134 255 255 132 176 137 255] [237 255 58 207 128 104 104 255 139 214]]颜色反转: [[232 37 99 165 106 0 139 151 247 195] [185 213 181 75 28 238 66 163 244 165] [ 48 194 145 32 234 102 208 119 235 30] [247 162 102 174 174 241 143 148 6 205] [ 95 106 160 195 41 22 106 8 128 248] [115 72 223 173 8 127 81 239 211 43] [221 52 45 166 157 196 207 55 74 144] [144 232 156 154 147 125 190 40 132 50] [ 85 162 45 171 25 42 173 129 168 8] [ 68 5 247 98 177 201 201 28 166 91]]二值化: [[0 1 1 0 1 1 0 0 0 0] [0 0 0 1 1 0 1 0 0 0] [1 0 0 1 0 1 0 1 0 1] [0 0 1 0 0 0 0 0 1 0] [1 1 0 0 1 1 1 1 0 0] [1 1 0 0 1 0 1 0 0 1] [0 1 1 0 0 0 0 1 1 0] [0 0 0 0 0 1 0 1 0 1] [1 0 1 0 1 1 0 0 0 1] [1 1 0 1 0 0 0 1 0 1]]</code>
<code class="javascript">import numpy as np# 不好的做法:使用Python循环def slow_sum(arr): result = 0 for x in arr: result += x return result# 好的做法:使用NumPy向量化操作def fast_sum(arr): return np.sum(arr)# 测试性能large_arr = np.random.rand(1000000)import timestart = time.time()slow_result = slow_sum(large_arr)end = time.time()print(f"循环求和: {end - start:.6f}秒")start = time.time()fast_result = fast_sum(large_arr)end = time.time()print(f"向量化求和: {end - start:.6f}秒")</code>输出结果:
<code class="javascript">循环求和: 0.471191秒向量化求和: 0.003989秒</code>
<code class="javascript">import numpy as np# 错误:视图 vs 副本arr = np.array([1, 2, 3, 4])view = arr[1:3] # 这是视图,修改会影响原数组copy = arr[1:3].copy() # 这是副本,独立于原数组view[0] = 999print("原数组被修改:", arr) # [1, 999, 3, 4]copy[0] = 888print("原数组不变:", arr) # [1, 999, 3, 4]# 正确使用数据类型float_arr = np.array([1, 2, 3], dtype=np.float64)int_arr = np.array([1.5, 2.7, 3.1], dtype=np.int32) # 注意会截断print("浮点数组:", float_arr)print("整数数组:", int_arr) # [1, 2, 3]</code>输出结果:
<code class="javascript">原数组被修改: [ 1 999 3 4]原数组不变: [ 1 999 3 4]浮点数组: [1. 2. 3.]整数数组: [1 2 3]</code>
np.array(), np.zeros(), np.ones(), np.arange(), np.linspace() 数组属性:.shape, .dtype, .ndim 索引和切片:基本索引、布尔索引、花式索引 数组操作:reshape(), concatenate(), stack() 数学运算:向量化运算、广播机制 通用函数:np.sin(), np.exp(), np.sqrt()等 线性代数:np.dot(), np.linalg.norm()等<code class="javascript"> import numpy as np# 创建游戏棋盘def create_board(): """ 创建一个3x3的井字棋棋盘,初始状态为全0 返回值: 3x3的NumPy数组,数据类型为整数 0表示空位,1表示玩家X,2表示玩家O """ # np.zeros((3, 3), dtype=int) 创建一个3行3列的全0数组 return np.zeros((3, 3), dtype=int)# 打印棋盘(美化输出)def print_board(board): """ 将数字表示的棋盘转换为可视化的字符格式并打印 参数: board: 3x3的NumPy数组,表示当前棋盘状态 """ # 定义数字到符号的映射字典 # 0 -> 空格, 1 -> 'X', 2 -> 'O' symbols = {0: ' ', 1: 'X', 2: 'O'} # 遍历每一行 for i in range(3): # 将当前行的数字转换为对应的符号 row = [symbols[board[i, j]] for j in range(3)] # 使用' | '连接符号并打印,前面加空格使输出居中 print(' ' + ' | '.join(row)) # 如果不是最后一行,打印分隔线 if i < 2: print('-----------') print() # 打印空行使输出更清晰# 检查胜利条件def check_win(board, player): """ 检查指定玩家是否获胜 参数: board: 3x3的NumPy数组,表示当前棋盘状态 player: 整数,1表示玩家X,2表示玩家O 返回值: 布尔值,True表示该玩家获胜,False表示未获胜 """ # 检查所有行是否有获胜情况 # np.all() 检查给定轴上的所有元素是否为True for i in range(3): # 检查第i行是否全部由当前玩家的棋子占据 if np.all(board[i, :] == player): return True # 检查所有列是否有获胜情况 for j in range(3): # 检查第j列是否全部由当前玩家的棋子占据 if np.all(board[:, j] == player): return True # 检查两条对角线是否有获胜情况 # np.diag() 获取矩阵的主对角线元素 # np.fliplr() 左右翻转矩阵,然后获取对角线即为反对角线 if np.all(np.diag(board) == player) or np.all(np.diag(np.fliplr(board)) == player): return True # 如果以上条件都不满足,则该玩家未获胜 return False# 游戏演示# 创建初始棋盘board = create_board()print("初始棋盘:")print_board(board)# 模拟几步游戏# 玩家X在左上角(0,0)位置落子board[0, 0] = 1 # X 在左上角# 玩家O在中心(1,1)位置落子board[1, 1] = 2 # O 在中心# 玩家X在上中(0,1)位置落子board[0, 1] = 1 # X 在上中print("游戏进行中:")print_board(board)# 检查玩家X是否获胜print("X 是否获胜?", check_win(board, 1))</code>输出结果:
<code class="javascript">初始棋盘: | | ----------- | |----------- | |游戏进行中: X | X |----------- | O |----------- | |X 是否获胜? False</code>
np.zeros() 创建数组 二维数组索引 board[i, j] np.all() 检查所有元素是否满足条件 np.diag() 获取对角线元素 np.fliplr() 左右翻转数组<code class="javascript">import numpy as npimport matplotlib.pyplot as pltimport timefrom matplotlib.animation import FuncAnimationdef animated_monte_carlo(n_samples=10000, frame_interval=100): """ 创建蒙特卡洛方法估算π的动态可视化 参数: n_samples: 总采样点数,默认10000个点 frame_interval: 每帧更新的点数,默认每100个点更新一次动画 返回: matplotlib.animation.FuncAnimation对象,用于控制动画 """ # 生成所有随机点:在[-1, 1] x [-1, 1]的正方形区域内均匀采样 # points是一个n_samples x 2的数组,每行代表一个点的(x,y)坐标 points = np.random.uniform(-1, 1, size=(n_samples, 2)) # 计算每个点到原点(0,0)的距离 # 使用欧几里得距离公式:sqrt(x² + y²) distances = np.sqrt(points[:, 0]**2 + points[:, 1]**2) # 创建图形窗口,包含左右两个子图 # 左图显示随机点和单位圆,右图显示π估计值的收敛过程 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5)) # 初始化左图的散点图(开始时没有点) scatter = ax1.scatter([], [], s=1, alpha=0.5) # 小点,半透明 ax1.set_xlim(-1, 1) # 设置x轴范围 ax1.set_ylim(-1, 1) # 设置y轴范围 ax1.set_aspect('equal') # 保持纵横比相等,确保圆看起来是圆形 # 在左图绘制单位圆(半径为1的圆) # 这个圆用于可视化:圆内的点表示落在单位圆内 circle = plt.Circle((0, 0), 1, color='green', fill=False, linewidth=2) ax1.add_patch(circle) # 将圆添加到图中 # 初始化右图的收敛曲线(开始时没有数据) line, = ax2.plot([], [], linewidth=1) # 在右图添加一条水平线表示π的真实值 ax2.axhline(y=np.pi, color='r', linestyle='--', label='True π') ax2.set_xlim(0, n_samples) # 设置x轴范围(点数) ax2.set_ylim(2.8, 3.4) # 设置y轴范围(π的估计值范围) ax2.set_xlabel('Number of points') # x轴标签 ax2.set_ylabel('Estimate of π') # y轴标签 ax2.set_title('Convergence of π Estimate') # 右图标题 ax2.legend() # 显示图例 ax2.grid(True) # 显示网格 # 在左图添加文本框,显示当前点数、π估计值和误差 text = ax1.text(0.05, 0.95, '', transform=ax1.transAxes, fontsize=12, verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8)) # 动画更新函数 - 每一帧调用一次 def update(frame): # 计算当前帧应该显示的点数 # 每frame_interval个点更新一次,但不超过总点数n_samples n = min((frame + 1) * frame_interval, n_samples) # 更新左图的散点图 # 确定哪些点落在单位圆内(距离<=1) inside = distances[:n] <= 1 # 落在圆外的点 outside = ~inside # 逻辑非操作 # 创建颜色数组:圆内的点为蓝色,圆外的点为红色 colors = np.empty(n, dtype=object) # 创建空对象数组 colors[inside] = 'blue' # 圆内的点设为蓝色 colors[outside] = 'red' # 圆外的点设为红色 # 更新散点图的位置和颜色 scatter.set_offsets(points[:n]) # 设置点的位置 scatter.set_color(colors) # 设置点的颜色 # 更新右图的收敛曲线 # 计算累积落在圆内的点数(使用累积和) cumulative_inside = np.cumsum(inside) # 计算π的估计值:4 * (圆内点数 / 总点数) # 根据公式:π ≈ 4 * (圆内点数 / 总点数) cumulative_estimate = 4 * cumulative_inside / (np.arange(n) + 1) # 更新收敛曲线的数据 line.set_data(np.arange(n), cumulative_estimate) # 更新文本信息 # 获取当前的π估计值(最后一个值) current_estimate = cumulative_estimate[-1] if n > 0 else 0 # 设置文本内容:点数、估计值和误差 text.set_text(f'Points: {n:,}Estimate: {current_estimate:.6f}Error: {abs(current_estimate - np.pi):.6f}') # 返回需要更新的图形元素 return scatter, line, text # 计算总帧数:总点数除以每帧更新的点数 frames = n_samples // frame_interval # 创建动画对象 # fig: 动画所在的图形 # update: 更新函数 # frames: 总帧数 # interval: 帧间隔时间(毫秒) # blit: 使用blitting技术优化动画(只重绘变化的部分) ani = FuncAnimation(fig, update, frames=frames, interval=50, blit=True) # 调整子图布局,避免重叠 plt.tight_layout() # 显示动画 plt.show() # 返回动画对象,以便后续控制(如保存为视频) return ani# 运行动画# 使用10000个点,每100个点更新一次动画ani = animated_monte_carlo(n_samples=10000, frame_interval=100)</code>这段代码实现了使用蒙特卡洛方法估算π值的动态可视化,其数学原理如下:
基本思想:在一个边长为2的正方形内随机撒点,统计落在内切圆(半径为1)内的点数 面积关系: 正方形面积 = 2 × 2 = 4 圆形面积 = π × 1² = π 概率估计:点在圆内的概率 = 圆形面积 / 正方形面积 = π/4 π估算公式:π ≈ 4 × (圆内点数 / 总点数) 代码亮点解析 向量化计算:使用NumPy一次性生成所有随机点并计算距离,避免了低效的Python循环 动态可视化:使用Matplotlib的动画功能实时展示估算过程 双视图设计:左侧显示随机点分布,右侧显示π估计值的收敛过程 性能优化: 使用blit=True只重绘变化的部分,提高动画性能 分批更新点(每100个点更新一次),平衡视觉效果和性能 信息丰富:实时显示当前点数、π估计值和误差,方便观察收敛过程
<code class="javascript">import numpy as npfrom PIL import Imageimport matplotlib.pyplot as plt# 设置中文字体支持# 确保图表中的中文标题能够正确显示plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体显示中文plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题# 创建简单的测试图像def create_test_image(): """ 创建一个自定义的渐变测试图像,用于演示图像处理效果 返回: 一个100x100像素的RGB图像,数据类型为uint8(0-255范围) """ # 创建从0到1的等间距数组,用于x和y坐标 x = np.linspace(0, 1, 100) # 100个点,从0到1 y = np.linspace(0, 1, 100) # 100个点,从0到1 # 创建网格坐标矩阵 # xx的每一行都是x的复制,yy的每一列都是y的复制 xx, yy = np.meshgrid(x, y) # 创建RGB三个通道的渐变效果 red = xx # 红色通道:水平渐变(从左到右增强) green = yy # 绿色通道:垂直渐变(从下到上增强) blue = (xx + yy) / 2 # 蓝色通道:对角线渐变(从右下到左上增强) # 将三个通道堆叠成三维数组(高度×宽度×通道) # 然后缩放到0-255范围并转换为8位无符号整数 image = np.stack([red, green, blue], axis=2) return (image * 255).astype(np.uint8)# 定义彩虹色条纹的颜色值(RGB格式,范围0-1)colors = [ [1, 0, 0], # 红色 [1, 0.5, 0], # 橙色 [1, 1, 0], # 黄色 [0, 1, 0], # 绿色 [0, 0, 1], # 蓝色 [0.5, 0, 0.5],# 紫色]# 创建彩虹色条纹图像def create_rainbow_stripes(size=100): """ 创建一个彩虹色条纹图像 参数: size: 图像的大小(将创建size×size的正方形图像) 返回: 一个包含彩虹色条纹的RGB图像 """ # 创建一个全零的三维数组(高度×宽度×3个颜色通道) image = np.zeros((size, size, 3)) # 计算每个条纹的宽度(将图像水平分成6等份) stripe_width = size // len(colors) # 填充彩虹色条纹 for i, color in enumerate(colors): # 计算当前条纹的起始和结束列索引 start = i * stripe_width end = (i + 1) * stripe_width if i < len(colors) - 1 else size # 将当前条纹的所有行和指定列范围设置为当前颜色 image[:, start:end] = color return image# 应用各种滤镜def apply_filters(image): """ 对输入图像应用多种滤镜效果 参数: image: 输入图像(NumPy数组,uint8类型,0-255范围) 返回: 四个处理后的图像:灰度图、边缘检测图、颜色反转图、sepia色调图 """ # 将图像转换为浮点数并归一化到0-1范围,便于数学运算 img_float = image.astype(float) / 255.0 # 1. 灰度化:将彩色图像转换为灰度图像 # 方法:取RGB三个通道的平均值 gray = np.mean(img_float, axis=2) # 2. 边缘检测(使用简化的Sobel算子) # 定义Sobel算子的x方向和y方向卷积核 sobel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) # 水平边缘检测 sobel_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]]) # 垂直边缘检测 # 初始化边缘强度图 edges = np.zeros_like(gray) # 对每个颜色通道分别应用Sobel算子 for i in range(3): # 获取当前颜色通道 channel = img_float[:, :, i] # 使用卷积计算x方向和y方向的梯度 # 注意:这里使用了一维卷积,需要先将二维数组展平 gx = np.abs(np.convolve(channel.flatten(), sobel_x.flatten(), mode='same').reshape(channel.shape)) gy = np.abs(np.convolve(channel.flatten(), sobel_y.flatten(), mode='same').reshape(channel.shape)) # 计算梯度幅值并累加到边缘图中 edges += np.sqrt(gx**2 + gy**2) # 对三个通道的结果取平均 edges = edges / 3.0 # 3. 颜色反转:用1减去每个像素值,实现颜色反转效果 inverted = 1.0 - img_float # 4. Sepia色调(棕褐色调效果) # 定义Sepia色调的转换矩阵 sepia_matrix = np.array([[0.393, 0.769, 0.189], # 红色分量转换系数 [0.349, 0.686, 0.168], # 绿色分量转换系数 [0.272, 0.534, 0.131]]) # 蓝色分量转换系数 # 应用矩阵乘法实现颜色转换 sepia = np.dot(img_float, sepia_matrix.T) # 确保值在0-1范围内(使用np.clip防止溢出) sepia = np.clip(sepia, 0, 1) return gray, edges, inverted, sepia# 创建并处理图像# 生成测试图像image = create_test_image()# 应用各种滤镜gray, edges, inverted, sepia = apply_filters(image)# 创建彩虹色条纹图像rainbow_image = create_rainbow_stripes()# 显示结果# 创建2行3列的子图布局fig, axes = plt.subplots(2, 3, figsize=(15, 10))# 第一行第一列:原始图像axes[0, 0].imshow(image)axes[0, 0].set_title('原始图像')axes[0, 0].axis('off') # 隐藏坐标轴# 第一行第二列:灰度化效果axes[0, 1].imshow(gray, cmap='gray') # 使用灰度颜色映射axes[0, 1].set_title('灰度化')axes[0, 1].axis('off')# 第一行第三列:边缘检测效果axes[0, 2].imshow(edges, cmap='hot') # 使用热力图颜色映射axes[0, 2].set_title('边缘检测')axes[0, 2].axis('off')# 第二行第一列:颜色反转效果axes[1, 0].imshow(inverted)axes[1, 0].set_title('颜色反转')axes[1, 0].axis('off')# 第二行第二列:Sepia色调效果axes[1, 1].imshow(sepia)axes[1, 1].set_title('Sepia色调')axes[1, 1].axis('off')# 第二行第三列:彩虹条纹图像axes[1, 2].imshow(rainbow_image)axes[1, 2].set_title('彩虹条纹')axes[1, 2].axis('off')# 自动调整子图参数,使之填充整个图像区域plt.tight_layout()# 显示图形plt.show()</code>np.convolve() 卷积操作 np.clip() 限制数值范围 np.dot() 矩阵乘法np.linspace, np.meshgrid创建坐标网格 广播机制: 在创建渐变图像时利用了NumPy的广播功能 矩阵运算: 在Sepia滤镜中使用矩阵乘法实现颜色转换 卷积操作: 在边缘检测中使用卷积计算图像梯度 数组索引和切片: 在创建彩虹条纹时使用切片操作高效赋值操作 |
代码示例 |
说明 |
|---|---|---|
创建数组 |
np.array([1,2,3]) |
从列表创建 |
全零数组 |
np.zeros((3,3)) |
创建全0数组 |
全一数组 |
np.ones((2,2)) |
创建全1数组 |
范围数组 |
np.arange(0,10,2) |
创建等差数组 |
随机数组 |
np.random.rand(3,3) |
创建随机数组 |
改变形状 |
arr.reshape(2,3) |
改变数组形状 |
数组拼接 |
np.concatenate([a,b]) |
连接数组 |
数学运算 |
arr + 1, arr * 2 |
向量化运算 |
统计函数 |
np.mean(arr), np.std(arr) |
统计计算 |
以上就是构建AI智能体:AI数据科学NumPy — 不可不知、由点及面抽丝剥茧+趣味范例的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号