Загрузка...

понедельник, 9 марта 2009 г.

OpenCV: первые шаги

Что такое OpenCV? По этому поводу википедия говорит следующее:

OpenCV (англ. Open Source Computer Vision Library, библиотека компьютерного зрения с открытым исходным кодом) — библиотека алгоритмов компьютерного зрения, обработки изображений и численных алгоритмов общего назначения с открытым кодом. Реализована на C/C++, так же разрабатывается для Python, Ruby, Matlab и других языков. Может свободно использоваться в академических и коммерческих целях — распространяется в условиях лиценции BSD.
Direct link

Это действительно мощная библиотека, равных которой мне неизвестно. Хоть она используется в компьютерном "зрении", библиотека находит свое применение в работе с графикой (пример такой реализации - Photo Editor). Впрочем, если быть точным, то работа с видео сводится к обработке статических изображений (фреймов). Собственно, скачать и попробовать OpenCV можно отсюда.

Улыбочку, вас снимает камера

Простота и изящество библиотеки позволяет уже спустя несколько минут после знакомства отображать видео-картинку с веб-камеры. Вот так все просто! Давайте глянем на эту реализацию (как всегда, важные моменты помечены комментариями):

#include "stdafx.h"
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <iostream>
using namespace std;

void processFrame(IplImage*& image);

int main(int argc, char** argv) 
{
 // Инициализируем источник наших изображений.
 // В данном случае - это видеокамера, подключенная по 
 // одному из интерфейсов. 0 означает, что надо
 // выбрать первую попавшуюся камеру. У нас их одна,
 // поэтому не стоит волноваться по этому поводу :)
 CvCapture* capture = 0;
 capture = cvCreateCameraCapture(0);
 if (!capture)
 {
  cout << "Initialization failed" << endl;
  return EXIT_FAILURE;
 }

 // Работа с GUI упрощена до невозможного. Необходимо
 // определить идентификатор (по совместительству -
 // заголовок окна), по которому мы будем определять
 // наши окна.
 const char *windowName = "First steps with OpenCV";
 cvNamedWindow(windowName, CV_WINDOW_AUTOSIZE);

 while(true) 
 {
  // Опрашиваем камеру для получения следующего кадра
  IplImage* frame = cvQueryFrame( capture );
  if(!frame) 
   break;

  // processFrame(frame);

  // Отобразим наш фрейм в окне (не забыли, как мы его
  // определили? - через идентификатор)
  cvShowImage(windowName, frame);

  // По нажатию ESC - выход из цикла
  char c = cvWaitKey(33);
  if (c == 27) 
   break;
 }

 // Никогда не забываем освобождать память!
 cvReleaseCapture( &capture );
 cvDestroyWindow(windowName);
 return 0;
}

Замечание. Я не перегружаю пост указанием подготовительных действий. Библиотека исключительна проста в установке. Если возникают вопросы — можно спросить в комментариях.

Стоит заметить, что не OpenCV единым жив человек :) Можно задействовать и другие способы для работы с камерой. Тот же DirectShow имеет такие возможности. Но если глянуть на подобную реализацию (вот здесь), то сразу станет ясным — нам такой радости не надо.

Вернемся к нашему примеру. Чем он так хорош? А тем, что уже сейчас можно приниматься за обработку кадров! Чем мы сейчас и займемся :)

Обработка фреймов

Издеваться над кадрами мы будем в функции processFrame. Встроенных функций в OpenCV - уйма, и данной статьи на их описание не хватит. Но мы сделаем следующие: отобразим картинку (чтобы видеть себя как в зеркале), создадим копию фрейма в серых тонах и отобразим в новом окне. А перед тем, как выводить - вырежем центр изображения (если издеваться, то по полной :) ). И вот что мы получим:

void processFrame(IplImage*& image)
{
 // Стандартный флип
 cvFlip(image,image,1);

 // Создадим новое изображение
 CvSize size = cvSize(image->width, image->height);
 
 // Здесь 1 - количество каналов
 IplImage* newImage = cvCreateImage(size, image->depth, 1);

 // Копируем изображение с переводом в grayscale
 cvCvtColor(image, newImage, CV_RGB2GRAY);

 // Определяем центр изображения
 CvRect rect = cvRect(image->width/4,image->height/4,
    image->width/2,image->height/2);

 // Определяем region of interest, который мы затем обнулим
 cvSetImageROI(newImage, rect);
 cvZero(newImage);
 cvResetImageROI(newImage);

 // Отобразим наше изображение
 cvNamedWindow("newImage");
 cvShowImage("newImage",newImage);

 // Ох не забывайте про эту функцию :)
 cvReleaseImage(&newImage);
}

Стоит наверно пояснить, что такое ROI. Это очень удобная штука. Можно задать этот прямоугольник и все действия будут производится только над ним, не затрагивая другие части фрейма.

На этом я закончу, в скором ждите продолжения - будем определять предметы на изображении.

Disclaimer. Я не претендую на исключительную правильность и на глубокое понимание библиотеки: сам имею небольшой опыт общения с ней. Выкладываю свои наработки с целью немного расширить скудный материал по OpenCV на русском. Есть вопросы - велкам в комменты! :)

blog comments powered by Disqus


 
^

Powered by BloggerCreative Commons License