Итак, первая проблема - это угловой порядок. Они должны быть в одинаковом порядке в обоих векторах.
Итак, если в первом векторе ваш порядок: (вверху слева, внизу слева, внизу справа, вверху справа), они ДОЛЖНЫ быть в том же порядке в другом векторе.
Во-вторых, чтобы полученное изображение содержало только интересующий объект, вы должны установить его ширину и высоту, равные ширине и высоте получаемого прямоугольника. Не беспокойтесь, изображения src и dst в warpPerspective могут быть разных размеров.
В-третьих, проблема производительности. Хотя ваш метод абсолютно точен, поскольку вы выполняете только аффинные преобразования (вращение, изменение размера, выравнивание), математически вы можете использовать аффинный основной компонент ваших функций. Они намного быстрее .
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 = ¬_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);
}