当前位置: 首页 > news >正文

OpenCV(八):NumPy

OpenCV (Open Source Computer Vision Library) 和 NumPy (Numerical Python) 是 Python 中进行图像处理和计算机视觉任务时不可或缺的两个库。OpenCV-Python 的核心实现依赖于 NumPy,所有 OpenCV 的图像数据结构都以 NumPy 数组(numpy.ndarray)的形式表示。

图像表示与数据结构:NumPy 数组

在 OpenCV 中,图像被视为多维的 NumPy 数组。这是理解一切操作的基础。

图像的本质:多维数组

  • 灰度图: 一个二维数组(矩阵),形状通常为 (H,W),其中 H 是高(行数),W 是宽(列数)。每个元素代表一个像素的强度值(通常在 0 到 255 之间)。
  • 彩色图 (BGR/RGB): 一个三维数组,形状通常为 (H,W,C),其中 H 是高,W 是宽,C 是通道数(通常 C=3,分别对应蓝、绿、红或红、绿、蓝)。
    • 注意: OpenCV 默认的颜色顺序是 BGR(蓝-绿-红),而不是常见的 RGB。

NumPy 数组的属性

使用 NumPy 数组的属性,可以方便地查看图像的基本信息:

  • .shape 返回图像的维度信息(高、宽、通道数)。
    • 例如:彩色图 img.shape 可能返回 (480, 640, 3)
    • 灰度图 img.shape 可能返回 (480, 640)
  • .dtype 返回数组中元素的类型。图像像素最常用的类型是 uint8(8 位无符号整数,范围 0−255)。
  • .size 返回数组中元素的总个数(高 × 宽 × 通道数)。

像素访问与操作

NumPy 的切片和索引机制使得像素级别的操作变得非常高效和直观。

  • 访问单个像素(彩色图): img[y, x] 返回一个包含 B,G,R 三个通道值的数组。
    • 例如:pixel = img[100, 150] 得到 [B, G, R]
  • 访问单个通道: img[:, :, 0] 提取蓝色通道。
  • 区域操作 (ROI, Region of Interest): 使用切片来选取图像的特定矩形区域。
    • 例如:roi = img[y1:y2, x1:x2]
  • 修改像素值: 可以直接赋值修改像素或区域。
    • 例如:将左上角 50×50 区域设为黑色(0):img[0:50, 0:50] = [0, 0, 0]

NumPy 在图像操作中的优势

将图像存储为 NumPy 数组带来了巨大的性能和功能优势。

向量化操作(Vectorization)

NumPy 的核心优势在于向量化操作,它允许对整个数组(或数组的子集)进行元素级别的运算,而无需编写显式的 Python 循环。这大大提高了运算速度,因为底层操作是通过高度优化的 C/C++/Fortran 代码执行的。

  • 亮度调整: 增加图像亮度 50(饱和操作,需要注意数据溢出)。
    • new_img = cv2.add(img, 50) 或使用 NumPy 的 Clip 确保值在 0−255 之间:new_img = np.clip(img.astype(np.int32) + 50, 0, 255).astype(np.uint8)
  • 通道分离与合并: OpenCV 的 cv2.split()cv2.merge() 可以完成,但 NumPy 也能高效实现。
    • b, g, r = cv2.split(img)
    • img_merged = cv2.merge((b, g, r))

图像创建与初始化

NumPy 提供了便捷的方式来创建各种初始化图像(画布):

  • 全黑图像: black_img = np.zeros((H, W, 3), dtype=np.uint8)
  • 全白图像: white_img = np.ones((H, W, 3), dtype=np.uint8) * 255
  • 随机噪点图: random_img = np.random.randint(0, 256, size=(H, W, 3), dtype=np.uint8)

