본문 바로가기
프로그래밍/OpenCV

[OpenCV] OpenCV 4 설치 (설치 파일 사용)

by 별준 2022. 4. 30.

References

Contents

  • OpenCV 모듈
  • OpenCV 설치
  • OpenCV 프로젝트 생성
  • 튜토리얼 코드

OpenCV 4.0

OpenCV는 오픈 소스로 개발되고 있는 컴퓨터 비전 및 머신러닝 라이브러리이며, Open Source Computer Vision의 약자입니다. 2500개가 넘는 컴퓨터 비전과 머신러닝 알고리즘을 포함하고 있는데, 기본적인 영상 파일 입출력, 화실 향상, 객체 검출 및 인식, 추적 등 기능을 제공합니다. 또한, kNN(k-Nearest Neighbor) 알고리즘 서포트 벡터 머신(SVM)도 제공합니다. 최근에는 딥러닝을 위한 DNN 모델을 실행하는 기능도 제공됩니다.

 

OpenCV는 태생부터 실시간 처리를 고려하여 개발되었기 때문에 다양한 하드웨어 플랫폼에서 빠르게 동작됩니다. 기본적으로는 C/C++ 언어로 작성되어 있지만 파이썬, 자바 등의 인터페이스도 제공합니다. Windows, Linux, MaxOS 등을 지원하며, 안드로이드, iOS와 같은 모바일 환경도 지원합니다. OpenCV 대부분의 기능은 병렬 처리로 동작하며 MMX, SSE, AVX, NEON 등 CPU Instruction도 지원하며, CUDA와 OpenCL을 통한 GPU 연산도 지원하고 있습니다.

 

Apache License 2.0 라이센스를 따르고 있으며 별도의 허가없이 상업용으로 사용할 수 있으며, 소스 코드의 일부를 사용하여 프로그램을 개발하는 것도 허용됩니다.

 

 

OpenCV의 대략적인 역사를 살펴보면, 1999년 인텔에서 개발된 IPL(Image Primitive Library)을 기반으로 만들어지기 시작했고 2000년에 대중에게 공개되어 오픈소스로 개발되기 시작했습니다. 2006년 OpenCV 1.0버전이 정식으로 배포되었고, 이 버전은 C언어를 기반으로 구현되어 있습니다.

2009년에는 OpenCV 2.0이 발표되었고 이 버전부터 C++ 인터페이스를 채택하고, Mat이라는 클래스를 사용하여 영상 데이터를 표현하기 시작했습니다. 이후 지속적으로 버전이 올라가며 새로운 알고리즘, 성능 개선, 병렬 처리 강화 등이 추가되었습니다.

OpenCV 3.0은 2015년 6월에 발표되었습니다. 3.0에서는 프로젝트의 구조가 크게 개선되었고 전반적인 성능의 향상이 있었습니다. 그리고 2017년 8월에 발표된 3.3 버전에서는 Deep Neural Network를 지원하는 DNN 모듈이 기본 소스에 포함되었습니다. 또한 AVX/AVX2/SSE4.x 최적화가 추가되고, 최신 C++11 문법도 지원하기 시작했습니다.

 

OpenCV 4.0은 2018년 11월에 발표되었습니다. 가장 큰 변화는 C++11이 필수로 지원한다는 것이며 C++11을 지원하는 컴파일러 환경에서 사용할 수 있게 되었습니다. 이외에 DNN 모듈 기능이 강화되어 AlexNet, Inception v2, Resnet, VGG와 같은 네트워크뿐만 아니라 Mast-RCNN, tiny YOLO 같은 네트워크 구조도 지원합니다. 참고로 오랜된 C API 지원이 종료되어 IplImage 구조체 등을 사용할 수 없습니다.

 


OpenCV의 모듈

