OpenCV warpperspective

后端 未结 9 2355
孤城傲影
孤城傲影 2020-12-01 05:45

For some reason whenever I use OpenCV\'s warpPerspective() function, the final warped image does not contain everything in the original image. The left part of the image see

9条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-01 06:28

    Try the below homography_warp.

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

    src is the source image.

    H is your homography.

    dst is the warped image.

    homography_warp adjust your homography as described by https://stackoverflow.com/users/1060066/matt-freeman in his answer 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 transform_via_homography(const std::vector& points, const cv::Matx33f& homography)
    {
        std::vector ph;
        to_homogeneous(points, ph);
        for (size_t i = 0; i < ph.size(); i++) {
            ph[i] = homography*ph[i];
        }
        std::vector r;
        from_homogeneous(ph, r);
        return r;
    }
    
    // Find the bounding box of a vector of 2D non-homogeneous points.
    cv::Rect_ bounding_box(const std::vector& p)
    {
        cv::Rect_ 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_(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_ bb = bounding_box(projected);
    
        cv::Mat_ translation = (cv::Mat_(3, 3) << 1, 0, -bb.tl().x, 0, 1, -bb.tl().y, 0, 0, 1);
    
        cv::warpPerspective(src, dst, translation*H, bb.size());
    }
    

提交回复
热议问题