태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

라즈베리파이에 웹캠 연결해서 비디오 덤프

Daily life/Hard study 2012. 12. 7. 23:22

# 목표: 동영상을 캡쳐한다

# 들어가기 전에
    * opencv 라이브러리 설치: sudo apt-get install libopencv-*
    * pyopencv 설치: sudo pip install pyopencv
    * Doc: http://docs.opencv.org/

    * OpenCV 튜토리얼: http://docs.opencv.org/doc/tutorials/tutorials.html
    * OpenCV Python: http://opencv.willowgarage.com/wiki/PythonInterface
    튜토리얼이 많이 부족하다. 아직 작업중인데, 당신이 쓸거면 연락달라고 쓰인걸로 봐서 한동안은 기대할 수 없을듯.


# Modules:
     * core
     * imgproc
     * video
     * calib3d
     * features2d
     * objdetect
     * highgui
     * gpu
     * and so on …


# API Concepts

    * 모든 클래스와 함수는 cv 이름공간 안에 있다.
    * OpenCV 는 메모리 해제를 스스로 한다. 레퍼런스 카운트 시스템이 있다.
    * 대부분의 경우 함수의 결과물에 대한 메모리 할당도 스스로 한다.
    * 라이브러리 전체적으로 Saturation arithmetic 사용
    * 템플릿은 좀 자제했음 - 파이썬, 자바 등 다른 언어로 바인딩을 쉽게하고 인터페이스/구현 분리를 잘 하기 위해
    * 편의성 및 중복 제거를 위해 InputArray, OutputArray 가 여기저기서 사용됨
    * OpenCV 는 예외를 사용한다 (derived from cv::Exception)
    * fully re-enterable


# How to capture video?

