OpenCV总结之图像几何变换

1. 图像缩放

对图像进行放大或缩小,使用API:

cv2.resize(src, dsize, fx=0, fy=0, interpolation=cv2.INTER_LINEAR)

参数:

src:输入图像

dsize:绝对尺寸,直接指定调整之后图像的大小

fx, fy:相对尺寸,将dsize设置为None,然后将fx和fy设置为比例因子即可

interpolation:插值方法:

插值 含义
cv2.INTER_LINEAR 双线性插值法
cv2.INTER_NEAREST 最近邻插值
cv2.INTER_AREA 像素区域重采用
cv2.INTER_CUBIC 双三次插值

示例:

import cv2 as cv

#读取图片
img1 = cv.imread("E:\\loaddown\\opencv_test\\1.jpg")

#图像缩放
#绝对尺寸
rows,cols = img1.shape[:2]
res = cv.resize(img1, (2*cols, 2*rows), interpolation=cv.INTER_CUBIC)

#相对尺寸
res1 = cv.resize(img1, None, fx=0.5, fy=0.5)

#图像显示
cv.imshow("orignal", img1)
cv.imshow("enlarge", res)
cv.imshow("shrink", res1)
cv.waitKey(0)

运行结果:

扫描二维码关注公众号,回复: 15450360 查看本文章

2. 图像平移

指定平移矩阵后,调用cv.warpAffine()平移图像

cv.warpAffine(img, M, dsize)

参数:

img: 输入图像

M:2*3移动矩阵

要把(x, y)处的像素点移动到(x+t_{x}, y+t_{y})处,M矩阵应设置为:

M=\begin{Bmatrix} 1 & 0 & t_{x} \\ 0 & 1 & t_{y} \end{Bmatrix}

注意:将M设置为np.float32类型的Numpy数组

dsize:输出图像的大小

注意:输出图像的大小,它应该是(宽度,高度)的形式,请记住,width=列数,height=行数。

示例:

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

#读取图像
img1 = cv.imread("E:\\loaddown\\opencv_test\\1.jpg")

#图像平移,所有像素点移动(50,100)
rows,cols = img1.shape[:2]
M = np.float32([[1,0,50],[0,1,100]]) #平移矩阵
dst = cv.warpAffine(img1, M, [cols+50, rows+100])

#图像展示
fig,axes = plt.subplots(nrows=1, ncols=2, figsize=(10,8), dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("orignal")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("translation")
plt.show()

输出结果:

3.图像旋转

在opencv中图像旋转首先根据旋转中心和旋转角度获得旋转矩阵,然后根据旋转矩阵进行变换,也就是调用cv.getRotationMatrix2D()获取旋转矩阵,然后调用cv.warpAffine()进行旋转。

cv2.getRotationMatrix2D(center, angle, scale)

参数:

center:旋转中心

angle:旋转角度

scale:缩放比例

示例:

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

#读取图像
img1 = cv.imread("E:\\loaddown\\opencv_test\\1.jpg")

#获取图像size
rows, cols = img1.shape[:2]
#获取旋转矩阵
M = cv.getRotationMatrix2D((rows/2, cols/2), 30, 1)

#计算变换后图像的显示size
cos = np.abs(M[0, 0])
sin = np.abs(M[0, 1])
cols1 = rows * sin + cols * cos
rows1 = rows * cos + cols * sin
cols1 = int(np.round(cols1))
rows1 = int(np.round(rows1))
M[0,2] += (cols1 - cols) * 0.5
M[1,2] += (rows1 - rows) * 0.5
#图像旋转
dst = cv.warpAffine(img1, M, [cols1,rows1])
# print("M: ", M)

#图像显示
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10,8), dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("orignal")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("rotation")
plt.show()

输出结果:

4.仿射变换

仿射变换是对图像的缩放、旋转、翻转和平移等操作的组合。如图所示,图1一中的点1、2、3与图二中的三个点一一映射,仍然形成三角形,但是大小和相对距离等已经改变。通过这样两组感兴趣点(至少三个不共线的点)可以求出放射变换矩阵,然后把变换矩阵应用到图像中所有点,就完成了图像的仿射变换。

调用cv.getAffineTransform()将创建变换矩阵,最后该矩阵将传递给cv.warpAffine()进行变换

