roboforum.ru

Технический форум по робототехнике.

Уроки по OpenCV

Re: Уроки по OpenCV

galex1981 » 19 сен 2009, 11:18

С++ Builder очень схож с MFC только много упрощений. Потому если есть программа на С++ переделать ее на С++ Builder особого труда не составляет.

Re: Уроки по OpenCV

Slesh » 20 сен 2009, 00:22

Может тогда кто-нибудь подскажет как запустить программу facedetect из папки samples входящей в пакет OpenCV на Builder 6. Бьюсь уже 2-ой день никак. У кого-нибудь удалось хотябы как нибудь ее скомпилить на Билдере или VS?

Добавлено спустя 2 минуты 10 секунд:
Да и еще обнаружил баг:
Версия OpenCV 1.2 работает в Биледере только в режиме C, а в C++ выдает кучу ошибок:

Код: Выделить всёРазвернуть
  [C++ Error] cxcore.hpp(1253): E2299 Cannot generate template specialization from 'MatExpr_Op2_<A1,A2,M,Op>'
  [C++ Error] cxcore.hpp(1253): E2299 Cannot generate template specialization from 'MatExpr_<E,M>'
  [C++ Error] cxcore.hpp(1253): E2040 Declaration terminated incorrectly
  [C++ Error] cxcore.hpp(1254): E2299 Cannot generate template specialization from 'MatExpr_Op2_<A1,A2,M,Op>'
  [C++ Error] cxcore.hpp(1254): E2299 Cannot generate template specialization from 'MatExpr_<E,M>'
  [C++ Error] cxcore.hpp(1254): E2040 Declaration terminated incorrectly
  [C++ Error] cxcore.hpp(1256): E2299 Cannot generate template specialization from 'MatExpr_Op4_<A1,A2,A3,A4,M,Op>'
  [C++ Error] cxcore.hpp(1256): E2299 Cannot generate template specialization from 'MatExpr_<E,M>'
  [C++ Error] cxcore.hpp(1256): E2040 Declaration terminated incorrectly
  [C++ Error] cxcore.hpp(1258): E2299 Cannot generate template specialization from 'MatExpr_Op4_<A1,A2,A3,A4,M,Op>'
  [C++ Error] cxcore.hpp(1258): E2299 Cannot generate template specialization from 'MatExpr_<E,M>'
  [C++ Error] cxcore.hpp(1258): E2040 Declaration terminated incorrectly
  [C++ Error] cxcore.hpp(1261): E2299 Cannot generate template specialization from 'MatExpr_Op4_<A1,A2,A3,A4,M,Op>'
  [C++ Error] cxcore.hpp(1261): E2299 Cannot generate template specialization from 'MatExpr_<E,M>'
  [C++ Error] cxcore.hpp(1261): E2040 Declaration terminated incorrectly
  [C++ Error] cxcore.hpp(1299): E2299 Cannot generate template specialization from 'MatExpr_<E,M>'
  [C++ Error] cxcore.hpp(1299): E2076 Overloadable operator expected
  [C++ Error] cxcore.hpp(1299): E2040 Declaration terminated incorrectly
  [C++ Error] cxcore.hpp(2132): E2028 operator-> must return a pointer or a class
  [C++ Error] cxoperations.hpp(846): E2015 Ambiguity between '_STL::_fm_cos(const _STL::complex<long double> &)' and '_STL::_fm_cos(const _STL::complex<float> &)'
  [C++ Error] cxoperations.hpp(847): E2015 Ambiguity between '_STL::_fm_sin(const _STL::complex<long double> &)' and '_STL::_fm_sin(const _STL::complex<float> &)'
  [C++ Error] cxoperations.hpp(1875): E2028 operator-> must return a pointer or a class
  [C++ Error] cxmat.hpp(784): E2316 'Mat_<_Tp>::operator MatExpr_<Mat_<_Tp>,Mat_<_Tp> >() const' is not a member of 'Mat_<_Tp>'
  [C++ Error] cxmat.hpp(787): E2015 Ambiguity between 'Mat::operator MatExpr_<Mat,Mat>() const' and 'MatExpr_<Mat,Mat>::MatExpr_(const Mat &)'



