gpt4 book ai didi

c++ - 执行 cv::warpPerspective 以在一组 cv::Point 上进行假偏斜

转载 作者:IT老高 更新时间:2023-10-28 13:24:21 25 4
gpt4 key购买 nike

我正在尝试做一个 perspective transformation一组点以实现deskewing效果:

http://nuigroup.com/?ACT=28&fid=27&aid=1892_H6eNAaign4Mrnn30Au8d

我正在使用下图进行测试,绿色矩形显示感兴趣的区域。

我想知道使用 cv::getPerspectiveTransform 的简单组合是否有可能达到我希望的效果和 cv::warpPerspective .我正在分享到目前为止我编写的源代码,但它不起作用。这是生成的图像:

所以有一个 vector<cv::Point>定义了感兴趣的区域,但是这些点没有以任何特定的顺序存储在 vector 内,这是我在检测过程中无法改变的。无论如何,稍后, vector 中的点用于定义 RotatedRect ,而后者又用于组装 cv::Point2f src_vertices[4];cv::getPerspectiveTransform() 所需的变量之一.

我对顶点及其组织方式的理解可能是问题之一。我也认为使用 RotatedRect存储 ROI 的原始点并不是最好的主意,因为坐标会发生一些变化以适应旋转的矩形,并且 这不是很酷强>。

#include <cv.h>
#include <highgui.h>
#include <iostream>

using namespace std;
using namespace cv;

int main(int argc, char* argv[])
{
cv::Mat src = cv::imread(argv[1], 1);

// After some magical procedure, these are points detect that represent
// the corners of the paper in the picture:
// [408, 69] [72, 2186] [1584, 2426] [1912, 291]
vector<Point> not_a_rect_shape;
not_a_rect_shape.push_back(Point(408, 69));
not_a_rect_shape.push_back(Point(72, 2186));
not_a_rect_shape.push_back(Point(1584, 2426));
not_a_rect_shape.push_back(Point(1912, 291));

// For debugging purposes, draw green lines connecting those points
// and save it on disk
const Point* point = &not_a_rect_shape[0];
int n = (int)not_a_rect_shape.size();
Mat draw = src.clone();
polylines(draw, &point, &n, 1, true, Scalar(0, 255, 0), 3, CV_AA);
imwrite("draw.jpg", draw);

// Assemble a rotated rectangle out of that info
RotatedRect box = minAreaRect(cv::Mat(not_a_rect_shape));
std::cout << "Rotated box set to (" << box.boundingRect().x << "," << box.boundingRect().y << ") " << box.size.width << "x" << box.size.height << std::endl;

// Does the order of the points matter? I assume they do NOT.
// But if it does, is there an easy way to identify and order
// them as topLeft, topRight, bottomRight, bottomLeft?
cv::Point2f src_vertices[4];
src_vertices[0] = not_a_rect_shape[0];
src_vertices[1] = not_a_rect_shape[1];
src_vertices[2] = not_a_rect_shape[2];
src_vertices[3] = not_a_rect_shape[3];

Point2f dst_vertices[4];
dst_vertices[0] = Point(0, 0);
dst_vertices[1] = Point(0, box.boundingRect().width-1);
dst_vertices[2] = Point(0, box.boundingRect().height-1);
dst_vertices[3] = Point(box.boundingRect().width-1, box.boundingRect().height-1);

Mat warpMatrix = getPerspectiveTransform(src_vertices, dst_vertices);

cv::Mat rotated;
warpPerspective(src, rotated, warpMatrix, rotated.size(), INTER_LINEAR, BORDER_CONSTANT);

imwrite("rotated.jpg", rotated);

return 0;
}

谁能帮我解决这个问题?

最佳答案

所以,第一个问题是角顺序。它们在两个 vector 中的顺序必须相同。因此,如果在第一个 vector 中您的顺序是:(top-left, bottom-left, bottom-right, top-right) ,它们在另一个 vector 中的顺序必须相同。

其次,要使生成的图像仅包含感兴趣的对象,您必须将其宽度和高度设置为与生成的矩形宽度和高度相同。不用担心,warpPerspective 中的 src 和 dst 图像大小可以不同。

第三,性能问题。虽然您的方法绝对准确,因为您只进行仿射变换(旋转、调整大小、歪斜),但在数学上,您可以使用函数的仿射对应对象。它们更快

  • getAffineTransform()

  • warpAffine().

重要提示:getAffine 变换只需要和期望 3 个点,结果矩阵是 2×3,而不是 3×3。

如何使结果图像具有与输入不同的大小:

cv::warpPerspective(src, dst, dst.size(), ... );

使用

cv::Mat rotated;
cv::Size size(box.boundingRect().width, box.boundingRect().height);
cv::warpPerspective(src, dst, size, ... );

你到了,你的编程任务已经结束了。

void main()
{
cv::Mat src = cv::imread("r8fmh.jpg", 1);


// After some magical procedure, these are points detect that represent
// the corners of the paper in the picture:
// [408, 69] [72, 2186] [1584, 2426] [1912, 291]

vector<Point> not_a_rect_shape;
not_a_rect_shape.push_back(Point(408, 69));
not_a_rect_shape.push_back(Point(72, 2186));
not_a_rect_shape.push_back(Point(1584, 2426));
not_a_rect_shape.push_back(Point(1912, 291));

// For debugging purposes, draw green lines connecting those points
// and save it on disk
const Point* point = &not_a_rect_shape[0];
int n = (int)not_a_rect_shape.size();
Mat draw = src.clone();
polylines(draw, &point, &n, 1, true, Scalar(0, 255, 0), 3, CV_AA);
imwrite("draw.jpg", draw);

// Assemble a rotated rectangle out of that info
RotatedRect box = minAreaRect(cv::Mat(not_a_rect_shape));
std::cout << "Rotated box set to (" << box.boundingRect().x << "," << box.boundingRect().y << ") " << box.size.width << "x" << box.size.height << std::endl;

Point2f pts[4];

box.points(pts);

// Does the order of the points matter? I assume they do NOT.
// But if it does, is there an easy way to identify and order
// them as topLeft, topRight, bottomRight, bottomLeft?

cv::Point2f src_vertices[3];
src_vertices[0] = pts[0];
src_vertices[1] = pts[1];
src_vertices[2] = pts[3];
//src_vertices[3] = not_a_rect_shape[3];

Point2f dst_vertices[3];
dst_vertices[0] = Point(0, 0);
dst_vertices[1] = Point(box.boundingRect().width-1, 0);
dst_vertices[2] = Point(0, box.boundingRect().height-1);

/* Mat warpMatrix = getPerspectiveTransform(src_vertices, dst_vertices);

cv::Mat rotated;
cv::Size size(box.boundingRect().width, box.boundingRect().height);
warpPerspective(src, rotated, warpMatrix, size, INTER_LINEAR, BORDER_CONSTANT);*/
Mat warpAffineMatrix = getAffineTransform(src_vertices, dst_vertices);

cv::Mat rotated;
cv::Size size(box.boundingRect().width, box.boundingRect().height);
warpAffine(src, rotated, warpAffineMatrix, size, INTER_LINEAR, BORDER_CONSTANT);

imwrite("rotated.jpg", rotated);
}

关于c++ - 执行 cv::warpPerspective 以在一组 cv::Point 上进行假偏斜,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7838487/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com