用OpenCV围绕一个点旋转一个点

Rotate a point around a point with OpenCV

本文关键字:一个 旋转 OpenCV      更新时间:2023-10-16

有人知道我如何在OpenCV中旋转另一个点吗?

我正在寻找这样的函数:

Point2f rotatePoint(Point2f p1, Point2f center, float angle)
{
    /* MAGIC */
}

将一个点围绕另一个点旋转一个角度所需的步骤:

  1. 将该点平移为轴心点的负值
  2. 使用二维(或三维)旋转的标准方程旋转点
  3. 翻译回

旋转的标准方程为:

x' = xcos(alpha) - ysin(alpha)

y' = xsin(alpha) + ycos(alpha)

让我们以点(15,5)绕点(2,2)45度为例。

首先,翻译:

v = (15,5) - (2,2) = (13,3)

现在旋转45°:

v = (13 * cos 45°- 3 *罪45°,13 * sin 45°+ 3 * cos 45°)= (7.07 . .

11.31 . .)

最后,翻译回来:

v = v + (2,2) = (9.07..

13.31 . .)

注意:角度必须以弧度为单位,因此将角度数乘以Pi / 180

将点p1 = (x1, y1)p (x0, y0)旋转a:

x2 = ((x1 - x0) * cos(a)) - ((y1 - y0) * sin(a)) + x0;
y2 = ((x1 - x0) * sin(a)) + ((y1 - y0) * cos(a)) + y0;

其中(x2, y2)p1点的新位置

这可能有帮助

cv::Point2f rotate2d(const cv::Point2f& inPoint, const double& angRad)
{
    cv::Point2f outPoint;
    //CW rotation
    outPoint.x = std::cos(angRad)*inPoint.x - std::sin(angRad)*inPoint.y;
    outPoint.y = std::sin(angRad)*inPoint.x + std::cos(angRad)*inPoint.y;
    return outPoint;
}
cv::Point2f rotatePoint(const cv::Point2f& inPoint, const cv::Point2f& center, const double& angRad)
{
    return rotate2d(inPoint - center, angRad) + center;
}

如果你已经有了RotatedRect形式的点,你可以改变它的角度来旋转这些点。

//RotatedRect myRect;
Point2f oldPoints[4];
myRect.points(oldPoints);  //gives existing points of the rectangle.
myRect.angle = 0;          //change the angle.
Point2f newPoints[4];
myRect.points(newPoints);  //gives rotated points of the rectangle.

用原理图扩展razz的答案,给出一个关于旋转角度方向的概念:

/**
 * @brief rotate a point wrt a reference point by a given degree angle on an image
 * @param given_pt a point to be rotated
 * @param ref_pt a reference point wrt which the given_pt will be rotated
 * @param rotation_angle_deg rotation angle in degrees
 * @return rotated point
 *
 * .------------------------------------.
 * |            * -------.          img |
 * |    rotated_pt    -90              |
 * |                                   |
 * |                                   |
 * |            * ---------> *          |
 * |         ref_pt     given_pt        |
 * |                       /            |
 * |                      /             |
 * |    rotated_pt   +90 /              |
 * |            * ------'               |
 * '------------------------------------'
 */
cv::Point rotatePointOnImage(const cv::Point& given_pt, const cv::Point& ref_pt, const double& angle_deg) {
    double    rotation_angle = angle_deg * M_PI / 180.0;
    cv::Point rotated_pt;
    rotated_pt.x = (given_pt.x - ref_pt.x) * cos(rotation_angle) - (given_pt.y - ref_pt.y) * sin(rotation_angle) + ref_pt.x;
    rotated_pt.y = (given_pt.x - ref_pt.x) * sin(rotation_angle) + (given_pt.y - ref_pt.y) * cos(rotation_angle) + ref_pt.y;
    return rotated_pt;
}

我正在寻找图像的任何像素坐标的变换,我几乎找不到通过谷歌搜索它。不知何故,我找到了一个正确工作的python代码链接,这有助于我理解这个问题:https://cristianpb.github.io/blog/image-rotation-opencv

下面是相应的c++代码,如果有人正在寻找它:

// send the original angle and don't transform in radian
    cv::Point2f rotatePointUsingTransformationMat(const cv::Point2f& inPoint, const cv::Point2f& center, const double& rotAngle)
    {
        cv::Mat rot = cv::getRotationMatrix2D(center, rotAngle, 1.0);
        float cos = rot.at<double>(0,0);
        float sin = rot.at<double>(0,1);
        int newWidth = int( ((center.y*2)*sin) +  ((center.x*2)*cos) );
        int newHeight = int( ((center.y*2)*cos) +  ((center.x*2)*sin) );
        rot.at<double>(0,2) += newWidth/2.0 - center.x;
        rot.at<double>(1,2) += newHeight/2.0 - center.y;
        int v[3] = {static_cast<int>(inPoint.x),static_cast<int>(inPoint.y),1};
        int mat3[2][1] = {{0},{0}};
        for(int i=0; i<rot.rows; i++)
        {
            for(int j=0; j<= 0; j++)
            {
                int sum=0;
                for(int k=0; k<3; k++)
                {
                    sum = sum + rot.at<double>(i,k) * v[k];
                }
                mat3[i][j] = sum;
            }
        }
        return Point2f(mat3[0][0],mat3[1][0]);
    }