--- 목차 ----------

    1. 라즈베리파이 4/400 OpenCV 4.6.0 설치 : https://makeutil.tistory.com/207

    [현재 글] 이미지 파일 출력 (png, jpg, bmp) : https://makeutil.tistory.com/212

    3. 웹카메라를 이용한 영상 출력 : https://makeutil.tistory.com/220 

    4. 웹카메라를 이용한 영상 저장 : https://makeutil.tistory.com/221 

    5. 웹카메라로 저장한 미디어파일(.mp4) 출력 : https://makeutil.tistory.com/222 

    --------------------

     

     

        OpenCV를 사용하는 이유는 단순하다. 운영체제(리눅스/윈도우 뿐만 아니라 안드로이드까지)를 가리지 않고 간단한 코드 만으로 손쉽게 이미지를 처리할 수 있기 때문이다. 

     

    필자는 영상처리 관련 프로그래밍을 C로 배웠다. 논문을 구해서 공부하기도 했다. 물론, 그 논문의 공식이 말하고자 하는 것을 완벽하게 이해하고 했다고는 할수 없지만 말이다. 어쨋든 카메라 영상을 받아와서 화면에 출력하는 코드만해도 그리 손쉽게 만들수는 없었다. 그러던중 OpenCV를 이용해서 개발하는 사람들을 봤는데,  PC가 아닌 임베디드(PXA255, 200~400Mhz)에서 하니 너무 느려서 사용이 어려웠지만말이다. 

     

      세상이 변하고 임베디드 시스템도 성능이 비약적으로 발전해버렸다. 웬만한 임베디드에서는 OpenCV를 이용하더라도 느리지가 않으니 굳이 어려운 영상처리 부분을 모두 공부할 필요가 있을까? C코드로만 작성하면 웹캡으로 영상하나 출력하는 코드만 짜도 대략 500라인은 우습게 넘어간다. 더군다나 기능이나 성능을 위해서 작업한다면 더더욱 늘어나는데, OpenCV를 쓰면 몇줄로 구현이 가능하니까 말이다. 

     

      필자의 개인적인 생각으로는, 영상처리 자체를 처음부터 공부해야하는 친구들이라면 영상처리 관련 서적을 통해서 충분히 학습하고, 코딩해서 결과도 확인한 후에 OpenCV를 사용하는 것을 추천한다. 하지만, 단시간에 결과를 내야하는 분이라면 자료도 많고 검색도 잘되는 코드가 다양한 OpenCV를 통해 빠르게 결과를 만드는 것을 추천하겠다. 

     

      우선 간단한 예제로 한번 확인해보자. 필자가 얼마전 문을 닫은 emnbeddedclub.net에보면 영상 파일별로 ppm, bmp 헤더 처리하는 방법과 jpg 파일을 처리하는 방법에대해서 다룬 게시물이 있었따. 본 블로그에도 일부는 옮겨두었다. 만약, 임베디드 시스템이 있고 운영체제를 사용하지 못하는 상황이라면 그러한 라이브러리 또는 영상파일의 헤더를 보고 데이터를 RAW(Red, Green, Blue로 구성된 원시데이터)값으로 변환 후 LCD 출력을 위한 장치(프레임버퍼)에 기록하면 화면에 표시가 된다. 독자들이 그러한 열악한 시스템에서 처리하는 경우는 회사에 입사한 이후가 될것이고, 배우는 상황에서는 대부분 임베디드 시스템을 사용하더라도 GUI가 있는 리눅스나 안드로이드 쯤 될가능성이 높다. 그래서 필자는 라즈베리파이에서 OpenCV를 통해서 여러 예제를 소개하고자 한다. 

     

    1. 영상 파일을 만들자.

    독자 여러분들은 인터넷에서 여러가지 포맷의 이미지 파일을 다운로드 하여 예제를 작성하면된다. 필자는 좀 찝찝해서 파워포인터를 통해서 이미지 파일 3종류를 만들었다.

    1.1. 이미지 파일 생성과정

      파워포인트에서 대충 그려서, 블록으로 선택후 이미지 파일 저장을 눌러 저장하면된다. 다만, BMP파일은 블록으로 복사해서 그림판에 붙혀서 저장했다. 메뉴에서 찾기가...

     

    1) 파워포인트에서 아래처럼 대충 그려서

      생각보다 이쁘다. 그리고 글자색은 색상에 맞춰서 배치하여 은은함을..

     

    2) 저장할 때 포맷을 잘 지정해준다.

        JPEG하고 PNG는 각각 이렇게 저장하고한다. 

     

    다만, 비트맵 파일(BMP)를 저장하려하니 항목이 와닿지 않아서, BMP 파일은 그림판을 열어서 별도로 저장하였다. 

    1.2. 파일 복사

      해당 파일을 라즈베리파이에 넣어두자. 넣어둔 위치는 다음과 같다. 파일을 옮기는 것은 USB메모리를 이용하거 네트워크등을 통해서 복사할 수 있다.  필자는 그냥 USB에 복사해서 디렉터리를 만들고 붙혀 넣었다.

     

     

    2. 소스 작성

      준비는 다 되었으니 이제 샘플 코드를 작성해 보자. 라즈베리파이에 opencv는 이미 설치하였다. 그래서 opencv 디렉터리 아래에 별도의 디렉터리를 만들고 3종류의 이미지 파일을 복사한 상태에서 라즈베리파이에서 터미널을 실행시켜서 이미지 파일이 있는 디렉터리로 이동 후 소스를 작성해 보자. 

     

    2.1. 작업디렉터리로 이동

     

    2.2. 소스코드

    // 오류처리를 대충 해놨음에 유의.

    #include <opencv2/opencv.hpp>

    int main(int argc, char** argv) 
    {

        int opt;     
     
        // OpenCV의 매트릭스 객체이다. 이 객체에 영상을 담을수 있고 기본적인 처리를 할 수있다. 
        cv::Mat imageFile;  

        opt=atoi(argv[1]);   // 파일 명령뒤의 숫자(0~2)를 읽어와서 변수에 저장한다.
        if(opt<0||opt>2)
        {
            printf("Option 1: png, 2: bmp, 3: jpeg");
            return -1;
        }

        switch(opt)  // 실행시 입력되는 인자에 따라 각각 다른이름의 다른포맷의 이미지를 읽어온다.
        {
            case 0 :
                imageFile = cv::imread("./red.png"); 
            break;
            case 1 :
                imageFile = cv::imread("./green.bmp"); 
            break;
            case 2 :
                imageFile = cv::imread("./blue.jpg"); 
            break;
            default:
                 break;
        }

        cv::imshow("Pciture Show", imageFile);   // 로드한 그림파일을 윈도우에 넣어서 화면에 출력한다.

        cv::waitKey(0);           // 아무키나 누르면 종료시킨다.

        cv::destroyAllWindows();  // t사용했던 리소스를 반납한다.

        return 0;
    }

     

    2.3. 컴파일

      다음과 같이 입력하여 컴파일 한다. 

      $ g++ -o  picture_show picture_show.cpp $(pkg-config opencv4 --libs --cflags)

     

    2.4. 실행결과 결과

      다음과 같이 결과를 확인할 수 있다. 필자는 0으로 입력했기에 png 파일이 출력됨을 알 수 있다. 다른 인자인 1과 2를 넣으면 그에 맞는 이미지가 표시된다.  종료하려면 출력 윈도우를 클릭하고 아무키나 누른다. 

      ./picture_show 0 (0~2까지 입력하여 결과를 확인해보자.)

     

     

      독자 여러분들이 직접 해보시며 알겠지만, Png의 경우 배경을 트랜스패런트로 지정하면 제거한 상태로 저장이된다. 그래서 위의 결과 화면과 같이 검게 나왔지만, jpeg나 bmp는 트랜스페런트 모드가 없으므로 흰색으로 채워짐을 알 수 있다. 이렇게 몇줄 적지 않아도 영상을 출력할 수 있다. 

     

      그냥 C코드로 작성한거 같으면 이미지 변환한 버퍼에서 행과 열로 3바이트씩 가져와서 점을 만들고, 행과 열로 반복하면서 출력해주어야 동일하게 출력할 수 있다. 그에 비하면 많이 쉽게 느껴지지 않는가? 

     

     

    아... 자야되는데..

    반응형
    • 네이버 블러그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기