Может кто-нибудь знает как исправить проблему?

Добавлено спустя 12 минут 47 секунд:
Пробовал на версии 1.0 там тоже какая то проблема.Пока не разобрался: то ли в lib-ах, то ли header-ах.

Добавлено спустя 3 часа 10 минут 35 секунд:
Всё разобрался наконец-то и запустил facedetect. :Yahoo!:
В Builder 6 надо использовать версию OpenCV 1.0 (с 1.2 ошибок много). Перекодировать либы и включить их в проект. Но! Для работы facedetect нужено лишь 3 либа, а я все сразу добавлял (чтобы не напрягаться особо :roll: ). И при добавлении cvhaartraining.lib в проект возникает ошибка, но сборка проходит успешно, а при запуске самого exe файла пишет, что не найден cvhaartraining.dll :shock:( а его на самом деле и нет :o ). Вот и всё.

И вопрос как это на C++ перевести теперь? Или может создать dll и подключать потом?

Re: Уроки по OpenCV

Snable » 20 сен 2009, 01:39

Попробуй так:
Код: Выделить всёРазвернуть
extern "C" {
    #include <open_cv_libs>
}

Должно прокатить. Хотя именно с openCV такое не пробовал.

Re: Уроки по OpenCV

Slesh » 20 сен 2009, 02:51

Круто!!! Спасибо :Bravo: . Версия 1.0 пошла на C++

В версии 1.2 пишет:

