【总结】OpenCV-Python常用API(三)—— 图像矩阵处理(1)

文章目录

  • 0. 前言
  • 1. 图像翻转
    • 1.1 函数简述和原型
    • 1.2 参数
    • 1.3 返回值
    • 1.4 实例展示
  • 2. 图像转置
    • 2.1 函数简述和原型
    • 2.2 参数
    • 2.3 返回值
    • 2.4 实例展示
  • 3. 仿射变换
    • 3.1 函数简述和原型
    • 3.2 参数
    • 3.3 返回值
    • 3.4 用法举例
    • 3.5 实例展示
  • 4. 仿射变换矩阵生成
    • 4.1 函数简述和原型
    • 4.2 参数
    • 4.3 返回值
    • 4.4 用法举例
  • 5. 透视变换
    • 5.1 函数简述和原型
    • 5.2 参数
    • 5.3 返回值
    • 5.4 用法举例
    • 5.5 实例展示

0. 前言

图像在计算机中均是以二维矩阵的方式存储的,矩阵中的每个元素对应一个像素点,类型为uint8,因此值在0-255之间。灰度图像就是一个二维矩阵,0-255对应从黑到白256个级别的灰度。彩色图像根据不同的色彩空间有不同的存储方式,最常见的RGB彩色空间,则有三个通道,每个通道也是一个二维矩阵,对应了红、绿、蓝三种基本颜色的分量。

因此,OpenCV读取的图片或视频流中的一帧图像均为numpy的ndarray,若为灰度图像,即为一个二维矩阵;若为三通道BGR彩色图像,则为三个二维矩阵。原点默认为左上角,x轴为水平方向,向右为正方向;y轴为垂直方向,向下为正方向。也即矩阵的第一个元素 M 00 M_{00} M00就对应坐标为 ( 0 , 0 ) (0,0) (0,0)的像素,矩阵第 i i i行第 j j j列的元素 M i j M_{ij} Mij对应坐标为 ( j , i ) (j, i) (j,i)的像素,此处注意坐标和矩阵位置的顺序!此外,从图像角度描述图像大小时往往为宽*高,而从矩阵角度描述大小时,往往为行*列。而行对应高,列对应宽,故一张 1024 × 768 1024 \times 768 1024×768的图像对应的是 768 × 1024 768 \times 1024 768×1024的矩阵。

既然图像通过矩阵方式存储,那么针对图像的很多操作实际上就是针对矩阵的操作,下面就对OpenCV封装的对矩阵的一些操作进行小结。

1. 图像翻转

1.1 函数简述和原型

该函数用于对图片进行翻转。官方文档:https://docs.opencv.org/3.4.2/d2/de8/group__core__array.html#gaca7be533e3dac7feb70fc60635adf441

dst = cv2.flip(src, flipCode)

1.2 参数

  • src:要翻转的图片数据;
  • flipCode:翻转方向代码,int类型。有三种模式,0表示按x轴翻转(垂直翻转);大于0表示按y轴翻转(水平翻转);小于0表示两个方向均进行翻转(相当于旋转180度)

1.3 返回值

  • dst:翻转后的图片

1.4 实例展示

【总结】OpenCV-Python常用API(三)—— 图像矩阵处理(1)_第1张图片

2. 图像转置

2.1 函数简述和原型

该函数用于对图像的像素数据矩阵进行转置,即将图像沿y=x翻转,相当于逆时针旋转90°后再垂直翻转(或水平翻转后再逆时针旋转90°),注意与直接逆时针旋转90°的区别!官方文档:https://docs.opencv.org/3.4.2/d2/de8/group__core__array.html#ga46630ed6c0ea6254a35f447289bd7404

dst = cv2.transpose(src)

2.2 参数

  • src:要转置的图片数据;

2.3 返回值

  • dst:转置后的图片

2.4 实例展示

【总结】OpenCV-Python常用API(三)—— 图像矩阵处理(1)_第2张图片

3. 仿射变换

3.1 函数简述和原型

