반응형

Computer Vision 이미지 자료형

배경

Python2 시절까지만 해도 성능을 중요시했던 컴퓨터 비젼 분야는 오랫동안 C/C++ 계열이 메인이었는데, 지금은 컴퓨터 비젼을 한다면 Python도 필수로 해야 하는 시대가 되었다. 이건 딥러닝 파급의 효과가 가장 컸다. 다만, 최근에 내가 놓친 부분을 알기위해서 빠른 지식 습득 수단으로 강의를 듣고 있는데, 강의에서도 그렇고 회사에서 기술이전으로 로봇공학쪽 박사 포닥중인 강의 하시는 분도 그렇고 그냥 다르니 주의해라는 듯이 설명해서 내 입장에서는 난감했다. 사실 본래 자료형이 만들어진 목적이 있기 때문이다.

그래서 끄적여 본다.

Python 이미지 처리 모듈

기본적으로 이미지의 첫 출발은 이미지를 메모리에 올리는 것 부터 시작이 된다. Python 에서는 대표적인 모듈이 3가지가 존재한다. PIL, Scikit Image, OpenCV. 이중에서 현재는 OpenCV를 많이 사용하고 있다.다만, 대부분 이 라이브러리들은 이미지 파일을 로드하게 되면 numpy 모듈의 array로 로드를 하는 특징이 있다.

PIL

Python Image Library 로 초기 Python 영상처리 많이 사용했다. 필자도 OpenCV 보다 PIL 을 주로 썼었는데, 이는 OpenCV의 경우 BGR로 로드하는 반면 이 라이브러리는 RGB로 로드가 되었기 때문에 이런 변환 코드를 덜짜기 위해서 썼었다. 파이썬은 성능보다 생산성을 추구하였으니 말이다. 문제는 PIL 이 현재는 유지보수가 잘 안되고 있다. 지금의 PIL는 fork 된 프로젝트 중에서 호환만 경우 유지되고 있는 수준이다.

Scikit Image

Scipy 기반으로 제공되는 라이브러리이다. Scipy는 SCI 이름에서 알 수 있듯이 연구 용도로 많이 사용한다. 경우에 따라 Scipy 는 상당히 높은 수준의 연산을 도와주는 모듈들이 있다. 그러나 필자를 포함해서 널리 사용되지는 않는 것 같다.

OpenCV

인텔에서 개발하다가 오픈 소스로 전환된 라이브러리다. 이미지 로드시 BGR로 메모리에 올라가는 것을 특징으로 갖는데 이는 초기에 성능을 위해서 인텔 CPU가 리틀엔디안 방식으로 데이터를 처리하기 때문에 일부러 뒤집은 탓이다. OpenCV1 시절은 C, OpenCV2 시절은 C/C++, OpenCV3 에서는 Java/Python 이런식으로 확장되어 왔다. Mat 이라는 자체 이미지 자료구조를 가지고 있었는데, Python 에서는 numpy.array 자료구조를 사용한다.

개인적으로 numpy.array로 로드 되는 것을 처음 알았을 때는 기존 Mat 보다 이미지 정보가 적어서 불편하다 생각했지만, 수학적인 연산도 자연스럽게 사용할 수 있었고 그렇지 않아도 느린 버전업이 빨라 졌다. 즉 버그 픽스가 빨라졌다는 것이다. numpy 경우 Matlab 처럼 멀티 스레드로 메트릭스 연산을 하기 때문에 C로 단일 스레드로 연산한것 보다 빠르다.

numpy.array

numpy 모듈은 태생이 수학자들이 만든 C로 만들어진 모듈들이다. Python 이 런타임이 느린 언어이지만, 이 모듈로 간단히 몇 줄로 크게 뒤지지 않는 병렬 계산이 가능하다. 게다가 구조도 직관적이기도 하다.

다만 문제는 태생이 메트릭스 연산을 위해서 탄생한 구조이다보니 나중에 컴퓨터 비젼관련 라이브러리에서 다룰때 종종 헷깔리게 된다. 이미지에서의 크기의 개념은 (가로 x 세로)이나 메트릭스에서는 (행, 열) 개념이기 때문이다. 이미지의 값을 numpy에 넣게되면 (세로, 가로) 느낌으로 사용하게 된다.

이때문에 초보자들은 여기서 많이 틀린다. 문제는 내가 모든 강의를 들은 것은 아니지만 대부분 주의 하고 외우세요 하면서 가르치시더라. 태생이 원래 수학적 접근의 차이라 다른것 뿐이지만 말이다. 사실 각 모듈의 태생의 목적을 알면 헷깔릴 일이 별로 없다. 깜박해도 금방 생각날테니 말이다.

그렇다 이 말 하려고 어그로 끌었다. "모듈의 태생을 알면 이유를 알 수 있다"

이제 배경을 알았으니 array shape을 받을 때 rows, cols, dim = np.array().shape 형태로 사용하는 것이 좀 더 덜 헷깔릴 것이다. 작지만 유용한 팁이라 할 수 있다.

덤 OpenCV 가 cv2 인 이유

덤으로 이글을 쓰는 시기에 OpenCV4가 사용되고 있다. 그럼에도 Python 에서는 cv2 라는 모듈 네임을 사용하고 있다. 대체 왜 그럴까? cv2 부터 C++이 도입되면서 OpenCV 코드들이 객체화가 되었다. 그리고 Mat 이라는 class 를 사용했었는데, Python 에서는 Mat 대신 numpy를 사용하지만, 둘이 사용법이 비슷하고 굳이 cv3 처럼 올릴 필요가 없다. 객체지향으로 개발하는 이유가 원래 이런 것들을 유지하려고 했던것이 아니었겠는가? 그리고 성능을 위해서 알고리즘은 여전히 C++로 구현되고 Java를 포함해서 Python에 wrapper 된 경우도 많다. 그리고 CV2라는 네임스페이스는 C++이 쓰는 것 아니었는가?

반응형

+ Recent posts