라이브러리, OpenCV

BananaCube·2023년 3월 1일

OpenCV에 대해 알아보기 전에
OpenCV는 정적 라이브러리와 동적 라이브러리 두 가지 형태로 제공되지만
필자는 정적 라이브러리와 동적 라이브러리가 뭔지 모르기 때문에 동적 라이브러리, 정적 라이브러리가 무엇인지 먼저 알아보겠습니다.


정적 라이브러리와 동적 라이브러리는 모두 소프트웨어 개발에서 자주 사용되는 라이브러리 유형입니다.

정적 라이브러리

  • 컴파일 시에 프로그램 코드에 포함되어 실행 파일의 일부가 됨
  • 프로그램이 실행될 때 라이브러리를 별도로 로드할 필요가 없음

장점

  • 프로그램 실행 속도가 동적 라이브러리보다 빠름
  • 라이브러리와 프로그램 간의 인터페이스가 안정적임
  • 응용 프로그램이 다른 컴퓨터에서 실행될 때 라이브러리 버전 충돌 문제가 발생하지 않음

단점

  • 프로그램 실행 파일의 크기가 커짐

동적 라이브러리

  • 프로그램이 실행될 때 필요한 라이브러리만 별도로 로드하여 사용

장점

  • 실행 파일의 크기를 줄일 수 있음
  • 라이브러리를 공유하여 메모리를 절약
  • 라이브러리가 업데이트될 때 응용 프로그램을 다시 컴파일할 필요 없이 라이브러리만 업데이트할 수 있음

단점

  • 프로그램 실행 속도가 느림
  • 라이브러리와 프로그램 간의 인터페이스 문제가 발생할 수 있음
  • 다른 컴퓨터에서 실행될 때 라이브러리 버전 충돌 문제가 발생할 수 있음

따라서 정적 라이브러리는 안정성과 속도에 중점을 둔 응용 프로그램에 적합하고, 동적 라이브러리는 유연성과 효율성에 중점을 둔 응용 프로그램에 적합합니다.


*.dll, *.lib 그리고 *.h

*.dll, *.lib, *.h는 C/C++ 프로그램에서 외부 라이브러리를 사용하는 데 필요한 파일들입니다.

  • 동적 라이브러리 파일입니다. 여러 프로그램에서 공유해서 사용할 수 있는 코드의 집합으로, 프로그램 실행 시 필요한 함수들이 동적으로 로드되어 사용됩니다.

*.dll을 사용하는 이유

  1. 메모리 절약
    여러 프로그램에서 동일한 라이브러리를 사용할 경우, 이 라이브러리는 하나만 메모리에 로드되고, 모든 프로그램에서 이 라이브러리를 참조할 수 있습니다. 따라서 메모리 사용량이 줄어들고, 시스템 성능이 향상됩니다.
  2. 코드의 재사용
    동적 라이브러리를 사용하면 여러 프로그램에서 동일한 코드를 중복해서 작성하지 않아도 되므로, 코드의 재사용성이 높아집니다. 이는 개발 비용과 시간을 절약하는 데 큰 도움이 됩니다.
  3. 라이브러리 업데이트
    동적 라이브러리를 사용하면 라이브러리가 업데이트될 때 응용 프로그램을 다시 컴파일할 필요 없이 라이브러리만 업데이트할 수 있습니다. 이는 프로그램 유지보수에 매우 유용합니다.
  4. 유연성
    동적 라이브러리를 사용하면 프로그램이 실행될 때 필요한 라이브러리를 동적으로 로드할 수 있으므로, 프로그램의 유연성이 높아집니다. 이는 플러그인 시스템 등에서 매우 유용합니다.

*.lib (Library)

정적 라이브러리 파일입니다. 라이브러리를 사용하는 프로그램과 함께 링크되어 실행 파일에 포함됩니다. 따라서 프로그램 실행 시 라이브러리를 별도로 로드할 필요가 없습니다.