Код: Выделить всёРазвернуть
  [C++ Error] _pair.h(36): E2132 Templates and overloaded operators cannot have C linkage
  [C++ Error] _pair.h(36): E2040 Declaration terminated incorrectly
  [C++ Error] _pair.h(59): E2132 Templates and overloaded operators cannot have C linkage
  [C++ Error] _pair.h(59): E2040 Declaration terminated incorrectly
  [C++ Error] _algobase.h(290): E2428 Templates must be classes or functions
  [C++ Error] _algobase.h(290): E2092 Storage class 'inline' is not allowed here
  [C++ Error] _algobase.h(290): E2141 Declaration syntax error
  [C++ Error] _uninitialized.h(99): E2428 Templates must be classes or functions
  [C++ Error] _uninitialized.h(99): E2092 Storage class 'inline' is not allowed here
  [C++ Error] _uninitialized.h(99): E2445 Variable 'pair' is initialized more than once
  [C++ Error] _uninitialized.h(99): E2141 Declaration syntax error
  [C++ Error] _uninitialized.h(281): E2190 Unexpected }
  [C++ Error] _tempbuf.h(46): E2428 Templates must be classes or functions
  [C++ Error] _tempbuf.h(46): E2238 Multiple declaration for 'pair'
  [C++ Error] _uninitialized.h(99): E2344 Earlier declaration of 'pair'
  [C++ Error] _tempbuf.h(46): E2141 Declaration syntax error
  [C++ Error] _tempbuf.h(52): E2428 Templates must be classes or functions
  [C++ Error] _tempbuf.h(52): E2092 Storage class 'inline' is not allowed here
  [C++ Error] _tempbuf.h(52): E2445 Variable 'pair' is initialized more than once
  [C++ Error] _tempbuf.h(52): E2141 Declaration syntax error
  [C++ Error] _tempbuf.h(146): E2303 Type name expected
  [C++ Error] _tempbuf.h(146): E2275 { expected
  [C++ Error] _tempbuf.h(146): E2275 { expected
  [C++ Error] _tempbuf.c(32): E2428 Templates must be classes or functions
  [C++ Error] _tempbuf.c(32): E2238 Multiple declaration for 'pair'
  [C++ Error] _tempbuf.c(32): E2228 Too many error or warning messages

Re: Уроки по OpenCV

=DeaD= » 20 сен 2009, 09:55

Всё что выше 1.00 оно какое-то загадочное, т.к. Intel вышла из процесса разработки и видимо с тестированием полноценным у них совсем плохо стало.

Re: Уроки по OpenCV

Slesh » 20 сен 2009, 14:11

Обещают, кстати, что завтра новая версия выйдет 2.0
Спешу поделиться своим опытом:
facedetect выполняется точнее в версии 1.2 . Убедился на фильме "Всегда говори да".

У меня не хотят работать хэдеры из 1.2 , как я ни пытался у меня ничего не получилось. Но как-то случайно запустил компайл с хэдерами из 1.0, а lib из 1.2 .И о чудо всё заработало!!! :Yahoo!: Но в процессе усовершенствования программы, скомпилил тот же код с lib и header из 1.0 и facedetect перестал работать :o : в фильме не находил ни одного лица. Но покапавшись вернул всё на круги своя.

Так что если кто-нибудь будет пользоваться OpenCV в Builder 6 подлючайте header из 1.0 , а lib из 1.2.
Результат :good:

Re: Уроки по OpenCV

Slesh » 23 сен 2009, 00:27

Кто-нибудь пробовал обучать OpenCV ? У меня не выходит. 2 дня карпел. Возможно ли обучить его распознавать жесты.
Например, Сколько пальцев показывается.

Re: Уроки по OpenCV

SATANAblack » 17 янв 2010, 17:25

Можно. Я обучал человеческие лица распознавать. Процес обучения очень долгий.

opencv::highgui: поддерживаемые контролы

MiBBiM » 29 янв 2010, 20:40

opencv::highgui: поддерживаемые контролы
Консоль
Самая обычная консоль, создаваемая студией для нашего проекта. коноль - не часть opencv, но тем не менее часто используется как база для отладочного вывода. что ж, не будем пренебрегать таким удобным инструментом.
Код: Выделить всёРазвернуть
#include "highgui.h"
#include <stdio.h>

int main()
{
   printf("Console output");
   char c;
   scanf("%c", &c);
}

console.png
console.png (4.77 КиБ) Просмотров: 17280

Окошки: создание
Выше Lockdog описал создание и уничтожение, вот ещё пример (снято одно и то же окно, изображения выводились последовательно):
Код: Выделить всёРазвернуть
cvNamedWindow("window");
cvNamedWindow("window", 0);

without_auto_scale.png
cvNamedWindow("window", 0);
auto_scaling.png
cvNamedWindow("window");

Далее, функция
Код: Выделить всёРазвернуть
void cvMoveWindow( const char* name, int x, int y );

перемещает окно в заданную позицию, а
Код: Выделить всёРазвернуть
void cvDestroyAllWindows( void );

уничтожает все созданные окна.
для примера создадим два окна, переместим одно из них, а потом последовательно уничтожим оба.
Код: Выделить всёРазвернуть
#include "highgui.h"
#include <stdio.h>

int main()
{
   const char *window = "Тестовое окно";
   const char *window1 = "Тестовое окно #2";
   
   cvNamedWindow(window, 0);
   cvNamedWindow(window1);

   cvWaitKey(0);
   cvMoveWindow(window1, 100, 100);
   cvWaitKey(0);

   cvDestroyWindow(window);
   cvWaitKey(0);
   cvDestroyAllWindows();
}

ЗАМЕЧАНИЕ: cvwaitkey (описана выше) работает для любого окна и не привязана ни к одному из них.
ещё одна доступная функция позволяет изменить размеры окна (только если выключено авто масштабирование), прототип:
Код: Выделить всёРазвернуть
void cvResizeWindow( const char* name, int width, int height );

на вход подаются указатель на окно (его имя) и новые размеры.
Окошки: обработка мыши
завязана на событийной модели. первое, что нужно сделать, это подписать функцию вида:
Код: Выделить всёРазвернуть
void mouse_callback(int event, int x, int y, int flags, void* param)

функцией
Код: Выделить всёРазвернуть
void cvSetMouseCallback(
const char* window_name,
CvMouseCallback on_mouse,
void* param = NULL
);

посмотрите на прототип, для каждого окна и даже изображения можно привязывать свои функции для обработки. однако есть минус - без изображения привязать мышь невозможно (да и вряд ли это кому-нибудь может понадобится).
теперь о функции-обработчике, первый параметр - event - принимает значения
Код: Выделить всёРазвернуть
// названия событий говорящие, поэтому без комментариев
CV_EVENT_MOUSEMOVE
CV_EVENT_LBUTTONDOWN
CV_EVENT_RBUTTONDOWN
CV_EVENT_MBUTTONDOWN
CV_EVENT_LBUTTONUP
CV_EVENT_RBUTTONUP
CV_EVENT_MBUTTONUP
CV_EVENT_LBUTTONDBLCLK
CV_EVENT_RBUTTONDBLCLK
CV_EVENT_MBUTTONDBLCLK

дальше, x,y - координаты мыши относительно _левого верхнего угла_изображения_.
flags (показывает, зажаты ли управляющие клавиши):
Код: Выделить всёРазвернуть
// снова говорящие сами за себя константы, нажат ли контрл, шифт или альт
CV_EVENT_FLAG_CTRLKEY
CV_EVENT_FLAG_SHIFTKEY
CV_EVENT_FLAG_ALTKEY

последний параметр - опциональный и может использоваться для передачи чего угодно в функцию (может понадобиться для пользовательских вызовов)
пример использования мыши:
Код: Выделить всёРазвернуть
/* 
*   создание двух окон и закрытие одного из них (window) по щелчку левой кнопкой мыши.
*/
#include <highgui.h>
#include <stdio.h>

void mouse_callback(int event, int x, int y, int flags, void* param)    // обработчик
{
   if (event == CV_EVENT_LBUTTONDOWN) cvDestroyAllWindows();
}

int main()
{
   const char *window = "Тестовое окно";
   const char *window1 = "Тестовое окно #2";
   
   cvNamedWindow(window, 0);
   cvNamedWindow(window1);

   IplImage *img1 = cvLoadImage("1.jpg");
   IplImage *img2 = cvLoadImage("2.jpg");
   cvShowImage(window, img1);
   cvShowImage(window1, img2);
   cvSetMouseCallback(window, mouse_callback);   // привязка обработчика к любому изображению в окне
   // cvSetMouseCallback(window, mouse_callback, img1);   // привязка обработчика только к изображению img1 в окне window

   cvWaitKey(0);
   cvDestroyAllWindows();
}


Добавлено спустя 1 час 11 минут 25 секунд:
Окошки: слайдеры
сразу к делу, функция для создания:
Код: Выделить всёРазвернуть
int cvCreateTrackbar(
const char* trackbar_name,
const char* window_name,
int* value,
int count,
CvTrackbarCallback on_change
);

trackbar_name - имя (а также и подпись) слайдера
window_name - имя окна для вставки слайдера
value - _указатель_ на значение слайдера. можно поставить 0 или указатель на переменную типа int. теперь её значение всегда будет равно текущей позиции бегунка.
count - _максимальное_значение_ слайдера. количество позиций = count + 1 из-за нулевого начала отсчета.
on_change - указатель на функцию, которая будет вызываться при каждом изменении позиции слайдера.
Код: Выделить всёРазвернуть
void trackbar_callback(int position)
{
   // делаем что-то при изменении слайдера
}
....
int pos = 1;
cvCreateTrackbar("trackbar", "window", &pos, 10, trackbar_callback);
// создание без привязки к обработчику
cvCreateTrackbar("trackbar", "window", &pos, 10, NULL);

также есть функции для управления значениями слайдера:
Код: Выделить всёРазвернуть
// trackbar_name, window_name играют ту же роль, что и в функциях, описанных выше
int cvGetTrackbarPos(      // установление позиции слайдера
const char* trackbar_name,
const char* window_name
);
void cvSetTrackbarPos(     // получение позиции
const char* trackbar_name,
const char* window_name,
int pos
);

пример:
Код: Выделить всёРазвернуть
/*
* Работа со слайдером: создание, обработка событий, перемещение в указанную позицию по нажатию клавиши ['0'..'9']
*/
void trackbar_callback(int position)
{
   printf("position is: %d\r", position);
}

int main()
{
   const char *window = "Тестовое окно";   
   cvNamedWindow(window);

   const char *trackbar = "Слайдер";
   int pos = 1;
   cvCreateTrackbar(trackbar, window, &pos, 10, trackbar_callback);

   char key;
   do {
      key = cvWaitKey(0);
      if (key >= '0' && key <= '9')
         cvSetTrackbarPos(trackbar, window, key-'0');
   } while (key != 'e');

   cvDestroyAllWindows();
}

trackbar.png
trackbar.png (7.4 КиБ) Просмотров: 17312

ЗАМЕЧАНИЕ: заметил любопытный глюк - после достижения слайдбаром максимального значения, его позиция начинает передаваться в функцию как реальная_позиция<<(количество_разрядов_в_максимальном_значении-1) в десятичной системе. что интересно, значение переменной-указателя текущего значения остается актуальным и безошибочным.

Добавлено спустя 3 часа 24 минуты 39 секунд:
Окошки: переключатели
Создатели opencv придерживались концепции "нет кнопкам" =), поэтому в либе их нет. однако где наша не пропадала =). в качестве замены кнопок может служить фейковое изображение и подписанная процедура обработки мыши (см. выше). второй, более удобный вариант - это слайдбар о двух позициях - переключатель.
Код: Выделить всёРазвернуть
void trackbar_callback(int position)
{
   if (position) {;} else {;}
}

