리매핑: 영상의 특정 위치 픽셀을 다른 위치에 재배치하는 일반적인 프로세스
dst(x, y) = src(map_x ( x, y ), map_y( x,y ))
//출력영상의 x,y 좌표에서 픽셀 값을 입력영상에서 참조한다. 참조할 픽셀의 x좌표를 map_x , y좌표를 map_y로 표현하여 참조
어파인 변환, 투시 변환을 포함한 다양한 변환을 리매핑으로 표현가능
이동 변환
map_x(x,y) = x - 200 // map_x 함수 : 입력영상 , 우측 x는 출력영상
map_y(x, y) = y - 100
==> x축 200, y축 100 픽셀 이동
eg. x' : 출력 , x:입력
x = x' -200
y = y' - 100
==> x' = x+200 , y'= y+100 으로 x축으로 200, y축으로 100 픽셀이동
상하대칭
map_x(x,y) = x // x좌표 변환 없음
map_y(x,y) = h - 1 - y // ( h-1 == y좌표값의 최댓값)
영상의 세로크기 -1 에서 y좌표 빼는 형태로 수식 작성 시 y값이 0에 가까울 경우 map_y에 함수 반환값이 h -1에 가깝게 나타나고 y값이 점점 커져서 h에 가깝게 되는 경우 map_y 함수가 반환하는 값은 0에 가까운 값을 반환
크기변환
map_x(x,y) [입력] = x [출력] /2
map_y(x, y) [입력]= y[출력] /2
==> 가로, 세로 2배 확대.
(x,y) 에서 x는 0 ~( 2W -1 ) y는 0 ~ ( 2h -1 ) 까지 증가하는 형태로 해당 함수가 정의되야함.
if x' == 출력 , x == 입력 이라하면
x = x'/2 -> x' = 2x
y = y'/2 -> y' = 2y
void remap(InputArray src, OutputArray dst, InputArray map1,
InputArray map2, int interpolation, int borderMode = BORDER_CONSTANT,
const Scalar & borderValue = Scalar());
dst: map1과 같은 크기 , src와 같은 타입
map1: 결과 영상의 각 픽셀이 참조할 입력 영상의 (x,y) 좌표 또는 x좌표를 담고 있는 행렬.
CV_16SC2, CV_32FC2 또는 CV_32FC1
map2: 결과 영상의 (x,y) 좌표가 참조할 입력영상의 y좌표를 담고 있는 행렬. CV_16UC1 또는 CV_32FC1.
interpolation: 보간법 [ default: INTER_LINEAR , 좀 더 좋은 영상 나오게 하고싶을시 CUBIC으로 지정하기]
borderMode: 가장자리 픽셀 확장 방식
borderValue: BORDER_CONSTANT일 때 사용할 상수 값
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
#define TC 2
int main()
{
Mat src = imread("tekapo.png");
if (src.empty()) {
cerr << "Image laod failed!" << endl;
return -1;
}
int w = src.cols;
int h = src.rows;
#if TC ==1
Mat map1 = Mat::zeros(h, w, CV_32FC1);
Mat map2 = Mat::zeros(h, w, CV_32FC1);
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
map1.at<float>(y, x) = (float)x;
//map2.at<float>(y, x) = (float)y; // x, y (출력영상) 을 map1값 (입력영상)과 동일하게 설정함으로써 입력/출력 영상을 동일한 형태로 만듦
//map2.at<float>(y, x) = (float)h - 1 - y; // 상하반전 y값이 커지면서 0에 가까운 값을 참조하여 결과 영상을 출력
map2.at<float>(y,x) = (float)y + 10 * sin(x/32.f); // sin 형태 y좌표 그대로, x좌표 증가함에 따라 sin 커브를 그리는 식으로 픽셀 값 참조.
}
}
Mat dst;
//remap(src, dst, map1, map2, INTER_LINEAR);
remap(src, dst, map1, map2, INTER_LINEAR, BORDER_DEFAULT); // 픽셀값 0으로 채워지지 않코, 비슷한 픽셀값으로 채워짐에 따라 자연스러운 결과물이 나옴.
//remap(src, dst, map1, map2, INTER_CUBIC, BORDER_DEFAULT);
#elif TC ==2 // remap 함수를 통해 영상 확대할 경우
Mat map1 = Mat::zeros(h*2, w*2, CV_32FC1);
Mat map2 = Mat::zeros(h * 2, w * 2, CV_32FC1);
for (int y = 0; y < h * 2; y++) {
for (int x = 0; x < w * 2; x++) {
map1.at<float>(y, x) = (float)x/2; // 확대의 경우 나누기 2를 해야함. 곱하기 2는 아님.
map2.at<float>(y, x) = (float)y / 2;
}
}
Mat dst;
//remap(src, dst, map1, map2, INTER_LINEAR);
remap(src, dst, map1, map2, INTER_LINEAR, BORDER_DEFAULT); // 픽셀값 0으로 채워지지 않코, 비슷한 픽셀값으로 채워짐에 따라 자연스러운 결과물이 나옴.
//remap(src, dst, map1, map2, INTER_CUBIC, BORDER_DEFAULT);
#endif
imshow("src", src);
imshow("dst", dst);
waitKey();
}'프로그래머스 > OPENCV' 카테고리의 다른 글
| 컬러영상처리 (0) | 2022.12.07 |
|---|---|
| 색 공간 (0) | 2022.12.06 |
| 어파인 변환과 투시 변환 ( with bird eyeview) (0) | 2022.12.05 |
| 회전변환과 기하학적 변환의 조합 [다시] (0) | 2022.12.05 |
| 영상의 크기 변환 (scale transform == resize) 과 보간법 [ 다시] (0) | 2022.12.05 |