로버트 라가니에의 <OpenCV를 활용한 컴퓨터 비전 프로그래밍, 3판>을 참고서로 하루에 2시간 정도씩 opencv를 활용해서 영상처리를 공부하려고 한다. 그동안 매트랩을 주로 써왔는데, MATLAB만으로 영상처리 관련 프로젝트를 다 구현해내기에는 한계를 많이 느껴왔기 때문이다. 물론 이전에도 C++과 opencv를 간간히 활용했지만 자유자재로 구현할 수 있는 수준은 아니기에, 연습이 필요하다.
opencv를 활용하기 위해서 설치하고 빌드하는 과정이 복잡하지만 이 과정만 잘 거치면 영상처리를 위한 강력한 오픈소스 라이브러리를 활용할 수 있다.
▶ 영상 읽고, 띄우고, 축소하고, 좌우반전하고, 저장하기
오늘은 가장 기본적인 영상을 읽고, 띄우고, 축소하고, 좌우반전하고, 저장하기를 실행해보겠다. 아래와 같은 절차를 밟을 것이다.
1. 영상 읽기
2. 영상 띄우기
3. 영상 사이즈 변경- cv::resize
4. 영상 좌우 반전- cv::flip
5. 영상 저장
전체 코드를 우선 보자. 코드에 주석을 달아놓았으니 참고하자.
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp> // resize 함수 사용을 위해
#include <iostream>
int main()
{
cv::Mat image; // 빈 영상 생성
image = cv::imread("image1.JPG"); //이미지 읽기
if (image.empty()) //이미지를 제대로 읽을 수 없으면 에러 메시지 출력
{
std::cout << "error when reading image!" << std::endl;
return 0;
}
std::cout << "Origianl image is " << image.rows << " x " << image.cols << std::endl; //원본 이미지 사이즈 출력
cv::namedWindow("Original image"); // 원본 이미지를 전시할 창 만들기
cv::imshow("Original image", image); // 원본 이미지 보여주기
cv::Mat resized_image;
cv::resize(image, resized_image, cv::Size(), 0.25, 0.25, CV_INTER_AREA); //원본 이미지 크기 조정하기. 가로 세로 모두 1/4로 축소.
std::cout << "Resized image is " << resized_image.rows << " x " << resized_image.cols << std::endl; // 축소된 이미지 사이즈 출력
cv::namedWindow("Resized image");
cv::imshow("Resized image", resized_image); // 축소된 이미지 보여주기
cv::Mat result;
cv::flip(resized_image, result, 1); //영상 좌우 반전하기
cv::namedWindow("Fliped image");
cv::imshow("Fliped image", result); //좌우 반전된 이미지 보여주기
cv::imwrite("Fliped_image.bmp", result); //좌우 반전된 이미지 저장
cv::waitKey(0);
return 0;
}
이 코드를 실행한 결과 아래와 같은 세 개의 이미지가 전시되었다.
가장 큰 이미지가 원본 이미지, 아래에서 왼쪽에 있는 것이 축소된 이미지, 오른쪽에 있는 것이 좌우반전된 이미지다. 참고로 이 사진은 고척돔에서 찍은 것이다. 또한 원본 이미지의 사이즈와 크기를 조정한 이미지의 사이즈가 출력되었다.
가로, 세로 모두 1/4로 축소된 것을 알 수 있다.
▶ 좀 더 알고 넘어갈 것들
1) cv::resize(입력 이미지, 출력 이미지, 출력 이미지 사이즈, 가로 축척 비율, 세로 축척 비율, 보간법)
입력 매개변수들 중에서 마지막은 보간법(interpolation)과 관련된 것이다. 영상을 축소하는 경우에는 CV_INTER_AREA, 영상을 확대하는 경우에는 CV_INTER_CUBIC(다소 느림) 또는 CV_INTER_LINEAR(빠름)가 추천된다.
그리고 예제에서 영상을 가로, 세로 모두 1/4로 축소시킨 것과 달리 특정한 사이즈, 예를 들어 256x256으로 변경하고자 한다면,
cv::resize(image, resized_image, cv::Size(256, 256), 0, 0, CV_INTER_AREA)
과 같이 코드를 변경해주면 된다.
2) cv::flip(입력 이미지, 출력 이미지, 반전 방향)
세번째 매개변수는 어느 방향으로 반전시켜줄지를 결정한다. 예제와 같이 양수면 좌우반전, 0이면 상하반전, 음수면 좌우반전과 상하반전을 모두 시켜준다.
3) 영상 저장 관련
영상을 저장할 때는 cv::imwrite()가 활용되는데, 지원하는 영상 포맷은 JPG, PNG, TIFF이다.
4) 영상 읽기 관련
예제에서는 컬러영상을 컬러로 읽었는데, 만약 그레이스케일로 읽으려면,
image = cv::imread("image1.JPG", CV_LOAD_IMAGE_GRAYSCALE);
와 같이 코드를 변경해주면 된다. 아니면 컬러로 읽은 다음에 cv::cvtColor 함수를 활용해서 그레이영상으로 변환해줄 수도 있다.
영상의 채널 개수를 확인하고 싶을 때는 channels 메소드를 사용하면 된다. 컬러 영상이라면 3이, 그레이 영상이라면 1이 출력될 것이다.
<참고자료>
[1] 로버트 라가니에 지음, 이문호 옮김, "OpenCV를 활용한 컴퓨터 비전 프로그래밍 3/e", 에이콘
'Dev > C, C++' 카테고리의 다른 글
[opencv와 C++로 컴퓨터 비전] 영상에 소금-후추 잡음(salt-and-pepper noise) 넣기 (2) | 2018.02.01 |
---|---|
[opencv와 C++로 컴퓨터 비전] 영상 위에 로고 넣기 (0) | 2018.01.31 |
[opencv와 C++로 컴퓨터 비전] 영상 위에 그림 그리기 및 글쓰기 (0) | 2018.01.30 |
[opencv와 C++로 컴퓨터 비전] 마우스로 영상 위에서 클릭한 위치와 화소 값 출력하기 (0) | 2018.01.29 |
C언어의 메모리 구조: 데이터(Data), 스택(Stack) 그리고 힙(Heap) 영역 (2) | 2017.10.16 |
포인터의 이해 (6) | 2017.10.09 |
opencv에서 픽셀값 접근하기 (2) | 2017.07.05 |
[Learn opencv by examples] 8 (1). Sobel 엣지 검출 (6) | 2017.06.15 |