cv :: warpPerspective показывает только часть искаженного изображения

Я изменяю изображение с передней точки зрения на вид со ставками с помощью getHomography и warpPerspective.

Это работает в том, что изображение деформируется в желаемую перспективу, но кадрирование отключено. Он перемещает деформированное изображение в основном за пределы рамки изображения. Я предполагаю, что причина в том, что операция приводит к отрицательным координатам.

Я рассчитал баллы для расчета матрицы перевода вручную, а не с помощью какой-либо функции opencv: s, чтобы сделать это, т. Е. Функции шахматной доски не смогли определить правильные точки.

Я думаю, это можно исправить, внеся дополнительные изменения в матрицу преобразования. Но как это сделать? Кроме того, есть ли способ убедиться, что преобразованное изображение центрировано вдоль оси X, а затем позволить оси Y отрегулировать желаемое положение?

Фрагмент кода, который делает работу сейчас:

cv::Mat image; // image is loaded with the original image

cv::Mat warpPers; // The container for the resulting image
cv::Mat H;

std::vector<cv::Point2f> src;
std::vector<cv::Point2f> dst;

// In reality several more points.
src.push_back(cv::Point2f(264,301));
src.push_back(cv::Point2f(434,301));
src.push_back(cv::Point2f(243,356));
src.push_back(cv::Point2f(476,356));

dst.push_back(cv::Point2f(243,123));
dst.push_back(cv::Point2f(476,123));
dst.push_back(cv::Point2f(243,356));
dst.push_back(cv::Point2f(476,356));

H = cv::findHomography(src, dst, CV_RANSAC);

cv::warpPerspective(image,
newPers,
H,
cv::Size(3000,3000),
cv::INTER_NEAREST | CV_WARP_FILL_OUTLIERS
);

cv::namedWindow("Warped persp", cv::WINDOW_AUTOSIZE );
cv::imshow( "Warped persp", newPers);

3

Решение

Opencv предоставляет очень удобный способ сделать соответствующее преобразование. Единственное, что вам нужно сделать, — это позаботиться о возвращении гомографии с помощью findHomography.
Действительно, возможно, некоторые точки изображения, которые вы предоставляете, идут в отрицательной части оси x или y.
Таким образом, вы должны сделать некоторую проверку, прежде чем деформировать изображение.

Шаг 1: найти гомографию H с помощью findHomography
вы получите классическую структуру для гомографии

H = [ h00, h01, h02;
h10, h11, h12;
h20, h21,   1];

шаг 2: поиск положения углов изображения после деформации

Итак, позвольте мне определить порядок для угла:

(0,0) ________ (0, w)
|        |
|________|
(h,0)          (h,w)

Для этого просто создайте такую ​​матрицу:

P = [0, w, w, 0;
0, 0, h, h;
1, 1, 1, 1]

Сделайте произведение с помощью H и получите деформированные координаты:

P' = H * P

шаг 3: проверьте минимум в x и y с этими новыми 4 точками и получите размер искаженного изображения
После того, как вы сделали продукт, вы получите что-то вроде этого:

P' = [s1*x1, s2*x2, s3*x3, s4*x4;
s1*y1, s2*y2, s3*y3, s4*y4;
s1   , s2   , s3   , s4]

Таким образом, чтобы получить новую действительную координату, просто разделите линии 1 и 2 на линию 3

После этого проверьте минимум для столбца в первой строке и минимум для строки во второй строке (используйте cvReduce)

чтобы найти ограничивающую рамку, которая будет содержать изображение (то есть размер матрицы dst для функции warpPerspective), просто найдите с помощью cvReduce максимум по каждой строке

пусть minx будет минимумом в первой строке (т.е. для столбца), maxx (максимумом для 1 строки)
miny и maxy для второго ряда

Таким образом, размер деформированного изображения должен быть cvSize (maxx-minx, maxy-miny)

шаг 4: добавить исправление к омографии
Проверьте, является ли minx и / или miny отрицательным, если minx < 0 тогда добавьте -minx к h02 и если miny < 0, затем добавьте -miny к h12

поэтому H должно быть:

H = [ h00, h01, h02-minx; //if minx <0
h10, h11, h12-miny; //if miny <0
h20, h21,   1];

шаг 5: деформируем изображение

