打开简历。如何将点和矩阵相乘 (CvMat)

OpenCV. How do I multiply point and matrix (CvMat)

我有用于旋转的矩阵:

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

这个矩阵用于图像运算。

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

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

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

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

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]; 

我在这个 forum 中找到了答案。以防万一 link 在这里失败是解决方案:

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)); 
} 

如果您已经将信息存储在 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;
}
  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) }