OpenCV github의 modules 폴더를 들어가보면, OpenCV에서 지원하는 모듈들이 있습니다. 각 모듈들의 역할을 간단하게 정리하면 다음과 같습니다.

  • calib3d : 카메라 Calibration과 3차원 재구성
  • core : 행렬, 벡터 등 OpenCV의 클래스와 연산 함수 지원
  • features2d : 2차원 feature 관련 프레임워크 (feature detection & description, descriptor matching...)
  • flann : 다차원 공간에서의 Clustering & Search (FLANN: Fast Library for Approximate Nearest Neighbors)
  • gapi : Graph API. 빠른 regular image processing와 portable을 위한 모듈. OpenCV의 특수한 모듈이며 다른 모듈과 다르게 특정 CV 알고리즘이 아닌 프레임워크 역할을 수행
  • highgui : High-level GUI. 영상의 화면 출력, 마우스 이벤트 처리 등 사용자 인터페이스 처리 모듈
  • imgcodecs : 이미지 파일 reading/writing 지원
  • imgproc : 이미지 처리 모듈 (filtering, image transformation, conversion 등)
  • ml : 머신러닝 알고리즘 지원 (statistical classification, regression, clustering)
  • objdetect : Object Detection. 얼굴 등의 객체 검출 지원
  • photo : 사진 처리 기능 지원 (HDR imaging, Denoising 등)
  • stitching : Images Stiching 지원 (Features Finding & Images Matching, Autocalibration 등)
  • video : 비디오 분석 지원 (Motion Analysis, Object Tracking)
  • videoio : 비디오 I/O 지원
  • world : 여러 OpenCV 모듈을 포함하는 통합 모듈

OpenCV의 모듈들은 제공하는 다양한 클래스, 함수와 그 기능들을 성격에 따라 나눈 부분 라이브러리들입니다. 따라서 OpenCV는 다수의 모듈 라이브러리가 모여서 만들어진 것이라고 볼 수 있습니다.

 

OpenCV 모듈은 각각 별도의 *.lib 파일과 *.dll 파일(윈도우 기준)로 만들어집니다. 예를 들어 OpenCV 4.0.0 버전의 core 모듈은 opencv_core400.lib와 opencv_core400.dll 파일로 만들어집니다.

 

core 모듈은 OpenCV에서 행렬, 벡터 등 기본적인 클래스를 지원하므로 항상 필요하며 그 이외에는 필요에 따라 포함할 수 있을 것 같습니다. 다만, 대부분의 컴퓨터 비전 프로그램에서 core, imgcodecs, imgproc, highgui 모듈은 거의 항상 필요로 하는 것 같습니다.

이처럼 프로젝트마다 다수의 모듈을 포함하거나 제외하는 과정이 번거롭기 때문에 OpenCV는 여러 개의 모듈을 통합하는 world 모듈을 제공합니다. world 모듈은 개별적으로 나뉘어져 있는 모듈들을 모두 합쳐서 하나의 모듈로 재구성합니다 따라서 world 모듈 하나만 프로젝트에 추가하면 OpenCV에서 제공하는 모든 기능을 사용할 수 있습니다.

 

위의 모듈들은 OpenCV의 main 모듈에 해당됩니다. 최신 컴퓨터 비전 알고리즘은 추가 모듈(extra module) 형태로 함께 개발되는데 주로 아직 안정화가 되지 않은 최신 알고리즘 구현이 포함됩니다. 이외에도 소스 코드는 공개되었지만 특허가 걸려있어 무료로 사용할 수 없는 기능과 CUDA 관련 기능도 여기서 배포됩니다. 이러한 추가 모듈들은 opencv_contrib에서 배포되고 있습니다. 추가 모듈에 대한 내용은 따로 여기서 다루진 않겠습니다.

 

 


OpenCV 설치

프로젝트에서 OpenCV를 사용하기 위해서는 OpenCV를 설치(?)해야 합니다. 즉, 관련된 헤더 파일, lib 파일, dll 파일을 사용할 컴퓨터에 생성해야 합니다. 윈도우의 경우에는 2가지 방법을 통해 가능합니다.

