관심쟁이 영호

[#7.1]OpenCV (With. c++) ㅣ 기본 행렬 연산 함수! 본문

학교공부/OpenCV

[#7.1]OpenCV (With. c++) ㅣ 기본 행렬 연산 함수!

관심쟁이 영호 2020. 11. 10. 01:30
반응형

안녕하세요!

관심쟁이 영호입니다.

 

오늘은 OpenCV에서 사용되는 기본 행렬 연산 함수를 다룰 예정이에요!

 


이미지와 비디오는 기본적으로 행렬로 이루어져있으니

행렬 연산을 잘안다면 영상을 작업하는데 있어서 훨씬 유리하겠죠!!

그렇다고 달달 외워둘 필요는 없어요!

그냥 이런것이 있구나 정도말 알아두시고 필요하실때 구글링을 통해 찾아보시면 됩니다!

 

오늘 공부해볼 함수는요!

 

함수 이름 기능 또는 내용
-flip 입력된 2차원 배열을 수직, 수평, 양축으로 뒤집는다.
-repeat 입력 배열의 반복된 복사본으로 출력배열을 채운다.
-transpose 입력 행렬의 전치 행렬을 출력 인수로 반환한다.
-merge 여러 개의 단일 채널 배열로 다중 채널의 배열을 합성한다.
-split 다중 채널 배열을 여러개의 단일 채널의 배열로 분리한다.
-사칙연산(add, subtract, multiply, divide, addweighted) 행렬내 데이터에 사칙연산을 수행한다.
-위상연산(magnitude, phase,cartToPolar, polarToCart) 기하학적 연산을 수행한다.

이렇게 공부를 해보겠습니다!

 

flip()

"입력된 2차원 배열을 수직, 수평, 양축으로 뒤집는다."

 

flip(입력배열, 출력배열, 기준 축 0 or 1 or -1)

 - 0 : x축을 기준으로 위아래로 뒤집는다.

 - 1 : y축을 기준으로 좌우로 뒤집는다.

 - -1: x,y축을 기준으로 위아래-좌우로 뒤집는다.

 

하나의 이미지를 예시로 설명하자면!

행렬이 수직, 수평, 양축으로 뒤집기 때문에 이미지가 축을 기준으로 뒤집어져서 나타나게 되는겁니다!

 

repeat()

"입력 배열의 반복된 복사본으로 출력배열을 채운다.

 

repeat(입력배열, 수직방향 반복 횟수, 수평방향 반복횟수, 출력배열)

여기서 말하는 수직수평방향 반복횟수는 채울때 해당 이미지를 몇번 반복할 지 정해주는 겁니다!

3이라고 하면 다 채우지 않았는데도 3번만 반복을 하게 되는거죠!

 

transpose()

"입력 행렬의 전치 행렬을 출력 인수로 반환한다."

 

transpose(입력배열, 출력배열)

한마디로 x의 값 <-> y의 값을 맞바꾼다는 소리입니다!

 

이미지를 예로 들면 옆으로 돌린 효과가 나타나요!

 

merge()

"여러개의 단일채널 배열로 다중 채널의 배열을 합성한다."

 

merge(합쳐질 행렬들이 있는 배열, 합성될 배열의 갯수, 출력배열)

여기서 합쳐질 행렬들이 있는 배열이란! 배열에 Mat타입의 1채널 행렬이 3개가 있을 때! 그 배열을 가르키는 것입니다.

 

좀 더 쉽게 말씀드리면, 1채널로된 배열 3개를 merge()하게 되면 3채널의 독단적인 3채널 배열이 탄생하게 됩니다!

 

split()

"다중 채널 배열을 여러개의 단일채널 배열로 분리한다."

 

spilt(다중 채널 행렬, 분리되는 채널들을 저장할 배열)

 

사칙연산

add, abstract, multiply, divide는 사용방법이 동일합니다!

 

add(행렬1, 행렬2, 더해진 행렬을 저장하는 Mat타입의 행렬3)

나머지 연산들도 다 비슷하다고 보시면 됩니다!

행렬3 = 행렬1 +-*/ 행렬2 이렇게 생각 하시면 됩니다.

추가적인 값을 지정해줄 수 도 있는데 생략할게요!

 

addweight()

"두 배열의 가중된 합을 계산한다."

 

addweight(행렬1, Alpha, 행렬2, beta, Gamma, 행렬3)

이 뜻은!

행렬3 = (행렬1xAlpha) + (행렬2xBeta) + Gamma

 

위상연산

이것은 기하학적 계산이라고 볼 수 있겠네요!!

 

exp()

모든 배열 원소의 지수를 계산

 

log()

모든 배열 원소의 절댓값에 대한 자연 로그를 계싼

 

sqrt()

모든 배열 원소에 대해 제곱근을 계산

 

pow()

모든 배열 원소에 대해서 power 승수 계산

 

magnitude()

2차원 벡터들의 크기를 계산한다.

 

phase()

2차원 벡터의 회전 각도를 계산한다.

 

cartToPolar()

2차원 벡터들의 크기와 각도를 계산한다.

 

polarToCart()

각도와 크기로부터 2차원 벡터들의 좌표를 계산한다.

 

설명을 먼저 드렸어요!

바로 코드로 살펴보겠습니다!!

 

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

void main() {
	
	string filename = "../image/sample_image2.jpg";
	Mat image = imread(filename, IMREAD_COLOR);
	Mat flipx, flipy, flipxy, repeat1, transpose1, merge1, split1,add2, subtract1, multiply1, divide1;
	Mat arr1[3];
	CV_Assert(image.data);

	flip(image, flipx, 0);
	flip(image, flipy, 1);
	flip(image, flipxy, -1);
	repeat(image, 1, 2, repeat1);
	transpose(image, transpose1);

	imshow("원본", image);
	imshow("x축 반전", flipx);
	imshow("y축 반전", flipy);
	imshow("xy축 반전", flipxy);
	imshow("repeat", repeat1);

	split(image, arr1);

	imshow("split한 후 0채널", arr1[0]);
	imshow("split한 후 1채널", arr1[1]);
	imshow("split한 후 2채널", arr1[2]);
	
	
	Mat arr2[] = { arr1[0], arr1[1] };
	merge1 = Mat(image.size(), image.type());
	merge(arr2, 2, merge1);
	Point pt1(1, 1), pt2(10, 10);
	Rect roi(pt1, pt2);
	
	cout << "merge한 값!" << endl<<merge1(roi) << endl;
	
	
	Mat add1(image.size(), image.type() , Scalar(20, 20, 20));
	add(image, add1,add2);
	imshow("add한것!", add2);

	subtract(image, add1, subtract1);
	imshow("subtract한것!", subtract1);
	
	Mat multi(image.size(), image.type(), Scalar(1.2, 1.2, 1.2));
	
	multiply(image, multi, multiply1);
	imshow("multiply", multiply1);

	Mat divi(image.size(), image.type(), Scalar(2, 2, 2));

	divide(image, divi, divide1);
	imshow("divide", divide1);
	

	
	
	waitKey(0);
	

}

먼저 샘플 이미지는!

이것을 사용했어요!

 

그 다음 코드를 통해서

이것을 출력해보았어요!

 

잘 보이실까요..?

 

각각 연산을 다 출력해보았어요!

 


오늘은 여기까지!

 

다음 시간에는 논리연산을 해볼게요!

 

300x250
Comments