*.lib를 사용하는 이유

  1. 실행속도
    정적 라이브러리를 사용하면 라이브러리의 함수나 코드가 실행 파일에 포함되므로, 프로그램이 실행될 때 라이브러리를 별도로 로드할 필요가 없습니다. 따라서 실행 속도가 빨라집니다.
  2. 안정성
    정적 라이브러리를 사용하면 라이브러리와 프로그램 간의 인터페이스가 안정적이며, 라이브러리 버전 충돌 문제가 발생하지 않습니다. 따라서 안정성이 높아집니다.
  3. 배포
    정적 라이브러리를 사용하면 라이브러리 파일이 프로그램 실행 파일에 포함되므로, 라이브러리 파일을 따로 배포할 필요가 없습니다. 이는 프로그램 배포를 간편하게 할 수 있도록 도와줍니다.
  4. 플랫폼 호환성
    정적 라이브러리를 사용하면 프로그램이 실행될 때 필요한 라이브러리가 없어도 실행이 가능합니다. 따라서 플랫폼 호환성이 높아집니다.
  5. 이식성
    정적 라이브러리를 사용하면 라이브러리를 소스 코드와 함께 배포할 수 있으므로, 이식성이 높아집니다.

*.h (Header)

헤더 파일입니다. 라이브러리에서 제공하는 함수와 변수 등의 정보를 선언하는 파일로, 프로그램에서 해당 라이브러리의 기능을 사용하기 위해 필요한 정보를 제공합니다.


OpenCV

OpenCV란?

OpenCV는 컴퓨터 비전 및 이미지 처리 분야에서 사용되는 라이브러리로, 영상 처리, 물체 인식, 얼굴 인식 등 다양한 컴퓨터 비전 기능을 제공합니다. C++, Python, Java 등의 언어에서 사용할 수 있으며, 오픈 소스로 제공되어 있어 무료로 사용할 수 있습니다. OpenCV는 컴퓨터 비전 분야에서 널리 사용되는 라이브러리 중 하나이며, 영상 처리, 컴퓨터 비전 및 머신 러닝 등 다양한 분야에서 활용됩니다.

간단한 이미지 창 띄우는 예제

// 현재 사용하고 있는 OpenCV 라이브러리 버전 출력
std::cout << "OpenCV version : " << MessageBox(_T(CV_VERSION)) << std::endl;

// OpenCV에서 이미지를 다루기 위한 Mat 클래스 객체 img 생성
cv::Mat img;

// 이미지 파일을 읽어서 img 객체에 저장
img = cv::imread("Test-shinho-0301-2.bmp");

// 이미지 파일이 정상적으로 로드되지 않았을 때 예외 처리
if (img.empty())
{
	// 에러 메시지 출력
	MessageBox(_T("Image load failed"));
	return;
}

// 윈도우 창 생성
cv::namedWindow("image");

// img 객체에 저장된 이미지를 윈도우 창에 출력
cv::imshow("image", img);

// 키 입력을 기다리며 윈도우 창이 유지되도록 함
cv::waitKey();

결과 화면

예제 코드에서 사용된 함수들 원형

cv::imread()

이미지 파일을 읽어서 Mat 클래스 객체로 반환합니다.
cv::Mat cv::imread(const String& filename, int flags = cv::IMREAD_COLOR)
imread 함수의 인자로는 이미지 파일의 경로와 파일 형식에 대한 정보를 전달합니다.
filename 인자는 읽어들일 이미지 파일의 경로와 파일 이름을 문자열 형태로 전달합니다.
flags 인자는 이미지 파일을 읽어들일 때 사용할 옵션을 전달합니다. 기본값은 IMREAD_COLOR으로, 이미지 파일을 컬러 이미지로 읽어들입니다. 이외에도 IMREAD_GRAYSCALE, IMREAD_UNCHANGED 등의 다양한 옵션이 있습니다.
imread 함수는 읽어들인 이미지를 Mat 클래스 객체로 반환합니다. 반환된 객체는 읽어들인 이미지의 픽셀 데이터를 가지고 있습니다.

Mat::empty()

Mat 객체가 비어있는지 여부를 반환합니다. 객체가 비어있으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.
bool Mat::empty() const
empty() 메서드는 객체가 초기화되었거나, 메모리 할당에 실패했을 때 등에 유용하게 사용될 수 있습니다. 예를 들어, imread() 함수로 이미지를 읽어들인 후, 해당 이미지가 비어있는지 여부를 empty() 메서드로 확인하여 예외 처리를 수행할 수 있습니다.

