어파인 변환과 투시변환

전종원·2022년 10월 31일
0

1. 어파인 변환과 투시 변환

어파인 변환 행렬 구하기

Mat getAffineTransform(const Point2f src[], const Point2f dst[]);
Mat getAffineTransform(InputArray src, Input Array dst);
  • src: 3개의 원본 좌표점
  • dst: 3개의 결과 좌표점
  • 반환값: 2x3 크기의 어파인변환행렬(CV_64F)

투시변환 행렬 구하기

Mat getPerspectiveTransform(const Point2f src[], const Point2f dst[], 
							int solveMethod = DECOMP_LU);
Mat getPerspectiveTransform(InputArray src, InputArray dst, 
							int solveMethod = DECOMP_LU);
  • src: 4개의 원본 좌표점
  • dst: 4개의 결과 좌표점
  • 반환값: 3x3 크기의 변환행렬

영상의 어파인 변환

void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize,
				int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT,
                const Scalar& borderValue = Scalar());

영상의 투시 변환

void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize,
					int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT,
                	const Scalar& borderValue = Scalar());

실습코드

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);

	if (src.empty()) {
		cerr << "Image load failed!" << endl;
		return -1;
	}

#if 1
	Mat dst = Mat::zeros(src.size(), CV_8UC1);

	for (int y = 0; y < src.rows; y++) {
		for (int x = 0; x < src.cols; x++) {
			int x_ = x + 100;
			int y_ = y + 100;
			if (x_ < 0 || x_ >= dst.cols) continue;
			if (y_ < 0 || y_ >= dst.rows) continue;
			dst.at<uchar>(y_, x_) = src.at<uchar>(y, x);
		}
	}
#else
	Mat trans = (Mat_<float>(2, 3) << 1, 0, 100, 0, 1, 100);

	Mat dst;
	warpAffine(src, dst, trans, Size());
#endif

	imshow("src", src);
	imshow("dst", dst);
	waitKey();
}

2. 차선 영상의 버드아이뷰 만들기

  • 새가 하늘에서 내려다보듯이 매우 높은 곳에 위치한 카메라가 아래의 피사체를 찍은 화면

실습코드

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
	VideoCapture cap("test_video.mp4");

	if (!cap.isOpened()) {
		cerr << "Video open failed!" << endl;
		return -1;
	}

	Mat src;
	while (true) {
		cap >> src;

		if (src.empty())
			break;

		int w = 500, h = 260;

		//Á¡ 4°³ ÀúÀåÇÒ ÄÁÅ×ÀÌ³Ê Œ±Ÿð
		vector<Point2f> src_pts(4); 
		vector<Point2f> dst_pts(4);

		src_pts[0] = Point2f(474, 400);	src_pts[1] = Point2f(710, 400);
		src_pts[2] = Point2f(866, 530); src_pts[3] = Point2f(366, 530);

		dst_pts[0] = Point2f(0, 0);		dst_pts[1] = Point2f(w - 1, 0);
		dst_pts[2] = Point2f(w - 1, h - 1);	dst_pts[3] = Point2f(0, h - 1);

		Mat per_mat = getPerspectiveTransform(src_pts, dst_pts);

		Mat dst;
		warpPerspective(src, dst, per_mat, Size(w, h));

#if 1
		vector<Point> pts;
		for (auto pt : src_pts) {
			pts.push_back(Point(pt.x, pt.y));
		}
		polylines(src, pts, true, Scalar(0, 0, 255), 2, LINE_AA);
#endif

		imshow("src", src);
		imshow("dst", dst);

		if (waitKey(10) == 27)
			break;
	}
}

결과영상

0개의 댓글