从线性代数的知识可知,一个n维方阵可以表示对n维空间的线性变换。那么既然图像以二维矩阵的方式存储在计算机中(多通道彩色图像可以看做多个二维矩阵的叠加),图像的二维矩阵左乘一个2*2的矩阵,就可以对该图像进行线性变换,包括拉伸、旋转,再加上平移即组成了图像的仿射变换。因此OpenCV提供了对图像进行仿射变换的函数,主要作用即为对图像数据左乘2维方阵进行线性变换,再加上平移。官方文档:https://docs.opencv.org/3.4.2/d7/d1b/group__imgproc__misc.html#ga72b913f352e4a1b1b397736707afcde3

dst = cv2.warpAffine(src, M, dsize[, flags[, borderMode[, borderValue]]])

3.2 参数

  • src:要处理的图像数据,可以为多通道彩色图像;
  • M:ndarray类型,一个2*3的矩阵,元素类型为float32。其中前两列构成了对图像进行线性变换的2*2方阵,第三列表示将图像分别在x轴和y轴两个方向上进行平移的距离(以像素为单位);
  • dsize:输出图像的大小,二元元组,分别为输出图像的宽和高;
  • flags:插值方法的flag,默认为cv2.INTER_LINEAR(线性插值法)。若为cv2.WARP_INVERSE_MAP,表示使用M的逆矩阵对图像进行逆向变换;
  • borderMode:边界外推模式,默认为cv2.BORDER_CONSTANT,即使用常数填充边界;
  • borderValue:边界填充值,当边界外推模式为cv2.BORDER_CONSTANT时,填充边界所用的常数,默认值为0;

3.3 返回值

  • dst:仿射变换后的图像;

3.4 用法举例

img = cv2.imread(r'.\image.jpg', cv2.IMREAD_COLOR)
h, w, channels = img.shape

# 定义平移矩阵,需要是numpy的float32类型
# x轴平移100,y轴平移50的矩阵
M = np.float32([[1, 0, 100],
                [0, 1, 50]])
# 使用仿射变换实现平移,并使用白色填充边界
imgShift = cv2.warpAffine(img, M, (w, h), borderMode=cv2.BORDER_CONSTANT, borderValue=(255, 255, 255))
cv2.imshow('shift', imgShift)

# 定义一个绕图片中心逆时针旋转90°的仿射变换矩阵
M = np.float32([[0, 1, 0],
                [1, 0, 0]])
imgRotate = cv2.warpAffine(img, M, (h, w))
cv2.imshow('rotate', imgRotate)

# 定义一个斜右下角剪切(shear)的仿射变换矩阵
M = np.float32([[1, 1, 0],
                [0, 1, 0]])
imgShear = cv2.warpAffine(img, M, (2*w, h), borderMode=cv2.BORDER_CONSTANT, borderValue=(255, 255, 255))
cv2.imshow('shear', imgShear)

3.5 实例展示

【总结】OpenCV-Python常用API(三)—— 图像矩阵处理(1)_第3张图片

4. 仿射变换矩阵生成

4.1 函数简述和原型

如上所述,仿射变换可以完成很多针对图像的操作,如平移、旋转、拉伸等。但往往计算仿射变换对应的矩阵需要具备线性代数的相关知识,并且计算量也较大。因此OpenCV提供了两个函数来生成仿射变换矩阵,极为方便。其中getRotationMatrix2D函数是专用于生成旋转对应的仿射变换的矩阵,getAffineTransform则更为通用,通过变换前后三个非共线点的坐标来生成对应的仿射变换矩阵。官方文档:https://docs.opencv.org/3.4.2/da/d54/group__imgproc__transform.html

# 生成旋转对应的仿射变换矩阵
M = cv2.getRotationMatrix2D(center, angle, scale)
# 根据仿射变换前后三个点的位置变化生成对应的矩阵
M = cv2.getAffineTransform(src, dst)

