【问题标题】:Rotating back points from a rotated image in OpenCV从OpenCV中的旋转图像旋转回点
【发布时间】:2011-10-15 10:51:17
【问题描述】:

我遇到了轮换问题。 我想做的是这样的:

  • 旋转图像
  • 检测旋转图像上的特征(点)
  • 向后旋转点,这样我就可以得到与初始图像相对应的点坐标

我在第三步有点卡住了。

我设法使用以下代码旋转了图像:

cv::Mat M(2, 3, CV_32FC1);
cv::Point2f center((float)dst_img.rows / 2.0f, (float)dst_img.cols / 2.0f);
M = cv::getRotationMatrix2D(center, rotateAngle, 1.0);
cv::warpAffine(dst_img, rotated, M, cv::Size(rotated.cols, rotated.rows));

我尝试使用以下代码旋转点:

float xp = r.x * std::cos( PI * (-rotateAngle) / 180 ) - r.y * sin(PI * (rotateAngle) / 180);
float yp = r.x * sin(PI * (-rotateAngle) / 180) + r.y * cos(PI * (rotateAngle) / 180);

工作不正常,但图像上的点不能很好地恢复。有一个偏移量。

感谢您的帮助

【问题讨论】:

  • 为什么不尝试使用 -rotate angle、getRotationMatrix() 和 warp affine 来旋转矩阵...
  • 为什么不对旋转矩阵使用逆矩阵呢?三角函数对我来说听起来很脆弱。
  • 是的,但是如何找回旋转矩阵中的点?

标签: c++ opencv matrix rotation


【解决方案1】:
  • 您需要根据图像的中心点旋转点。
  • 这里 x 和 y 是您要旋转的点,imageCenter_x a 和 _y 是图像的中心点。
  • 下面是我的代码。

    angle = angle * (M_PI / 180);  
    float axis_x = x - imageCenter_x;  
    float axis_y = y - imageCenter_y;       
    
    x = axis_x * cos(angle) + axis_y * sin(angle);   
    y = (-axis_x) * sin(angle) + axis_y * cos(angle);
    
    x = x + imageCenter_x;  
    y = y + imageCenter_y;
    

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。

    对于旋转图像中的变换M 和点pp,我们希望在原始图像的坐标中找到点pp_org。使用以下行:

    cv::Mat_<double> iM;
    cv::invertAffineTransform(M, iM);
    cv::Point2f pp_org = iM*pp;
    

    上面一行中的操作符*定义为:

    cv::Point2f operator*(cv::Mat_<double> M, const cv::Point2f& p)
    { 
        cv::Mat_<double> src(3/*rows*/,1 /* cols */); 
    
        src(0,0)=p.x; 
        src(1,0)=p.y; 
        src(2,0)=1.0; 
    
        cv::Mat_<double> dst = M*src; //USE MATRIX ALGEBRA 
        return cv::Point2f(dst(0,0),dst(1,0)); 
    } 
    

    注意:M是你用来从原始图像到旋转图像的旋转矩阵

    【讨论】:

      【解决方案3】:

      如果M 是您从cv::getRotationMatrix2D 获得的旋转矩阵,则要使用此矩阵旋转cv::Point p,您可以这样做:

      cv::Point result;
      result.x = M.at<double>(0,0)*p.x + M.at<double>(0,1)*p.y + M.at<double>(0,2);
      result.y = M.at<double>(1,0)*p.x + M.at<double>(1,1)*p.y + M.at<double>(1,2);
      

      如果要旋转一个点,生成M的逆矩阵或者使用cv::getRotationMatrix2D(center, -rotateAngle, scale)生成逆旋转矩阵。

      【讨论】:

        【解决方案4】:

        对于一个旋转矩阵,它的转置是它的逆矩阵。因此,您只需执行M.t() * r 将其移回原始帧,其中rcv::Mat(您可能必须将其从cv::Point2f 或其他任何内容转换为cv::Mat,或者只是写出矩阵乘法)。

        这是明确执行此操作的代码(应该是正确的,但警告,它完全未经测试):

        cv::Point2f p;
        p.x = M.at<float>(0, 0) * r.x + M.at<float>(1, 0) * r.y;
        p.y = M.at<float>(0, 1) * r.x + M.at<float>(1, 1) * r.y;
        // p contains r rotated back to the original frame.
        

        【讨论】:

        • 我想使用您的代码明确地进行矩阵乘法,但我在元素访问时遇到断言错误。 codeOpenCV 错误:断言失败 (dims ::channels) > ((DataType<_tp>::depth) & ((1 code
        • 你的公式错过了来自 M 的翻译
        猜你喜欢
        • 1970-01-01
        • 2020-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多