int main()
{
   const char *window = "Тестовое окно";   
   cvNamedWindow(window, 0);

   const char *trackbar = "Слайдер";
   int pos = 1;
   cvCreateTrackbar(trackbar, window, &pos, 1, trackbar_callback);

   char key = cvWaitKey(0);

   cvDestroyAllWindows();
}

switches.png
switches.png (3.31 КиБ) Просмотров: 17279


На этой ноте доступные контролы заканчиваются.

Re: Уроки по OpenCV

TrashVigor » 29 янв 2010, 23:18

А как узнать что нибудь о пикселе? Его RGB

opencv::highgui: средства ввода-вывода

MiBBiM » 30 янв 2010, 02:41

opencv::highgui: средства ввода-вывода
Прежде чем обрабатывать изображения/видео нужно вначале их загрузить, чем мы и займемся.
Изображения
Для картинок существует тип IplImage (о нем расскажу гораздо позднее). функции тривиальны, поэтому сразу к прототипам:
Код: Выделить всёРазвернуть
// загрузка изображения из файла
// filename - имя файла
// iscolor - флаг, обозначающий необходимость загрузки изображения в цвете. по умолчанию активен, чтобы сбросить, записываем в качестве значения 0
IplImage* cvLoadImage(
const char* filename,
int iscolor = CV_LOAD_IMAGE_COLOR
);
// сохранение изображения в файл
// filename - имя файла, выбор формата осуществляется на основании расширения.
// image - само изображение
int cvSaveImage(
const char* filename,
const CvArr* image
);
// рисование изображения в окне
// name - окно для вывода
// image - само изображение
void cvShowImage(
const char* name,
const CvArr* image
);

