Я пытаюсь сделать перспективное преобразование набора точек, чтобы достичь deskewing эффект:
http://nuigroup.com/?ACT=28&fid=27&aid=1892_H6eNAaign4Mrnn30Au8d
Я использую изображение ниже для тестов, а прямоугольник зеленый отображает интересующую область.
Мне было интересно, можно ли добиться эффекта, который я намереваюсь использовать с помощью простой комбинации cv::getPerspectiveTransform
и cv::warpPerspective
. Я использую исходный код, который я написал до сих пор, но он не работает. Это результирующее изображение:
Итак, существует vector<cv::Point>
, что определяет интересующую область, но точки не сохраняются в каком-либо конкретном порядке внутри вектора и что я могу Изменение процедуры обнаружения. Во всяком случае, позже, точки в векторе используются для определения a 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 = ¬_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;
}
Может кто-нибудь помочь мне решить эту проблему?