OpenCV/DirectShowでキャプチャした画像を表示する

Last-modified: 2010-12-21 (火) 18:33:03

説明

  • OpenCVのカメラキャプチャの性能が若干不安定だったので、DirectShowからカメラを取得して、キャプチャしたバッファだけを貰ってきてOpenCVで動かす。
    • (2006.12.21変更) IplImage* を返すようにした。
  • 処理速度の検証のため、ループを一周するのにかかった時間を画面内に表示している。
    • 結果として、キャプチャ速度に大幅な改善が見られた。原因は不明。
    • 処理速度比較に関する第一段階 : 作業ログ/2006-12-17



スクリーンショット

20061219.PNG


コードに関するコメント

  • 前回のコードにバグが認められたので、クラス部分を全面的に書き換えた。
  • DirectShowでのカメラ利用にあたり、EWCLIB(http://www.geocities.jp/in_subaru/ewclib/index.html)を使用しました。
    これ、ものすごく便利です。おすすめ。

VisualStudioプロジェクトファイル

  • コンパイルには ewclib.h が必要です。



    filemain.cpp
    
    #include <stdio.h>
    #include <cv.h>
    #include <highgui.h>
    
    #include "DirectShow.h"
    
    // ???C?u?????????
    #pragma comment(lib,"cv.lib")
    #pragma comment(lib,"cxcore.lib")
    #pragma comment(lib,"cvaux.lib")
    #pragma comment(lib,"highgui.lib")
    
    // ???
    #define CAPTURE_SIZE_X  320
    #define CAPTURE_SIZE_Y  240
    
    int main()
    {
        //DirectShow?N???X???
        DirectShow capture(CAPTURE_SIZE_X, CAPTURE_SIZE_Y, 0);
        char* window_name = "Capture for DirectShow";
        //????x?\ヲ?p
        CvFont dfont;
        char message[64] = "";
    
        //?t?H???g?????
        cvInitFont(&dfont, CV_FONT_HERSHEY_SIMPLEX , 1.0f, 1.0f, 0.0f, 2, CV_AA);
     
        //OpenCV?p???????m?
        IplImage *frame = cvCreateImage(cvSize(CAPTURE_SIZE_X, CAPTURE_SIZE_Y),
            8, 3);
        IplImage *image = cvCreateImage(cvSize(CAPTURE_SIZE_X, CAPTURE_SIZE_Y),
            8, 3);
        //?E?C???h?E??J?
        cvNamedWindow(window_name,  CV_WINDOW_AUTOSIZE);
    
        //?????[?v
        while(1) {
            //??????Z?p
            double t = (double)cvGetTickCount();
    
            //?L???v?`??
            frame = capture.capture();
            cvCopy(frame, image);
    
            //?L?[?????
            int c = cvWaitKey(10);
            if( (char)c == 27 ) {   //Ecs?L?[??I?
                break;
            }
    
            //?O? cvGetTickCount() ???s????????o??????Z
            t = (double)cvGetTickCount() - t;
            sprintf(message, "%gms", t/((double)cvGetTickFrequency()*1000.) );
    
            //?e?L?X?g??\ヲ
            cvPutText(image, message, cvPoint(50, 50), &dfont, CV_RGB(255, 255, 255));
    
            //????\ヲ
            cvShowImage(window_name, image);
        }
    
        //?????
        cvDestroyWindow(window_name);
        cvReleaseImage(&image);
    }

    fileDirectShow.h
    #ifndef _DIRECTSHOW_H
    #define _DIRECTSHOW_H
    
    //OpenCV
    #include <cv.h>
    #include <highgui.h>
    #pragma comment(lib,"cv.lib")
    #pragma comment(lib,"cxcore.lib")
    #pragma comment(lib,"cvaux.lib")
    #pragma comment(lib,"highgui.lib")
    
    //frame per seconds
    #define FPS 30
    
    class DirectShow{
    public:
        //?O?????J?????\?b?h
        DirectShow(int width, int height, int num=0) {
            capture_size_x = width;
            capture_size_y = height;
            camera_number = num;
            init();
        };
        ~DirectShow() {
            release();
        };
        IplImage* capture();
    
    private:
        //?N???X?????????????\?b?h????
        void init();
        void release();
        int capture_size_x;
        int capture_size_y;
        int camera_number;
        char *buffer;
        IplImage *image;
    };
    
    
    #endif //_DIRECTSHOW_H

    fileDirectShow.cpp
    
    //?J?????????C?u????
    //http://www.geocities.jp/in_subaru/ ?i???P?j
    //http://www.vector.co.jp/soft/winnt/prog/se363340.html ?iVector?j
    #include "ewclib.h"
    
    #include "DirectShow.h"
    
    //?J???????????????????m???
    void DirectShow::init()
    {
        EWC_Open(MEDIASUBTYPE_RGB24, capture_size_x, capture_size_y, FPS);
        buffer = new char[EWC_GetBufferSize(camera_number)];
        image = cvCreateImage(cvSize(capture_size_x, capture_size_y), 8, 3);
    }
    
    //?L???v?`???????? IplImage* ???????
    IplImage* DirectShow::capture()
    {
        EWC_GetImage(camera_number, buffer);
        image->imageData=buffer;
        return image;
    }
    
    //?J??????????????????
    void DirectShow::release()
    {
        EWC_Close();
        cvReleaseImage(&image);
        delete buffer;
    }