// конвертирование изображения из одного формата в другой (напомню, что формат задается расширением имени при открытии изображения)
// дополнительно осуществляется преобразование цветной/черно-белый, если соответствующие опции были заданы во время открытия изображения.
// src - источник
// dst - контейнер
// flags - флаг. если установлен, то изображение зеркалируется по вертикали.
void cvConvertImage(
const CvArr* src,
CvArr* dst,
int flags = 0
);


пример, загружаем изображение, показываем, тут же сохраняем в другом файле:
Код: Выделить всёРазвернуть
/*
* Программа загружает изображение, выводит его в окно, сохраняет
* в другой файл и ждет нажатия клавиши до завершения
*/
#include <highgui.h>
#include <stdio.h>

int main()
{
   const char *window = "Тестовое окно";   
   cvNamedWindow(window);
   
   IplImage *img = cvLoadImage("1.jpg");   

   cvShowImage(window, img);

   cvSaveImage("1buf.jpg", img);

   char key = cvWaitKey(0);
   cvDestroyAllWindows();
}

Видео: ввод
Для организации ввода-вывода видео существуют струкутры CvCapture, CvVideoWriter, первая для хранения информации о вводимом потоке, вторая - о выводимом.
Для начала рассмотрим ввод. У CvCapture есть список свойств:
Код: Выделить всёРазвернуть
CV_CAP_PROP_POS_MSEC      // текущая позиция воспроизведения в мсек
CV_CAP_PROP_POS_FRAME      // номер текущего кадра
CV_CAP_PROP_POS_AVI_RATIO   // значение отношения уже воспроизведенного к общему объему файла, лежит в множестве [0..1]
CV_CAP_PROP_FRAME_WIDTH      // ширина кадра
CV_CAP_PROP_FRAME_HEIGHT   // высота кадра
CV_CAP_PROP_FPS         // FPS, количество кадров в секунду
CV_CAP_PROP_FOURCC      // четырех буквенный идентификатор кодека (XVID, DIVX, etc.)
CV_CAP_PROP_FRAME_COUNT      // общее количество кадров

