【问题标题】:OpenCV. How do I multiply point and matrix (CvMat)开放式简历。如何将点和矩阵相乘(CvMat)
【发布时间】:2015-03-14 21:29:59
【问题描述】:

我有一个用于旋转的矩阵:

CvMat* rot_mat = cvCreateMat(2, 3, CV_32FC1);
cv2DRotationMatrix(center, angle, scale, rot_mat);
...

这个矩阵用于图像操作。

cvWarpAffine(..., ..., rot_mat, ..., ...);

我必须知道,这个矩阵应该如何影响确切的像素 - 它应该被转移的位置。

如何将 2D 点(像素位置)与我的矩阵相乘以找出像素应该转移到哪里?

【问题讨论】:

标签: c opencv


【解决方案1】:

我为此实现了一些愚蠢的代码。我想应该有更复杂的解决方案:

CvMat* rot_mat; 
CvPoint* p;

...

float* data = (float*)(rot_mat->data.ptr);  
float newX = data[0] * p->x + data[1] * p->y + data[2]; 
float newY = data[3] * p->x + data[4] * p->y + data[5]; 

【讨论】:

  • 每次编译器找不到正确的转换时都不需要重新发明轮子
【解决方案2】:

我在forum 中找到了答案。万一链接失败,这里的解决方案是:

cv::Point2f operator*(cv::Mat 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)); 
} 

【讨论】:

    【解决方案3】:

    如果您已经将信息存储在 cv::Point 元素中,则可以使用 cv::Mat 构造函数将该信息转换为无需内存复制的矩阵,例如

    cv::Mat V = cv::Mat(v, false); // false to avoid memory copy
    

    使用'V'的操作后你可以回到原来的结构像

     V.copyTo( cv::Mat(p, false) );
    

    您可以使用相同的构造函数解析它们的单个点或列表(std::vector)。这个示例代码可以更好地展示这个想法:

    #include <iostream>
    #include <opencv2/core/core.hpp>
    
    int main( )
    {
        std::vector< cv::Point2f > v(3);
        v[0] = cv::Point2f(1, 1);
        v[1] = cv::Point2f(2, 2);
        v[2] = cv::Point2f(3, 3);
    
        cv::Mat V = cv::Mat(v, false); // false to avoid memory copy
    
        std::vector< cv::Point2f > p(3);
        V.copyTo( cv::Mat(p, false) );
    
        for (int i = 0; i < 3; ++i) {
            std::cout << p[i] << std::endl;
        }
    
        return 0;
    }
    

    【讨论】:

      【解决方案4】:
      1. 对于 3D 点
      std::vector<cv::Point3d> transform_3d_points(std::vector<cv::Point3d> points3d, cv::Mat transformation_matrix){
        std::vector<cv::Point3d> transformed_points3d;
        cv::perspectiveTransform(points3d, transformed_points3d, transformation_matrix);
        return transformed_points3d;
      }
      
      1. 对于二维点
      std::vector<cv::Point2d> transform_2d_points(std::vector<cv::Point2d> points2d, cv::Mat transformation_matrix){
        std::vector<cv::Point2d> transformed_points2d;
        cv::perspectiveTransform(points2d, transformed_points2d, transformation_matrix);
        return transformed_points2d;
      }
      

      对于 3d 点,变换矩阵应该是 4*4 齐次的。 例如

      cv::Mat transformation_matrix = (cv::Mat_<double>(4, 4) << 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
      std::vector<cv::Points3d> points3d = { cv::Points3d(0,0,0),  cv::Points3d(1,1,1) }
      

      对于 2d 点,变换矩阵应该是 3*3 齐次的。 例如

      cv::Mat transformation_matrix = (cv::Mat_<double>(3, 3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);
      std::vector<cv::Points2d> points2d = { cv::Points2d(0,0),  cv::Points3d(1,1) }
      

      【讨论】:

        猜你喜欢
        • 2012-05-25
        • 2022-06-30
        • 1970-01-01
        • 2019-10-13
        • 1970-01-01
        • 1970-01-01
        • 2015-01-24
        • 2016-12-11
        相关资源
        最近更新 更多