본문 바로가기
런닝머신 (ML)

[컴퓨터 비전 & 머신러닝] 어파인 변환 1

728x90

어파인 변환은 영상의 평행 이동, 확대 및 축소, 회전 등의 조합으로 만들 수 있는 기하학적 변환을 나타낸다.

 

어파인 변환은 모두 여섯 개의 파라미터(a, b, c, d, e, f)를 시용한 수식으로 정의할 수 있다.

 

어파인 변환에 의해 입력 영상의 좌표 (x, y)가 결과 영상의 좌표 (x', y')로 이동하는 수식이다

 

행렬을 이용하여 하나의 수식으로 표현할 수 있다.  x,y 앞에는 2x2 행렬을 곱하고, 2x1 행렬을 더하는 형태로 어파인 변환을 표현한다. 수학적 편의를 위해 입력 영상의 좌표 (x, y)에 1을 추가하여 (x, y, 1) 형태로 바꿀 수 있다.

 

입력 영상과 어파인 변환 결과 영상으로부터 어파인 변환 행렬을 구하기 위해서는 최소 세 점의 이동관계를 알아야 한다

 

어파인 변환에 의해 직사각형 영상은 평행사변형 형태로 변환될 수 있기 때문에 입력 영상의 좌측 하단 모서리 점이 이동하는 위치는 자동으로 결정되기 때문에 세점만 알아도 정의할 수 있다.

 

void affine_transform()
{
	Mat src = imread("tekapo.bmp"); //640x480

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

	//입력 영상과 출력 영상에서의 세 점 좌표를 저장할 srcPts와 dstPts 배열 선언
	Point2f srcPts[3], dstPts[3];
	srcPts[0] = Point2f(0, 0); //src 좌측 상단
	srcPts[1] = Point2f(src.cols - 1, 0); //(639, 0) src 우측 상단
	srcPts[2] = Point2f(src.cols - 1, src.rows - 1); //(639, 479) src 우측 하단
	dstPts[0] = Point2f(50, 50); //dst 좌측 상단
	dstPts[1] = Point2f(src.cols - 100, 100); //(540, 100) dst 우측 상단
	dstPts[2] = Point2f(src.cols - 50, src.rows - 50); //(590, 430) dst 우측 하단

	//2x3 어파인 변환 행렬을 M에 저장
	Mat M = getAffineTransform(srcPts, dstPts);

	Mat dst;
	warpAffine(src, dst, M, Size());

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

	waitKey();
	destroyAllWindows();
}


이동 변환은 영상을 가로 또는 세로 방향으로 일정 크기 만큼 이동시키는 연산을 의미하며 시프트 연산이라고도 한다.

void affine_translation()
{
	Mat src = imread("tekapo.bmp");

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

	//2x3 어파인 변환 행렬, 가로로 150픽셀, 세로로 100픽셀 이동하는 어파인 변환 행렬 M 생성
	Mat M = Mat_<double>({ 2, 3 }, { 1, 0, 150, 0, 1, 100 });

	Mat dst;
	warpAffine(src, dst, M, Size());

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

	waitKey();
	destroyAllWindows();
}


전단 변환은 직사각형 형태의 영상을 한쪽 방향으로 밀어서 평행사변형 모양으로 변형되는 변환, 층밀림 변환이라고도 한다

void affine_shear()
{
	Mat src = imread("tekapo.bmp");

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


	//가로 방향으로 밀림 정도를 0.3으로 설정한 전단 변환 행렬 M을 생성
	double mx = 0.3;
	Mat M = Mat_<double>({ 2, 3 }, { 1, mx, 0, 0, 1, 0 });
	//세로 방량으로 밀림 정도 0.3으로 설정
	//Mat M = Mat_<double>({ 2, 3 }, { 1, 0, 0, mx, 1, 0 });

	Mat dst;
	warpAffine(src, dst, M, Size(cvRound(src.cols + src.rows * mx), src.rows));
	//warpAffine(src, dst, M, Size(src.cols, cvRound(src.cols * mx + src.rows)));
    
	imshow("src", src);
	imshow("dst", dst);

	waitKey();
	destroyAllWindows();
}

 

728x90