доступ к которым осуществляется функциями
Код: Выделить всёРазвернуть
// получает значение свойства
// property_id - номер свойства (константы выше)
double cvGetCaptureProperty(
CvCapture* capture,
int property_id
);
// устанавилвает значение свойства
// property_id - номер свойства (константы выше)
int cvSetCaptureProperty(
CvCapture* capture,
int property_id,
double value
)

// вводит в заблуждение тип double применительно к свойству FOURCC, однако ничего необычного здесь почти нет, нужно лишь перекастовать тип
double f = cvGetCaptureProperty(capture,CV_CAP_PROP_FOURCC);
char* fourcc = (char*) (&f);

Соответственно все управление вводом сходится к изменению этих свойств.
Поток может быть получен из файла на диске (функция cvCreateFileCapture, рассмотренная Lockdog'ом) и с камеры (кстати, функции в случае неудачи возвращают NULL):
Код: Выделить всёРазвернуть
// index - номер устройства для извлечения видео, отсчет с нуля.
CvCapture* cvCreateCameraCapture( int index );
/*
* устройства отсортированы в соответствии со списком:
CV_CAP_ANY      0
CV_CAP_MIL      100
CV_CAP_VFW      200
CV_CAP_V4L      200
CV_CAP_V4L2      200
CV_CAP_FIREWIRE      300
CV_CAP_IEEE1394      300
CV_CAP_DC1394      300
CV_CAP_CMU1394      300
допустим, первая камера, принадлежащая множеству любых, будет CV_CAP_ANY, следующая - (CV_CAP_ANY+1)
для камер с fireware интерфейсом аналогично: первая - CV_CAP_FIREWIRE, вторая (CV_CAP_FIREWIRE+1).
*/

Уничтожить поток можно функцией
Код: Выделить всёРазвернуть
void cvReleaseCapture( CvCapture** capture );

Из потока можно читать кадры, для чего используются три функции
Код: Выделить всёРазвернуть
int cvGrabFrame( CvCapture* capture );
IplImage* cvRetrieveFrame( CvCapture* capture );
IplImage* cvQueryFrame( CvCapture* capture );

Первая захватывает кадр из потока, копирует в буфер, невидимый для пользователя, и возвращает 1 в случае успеха, 0 - неудачи. Почему пользователь лишен доступа к этому буферу? Все очень просто, кадры, размещенные там, не могут быть изменены никоим образом (не декодированы для использования в стандартных функциях). глобальная цель - как можно более быстрая работа, что актуально при наличии многих камер.
После захвата мы можем получить кадр, используя вторую функцию, которая декодирует его во внутреннее представление, заполняет информационные поля и т.д.
Стоит отметить, что вызов cvGrabFrame автоматически производит инкремент текущего кадра в структуре cvCapture
Третья функция - суперпозиция вызовов первых двух, удобна для использования, когда в системе малое количество потоков и о скорости можно не беспокоиться.
Видео: вывод
Как было упомянуто выше, для вывода (в файл, на экран покадрово cvShowImage) используется структура CvVideoWriter. Прототипы фунуций для создания и уничтожения ниже:
Код: Выделить всёРазвернуть
/* распространенные идентификаторы
CV_FOURCC('X', 'V', 'I', 'D') = FLV1 codec
CV_FOURCC('P','I','M','1')    = MPEG-1 codec
CV_FOURCC('M','J','P','G')    = motion-jpeg codec (does not work well)
CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec
CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec
CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec
CV_FOURCC('U', '2', '6', '3') = H263 codec
CV_FOURCC('I', '2', '6', '3') = H263I codec
CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec
*/
// создает структуру
// filename - файл для записи
// fourcc - четырех буквенный идентификатор кодека, чтобы вручную не кастовать типы, можно воспользоваться макросом CV_FOURCC(c0,c1,c2,c3)
// fps - количество кадров в секунду
// frame_size - структура CvSize, хранящая высоту и ширину в данном случае кадра
// is_color - цветность кадра
CvVideoWriter* cvCreateVideoWriter(
const char* filename,
int fourcc,
double fps,
CvSize frame_size,
int is_color = 1
);
// уничтожает структуру и высвобождает память
void cvReleaseVideoWriter(
CvVideoWriter** writer
);

После того, как создан выходной поток и получена структура, можно записывать кадры:
Код: Выделить всёРазвернуть
// записывает кадр в выходной поток
// writer - структура-описатель потока
// image - кадр
int cvWriteFrame(
CvVideoWriter* writer,
const IplImage* image
);

В таком случае алгоритм вывода можно представить как совокупность операций создания потока, последовательной записи кадров, закрытия потока.
Видео: примеры
Первый пример Lockdog связал с чтением видео из файла, используя одинаковую для всех видео задержку между кадрами. устраним эту досадную оплошность.
Код: Выделить всёРазвернуть
/*
* Программа читает видео из файла, подстраиваясь под фреймрейт
* Для выхода используется клавиша e
*/
#include <highgui.h>
#include <stdio.h>

int main()
{
   // создаем окошко для манипуляций
   const char *window = "Тестовое окно";   
   cvNamedWindow(window);
   
   // буфер-кадр
   IplImage *img;
   // создаем поток для видео
   const char *video = "The Outer Limits - 3x13 - Dead Mans Switch (Rus).avi";
   CvCapture *capture = cvCreateFileCapture(video);
   // читаем фреймрейт
   double framerate = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
   int delay = (int) (1000 / framerate);
   printf("FPS: %0.3f\nDelay: %d\n", framerate, delay);
   do {
      img = cvQueryFrame(capture);
      cvShowImage(window, img);
   } while (cvWaitKey(delay) != 'e');

   cvDestroyAllWindows();
}

давайте ещё и добавим прокрутку, используя знания о слайдерах:
Код: Выделить всёРазвернуть
/*
* Программа читает видео из файла, подстраиваясь под фреймрейт
* А также представляет функциональность прокрутки
* Для выхода используется клавиша e
*/
// cxcore.lib cv.lib highgui.lib cvaux.lib cvcam.lib
#include <highgui.h>
#include <stdio.h>

int main()
{
   // создаем окошко для манипуляций
   const char *window = "Тестовое окно";   
   cvNamedWindow(window);

   // создаем слайдер и подписываем функцию на изменение
   // пусть у него будет 1000 делений, делать больше - нерационально
   const int resolution = 1000;
   const char *trackbar = "Позиция";
   cvCreateTrackbar(trackbar, window, 0, resolution-1, NULL);
   
   // буфер-кадр
   IplImage *img;
   // создаем поток для видео
   const char *video = "The Outer Limits - 3x13 - Dead Mans Switch (Rus).avi";
   CvCapture *capture = cvCreateFileCapture(video);
   // читаем фреймрейт
   double framerate = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
   int delay = (int) (1000 / framerate);
   printf("FPS: %0.3f\nDelay: %d\n", framerate, delay);


   int old_trackbar_pos = 0;
   do {
      img = cvQueryFrame(capture);
      cvShowImage(window, img);
      int new_trackbar_pos = cvGetTrackbarPos(trackbar, window);
      if (new_trackbar_pos != old_trackbar_pos) {
         float scale = (float) new_trackbar_pos / resolution;
         cvSetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO, scale);
      }
      float pos = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO);
      old_trackbar_pos = (int) (pos*resolution);
      cvSetTrackbarPos(trackbar, window, old_trackbar_pos);
      printf("position is: %0.2f%%\r", pos*100);
   } while (cvWaitKey(delay) != 'e');

   cvDestroyAllWindows();
}