하나는 OpenCV 홈페이지에서 설치 파일을 다운받아서 설치하는 방법이고, 다른 하나는 OpenCV 소스 코드를 받아서 직접 빌드하여 설치하는 방법입니다.

 

이번 포스팅에서는 설치 파일을 통한 방법만 다루고 직접 소스 코드를 빌드하여 설치하는 것은 다른 포스팅에서 다루도록 하겠습니다.

 

https://opencv.org/releases/

 

Releases - OpenCV

Become a Member Stay up to date on OpenCV and Computer Vision news Join our Newsletter  

opencv.org

설치 파일은 위 사이트에서 내려받을 수 있습니다. 설치파일을 사용하면 직접 빌드하여 설치하는 것보다 빠르고 간단하지만 OpenCV의 추가 모듈을 사용할 수 없고 64비트 OS만 지원한다는 단점이 있습니다.

저는 여기서 Windows를 클릭해 설치 파일을 다운받았고, 실행하면 아래와 같이 압축을 해제합니다.

완료되면 설정한 경로에 opencv 폴더가 생성된 것을 확인할 수 있습니다.

opencv 폴더 내에는 build 폴더와 sources 폴더가 생성되는데, build 폴더에는 소스 코드로부터 만들어진 라이브러리 파일과 헤더 파일 등이 저장되어 있으며, sources 폴더에는 OpenCV 소스 코드 파일이 들어 있습니다.

 

OpenCV 라이브러리에서 사용하는 OpenCV 관련 헤더 파일은 모두 'opencv/build/include'에 모여 있습니다.

그리고 미리 빌드된 OpenCV 라이브러리 파일은 'opencv/build/x64' 폴더에 위치합니다. 이 폴더 내에는 vc14와 vc15라는 폴더가 있는데 vc14는 Visual Studio 2015를 이용하여 빌드된 라이브러리 파일이 있고 vc15에는 Visual Studio 2017을 이용하여 빌드된 라이브러리 파일이 있습니다. 그리고 각 폴더 내에는 bin과 lib 폴더가 존재합니다. bin 폴더에는 OpenCV 프로그램 실행 시 필요한 DLL 파일과 OpenCV 유틸리티 프로그램이 있습니다. 그리고 OpenCV DLL이 생성될 때 함께 만들어지는 import 라이브러리 파일은 lib 폴더에 위치합니다.

 

OpenCV 설치 파일은 world 모듈을 이용하여 빌드된 라이브러리 파일을 제공하는데, 따라서 이 설치 파일(v4.5.5)에서 제공하는 DLL 파일은 opencv_world455.dll 이 됩니다.

 

 


OpenCV 프로젝트 생성

그럼 다음으로 Visual Studio에서 OpenCV를 사용하려면 어떻게 설정해야 하는지 살펴보겠습니다. 저는 Visual Studio 2019를 사용하였습니다.

 

프로젝트를 생성하기 전에 먼저 환경 변수를 추가해주어야 하는데, 'opencv\build\x64\vc15\bin' 경로를 시스템 환경 변수 Path에 추가해줍니다. 

 

아마 기본적인 프로젝트 생성하는 방법은 다 아실 것이라고 생각하고 생략하겠습니다.

빈 프로젝트를 만들었으면, 프로젝트 속성에 들어갑니다. 먼저 Debug 모드에 대한 설정부터 진행하겠습니다.

프로젝트 속성의 Configuration Properties - C/C++ - General의 Additional Include Directories에 우리가 설치했던 opencv 폴더 내의 build - include 경로를 추가합니다. 

다음으로는 Configuration Properties - Linker - General의 Additional Library Directories에 설치한 opencv 폴더 내 x64/vc15/lib 위치의 경로를 추가합니다.

마지막으로 Linker - Input의 Additional Dependencies의 Edit을 눌러서 OpenCV 라이브러리의 이름을 입력합니다. 제가 사용할 OpenCV 라이브러리의 이름은 opencv_world455d.lib이며, 이를 입력하고 확인을 누릅니다.

 

