在 OpenCV 中展开一组矩形以形成正方形网格
Unwarping a set of rectangles to form a square grid in OpenCV
我正在尝试映射包含这些点的图像,使用左上角点和右下角点绘制为矩形,尽管我确实将这些点作为四边形
我正在尝试将带有上面方块的图像映射到下面的方块:
我相信我应该从每个四边形获得透视变换。这是我写的一些代码来尝试促进这一点:
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 透视变换矩阵,将所有这些对应关系包含在一起。具体来说,查看源图像中每个四边形的所有角点,确定它们在变形图像中的映射位置,并定义一个描述所有这些点的透视变换矩阵。这样,当您提供来自源图像的点时,它们应该准确地映射到扭曲中的扭曲点,并且其他所有内容都应该干净地插值。
在实施方面,有两个 vector
容器,其中一个容器包含所有 source 图像点,另一个 vector
容器包含所有warped 图像点。顺序很重要,因此请确保源 vector
容器中的每个位置对应于变形 vector
容器中的相同位置。
但是,您将不得不换档并改用 findHomography
。 findHomography
是 getPerspectiveTransform
的更一般情况,因为您正在确定一个转换矩阵,该矩阵可以最好地将一组点扭曲到另一组点,并且误差最小。 getPerspectiveTransform
只允许您指定 4 个点。 findHomography
允许您指定任意数量的点。
如果您想将其修改为您当前的框架,您已经拥有包含输入和变形图像的每个相应四边形的点向量的向量的代码。您正在访问每个向量并将其指定为 getPerspectiveTransform
以获得每个四边形的透视变换矩阵。只需为输入指定一个向量,为包含所有四边形点的变形图像指定一个向量,然后调用 findHomography
。显然顺序很重要,因此请确保输入图像中四边形的每个位置都与变形图像的输出位置相匹配。
另外,请确保您的坐标系正确无误。 OpenCV 的 Point
结构假定 x
是 水平 坐标,而 y
是 垂直 坐标。由于您已将我建议的编辑放在您的原始 post 中,我将把它们放在此处以确保完整性并使答案独立:
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;
}
我正在尝试映射包含这些点的图像,使用左上角点和右下角点绘制为矩形,尽管我确实将这些点作为四边形
我正在尝试将带有上面方块的图像映射到下面的方块:
我相信我应该从每个四边形获得透视变换。这是我写的一些代码来尝试促进这一点:
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 透视变换矩阵,将所有这些对应关系包含在一起。具体来说,查看源图像中每个四边形的所有角点,确定它们在变形图像中的映射位置,并定义一个描述所有这些点的透视变换矩阵。这样,当您提供来自源图像的点时,它们应该准确地映射到扭曲中的扭曲点,并且其他所有内容都应该干净地插值。
在实施方面,有两个 vector
容器,其中一个容器包含所有 source 图像点,另一个 vector
容器包含所有warped 图像点。顺序很重要,因此请确保源 vector
容器中的每个位置对应于变形 vector
容器中的相同位置。
但是,您将不得不换档并改用 findHomography
。 findHomography
是 getPerspectiveTransform
的更一般情况,因为您正在确定一个转换矩阵,该矩阵可以最好地将一组点扭曲到另一组点,并且误差最小。 getPerspectiveTransform
只允许您指定 4 个点。 findHomography
允许您指定任意数量的点。
如果您想将其修改为您当前的框架,您已经拥有包含输入和变形图像的每个相应四边形的点向量的向量的代码。您正在访问每个向量并将其指定为 getPerspectiveTransform
以获得每个四边形的透视变换矩阵。只需为输入指定一个向量,为包含所有四边形点的变形图像指定一个向量,然后调用 findHomography
。显然顺序很重要,因此请确保输入图像中四边形的每个位置都与变形图像的输出位置相匹配。
另外,请确保您的坐标系正确无误。 OpenCV 的 Point
结构假定 x
是 水平 坐标,而 y
是 垂直 坐标。由于您已将我建议的编辑放在您的原始 post 中,我将把它们放在此处以确保完整性并使答案独立:
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;
}