理解如何创建 Mat 就是理解如何创建和初始化 numpy.ndarray 数组。

下面我将从最简单到最复杂,详细介绍各种创建 Mat(即 numpy.ndarray)的方法。
核心概念:numpy.ndarray 是 cv2.Mat
在 Python OpenCV 中,图像被表示为 numpy.ndarray 数组,这个数组包含了图像的像素数据、尺寸、通道数等信息,其底层结构对应于 C++ 中的 cv::Mat。
一个关键点是 图像通道的顺序:
- OpenCV 默认使用 BGR 顺序(Blue, Green, Red)。
- 许多其他库(如 Matplotlib, PIL)默认使用 RGB 顺序。
这一点在显示或保存图像时尤其重要。

使用 NumPy 直接创建数组
这是最基本的方法,通过 numpy 库创建一个多维数组,然后就可以用 OpenCV 的函数来处理它。
创建空白图像
我们会创建一个全黑、全白或特定颜色的图像。
创建一个全黑的图像
import numpy as np
import cv2
# 创建一个高度为 300,宽度为 400 的 3 通道(BGR)图像,数据类型为 8 位无符号整数
# np.uint8 是图像处理中最常用的数据类型
black_image = np.zeros((300, 400, 3), dtype=np.uint8)
# 注意:创建的数组默认是浮点型,所以必须指定 dtype=np.uint8
# black_image = np.zeros((300, 400, 3)) # 错误示例,像素值会是 0.0
# 显示图像
cv2.imshow('Black Image', black_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
创建一个全白的图像

import numpy as np
import cv2
# 创建一个全白的图像,像素值为 255
white_image = np.full((300, 400, 3), 255, dtype=np.uint8)
# 显示图像
cv2.imshow('White Image', white_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
创建一个特定颜色的图像
import numpy as np
import cv2
# 创建一个纯蓝色图像
# OpenCV 中 BGR 顺序,(255, 0, 0) 是蓝色
blue_image = np.full((300, 400, 3), [255, 0, 0], dtype=np.uint8)
# 创建一个绿色图像
green_image = np.full((300, 400, 3), [0, 255, 0], dtype=np.uint8)
# 创建一个红色图像
red_image = np.full((300, 400, 3), [0, 0, 255], dtype=np.uint8)
# 显示图像
cv2.imshow('Blue Image', blue_image)
cv2.imshow('Green Image', green_image)
cv2.imshow('Red Image', red_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
创建灰度图像
灰度图像只有一个通道。
import numpy as np
import cv2
# 创建一个 200x200 的全黑灰度图像
gray_black = np.zeros((200, 200), dtype=np.uint8)
# 创建一个 200x200 的全白灰度图像
gray_white = np.full((200, 200), 255, dtype=np.uint8)
# 显示图像
cv2.imshow('Gray Black', gray_black)
cv2.imshow('Gray White', gray_white)
cv2.waitKey(0)
cv2.destroyAllWindows()
使用 OpenCV 的 cv2 函数创建
OpenCV 提供了一些便捷函数来创建常用的图像,这些函数在底层也是调用 NumPy 来实现的。
cv2.getTickCount() 和 cv2.getTickFrequency() (性能测量)
这两个函数虽然不直接创建图像,但常用于代码性能分析,是 OpenCV 的一部分。
import cv2
# 获取时钟计数
e1 = cv2.getTickCount()
# --- 在这里执行你的代码,例如一个循环 ---
for i in range(0, 100000):
pass
# -----------------------------------------
# 获取时钟频率
e2 = cv2.getTickCount()
time = (e2 - e1) / cv2.getTickFrequency()
print(f"执行时间: {time} 秒")
cv2.rectangle(), cv2.circle(), cv2.line() 等
这些函数通常用于在已有的图像上绘制图形,但也可以用来创建一个初始图像。
import numpy as np
import cv2
# 创建一个空白画布
canvas = np.zeros((512, 512, 3), dtype=np.uint8)
# 在画布上画一个绿色矩形
# cv2.rectangle(图像, 左上角坐标, 右下角坐标, 颜色(BGR), 线条厚度)
cv2.rectangle(canvas, (100, 100), (300, 250), (0, 255, 0), 3)
# 画一个红色实心圆
# cv2.circle(图像, 圆心坐标, 半径, 颜色(BGR), 线条厚度(负数或-1表示填充))
cv2.circle(canvas, (400, 300), 50, (0, 0, 255), -1)
# 画一条蓝色对角线
# cv2.line(图像, 起点, 终点, 颜色(BGR), 线条厚度)
cv2.line(canvas, (0, 0), (511, 511), (255, 0, 0), 5)
# 显示图像
cv2.imshow('Canvas with Shapes', canvas)
cv2.waitKey(0)
cv2.destroyAllWindows()
从文件加载图像
这是最常见的方式,即从磁盘读取一张图片,OpenCV 会自动为你创建一个 numpy.ndarray 对象。
import cv2
# 从文件加载图像
# cv2.IMREAD_COLOR: 加载彩色图像,忽略透明度(默认)
# cv2.IMREAD_GRAYSCALE: 加载为灰度图像
# cv2.IMREAD_UNCHANGED: 加载包含 alpha 通道的图像
image = cv2.imread('path/to/your/image.jpg', cv2.IMREAD_COLOR)
# 检查图像是否成功加载
if image is None:
print("错误:无法加载图像,请检查路径是否正确。")
else:
# 打印图像的属性(即 NumPy 数组的属性)
print(f"图像类型: {type(image)}")
print(f"图像形状: {image.shape}") # (高度, 宽度, 通道数)
print(f"图像数据类型: {image.dtype}")
# 显示图像
cv2.imshow('Loaded Image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
从摄像头捕获视频流
通过 cv2.VideoCapture() 可以从摄像头或视频文件中创建帧流,每一帧都是一个 numpy.ndarray。
import cv2
# 创建一个 VideoCapture 对象,参数 0 通常代表默认摄像头
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("无法打开摄像头")
exit()
while True:
# cap.read() 返回两个值:
# 1. 一个布尔值,表示是否成功读取到帧
# 2. 读取到的帧(一个 numpy.ndarray)
ret, frame = cap.read()
if not ret:
print("无法获取帧,或视频已结束。")
break
# 在帧上添加一些文本
cv2.putText(frame, 'Press Q to quit', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# 显示帧
cv2.imshow('Camera Feed', frame)
# 按下 'q' 键退出循环
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
使用 NumPy 的随机数创建
可以创建一个包含随机像素值的图像,常用于测试或生成纹理。
import numpy as np
import cv2
# 创建一个 200x200x3 的随机 BGR 图像
# 像素值范围是 0 到 255
random_image = np.random.randint(0, 256, (200, 200, 3), dtype=np.uint8)
# 创建一个 200x200 的随机灰度图像
random_gray = np.random.randint(0, 256, (200, 200), dtype=np.uint8)
# 显示图像
cv2.imshow('Random Color Image', random_image)
cv2.imshow('Random Gray Image', random_gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
总结与最佳实践
| 方法 | 描述 | 适用场景 |
|---|---|---|
np.zeros(), np.full() |
从头创建一个指定值(如0或255)的数组。 | 创建空白画布、纯色背景、初始化图像数据。 |
cv2.imread() |
从磁盘文件加载图像。 | 最常用,处理已有图片。 |
cv2.VideoCapture() |
从摄像头或视频文件捕获帧。 | 实时视频处理、计算机视觉应用。 |
cv2.rectangle(), cv2.circle() |
在现有图像上绘制图形。 | 图像标注、数据可视化、创建合成数据集。 |
np.random.randint() |
创建随机像素值的图像。 | 算法测试、生成随机纹理。 |
重要提示:
- 数据类型:几乎所有的图像处理都应使用
dtype=np.uint8,这表示每个像素值是 8 位无符号整数,范围在 0 到 255 之间。 - BGR vs. RGB:始终记住 OpenCV 使用 BGR 顺序,如果你用
matplotlib显示 OpenCV 图像,需要先进行颜色空间转换:import matplotlib.pyplot as plt # image_bgr 是由 OpenCV 读取的图像 image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB) plt.imshow(image_rgb) plt.show()
