1、仿射变换
(1) 缩放:图像大小按照指定的比率放大或者缩小,cv2.resize(), cv.INTER_AREA、cv.INTER_CUBIC、cv.INTER_LINEAR
import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg')
res = cv.resize(img,None,fx=2, fy=2, interpolation = cv.INTER_CUBIC)
#OR
height, width = img.shape[:2]
res = cv.resize(img,(2*width, 2*height), interpolation = cv.INTER_CUBIC)
(2) 平移:将图像中所有的点按照指定的平移量水平或垂直移动,平移矩阵M作为warpAffine()输入
import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
M = np.float32([[1,0,100],[0,1,50]])
dst = cv.warpAffine(img,M,(cols,rows))
(3) 旋转:将图像绕某一指定点旋转一定的角度,旋转θ的旋转矩阵
绕中心点边缩放边旋转:
img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
M = cv.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv.warpAffine(img,M,(cols,rows))
(4) 仿射变换:需要3对点,cv.getAffineTransform得到2*3矩阵
img = cv.imread('drawing.png')
rows,cols,ch = img.shape
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv.getAffineTransform(pts1,pts2)
dst = cv.warpAffine(img,M,(cols,rows))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
2、投影变换
需要4对点,其中3对点不共线,cv.getPerspectiveTransform得到3*3矩阵
img = cv.imread('sudoku.png')
rows,cols,ch = img.shape
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv.getPerspectiveTransform(pts1,pts2)
dst = cv.warpPerspective(img,M,(300,300))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
3、图像变换
输入图像经过仿射变换后变成输出图像。注意输出图像内的整数坐标变换为原始图像中的非整数坐标,所以灰度值必须由插值得到。
输出图像中的一个像素已被变换回输入图像中,注意转换后这个像素的中心点是位于邻近的四个像素中心点之间,是一个非整数的位置。最简单快速的插值法是先对转换后像素中心的非整数坐标进行取整处理,以找到与此坐标相邻的四个像素点的中心位置中最近的一个,然后将输入图像里的最邻近位置的像素的灰度值视为输出图像内相应像素点的灰度值。称为最近领域插值法。双线性插值:计算转换后的坐标到四个相邻像素中心点的垂直方向和水平方向的距离。注意这些计算出的距离值在0到1之间。然后,根据距离值计算出不同灰度值所占的权重后得到双线性插值的结果。
for (size_t n = 0; n < neighbors; n++) {
float x = static_cast<float>(-radius) *
sin(2.0 * CV_PI * n / static_cast<float>(neighbors));
float y = static_cast<float>(radius) *
cos(2.0 * CV_PI * n / static_cast<float>(neighbors));
//下取整或上取整
int fx = static_cast<int>(floor(x));
int fy = static_cast<int>(floor(y));
int cx = static_cast<int>(ceil(x));
int cy = static_cast<int>(ceil(y));
// fraction part
float tx = x - fx;
float ty = y - fy;
//设置四个点的插值权重
float w1 = (1 - tx) * (1 - ty);
float w2 = tx * (1 - ty);
float w3 = (1 - tx) * ty;
float w4 = tx * ty;
for (int i = radius; i < src.rows - radius; i++)
for (int j = radius; j < src.cols - radius; j++) {
float t =
w1 * src.at<_Tp>(i + fy, j + fx) + w2 * src.at<_Tp>(i + fy, j + cx) +
w3 * src.at<_Tp>(i + cy, j + fx) + w4 * src.at<_Tp>(i + cy, j + cx);
dst.at<int>(i - radius, j - radius) +=
((t > src.at<_Tp>(i, j)) || (std::abs(t - src.at<_Tp>(i, j)) <
std::numeric_limits<float>::epsilon()))
<< n;
}
}
4、极坐标变换
极坐标变换通常被用来矫正图像中的圆形物体或被包含在圆环中的物体