pleer.png

Далее, захватим изображение с камеры:
Код: Выделить всёРазвернуть
/*
* Программа захватывает видео с камеры
* Для выхода используется клавиша e
*/
#include <highgui.h>
#include <stdio.h>

int main()
{
   // создаем окошко для манипуляций
   const char *window = "Тестовое окно";   
   cvNamedWindow(window);

   // буфер-кадр
   IplImage *img;
   // создаем поток для видео
   CvCapture *camera = cvCreateCameraCapture(CV_CAP_ANY);

   int old_trackbar_pos = 0;
   do {
      img = cvQueryFrame(camera);
      cvShowImage(window, img);
   } while (cvWaitKey(33) != 'e');

   cvDestroyAllWindows();
}

camera.png

Ещё примерчик, захват видео с камеры и запись в файл
Код: Выделить всёРазвернуть
/*
* Программа захватывает видео с камеры и записывает в avi файл, кодек XviD
*/
#include <highgui.h>
#include <stdio.h>

int main()
{
   const char *window = "Тестовое окно";
   cvNamedWindow(window);

   CvCapture *camera = cvCreateCameraCapture(CV_CAP_ANY);

   const char *filename = "1.avi";
   CvSize size = cvSize(640, 480);
   CvVideoWriter *writer = cvCreateVideoWriter(filename, CV_FOURCC('X','V','I','D'), 15, size);

   IplImage *frame;
   do {
      frame = cvQueryFrame(camera);
      cvWriteFrame(writer, frame);
      cvShowImage(window, frame);      
   } while (cvWaitKey(1) != 'e');

   cvReleaseVideoWriter(&writer);
   cvDestroyAllWindows();
}

