【问题标题】:Image Warping using opencv使用 opencv 进行图像变形
【发布时间】:2017-04-05 09:09:09
【问题描述】:

我想使用 opencv 执行 图像变形。 我已经检测到图像的 4 个角((ex)4000x4000),并在 opencv 中使用getPerspectiveTransform 得到了变换矩阵。 现在,我想在图像中心扭曲图像。 所以我使用了warpPerspective。 我输入的源图像的大小是 450x450,我使用了我为整个图像计算的变换矩阵。

但是屏幕上什么也没有显示。 任何帮助表示赞赏。

这里是示例代码和示例图片。

这是源图像。

检测到此图像

这是我想要的图像变形区域。(代码中的 src_crop)

这是结果。

        source[0] = Point2f(lt.x, lt.y);
        source[1] = Point2f(rt.x, rt.y);
        source[2] = Point2f(rb.x, rb.y);
        source[3] = Point2f(lb.x, lb.y);

        dst[0] = Point2f(6, 10);
        dst[1] = Point2f(3899, 7);
        dst[2] = Point2f(3901, 3899);
        dst[3] = Point2f(9, 3902);

        Mat transformMatrix ;
        transformMatrix = getPerspectiveTransform(source, dst);



        Mat dstFrame ;
        warpPerspective(src_crop, dstFrame, transformMatrix, Size(450, 450));

【问题讨论】:

    标签: opencv image-processing warp


    【解决方案1】:

    您的转换失败,因为您为 getPerspectiveTransform 方法使用了错误的值。您似乎混淆了如何创建输出图像以及如何从该图像的数据中填充目标角。

    此外,链接数组中的右上角(左上、右上、左下、右下)也很重要,你似乎把它弄混了。

    此示例将向您展示如何连接正确的点并将其输出到一个空的输出图像中:

    // Assuming your source image is called 'sourceImage' and you have the corner points you need:
    
    // Create vectors to store the corners
    vector<Point2f> originalCorners;
    vector<Point2f> destinationCorners;
    
    // Put the Sudoku corners in your originalCorners
    originalCorners.clear();
    originalCorners.push_back(Point2f(lt.x, lt.y);
    originalCorners.push_back(Point2f(rt.x, rt.y);
    originalCorners.push_back(Point2f(lb.x, lb.y);
    originalCorners.push_back(Point2f(rb.x, rb.y);
    
    // Output image size of 450x450
    int ouputImageWidth = 450;
    int outputImageHeight = 450;
    
    // Create an empty image (450x450) to output your transformation result in
    Mat transformedOutputImage(ouputImageWidth, outputImageHeight, sourceImage.type());
    
    // Now put the corners of the output image so the warp knows where to warp to
    destinationCorners.clear();
    destinationCorners.push_back(Point2f(0, 0));
    destinationCorners.push_back(Point2f(ouputImageWidth, 0));
    destinationCorners.push_back(Point2f(0, outputImageHeight));
    destinationCorners.push_back(Point2f(ouputImageWidth, outputImageHeight));
    
    // Now we have all corners sorted, so we can create the warp matrix
    Mat warpMatrix = getPerspectiveTransform(originalCorners, destinationCorners);
    
    // And now we can warp the Sudoku in the new image
    warpPerspective(sourceImage, transformedOutputImage, warpMatrix, Size(ouputImageWidth, ouputImageHeight));
    

    现在,这假设您知道要变形的图像部分的角点。如果您不知道如何获得中间正方形的积分,我建议您看看these excellent answers

    但是,只要您有四个角点,此方法就可以工作。您甚至可以通过手动查找中间方形角点并插入这些点来尝试。

    【讨论】:

    • 感谢您的回答。我知道计算整个图像(4000 x 4000)的变换矩阵。但是我将 src_crop(450 x 450) 图像输入 warpPerspective 作为源图像。所以我认为 src_crop 图像也在使用变换矩阵进行变形。是不可能的?如果我不知道 src_crop 图像的角点,我想为 src_crop 图像扭曲图像
    • 您应该只使用sourceImage (4000x4000) 而不是裁剪它。裁剪将导致您的 originalCorners 数组指向不存在的角。我在翘曲之前从未做过压缩,但这可能会导致您的输出完全是黑色的?
    • 实际上我使用裁剪图像是为了减少程序的运行时间。我使用 matchTemplate 函数来检测裁剪图像的中心点。所以我想裁剪图像变形而不是整个图像变形的变形时间很短。
    • 我迭代整个图像的角落以减少整个图像翘曲中心周围的误差。因此我们从整幅图像中得到变换矩阵,并尝试在对裁剪后的图像进行变形后通过模板匹配找到中心点。这样做的原因是中心点误差在中心附近,但是扭曲整个图像需要很长时间。因此,我们尝试在仅围绕中心进行翘曲之后,对整个图像的中心误差较小的角落进行最终翘曲。 WarpPerspective 函数不支持那种方式?
    • 据我所知这是不可能的。你应该做什么:裁剪图像,然后在裁剪图像中检测要变形的角,然后变形。另一种方法是先调整原始图像的大小,然后找到角点,但这可能也很慢(尽管您可以查看是否存在性能差异)。
    猜你喜欢
    • 2017-04-14
    • 2014-08-02
    • 1970-01-01
    • 2011-06-27
    • 2012-03-08
    • 2014-11-30
    • 2016-09-26
    • 2011-02-23
    • 2012-06-29
    相关资源
    最近更新 更多