Release 모드도 거의 유사합니다. 동일하게 C/C++의 Additional Include Directories와 Linker의 Additional Library Directories를 추가해주고, Linker - Input의 Additional Dependencies에만 'opencv_world455.lib'을 추가해줍니다.

OpenCV 라이브러리 중 이름 뒤에 'd'가 붙은 파일은 Debug 모드에서 사용하는 파일이고, 붙어 있지 않은 파일은 Release 모드에서 사용하는 파일입니다.

 

 

그럼 이제 아래와 같이 간단한 메인 함수를 작성하고 빌드 후 실행해보도록 하겠습니다.

#include <iostream>
#include "opencv2/opencv.hpp"

int main(int argc, char* argv[])
{
    std::cout << "Hello OpenCV " << CV_VERSION << std::endl;

    return 0;
}

line 2에서 OpenCV에서 사용하는 다양한 클래스와 함수가 선언되어 있는 opencv.hpp 헤더 파일을 include합니다. OpenCV 헤더 파일들은 opencv2라는 이름의 폴더 내에 존재하기 때문에 'opencv2/opencv.hpp' 형태로 입력합니다.

 

제가 설치한 OpenCV 버전은 4.5.5이기 때문에 아래와 같이 출력하게 됩니다.

 


간단한 튜토리얼

이번에는 간단하게 이미지 한 장을 읽어서 화면에 나타내는 방법을 살펴보겠습니다.

 

OpenCV에서 이미지나 영상 데이터는 Mat 클래스를 사용해 표현합니다. Mat 클래스는 다양한 자료형의 행렬을 표현하는 general 행렬 클래스입니다. 이미지는 0부터 255까지의 정수값을 가지는 이차원 행렬로 표현할 수 있으므로 따라서 Mat으로 표현할 수 있습니다.

 

임의의 사진 한 장을 입력받아 화면에 출력하는 소스 코드는 다음과 같습니다.

#include <iostream>
#include "opencv2/opencv.hpp"

int main(int argc, char* argv[])
{
    std::cout << "Hello OpenCV " << CV_VERSION << std::endl;

    std::string img_path{ "lena.png" };
    cv::Mat img = cv::imread(img_path, cv::IMREAD_COLOR);

    if (img.empty()) {
        std::cout << "Could not read the image\n";
        return -1;
    }

    cv::namedWindow("image");
    cv::imshow("image", img);

    cv::waitKey(0);

    return 0;
}

이를 실행하면 다음과 같이 출력됩니다.

간단히 코드를 살펴보면 line 9에서 Mat 클래스 타입의 변수 img를 선언하고 OpenCV에서 제공하는 imread() 함수를 사용해 lena.png 파일을 불러와 img 변수에 저장합니다.

아래 line 11-14 코드는 lena.png 파일을 제대로 불러오지 못한 경우에 대한 예외 처리 코드입니다. 디렉토리에 해당 이미지 파일이 존재하지 않거나 파일이 손상되어 제대로 불러오지 못한 경우 Mat 클래스 멤버 함수 empty()는 true를 반환합니다.

line 16의 namedWindow() 함수를 이용하면 이미지를 화면에 나타내기 위한 새로운 창을 생성하고, 그 창의 이름을 'image'로 부여합니다. 위의 스크린샷에서는 이미지 창이 너무 작아서 해당 이름이 나타나진 않고 있습니다.

그리고 line 17에서 imshow() 함수를 사용해 'image'라는 이름의 창에 img 변수가 가지고 있는 lena.png의 이미지를 출력합니다.

line 19의 waitKey() 함수는 사용자 키보드 입력을 기다리는 함수이며, 사용자가 키보드 입력을 누르기 전까지 출력한 이미지를 화면에 계속 나타나게 해줍니다. 사용자가 아무 키나 누르면 line 19를 지나 return 하며 프로그램이 종료됩니다.

 

