图像运动专题-图像旋转-基于近邻插值的图像旋转
目录
1. 图像处理前后结果展示
图像处理前
图像处理后
图像处理后
2.图像旋转原理
基于近邻插值的图像旋转可以保证旋转后的图像内每个像素点都对应原图中的相应位置,而不会出现有黑点存在的情况。
上一篇文章介绍了图像的几何旋转,是计算原图中每个像素点旋转后的位置,将原图中的像素点的值赋给旋转后对应位置的像素点。这样存在的一个问题就是,原图中有些像素点旋转后的坐标取整后会映射到同一个点,这就造成了旋转后的图像中会出现一些黑点,也就是图像范围中有一些点是映射不到的。
这篇文章介绍的出发点是解决图像旋转后出现黑点的问题,所使用的方法是利用插值方法。其思想是,将旋转后图像的像素点映射回原图像,找到它的采样点,就是旋转的逆变换,将变换后的图像旋转到原图。映射的结果不会都是整数像素点,那么旋转后的点的像素值由与采样点最邻近的像素值表示,这是最近邻插值。
如下图,P0(x0,y0)是原图像中的点,P1(x1,y1)是旋转后的点,P1映射到原图中得到的P0附近的红点,近似地用P0表示红点的像素值;
点P0旋转θ角度到P1点。由P1映射到P0的方法是,令
由P1到P0,有,
于是有,
先给出利用opencv自带的函数进行图像旋转的结果,旋转角度的问题在上一篇中有介绍,这里不再赘述,其代码如代码1。
改变尺寸的图像旋转
这种旋转是将旋转后的图像内容完全显示出来,所以要先确定新的图像的尺寸,在上一篇文章中有关于新图像尺寸计算的介绍。
关键问题是如何将旋转后的图像逆变换后得到原图像。本篇文章所用的图像的轮廓示意图如下,黑色边框是新图像的轮廓,深红色轮廓是原图旋转后的轮廓。在新图像中原图的旋转可以看做是绕A点进行旋转,在做新图像向原图像映射的时候,是先把新图像左移|OA|的距离,绕点O进行逆旋转。
新图像中每一个像素点都参与逆变换过程,而目标像素点是经过逆变换落在原图像区域的点,对这些点进行相应的赋值。代码如代码2。
3.3.代码展示
代码1
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include <string>
#include <iostream>
#include<stdlib.h>
using namespace cv;
using namespace std;
int main()
{
Mat image = imread("C:\\Users\\DELL\\Desktop\\six.jpg");
float map[6];
Mat map_matrix;
map_matrix = getRotationMatrix2D(Point(0, 0), -15, 1.0); //旋转中心,旋转角度,缩放比例
Mat src(image.rows, image.cols, CV_8UC3);
warpAffine(image, src, map_matrix, Size(image.cols, image.rows));
imwrite("C:\\Users\\DELL\\Desktop\\six_spin.jpg", src);
}
代码2
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include <string>
#include <iostream>
#include<stdlib.h>
using namespace cv;
using namespace std;
int main()
{
Mat image1 = imread("C:\\Users\\DELL\\Desktop\\six.jpg");
int x0, y0, x1, y1;
double pi = 3.14159265358979323846264;
double angle = pi / 12;
int dx = (int)(image1.cols*cos(angle) + image1.rows*sin(angle));
int dy = (int)(image1.cols*sin(angle) + image1.rows*cos(angle));
Mat dst(dy, dx, CV_8UC3, Scalar(0)); //创建新图像
for (x1 = 0; x1 < dst.cols; x1++)
{
for (y1 = 0; y1 < dst.rows; y1++)
{
x0 = (x1 - image1.rows*sin(angle))*cos(angle) + y1 * sin(angle);
y0 = y1 * cos(angle) - (x1 - image1.rows*sin(angle))*sin(angle);
if (x0 >= 0 && x0 < image1.cols && y0 >= 0 && y0 < image1.rows)
{
dst.at<Vec3b>(Point(x1, y1)) = image1.at<Vec3b>(Point(x0, y0));
}
else
dst.at<Vec3b>(Point(x1, y1)) = 0;
}
}
imwrite("C:\\Users\\DELL\\Desktop\\six_spin.jpg", dst);
}