본문 목표
연산속도를 빠르게 하기위해서 RGB 색 채널보다는 Grayscale을 사용한다.
그런데 이보다 더 연산속도를 빠르게 할 수 있는 방법은 이미지 사이즈를 줄이는 것이다.
opencv에서 제공하는 이미지 사이즈 변경 방법에 대해서 알아보자.
키워드 : resize , 보간법
알아볼 함수 원형
- 이미지 크기 변경 ( Resize )
...
Mat img = imread("Lenna.png");
img_small;
resize(img, img_small, Size(200, 200));
...
resize( src, dst, Size(cols, rows) )
○ src : 입력할 이미지 변수
○ dst : 필터가 적용되어 저장될 이미지 변수
○ Size(cols, rows) : 변환시킬 이미지의 크기, 열과 행 순서로 입력한다.
- 정확히는 Size(x, y) 이다.
x는 흔히 가로축이라서 열의 너비를 뜻하고,
y는 세로축이라서 행의 높이를 뜻한다.
이 외에도 fx, fy, interpolation(보간법) 에 대한 정보를 필요로 한다.
하지만 기본값을 사용하면 되는 부분이라 신경 쓸 필요 없으니 다루지 않도록 한다.
resize 의 원리를 좀 자세하게 살펴보자.
우선 이미지를 축소시키는 것이 확대하는 것보다 쉽다.
이미지를 축소 시키는 방법에 대해서 생각해보자.
가장 쉽게 떠오르는 방법은 이미지의 행과 열을 이용하는 방법이다.
홀수 번호의 행과 열들만 이용해서 이미지를 새롭게 만든다면 그 이미지는 원본 이미지의 절반 크기가 된다.
하지만 반대로 이미지를 확대 시키는 방법을 생각해보면,
단순하게 행과 열을 이용해서 늘릴 수가 없다.
기존의 행들과 열 사이에 추가로 행과 열을 삽입했다고 했을 때,
그 삽입된 행과 열들을 이루고 있는 픽셀들의 데이터는 어떻게 되어야 하는지 쉽게 말하기 어렵다.
이미지를 확대시킬 때, 사용하는 방법이 보간법이다.
통계를 다뤘거나 수학 좀 했다면, 보간법은 익숙한 단어이다.
보통 선형보간법을 다루는데, 기존의 사실들로 하여금 추정하는 것이 보간법이라고 생각하면 쉽다.
이미지 확대에서도 마찬가지다.
새로 생긴 픽셀 주변의 픽셀들은 기존의 이미지의 픽셀 정보들을 갖고있다.
이 사실을 바탕으로 선형 보간법 방정식을 이용해서 최대한 이질감이 들지 않게 데이터를 정하는 것이다.
위의 자료를 보면
기존의 ABCD 의 픽셀들을 이용해서, 새로운 X좌표의 픽셀 데이터가 정해지는 관계식을 알 수 있다.
순서를 보면, E와 F 좌표의 값을 비례식을 통해서 구하고,
X 좌표의 값을 앞서 구한 E와 F의 값을 비례식을 이용해 구한다.
선형 보간법의 원리이다.
이미지가 2배로 커지거나 하면 좋겠지만,
위의 자료처럼 애매하게 커지는 경우를 대비해서 선형보간법을 사용하는 것이다.
물론 이미지가 작아질 때에도 선형보간법이 사용된다.
Matlab 에서 확인해보면
위의 작은 원본 이미지를 선형보간법을 이용한 것과 인접 픽셀값을 이용한 보간법의 결과이다.
확실히 왼쪽의 선형보간법으로 확대된 이미지가 자연스럽다.
오른쪽의 인접 픽셀 정보를 그대로 사용한 이미지는 확실히 강제로 이미지를 확대시킨것 같은 느낌이다.
그렇다고해서 오른쪽의 결과가 나쁜 것은 아니다.
오른쪽의 결과로도 충분하다면, 연산이 적은 오른쪽의 알고리즘을 사용하는 것이 연산속도를 빠르게하는데 도움이 된다.
선형 보간법을 사용한다면 아무래도 비교적 연산처리가 많아지게 되기 때문이다.
실시간 영상처리에 있어서는 충분히 고려해야할 사항이다.
다행히도 OpenCV에서는 기본값으로 선형보간을 사용해주고 있기에,
특별히 건드려야 할 것이 아니라면 그냥 기본값을 사용하면 좋은 결과를 얻을 수 있다.
그리고, 선형 보간말고 인접보간, 큐빅보간 등을 사용하려면 해당 옵션을 부여해야한다.
인접 보간과 선형 보간, 큐빈스플라인 보간의 연산 속도 차이에 대해서는
다음에 좀 전문적으로 다뤄보도록하고, 여기에서는 넘어가도록 하자.
살짝 정리하자면
INTER_NN : 인접 보간으로 부자연 스러운 결과를 얻을 수 있다.
INTER_LINEAR : 가장 기본이 되는 선형보간으로 만족스러운 결과를 얻을 수 있다.
INTER_CUBIC : 큐빅 스플라인이라는 두 점 사이를 자연스럽게 이어주는 방식을 사용, 부드러운(흐릿한) 결과를 얻을 수 있다.
왼쪽부터 인접보간, 선형보간, 큐빅보간 이다.
이미지를 더 크게 확대시킬 수록 차이가 크게 발생한다.
코드 테스트 결과
- CODE
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int ac, char** av)
{
Mat img = imread("Lenna.png");
Mat img_big, img_small;
resize(img, img_big, Size(1000, 1000));
resize(img, img_small, Size(200, 200));
imshow("original", img);
imshow("img_big", img_big);
imshow("img_small", img_small);
waitKey(0);
return 0;
}
- RESULT
이미지를 거의 2배정도 확대시켰음에도 꽤 괜찮은 결과를 얻을 수 있었다.
보간법을 사용했기 때문이고, 선형보간이기에 자연스럽다.
축소시킨 이미지는 3배 정도로 축소시킨 결과인데, 정상적으로 축소가 되었음을 확인할 수 있다.
결론.
OpenCV 에서는 기본적으로 resize( ) 함수를 제공하여 이미지 크기를 쉽게 변경할 수 있다.
이미지 크기를 변경할 때에는 보간법이 사용된다.
각 보간법에는 방식의 차이가 있고, 결과의 차이가 있다. 연산속도의 차이도 존재한다.
도움이 되었거나, 문제가 있는 경우 댓글로 알려주세요~!
감사의 댓글은 작성자에게 큰 힘이 됩니다 ^^
'코딩 > OpenCV' 카테고리의 다른 글
[C++ opencv] High pass filter (HPF)로 윤곽선 검출, edge detection (1) | 2020.07.15 |
---|---|
[C++ opencv] low pass filters (LPF)로 노이즈 제거하기 (0) | 2020.07.15 |
[C++ opencv] 이미지에서 경계선 검출하기, Edge detection (1) | 2020.07.04 |
[C++ opencv] opening, closing 기법 사용하여 경계 확실히 하기 (0) | 2020.07.03 |
[C++ opencv] erode, dilate 사용하여 물체 명확하게 하기 (5) | 2020.07.01 |
댓글