cv2.getAffineTransform(src, dst)

参数:

src: 原始图像中三个感兴趣点的坐标

dst: 目标图像中对应的三个感兴趣点的坐标

需要注意的是,原始图像中所有平行线经过仿射变换后仍然平行。

示例:

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

#读取图像
img1 = cv.imread('E:\\loaddown\\opencv_test\\1.jpg')

#获取仿射变换矩阵
rows, cols = img1.shape[:2]
pts1 = np.float32([[50,50], [200,50], [50,200]])
pts2 = np.float32([[100,100], [200,50], [100,250]])
M = cv.getAffineTransform(pts1, pts2)

#进行仿射变换
dst = cv.warpAffine(img1, M, (cols, rows))

#图像显示
fig,axes = plt.subplots(nrows=1, ncols=2, figsize=(10,8), dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("orignal")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("affine")
plt.show()

输出结果:

5. 透射变换

透射变换的本质是将图像投射到一个新的平面,其通用变换公式为:

\left [ \begin{matrix} x' & y' & z' \end{matrix} \right ] = \left [ \begin{matrix} u & v & w \end{matrix} \right ] T = \left [ \begin{matrix} u & v & w \end{matrix} \right ] \left [ \begin{matrix} T_{1} & T_{2} \\ T_{3} & a_{22} \end{matrix} \right ] = \left [ \begin{matrix} u & v & w \end{matrix} \right ]\left [ \begin{matrix} a_{00} & a_{01} & a_{02} \\ a_{10} & a_{11} & a_{12}\\ a_{20} & a_{21} & a_{22} \end{matrix} \right ]

其中,\left ( u,v \right )是原始的图像像素坐标,w取值为1,(x=\frac{x'}{z'}, y=\frac{y'}{z'})是透射变换后的结果,T矩阵是透射变换矩阵,可以分成三部分:T_1表示对图像进行线性变换,T_2对图像进行平移,T_3表示对图像进行投射变换,a_{22}一般设为1。

在opencv中,需要找到四个点(其中任意三个不共线)来计算获取变换矩阵T,再进行透射变换。通过函数cv.getPerspectiveTransform()找到变换矩阵,将cv.warpPerspective()进行投射变换。

示例:

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

#读取图像
img1 = cv.imread("E:\\loaddown\\opencv_test\\1.jpg")

#获取透射变换矩阵
rows,cols = img1.shape[:2]
pts1 = np.float32([[56,65], [168,52], [28,187], [189,190]])
pts2 = np.float32([[100, 145], [200, 100], [80,190], [210,200]])

T = cv.getPerspectiveTransform(pts1, pts2)
#透射变换
dst = cv.warpPerspective(img1, T, (cols, rows))
#图像显示
fig,axes = plt.subplots(nrows=1, ncols=2, figsize=(10,8), dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("orignal")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("perspective")
plt.show()

输出结果:

6.图像金字塔

图像金字塔是图像多尺度表达的一种,最主要用于图像分割,是一种以多分辨率来解决图形的有效且概念简单的结构。图像金字塔用于机器视觉和图像压缩,一幅图像的金字塔是一系列以金字塔形状排列的分辨率递减且来源于同一张原始图的图像集合。其通过梯次向下采样获得,直到达到某个终止条件才停止采样。

金字塔的底部是高分辨率的待处理图像表示,顶部是低分辨率的图像,层级越高,图像越小,分辨率越低。

图像金字塔是图像多尺度表达的一种,使用API:

cv.pyrUp(image)  #向上采样

cv.pyrDown(image)  #向下采样

示例:

mport cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

#读取图像
img1 = cv.imread("E:\\loaddown\\opencv_test\\1.jpg")

#进行图像采样
up_img = cv.pyrUp(img1) #上采样操作
down_img = cv.pyrDown(img1) #下采样操作

#图像显示
fig,axes = plt.subplots(nrows=1, ncols=3, figsize=(10,8), dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("orignal")
axes[1].imshow(up_img[:,:,::-1])
axes[1].set_title("up_img")
axes[2].imshow(down_img[:,:,::-1])
axes[2].set_title("down_img")
plt.show()

输出结果:

猜你喜欢

转载自blog.csdn.net/panpan_jiang1/article/details/129150095