4.2 参数

  • center:旋转中心的点坐标,一个二元组;
  • angle:旋转角度,double类型,正数表示逆时针旋转,负数表示顺时针旋转;
  • scale:double类型,各向同性的缩放比例;
  • src:仿射变换前三个点的坐标;
  • dst:仿射变换后对应的三个点的坐标;

4.3 返回值

  • M:参数决定的仿射变换所对应的矩阵,一个2*3的ndarray,元素为float32类型,可以直接用于warpAffine函数;

4.4 用法举例

img = cv2.imread(r'\image.jpg', cv2.IMREAD_COLOR)
h, w, channels = img.shape

# 绕图片中心逆时针旋转45°,并缩小一半
M = cv2.getRotationMatrix2D((w / 2, h / 2), 45, 0.5)
imgRot = cv2.warpAffine(img, M, (w, h))
cv2.imshow('rotation', imgRot)

# 通过变换前后三个点的坐标获取对应的仿射变换矩阵
# 变换前的三个点
pts1 = np.float32([[0, 0], [1, 0], [0, 1]])
# 变换后的三个点,逆时针旋转90°,并均下移宽度位置
pts2 = np.float32([[0, w], [0, -1+w], [1, w]])

# 生成变换矩阵
M = cv2.getAffineTransform(pts1, pts2)
imgRot = cv2.warpAffine(img, M, (h, w))
cv2.imshow('image Rotation', imgRot)

5. 透视变换

5.1 函数简述和原型

图像的几何变换中,除了仿射变换,还有透视变换,也就是将图片重新投影到一个新的视平面。实际应用中往往通过这种方式矫正图片。类似仿射变换,配套透视变换函数warpPerspective的还有生成透视变换矩阵的函数getPerspectiveTransform,通过四个非共线点来生成对应的透视变换矩阵。官方文档:https://docs.opencv.org/3.4.2/da/d54/group__imgproc__transform.html

# 根据透视变换前后非共线的四个点的位置变化生成对应的透视变换矩阵
M = cv2.getPerspectiveTransform(src, dst)
# 根据透视变换矩阵将图像进行透视变换
ret = cv2.warpPerspective(img, M, dsize[, flags[, borderMode[, borderValue]]])

5.2 参数

  • src:透视变换前四个非共线的点的坐标;
  • dst:透视变换后对应的四个点的坐标;
  • img:要进行透视变换的图像,可以是多通道彩色图像;
  • M:透视变换的矩阵,一个3*3的ndarray;
  • dsize:输出图像的大小,二元元组,分别为输出图像的宽和高;
  • flags:插值方法的flag,默认为cv2.INTER_LINEAR(线性插值法)。若为cv2.WARP_INVERSE_MAP,表示使用M的逆矩阵对图像进行逆向变换;
  • borderMode:边界外推模式,默认为cv2.BORDER_CONSTANT,即使用常数填充边界;
  • borderValue:边界填充值,当边界外推模式为cv2.BORDER_CONSTANT时,填充边界所用的常数,默认值为0;

5.3 返回值

  • M:参数决定的透视变换所对应的矩阵,一个3*3的ndarray,元素为float32类型,可以直接用于warpPerspective函数;
  • ret:透视变换后的图像数据;

5.4 用法举例

img = cv2.imread(r'.\image.jpg', cv2.IMREAD_COLOR)
h, w, channels = img.shape

# 卡片的四个角点,非共线的四个点才能唯一确定透视变换
pts1 = np.float32([[148, 80], [437, 114], [94, 247], [423, 288]])
# 变换后分别在左上、右上、左下、右下四个点
pts2 = np.float32([[0, 0], [320, 0], [0, 178], [320, 178]])

# 根据变换前后点的位置生成透视变换矩阵
M = cv2.getPerspectiveTransform(pts1, pts2)
# 进行透视变换
imgPersp = cv2.warpPerspective(img, M, (320, 178))
cv2.imshow('Perspective transform', imgPersp)

5.5 实例展示

【总结】OpenCV-Python常用API(三)—— 图像矩阵处理(1)_第4张图片

你可能感兴趣的:(OpenCV)