cv::namedWindow()

윈도우 창을 생성합니다.
void cv::namedWindow(const String& winname, int flags = cv::WINDOW_AUTOSIZE)
winname: 생성할 윈도우 창의 이름을 전달합니다.
flags: 윈도우 창의 속성을 전달합니다. 기본값은 WINDOW_AUTOSIZE로, 윈도우 창 크기가 이미지 크기에 맞게 자동으로 조정됩니다. WINDOW_NORMAL, WINDOW_FULLSCREEN, WINDOW_OPENGL 등의 다양한 속성을 사용할 수 있습니다.
namedWindow() 함수를 호출하면, 지정한 이름을 가진 새로운 윈도우 창이 생성됩니다. 만약 같은 이름을 가진 윈도우 창이 이미 존재하는 경우, 해당 윈도우 창을 찾아내어 활성화합니다.
생성된 윈도우 창은 imshow() 함수로 이미지를 출력할 때 사용됩니다. imshow() 함수의 첫 번째 인자로 윈도우 창의 이름을 전달하면, 해당 윈도우 창에 이미지가 출력됩니다.

cv::imshow()

이미지를 화면에 출력합니다.
void cv::imshow(const String& winname, cv::InputArray mat)
winname: 출력할 윈도우 창의 이름을 전달합니다.
mat: 출력할 이미지를 cv::Mat 클래스 객체로 전달합니다.
imshow() 함수를 호출하면, 지정한 이름을 가진 윈도우 창에 이미지가 출력됩니다. 이미지 출력 후, 사용자의 입력을 대기하기 위해 waitKey() 함수를 호출해야 합니다.
주의할 점은 imshow() 함수의 두 번째 인자로 전달되는 이미지는 cv::Mat 클래스 객체 뿐만 아니라, cv::UMat, cv::MatExpr, cv::cuda::GpuMat 등의 다양한 형태로 전달될 수 있다는 것입니다.

waitKey()

입력된 키보드 이벤트를 처리합니다.
int cv::waitKey(int delay = 0)
delay: 키 입력 대기 시간을 밀리초 단위로 전달합니다. 기본값은 0으로, 무한정 대기합니다.
waitKey() 함수를 호출하면, 지정한 시간 동안 사용자의 입력을 대기합니다. 사용자가 키를 입력하면 해당 키의 ASCII 코드값이 반환됩니다. 입력된 키의 코드값이 없으면 -1을 반환합니다.
waitKey() 함수를 호출하는 이유는, imshow() 함수로 출력된 이미지가 화면에 보여지도록 하기 위해 사용자 입력을 대기해야 하기 때문입니다. waitKey() 함수는 이벤트 루프에서 사용되며, 대기하는 동안 다른 이벤트를 처리할 수 있도록 해 줍니다. 대기 시간이 0일 경우, 사용자 입력을 기다리지 않고 즉시 종료됩니다.

ESC 키로 창 닫기 예제

while (true)
{
	int key = cv::waitKey(1); // 1ms 대기 후 사용자 입력 대기

	if (key == 27) // ESC 키가 눌리면
	{
		cv::destroyAllWindows(); // 모든 윈도우 창 닫기
		break; // 루프 종료
	}
}

destroyAllWindows()

모든 윈도우 창을 닫습니다.
void cv::destroyAllWindows()
destroyAllWindows() 함수를 호출하면, 현재 생성된 모든 윈도우 창을 닫습니다. 이 함수는 namedWindow() 함수로 생성한 모든 윈도우 창을 닫으며, createWindow() 함수로 생성한 윈도우 창은 닫지 않습니다.

(이어서...)

출처 :
1. https://www.vbflash.net/193
2. https://velog.io/@msj0130/OpenCV-C-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%B6%9C%EB%A0%A5%ED%95%B4%EB%B3%B4%EA%B8%B0

profile
C++ 독학한 내용을 정리하는 벨로그입니다.

0개의 댓글