вторник, 12 февраля 2013 г.

Захват с web-камеры с OpenCV под Linux


Подключение web-камеры в OpenCV под виндой проходит, чаще всего, успешно. А вот ситуация с доступом к камере под linux не столь замечательна. Предлагаю одно решение  проблемы.


Итак, один из способов получить дескриптор камеры


//n - номер устройства ввода
//domain - зона в которой библиотека будет искать камеру
//Для просмотра всего списка можно использовать CV_CAP_ANY
//В заголовках highgui вы можете посмотреть полный список зон
CvCapture* capture = cvCreateCameraCapture( domain + n );

// В справке написано, что если вызвать
CvCapture* capture = cvCreateCameraCapture( -1 );
//То должно вывестись окно выбора источника ввода
//но у меня не работает. Вероятно, это только для Win 


Но, чаще всего, запуская такую(или любую другую) процедуру мы получим NULL. Иногда всё дело решается с помощью выбора подходящей зоны размещения устройства(соответственно, выбором драйвера), так что прежде советую попробовать различные зоны, типа(CV_CAP_V4L и CV_CAP_V4L2)

В чём же дело? Ни уже ли моя камера не поддерживается?
Не торопитесь горевать - скорее всего, при сборке OpenCV не была включена поддержка V4L.

Чтобы всё заработало нужно:

1)Прежде всего, убедиться, что все необходимые пакеты на месте:

ffmpeg
v4l
gstreamer

2)Перекомпилить OpenCV с поддержкой V4L и GStreamer
Зайти в папку с исходниками OpenCV

mkdir release
cd release

cmake -D CMAKE_BULD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_PYTHON_SUPPORT=ON USE_V4L=ON WITH_TBB=ON -D BUILD_NEW_PYTHON_SUPPORT=ON USE_GStreamer=ON ..

make
sudo make install

Данное решение было опробовано на Kubuntu 12.10, встроенной камере ноутбука и камере Logitech QuickCam Messenger.

Следующий тестовый проект поможет вам убедиться в работоспособности.

#include <opencv/cv.h>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/highgui/highgui_c.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    // Get a camera
      CvCapture* capture = cvCreateCameraCapture(CV_CAP_ANY);
      assert( capture );

    //Get camera frame resolution

double width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
    double height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
    printf("[i] %.0f x %.0f\n", width, height );

    IplImage* frame=0;

    cvNamedWindow("capture", CV_WINDOW_AUTOSIZE);

    while(1){
        // let's get a frame
        frame = cvQueryFrame( capture );

        // show it
        cvShowImage("capture", frame);
   
        char c = cvWaitKey(33);
        if (c == 27) { //  ESC pressed
            break;
        }
    }
    // free all resources
    cvReleaseCapture( &capture );
    cvDestroyWindow("capture");
    return 0;
}


Удачной работы!

2 комментария:

  1. Этот комментарий был удален администратором блога.

    ОтветитьУдалить
    Ответы
    1. У меня была идея использовать в качестве промежуточных узлов сбора данных/управления дешевые роутеры. Пробовал подключать камеру к DLink(DIR-320), собирал для него OpenWRT. Изображение пишет хорошо, но вот вещание напрямую 640х480 несколько fps ест почти всё время CPU, что печально. А для лёгких по ресурсам задач - хорошее решение.

      Удалить