Opencv4--仿射变换和透视变换

仿射变换和透视变换

  • 引言
  • 仿射变换和透视变换概念
  • OpenCV函数封装
    • C++函数封装
    • python 函数封装
  • 仿射变换和透视变换作用
    • 仿射变换
    • 透视变换
  • imutils.perspective 进行透视变换
    • imutils包

引言

  • 我们在拍摄物体时,由于存在倾斜,拍摄图像中的物体难免会出现形变!因此我们需要对此类物体进行矫正处理!
    Opencv4--仿射变换和透视变换_第1张图片

仿射变换和透视变换概念

  • 其实仿射变换和透视变换更直观的叫法可以叫做「平面变换」和「空间变换」或者「二维坐标变换」和「三维坐标变换」。如果这么命名的话,其实很显然,这俩是一回事,只不过一个是二维坐标(x,y),一个是三维坐标(x,y,z)
    Opencv4--仿射变换和透视变换_第2张图片
  • 从另一个角度也能说明三维变换和二维变换的意思,仿射变换的方程组有6个未知数,所以要求解就需要找到3组映射点,三个点刚好确定一个平面。透视变换的方程组有8个未知数,所以要求解就需要找到4组映射点,四个点就刚好确定了一个三维空间。Opencv4--仿射变换和透视变换_第3张图片

OpenCV函数封装

C++函数封装

  • 仿射/透视变换:warpAffine / warpPerspective
void warpAffine(InputArray src, OutputArray dst, InputArray M, 
                Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, 
                const Scalar& borderValue=Scalar())
                
参数InputArray src:输入变换前的图像;
参数OutputArray dst:输出变换后图像,需要初始化一个空矩阵用来保存结果,不用设定矩阵尺寸;
参数Size dsize:设置输出图像大小;
参数int flags=INTER_LINEAR:设置插值方式,默认方式为线性插值;
后两个参数不常用,在此不赘述。
                
void warpPerspective(InputArray src, OutputArray dst, InputArray M, 
                    Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, 
                    const Scalar& borderValue=Scalar())
  • 获取变换矩阵:getAffineTransform / getPerspectiveTransform
Mat getAffineTransform(const Point2f* src, const Point2f* dst)

参数const Point2f* src:原图的三个固定顶点
参数const Point2f* dst:目标图像的三个固定顶点
返回值:Mat型变换矩阵,可直接用于warpAffine()函数
注意,顶点数组长度超过3个,则会自动以前3个为变换顶点;数组可用Point2f[]或Point2f*表示

Mat getPerspectiveTransform(const Point2f* src, const Point2f* dst)

python 函数封装

  • warpAffine / warpPerspective
dst = cv2.warpAffine(img, M, (cols,rows))

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

dst:透视后的输出图像,dsize决定输出图像大小
src:输入图像
M:3*3变换矩阵
flags:插值方法,默认为INTER_LINEAR
borderMode:边类型,默认为BORDER_CONSTANT
borderValue:边界值,默认为0
  • getAffineTransform / getPerspectiveTransform
retval = cv.getAffineTransform(src, dst)
src:输入图像的三个点坐标
dst:输出图像的三个点坐标
三个点分别对应左上角、右上角、左下角

M = cv2.getPerspectiveTransform(pts1, pts2)

仿射变换和透视变换作用

仿射变换

  • 用于: 旋转 (线性变换),平移 (向量加).缩放(线性变换),错切,反转
  • 仿射变换是一种二维坐标到二维坐标之间的线性变换,它保持了二维图形的“平直性”(直线经过变换之后依然是直线)和“平行性”(二维图形之间的相对位置关系保持不变,平行线依然是平行线,且直线上点的位置顺序不变)。任意的仿射变换都能表示为乘以一个矩阵(线性变换),再加上一个向量 (平移) 的形式
  • 例子:平移、缩放、旋转、翻转
#------------ warpAffine
import numpy as np
import cv2

