【问题标题】:Unwarping a set of rectangles to form a square grid in OpenCV在 OpenCV 中展开一组矩形以形成正方形网格
【发布时间】:2015-04-01 07:32:19
【问题描述】:

我正在尝试映射包含这些点的图像,使用左上角和右下角绘制为矩形,尽管我确实将这些点作为四边形

我正在尝试将带有上述正方形的图像映射到下面的正方形:

我相信我应该从每个四边形获得透视变换。这是我编写的一些代码来尝试和促进这一点:

cv::Mat output = cv::Mat::zeros(outputSize,CV_32F);


    // Uses the size of the quadOutput to
    std::vector<std::vector<cv::Point2f>> quadOutputImage = quadralateralsFromImageOutput(imageToWarp.size().height);

    cv::Mat perspectiveMatrix = cv::Mat(3,3,CV_32F);

    cv::Mat warp = cv::Mat::zeros(outputSize,CV_32F);

    for (int i = 0; i < quadOutputImage.size(); i ++) {

            // get the mapping from the quadtriangles
            perspectiveMatrix = cv::getPerspectiveTransform(quadCentroids[i],quadOutputImage[i]);

            // perform the warp with the current quadtriangles
            cv::warpPerspective(imageToWarp,warp,perspectiveMatrix,output.size());

            // copy roi to output

    }

    return warp;

我逐个四边形地做这个,图像似乎根本不正确。好像有点歪。

编辑

我也尝试找到单应矩阵,但结果很奇怪。这是我写的代码

    cv::Mat warpedImageGeneration(const cv::Mat& imageToWarp,cv::Size outputSize, std::vector<std::vector<cv::Point2f>> quadCentroids) {        

    // Uses the size of the quadOutput 50 by 50 squares
    std::vector<std::vector<cv::Point2f>> quadOutputImage = quadralateralsFromImageOutput(450);

    // flatten the matrices
    std::vector<cv::Point2f> flattenedQuads = flattenMatrix(quadOutputImage);
    std::vector<cv::Point2f> flattenedCentroids = flattenMatrix(quadCentroids);

    cv::Mat perspectiveMatrix = cv::Mat(3,3,CV_32F);

    cv::Mat warp = cv::Mat::zeros(450,450,CV_32F);

    perspectiveMatrix = cv::findHomography(flattenedCentroids, flattenedQuads);

    cv::warpPerspective(imageToWarp, warp, perspectiveMatrix, warp.size());

    return warp;
 }

在示例图像上,这是我得到的未变形结果:

我认为问题可能是源的顶点不符合四边形顺序,即左上角、右上角、左下角和右下角。

【问题讨论】:

  • 如果您知道每个四边形从原始图像映射到扭曲后的确切坐标,请尝试定义包含所有这些对应关系的 一个 透视变换矩阵。具体来说,查看源图像中每个四边形的所有角点,确定它们应该在扭曲图像中映射的位置,并定义一个描述所有这些点的透视变换矩阵。这样,当您提供源图像中的点时,它们应该精确地映射到扭曲中的扭曲点,并且其他所有内容都应该干净地插值。
  • 如何从一张图像的所有四边形中获得一个透视变换矩阵?
  • 简单。您已经有代码,其中包含输入和扭曲图像的每个相应四边形的点向量的向量。您正在访问每个向量并将其指定为 getPerspectiveTransform 以获得每个四边形的透视变换矩阵。只需为输入指定 one 向量,为包含 所有 个四边形点的扭曲图像指定 one 向量,然后制作一个 单个呼叫getPerspectiveTransform。显然顺序很重要,因此请确保输入图像中四边形的每个位置都与变形图像的输出位置相匹配。
  • 哦,我不做我正在做的那个循环,而是把我所有的点都按顺序用于两个向量,然后把它塞进 2 个单个向量中,然后运行我不知道的 getPerspectiveTransform你可以这样做,我试试看!
  • 糟糕。看来我说得太早了。如果你想像我指定的那样做,getPerspectiveTransform 不会像预期的那样工作 4 分 - 我认为它确实如此。您想要其他可以处理> 4分的东西。代替getPerspectiveTransform,使用findHomography: docs.opencv.org/modules/calib3d/doc/…。它基本上接受与getPerspectiveTransform 相同的输入。 findHomography 确定将一组点从一幅图像映射到另一幅图像的最佳变换矩阵,并且误差量最小。

标签: c++ opencv image-processing computer-vision


【解决方案1】:

单独扭曲每个矩形不会通过getPerspectiveTransform 为您提供最佳结果。相反,如果您知道每个四边形从原始图像映射到扭曲后的确切坐标,请尝试定义包含所有这些对应关系的 一个 透视变换矩阵。具体来说,查看源图像中每个四边形的所有角点,确定它们应该在扭曲图像中映射的位置,并定义一个描述所有这些点的透视变换矩阵。这样,当您提供源图像中的点时,它们应该准确地映射到扭曲中的扭曲点,并且其他所有内容都应该干净地插值。

在实现方面,有两个vector 容器,其中一个容器包含所有 图像点,另一个vector 容器包含所有扭曲图像点。顺序很重要,因此请确保源 vector 容器中的每个位置都对应于扭曲的 vector 容器上的相同位置。

但是,您将不得不换档并改用findHomographyfindHomographygetPerspectiveTransform 的更一般情况,因为您正在确定一个转换矩阵,该矩阵最好地将一组点扭曲到另一组点,并且误差最少。 getPerspectiveTransform 只允许您指定 4 个点。 findHomography 允许您指定任意数量的点。

如果您想将其修改为您当前的框架,您已经拥有包含输入和扭曲图像的每个相应四边形的点向量的向量的代码。您正在访问每个向量并将其指定为 getPerspectiveTransform 以获得每个四边形的透视变换矩阵。只需为输入指定一个向量,为包含所有四边形点的扭曲图像指定一个向量,然后调用findHomography。显然,顺序很重要,因此请确保输入图像中四边形的每个位置都与扭曲图像的输出位置相匹配。

另外,请确保您的坐标系正确。 OpenCV 的Point 结构假定x水平 坐标,而y垂直 坐标。由于您已将我在原始帖子中建议的编辑进行了放置,因此为了完整起见,我将把它们放在这里并使答案自成一体:

 cv::Mat warpedImageGeneration(const cv::Mat& imageToWarp,cv::Size outputSize, std::vector<std::vector<cv::Point2f>> quadCentroids) {

    // Uses the size of the quadOutput 50 by 50 squares
    std::vector<std::vector<cv::Point2f>> quadOutputImage = quadralateralsFromImageOutput(450);

    // flatten the matrices
    std::vector<cv::Point2f> flattenedQuads = flattenMatrix(quadOutputImage);
    std::vector<cv::Point2f> flattenedCentroids = flattenMatrix(quadCentroids);

    cv::Mat perspectiveMatrix = cv::Mat(3,3,CV_32F);

    cv::Mat warp = cv::Mat::zeros(450,450,CV_32F);

    perspectiveMatrix = cv::findHomography(flattenedCentroids, flattenedQuads);

    cv::warpPerspective(imageToWarp, warp, perspectiveMatrix, warp.size());

    return warp;
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    相关资源
    最近更新 更多