Я пытаюсь добиться следующего эффекта, показанного здесь, используя инструмент перспективы в GIMP.
исходное изображение (620×466 пикселей)
преобразование изображения
У меня есть фиксированная веб-камера, и я хотел бы добавить приведенные выше цифры матрицы преобразования, что приведет к неискаженному выводу в форме трапеции.
Мне известно, что в OpenCV есть и другие варианты, позволяющие неискажать изображения, но я бы очень хотел предоставить цифры матрицы преобразования вручную, при этом получая изображение в форме трапеции.
От прочтения у меня возникает чувство warpPerspective
, findHomography
или же getPerspectiveTransform
может быть полезным, но не уверен, как это сделать в C ++
Любой полезный совет будет принята с благодарностью.
Пробовал работать со следующим кодом, но у меня только окно с показом 1 пиксель.
Может быть, способ, которым я указал точки в пикселях, это правильно?
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include <cv.h>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
cv::Mat OpenWarpPerspective(const cv::Mat& _image
, const cv::Point2f& _lu
, const cv::Point2f& _ru
, const cv::Point2f& _rd
, const cv::Point2f& _ld
, const cv::Point2f& _lu_result
, const cv::Point2f& _ru_result
, const cv::Point2f& _rd_result
, const cv::Point2f& _ld_result
, cv::Mat& _transform_matrix)
{
// todo do some checks on input.
cv::Point2f source_points[4];
cv::Point2f dest_points[4];source_points[0] = _lu;
source_points[1] = _ru;
source_points[2] = _rd;
source_points[3] = _ld;
dest_points[0] = _lu_result;
dest_points[1] = _ru_result;
dest_points[2] = _rd_result;
dest_points[3] = _ld_result;
cv::Mat dst;
_transform_matrix = cv::getPerspectiveTransform(source_points, dest_points);
cv::warpPerspective(_image, dst, _transform_matrix, dst.size());
return dst;
}
int main( int argc, char** argv )
{
Mat image;
Mat edited;
image = imread("c:/org.png", CV_LOAD_IMAGE_COLOR); // Read the file
namedWindow( "Display window", CV_WINDOW_AUTOSIZE );// Create a window for display.
Point2f one = (0.0, 0.0);
Point2f two = (317.0, 0.0);
Point2f three = (317.0, 240.0);
Point2f four = (0.0, 240.0);
Point2f five = (-100.0, 0.0);
Point2f six = (617.0, 0.0);
Point2f seven = (317.0, 240.0);
Point2f eight = (0.0, 240.0);
OpenWarpPerspective(image,one,two,three,four,five,six,seven,eight,edited);
imshow( "Display window", edited ); // Show our image inside it.
waitKey(0); // Wait for a keystroke in the window
return 0;
}
Если у вас есть три угловые точки, используйте Warp Affine transform. Если у вас есть четыре угловые точки, используйте трансформацию Warp Perspective. Вот как вы должны использовать Warp Perspective transform. Выберите четыре угловые точки изображения. Затем выберите четыре соответствующие точки желаемого прямоугольника. Деформация деформации сделает все остальное.
cv::Mat OpenWarpPerspective(const cv::Mat& _image
, const cv::Point2f& _lu
, const cv::Point2f& _ru
, const cv::Point2f& _rd
, const cv::Point2f& _ld
, const cv::Point2f& _lu_result
, const cv::Point2f& _ru_result
, const cv::Point2f& _rd_result
, const cv::Point2f& _ld_result
, cv::Mat& _transform_matrix)
{
// todo do some checks on input.
cv::Point2f source_points[4];
cv::Point2f dest_points[4];source_points[0] = _lu;
source_points[1] = _ru;
source_points[2] = _rd;
source_points[3] = _ld;
dest_points[0] = _lu_result;
dest_points[1] = _ru_result;
dest_points[2] = _rd_result;
dest_points[3] = _ld_result;
cv::Mat dst;
_transform_matrix = cv::getPerspectiveTransform(source_points, dest_points);
cv::warpPerspective(_image, dst, _transform_matrix, cv::Size(_width, _height));
return dst;
}
Следующие работы:
Пожалуйста, исправьте координаты на входном изображении, я не понял.
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
//#include "cv.hpp"#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
cv::Mat OpenWarpPerspective(const cv::Mat& _image
, const cv::Point2f& _lu
, const cv::Point2f& _ru
, const cv::Point2f& _rd
, const cv::Point2f& _ld
, const cv::Point2f& _lu_result
, const cv::Point2f& _ru_result
, const cv::Point2f& _rd_result
, const cv::Point2f& _ld_result
)
{
// todo do some checks on input.
cv::Point2f source_points[4];
cv::Point2f dest_points[4];
cv::Mat _transform_matrix;
source_points[0] = _lu;
source_points[1] = _ru;
source_points[2] = _rd;
source_points[3] = _ld;
dest_points[0] = _lu_result;
dest_points[1] = _ru_result;
dest_points[2] = _rd_result;
dest_points[3] = _ld_result;
cv::Mat dst = _image.clone();
_transform_matrix = cv::getPerspectiveTransform(source_points, dest_points);
cv::warpPerspective(_image, dst, _transform_matrix, dst.size());
return dst;
}
int main(int argc, char** argv)
{
Mat image;
Mat edited;
image = imread("img.png", CV_LOAD_IMAGE_COLOR); // Read the file // original image(620x466 pixels)
imshow("InputImage", image);
waitKey(0);Point2f one = (0.0, 0.0);
Point2f two = (500.0, 0.0);
Point2f three = (500.0, 100.0);
Point2f four = (250.0, 100.0);
Point2f five = (250.0, 0.0);
Point2f six = (500.0, 0.0);
Point2f seven = (500.0, 1000.0);
Point2f eight = (250.0, 100.0);edited= OpenWarpPerspective(image, one, two, three, four, five, six, seven, eight);
namedWindow("Display window", CV_WINDOW_AUTOSIZE);// Create a window for display.
imshow("Display window", edited); // Show our image inside it.
waitKey(0); // Wait for a keystroke in the window
return 0;
}
добавьте инициализацию dst:
Mat dst = _image.clone ();