Алгоритмы совмещения изображений - Компиляция примера кода
ОГЛАВЛЕНИЕ
Компиляция примера кода
Запустить пример очень легко – скачайте 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;
}