OpenCV Warperperspective
c++
image
image-processing
opencv
6
0

由于某种原因,每当我使用OpenCV的warpPerspective()函数时,最终的变形图像都不会包含原始图像中的所有内容。图像的左侧部分似乎被切断。我认为发生这种情况的原因是,扭曲图像是在warpPerspective()的画布的最左侧位置创建的。有什么办法可以解决这个问题?谢谢

参考资料:
Stack Overflow
收藏
评论
共 4 个回答
高赞 时间 活跃

秘密分两部分:变换矩阵(单应性)和所得图像大小。

  • 通过使用getPerspectiveTransform()计算正确的变换。从原始图像中获取4个点,计算它们在目标中的正确位置,将它们按相同顺序放入两个向量中,然后使用它们来计算透视变换矩阵。

  • 确保目标图像大小(warpPerspective()的第三个参数)正是您想要的。将其定义为Size(myWidth,myHeight)。

收藏
评论

发生问题是因为单应性将图像的一部分映射到图像区域之外的负x,y值,因此无法绘制。我们希望做的是将变形的输出偏移一定数量的像素,以将整个变形的图像“分流”为正坐标(因此在图像区域内)。

可以使用矩阵乘法来组合同形异义词(这就是它们如此强大的原因)。如果A和B是单应性,则AB表示应首先应用B,然后应用A的单应性。

因此,我们需要做的就是偏移输出,是为平移创建单应性矩阵以一定的偏移量,然后将其乘以原始的单应性矩阵

2D单应矩阵如下所示:

[R11,R12,T1]
[R21,R22,T2]
[ P , P , 1]

其中R代表旋转矩阵,T代表平移,P代表透视变形。因此,一个纯平移单应性看起来像这样:

[ 1 , 0 , x_offset]
[ 0 , 1 , y_offset]
[ 0 , 0 ,    1    ]

因此,只需将您的单应性乘以与上述相似的矩阵,您的输出图像就会被偏移。

(确保使用矩阵乘法,而不是元素明智的乘法!)

收藏
评论

我已经完成了一种方法。

  perspectiveTransform(obj_corners,scene_corners,H);
int maxCols(0),maxRows(0);

 for(int i=0;i<scene_corners.size();i++)
{
   if(maxRows < scene_corners.at(i).y)
        maxRows = scene_corners.at(i).y;
   if(maxCols < scene_corners.at(i).x)
        maxCols = scene_corners.at(i).x;
}

我只是分别找到x点和y点的最大值,然后放在

warpPerspective( tmp, transformedImage, homography, Size( maxCols, maxRows ) );
收藏
评论

试试下面的homography_warp

void homography_warp(const cv::Mat& src, const cv::Mat& H, cv::Mat& dst);

src是源图像。

H是您的应征。

dst是变形的图像。

homography_warp按照https://stackoverflow.com/users/1060066/matt-freeman在他的答案https://stackoverflow.com/a/8229116/15485中所述调整单应性

// Convert a vector of non-homogeneous 2D points to a vector of homogenehous 2D points.
void to_homogeneous(const std::vector< cv::Point2f >& non_homogeneous, std::vector< cv::Point3f >& homogeneous)
{
    homogeneous.resize(non_homogeneous.size());
    for (size_t i = 0; i < non_homogeneous.size(); i++) {
        homogeneous[i].x = non_homogeneous[i].x;
        homogeneous[i].y = non_homogeneous[i].y;
        homogeneous[i].z = 1.0;
    }
}

// Convert a vector of homogeneous 2D points to a vector of non-homogenehous 2D points.
void from_homogeneous(const std::vector< cv::Point3f >& homogeneous, std::vector< cv::Point2f >& non_homogeneous)
{
    non_homogeneous.resize(homogeneous.size());
    for (size_t i = 0; i < non_homogeneous.size(); i++) {
        non_homogeneous[i].x = homogeneous[i].x / homogeneous[i].z;
        non_homogeneous[i].y = homogeneous[i].y / homogeneous[i].z;
    }
}

// Transform a vector of 2D non-homogeneous points via an homography.
std::vector<cv::Point2f> transform_via_homography(const std::vector<cv::Point2f>& points, const cv::Matx33f& homography)
{
    std::vector<cv::Point3f> ph;
    to_homogeneous(points, ph);
    for (size_t i = 0; i < ph.size(); i++) {
        ph[i] = homography*ph[i];
    }
    std::vector<cv::Point2f> r;
    from_homogeneous(ph, r);
    return r;
}

// Find the bounding box of a vector of 2D non-homogeneous points.
cv::Rect_<float> bounding_box(const std::vector<cv::Point2f>& p)
{
    cv::Rect_<float> r;
    float x_min = std::min_element(p.begin(), p.end(), [](const cv::Point2f& lhs, const cv::Point2f& rhs) {return lhs.x < rhs.x; })->x;
    float x_max = std::max_element(p.begin(), p.end(), [](const cv::Point2f& lhs, const cv::Point2f& rhs) {return lhs.x < rhs.x; })->x;
    float y_min = std::min_element(p.begin(), p.end(), [](const cv::Point2f& lhs, const cv::Point2f& rhs) {return lhs.y < rhs.y; })->y;
    float y_max = std::max_element(p.begin(), p.end(), [](const cv::Point2f& lhs, const cv::Point2f& rhs) {return lhs.y < rhs.y; })->y;
    return cv::Rect_<float>(x_min, y_min, x_max - x_min, y_max - y_min);
}

// Warp the image src into the image dst through the homography H.
// The resulting dst image contains the entire warped image, this
// behaviour is the same of Octave's imperspectivewarp (in the 'image'
// package) behaviour when the argument bbox is equal to 'loose'.
// See http://octave.sourceforge.net/image/function/imperspectivewarp.html
void homography_warp(const cv::Mat& src, const cv::Mat& H, cv::Mat& dst)
{
    std::vector< cv::Point2f > corners;
    corners.push_back(cv::Point2f(0, 0));
    corners.push_back(cv::Point2f(src.cols, 0));
    corners.push_back(cv::Point2f(0, src.rows));
    corners.push_back(cv::Point2f(src.cols, src.rows));

    std::vector< cv::Point2f > projected = transform_via_homography(corners, H);
    cv::Rect_<float> bb = bounding_box(projected);

    cv::Mat_<double> translation = (cv::Mat_<double>(3, 3) << 1, 0, -bb.tl().x, 0, 1, -bb.tl().y, 0, 0, 1);

    cv::warpPerspective(src, dst, translation*H, bb.size());
}
收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号