И в заключение - отображение видео с камеры и запись скриншотов по нажатию клавиши 's'
Код: Выделить всёРазвернуть
/*
*  Программа отображает видео и созраняет скриншоты по нажатию клавиши 's'
*  Выход на клавишу 'e'
*/
#include <highgui.h>
#include <stdio.h>
#include <time.h>

int main()
{
   const char *window = "Тестовое окно";
   cvNamedWindow(window);

   CvCapture *camera = cvCreateCameraCapture(CV_CAP_ANY);


   IplImage *frame;
   char key;
   do {
      frame = cvQueryFrame(camera);   
      cvShowImage(window, frame);   
      key = cvWaitKey(1);
      if (key == 's') {
         time_t now = time(NULL);
         struct tm  *ts = localtime(&now);
         char buf[80];
         strftime(buf, sizeof(buf), "%Y-%m-%d-%H-%M-%S.jpg", ts);
         printf("Screenshot %s saved\n", buf);
         cvSaveImage(buf, frame);
      }
   } while (key != 'e');

   cvDestroyAllWindows();
}

capture_with_screenshot.png

Заключение
На этом изучение модуля highgui можно считать законченным, т.к. разъяснены все его функции.
P.S> оба сообщения - не перевод книжек, а лишь вольное изложение моих знаний. весь код писал и проверял лично я, поэтому примеры 100% рабочие.

Re: Уроки по OpenCV

MiBBiM » 30 янв 2010, 13:02

а теперь о проблемах. при захвате видео с камеры структура CvCapture, полученная функцией cvCreateCameraCapture, оказывается битой, т.е. из неё невозможно прочитать фреймрейт и четырех буквенный идентификатор кодека, что очень и очень печально. как это можно исправить?

Re: Уроки по OpenCV

Headmast » 14 фев 2010, 00:48

Очень интересный материал, спасибо за публикации

Re: Уроки по OpenCV

ferz » 02 мар 2010, 00:40

устанавливаю библиотеку впервый раз 2,0 1,0 ненашел все подругому код некомпилится
скажи что include files sorce и др в show directories как узнал что куда подключать
если в мануале на какой стр если есть ссылки скиньти плз

Re: Уроки по OpenCV

MiBBiM » 03 мар 2010, 22:49

установка описана в 4-ом сообщении темы.


Rambler\'s Top100 Mail.ru counter