마지막으로 위의 튜토리얼에서 사용된 함수와 주로 사용되는 간단한 함수 몇 가지를 살펴보고 포스팅을 마무리하겠습니다.

imread()

가장 먼저 소개할 함수는 imread() 함수입니다. 이 함수는 이미지 파일을 불러올 때 사용합니다. 함수 원형은 다음과 같습니다.

Mat imread( const String& filename, int flags = IMREAD_COLOR );
  • filename: 불러올 이미지 파일 이름
  • flags: 옵션 플래그. ImreadModes enum 상수를 지정

imread() 함수는 이미지 파일을 불러와 Mat 객체로 변환하여 반환합니다.

두 번째 인자인 flags는 파일을 읽을 때 사용할 컬러 모드 등을 지정할 수 있으며 아래와 같은 모드가 존재합니다.

//! Imread flags
enum ImreadModes {
       IMREAD_UNCHANGED            = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). Ignore EXIF orientation.
       IMREAD_GRAYSCALE            = 0,  //!< If set, always convert image to the single channel grayscale image (codec internal conversion).
       IMREAD_COLOR                = 1,  //!< If set, always convert image to the 3 channel BGR color image.
       IMREAD_ANYDEPTH             = 2,  //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
       IMREAD_ANYCOLOR             = 4,  //!< If set, the image is read in any possible color format.
       IMREAD_LOAD_GDAL            = 8,  //!< If set, use the gdal driver for loading the image.
       IMREAD_REDUCED_GRAYSCALE_2  = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2.
       IMREAD_REDUCED_COLOR_2      = 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2.
       IMREAD_REDUCED_GRAYSCALE_4  = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4.
       IMREAD_REDUCED_COLOR_4      = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4.
       IMREAD_REDUCED_GRAYSCALE_8  = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8.
       IMREAD_REDUCED_COLOR_8      = 65, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8.
       IMREAD_IGNORE_ORIENTATION   = 128 //!< If set, do not rotate the image according to EXIF's orientation flag.
     };

 

imwirte()

Mat 객체에 저장되어 있는 데이터를 파일로 저장하려면 imwirte() 함수를 사용합니다. 함수 원형은 다음과 같습니다.

bool imwrite( const String& filename, InputArray img,
              const std::vector<int>& params = std::vector<int>());
  • filename: 저장할 파일 이름
  • img: 저장할 데이터(Mat 객체)
  • params: 저장할 데이터 포맷에 의존하는 파라미터(플래그 & 값)
  • 반환값: 정상적으로 저장되면 true, 실패하면 false 반환

여기서 params에는 저장할 파일 포맷에 의존적인 별도의 옵션들을 지정할 수 있습니다. std::vector<int> 타입으로 지정하며, 옵션 플래그와 실제 값을 정수 값 두 개의 쌍으로 지정해야 합니다. 예를 들면, img 변수에 저장된 데이터를 jpg로 저장할 때 압축률을 95%로 지정하고 싶다면 다음과 같이 작성합니다.

std::vector<int> params;
params.push_back(IMWRITE_JPEG_QUALITY);
params.push_back(95);
imwrite("lena.jpg", img, params);

 

사용할 수 있는 플래그는 다음과 같습니다.

