Алгоритмы совмещения изображений - Компиляция примера кода

ОГЛАВЛЕНИЕ

Компиляция примера кода

Запустить пример очень легко – скачайте demo_binary.zip и запустите исполняемый файл.
Но для испытания кода вам придется скомпилировать его самостоятельно. Сначала установите Visual Studio .NET 2005. Экспресс-версия Visual C++ тоже подойдет.

Затем скачайте и установите библиотеку OpenCV отсюда. Скачайте OpenCV_1.0.exe и запустите его на вашем компьютере.

Наконец, настройте Visual Studio следующим образом:
•    В главном окне Visual Studio выберите пункт меню Инструменты -> Опции..., затем щелкните по элементу дерева Проекты и решения -> Каталоги VC++.
•    В комбинированном поле 'Показать каталоги для..' выберите 'Библиотечные файлы'. Добавляйте следующую строку к списку ниже:

C:\Program Files\OpenCV\lib

•    В комбинированном поле 'Показать каталоги для..' выберите 'Включаемые файлы'. Добавляйте следующие строки к списку ниже:

C:\Program Files\OpenCV\cv\include
C:\Program Files\OpenCV\cxcore\include
C:\Program Files\OpenCV\otherlibs\highgui

Вот и все! Теперь можно открыть align_demo.sln, скомпилировать и запустить его.

Несколько слов об устройстве примера проекта.

auxfunc.h и auxfunc.cpp содержат вспомогательные функции деформирования изображения. forwadditive.h и forwadditive.cppfiles содержат реализацию алгоритма Лукаса-Канаде. invcomp.h и invcomp.cpp содержат реализацию обратного композиционного алгоритма. И main.cpp содержит главную функцию.

Что делает программа?

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

В ходе процесса совмещения производятся операции деформации над шаблоном. Предполагается, что есть три разрешенных операции: поворот шаблона в одной плоскости и его двумерный перенос в направлениях X и Y. Эти операции называются разрешенным набором деформаций.

Разрешенный набор деформаций определяется путем определения матрицы деформаций, . Матрица W зависит от вектора параметров, p=(wz, tx, ty). Здесь tx и ty являются компонентами переноса, а wz является компонентом поворота.

Можно использовать более сложные наборы деформаций, например, трехмерный перенос и поворот, масштабирование, и так далее. Но для простоты используется относительно простой набор деформаций.

Логика приложения следующая.
1.    После компиляции и запуска демо выводится консольное окно, где будет отображаться диагностическая информация. Введите компоненты вектора p=(wz, tx, ty).
2.    Затем выведутся два окна, содержащие шаблон T и входное изображение I. Также отобразится белый прямоугольник на изображении I. Это начальное приближение положения бабочки. Просто предполагается, что бабочка расположена где-то вблизи этого участка.
3.    Нажмите любую клавишу, чтобы запустить алгоритм совмещения изображений Лукаса-Канаде. Этот алгоритм пытается найти местоположение бабочки, итерационно уменьшая разницу между шаблоном и изображением I. В консольном окне видно, как он работает. Видно текущее число итераций, увеличения параметров и среднее значение ошибки.
4.    После схождения процесса минимизации ошибки сводка выводится на консоль. Сводка включает в себя название алгоритма, время расчета, итоговую среднюю ошибку  и приближение параметров. Также виден белый прямоугольник, показывающий, как шаблон совмещен с изображением I.
5.    Теперь нажмите любую клавишу, чтобы запустить такой же процесс, но использующий обратный композиционный алгоритм совмещения изображений. Будут видны текущее число итераций и среднее значение ошибки.
6.    Отображается сводка для обратного композиционного алгоритма. Нажмите любую клавишу, чтобы выйти из программы.

Содержимое main.cpp приведено ниже:

// План:
//
// 1. Попросить пользователя ввести вектор параметров деформации изображения p=(wz, tx, ty)
// 2. Назначить прямоугольник шаблона ограничительным прямоугольником бабочки
// 3. Деформировать изображение с помощью матрицы деформации W(p)
// 4. Показать шаблон T и изображение I, ждать нажатия клавиши
// 5. Оценить параметры деформации с помощью метода Лукаса-Канаде, ждать нажатия клавиши
// 6. Оценить параметры деформации с помощью метода Бейкера-Деллаерта-Мэтьюса, ждать нажатия //клавиши
//

