OpenCV-Python快速入门系列03图像对象的创建与赋值

图像的本质是矩阵

OpenCV 使用 Mat(矩阵类)作为图像和数据的基本数据结构,这是因为图像本质上是一种二维或多维的矩阵形式。

  • 像素数据的表示: 图像可以看作一个二维矩阵,其中每个元素代表一个像素值。例如:
    • 灰度图像:一个二维矩阵,每个像素只有一个值。
    • 彩色图像:一个三维矩阵,第三个维度表示颜色通道(如 BGR)。
  • 矩阵计算的需求: 图像处理中很多操作本质上是矩阵运算,比如卷积、像素操作、几何变换等。

Mat 是专为图像矩阵设计的类,可以方便地表示这些数据结构。

Mat 的高效内存管理

  • 动态内存分配Mat 会自动管理图像数据的内存分配和释放,用户无需手动管理内存。
  • 引用计数Mat 使用引用计数技术,共享底层数据存储。当多个 Mat 对象引用同一块数据时,不会重复分配内存,而是通过引用计数器跟踪资源的使用情况。

支持多维数据

Mat 不仅支持二维数据,还可以支持多维矩阵,适合处理:

  • 高维数据(如科学计算中的张量)。
  • 视频帧序列(多帧图像堆叠为三维矩阵)。

数据结构灵活性

Mat 提供了丰富的功能以适应各种需求:

  • 支持多种数据类型(如 CV_8UC1CV_32FC3)。
  • 提供子矩阵和感兴趣区域(ROI)的操作,而不需要复制数据:cpp复制代码cv::Mat roi = image(cv::Rect(50, 50, 100, 100)); // 提取感兴趣区域
  • 支持各种通道数(单通道、三通道、四通道等)。

强大的接口支持

  • Mat 提供了很多成员函数,便于用户直接操作图像数据。例如:
    • clone():复制图像数据。
    • zeros()ones():创建全零或全一矩阵。
    • at<T>():访问矩阵中的特定元素。
    • 转换类型、大小、通道等的操作函数。

高效的兼容性和扩展性

  • 与 OpenCV 算法无缝集成: OpenCV 中的所有图像处理算法都以 Mat 作为输入和输出。
  • 与第三方库的兼容Mat 可以轻松转换为其他库的数据格式,如 NumPy 数组(在 Python 中)或 Eigen 矩阵(在 C++ 中)。
  • Mat 的设计继承了 OpenCV 的早期版本 IplImageCvMat 的优点,但克服了它们的一些缺点,例如类型不灵活、内存管理复杂等问题。
  • 它是 OpenCV 的统一数据结构,简化了库的设计,便于用户理解和使用。

使用OpenCV读取RGB图像和灰度图像

    image = cv.imread('images/test.png')
    print(image.shape) # (581, 400, 3) (Height,Width,Channel)

    image = cv.imread('images/test.png',cv.IMREAD_GRAYSCALE)
    print(image.shape) # (581, 400) (Height,Width)

print(image.shape)输出的值分别是高度、宽度和通道数。灰度图像只有一个通道,默认没显示。

如何创建一张空白图像

需要使用numpy来实现 import numpy as np

创建全黑色的空白图像

# 灰度图像(单通道)高度500, 宽度500
blank_image = np.zeros((500, 500), dtype=np.uint8)
# 彩色图像(三通道)
blank_image = np.zeros((500, 500, 3), dtype=np.uint8)

创建指定颜色的空白图像

# 单通道灰度图像,像素值全部为127
blank_image = np.full((500, 500), 127, dtype=np.uint8)

# 三通道彩色图像,BGR格式,蓝色
blank_image = np.zeros((500, 500, 3), dtype=np.uint8)
blank_image[:] = (255, 0, 0)  # 设置为蓝色 (BGR)

创建带透明通道的空白图像

带透明度的图像需要 4 通道,通常表示为 BGRA 格式。

# 透明背景 高度500, 宽度500, 4通道透明图像
blank_image = np.zeros((500, 500, 4), dtype=np.uint8)  # 4 通道 BGRA

# 设置为半透明红色背景
blank_image = np.zeros((500, 500, 4), dtype=np.uint8)
blank_image[:] = (0, 0, 255, 128)  # BGRA: 红色 (255, 0, 0) + 半透明 (128)

图像的复制与拷贝

图片[1]-OpenCV-Python快速入门系列03图像对象的创建与赋值-天煜博客
    roi = image[100:200,100:200]
    blank = np.zeros_like(image)
    blank[100:200,100:200] = roi
  • 通过 NumPy 切片,从 image 中提取一个矩形区域,坐标范围是:
    • 高度:100200(上下边界)。
    • 宽度:100200(左右边界)。
  • 切片范围
    • 起始索引包含,结束索引不包含(半开区间)。
    • 提取的区域大小为 (100, 100)

如果坐标超出了图像的边界(如 image[100:1000, 100:200]),会引发索引错误。

将 ROI 复制到空白图像时,目标区域大小需匹配,roi 的大小必须与目标区域的大小一致,否则会报错。

例如,roi 大小为 (100, 100, 3)blank[100:200, 100:200] 也是 (100, 100, 3)

# 使用.copy()去拷贝Mat
def mat_demo():
    image = cv.imread('images/test.png')
    if image is None:
        print("Error: Image not found or failed to load.")
        return

    print(image.shape)

    roi = image[100:200,100:200]
    blank = np.zeros_like(image)
    blank[300:400,100:200] = roi
    cv.imshow('blank', blank)

    blank_copy = blank.copy()
    cv.imshow('blank_copy', blank_copy)
    # cv.imshow('image', image)
    cv.waitKey()
    cv.destroyAllWindows()

copy() 和直接赋值(=)的操作之间的区别主要体现在是否是 深拷贝浅拷贝

直接赋值不会创建新的对象,而是将变量指向同一个内存地址(引用)。这是一种 浅拷贝

使用 copy() 会创建一个新的对象,并将原始对象的内容拷贝到新对象中。这是 深拷贝

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容