Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 计算给定两组点的相似变换矩阵?_C++_Opencv_Graphics_Transformation - Fatal编程技术网

C++ 计算给定两组点的相似变换矩阵?

C++ 计算给定两组点的相似变换矩阵?,c++,opencv,graphics,transformation,C++,Opencv,Graphics,Transformation,我知道在OpenCV中,我们可以得到给定两组点的仿射变换 但仅支持预先计算的角度和比例 如何计算给定两组点的相似性变换矩阵?有。可以选择具有6个自由度(旋转、平移、缩放、剪切)的完全仿射变换或具有5个自由度的部分仿射变换(旋转、平移、均匀缩放) 您可以使用以下代码通过两个向量p1和p2计算相似性变换: cv::Mat R=cv::EstimaterialgidTransform(p1,p2,false); //扩展刚性变换以使用透视变换: cv::Mat H=cv::Mat(3,3,R.type

我知道在OpenCV中,我们可以得到给定两组点的仿射变换

但仅支持预先计算的角度和比例

如何计算给定两组点的相似性变换矩阵?

有。可以选择具有6个自由度(旋转、平移、缩放、剪切)的完全仿射变换或具有5个自由度的部分仿射变换(旋转、平移、均匀缩放)

您可以使用以下代码通过两个
向量
p1和p2计算相似性变换:

cv::Mat R=cv::EstimaterialgidTransform(p1,p2,false);
//扩展刚性变换以使用透视变换:
cv::Mat H=cv::Mat(3,3,R.type());
H.at(0,0)=R.at(0,0);
H.at(0,1)=R.at(0,1);
H.at(0,2)=R.at(0,2);
H.at(1,0)=R.at(1,0);
H.at(1,1)=R.at(1,1);
H.at(1,2)=R.at(1,2);
H.at(2,0)=0.0;
H.at(2,1)=0.0;
H.at(2,2)=1.0;
//在p1上计算透视变换
std::向量结果;
cv::透视变换(p1,结果,H)
//带变换的扭曲图像
cv::毡翘曲;
warpPerspective(src,warped,H,src.size());

我没有尝试过,但参考答案,它应该可以正常工作。

在我使用的opencv版本中,使用
cv::EstimaterialGidTransform
时出现了一些问题,因此我编写了一个只适用于两点的函数(这对我来说足够了,我相信它会更快)

cv::Mat getSimilarityTransform(常量cv::Point2f src[],常量cv::Point2f dst[])
{
双src_d_y=src[0].y-src[1].y;
双src_d_x=src[0].x-src[1].x;
双src_dis=sqrt(pow(src_d_y,2)+pow(src_d_x,2));
双dst_d_y=dst[0].y-dst[1].y;
双dst_d_x=dst[0].x-dst[1].x;
双dst_dis=sqrt(功率(dst_d_y,2)+功率(dst_d_x,2));
双刻度=dst_dis/src_dis;
//两条线段之间的角度
//参考:http://stackoverflow.com/questions/3365171/calculating-the-angle-between-two-lines-without-having-to-calculate-the-slope
双角度=atan2(src_d_y,src_d_x)-atan2(dst_d_y,dst_d_x);
双alpha=cos(角度)*刻度;
双贝塔=正弦(角度)*刻度;
cv::Mat M(2,3,cv_64F);
double*m=m.ptr();
m[0]=α;
m[1]=β;
//tx=x'-α*x-β*y
//平均两分
m[2]=(dst[0].x-alpha*src[0].x-beta*src[0].y+dst[1].x-alpha*src[1].x-beta*src[1].y)/2;
m[3]=-beta;
m[4]=α;
//ty=y'+β*x-α*y
//平均两分
m[5]=(dst[0].y+beta*src[0].x-alpha*src[0].y+dst[1].y+beta*src[1].x-alpha*src[1].y)/2;
返回M;
}
一些结果(来自LFW数据集的图片)

有点自相矛盾,他们选择称之为刚性,而6和4自由度变换恰恰不是刚性的。非常感谢您的回答,为什么它有5个自由度而不是4个自由度?据我所知,只有4个参数,我对此感到困惑。我知道理论上有第五个参数e表示方向。但有一种说法称之为刚性,所以e应该等于1(保留原点)。
cv::Mat R = cv::estimateRigidTransform(p1,p2,false);

// extend rigid transformation to use perspectiveTransform:
cv::Mat H = cv::Mat(3,3,R.type());
H.at<double>(0,0) = R.at<double>(0,0);
H.at<double>(0,1) = R.at<double>(0,1);
H.at<double>(0,2) = R.at<double>(0,2);

H.at<double>(1,0) = R.at<double>(1,0);
H.at<double>(1,1) = R.at<double>(1,1);
H.at<double>(1,2) = R.at<double>(1,2);

H.at<double>(2,0) = 0.0;
H.at<double>(2,1) = 0.0;
H.at<double>(2,2) = 1.0;

// compute perspectiveTransform on p1
std::vector<cv::Point2f> result;
cv::perspectiveTransform(p1,result,H)

//warp image with transform
cv::Mat warped;
cv::warpPerspective(src,warped,H,src.size());
cv::Mat getSimilarityTransform(const cv::Point2f src[], const cv::Point2f dst[])
{
    double src_d_y = src[0].y - src[1].y;
    double src_d_x = src[0].x - src[1].x;
    double src_dis = sqrt(pow(src_d_y, 2) + pow(src_d_x, 2));

    double dst_d_y = dst[0].y - dst[1].y;
    double dst_d_x = dst[0].x - dst[1].x;
    double dst_dis = sqrt(pow(dst_d_y, 2) + pow(dst_d_x, 2));

    double scale = dst_dis / src_dis;
    // angle between two line segments
    // ref: http://stackoverflow.com/questions/3365171/calculating-the-angle-between-two-lines-without-having-to-calculate-the-slope
    double angle = atan2(src_d_y, src_d_x) - atan2(dst_d_y, dst_d_x);

    double alpha = cos(angle)*scale;
    double beta = sin(angle)*scale;

    cv::Mat M(2, 3, CV_64F);
    double* m = M.ptr<double>();

    m[0] = alpha;
    m[1] = beta;
    // tx = x' -alpha*x  -beta*y
    // average of two points
    m[2] = (dst[0].x - alpha*src[0].x - beta*src[0].y + dst[1].x - alpha*src[1].x - beta*src[1].y)/2;
    m[3] = -beta;
    m[4] = alpha;
    // ty = y' +beta*x  -alpha*y
    // average of two points
    m[5] = (dst[0].y + beta*src[0].x - alpha*src[0].y + dst[1].y + beta*src[1].x - alpha*src[1].y)/2;

    return M;
}