Executing cv::warpPerspective for a fake deskewing on a set of cv::Point

Я пытаюсь сделать перспективное преобразование набора точек для достижения эффекта выравнивания:

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

Я использую изображение ниже для тестов, и зеленый прямоугольник отображает область интереса.

Мне интересно, можно ли добиться эффекта, на который я рассчитываю, используя простую комбинацию cv::getPerspectiveTransform и cv::warpPerspective. Я делюсь исходным кодом, который я написал на данный момент, но он не работает. Вот полученное изображение:

Итак, есть вектор<:point>, который определяет область интереса, но точки не хранятся в определенном порядке внутри вектора, и это то, что я не могу изменить в процедуре обнаружения. В любом случае, позже, точки в векторе используются для определения RotatedRect, который в свою очередь используется для сборки cv::Point2f src_vertices[4];, одной из переменных, требуемых cv::getPerspectiveTransform().

Мое понимание о вершинах и о том, как они организованыможет быть одной из проблем. Я также думаю, что использование RotatedRect - не лучшая идея для хранения исходных точек ROI, поскольку координаты немного изменятся, чтобы вписаться в повернутый прямоугольник, а это не очень здорово.

#include 
#include 
#include 

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 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;
}

Может кто-нибудь помочь мне решить эту проблему?

57
задан karlphillip 19 December 2014 в 15:09
поделиться