7

Другие решения

Я думаю этот вопрос OpenCV warpperspective похоже на текущий вопрос cv :: warpPerspective показывает только часть искаженного изображения

Так что я даю вам свой ответ https://stackoverflow.com/a/37275961/15485 также здесь:

Попробуйте ниже homography_warp,

void homography_warp(const cv::Mat& src, const cv::Mat& H, cv::Mat& dst);

src это исходное изображение.

H это твоя гомография

dst это искаженное изображение.

homography_warp отрегулируйте свою гомографию, как описано https://stackoverflow.com/users/1060066/matt-freeman в своем ответе https://stackoverflow.com/a/8229116/15485

// Convert a vector of non-homogeneous 2D points to a vector of homogenehous 2D points.
void to_homogeneous(const std::vector< cv::Point2f >& non_homogeneous, std::vector< cv::Point3f >& homogeneous)
{
homogeneous.resize(non_homogeneous.size());
for (size_t i = 0; i < non_homogeneous.size(); i++) {
homogeneous[i].x = non_homogeneous[i].x;
homogeneous[i].y = non_homogeneous[i].y;
homogeneous[i].z = 1.0;
}
}

// Convert a vector of homogeneous 2D points to a vector of non-homogenehous 2D points.
void from_homogeneous(const std::vector< cv::Point3f >& homogeneous, std::vector< cv::Point2f >& non_homogeneous)
{
non_homogeneous.resize(homogeneous.size());
for (size_t i = 0; i < non_homogeneous.size(); i++) {
non_homogeneous[i].x = homogeneous[i].x / homogeneous[i].z;
non_homogeneous[i].y = homogeneous[i].y / homogeneous[i].z;
}
}

// Transform a vector of 2D non-homogeneous points via an homography.
std::vector<cv::Point2f> transform_via_homography(const std::vector<cv::Point2f>& points, const cv::Matx33f& homography)
{
std::vector<cv::Point3f> ph;
to_homogeneous(points, ph);
for (size_t i = 0; i < ph.size(); i++) {
ph[i] = homography*ph[i];
}
std::vector<cv::Point2f> r;
from_homogeneous(ph, r);
return r;
}

// Find the bounding box of a vector of 2D non-homogeneous points.
cv::Rect_<float> bounding_box(const std::vector<cv::Point2f>& p)
{
cv::Rect_<float> r;
float x_min = std::min_element(p.begin(), p.end(), [](const cv::Point2f& lhs, const cv::Point2f& rhs) {return lhs.x < rhs.x; })->x;
float x_max = std::max_element(p.begin(), p.end(), [](const cv::Point2f& lhs, const cv::Point2f& rhs) {return lhs.x < rhs.x; })->x;
float y_min = std::min_element(p.begin(), p.end(), [](const cv::Point2f& lhs, const cv::Point2f& rhs) {return lhs.y < rhs.y; })->y;
float y_max = std::max_element(p.begin(), p.end(), [](const cv::Point2f& lhs, const cv::Point2f& rhs) {return lhs.y < rhs.y; })->y;
return cv::Rect_<float>(x_min, y_min, x_max - x_min, y_max - y_min);
}

// Warp the image src into the image dst through the homography H.
// The resulting dst image contains the entire warped image, this
// behaviour is the same of Octave's imperspectivewarp (in the 'image'
// package) behaviour when the argument bbox is equal to 'loose'.
// See http://octave.sourceforge.net/image/function/imperspectivewarp.html
void homography_warp(const cv::Mat& src, const cv::Mat& H, cv::Mat& dst)
{
std::vector< cv::Point2f > corners;
corners.push_back(cv::Point2f(0, 0));
corners.push_back(cv::Point2f(src.cols, 0));
corners.push_back(cv::Point2f(0, src.rows));
corners.push_back(cv::Point2f(src.cols, src.rows));

std::vector< cv::Point2f > projected = transform_via_homography(corners, H);
cv::Rect_<float> bb = bounding_box(projected);

cv::Mat_<double> translation = (cv::Mat_<double>(3, 3) << 1, 0, -bb.tl().x, 0, 1, -bb.tl().y, 0, 0, 1);

cv::warpPerspective(src, dst, translation*H, bb.size());
}
0

По вопросам рекламы [email protected]