关于点的旋转
- 将坐标(x, y)以(rx0, ry0)为原点逆时针旋转 a 度,得到新坐标(x0,y0)
x0 = (x - rx0) * cos(a) - (y - ry0) * sin(a) + rx0
y0 = (x - rx0) * sin(a) + (y - ry0) * cos(a) + ry0
- 将上式进行变形(令rx0=ry0=0)
cos(a) = (x * x0 + y*y0) / (x^2 + y^2)
sin(a) = (x * y0 - y*x0) / (x^2 + y^2)
仿射变换
c++利用opencv实现的图片旋转
void MyOpencv::rotate(Mat &src, Mat &dst, float angle)
{
int heightNew = int(src.cols*fabs(sin(angle*3.14 / 180)) + src.rows * fabs(cos(angle*3.14 / 180)));
int widthNew = int(src.rows*fabs(sin(angle*3.14 / 180)) + src.cols * fabs(cos(angle*3.14 / 180)));
Point2f pt(src.cols / 2., src.rows / 2.);
//旋转矩阵
//-- --
//| ∂, β, (1-∂)*pt.x-β*pt.y |
//|-β, ∂, β*pt.x+(1-∂)*pt.y |
//-- --
// 其中 ∂=scale*cos(angle), β=scale*sin(angle)
Mat r = getRotationMatrix2D(pt, angle, 1.0); // 获取旋转矩阵(旋转中心(pt), 旋转角度(angle), 缩放系数(scale)
r.at<double>(0, 2) += (widthNew - src.cols) / 2;
r.at<double>(1, 2) += (heightNew - src.rows) / 2;
warpAffine(src, dst, r, Size(widthNew, heightNew), INTER_LINEAR, BORDER_CONSTANT );// 进行仿射变换(输入图像, 输出图像, 2X3的变换矩阵, 指定图像输出尺寸, 插值算法标识符, 边界填充BORDER_REPLICATE)
}
python版
def rotate(image, angle):
"""
旋转图片
:param image:
:param angle:
:return:
"""
PI = np.pi
heightNew = int(image.shape[1] * np.abs(np.sin(angle * PI / 180)) + image.shape[0] * np.abs(np.cos(angle * PI / 180)))
widthNew = int(image.shape[0] * np.abs(np.sin(angle * PI / 180)) + image.shape[1] * np.abs(np.cos(angle * PI / 180)))
pt = (image.shape[1] / 2., image.shape[0] / 2.)
# 旋转矩阵
# -- --
# | ∂, β, (1 -∂) * pt.x - β * pt.y |
# | -β, ∂, β * pt.x + (1 -∂) * pt.y |
# -- --
# 其中 ∂=scale * cos(angle), β = scale * sin(angle)
### getRotationMatrix2D 的实现 ###
scale = 1
a = scale * np.cos(angle * PI / 180)
b = scale * np.sin(angle * PI / 180)
r1 = np.array([[a, b, (1 - a) * pt[0] - b * pt[1]],
[-b, a, b * pt[0] + (1 - a) * pt[1]]])
### getRotationMatrix2D 的实现 ###
r = cv2.getRotationMatrix2D(pt, angle, 1.0) # 获取旋转矩阵(旋转中心(pt), 旋转角度(angle), 缩放系数(scale)
r[0, 2] += (widthNew - image.shape[1]) / 2
r[1, 2] += (heightNew - image.shape[0]) / 2
dst = cv2.warpAffine(image, r, (widthNew, heightNew), cv2.INTER_LINEAR, cv2.BORDER_CONSTANT) # 进行仿射变换(输入图像, 2X3的变换矩阵, 指定图像输出尺寸, 插值算法标识符, 边界填充BORDER_REPLICATE)
return dst