CG :
- 该笔记是我大一开始接触图形学的一些问题时候的笔记
- 该笔记关于图像的平移和旋转,主要是2D 平面下
- 本文用到 OpenCV 库
Calc :
左图中演示了平移和旋转,平移比较好理解,只涉及到分别沿 x 和 y 轴的位移量 dx 和 dy,旋转涉及到旋转角度 θ 和参考点 ref_point,当涉及到参考点的时候,如右图,可以先通过转换坐标系来求解旋转方程。
平移:
旋转(绕原点):
在 opencv 的坐标系统下,y 轴是向下递增的,故如果旋转30度都表示是顺时针旋转,那么在 opencv 的坐标系统下,上面表达式中的 α - θ 应该替换为 α + θ,由此计算得到的上式中的黄色标记的旋转变换矩阵中的 -sinθ 为 sinθ,sinθ 为 -sin θ。
旋转(绕指定的参考点):
先通过一次平移变换转换原坐标系统到以参考点为原点的坐标系统,在新得到的坐标系统中通过旋转变换得到点的坐标,然后再经过一次恢复平移的变换来把当前新系统中的坐标转换到旧系统中的坐标。即 p1 = p0 * T1 * R * T2;其中 T1 为第一次平移变换,用于转换到新坐标系统,R 为旋转变换,T2 为第二次平移变换,用于恢复到原系统中的坐标。
Code : 在这里只贴了旋转的代码
1: #include <opencv\highgui.h>2: #pragma comment(lib, "opencv_core231d.lib")3: #pragma comment(lib, "opencv_highgui231d.lib")4: #pragma comment(lib, "opencv_imgproc231d.lib")5: using namespace cv;6:
7: Mat getRotateMatrix(double theta, const Point2d& ref_point = Point2d(0, 0))8: //参考点ref_point可指定,默认绕原点(0,0)旋转9: {
10: theta = theta / 180 * 3.1415;
11: //因为OpenCV中x,y方向与传统的坐标轴向不同,y轴向下递增,12: //故旋转30度如果在视觉上都为顺时针,那么旋转矩阵中的值会有变化(如文中所述)13: Mat result = (Mat_<double>(3, 3) <<14: cos(theta), sin(theta), 0,
15: -sin(theta),cos(theta), 0,
16: 0, 0, 1);
17: if (ref_point.x != 0 || ref_point.y != 0)18: //如果参考点不是原点,那么需要转换坐标系,然后再还原坐标系,用两个平移变换来实现19: {
20: double dx = -ref_point.x;21: double dy = -ref_point.y;22: Mat translate = (Mat_<double>(3, 3) <<23: 1, 0, 0,
24: 0, 1, 0,
25: dx, dy, 1);
26: Mat inv_translate = (Mat_<double>(3, 3) <<27: 1, 0, 0,
28: 0, 1, 0,
29: -dx, -dy, 0);
30: result = translate * result * inv_translate;
31: }
32: return result;33: }
34:
35: int main()36: {
37: const Scalar White(Scalar(255, 255, 255));38: const Scalar Red(Scalar(0, 0, 255));39: const Scalar Green(Scalar(0, 255, 0));40: const Scalar Yellow(Scalar(0, 255, 255));41:
42: Mat mat(400, 400, CV_8UC3, Scalar(0));
43:
44: Point a(200, 50);
45: circle(mat, a, 2, Green, 2); //画A点(200, 50)46: putText(mat, "A", a + Point(3, 3), FONT_HERSHEY_PLAIN, 1.0, Yellow);47:
48: Mat bm = (Mat)(Mat_<double>(1, 3) << a.x, a.y, 1) * getRotateMatrix(30); //转换A点坐标,绕原点(0,0)旋转30度49: Point b(bm.at<double>(0, 0), bm.at<double>(0, 1));50: circle(mat, b, 2, Green, 2); //画B点51: putText(mat, "B", b + Point(3, 3), FONT_HERSHEY_PLAIN, 1.0, Yellow);52:
53: Point ref_point(50, 200);
54: circle(mat, ref_point, 2, Red, 2); //画参考点(50, 200)55: putText(mat, "ref_point", ref_point + Point(3, 3), FONT_HERSHEY_COMPLEX, 0.5, Yellow);56:
57: //根据参考点计算绕参考点(50,200)旋转90度后的A点的坐标点C58: Mat cm = (Mat)(Mat_<double>(1, 3) << a.x, a.y, 1) * getRotateMatrix(90, ref_point);59: Point c(cm.at<double>(0, 0), cm.at<double>(0, 1));60: circle(mat, c, 2, Green, 2); //画C点61: putText(mat, "C", c+ Point(3, 3), FONT_HERSHEY_PLAIN, 1.0, Yellow);62:
63: //画白线连接参考点与相应的旋转点64: line(mat, Point(0, 0), a, White);
65: line(mat, Point(0, 0), b, White);
66: line(mat, ref_point, a, White);
67: line(mat, ref_point, c, White);
68:
69: imshow("Mat", mat);70: cv::waitKey(0);
71: return 0;72: }
A点绕原点旋转30度到B点,绕ref_point旋转90度到C点:
@Ggicci 本文属于个人学习笔记,如有错误,希望您能指正!转载请注明出处,谢谢 [CSDN博客] |