//! Imwrite flags
enum ImwriteFlags {
       IMWRITE_JPEG_QUALITY        = 1,  //!< For JPEG, it can be a quality from 0 to 100 (the higher is the better). Default value is 95.
       IMWRITE_JPEG_PROGRESSIVE    = 2,  //!< Enable JPEG features, 0 or 1, default is False.
       IMWRITE_JPEG_OPTIMIZE       = 3,  //!< Enable JPEG features, 0 or 1, default is False.
       IMWRITE_JPEG_RST_INTERVAL   = 4,  //!< JPEG restart interval, 0 - 65535, default is 0 - no restart.
       IMWRITE_JPEG_LUMA_QUALITY   = 5,  //!< Separate luma quality level, 0 - 100, default is 0 - don't use.
       IMWRITE_JPEG_CHROMA_QUALITY = 6,  //!< Separate chroma quality level, 0 - 100, default is 0 - don't use.
       IMWRITE_PNG_COMPRESSION     = 16, //!< For PNG, it can be the compression level from 0 to 9. A higher value means a smaller size and longer compression time. If specified, strategy is changed to IMWRITE_PNG_STRATEGY_DEFAULT (Z_DEFAULT_STRATEGY). Default value is 1 (best speed setting).
       IMWRITE_PNG_STRATEGY        = 17, //!< One of cv::ImwritePNGFlags, default is IMWRITE_PNG_STRATEGY_RLE.
       IMWRITE_PNG_BILEVEL         = 18, //!< Binary level PNG, 0 or 1, default is 0.
       IMWRITE_PXM_BINARY          = 32, //!< For PPM, PGM, or PBM, it can be a binary format flag, 0 or 1. Default value is 1.
       IMWRITE_EXR_TYPE            = (3 << 4) + 0, /* 48 */ //!< override EXR storage type (FLOAT (FP32) is default)
       IMWRITE_EXR_COMPRESSION     = (3 << 4) + 1, /* 49 */ //!< override EXR compression type (ZIP_COMPRESSION = 3 is default)
       IMWRITE_WEBP_QUALITY        = 64, //!< For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used.
       IMWRITE_PAM_TUPLETYPE       = 128,//!< For PAM, sets the TUPLETYPE field to the corresponding string value that is defined for the format
       IMWRITE_TIFF_RESUNIT = 256,//!< For TIFF, use to specify which DPI resolution unit to set; see libtiff documentation for valid values
       IMWRITE_TIFF_XDPI = 257,//!< For TIFF, use to specify the X direction DPI
       IMWRITE_TIFF_YDPI = 258, //!< For TIFF, use to specify the Y direction DPI
       IMWRITE_TIFF_COMPRESSION = 259, //!< For TIFF, use to specify the image compression scheme. See libtiff for integer constants corresponding to compression formats. Note, for images whose depth is CV_32F, only libtiff's SGILOG compression scheme is used. For other supported depths, the compression scheme can be specified by this flag; LZW compression is the default.
       IMWRITE_JPEG2000_COMPRESSION_X1000 = 272 //!< For JPEG2000, use to specify the target compression rate (multiplied by 1000). The value can be from 0 to 1000. Default is 1000.
     };

 

namedWindow()

이 함수는 데이터를 화면에 출력하기 전에 먼저 출력을 위한 빈 창을 생성합니다. 이 함수의 원형은 다음과 같습니다.

void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE);
  • winname: 창의 고유 이름. 이 문자열로 창을 구분함
  • flags: 생성되는 창의 속성을 지정하는 플래그. WindowsFlags enum의 상수들을 사용

OpenCV에서는 각각의 창에 고유한 문자열을 부여하여 구분합니다. winname으로 지정한 고유 이름은 실제 생성되는 창의 상단 제목 표시줄에 출력됩니다.

 

두 번째 인수 flags는 창의 속성을 지정하는 용도로 사용되는데, 사용되는 상수값들은 다음과 같습니다.

//! Flags for cv::namedWindow
enum WindowFlags {
       WINDOW_NORMAL     = 0x00000000, //!< the user can resize the window (no constraint) / also use to switch a fullscreen window to a normal size.
       WINDOW_AUTOSIZE   = 0x00000001, //!< the user cannot resize the window, the size is constrainted by the image displayed.
       WINDOW_OPENGL     = 0x00001000, //!< window with opengl support.

       WINDOW_FULLSCREEN = 1,          //!< change the window to fullscreen.
       WINDOW_FREERATIO  = 0x00000100, //!< the image expends as much as it can (no ratio constraint).
       WINDOW_KEEPRATIO  = 0x00000000, //!< the ratio of the image is respected.
       WINDOW_GUI_EXPANDED=0x00000000, //!< status bar and tool bar
       WINDOW_GUI_NORMAL = 0x00000010, //!< old fashious way
    };

