OpenCV中的图像表示详解:Mat与ndarray


OpenCV是一个计算机视觉库,其主要重点是处理和操作图像数据。因此需要熟悉的第一件事是 OpenCV如何存储和处理图像。由上一篇博客: 数字图像处理基础与OpenCV中的图片读写 可以知道,图像在计算机中的存储方式其实就是数组矩阵。

1.Mat对象:C++API中的基本图像容器

2000年6月,第一个开源版本OpenCV alpha 3发布,那个时候的OpenCV是围绕C语言接口构建的,为了将图像存储在内存中,OpenCV使用了称为IplImage的C语言结构体。这也将C语言的所有缺点都带到了台面上,比如比较显著的问题之一是手动内存管理。

OpneCV 2.0之后的C++库中,图像都用Mat对象来存储,该接口提供了一种新的处理方式。这意味着在使用C++ OpenCV时无需费心处理内存管理,不再需要手动分配其内存并在不需要时立即释放它。

Mat对象本质上是具有两个数据部分的类:

  • 矩阵头,包含诸如矩阵大小,用于存储的方法,用于存储矩阵的地址之类的信息等等。
  • 指向存储像素值矩阵的指针,根据选择的图像存储方法可以保存成任何维度的数组。

矩阵头的大小是恒定的,但是矩阵本身的大小可能因图像而异,通常会增加几个数量级。

在这里插入图片描述

2. Mat对象基本OP

2.1 创建Mat对象

Mat对象常用构造函数:

Mat::Mat();	//默认构造函数
Mat::Mat(int rows, int cols, int type);	//指定类型的二维数组
Mat::Mat(Size size, int type);	//指定类型的二维数组
Mat::Mat(int rows, int cols, int type, const Scalar& s);	//指定类型的二维数组,并指定初始化值
Mat::Mat(Size size, int type, const Scalar& s);	//指定类型的多维数组,并指定初始化值
Mat::Mat(const Mat& m);	//复制构造函数,深拷贝
Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);	//指定类型的二维数组,并指定预先存储的数据
Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP);	//指定类型的多维数组,并指定预先存储的数据
Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange);	//从指定行列中复制数据
Mat::Mat(const Mat& m, const Rect& roi);	//从ROI中复制数据

2.2 Mat对象的赋值和拷贝

克隆和复制对应C++中的深拷贝,即与原图片有不同的数据块。而直接赋值对应C++中的浅拷贝,即与原图片占有同一块数据块。

mat_create_and_assignment.cpp

Mat input_image = imread("test_images/opencv.jpg",1);
	
//克隆:与原图片占有不同data block
Mat clone_img = input_image.clone();
imshow("clone", clone_img);

//复制:与原图片占有不同data block
Mat copy_img;
input_image.copyTo(copy_img);
imshow("copy", copy_img);

//直接赋值:与原图同一块data block
Mat assign_img = input_image;
imshow("assign", assign_img);

2.3 创建空白Mat

mat_create_and_assignment.cpp

//创建空白图像
Mat empty_1 = Mat::zeros(input_image.size(), input_image.type());
imshow("empty_1", empty_1);
	
//自定义大小 Size()
Mat empty_2 = Mat::zeros(Size(512,512), input_image.type());
imshow("empty_2", empty_2);
Mat empty_3 = Mat::ones(Size(512, 512), CV_8UC3);
imshow("empty_3", empty_3);

2.4 自定义卷积核

在使用自定义滤波器时常常需要自定义卷积核,这里可以使用运算符<<重载的方式来创建一个卷积核,卷积核本身也是一个矩阵,因此也可以跟图像数据一样用Mat对象来表示。

创建一个3x3的卷积核 mat_create_and_assignment.cpp

[ 0 − 1 0 − 1 5 − 1 0 − 1 0 ] \begin{bmatrix} 0&-1&0\\ -1&5&-1\\ 0&-1&0\\ \end{bmatrix} 010151010

Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);

3.Numpy ndarray:Python API中的基本图像容器

在这里插入图片描述
NumPy(Numerical Python)Python语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。ndarrayNumPy中的一个功能和性能都十分强大的N维数组对象,之前说过图像在计算机内存中就是数组,这使得ndarray与图像数据契合。

NmuPy的官网在 https://www.numpy.org.cn/ ,在上面可以详细地了解这个库。

3.1导入需要的包

因为Python API中图像存储借助于numpyndarray,因此进行图像赋值等操作时其实使用的是numpy ndarray带有的相关方法,因此除了导入cv2,还需要导入numpy这个库。

import cv2 as cv
import numpy as np 

3.2 以单通道方式读取图片

input = cv.imread("./test_images/opencv.jpg",0)

3.3 克隆图像

clone_image = np.copy(input)

3.4 赋值

ass_image = input

3.5创建空白图像

em_image = np.zeros(input.shape,input.dtype)

3.5 创建卷积核等矩阵

kernel = np.array([[0, -1, 0],[-1, 5, -1],[0, -1, 0]])
print(kernel.shape) # 3x3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值