int main(int argc, char* argv[])
{
 // Попросить пользователя ввести вектор параметров деформации изображения.
 // p = (wz, tx, ty)
 
 float WZ=0, TX=0, TY=0;
 printf("Please enter WZ, TX and TY, separated by space.\n");
 printf("Example: -0.01 5 -3\n");
 printf(">");
 scanf("%f %f %f", &WZ, &TX, &TY);

В OpenCV изображения будут храниться в структуре IplImage, поэтому здесь определяются и вначале устанавливаются в нуль указатели на изображения.

 // Здесь будут храниться изображения.
 IplImage* pColorPhoto = 0; // Фото бабочки на цветке.
 IplImage* pGrayPhoto = 0; // Полутоновая копия фото.
 IplImage* pImgT = 0; // Шаблон T.
 IplImage* pImgI = 0; // Изображение I.

В OpenCV матрицы хранятся в структурах CvMat. Определяется и инициализируется нулем указатель на матрицу деформации W.

 // Здесь будет храниться матрица деформации.
 CvMat* W = 0; // Деформировать W(p)

Теперь создаются два окна для шаблона T и для изображения I. OpenCV поддерживает базовый GUI(графический пользовательский интерфейс). Поддержка GUI реализована в составе OpenCV под названием библиотека highgui. Функция cvLoadImage() позволяет загрузить изображение из файла JPG.
Теперь выделяется память для изображений с помощью функции cvCreateImage(). Первый параметр – размер изображения в пикселях, второй - глубина, а третий – число каналов. Изображения RGB имеют глубину IPL_DEPTH_8U и три канала. IPL_DEPTH_8U использует unsigned char как элемент изображения.IPL_DEPTH_16S использует short int как элемент изображения.

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

 // Создать два простых окна.
 cvNamedWindow("template"); // Здесь будет отображаться T(x).
 cvNamedWindow("image"); // Здесь будет отображаться I(x).

 // Загрузить фото.
 pColorPhoto = cvLoadImage("..\\data\\photo.jpg");

 // Создать другие изображения.
 CvSize photo_size = cvSize(pColorPhoto->width,pColorPhoto->height);
 pGrayPhoto = cvCreateImage(photo_size, IPL_DEPTH_8U, 1);
 pImgT = cvCreateImage(photo_size, IPL_DEPTH_8U, 1);
 pImgI = cvCreateImage(photo_size, IPL_DEPTH_8U, 1);

 // Преобразовать фото в полутоновое, потому что нужны значения интенсивности вместо RGB.
 cvCvtColor(pColorPhoto, pGrayPhoto, CV_RGB2GRAY);

Теперь выделяется память для матрицы деформации W с помощью функции cvCreateMat(). Первые два параметра определяют размер матрицы (3x3), а последний является типом элемента матрицы. CV_32F означает, что используется float в качестве типа элемента матрицы.

 // Создать матрицу деформации, используемую для создания изображения I.
 W = cvCreateMat(3, 3, CV_32F);

Определяется, какой шаблон будет использоваться. Определяется прямоугольник omega, указывающий положение бабочки.

 // Создать шаблон T
 // задать нужный участок для ограничительного прямоугольника бабочки.
 cvCopy(pGrayPhoto, pImgT);
 CvRect omega = cvRect(110, 100, 200, 150);

Определяется, какое изображение будет использоваться, путем слабой деформации шаблона.

 // Создать I путем деформации фото. 
 init_warp(W, WZ, TX, TY);
 warp_image(pGrayPhoto, pImgI, W);
 
 // Нарисовать прямоугольник приближения начального положения шаблона.
 cvSetIdentity(W);
 draw_warped_rect(pImgI, omega, W);

 // Показать T и I и ждать нажатия клавиши.
 cvSetImageROI(pImgT, omega);
 cvShowImage("template", pImgT);
 cvShowImage("image", pImgI);
 printf("Press any key to start Lucas-Kanade algorithm.\n");
 cvWaitKey(0);
 cvResetImageROI(pImgT);

 // Напечатать параметры, введенные пользователем.
 printf("==========================================================\n");
 printf("Ground truth: WZ=%f TX=%f TY=%f\n", WZ, TX, TY);
 printf("==========================================================\n");

 init_warp(W, WZ, TX, TY);

Запускается алгоритм Лукаса-Канаде:

 // Восстановить изображение I
 warp_image(pGrayPhoto, pImgI, W);

 /* Лукас-Канаде */
 align_image_forwards_additive(pImgT, omega, pImgI);
Теперь ожидается нажатие клавиши, и запускается обратный композиционный алгоритм:

 // Восстановить изображение I
 warp_image(pGrayPhoto, pImgI, W);

 printf("Press any key to start Baker-Dellaert-Matthews algorithm.\n");
 cvWaitKey();

 /* Бейкер-Деллаерт-Мэтьюс*/
 align_image_inverse_compositional(pImgT, omega, pImgI);
Ожидается нажатие клавиши, освобождаются все используемые ресурсы, и завершается работа.

 printf("Press any key to exit the demo.\n");
 cvWaitKey();

 // освободить все используемые ресурсы и завершить работу
 cvDestroyWindow("template");
 cvDestroyWindow("image");
 cvReleaseImage(&pImgT);
 cvReleaseImage(&pImgI);
 cvReleaseMat(&W);
 
 return 0;
}