내가 필요한건 highgui(http://docs.opencv.org/modules/highgui/doc/highgui.html) 에 있는 것 같다.
highgui 문서 앞쪽에 보면 아래와 같은 설명이 있다.

   * Create and manipulate windows that can display images and “remember” their content (no need to handle repaint events from OS).
   * Add trackbars to the windows, handle simple mouse events as well as keyboard commands.
   * Read and write images to/from disk or memory.
   * Read video from camera or file and write video to a file.


cv::VideoCapture 클래스가 있다. 그리고 API 페이지(http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#videocapture)를 보니, python, C 인터페이스까지 나와 있다. C/C++ 인터페이스가 별도라는 데 주의. 일단 C++ 로 먼저 해본다.

VideoCapture 클래스로 웹캠에서 프레임을 얻어내고, 이렇게 얻어낸 프레임들을 imwrite 로 이미지파일로 각각 저장하거나 VideoWriter 을 사용해서 영상파일로 덤프하자.


# C++ 코드 컴파일

    * /usr/include/opencv, /usr/include/opencv2 이렇게 디렉토리가 두개다. opencv 는 이전 인터페이스를 하위호환성때문에 유지하는 듯. opencv2/opencv.hpp 를 가져다 쓰자.
    * 링크할 때 -lopencv_core -lopencv_highgui 이렇게 core 와 사용할(한) 모듈을 주어야 한다. -lopencv 이 아니다.


# Code

#include <cstdio>
#include <boost/format.hpp>
#include <opencv2/opencv.hpp>

int main(int, char**) {
    cv::VideoCapture cap(0);
    if (!cap.isOpened()) return -1;

    cv::Mat frame;
    for (int i=0; i<10; ++i) {
        cv::Mat image;
        while (!cap.read(image))
            usleep(1000*100);
        std::fprintf(stderr, "%d\n", i);
        cv::imwrite((boost::format("%05d.jpg") % i).str(), image);
    }
    return 0;
}

근데 망했다. 파일이 나오긴 나오지만 다 그냥 까만 화면이다. 카메라에 설정값이 뭔가 안좋은듯 하다. BRIGHTNESS, CONTRAST, SATURATION, GAIN 를 모두 적당한 값(중간값)으로 세팅해봐야겠다. 일단 지금 값을 확인하기 위한 함수를 하나 만들고 스케일에 맞춰 적당한 값을 넣자.



0~255 스케일이라고 생각했는데 0.0~1.0 스케일이다. 0.5 를 넣는다.

#include <cstdio>
#include <boost/format.hpp>
#include <opencv2/opencv.hpp>

void printProperties(cv::VideoCapture& cap) {
    fprintf(stdout, "CV_CAP_PROP_POS_MSEC    : %f\n", cap.get(CV_CAP_PROP_POS_MSEC));
    fprintf(stdout, "CV_CAP_PROP_FRAME_WIDTH : %f\n", cap.get(CV_CAP_PROP_FRAME_WIDTH));
    fprintf(stdout, "CV_CAP_PROP_FRAME_HEIGHT: %f\n", cap.get(CV_CAP_PROP_FRAME_HEIGHT));
    fprintf(stdout, "CV_CAP_PROP_FPS         : %f\n", cap.get(CV_CAP_PROP_FPS));
    fprintf(stdout, "CV_CAP_PROP_MODE        : %f\n", cap.get(CV_CAP_PROP_MODE));
    fprintf(stdout, "CV_CAP_PROP_BRIGHTNESS  : %f\n", cap.get(CV_CAP_PROP_BRIGHTNESS));
    fprintf(stdout, "CV_CAP_PROP_CONTRAST    : %f\n", cap.get(CV_CAP_PROP_CONTRAST));
    fprintf(stdout, "CV_CAP_PROP_SATURATION  : %f\n", cap.get(CV_CAP_PROP_SATURATION));
    fprintf(stdout, "CV_CAP_PROP_GAIN        : %f\n", cap.get(CV_CAP_PROP_GAIN));
    fprintf(stdout, "CV_CAP_PROP_HUE         : %f\n\n", cap.get(CV_CAP_PROP_HUE));
}

int main(int, char**) {
    cv::VideoCapture cap(0);
    if (!cap.isOpened()) return -1;

    printProperties(cap);
    cap.set(CV_CAP_PROP_BRIGHTNESS, 0.5);
    cap.set(CV_CAP_PROP_CONTRAST, 0.5);
    cap.set(CV_CAP_PROP_SATURATION, 0.5);
    cap.set(CV_CAP_PROP_GAIN, 0.5);
    cap.set(CV_CAP_PROP_FRAME_WIDTH, 160);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 120);
    printProperties(cap);

    cv::Mat frame;
    for (int i=0; i<10; ++i) {
        cv::Mat image;
        while (!cap.read(image))
            usleep(1000*100);
        std::fprintf(stderr, "%f\n", i);
        cv::imwrite((boost::format("%05d.jpg") % i).str(), image);
    }
    return 0;
}




select timeout 이 뜨면서 계속 까만 화면만 나온다. 구글링 결과 http://www.raspberrypi.org/phpBB3/viewtopic.php?f=37&t=11745 이런 페이지를 발견했다! 그리고 원래 잘 동작하던 uvccapture 로도 까만 스샷만 나오고 있다. 파이를 리붓해보자.



현재 라즈베리파이와 웹캠을 던져둔 방에 불이 꺼져서 어두운 상태라는 것이 확인되었다 -_-; 집으로 컴백 후 장소를 옮기고 나서 작업해야겠다. ㅠㅠ


Trackbacks 0 : Comments 4
  1. seunghoon 2012.12.10 10:10 Modify/Delete Reply

    방에 불 꺼졌단 말에 빵터져서 간만에 댓글...

    회사 옆방 사람도 라즈베리파이 구매했던데... 용도가 뭔지 모르겠지만 오늘은 거기에 연결할 usb 무선랜카드를 찾고 있더군...

  2. etermory 2013.01.26 02:48 Modify/Delete Reply

    다음 연재는?

  3. Favicon of https://take2.tistory.com take2 2013.02.13 11:23 신고 Modify/Delete Reply

    문화인에는 조금 부족하지만 댓글답니다.
    제 인생에서 가장 배우고 싶은 것 중의 하나가 C++과 Java입니다. 전혀 다른 직종에서 일하고 있지만 우연히 필
    요에 의해서 C언어를 공부했던 적이 있습니다.

    충격이었습니다.

    이렇게 말 잘듣고 시키는대로 하는 녀석이 어디 있단 말인가?
    for문을 이용해 100만번 루핑을 시키는데, 이 녀석 하더라고요.

    그 뒤로 일이 바빠서 못하고 있지만 다시 시작해 봐야겠습니다. 이렇게 언어 잘하시는 분들 보면 자극이 되거든요. 잘 보고 갑니다!

    from 문화인에 쪼금 부복한 사람...

  4. Favicon of http://2378.foodsnut.com/cheapoakleys.php cheap oakley sunglasses 2013.07.11 03:43 Modify/Delete Reply

    창밖을 봐 바람에 나뭇가지가 살며시 흔들리면 네가 사랑하는 사람이 널 사랑하고 있는거야.

Write a comment