flags의 기본값은 WINDOW_AUTOSIZE이기 때문에 이 값을 지정하지 않으면 만들어진 창의 크기는 자동으로 데이터에 맞게 조정됩니다. 만약 모니터 해상도보다 큰 이미지를 화면에 출력하려고 하는 경우에는 이미지의 일부가 화면에 표시되지 않을 수 있습니다. 만약 새로 생성한 창의 크기를 마우스 또는 resizeWindow() 함수를 이용해 변경하고 싶다면 flags 인수에 WINDOW_NORMAL을 지정해주어야 합니다.

 

 

추가로 namedWindow() 함수에 의해 생성된 출력 창은 destroyWindow() 또는 destroyAllWindows() 함수를 이용해 닫을 수 있습니다.

void destroyWindow(const String& winname);
void destroyAllWindows();

 

imshow()

이 함수는 Mat 클래스 객체에 저장된 데이터를 화면에 출력합니다. 함수 원형은 다음과 같습니다.

void imshow(const String& winname, InputArray mat);

imshow()는 winname 창에 mat 인수로 전달된 데이터를 출력합니다. 만약 mat 객체에 전달된 데이터가 1채널 8비트 uchar 타입이라면 픽셀값을 그대로 그레이스케일 밝기 형태로 출력합니다. 만약 저장된 데이터가 uchar 타입을 사용하는 3채널 컬러 영상이라면 색상 채널이 BGR 순서로 되어 있다고 간주하여 색상을 표현합니다. 만약 mat 객체가 부호없는 16비트 또는 32비트 정수형이라면 행렬 원소 값을 256으로 나눈 값을 영상의 밝기 값으로 사용합니다. 반면 mat 객체가 32비트 또는 64비트의 실수형 행렬이라면 행렬 원소에 255를 곱한 값을 밝기 값으로 사용합니다.

 

여기서 imshow 함수의 두 번째 인수가 InputArray 타입이라는 것이 조금 특이한데, InputArray 타입은 Mat, vector<T> 등 다양한 객체를 표현할 수 있는 인터페이스 클래스이며, 주로 OpenCV 함수 입력에 해당하는 인수의 자료형으로 사용됩니다. 인수 타입이 InputArray라고 되어 있으면, 대부분 Mat 클래스 타입의 변수를 전달한다고 생각해도 무방합니다. InputArray에 대한 내용은 다음에 알아보겠습니다.

 

만약 imshow()가 호출되는 시점에 winname에 해당되는 창이 없다면 imshow() 함수가 자동으로 해당 창을 WINDOW_AUTOSIZE 속성으로 생성하여 출력합니다. 참고로 Win OS에서는 Ctrl+C를 눌러 출력 창에 나타난 데이터를 비트맵 형식으로 클립보드에 복사할 수 있고, Ctrl+S를 눌러 파일 형태로 저장할 수 있습니다.

 

waitKey()

이 함수는 사용자로부터 키보드 입력을 받는 용도로 사용됩니다. 원형은 다음과 같습니다.

int waitKey(int delay = 0);
  • delay: 키 입력을 기다릴 시간(ms 단위). delay <= 0이면 무한히 기다림
  • 반환값: 눌린 키의 값. 지정한 시간 동안 키가 눌리지 않았으면 -1 반환

이 함수를 호출한 뒤 지정한 delay 시간 동안 키 입력이 있으면 해당 키의 아스키 코드 값을 반환합니다.

사실 이 함수는 키 입력을 기다리는 것 외에 더 중요한 기능이 하나 숨어 있습니다. 위에서 imshow() 함수가 이미지를 화면에 출력하는 함수라고 언급했는데 실제로 imshow() 함수만 사용하면 이미지가 화면에 나타나지 않으며, imshow()를 호출한 후 waitKey() 함수를 호출해야만 화면 그리기 이벤트가 동작하여 이미지가 화면에 정상적으로 출력됩니다.

댓글