仿射变换
二维放射变换:
齐次坐标下:
平移变换:
绕原点放大和缩小:
绕点(x, y)放大和缩小(矩阵从右往左计算):
旋转变换:
顺时针公式推导:
逆时针公式推导:
计算仿射变换矩阵
方程法:
python
cv2.getAffineTransform(src, dst) //src代表的是原坐标,dst代表的是变换后的坐标,必须为浮点型
import cv2
import numpy as np
src = np.array([[0,0], [200,0], [0,200]], np.float32) #double [], else error :"only 2 non-keyword arguments accepted"
dst = np.array([[0,0], [100,0], [0,100]], np.float32) #after import numpy as np, only use np,don't use numpy
A = cv2.getAffineTransform(src,dst)
print(A)
C++
Point2f src [] = {Point2f(0,0), Point2f(200,0), Point2f(0,200)};
Point2f dst [] = {Point2f(0,0), Point2f(100,0), Point2f(0,100)};
Mat A = getAffineTransform(src,dst);
//return data type CV_64 not CV_32
//method two
Mat src = (Mat_<float>(3,2) << 0,0,200,0,0,200);
Mat dst = (Mat_<float>(3,2) << 0,0,100,0,0,100);
Mat A = getAffineTransform(src, dst);
矩阵法
python
s = np.array([[0.5,0,0], [0,0.5,0], [0,0,1]]); #Scaling matrix
t = np.array([[1,0,100], [0,1,200], [0,0,1]]); #translation matrix
A = np.dot(t, s) #matrix multiplication
print(A)
C++矩阵相乘
Mat s = (Mat_<float>(3,3) << 0.5,0,0,0,0.5,0,0,0,1); //Scaling matrix
Mat t =(Mat_<float>(3,3) << 1,0,100,0,1,200,0,0,1); //translation matrix
Mat A;
gemm(s, t,1.0, Mat(), 0, A, 0); //matrix multiplication
类似的,以(x0, y0)为中心进行缩放,然后逆时针旋转α,仿射变换矩阵为
如果是等比例缩放,即sx = sy俩个变换矩阵是相等的,opencv提供函数
cv2.getRotationMatrix2D(center, angle, scale)
center变换中心点坐标
angle等比例缩放系数
scale逆时针旋转角度;负数代表正时针旋转,以角度为单位,不是以弧度为单位
以(40,50)为旋转中心,逆时针旋转30°变换矩阵
A =cv2.getRotationMatrix2D((40,50), 30, 0.5)
print(A.dtype)
返回的是CV_64的数据类型
-
插值算法
使用最邻近插值算法,图像会出现锯齿状,对图像放大效果会更明显;若x,y不为整数,选取离f(x,y)最近点的坐标值。双线性插值
python实现
cv2.warpAffine(src, M, dsize, dst = None,flag = None, borderMode = None, borderValue = None)
src输入图像矩阵;M2行3列仿射变换矩阵,dsize二元元组(宽高),输出图像大小;flags插值法:INTE_NEAREST、INTE_LINEAR(默认)等;borderMode填充模式:BORDER_CONSTRANT等,borderValue当borderMode = BORDER_CONSTRANT的填充值
import cv2
import numpy as np
import sys
import math
#main function
if __name__ == "__main__":
image_path = "C:\\Users\\Pictures\\Saved Pictures\\1.jpg"
#"C:\\Users\\Pictures\\Saved Pictures\\1.jpg"
#"C:/Users/Pictures/Saved Pictures/1.jpg"
#R("C:\Users\Pictures\Saved Pictures\1.jpg")
image = cv2.imread(image_path);
image1 = cv2.imread(image_path, cv2.COLOR_GRAY2RGB)
#Init image height, width
h,w = image.shape[:2]
#The affine transformation matrix shrinks by 2
#125 s
scalingMatrix = np.array([[0.5,0,0],[0,0.5,0]], np.float32)
scalingMat = cv2.warpAffine(image, scalingMatrix, (w,h), borderValue = 125)
#shrins by 2, translation
scalingMatrix1 = np.array([[0.5,0,w/4],[0,0.5,h/4]],np.float32)
scalingMat1 = cv2.warpAffine(image, scalingMatrix1, (w,h), borderValue=125)
#base scalingMatrix1,rotate 30°
scalingMatrix3 = cv2.getRotationMatrix2D((w/2,h/2),30, 1);
scalingMat2 = cv2.warpAffine(scalingMat1, scalingMatrix3, (w,h), borderValue=125)
cv2.imshow("scalingMat", scalingMat);
cv2.imshow("scalingMat1", scalingMat1);
cv2.imshow("scalingMat2", scalingMat2);
cv2.waitKey(0)
cv2.destroyAllWindows()
C++实现
使用warpAffine()函数,先创建仿射矩阵,resize()函数对图像进行放缩
void resize(InputArray src, OutArray dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR)
src:输入图像矩阵; dst:输出图像矩阵;dsize二元元组(宽高),输出图像大小;fx:在水平方向上缩放比例,默认值为0;fy:在垂直方向上缩放比例,默认值为0;flags插值法:INTE_NEAREST、INTE_LINEAR(默认)等;
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
#include<string>
using namespace cv;
int main()
{
std::string image_path = "C:\\Users\\Pictures\\Saved Pictures\\1.jpg";
Mat image = imread(image_path, 1); //default = 1,color;gray set to 0
if (!image.data)
{
return -1;
}
Mat AffineMatrix = (Mat_<float>(2, 3) << 0.5, 0, 0, 0, 0.5, 0);
Mat AffineMat;
//shrink 1/2
// method one
warpAffine(image, AffineMat, AffineMatrix, Size(image.cols / 2, image.rows / 2));
//method two
Mat resizeMat;
resize(image, resizeMat, Size(image.cols / 2, image.rows / 2), 0.5, 0.5);
//display
imshow("image", image);
imshow("warpAffine", AffineMat);
imshow("resize", resizeMat);
waitKey(0);
return 0;
}
旋转函数
void rotate(InputArray src, OutArray dst, int rotateCode)
//rotateCode: ROTATE_90_CLOCKWISE, ROTATE_180, ROTATE_90_COUNTERCLOCKWISE
顺时针旋转90°,180°,270°
#rotate 90°
rotateImage = cv2.rotate(image, cv2.ROTATE_90_CLOCKWISE)
cv2.imshow("rotateImage",rotateImage)
//c++ code
Mat rotateImage;
rotate(image, rotateImage, ROTATE_180);
imshow("rotateImage",rotateImage);