美文网首页
图片中点的旋转

图片中点的旋转

作者: haoshengup | 来源:发表于2019-08-22 18:55 被阅读0次

  在图片处理中,经常会遇到点的旋转和坐标系的旋转问题,这里对一个点(x, y)绕另一个点(x0, y0)旋转的问题做一个总结。
  一、在介绍之前,先总结一下编程的问题,因为在实现的过程中碰到了一些坑:
  (1)c++中,三角函数的输入和反三角函数的输出都是:弧度。
  (2)opencv中涉及的都是角度,比如旋转矩形的角度、仿射变换时旋转图片的角度。

  二、假设有两个点,一个点为p(x, y),另一个点为p0(x0, y0)。让点p绕着点p0旋转α(角度或者弧度都可以),求旋转之后点的坐标p1(x1, y1)。我们可以分成三个步骤来完成:(1)先将原点移动到旋转中心。(2)让p0围绕原点旋转α。(3)移回坐标原点。
  1、将原点移动到旋转中心p0处。那么点p0在新坐标系中的坐标为:(0, 0),点p1在新坐标系中的坐标为:(x - x0, y- y0)。
  2、将点(x - x0, y- y0)绕着原点旋转角度α,将旋转之后点的坐标记为p2(x2, y2)。那么:
    x2 = (x - x0) * cosα + (y - y0) * sinα,     y2 = -(x - x0) * sinα + (y - y0) * cosα
  3、将坐标原点移回到原来的位置,那么可以根据点p2得到我们最终的结果p1(x1, y1)。即:
    x2 = (x - x0) * cosα + (y - y0) * sinα + x0,   y2 = -(x - x0) * sinα + (y - y0) * cosα + y0

  三、应用举例
  图片中有一条线段,线段L的两个顶点分别为:p1(x1, y1),p2(x2, y3)。我们的目标是将L旋转为水平,旋转之后的线段记为L'L'的两个顶点分别为p3(x3, y3),p4(x4, y4),其中p3和p1对应,p4和p2对应,我们需要计算旋转之后的点p3和p4的坐标。
  实现代码如下:

void point_rotate() {

    // 得到一张空白的灰度图
    Mat image = Mat::zeros(Size(500, 500), CV_8UC1);
    float x0 = image.cols / 2;
    float y0 = image.rows / 2;

    // 初始化两个点, p1和p2
    Point p1 = Point(100, 100);
    Point p2 = Point(200, 120);

    //分别得到两个点的坐标
    float x1 = p1.x;
    float y1 = p1.y;
    float x2 = p2.x;
    float y2 = p2.y;

    //在图上画出两个点,以及两个点连成的线L
    circle(image, p1, 3, Scalar(255), -1);
    circle(image, p2, 3, Scalar(255), -1);
    line(image, p1, p2, Scalar(255));

    // 计算L的偏转角度
    float angle = atan((y2 - y1) / (x2 - x1));  //注意:这里得到的是弧度

    //以rotate_angle角度来旋转图片m,注意,opencv中的都是角度,所以这里需要把弧度转化为角度
    // 旋转的时候也需要注意,opencv中,负角度指的是顺时针
    Mat rotate_img;
    float rotate_angle = angle * 180 / 3.14159265358979323846;
    Mat m = getRotationMatrix2D(Point2f(x0, y0), rotate_angle, 1);
    warpAffine(image, rotate_img, m, Size(image.cols, image.rows), 1, 0, 255);

    //计算p1在新图片中对应的坐标p3
    float x3 = (x1 - x0) * cos(angle) + (y1 - y0) * sin(angle) + x0;
    float y3 = -(x1 - x0) * sin(angle) + (y1 - y0) * cos(angle) + y0;
    Point p3 = Point(int(x3), int(y3));

    //计算p2在新图片中对应的坐标p4
    float x4 = (x2 - x0) * cos(angle) + (y2 - y0) * sin(angle) + x0;
    float y4 = -(x2 - x0) * sin(angle) + (y2 - y0) * cos(angle) + y0;
    Point p4 = Point(int(x4), int(y4));

    //在旋转之后的图片中画出点p1, p2, p3, p4, 以及p1和p2的连线L,p3和p4的连线L'
    circle(rotate_img, p1, 3, Scalar(255), -1);
    circle(rotate_img, p2, 3, Scalar(255), -1);
    line(rotate_img, p1, p2, Scalar(255));

    circle(rotate_img, p3, 3, Scalar(255), -1);
    circle(rotate_img, p4, 3, Scalar(255), -1);
    line(rotate_img, p3, p4, Scalar(255));

    //标识每个点的位置
    putText(rotate_img, "p1", p1, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));
    putText(rotate_img, "p2", p2, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));
    putText(rotate_img, "p3", p3, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));
    putText(rotate_img, "p4", p4, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));

    //画出旋转中心,以及p1,p3分别和旋转中心的连线
    Point center = Point(x0, y0);
    circle(rotate_img, center, 3, Scalar(255), -1);
    line(rotate_img, p1, center, Scalar(255)); 
    line(rotate_img, p3, center, Scalar(255));

    //沿着p1点画一条水平基准线
    line(rotate_img, Point(0, 100), Point(rotate_img.cols, 100), Scalar(255));

    // 保存图片image, rotate_img
    imwrite("E:\\image.bmp", image);
    imwrite("E:\\rotate_img.bmp", rotate_img);
}

  结果如下图所示:



  在上图的角度标识中,角度1为:计算出的线段L的角度;角度2为:图片旋转的角度;角度3为:点p1旋转的角度。从视觉效果上来看,这三个角度应该是一致的。

相关文章

  • 图片中点的旋转

      在图片处理中,经常会遇到点的旋转和坐标系的旋转问题,这里对一个点(x, y)绕另一个点(x0, y0)旋转的问...

  • 【Android】图片显示旋转问题

    读取图片旋转角度 旋转图片

  • iOS-image图片旋转方向

    图片旋转 以下是图片方向的选择 view旋转

  • iOS 图片旋转方向

    图片旋转 view旋转

  • 图片旋转

    IOS上传照片会旋转一定的角度,所以有时候需要把图片给旋转。具体实现如下: public String rotat...

  • 旋转图片

    不改变View的情况下,旋转view里面的图片

  • 旋转图片

    未使用Camera实现的,其实使用Camera也就几行代码的事。我这叫闲的蛋疼。

  • 旋转图片

    给定一个 n × n 的二维矩阵表示一个图像。 将图像顺时针旋转 90 度。 说明: 你必须在原地旋转图像,这意味...

  • 图片旋转

    版权声明:本文为博主原创文章,转载请注明出处。个人博客地址:https://yangyuanlin.club欢迎来...

  • iOS中通过CGContext实现图片围绕任意点旋转任意角度的功

    需求 需要围绕任意点旋转若干角度返回和原始图片大小相同的图片。 实现 代码如下: 输入:需要旋转的图片,旋转的角度...

网友评论

      本文标题:图片中点的旋转

      本文链接:https://www.haomeiwen.com/subject/hngisctx.html