数据类型转换(dtype

图像处理中经常需要进行数据类型转换,例如,为了进行精确的浮点数运算(如傅里叶变换或归一化),或为了处理溢出问题。

  • 归一化到 0.0−1.0: float_img = img.astype(np.float32) / 255.0
  • 反归一化回 0−255: uint8_img = (float_img * 255).astype(np.uint8)

OpenCV 函数对 NumPy 的无缝支持

OpenCV-Python 的设计哲学是所有接受图像作为输入的函数,都期望接收一个 NumPy 数组;所有返回图像的函数,都会返回一个 NumPy 数组。

图像 I/O

  • 读取图像: cv2.imread() 返回一个 NumPy 数组。
  • 显示图像: cv2.imshow() 接受一个 NumPy 数组作为参数。
  • 写入图像: cv2.imwrite() 接受一个 NumPy 数组作为参数。

几何变换

像平移、旋转、缩放等操作,其变换矩阵本身就是 NumPy 数组,而 OpenCV 函数内部会对输入的图像(NumPy 数组)高效地进行矩阵运算。

  • 平移: 需要定义 2×3 的平移矩阵 M,该矩阵就是一个 NumPy 数组。

    M = np.float32([[1, 0, tx], [0, 1, ty]])
    shifted = cv2.warpAffine(img, M, (W, H))
    
  • 旋转: cv2.getRotationMatrix2D() 返回的也是一个 NumPy 数组。

卷积与滤波

像高斯模糊、Sobel 梯度等操作,其核心是卷积运算。OpenCV 的 cv2.filter2D() 函数可以接受一个 NumPy 数组作为自定义卷积核(Kernel)

# 定义一个 3x3 的均值模糊核
kernel = np.ones((3, 3), np.float32) / 9
dst = cv2.filter2D(img, -1, kernel)

与其他库的集成

NumPy 的通用性使得 OpenCV 能够轻松地与其他流行的 Python 科学计算和数据可视化库集成。

  • Matplotlib: 最常用的可视化工具。要正确显示 OpenCV 读取的彩色图,通常需要进行颜色通道转换,因为 Matplotlib 期望的是 RGB 顺序。

    import matplotlib.pyplot as plt
    # OpenCV to RGB
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    plt.imshow(img_rgb)
    plt.show()
    
  • Scikit-image, SciPy: 这些库中的许多图像处理算法可以直接接收和返回 NumPy 数组,实现功能上的扩展。

使用示例

import numpy as np
import time# --- 一、 数组的创建 (Creating Arrays) ---print("--- 1. 数组的创建 ---")# 1.1 从 Python 列表创建 (最常用)
a = np.array([1, 2, 3])
b = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float64) # 指定数据类型
print("a (一维数组):\n", a)
print("b (二维数组):\n", b)
print("b 的形状 (shape):", b.shape)
print("b 的数据类型 (dtype):", b.dtype)
print("-" * 20)# 1.2 使用内置函数创建全零/全一/空数组
c = np.zeros((2, 3), dtype=np.int32) # 2行3列的全零矩阵
d = np.ones((1, 4))                  # 1行4列的全一矩阵 (默认 float)
e = np.empty((2, 2))                 # 创建一个元素值随机的数组 (通常用于占位)
print("c (全零):\n", c)
print("d (全一):\n", d)
print("-" * 20)# 1.3 创建序列数组
f = np.arange(10)      # 0 到 9 的整数序列
g = np.arange(2, 10, 2) # 2 到 10 (不包含) 步长为 2
h = np.linspace(0, 1, 5) # 在 0 和 1 之间平均创建 5 个点
print("f (arange 0-9):", f)
print("h (linspace 0-1, 5点):", h)
print("-" * 20)# 1.4 随机数组
i = np.random.rand(2, 3) # 2x3 均匀分布的随机数 (0-1)
j = np.random.randint(0, 10, size=(2, 2)) # 2x2 随机整数 (0 到 9)
print("i (随机浮点数):\n", i)
print("-" * 20)# --- 二、 数组的索引与切片 (Indexing and Slicing) ---print("--- 2. 数组的索引与切片 ---")# 2.1 一维数组
arr1d = np.arange(10) # [0 1 2 3 4 5 6 7 8 9]
print("arr1d:", arr1d)
print("arr1d[2]:", arr1d[2])        # 元素索引
print("arr1d[2:5]:", arr1d[2:5])    # 切片 [2, 3, 4]
print("arr1d[:5]:", arr1d[:5])      # 从开始到索引 5 之前
print("arr1d[5:]:", arr1d[5:])      # 从索引 5 到末尾
print("arr1d[::-1]:", arr1d[::-1])  # 逆序
print("-" * 20)# 2.2 二维数组 (图像/矩阵操作的核心)
arr2d = np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
print("arr2d:\n", arr2d)
print("单个元素 arr2d[1, 2]:", arr2d[1, 2]) # 索引:第1行,第2列 (从0开始) -> 6
print("切片 arr2d[0:2, 1:3]:\n", arr2d[0:2, 1:3]) # 第0, 1行 和 第1, 2列
# 结果: [[2, 3], [5, 6]]
print("仅获取第1行 arr2d[1, :]:", arr2d[1, :]) # 获取整行
print("仅获取第2列 arr2d[:, 2]:", arr2d[:, 2]) # 获取整列 -> [3, 6, 9]
print("-" * 20)# 2.3 布尔索引 (非常强大)
mask = arr2d > 5 # 创建布尔数组 (True/False)
print("布尔掩码:\n", mask)
print("arr2d[mask]:", arr2d[mask]) # 只保留 True 对应的元素 -> [6 7 8 9]
arr2d[arr2d < 3] = 0 # 将所有小于 3 的元素设置为 0
print("修改后的 arr2d:\n", arr2d)
print("-" * 20)# --- 三、 数组的基本操作 (Basic Operations) ---print("--- 3. 数组的基本操作 ---")m1 = np.array([1, 2, 3])
m2 = np.array([4, 5, 6])# 3.1 算术运算 (逐元素操作/Element-wise)
print("加法 m1 + m2:", m1 + m2)     # [5, 7, 9]
print("乘法 m1 * m2:", m1 * m2)     # [4, 10, 18]
print("标量运算 m1 * 2:", m1 * 2)   # [2, 4, 6]
print("-" * 20)# 3.2 矩阵乘法 (使用 @ 或 np.dot())
matA = np.array([[1, 2], [3, 4]])
matB = np.array([[5, 6], [7, 8]])
matC = matA @ matB # 矩阵乘法
print("矩阵 A:\n", matA)
print("矩阵 B:\n", matB)
print("矩阵乘法 A @ B:\n", matC)
print("-" * 20)# 3.3 聚合函数 (Aggregation)
arr_agg = np.array([[10, 20], [30, 40]])
print("arr_agg:\n", arr_agg)
print("总和:", arr_agg.sum())       # 100
print("最小值:", arr_agg.min())       # 10
print("按列求和 (axis=0):", arr_agg.sum(axis=0)) # [40, 60]
print("按行求和 (axis=1):", arr_agg.sum(axis=1)) # [30, 70]
print("-" * 20)# --- 四、 数组形状操作 (Shape Manipulation) ---print("--- 4. 数组形状操作 ---")# 4.1 reshape (改变数组形状,不改变数据)
arr_r = np.arange(12)
arr_2x6 = arr_r.reshape(2, 6)
arr_3x4 = arr_r.reshape(3, 4)
arr_4x_1 = arr_r.reshape(4, -1) # -1 自动计算维度
print("原始数组:\n", arr_r)
print("重塑为 3x4:\n", arr_3x4)
print("-" * 20)# 4.2 flatten (将数组展平为一维)
arr_flat = arr_3x4.flatten()
print("展平后:", arr_flat)
print("-" * 20)# 4.3 堆叠 (Stacking)
s1 = np.array([1, 2, 3])
s2 = np.array([4, 5, 6])
v_stack = np.vstack((s1, s2)) # 垂直堆叠 (行增加)
h_stack = np.hstack((s1, s2)) # 水平堆叠 (列增加)
print("垂直堆叠 (vstack):\n", v_stack)
print("水平堆叠 (hstack):", h_stack)
print("-" * 20)# --- 五、 NumPy 与 Python 列表的性能对比 (简要) ---print("--- 5. 性能对比 (NumPy 优势) ---")
array_size = 1000000# 5.1 Python 列表加法
list_a = list(range(array_size))
list_b = list(range(array_size))t0 = time.time()
list_result = [list_a[i] + list_b[i] for i in range(array_size)]
t1 = time.time()
print(f"Python 列表加法耗时: {(t1 - t0):.4f} 秒")# 5.2 NumPy 数组加法 (向量化操作)
np_a = np.array(list_a)
np_b = np.array(list_b)t2 = time.time()
np_result = np_a + np_b
t3 = time.time()
print(f"NumPy 数组加法耗时: {(t3 - t2):.4f} 秒")
# NumPy 通常快数十到数百倍