rect_img = np.zeros((512, 512), dtype=np.uint8)
rect_img = cv2.cvtColor(rect_img, cv2.COLOR_GRAY2BGR)
pts = [(50, 50), (100, 200)]
cv2.rectangle(rect_img, pts[0], pts[1], (0,255,0), 2)
cv2.circle(rect_img, (50, 200), 2, (255,0,0), 2)
cv2.imshow('img', rect_img)

# move
rows, cols = rect_img.shape[:2]
moveM = np.float32([[1, 0, 100], [0, 1, 50]]) #构建平移矩阵
dst = cv2.warpAffine(rect_img, moveM, (rows, cols))
cv2.imshow('img_move', dst)

# resize
# cv2.resize()

# Rotation
# OpenCV直接提供了 cv.getRotationMatrix2D()函数来生成这个矩阵,该函数有三个参数:
# 参数1:图片的旋转中心
# 参数2:旋转角度(正:逆时针,负:顺时针)
# 参数3:缩放比例,0.5表示缩小一半
r_M = cv2.getRotationMatrix2D((50,200), 90, 1)
dst = cv2.warpAffine(rect_img, r_M, (cols, rows))
cv2.imshow('img_r', dst)


# reverse
# dst = cv2.flip(img, 1)
# 其中,函数中的第二个参数大于0,表示图像水平翻转(沿y轴);
# 第二个参数等于0,表示图像垂直翻转(沿x轴);
# 第二个参数小于0,表示图像既水平翻转,又垂直翻转。
dst = cv2.flip(rect_img, 0)
cv2.imshow('img_f', dst)

cv2.waitKey(0)
cv2.destroyAllWindows()

Opencv4--仿射变换和透视变换_第4张图片

透视变换

  • 用于:将2D矩阵图像变换成3D的空间显示效果,全景拼接.
  • 透视变换是将图片投影到一个新的视平面,也称作投影映射.它是二维(x,y)到三维(X,Y,Z),再到另一个二维(x’,y’)空间的映射.相对于仿射变换,它提供了更大的灵活性,将一个四边形区域映射到另一个四边形区域(不一定是平行四边形).它不止是线性变换.但也是通过矩阵乘法实现的,使用的是一个3x3的矩阵,矩阵的前两行与仿射矩阵相同(m11,m12,m13,m21,m22,m23),也实现了线性变换和平移,第三行用于实现透视变换.
  • 例子:

imutils.perspective 进行透视变换

imutils包

  • imutils项目
  • A common task in computer vision and image processing is to perform a 4-point perspective transform of a ROI in an image and obtain a top-down, “birds eye view” of the ROI. The perspective module takes care of this for you.
  • 使用说明:只要输入原图的四个点,调用four_point_transform方法就可以实现透视变换,常见的是将一个方形物体纠正,那么实际这四个点的获取方式有:(1)鼠标点击,保存点坐标,cv2.setMouseCallback;(2)轮廓提取,轮廓多边形拟合,找到四个角点。
  • Demo
# import the necessary packages
from imutils import perspective
import numpy as np
import cv2

# load the notecard code image, clone it, and initialize the 4 points
# that correspond to the 4 corners of the notecard
notecard = cv2.imread("../demo_images/notecard.png")
clone = notecard.copy()
pts = np.array([(73, 239), (356, 117), (475, 265), (187, 443)])

# loop over the points and draw them on the cloned image
for (x, y) in pts:
    cv2.circle(clone, (x, y), 5, (0, 255, 0), -1)

# apply the four point tranform to obtain a "birds eye view" of
# the notecard
warped = perspective.four_point_transform(notecard, pts)

# show the original and warped images
cv2.imshow("Original", clone)
cv2.imshow("Warped", warped)
cv2.waitKey(0)

Opencv4--仿射变换和透视变换_第5张图片

你可能感兴趣的:(OPENCV)