坐标轴转换
将图像坐标系x0y0转换到旋转坐标系x1y1,即将图像坐标系的原点移到图像中心,y轴翻转,如下图所示
设图像的高度为H,宽度为W,有
设图像顺时针旋转角度为θ,旋转后点的坐标为(X2,Y2),则
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210707204421792.png
双线性插值
代码
void rotateImg(const Mat srcImg, Mat& roImg, double theta)
{
int w = srcImg.cols;
int h = srcImg.rows;
for (int i = 0; i < roImg.rows; i++)
{
for (int j = 0; j < roImg.cols; j++)
{
double x = j;
double y = i;
double x0 = x * cos(theta) + y * sin(theta) - 0.5 * w * cos(theta) - 0.5 * h * sin(theta) + 0.5 * w;
double y0 = -x * sin(theta) + y * cos(theta) + 0.5 * w * sin(theta) - 0.5 * h * cos(theta) + 0.5 * h;
if (x0 <= 0 || x0 >= w - 1 || y0 <= 0 || y0 >= h - 1)
continue;
int x1 = ceil(x0);
int x2 = x1 - 1;
int y1 = ceil(y0);
int y2 = y1 - 1;
Vec3d temp1 = srcImg.at<Vec3b>(y1, x1) * (x0 - x2) + srcImg.at<Vec3b>(y1, x2) * (x1 - x0);
Vec3d temp2 = srcImg.at<Vec3b>(y2, x1) * (x0 - x2) + srcImg.at<Vec3b>(y2, x2) * (x1 - x0);
Vec3d temp = temp1 * (y0 - y2) + temp2 * (y1 - y0);
roImg.at<Vec3b>(i, j) = temp;
}
}
}
效果
旋转之前
逆时针旋转30度之后:
这里边缘没有做填充,需要的话自己对边缘做个填充还是很容易的