总结

NumPy 不仅仅是 OpenCV 的一个依赖库,它是 OpenCV-Python 图像处理功能的基石

特性NumPy 作用核心意义
数据表示将图像表示为多维数组 (ndarray)统一、高效的数据结构
性能实现底层 C 优化的向量化操作显著提升图像处理速度
操作便捷性提供强大的索引、切片和广播机制简化复杂的像素级和区域操作
互操作性作为科学计算领域的通用数组格式便于与 Matplotlib、SciPy 等库集成
http://www.dtcms.com/a/473333.html

相关文章:

  • 小微宝安网站建设有哪些做分析图用的网站
  • RabbitMQ 核心概念解析
  • 开发实战 - ego商城 - 2 nodejs搭建后端环境
  • 基于Java Swing的智能数据结构可视化系统 | 支持自然语言交互的AI算法助手
  • QQmusic sign值逆向实战 - Webpack打包分析
  • 城乡建设部网站首页网站建设公司应该怎么做推广
  • Linux环境下Hive4.0.1(最新版本)部署
  • dolphinscheduler之hivecli 任务
  • spark3访问低版本hive填坑记
  • 池化 (Pooling) 学习笔记
  • LeetCode160.相交链表【最通俗易懂版双指针】
  • Neo4j+Gephi制作社区检测染色图
  • 毕业设计代做网站机械工信部网站备案流程
  • aws ec服务器设置密码登录,ec服务器root登录 aws服务器初始化配置
  • Linux - 命令行参数与环境变量
  • 【高并发服务器】四、通用类型容器any
  • linux学习笔记(29)网络编程——服务器客户端 及多进程多线程服务器
  • 边缘服务器 FTP/TFTP 服务搭建与使用(Docker 方式)
  • VMware安装Kali-Linux
  • (6)数据中心、台式(塔式)服务器、机架式服务器、刀片式服务器
  • 为什么 socket.io 客户端在浏览器能连接服务器但在 Node.js 中报错 transport close
  • Arbess CICD实战(10) - 使用Arbess+GitLab实现PHP项目自动化部署
  • 电子商务网站建设的作用广告视频拍摄制作
  • 深圳集团网站建设企业如何快速推广
  • 创新的商城网站建网站建设和优化
  • 学校网站开发背景wordpress 电影 插件
  • 进入官方网站电影网站开发现状
  • 网站建设各模块功能简述如何做网站营销推广
  • 先有域名才可以做网站吗南宁品牌网站建设
  • 温州网站推广效果好公司可以备案几个网站